Table of Contents

  1. 1 Well-Known Symbols
  2. 2 Promises
    1. 2.1 Reacting to Promises
  3. 3 Common Operations
    1. 3.1 CreateObject()
    2. 3.2 SimpleDefine(obj, name, value)
    3. 3.3 GetStateValue(state)
    4. 3.4 SetStateToMax(entry, newState)
  4. 4 Loader Objects
    1. 4.1 The Reflect.Loader Constructor
      1. 4.1.1 Reflect.Loader()
    2. 4.2 Properties of the Reflect.Loader Constructor
      1. 4.2.1 Reflect.Loader.prototype
    3. 4.3 Properties of the Reflect.Loader Prototype Object
      1. 4.3.1 Reflect.Loader.prototype.constructor
      2. 4.3.2 Reflect.Loader.prototype.import(name[, referrer])
      3. 4.3.3 Reflect.Loader.prototype.resolve(name[, referrer])
      4. 4.3.4 Reflect.Loader.prototype.load(name[, referrer[, stage]])
      5. 4.3.5 get Reflect.Loader.prototype.registry
      6. 4.3.6 Reflect.Loader.prototype [ @@toStringTag ]
    4. 4.4 Properties of Reflect.Loader Instances
  5. 5 Registry Objects
    1. 5.1 Abstract Operations for Registry Objects
      1. 5.1.1 GetRegistryEntry(registry, key)
    2. 5.2 The Registry Constructor
      1. 5.2.1 Registry(loader)
    3. 5.3 Registry.prototype
  6. 6 Properties of the Registry Prototype Object
    1. 6.1 Registry.prototype.constructor
    2. 6.2 Registry.prototype[ @@iterator ]()
    3. 6.3 Registry.prototype.lookup(key)
    4. 6.4 Registry.prototype.install(key, module)
    5. 6.5 Registry.prototype.uninstall(key)
    6. 6.6 Registry.prototype.cancel(key)
    7. 6.7 Registry.prototype.provide(key, stage, value)
    8. 6.8 Registry.prototype.error(key, stage, value)
  7. 7 Properties of Registry Instances
  8. 8 Loading Semantics
    1. 8.1 Auxiliary Operations
      1. 8.1.1 EnsureRegistered(loader, key)
      2. 8.1.2 Resolve(loader, name, referrer)
      3. 8.1.3 FulfillFetch(loader, entry, payload)
      4. 8.1.4 FulfillTranslate(loader, entry, source)
      5. 8.1.5 FulfillInstantiate(loader, entry, optionalInstance, source)
      6. 8.1.6 CommitInstantiated(loader, entry, optionalInstance, source)
      7. 8.1.7 Instantiation(loader, result, source)
    2. 8.2 Loading Operations
      1. 8.2.1 RequestFetch(loader, key)
      2. 8.2.2 RequestTranslate(loader, key)
      3. 8.2.3 RequestInstantiate(loader, key)
      4. 8.2.4 RequestInstantiateAll(loader, key)
      5. 8.2.5 RequestLink(loader, key)
      6. 8.2.6 RequestReady(loader, key)
  9. 9 Module Objects
    1. 9.1 Reflective Module Records
    2. 9.2 Abstract Operations for Module Objects
      1. 9.2.1 ParseExportsDescriptors(obj)
      2. 9.2.2 CreateModuleMutator(module)
      3. 9.2.3 GetExportNames(exportStarStack)
      4. 9.2.4 ResolveExport(exportName, resolveStack, exportStarStack)
      5. 9.2.5 ModuleDeclarationInstantiation()
      6. 9.2.6 ModuleEvaluation()
    3. 9.3 The Reflect.Module Constructor
      1. 9.3.1 Reflect.Module(descriptors[, executor[, evaluate]])
    4. 9.4 Properties of the Reflect.Module Constructor
      1. 9.4.1 Reflect.Module.evaluate(m)
      2. 9.4.2 Reflect.Module.prototype
    5. 9.5 Properties of Module Instances

1Well-Known Symbols#

