Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ jobs:
- name: Install Node.js
uses: actions/setup-node@v6
with:
node-version: '18'
node-version: '22'
- name: Install wasmtime
uses: bytecodealliance/actions/wasmtime/setup@v1
with:
Expand Down
2 changes: 1 addition & 1 deletion GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ wasi-cm:
rsync -rv --delete --exclude go.mod --exclude '*_test.go' --exclude '*_json.go' --exclude '*.md' --exclude LICENSE $(shell go list -m -f {{.Dir}} $(WASM_TOOLS_MODULE)/cm)/ ./src/internal/cm

# Check for Node.js used during WASM tests.
MIN_NODEJS_VERSION=18
MIN_NODEJS_VERSION=22

.PHONY: check-nodejs-version
check-nodejs-version:
Expand Down
2 changes: 1 addition & 1 deletion targets/wasm.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@
"src/runtime/asm_tinygowasm.S",
"src/runtime/gc_boehm.c"
],
"emulator": "node {root}/targets/wasm_exec.js {}"
"emulator": "node {root}/targets/wasm_exec_node.js {}"
}
113 changes: 27 additions & 86 deletions targets/wasm_exec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,51 +3,25 @@
// license that can be found in the LICENSE file.
//
// This file has been modified for use by the TinyGo compiler.
"use strict";

