[6a3a178] | 1 | #!/usr/bin/env node
|
---|
| 2 |
|
---|
| 3 | // Forward to the automatically-generated WebAssembly loader from the Go compiler
|
---|
| 4 |
|
---|
| 5 | const crypto = require('crypto');
|
---|
| 6 | const path = require('path');
|
---|
| 7 | const zlib = require('zlib');
|
---|
| 8 | const fs = require('fs');
|
---|
| 9 | const os = require('os');
|
---|
| 10 |
|
---|
| 11 | const wasm_exec = path.join(__dirname, '..', 'wasm_exec.js');
|
---|
| 12 | const esbuild_wasm = path.join(__dirname, '..', 'esbuild.wasm');
|
---|
| 13 |
|
---|
| 14 | const code = fs.readFileSync(wasm_exec, 'utf8');
|
---|
| 15 | const wrapper = new Function('require', 'module', 'process', 'WebAssembly', code);
|
---|
| 16 |
|
---|
| 17 | function instantiate(bytes, importObject) {
|
---|
| 18 | // Using this API causes "./esbuild --version" to run around 1 second faster
|
---|
| 19 | // than using the "WebAssembly.instantiate()" API when run in node (v12.16.2)
|
---|
| 20 | const module = new WebAssembly.Module(bytes);
|
---|
| 21 | const instance = new WebAssembly.Instance(module, importObject);
|
---|
| 22 | return Promise.resolve({ instance, module });
|
---|
| 23 | }
|
---|
| 24 |
|
---|
| 25 | // Node has an unfortunate bug where the node process is unnecessarily kept open while a
|
---|
| 26 | // WebAssembly module is being optimized: https://github.com/nodejs/node/issues/36616.
|
---|
| 27 | // This means cases where running "esbuild" should take a few milliseconds can end up
|
---|
| 28 | // taking many seconds instead. To work around this bug, it is possible to force node to
|
---|
| 29 | // exit by calling the operating system's exit function. That's what this code does.
|
---|
| 30 | process.on('exit', code => {
|
---|
| 31 | // If it's a non-zero exit code, we can just kill our own process to stop. This will
|
---|
| 32 | // preserve the fact that there is a non-zero exit code although the exit code will
|
---|
| 33 | // be different. We cannot use this if the exit code is supposed to be zero.
|
---|
| 34 | if (code !== 0) {
|
---|
| 35 | try {
|
---|
| 36 | process.kill(process.pid, 'SIGINT');
|
---|
| 37 | } catch (e) {
|
---|
| 38 | }
|
---|
| 39 | return;
|
---|
| 40 | }
|
---|
| 41 |
|
---|
| 42 | // Otherwise if the exit code is zero, try to fall back to a binary N-API module that
|
---|
| 43 | // calls the operating system's "exit(0)" function.
|
---|
| 44 | const nativeModule = `${process.platform}-${os.arch()}-${os.endianness()}.node`;
|
---|
| 45 | const base64 = require('../exit0')[nativeModule];
|
---|
| 46 | if (base64) {
|
---|
| 47 | try {
|
---|
| 48 | const data = zlib.inflateRawSync(Buffer.from(base64, 'base64'));
|
---|
| 49 | const hash = crypto.createHash('sha256').update(base64).digest().toString('hex').slice(0, 16);
|
---|
| 50 | const tempFile = path.join(os.tmpdir(), `${hash}-${nativeModule}`);
|
---|
| 51 | try {
|
---|
| 52 | if (fs.readFileSync(tempFile).equals(data)) {
|
---|
| 53 | require(tempFile);
|
---|
| 54 | }
|
---|
| 55 | } finally {
|
---|
| 56 | fs.writeFileSync(tempFile, data);
|
---|
| 57 | require(tempFile);
|
---|
| 58 | }
|
---|
| 59 | } catch (e) {
|
---|
| 60 | }
|
---|
| 61 | }
|
---|
| 62 | });
|
---|
| 63 |
|
---|
| 64 | // Node has another bug where using "fs.read" to read from stdin reads
|
---|
| 65 | // everything successfully and then throws an error, but only on Windows. Go's
|
---|
| 66 | // WebAssembly support uses "fs.read" so it hits this problem. This is a patch
|
---|
| 67 | // to try to work around the bug in node. This bug has been reported to node
|
---|
| 68 | // at least twice in https://github.com/nodejs/node/issues/35997 and in
|
---|
| 69 | // https://github.com/nodejs/node/issues/19831. This issue has also been
|
---|
| 70 | // reported to the Go project: https://github.com/golang/go/issues/43913.
|
---|
| 71 | const read = fs.read;
|
---|
| 72 | fs.read = function () {
|
---|
| 73 | const callback = arguments[5];
|
---|
| 74 | arguments[5] = function (err, count) {
|
---|
| 75 | if (count === 0 && err && err.code === 'EOF') {
|
---|
| 76 | arguments[0] = null;
|
---|
| 77 | }
|
---|
| 78 | return callback.apply(this, arguments);
|
---|
| 79 | };
|
---|
| 80 | return read.apply(this, arguments);
|
---|
| 81 | };
|
---|
| 82 |
|
---|
| 83 | const argv = ['node', wasm_exec, esbuild_wasm].concat(process.argv.slice(2));
|
---|
| 84 | wrapper(require, require.main, Object.assign(Object.create(process), { argv }), Object.assign(Object.create(WebAssembly), { instantiate }));
|
---|