@zappdev/cli 0.1.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/README.md +55 -0
- package/dist/zapp-cli.js +9471 -0
- package/native/src/app/app.zc +490 -0
- package/native/src/event/event.zc +24 -0
- package/native/src/event/events.zc +70 -0
- package/native/src/platform/darwin/backend.zc +923 -0
- package/native/src/platform/darwin/backend_bootstrap.zc +9 -0
- package/native/src/platform/darwin/bootstrap.zc +9 -0
- package/native/src/platform/darwin/engine_jsc.zc +86 -0
- package/native/src/platform/darwin/engine_qjs.zc +92 -0
- package/native/src/platform/darwin/platform.zc +156 -0
- package/native/src/platform/darwin/webview.zc +550 -0
- package/native/src/platform/darwin/webview_bootstrap.zc +9 -0
- package/native/src/platform/darwin/window.zc +1223 -0
- package/native/src/platform/darwin/worker/common.zc +223 -0
- package/native/src/platform/darwin/worker/core/base64_core.zc +29 -0
- package/native/src/platform/darwin/worker/core/crypto_core.zc +19 -0
- package/native/src/platform/darwin/worker/core/encoding_core.zc +32 -0
- package/native/src/platform/darwin/worker/core/fetch_core.zc +145 -0
- package/native/src/platform/darwin/worker/core/url_core.zc +69 -0
- package/native/src/platform/darwin/worker/core/websocket_core.zc +179 -0
- package/native/src/platform/darwin/worker/dispatch.zc +55 -0
- package/native/src/platform/darwin/worker/jsc/base64_jsc.zc +39 -0
- package/native/src/platform/darwin/worker/jsc/crypto_jsc.zc +49 -0
- package/native/src/platform/darwin/worker/jsc/encoding_jsc.zc +86 -0
- package/native/src/platform/darwin/worker/jsc/fetch_jsc.zc +149 -0
- package/native/src/platform/darwin/worker/jsc/url_jsc.zc +54 -0
- package/native/src/platform/darwin/worker/jsc/websocket_jsc.zc +127 -0
- package/native/src/platform/darwin/worker/jsc.zc +670 -0
- package/native/src/platform/darwin/worker/mod.zc +30 -0
- package/native/src/platform/darwin/worker/qjs/fetch_qjs.zc +233 -0
- package/native/src/platform/darwin/worker/qjs/qjs_macros.zc +23 -0
- package/native/src/platform/darwin/worker/qjs/websocket_qjs.zc +223 -0
- package/native/src/platform/darwin/worker/qjs.zc +1053 -0
- package/native/src/platform/darwin/worker/timers.zc +149 -0
- package/native/src/platform/darwin/worker/timers_qjs.zc +209 -0
- package/native/src/platform/platform.zc +64 -0
- package/native/src/platform/shared/log.zc +156 -0
- package/native/src/platform/shared/worker/qjs/base64_qjs.zc +38 -0
- package/native/src/platform/shared/worker/qjs/crypto_qjs.zc +44 -0
- package/native/src/platform/shared/worker/qjs/encoding_qjs.zc +95 -0
- package/native/src/platform/shared/worker/qjs/url_qjs.zc +65 -0
- package/native/src/platform/shared/worker_registry.zc +206 -0
- package/native/src/platform/window.zc +446 -0
- package/native/src/platform/windows/backend.zc +452 -0
- package/native/src/platform/windows/backend_bootstrap.zc +9 -0
- package/native/src/platform/windows/bootstrap.zc +9 -0
- package/native/src/platform/windows/engine_qjs.zc +60 -0
- package/native/src/platform/windows/platform.zc +387 -0
- package/native/src/platform/windows/webview.zc +1175 -0
- package/native/src/platform/windows/webview_bootstrap.zc +9 -0
- package/native/src/platform/windows/window.zc +1271 -0
- package/native/src/platform/windows/worker/common.zc +409 -0
- package/native/src/platform/windows/worker/core/base64_core.zc +52 -0
- package/native/src/platform/windows/worker/core/crypto_core.zc +34 -0
- package/native/src/platform/windows/worker/core/encoding_core.zc +60 -0
- package/native/src/platform/windows/worker/core/fetch_core.zc +274 -0
- package/native/src/platform/windows/worker/core/url_core.zc +216 -0
- package/native/src/platform/windows/worker/core/websocket_core.zc +343 -0
- package/native/src/platform/windows/worker/dispatch.zc +34 -0
- package/native/src/platform/windows/worker/mod.zc +46 -0
- package/native/src/platform/windows/worker/qjs/fetch_qjs.zc +255 -0
- package/native/src/platform/windows/worker/qjs/websocket_qjs.zc +263 -0
- package/native/src/platform/windows/worker/qjs.zc +1049 -0
- package/native/src/platform/windows/worker/timers_qjs.zc +288 -0
- package/native/src/platform/worker.zc +8 -0
- package/native/src/service/service.zc +228 -0
- package/native/vendor/quickjs-ng/.gitattributes +4 -0
- package/native/vendor/quickjs-ng/.github/dependabot.yml +7 -0
- package/native/vendor/quickjs-ng/.github/workflows/ci.yml +812 -0
- package/native/vendor/quickjs-ng/.github/workflows/docs.yml +49 -0
- package/native/vendor/quickjs-ng/.github/workflows/release.yml +162 -0
- package/native/vendor/quickjs-ng/.github/workflows/test-docs.yml +23 -0
- package/native/vendor/quickjs-ng/.github/workflows/tsan.yml +32 -0
- package/native/vendor/quickjs-ng/.github/workflows/valgrind.yml +33 -0
- package/native/vendor/quickjs-ng/.gitmodules +5 -0
- package/native/vendor/quickjs-ng/CMakeLists.txt +553 -0
- package/native/vendor/quickjs-ng/LICENSE +24 -0
- package/native/vendor/quickjs-ng/Makefile +149 -0
- package/native/vendor/quickjs-ng/amalgam.js +53 -0
- package/native/vendor/quickjs-ng/api-test.c +927 -0
- package/native/vendor/quickjs-ng/builtin-array-fromasync.h +119 -0
- package/native/vendor/quickjs-ng/builtin-array-fromasync.js +36 -0
- package/native/vendor/quickjs-ng/builtin-iterator-zip-keyed.h +332 -0
- package/native/vendor/quickjs-ng/builtin-iterator-zip-keyed.js +194 -0
- package/native/vendor/quickjs-ng/builtin-iterator-zip.h +337 -0
- package/native/vendor/quickjs-ng/builtin-iterator-zip.js +210 -0
- package/native/vendor/quickjs-ng/ctest.c +17 -0
- package/native/vendor/quickjs-ng/cutils.h +2013 -0
- package/native/vendor/quickjs-ng/cxxtest.cc +2 -0
- package/native/vendor/quickjs-ng/dtoa.c +1619 -0
- package/native/vendor/quickjs-ng/dtoa.h +87 -0
- package/native/vendor/quickjs-ng/examples/fib.c +67 -0
- package/native/vendor/quickjs-ng/examples/fib_module.js +10 -0
- package/native/vendor/quickjs-ng/examples/hello.js +1 -0
- package/native/vendor/quickjs-ng/examples/hello_module.js +6 -0
- package/native/vendor/quickjs-ng/examples/meson.build +17 -0
- package/native/vendor/quickjs-ng/examples/pi_bigint.js +118 -0
- package/native/vendor/quickjs-ng/examples/point.c +154 -0
- package/native/vendor/quickjs-ng/examples/test_fib.js +8 -0
- package/native/vendor/quickjs-ng/examples/test_point.js +43 -0
- package/native/vendor/quickjs-ng/fuzz.c +51 -0
- package/native/vendor/quickjs-ng/gen/function_source.c +81 -0
- package/native/vendor/quickjs-ng/gen/hello.c +53 -0
- package/native/vendor/quickjs-ng/gen/hello_module.c +106 -0
- package/native/vendor/quickjs-ng/gen/repl.c +3053 -0
- package/native/vendor/quickjs-ng/gen/standalone.c +324 -0
- package/native/vendor/quickjs-ng/gen/test_fib.c +81 -0
- package/native/vendor/quickjs-ng/libregexp-opcode.h +58 -0
- package/native/vendor/quickjs-ng/libregexp.c +2687 -0
- package/native/vendor/quickjs-ng/libregexp.h +98 -0
- package/native/vendor/quickjs-ng/libunicode-table.h +4707 -0
- package/native/vendor/quickjs-ng/libunicode.c +1746 -0
- package/native/vendor/quickjs-ng/libunicode.h +126 -0
- package/native/vendor/quickjs-ng/list.h +107 -0
- package/native/vendor/quickjs-ng/lre-test.c +73 -0
- package/native/vendor/quickjs-ng/meson.build +684 -0
- package/native/vendor/quickjs-ng/meson_options.txt +6 -0
- package/native/vendor/quickjs-ng/qjs-wasi-reactor.c +208 -0
- package/native/vendor/quickjs-ng/qjs.c +748 -0
- package/native/vendor/quickjs-ng/qjsc.c +673 -0
- package/native/vendor/quickjs-ng/quickjs-atom.h +267 -0
- package/native/vendor/quickjs-ng/quickjs-c-atomics.h +54 -0
- package/native/vendor/quickjs-ng/quickjs-libc.c +4986 -0
- package/native/vendor/quickjs-ng/quickjs-libc.h +79 -0
- package/native/vendor/quickjs-ng/quickjs-opcode.h +369 -0
- package/native/vendor/quickjs-ng/quickjs.c +60259 -0
- package/native/vendor/quickjs-ng/quickjs.h +1419 -0
- package/native/vendor/quickjs-ng/repl.js +1927 -0
- package/native/vendor/quickjs-ng/run-test262.c +2417 -0
- package/native/vendor/quickjs-ng/standalone.js +129 -0
- package/native/vendor/quickjs-ng/tests/assert.js +49 -0
- package/native/vendor/quickjs-ng/tests/bug1221.js +16 -0
- package/native/vendor/quickjs-ng/tests/bug1296.js +12 -0
- package/native/vendor/quickjs-ng/tests/bug1297.js +22 -0
- package/native/vendor/quickjs-ng/tests/bug1301.js +21 -0
- package/native/vendor/quickjs-ng/tests/bug1302.js +24 -0
- package/native/vendor/quickjs-ng/tests/bug1305.js +26 -0
- package/native/vendor/quickjs-ng/tests/bug1318.js +54 -0
- package/native/vendor/quickjs-ng/tests/bug1352.js +8 -0
- package/native/vendor/quickjs-ng/tests/bug1354.js +6 -0
- package/native/vendor/quickjs-ng/tests/bug1355.js +58 -0
- package/native/vendor/quickjs-ng/tests/bug1368.js +9 -0
- package/native/vendor/quickjs-ng/tests/bug39/1.js +6 -0
- package/native/vendor/quickjs-ng/tests/bug39/2.js +6 -0
- package/native/vendor/quickjs-ng/tests/bug39/3.js +7 -0
- package/native/vendor/quickjs-ng/tests/bug488-upstream.js +7 -0
- package/native/vendor/quickjs-ng/tests/bug633/0.js +7 -0
- package/native/vendor/quickjs-ng/tests/bug633/1.js +4 -0
- package/native/vendor/quickjs-ng/tests/bug633/2.js +4 -0
- package/native/vendor/quickjs-ng/tests/bug633/3.js +4 -0
- package/native/vendor/quickjs-ng/tests/bug645/0.js +4 -0
- package/native/vendor/quickjs-ng/tests/bug645/1.js +9 -0
- package/native/vendor/quickjs-ng/tests/bug645/2.js +7 -0
- package/native/vendor/quickjs-ng/tests/bug648.js +13 -0
- package/native/vendor/quickjs-ng/tests/bug652.js +4 -0
- package/native/vendor/quickjs-ng/tests/bug741.js +19 -0
- package/native/vendor/quickjs-ng/tests/bug775.js +7 -0
- package/native/vendor/quickjs-ng/tests/bug776.js +7 -0
- package/native/vendor/quickjs-ng/tests/bug832.js +2 -0
- package/native/vendor/quickjs-ng/tests/bug858.js +26 -0
- package/native/vendor/quickjs-ng/tests/bug904.js +6 -0
- package/native/vendor/quickjs-ng/tests/bug988.js +7 -0
- package/native/vendor/quickjs-ng/tests/bug999.js +3 -0
- package/native/vendor/quickjs-ng/tests/destructured-export.js +8 -0
- package/native/vendor/quickjs-ng/tests/detect_module/0.js +1 -0
- package/native/vendor/quickjs-ng/tests/detect_module/1.js +2 -0
- package/native/vendor/quickjs-ng/tests/detect_module/2.js +1 -0
- package/native/vendor/quickjs-ng/tests/detect_module/3.js +8 -0
- package/native/vendor/quickjs-ng/tests/detect_module/4.js +3 -0
- package/native/vendor/quickjs-ng/tests/empty.js +0 -0
- package/native/vendor/quickjs-ng/tests/fixture_cyclic_import.js +2 -0
- package/native/vendor/quickjs-ng/tests/fixture_string_exports.js +12 -0
- package/native/vendor/quickjs-ng/tests/function_source.js +14 -0
- package/native/vendor/quickjs-ng/tests/microbench.js +1267 -0
- package/native/vendor/quickjs-ng/tests/null_or_undefined.js +38 -0
- package/native/vendor/quickjs-ng/tests/str-pad-leak.js +5 -0
- package/native/vendor/quickjs-ng/tests/test_bigint.js +107 -0
- package/native/vendor/quickjs-ng/tests/test_bjson.js +366 -0
- package/native/vendor/quickjs-ng/tests/test_builtin.js +1314 -0
- package/native/vendor/quickjs-ng/tests/test_closure.js +220 -0
- package/native/vendor/quickjs-ng/tests/test_cyclic_import.js +12 -0
- package/native/vendor/quickjs-ng/tests/test_domexception.js +35 -0
- package/native/vendor/quickjs-ng/tests/test_language.js +755 -0
- package/native/vendor/quickjs-ng/tests/test_loop.js +367 -0
- package/native/vendor/quickjs-ng/tests/test_queue_microtask.js +39 -0
- package/native/vendor/quickjs-ng/tests/test_std.js +340 -0
- package/native/vendor/quickjs-ng/tests/test_string_exports.js +25 -0
- package/native/vendor/quickjs-ng/tests/test_worker.js +43 -0
- package/native/vendor/quickjs-ng/tests/test_worker_module.js +30 -0
- package/native/vendor/quickjs-ng/tests.conf +14 -0
- package/native/vendor/quickjs-ng/unicode_download.sh +19 -0
- package/native/vendor/quickjs-ng/unicode_gen.c +3108 -0
- package/native/vendor/quickjs-ng/unicode_gen_def.h +310 -0
- package/native/vendor/quickjs-ng/update-version.sh +32 -0
- package/native/vendor/webview2/include/WebView2.h +60636 -0
- package/native/vendor/webview2/include/WebView2EnvironmentOptions.h +406 -0
- package/package.json +33 -0
- package/src/backend.ts +139 -0
- package/src/build-config.ts +87 -0
- package/src/build.ts +276 -0
- package/src/common.ts +195 -0
- package/src/config.ts +89 -0
- package/src/dev.ts +164 -0
- package/src/generate.ts +200 -0
- package/src/icons.ts +116 -0
- package/src/init.ts +190 -0
- package/src/package.ts +150 -0
- package/src/zapp-cli.ts +263 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import * as std from "qjs:std";
|
|
2
|
+
import * as os from "qjs:os";
|
|
3
|
+
import * as bjson from "qjs:bjson";
|
|
4
|
+
|
|
5
|
+
// See quickjs.h
|
|
6
|
+
const JS_READ_OBJ_BYTECODE = 1 << 0;
|
|
7
|
+
const JS_READ_OBJ_REFERENCE = 1 << 3;
|
|
8
|
+
const JS_WRITE_OBJ_BYTECODE = 1 << 0;
|
|
9
|
+
const JS_WRITE_OBJ_REFERENCE = 1 << 3;
|
|
10
|
+
const JS_WRITE_OBJ_STRIP_SOURCE = 1 << 4;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Trailer for standalone binaries. When some code gets bundled with the qjs
|
|
14
|
+
* executable we add a 12 byte trailer. The first 8 bytes are the magic
|
|
15
|
+
* string that helps us understand this is a standalone binary, and the
|
|
16
|
+
* remaining 4 are the offset (before the trailer) where the bundled data
|
|
17
|
+
* is located.
|
|
18
|
+
*
|
|
19
|
+
* The offset is stored as a 32bit little-endian number.
|
|
20
|
+
*/
|
|
21
|
+
const Trailer = {
|
|
22
|
+
Magic: 'quickjs2',
|
|
23
|
+
MagicSize: 8,
|
|
24
|
+
DataSize: 4,
|
|
25
|
+
Size: 12
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
function encodeAscii(txt) {
|
|
29
|
+
return new Uint8Array(txt.split('').map(c => c.charCodeAt(0)));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function decodeAscii(buf) {
|
|
33
|
+
return Array.from(buf).map(c => String.fromCharCode(c)).join('')
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function compileStandalone(inFile, outFile, targetExe) {
|
|
37
|
+
// Step 1: compile the source file to bytecode
|
|
38
|
+
const js = std.loadFile(inFile);
|
|
39
|
+
|
|
40
|
+
if (!js) {
|
|
41
|
+
throw new Error(`failed to open ${inFile}`);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const code = std.evalScript(js, {
|
|
45
|
+
compile_only: true,
|
|
46
|
+
compile_module: true
|
|
47
|
+
});
|
|
48
|
+
const bytecode = new Uint8Array(bjson.write(code, JS_WRITE_OBJ_BYTECODE | JS_WRITE_OBJ_REFERENCE | JS_WRITE_OBJ_STRIP_SOURCE));
|
|
49
|
+
|
|
50
|
+
// Step 2: copy the bytecode to the end of the executable and add a marker.
|
|
51
|
+
const exeFileName = targetExe ?? os.exePath() ?? globalThis.argv0;
|
|
52
|
+
const exe = std.loadFile(exeFileName, { binary: true });
|
|
53
|
+
|
|
54
|
+
if (!exe) {
|
|
55
|
+
throw new Error(`failed to open executable: ${exeFileName}`);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const exeSize = exe.length;
|
|
59
|
+
const newBuffer = exe.buffer.transfer(exeSize + bytecode.length + Trailer.Size);
|
|
60
|
+
const newExe = new Uint8Array(newBuffer);
|
|
61
|
+
|
|
62
|
+
newExe.set(bytecode, exeSize);
|
|
63
|
+
newExe.set(encodeAscii(Trailer.Magic), exeSize + bytecode.length);
|
|
64
|
+
|
|
65
|
+
const dw = new DataView(newBuffer, exeSize + bytecode.length + Trailer.MagicSize, Trailer.DataSize);
|
|
66
|
+
|
|
67
|
+
dw.setUint32(0, bytecode.length, true /* little-endian */);
|
|
68
|
+
|
|
69
|
+
// We use os.open() so we can set the permissions mask.
|
|
70
|
+
const newFd = os.open(outFile, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o755);
|
|
71
|
+
|
|
72
|
+
if (newFd < 0) {
|
|
73
|
+
throw new Error(`failed to create ${outFile}`);
|
|
74
|
+
}
|
|
75
|
+
if (os.write(newFd, newBuffer, 0, newBuffer.byteLength) < 0) {
|
|
76
|
+
os.close(newFd);
|
|
77
|
+
throw new Error(`failed to write to output file`);
|
|
78
|
+
}
|
|
79
|
+
os.close(newFd);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function runStandalone() {
|
|
83
|
+
const file = os.exePath() ?? globalThis.argv0;
|
|
84
|
+
const exe = std.open(file, 'rb');
|
|
85
|
+
|
|
86
|
+
if (!exe) {
|
|
87
|
+
throw new Error(`failed to open executable: ${file}`);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
let r = exe.seek(-Trailer.Size, std.SEEK_END);
|
|
91
|
+
if (r < 0) {
|
|
92
|
+
throw new Error(`seek error: ${-r}`);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const trailer = new Uint8Array(Trailer.Size);
|
|
96
|
+
|
|
97
|
+
exe.read(trailer.buffer, 0, Trailer.Size);
|
|
98
|
+
|
|
99
|
+
const magic = new Uint8Array(trailer.buffer, 0, Trailer.MagicSize);
|
|
100
|
+
|
|
101
|
+
// Shouldn't happen since qjs.c checks for it.
|
|
102
|
+
if (decodeAscii(magic) !== Trailer.Magic) {
|
|
103
|
+
exe.close();
|
|
104
|
+
throw new Error('corrupted binary, magic mismatch');
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const dw = new DataView(trailer.buffer, Trailer.MagicSize, Trailer.DataSize);
|
|
108
|
+
const bytecodelen = dw.getUint32(0, true /* little-endian */);
|
|
109
|
+
const bytecode = new Uint8Array(bytecodelen);
|
|
110
|
+
|
|
111
|
+
r = exe.seek(-(bytecodelen + Trailer.Size), std.SEEK_END);
|
|
112
|
+
if (r < 0) {
|
|
113
|
+
exe.close();
|
|
114
|
+
throw new Error(`seek error: ${-r}`);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
exe.read(bytecode.buffer, 0, bytecode.length);
|
|
118
|
+
if (exe.error()) {
|
|
119
|
+
exe.close();
|
|
120
|
+
throw new Error('read error');
|
|
121
|
+
}
|
|
122
|
+
exe.close();
|
|
123
|
+
|
|
124
|
+
const code = bjson.read(bytecode.buffer, 0, bytecode.length, JS_READ_OBJ_BYTECODE | JS_READ_OBJ_REFERENCE);
|
|
125
|
+
|
|
126
|
+
return std.evalScript(code, {
|
|
127
|
+
eval_module: true
|
|
128
|
+
});
|
|
129
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export function assert(actual, expected, message) {
|
|
2
|
+
if (arguments.length === 1)
|
|
3
|
+
expected = true;
|
|
4
|
+
|
|
5
|
+
if (typeof actual === typeof expected) {
|
|
6
|
+
if (actual === expected) {
|
|
7
|
+
if (actual !== 0 || (1 / actual) === (1 / expected))
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
if (typeof actual === 'number') {
|
|
11
|
+
if (isNaN(actual) && isNaN(expected))
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
if (typeof actual === 'object') {
|
|
15
|
+
if (actual !== null && expected !== null
|
|
16
|
+
&& actual.constructor === expected.constructor
|
|
17
|
+
&& actual.toString() === expected.toString())
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
throw Error("assertion failed: got |" + actual + "|" +
|
|
22
|
+
", expected |" + expected + "|" +
|
|
23
|
+
(message ? " (" + message + ")" : ""));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function assertThrows(err, func)
|
|
27
|
+
{
|
|
28
|
+
var ex;
|
|
29
|
+
ex = false;
|
|
30
|
+
try {
|
|
31
|
+
func();
|
|
32
|
+
} catch(e) {
|
|
33
|
+
ex = true;
|
|
34
|
+
assert(e instanceof err);
|
|
35
|
+
}
|
|
36
|
+
assert(ex, true, "exception expected");
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function assertArrayEquals(a, b)
|
|
40
|
+
{
|
|
41
|
+
if (!Array.isArray(a) || !Array.isArray(b))
|
|
42
|
+
return assert(false);
|
|
43
|
+
|
|
44
|
+
assert(a.length, b.length);
|
|
45
|
+
|
|
46
|
+
a.forEach((value, idx) => {
|
|
47
|
+
assert(b[idx], value);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {assert} from "./assert.js"
|
|
2
|
+
|
|
3
|
+
let caught = 0
|
|
4
|
+
for (let i = 1; i <= 32; i++) {
|
|
5
|
+
const prefix = "(:?".repeat(i)
|
|
6
|
+
const suffix = "|)+".repeat(i)
|
|
7
|
+
const between = "(?:a|)+"
|
|
8
|
+
try {
|
|
9
|
+
new RegExp(prefix + between + suffix)
|
|
10
|
+
} catch (e) {
|
|
11
|
+
assert(e instanceof SyntaxError)
|
|
12
|
+
assert(e.message, "out of memory")
|
|
13
|
+
caught++
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
assert(caught, 12) // subject to change
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const ab = new ArrayBuffer(10, { maxByteLength: 10 });
|
|
2
|
+
function f() {
|
|
3
|
+
return 1337;
|
|
4
|
+
}
|
|
5
|
+
const evil = f.bind();
|
|
6
|
+
|
|
7
|
+
Object.defineProperty(evil, "prototype", { get: () => {
|
|
8
|
+
print("resizing");
|
|
9
|
+
return ab.resize();
|
|
10
|
+
} });
|
|
11
|
+
let u8 = Reflect.construct(Uint8Array, [ab], evil);
|
|
12
|
+
print(u8);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// Test for issue #1297: Heap buffer overflow in js_typed_array_sort
|
|
2
|
+
// The bug occurs when a comparator function resizes the ArrayBuffer during sort
|
|
3
|
+
|
|
4
|
+
const sz = 256;
|
|
5
|
+
const newSz = 10;
|
|
6
|
+
const ab = new ArrayBuffer(sz, { maxByteLength: sz * 10 });
|
|
7
|
+
const u8 = new Uint8Array(ab);
|
|
8
|
+
|
|
9
|
+
for (let i = 0; i < sz; i++) u8[i] = i;
|
|
10
|
+
u8[sz - 1] = 0;
|
|
11
|
+
|
|
12
|
+
let cnt = 0;
|
|
13
|
+
u8.sort((a, b) => {
|
|
14
|
+
for (let i = 0; i < 3000; i++) {
|
|
15
|
+
try { ab.resize(newSz); } catch(e){}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return a - b;
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// If we get here without crashing, the fix works
|
|
22
|
+
print("PASS: bug1297 - typed array sort with resize did not crash");
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/*---
|
|
2
|
+
features: [skip-if-tcc]
|
|
3
|
+
---*/
|
|
4
|
+
|
|
5
|
+
import {assert} from "./assert.js"
|
|
6
|
+
|
|
7
|
+
const rab = new ArrayBuffer(1024, { maxByteLength: 1024 * 1024 });
|
|
8
|
+
const i32 = new Int32Array(rab);
|
|
9
|
+
const evil = {
|
|
10
|
+
valueOf: () => {
|
|
11
|
+
print("resize buffer");
|
|
12
|
+
rab.resize(0);
|
|
13
|
+
return 123;
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
try {
|
|
18
|
+
Atomics.store(i32, 0, evil);
|
|
19
|
+
} catch (e) {
|
|
20
|
+
assert(e instanceof RangeError);
|
|
21
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/*---
|
|
2
|
+
features: [skip-if-tcc]
|
|
3
|
+
---*/
|
|
4
|
+
|
|
5
|
+
import {assert} from "./assert.js"
|
|
6
|
+
|
|
7
|
+
const rab = new ArrayBuffer(1024, { maxByteLength: 1024 * 1024 });
|
|
8
|
+
const i32 = new Int32Array(rab);
|
|
9
|
+
const evil = {
|
|
10
|
+
valueOf: () => {
|
|
11
|
+
print("resize buffer");
|
|
12
|
+
rab.resize(0);
|
|
13
|
+
return 123;
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
try {
|
|
17
|
+
Atomics.add(i32, 0, evil);
|
|
18
|
+
// Atomics.sub(i32, 0, evil);
|
|
19
|
+
// Atomics.and(i32, 0, evil);
|
|
20
|
+
// Atomics.or(i32, 0, evil);
|
|
21
|
+
// Atomics.xor(i32, 0, evil);
|
|
22
|
+
} catch (e) {
|
|
23
|
+
assert(e instanceof RangeError);
|
|
24
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import {assert} from "./assert.js"
|
|
2
|
+
|
|
3
|
+
const rab = new ArrayBuffer(10, { maxByteLength: 10 });
|
|
4
|
+
const src = new Uint8Array(rab, 0);
|
|
5
|
+
|
|
6
|
+
function f() {
|
|
7
|
+
return 1337;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const EvilConstructor = new Proxy(function(){}, {
|
|
11
|
+
get: function(target, prop, receiver) {
|
|
12
|
+
if (prop === 'prototype') {
|
|
13
|
+
print("resizing");
|
|
14
|
+
rab.resize(0);
|
|
15
|
+
return Uint8Array.prototype;
|
|
16
|
+
}
|
|
17
|
+
return Reflect.get(target, prop, receiver);
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
let u8 = Reflect.construct(Uint8Array, [src], EvilConstructor);
|
|
23
|
+
print(u8);
|
|
24
|
+
} catch (e) {
|
|
25
|
+
assert(e instanceof RangeError);
|
|
26
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import * as std from "qjs:std";
|
|
2
|
+
// https://github.com/quickjs-ng/quickjs/issues/1318
|
|
3
|
+
// Heap use-after-free when FinalizationRegistry is part of a reference cycle.
|
|
4
|
+
// Run under ASAN.
|
|
5
|
+
|
|
6
|
+
// Test 1: held value is the FR itself (original PoC pattern)
|
|
7
|
+
{
|
|
8
|
+
let target = {};
|
|
9
|
+
let fr = new FinalizationRegistry(function() {});
|
|
10
|
+
fr.register(target, fr);
|
|
11
|
+
fr.ref = target;
|
|
12
|
+
target.ref = fr;
|
|
13
|
+
target = null;
|
|
14
|
+
fr = null;
|
|
15
|
+
std.gc();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Test 2: callback is part of the cycle
|
|
19
|
+
{
|
|
20
|
+
let target = {};
|
|
21
|
+
let cb = function() {};
|
|
22
|
+
let fr = new FinalizationRegistry(cb);
|
|
23
|
+
fr.register(target, 42);
|
|
24
|
+
fr.ref = target;
|
|
25
|
+
target.ref = fr;
|
|
26
|
+
target.cb = cb;
|
|
27
|
+
target = null;
|
|
28
|
+
fr = null;
|
|
29
|
+
cb = null;
|
|
30
|
+
std.gc();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Test 3: simplified real-world pattern (from issue comment)
|
|
34
|
+
{
|
|
35
|
+
class Registry {
|
|
36
|
+
#fr = new FinalizationRegistry(v => {});
|
|
37
|
+
set(key) {
|
|
38
|
+
const ref = new WeakRef(key);
|
|
39
|
+
this.#fr.register(key, {}, ref);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function Observer() {
|
|
43
|
+
this.targets = new Registry;
|
|
44
|
+
}
|
|
45
|
+
Observer.prototype.observe = function(target) {
|
|
46
|
+
this.targets.set(target);
|
|
47
|
+
target.subset = new Set;
|
|
48
|
+
target.subset.add(this);
|
|
49
|
+
}
|
|
50
|
+
let sample = {};
|
|
51
|
+
new Observer().observe(sample);
|
|
52
|
+
sample = null;
|
|
53
|
+
std.gc();
|
|
54
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
function deferred() {
|
|
2
|
+
let resolve
|
|
3
|
+
const promise = new Promise(f => {
|
|
4
|
+
resolve = f
|
|
5
|
+
})
|
|
6
|
+
return { promise, resolve }
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
let it, a, b, c
|
|
10
|
+
let getterHit = 0
|
|
11
|
+
let inGetter = false
|
|
12
|
+
|
|
13
|
+
Object.defineProperty(Object.prototype, "then", {
|
|
14
|
+
configurable: true,
|
|
15
|
+
get() {
|
|
16
|
+
if (inGetter || !it) return undefined
|
|
17
|
+
inGetter = true
|
|
18
|
+
try {
|
|
19
|
+
if (getterHit === 0) {
|
|
20
|
+
it.return(0)
|
|
21
|
+
} else if (getterHit === 1) {
|
|
22
|
+
it.next(1)
|
|
23
|
+
it.return(1)
|
|
24
|
+
}
|
|
25
|
+
getterHit++
|
|
26
|
+
} catch (_) {
|
|
27
|
+
}
|
|
28
|
+
inGetter = false
|
|
29
|
+
return undefined
|
|
30
|
+
},
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
async function* g() {
|
|
34
|
+
try {
|
|
35
|
+
await a.promise
|
|
36
|
+
yield 1
|
|
37
|
+
await b.promise
|
|
38
|
+
yield 2
|
|
39
|
+
await c.promise
|
|
40
|
+
} finally {
|
|
41
|
+
await c.promise
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
(async () => {
|
|
46
|
+
a = deferred()
|
|
47
|
+
b = deferred()
|
|
48
|
+
c = deferred()
|
|
49
|
+
it = g()
|
|
50
|
+
|
|
51
|
+
it.next()
|
|
52
|
+
a.resolve({})
|
|
53
|
+
await Promise.resolve()
|
|
54
|
+
await Promise.resolve()
|
|
55
|
+
b.resolve({})
|
|
56
|
+
c.resolve({})
|
|
57
|
+
await Promise.resolve()
|
|
58
|
+
})()
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { assert, assertThrows } from "../assert.js";
|
|
2
|
+
const ab = new ArrayBuffer(1);
|
|
3
|
+
const u8 = new Uint8Array(ab);
|
|
4
|
+
assert(!ab.detached);
|
|
5
|
+
// Detach the ArrayBuffer.
|
|
6
|
+
ab.transfer();
|
|
7
|
+
assert(ab.detached);
|
|
8
|
+
u8[100] = 123; // Doesn't throw.
|
|
9
|
+
assertThrows(TypeError, () => Object.defineProperty(u8, "100", { value: 123 }));
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { assert, assertThrows } from "../assert.js";
|
|
2
|
+
const ab = new ArrayBuffer(16, { maxByteLength: 32 });
|
|
3
|
+
const u8 = new Uint8Array(ab, 16);
|
|
4
|
+
ab.resize(8);
|
|
5
|
+
assert(ab.byteLength, 8);
|
|
6
|
+
u8[1] = 123; // Doesn't throw.
|
|
7
|
+
assertThrows(TypeError, () => Object.defineProperty(u8, "1", { value: 123 }));
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/*---
|
|
2
|
+
negative:
|
|
3
|
+
phase: runtime
|
|
4
|
+
type: Error
|
|
5
|
+
---*/
|
|
6
|
+
let finrec = new FinalizationRegistry(v => {})
|
|
7
|
+
let object = {object:"object"}
|
|
8
|
+
finrec.register(object, {held:"held"}, {token:"token"})
|
|
9
|
+
object = undefined
|
|
10
|
+
// abrupt termination should not leak |held|
|
|
11
|
+
// unfortunately only shows up in qjs, not run-test262,
|
|
12
|
+
// but still good to have a regression test
|
|
13
|
+
throw Error("ok")
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import {assert} from "./assert.js"
|
|
2
|
+
|
|
3
|
+
while (1) label: break
|
|
4
|
+
|
|
5
|
+
var i = 0
|
|
6
|
+
while (i < 3) label: {
|
|
7
|
+
if (i > 0)
|
|
8
|
+
break
|
|
9
|
+
i++
|
|
10
|
+
}
|
|
11
|
+
assert(i, 1)
|
|
12
|
+
|
|
13
|
+
for (;;) label: break
|
|
14
|
+
|
|
15
|
+
for (i = 0; i < 3; i++) label: {
|
|
16
|
+
if (i > 0)
|
|
17
|
+
break
|
|
18
|
+
}
|
|
19
|
+
assert(i, 1)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import {assert} from "./assert.js";
|
|
2
|
+
|
|
3
|
+
Error.stackTraceLimit = Infinity;
|
|
4
|
+
assert(Error.stackTraceLimit === Infinity);
|
|
5
|
+
assert(new Error("error").stack.includes("bug858.js")); // stack should not be empty
|
|
6
|
+
|
|
7
|
+
Error.stackTraceLimit = -Infinity;
|
|
8
|
+
assert(Error.stackTraceLimit === -Infinity);
|
|
9
|
+
assert(!new Error("error").stack.includes("bug858.js")); // stack should be empty
|
|
10
|
+
|
|
11
|
+
Error.stackTraceLimit = NaN;
|
|
12
|
+
assert(Number.isNaN(Error.stackTraceLimit));
|
|
13
|
+
assert(!new Error("error").stack.includes("bug858.js")); // stack should be empty
|
|
14
|
+
|
|
15
|
+
Error.stackTraceLimit = -0;
|
|
16
|
+
assert(Object.is(Error.stackTraceLimit, -0));
|
|
17
|
+
assert(!new Error("error").stack.includes("bug858.js")); // stack should be empty
|
|
18
|
+
|
|
19
|
+
const obj = { valueOf() { throw "evil" } };
|
|
20
|
+
Error.stackTraceLimit = obj;
|
|
21
|
+
assert(Error.stackTraceLimit === obj);
|
|
22
|
+
try {
|
|
23
|
+
throw new Error("fail")
|
|
24
|
+
} catch (e) {
|
|
25
|
+
assert(e.message.includes("fail"));
|
|
26
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import {assert} from "./assert.js"
|
|
2
|
+
const expected = [97,98,99]
|
|
3
|
+
const ab = new ArrayBuffer(0, {maxByteLength:3})
|
|
4
|
+
const dv = new DataView(ab)
|
|
5
|
+
ab.resize(3)
|
|
6
|
+
for (const [i,v] of Object.entries(expected)) dv.setUint8(i, v)
|
|
7
|
+
for (const [i,v] of Object.entries(expected)) assert(v, dv.getUint8(i))
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { assert, assertArrayEquals } from "./assert.js";
|
|
2
|
+
import * as mod from "./destructured-export.js";
|
|
3
|
+
|
|
4
|
+
export const { a, b, c } = { a: 1, b: 2, c: 3 };
|
|
5
|
+
export const d = 4;
|
|
6
|
+
|
|
7
|
+
assert(typeof mod === 'object');
|
|
8
|
+
assertArrayEquals(Object.keys(mod), ["a", "b", "c", "d"]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
await undefined
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
await = 42 // parsed as classic script
|