Skip to content

Commit

Permalink
Bug 1496852 - Update spec references in Module.js r=jorendorff
Browse files Browse the repository at this point in the history
Update spec references and step numbers to match ES2020. Add TODOs for the
missing steps. There are some editorial changes in latest draft that affect
step numbers, but behaviour is the same for these methods.

Differential Revision: https://phabricator.services.mozilla.com/D80984
  • Loading branch information
moztcampbell committed Jul 15, 2020
1 parent 6c06ff6 commit e67cc9e
Showing 1 changed file with 55 additions and 42 deletions.
97 changes: 55 additions & 42 deletions js/src/builtin/Module.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,43 +12,44 @@ function CallModuleResolveHook(module, specifier, expectedMinimumStatus)
return requestedModule;
}

// 15.2.1.16.2 GetExportedNames(exportStarSet)
// https://tc39.es/ecma262/#sec-getexportednames
// ES2020 15.2.1.17.2 GetExportedNames
function ModuleGetExportedNames(exportStarSet = new_List())
{
if (!IsObject(this) || !IsModule(this)) {
return callFunction(CallModuleMethodIfWrapped, this, exportStarSet,
"ModuleGetExportedNames");
}

// Step 1
// Step 3
let module = this;

// Step 2
// Step 4
if (callFunction(ArrayIncludes, exportStarSet, module))
return new_List();

// Step 3
// Step 5
_DefineDataProperty(exportStarSet, exportStarSet.length, module);

// Step 4
// Step 6
let exportedNames = new_List();
let namesCount = 0;

// Step 5
// Step 7
let localExportEntries = module.localExportEntries;
for (let i = 0; i < localExportEntries.length; i++) {
let e = localExportEntries[i];
_DefineDataProperty(exportedNames, namesCount++, e.exportName);
}

// Step 6
// Step 8
let indirectExportEntries = module.indirectExportEntries;
for (let i = 0; i < indirectExportEntries.length; i++) {
let e = indirectExportEntries[i];
_DefineDataProperty(exportedNames, namesCount++, e.exportName);
}

// Step 7
// Step 9
let starExportEntries = module.starExportEntries;
for (let i = 0; i < starExportEntries.length; i++) {
let e = starExportEntries[i];
Expand Down Expand Up @@ -82,7 +83,8 @@ function ModuleSetStatus(module, newStatus)
UnsafeSetReservedSlot(module, MODULE_OBJECT_STATUS_SLOT, newStatus);
}

// 15.2.1.16.3 ResolveExport(exportName, resolveSet)
// https://tc39.es/ecma262/#sec-getexportednames
// ES2020 15.2.1.17.3 ResolveExport
//
// Returns an object describing the location of the resolved export or
// indicating a failure.
Expand All @@ -104,10 +106,10 @@ function ModuleResolveExport(exportName, resolveSet = new_List())
"ModuleResolveExport");
}

// Step 1
// Step 3
let module = this;

// Step 2
// Step 4
for (let i = 0; i < resolveSet.length; i++) {
let r = resolveSet[i];
if (r.module === module && r.exportName === exportName) {
Expand All @@ -116,39 +118,42 @@ function ModuleResolveExport(exportName, resolveSet = new_List())
}
}

// Step 3
// Step 5
_DefineDataProperty(resolveSet, resolveSet.length, {module, exportName});

// Step 4
// Step 6
let localExportEntries = module.localExportEntries;
for (let i = 0; i < localExportEntries.length; i++) {
let e = localExportEntries[i];
if (exportName === e.exportName)
return {module, bindingName: e.localName};
}

// Step 5
// Step 7
let indirectExportEntries = module.indirectExportEntries;
for (let i = 0; i < indirectExportEntries.length; i++) {
let e = indirectExportEntries[i];
if (exportName === e.exportName) {
let importedModule = CallModuleResolveHook(module, e.moduleRequest,
MODULE_STATUS_UNLINKED);

// TODO: Step 7.a.ii

return callFunction(importedModule.resolveExport, importedModule, e.importName,
resolveSet);
}
}

