|
131 | 131 |
|
132 | 132 | namespace node {
|
133 | 133 |
|
| 134 | +using v8::Array; |
| 135 | +using v8::Context; |
134 | 136 | using v8::EscapableHandleScope;
|
| 137 | +using v8::Function; |
135 | 138 | using v8::Isolate;
|
136 | 139 | using v8::Local;
|
137 | 140 | using v8::MaybeLocal;
|
@@ -278,26 +281,65 @@ MaybeLocal<Value> StartExecution(Environment* env, const char* main_script_id) {
|
278 | 281 | return scope.EscapeMaybe(realm->ExecuteBootstrapper(main_script_id));
|
279 | 282 | }
|
280 | 283 |
|
| 284 | +// Convert the result returned by an intermediate main script into |
| 285 | +// StartExecutionCallbackInfo. Currently the result is an array containing |
| 286 | +// [process, requireFunction, cjsRunner] |
| 287 | +std::optional<StartExecutionCallbackInfo> CallbackInfoFromArray( |
| 288 | + Local<Context> context, Local<Value> result) { |
| 289 | + CHECK(result->IsArray()); |
| 290 | + Local<Array> args = result.As<Array>(); |
| 291 | + CHECK_EQ(args->Length(), 3); |
| 292 | + Local<Value> process_obj, require_fn, runcjs_fn; |
| 293 | + if (!args->Get(context, 0).ToLocal(&process_obj) || |
| 294 | + !args->Get(context, 1).ToLocal(&require_fn) || |
| 295 | + !args->Get(context, 2).ToLocal(&runcjs_fn)) { |
| 296 | + return std::nullopt; |
| 297 | + } |
| 298 | + CHECK(process_obj->IsObject()); |
| 299 | + CHECK(require_fn->IsFunction()); |
| 300 | + CHECK(runcjs_fn->IsFunction()); |
| 301 | + node::StartExecutionCallbackInfo info{process_obj.As<Object>(), |
| 302 | + require_fn.As<Function>(), |
| 303 | + runcjs_fn.As<Function>()}; |
| 304 | + return info; |
| 305 | +} |
| 306 | + |
281 | 307 | MaybeLocal<Value> StartExecution(Environment* env, StartExecutionCallback cb) {
|
282 | 308 | InternalCallbackScope callback_scope(
|
283 | 309 | env,
|
284 | 310 | Object::New(env->isolate()),
|
285 | 311 | { 1, 0 },
|
286 | 312 | InternalCallbackScope::kSkipAsyncHooks);
|
287 | 313 |
|
| 314 | + // Only snapshot builder or embedder applications set the |
| 315 | + // callback. |
288 | 316 | if (cb != nullptr) {
|
289 | 317 | EscapableHandleScope scope(env->isolate());
|
290 |
| - // TODO(addaleax): pass the callback to the main script more directly, |
291 |
| - // e.g. by making StartExecution(env, builtin) parametrizable |
292 |
| - env->set_embedder_entry_point(std::move(cb)); |
293 |
| - auto reset_entry_point = |
294 |
| - OnScopeLeave([&]() { env->set_embedder_entry_point({}); }); |
295 | 318 |
|
296 |
| - const char* entry = env->isolate_data()->is_building_snapshot() |
297 |
| - ? "internal/main/mksnapshot" |
298 |
| - : "internal/main/embedding"; |
| 319 | + Local<Value> result; |
| 320 | + if (env->isolate_data()->is_building_snapshot()) { |
| 321 | + if (!StartExecution(env, "internal/main/mksnapshot").ToLocal(&result)) { |
| 322 | + return MaybeLocal<Value>(); |
| 323 | + } |
| 324 | + } else { |
| 325 | + if (!StartExecution(env, "internal/main/embedding").ToLocal(&result)) { |
| 326 | + return MaybeLocal<Value>(); |
| 327 | + } |
| 328 | + } |
| 329 | + |
| 330 | + auto info = CallbackInfoFromArray(env->context(), result); |
| 331 | + if (!info.has_value()) { |
| 332 | + MaybeLocal<Value>(); |
| 333 | + } |
| 334 | +#if HAVE_INSPECTOR |
| 335 | + if (env->options()->debug_options().break_first_line) { |
| 336 | + env->inspector_agent()->PauseOnNextJavascriptStatement("Break on start"); |
| 337 | + } |
| 338 | +#endif |
299 | 339 |
|
300 |
| - return scope.EscapeMaybe(StartExecution(env, entry)); |
| 340 | + env->performance_state()->Mark( |
| 341 | + performance::NODE_PERFORMANCE_MILESTONE_BOOTSTRAP_COMPLETE); |
| 342 | + return scope.EscapeMaybe(cb(info.value())); |
301 | 343 | }
|
302 | 344 |
|
303 | 345 | CHECK(!env->isolate_data()->is_building_snapshot());
|
|
0 commit comments