@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,288 @@
1
+ raw {
2
+ #if defined(_WIN32) && defined(ZAPP_WORKER_ENGINE_QJS)
3
+ #include <windows.h>
4
+ #include <stdio.h>
5
+ #include <stdlib.h>
6
+ #include <string.h>
7
+ #include "quickjs.h"
8
+ #include "quickjs-libc.h"
9
+
10
+ extern void* zapp_windows_qjs_get_context(const char* workerId);
11
+ extern void zapp_windows_qjs_dispatch(void (*func)(void*), void* data);
12
+ extern void zapp_windows_qjs_drain_jobs(void* ctx, const char* label);
13
+ static void qjs_call_bridge_method(JSContext* ctx, const char* methodName, int argc, JSValue* argv);
14
+
15
+ // -----------------------------------------------------------------------
16
+ // Timer state
17
+ // -----------------------------------------------------------------------
18
+
19
+ #define ZAPP_MAX_TIMERS_PER_WORKER 256
20
+ #define ZAPP_MAX_TOTAL_TIMERS 4096
21
+ #define ZAPP_MIN_INTERVAL_MS 4
22
+
23
+ typedef struct {
24
+ int id;
25
+ char workerId[128];
26
+ HANDLE hTimer;
27
+ JSContext* creatingCtx;
28
+ JSValue savedFn;
29
+ int shouldRepeat;
30
+ int cancelled;
31
+ DWORD intervalMs;
32
+ } ZappTimer;
33
+
34
+ static HANDLE zapp_timer_queue = NULL;
35
+ static ZappTimer zapp_timers[ZAPP_MAX_TOTAL_TIMERS] = {0};
36
+ static int zapp_next_timer_id = 1;
37
+ static CRITICAL_SECTION zapp_timer_lock;
38
+ static int zapp_timer_lock_init = 0;
39
+
40
+ static void zapp_timers_ensure_init(void) {
41
+ if (!zapp_timer_lock_init) {
42
+ InitializeCriticalSection(&zapp_timer_lock);
43
+ zapp_timer_lock_init = 1;
44
+ }
45
+ if (!zapp_timer_queue) {
46
+ zapp_timer_queue = CreateTimerQueue();
47
+ }
48
+ }
49
+
50
+ static ZappTimer* zapp_timer_find(int id) {
51
+ for (int i = 0; i < ZAPP_MAX_TOTAL_TIMERS; i++) {
52
+ if (zapp_timers[i].id == id && zapp_timers[i].hTimer != NULL) {
53
+ return &zapp_timers[i];
54
+ }
55
+ }
56
+ return NULL;
57
+ }
58
+
59
+ static ZappTimer* zapp_timer_alloc(void) {
60
+ for (int i = 0; i < ZAPP_MAX_TOTAL_TIMERS; i++) {
61
+ if (zapp_timers[i].id == 0) {
62
+ return &zapp_timers[i];
63
+ }
64
+ }
65
+ return NULL;
66
+ }
67
+
68
+ static int zapp_timers_count_for_worker(const char* workerId) {
69
+ int count = 0;
70
+ for (int i = 0; i < ZAPP_MAX_TOTAL_TIMERS; i++) {
71
+ if (zapp_timers[i].id != 0 && strcmp(zapp_timers[i].workerId, workerId) == 0) {
72
+ count++;
73
+ }
74
+ }
75
+ return count;
76
+ }
77
+
78
+ // -----------------------------------------------------------------------
79
+ // Timer callback (fires on threadpool, dispatches to QJS thread)
80
+ // -----------------------------------------------------------------------
81
+
82
+ typedef struct {
83
+ int timerId;
84
+ } ZappTimerFireData;
85
+
86
+ static void zapp_timer_fire_on_qjs(void* data) {
87
+ ZappTimerFireData* fd = (ZappTimerFireData*)data;
88
+ int timerId = fd->timerId;
89
+ free(fd);
90
+
91
+ EnterCriticalSection(&zapp_timer_lock);
92
+ ZappTimer* timer = zapp_timer_find(timerId);
93
+ if (!timer || timer->cancelled) {
94
+ LeaveCriticalSection(&zapp_timer_lock);
95
+ return;
96
+ }
97
+
98
+ char workerId[128];
99
+ strncpy(workerId, timer->workerId, sizeof(workerId));
100
+ JSContext* creatingCtx = timer->creatingCtx;
101
+ JSValue savedFn = timer->savedFn;
102
+ int shouldRepeat = timer->shouldRepeat;
103
+ LeaveCriticalSection(&zapp_timer_lock);
104
+
105
+ void* ctx_ptr = zapp_windows_qjs_get_context(workerId);
106
+ if (!ctx_ptr || (JSContext*)ctx_ptr != creatingCtx) {
107
+ return;
108
+ }
109
+ JSContext* ctx = (JSContext*)ctx_ptr;
110
+
111
+ JSValue ret = JS_Call(ctx, savedFn, JS_UNDEFINED, 0, NULL);
112
+ if (JS_IsException(ret)) {
113
+ JSValue exception = JS_GetException(ctx);
114
+ JSValue args[1];
115
+ args[0] = JS_DupValue(ctx, exception);
116
+ qjs_call_bridge_method(ctx, "reportError", 1, args);
117
+ JS_FreeValue(ctx, args[0]);
118
+ JS_FreeValue(ctx, exception);
119
+ }
120
+ JS_FreeValue(ctx, ret);
121
+ zapp_windows_qjs_drain_jobs(ctx, "timer");
122
+
123
+ if (!shouldRepeat) {
124
+ EnterCriticalSection(&zapp_timer_lock);
125
+ ZappTimer* t = zapp_timer_find(timerId);
126
+ if (t) {
127
+ if (t->hTimer) {
128
+ DeleteTimerQueueTimer(zapp_timer_queue, t->hTimer, NULL);
129
+ }
130
+ if (ctx_ptr && (JSContext*)ctx_ptr == t->creatingCtx) {
131
+ JS_FreeValue(t->creatingCtx, t->savedFn);
132
+ }
133
+ memset(t, 0, sizeof(ZappTimer));
134
+ }
135
+ LeaveCriticalSection(&zapp_timer_lock);
136
+ }
137
+ }
138
+
139
+ static VOID CALLBACK zapp_timer_callback(PVOID lpParameter, BOOLEAN TimerOrWaitFired) {
140
+ (void)TimerOrWaitFired;
141
+ int timerId = (int)(intptr_t)lpParameter;
142
+
143
+ ZappTimerFireData* fd = (ZappTimerFireData*)calloc(1, sizeof(ZappTimerFireData));
144
+ fd->timerId = timerId;
145
+ zapp_windows_qjs_dispatch(zapp_timer_fire_on_qjs, fd);
146
+ }
147
+
148
+ // -----------------------------------------------------------------------
149
+ // QJS bridge functions: setTimer, clearTimer
150
+ // -----------------------------------------------------------------------
151
+
152
+ static JSValue qjs_bridge_setTimer(JSContext* ctx, JSValue this_val, int argc, JSValue* argv, int magic, JSValue* func_data) {
153
+ (void)this_val; (void)magic;
154
+ if (argc < 3) return JS_NewInt32(ctx, 0);
155
+
156
+ const char* worker_id = JS_ToCString(ctx, func_data[0]);
157
+ if (!worker_id) return JS_NewInt32(ctx, 0);
158
+
159
+ if (!JS_IsFunction(ctx, argv[0])) {
160
+ JS_FreeCString(ctx, worker_id);
161
+ return JS_NewInt32(ctx, 0);
162
+ }
163
+
164
+ double ms = 0;
165
+ JS_ToFloat64(ctx, &ms, argv[1]);
166
+ if (!(ms >= 0)) ms = 0;
167
+
168
+ int shouldRepeat = JS_ToBool(ctx, argv[2]);
169
+ if (shouldRepeat && ms < ZAPP_MIN_INTERVAL_MS) {
170
+ ms = ZAPP_MIN_INTERVAL_MS;
171
+ }
172
+
173
+ zapp_timers_ensure_init();
174
+
175
+ EnterCriticalSection(&zapp_timer_lock);
176
+
177
+ if (zapp_timers_count_for_worker(worker_id) >= ZAPP_MAX_TIMERS_PER_WORKER) {
178
+ LeaveCriticalSection(&zapp_timer_lock);
179
+ JS_FreeCString(ctx, worker_id);
180
+ return JS_NewInt32(ctx, 0);
181
+ }
182
+
183
+ ZappTimer* timer = zapp_timer_alloc();
184
+ if (!timer) {
185
+ LeaveCriticalSection(&zapp_timer_lock);
186
+ JS_FreeCString(ctx, worker_id);
187
+ return JS_NewInt32(ctx, 0);
188
+ }
189
+
190
+ int timerId = zapp_next_timer_id++;
191
+ memset(timer, 0, sizeof(ZappTimer));
192
+ timer->id = timerId;
193
+ strncpy(timer->workerId, worker_id, sizeof(timer->workerId) - 1);
194
+ timer->creatingCtx = ctx;
195
+ timer->savedFn = JS_DupValue(ctx, argv[0]);
196
+ timer->shouldRepeat = shouldRepeat;
197
+ timer->cancelled = 0;
198
+ timer->intervalMs = (DWORD)(ms > 0 ? ms : 1);
199
+
200
+ BOOL ok = CreateTimerQueueTimer(
201
+ &timer->hTimer,
202
+ zapp_timer_queue,
203
+ zapp_timer_callback,
204
+ (PVOID)(intptr_t)timerId,
205
+ timer->intervalMs,
206
+ shouldRepeat ? timer->intervalMs : 0,
207
+ WT_EXECUTEDEFAULT
208
+ );
209
+
210
+ LeaveCriticalSection(&zapp_timer_lock);
211
+ JS_FreeCString(ctx, worker_id);
212
+
213
+ if (!ok) return JS_NewInt32(ctx, 0);
214
+ return JS_NewInt32(ctx, timerId);
215
+ }
216
+
217
+ static JSValue qjs_bridge_clearTimer(JSContext* ctx, JSValue this_val, int argc, JSValue* argv, int magic, JSValue* func_data) {
218
+ (void)this_val; (void)magic;
219
+ if (argc < 1) return JS_UNDEFINED;
220
+
221
+ const char* worker_id = JS_ToCString(ctx, func_data[0]);
222
+ if (!worker_id) return JS_UNDEFINED;
223
+
224
+ int32_t tId = 0;
225
+ JS_ToInt32(ctx, &tId, argv[0]);
226
+
227
+ EnterCriticalSection(&zapp_timer_lock);
228
+ ZappTimer* timer = zapp_timer_find(tId);
229
+ if (timer && strcmp(timer->workerId, worker_id) == 0) {
230
+ timer->cancelled = 1;
231
+ if (timer->hTimer) {
232
+ DeleteTimerQueueTimer(zapp_timer_queue, timer->hTimer, NULL);
233
+ }
234
+ void* ctx_ptr = zapp_windows_qjs_get_context(worker_id);
235
+ if (ctx_ptr && (JSContext*)ctx_ptr == timer->creatingCtx) {
236
+ JS_FreeValue(timer->creatingCtx, timer->savedFn);
237
+ }
238
+ memset(timer, 0, sizeof(ZappTimer));
239
+ }
240
+ LeaveCriticalSection(&zapp_timer_lock);
241
+
242
+ JS_FreeCString(ctx, worker_id);
243
+ return JS_UNDEFINED;
244
+ }
245
+
246
+ // -----------------------------------------------------------------------
247
+ // Cancel all timers for a given worker
248
+ // -----------------------------------------------------------------------
249
+
250
+ void zapp_windows_qjs_timers_cancel(const char* workerId) {
251
+ if (!workerId || !zapp_timer_lock_init) return;
252
+
253
+ EnterCriticalSection(&zapp_timer_lock);
254
+ for (int i = 0; i < ZAPP_MAX_TOTAL_TIMERS; i++) {
255
+ if (zapp_timers[i].id != 0 && strcmp(zapp_timers[i].workerId, workerId) == 0) {
256
+ zapp_timers[i].cancelled = 1;
257
+ if (zapp_timers[i].hTimer) {
258
+ DeleteTimerQueueTimer(zapp_timer_queue, zapp_timers[i].hTimer, NULL);
259
+ }
260
+ void* ctx_ptr = zapp_windows_qjs_get_context(workerId);
261
+ if (ctx_ptr && (JSContext*)ctx_ptr == zapp_timers[i].creatingCtx) {
262
+ JS_FreeValue(zapp_timers[i].creatingCtx, zapp_timers[i].savedFn);
263
+ }
264
+ memset(&zapp_timers[i], 0, sizeof(ZappTimer));
265
+ }
266
+ }
267
+ LeaveCriticalSection(&zapp_timer_lock);
268
+ }
269
+
270
+ // -----------------------------------------------------------------------
271
+ // Install setTimer/clearTimer on a QJS bridge object
272
+ // -----------------------------------------------------------------------
273
+
274
+ void zapp_windows_qjs_timers_install(JSContext* ctx, JSValue bridge, const char* worker_id) {
275
+ zapp_timers_ensure_init();
276
+ JSValue wIdVal = JS_NewString(ctx, worker_id);
277
+ JSValue funcData[1] = { wIdVal };
278
+
279
+ JSValue setTimerFunc = JS_NewCFunctionData(ctx, qjs_bridge_setTimer, 3, 0, 1, funcData);
280
+ JS_SetPropertyStr(ctx, bridge, "setTimer", setTimerFunc);
281
+
282
+ JSValue clearTimerFunc = JS_NewCFunctionData(ctx, qjs_bridge_clearTimer, 1, 0, 1, funcData);
283
+ JS_SetPropertyStr(ctx, bridge, "clearTimer", clearTimerFunc);
284
+
285
+ JS_FreeValue(ctx, wIdVal);
286
+ }
287
+ #endif
288
+ }
@@ -0,0 +1,8 @@
1
+ // Cross-platform Worker contract. Each OS (darwin, windows) wires a backend that
2
+ // implements this trait; the app only calls platform_bind_runtime and
3
+ // platform_handle_worker_bridge. On darwin, the engine (JSC vs QuickJS vs XS) is
4
+ // selected by @cfg(ZAPP_WORKER_ENGINE_*) in platform/darwin/worker.zc.
5
+ trait WorkerBackend {
6
+ fn bind_runtime(self, app: App*) -> void;
7
+ fn handle_bridge(self, app: App*, action: string, payload: string) -> void;
8
+ }
@@ -0,0 +1,228 @@
1
+ struct App;
2
+
3
+ import "std/result.zc";
4
+ include <string.h>
5
+
6
+ def SERVICE_MAX_BINDINGS = 128;
7
+ def SERVICE_MAX_NAME = 96;
8
+ def SERVICE_MAX_PAYLOAD_BYTES = 65536;
9
+
10
+ struct ServiceManager {
11
+ app: App*;
12
+ }
13
+
14
+ let g_service_names: string[SERVICE_MAX_BINDINGS];
15
+ let g_service_handlers: void*[SERVICE_MAX_BINDINGS];
16
+ let g_service_startup_handlers: void*[SERVICE_MAX_BINDINGS];
17
+ let g_service_shutdown_handlers: void*[SERVICE_MAX_BINDINGS];
18
+ let g_service_public: bool[SERVICE_MAX_BINDINGS];
19
+ let g_service_capabilities: string[SERVICE_MAX_BINDINGS];
20
+ let g_service_count: int = 0;
21
+
22
+ fn service_is_valid_name(name: string) -> bool {
23
+ if name == "" {
24
+ return false;
25
+ }
26
+ raw {
27
+ const char* s = (const char*)name;
28
+ int len = 0;
29
+ while (*s != '\0') {
30
+ char ch = *s;
31
+ int ok =
32
+ (ch >= 'a' && ch <= 'z') ||
33
+ (ch >= 'A' && ch <= 'Z') ||
34
+ (ch >= '0' && ch <= '9') ||
35
+ ch == '.' || ch == '_' || ch == '-';
36
+ if (!ok) return false;
37
+ len++;
38
+ if (len > SERVICE_MAX_NAME) return false;
39
+ s++;
40
+ }
41
+ return len > 0;
42
+ }
43
+ }
44
+
45
+ fn service_payload_size_ok(payload: string) -> bool {
46
+ if payload == NULL {
47
+ return true;
48
+ }
49
+ raw {
50
+ size_t n = strlen((const char*)payload);
51
+ return n <= SERVICE_MAX_PAYLOAD_BYTES;
52
+ }
53
+ }
54
+
55
+ fn service_index_of(name: string) -> int {
56
+ raw {
57
+ for (int i = 0; i < g_service_count; i++) {
58
+ if (strcmp((const char*)g_service_names[i], (const char*)name) == 0) return i;
59
+ }
60
+ return -1;
61
+ }
62
+ }
63
+
64
+ fn service_add_with_lifecycle(
65
+ name: string,
66
+ handler: fn*(App*, string) -> string,
67
+ startup: fn*(App*) -> bool,
68
+ shutdown: fn*(App*) -> void,
69
+ public: bool,
70
+ capability: string
71
+ ) -> bool {
72
+ if !service_is_valid_name(name) {
73
+ return false;
74
+ }
75
+ if g_service_count >= SERVICE_MAX_BINDINGS {
76
+ return false;
77
+ }
78
+ if service_index_of(name) >= 0 {
79
+ return false;
80
+ }
81
+ g_service_names[g_service_count] = name;
82
+ g_service_public[g_service_count] = public;
83
+ g_service_capabilities[g_service_count] = capability;
84
+ raw {
85
+ g_service_handlers[g_service_count] = (void*)handler;
86
+ g_service_startup_handlers[g_service_count] = (void*)startup;
87
+ g_service_shutdown_handlers[g_service_count] = (void*)shutdown;
88
+ }
89
+ g_service_count += 1;
90
+ return true;
91
+ }
92
+
93
+ fn service_add(name: string, handler: fn*(App*, string) -> string) -> bool {
94
+ return service_add_with_lifecycle(name, handler, NULL, NULL, true, "");
95
+ }
96
+
97
+ fn service_start_all(app: App*) -> bool {
98
+ for i in 0..g_service_count {
99
+ if g_service_startup_handlers[i] != NULL {
100
+ raw {
101
+ typedef bool (*StartupFnPtr)(void*);
102
+ StartupFnPtr cb = (StartupFnPtr)g_service_startup_handlers[i];
103
+ if (!cb((void*)app)) {
104
+ return false;
105
+ }
106
+ }
107
+ }
108
+ }
109
+ return true;
110
+ }
111
+
112
+ fn service_shutdown_all(app: App*) -> void {
113
+ let _ = app;
114
+ for j in 0..g_service_count {
115
+ let i = g_service_count - 1 - j;
116
+ if i < 0 {
117
+ continue;
118
+ }
119
+ if g_service_shutdown_handlers[i] != NULL {
120
+ raw {
121
+ typedef void (*ShutdownFnPtr)(void*);
122
+ ShutdownFnPtr cb = (ShutdownFnPtr)g_service_shutdown_handlers[i];
123
+ cb((void*)app);
124
+ }
125
+ }
126
+ }
127
+ }
128
+
129
+ fn service_get_bindings_manifest_json() -> string {
130
+ raw {
131
+ static char manifest[16384];
132
+ strcpy(manifest, "{\"v\":1,\"generatedAt\":\"native\",\"services\":[");
133
+ for (int i = 0; i < g_service_count; i++) {
134
+ if (i > 0) strcat(manifest, ",");
135
+ strcat(manifest, "{\"name\":\"");
136
+ strcat(manifest, (const char*)g_service_names[i]);
137
+ strcat(manifest, "\",\"methods\":[{\"name\":\"");
138
+ strcat(manifest, (const char*)g_service_names[i]);
139
+ strcat(manifest, "\"}]");
140
+ if (g_service_capabilities[i] != NULL && ((const char*)g_service_capabilities[i])[0] != '\0') {
141
+ strcat(manifest, ",\"capability\":\"");
142
+ strcat(manifest, (const char*)g_service_capabilities[i]);
143
+ strcat(manifest, "\"");
144
+ }
145
+ strcat(manifest, "}");
146
+ }
147
+ strcat(manifest, "]}");
148
+ return (char*)manifest;
149
+ }
150
+ }
151
+
152
+ fn service_invoke_with_policy(
153
+ app: App*,
154
+ name: string,
155
+ payload: string,
156
+ capability: string
157
+ ) -> Result<string> {
158
+ if !service_is_valid_name(name) {
159
+ return Result<string>::Err("INVALID_METHOD");
160
+ }
161
+ if !service_payload_size_ok(payload) {
162
+ return Result<string>::Err("BAD_REQUEST");
163
+ }
164
+
165
+ let idx = service_index_of(name);
166
+ if idx < 0 {
167
+ return Result<string>::Err("NOT_FOUND");
168
+ }
169
+
170
+ if !g_service_public[idx] {
171
+ return Result<string>::Err("UNAUTHORIZED");
172
+ }
173
+
174
+ let required_capability = g_service_capabilities[idx];
175
+ raw {
176
+ int has_cap = (required_capability != NULL && ((const char*)required_capability)[0] != '\0');
177
+ int cap_match = has_cap ? (strcmp((const char*)capability, (const char*)required_capability) == 0) : 1;
178
+ if (has_cap && !cap_match) {
179
+ return Result_string__Err("UNAUTHORIZED");
180
+ }
181
+
182
+ if (g_service_handlers[idx] != NULL) {
183
+ typedef char* (*ServiceFnPtr)(void*, char*);
184
+ ServiceFnPtr cb = (ServiceFnPtr)g_service_handlers[idx];
185
+ char* res = cb((void*)app, (char*)payload);
186
+ return Result_string__Ok(res);
187
+ }
188
+
189
+ return Result_string__Err("INTERNAL_ERROR");
190
+ }
191
+ }
192
+
193
+ fn service_error_message(code: string) -> string {
194
+ if code == "INVALID_METHOD" { return "Invalid service method name."; }
195
+ if code == "BAD_REQUEST" { return "Service payload exceeds max size."; }
196
+ if code == "NOT_FOUND" { return "Service method not found."; }
197
+ if code == "UNAUTHORIZED" { return "Unauthorized."; }
198
+ if code == "INTERNAL_ERROR" { return "Service handler is not available."; }
199
+ return "Unknown error.";
200
+ }
201
+
202
+ fn service_invoke(app: App*, name: string, payload: string) -> Result<string> {
203
+ return service_invoke_with_policy(app, name, payload, "");
204
+ }
205
+
206
+ impl ServiceManager {
207
+ fn new() -> Self {
208
+ return ServiceManager{ app: NULL };
209
+ }
210
+
211
+ fn add(self, name: string, handler: fn*(App*, string) -> string) -> bool {
212
+ let _ = self;
213
+ return service_add(name, handler);
214
+ }
215
+
216
+ fn add_with_lifecycle(
217
+ self,
218
+ name: string,
219
+ handler: fn*(App*, string) -> string,
220
+ startup: fn*(App*) -> bool,
221
+ shutdown: fn*(App*) -> void,
222
+ public: bool,
223
+ capability: string
224
+ ) -> bool {
225
+ let _ = self;
226
+ return service_add_with_lifecycle(name, handler, startup, shutdown, public, capability);
227
+ }
228
+ }
@@ -0,0 +1,4 @@
1
+ # Don't show changes in generated files when doing git diff
2
+
3
+ gen/** -diff
4
+ builtin-*.h -diff
@@ -0,0 +1,7 @@
1
+ # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
2
+ version: 2
3
+ updates:
4
+ - package-ecosystem: "github-actions"
5
+ directory: "/" # Location of package manifests
6
+ schedule:
7
+ interval: "weekly"