Skip to content

Commit dac1caa

Browse files
committed
Merge remote-tracking branch 'Nativescript/main'
2 parents d354220 + 7101127 commit dac1caa

File tree

2 files changed

+49
-8
lines changed

2 files changed

+49
-8
lines changed

NativeScript/runtime/ArgConverter.mm

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
#include <Foundation/Foundation.h>
22
#include <sstream>
3+
#include <unordered_set>
34
#include "ArgConverter.h"
45
#include "NativeScriptException.h"
56
#include "DictionaryAdapter.h"
67
#include "ObjectManager.h"
78
#include "Interop.h"
89
#include "Helpers.h"
910
#include "Runtime.h"
11+
#include "RuntimeConfig.h"
1012

1113
using namespace v8;
1214
using namespace std;
@@ -27,7 +29,27 @@
2729
bool callSuper = false;
2830
if (instanceMethod) {
2931
BaseDataWrapper* wrapper = tns::GetValue(isolate, receiver);
30-
tns::Assert(wrapper != nullptr, isolate);
32+
33+
if (wrapper == nullptr) {
34+
// During fast view churn like HMR in development, JS objects can outlive their
35+
// native wrappers briefly. In Debug, avoid a crash and just skip the native call.
36+
// In Release, assert so crash reporting can capture unexpected cases.
37+
if (RuntimeConfig.IsDebug) {
38+
const char* selectorStr = meta ? meta->selectorAsString() : "<unknown>";
39+
const char* jsNameStr = meta ? meta->jsName() : "<unknown>";
40+
const char* classNameStr = klass ? class_getName(klass) : "<unknown>";
41+
// Suppress duplicate logs: only log once per class+selector for this process.
42+
static std::unordered_set<std::string> s_logged;
43+
std::string key = std::string(classNameStr) + ":" + selectorStr;
44+
if (s_logged.insert(key).second) {
45+
Log(@"Note: ignore method on non-native receiver (class: %s, selector: %s, jsName: %s, args: %d). Common during HMR.",
46+
classNameStr, selectorStr, jsNameStr, (int)args.Length());
47+
}
48+
return v8::Undefined(isolate);
49+
} else {
50+
tns::Assert(false, isolate);
51+
}
52+
}
3153

3254
if (wrapper->Type() == WrapperType::ObjCAllocObject) {
3355
ObjCAllocDataWrapper* allocWrapper = static_cast<ObjCAllocDataWrapper*>(wrapper);
@@ -43,7 +65,21 @@
4365
// For extended classes we will call the base method
4466
callSuper = isMethodCallback && it != cache->ClassPrototypes.end();
4567
} else {
46-
tns::Assert(false, isolate);
68+
if (RuntimeConfig.IsDebug) {
69+
const char* selectorStr = meta ? meta->selectorAsString() : "<unknown>";
70+
const char* jsNameStr = meta ? meta->jsName() : "<unknown>";
71+
const char* classNameStr = klass ? class_getName(klass) : "<unknown>";
72+
// Suppress duplicate logs: only log once per class+selector for this process.
73+
static std::unordered_set<std::string> s_logged;
74+
std::string key = std::string(classNameStr) + ":" + selectorStr;
75+
if (s_logged.insert(key).second) {
76+
Log(@"Note: ignore receiver wrapper type %d (class: %s, selector: %s, jsName: %s). Common during HMR.",
77+
(int)wrapper->Type(), classNameStr, selectorStr, jsNameStr);
78+
}
79+
return v8::Undefined(isolate);
80+
} else {
81+
tns::Assert(false, isolate);
82+
}
4783
}
4884
}
4985

@@ -878,7 +914,7 @@
878914
Local<Object> thiz = args.This();
879915
Isolate* isolate = args.GetIsolate();
880916
BaseDataWrapper* wrapper = tns::GetValue(isolate, thiz);
881-
if (wrapper == nullptr && wrapper->Type() != WrapperType::ObjCObject) {
917+
if (wrapper == nullptr || wrapper->Type() != WrapperType::ObjCObject) {
882918
return;
883919
}
884920

NativeScript/runtime/SymbolLoader.mm

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,17 @@
22
#include "SymbolLoader.h"
33
#include "Helpers.h"
44
#include <dlfcn.h>
5+
#include <os/log.h>
56

67
namespace tns {
78

9+
// Unified logging: create a dedicated log for the SymbolLoader
10+
static os_log_t ns_symbolloader_log() {
11+
// Function-local static initialization is thread-safe in C++11+.
12+
static os_log_t log = os_log_create("@nativescript/ios", "SymbolLoader");
13+
return log;
14+
}
15+
816
class SymbolResolver {
917
public:
1018
virtual void* loadFunctionSymbol(const char* symbolName) = 0;
@@ -35,7 +43,7 @@ virtual bool load() override {
3543
CFErrorRef error = nullptr;
3644
bool loaded = CFBundleLoadExecutableAndReturnError(this->_bundle, &error);
3745
if (error) {
38-
NSLog(@"%s", [[(NSError*)error localizedDescription] UTF8String]);
46+
os_log_error(ns_symbolloader_log(), "%{public}s", [[(NSError*)error localizedDescription] UTF8String]);
3947
}
4048

4149
return loaded;
@@ -100,8 +108,6 @@ virtual bool load() override {
100108
NSURL* bundleUrl = [NSURL URLWithString:frameworkPathStr relativeToURL:baseUrl];
101109
if (CFBundleRef bundle = CFBundleCreate(kCFAllocatorDefault, (CFURLRef)bundleUrl)) {
102110
resolver = std::make_unique<CFBundleSymbolResolver>(bundle);
103-
} else {
104-
NSLog(@"NativeScript could not load bundle %s\n", bundleUrl.absoluteString.UTF8String);
105111
}
106112
} else if (module->libraries->count == 1) {
107113
if (module->isSystem()) {
@@ -110,10 +116,9 @@ virtual bool load() override {
110116
NSString* libraryPath = [NSString stringWithFormat:@"%@/lib%s.dylib", libsPath, module->libraries->first()->value().getName()];
111117

112118
if (void* library = dlopen(libraryPath.UTF8String, RTLD_LAZY | RTLD_LOCAL)) {
113-
NSLog(@"NativeScript loaded library %s\n", libraryPath.UTF8String);
114119
resolver = std::make_unique<DlSymbolResolver>(library);
115120
} else if (const char* libraryError = dlerror()) {
116-
NSLog(@"NativeScript could not load library %s, error: %s\n", libraryPath.UTF8String, libraryError);
121+
os_log_debug(ns_symbolloader_log(), "NativeScript could not load library %{public}s, error: %{public}s", libraryPath.UTF8String, libraryError);
117122
}
118123
}
119124
}

0 commit comments

Comments
 (0)