Well-known symbols are built-in Symbol values that are explicitly referenced by algorithms of this specification. They are typically used as the keys of properties whose values serve as extension points of a specification algorithm.

Within this specification a well-known symbol is referred to by using a notation of the form @@name, where "name" is one of the values listed in table below:

Specification Name [[Description]] Value and Purpose
@@resolve "Reflect.Loader.resolve" A function valued property that is the resolve hook function of loader’s instances.
@@fetch "Reflect.Loader.fetch" A function valued property that is the fetch hook function of loader’s instances.
@@translate "Reflect.Loader.translate" A function valued property that is the translate hook function of loader’s instances.
@@instantiate "Reflect.Loader.instantiate" A function valued property that is the instantiate hook function of loader’s instances.

2Promises#

This spec makes heavy use of promises, and adopts the notational conventions established in the promises guide.

2.1Reacting to Promises#

Transforming p with a new pass-through promise is a shorthand for wrapping the promise to avoid exposing the original promise. It represents the following step:

  1. Transforming p with a fulfillment handler that, when called with argument value, returns value.

3Common Operations#

3.1CreateObject()#

  1. Let obj be ObjectCreate(%ObjectPrototype%).
  2. Return obj.

3.2SimpleDefine(obj, name, value)#

  1. Let desc be a new PropertyDescriptor record {[[Value]]: value, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}.
  2. Return the result of calling OrdinaryDefineOwnProperty(obj, name, desc).

3.3GetStateValue(state)#

  1. If state is the string "fetch" return 0.
  2. If state is the string "translate" return 1.
  3. If state is the string "instantiate" return 2.
  4. If state is the string "link" return 3.
  5. If state is the string "ready" return 4.

3.4SetStateToMax(entry, newState)#

  1. Let state be entry.[[State]].
  2. Let stateValue be GetStateValue(state).
  3. Let newStateValue be GetStateValue(newState).
  4. If newStateValue is larger than stateValue, set entry.[[State]] to newState.

4Loader Objects#

4.1The Reflect.Loader Constructor#

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

The Reflect.Loader 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 Loader behaviour must include a super call to the Reflect.Loader constructor to create and initialize the subclass instance with the internal state necessary to support the Reflect.Loader.prototype built-in methods.

4.1.1Reflect.Loader()#

When Reflect.Loader is called with no arguments, the following steps are taken:
  1. If NewTarget is undefined, then throw a TypeError exception.
  2. Let O be OrdinaryCreateFromConstructor(NewTarget, "Reflect.Loader.prototype").
  3. ReturnIfAbrupt(O).
  4. Let registry to a new Registry(O).
  5. Set O’s [[Registry]] internal slot to registry.
  6. Return O.

4.2Properties of the Reflect.Loader Constructor#

The value of the [[Prototype]] internal slot of the Reflect.Loader constructor is the intrinsic object %FunctionPrototype%. Besides the internal slots and the length property (whose value is 0), the Reflect.Loader constructor has the following properties:

4.2.1Reflect.Loader.prototype#

The value of Reflect.Loader.prototype is an ordinary object. This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

4.3Properties of the Reflect.Loader Prototype Object#

4.3.1Reflect.Loader.prototype.constructor#

The initial value of Reflect.Loader.prototype.constructor is Reflect.Loader.

4.3.2Reflect.Loader.prototype.import(name[, referrer])#

The following steps are taken:

  1. Let loader be this value.
  2. If Type(loader) is not Object, throw a TypeError exception.
  3. If loader does not have a [[Registry]] internal slot throw a TypeError exception.
  4. Return the result of transforming Resolve(loader, name, referrer) with a fulfillment handler that, when called with argument key, runs the following steps:
    1. Return RequestReady(loader, key).

4.3.3Reflect.Loader.prototype.resolve(name[, referrer])#

The following steps are taken:

  1. Let loader be this value.
  2. If Type(loader) is not Object, throw a TypeError exception.
  3. Return Resolve(loader, name, referrer).

4.3.4Reflect.Loader.prototype.load(name[, referrer[, stage]])#

