@@ -12,140 +12,11 @@ import {
1212
1313import { getCachedBlueReferences , linkUnforgeables , tameDOM } from './window' ;
1414
15- const IFRAME_SANDBOX_ATTRIBUTE_VALUE = 'allow-same-origin allow-scripts' ;
16-
17- const emptyArray : [ ] = [ ] ;
18- const {
19- close : DocumentProtoClose ,
20- createElement : DocumentProtoCreateElement ,
21- open : DocumentProtoOpen ,
22- } = document ;
23- const { remove : ElementProtoRemove , setAttribute : ElementProtoSetAttribute } = Element . prototype ;
24- const { appendChild : NodeProtoAppendChild } = Node . prototype ;
2515const { assign : ObjectAssign } = Object ;
26- const {
27- // eslint-disable-next-line @typescript-eslint/naming-convention
28- __lookupGetter__ : ObjectProto__lookupGetter__ ,
29- hasOwnProperty : ObjectProtoHasOwnProperty ,
30- } = Object . prototype as any ;
31- const { apply : ReflectApply } = Reflect ;
32-
33- function ObjectLookupOwnGetter ( obj : object , key : PropertyKey ) : Function | undefined {
34- // Since this function is only used internally, and would not otherwise be
35- // reachable by user code, istanbul can ignore test coverage for the
36- // following condition.
37- // istanbul ignore next
38- // eslint-disable-next-line @typescript-eslint/no-use-before-define
39- if ( obj === null || obj === undefined || ! ReflectApply ( ObjectProtoHasOwnProperty , obj , [ key ] ) ) {
40- return undefined ;
41- }
42- // eslint-disable-next-line @typescript-eslint/no-use-before-define
43- return ReflectApply ( ObjectProto__lookupGetter__ , obj , [ key ] ) ;
44- }
45-
46- const DocumentProtoBodyGetter = ObjectLookupOwnGetter ( Document . prototype , 'body' ) ! ;
47- const HTMLElementProtoStyleGetter = ObjectLookupOwnGetter ( HTMLElement . prototype , 'style' ) ! ;
48- const HTMLIFrameElementProtoContentWindowGetter = ObjectLookupOwnGetter (
49- HTMLIFrameElement . prototype ,
50- 'contentWindow'
51- ) ! ;
52- const NodeProtoIsConnectedGetter = ObjectLookupOwnGetter ( Node . prototype , 'isConnected' ) ! ;
53- const NodeProtoLastChildGetter = ObjectLookupOwnGetter ( Node . prototype , 'lastChild' ) ! ;
54-
55- function DocumentBody ( doc : Document ) : typeof Document . prototype . body {
56- return ReflectApply ( DocumentProtoBodyGetter , doc , emptyArray ) ;
57- }
58-
59- function DocumentClose ( doc : Document ) : ReturnType < typeof Document . prototype . close > {
60- return ReflectApply ( DocumentProtoClose , doc , emptyArray ) ;
61- }
62-
63- function DocumentCreateElement (
64- doc : Document ,
65- tagName : string
66- ) : ReturnType < typeof Document . prototype . createElement > {
67- return ReflectApply ( DocumentProtoCreateElement , doc , [ tagName ] ) ;
68- }
69-
70- function DocumentOpen ( doc : Document ) : ReturnType < typeof Document . prototype . open > {
71- return ReflectApply ( DocumentProtoOpen , doc , emptyArray ) ;
72- }
73-
74- function ElementSetAttribute (
75- el : Element ,
76- name : string ,
77- value : string
78- ) : ReturnType < typeof Element . prototype . setAttribute > {
79- return ReflectApply ( ElementProtoSetAttribute , el , [ name , value ] ) ;
80- }
81-
82- function ElementRemove ( element : Element ) : Element {
83- return ReflectApply ( ElementProtoRemove , element , emptyArray ) ;
84- }
85-
86- function HTMLElementStyleGetter ( el : HTMLElement ) : typeof HTMLElement . prototype . style {
87- return ReflectApply ( HTMLElementProtoStyleGetter , el , emptyArray ) ;
88- }
89-
90- function HTMLIFrameElementContentWindowGetter (
91- iframe : HTMLIFrameElement
92- ) : typeof HTMLIFrameElement . prototype . contentWindow {
93- return ReflectApply ( HTMLIFrameElementProtoContentWindowGetter , iframe , emptyArray ) ;
94- }
95-
96- function NodeAppendChild ( parent : Node , child : ChildNode ) : ChildNode {
97- return ReflectApply ( NodeProtoAppendChild , parent , [ child ] ) ;
98- }
99-
100- // It's impossible to test whether NodeLastChild(document) is reached
101- // in a normal Karma test environment, because the document will always
102- // have a body element. Ignore this in coverage reporting to
103- // avoid a penalty.
104- // istanbul ignore next
105- function NodeLastChild ( node : Node ) : typeof Node . prototype . lastChild {
106- return ReflectApply ( NodeProtoLastChildGetter , node , emptyArray ) ;
107- }
108-
109- function NodeIsConnected ( node : Node ) : boolean {
110- return ReflectApply ( NodeProtoIsConnectedGetter , node , emptyArray ) ;
111- }
112-
113- function createDetachableIframe ( ) : HTMLIFrameElement {
114- // @ts -ignore document global ref - in browsers
115- const iframe = DocumentCreateElement ( document , 'iframe' ) as HTMLIFrameElement ;
116- // It's impossible to test whether NodeLastChild(document) is reached
117- // in a normal Karma test environment. (See explanation above,
118- // at NodeLastChild definition.)
119- const parent = DocumentBody ( document ) || /* istanbul ignore next */ NodeLastChild ( document ) ;
120- const style = HTMLElementStyleGetter ( iframe ) ;
121- style . display = 'none' ;
122- ElementSetAttribute ( iframe , 'sandbox' , IFRAME_SANDBOX_ATTRIBUTE_VALUE ) ;
123- NodeAppendChild ( parent , iframe ) ;
124- return iframe ;
125- }
126-
127- function removeIframe ( iframe : HTMLIFrameElement ) {
128- // In Chrome debugger statements will be ignored when the iframe is removed
129- // from the document. Other browsers like Firefox and Safari work as expected.
130- // https://bugs.chromium.org/p/chromium/issues/detail?id=1015462
131-
132- // Because the detachable iframe is created, and then optionally removed, all
133- // within the execution of createVirtualEnvironment, there is no point in which
134- // test code can interfere with iframe element, or its prototype chain, in
135- // order to remove it from the DOM, or stub the isConnected accessor
136- // (the latter is already too late before createVirtualEnvironment is ever called).
137- // For this reason, ignore the lack of `else` path coverage.
138- //
139- // istanbul ignore else
140- if ( NodeIsConnected ( iframe ) ) {
141- ElementRemove ( iframe ) ;
142- }
143- }
14416
14517interface BrowserEnvironmentOptions {
14618 distortionCallback ?: DistortionCallback ;
14719 endowments ?: object ;
148- keepAlive ?: boolean ;
14920 support ?: SupportFlagsObject ;
15021 instrumentation ?: InstrumentationHooks ;
15122}
@@ -165,17 +36,16 @@ export default function createVirtualEnvironment(
16536 const options = ObjectAssign (
16637 {
16738 __proto__ : null ,
168- keepAlive : false ,
16939 } ,
17040 providedOptions
17141 ) ;
17242 // eslint-disable-next-line prefer-object-spread
173- const { distortionCallback, endowments = { } , keepAlive , support, instrumentation } = options ;
174- const iframe = createDetachableIframe ( ) ;
175- const redWindow = HTMLIFrameElementContentWindowGetter ( iframe ) ! . window ;
176- const { document : redDocument } = redWindow ;
43+ const { distortionCallback, endowments = { } , support, instrumentation } = options ;
44+ // @ts -ignore: TypeScript doesn't know what a ShadowRealm is yet.
45+ const shadowRealm = new ShadowRealm ( ) ;
46+ const shadowRealmEval = shadowRealm . evaluate . bind ( shadowRealm ) ;
17747 const blueConnector = createHooksCallback ;
178- const redConnector = createConnector ( redWindow . eval ) ;
48+ const redConnector = createConnector ( shadowRealmEval ) ;
17949 // Extract the global references and descriptors before any interference.
18050 const blueRefs = getCachedBlueReferences ( globalObjectVirtualizationTarget ) ;
18151 // Create a new environment.
@@ -190,15 +60,5 @@ export default function createVirtualEnvironment(
19060 linkIntrinsics ( env , globalObjectVirtualizationTarget ) ;
19161 linkUnforgeables ( env , globalObjectVirtualizationTarget ) ;
19262 tameDOM ( env , blueRefs , getResolvedShapeDescriptors ( globalObjectShape , endowments ) ) ;
193- // Once we get the iframe info ready, and all mapped, we can proceed
194- // to detach the iframe only if the keepAlive option isn't true.
195- if ( keepAlive !== true ) {
196- removeIframe ( iframe ) ;
197- } else {
198- // TODO: Temporary hack to preserve the document reference in Firefox.
199- // https://bugzilla.mozilla.org/show_bug.cgi?id=543435
200- DocumentOpen ( redDocument ) ;
201- DocumentClose ( redDocument ) ;
202- }
20363 return env ;
20464}
0 commit comments