@@ -1919,32 +1919,111 @@ Class tagStaticAppearanceNativeResult(
19191919 return customizableClass;
19201920}
19211921
1922- void installAppearanceProxyTargetPrototype (
1922+ std::shared_ptr<void > retainAppearanceProxyForAccessor (id native) {
1923+ id retained = [native retain ];
1924+ return std::shared_ptr<void >(static_cast <void *>(retained), [](void * value) {
1925+ [(id )value release ];
1926+ });
1927+ }
1928+
1929+ bool shouldInstallAppearanceProxyAccessor (const NativeApiMember& member) {
1930+ if (!member.property || member.name .empty ()) {
1931+ return false ;
1932+ }
1933+ bool memberIsStatic = (member.flags & metagen::mdMemberStatic) != 0 ;
1934+ if (memberIsStatic) {
1935+ return false ;
1936+ }
1937+ return member.name != " superclass" && member.name != " class" &&
1938+ member.name != " constructor" && member.name != " debugDescription" &&
1939+ member.name != " className" && member.name != " description" ;
1940+ }
1941+
1942+ Function makeAppearanceProxyPropertyGetter (
1943+ Runtime& runtime, std::shared_ptr<NativeApiBridge> bridge, id native,
1944+ std::shared_ptr<void > retainedNative, std::string property) {
1945+ return Function::createFromHostFunction (
1946+ runtime, PropNameID::forAscii (runtime, property.c_str ()), 0 ,
1947+ [bridge = std::move (bridge), native, retainedNative = std::move (retainedNative),
1948+ property = std::move (property)](Runtime& runtime, const Value&,
1949+ const Value*, size_t ) -> Value {
1950+ return cachedAppearanceProxyPropertyValue (runtime, bridge, native,
1951+ property);
1952+ });
1953+ }
1954+
1955+ Function makeAppearanceProxyPropertySetter (
1956+ Runtime& runtime, std::shared_ptr<NativeApiBridge> bridge, id native,
1957+ std::shared_ptr<void > retainedNative, NativeApiMember member) {
1958+ std::string functionName = member.setterSelectorName .empty ()
1959+ ? member.name
1960+ : member.setterSelectorName ;
1961+ return Function::createFromHostFunction (
1962+ runtime, PropNameID::forAscii (runtime, functionName.c_str ()), 1 ,
1963+ [bridge = std::move (bridge), native, retainedNative = std::move (retainedNative),
1964+ member = std::move (member)](Runtime& runtime, const Value&, const Value* args,
1965+ size_t count) -> Value {
1966+ if (count < 1 ) {
1967+ throw JSError (runtime,
1968+ " UIAppearance property setter expects a value." );
1969+ }
1970+ NativeApiMember setterMember = member;
1971+ setterMember.selectorName = member.setterSelectorName ;
1972+ setterMember.signatureOffset = member.setterSignatureOffset ;
1973+ Value setterArgs[] = {Value (runtime, args[0 ])};
1974+ callObjCSelector (runtime, bridge, native, false ,
1975+ setterMember.selectorName , &setterMember, setterArgs,
1976+ 1 );
1977+ cacheAppearanceProxyPropertyValue (runtime, bridge, native, member.name ,
1978+ args[0 ]);
1979+ return Value::undefined ();
1980+ });
1981+ }
1982+
1983+ void installAppearanceProxyPropertyAccessors (
19231984 Runtime& runtime, const std::shared_ptr<NativeApiBridge>& bridge,
1924- Class customizableClass, Object& resultObject) {
1985+ Class customizableClass, id native, Object& resultObject) {
19251986 if (bridge == nullptr || customizableClass == Nil ) {
19261987 return ;
19271988 }
1989+ const NativeApiSymbol* symbol =
1990+ bridge->findClassForRuntimeClass (customizableClass);
1991+ if (symbol == nullptr ) {
1992+ return ;
1993+ }
19281994
1929- Value prototypeValue =
1930- bridge->findClassPrototype (runtime, customizableClass);
1931- if (!prototypeValue.isObject ()) {
1932- Value classWrapperValue =
1933- bridge->findClassValue (runtime, customizableClass);
1934- if (!classWrapperValue.isObject ()) {
1935- classWrapperValue = makeNativeClassValue (
1936- runtime, bridge,
1937- nativeApiSymbolForRuntimeClass (bridge, customizableClass));
1938- }
1939- if (classWrapperValue.isObject ()) {
1940- prototypeValue =
1941- classWrapperValue.asObject (runtime).getProperty (runtime, " prototype" );
1995+ Object objectConstructor =
1996+ runtime.global ().getPropertyAsObject (runtime, " Object" );
1997+ Function defineProperty =
1998+ objectConstructor.getPropertyAsFunction (runtime, " defineProperty" );
1999+ std::unordered_set<std::string> installed;
2000+ std::shared_ptr<void > retainedNative =
2001+ retainAppearanceProxyForAccessor (native);
2002+ const auto & members = bridge->membersForClass (*symbol);
2003+ for (const auto & member : members) {
2004+ if (!shouldInstallAppearanceProxyAccessor (member) ||
2005+ !installed.insert (member.name ).second ) {
2006+ continue ;
19422007 }
1943- }
19442008
1945- if (prototypeValue.isObject ()) {
1946- Object prototype = prototypeValue.asObject (runtime);
1947- SetNativeApiObjectPrototype (runtime, resultObject, prototype);
2009+ try {
2010+ Object descriptor (runtime);
2011+ descriptor.setProperty (runtime, " configurable" , true );
2012+ descriptor.setProperty (runtime, " enumerable" , false );
2013+ descriptor.setProperty (
2014+ runtime, " get" ,
2015+ makeAppearanceProxyPropertyGetter (runtime, bridge, native,
2016+ retainedNative, member.name ));
2017+ if (!member.readonly && !member.setterSelectorName .empty ()) {
2018+ descriptor.setProperty (
2019+ runtime, " set" ,
2020+ makeAppearanceProxyPropertySetter (runtime, bridge, native,
2021+ retainedNative, member));
2022+ }
2023+ defineProperty.call (runtime, resultObject, makeString (runtime, member.name ),
2024+ descriptor);
2025+ } catch (const std::exception&) {
2026+ }
19482027 }
19492028}
19502029
@@ -1963,8 +2042,10 @@ Value tagStaticAppearanceSelectorResult(
19632042 Class customizableClass = tagStaticAppearanceNativeResult (
19642043 runtime, bridge, static_cast <Class >(receiver),
19652044 resultObject.getHostObject <NativeApiObjectHostObject>(runtime)->object ());
1966- installAppearanceProxyTargetPrototype (runtime, bridge, customizableClass,
1967- resultObject);
2045+ installAppearanceProxyPropertyAccessors (
2046+ runtime, bridge, customizableClass,
2047+ resultObject.getHostObject <NativeApiObjectHostObject>(runtime)->object (),
2048+ resultObject);
19682049 return result;
19692050}
19702051
@@ -2220,9 +2301,8 @@ throw JSError(runtime,
22202301 Class customizableClass =
22212302 tagStaticAppearanceNativeResult (runtime, bridge, cls,
22222303 native);
2223- installAppearanceProxyTargetPrototype (runtime, bridge,
2224- customizableClass,
2225- resultObject);
2304+ installAppearanceProxyPropertyAccessors (
2305+ runtime, bridge, customizableClass, native, resultObject);
22262306 }
22272307 }
22282308 return result;
0 commit comments