@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.
Files changed (209) hide show
  1. package/README.md +55 -0
  2. package/dist/zapp-cli.js +9471 -0
  3. package/native/src/app/app.zc +490 -0
  4. package/native/src/event/event.zc +24 -0
  5. package/native/src/event/events.zc +70 -0
  6. package/native/src/platform/darwin/backend.zc +923 -0
  7. package/native/src/platform/darwin/backend_bootstrap.zc +9 -0
  8. package/native/src/platform/darwin/bootstrap.zc +9 -0
  9. package/native/src/platform/darwin/engine_jsc.zc +86 -0
  10. package/native/src/platform/darwin/engine_qjs.zc +92 -0
  11. package/native/src/platform/darwin/platform.zc +156 -0
  12. package/native/src/platform/darwin/webview.zc +550 -0
  13. package/native/src/platform/darwin/webview_bootstrap.zc +9 -0
  14. package/native/src/platform/darwin/window.zc +1223 -0
  15. package/native/src/platform/darwin/worker/common.zc +223 -0
  16. package/native/src/platform/darwin/worker/core/base64_core.zc +29 -0
  17. package/native/src/platform/darwin/worker/core/crypto_core.zc +19 -0
  18. package/native/src/platform/darwin/worker/core/encoding_core.zc +32 -0
  19. package/native/src/platform/darwin/worker/core/fetch_core.zc +145 -0
  20. package/native/src/platform/darwin/worker/core/url_core.zc +69 -0
  21. package/native/src/platform/darwin/worker/core/websocket_core.zc +179 -0
  22. package/native/src/platform/darwin/worker/dispatch.zc +55 -0
  23. package/native/src/platform/darwin/worker/jsc/base64_jsc.zc +39 -0
  24. package/native/src/platform/darwin/worker/jsc/crypto_jsc.zc +49 -0
  25. package/native/src/platform/darwin/worker/jsc/encoding_jsc.zc +86 -0
  26. package/native/src/platform/darwin/worker/jsc/fetch_jsc.zc +149 -0
  27. package/native/src/platform/darwin/worker/jsc/url_jsc.zc +54 -0
  28. package/native/src/platform/darwin/worker/jsc/websocket_jsc.zc +127 -0
  29. package/native/src/platform/darwin/worker/jsc.zc +670 -0
  30. package/native/src/platform/darwin/worker/mod.zc +30 -0
  31. package/native/src/platform/darwin/worker/qjs/fetch_qjs.zc +233 -0
  32. package/native/src/platform/darwin/worker/qjs/qjs_macros.zc +23 -0
  33. package/native/src/platform/darwin/worker/qjs/websocket_qjs.zc +223 -0
  34. package/native/src/platform/darwin/worker/qjs.zc +1053 -0
  35. package/native/src/platform/darwin/worker/timers.zc +149 -0
  36. package/native/src/platform/darwin/worker/timers_qjs.zc +209 -0
  37. package/native/src/platform/platform.zc +64 -0
  38. package/native/src/platform/shared/log.zc +156 -0
  39. package/native/src/platform/shared/worker/qjs/base64_qjs.zc +38 -0
  40. package/native/src/platform/shared/worker/qjs/crypto_qjs.zc +44 -0
  41. package/native/src/platform/shared/worker/qjs/encoding_qjs.zc +95 -0
  42. package/native/src/platform/shared/worker/qjs/url_qjs.zc +65 -0
  43. package/native/src/platform/shared/worker_registry.zc +206 -0
  44. package/native/src/platform/window.zc +446 -0
  45. package/native/src/platform/windows/backend.zc +452 -0
  46. package/native/src/platform/windows/backend_bootstrap.zc +9 -0
  47. package/native/src/platform/windows/bootstrap.zc +9 -0
  48. package/native/src/platform/windows/engine_qjs.zc +60 -0
  49. package/native/src/platform/windows/platform.zc +387 -0
  50. package/native/src/platform/windows/webview.zc +1175 -0
  51. package/native/src/platform/windows/webview_bootstrap.zc +9 -0
  52. package/native/src/platform/windows/window.zc +1271 -0
  53. package/native/src/platform/windows/worker/common.zc +409 -0
  54. package/native/src/platform/windows/worker/core/base64_core.zc +52 -0
  55. package/native/src/platform/windows/worker/core/crypto_core.zc +34 -0
  56. package/native/src/platform/windows/worker/core/encoding_core.zc +60 -0
  57. package/native/src/platform/windows/worker/core/fetch_core.zc +274 -0
  58. package/native/src/platform/windows/worker/core/url_core.zc +216 -0
  59. package/native/src/platform/windows/worker/core/websocket_core.zc +343 -0
  60. package/native/src/platform/windows/worker/dispatch.zc +34 -0
  61. package/native/src/platform/windows/worker/mod.zc +46 -0
  62. package/native/src/platform/windows/worker/qjs/fetch_qjs.zc +255 -0
  63. package/native/src/platform/windows/worker/qjs/websocket_qjs.zc +263 -0
  64. package/native/src/platform/windows/worker/qjs.zc +1049 -0
  65. package/native/src/platform/windows/worker/timers_qjs.zc +288 -0
  66. package/native/src/platform/worker.zc +8 -0
  67. package/native/src/service/service.zc +228 -0
  68. package/native/vendor/quickjs-ng/.gitattributes +4 -0
  69. package/native/vendor/quickjs-ng/.github/dependabot.yml +7 -0
  70. package/native/vendor/quickjs-ng/.github/workflows/ci.yml +812 -0
  71. package/native/vendor/quickjs-ng/.github/workflows/docs.yml +49 -0
  72. package/native/vendor/quickjs-ng/.github/workflows/release.yml +162 -0
  73. package/native/vendor/quickjs-ng/.github/workflows/test-docs.yml +23 -0
  74. package/native/vendor/quickjs-ng/.github/workflows/tsan.yml +32 -0
  75. package/native/vendor/quickjs-ng/.github/workflows/valgrind.yml +33 -0
  76. package/native/vendor/quickjs-ng/.gitmodules +5 -0
  77. package/native/vendor/quickjs-ng/CMakeLists.txt +553 -0
  78. package/native/vendor/quickjs-ng/LICENSE +24 -0
  79. package/native/vendor/quickjs-ng/Makefile +149 -0
  80. package/native/vendor/quickjs-ng/amalgam.js +53 -0
  81. package/native/vendor/quickjs-ng/api-test.c +927 -0
  82. package/native/vendor/quickjs-ng/builtin-array-fromasync.h +119 -0
  83. package/native/vendor/quickjs-ng/builtin-array-fromasync.js +36 -0
  84. package/native/vendor/quickjs-ng/builtin-iterator-zip-keyed.h +332 -0
  85. package/native/vendor/quickjs-ng/builtin-iterator-zip-keyed.js +194 -0
  86. package/native/vendor/quickjs-ng/builtin-iterator-zip.h +337 -0
  87. package/native/vendor/quickjs-ng/builtin-iterator-zip.js +210 -0
  88. package/native/vendor/quickjs-ng/ctest.c +17 -0
  89. package/native/vendor/quickjs-ng/cutils.h +2013 -0
  90. package/native/vendor/quickjs-ng/cxxtest.cc +2 -0
  91. package/native/vendor/quickjs-ng/dtoa.c +1619 -0
  92. package/native/vendor/quickjs-ng/dtoa.h +87 -0
  93. package/native/vendor/quickjs-ng/examples/fib.c +67 -0
  94. package/native/vendor/quickjs-ng/examples/fib_module.js +10 -0
  95. package/native/vendor/quickjs-ng/examples/hello.js +1 -0
  96. package/native/vendor/quickjs-ng/examples/hello_module.js +6 -0
  97. package/native/vendor/quickjs-ng/examples/meson.build +17 -0
  98. package/native/vendor/quickjs-ng/examples/pi_bigint.js +118 -0
  99. package/native/vendor/quickjs-ng/examples/point.c +154 -0
  100. package/native/vendor/quickjs-ng/examples/test_fib.js +8 -0
  101. package/native/vendor/quickjs-ng/examples/test_point.js +43 -0
  102. package/native/vendor/quickjs-ng/fuzz.c +51 -0
  103. package/native/vendor/quickjs-ng/gen/function_source.c +81 -0
  104. package/native/vendor/quickjs-ng/gen/hello.c +53 -0
  105. package/native/vendor/quickjs-ng/gen/hello_module.c +106 -0
  106. package/native/vendor/quickjs-ng/gen/repl.c +3053 -0
  107. package/native/vendor/quickjs-ng/gen/standalone.c +324 -0
  108. package/native/vendor/quickjs-ng/gen/test_fib.c +81 -0
  109. package/native/vendor/quickjs-ng/libregexp-opcode.h +58 -0
  110. package/native/vendor/quickjs-ng/libregexp.c +2687 -0
  111. package/native/vendor/quickjs-ng/libregexp.h +98 -0
  112. package/native/vendor/quickjs-ng/libunicode-table.h +4707 -0
  113. package/native/vendor/quickjs-ng/libunicode.c +1746 -0
  114. package/native/vendor/quickjs-ng/libunicode.h +126 -0
  115. package/native/vendor/quickjs-ng/list.h +107 -0
  116. package/native/vendor/quickjs-ng/lre-test.c +73 -0
  117. package/native/vendor/quickjs-ng/meson.build +684 -0
  118. package/native/vendor/quickjs-ng/meson_options.txt +6 -0
  119. package/native/vendor/quickjs-ng/qjs-wasi-reactor.c +208 -0
  120. package/native/vendor/quickjs-ng/qjs.c +748 -0
  121. package/native/vendor/quickjs-ng/qjsc.c +673 -0
  122. package/native/vendor/quickjs-ng/quickjs-atom.h +267 -0
  123. package/native/vendor/quickjs-ng/quickjs-c-atomics.h +54 -0
  124. package/native/vendor/quickjs-ng/quickjs-libc.c +4986 -0
  125. package/native/vendor/quickjs-ng/quickjs-libc.h +79 -0
  126. package/native/vendor/quickjs-ng/quickjs-opcode.h +369 -0
  127. package/native/vendor/quickjs-ng/quickjs.c +60259 -0
  128. package/native/vendor/quickjs-ng/quickjs.h +1419 -0
  129. package/native/vendor/quickjs-ng/repl.js +1927 -0
  130. package/native/vendor/quickjs-ng/run-test262.c +2417 -0
  131. package/native/vendor/quickjs-ng/standalone.js +129 -0
  132. package/native/vendor/quickjs-ng/tests/assert.js +49 -0
  133. package/native/vendor/quickjs-ng/tests/bug1221.js +16 -0
  134. package/native/vendor/quickjs-ng/tests/bug1296.js +12 -0
  135. package/native/vendor/quickjs-ng/tests/bug1297.js +22 -0
  136. package/native/vendor/quickjs-ng/tests/bug1301.js +21 -0
  137. package/native/vendor/quickjs-ng/tests/bug1302.js +24 -0
  138. package/native/vendor/quickjs-ng/tests/bug1305.js +26 -0
  139. package/native/vendor/quickjs-ng/tests/bug1318.js +54 -0
  140. package/native/vendor/quickjs-ng/tests/bug1352.js +8 -0
  141. package/native/vendor/quickjs-ng/tests/bug1354.js +6 -0
  142. package/native/vendor/quickjs-ng/tests/bug1355.js +58 -0
  143. package/native/vendor/quickjs-ng/tests/bug1368.js +9 -0
  144. package/native/vendor/quickjs-ng/tests/bug39/1.js +6 -0
  145. package/native/vendor/quickjs-ng/tests/bug39/2.js +6 -0
  146. package/native/vendor/quickjs-ng/tests/bug39/3.js +7 -0
  147. package/native/vendor/quickjs-ng/tests/bug488-upstream.js +7 -0
  148. package/native/vendor/quickjs-ng/tests/bug633/0.js +7 -0
  149. package/native/vendor/quickjs-ng/tests/bug633/1.js +4 -0
  150. package/native/vendor/quickjs-ng/tests/bug633/2.js +4 -0
  151. package/native/vendor/quickjs-ng/tests/bug633/3.js +4 -0
  152. package/native/vendor/quickjs-ng/tests/bug645/0.js +4 -0
  153. package/native/vendor/quickjs-ng/tests/bug645/1.js +9 -0
  154. package/native/vendor/quickjs-ng/tests/bug645/2.js +7 -0
  155. package/native/vendor/quickjs-ng/tests/bug648.js +13 -0
  156. package/native/vendor/quickjs-ng/tests/bug652.js +4 -0
  157. package/native/vendor/quickjs-ng/tests/bug741.js +19 -0
  158. package/native/vendor/quickjs-ng/tests/bug775.js +7 -0
  159. package/native/vendor/quickjs-ng/tests/bug776.js +7 -0
  160. package/native/vendor/quickjs-ng/tests/bug832.js +2 -0
  161. package/native/vendor/quickjs-ng/tests/bug858.js +26 -0
  162. package/native/vendor/quickjs-ng/tests/bug904.js +6 -0
  163. package/native/vendor/quickjs-ng/tests/bug988.js +7 -0
  164. package/native/vendor/quickjs-ng/tests/bug999.js +3 -0
  165. package/native/vendor/quickjs-ng/tests/destructured-export.js +8 -0
  166. package/native/vendor/quickjs-ng/tests/detect_module/0.js +1 -0
  167. package/native/vendor/quickjs-ng/tests/detect_module/1.js +2 -0
  168. package/native/vendor/quickjs-ng/tests/detect_module/2.js +1 -0
  169. package/native/vendor/quickjs-ng/tests/detect_module/3.js +8 -0
  170. package/native/vendor/quickjs-ng/tests/detect_module/4.js +3 -0
  171. package/native/vendor/quickjs-ng/tests/empty.js +0 -0
  172. package/native/vendor/quickjs-ng/tests/fixture_cyclic_import.js +2 -0
  173. package/native/vendor/quickjs-ng/tests/fixture_string_exports.js +12 -0
  174. package/native/vendor/quickjs-ng/tests/function_source.js +14 -0
  175. package/native/vendor/quickjs-ng/tests/microbench.js +1267 -0
  176. package/native/vendor/quickjs-ng/tests/null_or_undefined.js +38 -0
  177. package/native/vendor/quickjs-ng/tests/str-pad-leak.js +5 -0
  178. package/native/vendor/quickjs-ng/tests/test_bigint.js +107 -0
  179. package/native/vendor/quickjs-ng/tests/test_bjson.js +366 -0
  180. package/native/vendor/quickjs-ng/tests/test_builtin.js +1314 -0
  181. package/native/vendor/quickjs-ng/tests/test_closure.js +220 -0
  182. package/native/vendor/quickjs-ng/tests/test_cyclic_import.js +12 -0
  183. package/native/vendor/quickjs-ng/tests/test_domexception.js +35 -0
  184. package/native/vendor/quickjs-ng/tests/test_language.js +755 -0
  185. package/native/vendor/quickjs-ng/tests/test_loop.js +367 -0
  186. package/native/vendor/quickjs-ng/tests/test_queue_microtask.js +39 -0
  187. package/native/vendor/quickjs-ng/tests/test_std.js +340 -0
  188. package/native/vendor/quickjs-ng/tests/test_string_exports.js +25 -0
  189. package/native/vendor/quickjs-ng/tests/test_worker.js +43 -0
  190. package/native/vendor/quickjs-ng/tests/test_worker_module.js +30 -0
  191. package/native/vendor/quickjs-ng/tests.conf +14 -0
  192. package/native/vendor/quickjs-ng/unicode_download.sh +19 -0
  193. package/native/vendor/quickjs-ng/unicode_gen.c +3108 -0
  194. package/native/vendor/quickjs-ng/unicode_gen_def.h +310 -0
  195. package/native/vendor/quickjs-ng/update-version.sh +32 -0
  196. package/native/vendor/webview2/include/WebView2.h +60636 -0
  197. package/native/vendor/webview2/include/WebView2EnvironmentOptions.h +406 -0
  198. package/package.json +33 -0
  199. package/src/backend.ts +139 -0
  200. package/src/build-config.ts +87 -0
  201. package/src/build.ts +276 -0
  202. package/src/common.ts +195 -0
  203. package/src/config.ts +89 -0
  204. package/src/dev.ts +164 -0
  205. package/src/generate.ts +200 -0
  206. package/src/icons.ts +116 -0
  207. package/src/init.ts +190 -0
  208. package/src/package.ts +150 -0
  209. 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,8 @@
