@@ -24,17 +24,61 @@ if (location.protocol == "file:") {
2424 const { exportFunction, patchWindow} = Worlds . main ;
2525
2626 function modifyWindow ( scope , { port, xray} ) {
27- const { window} = xray ;
27+ const { window } = xray ;
28+ const { Proxy, document } = window ;
29+
30+ const { Reflect } = globalThis ;
2831
29- const { Proxy } = window ;
3032 const { addEventListener } = window . EventTarget . prototype ;
33+ const nodeProps = { } ;
34+ for ( const prop of [ "ownerDocument" , "parentNode" , "nextSibling" ] ) {
35+ nodeProps [ prop ] = xray . getSafeDescriptor ( Node . prototype , prop , "get" ) . get ;
36+ }
37+ for ( const method of [ "insertBefore" , "removeChild" ] ) {
38+ nodeProps [ method ] = Node . prototype [ method ] ;
39+ }
40+ const adoptNode = document . adoptNode ;
41+ const getDocumentElement = xray . getSafeDescriptor ( Document . prototype , "documentElement" , "get" ) . get ;
3142
3243 const watchList = new WeakSet ( ) ;
3344
45+ const NO_ARGS = [ ] ;
46+ const call = ( func , obj , ...args ) => Reflect . apply ( func , obj , args || NO_ARGS ) ;
47+
3448 const watch = watching => {
3549 if ( ! watchList . has ( watching ) ) {
36- port . postMessage ( { watching} ) ;
37- watchList . add ( watching ) ;
50+ const ownerDocument = call ( nodeProps . ownerDocument , watching ) ;
51+ const crossDoc = ownerDocument != document ;
52+ const parentNode = call ( nodeProps . parentNode , watching ) ;
53+
54+ if ( ! crossDoc && parentNode ) {
55+ // Nothing to do: eventHook.js' MutationObserver should kick in
56+ return ;
57+ }
58+
59+ if ( xray . enabled ) {
60+ port . postMessage ( { watching} ) ;
61+ watchList . add ( watching ) ;
62+ return ;
63+ }
64+
65+ // Chromium cannot marshall DOM nodes in port.postMessage():
66+ // following hack triggers eventHook.js' mutation observer instead.
67+
68+ const nextSibling = call ( nodeProps . nextSibling , watching ) ;
69+ if ( crossDoc ) {
70+ call ( adoptNode , document , watching ) ;
71+ }
72+ const documentElement = call ( getDocumentElement , document ) ;
73+ call ( nodeProps . insertBefore , documentElement , watching , null ) ;
74+ call ( nodeProps . removeChild , documentElement , watching ) ;
75+ if ( crossDoc ) {
76+ // put the node back at its place in its document
77+ call ( adoptNode , ownerDocument , watching ) ;
78+ if ( parentNode ) {
79+ call ( nodeProps . insertBefore , ownerDocument , watching , nextSibling ) ;
80+ }
81+ }
3882 }
3983 }
4084
0 commit comments