// Step 6
// Step 8
if (exportName === "default") {
// A default export cannot be provided by an export *.
return null;
}

// Step 7
// Step 9
let starResolution = null;

// Step 8
// Step 10
let starExportEntries = module.starExportEntries;
for (let i = 0; i < starExportEntries.length; i++) {
let e = starExportEntries[i];
Expand All @@ -171,7 +176,7 @@ function ModuleResolveExport(exportName, resolveSet = new_List())
}
}

// Step 9
// Step 11
return starResolution;
}

Expand All @@ -182,7 +187,8 @@ function IsResolvedBinding(resolution)
return typeof resolution === "object" && resolution !== null;
}

// 15.2.1.18 GetModuleNamespace(module)
// https://tc39.es/ecma262/#sec-getmodulenamespace
// ES2020 15.2.1.21 GetModuleNamespace
function GetModuleNamespace(module)
{
// Step 1
Expand Down Expand Up @@ -212,19 +218,21 @@ function GetModuleNamespace(module)
return namespace;
}

// 9.4.6.13 ModuleNamespaceCreate(module, exports)
// https://tc39.es/ecma262/#sec-modulenamespacecreate
// ES2020 9.4.6.11 ModuleNamespaceCreate
function ModuleNamespaceCreate(module, exports)
{
callFunction(ArraySort, exports);

let ns = NewModuleNamespace(module, exports);

// Pre-compute all bindings now rather than calling ResolveExport() on every
// access.
// Pre-compute all binding mappings now instead of on each access.
// See: ES2020 9.4.6.7 Module Namespace Exotic Object [[Get]]
for (let i = 0; i < exports.length; i++) {
let name = exports[i];
let binding = callFunction(module.resolveExport, module, name);
assert(IsResolvedBinding(binding), "Failed to resolve binding");
// TODO: ES2020 9.4.6.7 Module Namespace Exotic Object [[Get]], Step 10.
AddModuleNamespaceBinding(ns, name, binding.module, binding.bindingName);
}

Expand Down Expand Up @@ -331,9 +339,8 @@ function ModuleInstantiate()
}
_SetCanonicalName(ModuleInstantiate, "ModuleInstantiate");

