diff --git a/lib/internal/util.js b/lib/internal/util.js index 80ce774a211644..dfa737695faddd 100644 --- a/lib/internal/util.js +++ b/lib/internal/util.js @@ -54,6 +54,8 @@ const { overrideStackTrace, } = require('internal/errors'); const { signals } = internalBinding('constants').os; +const { getEmbeddedData } = internalBinding('sea'); + const { isArrayBufferDetached: _isArrayBufferDetached, guessHandleType: _guessHandleType, @@ -874,6 +876,7 @@ class WeakReference { } module.exports = { + getEmbeddedData, getLazy, assertCrypto, cachedResult, diff --git a/lib/util.js b/lib/util.js index 9ddb332f866355..f83c6649db179a 100644 --- a/lib/util.js +++ b/lib/util.js @@ -77,6 +77,7 @@ const { promisify, toUSVString, defineLazyProperties, + getEmbeddedData, } = require('internal/util'); let abortController; @@ -384,6 +385,7 @@ module.exports = { formatWithOptions, getSystemErrorMap, getSystemErrorName, + getEmbeddedData, inherits, inspect, isArray: ArrayIsArray, diff --git a/src/node_sea.cc b/src/node_sea.cc index d1ab5051032d76..8efc7c09a20202 100644 --- a/src/node_sea.cc +++ b/src/node_sea.cc @@ -257,6 +257,42 @@ void GetCodeCache(const FunctionCallbackInfo& args) { args.GetReturnValue().Set(data_view); } +#define POSTJECT_SENTINEL_EMBED "NODE_EMBED_fce680ab2cc467b6e072b8b5df1996b2" +static inline bool hasEmbeddedData() { + static const volatile char* sentinel = POSTJECT_SENTINEL_EMBED ":0"; + return sentinel[sizeof(POSTJECT_SENTINEL_EMBED)] == '1'; +} +#undef POSTJECT_SENTINEL_EMBED +void GetEmbeddedData(const FunctionCallbackInfo& args) { + if (!hasEmbeddedData()) { + return; + } + + Isolate* isolate = args.GetIsolate(); + size_t size = 0; +#ifdef __APPLE__ + postject_options options; + postject_options_init(&options); + options.macho_segment_name = "NODE_SEA"; + const void* data = + postject_find_resource("NODE_EMBEDDED_DATA", &size, &options); +#else + const void* data = + postject_find_resource("NODE_EMBEDDED_DATA", &size, nullptr); +#endif + + std::shared_ptr backing_store = ArrayBuffer::NewBackingStore( + const_cast(static_cast(data)), + size, + [](void* /* data */, size_t /* length */, void* /* deleter_data */) { + // The code cache data blob is not freed here because it is a static + // blob which is not allocated by the BackingStore allocator. + }, + nullptr); + Local array_buffer = ArrayBuffer::New(isolate, backing_store); + args.GetReturnValue().Set(array_buffer); +} + void GetCodePath(const FunctionCallbackInfo& args) { DCHECK(IsSingleExecutable()); @@ -558,6 +594,7 @@ void Initialize(Local target, IsExperimentalSeaWarningNeeded); SetMethod(context, target, "getCodePath", GetCodePath); SetMethod(context, target, "getCodeCache", GetCodeCache); + SetMethod(context, target, "getEmbeddedData", GetEmbeddedData); } void RegisterExternalReferences(ExternalReferenceRegistry* registry) { @@ -565,6 +602,7 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) { registry->Register(IsExperimentalSeaWarningNeeded); registry->Register(GetCodePath); registry->Register(GetCodeCache); + registry->Register(GetEmbeddedData); } } // namespace sea