2222
2323using namespace std ;
2424
25+ namespace {
26+ napi_value EnsureConstructorThis (napi_env env, napi_value jsThis, napi_value prototype) {
27+ if (!napi_util::is_null_or_undefined (env, jsThis)) {
28+ return jsThis;
29+ }
30+
31+ auto runtime = Runtime::GetRuntime (env);
32+ auto receiver = runtime->GetObjectManager ()->GetEmptyObject ();
33+ if (!napi_util::is_null_or_undefined (env, receiver) &&
34+ !napi_util::is_null_or_undefined (env, prototype)) {
35+ napi_util::setPrototypeOf (env, receiver, prototype);
36+ }
37+
38+ return receiver;
39+ }
40+ }
41+
2542void MetadataNode::Init (napi_env env) {
2643 auto cache = GetMetadataNodeCache (env);
2744}
@@ -41,7 +58,12 @@ napi_value MetadataNode::CreateArrayObjectConstructor(napi_env env) {
4158 napi_define_class (env, name, strlen (name),
4259 [](napi_env env, napi_callback_info info) -> napi_value {
4360 NAPI_CALLBACK_BEGIN (0 )
44- return jsThis;
61+ napi_value newTarget;
62+ napi_get_new_target (env, info, &newTarget);
63+ napi_value receiverPrototype = !napi_util::is_null_or_undefined (env, newTarget)
64+ ? napi_util::get_prototype (env, newTarget)
65+ : nullptr ;
66+ return EnsureConstructorThis (env, jsThis, receiverPrototype);
4567 }, nullptr , 0 , nullptr , &arrayConstructor);
4668 napi_value proto = napi_util::get_prototype (env, arrayConstructor);
4769 ObjectManager::MarkObject (env, proto);
@@ -67,11 +89,14 @@ napi_value MetadataNode::CreateExtendedJSWrapper(napi_env env, ObjectManager *ob
6789
6890 if (cacheData.node != nullptr ) {
6991 extInstance = objectManager->GetEmptyObject ();
92+ if (napi_util::is_null_or_undefined (env, extInstance)) {
93+ return nullptr ;
94+ }
7095 ObjectManager::MarkSuperCall (env, extInstance);
7196 napi_value extendedCtorFunc = napi_util::get_ref_value (env,
7297 cacheData.extendedCtorFunction );
73- napi_util::setPrototypeOf (env, extInstance,
74- napi_util::get_prototype (env, extendedCtorFunc) );
98+ napi_value extendedPrototype = napi_util::get_prototype (env, extendedCtorFunc);
99+ napi_util::setPrototypeOf (env, extInstance, extendedPrototype );
75100
76101 napi_set_named_property (env, extInstance, CONSTRUCTOR , extendedCtorFunc);
77102
@@ -323,19 +348,21 @@ napi_value MetadataNode::ExtendedClassConstructorCallback(napi_env env, napi_cal
323348 napi_value newTarget;
324349 napi_get_new_target (env, info, &newTarget);
325350 if (napi_util::is_null_or_undefined (env, newTarget)) return nullptr ;
351+ napi_value receiver = EnsureConstructorThis (env, jsThis, napi_util::get_prototype (env, newTarget));
352+ if (napi_util::is_null_or_undefined (env, receiver)) return nullptr ;
326353
327354 auto extData = reinterpret_cast <ExtendedClassCallbackData *>(data);
328- SetInstanceMetadata (env, jsThis , extData->node );
355+ SetInstanceMetadata (env, receiver , extData->node );
329356
330357 napi_value implementationObject = napi_util::get_ref_value (env,
331358 extData->implementationObject );
332- ObjectManager::MarkSuperCall (env, jsThis );
359+ ObjectManager::MarkSuperCall (env, receiver );
333360
334361 string fullClassName = extData->fullClassName ;
335362
336363 ArgsWrapper argWrapper (argv.data (), argc, ArgType::Class);
337364 napi_value jsThisProxy;
338- bool success = CallbackHandlers::RegisterInstance (env, jsThis , fullClassName, argWrapper,
365+ bool success = CallbackHandlers::RegisterInstance (env, receiver , fullClassName, argWrapper,
339366 implementationObject, false ,
340367 &jsThisProxy, extData->node ->m_name );
341368
@@ -403,23 +430,30 @@ napi_value MetadataNode::InterfaceConstructorCallback(napi_env env, napi_callbac
403430 auto node = reinterpret_cast <MetadataNode *>(data);
404431
405432 auto className = node->m_implType ;
433+ napi_value newTarget;
434+ napi_get_new_target (env, info, &newTarget);
435+ napi_value receiverPrototype = !napi_util::is_null_or_undefined (env, newTarget)
436+ ? napi_util::get_prototype (env, newTarget)
437+ : nullptr ;
438+ napi_value receiver = EnsureConstructorThis (env, jsThis, receiverPrototype);
439+ if (napi_util::is_null_or_undefined (env, receiver)) return nullptr ;
406440
407- SetInstanceMetadata (env, jsThis , node);
441+ SetInstanceMetadata (env, receiver , node);
408442
409- ObjectManager::MarkSuperCall (env, jsThis );
443+ ObjectManager::MarkSuperCall (env, receiver );
410444
411445
412446 napi_util::setPrototypeOf (env, implementationObject,
413- napi_util::getPrototypeOf (env, jsThis ));
447+ napi_util::getPrototypeOf (env, receiver ));
414448
415- napi_util::setPrototypeOf (env, jsThis , implementationObject);
449+ napi_util::setPrototypeOf (env, receiver , implementationObject);
416450
417- napi_set_named_property (env, jsThis , CLASS_IMPLEMENTATION_OBJECT , implementationObject);
451+ napi_set_named_property (env, receiver , CLASS_IMPLEMENTATION_OBJECT , implementationObject);
418452
419453 ArgsWrapper argsWrapper (argv.data (), argc, ArgType::Interface);
420454
421455 napi_value jsThisProxy;
422- auto success = CallbackHandlers::RegisterInstance (env, jsThis , className, argsWrapper,
456+ auto success = CallbackHandlers::RegisterInstance (env, receiver , className, argsWrapper,
423457 implementationObject, true , &jsThisProxy);
424458 return jsThisProxy;
425459
@@ -444,8 +478,15 @@ napi_value MetadataNode::ClassConstructorCallback(napi_env env, napi_callback_in
444478 try {
445479
446480 auto node = reinterpret_cast <MetadataNode *>(data);
481+ napi_value newTarget;
482+ napi_get_new_target (env, info, &newTarget);
483+ napi_value receiverPrototype = !napi_util::is_null_or_undefined (env, newTarget)
484+ ? napi_util::get_prototype (env, newTarget)
485+ : nullptr ;
486+ napi_value receiver = EnsureConstructorThis (env, jsThis, receiverPrototype);
487+ if (napi_util::is_null_or_undefined (env, receiver)) return nullptr ;
447488
448- SetInstanceMetadata (env, jsThis , node);
489+ SetInstanceMetadata (env, receiver , node);
449490
450491 string extendName;
451492 auto className = node->m_name ;
@@ -454,7 +495,7 @@ napi_value MetadataNode::ClassConstructorCallback(napi_env env, napi_callback_in
454495
455496 ArgsWrapper argsWrapper (argv.data (), argc, ArgType::Class);
456497 napi_value jsThisProxy;
457- bool success = CallbackHandlers::RegisterInstance (env, jsThis , fullClassName, argsWrapper,
498+ bool success = CallbackHandlers::RegisterInstance (env, receiver , fullClassName, argsWrapper,
458499 nullptr , false , &jsThisProxy, className);
459500
460501 return jsThisProxy;
@@ -901,6 +942,7 @@ napi_value MetadataNode::PackageGetterCallback(napi_env env, napi_callback_info
901942 NativeScriptException nsEx (std::string (" Error: c++ exception!" ));
902943 nsEx.ReThrowToNapi (env);
903944 }
945+ return nullptr ;
904946}
905947
906948void MetadataNode::RegisterSymbolHasInstanceCallback (napi_env env, const MetadataTreeNode *treeNode,
@@ -2160,4 +2202,4 @@ robin_hood::unordered_map<MetadataTreeNode *, MetadataNode *> MetadataNode::s_tr
21602202tns::ConcurrentMap<napi_env, MetadataNode::MetadataNodeCache *> MetadataNode::s_metadata_node_cache;
21612203robin_hood::unordered_map<napi_env, napi_ref> MetadataNode::s_arrayObjects;
21622204
2163- bool MetadataNode::s_profilerEnabled = false ;
2205+ bool MetadataNode::s_profilerEnabled = false ;
0 commit comments