0
0
mirror of https://github.com/nodejs/node.git synced 2024-12-01 16:10:02 +01:00

src: provide a variant of LoadEnvironment taking a callback

This allows embedders to flexibly control how they start JS code
rather than using `third_party_main`.

PR-URL: https://github.com/nodejs/node/pull/30467
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Gireesh Punathil <gpunathi@in.ibm.com>
This commit is contained in:
Anna Henningsen 2019-11-13 15:54:57 +00:00
parent a9fb51f9be
commit c44edec4da
No known key found for this signature in database
GPG Key ID: A94130F0BFC8EBE9
6 changed files with 77 additions and 20 deletions

View File

@ -422,11 +422,12 @@ NODE_EXTERN std::unique_ptr<InspectorParentHandle> GetInspectorParentHandle(
}
void LoadEnvironment(Environment* env) {
USE(LoadEnvironment(env, {}));
USE(LoadEnvironment(env, nullptr, {}));
}
MaybeLocal<Value> LoadEnvironment(
Environment* env,
StartExecutionCallback cb,
std::unique_ptr<InspectorParentHandle> inspector_parent_handle) {
env->InitializeLibuv(per_process::v8_is_profiling);
env->InitializeDiagnostics();
@ -441,9 +442,7 @@ MaybeLocal<Value> LoadEnvironment(
}
#endif
// TODO(joyeecheung): Allow embedders to customize the entry
// point more directly without using _third_party_main.js
return StartExecution(env);
return StartExecution(env, cb);
}
Environment* GetCurrentEnvironment(Local<Context> context) {

View File

@ -372,6 +372,7 @@ void MarkBootstrapComplete(const FunctionCallbackInfo<Value>& args) {
performance::NODE_PERFORMANCE_MILESTONE_BOOTSTRAP_COMPLETE);
}
static
MaybeLocal<Value> StartExecution(Environment* env, const char* main_script_id) {
EscapableHandleScope scope(env->isolate());
CHECK_NOT_NULL(main_script_id);
@ -392,17 +393,31 @@ MaybeLocal<Value> StartExecution(Environment* env, const char* main_script_id) {
->GetFunction(env->context())
.ToLocalChecked()};
return scope.EscapeMaybe(
ExecuteBootstrapper(env, main_script_id, &parameters, &arguments));
}
MaybeLocal<Value> StartExecution(Environment* env, StartExecutionCallback cb) {
InternalCallbackScope callback_scope(
env,
Object::New(env->isolate()),
{ 1, 0 },
InternalCallbackScope::kSkipAsyncHooks);
return scope.EscapeMaybe(
ExecuteBootstrapper(env, main_script_id, &parameters, &arguments));
if (cb != nullptr) {
EscapableHandleScope scope(env->isolate());
if (StartExecution(env, "internal/bootstrap/environment").IsEmpty())
return {};
StartExecutionCallbackInfo info = {
env->process_object(),
env->native_module_require(),
};
return scope.EscapeMaybe(cb(info));
}
MaybeLocal<Value> StartExecution(Environment* env) {
// To allow people to extend Node in different ways, this hook allows
// one to drop a file lib/_third_party_main.js into the build
// directory which will be executed instead of Node's normal loading.

View File

@ -73,6 +73,7 @@
#include "node_version.h" // NODE_MODULE_VERSION
#include <memory>
#include <functional>
// We cannot use __POSIX__ in this header because that's only defined when
// building Node.js.
@ -438,12 +439,20 @@ NODE_EXTERN std::unique_ptr<InspectorParentHandle> GetInspectorParentHandle(
ThreadId child_thread_id,
const char* child_url);
// TODO(addaleax): Deprecate this in favour of the MaybeLocal<> overload
// and provide a more flexible approach than third_party_main.
struct StartExecutionCallbackInfo {
v8::Local<v8::Object> process_object;
v8::Local<v8::Function> native_require;
};
using StartExecutionCallback =
std::function<v8::MaybeLocal<v8::Value>(const StartExecutionCallbackInfo&)>;
// TODO(addaleax): Deprecate this in favour of the MaybeLocal<> overload.
NODE_EXTERN void LoadEnvironment(Environment* env);
NODE_EXTERN v8::MaybeLocal<v8::Value> LoadEnvironment(
Environment* env,
std::unique_ptr<InspectorParentHandle> inspector_parent_handle);
StartExecutionCallback cb,
std::unique_ptr<InspectorParentHandle> inspector_parent_handle = {});
NODE_EXTERN void FreeEnvironment(Environment* env);
// This may return nullptr if context is not associated with a Node instance.

View File

@ -298,9 +298,10 @@ void DefineZlibConstants(v8::Local<v8::Object> target);
v8::Isolate* NewIsolate(v8::Isolate::CreateParams* params,
uv_loop_t* event_loop,
MultiIsolatePlatform* platform);
v8::MaybeLocal<v8::Value> StartExecution(Environment* env);
// This overload automatically picks the right 'main_script_id' if no callback
// was provided by the embedder.
v8::MaybeLocal<v8::Value> StartExecution(Environment* env,
const char* main_script_id);
StartExecutionCallback cb = nullptr);
v8::MaybeLocal<v8::Object> GetPerContextExports(v8::Local<v8::Context> context);
v8::MaybeLocal<v8::Value> ExecuteBootstrapper(
Environment* env,

View File

@ -323,6 +323,7 @@ void Worker::Run() {
CreateEnvMessagePort(env_.get());
Debug(this, "Created message port for worker %llu", thread_id_.id);
if (LoadEnvironment(env_.get(),
nullptr,
std::move(inspector_parent_handle_))
.IsEmpty()) {
return;

View File

@ -51,6 +51,35 @@ class EnvironmentTest : public EnvironmentTestFixture {
// CHECK(result->IsString());
// }
TEST_F(EnvironmentTest, LoadEnvironmentWithCallback) {
const v8::HandleScope handle_scope(isolate_);
const Argv argv;
Env env {handle_scope, argv};
v8::Local<v8::Context> context = isolate_->GetCurrentContext();
bool called_cb = false;
node::LoadEnvironment(*env,
[&](const node::StartExecutionCallbackInfo& info)
-> v8::MaybeLocal<v8::Value> {
called_cb = true;
CHECK(info.process_object->IsObject());
CHECK(info.native_require->IsFunction());
v8::Local<v8::Value> argv0 = info.process_object->Get(
context,
v8::String::NewFromOneByte(
isolate_,
reinterpret_cast<const uint8_t*>("argv0"),
v8::NewStringType::kNormal).ToLocalChecked()).ToLocalChecked();
CHECK(argv0->IsString());
return info.process_object;
});
CHECK(called_cb);
}
TEST_F(EnvironmentTest, AtExitWithEnvironment) {
const v8::HandleScope handle_scope(isolate_);
const Argv argv;
@ -188,9 +217,6 @@ static void at_exit_js(void* arg) {
called_at_exit_js = true;
}
// TODO(addaleax): Re-enable this test once it is possible to initialize the
// Environment properly.
/*
TEST_F(EnvironmentTest, SetImmediateCleanup) {
int called = 0;
int called_unref = 0;
@ -200,6 +226,12 @@ TEST_F(EnvironmentTest, SetImmediateCleanup) {
const Argv argv;
Env env {handle_scope, argv};
node::LoadEnvironment(*env,
[&](const node::StartExecutionCallbackInfo& info)
-> v8::MaybeLocal<v8::Value> {
return v8::Object::New(isolate_);
});
(*env)->SetImmediate([&](node::Environment* env_arg) {
EXPECT_EQ(env_arg, *env);
called++;
@ -212,7 +244,7 @@ TEST_F(EnvironmentTest, SetImmediateCleanup) {
EXPECT_EQ(called, 1);
EXPECT_EQ(called_unref, 0);
}*/
}
static char hello[] = "hello";