@astrojs/compiler 0.10.1 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -0
- package/astro.wasm +0 -0
- package/browser/index.js +1 -7
- package/browser/wasm_exec.d.ts +29 -1
- package/browser/wasm_exec.js +249 -192
- package/node/index.js +1 -7
- package/node/wasm_exec.d.ts +29 -1
- package/node/wasm_exec.js +270 -207
- package/package.json +1 -1
package/node/wasm_exec.js
CHANGED
|
@@ -4,97 +4,92 @@
|
|
|
4
4
|
// Use of this source code is governed by a BSD-style
|
|
5
5
|
// license that can be found in the LICENSE file.
|
|
6
6
|
//
|
|
7
|
-
// This file has been modified for use by
|
|
8
|
-
// This file has been further modified for use by Astro.
|
|
7
|
+
// This file has been modified for use by Astro.
|
|
9
8
|
import fs from 'fs';
|
|
10
9
|
import crypto from 'crypto';
|
|
11
10
|
import { TextEncoder, TextDecoder } from 'util';
|
|
12
|
-
|
|
13
|
-
fs
|
|
11
|
+
if (!globalThis.fs) {
|
|
12
|
+
Object.defineProperty(globalThis, 'fs', {
|
|
14
13
|
value: fs,
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
if (!globalThis.process) {
|
|
17
|
+
Object.defineProperties(globalThis, 'process', {
|
|
18
|
+
value: process,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
if (!globalThis.crypto) {
|
|
22
|
+
Object.defineProperty(globalThis, 'crypto', {
|
|
18
23
|
value: {
|
|
19
24
|
getRandomValues(b) {
|
|
20
|
-
crypto.randomFillSync(b);
|
|
25
|
+
return crypto.randomFillSync(b);
|
|
21
26
|
},
|
|
22
27
|
},
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
if (!globalThis.performance) {
|
|
31
|
+
Object.defineProperty(globalThis, 'performance', {
|
|
26
32
|
value: {
|
|
27
33
|
now() {
|
|
28
34
|
const [sec, nsec] = process.hrtime();
|
|
29
35
|
return sec * 1000 + nsec / 1000000;
|
|
30
36
|
},
|
|
31
37
|
},
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
// End of polyfills for common API.
|
|
35
41
|
const encoder = new TextEncoder('utf-8');
|
|
36
42
|
const decoder = new TextDecoder('utf-8');
|
|
37
|
-
|
|
43
|
+
var logLine = [];
|
|
38
44
|
export default class Go {
|
|
39
45
|
constructor() {
|
|
40
|
-
this.
|
|
41
|
-
this.
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
46
|
+
this.argv = ['js'];
|
|
47
|
+
this.env = {};
|
|
48
|
+
this.exit = (code) => {
|
|
49
|
+
if (code !== 0) {
|
|
50
|
+
console.warn('exit code:', code);
|
|
51
|
+
}
|
|
45
52
|
};
|
|
53
|
+
this._exitPromise = new Promise((resolve) => {
|
|
54
|
+
this._resolveExitPromise = resolve;
|
|
55
|
+
});
|
|
56
|
+
this._pendingEvent = null;
|
|
57
|
+
this._scheduledTimeouts = new Map();
|
|
58
|
+
this._nextCallbackTimeoutID = 1;
|
|
46
59
|
const setInt64 = (addr, v) => {
|
|
47
|
-
mem
|
|
48
|
-
mem
|
|
60
|
+
this.mem.setUint32(addr + 0, v, true);
|
|
61
|
+
this.mem.setUint32(addr + 4, Math.floor(v / 4294967296), true);
|
|
49
62
|
};
|
|
50
63
|
const getInt64 = (addr) => {
|
|
51
|
-
const low = mem
|
|
52
|
-
const high = mem
|
|
64
|
+
const low = this.mem.getUint32(addr + 0, true);
|
|
65
|
+
const high = this.mem.getInt32(addr + 4, true);
|
|
53
66
|
return low + high * 4294967296;
|
|
54
67
|
};
|
|
55
68
|
const loadValue = (addr) => {
|
|
56
|
-
const f = mem
|
|
69
|
+
const f = this.mem.getFloat64(addr, true);
|
|
57
70
|
if (f === 0) {
|
|
58
71
|
return undefined;
|
|
59
72
|
}
|
|
60
73
|
if (!isNaN(f)) {
|
|
61
74
|
return f;
|
|
62
75
|
}
|
|
63
|
-
const id = mem
|
|
76
|
+
const id = this.mem.getUint32(addr, true);
|
|
64
77
|
return this._values[id];
|
|
65
78
|
};
|
|
66
79
|
const storeValue = (addr, v) => {
|
|
67
80
|
const nanHead = 0x7ff80000;
|
|
68
|
-
if (typeof v === 'number') {
|
|
81
|
+
if (typeof v === 'number' && v !== 0) {
|
|
69
82
|
if (isNaN(v)) {
|
|
70
|
-
mem
|
|
71
|
-
mem
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
if (v === 0) {
|
|
75
|
-
mem().setUint32(addr + 4, nanHead, true);
|
|
76
|
-
mem().setUint32(addr, 1, true);
|
|
83
|
+
this.mem.setUint32(addr + 4, nanHead, true);
|
|
84
|
+
this.mem.setUint32(addr, 0, true);
|
|
77
85
|
return;
|
|
78
86
|
}
|
|
79
|
-
mem
|
|
87
|
+
this.mem.setFloat64(addr, v, true);
|
|
80
88
|
return;
|
|
81
89
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
return;
|
|
86
|
-
case null:
|
|
87
|
-
mem().setUint32(addr + 4, nanHead, true);
|
|
88
|
-
mem().setUint32(addr, 2, true);
|
|
89
|
-
return;
|
|
90
|
-
case true:
|
|
91
|
-
mem().setUint32(addr + 4, nanHead, true);
|
|
92
|
-
mem().setUint32(addr, 3, true);
|
|
93
|
-
return;
|
|
94
|
-
case false:
|
|
95
|
-
mem().setUint32(addr + 4, nanHead, true);
|
|
96
|
-
mem().setUint32(addr, 4, true);
|
|
97
|
-
return;
|
|
90
|
+
if (v === undefined) {
|
|
91
|
+
this.mem.setFloat64(addr, 0, true);
|
|
92
|
+
return;
|
|
98
93
|
}
|
|
99
94
|
let id = this._ids.get(v);
|
|
100
95
|
if (id === undefined) {
|
|
@@ -107,8 +102,13 @@ export default class Go {
|
|
|
107
102
|
this._ids.set(v, id);
|
|
108
103
|
}
|
|
109
104
|
this._goRefCounts[id]++;
|
|
110
|
-
let typeFlag =
|
|
105
|
+
let typeFlag = 0;
|
|
111
106
|
switch (typeof v) {
|
|
107
|
+
case 'object':
|
|
108
|
+
if (v !== null) {
|
|
109
|
+
typeFlag = 1;
|
|
110
|
+
}
|
|
111
|
+
break;
|
|
112
112
|
case 'string':
|
|
113
113
|
typeFlag = 2;
|
|
114
114
|
break;
|
|
@@ -119,84 +119,105 @@ export default class Go {
|
|
|
119
119
|
typeFlag = 4;
|
|
120
120
|
break;
|
|
121
121
|
}
|
|
122
|
-
mem
|
|
123
|
-
mem
|
|
122
|
+
this.mem.setUint32(addr + 4, nanHead | typeFlag, true);
|
|
123
|
+
this.mem.setUint32(addr, id, true);
|
|
124
124
|
};
|
|
125
|
-
const loadSlice = (
|
|
126
|
-
|
|
125
|
+
const loadSlice = (addr) => {
|
|
126
|
+
const array = getInt64(addr + 0);
|
|
127
|
+
const len = getInt64(addr + 8);
|
|
128
|
+
return new Uint8Array(this._inst.exports.mem.buffer, array, len);
|
|
127
129
|
};
|
|
128
|
-
const loadSliceOfValues = (
|
|
130
|
+
const loadSliceOfValues = (addr) => {
|
|
131
|
+
const array = getInt64(addr + 0);
|
|
132
|
+
const len = getInt64(addr + 8);
|
|
129
133
|
const a = new Array(len);
|
|
130
134
|
for (let i = 0; i < len; i++) {
|
|
131
135
|
a[i] = loadValue(array + i * 8);
|
|
132
136
|
}
|
|
133
137
|
return a;
|
|
134
138
|
};
|
|
135
|
-
const loadString = (
|
|
136
|
-
|
|
139
|
+
const loadString = (addr) => {
|
|
140
|
+
const saddr = getInt64(addr + 0);
|
|
141
|
+
const len = getInt64(addr + 8);
|
|
142
|
+
return decoder.decode(new DataView(this._inst.exports.mem.buffer, saddr, len));
|
|
137
143
|
};
|
|
138
144
|
const timeOrigin = Date.now() - performance.now();
|
|
139
145
|
this.importObject = {
|
|
140
|
-
|
|
141
|
-
//
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
// LF
|
|
157
|
-
// write line
|
|
158
|
-
let line = decoder.decode(new Uint8Array(logLine));
|
|
159
|
-
logLine = [];
|
|
160
|
-
console.log(line);
|
|
161
|
-
}
|
|
162
|
-
else {
|
|
163
|
-
logLine.push(c);
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
else {
|
|
169
|
-
console.error('invalid file descriptor:', fd);
|
|
170
|
-
}
|
|
171
|
-
mem().setUint32(nwritten_ptr, nwritten, true);
|
|
172
|
-
return 0;
|
|
146
|
+
go: {
|
|
147
|
+
// Go's SP does not change as long as no Go code is running. Some operations (e.g. calls, getters and setters)
|
|
148
|
+
// may synchronously trigger a Go event handler. This makes Go code get executed in the middle of the imported
|
|
149
|
+
// function. A goroutine can switch to a new stack if the current stack is too small (see morestack function).
|
|
150
|
+
// This changes the SP, thus we have to update the SP used by the imported function.
|
|
151
|
+
// func wasmExit(code int32)
|
|
152
|
+
'runtime.wasmExit': (sp) => {
|
|
153
|
+
sp >>>= 0;
|
|
154
|
+
const code = this.mem.getInt32(sp + 8, true);
|
|
155
|
+
this.exited = true;
|
|
156
|
+
delete this._inst;
|
|
157
|
+
delete this._values;
|
|
158
|
+
delete this._goRefCounts;
|
|
159
|
+
delete this._ids;
|
|
160
|
+
delete this._idPool;
|
|
161
|
+
this.exit(code);
|
|
173
162
|
},
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
throw 'trying to exit with code ' + code;
|
|
182
|
-
}
|
|
163
|
+
// func wasmWrite(fd uintptr, p unsafe.Pointer, n int32)
|
|
164
|
+
'runtime.wasmWrite': (sp) => {
|
|
165
|
+
sp >>>= 0;
|
|
166
|
+
const fd = getInt64(sp + 8);
|
|
167
|
+
const p = getInt64(sp + 16);
|
|
168
|
+
const n = this.mem.getInt32(sp + 24, true);
|
|
169
|
+
fs.writeSync(fd, new Uint8Array(this._inst.exports.mem.buffer, p, n));
|
|
183
170
|
},
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
171
|
+
// func resetMemoryDataView()
|
|
172
|
+
'runtime.resetMemoryDataView': (sp) => {
|
|
173
|
+
sp >>>= 0;
|
|
174
|
+
this.mem = new DataView(this._inst.exports.mem.buffer);
|
|
175
|
+
},
|
|
176
|
+
// func nanotime1() int64
|
|
177
|
+
'runtime.nanotime1': (sp) => {
|
|
178
|
+
sp >>>= 0;
|
|
179
|
+
setInt64(sp + 8, (timeOrigin + performance.now()) * 1000000);
|
|
180
|
+
},
|
|
181
|
+
// func walltime() (sec int64, nsec int32)
|
|
182
|
+
'runtime.walltime': (sp) => {
|
|
183
|
+
sp >>>= 0;
|
|
184
|
+
const msec = new Date().getTime();
|
|
185
|
+
setInt64(sp + 8, msec / 1000);
|
|
186
|
+
this.mem.setInt32(sp + 16, (msec % 1000) * 1000000, true);
|
|
187
|
+
},
|
|
188
|
+
// func scheduleTimeoutEvent(delay int64) int32
|
|
189
|
+
'runtime.scheduleTimeoutEvent': (sp) => {
|
|
190
|
+
sp >>>= 0;
|
|
191
|
+
const id = this._nextCallbackTimeoutID;
|
|
192
|
+
this._nextCallbackTimeoutID++;
|
|
193
|
+
this._scheduledTimeouts.set(id, setTimeout(() => {
|
|
194
|
+
this._resume();
|
|
195
|
+
while (this._scheduledTimeouts.has(id)) {
|
|
196
|
+
// for some reason Go failed to register the timeout event, log and try again
|
|
197
|
+
// (temporary workaround for https://github.com/golang/go/issues/28975)
|
|
198
|
+
console.warn('scheduleTimeoutEvent: missed timeout event');
|
|
199
|
+
this._resume();
|
|
200
|
+
}
|
|
201
|
+
}, getInt64(sp + 8) + 1 // setTimeout has been seen to fire up to 1 millisecond early
|
|
202
|
+
));
|
|
203
|
+
this.mem.setInt32(sp + 16, id, true);
|
|
204
|
+
},
|
|
205
|
+
// func clearTimeoutEvent(id int32)
|
|
206
|
+
'runtime.clearTimeoutEvent': (sp) => {
|
|
207
|
+
sp >>>= 0;
|
|
208
|
+
const id = this.mem.getInt32(sp + 8, true);
|
|
209
|
+
clearTimeout(this._scheduledTimeouts.get(id));
|
|
210
|
+
this._scheduledTimeouts.delete(id);
|
|
189
211
|
},
|
|
190
|
-
// func
|
|
191
|
-
'runtime.
|
|
192
|
-
|
|
193
|
-
|
|
212
|
+
// func getRandomData(r []byte)
|
|
213
|
+
'runtime.getRandomData': (sp) => {
|
|
214
|
+
sp >>>= 0;
|
|
215
|
+
globalThis.crypto.getRandomValues(loadSlice(sp + 8));
|
|
194
216
|
},
|
|
195
217
|
// func finalizeRef(v ref)
|
|
196
|
-
'syscall/js.finalizeRef': (
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
const id = mem().getUint32(v_addr, true);
|
|
218
|
+
'syscall/js.finalizeRef': (sp) => {
|
|
219
|
+
sp >>>= 0;
|
|
220
|
+
const id = this.mem.getUint32(sp + 8, true);
|
|
200
221
|
this._goRefCounts[id]--;
|
|
201
222
|
if (this._goRefCounts[id] === 0) {
|
|
202
223
|
const v = this._values[id];
|
|
@@ -206,136 +227,152 @@ export default class Go {
|
|
|
206
227
|
}
|
|
207
228
|
},
|
|
208
229
|
// func stringVal(value string) ref
|
|
209
|
-
'syscall/js.stringVal': (
|
|
210
|
-
|
|
211
|
-
storeValue(
|
|
230
|
+
'syscall/js.stringVal': (sp) => {
|
|
231
|
+
sp >>>= 0;
|
|
232
|
+
storeValue(sp + 24, loadString(sp + 8));
|
|
212
233
|
},
|
|
213
234
|
// func valueGet(v ref, p string) ref
|
|
214
|
-
'syscall/js.valueGet': (
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
storeValue(
|
|
235
|
+
'syscall/js.valueGet': (sp) => {
|
|
236
|
+
sp >>>= 0;
|
|
237
|
+
const result = Reflect.get(loadValue(sp + 8), loadString(sp + 16));
|
|
238
|
+
sp = this._inst.exports.getsp() >>> 0; // see comment above
|
|
239
|
+
storeValue(sp + 32, result);
|
|
219
240
|
},
|
|
220
241
|
// func valueSet(v ref, p string, x ref)
|
|
221
|
-
'syscall/js.valueSet': (
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
const x = loadValue(x_addr);
|
|
225
|
-
Reflect.set(v, p, x);
|
|
242
|
+
'syscall/js.valueSet': (sp) => {
|
|
243
|
+
sp >>>= 0;
|
|
244
|
+
Reflect.set(loadValue(sp + 8), loadString(sp + 16), loadValue(sp + 32));
|
|
226
245
|
},
|
|
227
246
|
// func valueDelete(v ref, p string)
|
|
228
|
-
'syscall/js.valueDelete': (
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
Reflect.deleteProperty(v, p);
|
|
247
|
+
'syscall/js.valueDelete': (sp) => {
|
|
248
|
+
sp >>>= 0;
|
|
249
|
+
Reflect.deleteProperty(loadValue(sp + 8), loadString(sp + 16));
|
|
232
250
|
},
|
|
233
251
|
// func valueIndex(v ref, i int) ref
|
|
234
|
-
'syscall/js.valueIndex': (
|
|
235
|
-
|
|
252
|
+
'syscall/js.valueIndex': (sp) => {
|
|
253
|
+
sp >>>= 0;
|
|
254
|
+
storeValue(sp + 24, Reflect.get(loadValue(sp + 8), getInt64(sp + 16)));
|
|
236
255
|
},
|
|
237
256
|
// valueSetIndex(v ref, i int, x ref)
|
|
238
|
-
'syscall/js.valueSetIndex': (
|
|
239
|
-
|
|
257
|
+
'syscall/js.valueSetIndex': (sp) => {
|
|
258
|
+
sp >>>= 0;
|
|
259
|
+
Reflect.set(loadValue(sp + 8), getInt64(sp + 16), loadValue(sp + 24));
|
|
240
260
|
},
|
|
241
261
|
// func valueCall(v ref, m string, args []ref) (ref, bool)
|
|
242
|
-
'syscall/js.valueCall': (
|
|
243
|
-
|
|
244
|
-
const name = loadString(m_ptr, m_len);
|
|
245
|
-
const args = loadSliceOfValues(args_ptr, args_len, args_cap);
|
|
262
|
+
'syscall/js.valueCall': (sp) => {
|
|
263
|
+
sp >>>= 0;
|
|
246
264
|
try {
|
|
247
|
-
const
|
|
248
|
-
|
|
249
|
-
|
|
265
|
+
const v = loadValue(sp + 8);
|
|
266
|
+
const m = Reflect.get(v, loadString(sp + 16));
|
|
267
|
+
const args = loadSliceOfValues(sp + 32);
|
|
268
|
+
const result = Reflect.apply(m, v, args);
|
|
269
|
+
sp = this._inst.exports.getsp() >>> 0; // see comment above
|
|
270
|
+
storeValue(sp + 56, result);
|
|
271
|
+
this.mem.setUint8(sp + 64, 1);
|
|
250
272
|
}
|
|
251
273
|
catch (err) {
|
|
252
|
-
|
|
253
|
-
|
|
274
|
+
sp = this._inst.exports.getsp() >>> 0; // see comment above
|
|
275
|
+
storeValue(sp + 56, err);
|
|
276
|
+
this.mem.setUint8(sp + 64, 0);
|
|
254
277
|
}
|
|
255
278
|
},
|
|
256
279
|
// func valueInvoke(v ref, args []ref) (ref, bool)
|
|
257
|
-
'syscall/js.valueInvoke': (
|
|
280
|
+
'syscall/js.valueInvoke': (sp) => {
|
|
281
|
+
sp >>>= 0;
|
|
258
282
|
try {
|
|
259
|
-
const v = loadValue(
|
|
260
|
-
const args = loadSliceOfValues(
|
|
261
|
-
|
|
262
|
-
|
|
283
|
+
const v = loadValue(sp + 8);
|
|
284
|
+
const args = loadSliceOfValues(sp + 16);
|
|
285
|
+
const result = Reflect.apply(v, undefined, args);
|
|
286
|
+
sp = this._inst.exports.getsp() >>> 0; // see comment above
|
|
287
|
+
storeValue(sp + 40, result);
|
|
288
|
+
this.mem.setUint8(sp + 48, 1);
|
|
263
289
|
}
|
|
264
290
|
catch (err) {
|
|
265
|
-
|
|
266
|
-
|
|
291
|
+
sp = this._inst.exports.getsp() >>> 0; // see comment above
|
|
292
|
+
storeValue(sp + 40, err);
|
|
293
|
+
this.mem.setUint8(sp + 48, 0);
|
|
267
294
|
}
|
|
268
295
|
},
|
|
269
296
|
// func valueNew(v ref, args []ref) (ref, bool)
|
|
270
|
-
'syscall/js.valueNew': (
|
|
271
|
-
|
|
272
|
-
const args = loadSliceOfValues(args_ptr, args_len, args_cap);
|
|
297
|
+
'syscall/js.valueNew': (sp) => {
|
|
298
|
+
sp >>>= 0;
|
|
273
299
|
try {
|
|
274
|
-
|
|
275
|
-
|
|
300
|
+
const v = loadValue(sp + 8);
|
|
301
|
+
const args = loadSliceOfValues(sp + 16);
|
|
302
|
+
const result = Reflect.construct(v, args);
|
|
303
|
+
sp = this._inst.exports.getsp() >>> 0; // see comment above
|
|
304
|
+
storeValue(sp + 40, result);
|
|
305
|
+
this.mem.setUint8(sp + 48, 1);
|
|
276
306
|
}
|
|
277
307
|
catch (err) {
|
|
278
|
-
|
|
279
|
-
|
|
308
|
+
sp = this._inst.exports.getsp() >>> 0; // see comment above
|
|
309
|
+
storeValue(sp + 40, err);
|
|
310
|
+
this.mem.setUint8(sp + 48, 0);
|
|
280
311
|
}
|
|
281
312
|
},
|
|
282
313
|
// func valueLength(v ref) int
|
|
283
|
-
'syscall/js.valueLength': (
|
|
284
|
-
|
|
314
|
+
'syscall/js.valueLength': (sp) => {
|
|
315
|
+
sp >>>= 0;
|
|
316
|
+
setInt64(sp + 16, parseInt(loadValue(sp + 8).length));
|
|
285
317
|
},
|
|
286
318
|
// valuePrepareString(v ref) (ref, int)
|
|
287
|
-
'syscall/js.valuePrepareString': (
|
|
288
|
-
|
|
289
|
-
const str = encoder.encode(
|
|
290
|
-
storeValue(
|
|
291
|
-
setInt64(
|
|
319
|
+
'syscall/js.valuePrepareString': (sp) => {
|
|
320
|
+
sp >>>= 0;
|
|
321
|
+
const str = encoder.encode(String(loadValue(sp + 8)));
|
|
322
|
+
storeValue(sp + 16, str);
|
|
323
|
+
setInt64(sp + 24, str.length);
|
|
292
324
|
},
|
|
293
325
|
// valueLoadString(v ref, b []byte)
|
|
294
|
-
'syscall/js.valueLoadString': (
|
|
295
|
-
|
|
296
|
-
|
|
326
|
+
'syscall/js.valueLoadString': (sp) => {
|
|
327
|
+
sp >>>= 0;
|
|
328
|
+
const str = loadValue(sp + 8);
|
|
329
|
+
loadSlice(sp + 16).set(str);
|
|
297
330
|
},
|
|
298
331
|
// func valueInstanceOf(v ref, t ref) bool
|
|
299
|
-
'syscall/js.valueInstanceOf': (
|
|
300
|
-
|
|
332
|
+
'syscall/js.valueInstanceOf': (sp) => {
|
|
333
|
+
sp >>>= 0;
|
|
334
|
+
this.mem.setUint8(sp + 24, loadValue(sp + 8) instanceof loadValue(sp + 16) ? 1 : 0);
|
|
301
335
|
},
|
|
302
336
|
// func copyBytesToGo(dst []byte, src ref) (int, bool)
|
|
303
|
-
'syscall/js.copyBytesToGo': (
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
const
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
mem().setUint8(returned_status_addr, 0); // Return "not ok" status
|
|
337
|
+
'syscall/js.copyBytesToGo': (sp) => {
|
|
338
|
+
sp >>>= 0;
|
|
339
|
+
const dst = loadSlice(sp + 8);
|
|
340
|
+
const src = loadValue(sp + 32);
|
|
341
|
+
if (!(src instanceof Uint8Array || src instanceof Uint8ClampedArray)) {
|
|
342
|
+
this.mem.setUint8(sp + 48, 0);
|
|
310
343
|
return;
|
|
311
344
|
}
|
|
312
345
|
const toCopy = src.subarray(0, dst.length);
|
|
313
346
|
dst.set(toCopy);
|
|
314
|
-
setInt64(
|
|
315
|
-
mem
|
|
347
|
+
setInt64(sp + 40, toCopy.length);
|
|
348
|
+
this.mem.setUint8(sp + 48, 1);
|
|
316
349
|
},
|
|
317
|
-
// copyBytesToJS(dst ref, src []byte) (int, bool)
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
const src = loadSlice(source_addr, source_len);
|
|
325
|
-
if (!(dst instanceof Uint8Array)) {
|
|
326
|
-
mem().setUint8(returned_status_addr, 0); // Return "not ok" status
|
|
350
|
+
// func copyBytesToJS(dst ref, src []byte) (int, bool)
|
|
351
|
+
'syscall/js.copyBytesToJS': (sp) => {
|
|
352
|
+
sp >>>= 0;
|
|
353
|
+
const dst = loadValue(sp + 8);
|
|
354
|
+
const src = loadSlice(sp + 16);
|
|
355
|
+
if (!(dst instanceof Uint8Array || dst instanceof Uint8ClampedArray)) {
|
|
356
|
+
this.mem.setUint8(sp + 48, 0);
|
|
327
357
|
return;
|
|
328
358
|
}
|
|
329
359
|
const toCopy = src.subarray(0, dst.length);
|
|
330
360
|
dst.set(toCopy);
|
|
331
|
-
setInt64(
|
|
332
|
-
mem
|
|
361
|
+
setInt64(sp + 40, toCopy.length);
|
|
362
|
+
this.mem.setUint8(sp + 48, 1);
|
|
363
|
+
},
|
|
364
|
+
debug: (value) => {
|
|
365
|
+
console.log(value);
|
|
333
366
|
},
|
|
334
367
|
},
|
|
335
368
|
};
|
|
336
369
|
}
|
|
337
370
|
async run(instance) {
|
|
371
|
+
if (!(instance instanceof WebAssembly.Instance)) {
|
|
372
|
+
throw new Error('Go.run: WebAssembly.Instance expected');
|
|
373
|
+
}
|
|
338
374
|
this._inst = instance;
|
|
375
|
+
this.mem = new DataView(this._inst.exports.mem.buffer);
|
|
339
376
|
this._values = [
|
|
340
377
|
// JS values that Go currently has references to, indexed by reference id
|
|
341
378
|
NaN,
|
|
@@ -346,26 +383,52 @@ export default class Go {
|
|
|
346
383
|
globalThis,
|
|
347
384
|
this,
|
|
348
385
|
];
|
|
349
|
-
this._goRefCounts =
|
|
350
|
-
this._ids = new Map(
|
|
386
|
+
this._goRefCounts = new Array(this._values.length).fill(Infinity); // number of references that Go has to a JS value, indexed by reference id
|
|
387
|
+
this._ids = new Map([
|
|
388
|
+
// mapping from JS values to reference ids
|
|
389
|
+
[0, 1],
|
|
390
|
+
[null, 2],
|
|
391
|
+
[true, 3],
|
|
392
|
+
[false, 4],
|
|
393
|
+
[globalThis, 5],
|
|
394
|
+
[this, 6],
|
|
395
|
+
]);
|
|
351
396
|
this._idPool = []; // unused ids that have been garbage collected
|
|
352
397
|
this.exited = false; // whether the Go program has exited
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
});
|
|
363
|
-
this._inst.exports._start();
|
|
364
|
-
if (this.exited) {
|
|
365
|
-
break;
|
|
398
|
+
// Pass command line arguments and environment variables to WebAssembly by writing them to the linear memory.
|
|
399
|
+
let offset = 4096;
|
|
400
|
+
const strPtr = (str) => {
|
|
401
|
+
const ptr = offset;
|
|
402
|
+
const bytes = encoder.encode(str + '\0');
|
|
403
|
+
new Uint8Array(this.mem.buffer, offset, bytes.length).set(bytes);
|
|
404
|
+
offset += bytes.length;
|
|
405
|
+
if (offset % 8 !== 0) {
|
|
406
|
+
offset += 8 - (offset % 8);
|
|
366
407
|
}
|
|
367
|
-
|
|
408
|
+
return ptr;
|
|
409
|
+
};
|
|
410
|
+
const argc = this.argv.length;
|
|
411
|
+
const argvPtrs = [];
|
|
412
|
+
this.argv.forEach((arg) => {
|
|
413
|
+
argvPtrs.push(strPtr(arg));
|
|
414
|
+
});
|
|
415
|
+
argvPtrs.push(0);
|
|
416
|
+
const keys = Object.keys(this.env).sort();
|
|
417
|
+
keys.forEach((key) => {
|
|
418
|
+
argvPtrs.push(strPtr(`${key}=${this.env[key]}`));
|
|
419
|
+
});
|
|
420
|
+
argvPtrs.push(0);
|
|
421
|
+
const argv = offset;
|
|
422
|
+
argvPtrs.forEach((ptr) => {
|
|
423
|
+
this.mem.setUint32(offset, ptr, true);
|
|
424
|
+
this.mem.setUint32(offset + 4, 0, true);
|
|
425
|
+
offset += 8;
|
|
426
|
+
});
|
|
427
|
+
this._inst.exports.run(argc, argv);
|
|
428
|
+
if (this.exited) {
|
|
429
|
+
this._resolveExitPromise();
|
|
368
430
|
}
|
|
431
|
+
await this._exitPromise;
|
|
369
432
|
}
|
|
370
433
|
_resume() {
|
|
371
434
|
if (this.exited) {
|