[modules] Implement the new semantics of instantiation and evaluation.
This implements the changes proposed at https://github.com/tc39/ecma262/pull/916. The API will be extended in a follow-up CL. R=adamk@chromium.org Bug: v8:1569 Cq-Include-Trybots: master.tryserver.chromium.linux:linux_chromium_rel_ng Change-Id: I79476b5b674c924fea390dff1b9bee7f86a111c6 Reviewed-on: https://chromium-review.googlesource.com/544970 Reviewed-by: Adam Klein <adamk@chromium.org> Commit-Queue: Georg Neis <neis@chromium.org> Cr-Commit-Position: refs/heads/master@{#46289}
This commit is contained in:
parent
e027a3ee23
commit
d02cb6f0ff
@ -2181,7 +2181,7 @@ MaybeLocal<Value> Module::Evaluate(Local<Context> context) {
|
||||
|
||||
i::Handle<i::Module> self = Utils::OpenHandle(this);
|
||||
// It's an API error to call Evaluate before Instantiate.
|
||||
CHECK(self->instantiated());
|
||||
CHECK_GE(self->status(), i::Module::kInstantiated);
|
||||
|
||||
Local<Value> result;
|
||||
has_pending_exception = !ToLocal(i::Module::Evaluate(self), &result);
|
||||
|
@ -2019,9 +2019,10 @@ Handle<Module> Factory::NewModule(Handle<SharedFunctionInfo> code) {
|
||||
module->set_module_namespace(isolate()->heap()->undefined_value());
|
||||
module->set_requested_modules(*requested_modules);
|
||||
module->set_script(Script::cast(code->script()));
|
||||
module->set_status(Module::kUnprepared);
|
||||
DCHECK(!module->instantiated());
|
||||
DCHECK(!module->evaluated());
|
||||
module->set_status(Module::kUninstantiated);
|
||||
module->set_exception(isolate()->heap()->the_hole_value());
|
||||
module->set_dfs_index(-1);
|
||||
module->set_dfs_ancestor_index(-1);
|
||||
return module;
|
||||
}
|
||||
|
||||
|
@ -1250,27 +1250,26 @@ void Module::ModuleVerify() {
|
||||
VerifyPointer(module_namespace());
|
||||
VerifyPointer(requested_modules());
|
||||
VerifyPointer(script());
|
||||
VerifyPointer(exception());
|
||||
VerifySmiField(kHashOffset);
|
||||
VerifySmiField(kStatusOffset);
|
||||
|
||||
CHECK((!instantiated() && code()->IsSharedFunctionInfo()) ||
|
||||
(instantiated() && !evaluated() && code()->IsJSFunction()) ||
|
||||
(instantiated() && evaluated() && code()->IsModuleInfo()));
|
||||
CHECK((status() < kInstantiating && code()->IsSharedFunctionInfo()) ||
|
||||
(status() < kEvaluating && code()->IsJSFunction()) ||
|
||||
code()->IsModuleInfo());
|
||||
|
||||
CHECK_EQ(status() == kErrored, !exception()->IsTheHole(GetIsolate()));
|
||||
|
||||
CHECK(module_namespace()->IsUndefined(GetIsolate()) ||
|
||||
module_namespace()->IsJSModuleNamespace());
|
||||
if (module_namespace()->IsJSModuleNamespace()) {
|
||||
CHECK(instantiated());
|
||||
CHECK_LE(kInstantiating, status());
|
||||
CHECK_EQ(JSModuleNamespace::cast(module_namespace())->module(), this);
|
||||
}
|
||||
|
||||
CHECK_EQ(requested_modules()->length(), info()->module_requests()->length());
|
||||
|
||||
CHECK_NE(hash(), 0);
|
||||
|
||||
CHECK_LE(kUnprepared, status());
|
||||
CHECK_LE(status(), kPrepared);
|
||||
CHECK_IMPLIES(instantiated(), status() == kPrepared);
|
||||
}
|
||||
|
||||
void PrototypeInfo::PrototypeInfoVerify() {
|
||||
|
@ -4621,23 +4621,17 @@ ACCESSORS(Module, regular_imports, FixedArray, kRegularImportsOffset)
|
||||
ACCESSORS(Module, module_namespace, HeapObject, kModuleNamespaceOffset)
|
||||
ACCESSORS(Module, requested_modules, FixedArray, kRequestedModulesOffset)
|
||||
ACCESSORS(Module, script, Script, kScriptOffset)
|
||||
ACCESSORS(Module, exception, Object, kExceptionOffset)
|
||||
SMI_ACCESSORS(Module, status, kStatusOffset)
|
||||
SMI_ACCESSORS(Module, dfs_index, kDfsIndexOffset)
|
||||
SMI_ACCESSORS(Module, dfs_ancestor_index, kDfsAncestorIndexOffset)
|
||||
SMI_ACCESSORS(Module, hash, kHashOffset)
|
||||
|
||||
bool Module::evaluated() const { return code()->IsModuleInfo(); }
|
||||
|
||||
void Module::set_evaluated() {
|
||||
DCHECK(instantiated());
|
||||
DCHECK(!evaluated());
|
||||
return set_code(
|
||||
JSFunction::cast(code())->shared()->scope_info()->ModuleDescriptorInfo());
|
||||
}
|
||||
|
||||
bool Module::instantiated() const { return !code()->IsSharedFunctionInfo(); }
|
||||
|
||||
ModuleInfo* Module::info() const {
|
||||
if (evaluated()) return ModuleInfo::cast(code());
|
||||
ScopeInfo* scope_info = instantiated()
|
||||
if (status() >= kEvaluating) {
|
||||
return ModuleInfo::cast(code());
|
||||
}
|
||||
ScopeInfo* scope_info = status() >= kInstantiating
|
||||
? JSFunction::cast(code())->shared()->scope_info()
|
||||
: SharedFunctionInfo::cast(code())->scope_info();
|
||||
return scope_info->ModuleDescriptorInfo();
|
||||
|
@ -1299,7 +1299,7 @@ void ModuleInfoEntry::ModuleInfoEntryPrint(std::ostream& os) { // NOLINT
|
||||
void Module::ModulePrint(std::ostream& os) { // NOLINT
|
||||
HeapObject::PrintHeader(os, "Module");
|
||||
// TODO(neis): Simplify once modules have a script field.
|
||||
if (!evaluated()) {
|
||||
if (status() < kEvaluating) {
|
||||
SharedFunctionInfo* shared = code()->IsSharedFunctionInfo()
|
||||
? SharedFunctionInfo::cast(code())
|
||||
: JSFunction::cast(code())->shared();
|
||||
@ -1310,8 +1310,8 @@ void Module::ModulePrint(std::ostream& os) { // NOLINT
|
||||
os << "\n - exports: " << Brief(exports());
|
||||
os << "\n - requested_modules: " << Brief(requested_modules());
|
||||
os << "\n - script: " << Brief(script());
|
||||
os << "\n - instantiated, evaluated: " << instantiated() << ", "
|
||||
<< evaluated();
|
||||
os << "\n - status: " << status();
|
||||
os << "\n - exception: " << Brief(exception());
|
||||
os << "\n";
|
||||
}
|
||||
|
||||
|
241
src/objects.cc
241
src/objects.cc
@ -19512,6 +19512,48 @@ void Module::StoreVariable(Handle<Module> module, int cell_index,
|
||||
module->GetCell(cell_index)->set_value(*value);
|
||||
}
|
||||
|
||||
void Module::SetStatus(Status new_status) {
|
||||
DisallowHeapAllocation no_alloc;
|
||||
DCHECK_LE(status(), new_status);
|
||||
DCHECK_NE(new_status, Module::kErrored);
|
||||
set_status(new_status);
|
||||
}
|
||||
|
||||
void Module::RecordError() {
|
||||
DisallowHeapAllocation no_alloc;
|
||||
|
||||
Isolate* isolate = GetIsolate();
|
||||
Object* the_exception = isolate->pending_exception();
|
||||
DCHECK(!the_exception->IsTheHole(isolate));
|
||||
|
||||
switch (status()) {
|
||||
case Module::kUninstantiated:
|
||||
case Module::kPreInstantiating:
|
||||
case Module::kInstantiating:
|
||||
case Module::kEvaluating:
|
||||
break;
|
||||
case Module::kErrored:
|
||||
DCHECK_EQ(exception(), the_exception);
|
||||
return;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
set_code(info());
|
||||
|
||||
DCHECK(exception()->IsTheHole(isolate));
|
||||
set_status(Module::kErrored);
|
||||
set_exception(the_exception);
|
||||
}
|
||||
|
||||
Object* Module::GetException() {
|
||||
DisallowHeapAllocation no_alloc;
|
||||
DCHECK_EQ(status(), Module::kErrored);
|
||||
Object* the_exception = exception();
|
||||
DCHECK(!the_exception->IsTheHole(GetIsolate()));
|
||||
return the_exception;
|
||||
}
|
||||
|
||||
MaybeHandle<Cell> Module::ResolveImport(Handle<Module> module,
|
||||
Handle<String> name, int module_request,
|
||||
MessageLocation loc, bool must_resolve,
|
||||
@ -19519,15 +19561,23 @@ MaybeHandle<Cell> Module::ResolveImport(Handle<Module> module,
|
||||
Isolate* isolate = module->GetIsolate();
|
||||
Handle<Module> requested_module(
|
||||
Module::cast(module->requested_modules()->get(module_request)), isolate);
|
||||
return Module::ResolveExport(requested_module, name, loc, must_resolve,
|
||||
resolve_set);
|
||||
MaybeHandle<Cell> result = Module::ResolveExport(requested_module, name, loc,
|
||||
must_resolve, resolve_set);
|
||||
if (isolate->has_pending_exception()) {
|
||||
DCHECK(result.is_null());
|
||||
module->RecordError();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
MaybeHandle<Cell> Module::ResolveExport(Handle<Module> module,
|
||||
Handle<String> name,
|
||||
MessageLocation loc, bool must_resolve,
|
||||
Module::ResolveSet* resolve_set) {
|
||||
DCHECK_EQ(module->status(), kPrepared);
|
||||
DCHECK_NE(module->status(), kErrored);
|
||||
DCHECK_NE(module->status(), kEvaluating);
|
||||
DCHECK_GE(module->status(), kPreInstantiating);
|
||||
|
||||
Isolate* isolate = module->GetIsolate();
|
||||
Handle<Object> object(module->exports()->Lookup(name), isolate);
|
||||
if (object->IsCell()) {
|
||||
@ -19649,14 +19699,39 @@ MaybeHandle<Cell> Module::ResolveExportUsingStarExports(
|
||||
|
||||
bool Module::Instantiate(Handle<Module> module, v8::Local<v8::Context> context,
|
||||
v8::Module::ResolveCallback callback) {
|
||||
return PrepareInstantiate(module, context, callback) &&
|
||||
FinishInstantiate(module, context);
|
||||
Isolate* isolate = module->GetIsolate();
|
||||
if (module->status() == kErrored) {
|
||||
isolate->Throw(module->GetException());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!PrepareInstantiate(module, context, callback)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Zone zone(isolate->allocator(), ZONE_NAME);
|
||||
ZoneForwardList<Handle<Module>> stack(&zone);
|
||||
unsigned dfs_index = 0;
|
||||
if (!FinishInstantiate(module, &stack, &dfs_index)) {
|
||||
for (auto& descendant : stack) {
|
||||
descendant->RecordError();
|
||||
}
|
||||
DCHECK_EQ(module->GetException(), isolate->pending_exception());
|
||||
return false;
|
||||
}
|
||||
DCHECK(module->status() == kInstantiated || module->status() == kEvaluated);
|
||||
DCHECK(stack.empty());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Module::PrepareInstantiate(Handle<Module> module,
|
||||
v8::Local<v8::Context> context,
|
||||
v8::Module::ResolveCallback callback) {
|
||||
if (module->status() == kPrepared) return true;
|
||||
DCHECK_NE(module->status(), kErrored);
|
||||
DCHECK_NE(module->status(), kEvaluating);
|
||||
DCHECK_NE(module->status(), kInstantiating);
|
||||
if (module->status() >= kPreInstantiating) return true;
|
||||
module->SetStatus(kPreInstantiating);
|
||||
|
||||
// Obtain requested modules.
|
||||
Isolate* isolate = module->GetIsolate();
|
||||
@ -19670,18 +19745,29 @@ bool Module::PrepareInstantiate(Handle<Module> module,
|
||||
v8::Utils::ToLocal(module))
|
||||
.ToLocal(&api_requested_module)) {
|
||||
isolate->PromoteScheduledException();
|
||||
module->RecordError();
|
||||
return false;
|
||||
}
|
||||
Handle<Module> requested_module = Utils::OpenHandle(*api_requested_module);
|
||||
if (requested_module->status() == kErrored) {
|
||||
// TODO(neis): Move this into callback?
|
||||
isolate->Throw(requested_module->GetException());
|
||||
module->RecordError();
|
||||
DCHECK_EQ(module->GetException(), requested_module->GetException());
|
||||
return false;
|
||||
}
|
||||
requested_modules->set(i, *requested_module);
|
||||
}
|
||||
|
||||
// Recurse.
|
||||
module->set_status(kPrepared);
|
||||
for (int i = 0, length = requested_modules->length(); i < length; ++i) {
|
||||
Handle<Module> requested_module(Module::cast(requested_modules->get(i)),
|
||||
isolate);
|
||||
if (!PrepareInstantiate(requested_module, context, callback)) return false;
|
||||
if (!PrepareInstantiate(requested_module, context, callback)) {
|
||||
module->RecordError();
|
||||
DCHECK_EQ(module->GetException(), requested_module->GetException());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Set up local exports.
|
||||
@ -19707,34 +19793,79 @@ bool Module::PrepareInstantiate(Handle<Module> module,
|
||||
CreateIndirectExport(module, Handle<String>::cast(export_name), entry);
|
||||
}
|
||||
|
||||
DCHECK_EQ(module->status(), kPrepared);
|
||||
DCHECK(!module->instantiated());
|
||||
DCHECK_EQ(module->status(), kPreInstantiating);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Module::FinishInstantiate(Handle<Module> module,
|
||||
v8::Local<v8::Context> context) {
|
||||
DCHECK_EQ(module->status(), kPrepared);
|
||||
if (module->instantiated()) return true;
|
||||
void Module::MaybeTransitionComponent(Handle<Module> module,
|
||||
ZoneForwardList<Handle<Module>>* stack,
|
||||
Status new_status) {
|
||||
DCHECK(new_status == kInstantiated || new_status == kEvaluated);
|
||||
SLOW_DCHECK(
|
||||
// {module} is on the {stack}.
|
||||
std::count_if(stack->begin(), stack->end(),
|
||||
[&](Handle<Module> m) { return *m == *module; }) == 1);
|
||||
DCHECK_LE(module->dfs_ancestor_index(), module->dfs_index());
|
||||
if (module->dfs_ancestor_index() == module->dfs_index()) {
|
||||
// This is the root of its strongly connected component.
|
||||
Handle<Module> ancestor;
|
||||
do {
|
||||
ancestor = stack->front();
|
||||
stack->pop_front();
|
||||
DCHECK_EQ(ancestor->status(),
|
||||
new_status == kInstantiated ? kInstantiating : kEvaluating);
|
||||
ancestor->SetStatus(new_status);
|
||||
} while (*ancestor != *module);
|
||||
}
|
||||
}
|
||||
|
||||
// Instantiate SharedFunctionInfo and mark module as instantiated for
|
||||
bool Module::FinishInstantiate(Handle<Module> module,
|
||||
ZoneForwardList<Handle<Module>>* stack,
|
||||
unsigned* dfs_index) {
|
||||
DCHECK_NE(module->status(), kErrored);
|
||||
DCHECK_NE(module->status(), kEvaluating);
|
||||
if (module->status() >= kInstantiating) return true;
|
||||
DCHECK_EQ(module->status(), kPreInstantiating);
|
||||
|
||||
// Instantiate SharedFunctionInfo and mark module as instantiating for
|
||||
// the recursion.
|
||||
Isolate* isolate = module->GetIsolate();
|
||||
Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(module->code()),
|
||||
isolate);
|
||||
Handle<JSFunction> function =
|
||||
isolate->factory()->NewFunctionFromSharedFunctionInfo(
|
||||
shared,
|
||||
handle(Utils::OpenHandle(*context)->native_context(), isolate));
|
||||
shared, isolate->native_context());
|
||||
module->set_code(*function);
|
||||
DCHECK(module->instantiated());
|
||||
module->SetStatus(kInstantiating);
|
||||
module->set_dfs_index(*dfs_index);
|
||||
module->set_dfs_ancestor_index(*dfs_index);
|
||||
stack->push_front(module);
|
||||
(*dfs_index)++;
|
||||
|
||||
// Recurse.
|
||||
Handle<FixedArray> requested_modules(module->requested_modules(), isolate);
|
||||
for (int i = 0, length = requested_modules->length(); i < length; ++i) {
|
||||
Handle<Module> requested_module(Module::cast(requested_modules->get(i)),
|
||||
isolate);
|
||||
if (!FinishInstantiate(requested_module, context)) return false;
|
||||
if (!FinishInstantiate(requested_module, stack, dfs_index)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DCHECK_NE(requested_module->status(), kErrored);
|
||||
DCHECK_NE(requested_module->status(), kEvaluating);
|
||||
DCHECK_GE(requested_module->status(), kInstantiating);
|
||||
SLOW_DCHECK(
|
||||
// {requested_module} is instantiating iff it's on the {stack}.
|
||||
(requested_module->status() == kInstantiating) ==
|
||||
std::count_if(stack->begin(), stack->end(), [&](Handle<Module> m) {
|
||||
return *m == *requested_module;
|
||||
}));
|
||||
|
||||
if (requested_module->status() == kInstantiating) {
|
||||
module->set_dfs_ancestor_index(
|
||||
std::min(module->dfs_ancestor_index(),
|
||||
requested_module->dfs_ancestor_index()));
|
||||
}
|
||||
}
|
||||
|
||||
Zone zone(isolate->allocator(), ZONE_NAME);
|
||||
@ -19780,17 +19911,53 @@ bool Module::FinishInstantiate(Handle<Module> module,
|
||||
}
|
||||
}
|
||||
|
||||
MaybeTransitionComponent(module, stack, kInstantiated);
|
||||
return true;
|
||||
}
|
||||
|
||||
MaybeHandle<Object> Module::Evaluate(Handle<Module> module) {
|
||||
DCHECK(module->instantiated());
|
||||
|
||||
// Each module can only be evaluated once.
|
||||
Isolate* isolate = module->GetIsolate();
|
||||
if (module->evaluated()) return isolate->factory()->undefined_value();
|
||||
if (module->status() == kErrored) {
|
||||
isolate->Throw(module->GetException());
|
||||
return MaybeHandle<Object>();
|
||||
}
|
||||
DCHECK_NE(module->status(), kEvaluating);
|
||||
DCHECK_GE(module->status(), kInstantiated);
|
||||
Zone zone(isolate->allocator(), ZONE_NAME);
|
||||
|
||||
ZoneForwardList<Handle<Module>> stack(&zone);
|
||||
unsigned dfs_index = 0;
|
||||
Handle<Object> result;
|
||||
if (!Evaluate(module, &stack, &dfs_index).ToHandle(&result)) {
|
||||
for (auto& descendant : stack) {
|
||||
DCHECK_EQ(descendant->status(), kEvaluating);
|
||||
descendant->RecordError();
|
||||
}
|
||||
DCHECK_EQ(module->GetException(), isolate->pending_exception());
|
||||
return MaybeHandle<Object>();
|
||||
}
|
||||
DCHECK_EQ(module->status(), kEvaluated);
|
||||
DCHECK(stack.empty());
|
||||
return result;
|
||||
}
|
||||
|
||||
MaybeHandle<Object> Module::Evaluate(Handle<Module> module,
|
||||
ZoneForwardList<Handle<Module>>* stack,
|
||||
unsigned* dfs_index) {
|
||||
Isolate* isolate = module->GetIsolate();
|
||||
DCHECK_NE(module->status(), kErrored);
|
||||
if (module->status() >= kEvaluating) {
|
||||
return isolate->factory()->undefined_value();
|
||||
}
|
||||
DCHECK_EQ(module->status(), kInstantiated);
|
||||
|
||||
Handle<JSFunction> function(JSFunction::cast(module->code()), isolate);
|
||||
module->set_evaluated();
|
||||
module->set_code(function->shared()->scope_info()->ModuleDescriptorInfo());
|
||||
module->SetStatus(kEvaluating);
|
||||
module->set_dfs_index(*dfs_index);
|
||||
module->set_dfs_ancestor_index(*dfs_index);
|
||||
stack->push_front(module);
|
||||
(*dfs_index)++;
|
||||
|
||||
// Initialization.
|
||||
DCHECK_EQ(MODULE_SCOPE, function->shared()->scope_info()->scope_type());
|
||||
@ -19805,8 +19972,25 @@ MaybeHandle<Object> Module::Evaluate(Handle<Module> module) {
|
||||
// Recursion.
|
||||
Handle<FixedArray> requested_modules(module->requested_modules(), isolate);
|
||||
for (int i = 0, length = requested_modules->length(); i < length; ++i) {
|
||||
Handle<Module> import(Module::cast(requested_modules->get(i)), isolate);
|
||||
RETURN_ON_EXCEPTION(isolate, Evaluate(import), Object);
|
||||
Handle<Module> requested_module(Module::cast(requested_modules->get(i)),
|
||||
isolate);
|
||||
RETURN_ON_EXCEPTION(isolate, Evaluate(requested_module, stack, dfs_index),
|
||||
Object);
|
||||
|
||||
DCHECK_GE(requested_module->status(), kEvaluating);
|
||||
DCHECK_NE(requested_module->status(), kErrored);
|
||||
SLOW_DCHECK(
|
||||
// {requested_module} is evaluating iff it's on the {stack}.
|
||||
(requested_module->status() == kEvaluating) ==
|
||||
std::count_if(stack->begin(), stack->end(), [&](Handle<Module> m) {
|
||||
return *m == *requested_module;
|
||||
}));
|
||||
|
||||
if (requested_module->status() == kEvaluating) {
|
||||
module->set_dfs_ancestor_index(
|
||||
std::min(module->dfs_ancestor_index(),
|
||||
requested_module->dfs_ancestor_index()));
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluation of module body.
|
||||
@ -19819,6 +20003,8 @@ MaybeHandle<Object> Module::Evaluate(Handle<Module> module) {
|
||||
DCHECK(static_cast<JSIteratorResult*>(JSObject::cast(*result))
|
||||
->done()
|
||||
->BooleanValue());
|
||||
|
||||
MaybeTransitionComponent(module, stack, kEvaluated);
|
||||
return handle(
|
||||
static_cast<JSIteratorResult*>(JSObject::cast(*result))->value(),
|
||||
isolate);
|
||||
@ -19828,7 +20014,8 @@ namespace {
|
||||
|
||||
void FetchStarExports(Handle<Module> module, Zone* zone,
|
||||
UnorderedModuleSet* visited) {
|
||||
DCHECK(module->instantiated());
|
||||
DCHECK_NE(module->status(), Module::kErrored);
|
||||
DCHECK_GE(module->status(), Module::kInstantiated);
|
||||
|
||||
bool cycle = !visited->insert(module).second;
|
||||
if (cycle) return;
|
||||
|
@ -959,6 +959,8 @@ class FeedbackVector;
|
||||
class WeakCell;
|
||||
class TransitionArray;
|
||||
class TemplateList;
|
||||
template <typename T>
|
||||
class ZoneForwardList;
|
||||
|
||||
// A template-ized version of the IsXXX functions.
|
||||
template <class C> inline bool Is(Object* obj);
|
||||
@ -4852,9 +4854,21 @@ class Module : public Struct {
|
||||
// Hash for this object (a random non-zero Smi).
|
||||
DECL_INT_ACCESSORS(hash)
|
||||
|
||||
// Internal instantiation status.
|
||||
// Status.
|
||||
DECL_INT_ACCESSORS(status)
|
||||
enum InstantiationStatus { kUnprepared, kPrepared };
|
||||
enum Status {
|
||||
// Order matters!
|
||||
kUninstantiated,
|
||||
kPreInstantiating,
|
||||
kInstantiating,
|
||||
kInstantiated,
|
||||
kEvaluating,
|
||||
kEvaluated,
|
||||
kErrored
|
||||
};
|
||||
|
||||
// The exception in the case {status} is kErrored.
|
||||
Object* GetException();
|
||||
|
||||
// The namespace object (or undefined).
|
||||
DECL_ACCESSORS(module_namespace, HeapObject)
|
||||
@ -4870,9 +4884,6 @@ class Module : public Struct {
|
||||
// Get the ModuleInfo associated with the code.
|
||||
inline ModuleInfo* info() const;
|
||||
|
||||
inline bool instantiated() const;
|
||||
inline bool evaluated() const;
|
||||
|
||||
// Implementation of spec operation ModuleDeclarationInstantiation.
|
||||
// Returns false if an exception occurred during instantiation, true
|
||||
// otherwise. (In the case where the callback throws an exception, that
|
||||
@ -4907,10 +4918,23 @@ class Module : public Struct {
|
||||
static const int kRequestedModulesOffset =
|
||||
kModuleNamespaceOffset + kPointerSize;
|
||||
static const int kStatusOffset = kRequestedModulesOffset + kPointerSize;
|
||||
static const int kScriptOffset = kStatusOffset + kPointerSize;
|
||||
static const int kDfsIndexOffset = kStatusOffset + kPointerSize;
|
||||
static const int kDfsAncestorIndexOffset = kDfsIndexOffset + kPointerSize;
|
||||
static const int kExceptionOffset = kDfsAncestorIndexOffset + kPointerSize;
|
||||
static const int kScriptOffset = kExceptionOffset + kPointerSize;
|
||||
static const int kSize = kScriptOffset + kPointerSize;
|
||||
|
||||
private:
|
||||
friend class Factory;
|
||||
|
||||
DECL_ACCESSORS(exception, Object)
|
||||
|
||||
// TODO(neis): Don't store those in the module object?
|
||||
DECL_INT_ACCESSORS(dfs_index)
|
||||
DECL_INT_ACCESSORS(dfs_ancestor_index)
|
||||
|
||||
// Helpers for Instantiate and Evaluate.
|
||||
|
||||
static void CreateExport(Handle<Module> module, int cell_index,
|
||||
Handle<FixedArray> names);
|
||||
static void CreateIndirectExport(Handle<Module> module, Handle<String> name,
|
||||
@ -4937,13 +4961,23 @@ class Module : public Struct {
|
||||
Handle<Module> module, Handle<String> name, MessageLocation loc,
|
||||
bool must_resolve, ResolveSet* resolve_set);
|
||||
|
||||
inline void set_evaluated();
|
||||
|
||||
static MUST_USE_RESULT bool PrepareInstantiate(
|
||||
Handle<Module> module, v8::Local<v8::Context> context,
|
||||
v8::Module::ResolveCallback callback);
|
||||
static MUST_USE_RESULT bool FinishInstantiate(Handle<Module> module,
|
||||
v8::Local<v8::Context> context);
|
||||
static MUST_USE_RESULT bool FinishInstantiate(
|
||||
Handle<Module> module, ZoneForwardList<Handle<Module>>* stack,
|
||||
unsigned* dfs_index);
|
||||
static MUST_USE_RESULT MaybeHandle<Object> Evaluate(
|
||||
Handle<Module> module, ZoneForwardList<Handle<Module>>* stack,
|
||||
unsigned* dfs_index);
|
||||
|
||||
static void MaybeTransitionComponent(Handle<Module> module,
|
||||
ZoneForwardList<Handle<Module>>* stack,
|
||||
Status new_status);
|
||||
|
||||
// To set status to kErrored, RecordError should be used.
|
||||
void SetStatus(Status status);
|
||||
void RecordError();
|
||||
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(Module);
|
||||
};
|
||||
|
@ -6,6 +6,7 @@
|
||||
#define V8_SRC_ZONE_ZONE_CONTAINERS_H_
|
||||
|
||||
#include <deque>
|
||||
#include <forward_list>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <queue>
|
||||
@ -44,7 +45,7 @@ class ZoneVector : public std::vector<T, ZoneAllocator<T>> {
|
||||
: std::vector<T, ZoneAllocator<T>>(first, last, ZoneAllocator<T>(zone)) {}
|
||||
};
|
||||
|
||||
// A wrapper subclass std::deque to make it easy to construct one
|
||||
// A wrapper subclass for std::deque to make it easy to construct one
|
||||
// that uses a zone allocator.
|
||||
template <typename T>
|
||||
class ZoneDeque : public std::deque<T, RecyclingZoneAllocator<T>> {
|
||||
@ -55,7 +56,7 @@ class ZoneDeque : public std::deque<T, RecyclingZoneAllocator<T>> {
|
||||
RecyclingZoneAllocator<T>(zone)) {}
|
||||
};
|
||||
|
||||
// A wrapper subclass std::list to make it easy to construct one
|
||||
// A wrapper subclass for std::list to make it easy to construct one
|
||||
// that uses a zone allocator.
|
||||
// TODO(mstarzinger): This should be renamed to ZoneList once we got rid of our
|
||||
// own home-grown ZoneList that actually is a ZoneVector.
|
||||
@ -67,7 +68,17 @@ class ZoneLinkedList : public std::list<T, ZoneAllocator<T>> {
|
||||
: std::list<T, ZoneAllocator<T>>(ZoneAllocator<T>(zone)) {}
|
||||
};
|
||||
|
||||
// A wrapper subclass std::priority_queue to make it easy to construct one
|
||||
// A wrapper subclass for std::forward_list to make it easy to construct one
|
||||
// that uses a zone allocator.
|
||||
template <typename T>
|
||||
class ZoneForwardList : public std::forward_list<T, ZoneAllocator<T>> {
|
||||
public:
|
||||
// Constructs an empty list.
|
||||
explicit ZoneForwardList(Zone* zone)
|
||||
: std::forward_list<T, ZoneAllocator<T>>(ZoneAllocator<T>(zone)) {}
|
||||
};
|
||||
|
||||
// A wrapper subclass for std::priority_queue to make it easy to construct one
|
||||
// that uses a zone allocator.
|
||||
template <typename T, typename Compare = std::less<T>>
|
||||
class ZonePriorityQueue
|
||||
|
@ -104,7 +104,6 @@ i::Handle<i::BytecodeArray>
|
||||
BytecodeExpectationsPrinter::GetBytecodeArrayForModule(
|
||||
v8::Local<v8::Module> module) const {
|
||||
i::Handle<i::Module> i_module = v8::Utils::OpenHandle(*module);
|
||||
CHECK(!i_module->instantiated());
|
||||
return i::handle(SharedFunctionInfo::cast(i_module->code())->bytecode_array(),
|
||||
i_isolate());
|
||||
}
|
||||
|
13
test/mjsunit/harmony/import-from-compilation-errored.js
Normal file
13
test/mjsunit/harmony/import-from-compilation-errored.js
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright 2017 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --allow-natives-syntax --harmony-dynamic-import
|
||||
|
||||
var error1, error2;
|
||||
import('modules-skip-12.js').catch(e => error1 = e);
|
||||
import('modules-skip-12.js').catch(e => error2 = e);
|
||||
%RunMicrotasks();
|
||||
|
||||
assertEquals(error1, error2);
|
||||
assertInstanceof(error1, SyntaxError);
|
13
test/mjsunit/harmony/import-from-evaluation-errored.js
Normal file
13
test/mjsunit/harmony/import-from-evaluation-errored.js
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright 2017 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --allow-natives-syntax --harmony-dynamic-import
|
||||
|
||||
var error1, error2;
|
||||
import('modules-skip-11.js').catch(e => error1 = e);
|
||||
import('modules-skip-11.js').catch(e => error2 = e);
|
||||
%RunMicrotasks();
|
||||
|
||||
assertEquals(error1, error2);
|
||||
assertEquals(typeof error1, "symbol");
|
13
test/mjsunit/harmony/import-from-fetch-errored.js
Normal file
13
test/mjsunit/harmony/import-from-fetch-errored.js
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright 2017 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --allow-natives-syntax --harmony-dynamic-import
|
||||
|
||||
var error1, error2;
|
||||
import('no-such-file').catch(e => error1 = e);
|
||||
import('no-such-file').catch(e => error2 = e);
|
||||
%RunMicrotasks();
|
||||
|
||||
assertEquals(error1, error2);
|
||||
assertEquals(typeof error1, "string");
|
13
test/mjsunit/harmony/import-from-instantiation-errored.js
Normal file
13
test/mjsunit/harmony/import-from-instantiation-errored.js
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright 2017 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --allow-natives-syntax --harmony-dynamic-import
|
||||
|
||||
var error1, error2;
|
||||
import('modules-skip-10.js').catch(e => error1 = e);
|
||||
import('modules-skip-10.js').catch(e => error2 = e);
|
||||
%RunMicrotasks();
|
||||
|
||||
assertEquals(error1, error2);
|
||||
assertInstanceof(error1, SyntaxError);
|
5
test/mjsunit/harmony/modules-skip-10.js
Normal file
5
test/mjsunit/harmony/modules-skip-10.js
Normal file
@ -0,0 +1,5 @@
|
||||
// Copyright 2017 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import {x} from "./modules-skip-10.js"
|
5
test/mjsunit/harmony/modules-skip-11.js
Normal file
5
test/mjsunit/harmony/modules-skip-11.js
Normal file
@ -0,0 +1,5 @@
|
||||
// Copyright 2017 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
throw Symbol();
|
5
test/mjsunit/harmony/modules-skip-12.js
Normal file
5
test/mjsunit/harmony/modules-skip-12.js
Normal file
@ -0,0 +1,5 @@
|
||||
// Copyright 2017 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
$^#$%@#@^^%^%$^#%%#!#$%!#$@#$%
|
Loading…
Reference in New Issue
Block a user