1
+ // run under ASAN
2
+ let key = Symbol("fortytwo")
3
+ let wm = new WeakMap()
4
+ let fr = new FinalizationRegistry(() => {})
5
+ fr.register(key, 42)
6
+ wm.set(key, fr)
7
+ fr = null
8
+ key = null
@@ -0,0 +1,6 @@
1
+ /*---
2
+ negative:
3
+ phase: runtime
4
+ type: SyntaxError
5
+ ---*/
6
+ new RegExp("[", "v") // run under ASAN
@@ -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
+ let it;
2
+ const evil = {
3
+ [Symbol.iterator]() {
4
+ it.return();
5
+ return [][Symbol.iterator]();
6
+ }
7
+ };
8
+ it = Iterator.concat(evil);
9
+ it.next();
@@ -0,0 +1,6 @@
1
+ /*---
2
+ flags: [qjs:track-promise-rejections]
3
+ ---*/
4
+
5
+ Promise.reject().catch(() => print('oops'))
6
+ Promise.resolve().then(() => print('ok'))
@@ -0,0 +1,6 @@
1
+ /*---
2
+ flags: [qjs:track-promise-rejections]
3
+ ---*/
4
+
5
+ const error = await Promise.resolve().then(() => Promise.reject('reject')).catch(e => e)
6
+ print('Got this error:', error)
@@ -0,0 +1,7 @@
1
+ /*---
2
+ flags: [qjs:track-promise-rejections]
3
+ ---*/
4
+
5
+ const promise = Promise.reject('reject')
6
+ const error = await Promise.resolve().then(() => promise).catch(e => e)
7
+ print('Got this error:', error)
@@ -0,0 +1,7 @@
1
+ // for-of with yield in iterable expression should not cause stack underflow
2
+ function* x() {
3
+ for (var e of yield []);
4
+ }
5
+ var g = x();
6
+ g.next();
7
+ g.return("test");
@@ -0,0 +1,7 @@
1
+ /*---
2
+ flags: [qjs:no-detect-module]
3
+ negative:
4
+ phase: parse
5
+ type: SyntaxError
6
+ ---*/
7
+ const undefined = 42 // SyntaxError at global scope
@@ -0,0 +1,4 @@
1
+ /*---
2
+ flags: [qjs:no-detect-module, module]
3
+ ---*/
4
+ const undefined = 42 // not a SyntaxError at toplevel module scope
@@ -0,0 +1,4 @@
1
+ /*---
2
+ flags: [qjs:no-detect-module]
3
+ ---*/
4
+ { const undefined = 42 } // not a SyntaxError, not at global scope
@@ -0,0 +1,4 @@
1
+ /*---
2
+ flags: [qjs:no-detect-module]
3
+ ---*/
4
+ ;(function() { const undefined = 42 })() // not a SyntaxError, not at global scope
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+
3
+ const u8 = new Uint8Array(1);
4
+ u8[100] = 123; // Should not throw.
@@ -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,4 @@
1
+ import { assert } from "./assert.js"
2
+ const ref = new WeakRef({})
3
+ const val = ref.deref() // should not throw
4
+ assert(val, undefined)
@@ -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,7 @@
1
+ /*---
2
+ negative:
3
+ phase: runtime
4
+ type: RangeError
5
+ ---*/
6
+ function f() { f() } // was problematic under ASan
7
+ f()
@@ -0,0 +1,7 @@
1
+ /*---
2
+ negative:
3
+ phase: runtime
4
+ type: RangeError
5
+ ---*/
6
+ function f() { f.apply(null) } // was problematic under ASan
7
+ f()
@@ -0,0 +1,2 @@
1
+ const m = await import("./empty.js")
2
+ print(m) // should not throw
@@ -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,6 @@
1
+ import {assert, assertThrows} from "./assert.js"
2
+ let calls = 0
3
+ Error.prepareStackTrace = function() { calls++ }
4
+ function f() { f() }
5
+ assertThrows(RangeError, f)
6
+ assert(calls, 0)
@@ -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,3 @@
1
+ function* f(r){ return r } // must return r
2
+ [...f({})]
3
+
@@ -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,2 @@
1
+ const p = Promise.resolve(42)
2
+ await p
@@ -0,0 +1 @@
1
+ await = 42 // parsed as classic script