Skip to content

Commit 4a6748d

Browse files
committed
src: add LoadEnvironment() variant taking a string
Allow passing a string as the main module rather than using the callback variant. Backport-PR-URL: #35241 PR-URL: #30467 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Gireesh Punathil <[email protected]>
1 parent c5aa3f4 commit 4a6748d

File tree

10 files changed

+94
-2
lines changed

10 files changed

+94
-2
lines changed

src/api/environment.cc

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,9 @@ NODE_EXTERN std::unique_ptr<InspectorParentHandle> GetInspectorParentHandle(
409409
}
410410

411411
void LoadEnvironment(Environment* env) {
412-
USE(LoadEnvironment(env, nullptr, {}));
412+
USE(LoadEnvironment(env,
413+
StartExecutionCallback{},
414+
{}));
413415
}
414416

415417
MaybeLocal<Value> LoadEnvironment(
@@ -432,6 +434,38 @@ MaybeLocal<Value> LoadEnvironment(
432434
return StartExecution(env, cb);
433435
}
434436

437+
MaybeLocal<Value> LoadEnvironment(
438+
Environment* env,
439+
const char* main_script_source_utf8,
440+
std::unique_ptr<InspectorParentHandle> inspector_parent_handle) {
441+
CHECK_NOT_NULL(main_script_source_utf8);
442+
return LoadEnvironment(
443+
env,
444+
[&](const StartExecutionCallbackInfo& info) -> MaybeLocal<Value> {
445+
// This is a slightly hacky way to convert UTF-8 to UTF-16.
446+
Local<String> str =
447+
String::NewFromUtf8(env->isolate(),
448+
main_script_source_utf8,
449+
v8::NewStringType::kNormal).ToLocalChecked();
450+
auto main_utf16 = std::make_unique<String::Value>(env->isolate(), str);
451+
452+
// TODO(addaleax): Avoid having a global table for all scripts.
453+
std::string name = "embedder_main_" + std::to_string(env->thread_id());
454+
native_module::NativeModuleEnv::Add(
455+
name.c_str(),
456+
UnionBytes(**main_utf16, main_utf16->length()));
457+
env->set_main_utf16(std::move(main_utf16));
458+
std::vector<Local<String>> params = {
459+
env->process_string(),
460+
env->require_string()};
461+
std::vector<Local<Value>> args = {
462+
env->process_object(),
463+
env->native_module_require()};
464+
return ExecuteBootstrapper(env, name.c_str(), &params, &args);
465+
},
466+
std::move(inspector_parent_handle));
467+
}
468+
435469
Environment* GetCurrentEnvironment(Local<Context> context) {
436470
return Environment::GetCurrent(context);
437471
}

src/env-inl.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1216,6 +1216,11 @@ int64_t Environment::base_object_count() const {
12161216
return base_object_count_;
12171217
}
12181218

1219+
void Environment::set_main_utf16(std::unique_ptr<v8::String::Value> str) {
1220+
CHECK(!main_utf16_);
1221+
main_utf16_ = std::move(str);
1222+
}
1223+
12191224
#define VP(PropertyName, StringValue) V(v8::Private, PropertyName)
12201225
#define VY(PropertyName, StringValue) V(v8::Symbol, PropertyName)
12211226
#define VS(PropertyName, StringValue) V(v8::String, PropertyName)

src/env.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1269,6 +1269,8 @@ class Environment : public MemoryRetainer {
12691269
void AddArrayBufferAllocatorToKeepAliveUntilIsolateDispose(
12701270
std::shared_ptr<v8::ArrayBuffer::Allocator>);
12711271

1272+
inline void set_main_utf16(std::unique_ptr<v8::String::Value>);
1273+
12721274
private:
12731275
inline void ThrowError(v8::Local<v8::Value> (*fun)(v8::Local<v8::String>),
12741276
const char* errmsg);
@@ -1435,6 +1437,11 @@ class Environment : public MemoryRetainer {
14351437
#undef V
14361438

14371439
v8::Global<v8::Context> context_;
1440+
1441+
// Keeps the main script source alive is one was passed to LoadEnvironment().
1442+
// We should probably find a way to just use plain `v8::String`s created from
1443+
// the source passed to LoadEnvironment() directly instead.
1444+
std::unique_ptr<v8::String::Value> main_utf16_;
14381445
};
14391446

14401447
} // namespace node

src/node.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,10 @@ NODE_EXTERN v8::MaybeLocal<v8::Value> LoadEnvironment(
432432
Environment* env,
433433
StartExecutionCallback cb,
434434
std::unique_ptr<InspectorParentHandle> inspector_parent_handle = {});
435+
NODE_EXTERN v8::MaybeLocal<v8::Value> LoadEnvironment(
436+
Environment* env,
437+
const char* main_script_source_utf8,
438+
std::unique_ptr<InspectorParentHandle> inspector_parent_handle = {});
435439
NODE_EXTERN void FreeEnvironment(Environment* env);
436440

437441
// This may return nullptr if context is not associated with a Node instance.

src/node_native_module.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,14 @@ bool NativeModuleLoader::Exists(const char* id) {
3030
return source_.find(id) != source_.end();
3131
}
3232

33+
bool NativeModuleLoader::Add(const char* id, const UnionBytes& source) {
34+
if (Exists(id)) {
35+
return false;
36+
}
37+
source_.emplace(id, source);
38+
return true;
39+
}
40+
3341
Local<Object> NativeModuleLoader::GetSourceObject(Local<Context> context) {
3442
Isolate* isolate = context->GetIsolate();
3543
Local<Object> out = Object::New(isolate);

src/node_native_module.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ class NativeModuleLoader {
4747
UnionBytes GetConfig(); // Return data for config.gypi
4848

4949
bool Exists(const char* id);
50+
bool Add(const char* id, const UnionBytes& source);
51+
5052
v8::Local<v8::Object> GetSourceObject(v8::Local<v8::Context> context);
5153
v8::Local<v8::String> GetConfigString(v8::Isolate* isolate);
5254
std::vector<std::string> GetModuleIds();

src/node_native_module_env.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ Local<Set> ToJsSet(Local<Context> context, const std::set<std::string>& in) {
3232
return out;
3333
}
3434

35+
bool NativeModuleEnv::Add(const char* id, const UnionBytes& source) {
36+
return NativeModuleLoader::GetInstance()->Add(id, source);
37+
}
38+
3539
bool NativeModuleEnv::Exists(const char* id) {
3640
return NativeModuleLoader::GetInstance()->Exists(id);
3741
}

src/node_native_module_env.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ class NativeModuleEnv {
2929
// Returns config.gypi as a JSON string
3030
static v8::Local<v8::String> GetConfigString(v8::Isolate* isolate);
3131
static bool Exists(const char* id);
32+
static bool Add(const char* id, const UnionBytes& source);
3233

3334
// Loads data into NativeModuleLoader::.instance.code_cache_
3435
// Generated by mkcodecache as node_code_cache.cc when

src/node_worker.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ void Worker::Run() {
333333
CreateEnvMessagePort(env_.get());
334334
Debug(this, "Created message port for worker %llu", thread_id_.id);
335335
if (LoadEnvironment(env_.get(),
336-
nullptr,
336+
StartExecutionCallback{},
337337
std::move(inspector_parent_handle_))
338338
.IsEmpty()) {
339339
return;

test/cctest/test_environment.cc

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,33 @@ TEST_F(EnvironmentTest, LoadEnvironmentWithCallback) {
8080
CHECK(called_cb);
8181
}
8282

83+
TEST_F(EnvironmentTest, LoadEnvironmentWithSource) {
84+
const v8::HandleScope handle_scope(isolate_);
85+
const Argv argv;
86+
Env env {handle_scope, argv};
87+
88+
v8::Local<v8::Context> context = isolate_->GetCurrentContext();
89+
v8::Local<v8::Value> main_ret =
90+
node::LoadEnvironment(*env,
91+
"return { process, require };").ToLocalChecked();
92+
93+
CHECK(main_ret->IsObject());
94+
CHECK(main_ret.As<v8::Object>()->Get(
95+
context,
96+
v8::String::NewFromOneByte(
97+
isolate_,
98+
reinterpret_cast<const uint8_t*>("process"),
99+
v8::NewStringType::kNormal).ToLocalChecked())
100+
.ToLocalChecked()->IsObject());
101+
CHECK(main_ret.As<v8::Object>()->Get(
102+
context,
103+
v8::String::NewFromOneByte(
104+
isolate_,
105+
reinterpret_cast<const uint8_t*>("require"),
106+
v8::NewStringType::kNormal).ToLocalChecked())
107+
.ToLocalChecked()->IsFunction());
108+
}
109+
83110
TEST_F(EnvironmentTest, AtExitWithEnvironment) {
84111
const v8::HandleScope handle_scope(isolate_);
85112
const Argv argv;

0 commit comments

Comments
 (0)