[api] Add a dedicated UnboundModuleScript type

Module and script SharedFunctionInfos can't be used interchangeably
(e.g.: it should not be possible to bind a Module's SFI to a Context).

The dedicated type disambiguates the two.

This also adds an overload for CreateCodeCache which takes an unbound
module script instead of an unbound script. Both are just a SFI
underneath, so their behavior is identical.

Bug: v8:7685
Cq-Include-Trybots: luci.chromium.try:linux_chromium_rel_ng
Change-Id: Iab519d0d50b6b41c95abdb6397f5622e292da4d8
Reviewed-on: https://chromium-review.googlesource.com/1047107
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: Georg Neis <neis@chromium.org>
Reviewed-by: Yang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53150}
This commit is contained in:
jgruber 2018-05-08 13:19:30 +02:00 committed by Commit Bot
parent fb4163e330
commit 8ec92f5118
4 changed files with 84 additions and 19 deletions

View File

@ -1212,6 +1212,13 @@ class V8_EXPORT UnboundScript {
static const int kNoScriptId = 0;
};
/**
* A compiled JavaScript module, not yet tied to a Context.
*/
class V8_EXPORT UnboundModuleScript {
// Only used as a container for code caching.
};
/**
* A location in JavaScript source.
*/
@ -1313,12 +1320,12 @@ class V8_EXPORT Module {
Local<Value> GetModuleNamespace();
/**
* Returns the corresponding context-unbound script.
* Returns the corresponding context-unbound module script.
*
* The module must be unevaluated, i.e. its status must not be kEvaluating,
* kEvaluated or kErrored.
*/
Local<UnboundScript> GetUnboundScript();
Local<UnboundModuleScript> GetUnboundModuleScript();
};
/**
@ -1677,6 +1684,14 @@ class V8_EXPORT ScriptCompiler {
*/
static CachedData* CreateCodeCache(Local<UnboundScript> unbound_script);
/**
* Creates and returns code cache for the specified unbound_module_script.
* This will return nullptr if the script cannot be serialized. The
* CachedData returned by this function should be owned by the caller.
*/
static CachedData* CreateCodeCache(
Local<UnboundModuleScript> unbound_module_script);
V8_DEPRECATED("Source string is no longer required",
static CachedData* CreateCodeCache(
Local<UnboundScript> unbound_script, Local<String> source));

View File