(() => {
// Map multiple JavaScript environments to a single common API,
// preferring web standards over Node.js API.
//
// Environments considered:
// - Browsers
// - Node.js
// - Electron
// - Parcel

if (typeof global !== "undefined") {
// global already exists
} else if (typeof window !== "undefined") {
window.global = window;
} else if (typeof self !== "undefined") {
self.global = self;
} else {
throw new Error("cannot export Go (neither global, window nor self is defined)");
}

if (!global.require && typeof require !== "undefined") {
global.require = require;
}

if (!global.fs && global.require) {
global.fs = require("node:fs");
}

const enosys = () => {
const err = new Error("not implemented");
err.code = "ENOSYS";
return err;
};

if (!global.fs) {
if (!globalThis.fs) {
let outputBuf = "";
global.fs = {
constants: { O_WRONLY: -1, O_RDWR: -1, O_CREAT: -1, O_TRUNC: -1, O_APPEND: -1, O_EXCL: -1 }, // unused
globalThis.fs = {
constants: { O_WRONLY: -1, O_RDWR: -1, O_CREAT: -1, O_TRUNC: -1, O_APPEND: -1, O_EXCL: -1, O_DIRECTORY: -1 }, // unused
writeSync(fd, buf) {
outputBuf += decoder.decode(buf);
const nl = outputBuf.lastIndexOf("\n");
if (nl != -1) {
console.log(outputBuf.substr(0, nl));
outputBuf = outputBuf.substr(nl + 1);
console.log(outputBuf.substring(0, nl));
outputBuf = outputBuf.substring(nl + 1);
}
return buf.length;
},
Expand Down Expand Up @@ -85,8 +59,8 @@
};
}

if (!global.process) {
global.process = {
if (!globalThis.process) {
globalThis.process = {
getuid() { return -1; },
getgid() { return -1; },
geteuid() { return -1; },
Expand All @@ -100,41 +74,29 @@
}
}

if (!global.crypto) {
const nodeCrypto = require("node:crypto");
global.crypto = {
getRandomValues(b) {
nodeCrypto.randomFillSync(b);
},
};
if (!globalThis.crypto) {
throw new Error("globalThis.crypto is not available, polyfill required (crypto.getRandomValues only)");
}

if (!global.performance) {
global.performance = {
now() {
const [sec, nsec] = process.hrtime();
return sec * 1000 + nsec / 1000000;
},
};
if (!globalThis.performance) {
throw new Error("globalThis.performance is not available, polyfill required (performance.now only)");
}

if (!global.TextEncoder) {
global.TextEncoder = require("node:util").TextEncoder;
if (!globalThis.TextEncoder) {
throw new Error("globalThis.TextEncoder is not available, polyfill required");
}

if (!global.TextDecoder) {
global.TextDecoder = require("node:util").TextDecoder;
if (!globalThis.TextDecoder) {
throw new Error("globalThis.TextDecoder is not available, polyfill required");
}

// End of polyfills for common API.

const encoder = new TextEncoder("utf-8");
const decoder = new TextDecoder("utf-8");
let reinterpretBuf = new DataView(new ArrayBuffer(8));
var logLine = [];
const wasmExit = {}; // thrown to exit via proc_exit (not an error)

global.Go = class {
globalThis.Go = class {
constructor() {
this._callbackTimeouts = new Map();
this._nextCallbackTimeoutID = 1;
Expand Down Expand Up @@ -248,13 +210,13 @@
nwritten_ptr >>>= 0;
let nwritten = 0;
if (fd == 1) {
for (let iovs_i=0; iovs_i<iovs_len;iovs_i++) {
let iov_ptr = iovs_ptr+iovs_i*8; // assuming wasm32
for (let iovs_i = 0; iovs_i < iovs_len; iovs_i++) {
let iov_ptr = iovs_ptr + iovs_i * 8; // assuming wasm32
let ptr = mem().getUint32(iov_ptr + 0, true);
let len = mem().getUint32(iov_ptr + 4, true);
nwritten += len;
for (let i=0; i<len; i++) {
let c = mem().getUint8(ptr+i);
for (let i = 0; i < len; i++) {
let c = mem().getUint8(ptr + i);
if (c == 13) { // CR
// ignore
} else if (c == 10) { // LF
Expand Down Expand Up @@ -316,7 +278,7 @@
} catch (e) {
if (e !== wasmExit) throw e;
}
}, Number(timeout)/1e6);
}, Number(timeout) / 1e6);
},

// func finalizeRef(v ref)
Expand Down Expand Up @@ -432,7 +394,7 @@
mem().setUint8(ret_addr + 8, 1);
} catch (err) {
storeValue(ret_addr, err);
mem().setUint8(ret_addr+ 8, 0);
mem().setUint8(ret_addr + 8, 0);
}
},

Expand Down Expand Up @@ -460,7 +422,7 @@

// func valueInstanceOf(v ref, t ref) bool
"syscall/js.valueInstanceOf": (v_ref, t_ref) => {
return unboxValue(v_ref) instanceof unboxValue(t_ref);
return unboxValue(v_ref) instanceof unboxValue(t_ref);
},

// func copyBytesToGo(dst []byte, src ref) (int, bool)
Expand Down Expand Up @@ -520,7 +482,7 @@
null,
true,
false,
global,
globalThis,
this,
];
this._goRefCounts = []; // number of references that Go has to a JS value, indexed by reference id
Expand Down Expand Up @@ -565,34 +527,13 @@

_makeFuncWrapper(id) {
const go = this;
return function () {
return function() {
const event = { id: id, this: this, args: arguments };
go._pendingEvent = event;
go._resume();
return event.result;
};
}
}

if (
global.require &&
global.require.main === module &&
global.process &&
global.process.versions &&
!global.process.versions.electron
) {
if (process.argv.length != 3) {
console.error("usage: go_js_wasm_exec [wasm binary] [arguments]");
process.exit(1);
}

const go = new Go();
WebAssembly.instantiate(fs.readFileSync(process.argv[2]), go.importObject).then(async (result) => {
let exitCode = await go.run(result.instance);
process.exit(exitCode);
}).catch((err) => {
console.error(err);
process.exit(1);
});
}
})();

32 changes: 32 additions & 0 deletions targets/wasm_exec_node.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//
// This file has been modified for use by the TinyGo compiler.
"use strict";

if (process.argv.length < 3) {
console.error("usage: go_js_wasm_exec [wasm binary] [arguments]");
process.exit(1);
}

globalThis.require = require;
globalThis.fs = require("fs");

globalThis.performance = {
now() {
const [sec, nsec] = process.hrtime();
return sec * 1000 + nsec / 1000000;
},
};

require("./wasm_exec");

const go = new Go();
WebAssembly.instantiate(fs.readFileSync(process.argv[2]), go.importObject).then(async (result) => {
let exitCode = await go.run(result.instance);
process.exit(exitCode);
}).catch((err) => {
console.error(err);
process.exit(1);
});
2 changes: 2 additions & 0 deletions testdata/wasmexit.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
const fs = require('fs')

require('../targets/wasm_exec.js');

function runTests() {
Expand Down
2 changes: 2 additions & 0 deletions testdata/wasmexport.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
const fs = require('fs')

require('../targets/wasm_exec.js');

function runTests() {
Expand Down
2 changes: 2 additions & 0 deletions testdata/wasmfunc.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
const fs = require('fs')

require('../targets/wasm_exec.js');

var callback;
Expand Down
Loading