@@ -9,8 +9,11 @@ using v8::Context;
9
9
using v8::HandleScope;
10
10
using v8::Integer;
11
11
using v8::Isolate;
12
+ using v8::Just;
12
13
using v8::Local;
14
+ using v8::Maybe;
13
15
using v8::NewStringType;
16
+ using v8::Nothing;
14
17
using v8::Object;
15
18
using v8::String;
16
19
using v8::Value;
@@ -30,6 +33,10 @@ void AtExit(Environment* env, void (*cb)(void* arg), void* arg) {
30
33
}
31
34
32
35
void EmitBeforeExit (Environment* env) {
36
+ USE (EmitProcessBeforeExit (env));
37
+ }
38
+
39
+ Maybe<bool > EmitProcessBeforeExit (Environment* env) {
33
40
TraceEventScope trace_scope (TRACING_CATEGORY_NODE1 (environment),
34
41
" BeforeExit" , env);
35
42
if (!env->destroy_async_id_list ()->empty ())
@@ -40,39 +47,49 @@ void EmitBeforeExit(Environment* env) {
40
47
41
48
Local<Value> exit_code_v;
42
49
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 >() ;
44
51
45
52
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
+ }
47
56
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 );
51
59
}
52
60
53
61
int EmitExit (Environment* env) {
62
+ return EmitProcessExit (env).FromMaybe (1 );
63
+ }
64
+
65
+ Maybe<int > EmitProcessExit (Environment* env) {
54
66
// process.emit('exit')
55
67
HandleScope handle_scope (env->isolate ());
56
68
Context::Scope context_scope (env->context ());
57
69
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
59
76
->Set (env->context (),
60
77
FIXED_ONE_BYTE_STRING (env->isolate (), " _exiting" ),
61
- True (env->isolate ()))
62
- .Check ();
78
+ True (env->isolate ())).IsNothing ()) return Nothing<int >();
63
79
64
80
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);
76
93
}
77
94
78
95
typedef void (*CleanupHook)(void * arg);
0 commit comments