From 6a3fcd298c6f25e00e5adc81c8478e79e0c00a4c Mon Sep 17 00:00:00 2001 From: Ted Campbell Date: Wed, 15 Jul 2020 17:33:53 +0000 Subject: [PATCH] Bug 1496852 - Update spec references in Module.js r=jorendorff 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 --- js/src/builtin/Module.js | 97 +++++++++++++++++++++++----------------- 1 file changed, 55 insertions(+), 42 deletions(-) diff --git a/js/src/builtin/Module.js b/js/src/builtin/Module.js index 1ab93c60ec82..eac752346483 100644 --- a/js/src/builtin/Module.js +++ b/js/src/builtin/Module.js @@ -12,7 +12,8 @@ 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)) { @@ -20,35 +21,35 @@ function ModuleGetExportedNames(exportStarSet = new_List()) "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]; @@ -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. @@ -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) { @@ -116,10 +118,10 @@ 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]; @@ -127,28 +129,31 @@ function ModuleResolveExport(exportName, resolveSet = new_List()) 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]; @@ -171,7 +176,7 @@ function ModuleResolveExport(exportName, resolveSet = new_List()) } } - // Step 9 + // Step 11 return starResolution; } @@ -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 @@ -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); } @@ -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 @@ -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 || @@ -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 @@ -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 @@ -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); @@ -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); } @@ -538,16 +547,17 @@ 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) @@ -555,10 +565,10 @@ function ModuleEvaluate() 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) { @@ -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)