@@ -652,14 +652,10 @@ MetadataNode::GetCachedExtendedClassData(napi_env env, const string &proxyClassN
652652}
653653
654654MetadataNode::MetadataNodeCache *MetadataNode::GetMetadataNodeCache (napi_env env) {
655- MetadataNodeCache *cache;
656- auto itFound = s_metadata_node_cache.find (env);
657- if (itFound == s_metadata_node_cache.end ()) {
658- cache = new MetadataNodeCache;
659- s_metadata_node_cache.emplace (env, cache);
660- } else {
661- cache = itFound->second ;
662- }
655+ auto cache = s_metadata_node_cache.Get (env);
656+ if (cache) return cache;
657+ cache = new MetadataNodeCache;
658+ s_metadata_node_cache.Insert (env, cache);
663659 return cache;
664660}
665661
@@ -834,61 +830,45 @@ napi_value MetadataNode::CreateWrapper(napi_env env) {
834830}
835831
836832napi_value MetadataNode::PackageGetterCallback (napi_env env, napi_callback_info info) {
837- size_t argc = 1 ;
838- napi_value args[1 ];
839- napi_value thisArg;
840- void *data;
841-
842- napi_get_cb_info (env, info, &argc, args, &thisArg, &data);
843-
833+ NAPI_CALLBACK_BEGIN (0 )
844834 try {
845-
846- auto *methodInfo = static_cast <PackageGetterMethodData *>(data);
847-
848- if (methodInfo->value != nullptr ) {
849- napi_value value = napi_util::get_ref_value (env, methodInfo->value );
850- if (!napi_util::is_null_or_undefined (env, value)) {
851- return value;
852- }
835+ auto childTreeNode = static_cast <MetadataTreeNode *>(data);
836+ auto node = GetOrCreateInternal (childTreeNode->parent );
837+ DEBUG_WRITE (" Get package item: %s" , childTreeNode->name .c_str ());
838+ auto hiddenPropName = " __" + childTreeNode->name ;
839+ napi_value hiddenValue;
840+ napi_get_named_property (env, jsThis, hiddenPropName.c_str (), &hiddenValue);
841+
842+ if (!napi_util::is_null_or_undefined (env, hiddenValue)) {
843+ DEBUG_WRITE (" Get cached package item: %s" , hiddenPropName.c_str ());
844+ return hiddenValue;
853845 }
854846
855- auto node = methodInfo->node ;
856-
857- uint8_t nodeType = s_metadataReader.GetNodeType (node->m_treeNode );
858-
859- auto child = GetChildMetadataForPackage (node, methodInfo->utf8name );
860- auto foundChild = child.treeNode != nullptr ;
861- napi_value cachedItem = nullptr ;
862- if (foundChild) {
863- auto childNode = MetadataNode::GetOrCreateInternal (child.treeNode );
864- auto cache = GetMetadataNodeCache (env);
865- if (methodInfo->value != nullptr ) {
866- cache->CtorFuncCache .erase (childNode->m_treeNode );
867- }
868- cachedItem = childNode->CreateWrapper (env);
869- methodInfo->value = napi_util::make_ref (env, cachedItem);
870-
871- uint8_t childNodeType = s_metadataReader.GetNodeType (child.treeNode );
872- bool isInterface = s_metadataReader.IsNodeTypeInterface (childNodeType);
873- if (isInterface) {
874- // For all java interfaces we register the special Symbol.hasInstance property
875- // which is invoked by the instanceof operator (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/hasInstance).
876- // For example:
877- //
878- // Object.defineProperty(android.view.animation.Interpolator, Symbol.hasInstance, {
879- // value: function(obj) {
880- // return true;
881- // }
882- // });
883- RegisterSymbolHasInstanceCallback (env, child, cachedItem);
884- }
885-
886- if (node->m_name == " org/json" && child.name == " JSONObject" ) {
887- JSONObjectHelper::RegisterFromFunction (env, cachedItem);
888- }
847+ auto childNode = MetadataNode::GetOrCreateInternal (childTreeNode);
848+ hiddenValue = childNode->CreateWrapper (env);
849+
850+ uint8_t childNodeType = s_metadataReader.GetNodeType (childTreeNode);
851+ bool isInterface = s_metadataReader.IsNodeTypeInterface (childNodeType);
852+ if (isInterface) {
853+ // For all java interfaces we register the special Symbol.hasInstance property
854+ // which is invoked by the instanceof operator (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/hasInstance).
855+ // For example:
856+ //
857+ // Object.defineProperty(android.view.animation.Interpolator, Symbol.hasInstance, {
858+ // value: function(obj) {
859+ // return true;
860+ // }
861+ // });
862+ RegisterSymbolHasInstanceCallback (env, childTreeNode, hiddenValue);
863+ }
864+ auto parentNode = GetOrCreateInternal (childTreeNode->parent );
865+ if (parentNode->m_name == " org/json" && childTreeNode->name == " JSONObject" ) {
866+ JSONObjectHelper::RegisterFromFunction (env, hiddenValue);
889867 }
890868
891- return cachedItem;
869+ napi_set_named_property (env, jsThis, hiddenPropName.c_str (), hiddenValue);
870+
871+ return hiddenValue;
892872
893873 } catch (NativeScriptException &e) {
894874 e.ReThrowToNapi (env);
@@ -901,18 +881,17 @@ napi_value MetadataNode::PackageGetterCallback(napi_env env, napi_callback_info
901881 NativeScriptException nsEx (std::string (" Error: c++ exception!" ));
902882 nsEx.ReThrowToNapi (env);
903883 }
904-
905- return nullptr ;
906884}
907885
908- void MetadataNode::RegisterSymbolHasInstanceCallback (napi_env env, const MetadataEntry &entry ,
886+ void MetadataNode::RegisterSymbolHasInstanceCallback (napi_env env, const MetadataTreeNode* treeNode ,
909887 napi_value interface) {
910888 if (napi_util::is_undefined (env, interface) || napi_util::is_null (env, interface)) {
911889 return ;
912890 }
913891
914892 JEnv jEnv;
915- auto className = GetJniClassName (entry);
893+
894+ auto className = GetJniClassName (treeNode);
916895 auto clazz = jEnv.FindClass (className);
917896 if (clazz == nullptr ) {
918897 return ;
@@ -976,9 +955,10 @@ napi_value MetadataNode::SymbolHasInstanceCallback(napi_env env, napi_callback_i
976955
977956}
978957
979- std::string MetadataNode::GetJniClassName (const MetadataEntry &entry) {
958+
959+ std::string MetadataNode::GetJniClassName (const MetadataTreeNode * node) {
980960 std::stack<string> s;
981- MetadataTreeNode *node = entry. treeNode ;
961+
982962 while (node != nullptr && !node->name .empty ()) {
983963 s.push (node->name );
984964 node = node->parent ;
@@ -1002,29 +982,21 @@ napi_value MetadataNode::CreatePackageObject(napi_env env) {
1002982
1003983 if (ptrChildren != nullptr ) {
1004984 const auto &children = *ptrChildren;
1005-
1006985 auto lastChildName = " " ;
1007-
1008986 for (auto childNode: children) {
1009-
1010- auto *info = new PackageGetterMethodData ();
1011- info->utf8name = childNode->name .c_str ();
1012- info->node = this ;
1013- info->value = nullptr ;
1014-
1015- if (strcmp (info->utf8name , lastChildName) == 0 ) {
987+ if (strcmp (childNode->name .c_str (), lastChildName) == 0 ) {
1016988 continue ;
1017989 }
1018- lastChildName = info-> utf8name ;
990+ lastChildName = childNode-> name . c_str () ;
1019991 napi_property_descriptor descriptor{
1020992 childNode->name .c_str (),
1021993 nullptr ,
1022994 nullptr ,
1023995 PackageGetterCallback,
1024996 nullptr ,
1025997 nullptr ,
1026- napi_default ,
1027- info };
998+ napi_default_jsproperty ,
999+ childNode };
10281000 napi_define_properties (env, packageObj, 1 , &descriptor);
10291001 }
10301002 }
@@ -1377,10 +1349,22 @@ napi_value MetadataNode::GetConstructorFunctionInternal(napi_env env, MetadataTr
13771349 auto itFound = cache->CtorFuncCache .find (treeNode);
13781350 if (itFound != cache->CtorFuncCache .end ()) {
13791351 instanceMethodsCallbackData = itFound->second .instanceMethodCallbacks ;
1380- if (itFound->second .constructorFunction == nullptr )
1381- return nullptr ;
1382- auto value = napi_util::get_ref_value (env, itFound->second .constructorFunction );
1383- if (!napi_util::is_null_or_undefined (env, value)) return value;
1352+ if (itFound->second .constructorFunction != nullptr ) {
1353+ auto value = napi_util::get_ref_value (env, itFound->second .constructorFunction );
1354+ if (!napi_util::is_null_or_undefined (env, value)) {
1355+ return value;
1356+ }
1357+ }
1358+ }
1359+
1360+ if (itFound != cache->CtorFuncCache .end ()) {
1361+ if (itFound->second .constructorFunction != nullptr ) {
1362+ napi_delete_reference (env, itFound->second .constructorFunction );
1363+ }
1364+ for (const auto &data: itFound->second .instanceMethodCallbacks ) {
1365+ delete data;
1366+ }
1367+ cache->CtorFuncCache .erase (itFound);
13841368 }
13851369
13861370 auto node = GetOrCreateInternal (treeNode);
@@ -2075,15 +2059,34 @@ void MetadataNode::BuildMetadata(const std::string &filesPath) {
20752059
20762060void MetadataNode::onDisposeEnv (napi_env env) {
20772061 {
2078- auto it = s_metadata_node_cache.find (env);
2079- if (it != s_metadata_node_cache.end ()) {
2080- delete it->second ;
2081- s_metadata_node_cache.erase (it);
2062+ auto it = s_metadata_node_cache.Get (env);
2063+ if (it != nullptr ) {
2064+ for (const auto &entry: it->CtorFuncCache ) {
2065+ if (entry.second .constructorFunction == nullptr ) {
2066+ napi_delete_reference (env, entry.second .constructorFunction );
2067+ }
2068+ for (const auto data: entry.second .instanceMethodCallbacks ) {
2069+ delete data;
2070+ }
2071+ }
2072+ it->CtorFuncCache .clear ();
2073+
2074+ for (const auto &entry: it->ExtendedCtorFuncCache ) {
2075+ if (entry.second .extendedCtorFunction == nullptr ) {
2076+ napi_delete_reference (env, entry.second .extendedCtorFunction );
2077+ }
2078+ }
2079+ it->ExtendedCtorFuncCache .clear ();
20822080 }
2081+ s_metadata_node_cache.Remove (env);
2082+ delete it;
20832083 }
20842084 {
20852085 auto it = s_arrayObjects.find (env);
20862086 if (it != s_arrayObjects.end ()) {
2087+ if (it->second != nullptr ) {
2088+ napi_delete_reference (env, it->second );
2089+ }
20872090 s_arrayObjects.erase (it);
20882091 }
20892092 }
@@ -2095,8 +2098,7 @@ MetadataReader MetadataNode::s_metadataReader;
20952098robin_hood::unordered_map<std::string, MetadataNode *> MetadataNode::s_name2NodeCache;
20962099robin_hood::unordered_map<std::string, MetadataTreeNode *> MetadataNode::s_name2TreeNodeCache;
20972100robin_hood::unordered_map<MetadataTreeNode *, MetadataNode *> MetadataNode::s_treeNode2NodeCache;
2098- robin_hood::unordered_map <napi_env, MetadataNode::MetadataNodeCache *> MetadataNode::s_metadata_node_cache;
2101+ tns::ConcurrentMap <napi_env, MetadataNode::MetadataNodeCache *> MetadataNode::s_metadata_node_cache;
20992102robin_hood::unordered_map<napi_env, napi_ref> MetadataNode::s_arrayObjects;
21002103
2101- // TODO
21022104bool MetadataNode::s_profilerEnabled = false ;
0 commit comments