as-test 1.1.0 → 1.1.2
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 +17 -3
- package/README.md +14 -7
- package/as-test.config.schema.json +142 -142
- package/assembly/__fuzz__/math.fuzz.ts +22 -0
- package/assembly/__fuzz__/seed-perf.fuzz.ts +4 -2
- package/assembly/__fuzz__/string.fuzz.ts +31 -0
- package/assembly/index.ts +6 -9
- package/assembly/src/expectation.ts +99 -42
- package/assembly/src/fuzz.ts +44 -23
- package/assembly/util/format.ts +113 -0
- package/assembly/util/helpers.ts +7 -13
- package/assembly/util/json.ts +2 -2
- package/assembly/util/wipc.ts +5 -3
- package/bin/build-worker-pool.js +7 -1
- package/bin/commands/build-core.js +6 -1
- package/bin/commands/build.js +1 -1
- package/bin/commands/clean-core.js +61 -16
- package/bin/commands/clean.js +11 -3
- package/bin/commands/fuzz-core.js +2 -2
- package/bin/commands/run-core.js +35 -24
- package/bin/commands/web-runner-source.js +14 -14
- package/bin/commands/web-session.js +6 -1
- package/bin/crash-store.js +3 -1
- package/bin/index.js +303 -124
- package/bin/reporters/default.js +175 -33
- package/bin/util.js +36 -11
- package/bin/wipc.js +7 -2
- package/lib/build/index.js +93 -25
- package/lib/src/index.ts +115 -36
- package/package.json +1 -3
- package/transform/lib/coverage.js +3 -1
package/lib/build/index.js
CHANGED
|
@@ -5,7 +5,6 @@ import http from "http";
|
|
|
5
5
|
import os from "os";
|
|
6
6
|
import path from "path";
|
|
7
7
|
import { pathToFileURL } from "url";
|
|
8
|
-
import { WASI } from "wasi";
|
|
9
8
|
import { buildWebRunnerClientSource } from "./web-runner/client.js";
|
|
10
9
|
import { buildWebRunnerHtml } from "./web-runner/html.js";
|
|
11
10
|
import { buildWebRunnerWorkerSource } from "./web-runner/worker.js";
|
|
@@ -25,29 +24,81 @@ function withNodeIo(imports) {
|
|
|
25
24
|
}
|
|
26
25
|
export async function instantiate(imports) {
|
|
27
26
|
validateImports(imports, "instantiate");
|
|
28
|
-
const wasmPath =
|
|
29
|
-
|
|
30
|
-
throw new Error("AS_TEST_WASM_PATH is not set; as-test must resolve the wasm artifact before launching the runner");
|
|
31
|
-
}
|
|
32
|
-
const target = (process.env.AS_TEST_RUNTIME_TARGET || "bindings");
|
|
27
|
+
const wasmPath = resolveWasmPath();
|
|
28
|
+
const target = resolveRuntimeTarget();
|
|
33
29
|
if (target == "wasi") {
|
|
34
30
|
return instantiateWasiInstance(wasmPath, imports);
|
|
35
31
|
}
|
|
36
32
|
if (target == "web") {
|
|
37
33
|
return instantiateWebInstance(wasmPath, imports);
|
|
38
34
|
}
|
|
39
|
-
const
|
|
35
|
+
const helperPath = resolveBindingsHelperPath(wasmPath);
|
|
36
|
+
const kind = resolveBindingsKind(helperPath);
|
|
40
37
|
if (kind == "raw") {
|
|
41
|
-
return instantiateRawInstance(wasmPath, imports);
|
|
38
|
+
return instantiateRawInstance(wasmPath, helperPath, imports);
|
|
42
39
|
}
|
|
43
40
|
if (kind == "esm") {
|
|
44
|
-
return instantiateEsmInstance(wasmPath, imports);
|
|
41
|
+
return instantiateEsmInstance(wasmPath, helperPath, imports);
|
|
45
42
|
}
|
|
46
43
|
if (kind == "none") {
|
|
47
44
|
return instantiateNoBindingsInstance(wasmPath, imports);
|
|
48
45
|
}
|
|
49
46
|
throw new Error(`unsupported bindings kind "${kind}"`);
|
|
50
47
|
}
|
|
48
|
+
function resolveRuntimeTarget() {
|
|
49
|
+
const envTarget = process.env.AS_TEST_RUNTIME_TARGET?.trim();
|
|
50
|
+
if (envTarget == "bindings" || envTarget == "wasi" || envTarget == "web") {
|
|
51
|
+
return envTarget;
|
|
52
|
+
}
|
|
53
|
+
const runnerPath = String(process.argv[1] ?? "");
|
|
54
|
+
if (runnerPath.includes(".wasi."))
|
|
55
|
+
return "wasi";
|
|
56
|
+
if (runnerPath.includes(".web."))
|
|
57
|
+
return "web";
|
|
58
|
+
return "bindings";
|
|
59
|
+
}
|
|
60
|
+
function resolveWasmPath() {
|
|
61
|
+
const envWasmPath = process.env.AS_TEST_WASM_PATH?.trim();
|
|
62
|
+
if (envWasmPath?.length) {
|
|
63
|
+
return path.resolve(envWasmPath);
|
|
64
|
+
}
|
|
65
|
+
const argWasmPath = process.argv[2]?.trim();
|
|
66
|
+
if (argWasmPath?.length) {
|
|
67
|
+
return path.resolve(argWasmPath);
|
|
68
|
+
}
|
|
69
|
+
const runnerPath = String(process.argv[1] ?? "");
|
|
70
|
+
const runnerName = path.basename(runnerPath || "runner.js");
|
|
71
|
+
throw new Error([
|
|
72
|
+
"No wasm artifact was provided for this runner.",
|
|
73
|
+
"",
|
|
74
|
+
`Direct usage: node .as-test/runners/${runnerName} .as-test/build/<artifact>.wasm`,
|
|
75
|
+
"Managed usage: bunx ast test --mode <mode>",
|
|
76
|
+
"",
|
|
77
|
+
"as-test normally sets AS_TEST_WASM_PATH automatically when it launches the runner.",
|
|
78
|
+
].join("\n"));
|
|
79
|
+
}
|
|
80
|
+
function resolveBindingsHelperPath(wasmPath) {
|
|
81
|
+
const envHelperPath = process.env.AS_TEST_HELPER_PATH?.trim();
|
|
82
|
+
if (envHelperPath?.length) {
|
|
83
|
+
return path.resolve(envHelperPath);
|
|
84
|
+
}
|
|
85
|
+
const candidate = wasmPath.replace(/\.wasm$/i, ".js");
|
|
86
|
+
return fs.existsSync(candidate) ? candidate : "";
|
|
87
|
+
}
|
|
88
|
+
function resolveBindingsKind(helperPath) {
|
|
89
|
+
const envKind = process.env.AS_TEST_BINDINGS_KIND?.trim();
|
|
90
|
+
if (envKind == "raw" || envKind == "esm" || envKind == "none") {
|
|
91
|
+
return envKind;
|
|
92
|
+
}
|
|
93
|
+
if (!helperPath.length) {
|
|
94
|
+
return "none";
|
|
95
|
+
}
|
|
96
|
+
const source = fs.readFileSync(helperPath, "utf8");
|
|
97
|
+
if (/\bexport\s+(?:async\s+)?function\s+instantiate\b/.test(source)) {
|
|
98
|
+
return "raw";
|
|
99
|
+
}
|
|
100
|
+
return "esm";
|
|
101
|
+
}
|
|
51
102
|
function validateImports(imports, fnName) {
|
|
52
103
|
if (arguments.length < 1) {
|
|
53
104
|
throw new Error(`${fnName}(imports) requires an imports object; pass {} when unused`);
|
|
@@ -96,7 +147,25 @@ function readExact(length) {
|
|
|
96
147
|
}
|
|
97
148
|
function writeRaw(data) {
|
|
98
149
|
const view = Buffer.from(data);
|
|
99
|
-
|
|
150
|
+
let offset = 0;
|
|
151
|
+
while (offset < view.byteLength) {
|
|
152
|
+
let written = 0;
|
|
153
|
+
try {
|
|
154
|
+
written = fs.writeSync(1, view, offset, view.byteLength - offset);
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
if (error &&
|
|
158
|
+
typeof error == "object" &&
|
|
159
|
+
"code" in error &&
|
|
160
|
+
error.code == "EAGAIN") {
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
throw error;
|
|
164
|
+
}
|
|
165
|
+
if (!written)
|
|
166
|
+
continue;
|
|
167
|
+
offset += written;
|
|
168
|
+
}
|
|
100
169
|
}
|
|
101
170
|
function mergeImports(...groups) {
|
|
102
171
|
const out = {};
|
|
@@ -117,9 +186,8 @@ function mergeImports(...groups) {
|
|
|
117
186
|
}
|
|
118
187
|
return out;
|
|
119
188
|
}
|
|
120
|
-
async function instantiateRawInstance(wasmPath, imports) {
|
|
189
|
+
async function instantiateRawInstance(wasmPath, helperPath, imports) {
|
|
121
190
|
validateImports(imports, "instantiateRawInstance");
|
|
122
|
-
const helperPath = process.env.AS_TEST_HELPER_PATH || "";
|
|
123
191
|
if (!helperPath.length) {
|
|
124
192
|
throw new Error("bindings kind is raw but AS_TEST_HELPER_PATH is not set");
|
|
125
193
|
}
|
|
@@ -135,9 +203,8 @@ async function instantiateRawInstance(wasmPath, imports) {
|
|
|
135
203
|
});
|
|
136
204
|
return decorateInstance(instance, "bindings");
|
|
137
205
|
}
|
|
138
|
-
async function instantiateEsmInstance(wasmPath, imports) {
|
|
206
|
+
async function instantiateEsmInstance(wasmPath, helperPath, imports) {
|
|
139
207
|
validateImports(imports, "instantiateEsmInstance");
|
|
140
|
-
const helperPath = process.env.AS_TEST_HELPER_PATH || "";
|
|
141
208
|
if (!helperPath.length) {
|
|
142
209
|
throw new Error("bindings kind is esm but AS_TEST_HELPER_PATH is not set");
|
|
143
210
|
}
|
|
@@ -157,6 +224,7 @@ async function instantiateNoBindingsInstance(wasmPath, imports) {
|
|
|
157
224
|
async function instantiateWasiInstance(wasmPath, imports) {
|
|
158
225
|
validateImports(imports, "instantiateWasiInstance");
|
|
159
226
|
suppressExperimentalWasiWarning();
|
|
227
|
+
const { WASI } = await import("wasi");
|
|
160
228
|
const binary = fs.readFileSync(wasmPath);
|
|
161
229
|
const module = new WebAssembly.Module(binary);
|
|
162
230
|
const wasi = new WASI({
|
|
@@ -176,7 +244,8 @@ async function instantiateWebInstance(wasmPath, imports) {
|
|
|
176
244
|
if (hasUserImports(imports)) {
|
|
177
245
|
throw new Error("web runtime does not support custom imports in the default runner; pass {} or write a custom web runner");
|
|
178
246
|
}
|
|
179
|
-
const bindingsKind = (process.env.AS_TEST_BINDINGS_KIND ||
|
|
247
|
+
const bindingsKind = (process.env.AS_TEST_BINDINGS_KIND ||
|
|
248
|
+
"raw");
|
|
180
249
|
const helperPath = process.env.AS_TEST_HELPER_PATH
|
|
181
250
|
? path.resolve(process.cwd(), process.env.AS_TEST_HELPER_PATH)
|
|
182
251
|
: wasmPath.replace(/\.wasm$/, ".js");
|
|
@@ -402,9 +471,9 @@ async function instantiateWebInstance(wasmPath, imports) {
|
|
|
402
471
|
...headers,
|
|
403
472
|
"Content-Type": "text/html; charset=utf-8",
|
|
404
473
|
});
|
|
405
|
-
res.end(html.replace("</body>",
|
|
474
|
+
res.end(html.replace("</body>", " <script>window.__AS_TEST_ENV__ = " +
|
|
406
475
|
JSON.stringify(webRuntimeEnv) +
|
|
407
|
-
|
|
476
|
+
";</script>\n </body>"));
|
|
408
477
|
return;
|
|
409
478
|
}
|
|
410
479
|
if (url == "/client.js") {
|
|
@@ -482,9 +551,7 @@ async function instantiateWebInstance(wasmPath, imports) {
|
|
|
482
551
|
});
|
|
483
552
|
socket.on("error", (error) => {
|
|
484
553
|
if (!finished) {
|
|
485
|
-
rejectOnce(error instanceof Error
|
|
486
|
-
? error
|
|
487
|
-
: new Error(String(error)));
|
|
554
|
+
rejectOnce(error instanceof Error ? error : new Error(String(error)));
|
|
488
555
|
}
|
|
489
556
|
});
|
|
490
557
|
flushPendingFrames();
|
|
@@ -582,7 +649,7 @@ function suppressExperimentalWasiWarning() {
|
|
|
582
649
|
const message = typeof warning == "string"
|
|
583
650
|
? warning
|
|
584
651
|
: String(warning && typeof warning == "object" && "message" in warning
|
|
585
|
-
? warning.message ?? ""
|
|
652
|
+
? (warning.message ?? "")
|
|
586
653
|
: "");
|
|
587
654
|
if (name == "ExperimentalWarning" &&
|
|
588
655
|
message.includes("WASI is an experimental feature")) {
|
|
@@ -713,7 +780,7 @@ function openWithReusableBrowserWindow(url) {
|
|
|
713
780
|
}
|
|
714
781
|
function openWithSystemBrowser(url) {
|
|
715
782
|
if (process.env.BROWSER) {
|
|
716
|
-
return spawnBrowserCommand(process.env.BROWSER, url, false)?.process ?? null;
|
|
783
|
+
return (spawnBrowserCommand(process.env.BROWSER, url, false)?.process ?? null);
|
|
717
784
|
}
|
|
718
785
|
if (process.platform == "darwin") {
|
|
719
786
|
if (!hasExecutable("open"))
|
|
@@ -770,7 +837,7 @@ function buildMacBrowserOpenScript(appName, url) {
|
|
|
770
837
|
return [
|
|
771
838
|
`tell application "${escapedApp}"`,
|
|
772
839
|
"activate",
|
|
773
|
-
|
|
840
|
+
"if (count of windows) = 0 then make new window",
|
|
774
841
|
`set URL of active tab of front window to "${escapedUrl}"`,
|
|
775
842
|
"end tell",
|
|
776
843
|
];
|
|
@@ -779,7 +846,7 @@ function buildMacBrowserOpenScript(appName, url) {
|
|
|
779
846
|
return [
|
|
780
847
|
`tell application "${escapedApp}"`,
|
|
781
848
|
"activate",
|
|
782
|
-
|
|
849
|
+
"if (count of windows) = 0 then make new document",
|
|
783
850
|
`set URL of front document to "${escapedUrl}"`,
|
|
784
851
|
"end tell",
|
|
785
852
|
];
|
|
@@ -1089,7 +1156,8 @@ async function captureHelperInstance(runHelper) {
|
|
|
1089
1156
|
await runHelper();
|
|
1090
1157
|
}
|
|
1091
1158
|
finally {
|
|
1092
|
-
WebAssembly.instantiate =
|
|
1159
|
+
WebAssembly.instantiate =
|
|
1160
|
+
originalInstantiate;
|
|
1093
1161
|
}
|
|
1094
1162
|
if (!instance) {
|
|
1095
1163
|
throw new Error("bindings helper did not produce a WebAssembly.Instance");
|
package/lib/src/index.ts
CHANGED
|
@@ -6,7 +6,7 @@ import os from "os";
|
|
|
6
6
|
import path from "path";
|
|
7
7
|
import type { Duplex } from "stream";
|
|
8
8
|
import { pathToFileURL } from "url";
|
|
9
|
-
import { WASI } from "wasi";
|
|
9
|
+
import type { WASI } from "wasi";
|
|
10
10
|
import { buildWebRunnerClientSource } from "./web-runner/client.js";
|
|
11
11
|
import { buildWebRunnerHtml } from "./web-runner/html.js";
|
|
12
12
|
import { buildWebRunnerWorkerSource } from "./web-runner/worker.js";
|
|
@@ -45,26 +45,22 @@ export async function instantiate(
|
|
|
45
45
|
): Promise<WebAssembly.Instance> {
|
|
46
46
|
validateImports(imports, "instantiate");
|
|
47
47
|
|
|
48
|
-
const wasmPath =
|
|
49
|
-
|
|
50
|
-
throw new Error(
|
|
51
|
-
"AS_TEST_WASM_PATH is not set; as-test must resolve the wasm artifact before launching the runner",
|
|
52
|
-
);
|
|
53
|
-
}
|
|
54
|
-
const target = (process.env.AS_TEST_RUNTIME_TARGET || "bindings") as RuntimeTarget;
|
|
48
|
+
const wasmPath = resolveWasmPath();
|
|
49
|
+
const target = resolveRuntimeTarget();
|
|
55
50
|
if (target == "wasi") {
|
|
56
51
|
return instantiateWasiInstance(wasmPath, imports);
|
|
57
52
|
}
|
|
58
53
|
if (target == "web") {
|
|
59
54
|
return instantiateWebInstance(wasmPath, imports);
|
|
60
55
|
}
|
|
61
|
-
const
|
|
56
|
+
const helperPath = resolveBindingsHelperPath(wasmPath);
|
|
57
|
+
const kind = resolveBindingsKind(helperPath);
|
|
62
58
|
|
|
63
59
|
if (kind == "raw") {
|
|
64
|
-
return instantiateRawInstance(wasmPath, imports);
|
|
60
|
+
return instantiateRawInstance(wasmPath, helperPath, imports);
|
|
65
61
|
}
|
|
66
62
|
if (kind == "esm") {
|
|
67
|
-
return instantiateEsmInstance(wasmPath, imports);
|
|
63
|
+
return instantiateEsmInstance(wasmPath, helperPath, imports);
|
|
68
64
|
}
|
|
69
65
|
if (kind == "none") {
|
|
70
66
|
return instantiateNoBindingsInstance(wasmPath, imports);
|
|
@@ -72,6 +68,64 @@ export async function instantiate(
|
|
|
72
68
|
throw new Error(`unsupported bindings kind "${kind}"`);
|
|
73
69
|
}
|
|
74
70
|
|
|
71
|
+
function resolveRuntimeTarget(): RuntimeTarget {
|
|
72
|
+
const envTarget = process.env.AS_TEST_RUNTIME_TARGET?.trim();
|
|
73
|
+
if (envTarget == "bindings" || envTarget == "wasi" || envTarget == "web") {
|
|
74
|
+
return envTarget;
|
|
75
|
+
}
|
|
76
|
+
const runnerPath = String(process.argv[1] ?? "");
|
|
77
|
+
if (runnerPath.includes(".wasi.")) return "wasi";
|
|
78
|
+
if (runnerPath.includes(".web.")) return "web";
|
|
79
|
+
return "bindings";
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function resolveWasmPath(): string {
|
|
83
|
+
const envWasmPath = process.env.AS_TEST_WASM_PATH?.trim();
|
|
84
|
+
if (envWasmPath?.length) {
|
|
85
|
+
return path.resolve(envWasmPath);
|
|
86
|
+
}
|
|
87
|
+
const argWasmPath = process.argv[2]?.trim();
|
|
88
|
+
if (argWasmPath?.length) {
|
|
89
|
+
return path.resolve(argWasmPath);
|
|
90
|
+
}
|
|
91
|
+
const runnerPath = String(process.argv[1] ?? "");
|
|
92
|
+
const runnerName = path.basename(runnerPath || "runner.js");
|
|
93
|
+
throw new Error(
|
|
94
|
+
[
|
|
95
|
+
"No wasm artifact was provided for this runner.",
|
|
96
|
+
"",
|
|
97
|
+
`Direct usage: node .as-test/runners/${runnerName} .as-test/build/<artifact>.wasm`,
|
|
98
|
+
"Managed usage: bunx ast test --mode <mode>",
|
|
99
|
+
"",
|
|
100
|
+
"as-test normally sets AS_TEST_WASM_PATH automatically when it launches the runner.",
|
|
101
|
+
].join("\n"),
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function resolveBindingsHelperPath(wasmPath: string): string {
|
|
106
|
+
const envHelperPath = process.env.AS_TEST_HELPER_PATH?.trim();
|
|
107
|
+
if (envHelperPath?.length) {
|
|
108
|
+
return path.resolve(envHelperPath);
|
|
109
|
+
}
|
|
110
|
+
const candidate = wasmPath.replace(/\.wasm$/i, ".js");
|
|
111
|
+
return fs.existsSync(candidate) ? candidate : "";
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function resolveBindingsKind(helperPath: string): BindingsKind {
|
|
115
|
+
const envKind = process.env.AS_TEST_BINDINGS_KIND?.trim();
|
|
116
|
+
if (envKind == "raw" || envKind == "esm" || envKind == "none") {
|
|
117
|
+
return envKind;
|
|
118
|
+
}
|
|
119
|
+
if (!helperPath.length) {
|
|
120
|
+
return "none";
|
|
121
|
+
}
|
|
122
|
+
const source = fs.readFileSync(helperPath, "utf8");
|
|
123
|
+
if (/\bexport\s+(?:async\s+)?function\s+instantiate\b/.test(source)) {
|
|
124
|
+
return "raw";
|
|
125
|
+
}
|
|
126
|
+
return "esm";
|
|
127
|
+
}
|
|
128
|
+
|
|
75
129
|
function validateImports(
|
|
76
130
|
imports: WebAssembly.Imports,
|
|
77
131
|
fnName: string,
|
|
@@ -130,7 +184,25 @@ function readExact(length: number): ArrayBuffer {
|
|
|
130
184
|
|
|
131
185
|
function writeRaw(data: ArrayBuffer): void {
|
|
132
186
|
const view = Buffer.from(data);
|
|
133
|
-
|
|
187
|
+
let offset = 0;
|
|
188
|
+
while (offset < view.byteLength) {
|
|
189
|
+
let written = 0;
|
|
190
|
+
try {
|
|
191
|
+
written = fs.writeSync(1, view, offset, view.byteLength - offset);
|
|
192
|
+
} catch (error) {
|
|
193
|
+
if (
|
|
194
|
+
error &&
|
|
195
|
+
typeof error == "object" &&
|
|
196
|
+
"code" in error &&
|
|
197
|
+
error.code == "EAGAIN"
|
|
198
|
+
) {
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
throw error;
|
|
202
|
+
}
|
|
203
|
+
if (!written) continue;
|
|
204
|
+
offset += written;
|
|
205
|
+
}
|
|
134
206
|
}
|
|
135
207
|
|
|
136
208
|
function mergeImports(...groups: unknown[]): AnyImports {
|
|
@@ -155,16 +227,18 @@ function mergeImports(...groups: unknown[]): AnyImports {
|
|
|
155
227
|
|
|
156
228
|
async function instantiateRawInstance(
|
|
157
229
|
wasmPath: string,
|
|
230
|
+
helperPath: string,
|
|
158
231
|
imports: WebAssembly.Imports,
|
|
159
232
|
): Promise<WebAssembly.Instance> {
|
|
160
233
|
validateImports(imports, "instantiateRawInstance");
|
|
161
|
-
const helperPath = process.env.AS_TEST_HELPER_PATH || "";
|
|
162
234
|
if (!helperPath.length) {
|
|
163
235
|
throw new Error("bindings kind is raw but AS_TEST_HELPER_PATH is not set");
|
|
164
236
|
}
|
|
165
237
|
const binary = fs.readFileSync(wasmPath);
|
|
166
238
|
const module = new WebAssembly.Module(binary);
|
|
167
|
-
const helper = (await import(
|
|
239
|
+
const helper = (await import(
|
|
240
|
+
`${pathToFileURL(helperPath).href}?t=${Date.now()}`
|
|
241
|
+
)) as {
|
|
168
242
|
instantiate?: (
|
|
169
243
|
module: WebAssembly.Module,
|
|
170
244
|
imports?: WebAssembly.Imports,
|
|
@@ -182,10 +256,10 @@ async function instantiateRawInstance(
|
|
|
182
256
|
|
|
183
257
|
async function instantiateEsmInstance(
|
|
184
258
|
wasmPath: string,
|
|
259
|
+
helperPath: string,
|
|
185
260
|
imports: WebAssembly.Imports,
|
|
186
261
|
): Promise<WebAssembly.Instance> {
|
|
187
262
|
validateImports(imports, "instantiateEsmInstance");
|
|
188
|
-
const helperPath = process.env.AS_TEST_HELPER_PATH || "";
|
|
189
263
|
if (!helperPath.length) {
|
|
190
264
|
throw new Error("bindings kind is esm but AS_TEST_HELPER_PATH is not set");
|
|
191
265
|
}
|
|
@@ -215,6 +289,7 @@ async function instantiateWasiInstance(
|
|
|
215
289
|
): Promise<WebAssembly.Instance> {
|
|
216
290
|
validateImports(imports, "instantiateWasiInstance");
|
|
217
291
|
suppressExperimentalWasiWarning();
|
|
292
|
+
const { WASI } = await import("wasi");
|
|
218
293
|
const binary = fs.readFileSync(wasmPath);
|
|
219
294
|
const module = new WebAssembly.Module(binary);
|
|
220
295
|
const wasi = new WASI({
|
|
@@ -241,7 +316,8 @@ async function instantiateWebInstance(
|
|
|
241
316
|
);
|
|
242
317
|
}
|
|
243
318
|
|
|
244
|
-
const bindingsKind = (process.env.AS_TEST_BINDINGS_KIND ||
|
|
319
|
+
const bindingsKind = (process.env.AS_TEST_BINDINGS_KIND ||
|
|
320
|
+
"raw") as BindingsKind;
|
|
245
321
|
const helperPath = process.env.AS_TEST_HELPER_PATH
|
|
246
322
|
? path.resolve(process.cwd(), process.env.AS_TEST_HELPER_PATH)
|
|
247
323
|
: wasmPath.replace(/\.wasm$/, ".js");
|
|
@@ -360,9 +436,11 @@ async function instantiateWebInstance(
|
|
|
360
436
|
if (message?.kind == "instantiated") {
|
|
361
437
|
if (resolved) return;
|
|
362
438
|
resolved = true;
|
|
363
|
-
resolve(
|
|
364
|
-
|
|
365
|
-
|
|
439
|
+
resolve(
|
|
440
|
+
createWebInstanceController(() => {
|
|
441
|
+
sendControl({ kind: "start" });
|
|
442
|
+
}),
|
|
443
|
+
);
|
|
366
444
|
return;
|
|
367
445
|
}
|
|
368
446
|
if (message?.kind == "done") {
|
|
@@ -459,9 +537,9 @@ async function instantiateWebInstance(
|
|
|
459
537
|
res.end(
|
|
460
538
|
html.replace(
|
|
461
539
|
"</body>",
|
|
462
|
-
|
|
540
|
+
" <script>window.__AS_TEST_ENV__ = " +
|
|
463
541
|
JSON.stringify(webRuntimeEnv) +
|
|
464
|
-
|
|
542
|
+
";</script>\n </body>",
|
|
465
543
|
),
|
|
466
544
|
);
|
|
467
545
|
return;
|
|
@@ -543,11 +621,7 @@ async function instantiateWebInstance(
|
|
|
543
621
|
});
|
|
544
622
|
socket.on("error", (error) => {
|
|
545
623
|
if (!finished) {
|
|
546
|
-
rejectOnce(
|
|
547
|
-
error instanceof Error
|
|
548
|
-
? error
|
|
549
|
-
: new Error(String(error)),
|
|
550
|
-
);
|
|
624
|
+
rejectOnce(error instanceof Error ? error : new Error(String(error)));
|
|
551
625
|
}
|
|
552
626
|
});
|
|
553
627
|
flushPendingFrames();
|
|
@@ -604,7 +678,9 @@ async function instantiateWebInstance(
|
|
|
604
678
|
return;
|
|
605
679
|
}
|
|
606
680
|
if (code && code != 0) {
|
|
607
|
-
rejectOnce(
|
|
681
|
+
rejectOnce(
|
|
682
|
+
new Error(formatBrowserExitError(code, browserStderr)),
|
|
683
|
+
);
|
|
608
684
|
return;
|
|
609
685
|
}
|
|
610
686
|
if (ready || wsSocket) {
|
|
@@ -613,9 +689,7 @@ async function instantiateWebInstance(
|
|
|
613
689
|
});
|
|
614
690
|
}
|
|
615
691
|
} catch (error) {
|
|
616
|
-
rejectOnce(
|
|
617
|
-
error instanceof Error ? error : new Error(String(error)),
|
|
618
|
-
);
|
|
692
|
+
rejectOnce(error instanceof Error ? error : new Error(String(error)));
|
|
619
693
|
}
|
|
620
694
|
});
|
|
621
695
|
});
|
|
@@ -662,7 +736,7 @@ function suppressExperimentalWasiWarning(): void {
|
|
|
662
736
|
? warning
|
|
663
737
|
: String(
|
|
664
738
|
warning && typeof warning == "object" && "message" in warning
|
|
665
|
-
? (warning as { message?: unknown }).message ?? ""
|
|
739
|
+
? ((warning as { message?: unknown }).message ?? "")
|
|
666
740
|
: "",
|
|
667
741
|
);
|
|
668
742
|
if (
|
|
@@ -813,7 +887,9 @@ function launchWebBrowser(
|
|
|
813
887
|
function openWithReusableBrowserWindow(url: string): ChildProcess | null {
|
|
814
888
|
if (process.platform != "darwin") return null;
|
|
815
889
|
if (!hasExecutable("osascript")) return null;
|
|
816
|
-
const browserApp = resolveMacBrowserAppName(
|
|
890
|
+
const browserApp = resolveMacBrowserAppName(
|
|
891
|
+
process.env.BROWSER?.trim() ?? "",
|
|
892
|
+
);
|
|
817
893
|
if (!browserApp) return null;
|
|
818
894
|
const script = buildMacBrowserOpenScript(browserApp, url);
|
|
819
895
|
if (!script.length) return null;
|
|
@@ -826,7 +902,9 @@ function openWithReusableBrowserWindow(url: string): ChildProcess | null {
|
|
|
826
902
|
|
|
827
903
|
function openWithSystemBrowser(url: string): ChildProcess | null {
|
|
828
904
|
if (process.env.BROWSER) {
|
|
829
|
-
return
|
|
905
|
+
return (
|
|
906
|
+
spawnBrowserCommand(process.env.BROWSER, url, false)?.process ?? null
|
|
907
|
+
);
|
|
830
908
|
}
|
|
831
909
|
if (process.platform == "darwin") {
|
|
832
910
|
if (!hasExecutable("open")) return null;
|
|
@@ -883,7 +961,7 @@ function buildMacBrowserOpenScript(appName: string, url: string): string[] {
|
|
|
883
961
|
return [
|
|
884
962
|
`tell application "${escapedApp}"`,
|
|
885
963
|
"activate",
|
|
886
|
-
|
|
964
|
+
"if (count of windows) = 0 then make new window",
|
|
887
965
|
`set URL of active tab of front window to "${escapedUrl}"`,
|
|
888
966
|
"end tell",
|
|
889
967
|
];
|
|
@@ -892,7 +970,7 @@ function buildMacBrowserOpenScript(appName: string, url: string): string[] {
|
|
|
892
970
|
return [
|
|
893
971
|
`tell application "${escapedApp}"`,
|
|
894
972
|
"activate",
|
|
895
|
-
|
|
973
|
+
"if (count of windows) = 0 then make new document",
|
|
896
974
|
`set URL of front document to "${escapedUrl}"`,
|
|
897
975
|
"end tell",
|
|
898
976
|
];
|
|
@@ -1238,7 +1316,8 @@ async function captureHelperInstance(
|
|
|
1238
1316
|
try {
|
|
1239
1317
|
await runHelper();
|
|
1240
1318
|
} finally {
|
|
1241
|
-
WebAssembly.instantiate =
|
|
1319
|
+
WebAssembly.instantiate =
|
|
1320
|
+
originalInstantiate as typeof WebAssembly.instantiate;
|
|
1242
1321
|
}
|
|
1243
1322
|
|
|
1244
1323
|
if (!instance) {
|
package/package.json
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "as-test",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"author": "Jairus Tanaka",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/JairusSW/as-test.git"
|
|
8
8
|
},
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"as-rainbow": "^0.1.0",
|
|
11
|
-
"as-console": "^7.0.0",
|
|
12
10
|
"chalk": "^5.6.2",
|
|
13
11
|
"glob": "^13.0.6",
|
|
14
12
|
"typer-diff": "^1.1.1",
|
|
@@ -214,7 +214,9 @@ export class CoverageTransform extends Visitor {
|
|
|
214
214
|
const ifTrue = node.ifTrue;
|
|
215
215
|
const ifFalse = node.ifFalse;
|
|
216
216
|
const path = node.range.source.normalizedPath;
|
|
217
|
-
if (ifTrue
|
|
217
|
+
if (ifTrue &&
|
|
218
|
+
ifTrue.kind !== 31 &&
|
|
219
|
+
!isBuiltinStatement(ifTrue)) {
|
|
218
220
|
const trueLc = getLineCol(ifTrue);
|
|
219
221
|
const point = new CoverPoint();
|
|
220
222
|
point.line = trueLc?.line;
|