|
2 | 2 | // Use of this source code is governed by a BSD-style
|
3 | 3 | // license that can be found in the LICENSE file.
|
4 | 4 |
|
5 |
| -(() => { |
6 |
| - // Map multiple JavaScript environments to a single common API, |
7 |
| - // preferring web standards over Node.js API. |
8 |
| - // |
9 |
| - // Environments considered: |
10 |
| - // - Browsers |
11 |
| - // - Node.js |
12 |
| - // - Electron |
13 |
| - // - Parcel |
14 |
| - // - Webpack |
15 |
| - |
16 |
| - if (typeof global !== "undefined") { |
17 |
| - // global already exists |
18 |
| - } else if (typeof window !== "undefined") { |
19 |
| - window.global = window; |
20 |
| - } else if (typeof self !== "undefined") { |
21 |
| - self.global = self; |
22 |
| - } else { |
23 |
| - throw new Error("cannot export Go (neither global, window nor self is defined)"); |
24 |
| - } |
25 |
| - |
26 |
| - if (!global.require && typeof require !== "undefined") { |
27 |
| - global.require = require; |
28 |
| - } |
29 |
| - |
30 |
| - if (!global.fs && global.require) { |
31 |
| - const fs = require("fs"); |
32 |
| - if (typeof fs === "object" && fs !== null && Object.keys(fs).length !== 0) { |
33 |
| - global.fs = fs; |
34 |
| - } |
35 |
| - } |
| 5 | +"use strict"; |
36 | 6 |
|
| 7 | +(() => { |
37 | 8 | const enosys = () => {
|
38 | 9 | const err = new Error("not implemented");
|
39 | 10 | err.code = "ENOSYS";
|
40 | 11 | return err;
|
41 | 12 | };
|
42 | 13 |
|
43 |
| - if (!global.fs) { |
| 14 | + if (!globalThis.fs) { |
44 | 15 | let outputBuf = "";
|
45 |
| - global.fs = { |
| 16 | + globalThis.fs = { |
46 | 17 | constants: { O_WRONLY: -1, O_RDWR: -1, O_CREAT: -1, O_TRUNC: -1, O_APPEND: -1, O_EXCL: -1 }, // unused
|
47 | 18 | writeSync(fd, buf) {
|
48 | 19 | outputBuf += decoder.decode(buf);
|
49 | 20 | const nl = outputBuf.lastIndexOf("\n");
|
50 | 21 | if (nl != -1) {
|
51 |
| - console.log(outputBuf.substr(0, nl)); |
52 |
| - outputBuf = outputBuf.substr(nl + 1); |
| 22 | + console.log(outputBuf.substring(0, nl)); |
| 23 | + outputBuf = outputBuf.substring(nl + 1); |
53 | 24 | }
|
54 | 25 | return buf.length;
|
55 | 26 | },
|
|
87 | 58 | };
|
88 | 59 | }
|
89 | 60 |
|
90 |
| - if (!global.process) { |
91 |
| - global.process = { |
| 61 | + if (!globalThis.process) { |
| 62 | + globalThis.process = { |
92 | 63 | getuid() { return -1; },
|
93 | 64 | getgid() { return -1; },
|
94 | 65 | geteuid() { return -1; },
|
|
102 | 73 | }
|
103 | 74 | }
|
104 | 75 |
|
105 |
| - if (!global.crypto && global.require) { |
106 |
| - const nodeCrypto = require("crypto"); |
107 |
| - global.crypto = { |
108 |
| - getRandomValues(b) { |
109 |
| - nodeCrypto.randomFillSync(b); |
110 |
| - }, |
111 |
| - }; |
112 |
| - } |
113 |
| - if (!global.crypto) { |
114 |
| - throw new Error("global.crypto is not available, polyfill required (getRandomValues only)"); |
| 76 | + if (!globalThis.crypto) { |
| 77 | + throw new Error("globalThis.crypto is not available, polyfill required (crypto.getRandomValues only)"); |
115 | 78 | }
|
116 | 79 |
|
117 |
| - if (!global.performance) { |
118 |
| - global.performance = { |
119 |
| - now() { |
120 |
| - const [sec, nsec] = process.hrtime(); |
121 |
| - return sec * 1000 + nsec / 1000000; |
122 |
| - }, |
123 |
| - }; |
| 80 | + if (!globalThis.performance) { |
| 81 | + throw new Error("globalThis.performance is not available, polyfill required (performance.now only)"); |
124 | 82 | }
|
125 | 83 |
|
126 |
| - if (!global.TextEncoder && global.require) { |
127 |
| - global.TextEncoder = require("util").TextEncoder; |
128 |
| - } |
129 |
| - if (!global.TextEncoder) { |
130 |
| - throw new Error("global.TextEncoder is not available, polyfill required"); |
| 84 | + if (!globalThis.TextEncoder) { |
| 85 | + throw new Error("globalThis.TextEncoder is not available, polyfill required"); |
131 | 86 | }
|
132 | 87 |
|
133 |
| - if (!global.TextDecoder && global.require) { |
134 |
| - global.TextDecoder = require("util").TextDecoder; |
| 88 | + if (!globalThis.TextDecoder) { |
| 89 | + throw new Error("globalThis.TextDecoder is not available, polyfill required"); |
135 | 90 | }
|
136 |
| - if (!global.TextDecoder) { |
137 |
| - throw new Error("global.TextDecoder is not available, polyfill required"); |
138 |
| - } |
139 |
| - |
140 |
| - // End of polyfills for common API. |
141 | 91 |
|
142 | 92 | const encoder = new TextEncoder("utf-8");
|
143 | 93 | const decoder = new TextDecoder("utf-8");
|
144 | 94 |
|
145 |
| - global.Go = class { |
| 95 | + globalThis.Go = class { |
146 | 96 | constructor() {
|
147 | 97 | this.argv = ["js"];
|
148 | 98 | this.env = {};
|
|
163 | 113 | this.mem.setUint32(addr + 4, Math.floor(v / 4294967296), true);
|
164 | 114 | }
|
165 | 115 |
|
| 116 | + const setInt32 = (addr, v) => { |
| 117 | + this.mem.setUint32(addr + 0, v, true); |
| 118 | + } |
| 119 | + |
166 | 120 | const getInt64 = (addr) => {
|
167 | 121 | const low = this.mem.getUint32(addr + 0, true);
|
168 | 122 | const high = this.mem.getInt32(addr + 4, true);
|
|
256 | 210 |
|
257 | 211 | const timeOrigin = Date.now() - performance.now();
|
258 | 212 | this.importObject = {
|
259 |
| - go: { |
| 213 | + _gotest: { |
| 214 | + add: (a, b) => a + b, |
| 215 | + }, |
| 216 | + gojs: { |
260 | 217 | // Go's SP does not change as long as no Go code is running. Some operations (e.g. calls, getters and setters)
|
261 | 218 | // may synchronously trigger a Go event handler. This makes Go code get executed in the middle of the imported
|
262 | 219 | // function. A goroutine can switch to a new stack if the current stack is too small (see morestack function).
|
|
319 | 276 | this._resume();
|
320 | 277 | }
|
321 | 278 | },
|
322 |
| - getInt64(sp + 8) + 1, // setTimeout has been seen to fire up to 1 millisecond early |
| 279 | + getInt64(sp + 8), |
323 | 280 | ));
|
324 | 281 | this.mem.setInt32(sp + 16, id, true);
|
325 | 282 | },
|
|
517 | 474 | null,
|
518 | 475 | true,
|
519 | 476 | false,
|
520 |
| - global, |
| 477 | + globalThis, |
521 | 478 | this,
|
522 | 479 | ];
|
523 | 480 | this._goRefCounts = new Array(this._values.length).fill(Infinity); // number of references that Go has to a JS value, indexed by reference id
|
|
526 | 483 | [null, 2],
|
527 | 484 | [true, 3],
|
528 | 485 | [false, 4],
|
529 |
| - [global, 5], |
| 486 | + [globalThis, 5], |
530 | 487 | [this, 6],
|
531 | 488 | ]);
|
532 | 489 | this._idPool = []; // unused ids that have been garbage collected
|
|
567 | 524 | offset += 8;
|
568 | 525 | });
|
569 | 526 |
|
| 527 | + // The linker guarantees global data starts from at least wasmMinDataAddr. |
| 528 | + // Keep in sync with cmd/link/internal/ld/data.go:wasmMinDataAddr. |
| 529 | + const wasmMinDataAddr = 4096 + 8192; |
| 530 | + if (offset >= wasmMinDataAddr) { |
| 531 | + throw new Error("total length of command line and environment variables exceeds limit"); |
| 532 | + } |
| 533 | + |
570 | 534 | this._inst.exports.run(argc, argv);
|
571 | 535 | if (this.exited) {
|
572 | 536 | this._resolveExitPromise();
|
|
594 | 558 | };
|
595 | 559 | }
|
596 | 560 | }
|
597 |
| - |
598 |
| - if ( |
599 |
| - typeof module !== "undefined" && |
600 |
| - global.require && |
601 |
| - global.require.main === module && |
602 |
| - global.process && |
603 |
| - global.process.versions && |
604 |
| - !global.process.versions.electron |
605 |
| - ) { |
606 |
| - if (process.argv.length < 3) { |
607 |
| - console.error("usage: go_js_wasm_exec [wasm binary] [arguments]"); |
608 |
| - process.exit(1); |
609 |
| - } |
610 |
| - |
611 |
| - const go = new Go(); |
612 |
| - go.argv = process.argv.slice(2); |
613 |
| - go.env = Object.assign({ TMPDIR: require("os").tmpdir() }, process.env); |
614 |
| - go.exit = process.exit; |
615 |
| - WebAssembly.instantiate(fs.readFileSync(process.argv[2]), go.importObject).then((result) => { |
616 |
| - process.on("exit", (code) => { // Node.js exits if no event handler is pending |
617 |
| - if (code === 0 && !go.exited) { |
618 |
| - // deadlock, make Go print error and stack traces |
619 |
| - go._pendingEvent = { id: 0 }; |
620 |
| - go._resume(); |
621 |
| - } |
622 |
| - }); |
623 |
| - return go.run(result.instance); |
624 |
| - }).catch((err) => { |
625 |
| - console.error(err); |
626 |
| - process.exit(1); |
627 |
| - }); |
628 |
| - } |
629 | 561 | })();
|
0 commit comments