@@ -108,73 +108,79 @@ function createScopedEvaluatorFactory(unsafeRec, constants) {
108
108
` ) ;
109
109
}
110
110
111
- export function createSafeEvaluator ( unsafeRec , safeGlobal ) {
111
+ export function createSafeEvaluatorFactory ( unsafeRec , safeGlobal ) {
112
112
const { unsafeFunction } = unsafeRec ;
113
113
114
- // This proxy has several functions:
115
- // 1. works with the sentinel to alternate between direct eval and confined eval.
116
- // 2. shadows all properties of the unsafe global by declaring them as undefined.
117
- // 3. resolves all existing properties of the safe global.
118
- // 4. uses an empty object as the target, with the safe global as its prototype,
119
- // to bypass a proxy invariant that would prevent alternating between different
120
- // values of eval if the user was to freeze the eval property on the safe global.
121
114
const scopeHandler = new ScopeHandler ( unsafeRec ) ;
122
- const scopeTarget = create ( safeGlobal ) ;
123
- const scopeProxy = new Proxy ( scopeTarget , scopeHandler ) ;
124
-
125
115
const optimizableGlobals = getOptimizableGlobals ( safeGlobal ) ;
126
116
const scopedEvaluatorFactory = createScopedEvaluatorFactory ( unsafeRec , optimizableGlobals ) ;
127
- const scopedEvaluator = scopedEvaluatorFactory ( scopeProxy ) ;
128
-
129
- // We use the the concise method syntax to create an eval without a
130
- // [[Construct]] behavior (such that the invocation "new eval()" throws
131
- // TypeError: eval is not a constructor"), but which still accepts a 'this'
132
- // binding.
133
- const safeEval = {
134
- eval ( src ) {
135
- src = `${ src } ` ;
136
- rejectImportExpressions ( src ) ;
137
- scopeHandler . useUnsafeEvaluator = true ;
138
- let err ;
139
- try {
140
- // Ensure that "this" resolves to the safe global.
141
- return apply ( scopedEvaluator , safeGlobal , [ src ] ) ;
142
- } catch ( e ) {
143
- // stash the child-code error in hopes of debugging the internal failure
144
- err = e ;
145
- throw e ;
146
- } finally {
147
- // belt and suspenders: the proxy switches this off immediately after
148
- // the first access, but just in case we clear it here too
149
- if ( scopeHandler . useUnsafeEvaluator !== false ) {
150
- scopeHandler . useUnsafeEvaluator = false ;
151
- throwTantrum ( 'handler sets useUnsafeEvaluator = false' , err ) ;
117
+
118
+ function factory ( endowments ) {
119
+ const scopeTarget = create ( safeGlobal , getOwnPropertyDescriptors ( endowments ) ) ;
120
+ const scopeProxy = new Proxy ( scopeTarget , scopeHandler ) ;
121
+ const scopedEvaluator = scopedEvaluatorFactory ( scopeProxy ) ;
122
+
123
+ // We use the the concise method syntax to create an eval without a
124
+ // [[Construct]] behavior (such that the invocation "new eval()" throws
125
+ // TypeError: eval is not a constructor"), but which still accepts a
126
+ // 'this' binding.
127
+ const safeEval = {
128
+ eval ( src ) {
129
+ src = `${ src } ` ;
130
+ rejectImportExpressions ( src ) ;
131
+ scopeHandler . useUnsafeEvaluator = true ;
132
+ let err ;
133
+ try {
134
+ // Ensure that "this" resolves to the safe global.
135
+ return apply ( scopedEvaluator , safeGlobal , [ src ] ) ;
136
+ } catch ( e ) {
137
+ // stash the child-code error in hopes of debugging the internal failure
138
+ err = e ;
139
+ throw e ;
140
+ } finally {
141
+ // belt and suspenders: the proxy switches this off immediately after
142
+ // the first access, but just in case we clear it here too
143
+ if ( scopeHandler . useUnsafeEvaluator !== false ) {
144
+ scopeHandler . useUnsafeEvaluator = false ;
145
+ throwTantrum ( 'handler sets useUnsafeEvaluator = false' , err ) ;
146
+ }
152
147
}
153
148
}
154
- }
155
- } . eval ;
149
+ } . eval ;
156
150
157
- // safeEval's prototype is currently the primal realm's Function.prototype,
158
- // which we must not let escape. To make 'eval instanceof Function' be true
159
- // inside the realm, we need to point it at the RootRealm's value.
151
+ // safeEval's prototype is currently the primal realm's
152
+ // Function.prototype, which we must not let escape. To make 'eval
153
+ // instanceof Function' be true inside the realm, we need to point it at
154
+ // the RootRealm's value.
160
155
161
- // Ensure that eval from any compartment in a root realm is an
162
- // instance of Function in any compartment of the same root realm.
163
- setPrototypeOf ( safeEval , unsafeFunction . prototype ) ;
156
+ // Ensure that eval from any compartment in a root realm is an instance
157
+ // of Function in any compartment of the same root realm.
158
+ setPrototypeOf ( safeEval , unsafeFunction . prototype ) ;
164
159
165
- assert ( getPrototypeOf ( safeEval ) . constructor !== Function , 'hide Function' ) ;
166
- assert ( getPrototypeOf ( safeEval ) . constructor !== unsafeFunction , 'hide unsafeFunction' ) ;
160
+ assert ( getPrototypeOf ( safeEval ) . constructor !== Function , 'hide Function' ) ;
161
+ assert ( getPrototypeOf ( safeEval ) . constructor !== unsafeFunction , 'hide unsafeFunction' ) ;
167
162
168
- // note: be careful to not leak our primal Function.prototype by setting
169
- // this to a plain arrow function. Now that we have safeEval, use it.
170
- defineProperty ( safeEval , 'toString' , {
171
- value : safeEval ( "() => 'function eval() { [shim code] }'" ) ,
172
- writable : false ,
173
- enumerable : false ,
174
- configurable : true
175
- } ) ;
163
+ // note: be careful to not leak our primal Function.prototype by setting
164
+ // this to a plain arrow function. Now that we have safeEval, use it.
165
+ defineProperty ( safeEval , 'toString' , {
166
+ value : safeEval ( "() => 'function eval() { [shim code] }'" ) ,
167
+ writable : false ,
168
+ enumerable : false ,
169
+ configurable : true
170
+ } ) ;
171
+
172
+ return safeEval ;
173
+ }
174
+
175
+ return factory ;
176
+ }
177
+
178
+ export function createSafeEvaluator ( safeEvaluatorFactory ) {
179
+ return safeEvaluatorFactory ( { } ) ;
180
+ }
176
181
177
- return safeEval ;
182
+ export function createSafeEvaluatorWhichTakesEndowments ( safeEvaluatorFactory ) {
183
+ return ( x , endowments ) => safeEvaluatorFactory ( endowments ) ( x ) ;
178
184
}
179
185
180
186
/**
0 commit comments