ECMAScript Realms Spec Proposal

Table 1: Well-known Intrinsic Objects
Intrinsic Name Global Name ECMAScript Language Association
%Realm% Realm
%RealmPrototype% Realm.prototype

1Realms

Table 2: Realm Record Fields
Field Name Value Meaning
[[HostDefined]] ... ...
[[TransformTrap]] A function object or undefined The function that is used as the transform trap. If [[TransformTrap]] is undefined, the trap invoker will carry on the default behavior.
[[IsDirectEvalTrap]] A function object or undefined The function that is used as the direct eval check trap. If [[IsDirectEvalTrap]] is undefined, the trap invoker will carry on the default behavior.
[[ImportTrap]] A function object or undefined The function that is used as the import trap. If [[ImportTrap]] is undefined, the trap invoker will carry on the default behavior.
[[ImportMetaTrap]] A function object or undefined The function that is used as the import.meta trap. If [[ImportMetaTrap]] is undefined, the trap invoker will carry on the default behavior.

1.1InvokeIsDirectEvalTrap( trap, func )

The abstract operation InvokeIsDirectEvalTrap with arguments trap and func performs the following steps:

  1. Assert: IsCallable(trap) is true.
  2. Let result be ToBoolean( ? Call(trap, undefined, « func »)).
  3. Return result.

1.2InvokeTransformTrap ( trap, sourceText )

The abstract operation InvokeTransformTrap with arguments trap and sourceText performs the following steps:

  1. Assert: IsCallable(trap) is true.
  2. Let newSourceText be ? Call(trap, undefined, « sourceText »).
  3. Return ? ToString(newSourceText).

1.3InvokeImportTrap ( trap, referencingScriptOrModule, specifierString, promiseCapability )

The abstract operation InvokeImportTrap with arguments trap, referencingScriptOrModule, specifier and promiseCapability performs the following steps:

  1. Assert: IsCallable(trap) is true.
  2. Assert: Type(specifierString) is String.
  3. Assert: referencingScriptOrModule is a Script Record or Module Record (i.e. is not null).
  4. Assert: resultCapability is a PromiseCapability Record.
  5. If referencingScriptOrModule is a Module Record, then
    1. Assert: ModuleEvaluation has already been invoked on referencingScriptOrModule and successfully completed.
    2. Let referrer be GetModuleNamespace(referencingScriptOrModule).
    3. IfAbruptRejectPromise(referrer, promiseCapability).
  6. Else,
    1. Note: Top Level Script referrer is denoted as null.
    2. Let referrer be null.
  7. Let value be Call(trap, undefined, « referrer, specifier »).
  8. IfAbruptRejectPromise(value, promiseCapability).
  9. Perform ! Call(promiseCapability.[[Resolve]], undefined, « value »).

2Runtime Semantics: PerformEval( x, evalRealm, strictCaller, direct )

The abstract operation PerformEval with arguments x, evalRealm, strictCaller, and direct performs the following steps:

  1. Assert: If direct is false, then strictCaller is also false.
  2. If Type(x) is not String, return x.
  3. Let fn be evalRealm.[[TransformTrap]].
  4. If IsCallable(fn) is true, then
    1. Let x be ? InvokeTransformTrap(fn, x)..
  5. ...

3Runtime Semantics: Evaluation

CallExpression:CoverCallExpressionAndAsyncArrowHead
  1. Let expr be CoveredCallExpression of CoverCallExpressionAndAsyncArrowHead.
  2. Let memberExpr be the MemberExpression of expr.
  3. Let arguments be the Arguments of expr.
  4. Let ref be the result of evaluating memberExpr.
  5. Let func be ? GetValue(ref).
  6. If Type(ref) is Reference and IsPropertyReference(ref) is false and GetReferencedName(ref) is "eval", then
    1. Let evalRealm be the current Realm Record..
    2. Let trapFn be evalRealm.[[IsDirectEvalTrap]].
    3. If IsCallable(trapFn) is true, then
      1. Let isDirectEval be ? InvokeIsDirectEvalTrap(trapFn, func)..
    4. Else,
      1. Let isDirectEval be SameValue(func, %eval%).
    5. If isDirectEvalSameValue(func, %eval%) is true, then
      1. Let argList be ? ArgumentListEvaluation(arguments).
      2. If argList has no elements, return undefined.
      3. Let evalText be the first element of argList.
      4. If the source code matching this CallExpression is strict mode code, let strictCaller be true. Otherwise let strictCaller be false.
      5. Let evalRealm be the current Realm Record.
      6. Perform ? HostEnsureCanCompileStrings(evalRealm, evalRealm).
      7. Return ? PerformEval(evalText, evalRealm, strictCaller, true).
  7. Let thisCall be this CallExpression.
  8. Let tailCall be IsInTailPosition(thisCall).
  9. Return ? EvaluateCall(func, ref, arguments, tailCall).
...

4Import Calls

4.1Runtime Semantics: Evaluation

