@gjsify/iframe 0.21.0 → 0.23.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 +35 -0
- package/lib/esm/iframe-bridge.js +1 -1
- package/lib/esm/index.js +1 -1
- package/lib/esm/register.js +1 -0
- package/lib/types/iframe-bridge.d.ts +96 -6
- package/lib/types/register.d.ts +1 -0
- package/lib/types/register.spec.d.ts +3 -0
- package/package.json +13 -6
package/README.md
CHANGED
|
@@ -31,6 +31,41 @@ widget.iframeElement.srcdoc = '<h1>Hello</h1>';
|
|
|
31
31
|
window.set_child(widget);
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
+
## Globals
|
|
35
|
+
|
|
36
|
+
The package root is a **side-effect-free barrel** — importing it gives you named
|
|
37
|
+
exports and nothing else. The DOM wiring lives in the dedicated `/register`
|
|
38
|
+
subpath:
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
import '@gjsify/iframe/register';
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
It does two things:
|
|
45
|
+
|
|
46
|
+
- installs `globalThis.HTMLIFrameElement` (guarded — a global that already exists wins);
|
|
47
|
+
- registers the `'iframe'` element factory, so `document.createElement('iframe')`
|
|
48
|
+
returns a WebKit-backed `HTMLIFrameElement`.
|
|
49
|
+
|
|
50
|
+
You normally never write that import: `gjsify build` defaults to `--globals auto`,
|
|
51
|
+
which detects a free `HTMLIFrameElement` reference in the bundled output and injects
|
|
52
|
+
the subpath for you. Application and example code should rely on that (see the
|
|
53
|
+
tree-shakeable-globals convention in `AGENTS.md`).
|
|
54
|
+
|
|
55
|
+
`IFrameBridge` itself needs neither — it constructs its `HTMLIFrameElement`
|
|
56
|
+
directly — so `new IFrameBridge()` works with `--globals none`. If you want the
|
|
57
|
+
DOM surface unconditionally (overriding whatever is there), the bridge exposes the
|
|
58
|
+
explicit, imperative counterpart, which installs exactly the same pair:
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
widget.installGlobals(); // globalThis.HTMLIFrameElement + the 'iframe' element factory
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
> **Changed after 0.22.0** — up to and including 0.22.0, `import { IFrameBridge } from '@gjsify/iframe'`
|
|
65
|
+
> installed `globalThis.HTMLIFrameElement` and the `'iframe'` element factory as an
|
|
66
|
+
> import side effect. See
|
|
67
|
+
> [ADR 0012](https://github.com/gjsify/gjsify/blob/main/docs/adr/0012-framework-register-ownership.md).
|
|
68
|
+
|
|
34
69
|
## License
|
|
35
70
|
|
|
36
71
|
MIT
|
package/lib/esm/iframe-bridge.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./_virtual/_rolldown/runtime.js";import{buildClickElementExpression as e,buildGetLinksExpression as t,buildQueryDomExpression as n}from"./dom-queries.js";import{buildEvalScript as r,parseEvalResult as i}from"./eval.js";import{iframeWidget as a,windowProxy as o}from"./property-symbol.js";import{HTMLIFrameElement as s}from"./html-iframe-element.js";import{IFrameWindowProxy as c}from"./iframe-window-proxy.js";import"./promisify.js";import{MessageBridge as l}from"./message-bridge.js";import{notifyElementResize as
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{buildClickElementExpression as e,buildGetLinksExpression as t,buildQueryDomExpression as n}from"./dom-queries.js";import{buildEvalScript as r,parseEvalResult as i}from"./eval.js";import{iframeWidget as a,windowProxy as o}from"./property-symbol.js";import{HTMLIFrameElement as s}from"./html-iframe-element.js";import{IFrameWindowProxy as c}from"./iframe-window-proxy.js";import"./promisify.js";import{MessageBridge as l}from"./message-bridge.js";import{Document as u,notifyElementResize as d}from"@gjsify/dom-elements";import f from"gi://GLib?version=2.0";import p from"gi://GObject";import m from"gi://WebKit?version=6.0";const h=p.registerClass({GTypeName:`GjsifyIFrameBridge`},class IFrameBridge extends m.WebView{constructor(e){let{enableDeveloperExtras:t,enableJavascript:n,captureConsole:r,...i}=e??{},u=new m.UserContentManager,d=new m.Settings;d.enable_javascript=n??!0,d.enable_developer_extras=t??!0,super({...i,user_content_manager:u,settings:d}),this._readyCallbacks=[],this._navigationWaiters=[],this._lastLoadError=null,this._loadErrorCallbacks=[],this._options={enableDeveloperExtras:t,enableJavascript:n,captureConsole:r},this._iframe=new s,this._iframe[a]=this,this._messageBridge=new l(this,{captureConsole:r});let f=new c(this._messageBridge);this._iframe[o]=f,this._messageBridge.setWindowProxy(f),this.connect(`load-changed`,(e,t)=>{switch(t){case m.LoadEvent.STARTED:this._lastLoadError=null;break;case m.LoadEvent.COMMITTED:{let e=this.get_uri();e&&this._messageBridge.updateUri(e);break}case m.LoadEvent.FINISHED:this._iframe._onLoad();for(let e of this._readyCallbacks)e(this._iframe);this._readyCallbacks=[],this._settleNavigationWaiters(null);break}}),this.connect(`load-failed`,(e,t,n,r)=>{let i={uri:n,message:r?.message??`load failed`};this._lastLoadError=i;for(let e of this._loadErrorCallbacks)e(i);return this._iframe._onError(),this._settleNavigationWaiters(Error(`load failed for ${n}: ${i.message}`)),!1}),this.connect(`unrealize`,()=>{this._messageBridge.destroy();let e=this._iframe[o];e&&e._close(),this._iframe[a]=null,this._iframe[o]=null})}vfunc_size_allocate(e,t,n){super.vfunc_size_allocate(e,t,n),d(this._iframe,e,t)}get iframeElement(){return this._iframe}onReady(e){this._readyCallbacks.push(e)}loadUri(e){this._iframe.setAttribute(`src`,e),this.load_uri(e)}loadHtml(e,t){this._iframe.setAttribute(`srcdoc`,e),this.load_html(e,t??`about:srcdoc`)}postMessage(e,t=`*`){this._messageBridge.sendToWebView(e,t)}goBack(){this.go_back()}goForward(){this.go_forward()}get canGoBack(){return this.can_go_back()}get canGoForward(){return this.can_go_forward()}get currentUri(){return this.get_uri()??`about:blank`}get pageTitle(){return this.get_title()??``}get lastLoadError(){return this._lastLoadError}onLoadError(e){this._loadErrorCallbacks.push(e)}async evaluateJavaScript(e){return i((await this.evaluate_javascript(r(e),-1,null,null,null))?.to_string()??null)}async takeScreenshot(e=`full`){let t=e===`visible`?m.SnapshotRegion.VISIBLE:m.SnapshotRegion.FULL_DOCUMENT,n=(await this.get_snapshot(t,m.SnapshotOptions.NONE,null)).save_to_png_bytes().get_data();return n?new Uint8Array(n):new Uint8Array}waitForNavigation(e=3e4){return new Promise((t,n)=>{let r={resolve:t,reject:n,sourceId:null};e>0&&(r.sourceId=f.timeout_add(f.PRIORITY_DEFAULT,e,()=>{let t=this._navigationWaiters.indexOf(r);return t!==-1&&this._navigationWaiters.splice(t,1),r.sourceId=null,n(Error(`waitForNavigation: timed out after ${e}ms`)),f.SOURCE_REMOVE})),this._navigationWaiters.push(r)})}_settleNavigationWaiters(e){if(this._navigationWaiters.length===0)return;let t=this._navigationWaiters;this._navigationWaiters=[];for(let n of t)n.sourceId!==null&&(f.source_remove(n.sourceId),n.sourceId=null),e?n.reject(e):n.resolve()}getViewportSize(){return{width:this.get_allocated_width(),height:this.get_allocated_height()}}setViewportSize(e,t){this.set_size_request(e,t)}getConsoleLogs(){return this._messageBridge.getConsoleLogs()}clearConsoleLogs(){this._messageBridge.clearConsoleLogs()}onConsole(e){this._messageBridge.onConsole(e)}async getLinks(){let e=await this.evaluateJavaScript(t());return Array.isArray(e)?e:[]}async queryDom(e,t=200){let r=await this.evaluateJavaScript(n(e,t));return Array.isArray(r)?r:[]}async clickElement(t){return await this.evaluateJavaScript(e(t))===!0}installGlobals(){u.registerElementFactory(`iframe`,()=>new s),Object.defineProperty(globalThis,"HTMLIFrameElement",{value:s,writable:!0,configurable:!0})}});export{h as IFrameBridge};
|
package/lib/esm/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
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";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};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{HTMLIFrameElement as e}from"./html-iframe-element.js";import{Document as t}from"@gjsify/dom-elements";t.registerElementFactory(`iframe`,()=>new e),globalThis.HTMLIFrameElement===void 0&&Object.defineProperty(globalThis,"HTMLIFrameElement",{value:e,writable:!0,configurable:!0});
|
|
@@ -180,7 +180,22 @@ export declare const IFrameBridge: {
|
|
|
180
180
|
*/
|
|
181
181
|
clickElement(selectorOrText: string): Promise<boolean>;
|
|
182
182
|
/**
|
|
183
|
-
*
|
|
183
|
+
* Install the iframe DOM surface imperatively: sets
|
|
184
|
+
* `globalThis.HTMLIFrameElement` to the gjsify implementation AND registers
|
|
185
|
+
* the `'iframe'` element factory so `document.createElement('iframe')`
|
|
186
|
+
* returns it.
|
|
187
|
+
*
|
|
188
|
+
* This is the same pair `@gjsify/iframe/register` installs — the explicit,
|
|
189
|
+
* unconditional counterpart of the tree-shakeable `/register` subpath (which
|
|
190
|
+
* `--globals auto` injects when it sees a free `HTMLIFrameElement`). Both are
|
|
191
|
+
* needed here: the element factory used to come along for free with the
|
|
192
|
+
* barrel's import side effect, and app code that calls `installGlobals()` and
|
|
193
|
+
* then `document.createElement('iframe')` must keep working (ADR 0012 moved
|
|
194
|
+
* the side effect out of `index.ts`; it did not remove the capability).
|
|
195
|
+
*
|
|
196
|
+
* Unconditional by design — an explicit call means "make MY implementation
|
|
197
|
+
* the one `document` and `globalThis` hand out", so it overrides whatever is
|
|
198
|
+
* already installed.
|
|
184
199
|
*/
|
|
185
200
|
installGlobals(): void;
|
|
186
201
|
get automation_presentation_type(): WebKit.AutomationBrowsingContextPresentation;
|
|
@@ -882,7 +897,22 @@ export declare const IFrameBridge: {
|
|
|
882
897
|
*/
|
|
883
898
|
clickElement(selectorOrText: string): Promise<boolean>;
|
|
884
899
|
/**
|
|
885
|
-
*
|
|
900
|
+
* Install the iframe DOM surface imperatively: sets
|
|
901
|
+
* `globalThis.HTMLIFrameElement` to the gjsify implementation AND registers
|
|
902
|
+
* the `'iframe'` element factory so `document.createElement('iframe')`
|
|
903
|
+
* returns it.
|
|
904
|
+
*
|
|
905
|
+
* This is the same pair `@gjsify/iframe/register` installs — the explicit,
|
|
906
|
+
* unconditional counterpart of the tree-shakeable `/register` subpath (which
|
|
907
|
+
* `--globals auto` injects when it sees a free `HTMLIFrameElement`). Both are
|
|
908
|
+
* needed here: the element factory used to come along for free with the
|
|
909
|
+
* barrel's import side effect, and app code that calls `installGlobals()` and
|
|
910
|
+
* then `document.createElement('iframe')` must keep working (ADR 0012 moved
|
|
911
|
+
* the side effect out of `index.ts`; it did not remove the capability).
|
|
912
|
+
*
|
|
913
|
+
* Unconditional by design — an explicit call means "make MY implementation
|
|
914
|
+
* the one `document` and `globalThis` hand out", so it overrides whatever is
|
|
915
|
+
* already installed.
|
|
886
916
|
*/
|
|
887
917
|
installGlobals(): void;
|
|
888
918
|
get automation_presentation_type(): WebKit.AutomationBrowsingContextPresentation;
|
|
@@ -1584,7 +1614,22 @@ export declare const IFrameBridge: {
|
|
|
1584
1614
|
*/
|
|
1585
1615
|
clickElement(selectorOrText: string): Promise<boolean>;
|
|
1586
1616
|
/**
|
|
1587
|
-
*
|
|
1617
|
+
* Install the iframe DOM surface imperatively: sets
|
|
1618
|
+
* `globalThis.HTMLIFrameElement` to the gjsify implementation AND registers
|
|
1619
|
+
* the `'iframe'` element factory so `document.createElement('iframe')`
|
|
1620
|
+
* returns it.
|
|
1621
|
+
*
|
|
1622
|
+
* This is the same pair `@gjsify/iframe/register` installs — the explicit,
|
|
1623
|
+
* unconditional counterpart of the tree-shakeable `/register` subpath (which
|
|
1624
|
+
* `--globals auto` injects when it sees a free `HTMLIFrameElement`). Both are
|
|
1625
|
+
* needed here: the element factory used to come along for free with the
|
|
1626
|
+
* barrel's import side effect, and app code that calls `installGlobals()` and
|
|
1627
|
+
* then `document.createElement('iframe')` must keep working (ADR 0012 moved
|
|
1628
|
+
* the side effect out of `index.ts`; it did not remove the capability).
|
|
1629
|
+
*
|
|
1630
|
+
* Unconditional by design — an explicit call means "make MY implementation
|
|
1631
|
+
* the one `document` and `globalThis` hand out", so it overrides whatever is
|
|
1632
|
+
* already installed.
|
|
1588
1633
|
*/
|
|
1589
1634
|
installGlobals(): void;
|
|
1590
1635
|
get automation_presentation_type(): WebKit.AutomationBrowsingContextPresentation;
|
|
@@ -2286,7 +2331,22 @@ export declare const IFrameBridge: {
|
|
|
2286
2331
|
*/
|
|
2287
2332
|
clickElement(selectorOrText: string): Promise<boolean>;
|
|
2288
2333
|
/**
|
|
2289
|
-
*
|
|
2334
|
+
* Install the iframe DOM surface imperatively: sets
|
|
2335
|
+
* `globalThis.HTMLIFrameElement` to the gjsify implementation AND registers
|
|
2336
|
+
* the `'iframe'` element factory so `document.createElement('iframe')`
|
|
2337
|
+
* returns it.
|
|
2338
|
+
*
|
|
2339
|
+
* This is the same pair `@gjsify/iframe/register` installs — the explicit,
|
|
2340
|
+
* unconditional counterpart of the tree-shakeable `/register` subpath (which
|
|
2341
|
+
* `--globals auto` injects when it sees a free `HTMLIFrameElement`). Both are
|
|
2342
|
+
* needed here: the element factory used to come along for free with the
|
|
2343
|
+
* barrel's import side effect, and app code that calls `installGlobals()` and
|
|
2344
|
+
* then `document.createElement('iframe')` must keep working (ADR 0012 moved
|
|
2345
|
+
* the side effect out of `index.ts`; it did not remove the capability).
|
|
2346
|
+
*
|
|
2347
|
+
* Unconditional by design — an explicit call means "make MY implementation
|
|
2348
|
+
* the one `document` and `globalThis` hand out", so it overrides whatever is
|
|
2349
|
+
* already installed.
|
|
2290
2350
|
*/
|
|
2291
2351
|
installGlobals(): void;
|
|
2292
2352
|
get automation_presentation_type(): WebKit.AutomationBrowsingContextPresentation;
|
|
@@ -2988,7 +3048,22 @@ export declare const IFrameBridge: {
|
|
|
2988
3048
|
*/
|
|
2989
3049
|
clickElement(selectorOrText: string): Promise<boolean>;
|
|
2990
3050
|
/**
|
|
2991
|
-
*
|
|
3051
|
+
* Install the iframe DOM surface imperatively: sets
|
|
3052
|
+
* `globalThis.HTMLIFrameElement` to the gjsify implementation AND registers
|
|
3053
|
+
* the `'iframe'` element factory so `document.createElement('iframe')`
|
|
3054
|
+
* returns it.
|
|
3055
|
+
*
|
|
3056
|
+
* This is the same pair `@gjsify/iframe/register` installs — the explicit,
|
|
3057
|
+
* unconditional counterpart of the tree-shakeable `/register` subpath (which
|
|
3058
|
+
* `--globals auto` injects when it sees a free `HTMLIFrameElement`). Both are
|
|
3059
|
+
* needed here: the element factory used to come along for free with the
|
|
3060
|
+
* barrel's import side effect, and app code that calls `installGlobals()` and
|
|
3061
|
+
* then `document.createElement('iframe')` must keep working (ADR 0012 moved
|
|
3062
|
+
* the side effect out of `index.ts`; it did not remove the capability).
|
|
3063
|
+
*
|
|
3064
|
+
* Unconditional by design — an explicit call means "make MY implementation
|
|
3065
|
+
* the one `document` and `globalThis` hand out", so it overrides whatever is
|
|
3066
|
+
* already installed.
|
|
2992
3067
|
*/
|
|
2993
3068
|
installGlobals(): void;
|
|
2994
3069
|
get automation_presentation_type(): WebKit.AutomationBrowsingContextPresentation;
|
|
@@ -3690,7 +3765,22 @@ export declare const IFrameBridge: {
|
|
|
3690
3765
|
*/
|
|
3691
3766
|
clickElement(selectorOrText: string): Promise<boolean>;
|
|
3692
3767
|
/**
|
|
3693
|
-
*
|
|
3768
|
+
* Install the iframe DOM surface imperatively: sets
|
|
3769
|
+
* `globalThis.HTMLIFrameElement` to the gjsify implementation AND registers
|
|
3770
|
+
* the `'iframe'` element factory so `document.createElement('iframe')`
|
|
3771
|
+
* returns it.
|
|
3772
|
+
*
|
|
3773
|
+
* This is the same pair `@gjsify/iframe/register` installs — the explicit,
|
|
3774
|
+
* unconditional counterpart of the tree-shakeable `/register` subpath (which
|
|
3775
|
+
* `--globals auto` injects when it sees a free `HTMLIFrameElement`). Both are
|
|
3776
|
+
* needed here: the element factory used to come along for free with the
|
|
3777
|
+
* barrel's import side effect, and app code that calls `installGlobals()` and
|
|
3778
|
+
* then `document.createElement('iframe')` must keep working (ADR 0012 moved
|
|
3779
|
+
* the side effect out of `index.ts`; it did not remove the capability).
|
|
3780
|
+
*
|
|
3781
|
+
* Unconditional by design — an explicit call means "make MY implementation
|
|
3782
|
+
* the one `document` and `globalThis` hand out", so it overrides whatever is
|
|
3783
|
+
* already installed.
|
|
3694
3784
|
*/
|
|
3695
3785
|
installGlobals(): void;
|
|
3696
3786
|
get automation_presentation_type(): WebKit.AutomationBrowsingContextPresentation;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gjsify/iframe",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.23.0",
|
|
4
4
|
"description": "HTMLIFrameElement for GJS, backed by WebKit.WebView",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "lib/esm/index.js",
|
|
@@ -9,8 +9,15 @@
|
|
|
9
9
|
".": {
|
|
10
10
|
"types": "./lib/types/index.d.ts",
|
|
11
11
|
"default": "./lib/esm/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./register": {
|
|
14
|
+
"types": "./lib/types/register.d.ts",
|
|
15
|
+
"default": "./lib/esm/register.js"
|
|
12
16
|
}
|
|
13
17
|
},
|
|
18
|
+
"sideEffects": [
|
|
19
|
+
"./lib/esm/register.js"
|
|
20
|
+
],
|
|
14
21
|
"files": [
|
|
15
22
|
"lib"
|
|
16
23
|
],
|
|
@@ -38,13 +45,13 @@
|
|
|
38
45
|
"@girs/gtk-4.0": "^4.1.0",
|
|
39
46
|
"@girs/javascriptcore-6.0": "^4.1.0",
|
|
40
47
|
"@girs/webkit-6.0": "^4.1.0",
|
|
41
|
-
"@gjsify/dom-elements": "^0.
|
|
42
|
-
"@gjsify/dom-events": "^0.
|
|
43
|
-
"@gjsify/message-channel": "^0.
|
|
48
|
+
"@gjsify/dom-elements": "^0.23.0",
|
|
49
|
+
"@gjsify/dom-events": "^0.23.0",
|
|
50
|
+
"@gjsify/message-channel": "^0.23.0"
|
|
44
51
|
},
|
|
45
52
|
"devDependencies": {
|
|
46
|
-
"@gjsify/cli": "^0.
|
|
47
|
-
"@gjsify/unit": "^0.
|
|
53
|
+
"@gjsify/cli": "^0.23.0",
|
|
54
|
+
"@gjsify/unit": "^0.23.0",
|
|
48
55
|
"@types/node": "^25.9.2",
|
|
49
56
|
"typescript": "^6.0.3"
|
|
50
57
|
},
|