зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1284486 - Disallow returying ModuleDeclarationInstantiation after error r=shu
This commit is contained in:
Родитель
21644b0588
Коммит
9800e39e70
|
@ -183,6 +183,30 @@ function ModuleNamespaceCreate(module, exports)
|
|||
return ns;
|
||||
}
|
||||
|
||||
function GetModuleEnvironment(module)
|
||||
{
|
||||
assert(IsModule(module), "Non-module passed to GetModuleEnvironment");
|
||||
|
||||
let env = UnsafeGetReservedSlot(module, MODULE_OBJECT_ENVIRONMENT_SLOT);
|
||||
assert(env === undefined || env === null || IsModuleEnvironment(env),
|
||||
"Module environment slot contains unexpected value");
|
||||
|
||||
// Check for a previous failed attempt to instantiate this module. This can
|
||||
// only happen due to a bug in the module loader.
|
||||
if (env === null)
|
||||
ThrowInternalError(JSMSG_MODULE_INSTANTIATE_FAILED);
|
||||
|
||||
return env;
|
||||
}
|
||||
|
||||
function RecordInstantationFailure(module)
|
||||
{
|
||||
// Set the module's environment slot to 'null' to indicate a failed module
|
||||
// instantiation.
|
||||
assert(IsModule(module), "Non-module passed to RecordInstantationFailure");
|
||||
UnsafeSetReservedSlot(module, MODULE_OBJECT_ENVIRONMENT_SLOT, null);
|
||||
}
|
||||
|
||||
// 15.2.1.16.4 ModuleDeclarationInstantiation()
|
||||
function ModuleDeclarationInstantiation()
|
||||
{
|
||||
|
@ -200,46 +224,51 @@ function ModuleDeclarationInstantiation()
|
|||
CreateModuleEnvironment(module);
|
||||
let env = GetModuleEnvironment(module);
|
||||
|
||||
// Step 8
|
||||
let requestedModules = module.requestedModules;
|
||||
for (let i = 0; i < requestedModules.length; i++) {
|
||||
let required = requestedModules[i];
|
||||
let requiredModule = HostResolveImportedModule(module, required);
|
||||
callFunction(requiredModule.declarationInstantiation, requiredModule);
|
||||
}
|
||||
|
||||
// Step 9
|
||||
let indirectExportEntries = module.indirectExportEntries;
|
||||
for (let i = 0; i < indirectExportEntries.length; i++) {
|
||||
let e = indirectExportEntries[i];
|
||||
let resolution = callFunction(module.resolveExport, module, e.exportName);
|
||||
if (resolution === null)
|
||||
ThrowSyntaxError(JSMSG_MISSING_INDIRECT_EXPORT, e.exportName);
|
||||
if (resolution === "ambiguous")
|
||||
ThrowSyntaxError(JSMSG_AMBIGUOUS_INDIRECT_EXPORT, e.exportName);
|
||||
}
|
||||
|
||||
// Step 12
|
||||
let importEntries = module.importEntries;
|
||||
for (let i = 0; i < importEntries.length; i++) {
|
||||
let imp = importEntries[i];
|
||||
let importedModule = HostResolveImportedModule(module, imp.moduleRequest);
|
||||
if (imp.importName === "*") {
|
||||
let namespace = GetModuleNamespace(importedModule);
|
||||
CreateNamespaceBinding(env, imp.localName, namespace);
|
||||
} else {
|
||||
let resolution = callFunction(importedModule.resolveExport, importedModule,
|
||||
imp.importName);
|
||||
if (resolution === null)
|
||||
ThrowSyntaxError(JSMSG_MISSING_IMPORT, imp.importName);
|
||||
if (resolution === "ambiguous")
|
||||
ThrowSyntaxError(JSMSG_AMBIGUOUS_IMPORT, imp.importName);
|
||||
CreateImportBinding(env, imp.localName, resolution.module, resolution.bindingName);
|
||||
try {
|
||||
// Step 8
|
||||
let requestedModules = module.requestedModules;
|
||||
for (let i = 0; i < requestedModules.length; i++) {
|
||||
let required = requestedModules[i];
|
||||
let requiredModule = HostResolveImportedModule(module, required);
|
||||
callFunction(requiredModule.declarationInstantiation, requiredModule);
|
||||
}
|
||||
}
|
||||
|
||||
// Step 16.iv
|
||||
InstantiateModuleFunctionDeclarations(module);
|
||||
// Step 9
|
||||
let indirectExportEntries = module.indirectExportEntries;
|
||||
for (let i = 0; i < indirectExportEntries.length; i++) {
|
||||
let e = indirectExportEntries[i];
|
||||
let resolution = callFunction(module.resolveExport, module, e.exportName);
|
||||
if (resolution === null)
|
||||
ThrowSyntaxError(JSMSG_MISSING_INDIRECT_EXPORT, e.exportName);
|
||||
if (resolution === "ambiguous")
|
||||
ThrowSyntaxError(JSMSG_AMBIGUOUS_INDIRECT_EXPORT, e.exportName);
|
||||
}
|
||||
|
||||
// Step 12
|
||||
let importEntries = module.importEntries;
|
||||
for (let i = 0; i < importEntries.length; i++) {
|
||||
let imp = importEntries[i];
|
||||
let importedModule = HostResolveImportedModule(module, imp.moduleRequest);
|
||||
if (imp.importName === "*") {
|
||||
let namespace = GetModuleNamespace(importedModule);
|
||||
CreateNamespaceBinding(env, imp.localName, namespace);
|
||||
} else {
|
||||
let resolution = callFunction(importedModule.resolveExport, importedModule,
|
||||
imp.importName);
|
||||
if (resolution === null)
|
||||
ThrowSyntaxError(JSMSG_MISSING_IMPORT, imp.importName);
|
||||
if (resolution === "ambiguous")
|
||||
ThrowSyntaxError(JSMSG_AMBIGUOUS_IMPORT, imp.importName);
|
||||
CreateImportBinding(env, imp.localName, resolution.module, resolution.bindingName);
|
||||
}
|
||||
}
|
||||
|
||||
// Step 16.iv
|
||||
InstantiateModuleFunctionDeclarations(module);
|
||||
} catch (e) {
|
||||
RecordInstantationFailure(module);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
_SetCanonicalName(ModuleDeclarationInstantiation, "ModuleDeclarationInstantiation");
|
||||
|
||||
|
|
|
@ -629,6 +629,8 @@ ModuleEnvironmentObject*
|
|||
ModuleObject::environment() const
|
||||
{
|
||||
Value value = getReservedSlot(EnvironmentSlot);
|
||||
MOZ_ASSERT(!value.isNull());
|
||||
|
||||
if (value.isUndefined())
|
||||
return nullptr;
|
||||
|
||||
|
|
|
@ -10,11 +10,10 @@
|
|||
#include "jsapi.h"
|
||||
#include "jsatom.h"
|
||||
|
||||
#include "builtin/SelfHostingDefines.h"
|
||||
#include "gc/Zone.h"
|
||||
|
||||
#include "js/GCVector.h"
|
||||
#include "js/Id.h"
|
||||
|
||||
#include "vm/NativeObject.h"
|
||||
#include "vm/ProxyObject.h"
|
||||
|
||||
|
@ -224,6 +223,9 @@ class ModuleObject : public NativeObject
|
|||
SlotCount
|
||||
};
|
||||
|
||||
static_assert(EnvironmentSlot == MODULE_OBJECT_ENVIRONMENT_SLOT,
|
||||
"EnvironmentSlot must match self-hosting define");
|
||||
|
||||
static const Class class_;
|
||||
|
||||
static bool isInstance(HandleValue value);
|
||||
|
|
|
@ -99,4 +99,6 @@
|
|||
#define REGEXP_STICKY_FLAG 0x08
|
||||
#define REGEXP_UNICODE_FLAG 0x10
|
||||
|
||||
#define MODULE_OBJECT_ENVIRONMENT_SLOT 3
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
// |jit-test| error: InternalError
|
||||
|
||||
// This tests that attempting to perform ModuleDeclarationInstantation a second
|
||||
// time after a failure throws an error. Doing this would be a bug in the module
|
||||
// loader, which is expected to throw away modules if there is an error
|
||||
// instantiating them.
|
||||
//
|
||||
// The first attempt fails becuase module 'a' is not available. The second
|
||||
// attempt fails because of the previous failure (it would otherwise succeed as
|
||||
// 'a' is now available).
|
||||
|
||||
let moduleRepo = {};
|
||||
setModuleResolveHook(function(module, specifier) {
|
||||
return moduleRepo[specifier];
|
||||
});
|
||||
try {
|
||||
let b = moduleRepo['b'] = parseModule("export var b = 3; export var c = 4;");
|
||||
let c = moduleRepo['c'] = parseModule("export * from 'a'; export * from 'b';");
|
||||
c.declarationInstantiation();
|
||||
} catch (exc) {}
|
||||
let a = moduleRepo['a'] = parseModule("export var a = 1; export var b = 2;");
|
||||
let d = moduleRepo['d'] = parseModule("import { a } from 'c'; a;");
|
||||
d.declarationInstantiation();
|
|
@ -536,6 +536,7 @@ MSG_DEF(JSMSG_MISSING_IMPORT, 1, JSEXN_SYNTAXERR, "import '{0}' not f
|
|||
MSG_DEF(JSMSG_AMBIGUOUS_IMPORT, 1, JSEXN_SYNTAXERR, "ambiguous import '{0}'")
|
||||
MSG_DEF(JSMSG_MISSING_NAMESPACE_EXPORT, 0, JSEXN_SYNTAXERR, "export not found for namespace")
|
||||
MSG_DEF(JSMSG_MISSING_EXPORT, 1, JSEXN_SYNTAXERR, "local binding for export '{0}' not found")
|
||||
MSG_DEF(JSMSG_MODULE_INSTANTIATE_FAILED, 0, JSEXN_INTERNALERR, "attempt to re-instantiate module after failure")
|
||||
|
||||
// Promise
|
||||
MSG_DEF(JSMSG_CANNOT_RESOLVE_PROMISE_WITH_ITSELF, 0, JSEXN_TYPEERR, "A promise cannot be resolved with itself.")
|
||||
|
|
|
@ -369,6 +369,16 @@ intrinsic_ThrowSyntaxError(JSContext* cx, unsigned argc, Value* vp)
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
intrinsic_ThrowInternalError(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
MOZ_ASSERT(args.length() >= 1);
|
||||
|
||||
ThrowErrorWithType(cx, JSEXN_INTERNALERR, args);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles an assertion failure in self-hosted code just like an assertion
|
||||
* failure in C++ code. Information about the failure can be provided in args[0].
|
||||
|
@ -2115,23 +2125,6 @@ intrinsic_HostResolveImportedModule(JSContext* cx, unsigned argc, Value* vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
intrinsic_GetModuleEnvironment(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
MOZ_ASSERT(args.length() == 1);
|
||||
RootedModuleObject module(cx, &args[0].toObject().as<ModuleObject>());
|
||||
RootedModuleEnvironmentObject env(cx, module->environment());
|
||||
args.rval().setUndefined();
|
||||
if (!env) {
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
args.rval().setObject(*env);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
intrinsic_CreateModuleEnvironment(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
|
@ -2381,6 +2374,7 @@ static const JSFunctionSpec intrinsic_functions[] = {
|
|||
JS_FN("ThrowRangeError", intrinsic_ThrowRangeError, 4,0),
|
||||
JS_FN("ThrowTypeError", intrinsic_ThrowTypeError, 4,0),
|
||||
JS_FN("ThrowSyntaxError", intrinsic_ThrowSyntaxError, 4,0),
|
||||
JS_FN("ThrowInternalError", intrinsic_ThrowInternalError, 4,0),
|
||||
JS_FN("AssertionFailed", intrinsic_AssertionFailed, 1,0),
|
||||
JS_FN("DumpMessage", intrinsic_DumpMessage, 1,0),
|
||||
JS_FN("OwnPropertyKeys", intrinsic_OwnPropertyKeys, 1,0),
|
||||
|
@ -2628,7 +2622,7 @@ static const JSFunctionSpec intrinsic_functions[] = {
|
|||
JS_FN("CallModuleMethodIfWrapped",
|
||||
CallNonGenericSelfhostedMethod<Is<ModuleObject>>, 2, 0),
|
||||
JS_FN("HostResolveImportedModule", intrinsic_HostResolveImportedModule, 2, 0),
|
||||
JS_FN("GetModuleEnvironment", intrinsic_GetModuleEnvironment, 1, 0),
|
||||
JS_FN("IsModuleEnvironment", intrinsic_IsInstanceOfBuiltin<ModuleEnvironmentObject>, 1, 0),
|
||||
JS_FN("CreateModuleEnvironment", intrinsic_CreateModuleEnvironment, 1, 0),
|
||||
JS_FN("CreateImportBinding", intrinsic_CreateImportBinding, 4, 0),
|
||||
JS_FN("CreateNamespaceBinding", intrinsic_CreateNamespaceBinding, 3, 0),
|
||||
|
|
Загрузка…
Ссылка в новой задаче