@astrojs/compiler 0.10.2 → 0.11.1

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/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 the TinyGo compiler.
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
- Object.defineProperties(globalThis, {
13
- fs: {
11
+ if (!globalThis.fs) {
12
+ Object.defineProperty(globalThis, 'fs', {
14
13
  value: fs,
15
- enumerable: true,
16
- },
17
- crypto: {
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
- enumerable: true,
24
- },
25
- performance: {
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
- enumerable: true,
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
- let logLine = [];
43
+ var logLine = [];
38
44
  export default class Go {
39
45
  constructor() {
40
- this._callbackTimeouts = new Map();
41
- this._nextCallbackTimeoutID = 1;
42
- const mem = () => {
43
- // The buffer may change when requesting more memory.
44
- return new DataView(this._inst.exports.memory.buffer);
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().setUint32(addr + 0, v, true);
48
- mem().setUint32(addr + 4, Math.floor(v / 4294967296), true);
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().getUint32(addr + 0, true);
52
- const high = mem().getInt32(addr + 4, true);
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().getFloat64(addr, true);
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().getUint32(addr, true);
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().setUint32(addr + 4, nanHead, true);
71
- mem().setUint32(addr, 0, true);
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().setFloat64(addr, v, true);
87
+ this.mem.setFloat64(addr, v, true);
80
88
  return;
81
89
  }
82
- switch (v) {
83
- case undefined:
84
- mem().setFloat64(addr, 0, true);
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 = 1;
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().setUint32(addr + 4, nanHead | typeFlag, true);
123
- mem().setUint32(addr, id, true);
122
+ this.mem.setUint32(addr + 4, nanHead | typeFlag, true);
123
+ this.mem.setUint32(addr, id, true);
124
124
  };
125
- const loadSlice = (array, len, cap) => {
126
- return new Uint8Array(this._inst.exports.memory.buffer, array, len);
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 = (array, len, cap) => {
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 = (ptr, len) => {
136
- return decoder.decode(new DataView(this._inst.exports.memory.buffer, ptr, len));
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
- wasi_snapshot_preview1: {
141
- // https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#fd_write
142
- fd_write: function (fd, iovs_ptr, iovs_len, nwritten_ptr) {
143
- let nwritten = 0;
144
- if (fd == 1) {
145
- for (let iovs_i = 0; iovs_i < iovs_len; iovs_i++) {
146
- let iov_ptr = iovs_ptr + iovs_i * 8; // assuming wasm32
147
- let ptr = mem().getUint32(iov_ptr + 0, true);
148
- let len = mem().getUint32(iov_ptr + 4, true);
149
- for (let i = 0; i < len; i++) {
150
- let c = mem().getUint8(ptr + i);
151
- if (c == 13) {
152
- // CR
153
- // ignore
154
- }
155
- else if (c == 10) {
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
- proc_exit: (code) => {
175
- if (globalThis.process) {
176
- // Node.js
177
- process.exit(code);
178
- }
179
- else {
180
- // Can't exit in a browser.
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
- env: {
186
- // func ticks() float64
187
- 'runtime.ticks': () => {
188
- return timeOrigin + performance.now();
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 sleepTicks(timeout float64)
191
- 'runtime.sleepTicks': (timeout) => {
192
- // Do not sleep, only reactivate scheduler after the given timeout.
193
- setTimeout(this._inst.exports.go_scheduler, timeout);
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': (v_addr) => {
197
- // Note: TinyGo does not support finalizers so this is only called
198
- // for one specific case, by js.go:jsString.
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': (ret_ptr, value_ptr, value_len) => {
210
- const s = loadString(value_ptr, value_len);
211
- storeValue(ret_ptr, s);
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': (retval, v_addr, p_ptr, p_len) => {
215
- let prop = loadString(p_ptr, p_len);
216
- let value = loadValue(v_addr);
217
- let result = Reflect.get(value, prop);
218
- storeValue(retval, result);
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': (v_addr, p_ptr, p_len, x_addr) => {
222
- const v = loadValue(v_addr);
223
- const p = loadString(p_ptr, p_len);
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': (v_addr, p_ptr, p_len) => {
229
- const v = loadValue(v_addr);
230
- const p = loadString(p_ptr, p_len);
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': (ret_addr, v_addr, i) => {
235
- storeValue(ret_addr, Reflect.get(loadValue(v_addr), i));
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': (v_addr, i, x_addr) => {
239
- Reflect.set(loadValue(v_addr), i, loadValue(x_addr));
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': (ret_addr, v_addr, m_ptr, m_len, args_ptr, args_len, args_cap) => {
243
- const v = loadValue(v_addr);
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 m = Reflect.get(v, name);
248
- storeValue(ret_addr, Reflect.apply(m, v, args));
249
- mem().setUint8(ret_addr + 8, 1);
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
- storeValue(ret_addr, err);
253
- mem().setUint8(ret_addr + 8, 0);
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': (ret_addr, v_addr, args_ptr, args_len, args_cap) => {
280
+ 'syscall/js.valueInvoke': (sp) => {
281
+ sp >>>= 0;
258
282
  try {
259
- const v = loadValue(v_addr);
260
- const args = loadSliceOfValues(args_ptr, args_len, args_cap);
261
- storeValue(ret_addr, Reflect.apply(v, undefined, args));
262
- mem().setUint8(ret_addr + 8, 1);
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
- storeValue(ret_addr, err);
266
- mem().setUint8(ret_addr + 8, 0);
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': (ret_addr, v_addr, args_ptr, args_len, args_cap) => {
271
- const v = loadValue(v_addr);
272
- const args = loadSliceOfValues(args_ptr, args_len, args_cap);
297
+ 'syscall/js.valueNew': (sp) => {
298
+ sp >>>= 0;
273
299
  try {
274
- storeValue(ret_addr, Reflect.construct(v, args));
275
- mem().setUint8(ret_addr + 8, 1);
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
- storeValue(ret_addr, err);
279
- mem().setUint8(ret_addr + 8, 0);
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': (v_addr) => {
284
- return loadValue(v_addr).length;
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': (ret_addr, v_addr) => {
288
- const s = String(loadValue(v_addr));
289
- const str = encoder.encode(s);
290
- storeValue(ret_addr, str);
291
- setInt64(ret_addr + 8, str.length);
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': (v_addr, slice_ptr, slice_len, slice_cap) => {
295
- const str = loadValue(v_addr);
296
- loadSlice(slice_ptr, slice_len, slice_cap).set(str);
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': (v_addr, t_addr) => {
300
- return loadValue(v_addr) instanceof loadValue(t_addr);
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': (ret_addr, dest_addr, dest_len, dest_cap, source_addr) => {
304
- let num_bytes_copied_addr = ret_addr;
305
- let returned_status_addr = ret_addr + 4; // Address of returned boolean status variable
306
- const dst = loadSlice(dest_addr, dest_len);
307
- const src = loadValue(source_addr);
308
- if (!(src instanceof Uint8Array)) {
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(num_bytes_copied_addr, toCopy.length);
315
- mem().setUint8(returned_status_addr, 1); // Return "ok" status
347
+ setInt64(sp + 40, toCopy.length);
348
+ this.mem.setUint8(sp + 48, 1);
316
349
  },
317
- // copyBytesToJS(dst ref, src []byte) (int, bool)
318
- // Originally copied from upstream Go project, then modified:
319
- // https://github.com/golang/go/blob/3f995c3f3b43033013013e6c7ccc93a9b1411ca9/misc/wasm/wasm_exec.js#L404-L416
320
- 'syscall/js.copyBytesToJS': (ret_addr, dest_addr, source_addr, source_len, source_cap) => {
321
- let num_bytes_copied_addr = ret_addr;
322
- let returned_status_addr = ret_addr + 4; // Address of returned boolean status variable
323
- const dst = loadValue(dest_addr);
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(num_bytes_copied_addr, toCopy.length);
332
- mem().setUint8(returned_status_addr, 1); // Return "ok" status
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 = []; // number of references that Go has to a JS value, indexed by reference id
350
- this._ids = new Map(); // mapping from JS values to reference ids
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
- const mem = new DataView(this._inst.exports.memory.buffer);
354
- while (true) {
355
- const callbackPromise = new Promise((resolve) => {
356
- this._resolveCallbackPromise = () => {
357
- if (this.exited) {
358
- throw new Error('bad callback: Go program has already exited');
359
- }
360
- setTimeout(resolve, 0); // make sure it is asynchronous
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
- await callbackPromise;
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) {
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "type": "module",
6
6
  "bugs": "https://github.com/withastro/compiler/issues",
7
7
  "homepage": "https://astro.build",
8
- "version": "0.10.2",
8
+ "version": "0.11.1",
9
9
  "scripts": {
10
10
  "build": "tsc -p ."
11
11
  },