Skip to content

Commit 8390014

Browse files
joyeecheungBridgeAR
authored andcommitted
process: allow StartExecution() to take a main script ID
The idea is to allow the C++ layer to run arbitrary scripts as the main script. This paves the way for - cctest of the execution of Node.js instances - Earlier handling of per-process CLI options that affect execution modes (those usually do not make sense for the embedders). - Targets like mkcodecache or mksnapshot. Also moves the handling of `_third_party_main.js` into C++. PR-URL: #25474 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Minwoo Jung <minwoo@nodesource.com>
1 parent 28baf26 commit 8390014

13 files changed

+93
-50
lines changed

lib/internal/bootstrap/node.js

+34-20
Original file line numberDiff line numberDiff line change
@@ -317,33 +317,47 @@ function startup() {
317317
} = perf.constants;
318318
perf.markMilestone(NODE_PERFORMANCE_MILESTONE_BOOTSTRAP_COMPLETE);
319319

320-
return startExecution;
320+
if (isMainThread) {
321+
return startMainThreadExecution;
322+
} else {
323+
return startWorkerThreadExecution;
324+
}
325+
}
326+
327+
function startWorkerThreadExecution() {
328+
prepareUserCodeExecution();
329+
330+
// If we are in a worker thread, execute the script sent through the
331+
// message port.
332+
const {
333+
getEnvMessagePort,
334+
threadId
335+
} = internalBinding('worker');
336+
const {
337+
createMessageHandler,
338+
createWorkerFatalExeception
339+
} = NativeModule.require('internal/process/worker_thread_only');
340+
341+
// Set up the message port and start listening
342+
const debug = NativeModule.require('util').debuglog('worker');
343+
debug(`[${threadId}] is setting up worker child environment`);
344+
345+
const port = getEnvMessagePort();
346+
port.on('message', createMessageHandler(port));
347+
port.start();
348+
349+
// Overwrite fatalException
350+
process._fatalException = createWorkerFatalExeception(port);
321351
}
322352