The following steps are taken:

  1. Let loader be this value.
  2. If Type(loader) is not Object, throw a TypeError exception.
  3. If stage is undefined then let stage be "ready".
  4. Return the result of transforming Resolve(loader, name, referrer) with a fulfillment handler that, when called with argument key, runs the following steps:
    1. If stage is "fetch", then:
      1. Return the result of transforming RequestFetch(loader, key) with a new pass-through promise.
    2. If stage is "translate", then:
      1. Return the result of transforming RequestTranslate(loader, key) with a new pass-through promise.
    3. If stage is "instantiate", then:
      1. Return the result of transforming RequestInstantiateAll(loader, key) with a fulfillment handler that, when called with argument entry, runs the following steps:
        1. If entry.[[Module]] is a Function object, return entry.[[Module]].
        2. Return undefined.
    4. If stage is "link", then:
      1. Return the result of transforming RequestLink(loader, key) with a fulfillment handler that returns undefined.
    5. If stage is "ready", then:
      1. Return the result of transforming RequestReady(loader, key) with a fulfillment handler that, when called with argument entry, runs the following steps:
        1. Return GetModuleNamespace(entry.[[Module]]).
    6. Throw a new TypeError.

4.3.5get Reflect.Loader.prototype.registry#

Reflect.Loader.prototype.registry is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let loader be this value.
  2. Return loader.[[Registry]].

4.3.6Reflect.Loader.prototype [ @@toStringTag ]#

The initial value of the @@toStringTag property is the String value "Object".

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

4.4Properties of Reflect.Loader Instances#

Loader instances are ordinary objects that inherit properties from the Reflect.Loader.prototype.

Loader instances are initially created with the internal slots described in the following table:

Internal Slot Value Type (non-normative) Description (non-normative)
[[Realm]] Realm Record The realm this loader belongs to.
[[Registry]] An object An instance of Registry (4).

5Registry Objects#

5.1Abstract Operations for Registry Objects#

5.1.1GetRegistryEntry(registry, key)#

The abstract operation GetRegistryEntry with arguments registry and key performs the following steps:

  1. If Type(registry) is not Object, throw a TypeError exception.
  2. Let entries be registry.[[RegistryData]].
  3. Let pair be the entry in entries such that pair.[[key]] is equal to key.
  4. If pair does not exist, then return null.
  5. Let entry be pair.[[value]].
  6. Let result be CreateObject().
  7. Call SimpleDefine(result, "state", entry.[[State]]).
  8. Let statePromise be undefined.
  9. If entry.[[State]] is "fetch" and entry.[[Fetch]] is not undefined, then
    1. Set statePromise to the result of transforming entry.[[Fetch]] with a new pass-through promise.
  10. Else If entry.[[State]] is "translate" and entry.[[Translate]] is not undefined, then
    1. Set statePromise to the result of transforming entry.[[Translate]] with a new pass-through promise.
  11. Else If entry.[[State]] is "instantiate" and entry.[[Instantiate]] is not undefined, then
    1. Set statePromise to the result of transforming entry.[[Instantiate]] with a fulfillment handler that, when called with argument entry, runs the following steps:
      1. If entry.[[Module]] is a Function object, then return entry.[[Module]].
      2. Return undefined.
  12. Call SimpleDefine(result, "statePromise", statePromise).
  13. If entry.[[State]] is "ready" then let module be entry.[[Module]].
  14. Else let module be undefined.
  15. Call SimpleDefine(result, "module", module).
  16. If entry.[[Error]] is nothing, then:
    1. Call SimpleDefine(result, "error", null).
  17. Else:
    1. Let opt be CreateObject().
    2. Call SimpleDefine(opt, "value", entry.[[Error]]).
    3. Call SimpleDefine(result, "error", opt).
  18. Return result.
