@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,927 @@
1
+ #ifdef NDEBUG
2
+ #undef NDEBUG
3
+ #endif
4
+ #include <assert.h>
5
+ #include <stdlib.h>
6
+ #include <string.h>
7
+ #include "quickjs.h"
8
+ #include "cutils.h"
9
+
10
+ static JSValue eval(JSContext *ctx, const char *code)
11
+ {
12
+ return JS_Eval(ctx, code, strlen(code), "<input>", JS_EVAL_TYPE_GLOBAL);
13
+ }
14
+
15
+ static JSValue cfunc_callback(JSContext *ctx, JSValueConst this_val,
16
+ int argc, JSValueConst *argv)
17
+ {
18
+ return JS_ThrowTypeError(ctx, "from cfunc");
19
+ }
20
+
21
+ static JSValue cfuncdata_callback(JSContext *ctx, JSValueConst this_val,
22
+ int argc, JSValueConst *argv,
23
+ int magic, JSValueConst *func_data)
24
+ {
25
+ return JS_ThrowTypeError(ctx, "from cfuncdata");
26
+ }
27
+
28
+ static JSValue cclosure_callback(JSContext *ctx, JSValueConst this_val,
29
+ int argc, JSValueConst *argv,
30
+ int magic, void *func_data)
31
+ {
32
+ return JS_ThrowTypeError(ctx, "from cclosure");
33
+ }
34
+
35
+ static bool closure_finalized = false;
36
+
37
+ static void cclosure_opaque_finalize(void *opaque)
38
+ {
39
+ if ((intptr_t)opaque == 12)
40
+ closure_finalized = true;
41
+ }
42
+
43
+ static void cfunctions(void)
44
+ {
45
+ uint32_t length;
46
+ const char *s;
47
+ JSValue ret, stack;
48
+
49
+ JSRuntime *rt = JS_NewRuntime();
50
+ JSContext *ctx = JS_NewContext(rt);
51
+ JSValue cfunc = JS_NewCFunction(ctx, cfunc_callback, "cfunc", 42);
52
+ JSValue cfuncdata =
53
+ JS_NewCFunctionData2(ctx, cfuncdata_callback, "cfuncdata",
54
+ /*length*/1337, /*magic*/0, /*data_len*/0, NULL);
55
+ JSValue cclosure =
56
+ JS_NewCClosure(ctx, cclosure_callback, "cclosure", cclosure_opaque_finalize,
57
+ /*length*/0xC0DE, /*magic*/11, /*opaque*/(void*)12);
58
+ JSValue global = JS_GetGlobalObject(ctx);
59
+ JS_SetPropertyStr(ctx, global, "cfunc", cfunc);
60
+ JS_SetPropertyStr(ctx, global, "cfuncdata", cfuncdata);
61
+ JS_SetPropertyStr(ctx, global, "cclosure", cclosure);
62
+ JS_FreeValue(ctx, global);
63
+
64
+ ret = eval(ctx, "cfunc.name");
65
+ assert(!JS_IsException(ret));
66
+ assert(JS_IsString(ret));
67
+ s = JS_ToCString(ctx, ret);
68
+ JS_FreeValue(ctx, ret);
69
+ assert(s);
70
+ assert(!strcmp(s, "cfunc"));
71
+ JS_FreeCString(ctx, s);
72
+ ret = eval(ctx, "cfunc.length");
73
+ assert(!JS_IsException(ret));
74
+ assert(JS_IsNumber(ret));
75
+ assert(0 == JS_ToUint32(ctx, &length, ret));
76
+ assert(length == 42);
77
+
78
+ ret = eval(ctx, "cfuncdata.name");
79
+ assert(!JS_IsException(ret));
80
+ assert(JS_IsString(ret));
81
+ s = JS_ToCString(ctx, ret);
82
+ JS_FreeValue(ctx, ret);
83
+ assert(s);
84
+ assert(!strcmp(s, "cfuncdata"));
85
+ JS_FreeCString(ctx, s);
86
+ ret = eval(ctx, "cfuncdata.length");
87
+ assert(!JS_IsException(ret));
88
+ assert(JS_IsNumber(ret));
89
+ assert(0 == JS_ToUint32(ctx, &length, ret));
90
+ assert(length == 1337);
91
+
92
+ ret = eval(ctx, "cclosure.name");
93
+ assert(!JS_IsException(ret));
94
+ assert(JS_IsString(ret));
95
+ s = JS_ToCString(ctx, ret);
96
+ JS_FreeValue(ctx, ret);
97
+ assert(s);
98
+ assert(!strcmp(s, "cclosure"));
99
+ JS_FreeCString(ctx, s);
100
+ ret = eval(ctx, "cclosure.length");
101
+ assert(!JS_IsException(ret));
102
+ assert(JS_IsNumber(ret));
103
+ assert(0 == JS_ToUint32(ctx, &length, ret));
104
+ assert(length == 0xC0DE);
105
+
106
+ ret = eval(ctx, "cfunc()");
107
+ assert(JS_IsException(ret));
108
+ ret = JS_GetException(ctx);
109
+ assert(JS_IsError(ret));
110
+ stack = JS_GetPropertyStr(ctx, ret, "stack");
111
+ assert(JS_IsString(stack));
112
+ s = JS_ToCString(ctx, stack);
113
+ JS_FreeValue(ctx, stack);
114
+ assert(s);
115
+ assert(!strcmp(s, " at cfunc (native)\n at <eval> (<input>:1:1)\n"));
116
+ JS_FreeCString(ctx, s);
117
+ s = JS_ToCString(ctx, ret);
118
+ JS_FreeValue(ctx, ret);
119
+ assert(s);
120
+ assert(!strcmp(s, "TypeError: from cfunc"));
121
+ JS_FreeCString(ctx, s);
122
+
123
+ ret = eval(ctx, "cfuncdata()");
124
+ assert(JS_IsException(ret));
125
+ ret = JS_GetException(ctx);
126
+ assert(JS_IsError(ret));
127
+ stack = JS_GetPropertyStr(ctx, ret, "stack");
128
+ assert(JS_IsString(stack));
129
+ s = JS_ToCString(ctx, stack);
130
+ JS_FreeValue(ctx, stack);
131
+ assert(s);
132
+ assert(!strcmp(s, " at cfuncdata (native)\n at <eval> (<input>:1:1)\n"));
133
+ JS_FreeCString(ctx, s);
134
+ s = JS_ToCString(ctx, ret);
135
+ JS_FreeValue(ctx, ret);
136
+ assert(s);
137
+ assert(!strcmp(s, "TypeError: from cfuncdata"));
138
+ JS_FreeCString(ctx, s);
139
+
140
+ ret = eval(ctx, "cclosure()");
141
+ assert(JS_IsException(ret));
142
+ ret = JS_GetException(ctx);
143
+ assert(JS_IsError(ret));
144
+ stack = JS_GetPropertyStr(ctx, ret, "stack");
145
+ assert(JS_IsString(stack));
146
+ s = JS_ToCString(ctx, stack);
147
+ JS_FreeValue(ctx, stack);
148
+ assert(s);
149
+ assert(!strcmp(s, " at cclosure (native)\n at <eval> (<input>:1:1)\n"));
150
+ JS_FreeCString(ctx, s);
151
+ s = JS_ToCString(ctx, ret);
152
+ JS_FreeValue(ctx, ret);
153
+ assert(s);
154
+ assert(!strcmp(s, "TypeError: from cclosure"));
155
+ JS_FreeCString(ctx, s);
156
+
157
+ JS_FreeContext(ctx);
158
+ JS_FreeRuntime(rt);
159
+
160
+ assert(closure_finalized);
161
+ }
162
+
163
+ #define MAX_TIME 10
164
+
165
+ static int timeout_interrupt_handler(JSRuntime *rt, void *opaque)
166
+ {
167
+ int *time = (int *)opaque;
168
+ if (*time <= MAX_TIME)
169
+ *time += 1;
170
+ return *time > MAX_TIME;
171
+ }
172
+
173
+ static void sync_call(void)
174
+ {
175
+ static const char code[] =
176
+ "(function() { \
177
+ try { \
178
+ while (true) {} \
179
+ } catch (e) {} \
180
+ })();";
181
+
182
+ JSRuntime *rt = JS_NewRuntime();
183
+ JSContext *ctx = JS_NewContext(rt);
184
+ int time = 0;
185
+ JS_SetInterruptHandler(rt, timeout_interrupt_handler, &time);
186
+ JSValue ret = eval(ctx, code);
187
+ assert(time > MAX_TIME);
188
+ assert(JS_IsException(ret));
189
+ JS_FreeValue(ctx, ret);
190
+ assert(JS_HasException(ctx));
191
+ JSValue e = JS_GetException(ctx);
192
+ assert(JS_IsUncatchableError(e));
193
+ JS_FreeValue(ctx, e);
194
+ JS_FreeContext(ctx);
195
+ JS_FreeRuntime(rt);
196
+ }
197
+
198
+ static void async_call(void)
199
+ {
200
+ static const char code[] =
201
+ "(async function() { \
202
+ const loop = async () => { \
203
+ await Promise.resolve(); \
204
+ while (true) {} \
205
+ }; \
206
+ await loop().catch(() => {}); \
207
+ })();";
208
+
209
+ JSRuntime *rt = JS_NewRuntime();
210
+ JSContext *ctx = JS_NewContext(rt);
211
+ int time = 0;
212
+ JS_SetInterruptHandler(rt, timeout_interrupt_handler, &time);
213
+ JSValue ret = eval(ctx, code);
214
+ assert(!JS_IsException(ret));
215
+ JS_FreeValue(ctx, ret);
216
+ assert(JS_IsJobPending(rt));
217
+ int r = 0;
218
+ while (JS_IsJobPending(rt)) {
219
+ r = JS_ExecutePendingJob(rt, &ctx);
220
+ }
221
+ assert(time > MAX_TIME);
222
+ assert(r == -1);
223
+ assert(JS_HasException(ctx));
224
+ JSValue e = JS_GetException(ctx);
225
+ assert(JS_IsUncatchableError(e));
226
+ JS_FreeValue(ctx, e);
227
+ JS_FreeContext(ctx);
228
+ JS_FreeRuntime(rt);
229
+ }
230
+
231
+ static JSValue save_value(JSContext *ctx, JSValueConst this_val,
232
+ int argc, JSValueConst *argv)
233
+ {
234
+ assert(argc == 1);
235
+ JSValue *p = (JSValue *)JS_GetContextOpaque(ctx);
236
+ *p = JS_DupValue(ctx, argv[0]);
237
+ return JS_UNDEFINED;
238
+ }
239
+
240
+ static void async_call_stack_overflow(void)
241
+ {
242
+ static const char code[] =
243
+ "(async function() { \
244
+ const f = () => f(); \
245
+ try { \
246
+ await Promise.resolve(); \
247
+ f(); \
248
+ } catch (e) { \
249
+ save_value(e); \
250
+ } \
251
+ })();";
252
+
253
+ JSRuntime *rt = JS_NewRuntime();
254
+ JSContext *ctx = JS_NewContext(rt);
255
+ JSValue value = JS_UNDEFINED;
256
+ JS_SetContextOpaque(ctx, &value);
257
+ JSValue global = JS_GetGlobalObject(ctx);
258
+ JS_SetPropertyStr(ctx, global, "save_value", JS_NewCFunction(ctx, save_value, "save_value", 1));
259
+ JS_FreeValue(ctx, global);
260
+ JSValue ret = eval(ctx, code);
261
+ assert(!JS_IsException(ret));
262
+ JS_FreeValue(ctx, ret);
263
+ assert(JS_IsJobPending(rt));
264
+ int r = 0;
265
+ while (JS_IsJobPending(rt)) {
266
+ r = JS_ExecutePendingJob(rt, &ctx);
267
+ }
268
+ assert(r == 1);
269
+ assert(!JS_HasException(ctx));
270
+ assert(JS_IsError(value)); // stack overflow should be caught
271
+ JS_FreeValue(ctx, value);
272
+ JS_FreeContext(ctx);
273
+ JS_FreeRuntime(rt);
274
+ }
275
+
276
+ // https://github.com/quickjs-ng/quickjs/issues/914
277
+ static void raw_context_global_var(void)
278
+ {
279
+ JSRuntime *rt = JS_NewRuntime();
280
+ JSContext *ctx = JS_NewContextRaw(rt);
281
+ JS_AddIntrinsicEval(ctx);
282
+ {
283
+ JSValue ret = eval(ctx, "globalThis");
284
+ assert(JS_IsException(ret));
285
+ JS_FreeValue(ctx, ret);
286
+ }
287
+ {
288
+ JSValue ret = eval(ctx, "var x = 42");
289
+ assert(JS_IsUndefined(ret));
290
+ JS_FreeValue(ctx, ret);
291
+ }
292
+ {
293
+ JSValue ret = eval(ctx, "function f() {}");
294
+ assert(JS_IsUndefined(ret));
295
+ JS_FreeValue(ctx, ret);
296
+ }
297
+ JS_FreeContext(ctx);
298
+ JS_FreeRuntime(rt);
299
+ }
300
+
301
+ static void is_array(void)
302
+ {
303
+ JSRuntime *rt = JS_NewRuntime();
304
+ JSContext *ctx = JS_NewContext(rt);
305
+ {
306
+ JSValue ret = eval(ctx, "[]");
307
+ assert(!JS_IsException(ret));
308
+ assert(JS_IsArray(ret));
309
+ JS_FreeValue(ctx, ret);
310
+ }
311
+ {
312
+ JSValue ret = eval(ctx, "new Proxy([], {})");
313
+ assert(!JS_IsException(ret));
314
+ assert(!JS_IsArray(ret));
315
+ assert(JS_IsProxy(ret));
316
+ JSValue handler = JS_GetProxyHandler(ctx, ret);
317
+ JSValue target = JS_GetProxyTarget(ctx, ret);
318
+ assert(!JS_IsException(handler));
319
+ assert(!JS_IsException(target));
320
+ assert(!JS_IsProxy(handler));
321
+ assert(!JS_IsProxy(target));
322
+ assert(JS_IsObject(handler));
323
+ assert(JS_IsArray(target));
324
+ JS_FreeValue(ctx, handler);
325
+ JS_FreeValue(ctx, target);
326
+ JS_FreeValue(ctx, ret);
327
+ }
328
+ JS_FreeContext(ctx);
329
+ JS_FreeRuntime(rt);
330
+ }
331
+
332
+ static int loader_calls;
333
+
334
+ static JSModuleDef *loader(JSContext *ctx, const char *name, void *opaque)
335
+ {
336
+ loader_calls++;
337
+ assert(!strcmp(name, "b"));
338
+ static const char code[] = "export function f(x){}";
339
+ JSValue ret = JS_Eval(ctx, code, strlen(code), "b",
340
+ JS_EVAL_TYPE_MODULE|JS_EVAL_FLAG_COMPILE_ONLY);
341
+ assert(!JS_IsException(ret));
342
+ JSModuleDef *m = JS_VALUE_GET_PTR(ret);
343
+ assert(m);
344
+ JS_FreeValue(ctx, ret);
345
+ return m;
346
+ }
347
+
348
+ static void module_serde(void)
349
+ {
350
+ JSRuntime *rt = JS_NewRuntime();
351
+ //JS_SetDumpFlags(rt, JS_DUMP_MODULE_RESOLVE);
352
+ JS_SetModuleLoaderFunc(rt, NULL, loader, NULL);
353
+ JSContext *ctx = JS_NewContext(rt);
354
+ static const char code[] = "import {f} from 'b'; f()";
355
+ assert(loader_calls == 0);
356
+ JSValue mod = JS_Eval(ctx, code, strlen(code), "a",
357
+ JS_EVAL_TYPE_MODULE|JS_EVAL_FLAG_COMPILE_ONLY);
358
+ assert(loader_calls == 1);
359
+ assert(!JS_IsException(mod));
360
+ assert(JS_IsModule(mod));
361
+ size_t len = 0;
362
+ uint8_t *buf = JS_WriteObject(ctx, &len, mod,
363
+ JS_WRITE_OBJ_BYTECODE|JS_WRITE_OBJ_REFERENCE);
364
+ assert(buf);
365
+ assert(len > 0);
366
+ JS_FreeValue(ctx, mod);
367
+ assert(loader_calls == 1);
368
+ mod = JS_ReadObject(ctx, buf, len, JS_READ_OBJ_BYTECODE);
369
+ js_free(ctx, buf);
370
+ assert(loader_calls == 1); // 'b' is returned from cache
371
+ assert(!JS_IsException(mod));
372
+ JSValue ret = JS_EvalFunction(ctx, mod);
373
+ assert(!JS_IsException(ret));
374
+ assert(JS_IsPromise(ret));
375
+ JSValue result = JS_PromiseResult(ctx, ret);
376
+ assert(!JS_IsException(result));
377
+ assert(JS_IsUndefined(result));
378
+ JS_FreeValue(ctx, result);
379
+ JS_FreeValue(ctx, ret);
380
+ JS_FreeValue(ctx, mod);
381
+ JS_FreeContext(ctx);
382
+ JS_FreeRuntime(rt);
383
+ }
384
+
385
+ static void runtime_cstring_free(void)
386
+ {
387
+ JSRuntime *rt = JS_NewRuntime();
388
+ JSContext *ctx = JS_NewContext(rt);
389
+ // string -> cstring + JS_FreeCStringRT
390
+ {
391
+ JSValue ret = eval(ctx, "\"testStringPleaseIgnore\"");
392
+ assert(JS_IsString(ret));
393
+ const char *s = JS_ToCString(ctx, ret);
394
+ assert(s);
395
+ assert(strcmp(s, "testStringPleaseIgnore") == 0);
396
+ JS_FreeCStringRT(rt, s);
397
+ JS_FreeValue(ctx, ret);
398
+ }
399
+ // string -> cstring + JS_FreeCStringRT, destroying the source value first
400
+ {
401
+ JSValue ret = eval(ctx, "\"testStringPleaseIgnore\"");
402
+ assert(JS_IsString(ret));
403
+ const char *s = JS_ToCString(ctx, ret);
404
+ assert(s);
405
+ JS_FreeValue(ctx, ret);
406
+ assert(strcmp(s, "testStringPleaseIgnore") == 0);
407
+ JS_FreeCStringRT(rt, s);
408
+ }
409
+ // number -> cstring + JS_FreeCStringRT
410
+ {
411
+ JSValue ret = eval(ctx, "123987");
412
+ assert(JS_IsNumber(ret));
413
+ const char *s = JS_ToCString(ctx, ret);
414
+ assert(s);
415
+ assert(strcmp(s, "123987") == 0);
416
+ JS_FreeCStringRT(rt, s);
417
+ JS_FreeValue(ctx, ret);
418
+ }
419
+ JS_FreeContext(ctx);
420
+ JS_FreeRuntime(rt);
421
+ }
422
+
423
+ static void utf16_string(void)
424
+ {
425
+ JSRuntime *rt = JS_NewRuntime();
426
+ JSContext *ctx = JS_NewContext(rt);
427
+ {
428
+ JSValue v = JS_NewStringUTF16(ctx, NULL, 0);
429
+ assert(!JS_IsException(v));
430
+ const char *s = JS_ToCString(ctx, v);
431
+ assert(s);
432
+ assert(!strcmp(s, ""));
433
+ JS_FreeCString(ctx, s);
434
+ JS_FreeValue(ctx, v);
435
+ }
436
+ {
437
+ JSValue v = JS_NewStringUTF16(ctx, (uint16_t[]){'o','k'}, 2);
438
+ assert(!JS_IsException(v));
439
+ const char *s = JS_ToCString(ctx, v);
440
+ assert(s);
441
+ assert(!strcmp(s, "ok"));
442
+ JS_FreeCString(ctx, s);
443
+ size_t n;
444
+ const uint16_t *u = JS_ToCStringLenUTF16(ctx, &n, v);
445
+ assert(u);
446
+ assert(n == 2);
447
+ assert(u[0] == 'o');
448
+ assert(u[1] == 'k');
449
+ JS_FreeCStringUTF16(ctx, u);
450
+ JS_FreeValue(ctx, v);
451
+ }
452
+ {
453
+ JSValue v = JS_NewStringUTF16(ctx, (uint16_t[]){0xD800}, 1);
454
+ assert(!JS_IsException(v));
455
+ const char *s = JS_ToCString(ctx, v);
456
+ assert(s);
457
+ // questionable but surrogates don't map to UTF-8 without WTF-8
458
+ assert(!strcmp(s, "\xED\xA0\x80"));
459
+ JS_FreeCString(ctx, s);
460
+ size_t n;
461
+ const uint16_t *u = JS_ToCStringLenUTF16(ctx, &n, v);
462
+ assert(u);
463
+ assert(n == 1);
464
+ assert(u[0] == 0xD800);
465
+ JS_FreeCStringUTF16(ctx, u);
466
+ JS_FreeValue(ctx, v);
467
+ }
468
+ {
469
+ JSValue v = JS_NewStringLen(ctx, "ok", 2); // ascii -> ucs
470
+ assert(!JS_IsException(v));
471
+ size_t n;
472
+ const uint16_t *u = JS_ToCStringLenUTF16(ctx, &n, v);
473
+ assert(u);
474
+ assert(n == 2);
475
+ assert(u[0] == 'o');
476
+ assert(u[1] == 'k');
477
+ JS_FreeCStringUTF16(ctx, u);
478
+ JS_FreeValue(ctx, v);
479
+ }
480
+ JS_FreeContext(ctx);
481
+ JS_FreeRuntime(rt);
482
+ }
483
+
484
+ static void weak_map_gc_check(void)
485
+ {
486
+ static const char init_code[] =
487
+ "const map = new WeakMap(); \
488
+ function addItem() { \
489
+ const k = { \
490
+ text: 'a', \
491
+ }; \
492
+ map.set(k, {k}); \
493
+ }";
494
+ static const char test_code[] = "addItem()";
495
+
496
+ JSRuntime *rt = JS_NewRuntime();
497
+ JSContext *ctx = JS_NewContext(rt);
498
+
499
+ JSValue ret = eval(ctx, init_code);
500
+ assert(!JS_IsException(ret));
501
+
502
+ JSValue ret_test = eval(ctx, test_code);
503
+ assert(!JS_IsException(ret_test));
504
+ JS_RunGC(rt);
505
+ JSMemoryUsage memory_usage;
506
+ JS_ComputeMemoryUsage(rt, &memory_usage);
507
+
508
+ for (int i = 0; i < 3; i++) {
509
+ JSValue ret_test2 = eval(ctx, test_code);
510
+ assert(!JS_IsException(ret_test2));
511
+ JS_RunGC(rt);
512
+ JSMemoryUsage memory_usage2;
513
+ JS_ComputeMemoryUsage(rt, &memory_usage2);
514
+
515
+ assert(memory_usage.memory_used_count == memory_usage2.memory_used_count);
516
+ assert(memory_usage.memory_used_size == memory_usage2.memory_used_size);
517
+ JS_FreeValue(ctx, ret_test2);
518
+ }
519
+
520
+ JS_FreeValue(ctx, ret);
521
+ JS_FreeValue(ctx, ret_test);
522
+ JS_FreeContext(ctx);
523
+ JS_FreeRuntime(rt);
524
+ }
525
+
526
+ struct {
527
+ int hook_type_call_count[4];
528
+ } promise_hook_state;
529
+
530
+ static void promise_hook_cb(JSContext *ctx, JSPromiseHookType type,
531
+ JSValueConst promise, JSValueConst parent_promise,
532
+ void *opaque)
533
+ {
534
+ assert(type == JS_PROMISE_HOOK_INIT ||
535
+ type == JS_PROMISE_HOOK_BEFORE ||
536
+ type == JS_PROMISE_HOOK_AFTER ||
537
+ type == JS_PROMISE_HOOK_RESOLVE);
538
+ promise_hook_state.hook_type_call_count[type]++;
539
+ assert(opaque == (void *)&promise_hook_state);
540
+ if (!JS_IsUndefined(parent_promise)) {
541
+ JSValue global_object = JS_GetGlobalObject(ctx);
542
+ JS_SetPropertyStr(ctx, global_object, "actual",
543
+ JS_DupValue(ctx, parent_promise));
544
+ JS_FreeValue(ctx, global_object);
545
+ }
546
+ }
547
+
548
+ static void promise_hook(void)
549
+ {
550
+ int *cc = promise_hook_state.hook_type_call_count;
551
+ JSContext *unused;
552
+ JSRuntime *rt = JS_NewRuntime();
553
+ //JS_SetDumpFlags(rt, JS_DUMP_PROMISE);
554
+ JS_SetPromiseHook(rt, promise_hook_cb, &promise_hook_state);
555
+ JSContext *ctx = JS_NewContext(rt);
556
+ JSValue global_object = JS_GetGlobalObject(ctx);
557
+ {
558
+ // empty module; creates an outer and inner module promise;
559
+ // JS_Eval returns the outer promise
560
+ JSValue ret = JS_Eval(ctx, "", 0, "<input>", JS_EVAL_TYPE_MODULE);
561
+ assert(!JS_IsException(ret));
562
+ assert(JS_IsPromise(ret));
563
+ assert(JS_PROMISE_FULFILLED == JS_PromiseState(ctx, ret));
564
+ JS_FreeValue(ctx, ret);
565
+ assert(2 == cc[JS_PROMISE_HOOK_INIT]);
566
+ assert(0 == cc[JS_PROMISE_HOOK_BEFORE]);
567
+ assert(0 == cc[JS_PROMISE_HOOK_AFTER]);
568
+ assert(2 == cc[JS_PROMISE_HOOK_RESOLVE]);
569
+ assert(!JS_IsJobPending(rt));
570
+ }
571
+ memset(&promise_hook_state, 0, sizeof(promise_hook_state));
572
+ {
573
+ // module with unresolved promise; the outer and inner module promises
574
+ // are resolved but not the user's promise
575
+ static const char code[] = "new Promise(() => {})";
576
+ JSValue ret = JS_Eval(ctx, code, strlen(code), "<input>", JS_EVAL_TYPE_MODULE);
577
+ assert(!JS_IsException(ret));
578
+ assert(JS_IsPromise(ret));
579
+ assert(JS_PROMISE_FULFILLED == JS_PromiseState(ctx, ret)); // outer module promise
580
+ JS_FreeValue(ctx, ret);
581
+ assert(3 == cc[JS_PROMISE_HOOK_INIT]);
582
+ assert(0 == cc[JS_PROMISE_HOOK_BEFORE]);
583
+ assert(0 == cc[JS_PROMISE_HOOK_AFTER]);
584
+ assert(2 == cc[JS_PROMISE_HOOK_RESOLVE]); // outer and inner module promise
585
+ assert(!JS_IsJobPending(rt));
586
+ }
587
+ memset(&promise_hook_state, 0, sizeof(promise_hook_state));
588
+ {
589
+ // module with resolved promise
590
+ static const char code[] = "new Promise((resolve,reject) => resolve())";
591
+ JSValue ret = JS_Eval(ctx, code, strlen(code), "<input>", JS_EVAL_TYPE_MODULE);
592
+ assert(!JS_IsException(ret));
593
+ assert(JS_IsPromise(ret));
594
+ assert(JS_PROMISE_FULFILLED == JS_PromiseState(ctx, ret)); // outer module promise
595
+ JS_FreeValue(ctx, ret);
596
+ assert(3 == cc[JS_PROMISE_HOOK_INIT]);
597
+ assert(0 == cc[JS_PROMISE_HOOK_BEFORE]);
598
+ assert(0 == cc[JS_PROMISE_HOOK_AFTER]);
599
+ assert(3 == cc[JS_PROMISE_HOOK_RESOLVE]);
600
+ assert(!JS_IsJobPending(rt));
601
+ }
602
+ memset(&promise_hook_state, 0, sizeof(promise_hook_state));
603
+ {
604
+ // module with rejected promise
605
+ static const char code[] = "new Promise((resolve,reject) => reject())";
606
+ JSValue ret = JS_Eval(ctx, code, strlen(code), "<input>", JS_EVAL_TYPE_MODULE);
607
+ assert(!JS_IsException(ret));
608
+ assert(JS_IsPromise(ret));
609
+ assert(JS_PROMISE_FULFILLED == JS_PromiseState(ctx, ret)); // outer module promise
610
+ JS_FreeValue(ctx, ret);
611
+ assert(3 == cc[JS_PROMISE_HOOK_INIT]);
612
+ assert(0 == cc[JS_PROMISE_HOOK_BEFORE]);
613
+ assert(0 == cc[JS_PROMISE_HOOK_AFTER]);
614
+ assert(2 == cc[JS_PROMISE_HOOK_RESOLVE]);
615
+ assert(!JS_IsJobPending(rt));
616
+ }
617
+ memset(&promise_hook_state, 0, sizeof(promise_hook_state));
618
+ {
619
+ // module with promise chain
620
+ static const char code[] =
621
+ "globalThis.count = 0;"
622
+ "globalThis.actual = undefined;" // set by promise_hook_cb
623
+ "globalThis.expected = new Promise(resolve => resolve());"
624
+ "expected.then(_ => count++)";
625
+ JSValue ret = JS_Eval(ctx, code, strlen(code), "<input>", JS_EVAL_TYPE_MODULE);
626
+ assert(!JS_IsException(ret));
627
+ assert(JS_IsPromise(ret));
628
+ assert(JS_PROMISE_FULFILLED == JS_PromiseState(ctx, ret)); // outer module promise
629
+ JS_FreeValue(ctx, ret);
630
+ assert(4 == cc[JS_PROMISE_HOOK_INIT]);
631
+ assert(0 == cc[JS_PROMISE_HOOK_BEFORE]);
632
+ assert(0 == cc[JS_PROMISE_HOOK_AFTER]);
633
+ assert(3 == cc[JS_PROMISE_HOOK_RESOLVE]);
634
+ JSValue v = JS_GetPropertyStr(ctx, global_object, "count");
635
+ assert(!JS_IsException(v));
636
+ int32_t count;
637
+ assert(0 == JS_ToInt32(ctx, &count, v));
638
+ assert(0 == count);
639
+ JS_FreeValue(ctx, v);
640
+ assert(JS_IsJobPending(rt));
641
+ assert(1 == JS_ExecutePendingJob(rt, &unused));
642
+ assert(!JS_HasException(ctx));
643
+ assert(4 == cc[JS_PROMISE_HOOK_INIT]);
644
+ assert(0 == cc[JS_PROMISE_HOOK_BEFORE]);
645
+ assert(0 == cc[JS_PROMISE_HOOK_AFTER]);
646
+ assert(4 == cc[JS_PROMISE_HOOK_RESOLVE]);
647
+ assert(!JS_IsJobPending(rt));
648
+ v = JS_GetPropertyStr(ctx, global_object, "count");
649
+ assert(!JS_IsException(v));
650
+ assert(0 == JS_ToInt32(ctx, &count, v));
651
+ assert(1 == count);
652
+ JS_FreeValue(ctx, v);
653
+ JSValue actual = JS_GetPropertyStr(ctx, global_object, "actual");
654
+ JSValue expected = JS_GetPropertyStr(ctx, global_object, "expected");
655
+ assert(!JS_IsException(actual));
656
+ assert(!JS_IsException(expected));
657
+ assert(JS_IsSameValue(ctx, actual, expected));
658
+ JS_FreeValue(ctx, actual);
659
+ JS_FreeValue(ctx, expected);
660
+ }
661
+ memset(&promise_hook_state, 0, sizeof(promise_hook_state));
662
+ {
663
+ // module with thenable; fires before and after hooks
664
+ static const char code[] =
665
+ "new Promise(resolve => resolve({then(resolve){ resolve() }}))";
666
+ JSValue ret = JS_Eval(ctx, code, strlen(code), "<input>", JS_EVAL_TYPE_MODULE);
667
+ assert(!JS_IsException(ret));
668
+ assert(JS_IsPromise(ret));
669
+ assert(JS_PROMISE_FULFILLED == JS_PromiseState(ctx, ret)); // outer module promise
670
+ JS_FreeValue(ctx, ret);
671
+ assert(3 == cc[JS_PROMISE_HOOK_INIT]);
672
+ assert(0 == cc[JS_PROMISE_HOOK_BEFORE]);
673
+ assert(0 == cc[JS_PROMISE_HOOK_AFTER]);
674
+ assert(2 == cc[JS_PROMISE_HOOK_RESOLVE]);
675
+ assert(JS_IsJobPending(rt));
676
+ assert(1 == JS_ExecutePendingJob(rt, &unused));
677
+ assert(!JS_HasException(ctx));
678
+ assert(3 == cc[JS_PROMISE_HOOK_INIT]);
679
+ assert(1 == cc[JS_PROMISE_HOOK_BEFORE]);
680
+ assert(1 == cc[JS_PROMISE_HOOK_AFTER]);
681
+ assert(3 == cc[JS_PROMISE_HOOK_RESOLVE]);
682
+ assert(!JS_IsJobPending(rt));
683
+ }
684
+ JS_FreeValue(ctx, global_object);
685
+ JS_FreeContext(ctx);
686
+ JS_FreeRuntime(rt);
687
+ }
688
+
689
+ static void dump_memory_usage(void)
690
+ {
691
+ JSMemoryUsage stats;
692
+
693
+ JSRuntime *rt = NULL;
694
+ JSContext *ctx = NULL;
695
+
696
+ rt = JS_NewRuntime();
697
+ ctx = JS_NewContext(rt);
698
+
699
+ //JS_SetDumpFlags(rt, JS_DUMP_PROMISE);
700
+
701
+ static const char code[] =
702
+ "globalThis.count = 0;"
703
+ "globalThis.actual = undefined;" // set by promise_hook_cb
704
+ "globalThis.expected = new Promise(resolve => resolve());"
705
+ "expected.then(_ => count++)";
706
+
707
+ JSValue evalVal = JS_Eval(ctx, code, strlen(code), "<input>", 0);
708
+ JS_FreeValue(ctx, evalVal);
709
+
710
+ FILE *temp = tmpfile();
711
+ assert(temp != NULL);
712
+ JS_ComputeMemoryUsage(rt, &stats);
713
+ JS_DumpMemoryUsage(temp, &stats, rt);
714
+ // JS_DumpMemoryUsage(stdout, &stats, rt);
715
+ fclose(temp);
716
+
717
+ JS_FreeContext(ctx);
718
+ JS_FreeRuntime(rt);
719
+ }
720
+
721
+ static void new_errors(void)
722
+ {
723
+ typedef struct {
724
+ const char name[16];
725
+ JSValue (*func)(JSContext *, const char *, ...);
726
+ } Entry;
727
+ static const Entry entries[] = {
728
+ {"Error", JS_NewPlainError},
729
+ {"InternalError", JS_NewInternalError},
730
+ {"RangeError", JS_NewRangeError},
731
+ {"ReferenceError", JS_NewReferenceError},
732
+ {"SyntaxError", JS_NewSyntaxError},
733
+ {"TypeError", JS_NewTypeError},
734
+ };
735
+ const Entry *e;
736
+
737
+ JSRuntime *rt = JS_NewRuntime();
738
+ JSContext *ctx = JS_NewContext(rt);
739
+ for (e = entries; e < endof(entries); e++) {
740
+ JSValue obj = (*e->func)(ctx, "the %s", "needle");
741
+ assert(!JS_IsException(obj));
742
+ assert(JS_IsObject(obj));
743
+ assert(JS_IsError(obj));
744
+ const char *haystack = JS_ToCString(ctx, obj);
745
+ char needle[256];
746
+ snprintf(needle, sizeof(needle), "%s: the needle", e->name);
747
+ assert(strstr(haystack, needle));
748
+ JS_FreeCString(ctx, haystack);
749
+ JSValue stack = JS_GetPropertyStr(ctx, obj, "stack");
750
+ assert(!JS_IsException(stack));
751
+ assert(JS_IsString(stack));
752
+ JS_FreeValue(ctx, stack);
753
+ JS_FreeValue(ctx, obj);
754
+ }
755
+ JS_FreeContext(ctx);
756
+ JS_FreeRuntime(rt);
757
+ }
758
+
759
+ static int gop_get_own_property(JSContext *ctx, JSPropertyDescriptor *desc,
760
+ JSValueConst obj, JSAtom prop)
761
+ {
762
+ const char *name;
763
+ int found;
764
+
765
+ found = 0;
766
+ name = JS_AtomToCString(ctx, prop);
767
+ if (!name)
768
+ return -1;
769
+ if (!strcmp(name, "answer")) {
770
+ found = 1;
771
+ *desc = (JSPropertyDescriptor){
772
+ .value = JS_NewInt32(ctx, 42),
773
+ .flags = JS_PROP_C_W_E | JS_PROP_HAS_VALUE,
774
+ };
775
+ }
776
+ JS_FreeCString(ctx, name);
777
+ return found;
778
+ }
779
+
780
+ static void global_object_prototype(void)
781
+ {
782
+ static const char code[] = "answer";
783
+ JSValue global_object, proto, ret;
784
+ JSClassID class_id;
785
+ JSRuntime *rt;
786
+ JSContext *ctx;
787
+ int32_t answer;
788
+ int res;
789
+
790
+ {
791
+ rt = JS_NewRuntime();
792
+ ctx = JS_NewContext(rt);
793
+ proto = JS_NewObject(ctx);
794
+ assert(JS_IsObject(proto));
795
+ JSCFunctionListEntry prop = JS_PROP_INT32_DEF("answer", 42, JS_PROP_C_W_E);
796
+ JS_SetPropertyFunctionList(ctx, proto, &prop, 1);
797
+ global_object = JS_GetGlobalObject(ctx);
798
+ res = JS_SetPrototype(ctx, global_object, proto);
799
+ assert(res == true);
800
+ JS_FreeValue(ctx, global_object);
801
+ JS_FreeValue(ctx, proto);
802
+ ret = eval(ctx, code);
803
+ assert(!JS_IsException(ret));
804
+ assert(JS_IsNumber(ret));
805
+ res = JS_ToInt32(ctx, &answer, ret);
806
+ assert(res == 0);
807
+ assert(answer == 42);
808
+ JS_FreeValue(ctx, ret);
809
+ JS_FreeContext(ctx);
810
+ JS_FreeRuntime(rt);
811
+ }
812
+ {
813
+ JSClassExoticMethods exotic = (JSClassExoticMethods){
814
+ .get_own_property = gop_get_own_property,
815
+ };
816
+ JSClassDef def = (JSClassDef){
817
+ .class_name = "Global Object",
818
+ .exotic = &exotic,
819
+ };
820
+ rt = JS_NewRuntime();
821
+ class_id = 0;
822
+ JS_NewClassID(rt, &class_id);
823
+ res = JS_NewClass(rt, class_id, &def);
824
+ assert(res == 0);
825
+ ctx = JS_NewContext(rt);
826
+ proto = JS_NewObjectClass(ctx, class_id);
827
+ assert(JS_IsObject(proto));
828
+ global_object = JS_GetGlobalObject(ctx);
829
+ res = JS_SetPrototype(ctx, global_object, proto);
830
+ assert(res == true);
831
+ JS_FreeValue(ctx, global_object);
832
+ JS_FreeValue(ctx, proto);
833
+ ret = eval(ctx, code);
834
+ assert(!JS_IsException(ret));
835
+ assert(JS_IsNumber(ret));
836
+ res = JS_ToInt32(ctx, &answer, ret);
837
+ assert(res == 0);
838
+ assert(answer == 42);
839
+ JS_FreeValue(ctx, ret);
840
+ JS_FreeContext(ctx);
841
+ JS_FreeRuntime(rt);
842
+ }
843
+ }
844
+
845
+ // https://github.com/quickjs-ng/quickjs/issues/1178
846
+ static void slice_string_tocstring(void)
847
+ {
848
+ JSRuntime *rt = JS_NewRuntime();
849
+ JSContext *ctx = JS_NewContext(rt);
850
+ JSValue ret = eval(ctx, "'.'.repeat(16384).slice(1, -1)");
851
+ assert(!JS_IsException(ret));
852
+ assert(JS_IsString(ret));
853
+ const char *str = JS_ToCString(ctx, ret);
854
+ assert(strlen(str) == 16382);
855
+ JS_FreeCString(ctx, str);
856
+ JS_FreeValue(ctx, ret);
857
+ JS_FreeContext(ctx);
858
+ JS_FreeRuntime(rt);
859
+ }
860
+
861
+ static void immutable_array_buffer(void)
862
+ {
863
+ JSValue obj, ret;
864
+ bool immutable;
865
+ char buf[96];
866
+ int i, v;
867
+
868
+ JSRuntime *rt = JS_NewRuntime();
869
+ JSContext *ctx = JS_NewContext(rt);
870
+ for (i = 0; i < 2; i++) {
871
+ obj = JS_NewObject(ctx);
872
+ immutable = (i == 0);
873
+ assert(-1 == JS_IsImmutableArrayBuffer(JS_NULL));
874
+ assert(-1 == JS_IsImmutableArrayBuffer(JS_UNDEFINED));
875
+ assert(-1 == JS_IsImmutableArrayBuffer(obj));
876
+ assert(-1 == JS_SetImmutableArrayBuffer(JS_NULL, immutable));
877
+ assert(-1 == JS_SetImmutableArrayBuffer(JS_UNDEFINED, immutable));
878
+ assert(-1 == JS_SetImmutableArrayBuffer(obj, immutable));
879
+ JS_FreeValue(ctx, obj);
880
+ }
881
+ obj = eval(ctx, "globalThis.ab = new ArrayBuffer(1)");
882
+ assert(!JS_IsException(obj));
883
+ assert(JS_IsArrayBuffer(obj));
884
+ assert(!JS_IsImmutableArrayBuffer(obj));
885
+ for (i = 1; i <= 3; i++) {
886
+ immutable = (i == 2);
887
+ if (i > 1)
888
+ JS_SetImmutableArrayBuffer(obj, immutable);
889
+ assert(immutable == JS_IsImmutableArrayBuffer(obj));
890
+ snprintf(buf, sizeof(buf),
891
+ "var ta = new Uint8Array(ab); ta[0] = %d; ta[0]", i);
892
+ ret = eval(ctx, buf);
893
+ assert(!JS_IsException(ret));
894
+ assert(JS_IsNumber(ret));
895
+ assert(0 == JS_ToInt32(ctx, &v, ret));
896
+ JS_FreeValue(ctx, ret);
897
+ if (immutable) {
898
+ assert(v != i);
899
+ } else {
900
+ assert(v == i);
901
+ }
902
+ }
903
+ JS_FreeValue(ctx, obj);
904
+ JS_FreeContext(ctx);
905
+ JS_FreeRuntime(rt);
906
+ }
907
+
908
+ int main(void)
909
+ {
910
+ cfunctions();
911
+ sync_call();
912
+ async_call();
913
+ async_call_stack_overflow();
914
+ raw_context_global_var();
915
+ is_array();
916
+ module_serde();
917
+ runtime_cstring_free();
918
+ utf16_string();
919
+ weak_map_gc_check();
920
+ promise_hook();
921
+ dump_memory_usage();
922
+ new_errors();
923
+ global_object_prototype();
924
+ slice_string_tocstring();
925
+ immutable_array_buffer();
926
+ return 0;
927
+ }