From ca4b6bda34d13d3567521b279c5392245325511c Mon Sep 17 00:00:00 2001 From: Eduardo Speroni Date: Thu, 26 Oct 2023 15:22:08 -0300 Subject: [PATCH 01/54] chore: update changelog [skip ci] --- CHANGELOG.md | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c2a616c1b..4d0e89df7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,39 @@ +## [8.6.2](https://github.com/NativeScript/android/compare/v8.6.1...v8.6.2) (2023-10-10) + + + +## [8.6.1](https://github.com/NativeScript/android/compare/v8.6.0...v8.6.1) (2023-10-10) + + +### Bug Fixes + +* copy drawables ([4ff92cb](https://github.com/NativeScript/android/commit/4ff92cb32a954be4c3d32c302e301cef0a4b72a6)) + + + +# [8.6.0](https://github.com/NativeScript/android/compare/v8.5.3...v8.6.0) (2023-10-06) + + +### Bug Fixes + +* make jar files readonly prior to loading ([#1790](https://github.com/NativeScript/android/issues/1790)) ([2bcdaf0](https://github.com/NativeScript/android/commit/2bcdaf01fb850db4a982c22c2d792f9493a2a7fa)) +* only use project jar files if they are linked ([d23ca94](https://github.com/NativeScript/android/commit/d23ca94ba7c660b26224c57ba6f22085aa99f95c)) +* revert namespace change as to not break existing projects ([8b7b59d](https://github.com/NativeScript/android/commit/8b7b59d23d926b696bde3c1031cf3a842a24133d)) + + +### Features + +* improved error activity ui ([#1776](https://github.com/NativeScript/android/issues/1776)) ([ee3e354](https://github.com/NativeScript/android/commit/ee3e354f1bec89268daf93086aa6dd24898677b9)) +* upgrade client gradle version ([c778c0d](https://github.com/NativeScript/android/commit/c778c0d238c4ba44390f786ba06ab8e51ffb2c97)) + +## [8.5.4](https://github.com/NativeScript/android/compare/v8.5.3...v8.5.4) (2023-09-27) + + +### Bug Fixes + +* make jar files readonly prior to loading ([#1790](https://github.com/NativeScript/android/issues/1790)) ([14a932a](https://github.com/NativeScript/android/commit/14a932ad2d62c94f2f4e139125835da760dcdd58)) + + ## [8.5.3](https://github.com/NativeScript/android/compare/v8.5.2...v8.5.3) (2023-09-22) From b248dc4038d0c1a6af420447c713bc968431f97e Mon Sep 17 00:00:00 2001 From: Eduardo Speroni Date: Tue, 28 Nov 2023 17:19:00 -0300 Subject: [PATCH 02/54] feat: migrate to faster maps and use runtime context (#1793) * feat: migrate to faster maps and use runtime context * fix: missing include --- .../runtime/src/main/cpp/ArgConverter.cpp | 4 +- test-app/runtime/src/main/cpp/ArgConverter.h | 2 +- .../runtime/src/main/cpp/CallbackHandlers.cpp | 7 +-- .../runtime/src/main/cpp/CallbackHandlers.h | 6 ++- test-app/runtime/src/main/cpp/JEnv.cpp | 8 ++-- test-app/runtime/src/main/cpp/JEnv.h | 6 +-- .../runtime/src/main/cpp/MetadataNode.cpp | 26 +++++------ test-app/runtime/src/main/cpp/MetadataNode.h | 16 +++---- .../runtime/src/main/cpp/MetadataReader.cpp | 2 +- .../runtime/src/main/cpp/MetadataReader.h | 3 +- test-app/runtime/src/main/cpp/MethodCache.cpp | 6 +-- test-app/runtime/src/main/cpp/MethodCache.h | 2 +- .../runtime/src/main/cpp/ModuleInternal.cpp | 4 +- .../runtime/src/main/cpp/ModuleInternal.h | 45 +++++++++---------- .../runtime/src/main/cpp/NetworkAgentImpl.h | 2 +- .../runtime/src/main/cpp/ObjectManager.cpp | 4 +- .../runtime/src/main/cpp/PageAgentImpl.cpp | 4 +- test-app/runtime/src/main/cpp/Runtime.cpp | 6 +-- test-app/runtime/src/main/cpp/Runtime.h | 4 +- test-app/runtime/src/main/cpp/Timers.cpp | 3 +- test-app/runtime/src/main/cpp/Timers.h | 3 +- .../runtime/src/main/cpp/V8GlobalHelpers.cpp | 5 ++- 22 files changed, 86 insertions(+), 82 deletions(-) diff --git a/test-app/runtime/src/main/cpp/ArgConverter.cpp b/test-app/runtime/src/main/cpp/ArgConverter.cpp index 6319b44c8..a8ebe3d66 100644 --- a/test-app/runtime/src/main/cpp/ArgConverter.cpp +++ b/test-app/runtime/src/main/cpp/ArgConverter.cpp @@ -200,7 +200,7 @@ ArgConverter::TypeLongOperationsCache* ArgConverter::GetTypeLongCache(v8::Isolat auto itFound = s_type_long_operations_cache.find(isolate); if (itFound == s_type_long_operations_cache.end()) { cache = new TypeLongOperationsCache; - s_type_long_operations_cache.insert(make_pair(isolate, cache)); + s_type_long_operations_cache.emplace(isolate, cache); } else { cache = itFound->second; } @@ -230,4 +230,4 @@ void ArgConverter::onDisposeIsolate(Isolate* isolate) { } } -std::map ArgConverter::s_type_long_operations_cache; \ No newline at end of file +robin_hood::unordered_map ArgConverter::s_type_long_operations_cache; \ No newline at end of file diff --git a/test-app/runtime/src/main/cpp/ArgConverter.h b/test-app/runtime/src/main/cpp/ArgConverter.h index 88f940f21..151bd12f1 100644 --- a/test-app/runtime/src/main/cpp/ArgConverter.h +++ b/test-app/runtime/src/main/cpp/ArgConverter.h @@ -124,7 +124,7 @@ class ArgConverter { * "s_type_long_operations_cache" used to keep function * dealing with operations concerning java long -> javascript number. */ - static std::map s_type_long_operations_cache; + static robin_hood::unordered_map s_type_long_operations_cache; }; } diff --git a/test-app/runtime/src/main/cpp/CallbackHandlers.cpp b/test-app/runtime/src/main/cpp/CallbackHandlers.cpp index d86348e94..6f35d9698 100644 --- a/test-app/runtime/src/main/cpp/CallbackHandlers.cpp +++ b/test-app/runtime/src/main/cpp/CallbackHandlers.cpp @@ -685,7 +685,8 @@ int CallbackHandlers::RunOnMainThreadFdCallback(int fd, int events, void *data) Isolate::Scope isolate_scope(isolate); HandleScope handle_scope(isolate); Local cb = it->second.callback_.Get(isolate); - v8::Local context = cb->GetCreationContextChecked(); + Runtime* runtime = Runtime::GetRuntime(isolate); + v8::Local context = runtime->GetContext(); Context::Scope context_scope(context); // erase the it here as we're already done with its values and the callback might invalidate the iterator cache_.erase(it); @@ -1025,7 +1026,7 @@ void CallbackHandlers::NewThreadCallback(const v8::FunctionCallbackInfo(isolate, thiz); - id2WorkerMap.insert(make_pair(workerId, persistentWorker)); + id2WorkerMap.emplace(workerId, persistentWorker); DEBUG_WRITE("Called Worker constructor id=%d", workerId); @@ -1740,7 +1741,7 @@ std::atomic_uint64_t CallbackHandlers::frameCallbackCount_ = {0}; int CallbackHandlers::nextWorkerId = 0; -std::map *> CallbackHandlers::id2WorkerMap; +robin_hood::unordered_map *> CallbackHandlers::id2WorkerMap; short CallbackHandlers::MAX_JAVA_STRING_ARRAY_LENGTH = 100; jclass CallbackHandlers::RUNTIME_CLASS = nullptr; diff --git a/test-app/runtime/src/main/cpp/CallbackHandlers.h b/test-app/runtime/src/main/cpp/CallbackHandlers.h index 0ca90e7ac..d079d4730 100644 --- a/test-app/runtime/src/main/cpp/CallbackHandlers.h +++ b/test-app/runtime/src/main/cpp/CallbackHandlers.h @@ -18,6 +18,7 @@ #include #include "NativeScriptAssert.h" #include "NativeScriptException.h" +#include "Runtime.h" namespace tns { class CallbackHandlers { @@ -27,7 +28,7 @@ namespace tns { * Stores persistent handles of all 'Worker' objects initialized on the main thread * Note: No isolates different than that of the main thread should access this map */ - static std::map *> id2WorkerMap; + static robin_hood::unordered_map *> id2WorkerMap; static int nextWorkerId; @@ -364,7 +365,8 @@ namespace tns { v8::Isolate::Scope isolate_scope(isolate); v8::HandleScope handle_scope(isolate); v8::Local cb = entry->callback_.Get(isolate); - v8::Local context = cb->GetCreationContextChecked(); + Runtime* runtime = Runtime::GetRuntime(isolate); + v8::Local context = runtime->GetContext(); v8::Context::Scope context_scope(context); // we're running the callback now, so it's not scheduled anymore entry->markUnscheduled(); diff --git a/test-app/runtime/src/main/cpp/JEnv.cpp b/test-app/runtime/src/main/cpp/JEnv.cpp index cc6629749..dda0241b4 100644 --- a/test-app/runtime/src/main/cpp/JEnv.cpp +++ b/test-app/runtime/src/main/cpp/JEnv.cpp @@ -769,7 +769,7 @@ jclass JEnv::CheckForClassInCache(const string &className) { jclass JEnv::InsertClassIntoCache(const string &className, jclass &tmp) { auto global_class = reinterpret_cast(m_env->NewGlobalRef(tmp)); - s_classCache.insert(make_pair(className, global_class)); + s_classCache.emplace(className, global_class); m_env->DeleteLocalRef(tmp); return global_class; @@ -788,7 +788,7 @@ jthrowable JEnv::CheckForClassMissingCache(const string &className) { jthrowable JEnv::InsertClassIntoMissingCache(const string &className,const jthrowable &tmp) { auto throwable = reinterpret_cast(m_env->NewGlobalRef(tmp)); - s_missingClasses.insert(make_pair(className, throwable)); + s_missingClasses.emplace(className, throwable); m_env->DeleteLocalRef(tmp); return throwable; @@ -855,8 +855,8 @@ void JEnv::CheckForJavaException() { } JavaVM *JEnv::s_jvm = nullptr; -map JEnv::s_classCache; -map JEnv::s_missingClasses; +robin_hood::unordered_map JEnv::s_classCache; +robin_hood::unordered_map JEnv::s_missingClasses; jclass JEnv::RUNTIME_CLASS = nullptr; jmethodID JEnv::GET_CACHED_CLASS_METHOD_ID = nullptr; diff --git a/test-app/runtime/src/main/cpp/JEnv.h b/test-app/runtime/src/main/cpp/JEnv.h index a85fcc637..9c809449a 100644 --- a/test-app/runtime/src/main/cpp/JEnv.h +++ b/test-app/runtime/src/main/cpp/JEnv.h @@ -2,7 +2,7 @@ #define JENV_H_ #include "jni.h" -#include +#include "robin_hood.h" #include namespace tns { @@ -342,8 +342,8 @@ class JEnv { static jmethodID GET_CACHED_CLASS_METHOD_ID; - static std::map s_classCache; - static std::map s_missingClasses; + static robin_hood::unordered_map s_classCache; + static robin_hood::unordered_map s_missingClasses; }; } diff --git a/test-app/runtime/src/main/cpp/MetadataNode.cpp b/test-app/runtime/src/main/cpp/MetadataNode.cpp index 9959bf0ea..a01a5a1bf 100644 --- a/test-app/runtime/src/main/cpp/MetadataNode.cpp +++ b/test-app/runtime/src/main/cpp/MetadataNode.cpp @@ -97,7 +97,7 @@ MetadataNode* MetadataNode::GetOrCreate(const string& className) { node = GetOrCreateInternal(treeNode); - s_name2NodeCache.insert(make_pair(className, node)); + s_name2NodeCache.emplace(className, node); } else { node = it->second; } @@ -115,7 +115,7 @@ MetadataNode* MetadataNode::GetOrCreateInternal(MetadataTreeNode* treeNode) { } else { result = new MetadataNode(treeNode); - s_treeNode2NodeCache.insert(make_pair(treeNode, result)); + s_treeNode2NodeCache.emplace(treeNode, result); } return result; @@ -131,7 +131,7 @@ MetadataTreeNode* MetadataNode::GetOrCreateTreeNodeByName(const string& classNam } else { result = s_metadataReader.GetOrCreateTreeNodeByName(className); - s_name2TreeNodeCache.insert(make_pair(className, result)); + s_name2TreeNodeCache.emplace(className, result); } return result; @@ -993,7 +993,7 @@ Local MetadataNode::GetConstructorFunctionTemplate(Isolate* is ctorFuncTemplate.Clear(); auto pft = new Persistent(isolate, ctorFuncTemplate); CtorCacheData ctorCacheItem(pft, instanceMethodsCallbackData); - cache->CtorFuncCache.insert(make_pair(treeNode, ctorCacheItem)); + cache->CtorFuncCache.emplace(treeNode, ctorCacheItem); return ctorFuncTemplate; } @@ -1060,7 +1060,7 @@ Local MetadataNode::GetConstructorFunctionTemplate(Isolate* is //cache "ctorFuncTemplate" auto pft = new Persistent(isolate, ctorFuncTemplate); CtorCacheData ctorCacheItem(pft, instanceMethodsCallbackData); - cache->CtorFuncCache.insert(make_pair(treeNode, ctorCacheItem)); + cache->CtorFuncCache.emplace(treeNode, ctorCacheItem); SetInnerTypes(isolate, wrappedCtorFunc, treeNode); @@ -1735,11 +1735,11 @@ void MetadataNode::ExtendMethodCallback(const v8::FunctionCallbackInfoExtendedCtorFuncCache.insert(make_pair(fullExtendedName, cacheData)); + cache->ExtendedCtorFuncCache.emplace(fullExtendedName, cacheData); if (frame.check()) { frame.log("Extending: " + node->m_name); @@ -2027,7 +2027,7 @@ MetadataNode::MetadataNodeCache* MetadataNode::GetMetadataNodeCache(Isolate* iso auto itFound = s_metadata_node_cache.find(isolate); if (itFound == s_metadata_node_cache.end()) { cache = new MetadataNodeCache; - s_metadata_node_cache.insert(make_pair(isolate, cache)); + s_metadata_node_cache.emplace(isolate, cache); } else { cache = itFound->second; } @@ -2293,10 +2293,10 @@ void MetadataNode::onDisposeIsolate(Isolate* isolate) { string MetadataNode::TNS_PREFIX = "com/tns/gen/"; MetadataReader MetadataNode::s_metadataReader; -std::map MetadataNode::s_name2NodeCache; -std::map MetadataNode::s_name2TreeNodeCache; -std::map MetadataNode::s_treeNode2NodeCache; -map MetadataNode::s_metadata_node_cache; +robin_hood::unordered_map MetadataNode::s_name2NodeCache; +robin_hood::unordered_map MetadataNode::s_name2TreeNodeCache; +robin_hood::unordered_map MetadataNode::s_treeNode2NodeCache; +robin_hood::unordered_map MetadataNode::s_metadata_node_cache; bool MetadataNode::s_profilerEnabled = false; -std::map*> MetadataNode::s_arrayObjectTemplates; +robin_hood::unordered_map*> MetadataNode::s_arrayObjectTemplates; diff --git a/test-app/runtime/src/main/cpp/MetadataNode.h b/test-app/runtime/src/main/cpp/MetadataNode.h index d66ef0484..ea8a18ec7 100644 --- a/test-app/runtime/src/main/cpp/MetadataNode.h +++ b/test-app/runtime/src/main/cpp/MetadataNode.h @@ -170,18 +170,18 @@ class MetadataNode { PrototypeTemplateFiller& protoFiller); MetadataTreeNode* m_treeNode; - std::map*> m_poCtorCachePerIsolate; + robin_hood::unordered_map*> m_poCtorCachePerIsolate; std::string m_name; std::string m_implType; bool m_isArray; static std::string TNS_PREFIX; static MetadataReader s_metadataReader; - static std::map s_name2NodeCache; - static std::map s_name2TreeNodeCache; - static std::map s_treeNode2NodeCache; - static std::map s_metadata_node_cache; - static std::map*> s_arrayObjectTemplates; + static robin_hood::unordered_map s_name2NodeCache; + static robin_hood::unordered_map s_name2TreeNodeCache; + static robin_hood::unordered_map s_treeNode2NodeCache; + static robin_hood::unordered_map s_metadata_node_cache; + static robin_hood::unordered_map*> s_arrayObjectTemplates; static bool s_profilerEnabled; struct MethodCallbackData { @@ -263,9 +263,9 @@ class MetadataNode { struct MetadataNodeCache { v8::Persistent* MetadataKey; - std::map CtorFuncCache; + robin_hood::unordered_map CtorFuncCache; - std::map ExtendedCtorFuncCache; + robin_hood::unordered_map ExtendedCtorFuncCache; }; }; } diff --git a/test-app/runtime/src/main/cpp/MetadataReader.cpp b/test-app/runtime/src/main/cpp/MetadataReader.cpp index 282300f56..9fb9daa78 100644 --- a/test-app/runtime/src/main/cpp/MetadataReader.cpp +++ b/test-app/runtime/src/main/cpp/MetadataReader.cpp @@ -178,7 +178,7 @@ string MetadataReader::ReadTypeName(MetadataTreeNode* treeNode) { } else { name = ReadTypeNameInternal(treeNode); - m_typeNameCache.insert(make_pair(treeNode, name)); + m_typeNameCache.emplace(treeNode, name); } return name; diff --git a/test-app/runtime/src/main/cpp/MetadataReader.h b/test-app/runtime/src/main/cpp/MetadataReader.h index 284d1e952..1f3706994 100644 --- a/test-app/runtime/src/main/cpp/MetadataReader.h +++ b/test-app/runtime/src/main/cpp/MetadataReader.h @@ -6,6 +6,7 @@ #include #include #include +#include "robin_hood.h" namespace tns { typedef std::vector (*GetTypeMetadataCallback)(const std::string& classname, int index); @@ -186,7 +187,7 @@ class MetadataReader { std::vector m_v; GetTypeMetadataCallback m_getTypeMetadataCallback; - std::map m_typeNameCache; + robin_hood::unordered_map m_typeNameCache; }; } diff --git a/test-app/runtime/src/main/cpp/MethodCache.cpp b/test-app/runtime/src/main/cpp/MethodCache.cpp index 8e2f2a9d4..587933728 100644 --- a/test-app/runtime/src/main/cpp/MethodCache.cpp +++ b/test-app/runtime/src/main/cpp/MethodCache.cpp @@ -54,7 +54,7 @@ MethodCache::CacheMethodInfo MethodCache::ResolveMethodSignature(const string& c : env.GetMethodID(clazz, methodName, signature); - s_mthod_ctor_signature_cache.insert(make_pair(encoded_method_signature, method_info)); + s_mthod_ctor_signature_cache.emplace(encoded_method_signature, method_info); } } else { method_info = (*it).second; @@ -81,7 +81,7 @@ MethodCache::CacheMethodInfo MethodCache::ResolveConstructorSignature(const Args constructor_info.signature = signature; constructor_info.mid = env.GetMethodID(javaClass, "", signature); - s_mthod_ctor_signature_cache.insert(make_pair(encoded_ctor_signature, constructor_info)); + s_mthod_ctor_signature_cache.emplace(encoded_ctor_signature, constructor_info); } } else { constructor_info = (*it).second; @@ -261,7 +261,7 @@ string MethodCache::ResolveConstructor(const FunctionCallbackInfo& args, return resolvedSignature; } -map MethodCache::s_mthod_ctor_signature_cache; +robin_hood::unordered_map MethodCache::s_mthod_ctor_signature_cache; jclass MethodCache::RUNTIME_CLASS = nullptr; jmethodID MethodCache::RESOLVE_METHOD_OVERLOAD_METHOD_ID = nullptr; jmethodID MethodCache::RESOLVE_CONSTRUCTOR_SIGNATURE_ID = nullptr; diff --git a/test-app/runtime/src/main/cpp/MethodCache.h b/test-app/runtime/src/main/cpp/MethodCache.h index a37acaf10..b253d2b37 100644 --- a/test-app/runtime/src/main/cpp/MethodCache.h +++ b/test-app/runtime/src/main/cpp/MethodCache.h @@ -59,7 +59,7 @@ class MethodCache { * Used for caching the resolved constructor or method signature. * The encoded signature has template: .S/I....<...> */ - static std::map s_mthod_ctor_signature_cache; + static robin_hood::unordered_map s_mthod_ctor_signature_cache; }; } diff --git a/test-app/runtime/src/main/cpp/ModuleInternal.cpp b/test-app/runtime/src/main/cpp/ModuleInternal.cpp index e61be0273..07f2588cd 100644 --- a/test-app/runtime/src/main/cpp/ModuleInternal.cpp +++ b/test-app/runtime/src/main/cpp/ModuleInternal.cpp @@ -132,7 +132,7 @@ Local ModuleInternal::GetRequireFunction(Isolate* isolate, const strin auto poFunc = new Persistent(isolate, requireFunc); - m_requireCache.insert(make_pair(dirName, poFunc)); + m_requireCache.emplace(dirName, poFunc); } return requireFunc; @@ -446,7 +446,7 @@ Local ModuleInternal::LoadData(Isolate* isolate, const string& path) { auto poObj = new Persistent(isolate, json); - m_loadedModules.insert(make_pair(path, ModuleCacheEntry(poObj, true /* isData */))); + m_loadedModules.emplace(path, ModuleCacheEntry(poObj, true /* isData */)); return json; } diff --git a/test-app/runtime/src/main/cpp/ModuleInternal.h b/test-app/runtime/src/main/cpp/ModuleInternal.h index 4d20ebf1d..e7b8adaeb 100644 --- a/test-app/runtime/src/main/cpp/ModuleInternal.h +++ b/test-app/runtime/src/main/cpp/ModuleInternal.h @@ -39,9 +39,24 @@ class ModuleInternal { static int MODULE_PROLOGUE_LENGTH; private: - enum class ModulePathKind; + enum class ModulePathKind { + Global, + Relative, + Absolute + }; + + struct ModuleCacheEntry { + ModuleCacheEntry(v8::Persistent* _obj) + : obj(_obj), isData(false) { + } + + ModuleCacheEntry(v8::Persistent* _obj, bool _isData) + : obj(_obj), isData(_isData) { + } - struct ModuleCacheEntry; + bool isData; + v8::Persistent* obj; + }; static void RequireCallback(const v8::FunctionCallbackInfo& args); @@ -75,15 +90,15 @@ class ModuleInternal { v8::Isolate* m_isolate; v8::Persistent* m_requireFunction; v8::Persistent* m_requireFactoryFunction; - std::map*> m_requireCache; - std::map m_loadedModules; + robin_hood::unordered_map*> m_requireCache; + robin_hood::unordered_map m_loadedModules; class TempModule { public: TempModule(ModuleInternal* module, const std::string& modulePath, const std::string& cacheKey, v8::Persistent* poModuleObj) :m_module(module), m_dispose(true), m_modulePath(modulePath), m_cacheKey(cacheKey), m_poModuleObj(poModuleObj) { - m_module->m_loadedModules.insert(make_pair(m_modulePath, ModuleCacheEntry(m_poModuleObj))); - m_module->m_loadedModules.insert(make_pair(m_cacheKey, ModuleCacheEntry(m_poModuleObj))); + m_module->m_loadedModules.emplace(m_modulePath, ModuleCacheEntry(m_poModuleObj)); + m_module->m_loadedModules.emplace(m_cacheKey, ModuleCacheEntry(m_poModuleObj)); } ~TempModule() { @@ -105,24 +120,6 @@ class ModuleInternal { v8::Persistent* m_poModuleObj; }; - struct ModuleCacheEntry { - ModuleCacheEntry(v8::Persistent* _obj) - : obj(_obj), isData(false) { - } - - ModuleCacheEntry(v8::Persistent* _obj, bool _isData) - : obj(_obj), isData(_isData) { - } - - bool isData; - v8::Persistent* obj; - }; - - enum class ModulePathKind { - Global, - Relative, - Absolute - }; }; } diff --git a/test-app/runtime/src/main/cpp/NetworkAgentImpl.h b/test-app/runtime/src/main/cpp/NetworkAgentImpl.h index 68bdd5194..adf86c680 100644 --- a/test-app/runtime/src/main/cpp/NetworkAgentImpl.h +++ b/test-app/runtime/src/main/cpp/NetworkAgentImpl.h @@ -60,7 +60,7 @@ class NetworkAgentImpl : public protocol::Network::Backend { static NetworkAgentImpl* Instance; protocol::Network::Frontend m_frontend; - std::map m_responses; + robin_hood::unordered_map m_responses; private: V8InspectorSessionImpl* m_session; diff --git a/test-app/runtime/src/main/cpp/ObjectManager.cpp b/test-app/runtime/src/main/cpp/ObjectManager.cpp index f8995a78f..7e1901fdf 100644 --- a/test-app/runtime/src/main/cpp/ObjectManager.cpp +++ b/test-app/runtime/src/main/cpp/ObjectManager.cpp @@ -263,7 +263,7 @@ void ObjectManager::Link(const Local &object, uint32_t javaObjectID, jcl //link object->SetInternalField(jsInfoIdx, jsInfo); - m_idToObject.insert(make_pair(javaObjectID, objectHandle)); + m_idToObject.emplace(javaObjectID, objectHandle); } bool ObjectManager::CloneLink(const Local &src, const Local &dest) { @@ -384,7 +384,7 @@ void ObjectManager::JSObjectWeakCallback(Isolate *isolate, ObjectWeakCallbackSta if (jsInstanceInfo->IsJavaObjectWeak) { m_implObjWeak.emplace_back(po, javaObjectID); } else { - m_implObjStrong.insert(make_pair(javaObjectID, po)); + m_implObjStrong.emplace(javaObjectID, po); jsInstanceInfo->IsJavaObjectWeak = true; } } else { diff --git a/test-app/runtime/src/main/cpp/PageAgentImpl.cpp b/test-app/runtime/src/main/cpp/PageAgentImpl.cpp index 56e27cc41..f327d41ca 100644 --- a/test-app/runtime/src/main/cpp/PageAgentImpl.cpp +++ b/test-app/runtime/src/main/cpp/PageAgentImpl.cpp @@ -105,7 +105,7 @@ void PageAgentImpl::getResourceContent(const String& in_frameId, const String& i return; } - std::map cachedPageResources = utils::PageResource::s_cachedPageResources; + robin_hood::unordered_map cachedPageResources = utils::PageResource::s_cachedPageResources; if (utils::PageResource::s_cachedPageResources.size() == 0) { cachedPageResources = utils::PageResource::getPageResources(); } @@ -136,7 +136,7 @@ void PageAgentImpl::searchInResource(const String& in_frameId, const String& in_ bool isRegex = in_isRegex.fromMaybe(false); bool isCaseSensitive = in_caseSensitive.fromMaybe(false); - std::map cachedPageResources = utils::PageResource::s_cachedPageResources; + robin_hood::unordered_map cachedPageResources = utils::PageResource::s_cachedPageResources; if (utils::PageResource::s_cachedPageResources.size() == 0) { cachedPageResources = utils::PageResource::getPageResources(); } diff --git a/test-app/runtime/src/main/cpp/Runtime.cpp b/test-app/runtime/src/main/cpp/Runtime.cpp index 43238b0bc..45cfc5604 100644 --- a/test-app/runtime/src/main/cpp/Runtime.cpp +++ b/test-app/runtime/src/main/cpp/Runtime.cpp @@ -98,7 +98,7 @@ Runtime::Runtime(JNIEnv* env, jobject runtime, int id) m_runtime = env->NewGlobalRef(runtime); m_objectManager = new ObjectManager(m_runtime); m_loopTimer = new MessageLoopTimer(); - s_id2RuntimeCache.insert(make_pair(id, this)); + s_id2RuntimeCache.emplace(id, this); if (GET_USED_MEMORY_METHOD_ID == nullptr) { auto RUNTIME_CLASS = env->FindClass("com/tns/Runtime"); @@ -692,8 +692,8 @@ int Runtime::GetReader(){ JavaVM* Runtime::s_jvm = nullptr; jmethodID Runtime::GET_USED_MEMORY_METHOD_ID = nullptr; -map Runtime::s_id2RuntimeCache; -unordered_map Runtime::s_isolate2RuntimesCache; +robin_hood::unordered_map Runtime::s_id2RuntimeCache; +robin_hood::unordered_map Runtime::s_isolate2RuntimesCache; bool Runtime::s_mainThreadInitialized = false; v8::Platform* Runtime::platform = nullptr; int Runtime::m_androidVersion = Runtime::GetAndroidVersion(); diff --git a/test-app/runtime/src/main/cpp/Runtime.h b/test-app/runtime/src/main/cpp/Runtime.h index 7ffd17eb9..848336ff7 100644 --- a/test-app/runtime/src/main/cpp/Runtime.h +++ b/test-app/runtime/src/main/cpp/Runtime.h @@ -114,9 +114,9 @@ class Runtime { static int GetAndroidVersion(); static int m_androidVersion; - static std::map s_id2RuntimeCache; + static robin_hood::unordered_map s_id2RuntimeCache; - static std::unordered_map s_isolate2RuntimesCache; + static robin_hood::unordered_map s_isolate2RuntimesCache; static JavaVM* s_jvm; diff --git a/test-app/runtime/src/main/cpp/Timers.cpp b/test-app/runtime/src/main/cpp/Timers.cpp index 2099ffe71..939a9a6ab 100644 --- a/test-app/runtime/src/main/cpp/Timers.cpp +++ b/test-app/runtime/src/main/cpp/Timers.cpp @@ -294,7 +294,8 @@ int Timers::PumpTimerLoopCallback(int fd, int events, void *data) { thiz->addTask(task); } v8::Local cb = task->callback_.Get(isolate); - v8::Local context = cb->GetCreationContextChecked(); + Runtime* runtime = Runtime::GetRuntime(isolate); + v8::Local context = runtime->GetContext(); Context::Scope context_scope(context); TryCatch tc(isolate); auto argc = task->args_.get() == nullptr ? 0 : task->args_->size(); diff --git a/test-app/runtime/src/main/cpp/Timers.h b/test-app/runtime/src/main/cpp/Timers.h index 5f5dabd2e..ef6d8ccbb 100644 --- a/test-app/runtime/src/main/cpp/Timers.h +++ b/test-app/runtime/src/main/cpp/Timers.h @@ -6,6 +6,7 @@ #include "ObjectManager.h" #include "condition_variable" #include "thread" +#include "robin_hood.h" namespace tns { /** @@ -113,7 +114,7 @@ namespace tns { int currentTimerId = 0; int nesting = 0; // stores the map of timer tasks - std::map> timerMap_; + robin_hood::unordered_map> timerMap_; std::vector> sortedTimers_; // sets are faster than vector iteration // so we use this to avoid redundant isolate locks and we don't care about the diff --git a/test-app/runtime/src/main/cpp/V8GlobalHelpers.cpp b/test-app/runtime/src/main/cpp/V8GlobalHelpers.cpp index 2fc637848..cdeb715d2 100644 --- a/test-app/runtime/src/main/cpp/V8GlobalHelpers.cpp +++ b/test-app/runtime/src/main/cpp/V8GlobalHelpers.cpp @@ -5,11 +5,12 @@ #include "JEnv.h" #include "NativeScriptException.h" #include +#include "robin_hood.h" using namespace v8; using namespace std; -static std::map*> isolateToPersistentSmartJSONStringify = std::map*>(); +static robin_hood::unordered_map*> isolateToPersistentSmartJSONStringify = robin_hood::unordered_map*>(); Local GetSmartJSONStringifyFunction(Isolate* isolate) { auto it = isolateToPersistentSmartJSONStringify.find(isolate); @@ -61,7 +62,7 @@ Local GetSmartJSONStringifyFunction(Isolate* isolate) { auto smartStringifyPersistentFunction = new Persistent(isolate, smartStringifyFunction); - isolateToPersistentSmartJSONStringify.insert(std::make_pair(isolate, smartStringifyPersistentFunction)); + isolateToPersistentSmartJSONStringify.emplace(isolate, smartStringifyPersistentFunction); return smartStringifyPersistentFunction->Get(isolate); } From 643958b6a4c3698567edde3fd03052873b2644dc Mon Sep 17 00:00:00 2001 From: Eduardo Speroni Date: Wed, 29 Nov 2023 13:37:45 -0300 Subject: [PATCH 03/54] feat: use node module bindings like the iOS runtime (#1795) --- test-app/runtime/CMakeLists.txt | 1 + .../runtime/src/main/cpp/IsolateDisposer.cpp | 8 + .../runtime/src/main/cpp/IsolateDisposer.h | 27 + .../runtime/src/main/cpp/ModuleBinding.cpp | 101 ++++ test-app/runtime/src/main/cpp/ModuleBinding.h | 98 ++++ test-app/runtime/src/main/cpp/Runtime.cpp | 4 +- test-app/runtime/src/main/cpp/Runtime.h | 2 - test-app/runtime/src/main/cpp/Timers.cpp | 36 +- test-app/runtime/src/main/cpp/Timers.h | 2 + test-app/runtime/src/main/cpp/Util.cpp | 472 ++++++++++++++---- test-app/runtime/src/main/cpp/Util.h | 192 +++++++ 11 files changed, 836 insertions(+), 107 deletions(-) create mode 100644 test-app/runtime/src/main/cpp/ModuleBinding.cpp create mode 100644 test-app/runtime/src/main/cpp/ModuleBinding.h diff --git a/test-app/runtime/CMakeLists.txt b/test-app/runtime/CMakeLists.txt index 60b0a1714..13e770527 100644 --- a/test-app/runtime/CMakeLists.txt +++ b/test-app/runtime/CMakeLists.txt @@ -115,6 +115,7 @@ add_library( src/main/cpp/MetadataReader.cpp src/main/cpp/MetadataTreeNode.cpp src/main/cpp/MethodCache.cpp + src/main/cpp/ModuleBinding.cpp src/main/cpp/ModuleInternal.cpp src/main/cpp/NativeScriptException.cpp src/main/cpp/NumericCasts.cpp diff --git a/test-app/runtime/src/main/cpp/IsolateDisposer.cpp b/test-app/runtime/src/main/cpp/IsolateDisposer.cpp index b5453289a..c495f0dbe 100644 --- a/test-app/runtime/src/main/cpp/IsolateDisposer.cpp +++ b/test-app/runtime/src/main/cpp/IsolateDisposer.cpp @@ -9,11 +9,19 @@ #include + namespace tns { void disposeIsolate(v8::Isolate *isolate) { tns::ArgConverter::onDisposeIsolate(isolate); tns::MetadataNode::onDisposeIsolate(isolate); tns::V8GlobalHelpers::onDisposeIsolate(isolate); tns::Console::onDisposeIsolate(isolate); + // clear all isolate bound objects + std::lock_guard lock(isolateBoundObjectsMutex_); + auto it = isolateBoundObjects_.find(isolate); + if (it != isolateBoundObjects_.end()) { + it->second->clear(); + isolateBoundObjects_.erase(it); + } } } diff --git a/test-app/runtime/src/main/cpp/IsolateDisposer.h b/test-app/runtime/src/main/cpp/IsolateDisposer.h index 7ce85997c..7fdf757de 100644 --- a/test-app/runtime/src/main/cpp/IsolateDisposer.h +++ b/test-app/runtime/src/main/cpp/IsolateDisposer.h @@ -5,9 +5,36 @@ #ifndef TEST_APP_ISOLATEDISPOSER_H #define TEST_APP_ISOLATEDISPOSER_H #include "v8.h" +#include "robin_hood.h" +#include +#include +#include namespace tns { void disposeIsolate(v8::Isolate* isolate); + using unique_void_ptr = std::unique_ptr; + template + auto unique_void(T * ptr) -> unique_void_ptr + { + return unique_void_ptr(ptr, [](void const * data) { + T const * p = static_cast(data); + delete p; + }); + } + robin_hood::unordered_map>> isolateBoundObjects_; + std::mutex isolateBoundObjectsMutex_; + template + void registerIsolateBoundObject(v8::Isolate* isolate, T *ptr) { + std::lock_guard lock(isolateBoundObjectsMutex_); + auto it = isolateBoundObjects_.find(isolate); + if (it == isolateBoundObjects_.end()) { + auto vec = std::make_shared>(); + vec->push_back(unique_void(ptr)); + isolateBoundObjects_.emplace(isolate, vec); + } else { + it->second->push_back(unique_void(ptr)); + } + } } #endif //TEST_APP_ISOLATEDISPOSER_H diff --git a/test-app/runtime/src/main/cpp/ModuleBinding.cpp b/test-app/runtime/src/main/cpp/ModuleBinding.cpp new file mode 100644 index 000000000..5050ff1d5 --- /dev/null +++ b/test-app/runtime/src/main/cpp/ModuleBinding.cpp @@ -0,0 +1,101 @@ +// +// ModuleBinding.cpp +// NativeScript +// +// Created by Eduardo Speroni on 5/11/23. +// Copyright © 2023 Progress. All rights reserved. +// + +#include "ModuleBinding.h" + +// TODO: add here +//#define NSC_BUILTIN_STANDARD_BINDINGS(V) \ +//V(fs) + +#define NSC_BUILTIN_STANDARD_BINDINGS(V) + + +#define NSC_BUILTIN_BINDINGS(V) \ +NSC_BUILTIN_STANDARD_BINDINGS(V) + +// This is used to load built-in bindings. Instead of using +// __attribute__((constructor)), we call the _register_ +// function for each built-in bindings explicitly in +// binding::RegisterBuiltinBindings(). This is only forward declaration. +// The definitions are in each binding's implementation when calling +// the NODE_BINDING_CONTEXT_AWARE_INTERNAL. +#define V(modname) void _register_##modname(); +NSC_BUILTIN_BINDINGS(V) +#undef V + + + + +#define V(modname) \ + void _register_isolate_##modname(v8::Isolate* isolate, \ + v8::Local target); +NODE_BINDINGS_WITH_PER_ISOLATE_INIT(V) +#undef V + + + +using v8::Context; +using v8::EscapableHandleScope; +using v8::Exception; +using v8::FunctionCallbackInfo; +using v8::FunctionTemplate; +using v8::HandleScope; +using v8::Isolate; +using v8::Local; +using v8::Object; +using v8::String; +using v8::Value; + +namespace tns { +// Globals per process +static ns_module* modlist_internal; +static ns_module* modlist_linked; +static thread_local ns_module* thread_local_modpending; +bool node_is_initialized = false; + +extern "C" void nativescript_module_register(void* m) { + struct ns_module* mp = reinterpret_cast(m); + + if (mp->nm_flags & NM_F_INTERNAL) { + mp->nm_link = modlist_internal; + modlist_internal = mp; + } else if (!node_is_initialized) { + // "Linked" modules are included as part of the node project. + // Like builtins they are registered *before* node::Init runs. + mp->nm_flags = NM_F_LINKED; + mp->nm_link = modlist_linked; + modlist_linked = mp; + } else { + thread_local_modpending = mp; + } +} + +namespace binding { + +void RegisterBuiltinBindings() { +#define V(modname) _register_##modname(); + NSC_BUILTIN_BINDINGS(V) +#undef V +} + +void CreateInternalBindingTemplates(v8::Isolate* isolate, Local templ) { +#define V(modname) \ + do { \ + /*templ->InstanceTemplate()->SetInternalFieldCount( \ + BaseObject::kInternalFieldCount);*/ \ + _register_isolate_##modname(isolate, templ); \ + /*isolate_data->set_##modname##_binding(templ);*/ \ + } while (0); + NODE_BINDINGS_WITH_PER_ISOLATE_INIT(V) +#undef V +} + +}; + +}; + diff --git a/test-app/runtime/src/main/cpp/ModuleBinding.h b/test-app/runtime/src/main/cpp/ModuleBinding.h new file mode 100644 index 000000000..258b8d9bf --- /dev/null +++ b/test-app/runtime/src/main/cpp/ModuleBinding.h @@ -0,0 +1,98 @@ +// +// ModuleBinding.hpp +// NativeScript +// +// Created by Eduardo Speroni on 5/11/23. +// Copyright © 2023 Progress. All rights reserved. +// + +#ifndef ModuleBinding_hpp +#define ModuleBinding_hpp + +#include "v8.h" + + +namespace tns { + +#define NODE_BINDING_CONTEXT_AWARE_CPP(modname, regfunc, priv, flags) \ + static tns::ns_module _module = { \ + NODE_MODULE_VERSION, \ + flags, \ + nullptr, \ + __FILE__, \ + nullptr, \ + (tns::addon_context_register_func)(regfunc), \ + NODE_STRINGIFY(modname), \ + priv, \ + nullptr}; \ + void _register_##modname() { node_module_register(&_module); } + +#define NODE_BINDING_CONTEXT_AWARE_INTERNAL(modname, regfunc) \ + NODE_BINDING_CONTEXT_AWARE_CPP(modname, regfunc, nullptr, NM_F_INTERNAL) + + + + + + + + +#define NODE_BINDING_PER_ISOLATE_INIT(modname, per_isolate_func) \ + void _register_isolate_##modname(v8::Isolate* isolate, \ + v8::Local target) { \ + per_isolate_func(isolate, target); \ + } + + +// This is a helepr that gives the target as an ObjectTemplate (using target.PrototypeTemplate()) + +#define NODE_BINDING_PER_ISOLATE_INIT_OBJ(modname, per_isolate_func) \ + void _register_isolate_##modname(v8::Isolate* isolate, \ + v8::Local target) { \ + per_isolate_func(isolate, target->PrototypeTemplate()); \ + } + + +#define NODE_BINDINGS_WITH_PER_ISOLATE_INIT(V) \ +V(timers) + +enum { + NM_F_BUILTIN = 1 << 0, // Unused. + NM_F_LINKED = 1 << 1, + NM_F_INTERNAL = 1 << 2, + NM_F_DELETEME = 1 << 3, +}; + +typedef void (*addon_register_func)( + v8::Local exports, + v8::Local module, + void* priv); + +typedef void (*addon_context_register_func)( + v8::Local exports, + v8::Local module, + v8::Local context, + void* priv); + +struct ns_module { + int nm_version; + unsigned int nm_flags; + void* nm_dso_handle; + const char* nm_filename; + tns::addon_register_func nm_register_func; + tns::addon_context_register_func nm_context_register_func; + const char* nm_modname; + void* nm_priv; + struct ns_module* nm_link; +}; + +namespace binding { +void RegisterBuiltinBindings(); +void CreateInternalBindingTemplates(v8::Isolate* isolate, v8::Local templ); +}; + + +}; + + +#endif /* ModuleBinding_hpp */ diff --git a/test-app/runtime/src/main/cpp/Runtime.cpp b/test-app/runtime/src/main/cpp/Runtime.cpp index 45cfc5604..7e542170b 100644 --- a/test-app/runtime/src/main/cpp/Runtime.cpp +++ b/test-app/runtime/src/main/cpp/Runtime.cpp @@ -30,6 +30,7 @@ #include #include #include "File.h" +#include "ModuleBinding.h" #ifdef APPLICATION_IN_DEBUG // #include "NetworkDomainCallbackHandlers.h" @@ -500,6 +501,7 @@ Isolate* Runtime::PrepareV8Runtime(const string& filesPath, const string& native auto globalFunctionTemplate = FunctionTemplate::New(isolate); globalFunctionTemplate->SetClassName(ArgConverter::ConvertToV8String(isolate, "NativeScriptGlobalObject")); + tns::binding::CreateInternalBindingTemplates(isolate, globalFunctionTemplate); auto globalTemplate = ObjectTemplate::New(isolate, globalFunctionTemplate); const auto readOnlyFlags = static_cast(PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly); @@ -582,8 +584,6 @@ Isolate* Runtime::PrepareV8Runtime(const string& filesPath, const string& native CallbackHandlers::CreateGlobalCastFunctions(isolate, globalTemplate); - m_timers.Init(isolate, globalTemplate); - Local context = Context::New(isolate, nullptr, globalTemplate); auto global = context->Global(); diff --git a/test-app/runtime/src/main/cpp/Runtime.h b/test-app/runtime/src/main/cpp/Runtime.h index 848336ff7..995f76b89 100644 --- a/test-app/runtime/src/main/cpp/Runtime.h +++ b/test-app/runtime/src/main/cpp/Runtime.h @@ -94,8 +94,6 @@ class Runtime { WeakRef m_weakRef; - Timers m_timers; - Profiler m_profiler; MessageLoopTimer* m_loopTimer; diff --git a/test-app/runtime/src/main/cpp/Timers.cpp b/test-app/runtime/src/main/cpp/Timers.cpp index 939a9a6ab..31d417866 100644 --- a/test-app/runtime/src/main/cpp/Timers.cpp +++ b/test-app/runtime/src/main/cpp/Timers.cpp @@ -5,6 +5,9 @@ #include #include #include +#include "ModuleBinding.h" +#include "IsolateDisposer.h" +#include "Util.h" /** @@ -15,7 +18,6 @@ * ALL changes and scheduling of a TimerTask MUST be done when locked in an isolate to ensure consistency */ -using namespace tns; using namespace v8; // Takes a value and transform into a positive number @@ -43,22 +45,18 @@ static double now_ms() { return 1000.0 * res.tv_sec + (double) res.tv_nsec / 1e6; } +namespace tns { + + + void Timers::Init(v8::Isolate *isolate, v8::Local &globalObjectTemplate) { isolate_ = isolate; // TODO: remove the __ns__ prefix once this is validated - globalObjectTemplate->Set(ArgConverter::ConvertToV8String(isolate, "__ns__setTimeout"), - FunctionTemplate::New(isolate, SetTimeoutCallback, - External::New(isolate, this))); - globalObjectTemplate->Set(ArgConverter::ConvertToV8String(isolate, "__ns__setInterval"), - FunctionTemplate::New(isolate, SetIntervalCallback, - External::New(isolate, this))); - globalObjectTemplate->Set(ArgConverter::ConvertToV8String(isolate, "__ns__clearTimeout"), - FunctionTemplate::New(isolate, ClearTimer, - External::New(isolate, this))); - globalObjectTemplate->Set(ArgConverter::ConvertToV8String(isolate, "__ns__clearInterval"), - FunctionTemplate::New(isolate, ClearTimer, - External::New(isolate, this))); + SetMethod(isolate, globalObjectTemplate, "__ns__setTimeout", SetTimeoutCallback, External::New(isolate, this)); + SetMethod(isolate, globalObjectTemplate, "__ns__setInterval", SetIntervalCallback, External::New(isolate, this)); + SetMethod(isolate, globalObjectTemplate, "__ns__clearTimeout", ClearTimer, External::New(isolate, this)); + SetMethod(isolate, globalObjectTemplate, "__ns__clearInterval", ClearTimer, External::New(isolate, this)); auto res = pipe(fd_); assert(res != -1); res = fcntl(fd_[1], F_SETFL, O_NONBLOCK); @@ -324,4 +322,14 @@ int Timers::PumpTimerLoopCallback(int fd, int events, void *data) { } thiz->bufferFull.notify_one(); return 1; -} \ No newline at end of file +} + +void Timers::InitStatic(v8::Isolate* isolate, v8::Local globalObjectTemplate) { + auto timers = new Timers(); + timers->Init(isolate, globalObjectTemplate); + registerIsolateBoundObject(isolate, timers); +} + +}; + +NODE_BINDING_PER_ISOLATE_INIT_OBJ(timers, tns::Timers::InitStatic); \ No newline at end of file diff --git a/test-app/runtime/src/main/cpp/Timers.h b/test-app/runtime/src/main/cpp/Timers.h index ef6d8ccbb..eb55631aa 100644 --- a/test-app/runtime/src/main/cpp/Timers.h +++ b/test-app/runtime/src/main/cpp/Timers.h @@ -76,6 +76,8 @@ namespace tns { */ void Init(v8::Isolate *isolate, v8::Local &globalObjectTemplate); + static void InitStatic(v8::Isolate* isolate, v8::Local globalObjectTemplate); + /** * Disposes the timers. This will clear all references and stop all thread. * MUST be called in the same thread Init was called diff --git a/test-app/runtime/src/main/cpp/Util.cpp b/test-app/runtime/src/main/cpp/Util.cpp index c1cf1418f..990985f45 100644 --- a/test-app/runtime/src/main/cpp/Util.cpp +++ b/test-app/runtime/src/main/cpp/Util.cpp @@ -5,112 +5,113 @@ using namespace v8; using namespace std; -using namespace tns; +namespace tns { -string Util::JniClassPathToCanonicalName(const string& jniClassPath) { - std::string canonicalName; - const char prefix = jniClassPath[0]; + string Util::JniClassPathToCanonicalName(const string &jniClassPath) { + std::string canonicalName; - std::string rest; - int lastIndex; + const char prefix = jniClassPath[0]; - switch (prefix) { - case 'L': - canonicalName = jniClassPath.substr(1, jniClassPath.size() - 2); - std::replace(canonicalName.begin(), canonicalName.end(), '/', '.'); - std::replace(canonicalName.begin(), canonicalName.end(), '$', '.'); - break; + std::string rest; + int lastIndex; - case '[': - canonicalName = jniClassPath; - lastIndex = canonicalName.find_last_of('['); - rest = canonicalName.substr(lastIndex + 1); - canonicalName = canonicalName.substr(0, lastIndex + 1); - canonicalName.append(JniClassPathToCanonicalName(rest)); - break; + switch (prefix) { + case 'L': + canonicalName = jniClassPath.substr(1, jniClassPath.size() - 2); + std::replace(canonicalName.begin(), canonicalName.end(), '/', '.'); + std::replace(canonicalName.begin(), canonicalName.end(), '$', '.'); + break; - default: - // TODO: - canonicalName = jniClassPath; - break; + case '[': + canonicalName = jniClassPath; + lastIndex = canonicalName.find_last_of('['); + rest = canonicalName.substr(lastIndex + 1); + canonicalName = canonicalName.substr(0, lastIndex + 1); + canonicalName.append(JniClassPathToCanonicalName(rest)); + break; + + default: + // TODO: + canonicalName = jniClassPath; + break; + } + return canonicalName; } - return canonicalName; -} -void Util::SplitString(const string& str, const string& delimiters, vector& tokens) { - string::size_type delimPos = 0, tokenPos = 0, pos = 0; + void Util::SplitString(const string &str, const string &delimiters, vector &tokens) { + string::size_type delimPos = 0, tokenPos = 0, pos = 0; - if (str.length() < 1) { - return; - } + if (str.length() < 1) { + return; + } - while (true) { - delimPos = str.find_first_of(delimiters, pos); - tokenPos = str.find_first_not_of(delimiters, pos); + while (true) { + delimPos = str.find_first_of(delimiters, pos); + tokenPos = str.find_first_not_of(delimiters, pos); - if (string::npos != delimPos) { - if (string::npos != tokenPos) { - if (tokenPos < delimPos) { - tokens.push_back(str.substr(pos, delimPos - pos)); + if (string::npos != delimPos) { + if (string::npos != tokenPos) { + if (tokenPos < delimPos) { + tokens.push_back(str.substr(pos, delimPos - pos)); + } else { + tokens.emplace_back(""); + } } else { tokens.emplace_back(""); } + pos = delimPos + 1; } else { - tokens.emplace_back(""); - } - pos = delimPos + 1; - } else { - if (string::npos != tokenPos) { - tokens.push_back(str.substr(pos)); - } else { - tokens.emplace_back(""); + if (string::npos != tokenPos) { + tokens.push_back(str.substr(pos)); + } else { + tokens.emplace_back(""); + } + break; } - break; } } -} -bool Util::EndsWith(const string& str, const string& suffix) { - bool res = false; - if (str.size() > suffix.size()) { - res = equal(suffix.rbegin(), suffix.rend(), str.rbegin()); + bool Util::EndsWith(const string &str, const string &suffix) { + bool res = false; + if (str.size() > suffix.size()) { + res = equal(suffix.rbegin(), suffix.rend(), str.rbegin()); + } + return res; } - return res; -} - -string Util::ConvertFromJniToCanonicalName(const string& name) { - string converted = name; - replace(converted.begin(), converted.end(), '/', '.'); - return converted; -} -string Util::ConvertFromCanonicalToJniName(const string& name) { - string converted = name; - replace(converted.begin(), converted.end(), '.', '/'); - return converted; -} - -string Util::ReplaceAll(string& str, const string& from, const string& to) { - if (from.empty()) { - return str; + string Util::ConvertFromJniToCanonicalName(const string &name) { + string converted = name; + replace(converted.begin(), converted.end(), '/', '.'); + return converted; } - size_t start_pos = 0; - while ((start_pos = str.find(from, start_pos)) != string::npos) { - str.replace(start_pos, from.length(), to); - start_pos += to.length(); + string Util::ConvertFromCanonicalToJniName(const string &name) { + string converted = name; + replace(converted.begin(), converted.end(), '.', '/'); + return converted; } - return str; -} + string Util::ReplaceAll(string &str, const string &from, const string &to) { + if (from.empty()) { + return str; + } -u16string Util::ConvertFromUtf8ToUtf16(const string& str) { - auto utf16String = - std::wstring_convert, char16_t>().from_bytes(str); + size_t start_pos = 0; + while ((start_pos = str.find(from, start_pos)) != string::npos) { + str.replace(start_pos, from.length(), to); + start_pos += to.length(); + } + + return str; + } - return utf16String; -} + u16string Util::ConvertFromUtf8ToUtf16(const string &str) { + auto utf16String = + std::wstring_convert, char16_t>().from_bytes(str); + + return utf16String; + } //uint16_t* Util::ConvertFromUtf8ToProtocolUtf16(const string& str) { // auto utf16String = @@ -118,19 +119,312 @@ u16string Util::ConvertFromUtf8ToUtf16(const string& str) { // return (uint16_t *) utf16String.c_str(); //} -void Util::JoinString(const std::vector& list, const std::string& delimiter, - std::string& out) { - out.clear(); + void Util::JoinString(const std::vector &list, const std::string &delimiter, + std::string &out) { + out.clear(); - stringstream ss; + stringstream ss; - for (auto it = list.begin(); it != list.end(); ++it) { - ss << *it; + for (auto it = list.begin(); it != list.end(); ++it) { + ss << *it; - if (it != list.end() - 1) { - ss << delimiter; + if (it != list.end() - 1) { + ss << delimiter; + } } + + out = ss.str(); + } + + Local NewFunctionTemplate( + v8::Isolate *isolate, + v8::FunctionCallback callback, + Local data, + Local signature, + v8::ConstructorBehavior behavior, + v8::SideEffectType side_effect_type, + const v8::CFunction *c_function) { + return v8::FunctionTemplate::New(isolate, + callback, + data, + signature, + 0, + behavior, + side_effect_type, + c_function); } - out = ss.str(); -} \ No newline at end of file + void SetMethod(Local context, + Local that, + const char *name, + v8::FunctionCallback callback, + Local data) { + Isolate *isolate = context->GetIsolate(); + Local function = + NewFunctionTemplate(isolate, + callback, + data, + Local(), + v8::ConstructorBehavior::kThrow, + v8::SideEffectType::kHasSideEffect) + ->GetFunction(context) + .ToLocalChecked(); + // kInternalized strings are created in the old space. + const v8::NewStringType type = v8::NewStringType::kInternalized; + Local name_string = + v8::String::NewFromUtf8(isolate, name, type).ToLocalChecked(); + that->Set(context, name_string, function).Check(); + function->SetName(name_string); // NODE_SET_METHOD() compatibility. + } + + void SetMethod(v8::Isolate *isolate, + v8::Local that, + const char *name, + v8::FunctionCallback callback, + Local data) { + Local t = + NewFunctionTemplate(isolate, + callback, + data, + Local(), + v8::ConstructorBehavior::kThrow, + v8::SideEffectType::kHasSideEffect); + // kInternalized strings are created in the old space. + const v8::NewStringType type = v8::NewStringType::kInternalized; + Local name_string = + v8::String::NewFromUtf8(isolate, name, type).ToLocalChecked(); + that->Set(name_string, t); + } + + void SetFastMethod(Isolate *isolate, + Local