@ -2323,12 +2323,12 @@ Local<Value> Module::GetModuleNamespace() {
return ToApiHandle<Value>(module_namespace);
}
Local<UnboundScript> Module::GetUnboundScript() {
Local<UnboundModuleScript> Module::GetUnboundModuleScript() {
Utils::ApiCheck(
GetStatus() < kEvaluating, "v8::Module::GetUnboundScript",
"v8::Module::GetUnboundScript must be used on an unevaluated module");
i::Handle<i::Module> self = Utils::OpenHandle(this);
return ToApiHandle<UnboundScript>(
return ToApiHandle<UnboundModuleScript>(
i::Handle<i::SharedFunctionInfo>(self->GetSharedFunctionInfo()));
}
@ -2673,6 +2673,16 @@ ScriptCompiler::CachedData* ScriptCompiler::CreateCodeCache(
return i::CodeSerializer::Serialize(shared);
}
// static
ScriptCompiler::CachedData* ScriptCompiler::CreateCodeCache(
Local<UnboundModuleScript> unbound_module_script) {
i::Handle<i::SharedFunctionInfo> shared =
i::Handle<i::SharedFunctionInfo>::cast(
Utils::OpenHandle(*unbound_module_script));
DCHECK(shared->is_toplevel());
return i::CodeSerializer::Serialize(shared);
}
ScriptCompiler::CachedData* ScriptCompiler::CreateCodeCacheForFunction(
Local<Function> function, Local<String> source) {
return CreateCodeCacheForFunction(function);

View File

@ -112,6 +112,7 @@ class RegisteredExtension {
V(String, String) \
V(Symbol, Symbol) \
V(Script, JSFunction) \
V(UnboundModuleScript, SharedFunctionInfo) \
V(UnboundScript, SharedFunctionInfo) \
V(Module, Module) \
V(Function, JSReceiver) \

View File

@ -25636,6 +25636,55 @@ TEST(CodeCache) {
isolate2->Dispose();
}
v8::MaybeLocal<Module> UnexpectedModuleResolveCallback(Local<Context> context,
Local<String> specifier,
Local<Module> referrer) {
CHECK_WITH_MSG(false, "Unexpected call to resolve callback");
}
TEST(ModuleCodeCache) {
v8::Isolate::CreateParams create_params;
create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
const char* origin = "code cache test";
v8::ScriptCompiler::CachedData* cache;
v8::Isolate* isolate1 = v8::Isolate::New(create_params);
{
v8::Isolate::Scope iscope(isolate1);
v8::HandleScope scope(isolate1);
v8::Local<v8::Context> context = v8::Context::New(isolate1);
v8::Context::Scope cscope(context);
Local<String> source_text = v8_str(
"export default 5; export const a = 10; function f() { return 42; } "
"(function() { return f(); })();");
v8::ScriptOrigin script_origin(
v8_str(origin), Local<v8::Integer>(), Local<v8::Integer>(),
Local<v8::Boolean>(), Local<v8::Integer>(), Local<v8::Value>(),
Local<v8::Boolean>(), Local<v8::Boolean>(), True(isolate1));
v8::ScriptCompiler::Source source(source_text, script_origin);
Local<Module> module =
v8::ScriptCompiler::CompileModule(isolate1, &source).ToLocalChecked();
module->InstantiateModule(context, UnexpectedModuleResolveCallback)
.ToChecked();
// Fetch the shared function info before evaluation.
Local<v8::UnboundModuleScript> unbound_module_script =
module->GetUnboundModuleScript();
// Evaluate for possible lazy compilation.
Local<Value> completion_value = module->Evaluate(context).ToLocalChecked();
CHECK_EQ(42, completion_value->Int32Value(context).FromJust());
// Now create the cache.
cache = v8::ScriptCompiler::CreateCodeCache(unbound_module_script);
}
isolate1->Dispose();
// TODO(jgruber,v8:7685): Test module code cache consumption once implemented.
delete cache;
}
void TestInvalidCacheData(v8::ScriptCompiler::CompileOptions option) {
const char* garbage = "garbage garbage garbage garbage garbage garbage";
@ -27370,12 +27419,6 @@ void HostInitializeImportMetaObjectCallbackStatic(Local<Context> context,
meta->CreateDataProperty(context, v8_str("foo"), v8_str("bar")).ToChecked();
}
v8::MaybeLocal<Module> UnexpectedModuleResolveCallback(Local<Context> context,
Local<String> specifier,
Local<Module> referrer) {
CHECK_WITH_MSG(false, "Unexpected call to resolve callback");
}
TEST(ImportMeta) {
i::FLAG_harmony_dynamic_import = true;
i::FLAG_harmony_import_meta = true;
@ -27443,7 +27486,7 @@ TEST(GetModuleNamespace) {
->StrictEquals(v8::Number::New(isolate, 10)));
}
TEST(ModuleGetUnboundScript) {
TEST(ModuleGetUnboundModuleScript) {
LocalContext context;
v8::Isolate* isolate = context->GetIsolate();
v8::HandleScope scope(isolate);
@ -27457,11 +27500,12 @@ TEST(ModuleGetUnboundScript) {
v8::ScriptCompiler::Source source(source_text, origin);
Local<Module> module =
v8::ScriptCompiler::CompileModule(isolate, &source).ToLocalChecked();
Local<v8::UnboundScript> sfi_before_instantiation =
module->GetUnboundScript();
Local<v8::UnboundModuleScript> sfi_before_instantiation =
module->GetUnboundModuleScript();
module->InstantiateModule(context.local(), UnexpectedModuleResolveCallback)
.ToChecked();
Local<v8::UnboundScript> sfi_after_instantiation = module->GetUnboundScript();
Local<v8::UnboundModuleScript> sfi_after_instantiation =
module->GetUnboundModuleScript();
// Check object identity.
{
@ -27469,11 +27513,6 @@ TEST(ModuleGetUnboundScript) {
i::Handle<i::Object> s2 = v8::Utils::OpenHandle(*sfi_after_instantiation);
CHECK_EQ(*s1, *s2);
}
// Check unbound script values.
Local<v8::UnboundScript> sfi = sfi_after_instantiation;
CHECK(ValueEqualsString(isolate, sfi->GetScriptName(), "www.google.com"));
CHECK_EQ(0, sfi->GetLineNumber(0));
}
TEST(GlobalTemplateWithDoubleProperty) {