diff --git a/src/env_properties.h b/src/env_properties.h index 3b9f4c7ed27fb1..d6f45c892133b5 100644 --- a/src/env_properties.h +++ b/src/env_properties.h @@ -389,6 +389,8 @@ V(cipherinfo_detail_template, v8::DictionaryTemplate) \ V(cipherinfo_template, v8::DictionaryTemplate) \ V(cname_record_template, v8::DictionaryTemplate) \ + V(compiled_function_cjs_template, v8::DictionaryTemplate) \ + V(compiled_function_template, v8::DictionaryTemplate) \ V(contextify_global_template, v8::ObjectTemplate) \ V(contextify_wrapper_template, v8::ObjectTemplate) \ V(cpu_usage_template, v8::DictionaryTemplate) \ diff --git a/src/node_contextify.cc b/src/node_contextify.cc index 74279c3ba2566b..e66d4fcb0c064f 100644 --- a/src/node_contextify.cc +++ b/src/node_contextify.cc @@ -45,6 +45,7 @@ using v8::Array; using v8::ArrayBufferView; using v8::Boolean; using v8::Context; +using v8::DictionaryTemplate; using v8::EscapableHandleScope; using v8::Function; using v8::FunctionCallbackInfo; @@ -1088,14 +1089,15 @@ void ContextifyScript::New(const FunctionCallbackInfo& args) { new_cached_data.reset(ScriptCompiler::CreateCodeCache(v8_script)); } + auto self = args.This(); + if (contextify_script->object() ->SetPrivate(context, env->host_defined_option_symbol(), id_symbol) .IsNothing()) { return; } - if (StoreCodeCacheResult(env, - args.This(), + self, compile_options, source, produce_cached_data, @@ -1103,20 +1105,18 @@ void ContextifyScript::New(const FunctionCallbackInfo& args) { .IsNothing()) { return; } - - if (args.This() - ->Set(env->context(), + if (self->Set(env->context(), env->source_url_string(), v8_script->GetSourceURL()) - .IsNothing()) + .IsNothing()) { return; - - if (args.This() - ->Set(env->context(), + } + if (self->Set(env->context(), env->source_map_url_string(), v8_script->GetSourceMappingURL()) - .IsNothing()) + .IsNothing()) { return; + } TRACE_EVENT_END0(TRACING_CATEGORY_NODE2(vm, script), "ContextifyScript::New"); } @@ -1566,25 +1566,35 @@ MaybeLocal ContextifyFunction::CompileFunctionAndCacheResult( return {}; } - Isolate* isolate = env->isolate(); - Local result = Object::New(isolate); - if (result->Set(parsing_context, env->function_string(), fn).IsNothing()) - return {}; - - // ScriptOrigin::ResourceName() returns SourceURL magic comment content if - // present. - if (result - ->Set(parsing_context, - env->source_url_string(), - fn->GetScriptOrigin().ResourceName()) - .IsNothing()) { - return {}; + auto tmpl = env->compiled_function_template(); + if (tmpl.IsEmpty()) { + static constexpr std::string_view names[] = { + "function", + "sourceURL", + "sourceMapURL", + "cachedDataRejected", + "cachedDataProduced", + "cachedData", + }; + tmpl = DictionaryTemplate::New(env->isolate(), names); + env->set_compiled_function_template(tmpl); } - if (result - ->Set(parsing_context, - env->source_map_url_string(), - fn->GetScriptOrigin().SourceMapUrl()) - .IsNothing()) { + + auto scriptOrigin = fn->GetScriptOrigin(); + MaybeLocal values[] = { + fn, + // ScriptOrigin::ResourceName() returns SourceURL magic comment content if + // present. + scriptOrigin.ResourceName(), + scriptOrigin.SourceMapUrl(), + // These are conditionally filled in by StoreCodeCacheResult below. + Undefined(env->isolate()), // cachedDataRejected + Undefined(env->isolate()), // cachedDataProduced + Undefined(env->isolate()), // cachedData + }; + + Local result; + if (!NewDictionaryInstance(env->context(), tmpl, values).ToLocal(&result)) { return {}; } @@ -1799,12 +1809,12 @@ static void CompileFunctionForCJSLoader( // be reparsed as ESM. Utf8Value filename_utf8(isolate, filename); std::string url = url::FromFilePath(filename_utf8.ToStringView()); - Local url_value; - if (!String::NewFromUtf8(isolate, url.c_str()).ToLocal(&url_value)) { + Local url_value; + if (!ToV8Value(context, url).ToLocal(&url_value)) { return; } - can_parse_as_esm = - ShouldRetryAsESM(realm, cjs_message->Get(), code, url_value); + can_parse_as_esm = ShouldRetryAsESM( + realm, cjs_message->Get(), code, url_value.As()); if (!can_parse_as_esm) { // The syntax error is not related to ESM, throw the original error. isolate->ThrowException(cjs_exception); @@ -1827,15 +1837,22 @@ static void CompileFunctionForCJSLoader( } } + auto tmpl = env->compiled_function_cjs_template(); + if (tmpl.IsEmpty()) { + static constexpr std::string_view names[] = { + "cachedDataRejected", + "sourceMapURL", + "sourceURL", + "function", + "canParseAsESM", + }; + tmpl = DictionaryTemplate::New(isolate, names); + env->set_compiled_function_cjs_template(tmpl); + } + Local undefined = v8::Undefined(isolate); - Local names[] = { - env->cached_data_rejected_string(), - env->source_map_url_string(), - env->source_url_string(), - env->function_string(), - FIXED_ONE_BYTE_STRING(isolate, "canParseAsESM"), - }; - Local values[] = { + + MaybeLocal values[] = { Boolean::New(isolate, cache_rejected), fn.IsEmpty() ? undefined : fn->GetScriptOrigin().SourceMapUrl(), // ScriptOrigin::ResourceName() returns SourceURL magic comment content if @@ -1844,9 +1861,10 @@ static void CompileFunctionForCJSLoader( fn.IsEmpty() ? undefined : fn.As(), Boolean::New(isolate, can_parse_as_esm), }; - Local result = Object::New( - isolate, v8::Null(isolate), &names[0], &values[0], arraysize(names)); - args.GetReturnValue().Set(result); + Local result; + if (NewDictionaryInstance(env->context(), tmpl, values).ToLocal(&result)) { + args.GetReturnValue().Set(result); + } } bool ShouldRetryAsESM(Realm* realm,