@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.
- package/README.md +55 -0
- package/dist/zapp-cli.js +9471 -0
- package/native/src/app/app.zc +490 -0
- package/native/src/event/event.zc +24 -0
- package/native/src/event/events.zc +70 -0
- package/native/src/platform/darwin/backend.zc +923 -0
- package/native/src/platform/darwin/backend_bootstrap.zc +9 -0
- package/native/src/platform/darwin/bootstrap.zc +9 -0
- package/native/src/platform/darwin/engine_jsc.zc +86 -0
- package/native/src/platform/darwin/engine_qjs.zc +92 -0
- package/native/src/platform/darwin/platform.zc +156 -0
- package/native/src/platform/darwin/webview.zc +550 -0
- package/native/src/platform/darwin/webview_bootstrap.zc +9 -0
- package/native/src/platform/darwin/window.zc +1223 -0
- package/native/src/platform/darwin/worker/common.zc +223 -0
- package/native/src/platform/darwin/worker/core/base64_core.zc +29 -0
- package/native/src/platform/darwin/worker/core/crypto_core.zc +19 -0
- package/native/src/platform/darwin/worker/core/encoding_core.zc +32 -0
- package/native/src/platform/darwin/worker/core/fetch_core.zc +145 -0
- package/native/src/platform/darwin/worker/core/url_core.zc +69 -0
- package/native/src/platform/darwin/worker/core/websocket_core.zc +179 -0
- package/native/src/platform/darwin/worker/dispatch.zc +55 -0
- package/native/src/platform/darwin/worker/jsc/base64_jsc.zc +39 -0
- package/native/src/platform/darwin/worker/jsc/crypto_jsc.zc +49 -0
- package/native/src/platform/darwin/worker/jsc/encoding_jsc.zc +86 -0
- package/native/src/platform/darwin/worker/jsc/fetch_jsc.zc +149 -0
- package/native/src/platform/darwin/worker/jsc/url_jsc.zc +54 -0
- package/native/src/platform/darwin/worker/jsc/websocket_jsc.zc +127 -0
- package/native/src/platform/darwin/worker/jsc.zc +670 -0
- package/native/src/platform/darwin/worker/mod.zc +30 -0
- package/native/src/platform/darwin/worker/qjs/fetch_qjs.zc +233 -0
- package/native/src/platform/darwin/worker/qjs/qjs_macros.zc +23 -0
- package/native/src/platform/darwin/worker/qjs/websocket_qjs.zc +223 -0
- package/native/src/platform/darwin/worker/qjs.zc +1053 -0
- package/native/src/platform/darwin/worker/timers.zc +149 -0
- package/native/src/platform/darwin/worker/timers_qjs.zc +209 -0
- package/native/src/platform/platform.zc +64 -0
- package/native/src/platform/shared/log.zc +156 -0
- package/native/src/platform/shared/worker/qjs/base64_qjs.zc +38 -0
- package/native/src/platform/shared/worker/qjs/crypto_qjs.zc +44 -0
- package/native/src/platform/shared/worker/qjs/encoding_qjs.zc +95 -0
- package/native/src/platform/shared/worker/qjs/url_qjs.zc +65 -0
- package/native/src/platform/shared/worker_registry.zc +206 -0
- package/native/src/platform/window.zc +446 -0
- package/native/src/platform/windows/backend.zc +452 -0
- package/native/src/platform/windows/backend_bootstrap.zc +9 -0
- package/native/src/platform/windows/bootstrap.zc +9 -0
- package/native/src/platform/windows/engine_qjs.zc +60 -0
- package/native/src/platform/windows/platform.zc +387 -0
- package/native/src/platform/windows/webview.zc +1175 -0
- package/native/src/platform/windows/webview_bootstrap.zc +9 -0
- package/native/src/platform/windows/window.zc +1271 -0
- package/native/src/platform/windows/worker/common.zc +409 -0
- package/native/src/platform/windows/worker/core/base64_core.zc +52 -0
- package/native/src/platform/windows/worker/core/crypto_core.zc +34 -0
- package/native/src/platform/windows/worker/core/encoding_core.zc +60 -0
- package/native/src/platform/windows/worker/core/fetch_core.zc +274 -0
- package/native/src/platform/windows/worker/core/url_core.zc +216 -0
- package/native/src/platform/windows/worker/core/websocket_core.zc +343 -0
- package/native/src/platform/windows/worker/dispatch.zc +34 -0
- package/native/src/platform/windows/worker/mod.zc +46 -0
- package/native/src/platform/windows/worker/qjs/fetch_qjs.zc +255 -0
- package/native/src/platform/windows/worker/qjs/websocket_qjs.zc +263 -0
- package/native/src/platform/windows/worker/qjs.zc +1049 -0
- package/native/src/platform/windows/worker/timers_qjs.zc +288 -0
- package/native/src/platform/worker.zc +8 -0
- package/native/src/service/service.zc +228 -0
- package/native/vendor/quickjs-ng/.gitattributes +4 -0
- package/native/vendor/quickjs-ng/.github/dependabot.yml +7 -0
- package/native/vendor/quickjs-ng/.github/workflows/ci.yml +812 -0
- package/native/vendor/quickjs-ng/.github/workflows/docs.yml +49 -0
- package/native/vendor/quickjs-ng/.github/workflows/release.yml +162 -0
- package/native/vendor/quickjs-ng/.github/workflows/test-docs.yml +23 -0
- package/native/vendor/quickjs-ng/.github/workflows/tsan.yml +32 -0
- package/native/vendor/quickjs-ng/.github/workflows/valgrind.yml +33 -0
- package/native/vendor/quickjs-ng/.gitmodules +5 -0
- package/native/vendor/quickjs-ng/CMakeLists.txt +553 -0
- package/native/vendor/quickjs-ng/LICENSE +24 -0
- package/native/vendor/quickjs-ng/Makefile +149 -0
- package/native/vendor/quickjs-ng/amalgam.js +53 -0
- package/native/vendor/quickjs-ng/api-test.c +927 -0
- package/native/vendor/quickjs-ng/builtin-array-fromasync.h +119 -0
- package/native/vendor/quickjs-ng/builtin-array-fromasync.js +36 -0
- package/native/vendor/quickjs-ng/builtin-iterator-zip-keyed.h +332 -0
- package/native/vendor/quickjs-ng/builtin-iterator-zip-keyed.js +194 -0
- package/native/vendor/quickjs-ng/builtin-iterator-zip.h +337 -0
- package/native/vendor/quickjs-ng/builtin-iterator-zip.js +210 -0
- package/native/vendor/quickjs-ng/ctest.c +17 -0
- package/native/vendor/quickjs-ng/cutils.h +2013 -0
- package/native/vendor/quickjs-ng/cxxtest.cc +2 -0
- package/native/vendor/quickjs-ng/dtoa.c +1619 -0
- package/native/vendor/quickjs-ng/dtoa.h +87 -0
- package/native/vendor/quickjs-ng/examples/fib.c +67 -0
- package/native/vendor/quickjs-ng/examples/fib_module.js +10 -0
- package/native/vendor/quickjs-ng/examples/hello.js +1 -0
- package/native/vendor/quickjs-ng/examples/hello_module.js +6 -0
- package/native/vendor/quickjs-ng/examples/meson.build +17 -0
- package/native/vendor/quickjs-ng/examples/pi_bigint.js +118 -0
- package/native/vendor/quickjs-ng/examples/point.c +154 -0
- package/native/vendor/quickjs-ng/examples/test_fib.js +8 -0
- package/native/vendor/quickjs-ng/examples/test_point.js +43 -0
- package/native/vendor/quickjs-ng/fuzz.c +51 -0
- package/native/vendor/quickjs-ng/gen/function_source.c +81 -0
- package/native/vendor/quickjs-ng/gen/hello.c +53 -0
- package/native/vendor/quickjs-ng/gen/hello_module.c +106 -0
- package/native/vendor/quickjs-ng/gen/repl.c +3053 -0
- package/native/vendor/quickjs-ng/gen/standalone.c +324 -0
- package/native/vendor/quickjs-ng/gen/test_fib.c +81 -0
- package/native/vendor/quickjs-ng/libregexp-opcode.h +58 -0
- package/native/vendor/quickjs-ng/libregexp.c +2687 -0
- package/native/vendor/quickjs-ng/libregexp.h +98 -0
- package/native/vendor/quickjs-ng/libunicode-table.h +4707 -0
- package/native/vendor/quickjs-ng/libunicode.c +1746 -0
- package/native/vendor/quickjs-ng/libunicode.h +126 -0
- package/native/vendor/quickjs-ng/list.h +107 -0
- package/native/vendor/quickjs-ng/lre-test.c +73 -0
- package/native/vendor/quickjs-ng/meson.build +684 -0
- package/native/vendor/quickjs-ng/meson_options.txt +6 -0
- package/native/vendor/quickjs-ng/qjs-wasi-reactor.c +208 -0
- package/native/vendor/quickjs-ng/qjs.c +748 -0
- package/native/vendor/quickjs-ng/qjsc.c +673 -0
- package/native/vendor/quickjs-ng/quickjs-atom.h +267 -0
- package/native/vendor/quickjs-ng/quickjs-c-atomics.h +54 -0
- package/native/vendor/quickjs-ng/quickjs-libc.c +4986 -0
- package/native/vendor/quickjs-ng/quickjs-libc.h +79 -0
- package/native/vendor/quickjs-ng/quickjs-opcode.h +369 -0
- package/native/vendor/quickjs-ng/quickjs.c +60259 -0
- package/native/vendor/quickjs-ng/quickjs.h +1419 -0
- package/native/vendor/quickjs-ng/repl.js +1927 -0
- package/native/vendor/quickjs-ng/run-test262.c +2417 -0
- package/native/vendor/quickjs-ng/standalone.js +129 -0
- package/native/vendor/quickjs-ng/tests/assert.js +49 -0
- package/native/vendor/quickjs-ng/tests/bug1221.js +16 -0
- package/native/vendor/quickjs-ng/tests/bug1296.js +12 -0
- package/native/vendor/quickjs-ng/tests/bug1297.js +22 -0
- package/native/vendor/quickjs-ng/tests/bug1301.js +21 -0
- package/native/vendor/quickjs-ng/tests/bug1302.js +24 -0
- package/native/vendor/quickjs-ng/tests/bug1305.js +26 -0
- package/native/vendor/quickjs-ng/tests/bug1318.js +54 -0
- package/native/vendor/quickjs-ng/tests/bug1352.js +8 -0
- package/native/vendor/quickjs-ng/tests/bug1354.js +6 -0
- package/native/vendor/quickjs-ng/tests/bug1355.js +58 -0
- package/native/vendor/quickjs-ng/tests/bug1368.js +9 -0
- package/native/vendor/quickjs-ng/tests/bug39/1.js +6 -0
- package/native/vendor/quickjs-ng/tests/bug39/2.js +6 -0
- package/native/vendor/quickjs-ng/tests/bug39/3.js +7 -0
- package/native/vendor/quickjs-ng/tests/bug488-upstream.js +7 -0
- package/native/vendor/quickjs-ng/tests/bug633/0.js +7 -0
- package/native/vendor/quickjs-ng/tests/bug633/1.js +4 -0
- package/native/vendor/quickjs-ng/tests/bug633/2.js +4 -0
- package/native/vendor/quickjs-ng/tests/bug633/3.js +4 -0
- package/native/vendor/quickjs-ng/tests/bug645/0.js +4 -0
- package/native/vendor/quickjs-ng/tests/bug645/1.js +9 -0
- package/native/vendor/quickjs-ng/tests/bug645/2.js +7 -0
- package/native/vendor/quickjs-ng/tests/bug648.js +13 -0
- package/native/vendor/quickjs-ng/tests/bug652.js +4 -0
- package/native/vendor/quickjs-ng/tests/bug741.js +19 -0
- package/native/vendor/quickjs-ng/tests/bug775.js +7 -0
- package/native/vendor/quickjs-ng/tests/bug776.js +7 -0
- package/native/vendor/quickjs-ng/tests/bug832.js +2 -0
- package/native/vendor/quickjs-ng/tests/bug858.js +26 -0
- package/native/vendor/quickjs-ng/tests/bug904.js +6 -0
- package/native/vendor/quickjs-ng/tests/bug988.js +7 -0
- package/native/vendor/quickjs-ng/tests/bug999.js +3 -0
- package/native/vendor/quickjs-ng/tests/destructured-export.js +8 -0
- package/native/vendor/quickjs-ng/tests/detect_module/0.js +1 -0
- package/native/vendor/quickjs-ng/tests/detect_module/1.js +2 -0
- package/native/vendor/quickjs-ng/tests/detect_module/2.js +1 -0
- package/native/vendor/quickjs-ng/tests/detect_module/3.js +8 -0
- package/native/vendor/quickjs-ng/tests/detect_module/4.js +3 -0
- package/native/vendor/quickjs-ng/tests/empty.js +0 -0
- package/native/vendor/quickjs-ng/tests/fixture_cyclic_import.js +2 -0
- package/native/vendor/quickjs-ng/tests/fixture_string_exports.js +12 -0
- package/native/vendor/quickjs-ng/tests/function_source.js +14 -0
- package/native/vendor/quickjs-ng/tests/microbench.js +1267 -0
- package/native/vendor/quickjs-ng/tests/null_or_undefined.js +38 -0
- package/native/vendor/quickjs-ng/tests/str-pad-leak.js +5 -0
- package/native/vendor/quickjs-ng/tests/test_bigint.js +107 -0
- package/native/vendor/quickjs-ng/tests/test_bjson.js +366 -0
- package/native/vendor/quickjs-ng/tests/test_builtin.js +1314 -0
- package/native/vendor/quickjs-ng/tests/test_closure.js +220 -0
- package/native/vendor/quickjs-ng/tests/test_cyclic_import.js +12 -0
- package/native/vendor/quickjs-ng/tests/test_domexception.js +35 -0
- package/native/vendor/quickjs-ng/tests/test_language.js +755 -0
- package/native/vendor/quickjs-ng/tests/test_loop.js +367 -0
- package/native/vendor/quickjs-ng/tests/test_queue_microtask.js +39 -0
- package/native/vendor/quickjs-ng/tests/test_std.js +340 -0
- package/native/vendor/quickjs-ng/tests/test_string_exports.js +25 -0
- package/native/vendor/quickjs-ng/tests/test_worker.js +43 -0
- package/native/vendor/quickjs-ng/tests/test_worker_module.js +30 -0
- package/native/vendor/quickjs-ng/tests.conf +14 -0
- package/native/vendor/quickjs-ng/unicode_download.sh +19 -0
- package/native/vendor/quickjs-ng/unicode_gen.c +3108 -0
- package/native/vendor/quickjs-ng/unicode_gen_def.h +310 -0
- package/native/vendor/quickjs-ng/update-version.sh +32 -0
- package/native/vendor/webview2/include/WebView2.h +60636 -0
- package/native/vendor/webview2/include/WebView2EnvironmentOptions.h +406 -0
- package/package.json +33 -0
- package/src/backend.ts +139 -0
- package/src/build-config.ts +87 -0
- package/src/build.ts +276 -0
- package/src/common.ts +195 -0
- package/src/config.ts +89 -0
- package/src/dev.ts +164 -0
- package/src/generate.ts +200 -0
- package/src/icons.ts +116 -0
- package/src/init.ts +190 -0
- package/src/package.ts +150 -0
- package/src/zapp-cli.ts +263 -0
|
@@ -0,0 +1,670 @@
|
|
|
1
|
+
import "../../platform.zc";
|
|
2
|
+
import "../bootstrap.zc";
|
|
3
|
+
import "./common.zc";
|
|
4
|
+
import "./timers.zc";
|
|
5
|
+
import "./core/encoding_core.zc";
|
|
6
|
+
import "./core/url_core.zc";
|
|
7
|
+
import "./core/base64_core.zc";
|
|
8
|
+
import "./core/websocket_core.zc";
|
|
9
|
+
import "./core/crypto_core.zc";
|
|
10
|
+
import "./core/fetch_core.zc";
|
|
11
|
+
import "./jsc/encoding_jsc.zc";
|
|
12
|
+
import "./jsc/url_jsc.zc";
|
|
13
|
+
import "./jsc/base64_jsc.zc";
|
|
14
|
+
import "./jsc/websocket_jsc.zc";
|
|
15
|
+
import "./jsc/crypto_jsc.zc";
|
|
16
|
+
import "./jsc/fetch_jsc.zc";
|
|
17
|
+
import "../../shared/log.zc";
|
|
18
|
+
import "../../shared/worker_registry.zc";
|
|
19
|
+
@cfg(not(ZAPP_WORKER_ENGINE_QJS))
|
|
20
|
+
import "../engine_jsc.zc";
|
|
21
|
+
|
|
22
|
+
//> macos: framework: JavaScriptCore
|
|
23
|
+
raw {
|
|
24
|
+
#ifdef __APPLE__
|
|
25
|
+
#include <Cocoa/Cocoa.h>
|
|
26
|
+
#include <WebKit/WebKit.h>
|
|
27
|
+
#include <dispatch/dispatch.h>
|
|
28
|
+
#include <JavaScriptCore/JavaScriptCore.h>
|
|
29
|
+
#endif
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
raw {
|
|
33
|
+
#if !defined(ZAPP_WORKER_ENGINE_QJS)
|
|
34
|
+
#ifdef __APPLE__
|
|
35
|
+
extern void* engine_jsc_create_ctx(void* vm, const char* name);
|
|
36
|
+
extern int engine_jsc_eval(void* ctx, const char* utf8, size_t len, const char* filename);
|
|
37
|
+
extern const char* engine_jsc_get_exception_message(void* ctx);
|
|
38
|
+
extern void engine_jsc_free_ctx(void* ctx, void* vm, const char* new_name);
|
|
39
|
+
|
|
40
|
+
// Log functions from log.zc
|
|
41
|
+
extern void zapp_log_worker(int level, int window_id, int worker_id, const char* message);
|
|
42
|
+
#define ZAPP_LOG_ERROR 0
|
|
43
|
+
#define ZAPP_LOG_WARN 1
|
|
44
|
+
#define ZAPP_LOG_INFO 2
|
|
45
|
+
#define ZAPP_LOG_DEBUG 3
|
|
46
|
+
#define ZAPP_LOG_TRACE 4
|
|
47
|
+
|
|
48
|
+
// Worker registry functions from worker_registry.zc
|
|
49
|
+
extern void zapp_extract_owner_id(const char* worker_id, char* owner_buf, size_t buf_size);
|
|
50
|
+
extern void zapp_get_window_and_worker_id(const char* owner_id, int* window_id, int* worker_id);
|
|
51
|
+
extern void zapp_worker_register(const char* worker_id);
|
|
52
|
+
extern void zapp_worker_lookup(const char* worker_id, int* out_window_id, int* out_worker_seq_id);
|
|
53
|
+
|
|
54
|
+
extern void zapp_darwin_worker_js_sync(dispatch_block_t block);
|
|
55
|
+
extern void zapp_darwin_worker_timers_cancel(NSString* workerId);
|
|
56
|
+
extern void zapp_darwin_worker_timers_cancel_all(void);
|
|
57
|
+
extern void zapp_darwin_worker_timers_init(JSContext* ctx, NSString* workerId);
|
|
58
|
+
extern void zapp_darwin_worker_fetch_cancel(NSString* workerId);
|
|
59
|
+
extern void zapp_darwin_worker_fetch_cancel_all(void);
|
|
60
|
+
extern void zapp_darwin_worker_fetch_init(JSContext* ctx, NSString* workerId);
|
|
61
|
+
extern void zapp_darwin_worker_crypto_init(JSContext* ctx);
|
|
62
|
+
|
|
63
|
+
static JSVirtualMachine* zapp_worker_vm = nil;
|
|
64
|
+
static NSMutableDictionary<NSString*, JSContext*>* zapp_worker_contexts = nil;
|
|
65
|
+
static NSMutableDictionary<NSString*, NSString*>* zapp_worker_owners = nil;
|
|
66
|
+
static NSMutableDictionary<NSString*, NSString*>* zapp_worker_script_urls = nil;
|
|
67
|
+
static NSMutableDictionary<NSString*, NSNumber*>* zapp_worker_shared_flags = nil;
|
|
68
|
+
static NSMutableDictionary<NSString*, JSContext*>* zapp_shared_worker_contexts = nil;
|
|
69
|
+
static NSMutableDictionary<NSString*, NSNumber*>* zapp_shared_worker_refcounts = nil;
|
|
70
|
+
|
|
71
|
+
static void zapp_teardown_jscontext(JSContext* ctx, NSString* newName) {
|
|
72
|
+
if (ctx == nil) return;
|
|
73
|
+
engine_jsc_free_ctx((__bridge void*)ctx, (__bridge void*)zapp_worker_vm, newName ? [newName UTF8String] : NULL);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
static void zapp_ensure_worker_state(void) {
|
|
77
|
+
if (zapp_worker_contexts == nil) {
|
|
78
|
+
zapp_worker_contexts = [NSMutableDictionary dictionary];
|
|
79
|
+
}
|
|
80
|
+
if (zapp_worker_owners == nil) {
|
|
81
|
+
zapp_worker_owners = [NSMutableDictionary dictionary];
|
|
82
|
+
}
|
|
83
|
+
if (zapp_worker_script_urls == nil) {
|
|
84
|
+
zapp_worker_script_urls = [NSMutableDictionary dictionary];
|
|
85
|
+
}
|
|
86
|
+
if (zapp_worker_shared_flags == nil) {
|
|
87
|
+
zapp_worker_shared_flags = [NSMutableDictionary dictionary];
|
|
88
|
+
}
|
|
89
|
+
if (zapp_shared_worker_contexts == nil) {
|
|
90
|
+
zapp_shared_worker_contexts = [NSMutableDictionary dictionary];
|
|
91
|
+
}
|
|
92
|
+
if (zapp_shared_worker_refcounts == nil) {
|
|
93
|
+
zapp_shared_worker_refcounts = [NSMutableDictionary dictionary];
|
|
94
|
+
}
|
|
95
|
+
if (zapp_worker_vm == nil) {
|
|
96
|
+
zapp_worker_vm = [[JSVirtualMachine alloc] init];
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
static NSUInteger zapp_worker_active_context_count(void) {
|
|
101
|
+
if (zapp_worker_contexts == nil) return 0;
|
|
102
|
+
NSMutableSet<JSContext*>* seen = [NSMutableSet set];
|
|
103
|
+
for (NSString* key in zapp_worker_contexts) {
|
|
104
|
+
JSContext* ctx = zapp_worker_contexts[key];
|
|
105
|
+
if (ctx != nil) {
|
|
106
|
+
[seen addObject:ctx];
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return [seen count];
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
static void zapp_call_bridge_method_unsafe(JSContext* ctx, NSString* methodName, NSArray* args) {
|
|
113
|
+
if (ctx == nil || methodName == nil) return;
|
|
114
|
+
JSValue* bridge = [ctx evaluateScript:@"globalThis[Symbol.for('zapp.bridge')]"];
|
|
115
|
+
if (bridge == nil || bridge.isUndefined || ![bridge isObject]) return;
|
|
116
|
+
JSValue* fn = bridge[methodName];
|
|
117
|
+
if (fn == nil || fn.isUndefined) return;
|
|
118
|
+
@try {
|
|
119
|
+
[fn callWithArguments:args ?: @[]];
|
|
120
|
+
} @catch (NSException* e) {
|
|
121
|
+
char buf[256];
|
|
122
|
+
snprintf(buf, sizeof(buf), "bridge.%s exception: %s", [methodName UTF8String], [[e description] UTF8String]);
|
|
123
|
+
zapp_log_worker(ZAPP_LOG_ERROR, -1, -1, buf);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
static void zapp_reset_owner_workers_internal(NSString* ownerId) {
|
|
128
|
+
if (ownerId == nil || zapp_worker_owners == nil) return;
|
|
129
|
+
zapp_darwin_worker_js_sync(^{
|
|
130
|
+
NSArray<NSString*>* keys = [zapp_worker_owners allKeys];
|
|
131
|
+
for (NSString* key in keys) {
|
|
132
|
+
NSString* existingOwner = zapp_worker_owners[key];
|
|
133
|
+
if (![existingOwner isEqualToString:ownerId]) continue;
|
|
134
|
+
NSString* scriptUrl = zapp_worker_script_urls[key];
|
|
135
|
+
NSNumber* sharedFlag = zapp_worker_shared_flags[key];
|
|
136
|
+
BOOL isShared = (sharedFlag != nil && [sharedFlag boolValue]);
|
|
137
|
+
JSContext* ctx = zapp_worker_contexts[key];
|
|
138
|
+
|
|
139
|
+
[zapp_worker_contexts removeObjectForKey:key];
|
|
140
|
+
[zapp_worker_owners removeObjectForKey:key];
|
|
141
|
+
[zapp_worker_script_urls removeObjectForKey:key];
|
|
142
|
+
[zapp_worker_shared_flags removeObjectForKey:key];
|
|
143
|
+
|
|
144
|
+
zapp_darwin_worker_timers_cancel(key);
|
|
145
|
+
zapp_darwin_worker_fetch_cancel(key);
|
|
146
|
+
|
|
147
|
+
if (ctx == nil) continue;
|
|
148
|
+
|
|
149
|
+
if (isShared && scriptUrl != nil) {
|
|
150
|
+
zapp_call_bridge_method_unsafe(ctx, @"dispatchDisconnect", @[key]);
|
|
151
|
+
NSNumber* rc = zapp_shared_worker_refcounts[scriptUrl];
|
|
152
|
+
NSInteger next = (rc != nil ? [rc integerValue] : 1) - 1;
|
|
153
|
+
if (next > 0) {
|
|
154
|
+
[zapp_shared_worker_refcounts setObject:@(next) forKey:scriptUrl];
|
|
155
|
+
} else {
|
|
156
|
+
[zapp_shared_worker_refcounts removeObjectForKey:scriptUrl];
|
|
157
|
+
[zapp_shared_worker_contexts removeObjectForKey:scriptUrl];
|
|
158
|
+
zapp_teardown_jscontext(ctx, [NSString stringWithFormat:@"DeadSharedWorker:%@", key]);
|
|
159
|
+
}
|
|
160
|
+
} else {
|
|
161
|
+
zapp_teardown_jscontext(ctx, [NSString stringWithFormat:@"DeadWorker:%@", key]);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
void zapp_darwin_reset_owner_workers(const char* owner_id) {
|
|
168
|
+
if (owner_id == NULL) return;
|
|
169
|
+
NSString* ownerId = [NSString stringWithUTF8String:owner_id];
|
|
170
|
+
if (![ownerId isKindOfClass:[NSString class]] || [ownerId length] == 0) return;
|
|
171
|
+
zapp_reset_owner_workers_internal(ownerId);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
void zapp_darwin_reset_all_workers(void) {
|
|
175
|
+
zapp_darwin_worker_js_sync(^{
|
|
176
|
+
if (zapp_worker_contexts == nil) return;
|
|
177
|
+
|
|
178
|
+
NSArray<NSString*>* workerIds = [zapp_worker_contexts allKeys];
|
|
179
|
+
NSMutableSet<JSContext*>* seen = [NSMutableSet set];
|
|
180
|
+
|
|
181
|
+
for (NSString* workerId in workerIds) {
|
|
182
|
+
JSContext* ctx = zapp_worker_contexts[workerId];
|
|
183
|
+
zapp_darwin_worker_timers_cancel(workerId);
|
|
184
|
+
zapp_darwin_worker_fetch_cancel(workerId);
|
|
185
|
+
if (ctx == nil || [seen containsObject:ctx]) continue;
|
|
186
|
+
[seen addObject:ctx];
|
|
187
|
+
zapp_teardown_jscontext(ctx, [NSString stringWithFormat:@"DeadWorker:%@", workerId]);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
[zapp_worker_contexts removeAllObjects];
|
|
191
|
+
[zapp_worker_owners removeAllObjects];
|
|
192
|
+
[zapp_worker_script_urls removeAllObjects];
|
|
193
|
+
[zapp_worker_shared_flags removeAllObjects];
|
|
194
|
+
[zapp_shared_worker_contexts removeAllObjects];
|
|
195
|
+
[zapp_shared_worker_refcounts removeAllObjects];
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
extern void zapp_dispatch_worker_to_webviews(const char* kind, const char* worker_id, const char* payload_json);
|
|
200
|
+
extern NSString* zapp_json_stringify_obj(id obj);
|
|
201
|
+
|
|
202
|
+
static void zapp_worker_dispatch_error_string(NSString* workerId, NSString* message) {
|
|
203
|
+
if (workerId == nil || [workerId length] == 0) return;
|
|
204
|
+
if (message == nil || [message length] == 0) message = @"Worker error";
|
|
205
|
+
|
|
206
|
+
int window_id = -1, worker_seq_id = -1;
|
|
207
|
+
zapp_worker_lookup([workerId UTF8String], &window_id, &worker_seq_id);
|
|
208
|
+
|
|
209
|
+
zapp_log_worker(ZAPP_LOG_ERROR, window_id, worker_seq_id, [message UTF8String]);
|
|
210
|
+
|
|
211
|
+
NSDictionary* payload = @{@"message": message};
|
|
212
|
+
NSString* errJson = zapp_json_stringify_obj(payload);
|
|
213
|
+
zapp_dispatch_worker_to_webviews("error", [workerId UTF8String], [errJson UTF8String]);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
static NSString* zapp_jsc_exception_message(JSValue* exception) {
|
|
217
|
+
if (exception == nil || exception.isUndefined || exception.isNull) return @"Worker error";
|
|
218
|
+
@try {
|
|
219
|
+
return [exception toString] ?: @"Worker error";
|
|
220
|
+
} @catch (NSException* e) {
|
|
221
|
+
return @"Worker error";
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
static NSString* zapp_sync_payload_with_target(id reqObj, NSString* targetWorkerId) {
|
|
226
|
+
NSMutableDictionary* payload = [NSMutableDictionary dictionary];
|
|
227
|
+
if ([reqObj isKindOfClass:[NSDictionary class]]) {
|
|
228
|
+
[payload addEntriesFromDictionary:(NSDictionary*)reqObj];
|
|
229
|
+
}
|
|
230
|
+
if ([targetWorkerId isKindOfClass:[NSString class]] && [targetWorkerId length] > 0) {
|
|
231
|
+
[payload setObject:targetWorkerId forKey:@"targetWorkerId"];
|
|
232
|
+
}
|
|
233
|
+
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:nil];
|
|
234
|
+
NSString* json = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
|
|
235
|
+
return json ?: @"{}";
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
extern void zapp_backend_deliver_event(const char* name, const char* payload);
|
|
239
|
+
|
|
240
|
+
static void zapp_darwin_send_event_to_js(void* app_ptr, char* name, char* payload) {
|
|
241
|
+
(void)app_ptr;
|
|
242
|
+
if (name == NULL) return;
|
|
243
|
+
if (payload == NULL) payload = "{}";
|
|
244
|
+
|
|
245
|
+
NSString* n = [NSString stringWithUTF8String:name];
|
|
246
|
+
NSString* p = [NSString stringWithUTF8String:payload];
|
|
247
|
+
NSString* nEsc = [n stringByReplacingOccurrencesOfString:@"\\" withString:@"\\\\"];
|
|
248
|
+
nEsc = [nEsc stringByReplacingOccurrencesOfString:@"'" withString:@"\\'"];
|
|
249
|
+
NSString* pEsc = [p stringByReplacingOccurrencesOfString:@"\\" withString:@"\\\\"];
|
|
250
|
+
pEsc = [pEsc stringByReplacingOccurrencesOfString:@"'" withString:@"\\'"];
|
|
251
|
+
|
|
252
|
+
void (^work)(void) = ^{
|
|
253
|
+
NSString* js = [NSString stringWithFormat:
|
|
254
|
+
@"(function(){var b=globalThis[Symbol.for('zapp.bridge')];if(b&&typeof b.deliverEvent==='function'){b.deliverEvent('%@','%@');}})();",
|
|
255
|
+
nEsc, pEsc
|
|
256
|
+
];
|
|
257
|
+
|
|
258
|
+
for (NSWindow* window in [NSApp windows]) {
|
|
259
|
+
NSView* content = [window contentView];
|
|
260
|
+
if ([content isKindOfClass:[WKWebView class]]) {
|
|
261
|
+
WKWebView* webview = (WKWebView*)content;
|
|
262
|
+
[webview evaluateJavaScript:js completionHandler:nil];
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
zapp_darwin_worker_js_sync(^{
|
|
267
|
+
if (zapp_worker_contexts == nil) return;
|
|
268
|
+
NSMutableSet<JSContext*>* seen = [NSMutableSet set];
|
|
269
|
+
for (NSString* workerId in zapp_worker_contexts) {
|
|
270
|
+
JSContext* wCtx = zapp_worker_contexts[workerId];
|
|
271
|
+
if (wCtx == nil || [seen containsObject:wCtx]) continue;
|
|
272
|
+
[seen addObject:wCtx];
|
|
273
|
+
zapp_call_bridge_method_unsafe(wCtx, @"deliverEvent", @[n, p]);
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
if ([NSThread isMainThread]) {
|
|
279
|
+
work();
|
|
280
|
+
} else {
|
|
281
|
+
dispatch_async(dispatch_get_main_queue(), work);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// Also deliver to backend context
|
|
285
|
+
zapp_backend_deliver_event(name, payload);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
void zapp_darwin_worker_dispatch_sync_result(const char* worker_id, const char* payload_json) {
|
|
289
|
+
if (worker_id == NULL || payload_json == NULL) return;
|
|
290
|
+
NSString* workerId = [NSString stringWithUTF8String:worker_id];
|
|
291
|
+
NSString* payload = [NSString stringWithUTF8String:payload_json];
|
|
292
|
+
if (![workerId isKindOfClass:[NSString class]] || [workerId length] == 0) return;
|
|
293
|
+
if (![payload isKindOfClass:[NSString class]]) return;
|
|
294
|
+
|
|
295
|
+
zapp_darwin_worker_js_sync(^{
|
|
296
|
+
if (zapp_worker_contexts == nil) return;
|
|
297
|
+
JSContext* ctx = zapp_worker_contexts[workerId];
|
|
298
|
+
if (ctx == nil) return;
|
|
299
|
+
zapp_call_bridge_method_unsafe(ctx, @"dispatchSyncResult", @[payload]);
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
#endif /* __APPLE__ */
|
|
303
|
+
#endif
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
struct DarwinWorkerJsc {}
|
|
307
|
+
|
|
308
|
+
@unused
|
|
309
|
+
impl WorkerBackend for DarwinWorkerJsc {
|
|
310
|
+
fn handle_bridge(self, app: App*, action: string, payload: string) -> void {
|
|
311
|
+
raw {
|
|
312
|
+
#if !defined(ZAPP_WORKER_ENGINE_QJS)
|
|
313
|
+
#ifdef __APPLE__
|
|
314
|
+
if (action == NULL || payload == NULL) return;
|
|
315
|
+
|
|
316
|
+
NSDictionary* body = zapp_worker_parse_bridge_payload((const char*)payload);
|
|
317
|
+
if (body == nil) return;
|
|
318
|
+
|
|
319
|
+
NSString* actionStr = [NSString stringWithUTF8String:(const char*)action];
|
|
320
|
+
if (!actionStr) return;
|
|
321
|
+
|
|
322
|
+
zapp_ensure_worker_state();
|
|
323
|
+
|
|
324
|
+
NSString* ownerId = zapp_worker_body_owner_id(body);
|
|
325
|
+
BOOL shared = zapp_worker_body_shared(body);
|
|
326
|
+
|
|
327
|
+
if ([actionStr isEqualToString:@"reset_owner"]) {
|
|
328
|
+
if (ownerId == nil) return;
|
|
329
|
+
zapp_reset_owner_workers_internal(ownerId);
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
NSString* workerId = zapp_worker_body_worker_id(body);
|
|
334
|
+
if (workerId == nil) return;
|
|
335
|
+
|
|
336
|
+
if ([actionStr isEqualToString:@"create"]) {
|
|
337
|
+
NSString* scriptUrl = zapp_worker_body_script_url(body);
|
|
338
|
+
if (scriptUrl == nil) return;
|
|
339
|
+
|
|
340
|
+
NSError* readErr = nil;
|
|
341
|
+
NSString* source = zapp_worker_read_source(scriptUrl, &readErr);
|
|
342
|
+
if (!source || readErr) {
|
|
343
|
+
zapp_worker_dispatch_error_message(workerId, @"Failed to load worker script");
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
__block BOOL exceeded = NO;
|
|
348
|
+
|
|
349
|
+
zapp_darwin_worker_js_sync(^{
|
|
350
|
+
int maxWorkers = app->config.maxWorkers;
|
|
351
|
+
if (shared) {
|
|
352
|
+
JSContext* existingCtx = zapp_shared_worker_contexts[scriptUrl];
|
|
353
|
+
if (existingCtx != nil) {
|
|
354
|
+
NSNumber* rc = zapp_shared_worker_refcounts[scriptUrl];
|
|
355
|
+
NSInteger next = (rc != nil ? [rc integerValue] : 0) + 1;
|
|
356
|
+
[zapp_shared_worker_refcounts setObject:@(next) forKey:scriptUrl];
|
|
357
|
+
[zapp_worker_contexts setObject:existingCtx forKey:workerId];
|
|
358
|
+
[zapp_worker_script_urls setObject:scriptUrl forKey:workerId];
|
|
359
|
+
[zapp_worker_shared_flags setObject:@(YES) forKey:workerId];
|
|
360
|
+
if (ownerId != nil) {
|
|
361
|
+
[zapp_worker_owners setObject:ownerId forKey:workerId];
|
|
362
|
+
}
|
|
363
|
+
zapp_call_bridge_method_unsafe(existingCtx, @"dispatchConnect", @[workerId]);
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
if (maxWorkers > 0 && zapp_worker_active_context_count() >= (NSUInteger)maxWorkers) {
|
|
369
|
+
exceeded = YES;
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
NSString* ctxName = [NSString stringWithFormat:@"ZappWorker:%@", workerId];
|
|
374
|
+
void* opaque = engine_jsc_create_ctx((__bridge void*)zapp_worker_vm, [ctxName UTF8String]);
|
|
375
|
+
if (!opaque) {
|
|
376
|
+
zapp_worker_dispatch_error_message(workerId, @"Failed to create context");
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
JSContext* ctx = (__bridge JSContext*)opaque;
|
|
381
|
+
if (@available(macOS 13.3, *)) {
|
|
382
|
+
ctx.inspectable = app->window.webContentInspectable ? YES : NO;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
__weak JSContext* weakCtx = ctx;
|
|
386
|
+
ctx.exceptionHandler = ^(JSContext* context, JSValue* exception) {
|
|
387
|
+
void (^previousHandler)(JSContext *ctx, JSValue *exc) = context.exceptionHandler;
|
|
388
|
+
context.exceptionHandler = nil;
|
|
389
|
+
context.exception = nil;
|
|
390
|
+
NSString* dispatchId = [weakCtx[@"__zappWorkerDispatchId"] toString];
|
|
391
|
+
if (![dispatchId isKindOfClass:[NSString class]] || [dispatchId length] == 0) {
|
|
392
|
+
dispatchId = workerId;
|
|
393
|
+
}
|
|
394
|
+
zapp_worker_dispatch_error_string(dispatchId, zapp_jsc_exception_message(exception));
|
|
395
|
+
context.exceptionHandler = previousHandler;
|
|
396
|
+
};
|
|
397
|
+
|
|
398
|
+
ctx[@"globalThis"] = ctx.globalObject;
|
|
399
|
+
ctx[@"self"] = ctx.globalObject;
|
|
400
|
+
ctx[@"__zappWorkerDispatchId"] = workerId;
|
|
401
|
+
zapp_worker_register([workerId UTF8String]);
|
|
402
|
+
|
|
403
|
+
JSValue* bridge = [JSValue valueWithNewObjectInContext:ctx];
|
|
404
|
+
ctx[@"__zappBridge"] = bridge;
|
|
405
|
+
|
|
406
|
+
bridge[@"consoleLog"] = ^(JSValue* levelVal, JSValue* msgVal) {
|
|
407
|
+
NSString* level = [levelVal toString] ?: @"log";
|
|
408
|
+
NSString* msg = [msgVal toString] ?: @"";
|
|
409
|
+
|
|
410
|
+
int window_id = -1;
|
|
411
|
+
int worker_seq_id = -1;
|
|
412
|
+
zapp_worker_lookup([workerId UTF8String], &window_id, &worker_seq_id);
|
|
413
|
+
|
|
414
|
+
// Convert level string to int
|
|
415
|
+
int level_int = ZAPP_LOG_INFO;
|
|
416
|
+
if ([level isEqualToString:@"error"]) level_int = ZAPP_LOG_ERROR;
|
|
417
|
+
else if ([level isEqualToString:@"warn"]) level_int = ZAPP_LOG_WARN;
|
|
418
|
+
else if ([level isEqualToString:@"debug"]) level_int = ZAPP_LOG_DEBUG;
|
|
419
|
+
else if ([level isEqualToString:@"trace"]) level_int = ZAPP_LOG_TRACE;
|
|
420
|
+
|
|
421
|
+
zapp_log_worker(level_int, window_id, worker_seq_id, [msg UTF8String]);
|
|
422
|
+
};
|
|
423
|
+
|
|
424
|
+
zapp_darwin_worker_timers_init(ctx, workerId);
|
|
425
|
+
zapp_darwin_worker_fetch_init(ctx, workerId);
|
|
426
|
+
zapp_darwin_worker_crypto_init(ctx);
|
|
427
|
+
zapp_darwin_worker_encoding_init(ctx);
|
|
428
|
+
zapp_darwin_worker_url_init(ctx);
|
|
429
|
+
zapp_darwin_worker_base64_init(ctx);
|
|
430
|
+
zapp_darwin_worker_websocket_init(ctx);
|
|
431
|
+
|
|
432
|
+
bridge[@"emitToHost"] = ^(JSValue* nameVal, JSValue* payloadVal) {
|
|
433
|
+
NSString* eventName = [nameVal toString];
|
|
434
|
+
if (![eventName isKindOfClass:[NSString class]] || [eventName length] == 0) return;
|
|
435
|
+
id payloadObj = [payloadVal toObject];
|
|
436
|
+
NSString* payloadJson = zapp_json_stringify_obj(payloadObj);
|
|
437
|
+
if (payloadJson == nil) payloadJson = @"{}";
|
|
438
|
+
zapp_darwin_send_event_to_js((void*)app, (char*)[eventName UTF8String], (char*)[payloadJson UTF8String]);
|
|
439
|
+
};
|
|
440
|
+
|
|
441
|
+
bridge[@"invokeToHost"] = ^(JSValue* methodVal, JSValue* payloadVal) {
|
|
442
|
+
NSString* methodName = [methodVal toString];
|
|
443
|
+
if (![methodName isKindOfClass:[NSString class]] || [methodName length] == 0) return;
|
|
444
|
+
id payloadObj = [payloadVal toObject];
|
|
445
|
+
NSString* payloadJson = zapp_json_stringify_obj(payloadObj);
|
|
446
|
+
if (payloadJson == nil) payloadJson = @"{}";
|
|
447
|
+
NSString* wire = [NSString stringWithFormat:@"invoke\n%@\n%@", methodName, payloadJson];
|
|
448
|
+
zapp_handle_message((void*)app, (char*)[wire UTF8String]);
|
|
449
|
+
};
|
|
450
|
+
|
|
451
|
+
bridge[@"reportError"] = ^(JSValue* errVal) {
|
|
452
|
+
NSString* dispatchId = [weakCtx[@"__zappWorkerDispatchId"] toString];
|
|
453
|
+
if (![dispatchId isKindOfClass:[NSString class]] || [dispatchId length] == 0) {
|
|
454
|
+
dispatchId = workerId;
|
|
455
|
+
}
|
|
456
|
+
NSString* msg = @"Worker runtime error";
|
|
457
|
+
if (errVal != nil && !errVal.isUndefined && !errVal.isNull) {
|
|
458
|
+
@try { msg = [errVal toString] ?: msg; } @catch (NSException* e) {}
|
|
459
|
+
}
|
|
460
|
+
zapp_worker_dispatch_error_string(dispatchId, msg);
|
|
461
|
+
};
|
|
462
|
+
|
|
463
|
+
bridge[@"postMessage"] = ^(JSValue* data, JSValue* optTargetId) {
|
|
464
|
+
id obj = [data toObject];
|
|
465
|
+
NSString* json = zapp_json_stringify_obj(obj);
|
|
466
|
+
NSString* dispatchId = nil;
|
|
467
|
+
if (optTargetId != nil && !optTargetId.isUndefined && !optTargetId.isNull) {
|
|
468
|
+
dispatchId = [optTargetId toString];
|
|
469
|
+
} else {
|
|
470
|
+
dispatchId = [weakCtx[@"__zappWorkerDispatchId"] toString];
|
|
471
|
+
if (![dispatchId isKindOfClass:[NSString class]] || [dispatchId length] == 0) {
|
|
472
|
+
dispatchId = workerId;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
zapp_dispatch_worker_to_webviews("message", [dispatchId UTF8String], [json UTF8String]);
|
|
476
|
+
};
|
|
477
|
+
|
|
478
|
+
bridge[@"closeWorker"] = ^() {
|
|
479
|
+
NSString* dispatchId = [weakCtx[@"__zappWorkerDispatchId"] toString];
|
|
480
|
+
if (![dispatchId isKindOfClass:[NSString class]] || [dispatchId length] == 0) {
|
|
481
|
+
dispatchId = workerId;
|
|
482
|
+
}
|
|
483
|
+
zapp_dispatch_worker_to_webviews("close", [dispatchId UTF8String], "{}");
|
|
484
|
+
};
|
|
485
|
+
|
|
486
|
+
bridge[@"syncWait"] = ^(JSValue* requestVal) {
|
|
487
|
+
id reqObj = [requestVal toObject];
|
|
488
|
+
NSString* dispatchId = [weakCtx[@"__zappWorkerDispatchId"] toString];
|
|
489
|
+
if (![dispatchId isKindOfClass:[NSString class]] || [dispatchId length] == 0) {
|
|
490
|
+
dispatchId = workerId;
|
|
491
|
+
}
|
|
492
|
+
NSString* payloadJson = zapp_sync_payload_with_target(reqObj, dispatchId);
|
|
493
|
+
NSString* wire = [NSString stringWithFormat:@"sync\nwait\n%@", payloadJson];
|
|
494
|
+
void* appPtr = app_get_active();
|
|
495
|
+
if (appPtr != NULL) {
|
|
496
|
+
zapp_handle_message(appPtr, (char*)[wire UTF8String]);
|
|
497
|
+
}
|
|
498
|
+
};
|
|
499
|
+
|
|
500
|
+
bridge[@"syncNotify"] = ^(JSValue* requestVal) {
|
|
501
|
+
id reqObj = [requestVal toObject];
|
|
502
|
+
NSString* dispatchId = [weakCtx[@"__zappWorkerDispatchId"] toString];
|
|
503
|
+
if (![dispatchId isKindOfClass:[NSString class]] || [dispatchId length] == 0) {
|
|
504
|
+
dispatchId = workerId;
|
|
505
|
+
}
|
|
506
|
+
NSString* payloadJson = zapp_sync_payload_with_target(reqObj, dispatchId);
|
|
507
|
+
NSString* wire = [NSString stringWithFormat:@"sync\nnotify\n%@", payloadJson];
|
|
508
|
+
void* appPtr = app_get_active();
|
|
509
|
+
if (appPtr != NULL) {
|
|
510
|
+
zapp_handle_message(appPtr, (char*)[wire UTF8String]);
|
|
511
|
+
}
|
|
512
|
+
};
|
|
513
|
+
|
|
514
|
+
bridge[@"syncCancel"] = ^(JSValue* requestVal) {
|
|
515
|
+
id reqObj = [requestVal toObject];
|
|
516
|
+
NSString* dispatchId = [weakCtx[@"__zappWorkerDispatchId"] toString];
|
|
517
|
+
if (![dispatchId isKindOfClass:[NSString class]] || [dispatchId length] == 0) {
|
|
518
|
+
dispatchId = workerId;
|
|
519
|
+
}
|
|
520
|
+
NSString* payloadJson = zapp_sync_payload_with_target(reqObj, dispatchId);
|
|
521
|
+
NSString* wire = [NSString stringWithFormat:@"sync\ncancel\n%@", payloadJson];
|
|
522
|
+
void* appPtr = app_get_active();
|
|
523
|
+
if (appPtr != NULL) {
|
|
524
|
+
zapp_handle_message(appPtr, (char*)[wire UTF8String]);
|
|
525
|
+
}
|
|
526
|
+
};
|
|
527
|
+
|
|
528
|
+
const char* bootstrap = zapp_darwin_worker_bootstrap_script();
|
|
529
|
+
size_t blen = strlen(bootstrap);
|
|
530
|
+
int err = engine_jsc_eval((__bridge void*)ctx, bootstrap, blen, "bootstrap.js");
|
|
531
|
+
if (err != 0) {
|
|
532
|
+
const char* msg = engine_jsc_get_exception_message((__bridge void*)ctx);
|
|
533
|
+
|
|
534
|
+
int window_id = -1, worker_seq_id = -1;
|
|
535
|
+
zapp_worker_lookup([workerId UTF8String], &window_id, &worker_seq_id);
|
|
536
|
+
char log_buf[256];
|
|
537
|
+
snprintf(log_buf, sizeof(log_buf), "bootstrap failed: %s", msg ?: "(no message)");
|
|
538
|
+
zapp_log_worker(ZAPP_LOG_ERROR, window_id, worker_seq_id, log_buf);
|
|
539
|
+
|
|
540
|
+
NSString* errMsg = msg ? [NSString stringWithFormat:@"{\"message\":\"Bootstrap failed: %s\"}", msg] : @"{\"message\":\"Bootstrap failed\"}";
|
|
541
|
+
zapp_dispatch_worker_to_webviews("error", [workerId UTF8String], [errMsg UTF8String]);
|
|
542
|
+
zapp_darwin_worker_timers_cancel(workerId);
|
|
543
|
+
zapp_darwin_worker_fetch_cancel(workerId);
|
|
544
|
+
zapp_teardown_jscontext(ctx, [NSString stringWithFormat:@"DeadWorker:%@", workerId]);
|
|
545
|
+
return;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
NSString* wrappedSource = [NSString stringWithFormat:
|
|
549
|
+
@"(async function(){\n%@\n})()"
|
|
550
|
+
@".catch(function(e){"
|
|
551
|
+
@"var b=globalThis[Symbol.for('zapp.bridge')];"
|
|
552
|
+
@"if(b&&b.reportError)b.reportError(e);"
|
|
553
|
+
@"else if(typeof console!=='undefined')console.error('[worker] unhandled:',e);"
|
|
554
|
+
@"});", source];
|
|
555
|
+
NSData* wrappedData = [wrappedSource dataUsingEncoding:NSUTF8StringEncoding];
|
|
556
|
+
if (wrappedData == nil || [wrappedData length] == 0) {
|
|
557
|
+
zapp_worker_dispatch_error_message(workerId, @"Script encoding failed");
|
|
558
|
+
zapp_darwin_worker_timers_cancel(workerId);
|
|
559
|
+
zapp_darwin_worker_fetch_cancel(workerId);
|
|
560
|
+
zapp_teardown_jscontext(ctx, [NSString stringWithFormat:@"DeadWorker:%@", workerId]);
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
563
|
+
const char* wrappedUtf8 = (const char*)[wrappedData bytes];
|
|
564
|
+
size_t wrappedLen = [wrappedData length];
|
|
565
|
+
err = engine_jsc_eval((__bridge void*)ctx, wrappedUtf8, wrappedLen, scriptUrl ? [scriptUrl UTF8String] : NULL);
|
|
566
|
+
if (err != 0) {
|
|
567
|
+
const char* msg = engine_jsc_get_exception_message((__bridge void*)ctx);
|
|
568
|
+
|
|
569
|
+
int window_id = -1, worker_seq_id = -1;
|
|
570
|
+
zapp_worker_lookup([workerId UTF8String], &window_id, &worker_seq_id);
|
|
571
|
+
char log_buf[256];
|
|
572
|
+
snprintf(log_buf, sizeof(log_buf), "script eval failed: %s", msg ?: "(no message)");
|
|
573
|
+
zapp_log_worker(ZAPP_LOG_ERROR, window_id, worker_seq_id, log_buf);
|
|
574
|
+
|
|
575
|
+
NSString* errMsg = msg ? [NSString stringWithFormat:@"{\"message\":\"%@\"}", [NSString stringWithUTF8String:msg]] : @"{\"message\":\"Script error\"}";
|
|
576
|
+
zapp_dispatch_worker_to_webviews("error", [workerId UTF8String], [errMsg UTF8String]);
|
|
577
|
+
zapp_darwin_worker_timers_cancel(workerId);
|
|
578
|
+
zapp_darwin_worker_fetch_cancel(workerId);
|
|
579
|
+
zapp_teardown_jscontext(ctx, [NSString stringWithFormat:@"DeadWorker:%@", workerId]);
|
|
580
|
+
return;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
[zapp_worker_contexts setObject:ctx forKey:workerId];
|
|
584
|
+
[zapp_worker_script_urls setObject:scriptUrl forKey:workerId];
|
|
585
|
+
[zapp_worker_shared_flags setObject:@(shared) forKey:workerId];
|
|
586
|
+
if (ownerId != nil) {
|
|
587
|
+
[zapp_worker_owners setObject:ownerId forKey:workerId];
|
|
588
|
+
}
|
|
589
|
+
if (shared) {
|
|
590
|
+
[zapp_shared_worker_contexts setObject:ctx forKey:scriptUrl];
|
|
591
|
+
[zapp_shared_worker_refcounts setObject:@(1) forKey:scriptUrl];
|
|
592
|
+
zapp_call_bridge_method_unsafe(ctx, @"dispatchConnect", @[workerId]);
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
});
|
|
596
|
+
|
|
597
|
+
if (exceeded) {
|
|
598
|
+
zapp_worker_dispatch_max_workers_error(workerId, app->config.maxWorkers);
|
|
599
|
+
}
|
|
600
|
+
return;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
if ([actionStr isEqualToString:@"post"]) {
|
|
604
|
+
id dataObj = body[@"data"];
|
|
605
|
+
zapp_darwin_worker_js_sync(^{
|
|
606
|
+
JSContext* ctx = zapp_worker_contexts[workerId];
|
|
607
|
+
if (!ctx) return;
|
|
608
|
+
if (ownerId != nil) {
|
|
609
|
+
NSString* existingOwner = zapp_worker_owners[workerId];
|
|
610
|
+
if (existingOwner != nil && ![existingOwner isEqualToString:ownerId]) return;
|
|
611
|
+
}
|
|
612
|
+
zapp_call_bridge_method_unsafe(ctx, @"dispatchMessage", @[dataObj ?: [NSNull null], workerId]);
|
|
613
|
+
});
|
|
614
|
+
return;
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
if ([actionStr isEqualToString:@"terminate"]) {
|
|
618
|
+
zapp_darwin_worker_js_sync(^{
|
|
619
|
+
if (ownerId != nil) {
|
|
620
|
+
NSString* existingOwner = zapp_worker_owners[workerId];
|
|
621
|
+
if (existingOwner != nil && ![existingOwner isEqualToString:ownerId]) return;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
NSString* scriptUrl = zapp_worker_script_urls[workerId];
|
|
625
|
+
NSNumber* sharedFlag = zapp_worker_shared_flags[workerId];
|
|
626
|
+
BOOL isShared = (sharedFlag != nil && [sharedFlag boolValue]);
|
|
627
|
+
JSContext* ctx = zapp_worker_contexts[workerId];
|
|
628
|
+
|
|
629
|
+
[zapp_worker_contexts removeObjectForKey:workerId];
|
|
630
|
+
zapp_darwin_worker_timers_cancel(workerId);
|
|
631
|
+
zapp_darwin_worker_fetch_cancel(workerId);
|
|
632
|
+
[zapp_worker_owners removeObjectForKey:workerId];
|
|
633
|
+
[zapp_worker_script_urls removeObjectForKey:workerId];
|
|
634
|
+
[zapp_worker_shared_flags removeObjectForKey:workerId];
|
|
635
|
+
|
|
636
|
+
if (ctx == nil) return;
|
|
637
|
+
|
|
638
|
+
if (isShared && scriptUrl != nil) {
|
|
639
|
+
zapp_call_bridge_method_unsafe(ctx, @"dispatchDisconnect", @[workerId]);
|
|
640
|
+
|
|
641
|
+
NSNumber* rc = zapp_shared_worker_refcounts[scriptUrl];
|
|
642
|
+
NSInteger next = (rc != nil ? [rc integerValue] : 1) - 1;
|
|
643
|
+
if (next > 0) {
|
|
644
|
+
[zapp_shared_worker_refcounts setObject:@(next) forKey:scriptUrl];
|
|
645
|
+
} else {
|
|
646
|
+
[zapp_shared_worker_refcounts removeObjectForKey:scriptUrl];
|
|
647
|
+
[zapp_shared_worker_contexts removeObjectForKey:scriptUrl];
|
|
648
|
+
zapp_teardown_jscontext(ctx, [NSString stringWithFormat:@"DeadSharedWorker:%@", workerId]);
|
|
649
|
+
}
|
|
650
|
+
} else {
|
|
651
|
+
zapp_teardown_jscontext(ctx, [NSString stringWithFormat:@"DeadWorker:%@", workerId]);
|
|
652
|
+
}
|
|
653
|
+
});
|
|
654
|
+
return;
|
|
655
|
+
}
|
|
656
|
+
#endif /* __APPLE__ */
|
|
657
|
+
#endif
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
fn bind_runtime(self, app: App*) -> void {
|
|
662
|
+
raw {
|
|
663
|
+
#if !defined(ZAPP_WORKER_ENGINE_QJS)
|
|
664
|
+
#ifdef __APPLE__
|
|
665
|
+
app->event.send_event_to_js = (void*)zapp_darwin_send_event_to_js;
|
|
666
|
+
#endif /* __APPLE__ */
|
|
667
|
+
#endif
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
}
|