323353
// There are various modes that Node can run in. The most common two
324354
// are running from a script and running the REPL - but there are a few
325355
// others like the debugger or running --eval arguments. Here we decide
326356
// which mode we run in.
327-
function startExecution() {
328-
// This means we are in a Worker context, and any script execution
329-
// will be directed by the worker module.
330-
if (!isMainThread) {
331-
const workerThreadSetup = NativeModule.require(
332-
'internal/process/worker_thread_only'
333-
);
334-
// Set up the message port and start listening
335-
const { workerFatalExeception } = workerThreadSetup.setup();
336-
// Overwrite fatalException
337-
process._fatalException = workerFatalExeception;
338-
return;
339-
}
340-
341-
// To allow people to extend Node in different ways, this hook allows
342-
// one to drop a file lib/_third_party_main.js into the build
343-
// directory which will be executed instead of Node's normal loading.
344-
if (NativeModule.exists('_third_party_main')) {
357+
function startMainThreadExecution(mainScript) {
358+
if (mainScript) {
345359
process.nextTick(() => {
346-
NativeModule.require('_third_party_main');
360+
NativeModule.require(mainScript);
347361
});
348362
return;
349363
}

lib/internal/process/worker_thread_only.js

+2-13
Original file line numberDiff line numberDiff line change
@@ -118,19 +118,8 @@ function createWorkerFatalExeception(port) {
118118
};
119119
}
120120

121-
function setup() {
122-
debug(`[${threadId}] is setting up worker child environment`);
123-
124-
const port = getEnvMessagePort();
125-
port.on('message', createMessageHandler(port));
126-
port.start();
127-
128-
return {
129-
workerFatalExeception: createWorkerFatalExeception(port)
130-
};
131-
}
132-
133121
module.exports = {
134122
initializeWorkerStdio,
135-
setup
123+
createMessageHandler,
124+
createWorkerFatalExeception
136125
};

src/node.cc

+35-3
Original file line numberDiff line numberDiff line change
@@ -647,7 +647,28 @@ static MaybeLocal<Value> ExecuteBootstrapper(
647647

648648
void LoadEnvironment(Environment* env) {
649649
RunBootstrapping(env);
650-
StartExecution(env);
650+
651+
// To allow people to extend Node in different ways, this hook allows
652+
// one to drop a file lib/_third_party_main.js into the build
653+
// directory which will be executed instead of Node's normal loading.
654+
if (per_process::native_module_loader.Exists("_third_party_main")) {
655+
StartExecution(env, "_third_party_main");
656+
} else {
657+
// TODO(joyeecheung): create different scripts for different
658+
// execution modes:
659+
// - `main_thread_main.js` when env->is_main_thread()
660+
// - `worker_thread_main.js` when !env->is_main_thread()
661+
// - `run_third_party_main.js` for `_third_party_main`
662+
// - `inspect_main.js` for `node inspect`
663+
// - `mkcodecache_main.js` for the code cache generator
664+
// - `print_help_main.js` for --help
665+
// - `bash_completion_main.js` for --completion-bash
666+
// - `internal/v8_prof_processor` for --prof-process
667+
// And leave bootstrap/node.js dedicated to the setup of the environment.
668+
// We may want to move this switch out of LoadEnvironment, especially for
669+
// the per-process options.
670+
StartExecution(env, nullptr);
671+
}
651672
}
652673

653674
void RunBootstrapping(Environment* env) {
@@ -724,7 +745,7 @@ void RunBootstrapping(Environment* env) {
724745
env->set_start_execution_function(start_execution.As<Function>());
725746
}
726747

727-
void StartExecution(Environment* env) {
748+
void StartExecution(Environment* env, const char* main_script_id) {
728749
HandleScope handle_scope(env->isolate());
729750
// We have to use Local<>::New because of the optimized way in which we access
730751
// the object in the env->...() getters, which does not play well with
@@ -734,8 +755,19 @@ void StartExecution(Environment* env) {
734755
env->set_start_execution_function(Local<Function>());
735756

736757
if (start_execution.IsEmpty()) return;
758+
759+
Local<Value> main_script_v;
760+
if (main_script_id == nullptr) {
761+
// TODO(joyeecheung): make this mandatory - we may also create an overload
762+
// for main_script that is a Local<Function>.
763+
main_script_v = Undefined(env->isolate());
764+
} else {
765+
main_script_v = OneByteString(env->isolate(), main_script_id);
766+
}
767+
768+
Local<Value> argv[] = {main_script_v};
737769
USE(start_execution->Call(
738-
env->context(), Undefined(env->isolate()), 0, nullptr));
770+
env->context(), Undefined(env->isolate()), arraysize(argv), argv));
739771
}
740772

741773
static void StartInspector(Environment* env, const char* path) {

src/node_internals.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@ bool SafeGetenv(const char* key, std::string* text);
368368
void DefineZlibConstants(v8::Local<v8::Object> target);
369369

370370
void RunBootstrapping(Environment* env);
371-
void StartExecution(Environment* env);
371+
void StartExecution(Environment* env, const char* main_script_id);
372372

373373
} // namespace node
374374

src/node_native_module.cc

+4
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ Local<Set> ToJsSet(Local<Context> context,
6161
return out;
6262
}
6363

64+
bool NativeModuleLoader::Exists(const char* id) {
65+
return source_.find(id) != source_.end();
66+
}
67+
6468
void NativeModuleLoader::GetCacheUsage(
6569
const FunctionCallbackInfo<Value>& args) {
6670
Environment* env = Environment::GetCurrent(args);

src/node_native_module.h

+2
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ class NativeModuleLoader {
5454
std::vector<v8::Local<v8::Value>>* arguments,
5555
Environment* optional_env);
5656

57+
bool Exists(const char* id);
58+
5759
private:
5860
static void GetCacheUsage(const v8::FunctionCallbackInfo<v8::Value>& args);
5961
// Passing map of builtin module source code into JS land as

src/node_worker.cc

+4-2
Original file line numberDiff line numberDiff line change
@@ -185,8 +185,10 @@ void Worker::Run() {
185185
HandleScope handle_scope(isolate_);
186186
Environment::AsyncCallbackScope callback_scope(env_.get());
187187
env_->async_hooks()->push_async_ids(1, 0);
188-
// This loads the Node bootstrapping code.
189-
LoadEnvironment(env_.get());
188+
RunBootstrapping(env_.get());
189+
// TODO(joyeecheung): create a main script for worker threads
190+
// that starts listening on the message port.
191+
StartExecution(env_.get(), nullptr);
190192
env_->async_hooks()->pop_async_id(1);
191193

192194
Debug(this, "Loaded environment for worker %llu", thread_id_);

test/message/error_exit.out

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@ AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
1515
at Function.Module._load (internal/modules/cjs/loader.js:*:*)
1616
at Function.Module.runMain (internal/modules/cjs/loader.js:*:*)
1717
at executeUserCode (internal/bootstrap/node.js:*:*)
18-
at startExecution (internal/bootstrap/node.js:*:*)
18+
at startMainThreadExecution (internal/bootstrap/node.js:*:*)

test/message/eval_messages.out

+4-4
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ SyntaxError: Strict mode code may not include a with statement
1010
at Module._compile (internal/modules/cjs/loader.js:*:*)
1111
at evalScript (internal/process/execution.js:*:*)
1212
at executeUserCode (internal/bootstrap/node.js:*:*)
13-
at startExecution (internal/bootstrap/node.js:*:*)
13+
at startMainThreadExecution (internal/bootstrap/node.js:*:*)
1414
42
1515
42
1616
[eval]:1
@@ -25,7 +25,7 @@ Error: hello
2525
at Module._compile (internal/modules/cjs/loader.js:*:*)
2626
at evalScript (internal/process/execution.js:*:*)
2727
at executeUserCode (internal/bootstrap/node.js:*:*)
28-
at startExecution (internal/bootstrap/node.js:*:*)
28+
at startMainThreadExecution (internal/bootstrap/node.js:*:*)
2929

3030
[eval]:1
3131
throw new Error("hello")
@@ -39,7 +39,7 @@ Error: hello
3939
at Module._compile (internal/modules/cjs/loader.js:*:*)
4040
at evalScript (internal/process/execution.js:*:*)
4141
at executeUserCode (internal/bootstrap/node.js:*:*)
42-
at startExecution (internal/bootstrap/node.js:*:*)
42+
at startMainThreadExecution (internal/bootstrap/node.js:*:*)
4343
100
4444
[eval]:1
4545
var x = 100; y = x;
@@ -53,7 +53,7 @@ ReferenceError: y is not defined
5353
at Module._compile (internal/modules/cjs/loader.js:*:*)
5454
at evalScript (internal/process/execution.js:*:*)
5555
at executeUserCode (internal/bootstrap/node.js:*:*)
56-
at startExecution (internal/bootstrap/node.js:*:*)
56+
at startMainThreadExecution (internal/bootstrap/node.js:*:*)
5757

5858
[eval]:1
5959
var ______________________________________________; throw 10

test/message/events_unhandled_error_common_trace.out

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,4 @@ Emitted 'error' event at:
1919
at Module._compile (internal/modules/cjs/loader.js:*:*)
2020
[... lines matching original stack trace ...]
2121
at executeUserCode (internal/bootstrap/node.js:*:*)
22-
at startExecution (internal/bootstrap/node.js:*:*)
22+
at startMainThreadExecution (internal/bootstrap/node.js:*:*)

test/message/events_unhandled_error_nexttick.out

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ Error
1111
at Function.Module._load (internal/modules/cjs/loader.js:*:*)
1212
at Function.Module.runMain (internal/modules/cjs/loader.js:*:*)
1313
at executeUserCode (internal/bootstrap/node.js:*:*)
14-
at startExecution (internal/bootstrap/node.js:*:*)
14+
at startMainThreadExecution (internal/bootstrap/node.js:*:*)
1515
Emitted 'error' event at:
1616
at process.nextTick (*events_unhandled_error_nexttick.js:*:*)
1717
at processTicksAndRejections (internal/process/next_tick.js:*:*)
1818
at process.runNextTicks [as _tickCallback] (internal/process/next_tick.js:*:*)
1919
at Function.Module.runMain (internal/modules/cjs/loader.js:*:*)
2020
at executeUserCode (internal/bootstrap/node.js:*:*)
21-
at startExecution (internal/bootstrap/node.js:*:*)
21+
at startMainThreadExecution (internal/bootstrap/node.js:*:*)

test/message/events_unhandled_error_sameline.out

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ Error
1111
at Function.Module._load (internal/modules/cjs/loader.js:*:*)
1212
at Function.Module.runMain (internal/modules/cjs/loader.js:*:*)
1313
at executeUserCode (internal/bootstrap/node.js:*:*)
14-
at startExecution (internal/bootstrap/node.js:*:*)
14+
at startMainThreadExecution (internal/bootstrap/node.js:*:*)
1515
Emitted 'error' event at:
1616
at Object.<anonymous> (*events_unhandled_error_sameline.js:*:*)
1717
at Module._compile (internal/modules/cjs/loader.js:*:*)
1818
[... lines matching original stack trace ...]
19-
at startExecution (internal/bootstrap/node.js:*:*)
19+
at startMainThreadExecution (internal/bootstrap/node.js:*:*)

test/message/nexttick_throw.out

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ ReferenceError: undefined_reference_error_maker is not defined
88
at process.runNextTicks [as _tickCallback] (internal/process/next_tick.js:*:*)
99
at Function.Module.runMain (internal/modules/cjs/loader.js:*:*)
1010
at executeUserCode (internal/bootstrap/node.js:*:*)
11-
at startExecution (internal/bootstrap/node.js:*:*)
11+
at startMainThreadExecution (internal/bootstrap/node.js:*:*)

0 commit comments

Comments
 (0)