ImportCall:import(AssignmentExpression)
  1. Let referencingScriptOrModule be ! GetActiveScriptOrModule().
  2. Assert: referencingScriptOrModule is a Script Record or Module Record (i.e. is not null).
  3. Let argRef be the result of evaluating AssignmentExpression.
  4. Let specifier be ? GetValue(argRef).
  5. Let promiseCapability be ! NewPromiseCapability(%Promise%).
  6. Let specifierString be ToString(specifier).
  7. IfAbruptRejectPromise(specifierString, promiseCapability).
  8. Let evalRealm be the current Realm Record..
  9. Let fn be evalRealm.[[ImportTrap]].
  10. If IsCallable(fn) is true, then
    1. Perform ! InvokeImportTrap(fn, referencingScriptOrModule, specifierString, promiseCapability )..
  11. Else,
    1. Perform ! HostImportModuleDynamically(referencingScriptOrModule, specifierString, promiseCapability).
  12. Return promiseCapability.[[Promise]].

5Realm Objects

5.1Realm Abstract Operations

5.1.1CreateRealmRec ( intrinsics )

  1. Let realmRec be a new Realm Record.
  2. If intrinsics is undefined, then
    1. Perform CreateIntrinsics(realmRec).
  3. Else
    1. Assert: In this case, intrinsics must be a Record with field names listed in column one of Table 7.
    2. Set realmRec.[[Intrinsics]] to intrinsics.
  4. Set realmRec.[[GlobalObject]] to undefined.
  5. Set realmRec.[[GlobalEnv]] to undefined.
  6. Set realmRec.[[TemplateMap]] to a new empty List.
  7. Return realmRec.

5.2Built-in Function Objects

5.2.1Realm Default Import Trap Functions

A Realm default import trap function is an anonymous built-in function.

When a Realm default import trap function is called with arguments realm, referrer and specifier, the following steps are taken:

  1. Throw a new TypeError.
Note
By default, newly created realms do not expose host specific behavior when evaluating import() calls.

5.3The Realm Constructor

The Ream constructor is the %Realm% intrinsic object and the initial value of the Realm property of the global object. When called as a constructor it creates and initializes a new Realm object. Realm is not intended to be called as a function and will throw an exception when called in that manner.

The Realm constructor is designed to be subclassable. It may be used as the value in an extends clause of a class definition. Subclass constructors that intend to inherit the specified Realm behaviour must include a super call to the Realm constructor to create and initialize the subclass instance with the internal state necessary to support the Realm.prototype built-in methods.

5.3.1Realm ([ options ])

When Realm is called with argument option performs the following steps:
  1. If NewTarget is undefined, throw a TypeError exception.
  2. Let O be ? OrdinaryCreateFromConstructor(NewTarget, "%RealmPrototype%", « [[Realm]] »).
  3. If options is not undefined, then
    1. Let parentRealm be the current Realm Record.
    2. Let opts be ? ToObject(options).
    3. Let importTrap be ? Get(opts, "import").
    4. If importTrap is equal "inherit", then
      1. Set importTrap to parentRealm.[[ImportTrap]].
    5. Else if importTrap is not undefined and IsCallable(importTrap) is false, throw a TypeError exception.
    6. Let importMetaTrap be ? Get(opts, "meta").
    7. If importMetaTrap is equal "inherit", then
      1. Set importMetaTrap to parentRealm.[[ImportMetaTrap]].
    8. Else if importMetaTrap is not undefined and IsCallable(importMetaTrap) is false, throw a TypeError exception.
    9. Let transformTrap be ? Get(opts, "transform").
    10. If transformTrap is equal "inherit", then
      1. Set transformTrap to parentRealm.[[TransformTrap]].
    11. Else if transformTrap is not undefined and IsCallable(transformTrap) is false, throw a TypeError exception.
    12. Let isDirectEvalTrap be ? Get(opts, "isDirectEval").
    13. If isDirectEvalTrap is equal "inherit", then
      1. Set isDirectEvalTrap to parentRealm.[[IsDirectEvalTrap]].
    14. Else if isDirectEvalTrap is not undefined and IsCallable(isDirectEvalTrap) is false, throw a TypeError exception.
    15. Let intrinsics be ? Get(opts, "intrinsics").
    16. If intrinsics is equal "inherit", then
      1. Set intrinsics to parentRealm.[[Intrinsics]].
    17. Else if intrinsics is not undefined, throw a TypeError exception.
    18. Let thisValue be ? Get(opts, "thisValue").
    19. If thisValue is not undefined and Type(thisValue) is not Object, throw a TypeError exception.
  4. Let realmRec be CreateRealmRec(intrinsics).
  5. Set O.[[Realm]] to realmRec.
  6. Perform ? SetRealmGlobalObject(realmRec, undefined, thisValue).
  7. If importTrap is undefined, then
    1. Let importTrap be a new built-in function object as defined in 5.2.1.
  8. Set realmRec.[[ImportTrap]] to importTrap.
  9. If transformTrap is not undefined, then
    1. Set realmRec.[[TransformTrap]] to transformTrap.
  10. If isDirectEvalTrap is not undefined, then
    1. Set realmRec.[[IsDirectEvalTrap]] to isDirectEvalTrap.
  11. Let init be ? GetMethod(O, "init").
  12. If IsCallable(init) is not true, throw a TypeError exception.
  13. Perform ? Call(init, O).
  14. Return O.

