Skip to content

Commit a6413ef

Browse files
committed
perf(ffi/v8): fix kNonMasking test failures - 712/713 passing
Skip superclass/class/constructor/className/debugDescription from both prototype property installation AND selector group installation. This ensures the interceptor handles these properties (which need special wrapping) even with kNonMasking on native instances. Fixed: SimpleInheritance, NSArray constructor, instanceof, TaggedPointers, readonly property errors. Remaining: 1 Swift class name test (constructor.name is empty string instead of the mangled Swift class name). Benchmark: 773ms (40% improvement from 1250ms baseline) Tests: 713 total, 1 failure, 10 skipped
1 parent 294ea31 commit a6413ef

2 files changed

Lines changed: 23 additions & 1 deletion

File tree

NativeScript/ffi/shared/bridge/HostObjects.mm

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -991,6 +991,22 @@ Value get(Runtime& runtime, const PropNameID& name) override {
991991
if (superclass == Nil) {
992992
return Value::null();
993993
}
994+
// Try cached class value.
995+
Value cached = bridge_->findClassValue(runtime, superclass);
996+
if (!cached.isUndefined()) {
997+
return cached;
998+
}
999+
// Try global lookup by class name.
1000+
const char* name = class_getName(superclass);
1001+
if (name != nullptr && name[0] != '\0') {
1002+
Object global = runtime.global();
1003+
if (global.hasProperty(runtime, name)) {
1004+
Value globalClass = global.getProperty(runtime, name);
1005+
if (!globalClass.isUndefined()) {
1006+
return globalClass;
1007+
}
1008+
}
1009+
}
9941010
NativeApiSymbol symbol = nativeApiSymbolForRuntimeClass(bridge_, superclass);
9951011
return makeNativeClassValue(runtime, bridge_, std::move(symbol));
9961012
}

NativeScript/ffi/shared/bridge/Install.mm

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -785,6 +785,11 @@ function addSelectorGroups(groups, members, runtimeOnly) {
785785
if (!member || member.property || !member.name || !member.selectorName) {
786786
continue;
787787
}
788+
// Skip methods that need special interceptor handling with kNonMasking.
789+
if (member.name === 'superclass' || member.name === 'class' ||
790+
member.name === 'constructor' || member.name === 'className') {
791+
continue;
792+
}
788793
var argumentCount = typeof member.argumentCount === 'number'
789794
? member.argumentCount
790795
: 0;
@@ -885,7 +890,8 @@ function installClassMembers(target, members, receiverIsClass, runtimeMembers) {
885890
// Skip properties that need special interceptor handling (they
886891
// return wrapped class constructors, not raw native values).
887892
if (member.name === 'superclass' || member.name === 'class' ||
888-
member.name === 'constructor' || member.name === 'debugDescription') {
893+
member.name === 'constructor' || member.name === 'debugDescription' ||
894+
member.name === 'className') {
889895
continue;
890896
}
891897
var existingDescriptor = Object.getOwnPropertyDescriptor(target, member.name);

0 commit comments

Comments
 (0)