Stage 1 Draft / January 26, 2017

dynamic modules reform

Table 1: Additional Fields of Source Text Module Records
Field Name Value Type Meaning
[[ImportEntries]] List of ImportEntry Records A List of ImportEntry records derived from the code of this module.
[[PendingImportEntries]] List of ImportEntry Records A List of ImportEntry records that are pending to be validated.
[[LocalExportEntries]] List of ExportEntry Records A List of ExportEntry records derived from the code of this module that correspond to declarations that occur within the module.

1[[Get]] (P, Receiver)

When the [[Get]] internal method of a module namespace exotic object O is called with property key P and ECMAScript language value Receiver, the following steps are taken:

  1. Assert: IsPropertyKey(P) is true.
  2. If Type(P) is Symbol, then
    1. Return ?  OrdinaryGet(O, P, Receiver).
  3. Let exports be O.[[Exports]].
  4. If P is not an element of exports, return undefined.
  5. Let m be O.[[Module]].
  6. Let binding be ! m.ResolveExport(P, « », « »).
  7. Assert: binding is neither null nor "ambiguous".
  8. If binding is "pending" or binding is null or resolution is "ambiguous", throw a SyntaxError exception.
  9. Let targetModule be binding.[[Module]].
  10. Assert: targetModule is not undefined.
  11. Let targetEnv be targetModule.[[Environment]].
  12. If targetEnv is undefined, throw a ReferenceError exception.
  13. Let targetEnvRec be targetEnv's EnvironmentRecord.
  14. Return ? targetEnvRec.GetBindingValue(binding.[[BindingName]], true).
Note

ResolveExport is idempotent and side-effect free. An implementation might choose to pre-compute or cache the ResolveExport results for the [[Exports]] of each module namespace exotic object.

2ResolveExport( exportName, resolveSet, exportStarSet ) Concrete Method

The ResolveExport concrete method of a Source Text Module Record with arguments exportName, resolveSet, and exportStarSet performs the following steps:

  1. Let module be this Source Text Module Record.
  2. For each Record {[[Module]], [[ExportName]]} r in resolveSet, do:
    1. If module and r.[[Module]] are the same Module Record and SameValue(exportName, r.[[ExportName]]) is true, then
      1. Assert: This is a circular import request.
      2. Return null.
  3. Append the Record {[[Module]]: module, [[ExportName]]: exportName} to resolveSet.
  4. For each ExportEntry Record e in module.[[LocalExportEntries]], do
    1. If SameValue(exportName, e.[[ExportName]]) is true, then
      1. Assert: module provides the direct binding for this export.
      2. Return Record{[[Module]]: module, [[BindingName]]: e.[[LocalName]]}.
  5. For each ExportEntry Record e in module.[[IndirectExportEntries]], do
    1. If SameValue(exportName, e.[[ExportName]]) is true, then
      1. Assert: module imports a specific binding for this export.
      2. Let importedModule be ?  HostResolveImportedModule(module, e.[[ModuleRequest]]).
      3. Return ? importedModule.ResolveExport(e.[[ImportName]], resolveSet, exportStarSet).
  6. If SameValue(exportName, "default") is true, then
    1. Assert: A default export was not explicitly defined by this module.
    2. Return null.
    3. NOTE A default export cannot be provided by an export *.
  7. If exportStarSet contains module, return null.
  8. Append module to exportStarSet.
  9. Let starResolution be null.
  10. For each ExportEntry Record e in module.[[StarExportEntries]], do
    1. Let importedModule be ?  HostResolveImportedModule(module, e.[[ModuleRequest]]).
    2. Let resolution be ? importedModule.ResolveExport(exportName, resolveSet, exportStarSet).
    3. If resolution is "ambiguous", return "ambiguous".
    4. If resolution is "pending", return "pending".
    5. If resolution is not null, then
      1. If starResolution is null, let starResolution be resolution.
      2. Else,
        1. Assert: There is more than one * import that includes the requested name.
        2. If resolution.[[Module]] and starResolution.[[Module]] are not the same Module Record or SameValue(resolution.[[BindingName]], starResolution.[[BindingName]]) is false, return "ambiguous".
  11. Return starResolution.
Note

ResolveExport attempts to resolve an imported binding to the actual defining module and local binding name. The defining module may be the module represented by the Module Record this method was invoked on or some other module that is imported by that module. The parameter resolveSet is use to detect unresolved circular import/export paths. If a pair consisting of specific Module Record and exportName is reached that is already in resolveSet, an import circularity has been encountered. Before recursively calling ResolveExport, a pair consisting of module and exportName is added to resolveSet.

