From dbfe4a49d88f6655ed31285a40b63786ab1e8e49 Mon Sep 17 00:00:00 2001 From: Sathya Gunasekaran Date: Wed, 30 Aug 2017 14:21:13 -0700 Subject: [PATCH] [Modules] Introduce ScriptOrModule and HostDefinedOptions This patch introduces a new container type ScriptOrModule which provides the name and the host defined options of the script/module. This patch also introduces a new PrimitivesArray that can hold Primitive values, which the embedder can use to store metadata. The HostDefinedOptions is passed to V8 through the ScriptOrigin, and passed back to the embedder through HostImportModuleDynamically for module loading. Bug: v8:5785, v8:6658, v8:6683 Cq-Include-Trybots: master.tryserver.chromium.linux:linux_chromium_rel_ng Change-Id: I56c26fc9a680b273ac0a6691e5ad75f15b8dc80a Reviewed-on: https://chromium-review.googlesource.com/622158 Reviewed-by: Adam Klein Reviewed-by: Georg Neis Commit-Queue: Sathya Gunasekaran Cr-Commit-Position: refs/heads/master@{#47724} --- include/v8.h | 68 ++++++++++++++++++++++--- src/api.cc | 74 +++++++++++++++++++++++++-- src/api.h | 14 +++++- src/bootstrapper.cc | 5 +- src/compiler.cc | 6 ++- src/compiler.h | 2 +- src/d8.cc | 8 +-- src/d8.h | 3 +- src/factory.cc | 2 +- src/isolate.cc | 4 +- src/isolate.h | 2 +- src/objects/script-inl.h | 1 + src/objects/script.h | 7 ++- src/runtime/runtime-module.cc | 5 +- test/cctest/compiler/test-linkage.cc | 3 +- test/cctest/test-api.cc | 75 ++++++++++++++++++++++++++-- test/cctest/test-compiler.cc | 3 +- test/cctest/test-serialize.cc | 5 +- tools/v8heapconst.py | 30 +++++------ 19 files changed, 264 insertions(+), 53 deletions(-) diff --git a/include/v8.h b/include/v8.h index 189eed5e65..f790659f3f 100644 --- a/include/v8.h +++ b/include/v8.h @@ -104,6 +104,7 @@ class String; class StringObject; class Symbol; class SymbolObject; +class PrimitiveArray; class Private; class Uint32; class Utils; @@ -978,6 +979,48 @@ class V8_EXPORT Data { Data(); }; +/** + * This is an unfinished experimental feature, and is only exposed + * here for internal testing purposes. DO NOT USE. + * + * A container type that holds relevant metadata for module loading. + * + * This is passed back to the embedder as part of + * HostImportDynamicallyCallback for module loading. + */ +class V8_EXPORT ScriptOrModule { + public: + /** + * The name that was passed by the embedder as ResourceName to the + * ScriptOrigin. This can be either a v8::String or v8::Undefined. + */ + Local GetResourceName(); + + /** + * The options that were passed by the embedder as HostDefinedOptions to + * the ScriptOrigin. + */ + Local GetHostDefinedOptions(); +}; + +/** + * This is an unfinished experimental feature, and is only exposed + * here for internal testing purposes. DO NOT USE. + * + * An array to hold Primitive values. This is used by the embedder to + * pass host defined options to the ScriptOptions during compilation. + * + * This is passed back to the embedder as part of + * HostImportDynamicallyCallback for module loading. + * + */ +class V8_EXPORT PrimitiveArray { + public: + static Local New(Isolate* isolate, int length); + int Length() const; + void Set(int index, Local item); + Local Get(int index); +}; /** * The optional attributes of ScriptOrigin. @@ -1027,13 +1070,15 @@ class ScriptOrigin { Local source_map_url = Local(), Local resource_is_opaque = Local(), Local is_wasm = Local(), - Local is_module = Local()); + Local is_module = Local(), + Local host_defined_options = Local()); V8_INLINE Local ResourceName() const; V8_INLINE Local ResourceLineOffset() const; V8_INLINE Local ResourceColumnOffset() const; V8_INLINE Local ScriptID() const; V8_INLINE Local SourceMapUrl() const; + V8_INLINE Local HostDefinedOptions() const; V8_INLINE ScriptOriginOptions Options() const { return options_; } private: @@ -1043,6 +1088,7 @@ class ScriptOrigin { ScriptOriginOptions options_; Local script_id_; Local source_map_url_; + Local host_defined_options_; }; /** @@ -1289,6 +1335,7 @@ class V8_EXPORT ScriptCompiler { Local resource_column_offset; ScriptOriginOptions resource_options; Local source_map_url; + Local host_defined_options; // Cached data from previous compilation (if a kConsume*Cache flag is // set), or hold newly generated cache data (kProduce*Cache flags) are @@ -6204,8 +6251,8 @@ typedef void (*DeprecatedCallCompletedCallback)(); * embedder to load a module. This is used as part of the dynamic * import syntax. * - * The referrer is the name of the file which calls the dynamic - * import. The referrer can be used to resolve the module location. + * The referrer contains metadata about the script/module that calls + * import. * * The specifier is the name of the module that should be imported. * @@ -6220,7 +6267,8 @@ typedef void (*DeprecatedCallCompletedCallback)(); * that exception by returning an empty MaybeLocal. */ typedef MaybeLocal (*HostImportModuleDynamicallyCallback)( - Local context, Local referrer, Local specifier); + Local context, Local referrer, + Local specifier); /** * PromiseHook with type kInit is called when a new promise is @@ -9531,7 +9579,8 @@ ScriptOrigin::ScriptOrigin(Local resource_name, Local script_id, Local source_map_url, Local resource_is_opaque, - Local is_wasm, Local is_module) + Local is_wasm, Local is_module, + Local host_defined_options) : resource_name_(resource_name), resource_line_offset_(resource_line_offset), resource_column_offset_(resource_column_offset), @@ -9541,10 +9590,14 @@ ScriptOrigin::ScriptOrigin(Local resource_name, !is_wasm.IsEmpty() && is_wasm->IsTrue(), !is_module.IsEmpty() && is_module->IsTrue()), script_id_(script_id), - source_map_url_(source_map_url) {} + source_map_url_(source_map_url), + host_defined_options_(host_defined_options) {} Local ScriptOrigin::ResourceName() const { return resource_name_; } +Local ScriptOrigin::HostDefinedOptions() const { + return host_defined_options_; +} Local ScriptOrigin::ResourceLineOffset() const { return resource_line_offset_; @@ -9561,7 +9614,6 @@ Local ScriptOrigin::ScriptID() const { return script_id_; } Local ScriptOrigin::SourceMapUrl() const { return source_map_url_; } - ScriptCompiler::Source::Source(Local string, const ScriptOrigin& origin, CachedData* data) : source_string(string), @@ -9570,9 +9622,9 @@ ScriptCompiler::Source::Source(Local string, const ScriptOrigin& origin, resource_column_offset(origin.ResourceColumnOffset()), resource_options(origin.Options()), source_map_url(origin.SourceMapUrl()), + host_defined_options(origin.HostDefinedOptions()), cached_data(data) {} - ScriptCompiler::Source::Source(Local string, CachedData* data) : source_string(string), cached_data(data) {} diff --git a/src/api.cc b/src/api.cc index 0a2068fdb0..82c578649c 100644 --- a/src/api.cc +++ b/src/api.cc @@ -279,6 +279,8 @@ static ScriptOrigin GetScriptOriginForScript(i::Isolate* isolate, i::Handle script) { i::Handle scriptName(script->GetNameOrSourceURL(), isolate); i::Handle source_map_url(script->source_mapping_url(), isolate); + i::Handle host_defined_options(script->host_defined_options(), + isolate); v8::Isolate* v8_isolate = reinterpret_cast(script->GetIsolate()); ScriptOriginOptions options(script->origin_options()); @@ -291,7 +293,8 @@ static ScriptOrigin GetScriptOriginForScript(i::Isolate* isolate, Utils::ToLocal(source_map_url), v8::Boolean::New(v8_isolate, options.IsOpaque()), v8::Boolean::New(v8_isolate, script->type() == i::Script::TYPE_WASM), - v8::Boolean::New(v8_isolate, options.IsModule())); + v8::Boolean::New(v8_isolate, options.IsModule()), + Utils::ToLocal(host_defined_options)); return origin; } @@ -2090,6 +2093,21 @@ Local Script::Run() { RETURN_TO_LOCAL_UNCHECKED(Run(context), Value); } +Local ScriptOrModule::GetResourceName() { + i::Handle obj = Utils::OpenHandle(this); + i::Isolate* isolate = obj->GetIsolate(); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); + i::Handle val(obj->name(), isolate); + return ToApiHandle(val); +} + +Local ScriptOrModule::GetHostDefinedOptions() { + i::Handle obj = Utils::OpenHandle(this); + i::Isolate* isolate = obj->GetIsolate(); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); + i::Handle val(obj->host_defined_options(), isolate); + return ToApiHandle(val); +} Local Script::GetUnboundScript() { i::Handle obj = Utils::OpenHandle(this); @@ -2097,6 +2115,46 @@ Local Script::GetUnboundScript() { i::Handle(i::JSFunction::cast(*obj)->shared())); } +// static +Local PrimitiveArray::New(Isolate* v8_isolate, int length) { + i::Isolate* isolate = reinterpret_cast(v8_isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); + Utils::ApiCheck(length >= 0, "v8::PrimitiveArray::New", + "length must be equal or greater than zero"); + i::Handle array = isolate->factory()->NewFixedArray(length); + return ToApiHandle(array); +} + +int PrimitiveArray::Length() const { + i::Handle array = Utils::OpenHandle(this); + i::Isolate* isolate = array->GetIsolate(); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); + return array->length(); +} + +void PrimitiveArray::Set(int index, Local item) { + i::Handle array = Utils::OpenHandle(this); + i::Isolate* isolate = array->GetIsolate(); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); + Utils::ApiCheck(index >= 0 && index < array->length(), + "v8::PrimitiveArray::Set", + "index must be greater than or equal to 0 and less than the " + "array length"); + i::Handle i_item = Utils::OpenHandle(*item); + array->set(index, *i_item); +} + +Local PrimitiveArray::Get(int index) { + i::Handle array = Utils::OpenHandle(this); + i::Isolate* isolate = array->GetIsolate(); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); + Utils::ApiCheck(index >= 0 && index < array->length(), + "v8::PrimitiveArray::Get", + "index must be greater than or equal to 0 and less than the " + "array length"); + i::Handle i_item(array->get(index), isolate); + return ToApiHandle(i_item); +} Module::Status Module::GetStatus() const { i::Handle self = Utils::OpenHandle(this); @@ -2233,11 +2291,16 @@ MaybeLocal ScriptCompiler::CompileUnboundInternal( TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileScript"); i::Handle name_obj; i::Handle source_map_url; + i::Handle host_defined_options = + isolate->factory()->empty_fixed_array(); int line_offset = 0; int column_offset = 0; if (!source->resource_name.IsEmpty()) { name_obj = Utils::OpenHandle(*(source->resource_name)); } + if (!source->host_defined_options.IsEmpty()) { + host_defined_options = Utils::OpenHandle(*(source->host_defined_options)); + } if (!source->resource_line_offset.IsEmpty()) { line_offset = static_cast(source->resource_line_offset->Value()); } @@ -2251,7 +2314,7 @@ MaybeLocal ScriptCompiler::CompileUnboundInternal( result = i::Compiler::GetSharedFunctionInfoForScript( str, name_obj, line_offset, column_offset, source->resource_options, source_map_url, isolate->native_context(), NULL, &script_data, options, - i::NOT_NATIVES_CODE); + i::NOT_NATIVES_CODE, host_defined_options); has_pending_exception = result.is_null(); if (has_pending_exception && script_data != NULL) { // This case won't happen during normal operation; we have compiled @@ -2516,6 +2579,10 @@ MaybeLocal