@@ -566,18 +566,12 @@ bool objectGetPathCanReadRuntimeProperty(id object,
566566constexpr const char * kNativeApiAppearanceClassNameExpando =
567567 " __nativeApiAppearanceClassName" ;
568568
569- Class appearanceProxyCustomizableClassFromDescription (id object) {
569+ Class appearanceProxyCustomizableClassFromExactDescription (id object) {
570570#if TARGET_OS_IPHONE
571571 if (object == nil ) {
572572 return Nil ;
573573 }
574574
575- const char * runtimeClassName = object_getClassName (object);
576- if (runtimeClassName == nullptr ||
577- std::strstr (runtimeClassName, " Appearance" ) == nullptr ) {
578- return Nil ;
579- }
580-
581575 NSString * description = [object description ];
582576 NSString * prefix = @" <Customizable class: " ;
583577 if (description.length <= prefix.length + 1 ||
@@ -594,6 +588,24 @@ Class appearanceProxyCustomizableClassFromDescription(id object) {
594588#endif
595589}
596590
591+ Class appearanceProxyCustomizableClassFromDescription (id object) {
592+ #if TARGET_OS_IPHONE
593+ if (object == nil ) {
594+ return Nil ;
595+ }
596+
597+ const char * runtimeClassName = object_getClassName (object);
598+ if (runtimeClassName == nullptr ||
599+ std::strstr (runtimeClassName, " Appearance" ) == nullptr ) {
600+ return Nil ;
601+ }
602+
603+ return appearanceProxyCustomizableClassFromExactDescription (object);
604+ #else
605+ return Nil ;
606+ #endif
607+ }
608+
597609Class taggedAppearanceProxyClass (
598610 Runtime& runtime, const std::shared_ptr<NativeApiBridge>& bridge,
599611 id object) {
@@ -617,6 +629,28 @@ Class taggedAppearanceProxyClass(
617629 return " __nativeApiAppearance:" + property;
618630}
619631
632+ Value cachedAppearanceProxyPropertyValue (
633+ Runtime& runtime, const std::shared_ptr<NativeApiBridge>& bridge,
634+ id object, const std::string& property) {
635+ if (Class appearanceClass =
636+ taggedAppearanceProxyClass (runtime, bridge, object)) {
637+ return bridge->findObjectExpando (
638+ runtime, appearanceClass, appearanceProxyExpandoPropertyKey (property));
639+ }
640+ return Value::undefined ();
641+ }
642+
643+ void cacheAppearanceProxyPropertyValue (
644+ Runtime& runtime, const std::shared_ptr<NativeApiBridge>& bridge,
645+ id object, const std::string& property, const Value& value) {
646+ if (Class appearanceClass =
647+ taggedAppearanceProxyClass (runtime, bridge, object)) {
648+ bridge->setObjectExpando (runtime, appearanceClass,
649+ appearanceProxyExpandoPropertyKey (property),
650+ value);
651+ }
652+ }
653+
620654class NativeApiSuperHostObject final : public HostObject {
621655 public:
622656 NativeApiSuperHostObject (std::shared_ptr<NativeApiBridge> bridge,
@@ -1300,13 +1334,10 @@ Value get(Runtime& runtime, const PropNameID& name) override {
13001334 if (!expando.isUndefined ()) {
13011335 return expando;
13021336 }
1303- if (Class appearanceClass =
1304- taggedAppearanceProxyClass (runtime, bridge_, object_)) {
1305- Value appearanceExpando = bridge_->findObjectExpando (
1306- runtime, appearanceClass, appearanceProxyExpandoPropertyKey (property));
1307- if (!appearanceExpando.isUndefined ()) {
1308- return appearanceExpando;
1309- }
1337+ Value appearanceExpando =
1338+ cachedAppearanceProxyPropertyValue (runtime, bridge_, object_, property);
1339+ if (!appearanceExpando.isUndefined ()) {
1340+ return appearanceExpando;
13101341 }
13111342
13121343 // Fast path: cached metadata property-getter resolution. Skips the
@@ -1778,12 +1809,8 @@ throw JSError(
17781809 Value args[] = {Value (runtime, value)};
17791810 callObjCSelector (runtime, bridge_, object_, false ,
17801811 setterMember.selectorName , &setterMember, args, 1 );
1781- if (Class appearanceClass =
1782- taggedAppearanceProxyClass (runtime, bridge_, object_)) {
1783- bridge_->setObjectExpando (
1784- runtime, appearanceClass,
1785- appearanceProxyExpandoPropertyKey (property), value);
1786- }
1812+ cacheAppearanceProxyPropertyValue (runtime, bridge_, object_, property,
1813+ value);
17871814 NATIVE_API_SET_RETURN (true );
17881815 }
17891816 }
@@ -1793,12 +1820,8 @@ throw JSError(
17931820 Value args[] = {Value (runtime, value)};
17941821 callObjCSelector (runtime, bridge_, object_, false ,
17951822 *setterSelectorName, nullptr , args, 1 );
1796- if (Class appearanceClass =
1797- taggedAppearanceProxyClass (runtime, bridge_, object_)) {
1798- bridge_->setObjectExpando (
1799- runtime, appearanceClass,
1800- appearanceProxyExpandoPropertyKey (property), value);
1801- }
1823+ cacheAppearanceProxyPropertyValue (runtime, bridge_, object_, property,
1824+ value);
18021825 if (!objectGetPathCanReadRuntimeProperty (object_, property)) {
18031826 bridge_->setObjectExpando (runtime, object_, property, value);
18041827 }
@@ -1864,7 +1887,12 @@ void tagStaticAppearanceNativeResult(
18641887 if (bridge == nullptr || appearanceClass == Nil || native == nil ) {
18651888 return ;
18661889 }
1867- const char * className = class_getName (appearanceClass);
1890+ Class customizableClass =
1891+ appearanceProxyCustomizableClassFromExactDescription (native);
1892+ if (customizableClass == Nil ) {
1893+ customizableClass = appearanceClass;
1894+ }
1895+ const char * className = class_getName (customizableClass);
18681896 if (className == nullptr || className[0 ] == ' \0 ' ) {
18691897 return ;
18701898 }
@@ -2139,9 +2167,7 @@ throw JSError(runtime,
21392167 .getHostObject <NativeApiObjectHostObject>(
21402168 runtime)
21412169 ->object ();
2142- bridge->setObjectExpando (
2143- runtime, native, kNativeApiAppearanceClassNameExpando ,
2144- makeString (runtime, symbol.runtimeName ));
2170+ tagStaticAppearanceNativeResult (runtime, bridge, cls, native);
21452171 }
21462172 }
21472173 return result;
@@ -2647,6 +2673,11 @@ Value makeProtocolPropertyGetter(Runtime& runtime, NativeApiMember member,
26472673 throw JSError (
26482674 runtime, " Protocol property requires a native receiver." );
26492675 }
2676+ Value appearanceExpando = cachedAppearanceProxyPropertyValue (
2677+ runtime, bridge, receiver, member.name );
2678+ if (!appearanceExpando.isUndefined ()) {
2679+ return appearanceExpando;
2680+ }
26502681 NativeApiMember getterMember = member;
26512682 if (auto selector = respondingPropertyGetterSelector (
26522683 receiver, member.name , member.selectorName )) {
@@ -2692,9 +2723,12 @@ throw JSError(
26922723 NativeApiMember setterMember = member;
26932724 setterMember.selectorName = member.setterSelectorName ;
26942725 setterMember.signatureOffset = member.setterSignatureOffset ;
2695- return callObjCSelector (runtime, bridge, receiver, receiverIsClass,
2696- setterMember.selectorName , &setterMember,
2697- args, 1 );
2726+ Value result = callObjCSelector (
2727+ runtime, bridge, receiver, receiverIsClass,
2728+ setterMember.selectorName , &setterMember, args, 1 );
2729+ cacheAppearanceProxyPropertyValue (runtime, bridge, receiver,
2730+ member.name , args[0 ]);
2731+ return result;
26982732 });
26992733 }
27002734
0 commit comments