cj-tauri 2.0.0 → 2.1.1
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 +206 -139
- package/bin/cj-tauri.js +287 -287
- package/cjpm.toml +63 -52
- package/cli/cjpm.toml +22 -22
- package/cli/src/doctor.cj +308 -306
- package/cli/src/main.cj +129 -129
- package/cli/src/manifest.cj +643 -558
- package/cli/src/manifest_test.cj +87 -0
- package/cli/src/project.cj +770 -770
- package/cli/src/resolve.cj +348 -348
- package/cli/src/scaffold.cj +369 -369
- package/cli/src/sync.cj +638 -526
- package/cli/src/util.cj +168 -168
- package/cli/templates/app/README.md +51 -48
- package/cli/templates/app/assets/capabilities/default.json +7 -7
- package/cli/templates/app/assets/ui/index.html +120 -118
- package/cli/templates/app/cj-tauri.toml +32 -22
- package/cli/templates/app/cjpm.toml +34 -34
- package/cli/templates/app/src/main.cj +101 -90
- package/cli/templates/app-react/README.md +56 -56
- package/cli/templates/app-react/assets/capabilities/default.json +7 -7
- package/cli/templates/app-react/assets/ui/index.html +25 -25
- package/cli/templates/app-react/assets/ui/package.json +19 -19
- package/cli/templates/app-react/assets/ui/src/App.css +67 -67
- package/cli/templates/app-react/assets/ui/src/App.jsx +124 -124
- package/cli/templates/app-react/assets/ui/src/main.jsx +6 -6
- package/cli/templates/app-react/assets/ui/vite.config.js +24 -24
- package/cli/templates/app-react/cj-tauri.toml +33 -23
- package/cli/templates/app-react/cjpm.toml +34 -34
- package/cli/templates/app-react/src/main.cj +91 -91
- package/cli/templates/app-vue/README.md +56 -56
- package/cli/templates/app-vue/assets/capabilities/default.json +7 -7
- package/cli/templates/app-vue/assets/ui/index.html +25 -25
- package/cli/templates/app-vue/assets/ui/package.json +18 -18
- package/cli/templates/app-vue/assets/ui/src/App.vue +176 -176
- package/cli/templates/app-vue/assets/ui/src/main.js +4 -4
- package/cli/templates/app-vue/assets/ui/vite.config.js +24 -24
- package/cli/templates/app-vue/cj-tauri.toml +33 -23
- package/cli/templates/app-vue/cjpm.toml +34 -34
- package/cli/templates/app-vue/src/main.cj +91 -91
- package/cli/templates/ohos-skeleton/AppScope/app.json5 +13 -13
- package/cli/templates/ohos-skeleton/AppScope/resources/base/element/string.json +8 -8
- package/cli/templates/ohos-skeleton/AppScope/resources/base/media/layered_image.json +6 -6
- package/cli/templates/ohos-skeleton/README.md +84 -79
- package/cli/templates/ohos-skeleton/build-hap.sh +15 -0
- package/cli/templates/ohos-skeleton/build-profile.json5 +46 -46
- package/cli/templates/ohos-skeleton/entry/build-profile.json5 +26 -26
- package/cli/templates/ohos-skeleton/entry/cjpm.toml +51 -43
- package/cli/templates/ohos-skeleton/entry/hvigorfile.ts +6 -6
- package/cli/templates/ohos-skeleton/entry/oh-package.json5 +9 -9
- package/cli/templates/ohos-skeleton/entry/src/main/cangjie/ability_stage.cj +17 -17
- package/cli/templates/ohos-skeleton/entry/src/main/cangjie/app_host.cj +94 -94
- package/cli/templates/ohos-skeleton/entry/src/main/cangjie/dialog_host.cj +217 -0
- package/cli/templates/ohos-skeleton/entry/src/main/cangjie/index.cj +527 -167
- package/cli/templates/ohos-skeleton/entry/src/main/cangjie/main_ability.cj +139 -139
- package/cli/templates/ohos-skeleton/entry/src/main/module.json5 +57 -49
- package/cli/templates/ohos-skeleton/entry/src/main/resources/base/element/color.json +8 -8
- package/cli/templates/ohos-skeleton/entry/src/main/resources/base/element/string.json +16 -16
- package/cli/templates/ohos-skeleton/entry/src/main/resources/base/media/layered_image.json +6 -6
- package/cli/templates/ohos-skeleton/entry/src/main/resources/base/profile/main_pages.json +2 -2
- package/cli/templates/ohos-skeleton/entry/src/main/resources/rawfile/capabilities.json +6 -6
- package/cli/templates/ohos-skeleton/entry/src/main/resources/rawfile/index.html +92 -92
- package/cli/templates/ohos-skeleton/hvigor/hvigor-config.json5 +5 -5
- package/cli/templates/ohos-skeleton/hvigorfile.ts +6 -6
- package/cli/templates/ohos-skeleton/oh-package.json5 +10 -10
- package/native/build_win.bat +62 -62
- package/native/core/bridge_core.c +1681 -1626
- package/native/core/bridge_core.h +675 -618
- package/native/core/bridge_js.h +108 -108
- package/native/platforms/harmonyos/README.md +115 -6
- package/native/platforms/linux/bridge_linux.c +2787 -2485
- package/native/platforms/windows/bridge_win.c +3745 -3248
- package/native/tests/gtk_threading_probe.c +143 -143
- package/native/tests/test_bridge_core.c +1339 -1228
- package/package.json +53 -53
- package/src/api_system.cj +67 -67
- package/src/app.cj +335 -969
- package/src/app_events.cj +166 -0
- package/src/app_host_ops.cj +287 -0
- package/src/app_run.cj +283 -0
- package/src/app_spec.cj +76 -76
- package/src/arkweb_menu.cj +216 -0
- package/src/arkweb_script.cj +142 -142
- package/src/capability.cj +409 -409
- package/src/clipboard_bridge.cj +178 -0
- package/src/dialog_spec.cj +79 -0
- package/src/dragdrop.cj +26 -26
- package/src/embedded_assets.cj +98 -98
- package/src/host.cj +752 -607
- package/src/host_arkweb.cj +924 -778
- package/src/host_webkit.cj +663 -570
- package/src/host_webview2.cj +663 -570
- package/src/hotkey.cj +66 -66
- package/src/ipc_hub.cj +401 -337
- package/src/ipc_message.cj +286 -286
- package/src/launch.cj +62 -62
- package/src/logging.cj +127 -127
- package/src/menu.cj +197 -197
- package/src/platform/platform_app_context.cj +77 -77
- package/src/platform/platform_assets.cj +33 -33
- package/src/platform/platform_discover.cj +176 -176
- package/src/platform/platform_env.cj +29 -29
- package/src/platform/platform_feature.cj +31 -31
- package/src/platform/platform_page_source.cj +87 -87
- package/src/platform/platform_target_info.cj +32 -32
- package/src/platform_host_provider.cj +87 -87
- package/src/plugin.cj +333 -333
- package/src/plugins/clipboard/plugin_clipboard.cj +152 -152
- package/src/plugins/dialog/plugin_dialog.cj +209 -209
- package/src/plugins/fs/plugin_fs.cj +105 -1
- package/src/plugins/http/http_backend.cj +131 -0
- package/src/plugins/http/http_desktop.cj +195 -0
- package/src/plugins/http/http_ohos.cj +204 -0
- package/src/plugins/http/plugin_http.cj +310 -459
- package/src/plugins/log/plugin_log.cj +105 -105
- package/src/plugins/menu/plugin_menu.cj +158 -158
- package/src/plugins/notification/plugin_notification.cj +154 -154
- package/src/plugins/serial/plugin_serial.cj +458 -454
- package/src/plugins/serial/serial_bridge.cj +194 -194
- package/src/plugins/serial/serial_manager_ohos.cj +92 -0
- package/src/plugins/serial/serial_ohos.cj +529 -0
- package/src/plugins/shell/plugin_shell.cj +258 -258
- package/src/plugins/sqlite/plugin_sqlite.cj +705 -710
- package/src/plugins/sqlite/sqlite_ffi.cj +206 -211
- package/src/plugins/ws/plugin_ws.cj +488 -470
- package/src/process_hidden.cj +174 -174
- package/src/scope.cj +391 -391
- package/src/shell_event.cj +69 -69
- package/src/tests/app_spec_test.cj +130 -127
- package/src/tests/capability_test.cj +243 -243
- package/src/tests/dialog_spec_test.cj +73 -0
- package/src/tests/fake_host.cj +201 -201
- package/src/tests/ipc_hub_test.cj +563 -487
- package/src/tests/logging_test.cj +62 -62
- package/src/tests/platform_contract_test.cj +264 -251
- package/src/tests/plugin_clipboard_test.cj +222 -222
- package/src/tests/plugin_dialog_test.cj +237 -237
- package/src/tests/plugin_fs_test.cj +207 -0
- package/src/tests/plugin_http_test.cj +124 -124
- package/src/tests/plugin_notification_test.cj +205 -205
- package/src/tests/plugin_serial_test.cj +48 -0
- package/src/tests/plugin_test.cj +605 -585
- package/src/tests/plugin_ws_test.cj +40 -40
- package/src/tests/process_hidden_test.cj +129 -129
- package/src/tests/scope_test.cj +350 -350
- package/src/tests/system_host_test.cj +99 -81
- package/src/tests/urlutil_test.cj +53 -53
- package/src/tests/version_test.cj +75 -75
- package/src/tests/window_registry_test.cj +123 -123
- package/src/tray.cj +90 -90
- package/src/urlutil.cj +159 -159
- package/src/version.cj +44 -44
- package/src/window.cj +51 -51
- package/src/window_registry.cj +116 -116
- package/prebuilt/win32-x64/cj-tauri.exe +0 -0
- package/src/plugins/serial/serial_ohos_stub.cj +0 -61
- package/src/plugins/sqlite/sqlite_ohos_stub.cj +0 -91
package/src/shell_event.cj
CHANGED
|
@@ -1,69 +1,69 @@
|
|
|
1
|
-
package cjTauri
|
|
2
|
-
|
|
3
|
-
import stdx.encoding.json.*
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* shell 事件信封(C 桥 → 仓颉)的解析与语义映射:RFC-002 §5.5 / §5.6
|
|
7
|
-
*
|
|
8
|
-
* 信封形状(当前定稿,菜单):`{"kind":"menu","id":"file.save","enabled":true,"checked":false}`
|
|
9
|
-
* 托盘 / 拖放落地后各带自己的 kind(`tray` / `drop`),kind 决定投给前端哪个事件名。
|
|
10
|
-
*
|
|
11
|
-
* 为什么单独成文件:这里是**纯函数**(不进窗口、不碰线程),能脱离宿主在单测里直接验。
|
|
12
|
-
* 信封格式坏掉的表现是「事件静默不到」——没有纯函数边界时,只能靠实机点击去猜。
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
/** `kind` → 前端事件名;不认识的 kind 返回 None(调用方提示一句后丢弃,不抛异常) */
|
|
16
|
-
public func shellEventNameFor(kind: String): Option<String> {
|
|
17
|
-
match (kind) {
|
|
18
|
-
case "menu" => return Some("menu:click")
|
|
19
|
-
case "tray" => return Some("tray:click")
|
|
20
|
-
case "drop" => return Some("dragdrop:files")
|
|
21
|
-
case "hotkey" => return Some("hotkey:press")
|
|
22
|
-
case _ => return None
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* 解析信封成对象;不是合法 JSON 对象就返回 None
|
|
28
|
-
*
|
|
29
|
-
* 不抛异常:数据从 C 桥来(**不是**页面可控输入),格式坏了宁可丢一条事件 + 留一行日志,
|
|
30
|
-
* 也不要让异常穿到 FFI 边界——仓颉异常穿过 C 侧回调,进程状态就说不清了。
|
|
31
|
-
*/
|
|
32
|
-
public func parseShellEnvelope(json: String): Option<JsonObject> {
|
|
33
|
-
try {
|
|
34
|
-
let v = JsonValue.fromStr(json)
|
|
35
|
-
match (v.kind()) {
|
|
36
|
-
case JsonKind.JsObject => return Some(v.asObject())
|
|
37
|
-
case _ => return None
|
|
38
|
-
}
|
|
39
|
-
} catch (e: Exception) {
|
|
40
|
-
return None
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/** 取信封里的字符串字段(缺失 / 类型不对都给 None) */
|
|
45
|
-
public func shellString(obj: JsonObject, key: String): Option<String> {
|
|
46
|
-
match (obj.get(key)) {
|
|
47
|
-
case Some(v) => match (v.kind()) {
|
|
48
|
-
case JsonKind.JsString => return Some(v.asString().getValue())
|
|
49
|
-
case _ => return None
|
|
50
|
-
}
|
|
51
|
-
case None => return None
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* 取信封里的布尔字段(缺失 / 类型不对都给 None)
|
|
57
|
-
*
|
|
58
|
-
* 缺字段**不能**当 false 用:这两个值要回写到应用层菜单模型(见 `TauriApp` 的模型同步),
|
|
59
|
-
* 拿默认值顶等于把「用户刚点出来的勾选」按默认值改掉——宁可不写。
|
|
60
|
-
*/
|
|
61
|
-
public func shellBool(obj: JsonObject, key: String): Option<Bool> {
|
|
62
|
-
match (obj.get(key)) {
|
|
63
|
-
case Some(v) => match (v.kind()) {
|
|
64
|
-
case JsonKind.JsBool => return Some(v.asBool().getValue())
|
|
65
|
-
case _ => return None
|
|
66
|
-
}
|
|
67
|
-
case None => return None
|
|
68
|
-
}
|
|
69
|
-
}
|
|
1
|
+
package cjTauri
|
|
2
|
+
|
|
3
|
+
import stdx.encoding.json.*
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* shell 事件信封(C 桥 → 仓颉)的解析与语义映射:RFC-002 §5.5 / §5.6
|
|
7
|
+
*
|
|
8
|
+
* 信封形状(当前定稿,菜单):`{"kind":"menu","id":"file.save","enabled":true,"checked":false}`
|
|
9
|
+
* 托盘 / 拖放落地后各带自己的 kind(`tray` / `drop`),kind 决定投给前端哪个事件名。
|
|
10
|
+
*
|
|
11
|
+
* 为什么单独成文件:这里是**纯函数**(不进窗口、不碰线程),能脱离宿主在单测里直接验。
|
|
12
|
+
* 信封格式坏掉的表现是「事件静默不到」——没有纯函数边界时,只能靠实机点击去猜。
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/** `kind` → 前端事件名;不认识的 kind 返回 None(调用方提示一句后丢弃,不抛异常) */
|
|
16
|
+
public func shellEventNameFor(kind: String): Option<String> {
|
|
17
|
+
match (kind) {
|
|
18
|
+
case "menu" => return Some("menu:click")
|
|
19
|
+
case "tray" => return Some("tray:click")
|
|
20
|
+
case "drop" => return Some("dragdrop:files")
|
|
21
|
+
case "hotkey" => return Some("hotkey:press")
|
|
22
|
+
case _ => return None
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* 解析信封成对象;不是合法 JSON 对象就返回 None
|
|
28
|
+
*
|
|
29
|
+
* 不抛异常:数据从 C 桥来(**不是**页面可控输入),格式坏了宁可丢一条事件 + 留一行日志,
|
|
30
|
+
* 也不要让异常穿到 FFI 边界——仓颉异常穿过 C 侧回调,进程状态就说不清了。
|
|
31
|
+
*/
|
|
32
|
+
public func parseShellEnvelope(json: String): Option<JsonObject> {
|
|
33
|
+
try {
|
|
34
|
+
let v = JsonValue.fromStr(json)
|
|
35
|
+
match (v.kind()) {
|
|
36
|
+
case JsonKind.JsObject => return Some(v.asObject())
|
|
37
|
+
case _ => return None
|
|
38
|
+
}
|
|
39
|
+
} catch (e: Exception) {
|
|
40
|
+
return None
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** 取信封里的字符串字段(缺失 / 类型不对都给 None) */
|
|
45
|
+
public func shellString(obj: JsonObject, key: String): Option<String> {
|
|
46
|
+
match (obj.get(key)) {
|
|
47
|
+
case Some(v) => match (v.kind()) {
|
|
48
|
+
case JsonKind.JsString => return Some(v.asString().getValue())
|
|
49
|
+
case _ => return None
|
|
50
|
+
}
|
|
51
|
+
case None => return None
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* 取信封里的布尔字段(缺失 / 类型不对都给 None)
|
|
57
|
+
*
|
|
58
|
+
* 缺字段**不能**当 false 用:这两个值要回写到应用层菜单模型(见 `TauriApp` 的模型同步),
|
|
59
|
+
* 拿默认值顶等于把「用户刚点出来的勾选」按默认值改掉——宁可不写。
|
|
60
|
+
*/
|
|
61
|
+
public func shellBool(obj: JsonObject, key: String): Option<Bool> {
|
|
62
|
+
match (obj.get(key)) {
|
|
63
|
+
case Some(v) => match (v.kind()) {
|
|
64
|
+
case JsonKind.JsBool => return Some(v.asBool().getValue())
|
|
65
|
+
case _ => return None
|
|
66
|
+
}
|
|
67
|
+
case None => return None
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -1,127 +1,130 @@
|
|
|
1
|
-
package cjTauri.tests
|
|
2
|
-
|
|
3
|
-
import cjTauri.*
|
|
4
|
-
import cjTauri.platform.*
|
|
5
|
-
import cjTauri.plugins.store.*
|
|
6
|
-
import std.collection.*
|
|
7
|
-
import std.
|
|
8
|
-
import std.unittest.*
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
.
|
|
17
|
-
.
|
|
18
|
-
.
|
|
19
|
-
|
|
20
|
-
@Expect(spec.
|
|
21
|
-
@Expect(spec.
|
|
22
|
-
@Expect(spec.
|
|
23
|
-
@Expect(spec.windowConfig.
|
|
24
|
-
@Expect(spec.
|
|
25
|
-
@Expect(spec.
|
|
26
|
-
@Expect(spec.
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
case
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
return 100
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
public func create(label: String, target: TargetInfo): WebViewHost {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
let
|
|
59
|
-
|
|
60
|
-
.
|
|
61
|
-
.
|
|
62
|
-
.
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
@Expect(
|
|
68
|
-
@Expect(
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
h
|
|
77
|
-
|
|
78
|
-
@Expect(h.
|
|
79
|
-
h.
|
|
80
|
-
|
|
81
|
-
h.
|
|
82
|
-
|
|
83
|
-
h.
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
1
|
+
package cjTauri.tests
|
|
2
|
+
|
|
3
|
+
import cjTauri.*
|
|
4
|
+
import cjTauri.platform.*
|
|
5
|
+
import cjTauri.plugins.store.*
|
|
6
|
+
import std.collection.*
|
|
7
|
+
import std.unittest.*
|
|
8
|
+
import std.unittest.testmacro.*
|
|
9
|
+
|
|
10
|
+
// ---- 批次 3-PR1:AppSpec 构造器链与 assemble 装配 ----
|
|
11
|
+
|
|
12
|
+
@Test
|
|
13
|
+
func appSpecBuilderChain(): Unit {
|
|
14
|
+
let spec = AppSpec()
|
|
15
|
+
.page(PageSource.Inline("<p/>"))
|
|
16
|
+
.window(WindowConfig("t", 800, 600))
|
|
17
|
+
.capabilities("assets/capabilities")
|
|
18
|
+
.capabilityJson("{\"identifier\":\"default\"}")
|
|
19
|
+
@Expect(spec.appId, "")
|
|
20
|
+
@Expect(spec.capabilitiesDir, "assets/capabilities")
|
|
21
|
+
@Expect(spec.capabilityJsons.size, 1)
|
|
22
|
+
@Expect(spec.windowConfig.title, "t")
|
|
23
|
+
@Expect(spec.windowConfig.width, 800)
|
|
24
|
+
@Expect(spec.assetResolver.isSome(), false)
|
|
25
|
+
@Expect(spec.wireFn.isSome(), false)
|
|
26
|
+
@Expect(spec.plugins.size, 0)
|
|
27
|
+
match (spec.pageSource) {
|
|
28
|
+
case Inline(html) => @Expect(html, "<p/>")
|
|
29
|
+
case _ => @Expect(false, true)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** wire 闭包执行标记(仓颉闭包捕获 var 的语义不冒风险,用对象装状态) */
|
|
34
|
+
class WireBox {
|
|
35
|
+
public var on: Bool = false
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** 高优先级假宿主:TauriApp 字段初始化就调 resolveHost,无显示环境必须用注册表桩 */
|
|
39
|
+
class AppSpecProbeProvider <: HostProvider {
|
|
40
|
+
public var last: FakeHost = FakeHost("seed")
|
|
41
|
+
|
|
42
|
+
public func priority(target: TargetInfo): Int64 {
|
|
43
|
+
let _ = target
|
|
44
|
+
return 100
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
public func create(label: String, target: TargetInfo): WebViewHost {
|
|
48
|
+
let _ = target
|
|
49
|
+
this.last = FakeHost(label)
|
|
50
|
+
return this.last
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
@Test
|
|
55
|
+
func appSpecAssembleWiresApp(): Unit {
|
|
56
|
+
let prov = AppSpecProbeProvider()
|
|
57
|
+
registerHost(prov)
|
|
58
|
+
let box = WireBox()
|
|
59
|
+
let spec = AppSpec()
|
|
60
|
+
.page(PageSource.Inline("<p/>"))
|
|
61
|
+
.window(WindowConfig("spec窗", 640, 480))
|
|
62
|
+
.plugin(StorePlugin())
|
|
63
|
+
.wire({ _ =>
|
|
64
|
+
box.on = true
|
|
65
|
+
})
|
|
66
|
+
let app = assemble(spec)
|
|
67
|
+
@Expect(box.on, true)
|
|
68
|
+
@Expect(app.hostOf("main").isSome(), true)
|
|
69
|
+
@Expect(prov.last.label(), "main")
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// ---- 批次 3-PR3:load(source) 收敛——装配层把 PageSource 原样交给宿主,resolver 随装配进宿主 ----
|
|
73
|
+
|
|
74
|
+
@Test
|
|
75
|
+
func fakeHostLoadDispatchesPageSource(): Unit {
|
|
76
|
+
let h = FakeHost("main")
|
|
77
|
+
h.load(PageSource.Inline("<p>hi</p>"))
|
|
78
|
+
@Expect(h.shownHtml, "<p>hi</p>")
|
|
79
|
+
@Expect(h.startedUrl, "")
|
|
80
|
+
h.load(PageSource.Url("https://example.com"))
|
|
81
|
+
@Expect(h.startedUrl, "https://example.com")
|
|
82
|
+
h.load(PageSource.DevServer("http://127.0.0.1:5173"))
|
|
83
|
+
@Expect(h.startedUrl, "http://127.0.0.1:5173")
|
|
84
|
+
h.load(PageSource.Asset("ui/index.html"))
|
|
85
|
+
@Expect(h.loadedSource, "asset:ui/index.html")
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** run 路径探针:优先级压过既有注册表里的桩,保证本用例拿到的是自己造的宿主 */
|
|
89
|
+
class RunProbeProvider <: HostProvider {
|
|
90
|
+
public var last: FakeHost = FakeHost("seed")
|
|
91
|
+
|
|
92
|
+
public func priority(target: TargetInfo): Int64 {
|
|
93
|
+
let _ = target
|
|
94
|
+
return 200
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
public func create(label: String, target: TargetInfo): WebViewHost {
|
|
98
|
+
let _ = target
|
|
99
|
+
this.last = FakeHost(label)
|
|
100
|
+
return this.last
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* run() 路径:resolver 注入与页面来源交接发生在同一次装配(runWith)里。
|
|
106
|
+
* 宿主用 FakeHost 桩(不建窗口);run() 放后台线程,观测到交接后置 quitNow 让它返回。
|
|
107
|
+
*/
|
|
108
|
+
@Test
|
|
109
|
+
func runHandsResolverAndSourceToHost(): Unit {
|
|
110
|
+
let prov = RunProbeProvider()
|
|
111
|
+
let provIdx = registerHost(prov)
|
|
112
|
+
let spec = AppSpec()
|
|
113
|
+
.page(PageSource.Asset("ui/index.html"))
|
|
114
|
+
.window(WindowConfig("t", 640, 480))
|
|
115
|
+
.assets(StubResolver(HashMap()))
|
|
116
|
+
spawn {
|
|
117
|
+
let app = assemble(spec)
|
|
118
|
+
app.run(spec.pageSource)
|
|
119
|
+
}
|
|
120
|
+
var polls = 0
|
|
121
|
+
while (polls < 1000 && prov.last.loadedSource != "asset:ui/index.html") {
|
|
122
|
+
sleep(Duration.millisecond * 2)
|
|
123
|
+
polls += 1
|
|
124
|
+
}
|
|
125
|
+
@Expect(prov.last.loadedSource, "asset:ui/index.html")
|
|
126
|
+
@Expect(prov.last.resolverInjected.isSome(), true)
|
|
127
|
+
prov.last.quitNow = true
|
|
128
|
+
// 探针宿主清出全局注册表,免得压过后续用例自己的桩
|
|
129
|
+
unregisterHost(provIdx)
|
|
130
|
+
}
|