Loader

A Collection of Interesting Ideas — Last Updated

This version:
https://whatwg.github.io/loader
Issue Tracking:
GitHub
Editors:
Eric Ferraiuolo (Yahoo)
Dave Herman (Mozilla)
Yehuda Katz (jQuery Foundation)
Caridy Patiño (Yahoo)
Version History:
https://github.com/whatwg/loader/commits
Participate:
File an issue (open issues)

Abstract

This specification describes the behavior of loading JavaScript modules from a JavaScript host environment. It also provides APIs for intercepting the module loading process and customizing loading behavior.

Table of Contents

Status

This document is a work in progress and dreams of becoming a living standard.

1. Module Loading

This section is non-normative.

1.1. Introduction

Throughout their development, JavaScript modules have been divided into two general areas:

The authoring format was carefully designed to support pre-compilation (like Browserify) and on-demand asynchronous loading (like AMD). It defines the minimal syntax necessary to allow people to write portable modules that can work across different platforms, most notably Node.js and web browsers.

The JavaScript Loader allows host environments, like Node.js and browsers, to fetch and load modules on demand. It provides a hookable pipeline, to allow front-end packaging solutions like Browserify, WebPack and jspm to hook into the loading process.

This division provides a single format that developers can use in all JavaScript environments, and a separate loading mechanism for each environment. For example, a Node Loader would load its modules from the file system, using its own module lookup algorithm, while a Browser Loader would fetch modules and use browser-supplied packaging formats.

JavaScript itself, in ECMAScript 2015, defines the module syntax and the "linking semantics" between modules. When a module is requested, it delegates responsibility for loading the module to the host environment. The Loader defines how host environments can allow JavaScript code to configure that process.

The primary goal is to make as much of this process as possible consistent between Node and Browser environments. For example, if a JavaScript program wants to translate .coffee files to JavaScript on the fly, the Loader defines a "translate" hook that can be used. This allows programs to participate in the loading process, even though some details (specifically, the process of getting a particular module from its host-defined storage) will be different between environments.

1.2. Loader Pipeline

TODO: include pipeline diagram

2. Conventions

2.1. Well-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.

2.2. Well-Known Intrinsic Objects

Well-known intrinsics are built-in objects that are explicitly referenced by the algorithms of this specification and which usually have realm-specific identities. Unless otherwise specified each intrinsic object actually corresponds to a set of similar objects, one per realm.

Within this specification a reference such as %name% means the intrinsic object, associated with the current realm, corresponding to the name. Determination of the current realm and its intrinsics is described in ES2015, 8.3.

2.3. Promises

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

2.3.1. Reacting 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.

2.4. Shorthand Phrases

2.4.1. RejectIfAbrupt(x)

Algorithm steps that say

  1. RejectIfAbrupt(x).

mean the same thing as:

  1. If x is an abrupt completion, return a promise rejected with x.[[Value]].
  2. Else if x is a Completion Record, then let x be x.[[Value]].

2.5. Common Operations

2.5.1. CreateObject()

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

2.5.2. SimpleDefine(obj, name, value)

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

2.6. Built-in Function Objects

We follow the ECMA-262 convention for built-in function objects in which the value of NewTarget in each function argument is **undefined** for [[Call]] and the newTarget parameter for [[Construct]].

3. Loader Objects

3.1. The Loader Constructor

The Loader constructor is the %Loader% intrinsic object and 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. When Loader is called as a function rather than as a constructor, it throws an exception.

The Loader constructor is designed to be subclassable. It may be used as the value of an extends clause of a class definition. Subclass constructors that intend to inherit the specified Loader behaviour must include a super call to the Loader constructor to create and initialize the subclass instance with the corresponding internal slots.

3.1.1. Loader()

When 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, "%LoaderPrototype%", «[[Realm]], [[Registry]]»).
  3. Set O’s [[Realm]] internal slot to current Realm Record.
  4. Set O’s [[Registry]] internal slot to CreateRegistry().
  5. Return O.

3.2. Properties of the Loader Constructor

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

The Loader constructor has the following properties:

3.2.1. Loader.prototype

The initial value of Loader.prototype is the intrinsic object %LoaderPrototype%.

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

3.3. Properties of the Loader Prototype Object

3.3.1. Loader.prototype.constructor

The initial value of Loader.prototype.constructor is the intrinsic object %Loader%.

3.3.2. 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 all of the internal slots of a Loader Instance (3.5), 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. Let entry be EnsureRegistered(loader, key).
    2. Return the result of transforming LoadModule(entry, "instantiate") with a fulfillment handler that, when called, runs the following steps:
      1. Return EnsureEvaluated(entry).

3.3.3. 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. If loader does not have all of the internal slots of a Loader Instance (3.5), throw a TypeError exception.
  4. Return the result of transforming Resolve(loader, name, referrer) with a new pass-through promise.

3.3.4. 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 loader does not have all of the internal slots of a Loader Instance (3.5), throw a TypeError exception.
  4. If stage is undefined then let stageValue be "instantiate".
  5. Else let stageValue be ToString(stage).
  6. RejectIfAbrupt(stageValue).
  7. If IsValidStageValue(stageValue) is false, return a promise rejected with a new RangeError exception.
  8. Return the result of transforming Resolve(loader, name, referrer) with a fulfillment handler that, when called with argument key, runs the following steps:
    1. Let entry be EnsureRegistered(loader, key).
    2. Return LoadModule(entry, stageValue).

3.3.5. get Loader.prototype.registry

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. If Type(loader) is not Object, throw a TypeError exception.
  3. If loader does not have all of the internal slots of a Loader Instance (3.5), throw a TypeError exception.
  4. Return loader.[[Registry]].

3.3.6. 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 }.

3.4. Properties of Loader Instances

Loader instances are ordinary objects that inherit properties from the *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. Registry Objects

4.1. Abstract Operations for Registry Objects

4.1.1. CreateRegistry()

