Skip to content

Commit 4a6c71e

Browse files
committed
src: simplify embedder entry point execution
Previously we wrapped the embedder entry point callback into a binding and then invoke the binding from JS land which was a bit convoluted. Now we just call it directly from C++. The main scripts that needed to tail call the embedder callback now return the arguments in an array so that the C++ land can extract the arguments and pass them to the callback. We also set `PauseOnNextJavascriptStatement()` for --inspect-brk and mark the bootstrap complete milestone directly in C++ for these execution modes.
1 parent 53aed88 commit 4a6c71e

File tree

6 files changed

+54
-60
lines changed

6 files changed

+54
-60
lines changed

lib/internal/main/embedding.js

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
11
'use strict';
22
const {
33
prepareMainThreadExecution,
4-
markBootstrapComplete,
54
} = require('internal/process/pre_execution');
65
const { isExperimentalSeaWarningNeeded } = internalBinding('sea');
76
const { emitExperimentalWarning } = require('internal/util');
87
const { embedderRequire, embedderRunCjs } = require('internal/util/embedding');
9-
const { runEmbedderEntryPoint } = internalBinding('mksnapshot');
108

119
prepareMainThreadExecution(false, true);
12-
markBootstrapComplete();
1310

1411
if (isExperimentalSeaWarningNeeded()) {
1512
emitExperimentalWarning('Single executable application');
1613
}
1714

18-
return runEmbedderEntryPoint(process, embedderRequire, embedderRunCjs);
15+
return [process, embedderRequire, embedderRunCjs];

