1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "builtin/ShadowRealm.h"
9 #include "mozilla/Assertions.h"
12 #include "jsfriendapi.h"
13 #include "builtin/ModuleObject.h"
14 #include "builtin/Promise.h"
15 #include "builtin/WrappedFunctionObject.h"
16 #include "frontend/BytecodeCompiler.h" // CompileEvalScript
17 #include "js/ErrorReport.h"
18 #include "js/Exception.h"
19 #include "js/GlobalObject.h"
20 #include "js/Principals.h"
21 #include "js/Promise.h"
22 #include "js/PropertyAndElement.h"
23 #include "js/PropertyDescriptor.h"
24 #include "js/ShadowRealmCallbacks.h"
25 #include "js/SourceText.h"
26 #include "js/StableStringChars.h"
27 #include "js/StructuredClone.h"
28 #include "js/TypeDecls.h"
29 #include "js/Wrapper.h"
30 #include "vm/GlobalObject.h"
31 #include "vm/Interpreter.h"
32 #include "vm/JSObject.h"
33 #include "vm/ObjectOperations.h"
35 #include "builtin/HandlerFunction-inl.h"
36 #include "vm/Compartment-inl.h"
37 #include "vm/JSObject-inl.h"
38 #include "vm/Realm-inl.h"
42 using JS::AutoStableStringChars
;
43 using JS::CompileOptions
;
44 using JS::SourceOwnership
;
47 static JSObject
* DefaultNewShadowRealmGlobal(JSContext
* cx
,
48 JS::RealmOptions
& options
,
49 JSPrincipals
* principals
,
50 Handle
<JSObject
*> unused
) {
51 static const JSClass shadowRealmGlobal
= {
52 "ShadowRealmGlobal", JSCLASS_GLOBAL_FLAGS
, &JS::DefaultGlobalClassOps
};
54 return JS_NewGlobalObject(cx
, &shadowRealmGlobal
, principals
,
55 JS::FireOnNewGlobalHook
, options
);
58 // https://tc39.es/proposal-shadowrealm/#sec-shadowrealm-constructor
60 bool ShadowRealmObject::construct(JSContext
* cx
, unsigned argc
, Value
* vp
) {
61 CallArgs args
= CallArgsFromVp(argc
, vp
);
63 // Step 1. If NewTarget is undefined, throw a TypeError exception.
64 if (!args
.isConstructing()) {
65 JS_ReportErrorNumberASCII(cx
, GetErrorMessage
, nullptr,
66 JSMSG_NOT_CONSTRUCTOR
, "ShadowRealm");
70 // Step 2. Let O be ? OrdinaryCreateFromConstructor(NewTarget,
71 // "%ShadowRealm.prototype%", « [[ShadowRealm]], [[ExecutionContext]] »).
72 Rooted
<JSObject
*> proto(cx
);
73 if (!GetPrototypeFromBuiltinConstructor(cx
, args
, JSProto_ShadowRealm
,
78 Rooted
<ShadowRealmObject
*> shadowRealmObj(
79 cx
, NewObjectWithClassProto
<ShadowRealmObject
>(cx
, proto
));
80 if (!shadowRealmObj
) {
84 // Instead of managing Realms, spidermonkey associates a realm with a global
85 // object, and so we will manage and store a global.
87 // Step 3. Let realmRec be CreateRealm().
89 // Initially steal creation options from current realm:
90 JS::RealmOptions
options(cx
->realm()->creationOptions(),
91 cx
->realm()->behaviors());
93 // We don't want to have to deal with CCWs in addition to
94 // WrappedFunctionObjects.
95 options
.creationOptions().setExistingCompartment(cx
->compartment());
97 JS::GlobalCreationCallback newGlobal
=
98 cx
->runtime()->getShadowRealmGlobalCreationCallback();
99 // If an embedding didn't provide a callback to initialize the global,
100 // use the basic default one.
102 newGlobal
= DefaultNewShadowRealmGlobal
;
105 // Our shadow realm inherits the principals of the current realm,
106 // but is otherwise constrained.
107 JSPrincipals
* principals
= JS::GetRealmPrincipals(cx
->realm());
109 // Steps 5-11: In SpiderMonkey these fall under the aegis of the global
110 // creation. It's worth noting that the newGlobal callback
111 // needs to respect the SetRealmGlobalObject call below, which
112 // sets the global to
113 // OrdinaryObjectCreate(intrinsics.[[%Object.prototype%]]).
115 // Step 5. Let context be a new execution context.
116 // Step 6. Set the Function of context to null.
117 // Step 7. Set the Realm of context to realmRec.
118 // Step 8. Set the ScriptOrModule of context to null.
119 // Step 9. Set O.[[ExecutionContext]] to context.
120 // Step 10. Perform ? SetRealmGlobalObject(realmRec, undefined, undefined).
121 // Step 11. Perform ? SetDefaultGlobalBindings(O.[[ShadowRealm]]).
122 Rooted
<JSObject
*> global(cx
,
123 newGlobal(cx
, options
, principals
, cx
->global()));
128 // Make sure the new global hook obeyed our request in the
129 // creation options to have a same compartment global.
130 MOZ_RELEASE_ASSERT(global
->compartment() == cx
->compartment());
132 // Step 4. Set O.[[ShadowRealm]] to realmRec.
133 shadowRealmObj
->initFixedSlot(GlobalSlot
, ObjectValue(*global
));
135 // Step 12. Perform ? HostInitializeShadowRealm(O.[[ShadowRealm]]).
136 JS::GlobalInitializeCallback hostInitializeShadowRealm
=
137 cx
->runtime()->getShadowRealmInitializeGlobalCallback();
138 if (hostInitializeShadowRealm
) {
139 if (!hostInitializeShadowRealm(cx
, global
)) {
144 // Step 13. Return O.
145 args
.rval().setObject(*shadowRealmObj
);
149 // https://tc39.es/proposal-shadowrealm/#sec-validateshadowrealmobject
150 // (slightly modified into a cast operator too)
151 static ShadowRealmObject
* ValidateShadowRealmObject(JSContext
* cx
,
152 Handle
<Value
> value
) {
153 // Step 1. Perform ? RequireInternalSlot(O, [[ShadowRealm]]).
154 // Step 2. Perform ? RequireInternalSlot(O, [[ExecutionContext]]).
155 return UnwrapAndTypeCheckValue
<ShadowRealmObject
>(cx
, value
, [cx
]() {
156 JS_ReportErrorNumberASCII(cx
, GetErrorMessage
, nullptr,
157 JSMSG_NOT_SHADOW_REALM
);
161 void js::ReportPotentiallyDetailedMessage(JSContext
* cx
,
162 const unsigned detailedError
,
163 const unsigned genericError
) {
164 // Return for non-catchable exceptions like interrupt requests.
165 if (!cx
->isExceptionPending()) {
169 Rooted
<Value
> exception(cx
);
170 if (!cx
->getPendingException(&exception
)) {
173 cx
->clearPendingException();
175 JS::ErrorReportBuilder
jsReport(cx
);
176 JS::ExceptionStack
exnStack(cx
, exception
, nullptr);
177 if (!jsReport
.init(cx
, exnStack
, JS::ErrorReportBuilder::NoSideEffects
)) {
178 cx
->clearPendingException();
179 JS_ReportErrorNumberASCII(cx
, GetErrorMessage
, nullptr, genericError
);
183 JS_ReportErrorNumberUTF8(cx
, GetErrorMessage
, nullptr, detailedError
,
184 jsReport
.toStringResult().c_str());
187 // PerformShadowRealmEval ( sourceText: a String, callerRealm: a Realm Record,
188 // evalRealm: a Realm Record, )
190 // https://tc39.es/proposal-shadowrealm/#sec-performshadowrealmeval
191 static bool PerformShadowRealmEval(JSContext
* cx
, Handle
<JSString
*> sourceText
,
192 Realm
* callerRealm
, Realm
* evalRealm
,
193 MutableHandle
<Value
> rval
) {
194 MOZ_ASSERT(callerRealm
!= evalRealm
);
196 // Step 1. Perform ? HostEnsureCanCompileStrings(callerRealm, evalRealm).
197 if (!cx
->isRuntimeCodeGenEnabled(JS::RuntimeCode::JS
, sourceText
)) {
198 JS_ReportErrorNumberASCII(cx
, GetErrorMessage
, nullptr,
199 JSMSG_CSP_BLOCKED_SHADOWREALM
);
203 // Need to compile the script into the realm we will execute into.
205 // We hoist the error handling out however to ensure that errors
206 // are thrown from the correct realm.
207 bool compileSuccess
= false;
208 bool evalSuccess
= false;
211 Rooted
<GlobalObject
*> evalRealmGlobal(cx
, evalRealm
->maybeGlobal());
212 AutoRealm
ar(cx
, evalRealmGlobal
);
214 // Step 2. Perform the following substeps in an implementation-defined
215 // order, possibly interleaving parsing and error detection:
216 // a. Let script be ParseText(! StringToCodePoints(sourceText), Script).
217 // b. If script is a List of errors, throw a SyntaxError exception.
218 // c. If script Contains ScriptBody is false, return undefined.
219 // d. Let body be the ScriptBody of script.
220 // e. If body Contains NewTarget is true, throw a SyntaxError exception.
221 // f. If body Contains SuperProperty is true, throw a SyntaxError
222 // exception. g. If body Contains SuperCall is true, throw a SyntaxError
225 AutoStableStringChars
linearChars(cx
);
226 if (!linearChars
.initTwoByte(cx
, sourceText
)) {
229 SourceText
<char16_t
> srcBuf
;
230 if (!srcBuf
.initMaybeBorrowed(cx
, linearChars
)) {
234 // Lets propagate some information into the compilation here.
236 // We may need to censor the stacks eventually, see
237 // https://bugzilla.mozilla.org/show_bug.cgi?id=1770017
238 RootedScript
callerScript(cx
);
239 const char* filename
;
243 DescribeScriptedCallerForCompilation(cx
, &callerScript
, &filename
, &lineno
,
244 &pcOffset
, &mutedErrors
);
246 CompileOptions
options(cx
);
247 options
.setIsRunOnce(true)
248 .setNoScriptRval(false)
249 .setMutedErrors(mutedErrors
)
250 .setFileAndLine(filename
, lineno
);
252 Rooted
<Scope
*> enclosing(cx
, &evalRealmGlobal
->emptyGlobalScope());
254 cx
, frontend::CompileEvalScript(cx
, options
, srcBuf
, enclosing
,
257 compileSuccess
= !!script
;
258 if (!compileSuccess
) {
262 // Step 3. Let strictEval be IsStrict of script.
263 // Step 4. Let runningContext be the running execution context.
264 // Step 5. Let lexEnv be NewDeclarativeEnvironment(evalRealm.[[GlobalEnv]]).
265 // Step 6. Let varEnv be evalRealm.[[GlobalEnv]].
266 // Step 7. If strictEval is true, set varEnv to lexEnv.
267 // Step 8. If runningContext is not already suspended, suspend
268 // runningContext. Step 9. Let evalContext be a new ECMAScript code
269 // execution context. Step 10. Set evalContext's Function to null. Step 11.
270 // Set evalContext's Realm to evalRealm. Step 12. Set evalContext's
271 // ScriptOrModule to null. Step 13. Set evalContext's VariableEnvironment to
272 // varEnv. Step 14. Set evalContext's LexicalEnvironment to lexEnv. Step 15.
273 // Push evalContext onto the execution context stack; evalContext is
274 // now the running execution context.
275 // Step 16. Let result be EvalDeclarationInstantiation(body, varEnv,
276 // lexEnv, null, strictEval).
277 // Step 17. If result.[[Type]] is normal, then
278 // a. Set result to the result of evaluating body.
279 // Step 18. If result.[[Type]] is normal and result.[[Value]] is empty, then
280 // a. Set result to NormalCompletion(undefined).
282 // Step 19. Suspend evalContext and remove it from the execution context
284 // Step 20. Resume the context that is now on the top of the execution
285 // context stack as the running execution context.
286 Rooted
<JSObject
*> environment(cx
, &evalRealmGlobal
->lexicalEnvironment());
287 evalSuccess
= ExecuteKernel(cx
, script
, environment
,
288 /* evalInFrame = */ NullFramePtr(), rval
);
289 } while (false); // AutoRealm
291 if (!compileSuccess
) {
292 if (!cx
->isExceptionPending()) {
296 // Clone the exception into the current global and re-throw, as the
297 // exception has to come from the current global.
298 Rooted
<Value
> exception(cx
);
299 if (!cx
->getPendingException(&exception
)) {
303 // Clear our exception now that we've got it, so that we don't
304 // do the following call with an exception already pending.
305 cx
->clearPendingException();
307 Rooted
<Value
> clonedException(cx
);
308 if (!JS_StructuredClone(cx
, exception
, &clonedException
, nullptr,
313 cx
->setPendingException(clonedException
, ShouldCaptureStack::Always
);
318 // Step 21. If result.[[Type]] is not normal, throw a TypeError
321 // The type error here needs to come from the calling global, so has to
322 // happen outside the AutoRealm above.
323 ReportPotentiallyDetailedMessage(cx
,
324 JSMSG_SHADOW_REALM_EVALUATE_FAILURE_DETAIL
,
325 JSMSG_SHADOW_REALM_EVALUATE_FAILURE
);
330 // Wrap |rval| into the current compartment.
331 if (!cx
->compartment()->wrap(cx
, rval
)) {
335 // Step 22. Return ? GetWrappedValue(callerRealm, result.[[Value]]).
336 return GetWrappedValue(cx
, callerRealm
, rval
, rval
);
339 // ShadowRealm.prototype.evaluate ( sourceText )
340 // https://tc39.es/proposal-shadowrealm/#sec-shadowrealm.prototype.evaluate
341 static bool ShadowRealm_evaluate(JSContext
* cx
, unsigned argc
, Value
* vp
) {
342 CallArgs args
= CallArgsFromVp(argc
, vp
);
344 // Step 1. Let O be this value.
345 HandleValue obj
= args
.thisv();
347 // Step 2. Perform ? ValidateShadowRealmObject(O)
348 Rooted
<ShadowRealmObject
*> shadowRealm(cx
,
349 ValidateShadowRealmObject(cx
, obj
));
354 // Step 3. If Type(sourceText) is not String, throw a TypeError exception.
355 if (!args
.get(0).isString()) {
356 JS_ReportErrorNumberASCII(cx
, GetErrorMessage
, nullptr,
357 JSMSG_SHADOW_REALM_EVALUATE_NOT_STRING
);
360 Rooted
<JSString
*> sourceText(cx
, args
.get(0).toString());
362 // Step 4. Let callerRealm be the current Realm Record.
363 Realm
* callerRealm
= cx
->realm();
365 // Step 5. Let evalRealm be O.[[ShadowRealm]].
366 Realm
* evalRealm
= shadowRealm
->getShadowRealm();
367 // Step 6. Return ? PerformShadowRealmEval(sourceText, callerRealm,
369 return PerformShadowRealmEval(cx
, sourceText
, callerRealm
, evalRealm
,
373 enum class ImportValueIndices
: uint32_t {
381 // MG:XXX: Cribbed/Overlapping with StartDynamicModuleImport; may need to
382 // refactor to share.
383 // https://tc39.es/proposal-shadowrealm/#sec-shadowrealmimportvalue
384 static JSObject
* ShadowRealmImportValue(JSContext
* cx
,
385 Handle
<JSString
*> specifierString
,
386 Handle
<JSString
*> exportName
,
387 Realm
* callerRealm
, Realm
* evalRealm
) {
388 // Step 1. Assert: evalContext is an execution context associated to a
389 // ShadowRealm instance's [[ExecutionContext]].
391 // Step 2. Let innerCapability be ! NewPromiseCapability(%Promise%).
392 Rooted
<JSObject
*> promiseConstructor(cx
, JS::GetPromiseConstructor(cx
));
393 if (!promiseConstructor
) {
397 Rooted
<JSObject
*> promiseObject(cx
, JS::NewPromiseObject(cx
, nullptr));
398 if (!promiseObject
) {
402 Handle
<PromiseObject
*> promise
= promiseObject
.as
<PromiseObject
>();
404 JS::ModuleDynamicImportHook importHook
=
405 cx
->runtime()->moduleDynamicImportHook
;
408 // Dynamic import can be disabled by a pref and is not supported in all
409 // contexts (e.g. web workers).
412 "Dynamic module import is disabled or not supported in this context");
413 if (!RejectPromiseWithPendingError(cx
, promise
)) {
420 // Step 3. Let runningContext be the running execution context. (Implicit)
421 // Step 4. If runningContext is not already suspended, suspend
422 // runningContext. (Implicit)
423 // Step 5. Push evalContext onto the execution context stack; evalContext is
424 // now the running execution context. (Implicit)
425 Rooted
<GlobalObject
*> evalRealmGlobal(cx
, evalRealm
->maybeGlobal());
426 AutoRealm
ar(cx
, evalRealmGlobal
);
428 // Not Speced: Get referencing private to pass to importHook.
429 RootedScript
script(cx
);
430 const char* filename
;
434 DescribeScriptedCallerForCompilation(cx
, &script
, &filename
, &lineno
,
435 &pcOffset
, &mutedErrors
);
439 Rooted
<JSAtom
*> specifierAtom(cx
, AtomizeString(cx
, specifierString
));
440 if (!specifierAtom
) {
441 if (!RejectPromiseWithPendingError(cx
, promise
)) {
447 Rooted
<ArrayObject
*> assertionArray(cx
);
448 Rooted
<JSObject
*> moduleRequest(
449 cx
, ModuleRequestObject::create(cx
, specifierAtom
, assertionArray
));
450 if (!moduleRequest
) {
451 if (!RejectPromiseWithPendingError(cx
, promise
)) {
457 // Step 6. Perform ! HostImportModuleDynamically(null, specifierString,
460 // By specification, this is supposed to take ReferencingScriptOrModule as
461 // null, see first parameter above. However, if we do that, we don't end up
462 // with a script reference, which is used to figure out what the base-URI
463 // should be So then we end up using the default one for the module loader;
464 // which because of the way we set the parent module loader up, means we end
465 // up having the incorrect base URI, as the module loader ends up just using
466 // the document's base URI.
468 // I have filed https://github.com/tc39/proposal-shadowrealm/issues/363 to
470 Rooted
<Value
> referencingPrivate(cx
, script
->sourceObject()->getPrivate());
471 if (!importHook(cx
, referencingPrivate
, moduleRequest
, promise
)) {
472 // If there's no exception pending then the script is terminating
473 // anyway, so just return nullptr.
474 if (!cx
->isExceptionPending() ||
475 !RejectPromiseWithPendingError(cx
, promise
)) {
481 // Step 7. Suspend evalContext and remove it from the execution context
483 // Step 8. Resume the context that is now on the top of the execution
484 // context stack as the running execution context (Implicit)
487 // Step 9. Let steps be the steps of an ExportGetter function as described
489 // Step 10. Let onFulfilled be ! CreateBuiltinFunction(steps, 1, "", «
490 // [[ExportNameString]] », callerRealm).
492 // The handler can only hold onto a single object, so we pack that into a new
493 // array, and store there.
494 Rooted
<ArrayObject
*> handlerObject(
496 NewDenseFullyAllocatedArray(cx
, uint32_t(ImportValueIndices::Length
)));
497 if (!handlerObject
) {
501 handlerObject
->setDenseInitializedLength(
502 uint32_t(ImportValueIndices::Length
));
503 handlerObject
->initDenseElement(uint32_t(ImportValueIndices::CalleRealm
),
504 PrivateValue(callerRealm
));
505 handlerObject
->initDenseElement(
506 uint32_t(ImportValueIndices::ExportNameString
), StringValue(exportName
));
508 Rooted
<JSFunction
*> onFulfilled(
512 [](JSContext
* cx
, unsigned argc
, Value
* vp
) {
513 // This is the export getter function from
514 // https://tc39.es/proposal-shadowrealm/#sec-shadowrealmimportvalue
515 CallArgs args
= CallArgsFromVp(argc
, vp
);
516 MOZ_ASSERT(args
.length() == 1);
518 auto* handlerObject
= ExtraFromHandler
<ArrayObject
>(args
);
520 Rooted
<Value
> realmValue(
521 cx
, handlerObject
->getDenseElement(
522 uint32_t(ImportValueIndices::CalleRealm
)));
523 Rooted
<Value
> exportNameValue(
524 cx
, handlerObject
->getDenseElement(
525 uint32_t(ImportValueIndices::ExportNameString
)));
527 // Step 1. Assert: exports is a module namespace exotic object.
528 Handle
<Value
> exportsValue
= args
[0];
529 MOZ_ASSERT(exportsValue
.isObject() &&
530 exportsValue
.toObject().is
<ModuleNamespaceObject
>());
532 Rooted
<ModuleNamespaceObject
*> exports(
533 cx
, &exportsValue
.toObject().as
<ModuleNamespaceObject
>());
535 // Step 2. Let f be the active function object. (not implemented
538 // Step 3. Let string be f.[[ExportNameString]]. Step 4.
539 // Assert: Type(string) is String.
540 MOZ_ASSERT(exportNameValue
.isString());
542 Rooted
<JSAtom
*> stringAtom(
543 cx
, AtomizeString(cx
, exportNameValue
.toString()));
547 Rooted
<jsid
> stringId(cx
, AtomToId(stringAtom
));
549 // Step 5. Let hasOwn be ? HasOwnProperty(exports, string).
551 if (!HasOwnProperty(cx
, exports
, stringId
, &hasOwn
)) {
555 // Step 6. If hasOwn is false, throw a TypeError exception.
557 JS_ReportErrorNumberASCII(cx
, GetErrorMessage
, nullptr,
558 JSMSG_SHADOW_REALM_VALUE_NOT_EXPORTED
);
562 // Step 7. Let value be ? Get(exports, string).
563 Rooted
<Value
> value(cx
);
564 if (!GetProperty(cx
, exports
, exports
, stringId
, &value
)) {
568 // Step 8. Let realm be f.[[Realm]].
569 Realm
* callerRealm
= static_cast<Realm
*>(realmValue
.toPrivate());
571 // Step 9. Return ? GetWrappedValue(realm, value).
572 return GetWrappedValue(cx
, callerRealm
, value
, args
.rval());
574 promise
, handlerObject
));
579 Rooted
<JSFunction
*> onRejected(
582 [](JSContext
* cx
, unsigned argc
, Value
* vp
) {
583 JS_ReportErrorNumberASCII(
584 cx
, GetErrorMessage
, nullptr,
585 JSMSG_SHADOW_REALM_IMPORTVALUE_FAILED
);
593 // Step 11. Set onFulfilled.[[ExportNameString]] to exportNameString.
594 // Step 12. Let promiseCapability be ! NewPromiseCapability(%Promise%).
595 // Step 13. Return ! PerformPromiseThen(innerCapability.[[Promise]],
596 // onFulfilled, callerRealm.[[Intrinsics]].[[%ThrowTypeError%]],
597 // promiseCapability).
598 return OriginalPromiseThen(cx
, promise
, onFulfilled
, onRejected
);
601 // ShadowRealm.prototype.importValue ( specifier, exportName )
602 // https://tc39.es/proposal-shadowrealm/#sec-shadowrealm.prototype.importvalue
603 static bool ShadowRealm_importValue(JSContext
* cx
, unsigned argc
, Value
* vp
) {
604 CallArgs args
= CallArgsFromVp(argc
, vp
);
606 // Step 1. Let O be this value.
607 HandleValue obj
= args
.thisv();
609 // Step 2. Perform ? ValidateShadowRealmObject(O).
610 Rooted
<ShadowRealmObject
*> shadowRealm(cx
,
611 ValidateShadowRealmObject(cx
, obj
));
616 // Step 3. Let specifierString be ? ToString(specifier).
617 Rooted
<JSString
*> specifierString(cx
, ToString
<CanGC
>(cx
, args
.get(0)));
618 if (!specifierString
) {
622 // Step 4. If Type(exportName) is not String, throw a TypeError exception.
623 if (!args
.get(1).isString()) {
624 JS_ReportErrorNumberASCII(cx
, GetErrorMessage
, nullptr,
625 JSMSG_SHADOW_REALM_EXPORT_NOT_STRING
);
629 Rooted
<JSString
*> exportName(cx
, args
.get(1).toString());
634 // Step 5. Let callerRealm be the current Realm Record.
635 Realm
* callerRealm
= cx
->realm();
637 // Step 6. Let evalRealm be O.[[ShadowRealm]].
638 Realm
* evalRealm
= shadowRealm
->getShadowRealm();
640 // Step 7. Let evalContext be O.[[ExecutionContext]]
641 // (we dont' pass this explicitly, instead using the realm+global to
645 // ShadowRealmImportValue(specifierString, exportName,
646 // callerRealm, evalRealm,
649 JSObject
* res
= ShadowRealmImportValue(cx
, specifierString
, exportName
,
650 callerRealm
, evalRealm
);
655 args
.rval().set(ObjectValue(*res
));
659 static const JSFunctionSpec shadowrealm_methods
[] = {
660 JS_FN("evaluate", ShadowRealm_evaluate
, 1, 0),
661 JS_FN("importValue", ShadowRealm_importValue
, 2, 0),
665 static const JSPropertySpec shadowrealm_properties
[] = {
666 JS_STRING_SYM_PS(toStringTag
, "ShadowRealm", JSPROP_READONLY
),
670 static const ClassSpec ShadowRealmObjectClassSpec
= {
671 GenericCreateConstructor
<ShadowRealmObject::construct
, 0,
672 gc::AllocKind::FUNCTION
>,
673 GenericCreatePrototype
<ShadowRealmObject
>,
674 nullptr, // Static methods
675 nullptr, // Static properties
676 shadowrealm_methods
, // Methods
677 shadowrealm_properties
, // Properties
680 const JSClass
ShadowRealmObject::class_
= {
682 JSCLASS_HAS_CACHED_PROTO(JSProto_ShadowRealm
) |
683 JSCLASS_HAS_RESERVED_SLOTS(ShadowRealmObject::SlotCount
),
685 &ShadowRealmObjectClassSpec
,
688 const JSClass
ShadowRealmObject::protoClass_
= {
689 "ShadowRealm.prototype",
690 JSCLASS_HAS_CACHED_PROTO(JSProto_ShadowRealm
),
692 &ShadowRealmObjectClassSpec
,