The abstract operation CreateRegistry with no arguments performs the following steps:

  1. Let O be ? OrdinaryCreateFromConstructor(Registry, "%RegistryPrototype%", «[[RegistryMap]]» ).
  2. Let M be ObjectCreate(%MapIteratorPrototype%, «[[Map]], [[MapNextIndex]], [[MapIterationKind]]»).
  3. Set O’s [[RegistryMap]] internal slot to M.
  4. Return O.

4.2. The Registry Constructor

The Registry constructor is the %Registry% intrinsic object. It is not intended to be called as a function or as a constructor and will always throw an exception.

4.3. Properties of the Registry Constructor

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

The Registry constructor has the following properties:

4.3.1. Registry.prototype

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

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

4.4. Properties of the Registry Prototype Object

4.4.1. Registry.prototype.constructor

The initial value of the constructor property of the %RegistryPrototype% object is the %Registry% object.

Always throws to prevent the creation of new registry objects in user-land.

4.4.2. Registry.prototype[ @@iterator ]()

The initial value of the @@iterator property is the same function object as the initial value of the entries property.

The value of the name property of this function is "[Symbol.iterator]".

4.4.3. Registry.prototype.entries()

The following steps are taken:

  1. Let registry be this value.
  2. If Type(registry) is not Object, throw a TypeError exception.
  3. If registry does not have all of the internal slots of a Registry Instance (4.4), throw a TypeError exception.
  4. Let M be registry.[[RegistryMap]].
  5. Return CreateMapIterator(M, "key+value").

4.4.4. Registry.prototype.keys()

The following steps are taken:

  1. Let registry be this value.
  2. If Type(registry) is not Object, throw a TypeError exception.
  3. If registry does not have all of the internal slots of a Registry Instance (4.4), throw a TypeError exception.
  4. Let M be registry.[[RegistryMap]].
  5. Return CreateMapIterator(M, "key").

4.4.5. Registry.prototype.values()

The following steps are taken:

  1. Let registry be this value.
  2. If Type(registry) is not Object, throw a TypeError exception.
  3. If registry does not have all of the internal slots of a Registry Instance (4.4), throw a TypeError exception.
  4. Let M be registry.[[RegistryMap]].
  5. Return CreateMapIterator(M, "value").

4.4.6. Registry.prototype.get(key)

The following steps are taken:

  1. Let registry be this value.
  2. If Type(registry) is not Object, throw a TypeError exception.
  3. If registry does not have all of the internal slots of a Registry Instance (4.4), throw a TypeError exception.
  4. Let M be registry.[[RegistryMap]].
  5. Let entries be the List that is the value of M’s [[MapData]] internal slot.
  6. Repeat for each Record {[[key]], [[value]]} p that is an element of entries,
    1. If p.[[key]] is not empty and SameValueZero(p.[[key]], key) is true, return p.[[value]].
  7. Return undefined.

4.4.7. Registry.prototype.set(key, entry)

The following steps are taken:

  1. Let registry be this value.
  2. If Type(registry) is not Object, throw a TypeError exception.
  3. If registry does not have all of the internal slots of a Registry Instance (4.4), throw a TypeError exception.
  4. If Type(entry) is not Object, throw a TypeError exception.
  5. If entry does not have all of the internal slots of a ModuleStatus Instance (5.5), throw a TypeError exception.
  6. Let M be registry.[[RegistryMap]].
  7. Let entries be the List that is the value of M’s [[MapData]] internal slot.
  8. Repeat for each Record {[[key]], [[value]]} p that is an element of entries,
    1. If p.[[key]] is not empty and SameValueZero(p.[[key]], key) is true, then
      1. Set p.[[value]] to entry.
      2. Return registry.
  9. Let p be the Record {[[key]]: key, [[value]]: entry}.
  10. Append p as the last element of entries.
  11. Return registry.

4.4.8. Registry.prototype.has(key)

The following steps are taken:

  1. Let registry be this value.
  2. If Type(registry) is not Object, throw a TypeError exception.
  3. If registry does not have all of the internal slots of a Registry Instance (4.4), throw a TypeError exception.
  4. Let M be registry.[[RegistryMap]].
  5. Let entries be the List that is the value of M’s [[MapData]] internal slot.
  6. Repeat for each Record {[[key]], [[value]]} p that is an element of entries,
    1. If p.[[key]] is not empty and SameValueZero(p.[[key]], key) is true, then, return true.
  7. Return false.

4.4.9. Registry.prototype.delete(key)

The following steps are taken:

  1. Let registry be this value.
  2. If Type(registry) is not Object, throw a TypeError exception.
  3. If registry does not have all of the internal slots of a Registry Instance (4.4), throw a TypeError exception.
  4. Let M be registry.[[RegistryMap]].
  5. Let entries be the List that is the value of M’s [[MapData]] internal slot.
  6. Repeat for each Record {[[key]], [[value]]} p that is an element of entries,
    1. If p.[[key]] is not empty and SameValueZero(p.[[key]], key) is true, then
      1. Set p.[[key]] to empty.
      2. Set p.[[value]] to empty.
      3. Return true.
  7. Return false.
The value empty is used as a specification device to indicate that an entry has been deleted. Actual implementations may take other actions such as physically removing the entry from internal data structures.

4.5. Properties 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)
[[RegistryMap]] The Map object of pairs of String and module status. The registry of installed modules.

5. ModuleStatus Objects

5.1. Abstract Operations for ModuleStatus Objects

5.1.1. GetCurrentStage(entry)

The abstract operation GetCurrentStage with argument entry performs the following steps:

  1. Assert: entry must have all of the internal slots of a ModuleStatus Instance (5.5).
  2. Let stages be entry.[[Pipeline]].
  3. Return the first element of stages.

5.1.2. IsValidStageValue(stage)

The abstract operation IsValidStageValue with argument stage performs the following steps:

  1. Assert: Type(stage) is String.
  2. If stage is "fetch", "translate" or "instantiate", return true.
  3. Else return false.