5.4Properties of the Realm Constructor

The value of the [[Prototype]] internal slot of the Realm constructor is the intrinsic object %FunctionPrototype%.

5.5Properties of the Realm Prototype Object

5.5.1Realm.prototype.init ()

  1. Let O be this value.
  2. If Type(O) is not Object, throw a TypeError exception.
  3. If O does not have an [[Realm]] internal slot, throw a TypeError exception.
  4. Perform ? SetDefaultGlobalBindings(O.[[Realm]]).
Note
Extensible web: This is the dynamic way to define globals in a new realm.

5.5.2Realm.prototype.evaluate ( sourceText )

Synchronously execute a top-level script. The x is interpreted as a Script and evaluated with this bound to the realm's global object.
  1. Let O be this value.
  2. If Type(O) is not Object, throw a TypeError exception.
  3. If O does not have an [[Realm]] internal slot, throw a TypeError exception.
  4. If Type(sourceText) is not String, throw a TypeError exception.
  5. Let realm be O.[[Realm]].
  6. Let hostDefined be realm.[[HostDefined]].
  7. Let s be ParseScript(sourceText, realm, hostDefined).
  8. If s is a List of errors, then
    1. Perform HostReportErrors(s).
    2. Return NormalCompletion(undefined).
  9. Return ? ScriptEvaluation(s).
Note
Extensible web: This is the dynamic equivalent of a <script> in HTML.

5.5.3get Realm.prototype.global

Realm.prototype.global is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:
  1. Let O be this value.
  2. If Type(O) is not Object, throw a TypeError exception.
  3. If O does not have an [[Realm]] internal slot, throw a TypeError exception.
  4. Return O.[[Realm]].[[GlobalObject]].

5.5.4get Realm.prototype.thisValue

Realm.prototype.thisValue is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:
  1. Let O be this value.
  2. If Type(O) is not Object, throw a TypeError exception.
  3. If O does not have an [[Realm]] internal slot, throw a TypeError exception.
  4. Let envRec be O.[[Realm]].[[GlobalEnv]].
  5. Return envRec.[[GlobalThisValue]].

5.5.5get Realm.prototype.stdlib

Realm.prototype.stdlib is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:
  1. Let O be this value.
  2. If Type(O) is not Object, throw a TypeError exception.
  3. If O does not have an [[Realm]] internal slot, throw a TypeError exception.
  4. Let realmRec be O.[[Realm]].
  5. Let global be realmRec.[[GlobalObject]].
  6. Let stdlib be ObjectCreate(%ObjectPrototype%).
  7. For each property of the Global Object specified in clause 18 that correspond to an intrinsic object, do:
    1. Let name be the String value of the property name.
    2. Let value be the corresponding value of the intrinsic object from record realmRec.[[Intrinsics]].
    3. Let descObj be ObjectCreate(%ObjectPrototype%).
    4. Perform ? DefinePropertyOrThrow(descObj, "value", PropertyDescriptor{[[Value]]: value, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}).
    5. Perform ? DefinePropertyOrThrow(stdlib, name, PropertyDescriptor{[[Value]]: descObj, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}).
  8. Return stdlib.

5.5.6get Realm.prototype.intrinsics

Realm.prototype.intrinsics is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:
  1. Let O be this value.
  2. If Type(O) is not Object, throw a TypeError exception.
  3. If O does not have an [[Realm]] internal slot, throw a TypeError exception.
  4. Let realmRec be O.[[Realm]].
  5. Let intrinsics be ObjectCreate(%ObjectPrototype%).
  6. For each intrinsic name listed in Table 7, do:
    1. Let intrinsicName be the String value in column one of the table.
    2. Let name be the String value of intrinsicName without the % symbols.
    3. Let value be the value of the field name intrisicName from record realmRec.[[Intrinsics]].
    4. Perform ? DefinePropertyOrThrow(intrinsics, name, PropertyDescriptor{[[Value]]: value, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}).
  7. Return intrinsics.

5.5.7Realm.prototype [ @@toStringTag ]

The initial value of the @@toStringTag property is the String value "Realm". This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

5.6Properties of Realm Instances

Realm instances are ordinary objects that inherit properties from the Realm prototype object (the intrinsic, %RealmPrototype%). Realm instances are initially created with the internal slots described in Table 3.
Table 3: Internal Slots of Realm Instances
Internal Slot Type Description
[[Realm]] Realm Record The Realm Record for the initial execution context.