lib/internal/main/mksnapshot.js

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ const {
1111

1212
const { BuiltinModule: { normalizeRequirableId } } = require('internal/bootstrap/realm');
1313
const {
14-
runEmbedderEntryPoint,
1514
compileSerializeMain,
1615
anonymousMainPath,
1716
} = internalBinding('mksnapshot');
@@ -20,9 +19,6 @@ const { isExperimentalSeaWarningNeeded } = internalBinding('sea');
2019

2120
const { emitExperimentalWarning } = require('internal/util');
2221
const { emitWarningSync } = require('internal/process/warning');
23-
const {
24-
getOptionValue,
25-
} = require('internal/options');
2622

2723
const {
2824
initializeCallbacks,
@@ -179,18 +175,11 @@ function main() {
179175
return fn(requireForUserSnapshot, filename, dirname);
180176
}
181177

182-
const serializeMainArgs = [process, requireForUserSnapshot, minimalRunCjs];
183-
184178
if (isExperimentalSeaWarningNeeded()) {
185179
emitExperimentalWarning('Single executable application');
186180
}
187181

188-
if (getOptionValue('--inspect-brk')) {
189-
internalBinding('inspector').callAndPauseOnStart(
190-
runEmbedderEntryPoint, undefined, ...serializeMainArgs);
191-
} else {
192-
runEmbedderEntryPoint(...serializeMainArgs);
193-
}
182+
return [process, requireForUserSnapshot, minimalRunCjs];
194183
}
195184

196-
main();
185+
return main();

src/env-inl.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -430,14 +430,6 @@ inline builtins::BuiltinLoader* Environment::builtin_loader() {
430430
return &builtin_loader_;
431431
}
432432

433-
inline const StartExecutionCallback& Environment::embedder_entry_point() const {
434-
return embedder_entry_point_;
435-
}
436-
437-
inline void Environment::set_embedder_entry_point(StartExecutionCallback&& fn) {
438-
embedder_entry_point_ = std::move(fn);
439-
}
440-
441433
inline double Environment::new_async_id() {
442434
async_hooks()->async_id_fields()[AsyncHooks::kAsyncIdCounter] += 1;
443435
return async_hooks()->async_id_fields()[AsyncHooks::kAsyncIdCounter];

src/env.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -999,9 +999,6 @@ class Environment : public MemoryRetainer {
999999

10001000
#endif // HAVE_INSPECTOR
10011001

1002-
inline const StartExecutionCallback& embedder_entry_point() const;
1003-
inline void set_embedder_entry_point(StartExecutionCallback&& fn);
1004-
10051002
inline void set_process_exit_handler(
10061003
std::function<void(Environment*, ExitCode)>&& handler);
10071004

@@ -1207,7 +1204,6 @@ class Environment : public MemoryRetainer {
12071204
std::unique_ptr<PrincipalRealm> principal_realm_ = nullptr;
12081205

12091206
builtins::BuiltinLoader builtin_loader_;
1210-
StartExecutionCallback embedder_entry_point_;
12111207

12121208
// Used by allocate_managed_buffer() and release_managed_buffer() to keep
12131209
// track of the BackingStore for a given pointer.

src/node.cc

Lines changed: 51 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,10 @@
131131

132132
namespace node {
133133

134+
using v8::Array;
135+
using v8::Context;
134136
using v8::EscapableHandleScope;
137+
using v8::Function;
135138
using v8::Isolate;
136139
using v8::Local;
137140
using v8::MaybeLocal;
@@ -282,26 +285,65 @@ MaybeLocal<Value> StartExecution(Environment* env, const char* main_script_id) {
282285
return scope.EscapeMaybe(realm->ExecuteBootstrapper(main_script_id));
283286
}
284287

288+
// Convert the result returned by an intermediate main script into
289+
// StartExecutionCallbackInfo. Currently the result is an array containing
290+
// [process, requireFunction, cjsRunner]
291+
std::optional<StartExecutionCallbackInfo> CallbackInfoFromArray(
292+
Local<Context> context, Local<Value> result) {
293+
CHECK(result->IsArray());
294+
Local<Array> args = result.As<Array>();
295+
CHECK_EQ(args->Length(), 3);
296+
Local<Value> process_obj, require_fn, runcjs_fn;
297+
if (!args->Get(context, 0).ToLocal(&process_obj) ||
298+
!args->Get(context, 1).ToLocal(&require_fn) ||
299+
!args->Get(context, 2).ToLocal(&runcjs_fn)) {
300+
return std::nullopt;
301+
}
302+
CHECK(process_obj->IsObject());
303+
CHECK(require_fn->IsFunction());
304+
CHECK(runcjs_fn->IsFunction());
305+
node::StartExecutionCallbackInfo info{process_obj.As<Object>(),
306+
require_fn.As<Function>(),
307+
runcjs_fn.As<Function>()};
308+
return info;
309+
}
310+
285311
MaybeLocal<Value> StartExecution(Environment* env, StartExecutionCallback cb) {
286312
InternalCallbackScope callback_scope(
287313
env,
288314
Object::New(env->isolate()),
289315
{ 1, 0 },
290316
InternalCallbackScope::kSkipAsyncHooks);
291317

318+
// Only snapshot builder or embedder applications set the
319+
// callback.
292320
if (cb != nullptr) {
293321
EscapableHandleScope scope(env->isolate());
294-
// TODO(addaleax): pass the callback to the main script more directly,
295-
// e.g. by making StartExecution(env, builtin) parametrizable
296-
env->set_embedder_entry_point(std::move(cb));
297-
auto reset_entry_point =
298-
OnScopeLeave([&]() { env->set_embedder_entry_point({}); });
299322

300-
const char* entry = env->isolate_data()->is_building_snapshot()
301-
? "internal/main/mksnapshot"
302-
: "internal/main/embedding";
323+
Local<Value> result;
324+
if (env->isolate_data()->is_building_snapshot()) {
325+
if (!StartExecution(env, "internal/main/mksnapshot").ToLocal(&result)) {
326+
return MaybeLocal<Value>();
327+
}
328+
} else {
329+
if (!StartExecution(env, "internal/main/embedding").ToLocal(&result)) {
330+
return MaybeLocal<Value>();
331+
}
332+
}
333+
334+
auto info = CallbackInfoFromArray(env->context(), result);
335+
if (!info.has_value()) {
336+
MaybeLocal<Value>();
337+
}
338+
#ifdef HAVE_INSPECTOR
339+
if (env->options()->debug_options().break_first_line) {
340+
env->inspector_agent()->PauseOnNextJavascriptStatement("Break on start");
341+
}
342+
#endif
303343

304-
return scope.EscapeMaybe(StartExecution(env, entry));
344+
env->performance_state()->Mark(
345+
performance::NODE_PERFORMANCE_MILESTONE_BOOTSTRAP_COMPLETE);
346+
return scope.EscapeMaybe(cb(info.value()));
305347
}
306348

307349
CHECK(!env->isolate_data()->is_building_snapshot());

src/node_snapshotable.cc

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ using v8::FunctionCallbackInfo;
4040
using v8::HandleScope;
4141
using v8::Isolate;
4242
using v8::Local;
43-
using v8::MaybeLocal;
4443
using v8::Object;
4544
using v8::ObjectTemplate;
4645
using v8::ScriptCompiler;
@@ -1434,25 +1433,6 @@ void SerializeSnapshotableObjects(Realm* realm,
14341433
});
14351434
}
14361435

1437-
static void RunEmbedderEntryPoint(const FunctionCallbackInfo<Value>& args) {
1438-
Environment* env = Environment::GetCurrent(args);
1439-
Local<Value> process_obj = args[0];
1440-
Local<Value> require_fn = args[1];
1441-
Local<Value> runcjs_fn = args[2];
1442-
CHECK(process_obj->IsObject());
1443-
CHECK(require_fn->IsFunction());
1444-
CHECK(runcjs_fn->IsFunction());
1445-
1446-
const node::StartExecutionCallback& callback = env->embedder_entry_point();
1447-
node::StartExecutionCallbackInfo info{process_obj.As<Object>(),
1448-
require_fn.As<Function>(),
1449-
runcjs_fn.As<Function>()};
1450-
MaybeLocal<Value> retval = callback(info);
1451-
if (!retval.IsEmpty()) {
1452-
args.GetReturnValue().Set(retval.ToLocalChecked());
1453-
}
1454-
}
1455-
14561436
void CompileSerializeMain(const FunctionCallbackInfo<Value>& args) {
14571437
CHECK(args[0]->IsString());
14581438
Local<String> filename = args[0].As<String>();
@@ -1576,7 +1556,6 @@ void CreatePerContextProperties(Local<Object> target,
15761556
void CreatePerIsolateProperties(IsolateData* isolate_data,
15771557
Local<ObjectTemplate> target) {
15781558
Isolate* isolate = isolate_data->isolate();
1579-
SetMethod(isolate, target, "runEmbedderEntryPoint", RunEmbedderEntryPoint);
15801559
SetMethod(isolate, target, "compileSerializeMain", CompileSerializeMain);
15811560
SetMethod(isolate, target, "setSerializeCallback", SetSerializeCallback);
15821561
SetMethod(isolate, target, "setDeserializeCallback", SetDeserializeCallback);
@@ -1589,7 +1568,6 @@ void CreatePerIsolateProperties(IsolateData* isolate_data,
15891568
}
15901569

15911570
void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
1592-
registry->Register(RunEmbedderEntryPoint);
15931571
registry->Register(CompileSerializeMain);
15941572
registry->Register(SetSerializeCallback);
15951573
registry->Register(SetDeserializeCallback);

0 commit comments

Comments
 (0)