If a defining module is found a Record {[[Module]], [[BindingName]]} is returned. This record identifies the resolved binding of the originally requested export. If no definition was found or the request is found to be circular, null is returned. If the request is found to be ambiguous, the string "ambiguous" is returned. If the request is found to be pending, the string "pending" is returned.

3ModuleDeclarationInstantiation( ) Concrete Method

The ModuleDeclarationInstantiation concrete method of a Source Text Module Record performs the following steps:

  1. Let module be this Source Text Module Record.
  2. Let realm be module.[[Realm]].
  3. Assert: realm is not undefined.
  4. Let code be module.[[ECMAScriptCode]].
  5. If module.[[Environment]] is not undefined, return NormalCompletion( empty).
  6. Let env be NewModuleEnvironment(realm.[[GlobalEnv]]).
  7. Set module.[[Environment]] to env.
  8. For each String required that is an element of module.[[RequestedModules]] do,
    1. NOTE: Before instantiating a module, all of the modules it requested must be available. An implementation may perform this test at any time prior to this point.
    2. Let requiredModule be ?  HostResolveImportedModule(module, required).
    3. Perform ? requiredModule.ModuleDeclarationInstantiation().
  9. For each ExportEntry Record e in module.[[IndirectExportEntries]], do
    1. Let resolution be ? module.ResolveExport(e.[[ExportName]], « », « »).
    2. If resolution is null or resolution is "ambiguous", throw a SyntaxError exception.
  10. Assert: All named exports from module are resolvable.
  11. Let envRec be env's EnvironmentRecord.
  12. For each ImportEntry Record in in module.[[ImportEntries]], do
    1. Let importedModule be !  HostResolveImportedModule(module, in.[[ModuleRequest]]).
    2. NOTE: The above call cannot fail because imported module requests are a subset of module.[[RequestedModules]], and these have been resolved earlier in this algorithm.
    3. If in.[[ImportName]] is "*", then
      1. Let namespace be ?  GetModuleNamespace(importedModule).
      2. Perform ! envRec.CreateImmutableBinding(in.[[LocalName]], true).
      3. Call envRec.InitializeBinding(in.[[LocalName]], namespace).
    4. Else,
      1. Let resolution be ? importedModule.ResolveExport(in.[[ImportName]], « », « »).
      2. If resolution is null or resolution is "ambiguous", throw a SyntaxError exception.
      3. If resolution is "pending", then append in to module.[[PendingImportEntries]].
      4. Else, call envRec.CreateImportBinding(in.[[LocalName]], resolution.[[Module]], resolution.[[BindingName]]).
  13. Let varDeclarations be the VarScopedDeclarations of code.
  14. Let declaredVarNames be a new empty List.
  15. For each element d in varDeclarations do
    1. For each element dn of the BoundNames of d do
      1. If dn is not an element of declaredVarNames, then
        1. Perform ! envRec.CreateMutableBinding(dn, false).
        2. Call envRec.InitializeBinding(dn, undefined).
        3. Append dn to declaredVarNames.
  16. Let lexDeclarations be the LexicallyScopedDeclarations of code.
  17. For each element d in lexDeclarations do
    1. For each element dn of the BoundNames of d do
      1. If IsConstantDeclaration of d is true, then
        1. Perform ! envRec.CreateImmutableBinding(dn, true).
      2. Else,
        1. Perform ! envRec.CreateMutableBinding(dn, false).
      3. If d is a GeneratorDeclaration production or a FunctionDeclaration production, then
        1. Let fo be the result of performing InstantiateFunctionObject for d with argument env.
        2. Call envRec.InitializeBinding(dn, fo).
  18. Return NormalCompletion( empty).

4ModuleEvaluation() Concrete Method

