Skip to content

Commit

Permalink
deps: V8: backport b33af60
Browse files Browse the repository at this point in the history
Original commit message:

    [api] Get ScriptOrModule from CompileFunctionInContext

    Adds a new out param which allows accessing the ScriptOrModule
    of a function, which allows an embedder such as Node.js to use
    the function's i::Script lifetime.

    Refs: nodejs/node-v8#111
    Change-Id: I34346d94d76e8f9b8377c97d948673f4b95eb9d5
    Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1699698
    Reviewed-by: Yang Guo <yangguo@chromium.org>
    Commit-Queue: Yang Guo <yangguo@chromium.org>
    Cr-Commit-Position: refs/heads/master@{#62830}

Refs: v8/v8@b33af60

Backport-PR-URL: nodejs#28779
PR-URL: nodejs#28671
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Guy Bedford <guybedford@gmail.com>
  • Loading branch information
devsnek authored and targos committed Jul 23, 2019
1 parent 8586294 commit 674d33c
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 58 deletions.
2 changes: 1 addition & 1 deletion common.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@

# Reset this number to 0 on major V8 upgrades.
# Increment by one for each non-official patch applied to deps/v8.
'v8_embedder_string': '-node.15',
'v8_embedder_string': '-node.16',

##### V8 defaults for Node.js #####

Expand Down
7 changes: 7 additions & 0 deletions deps/v8/include/v8.h
Original file line number Diff line number Diff line change
Expand Up @@ -1703,6 +1703,13 @@ class V8_EXPORT ScriptCompiler {
CompileOptions options = kNoCompileOptions,
NoCacheReason no_cache_reason = kNoCacheNoReason);

static V8_WARN_UNUSED_RESULT MaybeLocal<Function> CompileFunctionInContext(
Local<Context> context, Source* source, size_t arguments_count,
Local<String> arguments[], size_t context_extension_count,
Local<Object> context_extensions[], CompileOptions options,
NoCacheReason no_cache_reason,
Local<ScriptOrModule>* script_or_module_out);

/**
* Creates and returns code cache for the specified unbound_script.
* This will return nullptr if the script cannot be serialized. The
Expand Down
133 changes: 78 additions & 55 deletions deps/v8/src/api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2500,69 +2500,92 @@ MaybeLocal<Function> ScriptCompiler::CompileFunctionInContext(
Local<String> arguments[], size_t context_extension_count,
Local<Object> context_extensions[], CompileOptions options,
NoCacheReason no_cache_reason) {
PREPARE_FOR_EXECUTION(v8_context, ScriptCompiler, CompileFunctionInContext,
Function);
TRACE_EVENT_CALL_STATS_SCOPED(isolate, "v8", "V8.ScriptCompiler");
return ScriptCompiler::CompileFunctionInContext(
v8_context, source, arguments_count, arguments, context_extension_count,
context_extensions, options, no_cache_reason, nullptr);
}

DCHECK(options == CompileOptions::kConsumeCodeCache ||
options == CompileOptions::kEagerCompile ||
options == CompileOptions::kNoCompileOptions);
MaybeLocal<Function> ScriptCompiler::CompileFunctionInContext(
Local<Context> v8_context, Source* source, size_t arguments_count,
Local<String> arguments[], size_t context_extension_count,
Local<Object> context_extensions[], CompileOptions options,
NoCacheReason no_cache_reason,
Local<ScriptOrModule>* script_or_module_out) {
Local<Function> result;

i::Handle<i::Context> context = Utils::OpenHandle(*v8_context);
{
PREPARE_FOR_EXECUTION(v8_context, ScriptCompiler, CompileFunctionInContext,
Function);
TRACE_EVENT_CALL_STATS_SCOPED(isolate, "v8", "V8.ScriptCompiler");

DCHECK(context->IsNativeContext());
i::Handle<i::SharedFunctionInfo> outer_info(
context->empty_function()->shared(), isolate);

i::Handle<i::JSFunction> fun;
i::Handle<i::FixedArray> arguments_list =
isolate->factory()->NewFixedArray(static_cast<int>(arguments_count));
for (int i = 0; i < static_cast<int>(arguments_count); i++) {
i::Handle<i::String> argument = Utils::OpenHandle(*arguments[i]);
if (!IsIdentifier(isolate, argument)) return Local<Function>();
arguments_list->set(i, *argument);
}

for (size_t i = 0; i < context_extension_count; ++i) {
i::Handle<i::JSReceiver> extension =
Utils::OpenHandle(*context_extensions[i]);
if (!extension->IsJSObject()) return Local<Function>();
context = isolate->factory()->NewWithContext(
context,
i::ScopeInfo::CreateForWithScope(
isolate,
context->IsNativeContext()
? i::Handle<i::ScopeInfo>::null()
: i::Handle<i::ScopeInfo>(context->scope_info(), isolate)),
extension);
}
DCHECK(options == CompileOptions::kConsumeCodeCache ||
options == CompileOptions::kEagerCompile ||
options == CompileOptions::kNoCompileOptions);

i::Compiler::ScriptDetails script_details = GetScriptDetails(
isolate, source->resource_name, source->resource_line_offset,
source->resource_column_offset, source->source_map_url,
source->host_defined_options);
i::Handle<i::Context> context = Utils::OpenHandle(*v8_context);

i::ScriptData* script_data = nullptr;
if (options == kConsumeCodeCache) {
DCHECK(source->cached_data);
// ScriptData takes care of pointer-aligning the data.
script_data = new i::ScriptData(source->cached_data->data,
source->cached_data->length);
DCHECK(context->IsNativeContext());

i::Handle<i::FixedArray> arguments_list =
isolate->factory()->NewFixedArray(static_cast<int>(arguments_count));
for (int i = 0; i < static_cast<int>(arguments_count); i++) {
i::Handle<i::String> argument = Utils::OpenHandle(*arguments[i]);
if (!IsIdentifier(isolate, argument)) return Local<Function>();
arguments_list->set(i, *argument);
}

for (size_t i = 0; i < context_extension_count; ++i) {
i::Handle<i::JSReceiver> extension =
Utils::OpenHandle(*context_extensions[i]);
if (!extension->IsJSObject()) return Local<Function>();
context = isolate->factory()->NewWithContext(
context,
i::ScopeInfo::CreateForWithScope(
isolate,
context->IsNativeContext()
? i::Handle<i::ScopeInfo>::null()
: i::Handle<i::ScopeInfo>(context->scope_info(), isolate)),
extension);
}

i::Compiler::ScriptDetails script_details = GetScriptDetails(
isolate, source->resource_name, source->resource_line_offset,
source->resource_column_offset, source->source_map_url,
source->host_defined_options);

i::ScriptData* script_data = nullptr;
if (options == kConsumeCodeCache) {
DCHECK(source->cached_data);
// ScriptData takes care of pointer-aligning the data.
script_data = new i::ScriptData(source->cached_data->data,
source->cached_data->length);
}

i::Handle<i::JSFunction> scoped_result;
has_pending_exception =
!i::Compiler::GetWrappedFunction(
Utils::OpenHandle(*source->source_string), arguments_list, context,
script_details, source->resource_options, script_data, options,
no_cache_reason)
.ToHandle(&scoped_result);
if (options == kConsumeCodeCache) {
source->cached_data->rejected = script_data->rejected();
}
delete script_data;
RETURN_ON_FAILED_EXECUTION(Function);
result = handle_scope.Escape(Utils::CallableToLocal(scoped_result));
}

i::Handle<i::JSFunction> result;
has_pending_exception =
!i::Compiler::GetWrappedFunction(
Utils::OpenHandle(*source->source_string), arguments_list, context,
script_details, source->resource_options, script_data, options,
no_cache_reason)
.ToHandle(&result);
if (options == kConsumeCodeCache) {
source->cached_data->rejected = script_data->rejected();
if (script_or_module_out != nullptr) {
i::Handle<i::JSFunction> function =
i::Handle<i::JSFunction>::cast(Utils::OpenHandle(*result));
i::Isolate* isolate = function->GetIsolate();
i::Handle<i::SharedFunctionInfo> shared(function->shared(), isolate);
i::Handle<i::Script> script(i::Script::cast(shared->script()), isolate);
*script_or_module_out = v8::Utils::ScriptOrModuleToLocal(script);
}
delete script_data;
RETURN_ON_FAILED_EXECUTION(Function);
RETURN_ESCAPED(Utils::CallableToLocal(result));

return result;
}

void ScriptCompiler::ScriptStreamingTask::Run() { data_->task->Run(); }
Expand Down
9 changes: 7 additions & 2 deletions deps/v8/test/cctest/test-compiler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -647,11 +647,16 @@ TEST(CompileFunctionInContextScriptOrigin) {
v8::Integer::New(CcTest::isolate(), 22),
v8::Integer::New(CcTest::isolate(), 41));
v8::ScriptCompiler::Source script_source(v8_str("throw new Error()"), origin);
Local<ScriptOrModule> script;
v8::Local<v8::Function> fun =
v8::ScriptCompiler::CompileFunctionInContext(env.local(), &script_source,
0, nullptr, 0, nullptr)
v8::ScriptCompiler::CompileFunctionInContext(
env.local(), &script_source, 0, nullptr, 0, nullptr,
v8::ScriptCompiler::CompileOptions::kNoCompileOptions,
v8::ScriptCompiler::NoCacheReason::kNoCacheNoReason, &script)
.ToLocalChecked();
CHECK(!fun.IsEmpty());
CHECK(!script.IsEmpty());
CHECK(script->GetResourceName()->StrictEquals(v8_str("test")));
v8::TryCatch try_catch(CcTest::isolate());
CcTest::isolate()->SetCaptureStackTraceForUncaughtExceptions(true);
CHECK(fun->Call(env.local(), env->Global(), 0, nullptr).IsEmpty());
Expand Down

0 comments on commit 674d33c

Please sign in to comment.