@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,30 @@
1
+ // Darwin worker: single platform-agnostic API; backend chosen by cfg.
2
+ // JSC = default (no engine flag). QJS = ZAPP_WORKER_ENGINE_QJS.
3
+
4
+ import "../../worker.zc";
5
+
6
+ @cfg(not(ZAPP_WORKER_ENGINE_QJS))
7
+ import "./jsc.zc";
8
+
9
+ @cfg(ZAPP_WORKER_ENGINE_QJS)
10
+ import "./qjs.zc";
11
+
12
+ @cfg(not(ZAPP_WORKER_ENGINE_QJS))
13
+ fn darwin_platform_bind_runtime(app: App*) -> void {
14
+ (DarwinWorkerJsc{}).bind_runtime(app);
15
+ }
16
+
17
+ @cfg(not(ZAPP_WORKER_ENGINE_QJS))
18
+ fn darwin_platform_handle_worker_bridge(app: App*, action: string, payload: string) -> void {
19
+ (DarwinWorkerJsc{}).handle_bridge(app, action, payload);
20
+ }
21
+
22
+ @cfg(ZAPP_WORKER_ENGINE_QJS)
23
+ fn darwin_platform_bind_runtime(app: App*) -> void {
24
+ (DarwinWorkerQjs{}).bind_runtime(app);
25
+ }
26
+
27
+ @cfg(ZAPP_WORKER_ENGINE_QJS)
28
+ fn darwin_platform_handle_worker_bridge(app: App*, action: string, payload: string) -> void {
29
+ (DarwinWorkerQjs{}).handle_bridge(app, action, payload);
30
+ }
@@ -0,0 +1,233 @@
1
+ // QJS wrapper for fetch. Delegates to core/fetch_core.zc.
2
+
3
+ import "../../../shared/log.zc";
4
+
5
+ @cfg(ZAPP_WORKER_ENGINE_QJS)
6
+ raw {
7
+ #ifdef ZAPP_WORKER_ENGINE_QJS
8
+ #ifdef __APPLE__
9
+ // Log functions from log.zc
10
+ extern void zapp_log_worker(int level, int window_id, int worker_id, const char* message);
11
+ #define ZAPP_LOG_ERROR 0
12
+ #define ZAPP_LOG_WARN 1
13
+ #define ZAPP_LOG_INFO 2
14
+ #define ZAPP_LOG_DEBUG 3
15
+ #define ZAPP_LOG_TRACE 4
16
+
17
+ extern NSValue* zapp_darwin_qjs_get_context(NSString* workerId);
18
+ extern void zapp_darwin_qjs_dispatch_async(dispatch_block_t block);
19
+ extern void zapp_darwin_qjs_drain_jobs(void* ctx, const char* label);
20
+
21
+ static void zapp_core_fetch_ensure_init(void);
22
+ static void zapp_core_fetch_execute(NSMutableURLRequest*, NSString*, zapp_fetch_completion_t);
23
+ static NSMutableURLRequest* zapp_core_fetch_build_request(const char*, const char*, const char**, const char**, int, const char*, size_t);
24
+ static void zapp_core_fetch_cancel(NSString*);
25
+ static void zapp_core_fetch_cancel_all(void);
26
+
27
+ static QJSValue qjs_bridge_fetch(QJSContext *ctx, QJSValue this_val, int argc, QJSValue *argv, int magic, QJSValue *func_data) {
28
+ if (argc < 4) return JS_UNDEFINED;
29
+
30
+ const char* worker_id = JS_ToCString(ctx, func_data[0]);
31
+ if (!worker_id) return JS_UNDEFINED;
32
+
33
+ // Extract URL
34
+ const char* urlStr = JS_ToCString(ctx, argv[0]);
35
+ if (!urlStr) { JS_FreeCString(ctx, worker_id); return JS_UNDEFINED; }
36
+ char* url_copy = strdup(urlStr);
37
+ JS_FreeCString(ctx, urlStr);
38
+
39
+ QJSValue optionsVal = argv[1];
40
+ QJSValue resolveVal = argv[2];
41
+ QJSValue rejectVal = argv[3];
42
+
43
+ // Extract method
44
+ char* method_copy = NULL;
45
+ if (!JS_IsUndefined(optionsVal) && !JS_IsNull(optionsVal)) {
46
+ QJSValue m = JS_GetPropertyStr(ctx, optionsVal, "method");
47
+ if (!JS_IsUndefined(m)) {
48
+ const char* ms = JS_ToCString(ctx, m);
49
+ if (ms) { method_copy = strdup(ms); JS_FreeCString(ctx, ms); }
50
+ }
51
+ JS_FreeValue(ctx, m);
52
+ }
53
+
54
+ // Extract headers
55
+ char** hKeys = NULL;
56
+ char** hVals = NULL;
57
+ int hCount = 0;
58
+ if (!JS_IsUndefined(optionsVal) && !JS_IsNull(optionsVal)) {
59
+ QJSValue headersVal = JS_GetPropertyStr(ctx, optionsVal, "headers");
60
+ if (JS_IsObject(headersVal)) {
61
+ QJSPropertyEnum *tab = NULL;
62
+ uint32_t len = 0;
63
+ if (JS_GetOwnPropertyNames(ctx, &tab, &len, headersVal, JS_GPN_STRING_MASK) == 0 && len > 0) {
64
+ hCount = (int)len;
65
+ hKeys = (char**)calloc(hCount, sizeof(char*));
66
+ hVals = (char**)calloc(hCount, sizeof(char*));
67
+ for (uint32_t i = 0; i < len; i++) {
68
+ const char* key = JS_AtomToCString(ctx, tab[i].atom);
69
+ QJSValue val = JS_GetProperty(ctx, headersVal, tab[i].atom);
70
+ const char* valStr = JS_ToCString(ctx, val);
71
+ hKeys[i] = key ? strdup(key) : NULL;
72
+ hVals[i] = valStr ? strdup(valStr) : NULL;
73
+ if (key) JS_FreeCString(ctx, key);
74
+ if (valStr) JS_FreeCString(ctx, valStr);
75
+ JS_FreeValue(ctx, val);
76
+ JS_FreeAtom(ctx, tab[i].atom);
77
+ }
78
+ js_free(ctx, tab);
79
+ }
80
+ }
81
+ JS_FreeValue(ctx, headersVal);
82
+ }
83
+
84
+ // Extract body
85
+ char* body_copy = NULL;
86
+ size_t body_len = 0;
87
+ if (!JS_IsUndefined(optionsVal) && !JS_IsNull(optionsVal)) {
88
+ QJSValue bodyVal = JS_GetPropertyStr(ctx, optionsVal, "body");
89
+ if (!JS_IsUndefined(bodyVal) && !JS_IsNull(bodyVal) && JS_IsString(bodyVal)) {
90
+ const char* bs = JS_ToCString(ctx, bodyVal);
91
+ if (bs) { body_copy = strdup(bs); body_len = strlen(body_copy); JS_FreeCString(ctx, bs); }
92
+ }
93
+ JS_FreeValue(ctx, bodyVal);
94
+ }
95
+
96
+ NSMutableURLRequest* request = zapp_core_fetch_build_request(
97
+ url_copy, method_copy,
98
+ (const char**)hKeys, (const char**)hVals, hCount,
99
+ body_copy, body_len);
100
+
101
+ free(url_copy);
102
+ free(method_copy);
103
+ for (int i = 0; i < hCount; i++) { free(hKeys[i]); free(hVals[i]); }
104
+ free(hKeys); free(hVals);
105
+ free(body_copy);
106
+
107
+ if (!request) {
108
+ QJSValue errArgs[1] = { JS_NewString(ctx, "Invalid URL") };
109
+ QJSValue ret = JS_Call(ctx, rejectVal, JS_UNDEFINED, 1, errArgs);
110
+ JS_FreeValue(ctx, ret); JS_FreeValue(ctx, errArgs[0]);
111
+ JS_FreeCString(ctx, worker_id);
112
+ return JS_UNDEFINED;
113
+ }
114
+
115
+ NSString* wId = [NSString stringWithUTF8String:worker_id];
116
+ JS_FreeCString(ctx, worker_id);
117
+
118
+ QJSValue savedResolve = JS_DupValue(ctx, resolveVal);
119
+ QJSValue savedReject = JS_DupValue(ctx, rejectVal);
120
+ QJSContext* creating_ctx = ctx;
121
+
122
+ zapp_core_fetch_execute(request, wId, ^(zapp_fetch_response_t* response, NSString* error) {
123
+ // The response pointer is only valid for the duration of this callback
124
+ // (fetch_core frees it immediately after). Copy data into ObjC objects
125
+ // which the block will retain across the async dispatch.
126
+ BOOL has_response = (response != nil);
127
+ int resp_status = 0;
128
+ NSString* resp_status_text = nil;
129
+ NSArray<NSString*>* resp_hdr_keys = nil;
130
+ NSArray<NSString*>* resp_hdr_vals = nil;
131
+ NSString* resp_body = nil;
132
+ NSString* resp_body_base64 = nil;
133
+
134
+ if (response) {
135
+ resp_status = response->status;
136
+ resp_status_text = response->status_text
137
+ ? [NSString stringWithUTF8String:response->status_text] : @"";
138
+ if (response->header_count > 0) {
139
+ NSMutableArray* hk = [NSMutableArray arrayWithCapacity:response->header_count];
140
+ NSMutableArray* hv = [NSMutableArray arrayWithCapacity:response->header_count];
141
+ for (int i = 0; i < response->header_count; i++) {
142
+ if (response->header_keys[i] && response->header_values[i]) {
143
+ [hk addObject:[NSString stringWithUTF8String:response->header_keys[i]]];
144
+ [hv addObject:[NSString stringWithUTF8String:response->header_values[i]]];
145
+ }
146
+ }
147
+ resp_hdr_keys = hk;
148
+ resp_hdr_vals = hv;
149
+ }
150
+ if (response->body)
151
+ resp_body = [NSString stringWithUTF8String:response->body];
152
+ else if (response->body_base64)
153
+ resp_body_base64 = [NSString stringWithUTF8String:response->body_base64];
154
+ }
155
+
156
+ zapp_darwin_qjs_dispatch_async(^{
157
+ NSValue* val = zapp_darwin_qjs_get_context(wId);
158
+ if (!val) return;
159
+
160
+ QJSContext* current_ctx = (QJSContext*)[val pointerValue];
161
+ if (current_ctx != creating_ctx) return;
162
+
163
+ if (error) {
164
+ QJSValue args[1] = { JS_NewString(current_ctx, [error UTF8String]) };
165
+ QJSValue ret = JS_Call(current_ctx, savedReject, JS_UNDEFINED, 1, args);
166
+ if (JS_IsException(ret)) {
167
+ QJSValue exc = JS_GetException(current_ctx);
168
+ const char* s = JS_ToCString(current_ctx, exc);
169
+ if (s) { zapp_log_worker(ZAPP_LOG_ERROR, -1, -1, s); JS_FreeCString(current_ctx, s); }
170
+ JS_FreeValue(current_ctx, exc);
171
+ }
172
+ JS_FreeValue(current_ctx, ret); JS_FreeValue(current_ctx, args[0]);
173
+ } else if (has_response) {
174
+ QJSValue resObj = JS_NewObject(current_ctx);
175
+ JS_SetPropertyStr(current_ctx, resObj, "status", JS_NewInt32(current_ctx, resp_status));
176
+ JS_SetPropertyStr(current_ctx, resObj, "statusText",
177
+ JS_NewString(current_ctx, [resp_status_text UTF8String]));
178
+
179
+ QJSValue headersObj = JS_NewObject(current_ctx);
180
+ if (resp_hdr_keys) {
181
+ for (NSUInteger i = 0; i < [resp_hdr_keys count]; i++) {
182
+ JS_SetPropertyStr(current_ctx, headersObj,
183
+ [resp_hdr_keys[i] UTF8String],
184
+ JS_NewString(current_ctx, [resp_hdr_vals[i] UTF8String]));
185
+ }
186
+ }
187
+ JS_SetPropertyStr(current_ctx, resObj, "headers", headersObj);
188
+
189
+ if (resp_body)
190
+ JS_SetPropertyStr(current_ctx, resObj, "body", JS_NewString(current_ctx, [resp_body UTF8String]));
191
+ else if (resp_body_base64)
192
+ JS_SetPropertyStr(current_ctx, resObj, "body_base64", JS_NewString(current_ctx, [resp_body_base64 UTF8String]));
193
+ else
194
+ JS_SetPropertyStr(current_ctx, resObj, "body", JS_NewString(current_ctx, ""));
195
+
196
+ QJSValue args[1] = { resObj };
197
+ QJSValue ret = JS_Call(current_ctx, savedResolve, JS_UNDEFINED, 1, args);
198
+ if (JS_IsException(ret)) {
199
+ QJSValue exc = JS_GetException(current_ctx);
200
+ const char* s = JS_ToCString(current_ctx, exc);
201
+ if (s) { zapp_log_worker(ZAPP_LOG_ERROR, -1, -1, s); JS_FreeCString(current_ctx, s); }
202
+ JS_FreeValue(current_ctx, exc);
203
+ }
204
+ JS_FreeValue(current_ctx, ret); JS_FreeValue(current_ctx, resObj);
205
+ }
206
+
207
+ JS_FreeValue(current_ctx, savedResolve);
208
+ JS_FreeValue(current_ctx, savedReject);
209
+ zapp_darwin_qjs_drain_jobs(current_ctx, "fetch");
210
+ });
211
+ });
212
+
213
+ return JS_UNDEFINED;
214
+ }
215
+
216
+ void zapp_darwin_qjs_fetch_cancel(NSString* workerId) {
217
+ zapp_core_fetch_cancel(workerId);
218
+ }
219
+
220
+ void zapp_darwin_qjs_fetch_cancel_all(void) {
221
+ zapp_core_fetch_cancel_all();
222
+ }
223
+
224
+ void zapp_darwin_qjs_fetch_install(QJSContext* ctx, QJSValue bridge, const char* worker_id) {
225
+ QJSValue wIdVal = JS_NewString(ctx, worker_id);
226
+ QJSValue funcData[1] = { wIdVal };
227
+ JS_SetPropertyStr(ctx, bridge, "fetch",
228
+ JS_NewCFunctionData(ctx, qjs_bridge_fetch, 4, 0, 1, funcData));
229
+ JS_FreeValue(ctx, wIdVal);
230
+ }
231
+ #endif /* __APPLE__ */
232
+ #endif
233
+ }
@@ -0,0 +1,23 @@
1
+ // Re-establish QuickJS type macros for the shared QJS wrapper files.
2
+ // engine_qjs.zc undef's them after including quickjs.h, so subsequent QJS
3
+ // modules need them back to avoid collisions with JavaScriptCore types.
4
+
5
+ @cfg(ZAPP_WORKER_ENGINE_QJS)
6
+ raw {
7
+ #ifdef __APPLE__
8
+ #ifdef ZAPP_WORKER_ENGINE_QJS
9
+ #define JSContext QJSContext
10
+ #define JSRuntime QJSRuntime
11
+ #define JSValue QJSValue
12
+ #define JSClassID QJSClassID
13
+ #define JSClassDef QJSClassDef
14
+ #define JSClassEx QJSClassEx
15
+ #define JSValueConst QJSValueConst
16
+ #define JSPropertyEnum QJSPropertyEnum
17
+ #define JSPropertyDescriptor QJSPropertyDescriptor
18
+ #include "quickjs.h"
19
+ #include "quickjs-libc.h"
20
+ /* Do NOT #undef: shared QJS modules need these macros active. */
21
+ #endif
22
+ #endif
23
+ }
@@ -0,0 +1,223 @@
1
+ // QJS wrapper for WebSocket. Delegates to core/websocket_core.zc.
2
+
3
+ @cfg(ZAPP_WORKER_ENGINE_QJS)
4
+ raw {
5
+ #ifdef ZAPP_WORKER_ENGINE_QJS
6
+ #ifdef __APPLE__
7
+ static char* zapp_core_ws_connect(const char* url_str, const char** protocols, int protocol_count,
8
+ zapp_ws_event_fn callback, void* user_data);
9
+ static void zapp_core_ws_send_text(const char* ws_id, const char* text);
10
+ static void zapp_core_ws_send_binary(const char* ws_id, const uint8_t* bytes, size_t len);
11
+ static void zapp_core_ws_close(const char* ws_id, int code, const char* reason);
12
+ static void zapp_core_ws_ensure_init(void);
13
+
14
+ dispatch_queue_t zapp_darwin_qjs_get_queue(void);
15
+ NSValue* zapp_darwin_qjs_get_context(NSString* workerId);
16
+ void zapp_darwin_qjs_drain_jobs(void* ctx, const char* label);
17
+
18
+ // Storage for QJS callback references keyed by wsId
19
+ static NSMutableDictionary<NSString*, NSMutableDictionary*>* zapp_qjs_ws_refs = nil;
20
+
21
+ // QJS WS callback: receives events from core and dispatches to QJS context.
22
+ static void zapp_qjs_ws_callback(const char* ws_id, const char* event_type, const char* json_payload, void* user_data) {
23
+ if (!ws_id || !json_payload || !user_data) return;
24
+
25
+ NSString* wsId = [NSString stringWithUTF8String:ws_id];
26
+ NSString* jsonStr = [NSString stringWithUTF8String:json_payload];
27
+ NSString* workerId = (__bridge NSString*)user_data;
28
+
29
+ dispatch_queue_t q = zapp_darwin_qjs_get_queue();
30
+ if (!q) return;
31
+
32
+ dispatch_async(q, ^{
33
+ NSValue* ctxVal = zapp_darwin_qjs_get_context(workerId);
34
+ if (!ctxVal) return;
35
+ QJSContext* ctx = (QJSContext*)[ctxVal pointerValue];
36
+
37
+ NSMutableDictionary* ref = zapp_qjs_ws_refs[wsId];
38
+ if (!ref) return;
39
+ NSValue* fnBoxed = ref[@"fn"];
40
+ if (!fnBoxed) return;
41
+ QJSValue fn = *(QJSValue*)[fnBoxed pointerValue];
42
+
43
+ // Parse JSON and call the JS callback
44
+ QJSValue global = JS_GetGlobalObject(ctx);
45
+ QJSValue JSON = JS_GetPropertyStr(ctx, global, "JSON");
46
+ QJSValue parse = JS_GetPropertyStr(ctx, JSON, "parse");
47
+ QJSValue jsonArg = JS_NewString(ctx, [jsonStr UTF8String]);
48
+ QJSValue parsed = JS_Call(ctx, parse, JSON, 1, &jsonArg);
49
+
50
+ QJSValue args[1] = { parsed };
51
+ QJSValue ret = JS_Call(ctx, fn, JS_UNDEFINED, 1, args);
52
+ if (JS_IsException(ret)) {
53
+ QJSValue exc = JS_GetException(ctx);
54
+ const char* s = JS_ToCString(ctx, exc);
55
+ NSLog(@"[zapp-ws-qjs] callback error: %s", s ? s : "unknown");
56
+ if (s) JS_FreeCString(ctx, s);
57
+ JS_FreeValue(ctx, exc);
58
+ }
59
+ JS_FreeValue(ctx, ret);
60
+ JS_FreeValue(ctx, parsed);
61
+ JS_FreeValue(ctx, jsonArg);
62
+ JS_FreeValue(ctx, parse);
63
+ JS_FreeValue(ctx, JSON);
64
+ JS_FreeValue(ctx, global);
65
+ zapp_darwin_qjs_drain_jobs(ctx, "ws-event");
66
+ });
67
+ }
68
+
69
+ static QJSValue qjs_bridge_wsConnect(QJSContext *ctx, QJSValue this_val, int argc, QJSValue *argv, int magic, QJSValue *func_data) {
70
+ if (argc < 3) return JS_NewString(ctx, "");
71
+
72
+ const char* urlStr = JS_ToCString(ctx, argv[0]);
73
+ if (!urlStr) return JS_NewString(ctx, "");
74
+
75
+ // Extract protocols array
76
+ const char** protos = NULL;
77
+ int protoCount = 0;
78
+ if (!JS_IsUndefined(argv[1]) && !JS_IsNull(argv[1])) {
79
+ QJSValue lenVal = JS_GetPropertyStr(ctx, argv[1], "length");
80
+ int32_t arrLen = 0;
81
+ JS_ToInt32(ctx, &arrLen, lenVal);
82
+ JS_FreeValue(ctx, lenVal);
83
+ if (arrLen > 0) {
84
+ protoCount = arrLen;
85
+ protos = (const char**)malloc(sizeof(const char*) * protoCount);
86
+ for (int i = 0; i < protoCount; i++) {
87
+ QJSValue el = JS_GetPropertyUint32(ctx, argv[1], (uint32_t)i);
88
+ protos[i] = JS_ToCString(ctx, el);
89
+ JS_FreeValue(ctx, el);
90
+ }
91
+ }
92
+ }
93
+
94
+ // Get worker ID for callback dispatch
95
+ const char* workerId = JS_ToCString(ctx, func_data[0]);
96
+ NSString* wId = workerId ? [NSString stringWithUTF8String:workerId] : @"";
97
+ if (workerId) JS_FreeCString(ctx, workerId);
98
+
99
+ // Retain JS callback
100
+ QJSValue jsFn = JS_DupValue(ctx, argv[2]);
101
+ QJSValue* fnBox = (QJSValue*)malloc(sizeof(QJSValue));
102
+ *fnBox = jsFn;
103
+
104
+ char* wsIdC = zapp_core_ws_connect(urlStr, protos, protoCount, zapp_qjs_ws_callback, (__bridge void*)wId);
105
+
106
+ // Free protocol strings
107
+ for (int i = 0; i < protoCount; i++) {
108
+ if (protos[i]) JS_FreeCString(ctx, protos[i]);
109
+ }
110
+ free(protos);
111
+ JS_FreeCString(ctx, urlStr);
112
+
113
+ if (!wsIdC) {
114
+ JS_FreeValue(ctx, jsFn);
115
+ free(fnBox);
116
+ return JS_NewString(ctx, "");
117
+ }
118
+
119
+ NSString* wsId = [NSString stringWithUTF8String:wsIdC];
120
+ if (zapp_qjs_ws_refs == nil) zapp_qjs_ws_refs = [NSMutableDictionary new];
121
+ zapp_qjs_ws_refs[wsId] = [@{
122
+ @"fn": [NSValue valueWithPointer:fnBox],
123
+ @"ctx": [NSValue valueWithPointer:ctx],
124
+ } mutableCopy];
125
+
126
+ QJSValue result = JS_NewString(ctx, wsIdC);
127
+ free(wsIdC);
128
+ return result;
129
+ }
130
+
131
+ static QJSValue qjs_bridge_wsSend(QJSContext *ctx, QJSValue this_val, int argc, QJSValue *argv) {
132
+ if (argc < 3) return JS_UNDEFINED;
133
+
134
+ const char* wsId = JS_ToCString(ctx, argv[0]);
135
+ if (!wsId) return JS_UNDEFINED;
136
+
137
+ int isBinary = JS_ToBool(ctx, argv[2]);
138
+
139
+ if (isBinary) {
140
+ size_t len = 0;
141
+ uint8_t* bytes = JS_GetArrayBuffer(ctx, &len, argv[1]);
142
+ if (!bytes) {
143
+ QJSValue bufProp = JS_GetPropertyStr(ctx, argv[1], "buffer");
144
+ if (!JS_IsUndefined(bufProp)) {
145
+ size_t bufLen = 0;
146
+ uint8_t* bufPtr = JS_GetArrayBuffer(ctx, &bufLen, bufProp);
147
+ QJSValue oVal = JS_GetPropertyStr(ctx, argv[1], "byteOffset");
148
+ QJSValue lVal = JS_GetPropertyStr(ctx, argv[1], "byteLength");
149
+ int32_t off = 0, blen = 0;
150
+ JS_ToInt32(ctx, &off, oVal);
151
+ JS_ToInt32(ctx, &blen, lVal);
152
+ JS_FreeValue(ctx, oVal);
153
+ JS_FreeValue(ctx, lVal);
154
+ if (bufPtr && off >= 0 && blen > 0 && (size_t)(off + blen) <= bufLen) {
155
+ bytes = bufPtr + off;
156
+ len = (size_t)blen;
157
+ }
158
+ }
159
+ JS_FreeValue(ctx, bufProp);
160
+ }
161
+ if (bytes && len > 0) zapp_core_ws_send_binary(wsId, bytes, len);
162
+ } else {
163
+ const char* text = JS_ToCString(ctx, argv[1]);
164
+ zapp_core_ws_send_text(wsId, text ? text : "");
165
+ if (text) JS_FreeCString(ctx, text);
166
+ }
167
+
168
+ JS_FreeCString(ctx, wsId);
169
+ return JS_UNDEFINED;
170
+ }
171
+
172
+ static QJSValue qjs_bridge_wsClose(QJSContext *ctx, QJSValue this_val, int argc, QJSValue *argv) {
173
+ if (argc < 1) return JS_UNDEFINED;
174
+ const char* wsId = JS_ToCString(ctx, argv[0]);
175
+ if (!wsId) return JS_UNDEFINED;
176
+
177
+ int32_t code = 1000;
178
+ if (argc >= 2 && !JS_IsUndefined(argv[1]) && !JS_IsNull(argv[1])) {
179
+ JS_ToInt32(ctx, &code, argv[1]);
180
+ }
181
+ const char* reason = NULL;
182
+ if (argc >= 3 && !JS_IsUndefined(argv[2]) && !JS_IsNull(argv[2])) {
183
+ reason = JS_ToCString(ctx, argv[2]);
184
+ }
185
+
186
+ zapp_core_ws_close(wsId, code, reason);
187
+
188
+ // Clean up JS callback reference
189
+ NSString* wsIdNS = [NSString stringWithUTF8String:wsId];
190
+ NSMutableDictionary* ref = zapp_qjs_ws_refs[wsIdNS];
191
+ if (ref) {
192
+ NSValue* fnBoxed = ref[@"fn"];
193
+ if (fnBoxed) {
194
+ QJSValue* fnBox = (QJSValue*)[fnBoxed pointerValue];
195
+ NSValue* ctxBoxed = ref[@"ctx"];
196
+ QJSContext* origCtx = ctxBoxed ? (QJSContext*)[ctxBoxed pointerValue] : ctx;
197
+ JS_FreeValue(origCtx, *fnBox);
198
+ free(fnBox);
199
+ }
200
+ [zapp_qjs_ws_refs removeObjectForKey:wsIdNS];
201
+ }
202
+
203
+ if (reason) JS_FreeCString(ctx, reason);
204
+ JS_FreeCString(ctx, wsId);
205
+ return JS_UNDEFINED;
206
+ }
207
+
208
+ void zapp_darwin_qjs_websocket_install(QJSContext* ctx, QJSValue bridge, const char* worker_id) {
209
+ zapp_core_ws_ensure_init();
210
+ if (zapp_qjs_ws_refs == nil) zapp_qjs_ws_refs = [NSMutableDictionary new];
211
+
212
+ QJSValue wIdVal = JS_NewString(ctx, worker_id);
213
+ QJSValue funcData[1] = { wIdVal };
214
+ JS_SetPropertyStr(ctx, bridge, "wsConnect", JS_NewCFunctionData(ctx, qjs_bridge_wsConnect, 3, 0, 1, funcData));
215
+ JS_FreeValue(ctx, wIdVal);
216
+
217
+ JS_SetPropertyStr(ctx, bridge, "wsSend", JS_NewCFunction(ctx, qjs_bridge_wsSend, "wsSend", 3));
218
+ JS_SetPropertyStr(ctx, bridge, "wsClose", JS_NewCFunction(ctx, qjs_bridge_wsClose, "wsClose", 3));
219
+ }
220
+
221
+ #endif /* __APPLE__ */
222
+ #endif
223
+ }