Skip to content
This repository was archived by the owner on Apr 16, 2020. It is now read-only.

WIP [Do not merge] - Irp type dynamic modules #29

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ module.exports = {
files: [
'doc/api/esm.md',
'*.mjs',
'test/es-module/test-esm-example-loader.js',
],
parserOptions: { sourceType: 'module' },
},
Expand Down
42 changes: 42 additions & 0 deletions deps/v8/include/v8.h
Original file line number Diff line number Diff line change
Expand Up @@ -1219,6 +1219,19 @@ class V8_EXPORT Module {
Local<UnboundModuleScript> GetUnboundModuleScript();
};

/**
* A Dynamic JavaScript module
*/
class V8_EXPORT DynamicModule : public Module {
public:
/**
* Set an export value, corresponding to an export name
*/
bool SetExport(Isolate* isolate, Local<String> export_name,
Local<Value> value);
V8_INLINE static DynamicModule* Cast(v8::Module* module);
};

/**
* A compiled JavaScript script, tied to a Context which was active when the
* script was compiled.
Expand Down Expand Up @@ -1547,6 +1560,12 @@ class V8_EXPORT ScriptCompiler {
CompileOptions options = kNoCompileOptions,
NoCacheReason no_cache_reason = kNoCacheNoReason);

/**
* Create a new Dynamic Module.
*/
static V8_WARN_UNUSED_RESULT MaybeLocal<DynamicModule> CreateDynamicModule(
Isolate* isolate);

/**
* Compile a function for a given context. This is equivalent to running
*
Expand Down Expand Up @@ -6421,6 +6440,15 @@ typedef void (*AddHistogramSampleCallback)(void* histogram, int sample);
typedef void (*BeforeCallEnteredCallback)(Isolate*);
typedef void (*CallCompletedCallback)(Isolate*);

/**
* HostExecuteDynamicModuleCallback is called at the exact point
* of execution of a dynamic module in the graph.
*
* It should call Module::SetExport for each defined export.
*/
typedef void (*HostExecuteDynamicModuleCallback)(Local<Context> context,
Local<DynamicModule> module);

/**
* HostImportModuleDynamicallyCallback is called when we require the
* embedder to load a module. This is used as part of the dynamic
Expand Down Expand Up @@ -7450,6 +7478,13 @@ class V8_EXPORT Isolate {
void SetAbortOnUncaughtExceptionCallback(
AbortOnUncaughtExceptionCallback callback);

/*
* This specifies the callback called by Dynamic Module records
* at their exact point of execution in the module graph.
*/
void SetHostExecuteDynamicModuleCallback(
HostExecuteDynamicModuleCallback callback);

