From 662d6b534e7e0ecbbb28cddf9c1bce9e68a1454b Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Wed, 23 Jul 2025 12:48:59 +1000 Subject: [PATCH 1/2] Fix #2419 --- pkgs/ffigen/CHANGELOG.md | 2 + pkgs/ffigen/lib/src/code_generator/func.dart | 35 +- .../lib/src/code_generator/objc_methods.dart | 91 ++++- .../visitor/copy_methods_from_super_type.dart | 20 +- .../inherited_instancetype_test.m | 5 + .../src/objective_c_bindings_generated.dart | 331 ++---------------- .../src/objective_c_bindings_generated.m | 22 +- 7 files changed, 154 insertions(+), 352 deletions(-) diff --git a/pkgs/ffigen/CHANGELOG.md b/pkgs/ffigen/CHANGELOG.md index ddae799346..ff4fc1fcf0 100644 --- a/pkgs/ffigen/CHANGELOG.md +++ b/pkgs/ffigen/CHANGELOG.md @@ -14,6 +14,8 @@ object may change, but the underlying ObjC object will still be the same. In any case, you should be using `Foo.isInstance(x)` instead of `x is Foo` to check the runtime type of an ObjC object. +- Fix [a bug](https://github.com/dart-lang/native/issues/2419) where methods + copied from super types might not be renamed correctly. ## 19.1.0 diff --git a/pkgs/ffigen/lib/src/code_generator/func.dart b/pkgs/ffigen/lib/src/code_generator/func.dart index f59808d513..9794f4c977 100644 --- a/pkgs/ffigen/lib/src/code_generator/func.dart +++ b/pkgs/ffigen/lib/src/code_generator/func.dart @@ -234,17 +234,30 @@ class Parameter extends AstNode { String name; Type type; final bool objCConsumed; - bool isCovariant = false; + bool isCovariant; + + Parameter._({ + required this.originalName, + required this.name, + required this.type, + required this.objCConsumed, + required this.isCovariant, + }); Parameter({ String? originalName, - this.name = '', + String name = '', required Type type, - required this.objCConsumed, - }) : originalName = originalName ?? name, - // A [NativeFunc] is wrapped with a pointer because this is a shorthand - // used in C for Pointer to function. - type = type.typealiasType is NativeFunc ? PointerType(type) : type; + required bool objCConsumed, + }) : this._( + originalName: originalName ?? name, + name: name, + // A [NativeFunc] is wrapped with a pointer because this is a shorthand + // used in C for Pointer to function. + type: type.typealiasType is NativeFunc ? PointerType(type) : type, + objCConsumed: objCConsumed, + isCovariant: false, + ); String getNativeType({String varName = ''}) => '${type.getNativeType(varName: varName)}' @@ -260,4 +273,12 @@ class Parameter extends AstNode { } bool get isNullable => type.typealiasType is ObjCNullable; + + Parameter clone() => Parameter._( + originalName: originalName, + name: name, + type: type, + objCConsumed: objCConsumed, + isCovariant: isCovariant, + ); } diff --git a/pkgs/ffigen/lib/src/code_generator/objc_methods.dart b/pkgs/ffigen/lib/src/code_generator/objc_methods.dart index 8389022ddc..6012a31bd2 100644 --- a/pkgs/ffigen/lib/src/code_generator/objc_methods.dart +++ b/pkgs/ffigen/lib/src/code_generator/objc_methods.dart @@ -30,6 +30,8 @@ mixin ObjCMethods { void addMethod(ObjCMethod? method) { if (method == null) return; + assert(!method._added); + method._added = true; final oldMethod = getSimilarMethod(method); if (oldMethod != null) { _methods[method.key] = _maybeReplaceMethod(oldMethod, method); @@ -39,6 +41,11 @@ mixin ObjCMethods { } } + void copyMethod(ObjCMethod method) { + assert(method._added); + addMethod(method.clone()); + } + void visitMethods(Visitor visitor) { visitor.visitAll(_methods.values); } @@ -194,7 +201,7 @@ class ObjCMethod extends AstNode { final String originalName; String name; String? dartMethodName; - late final String protocolMethodName; + final String protocolMethodName; final ObjCProperty? property; Type returnType; final List params; @@ -204,10 +211,11 @@ class ObjCMethod extends AstNode { ObjCMethodOwnership? ownershipAttribute; final ObjCMethodFamily? family; final ApiAvailability apiAvailability; - bool consumesSelfAttribute = false; + bool consumesSelfAttribute; ObjCInternalGlobal selObject; ObjCMsgSendFunc? msgSend; ObjCBlock? protocolBlock; + bool _added = false; @override void visitChildren(Visitor visitor) { @@ -220,26 +228,65 @@ class ObjCMethod extends AstNode { visitor.visit(protocolBlock); } - ObjCMethod({ + ObjCMethod._({ required this.builtInFunctions, + required this.dartDoc, required this.originalName, required this.name, - this.property, - this.dartDoc, + required this.dartMethodName, + required this.protocolMethodName, + required this.property, + required this.returnType, + required this.params, required this.kind, required this.isClassMethod, required this.isOptional, - required this.returnType, + required this.ownershipAttribute, required this.family, required this.apiAvailability, + required this.consumesSelfAttribute, + required this.selObject, + required this.msgSend, + required this.protocolBlock, + }); + + ObjCMethod({ + required ObjCBuiltInFunctions builtInFunctions, + required String originalName, + required String name, + ObjCProperty? property, + String? dartDoc, + required ObjCMethodKind kind, + required bool isClassMethod, + required bool isOptional, + required Type returnType, + required ObjCMethodFamily? family, + required ApiAvailability apiAvailability, List? params_, - }) : params = params_ ?? [], - selObject = builtInFunctions.getSelObject(originalName); + }) : this._( + builtInFunctions: builtInFunctions, + dartDoc: dartDoc, + originalName: originalName, + name: name, + dartMethodName: null, + protocolMethodName: name.replaceAll(':', '_'), + property: property, + returnType: returnType, + params: params_ ?? [], + kind: kind, + isClassMethod: isClassMethod, + isOptional: isOptional, + ownershipAttribute: null, + family: family, + apiAvailability: apiAvailability, + consumesSelfAttribute: false, + selObject: builtInFunctions.getSelObject(originalName), + msgSend: null, + protocolBlock: null, + ); // Must be called after all params are added to the method. void finalizeParams() { - protocolMethodName = name.replaceAll(':', '_'); - // Split the name at the ':'. The first chunk is the name of the method, and // the rest of the chunks are named parameters. Eg NSString's // - compare:options:range: @@ -273,6 +320,30 @@ class ObjCMethod extends AstNode { } } + // Not a super deep clone. Only clones this object and its params. Other + // fields are identitcal. It's not necessary to call [finalizeParams] again. + ObjCMethod clone() => ObjCMethod._( + builtInFunctions: builtInFunctions, + dartDoc: dartDoc, + originalName: originalName, + name: name, + dartMethodName: dartMethodName, + protocolMethodName: protocolMethodName, + property: property, + returnType: returnType, + params: [for (final p in params) p.clone()], + kind: kind, + isClassMethod: isClassMethod, + isOptional: isOptional, + ownershipAttribute: ownershipAttribute, + family: family, + apiAvailability: apiAvailability, + consumesSelfAttribute: consumesSelfAttribute, + selObject: selObject, + msgSend: msgSend, + protocolBlock: protocolBlock, + ); + bool get isProperty => kind == ObjCMethodKind.propertyGetter || kind == ObjCMethodKind.propertySetter; diff --git a/pkgs/ffigen/lib/src/visitor/copy_methods_from_super_type.dart b/pkgs/ffigen/lib/src/visitor/copy_methods_from_super_type.dart index 7a84d10778..16115944d9 100644 --- a/pkgs/ffigen/lib/src/visitor/copy_methods_from_super_type.dart +++ b/pkgs/ffigen/lib/src/visitor/copy_methods_from_super_type.dart @@ -49,18 +49,18 @@ class CopyMethodsFromSuperTypesVisitation extends Visitation { if (superType != null) { for (final m in superType.methods) { if (isNSObject) { - node.addMethod(m); + node.copyMethod(m); } else if (m.isClassMethod && !_excludedNSObjectMethods.contains(m.originalName)) { - node.addMethod(m); + node.copyMethod(m); } else if (ObjCBuiltInFunctions.isInstanceType(m.returnType)) { - node.addMethod(m); + node.copyMethod(m); } } } // Copy all methods from all the interface's protocols. - _copyMethodFromProtocols(node, node.protocols, node.addMethod); + _copyMethodFromProtocols(node, node.protocols, node.copyMethod); // Copy methods from all the categories that extend this interface, if those // methods return instancetype, because the Dart inheritance rules don't @@ -74,7 +74,7 @@ class CopyMethodsFromSuperTypesVisitation extends Visitation { for (final category in node.categories) { for (final m in category.methods) { if (category.shouldCopyMethodToInterface(m)) { - node.addMethod(m); + node.copyMethod(m); } } } @@ -83,16 +83,16 @@ class CopyMethodsFromSuperTypesVisitation extends Visitation { void _copyMethodFromProtocols( Binding node, List protocols, - void Function(ObjCMethod) addMethod, + void Function(ObjCMethod) copyMethod, ) { // Copy all methods from all the protocols. final isNSObject = ObjCBuiltInFunctions.isNSObject(node.originalName); for (final proto in protocols) { for (final m in proto.methods) { if (isNSObject) { - addMethod(m); + copyMethod(m); } else if (!_excludedNSObjectMethods.contains(m.originalName)) { - addMethod(m); + copyMethod(m); } } } @@ -103,7 +103,7 @@ class CopyMethodsFromSuperTypesVisitation extends Visitation { node.visitChildren(visitor); // Copy all methods from all the category's protocols. - _copyMethodFromProtocols(node, node.protocols, node.addMethod); + _copyMethodFromProtocols(node, node.protocols, node.copyMethod); } @override @@ -124,7 +124,7 @@ class CopyMethodsFromSuperTypesVisitation extends Visitation { // So copy across all the methods explicitly, rather than trying to use // Dart inheritance to get them implicitly. for (final method in superProtocol.methods) { - node.addMethod(method); + node.copyMethod(method); } } } diff --git a/pkgs/ffigen/test/native_objc_test/inherited_instancetype_test.m b/pkgs/ffigen/test/native_objc_test/inherited_instancetype_test.m index 8f1b20b883..848d62880e 100644 --- a/pkgs/ffigen/test/native_objc_test/inherited_instancetype_test.m +++ b/pkgs/ffigen/test/native_objc_test/inherited_instancetype_test.m @@ -7,9 +7,14 @@ @interface BaseClass : NSObject {} + (instancetype)create; - (instancetype)getSelf; + +// Regression test for https://github.com/dart-lang/native/issues/2419. +- (instancetype) initRegress2419:(int32_t) i; @end @interface ChildClass : BaseClass {} +- (instancetype) initRegress2419:(int32_t) i floatValue:(float) f; + @property int32_t field; @end diff --git a/pkgs/objective_c/lib/src/objective_c_bindings_generated.dart b/pkgs/objective_c/lib/src/objective_c_bindings_generated.dart index c5c9866228..b2401d343c 100644 --- a/pkgs/objective_c/lib/src/objective_c_bindings_generated.dart +++ b/pkgs/objective_c/lib/src/objective_c_bindings_generated.dart @@ -132,23 +132,6 @@ set NSLocalizedDescriptionKey(NSString value) { _NSLocalizedDescriptionKey = value.ref.retainAndReturnPointer(); } -@ffi.Native< - instancetype Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer>, - ) ->() -external instancetype _ObjectiveCBindings_protocolTrampoline_10z9f5k( - ffi.Pointer target, - ffi.Pointer arg0, - ffi.Pointer arg1, - ffi.Pointer arg2, - ffi.Pointer> arg3, -); - @ffi.Native< ffi.UnsignedLong Function( ffi.Pointer, @@ -3913,14 +3896,14 @@ extension NSEnumerator$Methods on NSEnumerator { int countByEnumeratingWithState( ffi.Pointer state, { required ffi.Pointer> objects, - required int count$1, + required int count, }) { return _objc_msgSend_1b5ysjl( this.ref.pointer, _sel_countByEnumeratingWithState_objects_count_, state, objects, - count$1, + count, ); } @@ -9365,13 +9348,13 @@ extension NSMutableArray$Methods on NSMutableArray { /// initWithObjects:count: NSMutableArray initWithObjects$1( ffi.Pointer> objects, { - required int count$1, + required int count, }) { final _ret = _objc_msgSend_zmbtbd( this.ref.retainAndReturnPointer(), _sel_initWithObjects_count_, objects, - count$1, + count, ); return NSMutableArray.castFromPointer(_ret, retain: false, release: true); } @@ -9823,13 +9806,13 @@ extension NSMutableData$Methods on NSMutableData { /// initWithBytes:length: NSMutableData initWithBytes( - ffi.Pointer bytes$1, { + ffi.Pointer bytes, { required int length, }) { final _ret = _objc_msgSend_3nbx5e( this.ref.retainAndReturnPointer(), _sel_initWithBytes_length_, - bytes$1, + bytes, length, ); return NSMutableData.castFromPointer(_ret, retain: false, release: true); @@ -9837,13 +9820,13 @@ extension NSMutableData$Methods on NSMutableData { /// initWithBytesNoCopy:length: NSMutableData initWithBytesNoCopy( - ffi.Pointer bytes$1, { + ffi.Pointer bytes, { required int length, }) { final _ret = _objc_msgSend_3nbx5e( this.ref.retainAndReturnPointer(), _sel_initWithBytesNoCopy_length_, - bytes$1, + bytes, length, ); return NSMutableData.castFromPointer(_ret, retain: false, release: true); @@ -9851,7 +9834,7 @@ extension NSMutableData$Methods on NSMutableData { /// initWithBytesNoCopy:length:deallocator: NSMutableData initWithBytesNoCopy$1( - ffi.Pointer bytes$1, { + ffi.Pointer bytes, { required int length, objc.ObjCBlock, ffi.UnsignedLong)>? deallocator, @@ -9864,7 +9847,7 @@ extension NSMutableData$Methods on NSMutableData { final _ret = _objc_msgSend_134vhyh( this.ref.retainAndReturnPointer(), _sel_initWithBytesNoCopy_length_deallocator_, - bytes$1, + bytes, length, deallocator?.ref.pointer ?? ffi.nullptr, ); @@ -9873,14 +9856,14 @@ extension NSMutableData$Methods on NSMutableData { /// initWithBytesNoCopy:length:freeWhenDone: NSMutableData initWithBytesNoCopy$2( - ffi.Pointer bytes$1, { + ffi.Pointer bytes, { required int length, required bool freeWhenDone, }) { final _ret = _objc_msgSend_161ne8y( this.ref.retainAndReturnPointer(), _sel_initWithBytesNoCopy_length_freeWhenDone_, - bytes$1, + bytes, length, freeWhenDone, ); @@ -10327,14 +10310,14 @@ extension NSMutableDictionary$Methods on NSMutableDictionary { NSMutableDictionary initWithObjects$1( ffi.Pointer> objects, { required ffi.Pointer> forKeys, - required int count$1, + required int count, }) { final _ret = _objc_msgSend_1dydpdi( this.ref.retainAndReturnPointer(), _sel_initWithObjects_forKeys_count_, objects, forKeys, - count$1, + count, ); return NSMutableDictionary.castFromPointer( _ret, @@ -14809,14 +14792,14 @@ extension NSOrderedCollectionDifference$Methods int countByEnumeratingWithState( ffi.Pointer state, { required ffi.Pointer> objects, - required int count$1, + required int count, }) { return _objc_msgSend_1b5ysjl( this.ref.pointer, _sel_countByEnumeratingWithState_objects_count_, state, objects, - count$1, + count, ); } @@ -15420,7 +15403,7 @@ extension NSOrderedSet$Methods on NSOrderedSet { /// initWithObjects:count: NSOrderedSet initWithObjects$1( ffi.Pointer> objects, { - required int count, + required int count$1, }) { objc.checkOsVersionInternal( 'NSOrderedSet.initWithObjects:count:', @@ -15431,7 +15414,7 @@ extension NSOrderedSet$Methods on NSOrderedSet { this.ref.retainAndReturnPointer(), _sel_initWithObjects_count_, objects, - count, + count$1, ); return NSOrderedSet.castFromPointer(_ret, retain: false, release: true); } @@ -17694,13 +17677,13 @@ extension NSSet$Methods on NSSet { /// initWithObjects:count: NSSet initWithObjects$1( ffi.Pointer> objects, { - required int count, + required int count$1, }) { final _ret = _objc_msgSend_zmbtbd( this.ref.retainAndReturnPointer(), _sel_initWithObjects_count_, objects, - count, + count$1, ); return NSSet.castFromPointer(_ret, retain: false, release: true); } @@ -33101,263 +33084,6 @@ extension ObjCBlock_instancetype_ffiVoid_NSCoder_CallExtension ); } -instancetype -_ObjCBlock_instancetype_ffiVoid_NSData_NSString_NSError_fnPtrTrampoline( - ffi.Pointer block, - ffi.Pointer arg0, - ffi.Pointer arg1, - ffi.Pointer arg2, - ffi.Pointer> arg3, -) => block.ref.target - .cast< - ffi.NativeFunction< - instancetype Function( - ffi.Pointer arg0, - ffi.Pointer arg1, - ffi.Pointer arg2, - ffi.Pointer> arg3, - ) - > - >() - .asFunction< - instancetype Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer>, - ) - >()(arg0, arg1, arg2, arg3); -ffi.Pointer -_ObjCBlock_instancetype_ffiVoid_NSData_NSString_NSError_fnPtrCallable = - ffi.Pointer.fromFunction< - instancetype Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer>, - ) - >(_ObjCBlock_instancetype_ffiVoid_NSData_NSString_NSError_fnPtrTrampoline) - .cast(); -instancetype -_ObjCBlock_instancetype_ffiVoid_NSData_NSString_NSError_closureTrampoline( - ffi.Pointer block, - ffi.Pointer arg0, - ffi.Pointer arg1, - ffi.Pointer arg2, - ffi.Pointer> arg3, -) => - (objc.getBlockClosure(block) - as instancetype Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer>, - ))(arg0, arg1, arg2, arg3); -ffi.Pointer -_ObjCBlock_instancetype_ffiVoid_NSData_NSString_NSError_closureCallable = - ffi.Pointer.fromFunction< - instancetype Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer>, - ) - >(_ObjCBlock_instancetype_ffiVoid_NSData_NSString_NSError_closureTrampoline) - .cast(); - -/// Construction methods for `objc.ObjCBlock? Function(ffi.Pointer, NSData, NSString, ffi.Pointer>)>`. -abstract final class ObjCBlock_instancetype_ffiVoid_NSData_NSString_NSError { - /// Returns a block that wraps the given raw block pointer. - static objc.ObjCBlock< - ffi.Pointer? Function( - ffi.Pointer, - NSData, - NSString, - ffi.Pointer>, - ) - > - castFromPointer( - ffi.Pointer pointer, { - bool retain = false, - bool release = false, - }) => - objc.ObjCBlock< - ffi.Pointer? Function( - ffi.Pointer, - NSData, - NSString, - ffi.Pointer>, - ) - >(pointer, retain: retain, release: release); - - /// Creates a block from a C function pointer. - /// - /// This block must be invoked by native code running on the same thread as - /// the isolate that registered it. Invoking the block on the wrong thread - /// will result in a crash. - static objc.ObjCBlock< - ffi.Pointer? Function( - ffi.Pointer, - NSData, - NSString, - ffi.Pointer>, - ) - > - fromFunctionPointer( - ffi.Pointer< - ffi.NativeFunction< - instancetype Function( - ffi.Pointer arg0, - ffi.Pointer arg1, - ffi.Pointer arg2, - ffi.Pointer> arg3, - ) - > - > - ptr, - ) => - objc.ObjCBlock< - ffi.Pointer? Function( - ffi.Pointer, - NSData, - NSString, - ffi.Pointer>, - ) - >( - objc.newPointerBlock( - _ObjCBlock_instancetype_ffiVoid_NSData_NSString_NSError_fnPtrCallable, - ptr.cast(), - ), - retain: false, - release: true, - ); - - /// Creates a block from a Dart function. - /// - /// This block must be invoked by native code running on the same thread as - /// the isolate that registered it. Invoking the block on the wrong thread - /// will result in a crash. - /// - /// If `keepIsolateAlive` is true, this block will keep this isolate alive - /// until it is garbage collected by both Dart and ObjC. - static objc.ObjCBlock< - ffi.Pointer? Function( - ffi.Pointer, - NSData, - NSString, - ffi.Pointer>, - ) - > - fromFunction( - Dartinstancetype? Function( - ffi.Pointer, - NSData, - NSString, - ffi.Pointer>, - ) - fn, { - bool keepIsolateAlive = true, - }) => - objc.ObjCBlock< - ffi.Pointer? Function( - ffi.Pointer, - NSData, - NSString, - ffi.Pointer>, - ) - >( - objc.newClosureBlock( - _ObjCBlock_instancetype_ffiVoid_NSData_NSString_NSError_closureCallable, - ( - ffi.Pointer arg0, - ffi.Pointer arg1, - ffi.Pointer arg2, - ffi.Pointer> arg3, - ) => - fn( - arg0, - NSData.castFromPointer(arg1, retain: true, release: true), - NSString.castFromPointer(arg2, retain: true, release: true), - arg3, - )?.ref.retainAndAutorelease() ?? - ffi.nullptr, - keepIsolateAlive, - ), - retain: false, - release: true, - ); -} - -/// Call operator for `objc.ObjCBlock? Function(ffi.Pointer, NSData, NSString, ffi.Pointer>)>`. -extension ObjCBlock_instancetype_ffiVoid_NSData_NSString_NSError_CallExtension - on - objc.ObjCBlock< - ffi.Pointer? Function( - ffi.Pointer, - NSData, - NSString, - ffi.Pointer>, - ) - > { - Dartinstancetype? call( - ffi.Pointer arg0, - NSData arg1, - NSString arg2, - ffi.Pointer> arg3, - ) => - ref.pointer.ref.invoke - .cast< - ffi.NativeFunction< - instancetype Function( - ffi.Pointer block, - ffi.Pointer arg0, - ffi.Pointer arg1, - ffi.Pointer arg2, - ffi.Pointer> arg3, - ) - > - >() - .asFunction< - instancetype Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer>, - ) - >()(ref.pointer, arg0, arg1.ref.pointer, arg2.ref.pointer, arg3) - .address == - 0 - ? null - : objc.ObjCObjectBase( - ref.pointer.ref.invoke - .cast< - ffi.NativeFunction< - instancetype Function( - ffi.Pointer block, - ffi.Pointer arg0, - ffi.Pointer arg1, - ffi.Pointer arg2, - ffi.Pointer> arg3, - ) - > - >() - .asFunction< - instancetype Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer>, - ) - >()(ref.pointer, arg0, arg1.ref.pointer, arg2.ref.pointer, arg3), - retain: true, - release: true, - ); -} - ffi.Pointer _ObjCBlock_objcObjCObject_NSError_NSErrorUserInfoKey_fnPtrTrampoline( ffi.Pointer block, @@ -35277,23 +35003,6 @@ final _objc_msgSend_16f0drb = objc.msgSendPointer int, ) >(); -final _objc_msgSend_16fy0up = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Long Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - > - >() - .asFunction< - int Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - >(); final _objc_msgSend_177cajs = objc.msgSendPointer .cast< ffi.NativeFunction< diff --git a/pkgs/objective_c/src/objective_c_bindings_generated.m b/pkgs/objective_c/src/objective_c_bindings_generated.m index f6c25a1b7c..6c5e8672d8 100644 --- a/pkgs/objective_c/src/objective_c_bindings_generated.m +++ b/pkgs/objective_c/src/objective_c_bindings_generated.m @@ -571,34 +571,28 @@ id _ObjectiveCBindings_protocolTrampoline_xr62hr(id target, void * sel, id arg1 return ((ProtocolTrampoline_13)((id (*)(id, SEL, SEL))objc_msgSend)(target, @selector(getDOBJCDartProtocolMethodForSelector:), sel))(sel, arg1); } -typedef id (^ProtocolTrampoline_14)(void * sel, id arg1, id arg2, id * arg3); -__attribute__((visibility("default"))) __attribute__((used)) -id _ObjectiveCBindings_protocolTrampoline_10z9f5k(id target, void * sel, id arg1, id arg2, id * arg3) { - return ((ProtocolTrampoline_14)((id (*)(id, SEL, SEL))objc_msgSend)(target, @selector(getDOBJCDartProtocolMethodForSelector:), sel))(sel, arg1, arg2, arg3); -} - -typedef id (^ProtocolTrampoline_15)(void * sel, struct _NSZone * arg1); +typedef id (^ProtocolTrampoline_14)(void * sel, struct _NSZone * arg1); __attribute__((visibility("default"))) __attribute__((used)) id _ObjectiveCBindings_protocolTrampoline_18nsem0(id target, void * sel, struct _NSZone * arg1) { - return ((ProtocolTrampoline_15)((id (*)(id, SEL, SEL))objc_msgSend)(target, @selector(getDOBJCDartProtocolMethodForSelector:), sel))(sel, arg1); + return ((ProtocolTrampoline_14)((id (*)(id, SEL, SEL))objc_msgSend)(target, @selector(getDOBJCDartProtocolMethodForSelector:), sel))(sel, arg1); } -typedef id (^ProtocolTrampoline_16)(void * sel, struct objc_selector * arg1); +typedef id (^ProtocolTrampoline_15)(void * sel, struct objc_selector * arg1); __attribute__((visibility("default"))) __attribute__((used)) id _ObjectiveCBindings_protocolTrampoline_50as9u(id target, void * sel, struct objc_selector * arg1) { - return ((ProtocolTrampoline_16)((id (*)(id, SEL, SEL))objc_msgSend)(target, @selector(getDOBJCDartProtocolMethodForSelector:), sel))(sel, arg1); + return ((ProtocolTrampoline_15)((id (*)(id, SEL, SEL))objc_msgSend)(target, @selector(getDOBJCDartProtocolMethodForSelector:), sel))(sel, arg1); } -typedef id (^ProtocolTrampoline_17)(void * sel, struct objc_selector * arg1, id arg2); +typedef id (^ProtocolTrampoline_16)(void * sel, struct objc_selector * arg1, id arg2); __attribute__((visibility("default"))) __attribute__((used)) id _ObjectiveCBindings_protocolTrampoline_1mllhpc(id target, void * sel, struct objc_selector * arg1, id arg2) { - return ((ProtocolTrampoline_17)((id (*)(id, SEL, SEL))objc_msgSend)(target, @selector(getDOBJCDartProtocolMethodForSelector:), sel))(sel, arg1, arg2); + return ((ProtocolTrampoline_16)((id (*)(id, SEL, SEL))objc_msgSend)(target, @selector(getDOBJCDartProtocolMethodForSelector:), sel))(sel, arg1, arg2); } -typedef id (^ProtocolTrampoline_18)(void * sel, struct objc_selector * arg1, id arg2, id arg3); +typedef id (^ProtocolTrampoline_17)(void * sel, struct objc_selector * arg1, id arg2, id arg3); __attribute__((visibility("default"))) __attribute__((used)) id _ObjectiveCBindings_protocolTrampoline_c7gk2u(id target, void * sel, struct objc_selector * arg1, id arg2, id arg3) { - return ((ProtocolTrampoline_18)((id (*)(id, SEL, SEL))objc_msgSend)(target, @selector(getDOBJCDartProtocolMethodForSelector:), sel))(sel, arg1, arg2, arg3); + return ((ProtocolTrampoline_17)((id (*)(id, SEL, SEL))objc_msgSend)(target, @selector(getDOBJCDartProtocolMethodForSelector:), sel))(sel, arg1, arg2, arg3); } Protocol* _ObjectiveCBindings_Observer(void) { return @protocol(Observer); } From 0b685147685ca9d270e2df9f2e4d678c26aa8963 Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Wed, 23 Jul 2025 13:28:25 +1000 Subject: [PATCH 2/2] Fix test --- pkgs/swiftgen/test/integration/util.dart | 30 +++++++++++++----------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/pkgs/swiftgen/test/integration/util.dart b/pkgs/swiftgen/test/integration/util.dart index af3fa49623..50d761fe94 100644 --- a/pkgs/swiftgen/test/integration/util.dart +++ b/pkgs/swiftgen/test/integration/util.dart @@ -85,23 +85,25 @@ class TestGenerator { expect(File(inputFile).existsSync(), isTrue); expect(File(outputFile).existsSync(), isTrue); - expect(File(outputObjCFile).existsSync(), isTrue); // The generation pipeline also creates some obj files as a byproduct. expect(File(objWrapperFile).existsSync(), isTrue); - // We also need to compile outputObjCFile to an obj file. - await run('clang', [ - '-x', - 'objective-c', - '-fobjc-arc', - '-c', - outputObjCFile, - '-fpic', - '-o', - objObjCFile, - ], tempDir); - expect(File(objObjCFile).existsSync(), isTrue); + final objCFileWasGenerated = File(outputObjCFile).existsSync(); + if (objCFileWasGenerated) { + // We also need to compile outputObjCFile to an obj file. + await run('clang', [ + '-x', + 'objective-c', + '-fobjc-arc', + '-c', + outputObjCFile, + '-fpic', + '-o', + objObjCFile, + ], tempDir); + expect(File(objObjCFile).existsSync(), isTrue); + } // Link all the obj files into a dylib. await run('clang', [ @@ -109,7 +111,7 @@ class TestGenerator { '-framework', 'Foundation', objWrapperFile, - objObjCFile, + if (objCFileWasGenerated) objObjCFile, '-o', dylibFile, ], tempDir);