The ModuleEvaluation concrete method of a Source Text Module Record performs the following steps:

  1. Let module be this Source Text Module Record.
  2. Assert: ModuleDeclarationInstantiation has already been invoked on module and successfully completed.
  3. Assert: module.[[Realm]] is not undefined.
  4. If module.[[Evaluated]] is true, return undefined.
  5. Set module.[[Evaluated]] to true.
  6. For each String required that is an element of module.[[RequestedModules]] do,
    1. Let requiredModule be !  HostResolveImportedModule(module, required).
    2. NOTE: ModuleDeclarationInstantiation must be completed prior to invoking this method, so every requested module is guaranteed to resolve successfully.
    3. Perform ? requiredModule.ModuleEvaluation().
  7. Let env be module.[[Environment]].
  8. Let envRec be env's EnvironmentRecord.
  9. For each ImportEntry Record in in module.[[PendingImportEntries]], do
    1. Let resolution be ? importedModule.ResolveExport(in.[[ImportName]], « », « »).
    2. If resolution is null or resolution is "ambiguous" or resultion is "pending", throw a SyntaxError exception.
    3. Remove ImportEntry Record in from module.[[PendingImportEntries]].
    4. Call envRec.CreateImportBinding(in.[[LocalName]], resolution.[[Module].
  10. Let moduleCxt be a new ECMAScript code execution context.
  11. Set the Function of moduleCxt to null.
  12. Set the Realm of moduleCxt to module.[[Realm]].
  13. Set the ScriptOrModule of moduleCxt to module.
  14. Assert: module has been linked and declarations in its module environment have been instantiated.
  15. Set the VariableEnvironment of moduleCxt to module.[[Environment]].
  16. Set the LexicalEnvironment of moduleCxt to module.[[Environment]].
  17. Suspend the currently running execution context.
  18. Push moduleCxt on to the execution context stack; moduleCxt is now the running execution context.
  19. Let result be the result of evaluating module.[[ECMAScriptCode]].
  20. Suspend moduleCxt and remove it from the execution context stack.
  21. Resume the context that is now on the top of the execution context stack as the running execution context.
  22. Return Completion(result).

5ParseModule ( sourceText, realm, hostDefined )

The abstract operation ParseModule with arguments sourceText, realm, and hostDefined creates a Source Text Module Record based upon the result of parsing sourceText as a Module. ParseModule performs the following steps:

  1. Assert: sourceText is an ECMAScript source text (see clause 10).
  2. Parse sourceText using Module as the goal symbol and analyze the parse result for any Early Error conditions. If the parse was successful and no early errors were found, let body be the resulting parse tree. Otherwise, let body be a List of one or more SyntaxError or ReferenceError objects representing the parsing errors and/or early errors. Parsing and early error detection may be interweaved in an implementation dependent manner. If more than one parsing error or early error is present, the number and ordering of error objects in the list is implementation dependent, but at least one must be present.
  3. If body is a List of errors, then return body.
  4. Let requestedModules be the ModuleRequests of body.
  5. Let importEntries be ImportEntries of body.
  6. Let pendingImportEntries be a new empty List.
  7. Let importedBoundNames be ImportedLocalNames(importEntries).
  8. Let indirectExportEntries be a new empty List.
  9. Let localExportEntries be a new empty List.
  10. Let starExportEntries be a new empty List.
  11. Let exportEntries be ExportEntries of body.
  12. For each record ee in exportEntries, do
    1. If ee.[[ModuleRequest]] is null, then
      1. If ee.[[LocalName]] is not an element of importedBoundNames, then
        1. Append ee to localExportEntries.
      2. Else,
        1. Let ie be the element of importEntries whose [[LocalName]] is the same as ee.[[LocalName]].
        2. If ie.[[ImportName]] is "*", then
          1. Assert: This is a re-export of an imported module namespace object.
          2. Append ee to localExportEntries.
        3. Else this is a re-export of a single name,
          1. Append to indirectExportEntries the Record {[[ModuleRequest]]: ie.[[ModuleRequest]], [[ImportName]]: ie.[[ImportName]], [[LocalName]]: null, [[ExportName]]: ee.[[ExportName]] }.
    2. Else if ee.[[ImportName]] is "*", then
      1. Append ee to starExportEntries.
    3. Else,
      1. Append ee to indirectExportEntries.
  13. Return Source Text Module Record {[[Realm]]: realm, [[Environment]]: undefined, [[HostDefined]]: hostDefined, [[Namespace]]: undefined, [[Evaluated]]: false, [[ECMAScriptCode]]: body, [[RequestedModules]]: requestedModules, [[ImportEntries]]: importEntries, [[PendingImportEntries]]: pendingImportEntries, [[LocalExportEntries]]: localExportEntries, [[StarExportEntries]]: starExportEntries, [[IndirectExportEntries]]: indirectExportEntries}.
Note

An implementation may parse module source text and analyze it for Early Error conditions prior to the evaluation of ParseModule for that module source text. However, the reporting of any errors must be deferred until the point where this specification actually performs ParseModule upon that source text.

ACopyright & Software License

Copyright Notice

© 2017 Caridy Patiño

Software License

All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT http://www.ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  3. Neither the name of the authors nor Ecma International may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.