diff --git a/CHANGELOG.md b/CHANGELOG.md index d132ca7e..cd612211 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,15 @@ +## [8.9.1](https://github.com/NativeScript/ios/compare/v8.9.0...v8.9.1) (2025-02-28) + + +### Features + +* Ada 3.1.3 ([#270](https://github.com/NativeScript/ios/issues/270)) ([7081e5a](https://github.com/NativeScript/ios/commit/7081e5a50ee34f1d9edc1a6c3ae8a0cdbace30ec)) + + + # [8.9.0](https://github.com/NativeScript/ios/compare/v8.8.2...v8.9.0) (2025-02-24) diff --git a/NativeScript/runtime/ClassBuilder.cpp b/NativeScript/runtime/ClassBuilder.cpp index a748e27f..a0c1e657 100644 --- a/NativeScript/runtime/ClassBuilder.cpp +++ b/NativeScript/runtime/ClassBuilder.cpp @@ -1,28 +1,66 @@ #include "ClassBuilder.h" +#if TARGET_CPU_X86_64 || TARGET_CPU_X86 +#include "SpinLock.h" +#endif namespace tns { -// Moved this method in a separate .cpp file because ARC destroys the class created with objc_allocateClassPair -// when the control leaves this method scope - -Class ClassBuilder::GetExtendedClass(std::string baseClassName, std::string staticClassName) { - Class baseClass = objc_getClass(baseClassName.c_str()); - std::string name = !staticClassName.empty() ? staticClassName : baseClassName + "_" + std::to_string(++ClassBuilder::classNameCounter_); - Class clazz = objc_getClass(name.c_str()); - - if (clazz != nil) { - int i = 1; - std::string initialName = name; - while (clazz != nil) { - name = initialName + std::to_string(i++); - clazz = objc_getClass(name.c_str()); - } +// Moved this method in a separate .cpp file because ARC destroys the class +// created with objc_allocateClassPair when the control leaves this method scope +// TODO: revist this as there are x86 simulator issues, so maybe a lock is +// needed regardless +Class ClassBuilder::GetExtendedClass(std::string baseClassName, + std::string staticClassName) { +#if TARGET_CPU_X86_64 || TARGET_CPU_X86 + // X86 simulators have this bugged, so we fallback to old behavior + static SpinMutex m; + SpinLock lock(m); + Class baseClass = objc_getClass(baseClassName.c_str()); + std::string name = + !staticClassName.empty() + ? staticClassName + : baseClassName + "_" + + std::to_string(++ClassBuilder::classNameCounter_); + Class clazz = objc_getClass(name.c_str()); + + if (clazz != nil) { + int i = 1; + std::string initialName = name; + while (clazz != nil) { + name = initialName + std::to_string(i++); + clazz = objc_getClass(name.c_str()); } + } - clazz = objc_allocateClassPair(baseClass, name.c_str(), 0); + clazz = objc_allocateClassPair(baseClass, name.c_str(), 0); - objc_registerClassPair(clazz); - return clazz; -} + objc_registerClassPair(clazz); + return clazz; +#else + Class baseClass = objc_getClass(baseClassName.c_str()); + std::string name = + !staticClassName.empty() + ? staticClassName + : baseClassName + "_" + + std::to_string(++ClassBuilder::classNameCounter_); + // here we could either call objc_getClass with the name to see if the class + // already exists or we can just try allocating it, which will return nil if + // the class already exists so we try allocating it every time to avoid race + // conditions in case this method is being executed by multiple threads + Class clazz = objc_allocateClassPair(baseClass, name.c_str(), 0); + if (clazz == nil) { + int i = 1; + std::string initialName = name; + while (clazz == nil) { + name = initialName + std::to_string(i++); + clazz = objc_allocateClassPair(baseClass, name.c_str(), 0); + } + } + + objc_registerClassPair(clazz); + return clazz; +#endif } + +} // namespace tns diff --git a/NativeScript/runtime/ClassBuilder.mm b/NativeScript/runtime/ClassBuilder.mm index 53ec9f33..58a25b5a 100644 --- a/NativeScript/runtime/ClassBuilder.mm +++ b/NativeScript/runtime/ClassBuilder.mm @@ -309,18 +309,28 @@ return retain(self, @selector(retain)); } if ([self retainCount] == 1) { - auto innerCache = isolateWrapper.GetCache(); - auto it = innerCache->Instances.find(self); - if (it != innerCache->Instances.end()) { - v8::Locker locker(isolate); - Isolate::Scope isolate_scope(isolate); - HandleScope handle_scope(isolate); - Local value = it->second->Get(isolate); - BaseDataWrapper* wrapper = tns::GetValue(isolate, value); - if (wrapper != nullptr && wrapper->Type() == WrapperType::ObjCObject) { - ObjCDataWrapper* objcWrapper = static_cast(wrapper); - objcWrapper->GcProtect(); + auto runtime = Runtime::GetRuntime(isolate); + auto runtimeLoop = runtime->RuntimeLoop(); + void* weakSelf = (__bridge void*)self; + auto gcProtect = ^() { + auto innerCache = isolateWrapper.GetCache(); + auto it = innerCache->Instances.find((id)weakSelf); + if (it != innerCache->Instances.end()) { + v8::Locker locker(isolate); + Isolate::Scope isolate_scope(isolate); + HandleScope handle_scope(isolate); + Local value = it->second->Get(isolate); + BaseDataWrapper* wrapper = tns::GetValue(isolate, value); + if (wrapper != nullptr && wrapper->Type() == WrapperType::ObjCObject) { + ObjCDataWrapper* objcWrapper = static_cast(wrapper); + objcWrapper->GcProtect(); + } } + }; + if (CFRunLoopGetCurrent() != runtimeLoop) { + tns::ExecuteOnRunLoop(runtimeLoop, gcProtect); + } else { + gcProtect(); } } @@ -337,18 +347,42 @@ } if ([self retainCount] == 2) { - auto innerCache = isolateWrapper.GetCache(); - auto it = innerCache->Instances.find(self); - if (it != innerCache->Instances.end()) { - v8::Locker locker(isolate); - Isolate::Scope isolate_scope(isolate); - HandleScope handle_scope(isolate); - if (it->second != nullptr) { - Local value = it->second->Get(isolate); - BaseDataWrapper* wrapper = tns::GetValue(isolate, value); - if (wrapper != nullptr && wrapper->Type() == WrapperType::ObjCObject) { - ObjCDataWrapper* objcWrapper = static_cast(wrapper); - objcWrapper->GcUnprotect(); + void* weakSelf = (__bridge void*)self; + auto gcUnprotect = ^() { + auto innerCache = isolateWrapper.GetCache(); + auto it = innerCache->Instances.find((id)weakSelf); + if (it != innerCache->Instances.end()) { + v8::Locker locker(isolate); + Isolate::Scope isolate_scope(isolate); + HandleScope handle_scope(isolate); + if (it->second != nullptr) { + Local value = it->second->Get(isolate); + BaseDataWrapper* wrapper = tns::GetValue(isolate, value); + if (wrapper != nullptr && wrapper->Type() == WrapperType::ObjCObject) { + ObjCDataWrapper* objcWrapper = static_cast(wrapper); + objcWrapper->GcUnprotect(); + } + } + } + }; + auto runtime = Runtime::GetRuntime(isolate); + auto runtimeLoop = runtime->RuntimeLoop(); + if (CFRunLoopGetCurrent() != runtimeLoop) { + tns::ExecuteOnRunLoop(runtimeLoop, gcUnprotect); + } else { + auto innerCache = isolateWrapper.GetCache(); + auto it = innerCache->Instances.find(self); + if (it != innerCache->Instances.end()) { + v8::Locker locker(isolate); + Isolate::Scope isolate_scope(isolate); + HandleScope handle_scope(isolate); + if (it->second != nullptr) { + Local value = it->second->Get(isolate); + BaseDataWrapper* wrapper = tns::GetValue(isolate, value); + if (wrapper != nullptr && wrapper->Type() == WrapperType::ObjCObject) { + ObjCDataWrapper* objcWrapper = static_cast(wrapper); + objcWrapper->GcUnprotect(); + } } } } @@ -952,4 +986,4 @@ unsigned long long ClassBuilder::classNameCounter_ = 0; -} +} // namespace tns pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy