Skip to content

Commit

Permalink
work around go 1.18 wasm changes
Browse files Browse the repository at this point in the history
  • Loading branch information
evanw committed Mar 25, 2022
1 parent 2b48929 commit 517f77f
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 44 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Expand Up @@ -8,12 +8,14 @@
/github/
/npm/esbuild-android-64/esbuild.wasm
/npm/esbuild-android-64/exit0.js
/npm/esbuild-android-64/wasm_exec_node.js
/npm/esbuild-android-64/wasm_exec.js
/npm/esbuild-wasm/browser.js
/npm/esbuild-wasm/esbuild.wasm
/npm/esbuild-wasm/esm/
/npm/esbuild-wasm/exit0.js
/npm/esbuild-wasm/lib/
/npm/esbuild-wasm/wasm_exec_node.js
/npm/esbuild-wasm/wasm_exec.js
/npm/esbuild/install.js
/npm/esbuild/lib/
Expand Down
4 changes: 2 additions & 2 deletions lib/npm/worker.ts
Expand Up @@ -5,7 +5,7 @@ declare function postMessage(message: any): void;

onmessage = ({ data: wasm }) => {
let decoder = new TextDecoder()
let fs = (global as any).fs
let fs = (globalThis as any).fs

let stderr = ''
fs.writeSync = (fd: number, buffer: Uint8Array) => {
Expand Down Expand Up @@ -57,7 +57,7 @@ onmessage = ({ data: wasm }) => {
callback(null, count)
}

let go = new (global as any).Go()
let go = new (globalThis as any).Go()
go.argv = ['', `--service=${ESBUILD_VERSION}`]

WebAssembly.instantiate(wasm, go.importObject)
Expand Down
42 changes: 37 additions & 5 deletions npm/esbuild-wasm/bin/esbuild
Expand Up @@ -2,17 +2,18 @@

// Forward to the automatically-generated WebAssembly loader from the Go compiler

const module_ = require('module');
const crypto = require('crypto');
const path = require('path');
const zlib = require('zlib');
const fs = require('fs');
const os = require('os');

const wasm_exec = path.join(__dirname, '..', 'wasm_exec.js');
const wasm_exec_node = path.join(__dirname, '..', 'wasm_exec_node.js');
const esbuild_wasm = path.join(__dirname, '..', 'esbuild.wasm');

const code = fs.readFileSync(wasm_exec, 'utf8');
const wrapper = new Function('require', 'module', 'process', 'WebAssembly', code);
const code = fs.readFileSync(wasm_exec_node, 'utf8');
const wrapper = new Function('require', 'WebAssembly', code);

function instantiate(bytes, importObject) {
// Using this API causes "./esbuild --version" to run around 1 second faster
Expand Down Expand Up @@ -80,6 +81,37 @@ fs.read = function () {
return read.apply(this, arguments);
};

// Hack around a Unicode bug in node: https://github.com/nodejs/node/issues/24550.
// See this for the matching Go issue: https://github.com/golang/go/issues/43917.
const write = fs.write;
fs.write = function (fd, buf, offset, length, position, callback) {
if (offset === 0 && length === buf.length && position === null) {
if (fd === process.stdout.fd) {
try {
process.stdout.write(buf, err => err ? callback(err, 0, null) : callback(null, length, buf));
} catch (err) {
callback(err, 0, null);
}
return;
}
if (fd === process.stderr.fd) {
try {
process.stderr.write(buf, err => err ? callback(err, 0, null) : callback(null, length, buf));
} catch (err) {
callback(err, 0, null);
}
return;
}
}
return write.apply(this, arguments);
};
const writeSync = fs.writeSync;
fs.writeSync = function (fd, buf) {
if (fd === process.stdout.fd) return process.stdout.write(buf), buf.length;
if (fd === process.stderr.fd) return process.stderr.write(buf), buf.length;
return writeSync.apply(this, arguments);
};

// WASM code generated with Go 1.17.2+ will crash when run in a situation with
// many environment variables: https://github.com/golang/go/issues/49011. An
// example of this situation is running a Go-compiled WASM executable in GitHub
Expand All @@ -97,5 +129,5 @@ for (let key in process.env) {
}
}

const argv = ['node', wasm_exec, esbuild_wasm].concat(process.argv.slice(2));
wrapper(require, require.main, Object.assign(Object.create(process), { argv }), Object.assign(Object.create(WebAssembly), { instantiate }));
process.argv.splice(2, 0, esbuild_wasm);
wrapper(module_.createRequire(wasm_exec_node), Object.assign(Object.create(WebAssembly), { instantiate }));
43 changes: 6 additions & 37 deletions scripts/esbuild.js
Expand Up @@ -106,41 +106,9 @@ exports.buildWasmLib = async (esbuildPath) => {
// Generate "npm/esbuild-wasm/wasm_exec.js"
const GOROOT = childProcess.execFileSync('go', ['env', 'GOROOT']).toString().trim();
let wasm_exec_js = fs.readFileSync(path.join(GOROOT, 'misc', 'wasm', 'wasm_exec.js'), 'utf8');
const replace = (toReplace, replacement) => {
if (wasm_exec_js.indexOf(toReplace) === -1) throw new Error(`Failed to find ${JSON.stringify(toReplace)} in Go JS shim code`);
wasm_exec_js = wasm_exec_js.replace(toReplace, replacement);
}
replace('global.fs = fs;', `
global.fs = Object.assign({}, fs, {
// Hack around a Unicode bug in node: https://github.com/nodejs/node/issues/24550
write(fd, buf, offset, length, position, callback) {
if (offset === 0 && length === buf.length && position === null) {
if (fd === process.stdout.fd) {
try {
process.stdout.write(buf, err => err ? callback(err, 0, null) : callback(null, length, buf));
} catch (err) {
callback(err, 0, null);
}
return;
}
if (fd === process.stderr.fd) {
try {
process.stderr.write(buf, err => err ? callback(err, 0, null) : callback(null, length, buf));
} catch (err) {
callback(err, 0, null);
}
return;
}
}
fs.write(fd, buf, offset, length, position, callback);
},
});
`);
replace('// End of polyfills for common API.', `
// Make sure Go sees the shadowed "fs" global
const { fs } = global;
`);
let wasm_exec_node_js = fs.readFileSync(path.join(GOROOT, 'misc', 'wasm', 'wasm_exec_node.js'), 'utf8');
fs.writeFileSync(path.join(npmWasmDir, 'wasm_exec.js'), wasm_exec_js);
fs.writeFileSync(path.join(npmWasmDir, 'wasm_exec_node.js'), wasm_exec_node_js);

// Generate "npm/esbuild-wasm/lib/main.js"
childProcess.execFileSync(esbuildPath, [
Expand Down Expand Up @@ -170,11 +138,11 @@ exports.buildWasmLib = async (esbuildPath) => {
// Process "npm/esbuild-wasm/wasm_exec.js" and "lib/worker.ts"
const input = `
let onmessage;
let global = {};
let globalThis = {};
for (let o = self; o; o = Object.getPrototypeOf(o))
for (let k of Object.getOwnPropertyNames(o))
if (!(k in global))
Object.defineProperty(global, k, { get: () => self[k] });
if (!(k in globalThis))
Object.defineProperty(globalThis, k, { get: () => self[k] });
${wasm_exec_js}
${fs.readFileSync(path.join(repoDir, 'lib', 'npm', 'worker.ts'), 'utf8')}
return m => onmessage(m)
Expand Down Expand Up @@ -248,6 +216,7 @@ module.exports = ${JSON.stringify(exit0Map, null, 2)};
for (const dir of npmWasmShimDirs) {
fs.mkdirSync(path.join(dir, 'bin'), { recursive: true })
fs.writeFileSync(path.join(dir, 'wasm_exec.js'), wasm_exec_js);
fs.writeFileSync(path.join(dir, 'wasm_exec_node.js'), wasm_exec_node_js);
fs.writeFileSync(path.join(dir, 'exit0.js'), exit0Code);
fs.copyFileSync(path.join(npmWasmDir, 'bin', 'esbuild'), path.join(dir, 'bin', 'esbuild'));
fs.copyFileSync(path.join(npmWasmDir, 'esbuild.wasm'), path.join(dir, 'esbuild.wasm'));
Expand Down

0 comments on commit 517f77f

Please sign in to comment.