@@ -9,8 +9,11 @@ using v8::Context;
99using v8::HandleScope;
1010using v8::Integer;
1111using v8::Isolate;
12+ using v8::Just;
1213using v8::Local;
14+ using v8::Maybe;
1315using v8::NewStringType;
16+ using v8::Nothing;
1417using v8::Object;
1518using v8::String;
1619using v8::Value;
@@ -30,6 +33,10 @@ void AtExit(Environment* env, void (*cb)(void* arg), void* arg) {
3033}
3134
3235void EmitBeforeExit (Environment* env) {
36+ USE (EmitProcessBeforeExit (env));
37+ }
38+
39+ Maybe<bool > EmitProcessBeforeExit (Environment* env) {
3340 TraceEventScope trace_scope (TRACING_CATEGORY_NODE1 (environment),
3441 " BeforeExit" , env);
3542 if (!env->destroy_async_id_list ()->empty ())
@@ -40,39 +47,49 @@ void EmitBeforeExit(Environment* env) {
4047
4148 Local<Value> exit_code_v;
4249 if (!env->process_object ()->Get (env->context (), env->exit_code_string ())
43- .ToLocal (&exit_code_v)) return ;
50+ .ToLocal (&exit_code_v)) return Nothing< bool >() ;
4451
4552 Local<Integer> exit_code;
46- if (!exit_code_v->ToInteger (env->context ()).ToLocal (&exit_code)) return ;
53+ if (!exit_code_v->ToInteger (env->context ()).ToLocal (&exit_code)) {
54+ return Nothing<bool >();
55+ }
4756
48- // TODO(addaleax): Provide variants of EmitExit() and EmitBeforeExit() that
49- // actually forward empty MaybeLocal<>s (and check env->can_call_into_js()).
50- USE (ProcessEmit (env, " beforeExit" , exit_code));
57+ return ProcessEmit (env, " beforeExit" , exit_code).IsEmpty () ?
58+ Nothing<bool >() : Just (true );
5159}
5260
5361int EmitExit (Environment* env) {
62+ return EmitProcessExit (env).FromMaybe (1 );
63+ }
64+
65+ Maybe<int > EmitProcessExit (Environment* env) {
5466 // process.emit('exit')
5567 HandleScope handle_scope (env->isolate ());
5668 Context::Scope context_scope (env->context ());
5769 Local<Object> process_object = env->process_object ();
58- process_object
70+
71+ // TODO(addaleax): It might be nice to share process._exiting and
72+ // process.exitCode via getter/setter pairs that pass data directly to the
73+ // native side, so that we don't manually have to read and write JS properties
74+ // here. These getters could use e.g. a typed array for performance.
75+ if (process_object
5976 ->Set (env->context (),
6077 FIXED_ONE_BYTE_STRING (env->isolate (), " _exiting" ),
61- True (env->isolate ()))
62- .Check ();
78+ True (env->isolate ())).IsNothing ()) return Nothing<int >();
6379
6480 Local<String> exit_code = env->exit_code_string ();
65- int code = process_object->Get (env->context (), exit_code)
66- .ToLocalChecked ()
67- ->Int32Value (env->context ())
68- .ToChecked ();
69- ProcessEmit (env, " exit" , Integer::New (env->isolate (), code));
70-
71- // Reload exit code, it may be changed by `emit('exit')`
72- return process_object->Get (env->context (), exit_code)
73- .ToLocalChecked ()
74- ->Int32Value (env->context ())
75- .ToChecked ();
81+ Local<Value> code_v;
82+ int code;
83+ if (!process_object->Get (env->context (), exit_code).ToLocal (&code_v) ||
84+ !code_v->Int32Value (env->context ()).To (&code) ||
85+ ProcessEmit (env, " exit" , Integer::New (env->isolate (), code)).IsEmpty () ||
86+ // Reload exit code, it may be changed by `emit('exit')`
87+ !process_object->Get (env->context (), exit_code).ToLocal (&code_v) ||
88+ !code_v->Int32Value (env->context ()).To (&code)) {
89+ return Nothing<int >();
90+ }
91+
92+ return Just (code);
7693}
7794
7895typedef void (*CleanupHook)(void * arg);
0 commit comments