/**
* This specifies the callback called by the upcoming dynamic
* import() language feature to load modules.
Expand Down Expand Up @@ -10163,6 +10198,13 @@ WasmCompiledModule* WasmCompiledModule::Cast(v8::Value* value) {
return static_cast<WasmCompiledModule*>(value);
}

DynamicModule* DynamicModule::Cast(v8::Module* value) {
#ifdef V8_ENABLE_CHECKS
CheckCast(value);
#endif
return static_cast<DynamicModule*>(value);
}

Promise::Resolver* Promise::Resolver::Cast(v8::Value* value) {
#ifdef V8_ENABLE_CHECKS
CheckCast(value);
Expand Down
121 changes: 84 additions & 37 deletions deps/v8/src/api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2292,6 +2292,79 @@ MaybeLocal<Value> Module::Evaluate(Local<Context> context) {
RETURN_ESCAPED(result);
}

class IsIdentifierHelper {
public:
IsIdentifierHelper() : is_identifier_(false), first_char_(true) {}

bool Check(i::String* string) {
i::ConsString* cons_string = i::String::VisitFlat(this, string, 0);
if (cons_string == nullptr) return is_identifier_;
// We don't support cons strings here.
return false;
}
void VisitOneByteString(const uint8_t* chars, int length) {
for (int i = 0; i < length; ++i) {
if (first_char_) {
first_char_ = false;
is_identifier_ = unicode_cache_.IsIdentifierStart(chars[0]);
} else {
is_identifier_ &= unicode_cache_.IsIdentifierPart(chars[i]);
}
}
}
void VisitTwoByteString(const uint16_t* chars, int length) {
for (int i = 0; i < length; ++i) {
if (first_char_) {
first_char_ = false;
is_identifier_ = unicode_cache_.IsIdentifierStart(chars[0]);
} else {
is_identifier_ &= unicode_cache_.IsIdentifierPart(chars[i]);
}
}
}

private:
bool is_identifier_;
bool first_char_;
i::UnicodeCache unicode_cache_;
DISALLOW_COPY_AND_ASSIGN(IsIdentifierHelper);
};

bool DynamicModule::SetExport(Isolate* v8_isolate, Local<String> export_name,
Local<Value> value) {
Utils::ApiCheck(
GetStatus() >= kEvaluating, "v8::Module::SetExport",
"v8::DynamicModule::SetExport must be used after instantiation");
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
i::Handle<i::Module> self = Utils::OpenHandle(this);
i::Handle<i::String> name = Utils::OpenHandle(*(export_name));
i::Handle<i::Object> object(self->exports()->Lookup(name), isolate);

i::Handle<i::Object> val = Utils::OpenHandle(*(value));

// Exports can be defined while executing
if (!object->IsCell()) {
if (GetStatus() == kEvaluating) {
i::Handle<i::String> internal_name =
isolate->factory()->InternalizeString(name);
// Return *false* for any invalid identifier passed
IsIdentifierHelper helper;
if (!helper.Check(*internal_name)) return false;
auto cell = i::Module::CreateDynamicExport(isolate, self, internal_name);
cell->set_value(*val);
return true;
}
else {
Utils::ApiCheck(object->IsCell(), "v8::Module::SetExport",
"v8::Module::SetExport unable to find local export name");
}
}

auto cell = i::Handle<i::Cell>::cast(object);
cell->set_value(*val);
return true;
}

namespace {

i::Compiler::ScriptDetails GetScriptDetails(
Expand Down Expand Up @@ -2417,44 +2490,12 @@ MaybeLocal<Module> ScriptCompiler::CompileModule(
return ToApiHandle<Module>(i_isolate->factory()->NewModule(shared));
}

MaybeLocal<DynamicModule> ScriptCompiler::CreateDynamicModule(
Isolate* isolate) {
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);

class IsIdentifierHelper {
public:
IsIdentifierHelper() : is_identifier_(false), first_char_(true) {}

bool Check(i::String* string) {
i::ConsString* cons_string = i::String::VisitFlat(this, string, 0);
if (cons_string == nullptr) return is_identifier_;
// We don't support cons strings here.
return false;
}
void VisitOneByteString(const uint8_t* chars, int length) {
for (int i = 0; i < length; ++i) {
if (first_char_) {
first_char_ = false;
is_identifier_ = unicode_cache_.IsIdentifierStart(chars[0]);
} else {
is_identifier_ &= unicode_cache_.IsIdentifierPart(chars[i]);
}
}
}
void VisitTwoByteString(const uint16_t* chars, int length) {
for (int i = 0; i < length; ++i) {
if (first_char_) {
first_char_ = false;
is_identifier_ = unicode_cache_.IsIdentifierStart(chars[0]);
} else {
is_identifier_ &= unicode_cache_.IsIdentifierPart(chars[i]);
}
}
}

private:
bool is_identifier_;
bool first_char_;
i::UnicodeCache unicode_cache_;
DISALLOW_COPY_AND_ASSIGN(IsIdentifierHelper);
};
return ToApiHandle<DynamicModule>(i_isolate->factory()->NewDynamicModule());
}

MaybeLocal<Function> ScriptCompiler::CompileFunctionInContext(
Local<Context> v8_context, Source* source, size_t arguments_count,
Expand Down Expand Up @@ -8286,6 +8327,12 @@ void Isolate::SetAbortOnUncaughtExceptionCallback(
isolate->SetAbortOnUncaughtExceptionCallback(callback);
}

void Isolate::SetHostExecuteDynamicModuleCallback(
HostExecuteDynamicModuleCallback callback) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
isolate->SetHostExecuteDynamicModuleCallback(callback);
}

void Isolate::SetHostImportModuleDynamicallyCallback(
HostImportModuleDynamicallyCallback callback) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
Expand Down
30 changes: 30 additions & 0 deletions deps/v8/src/heap/factory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3053,6 +3053,36 @@ Handle<Module> Factory::NewModule(Handle<SharedFunctionInfo> code) {
module->set_import_meta(roots.the_hole_value());
module->set_dfs_index(-1);
module->set_dfs_ancestor_index(-1);
module->set_module_type(Module::Type::kSourceTextModule);
return module;
}

Handle<Module> Factory::NewDynamicModule() {
Handle<ObjectHashTable> exports = ObjectHashTable::New(isolate(), 0);
// For dynamic modules, regular_exports is an
// ArrayList until execution completion.
Handle<ArrayList> regular_exports = ArrayList::New(isolate(), 0);
Handle<ArrayList> dynamic_namespaces = ArrayList::New(isolate(), 0);

ReadOnlyRoots roots(isolate());

Handle<Module> module = Handle<Module>::cast(NewStruct(MODULE_TYPE, TENURED));

module->set_code(roots.undefined_value());
module->set_exports(*exports);
module->set_regular_exports(*regular_exports);
// Dynamic modules reuse regular_imports to track dynamic_namespaces.
module->set_regular_imports(*dynamic_namespaces);
module->set_hash(isolate()->GenerateIdentityHash(Smi::kMaxValue));
module->set_module_namespace(roots.undefined_value());
module->set_requested_modules(roots.empty_fixed_array());
// module->set_script();
module->set_status(Module::kUninstantiated);
module->set_exception(roots.the_hole_value());
module->set_import_meta(roots.the_hole_value());
module->set_dfs_index(-1);
module->set_dfs_ancestor_index(-1);
module->set_module_type(Module::Type::kDynamicModule);
return module;
}

Expand Down
2 changes: 2 additions & 0 deletions deps/v8/src/heap/factory.h
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,8 @@ class V8_EXPORT_PRIVATE Factory {

Handle<Module> NewModule(Handle<SharedFunctionInfo> code);

Handle<Module> NewDynamicModule();

Handle<JSArrayBuffer> NewJSArrayBuffer(
SharedFlag shared = SharedFlag::kNotShared,
PretenureFlag pretenure = NOT_TENURED);
Expand Down
12 changes: 12 additions & 0 deletions deps/v8/src/isolate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4042,6 +4042,18 @@ void Isolate::SetHostInitializeImportMetaObjectCallback(
host_initialize_import_meta_object_callback_ = callback;
}

void Isolate::RunHostExecuteDynamicModuleCallback(Handle<Context> context,
Handle<Module> module) {
v8::Local<v8::Context> api_context = Utils::ToLocal(context);
host_execute_dynamic_module_callback_(
api_context, Utils::Convert<v8::internal::Object, DynamicModule>(module));
}

void Isolate::SetHostExecuteDynamicModuleCallback(
HostExecuteDynamicModuleCallback callback) {
host_execute_dynamic_module_callback_ = callback;
}

MaybeHandle<Object> Isolate::RunPrepareStackTraceCallback(
Handle<Context> context, Handle<JSObject> error) {
v8::Local<v8::Context> api_context = Utils::ToLocal(context);
Expand Down
7 changes: 7 additions & 0 deletions deps/v8/src/isolate.h
Original file line number Diff line number Diff line change
Expand Up @@ -1506,6 +1506,11 @@ class Isolate : private HiddenFactory {
Handle<JSObject> RunHostInitializeImportMetaObjectCallback(
Handle<Module> module);

void SetHostExecuteDynamicModuleCallback(
HostExecuteDynamicModuleCallback callback);
void RunHostExecuteDynamicModuleCallback(Handle<Context>,
Handle<Module> module);

void SetPrepareStackTraceCallback(PrepareStackTraceCallback callback);
MaybeHandle<Object> RunPrepareStackTraceCallback(Handle<Context>,
Handle<JSObject> Error);
Expand Down Expand Up @@ -1731,6 +1736,8 @@ class Isolate : private HiddenFactory {
HostImportModuleDynamicallyCallback host_import_module_dynamically_callback_;
HostInitializeImportMetaObjectCallback
host_initialize_import_meta_object_callback_;
HostExecuteDynamicModuleCallback host_execute_dynamic_module_callback_ =
nullptr;
base::Mutex rail_mutex_;
double load_start_time_ms_;

Expand Down
2 changes: 2 additions & 0 deletions deps/v8/src/messages.h
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,8 @@ class ErrorUtils : public AllStatic {
T(DuplicateExport, "Duplicate export of '%'") \
T(DuplicateProto, \
"Duplicate __proto__ fields are not allowed in object literals") \
T(DynamicModuleStarExport, \
"Star exports from dynamic module '%' are not allowed") \
T(ForInOfLoopInitializer, \
"% loop variable declaration may not have an initializer.") \
T(ForInOfLoopMultiBindings, \
Expand Down
1 change: 1 addition & 0 deletions deps/v8/src/objects/module-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ SMI_ACCESSORS(Module, status, kStatusOffset)
SMI_ACCESSORS(Module, dfs_index, kDfsIndexOffset)
SMI_ACCESSORS(Module, dfs_ancestor_index, kDfsAncestorIndexOffset)
SMI_ACCESSORS(Module, hash, kHashOffset)
SMI_ACCESSORS(Module, module_type, kModuleTypeOffset)

ModuleInfo* Module::info() const {
return (status() >= kEvaluating)
Expand Down
Loading