@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,149 @@
1
+ //> macos: framework: JavaScriptCore
2
+
3
+ raw {
4
+ #ifdef __APPLE__
5
+ #include <Cocoa/Cocoa.h>
6
+ #include <WebKit/WebKit.h>
7
+ #include <dispatch/dispatch.h>
8
+ #include <JavaScriptCore/JavaScriptCore.h>
9
+
10
+ static dispatch_queue_t zapp_worker_js_queue = nil;
11
+ static void* zapp_worker_js_queue_key = &zapp_worker_js_queue_key;
12
+ static NSMutableDictionary<NSString*, NSMutableDictionary<NSNumber*, id>*>* zapp_worker_timers = nil;
13
+ static NSInteger zapp_next_timer_id = 1;
14
+ static const NSInteger zapp_worker_max_timers_per_worker = 256;
15
+ static const double zapp_worker_min_interval_ms = 4.0;
16
+
17
+ void zapp_darwin_worker_ensure_queue(void) {
18
+ static dispatch_once_t onceToken;
19
+ dispatch_once(&onceToken, ^{
20
+ zapp_worker_js_queue = dispatch_queue_create("dev.zapp.worker-js", DISPATCH_QUEUE_SERIAL);
21
+ dispatch_queue_set_specific(zapp_worker_js_queue, zapp_worker_js_queue_key, (void*)1, NULL);
22
+ zapp_worker_timers = [NSMutableDictionary dictionary];
23
+ });
24
+ }
25
+
26
+ void zapp_darwin_worker_js_sync(dispatch_block_t block) {
27
+ zapp_darwin_worker_ensure_queue();
28
+ if (dispatch_get_specific(zapp_worker_js_queue_key) != NULL) {
29
+ block();
30
+ return;
31
+ }
32
+ dispatch_sync(zapp_worker_js_queue, block);
33
+ }
34
+
35
+ void zapp_darwin_worker_timers_cancel(NSString* workerId) {
36
+ if (workerId == nil || zapp_worker_timers == nil) return;
37
+ NSMutableDictionary<NSNumber*, id>* timers = zapp_worker_timers[workerId];
38
+ if (timers == nil) return;
39
+ for (NSNumber* key in [timers allKeys]) {
40
+ dispatch_source_t src = (dispatch_source_t)timers[key];
41
+ if (src != nil) {
42
+ dispatch_source_cancel(src);
43
+ }
44
+ }
45
+ [timers removeAllObjects]; // Break retain cycle: timers -> src -> block -> timers
46
+ [zapp_worker_timers removeObjectForKey:workerId];
47
+ }
48
+
49
+ void zapp_darwin_worker_timers_cancel_all(void) {
50
+ if (zapp_worker_timers != nil) {
51
+ NSArray<NSString*>* workerIds = [zapp_worker_timers allKeys];
52
+ for (NSString* workerId in workerIds) {
53
+ zapp_darwin_worker_timers_cancel(workerId);
54
+ }
55
+ [zapp_worker_timers removeAllObjects];
56
+ }
57
+ }
58
+
59
+ void zapp_darwin_worker_timers_init(JSContext* ctx, NSString* workerId) {
60
+ zapp_darwin_worker_ensure_queue();
61
+ zapp_worker_timers[workerId] = [NSMutableDictionary dictionary];
62
+ __weak JSContext* weakCtx = ctx;
63
+
64
+ JSValue* bridge = ctx[@"__zappBridge"];
65
+ if (bridge == nil || bridge.isUndefined) {
66
+ ctx[@"__zappBridge"] = [JSValue valueWithNewObjectInContext:ctx];
67
+ bridge = ctx[@"__zappBridge"];
68
+ }
69
+
70
+ bridge[@"setTimer"] = ^(JSValue* fnVal, JSValue* msVal, JSValue* repeatVal) {
71
+ if (fnVal == nil || ![fnVal isObject]) return (NSNumber*)@0;
72
+ NSString* wId = [weakCtx[@"__zappWorkerDispatchId"] toString];
73
+ if (![wId isKindOfClass:[NSString class]] || [wId length] == 0) {
74
+ wId = workerId;
75
+ }
76
+ if (wId == nil) return (NSNumber*)@0;
77
+ NSMutableDictionary<NSNumber*, id>* timers = zapp_worker_timers[wId];
78
+ if (timers == nil) {
79
+ timers = [NSMutableDictionary dictionary];
80
+ zapp_worker_timers[wId] = timers;
81
+ }
82
+ if ([timers count] >= zapp_worker_max_timers_per_worker) {
83
+ return (NSNumber*)@0;
84
+ }
85
+ double ms = [msVal toDouble];
86
+ if (!(ms >= 0)) ms = 0;
87
+ BOOL shouldRepeat = [repeatVal toBool] ? YES : NO;
88
+ if (shouldRepeat && ms < zapp_worker_min_interval_ms) {
89
+ ms = zapp_worker_min_interval_ms;
90
+ }
91
+ NSInteger nextId = zapp_next_timer_id++;
92
+ NSNumber* timerId = @(nextId);
93
+ uint64_t intervalNs = (uint64_t)(ms * (double)NSEC_PER_MSEC);
94
+ if (intervalNs == 0) intervalNs = 1 * NSEC_PER_MSEC;
95
+
96
+ dispatch_source_t src = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, zapp_worker_js_queue);
97
+ if (src == nil) return (NSNumber*)@0;
98
+ dispatch_source_set_timer(src, dispatch_time(DISPATCH_TIME_NOW, (int64_t)intervalNs), shouldRepeat ? intervalNs : DISPATCH_TIME_FOREVER, 1 * NSEC_PER_MSEC);
99
+
100
+ __weak JSContext* weakCtxForTimer = weakCtx;
101
+ __block __weak dispatch_source_t weakSrc = src;
102
+ __block JSValue* blockFnVal = fnVal; // Make mutable so we can nil it out
103
+
104
+ dispatch_source_set_event_handler(src, ^{
105
+ dispatch_source_t strongSrc = weakSrc;
106
+ JSContext* strongCtx = weakCtxForTimer;
107
+ if (strongCtx == nil) {
108
+ if (strongSrc) dispatch_source_cancel(strongSrc);
109
+ [timers removeObjectForKey:timerId];
110
+ return;
111
+ }
112
+ NSString* currentDispatchId = [strongCtx[@"__zappWorkerDispatchId"] toString];
113
+ if (![currentDispatchId isKindOfClass:[NSString class]] || [currentDispatchId length] == 0) {
114
+ currentDispatchId = wId;
115
+ }
116
+ if (blockFnVal) [blockFnVal callWithArguments:@[]];
117
+ if (!shouldRepeat) {
118
+ if (strongSrc) dispatch_source_cancel(strongSrc);
119
+ [timers removeObjectForKey:timerId];
120
+ }
121
+ });
122
+
123
+ dispatch_source_set_cancel_handler(src, ^{
124
+ blockFnVal = nil; // Crucial: break the strong reference to JSValue -> JSContext
125
+ });
126
+
127
+ dispatch_resume(src);
128
+ timers[timerId] = src;
129
+ return timerId;
130
+ };
131
+
132
+ bridge[@"clearTimer"] = ^(JSValue* idVal) {
133
+ NSString* wId = [weakCtx[@"__zappWorkerDispatchId"] toString];
134
+ if (![wId isKindOfClass:[NSString class]] || [wId length] == 0) {
135
+ wId = workerId;
136
+ }
137
+ if (wId == nil) return;
138
+ NSMutableDictionary<NSNumber*, id>* timers = zapp_worker_timers[wId];
139
+ if (timers == nil) return;
140
+ NSNumber* timerId = @([idVal toInt32]);
141
+ dispatch_source_t src = (dispatch_source_t)timers[timerId];
142
+ if (src != nil) {
143
+ dispatch_source_cancel(src);
144
+ [timers removeObjectForKey:timerId];
145
+ }
146
+ };
147
+ }
148
+ #endif
149
+ }
@@ -0,0 +1,209 @@
1
+ // QJS worker timers: setTimer, clearTimer. Only built when ZAPP_WORKER_ENGINE_QJS.
2
+ // Inlined after qjs.zc's QuickJS include so QJSContext/QJSValue are defined.
3
+
4
+ @cfg(ZAPP_WORKER_ENGINE_QJS)
5
+ raw {
6
+ #ifdef ZAPP_WORKER_ENGINE_QJS
7
+ #ifdef __APPLE__
8
+ #define JSContext QJSContext
9
+ #define JSRuntime QJSRuntime
10
+ #define JSValue QJSValue
11
+ #define JSClassID QJSClassID
12
+ #define JSClassDef QJSClassDef
13
+ #define JSClassEx QJSClassEx
14
+ #define JSValueConst QJSValueConst
15
+ #define JSPropertyEnum QJSPropertyEnum
16
+ #define JSPropertyDescriptor QJSPropertyDescriptor
17
+ #include "quickjs.h"
18
+ #include "quickjs-libc.h"
19
+ /* Do not #undef here: JS_UNDEFINED/JS_MKVAL etc. expand (JSValue){...} at use site;
20
+ later modules (fetch, crypto) and qjs need the macro active. */
21
+
22
+ static void qjs_call_bridge_method(QJSContext* ctx, NSString* methodName, int argc, QJSValue* argv);
23
+
24
+ extern NSValue* zapp_darwin_qjs_get_context(NSString* workerId);
25
+ extern dispatch_queue_t zapp_darwin_qjs_get_queue(void);
26
+ extern void zapp_darwin_qjs_drain_jobs(void* ctx, const char* label);
27
+
28
+ static NSMutableDictionary<NSString*, NSMutableDictionary<NSNumber*, id>*>* qjs_timers = nil;
29
+ static NSInteger qjs_next_timer_id = 1;
30
+ static const NSInteger qjs_max_timers_per_worker = 256;
31
+ static const double qjs_min_interval_ms = 4.0;
32
+
33
+ static QJSValue qjs_bridge_setTimer(QJSContext *ctx, QJSValue this_val, int argc, QJSValue *argv, int magic, QJSValue *func_data) {
34
+ if (argc < 3) return JS_NewInt32(ctx, 0);
35
+
36
+ const char *worker_id = JS_ToCString(ctx, func_data[0]);
37
+ if (!worker_id) return JS_NewInt32(ctx, 0);
38
+
39
+ QJSValue fnVal = argv[0];
40
+ if (!JS_IsFunction(ctx, fnVal)) {
41
+ JS_FreeCString(ctx, worker_id);
42
+ return JS_NewInt32(ctx, 0);
43
+ }
44
+
45
+ double ms = 0;
46
+ JS_ToFloat64(ctx, &ms, argv[1]);
47
+ if (!(ms >= 0)) ms = 0;
48
+
49
+ int shouldRepeat = JS_ToBool(ctx, argv[2]);
50
+ if (shouldRepeat && ms < qjs_min_interval_ms) {
51
+ ms = qjs_min_interval_ms;
52
+ }
53
+
54
+ NSString* wId = [NSString stringWithUTF8String:worker_id];
55
+ JS_FreeCString(ctx, worker_id);
56
+
57
+ dispatch_queue_t qjs_queue = zapp_darwin_qjs_get_queue();
58
+ if (!qjs_queue) return JS_NewInt32(ctx, 0);
59
+
60
+ if (!qjs_timers) qjs_timers = [NSMutableDictionary dictionary];
61
+ NSMutableDictionary<NSNumber*, id>* timers = qjs_timers[wId];
62
+ if (!timers) {
63
+ timers = [NSMutableDictionary dictionary];
64
+ qjs_timers[wId] = timers;
65
+ }
66
+
67
+ if ([timers count] >= qjs_max_timers_per_worker) {
68
+ return JS_NewInt32(ctx, 0);
69
+ }
70
+
71
+ NSInteger nextId = qjs_next_timer_id++;
72
+ NSNumber* timerId = @(nextId);
73
+ uint64_t intervalNs = (uint64_t)(ms * (double)NSEC_PER_MSEC);
74
+ if (intervalNs == 0) intervalNs = 1 * NSEC_PER_MSEC;
75
+
76
+ dispatch_source_t src = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, qjs_queue);
77
+ if (src == nil) return JS_NewInt32(ctx, 0);
78
+
79
+ dispatch_source_set_timer(
80
+ src,
81
+ dispatch_time(DISPATCH_TIME_NOW, (int64_t)intervalNs),
82
+ shouldRepeat ? intervalNs : DISPATCH_TIME_FOREVER,
83
+ 1 * NSEC_PER_MSEC
84
+ );
85
+
86
+ QJSValue savedFn = JS_DupValue(ctx, fnVal);
87
+ QJSContext* creating_ctx = ctx;
88
+ __block BOOL isFreed = NO;
89
+ __block __weak dispatch_source_t weakSrc = src;
90
+
91
+ dispatch_source_set_event_handler(src, ^{
92
+ dispatch_source_t strongSrc = weakSrc;
93
+ NSValue* val = zapp_darwin_qjs_get_context(wId);
94
+ if (!val) {
95
+ if (strongSrc) dispatch_source_cancel(strongSrc);
96
+ return;
97
+ }
98
+
99
+ QJSContext* current_ctx = (QJSContext*)[val pointerValue];
100
+ if (current_ctx != creating_ctx) {
101
+ if (strongSrc) dispatch_source_cancel(strongSrc);
102
+ return;
103
+ }
104
+
105
+ QJSValue ret = JS_Call(current_ctx, savedFn, JS_UNDEFINED, 0, NULL);
106
+ if (JS_IsException(ret)) {
107
+ QJSValue exception = JS_GetException(current_ctx);
108
+ QJSValue args[1];
109
+ args[0] = JS_DupValue(current_ctx, exception);
110
+ qjs_call_bridge_method(current_ctx, @"reportError", 1, args);
111
+ JS_FreeValue(current_ctx, args[0]);
112
+ JS_FreeValue(current_ctx, exception);
113
+ }
114
+ JS_FreeValue(current_ctx, ret);
115
+
116
+ zapp_darwin_qjs_drain_jobs(current_ctx, "timer");
117
+
118
+ if (!shouldRepeat) {
119
+ if (strongSrc) dispatch_source_cancel(strongSrc);
120
+ }
121
+ });
122
+
123
+ dispatch_source_set_cancel_handler(src, ^{
124
+ if (!isFreed) {
125
+ NSValue* val = zapp_darwin_qjs_get_context(wId);
126
+ if (val) {
127
+ QJSContext* current_ctx = (QJSContext*)[val pointerValue];
128
+ if (current_ctx == creating_ctx) {
129
+ JS_FreeValue(current_ctx, savedFn);
130
+ }
131
+ }
132
+ isFreed = YES;
133
+ }
134
+ [timers removeObjectForKey:timerId];
135
+ });
136
+
137
+ timers[timerId] = src;
138
+ dispatch_resume(src);
139
+
140
+ return JS_NewInt32(ctx, (int32_t)nextId);
141
+ }
142
+
143
+ static QJSValue qjs_bridge_clearTimer(QJSContext *ctx, QJSValue this_val, int argc, QJSValue *argv, int magic, QJSValue *func_data) {
144
+ if (argc < 1) return JS_UNDEFINED;
145
+
146
+ const char *worker_id = JS_ToCString(ctx, func_data[0]);
147
+ if (!worker_id) return JS_UNDEFINED;
148
+
149
+ int32_t tId = 0;
150
+ JS_ToInt32(ctx, &tId, argv[0]);
151
+
152
+ NSString* wId = [NSString stringWithUTF8String:worker_id];
153
+ JS_FreeCString(ctx, worker_id);
154
+
155
+ if (qjs_timers) {
156
+ NSMutableDictionary<NSNumber*, id>* timers = qjs_timers[wId];
157
+ if (timers) {
158
+ NSNumber* timerId = @((NSInteger)tId);
159
+ dispatch_source_t src = (dispatch_source_t)timers[timerId];
160
+ if (src) {
161
+ dispatch_source_cancel(src);
162
+ }
163
+ }
164
+ }
165
+
166
+ return JS_UNDEFINED;
167
+ }
168
+
169
+ void zapp_darwin_qjs_timers_cancel(NSString* workerId) {
170
+ if (workerId == nil || qjs_timers == nil) return;
171
+
172
+ NSMutableDictionary<NSNumber*, id>* timers = qjs_timers[workerId];
173
+ if (timers == nil) return;
174
+
175
+ for (NSNumber* key in [timers allKeys]) {
176
+ dispatch_source_t src = (dispatch_source_t)timers[key];
177
+ if (src != nil) {
178
+ dispatch_source_cancel(src);
179
+ }
180
+ }
181
+
182
+ [qjs_timers removeObjectForKey:workerId];
183
+ }
184
+
185
+ void zapp_darwin_qjs_timers_cancel_all(void) {
186
+ if (qjs_timers != nil) {
187
+ NSArray<NSString*>* workerIds = [qjs_timers allKeys];
188
+ for (NSString* workerId in workerIds) {
189
+ zapp_darwin_qjs_timers_cancel(workerId);
190
+ }
191
+ [qjs_timers removeAllObjects];
192
+ }
193
+ }
194
+
195
+ void zapp_darwin_qjs_timers_install(QJSContext* ctx, QJSValue bridge, const char* worker_id) {
196
+ QJSValue wIdVal = JS_NewString(ctx, worker_id);
197
+ QJSValue funcData[1] = { wIdVal };
198
+
199
+ QJSValue setTimerFunc = JS_NewCFunctionData(ctx, qjs_bridge_setTimer, 3, 0, 1, funcData);
200
+ JS_SetPropertyStr(ctx, bridge, "setTimer", setTimerFunc);
201
+
202
+ QJSValue clearTimerFunc = JS_NewCFunctionData(ctx, qjs_bridge_clearTimer, 1, 0, 1, funcData);
203
+ JS_SetPropertyStr(ctx, bridge, "clearTimer", clearTimerFunc);
204
+
205
+ JS_FreeValue(ctx, wIdVal);
206
+ }
207
+ #endif /* __APPLE__ */
208
+ #endif
209
+ }
@@ -0,0 +1,64 @@
1
+ //> macos: define: apple
2
+ //> windows: define: windows
3
+
4
+ import "./window.zc";
5
+
6
+ trait Platform {
7
+ fn init(self) -> void;
8
+ fn run(self, app: App*) -> int;
9
+ }
10
+
11
+ @cfg(apple)
12
+ import "./darwin/platform.zc";
13
+
14
+ @cfg(windows)
15
+ import "./windows/platform.zc";
16
+
17
+ @cfg(apple)
18
+ fn platform_bind_runtime(app: App*) -> void {
19
+ darwin_platform_bind_runtime(app);
20
+ }
21
+
22
+ @cfg(windows)
23
+ fn platform_bind_runtime(app: App*) -> void {
24
+ windows_platform_bind_runtime(app);
25
+ }
26
+
27
+ @cfg(ZAPP_LINUX)
28
+ fn platform_bind_runtime(app: App*) -> void {
29
+ let _ = app;
30
+ }
31
+
32
+ @cfg(apple)
33
+ fn platform_handle_worker_bridge(app: App*, action: string, payload: string) -> void {
34
+ darwin_platform_handle_worker_bridge(app, action, payload);
35
+ }
36
+
37
+ @cfg(windows)
38
+ fn platform_handle_worker_bridge(app: App*, action: string, payload: string) -> void {
39
+ windows_platform_handle_worker_bridge(app, action, payload);
40
+ }
41
+
42
+ @cfg(ZAPP_LINUX)
43
+ fn platform_handle_worker_bridge(app: App*, action: string, payload: string) -> void {
44
+
45
+ }
46
+
47
+ @cfg(apple)
48
+ fn platform_run(app: App*) -> int {
49
+ let platform = CocoaPlatform{};
50
+ return platform.run(app);
51
+ }
52
+
53
+ @cfg(windows)
54
+ fn platform_run(app: App*) -> int {
55
+ let platform = WindowsPlatform{};
56
+ return platform.run(app);
57
+ }
58
+
59
+ @cfg(ZAPP_LINUX)
60
+ fn platform_run(app: App*) -> int {
61
+ let _ = app;
62
+ println "Linux not implemented yet";
63
+ return 0;
64
+ }
@@ -0,0 +1,156 @@
1
+ // Zapp Unified Logging System
2
+ // Provides consistent, colored logging across all contexts (workers, backend, webview)
3
+
4
+ include <stdio.h>
5
+ include <string.h>
6
+
7
+ raw {
8
+ // Log levels (higher = more verbose)
9
+ #define ZAPP_LOG_ERROR 0
10
+ #define ZAPP_LOG_WARN 1
11
+ #define ZAPP_LOG_INFO 2
12
+ #define ZAPP_LOG_DEBUG 3
13
+ #define ZAPP_LOG_TRACE 4
14
+
15
+ // Context types
16
+ #define ZAPP_LOG_CTX_BACKEND 0
17
+ #define ZAPP_LOG_CTX_WEBVIEW 1
18
+ #define ZAPP_LOG_CTX_WORKER 2
19
+
20
+ // ANSI color codes
21
+ #define ZAPP_ANSI_RESET "\x1b[0m"
22
+ #define ZAPP_ANSI_RED "\x1b[31m"
23
+ #define ZAPP_ANSI_YELLOW "\x1b[33m"
24
+ #define ZAPP_ANSI_CYAN "\x1b[36m"
25
+ #define ZAPP_ANSI_GRAY "\x1b[90m"
26
+ #define ZAPP_ANSI_BOLD "\x1b[1m"
27
+
28
+ // Global log level (default: WARN for prod, INFO for dev)
29
+ // Can be overridden via ZAPP_LOG_LEVEL env var or CLI flag
30
+ static int g_zapp_log_level = ZAPP_LOG_WARN;
31
+ }
32
+
33
+ // Platform-specific TTY check - Windows
34
+ raw {
35
+ #ifdef _WIN32
36
+ #include <io.h>
37
+ static bool zapp_log_use_colors(void) {
38
+ return _isatty(_fileno(stderr)) != 0;
39
+ }
40
+ #endif
41
+ }
42
+
43
+ // Platform-specific TTY check - Unix/macOS
44
+ raw {
45
+ #ifndef _WIN32
46
+ #include <unistd.h>
47
+ static bool zapp_log_use_colors(void) {
48
+ return isatty(fileno(stderr)) != 0;
49
+ }
50
+ #endif
51
+ }
52
+
53
+ raw {
54
+ // Get ANSI color for log level
55
+ static const char* zapp_log_level_color(int level) {
56
+ if (!zapp_log_use_colors()) return "";
57
+ switch (level) {
58
+ case ZAPP_LOG_ERROR: return ZAPP_ANSI_RED;
59
+ case ZAPP_LOG_WARN: return ZAPP_ANSI_YELLOW;
60
+ case ZAPP_LOG_DEBUG: return ZAPP_ANSI_CYAN;
61
+ case ZAPP_LOG_TRACE: return ZAPP_ANSI_GRAY;
62
+ default: return "";
63
+ }
64
+ }
65
+
66
+ // Get level name string
67
+ static const char* zapp_log_level_name(int level) {
68
+ switch (level) {
69
+ case ZAPP_LOG_ERROR: return "error";
70
+ case ZAPP_LOG_WARN: return "warn";
71
+ case ZAPP_LOG_INFO: return "info";
72
+ case ZAPP_LOG_DEBUG: return "debug";
73
+ case ZAPP_LOG_TRACE: return "trace";
74
+ default: return "log";
75
+ }
76
+ }
77
+
78
+ // Core logging function
79
+ void zapp_log(int level, int ctx_type, int window_id, int worker_id, const char* message) {
80
+ if (level > g_zapp_log_level) return;
81
+ if (!message) return;
82
+
83
+ const char* color = zapp_log_level_color(level);
84
+ const char* reset = zapp_log_use_colors() ? ZAPP_ANSI_RESET : "";
85
+ const char* level_name = zapp_log_level_name(level);
86
+
87
+ // Build context string
88
+ char ctx_buf[64];
89
+ ctx_buf[0] = '\0';
90
+
91
+ if (ctx_type == ZAPP_LOG_CTX_BACKEND) {
92
+ snprintf(ctx_buf, sizeof(ctx_buf), "[B]");
93
+ } else if (ctx_type == ZAPP_LOG_CTX_WEBVIEW) {
94
+ snprintf(ctx_buf, sizeof(ctx_buf), "[V]");
95
+ } else if (ctx_type == ZAPP_LOG_CTX_WORKER) {
96
+ if (window_id >= 0 && worker_id >= 0) {
97
+ snprintf(ctx_buf, sizeof(ctx_buf), "[Win:%d][W:%d]", window_id, worker_id);
98
+ } else if (worker_id >= 0) {
99
+ snprintf(ctx_buf, sizeof(ctx_buf), "[W:%d]", worker_id);
100
+ } else {
101
+ snprintf(ctx_buf, sizeof(ctx_buf), "[W:?]");
102
+ }
103
+ }
104
+
105
+ // Output format: [Zapp] [Win:N][W:M] level: message
106
+ // Or for backend/webview: [Zapp] [B] level: message
107
+ fprintf(stderr, "%s[Zapp]%s %s %s%s:%s %s\n",
108
+ zapp_log_use_colors() ? ZAPP_ANSI_BOLD : "",
109
+ reset,
110
+ ctx_buf,
111
+ color,
112
+ level_name,
113
+ reset,
114
+ message);
115
+ }
116
+
117
+ // Convenience functions for each context
118
+ void zapp_log_backend(int level, const char* message) {
119
+ zapp_log(level, ZAPP_LOG_CTX_BACKEND, -1, -1, message);
120
+ }
121
+
122
+ void zapp_log_webview(int level, int window_id, const char* message) {
123
+ zapp_log(level, ZAPP_LOG_CTX_WEBVIEW, window_id, -1, message);
124
+ }
125
+
126
+ void zapp_log_worker(int level, int window_id, int worker_id, const char* message) {
127
+ zapp_log(level, ZAPP_LOG_CTX_WORKER, window_id, worker_id, message);
128
+ }
129
+
130
+ // Set global log level
131
+ void zapp_set_log_level(int level) {
132
+ if (level >= ZAPP_LOG_ERROR && level <= ZAPP_LOG_TRACE) {
133
+ g_zapp_log_level = level;
134
+ }
135
+ }
136
+
137
+ // Get current log level
138
+ int zapp_get_log_level(void) {
139
+ return g_zapp_log_level;
140
+ }
141
+
142
+ // Initialize log level from environment or default
143
+ void zapp_log_init(int default_level) {
144
+ g_zapp_log_level = default_level;
145
+
146
+ // Check environment variable
147
+ const char* env_level = getenv("ZAPP_LOG_LEVEL");
148
+ if (env_level) {
149
+ if (strcmp(env_level, "error") == 0) g_zapp_log_level = ZAPP_LOG_ERROR;
150
+ else if (strcmp(env_level, "warn") == 0) g_zapp_log_level = ZAPP_LOG_WARN;
151
+ else if (strcmp(env_level, "info") == 0) g_zapp_log_level = ZAPP_LOG_INFO;
152
+ else if (strcmp(env_level, "debug") == 0) g_zapp_log_level = ZAPP_LOG_DEBUG;
153
+ else if (strcmp(env_level, "trace") == 0) g_zapp_log_level = ZAPP_LOG_TRACE;
154
+ }
155
+ }
156
+ }
@@ -0,0 +1,38 @@
1
+ // Shared QJS wrapper for btoa/atob. Delegates to platform-specific core/base64_core.zc.
2
+
3
+ raw {
4
+ #if defined(ZAPP_WORKER_ENGINE_QJS)
5
+ #include "quickjs.h"
6
+ char* zapp_core_btoa(const char* input);
7
+ char* zapp_core_atob(const char* input);
8
+
9
+ static JSValue qjs_bridge_btoa(JSContext* ctx, JSValue this_val, int argc, JSValue* argv) {
10
+ (void)this_val;
11
+ if (argc < 1) return JS_NewString(ctx, "");
12
+ const char* input = JS_ToCString(ctx, argv[0]);
13
+ if (!input) return JS_NewString(ctx, "");
14
+ char* result = zapp_core_btoa(input);
15
+ JS_FreeCString(ctx, input);
16
+ JSValue ret = JS_NewString(ctx, result);
17
+ free(result);
18
+ return ret;
19
+ }
20
+
21
+ static JSValue qjs_bridge_atob(JSContext* ctx, JSValue this_val, int argc, JSValue* argv) {
22
+ (void)this_val;
23
+ if (argc < 1) return JS_NewString(ctx, "");
24
+ const char* input = JS_ToCString(ctx, argv[0]);
25
+ if (!input) return JS_NewString(ctx, "");
26
+ char* result = zapp_core_atob(input);
27
+ JS_FreeCString(ctx, input);
28
+ JSValue ret = JS_NewString(ctx, result);
29
+ free(result);
30
+ return ret;
31
+ }
32
+
33
+ void zapp_qjs_base64_install(JSContext* ctx, JSValue bridge) {
34
+ JS_SetPropertyStr(ctx, bridge, "btoa", JS_NewCFunction(ctx, qjs_bridge_btoa, "btoa", 1));
35
+ JS_SetPropertyStr(ctx, bridge, "atob", JS_NewCFunction(ctx, qjs_bridge_atob, "atob", 1));
36
+ }
37
+ #endif
38
+ }
@@ -0,0 +1,44 @@
1
+ // Shared QJS wrapper for crypto. Delegates to platform-specific core/crypto_core.zc.
2
+
3
+ raw {
4
+ #if defined(ZAPP_WORKER_ENGINE_QJS)
5
+ #include "quickjs.h"
6
+ void zapp_core_crypto_random_bytes(uint8_t* buf, size_t len);
7
+ char* zapp_core_crypto_random_uuid(void);
8
+
9
+ static JSValue qjs_bridge_getRandomValues(JSContext* ctx, JSValue this_val, int argc, JSValue* argv) {
10
+ (void)this_val;
11
+ if (argc < 1) return JS_UNDEFINED;
12
+
13
+ JSValue arrayVal = argv[0];
14
+ size_t byte_offset = 0, byte_length = 0, bytes_per_element = 0;
15
+ JSValue buffer = JS_GetTypedArrayBuffer(ctx, arrayVal, &byte_offset, &byte_length, &bytes_per_element);
16
+ if (!JS_IsException(buffer)) {
17
+ size_t len = 0;
18
+ uint8_t* buf = JS_GetArrayBuffer(ctx, &len, buffer);
19
+ if (buf) zapp_core_crypto_random_bytes(buf + byte_offset, byte_length);
20
+ JS_FreeValue(ctx, buffer);
21
+ } else {
22
+ size_t len = 0;
23
+ uint8_t* buf = JS_GetArrayBuffer(ctx, &len, arrayVal);
24
+ if (buf) zapp_core_crypto_random_bytes(buf, len);
25
+ }
26
+ return JS_DupValue(ctx, arrayVal);
27
+ }
28
+
29
+ static JSValue qjs_bridge_randomUUID(JSContext* ctx, JSValue this_val, int argc, JSValue* argv) {
30
+ (void)this_val; (void)argc; (void)argv;
31
+ char* uuid = zapp_core_crypto_random_uuid();
32
+ JSValue result = JS_NewString(ctx, uuid);
33
+ free(uuid);
34
+ return result;
35
+ }
36
+
37
+ void zapp_qjs_crypto_install(JSContext* ctx, JSValue bridge) {
38
+ JS_SetPropertyStr(ctx, bridge, "getRandomValues",
39
+ JS_NewCFunction(ctx, qjs_bridge_getRandomValues, "getRandomValues", 1));
40
+ JS_SetPropertyStr(ctx, bridge, "randomUUID",
41
+ JS_NewCFunction(ctx, qjs_bridge_randomUUID, "randomUUID", 0));
42
+ }
43
+ #endif
44
+ }