@gjsify/iframe 0.4.12 → 0.4.13
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/lib/esm/iframe-message-channel.js +1 -1
- package/lib/esm/index.js +1 -1
- package/lib/esm/message-bridge.js +5 -5
- package/lib/types/iframe-message-channel.d.ts +26 -36
- package/lib/types/iframe-window-proxy.d.ts +3 -3
- package/lib/types/index.d.ts +1 -1
- package/lib/types/message-bridge.d.ts +14 -11
- package/package.json +6 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./_virtual/_rolldown/runtime.js";import{
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{MessageChannel as e,MessagePort as t}from"@gjsify/message-channel";const n=t,r=e;var BridgePortTransport=class{constructor(e){this._bridge=e}send(e,t){this._bridge._sendPortMessage(e,t)}close(e){this._bridge._closePort(e)}};export{BridgePortTransport,r as IFrameMessageChannel,n as IFrameMessagePort,e as MessageChannel,t as MessagePort};
|
package/lib/esm/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./_virtual/_rolldown/runtime.js";import{HTMLIFrameElement as e}from"./html-iframe-element.js";import{IFrameWindowProxy as t}from"./iframe-window-proxy.js";import{
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{HTMLIFrameElement as e}from"./html-iframe-element.js";import{IFrameWindowProxy as t}from"./iframe-window-proxy.js";import{IFrameMessageChannel as n,IFrameMessagePort as r,MessageChannel as i,MessagePort as a}from"./iframe-message-channel.js";import{GJS_HOST_ORIGIN as o,MessageBridge as s}from"./message-bridge.js";import{IFrameBridge as c}from"./iframe-bridge.js";import{Document as l}from"@gjsify/dom-elements";l.registerElementFactory(`iframe`,()=>new e),Object.defineProperty(globalThis,`HTMLIFrameElement`,{value:e,writable:!0,configurable:!0});export{o as GJS_HOST_ORIGIN,e as HTMLIFrameElement,c as IFrameBridge,n as IFrameMessageChannel,r as IFrameMessagePort,t as IFrameWindowProxy,s as MessageBridge,i as MessageChannel,a as MessagePort};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import"./_virtual/_rolldown/runtime.js";import{BINARY_SERIALIZER_INJECTED_SRC as
|
|
2
|
-
var handler = window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers['${
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{BridgePortTransport as e}from"./iframe-message-channel.js";import{BINARY_SERIALIZER_INJECTED_SRC as t,decodeBinariesFromJson as n,encodeBinariesForJson as r}from"./serialize.js";import{MessageEvent as i}from"@gjsify/dom-events";import a from"gi://WebKit?version=6.0";import o from"gi://Gio?version=2.0";o._promisify(a.WebView.prototype,`evaluate_javascript`,`evaluate_javascript_finish`);const s=`gjsify-iframe`,c=`https://gjsify.local`;function normaliseTargetOrigin(e){if(e===`*`)return`*`;if(e===`/`)return null;try{return new URL(e).origin}catch{let t=Error(`Invalid target origin '${e}'`);throw t.name=`SyntaxError`,t}}const BOOTSTRAP_SCRIPT_FOR_TEST=()=>l,l=`(function() {
|
|
2
|
+
var handler = window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers['${s}'];
|
|
3
3
|
if (!handler) return;
|
|
4
4
|
|
|
5
5
|
// Idempotency guard: WebKit auto-injects this script at INJECTION_TIME.START
|
|
@@ -11,9 +11,9 @@ import"./_virtual/_rolldown/runtime.js";import{BINARY_SERIALIZER_INJECTED_SRC as
|
|
|
11
11
|
// __gjsifyBridge.origPostMessage would loop forever.
|
|
12
12
|
if (window.__gjsifyBridge && window.__gjsifyBridge.__bridgeVersion === 1) return;
|
|
13
13
|
|
|
14
|
-
var GJS_HOST_ORIGIN = '${
|
|
14
|
+
var GJS_HOST_ORIGIN = '${c}';
|
|
15
15
|
|
|
16
|
-
${
|
|
16
|
+
${t}
|
|
17
17
|
|
|
18
18
|
// Per-WebView registry of proxy ports created during GJS → WebView
|
|
19
19
|
// postMessage. Keyed by the GJS-allocated portId. Each entry has a
|
|
@@ -133,4 +133,4 @@ import"./_virtual/_rolldown/runtime.js";import{BINARY_SERIALIZER_INJECTED_SRC as
|
|
|
133
133
|
postMessage: bridgePostMessage,
|
|
134
134
|
origPostMessage: origPostMessage,
|
|
135
135
|
};
|
|
136
|
-
})();`;var MessageBridge=class{constructor(e){this._windowProxy=null,this._currentUri=`about:blank`,this._signalId=null,this._ports=new Map,this._nextPortId=1,this._webView=e,this._userContentManager=e.get_user_content_manager(),this._setupReceiver(),this._injectBootstrapScript()}setWindowProxy(e){this._windowProxy=e}updateUri(e){this._currentUri=e}getLocation(){let e;try{e=new URL(this._currentUri).origin}catch{e=`null`}return{href:this._currentUri,origin:e}}_registerTransferredPort(e){if(e._transferred)throw Error(`
|
|
136
|
+
})();`;var MessageBridge=class{_getTransport(){return this._transport===null&&(this._transport=new e(this)),this._transport}constructor(e){this._windowProxy=null,this._currentUri=`about:blank`,this._signalId=null,this._ports=new Map,this._nextPortId=1,this._transport=null,this._webView=e,this._userContentManager=e.get_user_content_manager(),this._setupReceiver(),this._injectBootstrapScript()}setWindowProxy(e){this._windowProxy=e}updateUri(e){this._currentUri=e}getLocation(){let e;try{e=new URL(this._currentUri).origin}catch{e=`null`}return{href:this._currentUri,origin:e}}_registerTransferredPort(e){if(e._transferred)throw Error(`MessagePort: already transferred`);let t=e._partner;if(!t)throw Error(`MessagePort: partner missing — port already transferred or closed`);let n=this._nextPortId++;return e._transferred=!0,e._partner=null,t._partner=null,t._transport=this._getTransport(),t._portId=n,this._ports.set(n,t),n}_sendPortMessage(e,n){let i=r(n),a=JSON.stringify(i),o=`(function(){${t}var p = window.__gjsifyPortRegistry && window.__gjsifyPortRegistry[${e}]; if (p) p.deliver(__decodeBin(JSON.parse(${JSON.stringify(a)})));})();`;this._webView.evaluate_javascript(o,-1,null,null,null).catch(()=>{})}_closePort(e){this._ports.delete(e);let t=`(function(){ if (window.__gjsifyPortRegistry) delete window.__gjsifyPortRegistry[${e}]; })();`;this._webView.evaluate_javascript(t,-1,null,null,null).catch(()=>{})}sendToWebView(e,n,i){let a=normaliseTargetOrigin(n);if(a!==`*`){let e=this.getLocation().origin;if((a??`https://gjsify.local`)!==e)return}let o=e;if(i&&i.length>0){let t=new Map;for(let e of i){let n=this._registerTransferredPort(e);t.set(e,n)}o=substitutePorts(e,t)}let s=r(o),l=JSON.stringify(s),u=JSON.stringify(c),d=`(function(){${t}var d = __decodeBin(JSON.parse(${JSON.stringify(l)})); if (window.__gjsifySubstitutePorts) d = window.__gjsifySubstitutePorts(d); window.dispatchEvent(new MessageEvent('message', { data: d, origin: ${u} }));})();`;this._webView.evaluate_javascript(d,-1,null,null,null).catch(()=>{})}destroy(){this._signalId!==null&&(this._userContentManager.disconnect(this._signalId),this._signalId=null),this._userContentManager.unregister_script_message_handler(s,null),this._windowProxy=null}_setupReceiver(){this._userContentManager.register_script_message_handler(s,null),this._signalId=this._userContentManager.connect(`script-message-received::${s}`,(e,t)=>{if(this._windowProxy)try{let e=t.to_string(),r=JSON.parse(e);if(typeof r.__gjsifyPortMessage==`number`){let e=r,t=this._ports.get(e.__gjsifyPortMessage);t&&t._receive(n(e.payload));return}if(typeof r.__gjsifyPortClose==`number`){let e=r,t=this._ports.get(e.__gjsifyPortClose);t&&t.close(),this._ports.delete(e.__gjsifyPortClose);return}let a=r,o=a.targetOrigin;if(o!==`*`&&o!==`https://gjsify.local`)return;let s=new i(`message`,{data:n(a.data),origin:a.origin});this._windowProxy.dispatchEvent(s)}catch(e){console.error(`[IFrame MessageBridge] Error processing message:`,e)}})}_injectBootstrapScript(){let e=new a.UserScript(l,a.UserContentInjectedFrames.ALL_FRAMES,a.UserScriptInjectionTime.START,null,null);this._userContentManager.add_script(e)}};function substitutePorts(e,t){let n=new WeakMap;function walk(e){if(typeof e!=`object`||!e)return e;if(e[Symbol.toStringTag]===`MessagePort`&&t.has(e))return{__gjsifyPort:t.get(e)};if(n.has(e))return n.get(e);if(Array.isArray(e)){let t=[];n.set(e,t);for(let n=0;n<e.length;n++)t[n]=walk(e[n]);return t}if(Object.prototype.toString.call(e).slice(8,-1)===`Object`){let t={};n.set(e,t);for(let n of Object.keys(e))t[n]=walk(e[n]);return t}return e}return walk(e)}export{BOOTSTRAP_SCRIPT_FOR_TEST,c as GJS_HOST_ORIGIN,MessageBridge,normaliseTargetOrigin};
|
|
@@ -1,38 +1,28 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { MessagePort, MessageChannel } from '@gjsify/message-channel';
|
|
2
|
+
import type { MessagePortTransport } from '@gjsify/message-channel';
|
|
2
3
|
import type { MessageBridge } from './message-bridge.js';
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
close(): void;
|
|
27
|
-
/** @internal Called by the bridge or the in-process partner. */
|
|
28
|
-
_receive(data: unknown): void;
|
|
29
|
-
private _dispatch;
|
|
30
|
-
addEventListener(type: string, listener: any, options?: any): void;
|
|
31
|
-
get [Symbol.toStringTag](): string;
|
|
32
|
-
}
|
|
33
|
-
export declare class IFrameMessageChannel {
|
|
34
|
-
readonly port1: IFrameMessagePort;
|
|
35
|
-
readonly port2: IFrameMessagePort;
|
|
36
|
-
constructor();
|
|
37
|
-
get [Symbol.toStringTag](): string;
|
|
4
|
+
export { MessagePort, MessageChannel };
|
|
5
|
+
/** @deprecated Re-exported alias of `MessagePort` from
|
|
6
|
+
* `@gjsify/message-channel`. Use the standard name. */
|
|
7
|
+
export declare const IFrameMessagePort: typeof MessagePort;
|
|
8
|
+
export type IFrameMessagePort = MessagePort;
|
|
9
|
+
/** @deprecated Re-exported alias of `MessageChannel` from
|
|
10
|
+
* `@gjsify/message-channel`. Use the standard name. */
|
|
11
|
+
export declare const IFrameMessageChannel: typeof MessageChannel;
|
|
12
|
+
export type IFrameMessageChannel = MessageChannel;
|
|
13
|
+
/**
|
|
14
|
+
* MessagePortTransport adapter that routes a port's outbound messages
|
|
15
|
+
* through a `MessageBridge` instance. Used internally by the bridge
|
|
16
|
+
* when it picks up `MessagePort` instances from a `postMessage`
|
|
17
|
+
* transferList — the transferred port's partner is attached to a
|
|
18
|
+
* `BridgePortTransport` so its `.postMessage` flows over the WebKit
|
|
19
|
+
* IPC instead of the in-process partner (which has been detached).
|
|
20
|
+
*
|
|
21
|
+
* @internal
|
|
22
|
+
*/
|
|
23
|
+
export declare class BridgePortTransport implements MessagePortTransport {
|
|
24
|
+
private _bridge;
|
|
25
|
+
constructor(_bridge: MessageBridge);
|
|
26
|
+
send(portId: number, data: unknown): void;
|
|
27
|
+
close(portId: number): void;
|
|
38
28
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { EventTarget } from '@gjsify/dom-events';
|
|
2
2
|
import type { MessageBridge } from './message-bridge.js';
|
|
3
|
-
import type {
|
|
3
|
+
import type { MessagePort } from '@gjsify/message-channel';
|
|
4
4
|
/**
|
|
5
5
|
* Lightweight Window-like proxy returned by `HTMLIFrameElement.contentWindow`.
|
|
6
6
|
*
|
|
@@ -24,13 +24,13 @@ export declare class IFrameWindowProxy extends EventTarget {
|
|
|
24
24
|
* @param message - Data to send (must be JSON-serializable + base64-encodable
|
|
25
25
|
* binaries — see @gjsify/iframe/serialize for supported binary types).
|
|
26
26
|
* @param targetOrigin - Target origin for the message. Default: '*'.
|
|
27
|
-
* @param transfer - Optional list of `
|
|
27
|
+
* @param transfer - Optional list of `MessagePort` instances to
|
|
28
28
|
* transfer. Each transferred port is detached locally; its surviving
|
|
29
29
|
* partner becomes the GJS-side endpoint of a bidirectional channel
|
|
30
30
|
* routed through the bridge. The WebView receives proxy ports under
|
|
31
31
|
* `MessageEvent.data` wherever the original ports appeared in `message`.
|
|
32
32
|
*/
|
|
33
|
-
postMessage(message: unknown, targetOrigin?: string, transfer?:
|
|
33
|
+
postMessage(message: unknown, targetOrigin?: string, transfer?: MessagePort[]): void;
|
|
34
34
|
/**
|
|
35
35
|
* Read-only location reflecting the current WebView URI.
|
|
36
36
|
*/
|
package/lib/types/index.d.ts
CHANGED
|
@@ -2,5 +2,5 @@ export { HTMLIFrameElement } from './html-iframe-element.js';
|
|
|
2
2
|
export { IFrameBridge } from './iframe-bridge.js';
|
|
3
3
|
export { IFrameWindowProxy } from './iframe-window-proxy.js';
|
|
4
4
|
export { MessageBridge, GJS_HOST_ORIGIN } from './message-bridge.js';
|
|
5
|
-
export { IFrameMessageChannel, IFrameMessagePort } from './iframe-message-channel.js';
|
|
5
|
+
export { MessageChannel, MessagePort, IFrameMessageChannel, IFrameMessagePort } from './iframe-message-channel.js';
|
|
6
6
|
export type { IFrameBridgeOptions, IFrameReadyCallback, IFrameMessageData } from './types/index.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import WebKit from 'gi://WebKit?version=6.0';
|
|
2
2
|
import type { IFrameWindowProxy } from './iframe-window-proxy.js';
|
|
3
|
-
import type {
|
|
3
|
+
import type { MessagePort } from '@gjsify/message-channel';
|
|
4
4
|
/**
|
|
5
5
|
* Synthetic origin attached to messages travelling FROM the GJS host
|
|
6
6
|
* INTO the WebView. The WebView can use this in a targetOrigin filter to
|
|
@@ -63,6 +63,8 @@ export declare class MessageBridge {
|
|
|
63
63
|
* we route the payload to `_ports.get(id)._receive(decoded)`. */
|
|
64
64
|
private _ports;
|
|
65
65
|
private _nextPortId;
|
|
66
|
+
private _transport;
|
|
67
|
+
private _getTransport;
|
|
66
68
|
constructor(webView: WebKit.WebView);
|
|
67
69
|
/** Connect the IFrameWindowProxy that will receive messages from the WebView */
|
|
68
70
|
setWindowProxy(proxy: IFrameWindowProxy): void;
|
|
@@ -79,24 +81,25 @@ export declare class MessageBridge {
|
|
|
79
81
|
*/
|
|
80
82
|
/**
|
|
81
83
|
* Register a port pair for cross-bridge transfer. Called by
|
|
82
|
-
* IFrameWindowProxy.postMessage when it sees
|
|
83
|
-
*
|
|
84
|
-
*
|
|
84
|
+
* IFrameWindowProxy.postMessage when it sees a `MessagePort` in the
|
|
85
|
+
* transferList. Returns the port-id placeholder that should be
|
|
86
|
+
* substituted into the outgoing payload.
|
|
85
87
|
*
|
|
86
88
|
* Marks the transferred port as detached locally and wires its
|
|
87
|
-
* surviving partner so the partner's
|
|
88
|
-
* the bridge
|
|
89
|
+
* surviving partner with a `BridgePortTransport` so the partner's
|
|
90
|
+
* postMessage routes back over the WebKit bridge instead of the
|
|
91
|
+
* (now-null) in-process partner.
|
|
89
92
|
*/
|
|
90
|
-
_registerTransferredPort(port:
|
|
91
|
-
/** @internal Called by
|
|
93
|
+
_registerTransferredPort(port: MessagePort): number;
|
|
94
|
+
/** @internal Called by MessagePort.postMessage when its partner
|
|
92
95
|
* was transferred to the WebView. Dispatches the data onto the
|
|
93
96
|
* WebView-side proxy port via evaluate_javascript. */
|
|
94
97
|
_sendPortMessage(portId: number, data: unknown): void;
|
|
95
|
-
/** @internal Called by
|
|
98
|
+
/** @internal Called by MessagePort.close to tear down the
|
|
96
99
|
* bridge-side registration. The WebView side keeps its proxy port
|
|
97
100
|
* alive in user-script land but subsequent .deliver calls go nowhere. */
|
|
98
101
|
_closePort(portId: number): void;
|
|
99
|
-
sendToWebView(data: unknown, targetOrigin: string, transfer?:
|
|
102
|
+
sendToWebView(data: unknown, targetOrigin: string, transfer?: MessagePort[]): void;
|
|
100
103
|
/** Clean up signal handlers */
|
|
101
104
|
destroy(): void;
|
|
102
105
|
/**
|
|
@@ -105,7 +108,7 @@ export declare class MessageBridge {
|
|
|
105
108
|
*/
|
|
106
109
|
private _setupReceiver;
|
|
107
110
|
/**
|
|
108
|
-
* Walk the user payload and replace each
|
|
111
|
+
* Walk the user payload and replace each MessagePort instance
|
|
109
112
|
* (transferred via the transferList) with a {__gjsifyPort: id}
|
|
110
113
|
* placeholder. Non-transferred ports are passed through untouched —
|
|
111
114
|
* matches W3C semantics where only ports in transferList are detached.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gjsify/iframe",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.13",
|
|
4
4
|
"description": "HTMLIFrameElement for GJS, backed by WebKit.WebView",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "lib/esm/index.js",
|
|
@@ -37,12 +37,13 @@
|
|
|
37
37
|
"@girs/gtk-4.0": "4.23.0-4.0.0-rc.15",
|
|
38
38
|
"@girs/javascriptcore-6.0": "2.52.1-4.0.0-rc.15",
|
|
39
39
|
"@girs/webkit-6.0": "2.52.1-4.0.0-rc.15",
|
|
40
|
-
"@gjsify/dom-elements": "^0.4.
|
|
41
|
-
"@gjsify/dom-events": "^0.4.
|
|
40
|
+
"@gjsify/dom-elements": "^0.4.13",
|
|
41
|
+
"@gjsify/dom-events": "^0.4.13",
|
|
42
|
+
"@gjsify/message-channel": "^0.4.13"
|
|
42
43
|
},
|
|
43
44
|
"devDependencies": {
|
|
44
|
-
"@gjsify/cli": "^0.4.
|
|
45
|
-
"@gjsify/unit": "^0.4.
|
|
45
|
+
"@gjsify/cli": "^0.4.13",
|
|
46
|
+
"@gjsify/unit": "^0.4.13",
|
|
46
47
|
"@types/node": "^25.6.2",
|
|
47
48
|
"typescript": "^6.0.3"
|
|
48
49
|
}
|