@@ -644,6 +644,41 @@ void cacheAppearanceProxyPropertyValue(
644644 }
645645}
646646
647+ const NativeApiMember* betterAppearanceProxyAccessorMember (
648+ const NativeApiMember* current, const NativeApiMember& candidate) {
649+ if (current == nullptr ) {
650+ return &candidate;
651+ }
652+ if (current->readonly != candidate.readonly ) {
653+ return candidate.readonly ? current : &candidate;
654+ }
655+ if (current->setterSelectorName .empty () &&
656+ !candidate.setterSelectorName .empty ()) {
657+ return &candidate;
658+ }
659+ if (current->signatureOffset == MD_SECTION_OFFSET_NULL &&
660+ candidate.signatureOffset != MD_SECTION_OFFSET_NULL ) {
661+ return &candidate;
662+ }
663+ return current;
664+ }
665+
666+ const NativeApiMember* selectAppearanceProxyPropertyMember (
667+ const std::vector<NativeApiMember>& members, const std::string& property) {
668+ const NativeApiMember* selected = nullptr ;
669+ for (const auto & member : members) {
670+ if (!member.property || member.name != property) {
671+ continue ;
672+ }
673+ bool memberIsStatic = (member.flags & metagen::mdMemberStatic) != 0 ;
674+ if (memberIsStatic) {
675+ continue ;
676+ }
677+ selected = betterAppearanceProxyAccessorMember (selected, member);
678+ }
679+ return selected;
680+ }
681+
647682class NativeApiSuperHostObject final : public HostObject {
648683 public:
649684 NativeApiSuperHostObject (std::shared_ptr<NativeApiBridge> bridge,
@@ -1787,34 +1822,13 @@ NativeApiHostSetResult set(Runtime& runtime, const PropNameID& name, const Value
17871822 throw JSError (runtime, " Cannot set property on nil object." );
17881823 }
17891824
1790- if (const NativeApiSymbol* symbol =
1791- bridge_->findClassForRuntimeClass (object_getClass (object_))) {
1792- const auto & members = bridge_->membersForClass (*symbol);
1793- if (const NativeApiMember* propertyMember =
1794- selectWritablePropertyMember (members, property, false )) {
1795- if (propertyMember->readonly ) {
1796- throw JSError (
1797- runtime, " Attempted to assign to readonly property." );
1798- }
1799- NativeApiMember setterMember = *propertyMember;
1800- setterMember.selectorName = propertyMember->setterSelectorName ;
1801- setterMember.signatureOffset = propertyMember->setterSignatureOffset ;
1802- Value args[] = {Value (runtime, value)};
1803- callObjCSelector (runtime, bridge_, object_, false ,
1804- setterMember.selectorName , &setterMember, args, 1 );
1805- cacheAppearanceProxyPropertyValue (runtime, bridge_, object_, property,
1806- value);
1807- NATIVE_API_SET_RETURN (true );
1808- }
1809- }
1810-
18111825 if (Class appearanceClass =
18121826 taggedAppearanceProxyClass (runtime, bridge_, object_)) {
18131827 if (const NativeApiSymbol* symbol =
18141828 bridge_->findClassForRuntimeClass (appearanceClass)) {
18151829 const auto & members = bridge_->membersForClass (*symbol);
18161830 if (const NativeApiMember* propertyMember =
1817- selectWritablePropertyMember (members, property, false )) {
1831+ selectAppearanceProxyPropertyMember (members, property)) {
18181832 if (propertyMember->readonly ) {
18191833 throw JSError (
18201834 runtime, " Attempted to assign to readonly property." );
@@ -1841,6 +1855,27 @@ throw JSError(
18411855 }
18421856 }
18431857
1858+ if (const NativeApiSymbol* symbol =
1859+ bridge_->findClassForRuntimeClass (object_getClass (object_))) {
1860+ const auto & members = bridge_->membersForClass (*symbol);
1861+ if (const NativeApiMember* propertyMember =
1862+ selectWritablePropertyMember (members, property, false )) {
1863+ if (propertyMember->readonly ) {
1864+ throw JSError (
1865+ runtime, " Attempted to assign to readonly property." );
1866+ }
1867+ NativeApiMember setterMember = *propertyMember;
1868+ setterMember.selectorName = propertyMember->setterSelectorName ;
1869+ setterMember.signatureOffset = propertyMember->setterSignatureOffset ;
1870+ Value args[] = {Value (runtime, value)};
1871+ callObjCSelector (runtime, bridge_, object_, false ,
1872+ setterMember.selectorName , &setterMember, args, 1 );
1873+ cacheAppearanceProxyPropertyValue (runtime, bridge_, object_, property,
1874+ value);
1875+ NATIVE_API_SET_RETURN (true );
1876+ }
1877+ }
1878+
18441879 if (auto setterSelectorName =
18451880 runtimeWritablePropertySetter (object_, property)) {
18461881 Value args[] = {Value (runtime, value)};
@@ -2013,15 +2048,20 @@ void installAppearanceProxyPropertyAccessors(
20132048 runtime.global ().getPropertyAsObject (runtime, " Object" );
20142049 Function defineProperty =
20152050 objectConstructor.getPropertyAsFunction (runtime, " defineProperty" );
2016- std::unordered_set<std::string> installed;
20172051 std::shared_ptr<void > retainedNative =
20182052 retainAppearanceProxyForAccessor (native);
20192053 const auto & members = bridge->membersForClass (*symbol);
2054+ std::unordered_map<std::string, const NativeApiMember*> accessors;
20202055 for (const auto & member : members) {
2021- if (!shouldInstallAppearanceProxyAccessor (member) ||
2022- !installed.insert (member.name ).second ) {
2056+ if (!shouldInstallAppearanceProxyAccessor (member)) {
20232057 continue ;
20242058 }
2059+ accessors[member.name] =
2060+ betterAppearanceProxyAccessorMember (accessors[member.name], member);
2061+ }
2062+
2063+ for (const auto & accessor : accessors) {
2064+ const NativeApiMember& member = *accessor.second ;
20252065
20262066 try {
20272067 Object descriptor (runtime);
0 commit comments