11cb0ef41Sopenharmony_ci#include "node_sea.h" 21cb0ef41Sopenharmony_ci 31cb0ef41Sopenharmony_ci#include "env-inl.h" 41cb0ef41Sopenharmony_ci#include "node_external_reference.h" 51cb0ef41Sopenharmony_ci#include "node_internals.h" 61cb0ef41Sopenharmony_ci#include "node_union_bytes.h" 71cb0ef41Sopenharmony_ci#include "simdutf.h" 81cb0ef41Sopenharmony_ci#include "v8.h" 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_ci// The POSTJECT_SENTINEL_FUSE macro is a string of random characters selected by 111cb0ef41Sopenharmony_ci// the Node.js project that is present only once in the entire binary. It is 121cb0ef41Sopenharmony_ci// used by the postject_has_resource() function to efficiently detect if a 131cb0ef41Sopenharmony_ci// resource has been injected. See 141cb0ef41Sopenharmony_ci// https://github.com/nodejs/postject/blob/35343439cac8c488f2596d7c4c1dddfec1fddcae/postject-api.h#L42-L45. 151cb0ef41Sopenharmony_ci#define POSTJECT_SENTINEL_FUSE "NODE_JS_FUSE_fce680ab2cc467b6e072b8b5df1996b2" 161cb0ef41Sopenharmony_ci#include "postject-api.h" 171cb0ef41Sopenharmony_ci#undef POSTJECT_SENTINEL_FUSE 181cb0ef41Sopenharmony_ci 191cb0ef41Sopenharmony_ci#include <memory> 201cb0ef41Sopenharmony_ci#include <string_view> 211cb0ef41Sopenharmony_ci#include <tuple> 221cb0ef41Sopenharmony_ci#include <vector> 231cb0ef41Sopenharmony_ci 241cb0ef41Sopenharmony_ci#if !defined(DISABLE_SINGLE_EXECUTABLE_APPLICATION) 251cb0ef41Sopenharmony_ci 261cb0ef41Sopenharmony_ciusing v8::Context; 271cb0ef41Sopenharmony_ciusing v8::FunctionCallbackInfo; 281cb0ef41Sopenharmony_ciusing v8::Local; 291cb0ef41Sopenharmony_ciusing v8::Object; 301cb0ef41Sopenharmony_ciusing v8::Value; 311cb0ef41Sopenharmony_ci 321cb0ef41Sopenharmony_cinamespace { 331cb0ef41Sopenharmony_ci 341cb0ef41Sopenharmony_ciconst std::string_view FindSingleExecutableCode() { 351cb0ef41Sopenharmony_ci static const std::string_view sea_code = []() -> std::string_view { 361cb0ef41Sopenharmony_ci size_t size; 371cb0ef41Sopenharmony_ci#ifdef __APPLE__ 381cb0ef41Sopenharmony_ci postject_options options; 391cb0ef41Sopenharmony_ci postject_options_init(&options); 401cb0ef41Sopenharmony_ci options.macho_segment_name = "NODE_JS"; 411cb0ef41Sopenharmony_ci const char* code = static_cast<const char*>( 421cb0ef41Sopenharmony_ci postject_find_resource("NODE_JS_CODE", &size, &options)); 431cb0ef41Sopenharmony_ci#else 441cb0ef41Sopenharmony_ci const char* code = static_cast<const char*>( 451cb0ef41Sopenharmony_ci postject_find_resource("NODE_JS_CODE", &size, nullptr)); 461cb0ef41Sopenharmony_ci#endif 471cb0ef41Sopenharmony_ci return {code, size}; 481cb0ef41Sopenharmony_ci }(); 491cb0ef41Sopenharmony_ci return sea_code; 501cb0ef41Sopenharmony_ci} 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_civoid GetSingleExecutableCode(const FunctionCallbackInfo<Value>& args) { 531cb0ef41Sopenharmony_ci node::Environment* env = node::Environment::GetCurrent(args); 541cb0ef41Sopenharmony_ci 551cb0ef41Sopenharmony_ci static const std::string_view sea_code = FindSingleExecutableCode(); 561cb0ef41Sopenharmony_ci 571cb0ef41Sopenharmony_ci if (sea_code.empty()) { 581cb0ef41Sopenharmony_ci return; 591cb0ef41Sopenharmony_ci } 601cb0ef41Sopenharmony_ci 611cb0ef41Sopenharmony_ci // TODO(joyeecheung): Use one-byte strings for ASCII-only source to save 621cb0ef41Sopenharmony_ci // memory/binary size - using UTF16 by default results in twice of the size 631cb0ef41Sopenharmony_ci // than necessary. 641cb0ef41Sopenharmony_ci static const node::UnionBytes sea_code_union_bytes = 651cb0ef41Sopenharmony_ci []() -> node::UnionBytes { 661cb0ef41Sopenharmony_ci size_t expected_u16_length = 671cb0ef41Sopenharmony_ci simdutf::utf16_length_from_utf8(sea_code.data(), sea_code.size()); 681cb0ef41Sopenharmony_ci auto out = std::make_shared<std::vector<uint16_t>>(expected_u16_length); 691cb0ef41Sopenharmony_ci size_t u16_length = simdutf::convert_utf8_to_utf16( 701cb0ef41Sopenharmony_ci sea_code.data(), 711cb0ef41Sopenharmony_ci sea_code.size(), 721cb0ef41Sopenharmony_ci reinterpret_cast<char16_t*>(out->data())); 731cb0ef41Sopenharmony_ci out->resize(u16_length); 741cb0ef41Sopenharmony_ci return node::UnionBytes{out}; 751cb0ef41Sopenharmony_ci }(); 761cb0ef41Sopenharmony_ci 771cb0ef41Sopenharmony_ci args.GetReturnValue().Set( 781cb0ef41Sopenharmony_ci sea_code_union_bytes.ToStringChecked(env->isolate())); 791cb0ef41Sopenharmony_ci} 801cb0ef41Sopenharmony_ci 811cb0ef41Sopenharmony_ci} // namespace 821cb0ef41Sopenharmony_ci 831cb0ef41Sopenharmony_cinamespace node { 841cb0ef41Sopenharmony_cinamespace sea { 851cb0ef41Sopenharmony_ci 861cb0ef41Sopenharmony_cibool IsSingleExecutable() { 871cb0ef41Sopenharmony_ci return postject_has_resource(); 881cb0ef41Sopenharmony_ci} 891cb0ef41Sopenharmony_ci 901cb0ef41Sopenharmony_cistd::tuple<int, char**> FixupArgsForSEA(int argc, char** argv) { 911cb0ef41Sopenharmony_ci // Repeats argv[0] at position 1 on argv as a replacement for the missing 921cb0ef41Sopenharmony_ci // entry point file path. 931cb0ef41Sopenharmony_ci if (IsSingleExecutable()) { 941cb0ef41Sopenharmony_ci static std::vector<char*> new_argv; 951cb0ef41Sopenharmony_ci new_argv.reserve(argc + 2); 961cb0ef41Sopenharmony_ci new_argv.emplace_back(argv[0]); 971cb0ef41Sopenharmony_ci new_argv.insert(new_argv.end(), argv, argv + argc); 981cb0ef41Sopenharmony_ci new_argv.emplace_back(nullptr); 991cb0ef41Sopenharmony_ci argc = new_argv.size() - 1; 1001cb0ef41Sopenharmony_ci argv = new_argv.data(); 1011cb0ef41Sopenharmony_ci } 1021cb0ef41Sopenharmony_ci 1031cb0ef41Sopenharmony_ci return {argc, argv}; 1041cb0ef41Sopenharmony_ci} 1051cb0ef41Sopenharmony_ci 1061cb0ef41Sopenharmony_civoid Initialize(Local<Object> target, 1071cb0ef41Sopenharmony_ci Local<Value> unused, 1081cb0ef41Sopenharmony_ci Local<Context> context, 1091cb0ef41Sopenharmony_ci void* priv) { 1101cb0ef41Sopenharmony_ci SetMethod( 1111cb0ef41Sopenharmony_ci context, target, "getSingleExecutableCode", GetSingleExecutableCode); 1121cb0ef41Sopenharmony_ci} 1131cb0ef41Sopenharmony_ci 1141cb0ef41Sopenharmony_civoid RegisterExternalReferences(ExternalReferenceRegistry* registry) { 1151cb0ef41Sopenharmony_ci registry->Register(GetSingleExecutableCode); 1161cb0ef41Sopenharmony_ci} 1171cb0ef41Sopenharmony_ci 1181cb0ef41Sopenharmony_ci} // namespace sea 1191cb0ef41Sopenharmony_ci} // namespace node 1201cb0ef41Sopenharmony_ci 1211cb0ef41Sopenharmony_ciNODE_BINDING_CONTEXT_AWARE_INTERNAL(sea, node::sea::Initialize) 1221cb0ef41Sopenharmony_ciNODE_BINDING_EXTERNAL_REFERENCE(sea, node::sea::RegisterExternalReferences) 1231cb0ef41Sopenharmony_ci 1241cb0ef41Sopenharmony_ci#endif // !defined(DISABLE_SINGLE_EXECUTABLE_APPLICATION) 125