@astrojs/compiler 0.1.4 → 0.1.9
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 +30 -0
- package/astro.wasm +0 -0
- package/browser/index.d.ts +3 -0
- package/browser/index.js +59 -0
- package/browser/wasm_exec.d.ts +7 -0
- package/browser/wasm_exec.js +432 -0
- package/node/index.d.ts +3 -0
- package/node/index.js +43 -0
- package/node/wasm_exec.d.ts +7 -0
- package/node/wasm_exec.js +387 -0
- package/package.json +1 -1
- package/shared/types.d.ts +18 -0
- package/shared/types.js +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# @astrojs/compiler
|
|
2
2
|
|
|
3
|
+
## 0.1.9
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 7d887de: Allows the Astro runtime to create the Astro.slots object
|
|
8
|
+
|
|
9
|
+
## 0.1.8
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- d159658: Publish via PR
|
|
14
|
+
|
|
15
|
+
## 0.1.7
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- c52e69b: Include astro.wasm in the package
|
|
20
|
+
|
|
21
|
+
## 0.1.6
|
|
22
|
+
|
|
23
|
+
### Patch Changes
|
|
24
|
+
|
|
25
|
+
- bd05f7c: Actually include _any_ files?
|
|
26
|
+
|
|
27
|
+
## 0.1.5
|
|
28
|
+
|
|
29
|
+
### Patch Changes
|
|
30
|
+
|
|
31
|
+
- c4ed69e: Includes the wasm binary in the npm package
|
|
32
|
+
|
|
3
33
|
## 0.1.4
|
|
4
34
|
|
|
5
35
|
### Patch Changes
|
package/astro.wasm
ADDED
|
Binary file
|
package/browser/index.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import Go from "./wasm_exec.js";
|
|
2
|
+
export const transform = (input, options) => {
|
|
3
|
+
return ensureServiceIsRunning().transform(input, options);
|
|
4
|
+
};
|
|
5
|
+
let initializePromise;
|
|
6
|
+
let longLivedService;
|
|
7
|
+
export const initialize = (options) => {
|
|
8
|
+
let wasmURL = options.wasmURL;
|
|
9
|
+
let useWorker = options.worker !== false;
|
|
10
|
+
if (!wasmURL)
|
|
11
|
+
throw new Error('Must provide the "wasmURL" option');
|
|
12
|
+
wasmURL += "";
|
|
13
|
+
if (initializePromise)
|
|
14
|
+
throw new Error('Cannot call "initialize" more than once');
|
|
15
|
+
initializePromise = startRunningService(wasmURL, useWorker);
|
|
16
|
+
initializePromise.catch(() => {
|
|
17
|
+
// Let the caller try again if this fails
|
|
18
|
+
initializePromise = void 0;
|
|
19
|
+
});
|
|
20
|
+
return initializePromise;
|
|
21
|
+
};
|
|
22
|
+
let ensureServiceIsRunning = () => {
|
|
23
|
+
if (longLivedService)
|
|
24
|
+
return longLivedService;
|
|
25
|
+
if (initializePromise)
|
|
26
|
+
throw new Error('You need to wait for the promise returned from "initialize" to be resolved before calling this');
|
|
27
|
+
throw new Error('You need to call "initialize" before calling this');
|
|
28
|
+
};
|
|
29
|
+
const instantiateWASM = async (wasmURL, importObject) => {
|
|
30
|
+
let response = undefined;
|
|
31
|
+
if (WebAssembly.instantiateStreaming) {
|
|
32
|
+
response = await WebAssembly.instantiateStreaming(fetch(wasmURL), importObject);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
const fetchAndInstantiateTask = async () => {
|
|
36
|
+
const wasmArrayBuffer = await fetch(wasmURL).then((response) => response.arrayBuffer());
|
|
37
|
+
return WebAssembly.instantiate(wasmArrayBuffer, importObject);
|
|
38
|
+
};
|
|
39
|
+
response = await fetchAndInstantiateTask();
|
|
40
|
+
}
|
|
41
|
+
return response;
|
|
42
|
+
};
|
|
43
|
+
const startRunningService = async (wasmURL, useWorker) => {
|
|
44
|
+
const go = new Go();
|
|
45
|
+
const wasm = await instantiateWASM(wasmURL, go.importObject);
|
|
46
|
+
go.run(wasm.instance);
|
|
47
|
+
const apiKeys = new Set([
|
|
48
|
+
'transform'
|
|
49
|
+
]);
|
|
50
|
+
const service = Object.create(null);
|
|
51
|
+
for (const key of apiKeys.values()) {
|
|
52
|
+
const globalKey = `__astro_${key}`;
|
|
53
|
+
service[key] = globalThis[globalKey];
|
|
54
|
+
delete globalThis[globalKey];
|
|
55
|
+
}
|
|
56
|
+
longLivedService = {
|
|
57
|
+
transform: (input, options) => new Promise((resolve) => resolve(service.transform(input, options || {})))
|
|
58
|
+
};
|
|
59
|
+
};
|
|
@@ -0,0 +1,432 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
// Copyright 2018 The Go Authors. All rights reserved.
|
|
3
|
+
// Use of this source code is governed by a BSD-style
|
|
4
|
+
// license that can be found in the LICENSE file.
|
|
5
|
+
//
|
|
6
|
+
// This file has been modified for use by the TinyGo compiler.
|
|
7
|
+
// This file has been further modified for use by Astro.
|
|
8
|
+
const enosys = () => {
|
|
9
|
+
const err = new Error("not implemented");
|
|
10
|
+
err.code = "ENOSYS";
|
|
11
|
+
return err;
|
|
12
|
+
};
|
|
13
|
+
let outputBuf = "";
|
|
14
|
+
const fs = {
|
|
15
|
+
constants: { O_WRONLY: -1, O_RDWR: -1, O_CREAT: -1, O_TRUNC: -1, O_APPEND: -1, O_EXCL: -1 },
|
|
16
|
+
writeSync(fd, buf) {
|
|
17
|
+
outputBuf += decoder.decode(buf);
|
|
18
|
+
const nl = outputBuf.lastIndexOf("\n");
|
|
19
|
+
if (nl != -1) {
|
|
20
|
+
console.log(outputBuf.substr(0, nl));
|
|
21
|
+
outputBuf = outputBuf.substr(nl + 1);
|
|
22
|
+
}
|
|
23
|
+
return buf.length;
|
|
24
|
+
},
|
|
25
|
+
write(fd, buf, offset, length, position, callback) {
|
|
26
|
+
if (offset !== 0 || length !== buf.length || position !== null) {
|
|
27
|
+
callback(enosys());
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const n = this.writeSync(fd, buf);
|
|
31
|
+
callback(null, n);
|
|
32
|
+
},
|
|
33
|
+
chmod(path, mode, callback) { callback(enosys()); },
|
|
34
|
+
chown(path, uid, gid, callback) { callback(enosys()); },
|
|
35
|
+
close(fd, callback) { callback(enosys()); },
|
|
36
|
+
fchmod(fd, mode, callback) { callback(enosys()); },
|
|
37
|
+
fchown(fd, uid, gid, callback) { callback(enosys()); },
|
|
38
|
+
fstat(fd, callback) { callback(enosys()); },
|
|
39
|
+
fsync(fd, callback) { callback(null); },
|
|
40
|
+
ftruncate(fd, length, callback) { callback(enosys()); },
|
|
41
|
+
lchown(path, uid, gid, callback) { callback(enosys()); },
|
|
42
|
+
link(path, link, callback) { callback(enosys()); },
|
|
43
|
+
lstat(path, callback) { callback(enosys()); },
|
|
44
|
+
mkdir(path, perm, callback) { callback(enosys()); },
|
|
45
|
+
open(path, flags, mode, callback) { callback(enosys()); },
|
|
46
|
+
read(fd, buffer, offset, length, position, callback) { callback(enosys()); },
|
|
47
|
+
readdir(path, callback) { callback(enosys()); },
|
|
48
|
+
readlink(path, callback) { callback(enosys()); },
|
|
49
|
+
rename(from, to, callback) { callback(enosys()); },
|
|
50
|
+
rmdir(path, callback) { callback(enosys()); },
|
|
51
|
+
stat(path, callback) { callback(enosys()); },
|
|
52
|
+
symlink(path, link, callback) { callback(enosys()); },
|
|
53
|
+
truncate(path, length, callback) { callback(enosys()); },
|
|
54
|
+
unlink(path, callback) { callback(enosys()); },
|
|
55
|
+
utimes(path, atime, mtime, callback) { callback(enosys()); },
|
|
56
|
+
};
|
|
57
|
+
const process = {
|
|
58
|
+
getuid() { return -1; },
|
|
59
|
+
getgid() { return -1; },
|
|
60
|
+
geteuid() { return -1; },
|
|
61
|
+
getegid() { return -1; },
|
|
62
|
+
getgroups() { throw enosys(); },
|
|
63
|
+
pid: -1,
|
|
64
|
+
ppid: -1,
|
|
65
|
+
umask() { throw enosys(); },
|
|
66
|
+
cwd() { throw enosys(); },
|
|
67
|
+
chdir() { throw enosys(); },
|
|
68
|
+
};
|
|
69
|
+
Object.defineProperties(globalThis, {
|
|
70
|
+
fs: {
|
|
71
|
+
value: fs,
|
|
72
|
+
enumerable: true,
|
|
73
|
+
},
|
|
74
|
+
process: {
|
|
75
|
+
value: process,
|
|
76
|
+
enumerable: true
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
const encoder = new TextEncoder("utf-8");
|
|
80
|
+
const decoder = new TextDecoder("utf-8");
|
|
81
|
+
var logLine = [];
|
|
82
|
+
export default class Go {
|
|
83
|
+
constructor() {
|
|
84
|
+
this._callbackTimeouts = new Map();
|
|
85
|
+
this._nextCallbackTimeoutID = 1;
|
|
86
|
+
const mem = () => {
|
|
87
|
+
// The buffer may change when requesting more memory.
|
|
88
|
+
return new DataView(this._inst.exports.memory.buffer);
|
|
89
|
+
};
|
|
90
|
+
const setInt64 = (addr, v) => {
|
|
91
|
+
mem().setUint32(addr + 0, v, true);
|
|
92
|
+
mem().setUint32(addr + 4, Math.floor(v / 4294967296), true);
|
|
93
|
+
};
|
|
94
|
+
const getInt64 = (addr) => {
|
|
95
|
+
const low = mem().getUint32(addr + 0, true);
|
|
96
|
+
const high = mem().getInt32(addr + 4, true);
|
|
97
|
+
return low + high * 4294967296;
|
|
98
|
+
};
|
|
99
|
+
const loadValue = (addr) => {
|
|
100
|
+
const f = mem().getFloat64(addr, true);
|
|
101
|
+
if (f === 0) {
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
if (!isNaN(f)) {
|
|
105
|
+
return f;
|
|
106
|
+
}
|
|
107
|
+
const id = mem().getUint32(addr, true);
|
|
108
|
+
return this._values[id];
|
|
109
|
+
};
|
|
110
|
+
const storeValue = (addr, v) => {
|
|
111
|
+
const nanHead = 0x7ff80000;
|
|
112
|
+
if (typeof v === "number") {
|
|
113
|
+
if (isNaN(v)) {
|
|
114
|
+
mem().setUint32(addr + 4, nanHead, true);
|
|
115
|
+
mem().setUint32(addr, 0, true);
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
if (v === 0) {
|
|
119
|
+
mem().setUint32(addr + 4, nanHead, true);
|
|
120
|
+
mem().setUint32(addr, 1, true);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
mem().setFloat64(addr, v, true);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
switch (v) {
|
|
127
|
+
case undefined:
|
|
128
|
+
mem().setFloat64(addr, 0, true);
|
|
129
|
+
return;
|
|
130
|
+
case null:
|
|
131
|
+
mem().setUint32(addr + 4, nanHead, true);
|
|
132
|
+
mem().setUint32(addr, 2, true);
|
|
133
|
+
return;
|
|
134
|
+
case true:
|
|
135
|
+
mem().setUint32(addr + 4, nanHead, true);
|
|
136
|
+
mem().setUint32(addr, 3, true);
|
|
137
|
+
return;
|
|
138
|
+
case false:
|
|
139
|
+
mem().setUint32(addr + 4, nanHead, true);
|
|
140
|
+
mem().setUint32(addr, 4, true);
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
let id = this._ids.get(v);
|
|
144
|
+
if (id === undefined) {
|
|
145
|
+
id = this._idPool.pop();
|
|
146
|
+
if (id === undefined) {
|
|
147
|
+
id = this._values.length;
|
|
148
|
+
}
|
|
149
|
+
this._values[id] = v;
|
|
150
|
+
this._goRefCounts[id] = 0;
|
|
151
|
+
this._ids.set(v, id);
|
|
152
|
+
}
|
|
153
|
+
this._goRefCounts[id]++;
|
|
154
|
+
let typeFlag = 1;
|
|
155
|
+
switch (typeof v) {
|
|
156
|
+
case "string":
|
|
157
|
+
typeFlag = 2;
|
|
158
|
+
break;
|
|
159
|
+
case "symbol":
|
|
160
|
+
typeFlag = 3;
|
|
161
|
+
break;
|
|
162
|
+
case "function":
|
|
163
|
+
typeFlag = 4;
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
mem().setUint32(addr + 4, nanHead | typeFlag, true);
|
|
167
|
+
mem().setUint32(addr, id, true);
|
|
168
|
+
};
|
|
169
|
+
const loadSlice = (array, len, cap) => {
|
|
170
|
+
return new Uint8Array(this._inst.exports.memory.buffer, array, len);
|
|
171
|
+
};
|
|
172
|
+
const loadSliceOfValues = (array, len, cap) => {
|
|
173
|
+
const a = new Array(len);
|
|
174
|
+
for (let i = 0; i < len; i++) {
|
|
175
|
+
a[i] = loadValue(array + i * 8);
|
|
176
|
+
}
|
|
177
|
+
return a;
|
|
178
|
+
};
|
|
179
|
+
const loadString = (ptr, len) => {
|
|
180
|
+
return decoder.decode(new DataView(this._inst.exports.memory.buffer, ptr, len));
|
|
181
|
+
};
|
|
182
|
+
const timeOrigin = Date.now() - performance.now();
|
|
183
|
+
this.importObject = {
|
|
184
|
+
wasi_snapshot_preview1: {
|
|
185
|
+
// https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#fd_write
|
|
186
|
+
fd_write: function (fd, iovs_ptr, iovs_len, nwritten_ptr) {
|
|
187
|
+
let nwritten = 0;
|
|
188
|
+
if (fd == 1) {
|
|
189
|
+
for (let iovs_i = 0; iovs_i < iovs_len; iovs_i++) {
|
|
190
|
+
let iov_ptr = iovs_ptr + iovs_i * 8; // assuming wasm32
|
|
191
|
+
let ptr = mem().getUint32(iov_ptr + 0, true);
|
|
192
|
+
let len = mem().getUint32(iov_ptr + 4, true);
|
|
193
|
+
for (let i = 0; i < len; i++) {
|
|
194
|
+
let c = mem().getUint8(ptr + i);
|
|
195
|
+
if (c == 13) {
|
|
196
|
+
// CR
|
|
197
|
+
// ignore
|
|
198
|
+
}
|
|
199
|
+
else if (c == 10) {
|
|
200
|
+
// LF
|
|
201
|
+
// write line
|
|
202
|
+
let line = decoder.decode(new Uint8Array(logLine));
|
|
203
|
+
logLine = [];
|
|
204
|
+
console.log(line);
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
logLine.push(c);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
console.error("invalid file descriptor:", fd);
|
|
214
|
+
}
|
|
215
|
+
mem().setUint32(nwritten_ptr, nwritten, true);
|
|
216
|
+
return 0;
|
|
217
|
+
},
|
|
218
|
+
proc_exit: (code) => {
|
|
219
|
+
if (globalThis.process) {
|
|
220
|
+
// Node.js
|
|
221
|
+
process.exit(code);
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
// Can't exit in a browser.
|
|
225
|
+
throw "trying to exit with code " + code;
|
|
226
|
+
}
|
|
227
|
+
},
|
|
228
|
+
},
|
|
229
|
+
env: {
|
|
230
|
+
// func ticks() float64
|
|
231
|
+
"runtime.ticks": () => {
|
|
232
|
+
return timeOrigin + performance.now();
|
|
233
|
+
},
|
|
234
|
+
// func sleepTicks(timeout float64)
|
|
235
|
+
"runtime.sleepTicks": (timeout) => {
|
|
236
|
+
// Do not sleep, only reactivate scheduler after the given timeout.
|
|
237
|
+
setTimeout(this._inst.exports.go_scheduler, timeout);
|
|
238
|
+
},
|
|
239
|
+
// func finalizeRef(v ref)
|
|
240
|
+
"syscall/js.finalizeRef": (v_addr) => {
|
|
241
|
+
// Note: TinyGo does not support finalizers so this is only called
|
|
242
|
+
// for one specific case, by js.go:jsString.
|
|
243
|
+
const id = mem().getUint32(v_addr, true);
|
|
244
|
+
this._goRefCounts[id]--;
|
|
245
|
+
if (this._goRefCounts[id] === 0) {
|
|
246
|
+
const v = this._values[id];
|
|
247
|
+
this._values[id] = null;
|
|
248
|
+
this._ids.delete(v);
|
|
249
|
+
this._idPool.push(id);
|
|
250
|
+
}
|
|
251
|
+
},
|
|
252
|
+
// func stringVal(value string) ref
|
|
253
|
+
"syscall/js.stringVal": (ret_ptr, value_ptr, value_len) => {
|
|
254
|
+
const s = loadString(value_ptr, value_len);
|
|
255
|
+
storeValue(ret_ptr, s);
|
|
256
|
+
},
|
|
257
|
+
// func valueGet(v ref, p string) ref
|
|
258
|
+
"syscall/js.valueGet": (retval, v_addr, p_ptr, p_len) => {
|
|
259
|
+
let prop = loadString(p_ptr, p_len);
|
|
260
|
+
let value = loadValue(v_addr);
|
|
261
|
+
let result = Reflect.get(value, prop);
|
|
262
|
+
storeValue(retval, result);
|
|
263
|
+
},
|
|
264
|
+
// func valueSet(v ref, p string, x ref)
|
|
265
|
+
"syscall/js.valueSet": (v_addr, p_ptr, p_len, x_addr) => {
|
|
266
|
+
const v = loadValue(v_addr);
|
|
267
|
+
const p = loadString(p_ptr, p_len);
|
|
268
|
+
const x = loadValue(x_addr);
|
|
269
|
+
Reflect.set(v, p, x);
|
|
270
|
+
},
|
|
271
|
+
// func valueDelete(v ref, p string)
|
|
272
|
+
"syscall/js.valueDelete": (v_addr, p_ptr, p_len) => {
|
|
273
|
+
const v = loadValue(v_addr);
|
|
274
|
+
const p = loadString(p_ptr, p_len);
|
|
275
|
+
Reflect.deleteProperty(v, p);
|
|
276
|
+
},
|
|
277
|
+
// func valueIndex(v ref, i int) ref
|
|
278
|
+
"syscall/js.valueIndex": (ret_addr, v_addr, i) => {
|
|
279
|
+
storeValue(ret_addr, Reflect.get(loadValue(v_addr), i));
|
|
280
|
+
},
|
|
281
|
+
// valueSetIndex(v ref, i int, x ref)
|
|
282
|
+
"syscall/js.valueSetIndex": (v_addr, i, x_addr) => {
|
|
283
|
+
Reflect.set(loadValue(v_addr), i, loadValue(x_addr));
|
|
284
|
+
},
|
|
285
|
+
// func valueCall(v ref, m string, args []ref) (ref, bool)
|
|
286
|
+
"syscall/js.valueCall": (ret_addr, v_addr, m_ptr, m_len, args_ptr, args_len, args_cap) => {
|
|
287
|
+
const v = loadValue(v_addr);
|
|
288
|
+
const name = loadString(m_ptr, m_len);
|
|
289
|
+
const args = loadSliceOfValues(args_ptr, args_len, args_cap);
|
|
290
|
+
try {
|
|
291
|
+
const m = Reflect.get(v, name);
|
|
292
|
+
storeValue(ret_addr, Reflect.apply(m, v, args));
|
|
293
|
+
mem().setUint8(ret_addr + 8, 1);
|
|
294
|
+
}
|
|
295
|
+
catch (err) {
|
|
296
|
+
storeValue(ret_addr, err);
|
|
297
|
+
mem().setUint8(ret_addr + 8, 0);
|
|
298
|
+
}
|
|
299
|
+
},
|
|
300
|
+
// func valueInvoke(v ref, args []ref) (ref, bool)
|
|
301
|
+
"syscall/js.valueInvoke": (ret_addr, v_addr, args_ptr, args_len, args_cap) => {
|
|
302
|
+
try {
|
|
303
|
+
const v = loadValue(v_addr);
|
|
304
|
+
const args = loadSliceOfValues(args_ptr, args_len, args_cap);
|
|
305
|
+
storeValue(ret_addr, Reflect.apply(v, undefined, args));
|
|
306
|
+
mem().setUint8(ret_addr + 8, 1);
|
|
307
|
+
}
|
|
308
|
+
catch (err) {
|
|
309
|
+
storeValue(ret_addr, err);
|
|
310
|
+
mem().setUint8(ret_addr + 8, 0);
|
|
311
|
+
}
|
|
312
|
+
},
|
|
313
|
+
// func valueNew(v ref, args []ref) (ref, bool)
|
|
314
|
+
"syscall/js.valueNew": (ret_addr, v_addr, args_ptr, args_len, args_cap) => {
|
|
315
|
+
const v = loadValue(v_addr);
|
|
316
|
+
const args = loadSliceOfValues(args_ptr, args_len, args_cap);
|
|
317
|
+
try {
|
|
318
|
+
storeValue(ret_addr, Reflect.construct(v, args));
|
|
319
|
+
mem().setUint8(ret_addr + 8, 1);
|
|
320
|
+
}
|
|
321
|
+
catch (err) {
|
|
322
|
+
storeValue(ret_addr, err);
|
|
323
|
+
mem().setUint8(ret_addr + 8, 0);
|
|
324
|
+
}
|
|
325
|
+
},
|
|
326
|
+
// func valueLength(v ref) int
|
|
327
|
+
"syscall/js.valueLength": (v_addr) => {
|
|
328
|
+
return loadValue(v_addr).length;
|
|
329
|
+
},
|
|
330
|
+
// valuePrepareString(v ref) (ref, int)
|
|
331
|
+
"syscall/js.valuePrepareString": (ret_addr, v_addr) => {
|
|
332
|
+
const s = String(loadValue(v_addr));
|
|
333
|
+
const str = encoder.encode(s);
|
|
334
|
+
storeValue(ret_addr, str);
|
|
335
|
+
setInt64(ret_addr + 8, str.length);
|
|
336
|
+
},
|
|
337
|
+
// valueLoadString(v ref, b []byte)
|
|
338
|
+
"syscall/js.valueLoadString": (v_addr, slice_ptr, slice_len, slice_cap) => {
|
|
339
|
+
const str = loadValue(v_addr);
|
|
340
|
+
loadSlice(slice_ptr, slice_len, slice_cap).set(str);
|
|
341
|
+
},
|
|
342
|
+
// func valueInstanceOf(v ref, t ref) bool
|
|
343
|
+
"syscall/js.valueInstanceOf": (v_addr, t_addr) => {
|
|
344
|
+
return loadValue(v_addr) instanceof loadValue(t_addr);
|
|
345
|
+
},
|
|
346
|
+
// func copyBytesToGo(dst []byte, src ref) (int, bool)
|
|
347
|
+
"syscall/js.copyBytesToGo": (ret_addr, dest_addr, dest_len, dest_cap, source_addr) => {
|
|
348
|
+
let num_bytes_copied_addr = ret_addr;
|
|
349
|
+
let returned_status_addr = ret_addr + 4; // Address of returned boolean status variable
|
|
350
|
+
const dst = loadSlice(dest_addr, dest_len);
|
|
351
|
+
const src = loadValue(source_addr);
|
|
352
|
+
if (!(src instanceof Uint8Array)) {
|
|
353
|
+
mem().setUint8(returned_status_addr, 0); // Return "not ok" status
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
const toCopy = src.subarray(0, dst.length);
|
|
357
|
+
dst.set(toCopy);
|
|
358
|
+
setInt64(num_bytes_copied_addr, toCopy.length);
|
|
359
|
+
mem().setUint8(returned_status_addr, 1); // Return "ok" status
|
|
360
|
+
},
|
|
361
|
+
// copyBytesToJS(dst ref, src []byte) (int, bool)
|
|
362
|
+
// Originally copied from upstream Go project, then modified:
|
|
363
|
+
// https://github.com/golang/go/blob/3f995c3f3b43033013013e6c7ccc93a9b1411ca9/misc/wasm/wasm_exec.js#L404-L416
|
|
364
|
+
"syscall/js.copyBytesToJS": (ret_addr, dest_addr, source_addr, source_len, source_cap) => {
|
|
365
|
+
let num_bytes_copied_addr = ret_addr;
|
|
366
|
+
let returned_status_addr = ret_addr + 4; // Address of returned boolean status variable
|
|
367
|
+
const dst = loadValue(dest_addr);
|
|
368
|
+
const src = loadSlice(source_addr, source_len);
|
|
369
|
+
if (!(dst instanceof Uint8Array)) {
|
|
370
|
+
mem().setUint8(returned_status_addr, 0); // Return "not ok" status
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
const toCopy = src.subarray(0, dst.length);
|
|
374
|
+
dst.set(toCopy);
|
|
375
|
+
setInt64(num_bytes_copied_addr, toCopy.length);
|
|
376
|
+
mem().setUint8(returned_status_addr, 1); // Return "ok" status
|
|
377
|
+
},
|
|
378
|
+
},
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
async run(instance) {
|
|
382
|
+
this._inst = instance;
|
|
383
|
+
this._values = [
|
|
384
|
+
// JS values that Go currently has references to, indexed by reference id
|
|
385
|
+
NaN,
|
|
386
|
+
0,
|
|
387
|
+
null,
|
|
388
|
+
true,
|
|
389
|
+
false,
|
|
390
|
+
globalThis,
|
|
391
|
+
this,
|
|
392
|
+
];
|
|
393
|
+
this._goRefCounts = []; // number of references that Go has to a JS value, indexed by reference id
|
|
394
|
+
this._ids = new Map(); // mapping from JS values to reference ids
|
|
395
|
+
this._idPool = []; // unused ids that have been garbage collected
|
|
396
|
+
this.exited = false; // whether the Go program has exited
|
|
397
|
+
const mem = new DataView(this._inst.exports.memory.buffer);
|
|
398
|
+
while (true) {
|
|
399
|
+
const callbackPromise = new Promise((resolve) => {
|
|
400
|
+
this._resolveCallbackPromise = () => {
|
|
401
|
+
if (this.exited) {
|
|
402
|
+
throw new Error("bad callback: Go program has already exited");
|
|
403
|
+
}
|
|
404
|
+
setTimeout(resolve, 0); // make sure it is asynchronous
|
|
405
|
+
};
|
|
406
|
+
});
|
|
407
|
+
this._inst.exports._start();
|
|
408
|
+
if (this.exited) {
|
|
409
|
+
break;
|
|
410
|
+
}
|
|
411
|
+
await callbackPromise;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
_resume() {
|
|
415
|
+
if (this.exited) {
|
|
416
|
+
throw new Error("Go program has already exited");
|
|
417
|
+
}
|
|
418
|
+
this._inst.exports.resume();
|
|
419
|
+
if (this.exited) {
|
|
420
|
+
this._resolveExitPromise();
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
_makeFuncWrapper(id) {
|
|
424
|
+
const go = this;
|
|
425
|
+
return function () {
|
|
426
|
+
const event = { id: id, this: this, args: arguments };
|
|
427
|
+
go._pendingEvent = event;
|
|
428
|
+
go._resume();
|
|
429
|
+
return event.result;
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
}
|
package/node/index.d.ts
ADDED
package/node/index.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { promises as fs } from 'fs';
|
|
2
|
+
import Go from "./wasm_exec.js";
|
|
3
|
+
import { fileURLToPath } from "url";
|
|
4
|
+
export const transform = async (input, options) => {
|
|
5
|
+
return ensureServiceIsRunning().then(service => service.transform(input, options));
|
|
6
|
+
};
|
|
7
|
+
export const compile = async (template) => {
|
|
8
|
+
const { default: mod } = await import(`data:text/javascript;charset=utf-8;base64,${Buffer.from(template).toString('base64')}`);
|
|
9
|
+
return mod.__render();
|
|
10
|
+
};
|
|
11
|
+
let longLivedService;
|
|
12
|
+
let ensureServiceIsRunning = () => {
|
|
13
|
+
if (longLivedService)
|
|
14
|
+
return Promise.resolve(longLivedService);
|
|
15
|
+
return startRunningService();
|
|
16
|
+
};
|
|
17
|
+
const instantiateWASM = async (wasmURL, importObject) => {
|
|
18
|
+
let response = undefined;
|
|
19
|
+
const fetchAndInstantiateTask = async () => {
|
|
20
|
+
const wasmArrayBuffer = await fs.readFile(wasmURL).then((response) => response.buffer);
|
|
21
|
+
return WebAssembly.instantiate(new Uint8Array(wasmArrayBuffer), importObject);
|
|
22
|
+
};
|
|
23
|
+
response = await fetchAndInstantiateTask();
|
|
24
|
+
return response;
|
|
25
|
+
};
|
|
26
|
+
const startRunningService = async () => {
|
|
27
|
+
const go = new Go();
|
|
28
|
+
const wasm = await instantiateWASM(fileURLToPath(new URL('../astro.wasm', import.meta.url)), go.importObject);
|
|
29
|
+
go.run(wasm.instance);
|
|
30
|
+
const apiKeys = new Set([
|
|
31
|
+
'transform'
|
|
32
|
+
]);
|
|
33
|
+
const service = Object.create(null);
|
|
34
|
+
for (const key of apiKeys.values()) {
|
|
35
|
+
const globalKey = `__astro_${key}`;
|
|
36
|
+
service[key] = globalThis[globalKey];
|
|
37
|
+
delete globalThis[globalKey];
|
|
38
|
+
}
|
|
39
|
+
longLivedService = {
|
|
40
|
+
transform: (input, options) => new Promise((resolve) => resolve(service.transform(input, options || {})))
|
|
41
|
+
};
|
|
42
|
+
return longLivedService;
|
|
43
|
+
};
|
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
// Copyright 2018 The Go Authors. All rights reserved.
|
|
3
|
+
// Use of this source code is governed by a BSD-style
|
|
4
|
+
// license that can be found in the LICENSE file.
|
|
5
|
+
//
|
|
6
|
+
// This file has been modified for use by the TinyGo compiler.
|
|
7
|
+
// This file has been further modified for use by Astro.
|
|
8
|
+
import fs from "fs";
|
|
9
|
+
import crypto from "crypto";
|
|
10
|
+
import { TextEncoder, TextDecoder } from "util";
|
|
11
|
+
Object.defineProperties(globalThis, {
|
|
12
|
+
fs: {
|
|
13
|
+
value: fs,
|
|
14
|
+
enumerable: true,
|
|
15
|
+
},
|
|
16
|
+
crypto: {
|
|
17
|
+
value: {
|
|
18
|
+
getRandomValues(b) {
|
|
19
|
+
crypto.randomFillSync(b);
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
enumerable: true,
|
|
23
|
+
},
|
|
24
|
+
performance: {
|
|
25
|
+
value: {
|
|
26
|
+
now() {
|
|
27
|
+
const [sec, nsec] = process.hrtime();
|
|
28
|
+
return sec * 1000 + nsec / 1000000;
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
enumerable: true,
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
const encoder = new TextEncoder("utf-8");
|
|
35
|
+
const decoder = new TextDecoder("utf-8");
|
|
36
|
+
var logLine = [];
|
|
37
|
+
export default class Go {
|
|
38
|
+
constructor() {
|
|
39
|
+
this._callbackTimeouts = new Map();
|
|
40
|
+
this._nextCallbackTimeoutID = 1;
|
|
41
|
+
const mem = () => {
|
|
42
|
+
// The buffer may change when requesting more memory.
|
|
43
|
+
return new DataView(this._inst.exports.memory.buffer);
|
|
44
|
+
};
|
|
45
|
+
const setInt64 = (addr, v) => {
|
|
46
|
+
mem().setUint32(addr + 0, v, true);
|
|
47
|
+
mem().setUint32(addr + 4, Math.floor(v / 4294967296), true);
|
|
48
|
+
};
|
|
49
|
+
const getInt64 = (addr) => {
|
|
50
|
+
const low = mem().getUint32(addr + 0, true);
|
|
51
|
+
const high = mem().getInt32(addr + 4, true);
|
|
52
|
+
return low + high * 4294967296;
|
|
53
|
+
};
|
|
54
|
+
const loadValue = (addr) => {
|
|
55
|
+
const f = mem().getFloat64(addr, true);
|
|
56
|
+
if (f === 0) {
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
if (!isNaN(f)) {
|
|
60
|
+
return f;
|
|
61
|
+
}
|
|
62
|
+
const id = mem().getUint32(addr, true);
|
|
63
|
+
return this._values[id];
|
|
64
|
+
};
|
|
65
|
+
const storeValue = (addr, v) => {
|
|
66
|
+
const nanHead = 0x7ff80000;
|
|
67
|
+
if (typeof v === "number") {
|
|
68
|
+
if (isNaN(v)) {
|
|
69
|
+
mem().setUint32(addr + 4, nanHead, true);
|
|
70
|
+
mem().setUint32(addr, 0, true);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (v === 0) {
|
|
74
|
+
mem().setUint32(addr + 4, nanHead, true);
|
|
75
|
+
mem().setUint32(addr, 1, true);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
mem().setFloat64(addr, v, true);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
switch (v) {
|
|
82
|
+
case undefined:
|
|
83
|
+
mem().setFloat64(addr, 0, true);
|
|
84
|
+
return;
|
|
85
|
+
case null:
|
|
86
|
+
mem().setUint32(addr + 4, nanHead, true);
|
|
87
|
+
mem().setUint32(addr, 2, true);
|
|
88
|
+
return;
|
|
89
|
+
case true:
|
|
90
|
+
mem().setUint32(addr + 4, nanHead, true);
|
|
91
|
+
mem().setUint32(addr, 3, true);
|
|
92
|
+
return;
|
|
93
|
+
case false:
|
|
94
|
+
mem().setUint32(addr + 4, nanHead, true);
|
|
95
|
+
mem().setUint32(addr, 4, true);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
let id = this._ids.get(v);
|
|
99
|
+
if (id === undefined) {
|
|
100
|
+
id = this._idPool.pop();
|
|
101
|
+
if (id === undefined) {
|
|
102
|
+
id = this._values.length;
|
|
103
|
+
}
|
|
104
|
+
this._values[id] = v;
|
|
105
|
+
this._goRefCounts[id] = 0;
|
|
106
|
+
this._ids.set(v, id);
|
|
107
|
+
}
|
|
108
|
+
this._goRefCounts[id]++;
|
|
109
|
+
let typeFlag = 1;
|
|
110
|
+
switch (typeof v) {
|
|
111
|
+
case "string":
|
|
112
|
+
typeFlag = 2;
|
|
113
|
+
break;
|
|
114
|
+
case "symbol":
|
|
115
|
+
typeFlag = 3;
|
|
116
|
+
break;
|
|
117
|
+
case "function":
|
|
118
|
+
typeFlag = 4;
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
mem().setUint32(addr + 4, nanHead | typeFlag, true);
|
|
122
|
+
mem().setUint32(addr, id, true);
|
|
123
|
+
};
|
|
124
|
+
const loadSlice = (array, len, cap) => {
|
|
125
|
+
return new Uint8Array(this._inst.exports.memory.buffer, array, len);
|
|
126
|
+
};
|
|
127
|
+
const loadSliceOfValues = (array, len, cap) => {
|
|
128
|
+
const a = new Array(len);
|
|
129
|
+
for (let i = 0; i < len; i++) {
|
|
130
|
+
a[i] = loadValue(array + i * 8);
|
|
131
|
+
}
|
|
132
|
+
return a;
|
|
133
|
+
};
|
|
134
|
+
const loadString = (ptr, len) => {
|
|
135
|
+
return decoder.decode(new DataView(this._inst.exports.memory.buffer, ptr, len));
|
|
136
|
+
};
|
|
137
|
+
const timeOrigin = Date.now() - performance.now();
|
|
138
|
+
this.importObject = {
|
|
139
|
+
wasi_snapshot_preview1: {
|
|
140
|
+
// https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#fd_write
|
|
141
|
+
fd_write: function (fd, iovs_ptr, iovs_len, nwritten_ptr) {
|
|
142
|
+
let nwritten = 0;
|
|
143
|
+
if (fd == 1) {
|
|
144
|
+
for (let iovs_i = 0; iovs_i < iovs_len; iovs_i++) {
|
|
145
|
+
let iov_ptr = iovs_ptr + iovs_i * 8; // assuming wasm32
|
|
146
|
+
let ptr = mem().getUint32(iov_ptr + 0, true);
|
|
147
|
+
let len = mem().getUint32(iov_ptr + 4, true);
|
|
148
|
+
for (let i = 0; i < len; i++) {
|
|
149
|
+
let c = mem().getUint8(ptr + i);
|
|
150
|
+
if (c == 13) {
|
|
151
|
+
// CR
|
|
152
|
+
// ignore
|
|
153
|
+
}
|
|
154
|
+
else if (c == 10) {
|
|
155
|
+
// LF
|
|
156
|
+
// write line
|
|
157
|
+
let line = decoder.decode(new Uint8Array(logLine));
|
|
158
|
+
logLine = [];
|
|
159
|
+
console.log(line);
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
logLine.push(c);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
console.error("invalid file descriptor:", fd);
|
|
169
|
+
}
|
|
170
|
+
mem().setUint32(nwritten_ptr, nwritten, true);
|
|
171
|
+
return 0;
|
|
172
|
+
},
|
|
173
|
+
proc_exit: (code) => {
|
|
174
|
+
if (globalThis.process) {
|
|
175
|
+
// Node.js
|
|
176
|
+
process.exit(code);
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
// Can't exit in a browser.
|
|
180
|
+
throw "trying to exit with code " + code;
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
env: {
|
|
185
|
+
// func ticks() float64
|
|
186
|
+
"runtime.ticks": () => {
|
|
187
|
+
return timeOrigin + performance.now();
|
|
188
|
+
},
|
|
189
|
+
// func sleepTicks(timeout float64)
|
|
190
|
+
"runtime.sleepTicks": (timeout) => {
|
|
191
|
+
// Do not sleep, only reactivate scheduler after the given timeout.
|
|
192
|
+
setTimeout(this._inst.exports.go_scheduler, timeout);
|
|
193
|
+
},
|
|
194
|
+
// func finalizeRef(v ref)
|
|
195
|
+
"syscall/js.finalizeRef": (v_addr) => {
|
|
196
|
+
// Note: TinyGo does not support finalizers so this is only called
|
|
197
|
+
// for one specific case, by js.go:jsString.
|
|
198
|
+
const id = mem().getUint32(v_addr, true);
|
|
199
|
+
this._goRefCounts[id]--;
|
|
200
|
+
if (this._goRefCounts[id] === 0) {
|
|
201
|
+
const v = this._values[id];
|
|
202
|
+
this._values[id] = null;
|
|
203
|
+
this._ids.delete(v);
|
|
204
|
+
this._idPool.push(id);
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
// func stringVal(value string) ref
|
|
208
|
+
"syscall/js.stringVal": (ret_ptr, value_ptr, value_len) => {
|
|
209
|
+
const s = loadString(value_ptr, value_len);
|
|
210
|
+
storeValue(ret_ptr, s);
|
|
211
|
+
},
|
|
212
|
+
// func valueGet(v ref, p string) ref
|
|
213
|
+
"syscall/js.valueGet": (retval, v_addr, p_ptr, p_len) => {
|
|
214
|
+
let prop = loadString(p_ptr, p_len);
|
|
215
|
+
let value = loadValue(v_addr);
|
|
216
|
+
let result = Reflect.get(value, prop);
|
|
217
|
+
storeValue(retval, result);
|
|
218
|
+
},
|
|
219
|
+
// func valueSet(v ref, p string, x ref)
|
|
220
|
+
"syscall/js.valueSet": (v_addr, p_ptr, p_len, x_addr) => {
|
|
221
|
+
const v = loadValue(v_addr);
|
|
222
|
+
const p = loadString(p_ptr, p_len);
|
|
223
|
+
const x = loadValue(x_addr);
|
|
224
|
+
Reflect.set(v, p, x);
|
|
225
|
+
},
|
|
226
|
+
// func valueDelete(v ref, p string)
|
|
227
|
+
"syscall/js.valueDelete": (v_addr, p_ptr, p_len) => {
|
|
228
|
+
const v = loadValue(v_addr);
|
|
229
|
+
const p = loadString(p_ptr, p_len);
|
|
230
|
+
Reflect.deleteProperty(v, p);
|
|
231
|
+
},
|
|
232
|
+
// func valueIndex(v ref, i int) ref
|
|
233
|
+
"syscall/js.valueIndex": (ret_addr, v_addr, i) => {
|
|
234
|
+
storeValue(ret_addr, Reflect.get(loadValue(v_addr), i));
|
|
235
|
+
},
|
|
236
|
+
// valueSetIndex(v ref, i int, x ref)
|
|
237
|
+
"syscall/js.valueSetIndex": (v_addr, i, x_addr) => {
|
|
238
|
+
Reflect.set(loadValue(v_addr), i, loadValue(x_addr));
|
|
239
|
+
},
|
|
240
|
+
// func valueCall(v ref, m string, args []ref) (ref, bool)
|
|
241
|
+
"syscall/js.valueCall": (ret_addr, v_addr, m_ptr, m_len, args_ptr, args_len, args_cap) => {
|
|
242
|
+
const v = loadValue(v_addr);
|
|
243
|
+
const name = loadString(m_ptr, m_len);
|
|
244
|
+
const args = loadSliceOfValues(args_ptr, args_len, args_cap);
|
|
245
|
+
try {
|
|
246
|
+
const m = Reflect.get(v, name);
|
|
247
|
+
storeValue(ret_addr, Reflect.apply(m, v, args));
|
|
248
|
+
mem().setUint8(ret_addr + 8, 1);
|
|
249
|
+
}
|
|
250
|
+
catch (err) {
|
|
251
|
+
storeValue(ret_addr, err);
|
|
252
|
+
mem().setUint8(ret_addr + 8, 0);
|
|
253
|
+
}
|
|
254
|
+
},
|
|
255
|
+
// func valueInvoke(v ref, args []ref) (ref, bool)
|
|
256
|
+
"syscall/js.valueInvoke": (ret_addr, v_addr, args_ptr, args_len, args_cap) => {
|
|
257
|
+
try {
|
|
258
|
+
const v = loadValue(v_addr);
|
|
259
|
+
const args = loadSliceOfValues(args_ptr, args_len, args_cap);
|
|
260
|
+
storeValue(ret_addr, Reflect.apply(v, undefined, args));
|
|
261
|
+
mem().setUint8(ret_addr + 8, 1);
|
|
262
|
+
}
|
|
263
|
+
catch (err) {
|
|
264
|
+
storeValue(ret_addr, err);
|
|
265
|
+
mem().setUint8(ret_addr + 8, 0);
|
|
266
|
+
}
|
|
267
|
+
},
|
|
268
|
+
// func valueNew(v ref, args []ref) (ref, bool)
|
|
269
|
+
"syscall/js.valueNew": (ret_addr, v_addr, args_ptr, args_len, args_cap) => {
|
|
270
|
+
const v = loadValue(v_addr);
|
|
271
|
+
const args = loadSliceOfValues(args_ptr, args_len, args_cap);
|
|
272
|
+
try {
|
|
273
|
+
storeValue(ret_addr, Reflect.construct(v, args));
|
|
274
|
+
mem().setUint8(ret_addr + 8, 1);
|
|
275
|
+
}
|
|
276
|
+
catch (err) {
|
|
277
|
+
storeValue(ret_addr, err);
|
|
278
|
+
mem().setUint8(ret_addr + 8, 0);
|
|
279
|
+
}
|
|
280
|
+
},
|
|
281
|
+
// func valueLength(v ref) int
|
|
282
|
+
"syscall/js.valueLength": (v_addr) => {
|
|
283
|
+
return loadValue(v_addr).length;
|
|
284
|
+
},
|
|
285
|
+
// valuePrepareString(v ref) (ref, int)
|
|
286
|
+
"syscall/js.valuePrepareString": (ret_addr, v_addr) => {
|
|
287
|
+
const s = String(loadValue(v_addr));
|
|
288
|
+
const str = encoder.encode(s);
|
|
289
|
+
storeValue(ret_addr, str);
|
|
290
|
+
setInt64(ret_addr + 8, str.length);
|
|
291
|
+
},
|
|
292
|
+
// valueLoadString(v ref, b []byte)
|
|
293
|
+
"syscall/js.valueLoadString": (v_addr, slice_ptr, slice_len, slice_cap) => {
|
|
294
|
+
const str = loadValue(v_addr);
|
|
295
|
+
loadSlice(slice_ptr, slice_len, slice_cap).set(str);
|
|
296
|
+
},
|
|
297
|
+
// func valueInstanceOf(v ref, t ref) bool
|
|
298
|
+
"syscall/js.valueInstanceOf": (v_addr, t_addr) => {
|
|
299
|
+
return loadValue(v_addr) instanceof loadValue(t_addr);
|
|
300
|
+
},
|
|
301
|
+
// func copyBytesToGo(dst []byte, src ref) (int, bool)
|
|
302
|
+
"syscall/js.copyBytesToGo": (ret_addr, dest_addr, dest_len, dest_cap, source_addr) => {
|
|
303
|
+
let num_bytes_copied_addr = ret_addr;
|
|
304
|
+
let returned_status_addr = ret_addr + 4; // Address of returned boolean status variable
|
|
305
|
+
const dst = loadSlice(dest_addr, dest_len);
|
|
306
|
+
const src = loadValue(source_addr);
|
|
307
|
+
if (!(src instanceof Uint8Array)) {
|
|
308
|
+
mem().setUint8(returned_status_addr, 0); // Return "not ok" status
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
const toCopy = src.subarray(0, dst.length);
|
|
312
|
+
dst.set(toCopy);
|
|
313
|
+
setInt64(num_bytes_copied_addr, toCopy.length);
|
|
314
|
+
mem().setUint8(returned_status_addr, 1); // Return "ok" status
|
|
315
|
+
},
|
|
316
|
+
// copyBytesToJS(dst ref, src []byte) (int, bool)
|
|
317
|
+
// Originally copied from upstream Go project, then modified:
|
|
318
|
+
// https://github.com/golang/go/blob/3f995c3f3b43033013013e6c7ccc93a9b1411ca9/misc/wasm/wasm_exec.js#L404-L416
|
|
319
|
+
"syscall/js.copyBytesToJS": (ret_addr, dest_addr, source_addr, source_len, source_cap) => {
|
|
320
|
+
let num_bytes_copied_addr = ret_addr;
|
|
321
|
+
let returned_status_addr = ret_addr + 4; // Address of returned boolean status variable
|
|
322
|
+
const dst = loadValue(dest_addr);
|
|
323
|
+
const src = loadSlice(source_addr, source_len);
|
|
324
|
+
if (!(dst instanceof Uint8Array)) {
|
|
325
|
+
mem().setUint8(returned_status_addr, 0); // Return "not ok" status
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
const toCopy = src.subarray(0, dst.length);
|
|
329
|
+
dst.set(toCopy);
|
|
330
|
+
setInt64(num_bytes_copied_addr, toCopy.length);
|
|
331
|
+
mem().setUint8(returned_status_addr, 1); // Return "ok" status
|
|
332
|
+
},
|
|
333
|
+
},
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
async run(instance) {
|
|
337
|
+
this._inst = instance;
|
|
338
|
+
this._values = [
|
|
339
|
+
// JS values that Go currently has references to, indexed by reference id
|
|
340
|
+
NaN,
|
|
341
|
+
0,
|
|
342
|
+
null,
|
|
343
|
+
true,
|
|
344
|
+
false,
|
|
345
|
+
globalThis,
|
|
346
|
+
this,
|
|
347
|
+
];
|
|
348
|
+
this._goRefCounts = []; // number of references that Go has to a JS value, indexed by reference id
|
|
349
|
+
this._ids = new Map(); // mapping from JS values to reference ids
|
|
350
|
+
this._idPool = []; // unused ids that have been garbage collected
|
|
351
|
+
this.exited = false; // whether the Go program has exited
|
|
352
|
+
const mem = new DataView(this._inst.exports.memory.buffer);
|
|
353
|
+
while (true) {
|
|
354
|
+
const callbackPromise = new Promise((resolve) => {
|
|
355
|
+
this._resolveCallbackPromise = () => {
|
|
356
|
+
if (this.exited) {
|
|
357
|
+
throw new Error("bad callback: Go program has already exited");
|
|
358
|
+
}
|
|
359
|
+
setTimeout(resolve, 0); // make sure it is asynchronous
|
|
360
|
+
};
|
|
361
|
+
});
|
|
362
|
+
this._inst.exports._start();
|
|
363
|
+
if (this.exited) {
|
|
364
|
+
break;
|
|
365
|
+
}
|
|
366
|
+
await callbackPromise;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
_resume() {
|
|
370
|
+
if (this.exited) {
|
|
371
|
+
throw new Error("Go program has already exited");
|
|
372
|
+
}
|
|
373
|
+
this._inst.exports.resume();
|
|
374
|
+
if (this.exited) {
|
|
375
|
+
this._resolveExitPromise();
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
_makeFuncWrapper(id) {
|
|
379
|
+
const go = this;
|
|
380
|
+
return function () {
|
|
381
|
+
const event = { id: id, this: this, args: arguments };
|
|
382
|
+
go._pendingEvent = event;
|
|
383
|
+
go._resume();
|
|
384
|
+
return event.result;
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface TransformOptions {
|
|
2
|
+
sourcefile?: string;
|
|
3
|
+
internalURL?: string;
|
|
4
|
+
sourcemap?: boolean | 'inline' | 'external' | 'both';
|
|
5
|
+
as?: 'document' | 'fragment';
|
|
6
|
+
}
|
|
7
|
+
export interface TransformResult {
|
|
8
|
+
code: string;
|
|
9
|
+
map: string;
|
|
10
|
+
warnings: any[];
|
|
11
|
+
}
|
|
12
|
+
export declare function transform(input: string, options?: TransformOptions): Promise<TransformResult>;
|
|
13
|
+
export declare function compile(input: string, options?: TransformOptions): Promise<TransformResult>;
|
|
14
|
+
export declare function initialize(options: InitializeOptions): Promise<void>;
|
|
15
|
+
export interface InitializeOptions {
|
|
16
|
+
wasmURL?: string;
|
|
17
|
+
worker?: boolean;
|
|
18
|
+
}
|
package/shared/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|