A registry entry is a record with the following fields:
Internal Slot Value Type (non-normative) Description (non-normative)
[[Key]] String The resolved module key.
[[State]] "fetch", "translate", "instantiate", "link", "ready" A constant value to indicating which phase the entry is at.
[[Metadata]] Object or undefined The metadata object passed through the pipeline.
[[Fetch]] Promise or undefined A promise for the result of [[#request-fetch]].
[[Translate]] Promise or undefined A promise for the result of [[#request-translate]].
[[Instantiate]] Promise or undefined A promise for the result of [[#request-instantiate]].
[[Dependencies]] List of pairs of String and (registry entry or undefined), or undefined. Table mapping unresolved names to their resolved modules.
[[Module]] Module Record or Function object or undefined The Module Record if the entry is ready, or a thunk if the entry is delayed; otherwise undefined.
[[Error]] Any or nothing An error that was encountered during one of the phases of the loading pipeline; nothing if no error has been encountered.

5.2The Registry Constructor#

The Registry constructor is the %Registry% intrinsic object. When called as a constructor it creates and initializes a new %Registry% object. %Registry% is not intended to be called as a function and will throw an exception when called in that manner.

5.2.1Registry(loader)#

When Registry is called with argument loader, the following steps are taken:

  1. If NewTarget is undefined, then throw a TypeError exception.
  2. If Type(loader) is not Object, throw a TypeError exception.
  3. Let O be OrdinaryCreateFromConstructor(NewTarget, "%RegistryPrototype%", «[[RegistryData]]» ).
  4. ReturnIfAbrupt(O).
  5. Set O’s [[RegistryData]] internal slot to a new empty List.
  6. Set O’s [[Loader]] internal slot to loader.
  7. Return O.

Properties of the Registry Constructor

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

Besides the internal slots and the length property (whose value is 0), the Registry constructor has the following properties:

5.3Registry.prototype#

The value of Registry.prototype is %RegistryPrototype%.

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

6Properties of the Registry Prototype Object#

6.1Registry.prototype.constructor#

The initial value of Registry.prototype.constructor is %Registry%.

6.2Registry.prototype[ @@iterator ]()#

When the @@iterator method is called it returns an Iterator object (ES2015 25.1.1.2) that iterates over the registry entries of the [[RegistryData]] internal slot, returning each entry as a key value pair. The following steps are taken:

  1. Let registry be this value.
  2. Let entries be a new List.
  3. For each pair in registry.[[RegistryData]], do:
    1. Let key be pair.[[key]].
    2. Let entry be GetRegistryEntry(registry, key).
    3. Append { [[key]]: key, [[value]]: entry } to entries.
  4. Return CreateListIterator(entries).
The value of the name property of this function is "[Symbol.iterator]".

6.3Registry.prototype.lookup(key)#

The following steps are taken:

  1. Let registry be this value.
  2. Return GetRegistryEntry(registry, key).

6.4Registry.prototype.install(key, module)#

The following steps are taken:

  1. Let registry be this value.
  2. If Type(registry) is not Object, throw a TypeError exception.
  3. Let entries be registry.[[RegistryData]].
  4. Let pair be the entry in entries such that pair.[[key]] is equal to key.
  5. If pair exists, then throw a new TypeError.
  6. Let entry be a new registry entry record { [[Key]]: key, [[State]]: "ready", [[Metadata]]: undefined, [[Fetch]]: undefined, [[Translate]]: undefined, [[Instantiate]]: undefined, [[Dependencies]]: undefined, [[Module]]: module }.
  7. Append { [[key]]: key, [[value]]: entry } to entries.

6.5Registry.prototype.uninstall(key)#

The following steps are taken:

  1. Let registry be this value.
  2. If Type(registry) is not Object, throw a TypeError exception.
  3. Let entries be registry.[[RegistryData]].
  4. Let pair be the entry in entries such that pair.[[key]] is equal to key.
  5. If pair does not exist, then throw a new TypeError.
  6. Let stateValue be GetStateValue(pair.[[value]].[[State]]).
  7. Let linkStateValue be GetStateValue("link").
  8. If stateValue is less than linkStateValue, then throw a new TypeError.
  9. Remove pair from entries.

6.6Registry.prototype.cancel(key)#

The following steps are taken:

  1. Let registry be this value.
  2. If Type(registry) is not Object, throw a TypeError exception.
  3. Let entries be registry.[[RegistryData]].
  4. Let pair be the entry in entries such that pair.[[key]] is equal to key.
  5. If pair does not exist, then throw a new TypeError.
  6. Let entry be pair.[[value]].
  7. Let stateValue be GetStateValue(entry.[[State]]).
  8. Let linkStateValue be GetStateValue("link").
  9. If stateValue is greater than or equal to linkStateValue, throw a new TypeError.
  10. Remove pair from entries.

6.7Registry.prototype.provide(key, stage, value)#

The following steps are taken:

  1. Let registry be this value.
  2. If Type(registry) is not Object, throw a TypeError exception.
  3. Let loader be registry.[[Loader]] value.
  4. Let entry be EnsureRegistered(loader, key).
  5. If stage is "fetch", then:
    1. Let stateValue be GetStateValue(entry.[[State]]).
    2. Let fetchStateValue be GetStateValue("fetch").
    3. If stateValue is greater than fetchStateValue, throw a new TypeError.
    4. Call FulfillFetch(loader, entry, value).
    5. Return undefined.
  6. If stage is "translate", then:
    1. Let stateValue be GetStateValue(entry.[[State]]).
    2. Let translateStateValue be GetStateValue("translate").
    3. If stateValue is greater than translateStateValue, throw a new TypeError.
    4. Call FulfillFetch(loader, entry, undefined).
    5. Call FulfillTranslate(loader, entry, value).
    6. Return undefined.
  7. If stage is "instantiate", then:
    1. Let stateValue be GetStateValue(entry.[[State]]).
    2. Let instantiateStateValue be GetStateValue("instantiate").
    3. If stateValue is greater than instantiateStateValue, throw a new TypeError.
    4. Call FulfillFetch(loader, entry, undefined).
    5. Call FulfillTranslate(loader, entry, undefined).
    6. Assert: entry.[[Translate]] is resolved or rejected.
    7. TODO: need to propagate rejections
    8. Let source be the fulfillment value of entry.[[Translate]].
    9. Call FulfillInstantiate(loader, entry, value, source).
    10. Return undefined.
  8. Throw a new TypeError.

6.8Registry.prototype.error(key, stage, value)#

The following steps are taken:

  1. // TODO

7Properties of Registry Instances#

Registry instances are ordinary objects that inherit properties from the %RegistryPrototype%.

Registry instances are initially created with the internal slots described in the following table:

Internal Slot Value Type (non-normative) Description (non-normative)
[[RegistryData]] List of pairs of String and registry entry. The registry of installed modules.
[[Loader]] An object The loader this registry belongs to.

8Loading Semantics#

8.1Auxiliary Operations#

8.1.1EnsureRegistered(loader, key)#

  1. Assert: loader has a [[Registry]] internal slot.
  2. Let pair be the entry in loader.[[Registry]] such that pair.[[key]] is equal to key.
  3. If pair exists, then:
    1. Let entry be pair.[[value]].
  4. Else:
    1. Let entry be a new registry entry record { [[Key]]: key, [[State]]: "fetch", [[Metadata]]: undefined, [[Fetch]]: undefined, [[Translate]]: undefined, [[Instantiate]]: undefined, [[Dependencies]]: undefined, [[Module]]: undefined, [[Error]]: nothing }.
    2. Append { [[key]]: key, [[value]]: entry } to loader.[[Registry]].
  5. Return entry.

8.1.2Resolve(loader, name, referrer)#

  1. Let hook be GetMethod(loader, @@resolve).
  2. Return the result of promise-calling hook(name, referrer).

8.1.3FulfillFetch(loader, entry, payload)#

  1. If entry.[[Fetch]] is undefined, then set entry.[[Fetch]] to a promise resolved with payload.
  2. Else fulfill entry.[[Fetch]] with payload.
  3. SetStateToMax(entry, "translate").

8.1.4FulfillTranslate(loader, entry, source)#

  1. If entry.[[Translate]] is undefined, then set entry.[[Translate]] to a promise resolved with source.
  2. Else fulfill entry.[[Translate]] with source.
  3. SetStateToMax(entry, "instantiate").

8.1.5FulfillInstantiate(loader, entry, optionalInstance, source)#

  1. If entry.[[Instantiate]] is undefined, then set entry.[[Instantiate]] to a new promise.
  2. Return CommitInstantiated(loader, entry, optionalInstance, source).

8.1.6CommitInstantiated(loader, entry, optionalInstance, source)#

  1. Let instance be Instantiation(loader, optionalInstance, source).
  2. ReturnIfAbrupt(instance).
  3. // TODO: edge case: what if instance is a thenable function?
  4. Let deps be a new empty List.
  5. If instance is a Module Record, then:
    1. Assert: instance is a Source Text Module Record.
    2. Set instance.[[RegistryEntry]] to entry.
    3. For each dep in instance.[[RequestedModules]], do:
      1. Append the record { [[key]]: dep, [[value]]: undefined } to deps.
  6. Set entry.[[Dependencies]] to deps.
  7. Set entry.[[Module]] to instance.
  8. SetStateToMax(entry, "link").

8.1.7Instantiation(loader, result, source)#

  1. If result is undefined, then return ParseModule(source).
  2. If IsCallable(result) is false then throw a new TypeError.
  3. Set result.[[Realm]] to loader.[[Realm]].
  4. Return result.

8.2Loading Operations#

8.2.1RequestFetch(loader, key)#

  1. Let entry be EnsureRegistered(loader, key).
  2. Let stateValue be GetStateValue(entry.[[State]]).
  3. Let linkStateValue be GetStateValue("link").
  4. If stateValue is greater than linkStateValue, return a new error promise.
  5. If entry.[[Fetch]] is not undefined, return entry.[[Fetch]].
  6. Let hook be GetMethod(loader, @@fetch).
  7. // TODO: metadata object
  8. Let p0 be the result of promise-calling hook(key).
  9. Let p1 be the result of transforming p0 with a new pass-through promise.
  10. Let p2 be the result of transforming p1 with a fulfillment handler that, when called with argument payload, runs the following steps:
    1. SetStateToMax(entry, "translate").
    2. Return payload.
  11. Set entry.[[Fetch]] to p1.
  12. Return p1.

8.2.2RequestTranslate(loader, key)#

  1. Let entry be EnsureRegistered(loader, key).
  2. Let stateValue be GetStateValue(entry.[[State]]).
  3. Let linkStateValue be GetStateValue("link").
  4. If stateValue is greater than linkStateValue, return a new error promise.
  5. If entry.[[Translate]] is not undefined, return entry.[[Translate]].
  6. Let hook be GetMethod(loader, @@translate).
  7. Let p be the result of transforming RequestFetch(loader, key) with a fulfillment handler that, when called with argument payload, runs the following steps:
    1. // TODO: metadata
    2. Let p0 be the result of promise-calling hook(key, payload).
    3. Let p1 be the result of transforming p0 with a new pass-through promise.
    4. Let p2 be the result of transforming p1 with a fulfillment handler that, when called with argument source, runs the following steps:
      1. SetStateToMax(entry, "instantiate").
      2. Return source.
    5. Return p1.
  8. Set entry.[[Translate]] to p.
  9. Return p.

8.2.3RequestInstantiate(loader, key)#

  1. Let entry be EnsureRegistered(loader, key).
  2. If entry.[[State]] is "ready", return a new error promise.
  3. If entry.[[Instantiate]] is not undefined, return entry.[[Instantiate]].
  4. Let hook be GetMethod(loader, @@instantiate).
  5. Let p be the result of transforming RequestTranslate(loader, key) with a fulfillment handler that, when called with argument source, runs the following steps:
    1. // TODO: metadata
    2. Let p0 be the result of promise-calling hook(key, source).
    3. Let p1 be the result of transforming p0 with a new pass-through promise.
    4. Let p2 be the result of transforming p1 with a fulfillment handler that, when called with argument optionalInstance, runs the following steps:
      1. Let status be CommitInstantiated(loader, entry, optionalInstance, source).
      2. ReturnIfAbrupt(status).
      3. Return entry.
    5. Return p1.
  6. Set entry.[[Instantiate]] to p.
  7. Return p.

8.2.4RequestInstantiateAll(loader, key)#

  1. Return the result of transforming RequestInstantiate(loader, key) with a fulfillment handler that, when called with argument entry, runs the following steps:
    1. Let depLoads be a new empty List.
    2. For each pair in entry.[[Dependencies]], do:
      1. Let p be the result of transforming Resolve(loader, pair.[[key]], key) with a fulfillment handler that, when called with value depKey, runs the following steps:
        1. Let depEntry be EnsureRegistered(loader, depKey).
        2. If depEntry.[[State]] is "ready", then:
          1. Let dep be depEntry.[[Module]].
          2. Set pair.[[value]] to dep.
          3. Return dep.
        3. Return the result of transforming RequestInstantiateAll(loader, depKey) with a fulfillment handler that, when called with value depEntry, runs the following steps:
          1. Let dep be depEntry.[[Module]].
          2. Set pair.[[value]] to dep.
          3. Return dep.
      2. Append p to depLoads.
    3. Let p be the result of waiting for all depLoads.
    4. Return the result of transforming p with a fulfillment handler that, when called, runs the following steps:
      1. Return entry.

8.2.5RequestLink(loader, key)#

  1. Let entry be EnsureRegistered(loader, key).
  2. If entry.[[State]] is "ready", return a promise resolved with entry.[[Module]].
  3. Return the result of transforming RequestInstantiateAll(loader, key) with a fulfillment handler that, when called with argument entry, runs the following steps:
    1. Assert: entry's whole dependency graph is in "link" state.
    2. Let status be Link(loader, entry).
    3. ReturnIfAbrupt(status).
    4. Assert: entry's whole dependency graph is in "ready" state.
    5. Return entry.

8.2.6RequestReady(loader, key)#

  1. Return the result of transforming RequestLink(loader, key) with a fulfillment handler that, when called with argument entry, runs the following steps:
    1. Let module be entry.[[Module]].
    2. Let status be the result of calling the ModuleEvaluation abstract operation of module with no arguments.
    3. ReturnIfAbrupt(status).
    4. Return module.

9Module Objects#

9.1Reflective Module Records#

A reflective module record is a kind of module record. It extends

Internal Slot Value Type (non-normative) Description (non-normative)
[[LocalExports]] A List of Strings The set of exported names stored in this module's environment.
[[IndirectExports]] A List of pairs of String and {[[module]]: Module Record, [[bindingName]]: String}. The set of re-exported bindings. This ensures that ResolveExport can fully resolve re-exports.
[[Evaluate]] A function object or undefined A thunk to call when the the module is evaluated, or undefined if the module is already evaluated.

9.2Abstract Operations for Module Objects#

9.2.1ParseExportsDescriptors(obj)#

TODO: parse as in these examples
  • uninitialized, mutable: { }
  • uninitialized, immutable: { const: true }
  • initialized, mutable: { value: 42 }
  • initialized, immutable: { value: 42, const: true }
  • re-export (immutable): { module: m, import: "foo" }
  1. // TODO: spec me

9.2.2CreateModuleMutator(module)#

  1. // TODO: spec me

9.2.3GetExportNames(exportStarStack)#

The following steps are taken:

  1. Let module be this Reflective Module Record.
  2. Let exports be a new empty List.
  3. For each name in module.[[LocalExports]], do:
    1. Append name to exports.
  4. For each pair in module.[[IndirectExports]], do:
    1. Append pair.[[key]] to exports.
  5. Return exports.

9.2.4ResolveExport(exportName, resolveStack, exportStarStack)#

  1. Let module be this Reflective Module Record.
  2. If resolveStack contains a record r such that r.[[module]] is equal to module and r.[[exportName]] is equal to exportName, then
    1. Assert: this is a circular import request.
    2. Throw a SyntaxError exception.
  3. Append the record {[[module]]: module, [[exportName]]: exportName} to resolveStack.
  4. Let exports be module.[[LocalExports]].
  5. Let pair be the pair in exports such that pair.[[key]] is equal to exportName.
  6. If pair is defined, then:
    1. Return the Record { [[module]]: module, [[bindingName]]: exportName }.
  7. Let exports be module.[[IndirectExports]].
  8. Let pair be the pair in exports such that pair.[[key]] is equal to exportName.
  9. If pair is defined, then return pair.[[value]].
  10. Return null.

9.2.5ModuleDeclarationInstantiation()#

Reflective modules are always already instantiated.

  1. Return undefined.

9.2.6ModuleEvaluation()#

  1. Let module be this Reflective Module Record.
  2. Let evaluate be module.[[Evaluate]].
  3. Set module.[[Evaluate]] to undefined.
  4. Return evaluate().

9.3The Reflect.Module Constructor#

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

The Reflect.Module 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 Module behaviour must include a super call to the Reflect.Module constructor to create and initialize the subclass instance with the internal state necessary to integrated with loaders.

9.3.1Reflect.Module(descriptors[, executor[, evaluate]])#

When Reflect.Module is called with arguments descriptors, executor, and evaluate, the following steps are taken:

  1. Let realm be the current Realm.
  2. Let env be NewModuleEnvironment(realm.[[globalEnv]]).
  3. Let exportDescriptors be ParseExportsDescriptors(descriptors). // TODO: interleave the subsequent loop with parsing?
  4. Let localExports be a new empty List.
  5. Let indirectExports be a new empty List.
  6. Let exportNames be a new empty List.
  7. Let envRec be env's environment record.
  8. For each desc in exportDescriptors, do:
    1. Let exportName be desc.[[Name]].
    2. Append exportName to exportNames.
    3. If desc is an Indirect Export Descriptor, then:
      1. Let otherMod be desc.[[Module]].
      2. Let resolution be otherMod.ResolveExport(desc.[[Import]], « »).
      3. ReturnIfAbrupt(resolution).
      4. If resolution is null, then throw a SyntaxError exception.
      5. Append the record {[[key]]: exportName, [[value]]: resolution} to indirectExports.
    4. Else:
      1. Append exportName to localExports.
      2. If desc is an Immutable Export Descriptor, then:
        1. Let status be envRec.CreateImmutableBinding(exportName, true).
        2. Assert: status is not an abrupt completion.
      3. Else:
        1. Assert: desc is a Mutable Export Descriptor.
        2. Let status be envRec.CreateMutableBinding(exportName, false).
        3. Assert: status is not an abrupt completion.
      4. If desc.[[Initialized]] is true, then:
        1. Call envRec.InitializeBinding(exportName, desc.[[Value]]).
  9. If evaluate is undefined, then let evaluated be true. Otherwise let evaluated be false.
  10. Let mod be a new Reflective Module Record {[[Realm]]: realm, [[Environment]]: env, [[Namespace]]: undefined, [[Evaluated]]: evaluated, [[LocalExports]]: localExports, [[IndirectExports]]: indirectExports, [[Evaluate]]: evaluate}.
  11. Let ns be ModuleNamespaceCreate(mod, realm, exportNames).
  12. Set mod.[[Namespace]] to ns.
  13. If executor is not undefined, then
    1. Let mutator be CreateModuleMutator(mod).
    2. Let status be executor(mutator, ns).
    3. ReturnIfAbrupt(status).
  14. Return ns.

9.4Properties of the Reflect.Module Constructor#

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

Besides the internal slots and the length property (whose value is 0), the Reflect.Loader constructor has the following properties:

9.4.1Reflect.Module.evaluate(m)#

TODO: way to force evaluation of a module namespace exotic object (Reflect.Module.evaluate(m)? m[Reflect.Module.evaluate]()?)

9.4.2Reflect.Module.prototype#

The value of Reflect.Module.prototype is an ordinary object with a null [[Prototype]].

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

9.5Properties of Module Instances#

Reflect.Module instances are module namespace exotic objects.