// rev b012019fea18f29737a67c36911340a3e25bfc63
// https://tc39.es/ecma262/#sec-InnerModuleLinking
// 15.2.1.16.1.1 InnerModuleLinking ( module, stack, index )
// ES2020 15.2.1.16.1.1 InnerModuleLinking
function InnerModuleLinking(module, stack, index)
{
// Step 1
Expand All @@ -342,7 +349,7 @@ function InnerModuleLinking(module, stack, index)
// a. Perform ? module.Link().
// b. Return index.

// Step 2.a
// Step 2
if (module.status === MODULE_STATUS_LINKING ||
module.status === MODULE_STATUS_LINKED ||
module.status === MODULE_STATUS_EVALUATED ||
Expand All @@ -368,13 +375,14 @@ function InnerModuleLinking(module, stack, index)
// Step 8. Append module to stack.
_DefineDataProperty(stack, stack.length, module);

// Step 9. For each String required that is an element of module.[[RequestedModules]], do
// Step 9. For each String required that is an element of module.[[RequestedModules]], do
let requestedModules = module.requestedModules;
for (let i = 0; i < requestedModules.length; i++) {
// Step 9.a-9.b
// Step 9.a
let required = requestedModules[i].moduleSpecifier;
let requiredModule = CallModuleResolveHook(module, required, MODULE_STATUS_UNLINKED);

// Step 9.b
index = InnerModuleLinking(requiredModule, stack, index);

// TODO: Check if requiredModule is a Cyclic Module Record
Expand Down Expand Up @@ -427,9 +435,8 @@ function InnerModuleLinking(module, stack, index)
return index;
}

// rev b012019fea18f29737a67c36911340a3e25bfc63
// https://tc39.es/ecma262/#sec-source-text-module-record-initialize-environment
// 15.2.1.17.4 InitializeEnvironment ( ) Concrete Method
// ES2020 15.2.1.17.4 InitializeEnvironment
function InitializeEnvironment()
{
// Step 1
Expand All @@ -449,17 +456,17 @@ function InitializeEnvironment()
// Omitting steps 4-5, for practical purposes it is impossible for a realm to be
// undefined at this point.

// Step 6-7
// Step 6-8
// Note that we have already created the environment by this point.
let env = GetModuleEnvironment(module);

// Step 8
// Step 9
let importEntries = module.importEntries;
for (let i = 0; i < importEntries.length; i++) {
let imp = importEntries[i];
let importedModule = CallModuleResolveHook(module, imp.moduleRequest,
MODULE_STATUS_LINKING);
// Step 8.c-8.d
// Step 9.c-9.d
if (imp.importName === "*") {
let namespace = GetModuleNamespace(importedModule);
CreateNamespaceBinding(env, imp.localName, namespace);
Expand All @@ -471,17 +478,19 @@ function InitializeEnvironment()
imp.lineNumber, imp.columnNumber);
}

// TODO: Step 9.d.iii

CreateImportBinding(env, imp.localName, resolution.module, resolution.bindingName);
}
}

// Steps 9-15
// Some of these do not need to happen for practical purposes. For steps 12-14, the bindings
// Steps 10-26
// Some of these do not need to happen for practical purposes. For steps 21-23, the bindings
// that can be handled in a similar way to regulars scripts are done separately. Function
// Declarations are special due to hoisting and are handled within this function.
// See ModuleScope and ModuleEnvironmentObject for further details.

// Step 14.a.iii is handled here.
// Step 24.a.iii is handled here.
// In order to have the functions correctly hoisted we need to do this separately.
InstantiateModuleFunctionDeclarations(module);
}
Expand Down Expand Up @@ -538,27 +547,28 @@ function RecordModuleEvaluationError(module, error)
UnsafeSetReservedSlot(module, MODULE_OBJECT_EVALUATION_ERROR_SLOT, error);
}

// 15.2.1.16.5 ModuleEvaluate()
// https://tc39.es/ecma262/#sec-moduleevaluation
// ES2020 15.2.1.16.2 ModuleEvaluate
function ModuleEvaluate()
{
if (!IsObject(this) || !IsModule(this))
return callFunction(CallModuleMethodIfWrapped, this, "ModuleEvaluate");

// Step 1
// Step 2
let module = this;

// Step 2
// Step 3
if (module.status !== MODULE_STATUS_LINKED &&
module.status !== MODULE_STATUS_EVALUATED &&
module.status !== MODULE_STATUS_EVALUATED_ERROR)
{
ThrowInternalError(JSMSG_BAD_MODULE_STATUS);
}

// Step 3
// Step 4
let stack = new_List();

// Steps 4-5
// Steps 5-6
try {
InnerModuleEvaluation(module, stack, 0);
} catch (error) {
Expand All @@ -579,20 +589,23 @@ function ModuleEvaluate()
throw error;
}

// Steps 7-8
assert(module.status === MODULE_STATUS_EVALUATED,
"Bad module status after successful evaluation");
assert(stack.length === 0,
"Stack should be empty after successful evaluation");

// Step 9
return undefined;
}
_SetCanonicalName(ModuleEvaluate, "ModuleEvaluate");

// 15.2.1.16.5.1 InnerModuleEvaluation(module, stack, index)
// https://tc39.es/ecma262/#sec-innermoduleevaluation
// ES2020 15.2.1.16.2.1 InnerModuleEvaluation
function InnerModuleEvaluation(module, stack, index)
{
// Step 1
// TODO: Support module records other than source text module records.
// TODO: Support module records other than Cyclic Module Records.

// Step 2
if (module.status === MODULE_STATUS_EVALUATED_ERROR)
Expand Down

0 comments on commit e67cc9e

Please sign in to comment.