5.1.3. GetStage(entry, stage)

The abstract operation GetStage with arguments entry and stage performs the following steps:

  1. Assert: entry must have all of the internal slots of a ModuleStatus Instance (5.5).
  2. Assert: Type(stage) is String.
  3. Let stages be entry.[[Pipeline]].
  4. For each element stageEntry of stages, do
    1. If stageEntry.[[Stage]] is equal to stage, return stageEntry.
  5. Return undefined.

5.1.4. LoadModule(entry, stage)

The abstract operation LoadModule with arguments entry and stage performs the following steps:

  1. Assert: entry must have all of the internal slots of a ModuleStatus Instance (5.5).
  2. Assert: Type(stage) is String.
  3. Assert: stage is a valid stage value.
  4. If stage is "fetch", then:
    1. Return the result of transforming RequestFetch(entry) with a new pass-through promise.
  5. If stage is "translate", then:
    1. Return the result of transforming RequestTranslate(entry) with a new pass-through promise.
  6. If stage is "instantiate", then:
    1. Return the result of transforming RequestInstantiate(entry) with a new pass-through promise.
  7. Return a promise rejected with a new RangeError exception.

5.1.5. UpgradeToStage(entry, stage)

The abstract operation UpgradeToStage with arguments entry and stage performs the following steps:

  1. Assert: entry must have all of the internal slots of a ModuleStatus Instance (5.5).
  2. Assert: Type(stage) is String.
  3. Let pipeline be entry.[[Pipeline]].
  4. Let stageEntry be GetStage(entry, stage).
  5. If stageEntry is not undefined, then
    1. Repeat while the first element of pipeline is not equal to stageEntry
      1. Remove first element from pipeline.
The internal slot [[Pipeline]] of an entry can never be empty. Alternative, this algo can be implemented using functional programming techinques or a reverse cycle to avoid walking the entries twice.

An stage is a record with the following fields:

Internal Slot Value Type (non-normative) Description (non-normative)
[[Stage]] "fetch", "translate", "instantiate" A constant value to indicating which phase the entry is at.
[[Result]] Promise or undefined A promise for the stage entry.

Each [[Stage]] value indicates the currently pending operation. If the [[Result]] field is *undefined*, the operation has not been initiated; if the [[Result]] field is a promise, the operation has been initiated but not completed. Once a stage completes, its Stage Entry is removed from the pipeline. The following table describes the intended purpose of each stage of the pipeline:

Value Description (non-normative)
"fetch" fetching the requested module (e.g. from a filesystem or network)
"translate" translating the fetched source (as via a preprocessor or compiler)
"instantiate" instantiating the translated source as a Module Record

5.2. The ModuleStatus Constructor

The ModuleStatus constructor is the %ModuleStatus% intrinsic object and the initial value of the Status property of the Reflect.Module object. When called as a constructor it creates and initializes a new ModuleStatus object. When ModuleStatus is called as a function rather than as a constructor, it throws an exception.

The ModuleStatus constructor is designed to be subclassable. It may be used as the value of an extends clause of a class definition. Subclass constructors that intend to inherit the specified ModuleStatus behaviour must include a super call to the ModuleStatus constructor to create and initialize the subclass instance with the corresponding internal slots.

5.2.1. ModuleStatus(loader, key, ns)

When ModuleStatus is called with arguments loader, key and ns, 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. If loader does not have all of the internal slots of a Loader Instance (3.5), throw a TypeError exception.
  4. Let keyString be ? ToString(key).
  5. Let O be ? OrdinaryCreateFromConstructor(NewTarget, "%ModuleStatusPrototype%", «[[Loader]], [[Pipeline]], [[Key]], [[Module]], [[Metadata]], [[Dependencies]], [[Error]]» ).
  6. Let pipeline be a new List.
  7. If ns is undefined, then:
    1. Let module be undefined.
    2. Let deps be undefined.
    3. Add new stage entry record { [[Stage]]: "fetch", [[Result]]: undefined } as a new element of the list pipeline.
    4. Add new stage entry record { [[Stage]]: "translate", [[Result]]: undefined } as a new element of the list pipeline.
    5. Add new stage entry record { [[Stage]]: "instantiate", [[Result]]: undefined } as a new element of the list pipeline.
  8. Else,
    1. If ns is not a module namespace exotic object, throw a TypeError exception.
    2. Let module be ns.[[Module]].
    3. Let deps be a new empty List.
    4. Assert: module is a Module Record.
    5. Assert: All [[RequestedModule]] of module are safistied.
    6. Let result be a promise resolved with ns.
    7. Add new stage entry record { [[Stage]]: "instantiate", [[Result]]: result } as a new element of the list pipeline.
  9. Set O’s [[Loader]] internal slot to loader.
  10. Set O’s [[Pipeline]] internal slot to pipeline.
  11. Set O’s [[Key]] internal slot to keyString.
  12. Set O’s [[Module]] internal slot to module.
  13. Set O’s [[Metadata]] internal slot to undefined.
  14. Set O’s [[Dependencies]] internal slot to deps.
  15. Set O’s [[Error]] internal slot to false.
  16. Return O.
A module status is associated to a loader instance at the time of its creation, the [[Loader]] backpointer reflects that. The optional third argument ns allows to create a module status in a way that synchronously circumvents the asynchronous loading process. A module status can be set into multiple Registry instances.

5.3. Properties of the ModuleStatus Constructor

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

The ModuleStatus constructor has the following properties:

5.3.1. ModuleStatus.prototype

The initial value of ModuleStatus.prototype is the intrinsic object %ModuleStatusPrototype%.

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

5.4. Properties of the ModuleStatus Prototype Object

5.4.1. ModuleStatus.prototype.constructor

The initial value of ModuleStatus.prototype.constructor is the intrinsic object %ModuleStatus%.

5.4.2. get ModuleStatus.prototype.stage

