@@ -5,49 +5,51 @@ import { ScramjetClient } from "@client/index";
55import { indirectEval } from "@client/shared/eval" ;
66
77export function createWrapFn ( client : ScramjetClient , self : typeof globalThis ) {
8+ let wrappedParent : typeof globalThis | null = null ;
9+ let wrappedTop : typeof globalThis | null = null ;
10+ if ( iswindow ) {
11+ try {
12+ if ( SCRAMJETCLIENT in self . parent ) {
13+ // ... then we're in a subframe, and the parent frame is also in a proxy context, so we should return its proxy
14+ wrappedParent = self . parent ;
15+ } else {
16+ // ... then we should pretend we aren't nested and return the current window
17+ wrappedParent = self ;
18+ }
19+ } catch {
20+ // accessing self.parent can throw if it's cross-origin, in which case we should also pretend we aren't nested
21+ wrappedParent = self ;
22+ }
23+ // instead of returning top, we need to return the uppermost parent that's inside a scramjet context
24+ let current = self ;
25+ for ( ; ; ) {
26+ const test = current . parent . self ;
27+ if ( test === current ) break ; // there is no parent, actual or emulated.
28+
29+ try {
30+ // ... then `test` represents a window outside of the proxy context, and therefore `current` is the topmost window in the proxy context
31+ if ( ! ( SCRAMJETCLIENT in test ) ) break ;
32+ } catch {
33+ // accessing test can throw if it's cross-origin, in which case we should also break
34+ break ;
35+ }
36+ // test is also insde a proxy, so we should continue up the chain
37+ current = test ;
38+ }
39+ wrappedTop = current ;
40+ }
41+
842 return function ( identifier : any , strict : boolean ) {
943 if ( identifier === self . location ) return client . locationProxy ;
1044 if ( identifier === self . eval ) return indirectEval . bind ( client , strict ) ;
11-
12- // TODO only do this once on init. a page can't suddenly gain a parent i don't think
1345 if ( iswindow ) {
1446 if ( identifier === self . parent ) {
15- try {
16- if ( SCRAMJETCLIENT in self . parent ) {
17- // ... then we're in a subframe, and the parent frame is also in a proxy context, so we should return its proxy
18- return self . parent ;
19- } else {
20- // ... then we should pretend we aren't nested and return the current window
21- return self ;
22- }
23- } catch {
24- // accessing self.parent can throw if it's cross-origin, in which case we should also pretend we aren't nested
25- return self ;
26- }
27- } else if ( identifier === self . top ) {
28- // instead of returning top, we need to return the uppermost parent that's inside a scramjet context
29- let current = self ;
30-
31- for ( ; ; ) {
32- const test = current . parent . self ;
33- if ( test === current ) break ; // there is no parent, actual or emulated.
34-
35- try {
36- // ... then `test` represents a window outside of the proxy context, and therefore `current` is the topmost window in the proxy context
37- if ( ! ( SCRAMJETCLIENT in test ) ) break ;
38- } catch {
39- // accessing test can throw if it's cross-origin, in which case we should also break
40- break ;
41- }
42-
43- // test is also insde a proxy, so we should continue up the chain
44- current = test ;
45- }
46-
47- return current ;
47+ return wrappedParent ;
48+ }
49+ else if ( identifier === self . top ) {
50+ return wrappedTop ;
4851 }
4952 }
50-
5153 return identifier ;
5254 } ;
5355}
0 commit comments