@@ -42,11 +42,9 @@ using v8::Local;
42
42
using v8::MaybeLocal;
43
43
using v8::Number;
44
44
using v8::Object;
45
- using v8::ObjectTemplate;
46
45
using v8::Promise;
47
46
using v8::PromiseHookType;
48
47
using v8::PropertyAttribute;
49
- using v8::PropertyCallbackInfo;
50
48
using v8::ReadOnly;
51
49
using v8::String;
52
50
using v8::Uint32;
@@ -173,59 +171,6 @@ void AsyncWrap::EmitAfter(Environment* env, double async_id) {
173
171
env->async_hooks_after_function ());
174
172
}
175
173
176
- class PromiseWrap : public AsyncWrap {
177
- public:
178
- enum InternalFields {
179
- kIsChainedPromiseField = AsyncWrap::kInternalFieldCount ,
180
- kInternalFieldCount
181
- };
182
- PromiseWrap (Environment* env, Local<Object> object, bool silent)
183
- : AsyncWrap(env, object, PROVIDER_PROMISE, kInvalidAsyncId , silent) {
184
- MakeWeak ();
185
- }
186
-
187
- SET_NO_MEMORY_INFO ()
188
- SET_MEMORY_INFO_NAME (PromiseWrap)
189
- SET_SELF_SIZE (PromiseWrap)
190
-
191
- static PromiseWrap* New (Environment* env,
192
- Local<Promise> promise,
193
- PromiseWrap* parent_wrap,
194
- bool silent);
195
- static void getIsChainedPromise (Local<String> property,
196
- const PropertyCallbackInfo<Value>& info);
197
- };
198
-
199
- PromiseWrap* PromiseWrap::New (Environment* env,
200
- Local<Promise> promise,
201
- PromiseWrap* parent_wrap,
202
- bool silent) {
203
- Local<Object> obj;
204
- if (!env->promise_wrap_template ()->NewInstance (env->context ()).ToLocal (&obj))
205
- return nullptr ;
206
- obj->SetInternalField (PromiseWrap::kIsChainedPromiseField ,
207
- parent_wrap != nullptr ? v8::True (env->isolate ())
208
- : v8::False (env->isolate ()));
209
- CHECK_NULL (promise->GetAlignedPointerFromInternalField (0 ));
210
- promise->SetInternalField (0 , obj);
211
- return new PromiseWrap (env, obj, silent);
212
- }
213
-
214
- void PromiseWrap::getIsChainedPromise (Local<String> property,
215
- const PropertyCallbackInfo<Value>& info) {
216
- info.GetReturnValue ().Set (
217
- info.Holder ()->GetInternalField (PromiseWrap::kIsChainedPromiseField ));
218
- }
219
-
220
- static PromiseWrap* extractPromiseWrap (Local<Promise> promise) {
221
- // This check is imperfect. If the internal field is set, it should
222
- // be an object. If it's not, we just ignore it. Ideally v8 would
223
- // have had GetInternalField returning a MaybeLocal but this works
224
- // for now.
225
- Local<Value> obj = promise->GetInternalField (0 );
226
- return obj->IsObject () ? Unwrap<PromiseWrap>(obj.As <Object>()) : nullptr ;
227
- }
228
-
229
174
static void PromiseHook (PromiseHookType type, Local<Promise> promise,
230
175
Local<Value> parent) {
231
176
Local<Context> context = promise->CreationContext ();
@@ -235,50 +180,14 @@ static void PromiseHook(PromiseHookType type, Local<Promise> promise,
235
180
TraceEventScope trace_scope (TRACING_CATEGORY_NODE1 (environment),
236
181
" EnvPromiseHook" , env);
237
182
238
- PromiseWrap* wrap = extractPromiseWrap (promise);
239
- if (type == PromiseHookType::kInit || wrap == nullptr ) {
240
- bool silent = type != PromiseHookType::kInit ;
241
-
242
- // set parent promise's async Id as this promise's triggerAsyncId
243
- if (parent->IsPromise ()) {
244
- // parent promise exists, current promise
245
- // is a chained promise, so we set parent promise's id as
246
- // current promise's triggerAsyncId
247
- Local<Promise> parent_promise = parent.As <Promise>();
248
- PromiseWrap* parent_wrap = extractPromiseWrap (parent_promise);
249
- if (parent_wrap == nullptr ) {
250
- parent_wrap = PromiseWrap::New (env, parent_promise, nullptr , true );
251
- if (parent_wrap == nullptr ) return ;
252
- }
253
-
254
- AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope (parent_wrap);
255
- wrap = PromiseWrap::New (env, promise, parent_wrap, silent);
256
- } else {
257
- wrap = PromiseWrap::New (env, promise, nullptr , silent);
258
- }
259
- }
183
+ Local<Value> argv[] = {
184
+ env->isolate_data ()->promise_hook_type (static_cast <int >(type)),
185
+ promise,
186
+ parent
187
+ };
260
188
261
- if (wrap == nullptr ) return ;
262
-
263
- if (type == PromiseHookType::kBefore ) {
264
- env->async_hooks ()->push_async_context (wrap->get_async_id (),
265
- wrap->get_trigger_async_id (), wrap->object ());
266
- wrap->EmitTraceEventBefore ();
267
- AsyncWrap::EmitBefore (wrap->env (), wrap->get_async_id ());
268
- } else if (type == PromiseHookType::kAfter ) {
269
- wrap->EmitTraceEventAfter (wrap->provider_type (), wrap->get_async_id ());
270
- AsyncWrap::EmitAfter (wrap->env (), wrap->get_async_id ());
271
- if (env->execution_async_id () == wrap->get_async_id ()) {
272
- // This condition might not be true if async_hooks was enabled during
273
- // the promise callback execution.
274
- // Popping it off the stack can be skipped in that case, because it is
275
- // known that it would correspond to exactly one call with
276
- // PromiseHookType::kBefore that was not witnessed by the PromiseHook.
277
- env->async_hooks ()->pop_async_context (wrap->get_async_id ());
278
- }
279
- } else if (type == PromiseHookType::kResolve ) {
280
- AsyncWrap::EmitPromiseResolve (wrap->env (), wrap->get_async_id ());
281
- }
189
+ Local<Function> promise_hook = env->promise_hook_handler ();
190
+ USE (promise_hook->Call (context, Undefined (env->isolate ()), 3 , argv));
282
191
}
283
192
284
193
@@ -310,23 +219,18 @@ static void SetupHooks(const FunctionCallbackInfo<Value>& args) {
310
219
SET_HOOK_FN (destroy);
311
220
SET_HOOK_FN (promise_resolve);
312
221
#undef SET_HOOK_FN
222
+ }
313
223
314
- {
315
- Local<FunctionTemplate> ctor =
316
- FunctionTemplate::New (env->isolate ());
317
- ctor->SetClassName (FIXED_ONE_BYTE_STRING (env->isolate (), " PromiseWrap" ));
318
- Local<ObjectTemplate> promise_wrap_template = ctor->InstanceTemplate ();
319
- promise_wrap_template->SetInternalFieldCount (
320
- PromiseWrap::kInternalFieldCount );
321
- promise_wrap_template->SetAccessor (
322
- FIXED_ONE_BYTE_STRING (env->isolate (), " isChainedPromise" ),
323
- PromiseWrap::getIsChainedPromise);
324
- env->set_promise_wrap_template (promise_wrap_template);
224
+ static void EnablePromiseHook (const FunctionCallbackInfo<Value>& args) {
225
+ Environment* env = Environment::GetCurrent (args);
226
+
227
+ if (!args[0 ]->IsFunction ()) {
228
+ return node::THROW_ERR_INVALID_ARG_TYPE (
229
+ env, " handler must be a function" );
325
230
}
326
- }
327
231
232
+ env->set_promise_hook_handler (args[0 ].As <Function>());
328
233
329
- static void EnablePromiseHook (const FunctionCallbackInfo<Value>& args) {
330
234
args.GetIsolate ()->SetPromiseHook (PromiseHook);
331
235
}
332
236
0 commit comments