Skip to content

Commit e9b87ea

Browse files
committed
♻️ [kmp/dwebview] ios的web-message垫片现在挪到polyfill项目中来编译
1 parent b8b0b35 commit e9b87ea

8 files changed

Lines changed: 91 additions & 85 deletions

File tree

next/kmp/dwebview/src/iosMain/kotlin/org/dweb_browser/dwebview/engine/DWebViewEngine.ios.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import kotlinx.coroutines.SupervisorJob
1616
import kotlinx.coroutines.cancel
1717
import kotlinx.coroutines.flow.MutableStateFlow
1818
import kotlinx.coroutines.launch
19-
import kotlinx.serialization.encodeToString
2019
import org.dweb_browser.core.help.types.MMID
2120
import org.dweb_browser.core.http.dwebHttpGatewayService
2221
import org.dweb_browser.core.http.dwebProxyService
@@ -290,15 +289,15 @@ class DWebViewEngine(
290289
name = "closeWatcher"
291290
)
292291
}
293-
ifNoDefineUserScript(DWebViewWebMessage.WebMessagePortPrepareCode) {
292+
ifNoDefineUserScript(DwebViewIosPolyfill.WebMessage) {
294293
addScriptMessageHandler(
295294
scriptMessageHandler = DWebViewWebMessage.WebMessagePortMessageHandler(),
296295
contentWorld = DWebViewWebMessage.webMessagePortContentWorld,
297296
name = "webMessagePort"
298297
)
299298
addUserScript(
300299
WKUserScript(
301-
source = DWebViewWebMessage.WebMessagePortPrepareCode,
300+
source = DwebViewIosPolyfill.WebMessage,
302301
injectionTime = WKUserScriptInjectionTime.WKUserScriptInjectionTimeAtDocumentEnd,
303302
forMainFrameOnly = false,
304303
inContentWorld = DWebViewWebMessage.webMessagePortContentWorld

next/kmp/dwebview/src/iosMain/kotlin/org/dweb_browser/dwebview/messagePort/DWebMessagePort.ios.kt

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import kotlinx.cinterop.BetaInteropApi
44
import kotlinx.coroutines.CancellationException
55
import kotlinx.coroutines.CoroutineScope
66
import kotlinx.coroutines.channels.Channel
7-
import kotlinx.serialization.encodeToString
87
import kotlinx.serialization.json.Json
98
import org.dweb_browser.core.ipc.helper.DWebMessage
109
import org.dweb_browser.core.ipc.helper.IWebMessagePort
@@ -58,21 +57,17 @@ class DWebMessagePort(val portId: Int, private val webview: DWebView, parentScop
5857

5958
override suspend fun postMessage(event: DWebMessage) {
6059
withMainContext {
60+
val ports = event.ports.map {
61+
require(it is DWebMessagePort)
62+
it.portId
63+
}.joinToString(",")
6164
if (event is DWebMessage.DWebMessageBytes) {
62-
val ports = event.ports.map {
63-
require(it is DWebMessagePort)
64-
it.portId
65-
}.joinToString(",")
6665
webview.engine.evalAsyncJavascript<Unit>(
6766
"nativePortPostMessage($portId, ${
6867
Json.encodeToString(event.text)
6968
}, [$ports])", null, DWebViewWebMessage.webMessagePortContentWorld
7069
).await()
7170
} else if (event is DWebMessage.DWebMessageString) {
72-
val ports = event.ports.map {
73-
require(it is DWebMessagePort)
74-
it.portId
75-
}.joinToString(",")
7671
webview.engine.evalAsyncJavascript<Unit>(
7772
"nativePortPostMessage($portId, ${
7873
Json.encodeToString(event.text)

next/kmp/dwebview/src/iosMain/kotlin/org/dweb_browser/dwebview/messagePort/DWebViewWebMessage.ios.kt

Lines changed: 1 addition & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -12,81 +12,14 @@ import platform.darwin.NSObject
1212

1313
internal class DWebViewWebMessage(val webview: DWebView) {
1414
companion object {
15-
16-
const val WebMessagePortPrepareCode = """
17-
const ALL_PORT = new Map();
18-
let portIdAcc = 1;
19-
const PORTS_ID = new WeakMap();
20-
const getPortId = (port) => {
21-
let port_id = PORTS_ID.get(port);
22-
if (port_id === undefined) {
23-
const current_port_id = portIdAcc++;
24-
port_id = current_port_id;
25-
ALL_PORT.set(port_id, port);
26-
port.addEventListener('message', (event) => {
27-
let data = event.data;
28-
if (typeof data !== 'string') {
29-
data = Array.from(data);
30-
}
31-
webkit.messageHandlers.webMessagePort.postMessage({
32-
type: 'message',
33-
id: current_port_id,
34-
data: data,
35-
ports: event.ports.map(getPortId),
36-
});
37-
});
38-
}
39-
return port_id;
40-
};
41-
function nativeCreateMessageChannel() {
42-
const channel = new MessageChannel();
43-
const port1_id = getPortId(channel.port1);
44-
const port2_id = getPortId(channel.port2);
45-
return [port1_id, port2_id];
46-
}
47-
function forceGetPort(port_id) {
48-
const port = ALL_PORT.get(port_id);
49-
if (port === undefined) {
50-
throw new Error(`no found messagePort by ref: $\{port_id}`);
51-
}
52-
return port;
53-
}
54-
function nativePortPostMessage(port_id, data, ports_id) {
55-
const origin_port = forceGetPort(port_id);
56-
const transfer_ports = ports_id.map(forceGetPort);
57-
if (typeof data !== "string") {
58-
const u8a = new Uint8Array(data);
59-
transfer_ports.push(u8a.buffer);
60-
origin_port.postMessage(u8a, transfer_ports);
61-
} else if(typeof data === "object") {
62-
origin_port.postMessage(JSON.stringify(data), transfer_ports);
63-
}
64-
else {
65-
origin_port.postMessage(data, transfer_ports);
66-
}
67-
}
68-
function nativeStart(port_id) {
69-
const origin_port = forceGetPort(port_id);
70-
origin_port.start();
71-
}
72-
function nativeWindowPostMessage(data, ports_id) {
73-
const ports = ports_id.map(forceGetPort);
74-
dispatchEvent(new MessageEvent('message', { data, ports }));
75-
}
76-
function nativeClose(port_id) {
77-
const origin_port = forceGetPort(port_id);
78-
origin_port.close();
79-
}
80-
""";
8115
val webMessagePortContentWorld = WKContentWorld.worldWithName("web-message-port");
8216
val allPorts = mutableMapOf<Int, DWebMessagePort>()
83-
8417
}
8518

8619
internal class WebMessagePortMessageHandler : NSObject(), WKScriptMessageHandlerProtocol {
8720
override fun userContentController(
8821
userContentController: WKUserContentController,
89-
didReceiveScriptMessage: WKScriptMessage
22+
didReceiveScriptMessage: WKScriptMessage,
9023
) {
9124
try {
9225
val message = didReceiveScriptMessage.body as NSObject

next/kmp/dwebview/src/iosMain/kotlin/org/dweb_browser/dwebview/polyfill/DwebViewPolyfill.ios.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ object DwebViewIosPolyfill : DwebViewCommonPolyfill() {
1212
launch { CloseWatcher = readDwebviewPolyfill("close-watcher.common.js") }
1313
launch { UserAgentData = readDwebviewPolyfill("user-agent-data.common.js") }
1414
launch { NavigationHook = readDwebviewPolyfill("navigation-hook.ios.js") }
15+
launch { WebMessage = readDwebviewPolyfill("web-message.ios.js") }
1516
}
1617
}
1718

@@ -25,4 +26,6 @@ object DwebViewIosPolyfill : DwebViewCommonPolyfill() {
2526
private set
2627
lateinit var NavigationHook: String
2728
private set
29+
lateinit var WebMessage: String
30+
private set
2831
}

next/kmp/platformIos/src/nativeInterop/cinterop/build.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,16 @@ import fs from "node:fs";
33
import os from "node:os";
44
import path from "node:path";
55

6-
import { walkSync } from "jsr:@std/fs";
76
import { which } from "jsr:@david/which";
7+
import { walkSync } from "jsr:@std/fs";
88
import { doArchiveItemTask } from "./archive.ts";
99
import { doCreateXcItemTask } from "./create-xc.ts";
10-
import { __dirname, exec, runTasks, sourceCodeDir } from "./util.ts";
10+
import { __dirname, runTasks, sourceCodeDir } from "./util.ts";
1111

12-
export const doBuildTask = async () => {
12+
export const doBuildTask = async (): Promise<number> => {
1313
// 使用xcodebuild 来判断是否是有 Xcode
1414
const xcodebuild = await which("xcodebuild");
15-
if(!xcodebuild) {
15+
if (!xcodebuild) {
1616
return 0;
1717
}
1818

next/kmp/platformIos/src/nativeInterop/cinterop/gradle-sync.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// ./gradlew :platformIos:cinteropSync
44
import { exec, runTasks } from "./util.ts";
55

6-
export const doGradleSyncTask = () => {
6+
export const doGradleSyncTask = (): Promise<number> => {
77
return runTasks(doClean, doCinteropSync);
88
};
99

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import "./ios.type.ts";
2+
const ALL_PORT = new Map();
3+
let portIdAcc = 1;
4+
const PORTS_ID = new WeakMap();
5+
const webMessagePort = webkit?.messageHandlers?.webMessagePort;
6+
if (webMessagePort == undefined) {
7+
throw new Error("webkit.messageHandlers.webMessagePort is undefined");
8+
}
9+
const getPortId = (port: MessagePort) => {
10+
let port_id = PORTS_ID.get(port);
11+
if (port_id === undefined) {
12+
const current_port_id = portIdAcc++;
13+
port_id = current_port_id;
14+
ALL_PORT.set(port_id, port);
15+
port.addEventListener("message", (event) => {
16+
let data = event.data;
17+
if (typeof data !== "string") {
18+
data = Array.from(data);
19+
}
20+
webMessagePort.postMessage({
21+
type: "message",
22+
id: current_port_id,
23+
data: data,
24+
ports: event.ports.map(getPortId),
25+
});
26+
});
27+
}
28+
return port_id;
29+
};
30+
function nativeCreateMessageChannel() {
31+
const channel = new MessageChannel();
32+
const port1_id = getPortId(channel.port1);
33+
const port2_id = getPortId(channel.port2);
34+
return [port1_id, port2_id];
35+
}
36+
function forceGetPort(port_id: number) {
37+
const port = ALL_PORT.get(port_id);
38+
if (port === undefined) {
39+
throw new Error(`no found messagePort by ref: $\{port_id}`);
40+
}
41+
return port;
42+
}
43+
function nativePortPostMessage(port_id: number, data: Uint8Array | string, ports_id: number[]) {
44+
const origin_port = forceGetPort(port_id);
45+
const transfer_ports = ports_id.map(forceGetPort);
46+
if (ArrayBuffer.isView(data)) {
47+
// 按需客隆
48+
const u8a = data.byteOffset === 0 && data.byteLength === data.buffer.byteLength ? data : new Uint8Array(data);
49+
transfer_ports.push(u8a.buffer);
50+
origin_port.postMessage(u8a, transfer_ports);
51+
} else if (typeof data === "string") {
52+
origin_port.postMessage(data, transfer_ports);
53+
} else {
54+
origin_port.postMessage(JSON.stringify(data), transfer_ports);
55+
}
56+
}
57+
function nativeStart(port_id: number) {
58+
const origin_port = forceGetPort(port_id);
59+
origin_port.start();
60+
}
61+
function nativeWindowPostMessage(data: unknown, ports_id: number[]) {
62+
const ports = ports_id.map(forceGetPort);
63+
dispatchEvent(new MessageEvent("message", { data, ports }));
64+
}
65+
function nativeClose(port_id: number) {
66+
const origin_port = forceGetPort(port_id);
67+
origin_port.close();
68+
}
69+
Object.assign(globalThis, {
70+
nativeCreateMessageChannel,
71+
nativePortPostMessage,
72+
nativeStart,
73+
nativeWindowPostMessage,
74+
nativeClose,
75+
});

toolkit/dweb-polyfill/vite.config.mts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export default defineConfig(() => {
99
"websocket.ios": "./src/websocket.ios.ts",
1010
"favicon.ios": "./src/favicon.ios.ts",
1111
"navigation-hook.ios": "./src/navigation-hook.ios.ts",
12+
"web-message.ios": "./src/web-message.ios.ts",
1213
"favicon.common": "./src/favicon.common.ts",
1314
"close-watcher.common": "./src/close-watcher/index.ts",
1415
"user-agent-data.common": "./src/user-agent-data.common.ts",

0 commit comments

Comments
 (0)