|
28 | 28 | #include "node_errors.h" |
29 | 29 | #include "node_external_reference.h" |
30 | 30 | #include "node_internals.h" |
| 31 | +#include "node_sea.h" |
31 | 32 | #include "node_snapshot_builder.h" |
32 | 33 | #include "node_watchdog.h" |
33 | 34 | #include "util-inl.h" |
@@ -956,6 +957,15 @@ Maybe<bool> StoreCodeCacheResult( |
956 | 957 | return Just(true); |
957 | 958 | } |
958 | 959 |
|
| 960 | +static Local<PrimitiveArray> GetHostDefinedOptions(Isolate* isolate, |
| 961 | + Local<Symbol> id_symbol) { |
| 962 | + Local<PrimitiveArray> host_defined_options = |
| 963 | + PrimitiveArray::New(isolate, loader::HostDefinedOptions::kLength); |
| 964 | + host_defined_options->Set( |
| 965 | + isolate, loader::HostDefinedOptions::kID, id_symbol); |
| 966 | + return host_defined_options; |
| 967 | +} |
| 968 | + |
959 | 969 | // TODO(RaisinTen): Reuse in ContextifyContext::CompileFunction(). |
960 | 970 | MaybeLocal<Function> CompileFunction(Local<Context> context, |
961 | 971 | Local<String> filename, |
@@ -1280,15 +1290,6 @@ void ContextifyContext::CompileFunction( |
1280 | 1290 | args.GetReturnValue().Set(result); |
1281 | 1291 | } |
1282 | 1292 |
|
1283 | | -Local<PrimitiveArray> ContextifyContext::GetHostDefinedOptions( |
1284 | | - Isolate* isolate, Local<Symbol> id_symbol) { |
1285 | | - Local<PrimitiveArray> host_defined_options = |
1286 | | - PrimitiveArray::New(isolate, loader::HostDefinedOptions::kLength); |
1287 | | - host_defined_options->Set( |
1288 | | - isolate, loader::HostDefinedOptions::kID, id_symbol); |
1289 | | - return host_defined_options; |
1290 | | -} |
1291 | | - |
1292 | 1293 | ScriptCompiler::Source ContextifyContext::GetCommonJSSourceInstance( |
1293 | 1294 | Isolate* isolate, |
1294 | 1295 | Local<String> code, |
@@ -1485,6 +1486,102 @@ void ContextifyContext::ContainsModuleSyntax( |
1485 | 1486 | args.GetReturnValue().Set(found_error_message_caused_by_module_syntax); |
1486 | 1487 | } |
1487 | 1488 |
|
| 1489 | +static void CompileFunctionForCJSLoader( |
| 1490 | + const FunctionCallbackInfo<Value>& args) { |
| 1491 | + CHECK(args[0]->IsString()); |
| 1492 | + CHECK(args[1]->IsString()); |
| 1493 | + Local<String> code = args[0].As<String>(); |
| 1494 | + Local<String> filename = args[1].As<String>(); |
| 1495 | + Isolate* isolate = args.GetIsolate(); |
| 1496 | + Local<Context> context = isolate->GetCurrentContext(); |
| 1497 | + Environment* env = Environment::GetCurrent(context); |
| 1498 | + |
| 1499 | + Local<Symbol> symbol = env->vm_dynamic_import_default_internal(); |
| 1500 | + Local<PrimitiveArray> hdo = GetHostDefinedOptions(isolate, symbol); |
| 1501 | + ScriptOrigin origin(isolate, |
| 1502 | + filename, |
| 1503 | + 0, // line offset |
| 1504 | + 0, // column offset |
| 1505 | + true, // is cross origin |
| 1506 | + -1, // script id |
| 1507 | + Local<Value>(), // source map URL |
| 1508 | + false, // is opaque |
| 1509 | + false, // is WASM |
| 1510 | + false, // is ES Module |
| 1511 | + hdo); |
| 1512 | + ScriptCompiler::CachedData* cached_data = nullptr; |
| 1513 | + |
| 1514 | +#ifndef DISABLE_SINGLE_EXECUTABLE_APPLICATION |
| 1515 | + bool used_cache_from_sea = false; |
| 1516 | + if (sea::IsSingleExecutable()) { |
| 1517 | + sea::SeaResource sea = sea::FindSingleExecutableResource(); |
| 1518 | + if (sea.use_code_cache()) { |
| 1519 | + std::string_view data = sea.code_cache.value(); |
| 1520 | + cached_data = new ScriptCompiler::CachedData( |
| 1521 | + reinterpret_cast<const uint8_t*>(data.data()), |
| 1522 | + static_cast<int>(data.size()), |
| 1523 | + v8::ScriptCompiler::CachedData::BufferNotOwned); |
| 1524 | + used_cache_from_sea = true; |
| 1525 | + } |
| 1526 | + } |
| 1527 | +#endif |
| 1528 | + ScriptCompiler::Source source(code, origin, cached_data); |
| 1529 | + |
| 1530 | + TryCatchScope try_catch(env); |
| 1531 | + |
| 1532 | + // TODO(joyeecheung): make it a per-realm persistent. |
| 1533 | + std::vector<Local<String>> params = { |
| 1534 | + FIXED_ONE_BYTE_STRING(isolate, "exports"), |
| 1535 | + FIXED_ONE_BYTE_STRING(isolate, "require"), |
| 1536 | + FIXED_ONE_BYTE_STRING(isolate, "module"), |
| 1537 | + FIXED_ONE_BYTE_STRING(isolate, "__filename"), |
| 1538 | + FIXED_ONE_BYTE_STRING(isolate, "__dirname"), |
| 1539 | + }; |
| 1540 | + MaybeLocal<Function> maybe_fn = ScriptCompiler::CompileFunction( |
| 1541 | + context, |
| 1542 | + &source, |
| 1543 | + params.size(), |
| 1544 | + params.data(), |
| 1545 | + 0, /* context extensions size */ |
| 1546 | + nullptr, /* context extensions data */ |
| 1547 | + // TODO(joyeecheung): allow optional eager compilation. |
| 1548 | + cached_data == nullptr ? ScriptCompiler::kNoCompileOptions |
| 1549 | + : ScriptCompiler::kConsumeCodeCache, |
| 1550 | + v8::ScriptCompiler::NoCacheReason::kNoCacheNoReason); |
| 1551 | + |
| 1552 | + Local<Function> fn; |
| 1553 | + if (!maybe_fn.ToLocal(&fn)) { |
| 1554 | + if (try_catch.HasCaught() && !try_catch.HasTerminated()) { |
| 1555 | + errors::DecorateErrorStack(env, try_catch); |
| 1556 | + if (!try_catch.HasTerminated()) { |
| 1557 | + try_catch.ReThrow(); |
| 1558 | + } |
| 1559 | + return; |
| 1560 | + } |
| 1561 | + } |
| 1562 | + |
| 1563 | + bool cache_rejected = false; |
| 1564 | +#ifndef DISABLE_SINGLE_EXECUTABLE_APPLICATION |
| 1565 | + if (used_cache_from_sea) { |
| 1566 | + cache_rejected = source.GetCachedData()->rejected; |
| 1567 | + } |
| 1568 | +#endif |
| 1569 | + |
| 1570 | + std::vector<Local<Name>> names = { |
| 1571 | + env->cached_data_rejected_string(), |
| 1572 | + env->source_map_url_string(), |
| 1573 | + env->function_string(), |
| 1574 | + }; |
| 1575 | + std::vector<Local<Value>> values = { |
| 1576 | + Boolean::New(isolate, cache_rejected), |
| 1577 | + fn->GetScriptOrigin().SourceMapUrl(), |
| 1578 | + fn, |
| 1579 | + }; |
| 1580 | + Local<Object> result = Object::New( |
| 1581 | + isolate, v8::Null(isolate), names.data(), values.data(), names.size()); |
| 1582 | + args.GetReturnValue().Set(result); |
| 1583 | +} |
| 1584 | + |
1488 | 1585 | static void StartSigintWatchdog(const FunctionCallbackInfo<Value>& args) { |
1489 | 1586 | int ret = SigintWatchdogHelper::GetInstance()->Start(); |
1490 | 1587 | args.GetReturnValue().Set(ret == 0); |
@@ -1537,6 +1634,10 @@ void CreatePerIsolateProperties(IsolateData* isolate_data, |
1537 | 1634 | isolate, target, "watchdogHasPendingSigint", WatchdogHasPendingSigint); |
1538 | 1635 |
|
1539 | 1636 | SetMethod(isolate, target, "measureMemory", MeasureMemory); |
| 1637 | + SetMethod(isolate, |
| 1638 | + target, |
| 1639 | + "compileFunctionForCJSLoader", |
| 1640 | + CompileFunctionForCJSLoader); |
1540 | 1641 | } |
1541 | 1642 |
|
1542 | 1643 | static void CreatePerContextProperties(Local<Object> target, |
@@ -1576,6 +1677,7 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) { |
1576 | 1677 | ContextifyContext::RegisterExternalReferences(registry); |
1577 | 1678 | ContextifyScript::RegisterExternalReferences(registry); |
1578 | 1679 |
|
| 1680 | + registry->Register(CompileFunctionForCJSLoader); |
1579 | 1681 | registry->Register(StartSigintWatchdog); |
1580 | 1682 | registry->Register(StopSigintWatchdog); |
1581 | 1683 | registry->Register(WatchdogHasPendingSigint); |
|
0 commit comments