@@ -36,6 +36,7 @@ using v8::Context;
36
36
using v8::Float64Array;
37
37
using v8::Function;
38
38
using v8::FunctionCallbackInfo;
39
+ using v8::FunctionTemplate;
39
40
using v8::HandleScope;
40
41
using v8::HeapProfiler;
41
42
using v8::Integer;
@@ -44,8 +45,10 @@ using v8::Local;
44
45
using v8::MaybeLocal;
45
46
using v8::Number;
46
47
using v8::Object;
48
+ using v8::ObjectTemplate;
47
49
using v8::Promise;
48
50
using v8::PromiseHookType;
51
+ using v8::PropertyCallbackInfo;
49
52
using v8::RetainedObjectInfo;
50
53
using v8::String;
51
54
using v8::Symbol;
@@ -282,37 +285,86 @@ bool AsyncWrap::EmitAfter(Environment* env, double async_id) {
282
285
class PromiseWrap : public AsyncWrap {
283
286
public:
284
287
PromiseWrap (Environment* env, Local<Object> object, bool silent)
285
- : AsyncWrap(env, object, PROVIDER_PROMISE, silent) {}
288
+ : AsyncWrap(env, object, PROVIDER_PROMISE, silent) {
289
+ MakeWeak (this );
290
+ }
286
291
size_t self_size () const override { return sizeof (*this ); }
292
+
293
+ static constexpr int kPromiseField = 1 ;
294
+ static constexpr int kParentIdField = 2 ;
295
+ static constexpr int kInternalFieldCount = 3 ;
296
+
297
+ static PromiseWrap* New (Environment* env,
298
+ Local<Promise> promise,
299
+ PromiseWrap* parent_wrap,
300
+ bool silent);
301
+ static void GetPromise (Local<String> property,
302
+ const PropertyCallbackInfo<Value>& info);
303
+ static void GetParentId (Local<String> property,
304
+ const PropertyCallbackInfo<Value>& info);
287
305
};
288
306
307
+ PromiseWrap* PromiseWrap::New (Environment* env,
308
+ Local<Promise> promise,
309
+ PromiseWrap* parent_wrap,
310
+ bool silent) {
311
+ Local<Object> object = env->promise_wrap_template ()
312
+ ->NewInstance (env->context ()).ToLocalChecked ();
313
+ object->SetInternalField (PromiseWrap::kPromiseField , promise);
314
+ if (parent_wrap != nullptr ) {
315
+ object->SetInternalField (PromiseWrap::kParentIdField ,
316
+ Number::New (env->isolate (),
317
+ parent_wrap->get_id ()));
318
+ }
319
+ CHECK_EQ (promise->GetAlignedPointerFromInternalField (0 ), nullptr );
320
+ promise->SetInternalField (0 , object);
321
+ return new PromiseWrap (env, object, silent);
322
+ }
323
+
324
+ void PromiseWrap::GetPromise (Local<String> property,
325
+ const PropertyCallbackInfo<Value>& info) {
326
+ info.GetReturnValue ().Set (info.Holder ()->GetInternalField (kPromiseField ));
327
+ }
328
+
329
+ void PromiseWrap::GetParentId (Local<String> property,
330
+ const PropertyCallbackInfo<Value>& info) {
331
+ info.GetReturnValue ().Set (info.Holder ()->GetInternalField (kParentIdField ));
332
+ }
289
333
290
334
static void PromiseHook (PromiseHookType type, Local<Promise> promise,
291
335
Local<Value> parent, void * arg) {
292
336
Local<Context> context = promise->CreationContext ();
293
337
Environment* env = Environment::GetCurrent (context);
294
- PromiseWrap* wrap = Unwrap<PromiseWrap>(promise);
338
+ Local<Value> resource_object_value = promise->GetInternalField (0 );
339
+ PromiseWrap* wrap = nullptr ;
340
+ if (resource_object_value->IsObject ()) {
341
+ Local<Object> resource_object = resource_object_value.As <Object>();
342
+ wrap = Unwrap<PromiseWrap>(resource_object);
343
+ }
295
344
if (type == PromiseHookType::kInit || wrap == nullptr ) {
296
345
bool silent = type != PromiseHookType::kInit ;
346
+ PromiseWrap* parent_wrap = nullptr ;
347
+
297
348
// set parent promise's async Id as this promise's triggerId
298
349
if (parent->IsPromise ()) {
299
350
// parent promise exists, current promise
300
351
// is a chained promise, so we set parent promise's id as
301
352
// current promise's triggerId
302
353
Local<Promise> parent_promise = parent.As <Promise>();
303
- auto parent_wrap = Unwrap<PromiseWrap>(parent_promise);
354
+ Local<Value> parent_resource = parent_promise->GetInternalField (0 );
355
+ if (parent_resource->IsObject ()) {
356
+ parent_wrap = Unwrap<PromiseWrap>(parent_resource.As <Object>());
357
+ }
304
358
305
359
if (parent_wrap == nullptr ) {
306
- // create a new PromiseWrap for parent promise with silent parameter
307
- parent_wrap = new PromiseWrap (env, parent_promise, true );
308
- parent_wrap->MakeWeak (parent_wrap);
360
+ parent_wrap = PromiseWrap::New (env, parent_promise, nullptr , true );
309
361
}
310
362
// get id from parentWrap
311
363
double trigger_id = parent_wrap->get_id ();
312
364
env->set_init_trigger_id (trigger_id);
313
365
}
314
- wrap = new PromiseWrap (env, promise, silent);
315
- wrap-> MakeWeak (wrap );
366
+
367
+ wrap = PromiseWrap::New (env, promise, parent_wrap, silent );
316
368
} else if (type == PromiseHookType::kResolve ) {
317
369
// TODO(matthewloring): need to expose this through the async hooks api.
318
370
}
@@ -351,6 +403,22 @@ static void SetupHooks(const FunctionCallbackInfo<Value>& args) {
351
403
SET_HOOK_FN (destroy);
352
404
env->AddPromiseHook (PromiseHook, nullptr );
353
405
#undef SET_HOOK_FN
406
+
407
+ {
408
+ Local<FunctionTemplate> ctor =
409
+ FunctionTemplate::New (env->isolate ());
410
+ ctor->SetClassName (FIXED_ONE_BYTE_STRING (env->isolate (), " PromiseWrap" ));
411
+ Local<ObjectTemplate> promise_wrap_template = ctor->InstanceTemplate ();
412
+ promise_wrap_template->SetInternalFieldCount (
413
+ PromiseWrap::kInternalFieldCount );
414
+ promise_wrap_template->SetAccessor (
415
+ FIXED_ONE_BYTE_STRING (env->isolate (), " promise" ),
416
+ PromiseWrap::GetPromise);
417
+ promise_wrap_template->SetAccessor (
418
+ FIXED_ONE_BYTE_STRING (env->isolate (), " parentId" ),
419
+ PromiseWrap::GetParentId);
420
+ env->set_promise_wrap_template (promise_wrap_template);
421
+ }
354
422
}
355
423
356
424
0 commit comments