ModuleStatus.prototype.stage is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let entry be this value.
  2. If Type(entry) is not Object, throw a TypeError exception.
  3. If entry does not have all of the internal slots of a ModuleStatus Instance (5.5), throw a TypeError exception.
  4. Let stageEntry be GetCurrentStage(entry).
  5. Return stageEntry.[[Stage]].

5.4.3. get ModuleStatus.prototype.originalKey

ModuleStatus.prototype.originalKey is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let entry be this value.
  2. If Type(entry) is not Object, throw a TypeError exception.
  3. If entry does not have all of the internal slots of a ModuleStatus Instance (5.5), throw a TypeError exception.
  4. Return entry.[[Key]].

5.4.4. get ModuleStatus.prototype.module

ModuleStatus.prototype.module is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let entry be this value.
  2. If Type(entry) is not Object, throw a TypeError exception.
  3. If entry does not have all of the internal slots of a ModuleStatus Instance (5.5), throw a TypeError exception.
  4. Let module be entry.[[Module]].
  5. If module is a Module Record, return GetModuleNamespace(module).
  6. Return undefined.

5.4.5. get ModuleStatus.prototype.error

ModuleStatus.prototype.error is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let entry be this value.
  2. If Type(entry) is not Object, throw a TypeError exception.
  3. If entry does not have all of the internal slots of a ModuleStatus Instance (5.5), throw a TypeError exception.
  4. Return entry.[[Error]].

5.4.6. get ModuleStatus.prototype.dependencies

ModuleStatus.prototype.dependencies is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let entry be this value.
  2. If Type(entry) is not Object, throw a TypeError exception.
  3. If entry does not have all of the internal slots of a ModuleStatus Instance (5.5), throw a TypeError exception.
  4. Let array be ArrayCreate(0).
  5. Let n be 0.
  6. For each pair in entry.[[Dependencies]], do:
    1. Let O be ObjectCreate(%ObjectPrototype%).
    2. Let requestNameDesc be the PropertyDescriptor{[[Value]]: pair.[[RequestName]], [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: false}.
    3. Perform ? DefinePropertyOrThrow(O, "requestName", requestNameDesc).
    4. Let moduleStatusDesc be the PropertyDescriptor{[[Value]]: pair.[[ModuleStatus]], [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: false}.
    5. Perform ? DefinePropertyOrThrow(O, "entry", moduleStatusDesc).
    6. Perform ? CreateDataProperty(array, ? ToString(n), O).
    7. Increment n by 1.
  7. Return array.
The dependencies accessor provides access to the dependency graph, exposing each dependency’s requestName, key and entry reference.

5.4.7. ModuleStatus.prototype.load(stage)

The following steps are taken:

  1. Let entry be this value.
  2. If Type(entry) is not Object, return a promise rejected with a new TypeError exception.
  3. If entry does not have all of the internal slots of a ModuleStatus Instance (5.5), return a promise rejected with a new TypeError exception.
  4. If stage is undefined, let stageValue be "fetch"; otherwise, let stageValue be ToString(stage).
  5. RejectIfAbrupt(stageValue).
  6. If IsValidStageValue(stageValue) is false, return a promise rejected with a new RangeError exception.
  7. Return LoadModule(entry, stageValue).

5.4.8. ModuleStatus.prototype.result(stage)

The following steps are taken:

  1. Let entry be this value.
  2. If Type(entry) is not Object, return a promise rejected with a new TypeError exception.
  3. If entry does not have all of the internal slots of a ModuleStatus Instance (5.5), return a promise rejected with a new TypeError exception.
  4. Let stageValue be ToString(stage).
  5. RejectIfAbrupt(stageValue).
  6. If IsValidStageValue(stageValue) is false, return a promise rejected with a new RangeError exception.
  7. Let stageEntry be GetStage(entry, stageValue).
  8. If stageEntry is undefined, return a promise resolved with undefined.
  9. If stageEntry.[[Result]] is undefined, return a promise resolved with undefined.
  10. Return the result of transforming stageEntry.[[Result]] with a new pass-through promise.

5.4.9. ModuleStatus.prototype.resolve(stage, result)

The following steps are taken:

  1. Let entry be this value.
  2. If Type(entry) is not Object, return a promise rejected with a new TypeError exception.
  3. If entry does not have all of the internal slots of a ModuleStatus Instance (5.5), return a promise rejected with a new TypeError exception.
  4. Let stageValue be ToString(stage).
  5. RejectIfAbrupt(stageValue).
  6. If IsValidStageValue(stageValue) is false, return a promise rejected with a new RangeError exception.
  7. Let stageEntry be GetStage(entry, stageValue).
  8. If stageEntry is undefined, return a promise rejected with a new TypeError exception.
  9. Perform UpgradeToStage(entry, stageValue).
  10. Let p0 be the result of transforming result with a new pass-through promise.
  11. Let p1 be the result of transforming p0 with a fulfillment handler that, when called with argument value, runs the following steps:
    1. If stageValue is "instantiate", then:
      1. Return the result of transforming SatisfyInstance(entry, value, undefined, undefined) with a fulfillment handler that, when called with value instance, runs the following steps:
        1. Set entry.[[Module]] to instance.
        2. Let stageEntry be GetStage(entry, stageValue).
        3. Assert: stageEntry is not undefined.
        4. Fulfill stageEntry.[[Result]] with value.
    2. Else,
      1. Let stageEntry be GetStage(entry, stageValue).
      2. If stageEntry is undefined, throw a new TypeError.
      3. Fulfill stageEntry.[[Result]] with value.
  12. Let pCatch be the result of transforming p1 with a rejection handler that, when called, runs the following steps:
    1. Set entry.[[Error]] to true.
  13. If stageEntry.[[Result]] is undefined, set stageEntry.[[Result]] to p1.
  14. Return p1.

5.4.10. ModuleStatus.prototype.reject(stage, error)

The following steps are taken:

  1. Let entry be this value.
  2. If Type(entry) is not Object, return a promise rejected with a new TypeError exception.
  3. If entry does not have all of the internal slots of a ModuleStatus Instance (5.5), return a promise rejected with a new TypeError exception.
  4. Let stageValue be ToString(stage).
  5. RejectIfAbrupt(stageValue).
  6. If IsValidStageValue(stageValue) is false, return a promise rejected with a new RangeError exception.
  7. Let stageEntry be GetStage(entry, stageValue).
  8. If stageEntry is undefined, return a promise rejected with a new TypeError exception.
  9. Perform UpgradeToStage(entry, stageValue).
  10. Let p0 be the result of transforming error with a new pass-through promise.
  11. Let p1 be the result of transforming p0 with a fulfillment handler that, when called with argument value, runs the following steps:
    1. Let stageEntry be GetStage(entry, stageValue).
    2. If stageEntry is undefined, throw a new TypeError.
    3. Reject stageEntry.[[Result]] with value.
  12. Let pCatch be the result of transforming p1 with a rejection handler that, when called, runs the following steps:
    1. Set entry.[[Error]] to true.
  13. If stageEntry.[[Result]] is undefined, set stageEntry.[[Result]] to p1.
  14. Return p1.

5.5. Properties of ModuleStatus Instances

ModuleStatus instances are ordinary objects that inherit properties from the %ModuleStatusPrototype%.

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

Internal Slot Value Type (non-normative) Description (non-normative)
[[Loader]] An object The loader this module status belongs to.
[[Pipeline]] A List A list whose elements are stage records.
[[Key]] A String A value that identifies what key was used to create the module status instance.
[[Metadata]] Object or undefined The metadata object passed through the pipeline.
[[Dependencies]] List of Records of the form {[[RequestName]]: String, [[ModuleStatus]]: Module Status} . Table mapping unresolved names to their resolved key and module status entries.
[[Module]] Module Record or Function object or undefined The Module Record or a thunk after the module has been satisfied; otherwise undefined.
[[Error]] A Boolean A boolean valued that if true indicates that an error that was encountered during one of the phases of the loading pipeline; false if no error has been encountered.

6. Loading Semantics

6.1. Auxiliary Operations

6.1.1. EnsureRegistered(loader, key)

When the abstract operation EnsureRegistered is called with arguments loader and key, the following steps are taken:

  1. Assert: loader must have all of the internal slots of a Loader Instance (3.5).
  2. Assert: Type(key) is String.
  3. Let registry be loader.[[Registry]].
  4. Let pair be the entry in registry.[[RegistryMap]] such that pair.[[Key]] is equal to key.
  5. If pair exists, then:
    1. Let entry be pair.[[Value]].
  6. Else,
    1. Let entry be a new ModuleStatus(loader, key).
  7. Return entry.

6.1.2. Resolve(loader, name, referrer)

When the abstract operation Resolve is called with arguments loader, name and referrer, the following steps are taken:

  1. Assert: loader must have all of the internal slots of a Loader Instance (3.5).
  2. Assert: Type(name) is String.
  3. Assert: Type(referrer) is String.
  4. Let hook be GetMethod(loader, @@resolve).
  5. Return the result of promise-calling hook(name, referrer).

6.1.3. ExtractDependencies(entry, instance)

When the abstract operation ExtractDependencies is called with arguments entry and instance, the following steps are taken:

  1. Assert: entry must have all of the internal slots of a ModuleStatus Instance (5.5).
  2. Let deps be a new empty List.
  3. If instance is a Source Text Module Record, then:
    1. For each dep in instance.[[RequestedModules]], do:
      1. Append the record { [[RequestName]]: dep, [[ModuleStatus]]: undefined } to deps.
  4. Set entry.[[Dependencies]] to deps.
[[Key]] will identifies the dependency module status in the entry’s corresponding loader.

6.1.4. Instantiation(loader, optionalInstance, source)

When the abstract operation Instantiation is called with arguments loader, optionalInstance and source, the following steps are taken:

  1. Assert: loader must have all of the internal slots of a Loader Instance (3.5).
  2. If optionalInstance is undefined, then:
    1. If source is not a ECMAScript source text, throw new TypeError.
    2. Let realm be loader.[[Realm]].
    3. Return ? ParseModule(source, realm, undefined).
  3. If optionalInstance is a namespace exotic object, return optionalInstance.[[Module]].
  4. If IsCallable(optionalInstance) is false then throw a new TypeError.
  5. Return optionalInstance.

6.2. Loading Operations

6.2.1. RequestFetch(entry)

When the abstract operation RequestFetch is called with argument entry, the following steps are taken:

  1. Assert: entry must have all of the internal slots of a ModuleStatus Instance (5.5).
  2. Let fetchStageEntry be GetStage(entry, "fetch").
  3. If fetchStageEntry is undefined, return a promise resolved with undefined.
  4. If fetchStageEntry.[[Result]] is not undefined, return fetchStageEntry.[[Result]].
  5. Let hook be GetMethod(entry.[[Loader]], @@fetch).
  6. Let hookResult be the result of promise-calling hook(entry, entry.[[Key]]).
  7. Let p be the result of transforming hookResult with a fulfillment handler that, when called with argument payload, runs the following steps:
    1. Perform UpgradeToStage(entry, "translate").
    2. Return payload.
  8. Let pCatch be the result of transforming p with a rejection handler that, when called, runs the following steps:
    1. Set entry.[[Error]] to true.
  9. Set fetchStageEntry.[[Result]] to p.
  10. Return p.

6.2.2. RequestTranslate(entry)

When the abstract operation RequestTranslate is called with argument entry, the following steps are taken:

  1. Assert: entry must have all of the internal slots of a ModuleStatus Instance (5.5).
  2. Let translateStageEntry be GetStage(entry, "translate").
  3. If translateStageEntry is undefined, return a promise resolved with undefined.
  4. If translateStageEntry.[[Result]] is not undefined, return translateStageEntry.[[Result]].
  5. Let p be the result of transforming RequestFetch(entry) with a fulfillment handler that, when called with argument payload, runs the following steps:
    1. Let hook be GetMethod(entry.[[Loader]], @@translate).
    2. Let hookResult be the result of promise-calling hook(entry, payload).
    3. Return the result of transforming hookResult with a fulfillment handler that, when called with argument source, runs the following steps:
      1. Perform UpgradeToStage(entry, "instantiate").
      2. Return source.
  6. Let pCatch be the result of transforming p with a rejection handler that, when called, runs the following steps:
    1. Set entry.[[Error]] to true.
  7. Set translateStageEntry.[[Result]] to p.
  8. Return p.

6.2.3. RequestInstantiate(entry, instantiateSet)

When the abstract operation RequestInstantiate is called with arguments entry and instantiateSet, the following steps are taken:

  1. Assert: entry must have all of the internal slots of a ModuleStatus Instance (5.5).
  2. Let instantiateStageEntry be GetStage(entry, "instantiate").
  3. If instantiateStageEntry is undefined, return a promise resolved with undefined.
  4. If instantiateStageEntry.[[Result]] is not undefined, return instantiateStageEntry.[[Result]].
  5. Let p be the result of transforming RequestTranslate(entry) with a fulfillment handler that, when called with argument source, runs the following steps:
    1. Let hook be GetMethod(entry.[[Loader]], @@instantiate).
    2. Let hookResult be the result of promise-calling hook(entry, source).
    3. Return the result of transforming hookResult with a fulfillment handler that, when called with argument optionalInstance, runs the following steps:
      1. Return the result of transforming SatisfyInstance(entry, optionalInstance, source, instantiateSet) with a fulfillment handler that, when called with value instance, runs the following steps:
        1. Set entry.[[Module]] to instance.
        2. Return optionalInstance.
  6. Let pCatch be the result of transforming p with a rejection handler that, when called, runs the following steps:
    1. Set entry.[[Error]] to true.
  7. Set instantiateStageEntry.[[Result]] to p.
  8. Return p.

6.2.4. SatisfyInstance(entry, optionalInstance, source, instantiateSet)

When the abstract operation SatisfyInstance is called with arguments entry, optionalInstance, source and instantiateSet, the following steps are taken:

  1. Assert: entry must have all of the internal slots of a ModuleStatus Instance (5.5).
  2. If instantiateSet is undefined, Set instantiateSet to a new empty List.
  3. If entry is already in instantiateSet, return undefined.
  4. Append entry to instantiateSet.
  5. Let loader be entry.[[Loader]].
  6. Let instance be ? Instantiation(loader, optionalInstance, source).
  7. If instance is a Module Record, then:
    1. Set instance.[[ModuleStatus]] to entry.
  8. Perform ? ExtractDependencies(entry, instance).
  9. Let list be a new empty List.
  10. For each pair in entry.[[Dependencies]], do:
    1. Let p be the result of transforming Resolve(loader, pair.[[RequestName]], entry.[[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 is already in instantiateSet, return undefined.
      3. Set pair.[[ModuleStatus]] to depEntry.
      4. Return RequestInstantiate(depEntry, instantiateSet).
    2. Append p to list.
  11. Return the result of waiting for all list with a fulfillment handler that, when called, return instance.
This abstract operation guarantees that all [[Dependencies]] are instantiated and ready to be linked and evaluated.

7. Linking Semantics

7.1. Resolving Dependencies

7.1.1. HostResolveImportedModule(module, requestName)

The modules spec should only invoke this abstract operation from methods of Source Text Module Records, and this spec does not invoke the operation at all.

When the abstract operation HostResolveImportedModule is called with arguments module and requestName, the following steps are taken:

  1. Assert: module is a Source Text Module Record.
  2. Assert: Type(requestName) is String.
  3. Let entry be module.[[ModuleStatus]].
  4. Let currentStageEntry be GetCurrentStage(entry).
  5. Assert: currentStageEntry.[[Stage]] is "instantiate" and currentStageEntry.[[Result]] is a resolved promise.
  6. Let pair be the pair in entry.[[Dependencies]] such that pair.[[RequestName]] is equal to requestName.
  7. Assert: pair is defined.
  8. Let depEntry be pair.[[ModuleStatus]].
  9. Let depStageEntry be GetCurrentStage(depEntry).
  10. Assert: depStageEntry.[[Stage]] is "instantiate" and depStageEntry.[[Result]] is a resolved promise.
  11. Return depEntry.[[Module]].

7.2. Linking

7.2.1. DependencyGraph(root)

When the abstract operation DependencyGraph is called with argument root the following steps are taken:

  1. Assert: root must have all of the internal slots of a ModuleStatus Instance (5.5).
  2. Let result be a new empty List.
  3. Call ComputeDependencyGraph(root, result).
  4. Return result.

7.2.2. ComputeDependencyGraph(entry, result)

When the abstract operation ComputeDependencyGraph is called with arguments entry and result, the following steps are taken:

  1. Assert: entry must have all of the internal slots of a ModuleStatus Instance (5.5).
  2. Assert: result must be a List.
  3. If entry is already in result, return undefined.
  4. Insert entry as the first element of result.
  5. For each pair in entry.[[Dependencies]], do:
    1. Assert: pair.[[ModuleStatus]] is defined.
    2. Call ComputeDependencyGraph(pair.[[ModuleStatus]], result).
  6. Return undefined.

7.2.3. EnsureLinked(entry)

When the abstract operation EnsureLinked is called with argument entry the following steps are taken:

  1. Assert: entry must have all of the internal slots of a ModuleStatus Instance (5.5).
  2. Let deps be DependencyGraph(entry).
  3. For each dep in deps, do:
    1. Let depStageEntry be GetCurrentStage(dep).
    2. Assert: depStageEntry.[[Stage]] is "instantiate" and depStageEntry.[[Result]] is a resolved promise.
    3. If dep.[[Module]] is a Function object, then:
      1. Let func be dep.[[Module]].
      2. Let argList be a new empty List.
      3. Let ns be ? Call(func, undefined, argList).
      4. If ns is not a module namespace exotic object, throw a TypeError exception.
      5. Set dep.[[Module]] to ns.[[Module]].
  4. Assert: the following sequence is guaranteed not to run any user code.
  5. For each dep in deps, do:
    1. Let module be dep.[[Module]].
    2. Assert: module is a Module Record.
    3. Perform ? module.ModuleDeclarationInstantiation().

7.2.4. EnsureEvaluated(entry)

When the abstract operation EnsureEvaluated is called with argument entry, the following steps are taken:

  1. Assert: entry must have all of the internal slots of a ModuleStatus Instance (5.5).
  2. Let stageEntry be GetCurrentStage(entry).
  3. Assert: stageEntry.[[Stage]] is "instantiate" and stageEntry.[[Result]] is a resolved promise.
  4. Let module be entry.[[Module]].
  5. If module.[[Evaluated]] is false, then:
    1. Perform ? EnsureLinked(entry).
    2. Perform ? module.ModuleEvaluation().
  6. Return ? GetModuleNamespace(module).

8. Module Objects

8.1. Reflective Module Records

A reflective module record is a kind of module record. In addition to the fields, defined in ES2016 Table 37, Reflective Module Records have the additional fields listed below. Each of these fields initially has the value undefined.

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.

-

8.2. Abstract Operations for Module Objects

8.2.1. ParseExportsDescriptors(obj)

When the abstract operation ParseExportsDescriptors is called with argument obj, the following steps are taken:

  1. Assert: Type(obj) is an Object.
  2. Let props be ? ToObject(Obj).
  3. Let keys be ? props.[[OwnPropertyKeys]]().
  4. Let descriptors be an empty List.
  5. Repeat for each element nextKey of keys in List order,
    1. Let propDesc be ? props.[[GetOwnProperty]](nextKey).
    2. If propDesc is not undefined and propDesc.[[Enumerable]] is true, then
      1. Let descObj be ? Get(props, nextKey).
      2. Let hasModule be ? HasProperty(descObj, "module").
      3. If hasModule is true, then
        1. Let ns be ? Get(descObj, "module").
        2. If ns is not a module namespace exotic object, throw a TypeError exception.
        3. Let import be ToString(? Get(descObj, "import")).
        4. Let desc be a new Indirect Export Descriptor Record {[[Name]]: nextKey, [[Module]]: ns.[[Module]], [[Import]]: import}.
      4. Else,
        1. Let hasValue be ? HasProperty(descObj, "value").
        2. If hasValue is true, let value be ? Get(descObj, "value").
        3. Let hasConst be ? HasProperty(descObj, "const").
        4. If hasConst is true, let isConst be ToBoolean(? Get(descObj, "const")).
        5. If isConst is true, then
          1. If hasValue is true, then
            1. Let desc be a new Immutable Export Descriptor Record {[[Name]]: nextKey, [[Value]]: value, [[Initialized]]: true}.
          2. Else,
            1. Let desc be a new Immutable Export Descriptor Record {[[Name]]: nextKey, [[Value]]: undefined, [[Initialized]]: false}.
        6. Else,
          1. If hasValue is true, then
            1. Let desc be a new Mutable Export Descriptor Record {[[Name]]: nextKey, [[Value]]: value, [[Initialized]]: true}.
          2. Else,
            1. Let desc be a new Mutable Export Descriptor Record {[[Name]]: nextKey, [[Value]]: undefined, [[Initialized]]: false}.
      5. Append desc to the end of descriptors.
  6. Return descriptors.
Parse as in these examples

8.2.2. CreateModuleMutator(module)

When the abstract operation CreateModuleMutator is called with argument module, the following steps are taken:

  1. Assert: module is a Reflective Module Records.
  2. Let mutator be ObjectCreate(%ObjectPrototype%).
  3. Let env be module.[[Environment]].
  4. Let envRec be env’s environment record.
  5. For each name in module.[[LocalExports]], do:
    1. Assert: mutator does not already have a binding for name.
    2. Let p be MakeArgSetter(name, envRec).
    3. Let localExportDesc be the PropertyDescriptor{[[Get]]: %ThrowTypeError%, [[Set]]: p, [[Enumerable]]: true, [[Configurable]]: false}.
    4. Perform ? DefinePropertyOrThrow(mutator, name, localExportDesc).
  6. Return mutator.

8.2.3. GetExportNames(exportStarStack)

When the abstract operation GetExportNames is called with argument 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.

8.2.4. ResolveExport(exportName, resolveStack, exportStarStack)

When the abstract operation ResolveExport is called with arguments exportName, resolveStack and exportStarStack, the following steps are taken:

  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 localExports be module.[[LocalExports]].
  5. If exportName is in localExports, then:
    1. Return the Record { [[module]]: module, [[bindingName]]: exportName }.
  6. Let indirectExports be module.[[IndirectExports]].
  7. Let pair be the pair in indirectExports such that pair.[[Key]] is equal to exportName.
  8. If pair is defined, return pair.[[Value]].
  9. Return null.

8.2.5. ModuleDeclarationInstantiation()

When the abstract operation ModuleDeclarationInstantiation is called with no arguments, the following steps are taken:

  1. Return undefined.
Reflective modules are always already instantiated.

8.2.6. ModuleEvaluation()

When the abstract operation ModuleEvaluation is called with no arguments, the following steps are taken:

  1. Let module be this Reflective Module Record.
  2. If module.[[Evaluated]] is true, return undefined.
  3. Let func be module.[[Evaluate]].
  4. Set module.[[Evaluated]] to true.
  5. Set module.[[Evaluate]] to undefined.
  6. For each pair in module.[[IndirectExports]], do:
    1. Let requiredModule be pair.[[Value]].[[module]].
    2. Assert: requiredModule is a Module Record.
    3. Perform ? requiredModule.ModuleEvaluation().
  7. If IsCallable(func) is true, then:
    1. Let argList be a new empty List.
    2. Perform ? Call(func, undefined, argList).
  8. Return undefined.

8.3. The 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. Module is not intended to be called as a function and will throw an exception when called in that manner.

The 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 Module constructor to create and initialize the subclass instance with the internal stage necessary to integrated with loaders.

8.3.1. Module(descriptors[, executor[, evaluate]])

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

  1. Let realm be the current Realm Record.
  2. Let env be NewModuleEnvironment(realm.[[globalEnv]]).
  3. If Type(descriptors) is not Object, throw a TypeError exception.
  4. Let exportDescriptors be ParseExportsDescriptors(descriptors). // TODO: interleave the subsequent loop with parsing?
  5. Let localExports be a new empty List.
  6. Let indirectExports be a new empty List.
  7. Let exportNames be a new empty List.
  8. Let envRec be env’s environment record.
  9. 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. If resolution is null, then throw a SyntaxError exception.
      4. 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. Perform ? envRec.CreateImmutableBinding(exportName, true).
      3. Else,
        1. Assert: desc is a Mutable Export Descriptor.
        2. Perform ? envRec.CreateMutableBinding(exportName, false).
      4. If desc.[[Initialized]] is true, then:
        1. Call envRec.InitializeBinding(exportName, desc.[[Value]]).
  10. If evaluate is not undefined, then
    1. If IsCallable(evaluate) is false, throw a new TypeError exception.
  11. Let mod be a new Reflective Module Record {[[Realm]]: realm, [[Environment]]: env, [[Namespace]]: undefined, [[LocalExports]]: localExports, [[IndirectExports]]: indirectExports, [[Evaluated]]: false, [[Evaluate]]: evaluate, [[HostDefined]]: undefined}.
  12. Let ns be ModuleNamespaceCreate(mod, realm, exportNames).
  13. Set mod.[[Namespace]] to ns.
  14. If executor is not undefined, then
    1. If IsCallable(executor) is false, throw a new TypeError exception.
    2. Let mutator be CreateModuleMutator(mod).
    3. Perform ? executor(mutator, ns).
  15. Return ns.

8.4. Properties of the Module Constructor

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

The Loader constructor has the following properties:

8.4.1. Module.evaluate(ns)

When Module.evaluate is called with argument ns, the following steps are taken:

  1. If ns is not a module namespace exotic object, throw a TypeError exception.
  2. Let module be ns.[[Module]].
  3. Let entry be module.[[Entry]].
  4. Let status be EnsureEvaluated(entry).
  5. RejectIfAbrupt(status);
  6. Return a promise resolved with undefined.

8.4.2. Module.prototype

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

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

8.5. Properties of Module Instances

Module instances are module namespace exotic objects.

9. Local Loading

TODO:

10. Browser Loader

Every host environment must implement a default loader object as the initial value of the loader property of the System object.

10.1. System.loader Object

The Default Browser Loader Object is an %BrowserLoader% instance, whose internal slots are set as if it had been constructed by the expression Construct(%BrowserLoader%).

11. BrowserLoader Objects

11.1. The BrowserLoader Constructor

The BrowserLoader constructor is the %BrowserLoader% intrinsic object. When called as a constructor it creates and initializes a new BrowserLoader object. When BrowserLoader is called as a function rather than as a constructor, it throws an exception.

11.2. Properties of the BrowserLoader Constructor

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

The BrowserLoader constructor has the following properties:

11.2.1. BrowserLoader.prototype

The initial value of BrowserLoader.prototype is the intrinsic object %BrowserLoaderPrototype%.

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

11.3. Properties of the BrowserLoader Prototype

11.3.1. BrowserLoader.prototype[ @@resolve ](name, referrer)

When the @@resolve method is called, the following steps are taken:

TODO: name resolution policy

The value of the name property of this function is "[Reflect.Loader.resolve]".

11.3.2. BrowserLoader.prototype[ @@fetch ](entry, key)

When the @@fetch method is called, the following steps are taken:

TODO:

The value of the name property of this function is "[Reflect.Loader.fetch]".

11.3.3. BrowserLoader.prototype[ @@translate ](entry, payload)

When the @@translate method is called, the following steps are taken:

TODO: no-op.

The value of the name property of this function is "[Reflect.Loader.translate]".

11.3.4. BrowserLoader.prototype[ @@instantiate ](entry, source)

When the @@instantiate method is called, the following steps are taken:

TODO:

The value of the name property of this function is "[Reflect.Loader.instantiate]".

Annexes

List of Well-Known Intrinsic Objects

The intrinsics are listed in table below:

Intrinsic Name Description (non-normative)
%Loader% The loader constructor (3.1)
%LoaderPrototype% The initial value of the *prototype* data property of %Loader% (3.2.1)
%BrowserLoader% The browser loader constructor (11.1)
%BrowserLoaderPrototype% The initial value of the *prototype* data property of %BrowserLoader% (11.2.1)
%Registry% The registry constructor (4.2)
%RegistryPrototype% The initial value of the *prototype* data property of %Registry% (4.3.1)
%ModuleStatus% The module status constructor (5.2)
%ModuleStatusPrototype% The initial value of the *prototype* data property of %ModuleStatus% (5.3.1)

Conformance

All diagrams, examples, and notes in this specification are non-normative, as are all sections explicitly marked non-normative. Everything else in this specification is normative.

The key words "MUST", "MUST NOT", "REQUIRED", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in the normative parts of this specification are to be interpreted as described in RFC2119. For readability, these words do not appear in all uppercase letters in this specification. [RFC2119]

Conformance requirements phrased as algorithms or specific steps may be implemented in any manner, so long as the end result is equivalent. (In particular, the algorithms defined in this specification are intended to be easy to follow, and not intended to be performant.)

Index

Terms defined by this specification

References

Normative References

[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://tools.ietf.org/html/rfc2119