From a968b8c96e72b51fb55ed6dc17dc33b299846889 Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Mon, 6 Jan 2025 15:10:00 +1100 Subject: [PATCH 1/8] test --- pkgs/ffigen/test/native_objc_test/category_test.dart | 5 +++++ pkgs/ffigen/test/native_objc_test/category_test.h | 4 ++++ pkgs/ffigen/test/native_objc_test/category_test.m | 6 ++++++ 3 files changed, 15 insertions(+) diff --git a/pkgs/ffigen/test/native_objc_test/category_test.dart b/pkgs/ffigen/test/native_objc_test/category_test.dart index dbde5a95bb..d7614907e2 100644 --- a/pkgs/ffigen/test/native_objc_test/category_test.dart +++ b/pkgs/ffigen/test/native_objc_test/category_test.dart @@ -73,5 +73,10 @@ void main() { NSString str2 = str.instancetypeMethod(); expect(str2.toString(), 'Hello'); }); + + test('Transitive category on built-in type', () { + // Regression test for https://github.com/dart-lang/native/issues/1820. + expect('Hello'.toNSString().extensionMethod(), 555); + }); }); } diff --git a/pkgs/ffigen/test/native_objc_test/category_test.h b/pkgs/ffigen/test/native_objc_test/category_test.h index 000694f9ed..1cfa999a5e 100644 --- a/pkgs/ffigen/test/native_objc_test/category_test.h +++ b/pkgs/ffigen/test/native_objc_test/category_test.h @@ -45,3 +45,7 @@ +(NSString*)staticMethod; -(instancetype)instancetypeMethod; @end + +@interface NSString (NSStringCategory) +-(int32_t)extensionMethod; +@end diff --git a/pkgs/ffigen/test/native_objc_test/category_test.m b/pkgs/ffigen/test/native_objc_test/category_test.m index 290ddcfe76..495ca3a234 100644 --- a/pkgs/ffigen/test/native_objc_test/category_test.m +++ b/pkgs/ffigen/test/native_objc_test/category_test.m @@ -70,3 +70,9 @@ -(instancetype)instancetypeMethod { return [self copy]; } @end + +@implementation NSString (NSStringCategory) +-(int32_t)extensionMethod { + return 555; +} +@end From 30d2e770ee50db24435281e89399faae20488feb Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Wed, 8 Jan 2025 11:01:58 +1100 Subject: [PATCH 2/8] wip --- pkgs/ffigen/lib/src/visitor/find_transitive_deps.dart | 6 ++++++ pkgs/ffigen/test/native_objc_test/category_config.yaml | 1 + pkgs/ffigen/test/native_objc_test/category_test.dart | 9 ++++++++- pkgs/ffigen/test/native_objc_test/category_test.h | 7 ++++++- pkgs/ffigen/test/native_objc_test/category_test.m | 8 +++++++- 5 files changed, 28 insertions(+), 3 deletions(-) diff --git a/pkgs/ffigen/lib/src/visitor/find_transitive_deps.dart b/pkgs/ffigen/lib/src/visitor/find_transitive_deps.dart index e9bc98e5d5..ed87e85254 100644 --- a/pkgs/ffigen/lib/src/visitor/find_transitive_deps.dart +++ b/pkgs/ffigen/lib/src/visitor/find_transitive_deps.dart @@ -41,6 +41,12 @@ class FindDirectTransitiveDepsVisitation extends Visitation { // included. This ensures that super types of stubs are also stubs, rather // than being omitted like the rest of the stub's children. visitor.visit(node.superType); + + // Visit the categories of built-in interfaces that have been explicitly + // included. https://github.com/dart-lang/native/issues/1820 + if (node.isObjCImport && includes.contains(node)) { + visitor.visitAll(node.categories); + } } @override diff --git a/pkgs/ffigen/test/native_objc_test/category_config.yaml b/pkgs/ffigen/test/native_objc_test/category_config.yaml index 2263a9d747..467b082a6d 100644 --- a/pkgs/ffigen/test/native_objc_test/category_config.yaml +++ b/pkgs/ffigen/test/native_objc_test/category_config.yaml @@ -7,6 +7,7 @@ objc-interfaces: include: - Thing - ChildOfThing + - NSURL objc-categories: include: - Sub diff --git a/pkgs/ffigen/test/native_objc_test/category_test.dart b/pkgs/ffigen/test/native_objc_test/category_test.dart index d7614907e2..112584a39d 100644 --- a/pkgs/ffigen/test/native_objc_test/category_test.dart +++ b/pkgs/ffigen/test/native_objc_test/category_test.dart @@ -76,7 +76,14 @@ void main() { test('Transitive category on built-in type', () { // Regression test for https://github.com/dart-lang/native/issues/1820. - expect('Hello'.toNSString().extensionMethod(), 555); + // Include transitive category of explicitly included buit-in type. + expect(NSURL.alloc().extensionMethod(), 555); + + // Don't include transitive category of built-in type that hasn't been + // explicitly included. + final bindings = File('test/native_objc_test/category_bindings.dart') + .readAsStringSync(); + expect(bindings, isNot(contains('excludedExtensionMethod'))); }); }); } diff --git a/pkgs/ffigen/test/native_objc_test/category_test.h b/pkgs/ffigen/test/native_objc_test/category_test.h index 1cfa999a5e..82df2fde29 100644 --- a/pkgs/ffigen/test/native_objc_test/category_test.h +++ b/pkgs/ffigen/test/native_objc_test/category_test.h @@ -4,6 +4,7 @@ #import #import +#import @interface Thing : NSObject {} -(int32_t)add:(int32_t)x Y:(int32_t) y; @@ -46,6 +47,10 @@ -(instancetype)instancetypeMethod; @end -@interface NSString (NSStringCategory) +@interface NSURL (NSURLCategory) -(int32_t)extensionMethod; @end + +@interface NSString (NSStringCategory) +-(int32_t)excludedExtensionMethod; +@end diff --git a/pkgs/ffigen/test/native_objc_test/category_test.m b/pkgs/ffigen/test/native_objc_test/category_test.m index 495ca3a234..3a777043e6 100644 --- a/pkgs/ffigen/test/native_objc_test/category_test.m +++ b/pkgs/ffigen/test/native_objc_test/category_test.m @@ -71,8 +71,14 @@ -(instancetype)instancetypeMethod { } @end -@implementation NSString (NSStringCategory) +@implementation NSURL (NSURLCategory) -(int32_t)extensionMethod { return 555; } @end + +@implementation NSString (NSStringCategory) +-(int32_t)excludedExtensionMethod { + return 999; +} +@end From b3cc1196b7eca30ab9cbc87391c408bd2d542c9e Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Thu, 16 Jan 2025 14:33:36 +1100 Subject: [PATCH 3/8] Fix bug where class/sel/msgSends weren't being generated --- pkgs/ffigen/lib/src/visitor/list_bindings.dart | 3 ++- pkgs/ffigen/test/native_objc_test/category_test.dart | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pkgs/ffigen/lib/src/visitor/list_bindings.dart b/pkgs/ffigen/lib/src/visitor/list_bindings.dart index c278f68917..ba88e95df8 100644 --- a/pkgs/ffigen/lib/src/visitor/list_bindings.dart +++ b/pkgs/ffigen/lib/src/visitor/list_bindings.dart @@ -24,7 +24,8 @@ class ListBindingsVisitation extends Visitation { final bindings = {}; ListBindingsVisitation( - this.config, this.includes, this.transitives, this.directTransitives); + this.config, this.includes, Set indirectTransitives, this.directTransitives) : + transitives = {...indirectTransitives, ...directTransitives}; void _add(Binding node) { node.visitChildren(visitor); diff --git a/pkgs/ffigen/test/native_objc_test/category_test.dart b/pkgs/ffigen/test/native_objc_test/category_test.dart index 112584a39d..504b80d049 100644 --- a/pkgs/ffigen/test/native_objc_test/category_test.dart +++ b/pkgs/ffigen/test/native_objc_test/category_test.dart @@ -84,6 +84,9 @@ void main() { final bindings = File('test/native_objc_test/category_bindings.dart') .readAsStringSync(); expect(bindings, isNot(contains('excludedExtensionMethod'))); + + // This method is from an NSObject extension, which shouldn't be included. + expect(bindings, isNot(contains('autoContentAccessingProxy'))); }); }); } From 1a34823b1028b491f892ea7e64a70badf755da4a Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Thu, 16 Jan 2025 14:48:30 +1100 Subject: [PATCH 4/8] Don't regenerate built-in categories --- .../objc_built_in_functions.dart | 20 +++++++++++++ .../lib/src/code_generator/objc_category.dart | 3 ++ pkgs/objective_c/lib/objective_c.dart | 11 +++++++ .../test/interface_lists_test.dart | 30 +++++++++++++++++++ 4 files changed, 64 insertions(+) diff --git a/pkgs/ffigen/lib/src/code_generator/objc_built_in_functions.dart b/pkgs/ffigen/lib/src/code_generator/objc_built_in_functions.dart index 980b9cedad..75cf813b1b 100644 --- a/pkgs/ffigen/lib/src/code_generator/objc_built_in_functions.dart +++ b/pkgs/ffigen/lib/src/code_generator/objc_built_in_functions.dart @@ -128,6 +128,24 @@ class ObjCBuiltInFunctions { static const builtInProtocols = { 'NSStreamDelegate', }; + @visibleForTesting + static const builtInCategories = { + 'NSDataCreation', + 'NSExtendedArray', + 'NSExtendedData', + 'NSExtendedDate', + 'NSExtendedDictionary', + 'NSExtendedEnumerator', + 'NSExtendedMutableArray', + 'NSExtendedMutableData', + 'NSExtendedMutableDictionary', + 'NSExtendedMutableOrderedSet', + 'NSExtendedMutableSet', + 'NSExtendedOrderedSet', + 'NSExtendedSet', + 'NSNumberCreation', + 'NSStringExtensionMethods', + }; // TODO(https://github.com/dart-lang/native/issues/1173): Ideally this check // would be based on more than just the name. @@ -139,6 +157,8 @@ class ObjCBuiltInFunctions { !generateForPackageObjectiveC && builtInEnums.contains(name); bool isBuiltInProtocol(String name) => !generateForPackageObjectiveC && builtInProtocols.contains(name); + bool isBuiltInCategory(String name) => + !generateForPackageObjectiveC && builtInCategories.contains(name); static bool isNSObject(String name) => name == 'NSObject'; // We need to load a separate instance of objc_msgSend for each signature. If diff --git a/pkgs/ffigen/lib/src/code_generator/objc_category.dart b/pkgs/ffigen/lib/src/code_generator/objc_category.dart index 7d3268f80e..711162f64b 100644 --- a/pkgs/ffigen/lib/src/code_generator/objc_category.dart +++ b/pkgs/ffigen/lib/src/code_generator/objc_category.dart @@ -34,6 +34,9 @@ class ObjCCategory extends NoLookUpBinding with ObjCMethods { return method.returnsInstanceType && !parent.isObjCImport; } + @override + bool get isObjCImport => builtInFunctions.isBuiltInCategory(originalName); + @override final ObjCBuiltInFunctions builtInFunctions; diff --git a/pkgs/objective_c/lib/objective_c.dart b/pkgs/objective_c/lib/objective_c.dart index 03ecc2628a..8c6de011ce 100644 --- a/pkgs/objective_c/lib/objective_c.dart +++ b/pkgs/objective_c/lib/objective_c.dart @@ -45,7 +45,18 @@ export 'src/objective_c_bindings_generated.dart' NSEnumerationOptions, NSEnumerator, NSError, + NSExtendedArray, + NSExtendedData, + NSExtendedDate, + NSExtendedDictionary, + NSExtendedEnumerator, + NSExtendedMutableArray, NSExtendedMutableData, + NSExtendedMutableDictionary, + NSExtendedMutableOrderedSet, + NSExtendedMutableSet, + NSExtendedOrderedSet, + NSExtendedSet, NSFastEnumerationState, NSIndexSet, NSInputStream, diff --git a/pkgs/objective_c/test/interface_lists_test.dart b/pkgs/objective_c/test/interface_lists_test.dart index 5959743862..e73dcbfd69 100644 --- a/pkgs/objective_c/test/interface_lists_test.dart +++ b/pkgs/objective_c/test/interface_lists_test.dart @@ -20,6 +20,7 @@ void main() { late List yamlStructs; late List yamlEnums; late List yamlProtocols; + late List yamlCategories; setUpAll(() { final yaml = @@ -47,6 +48,11 @@ void main() { .map((dynamic i) => i as String) .toList() ..sort(); + yamlCategories = ((yaml['objc-categories'] as YamlMap)['include'] + as YamlList) + .map((dynamic i) => i as String) + .toList() + ..sort(); }); test('ObjCBuiltInFunctions.builtInInterfaces', () { @@ -65,6 +71,10 @@ void main() { expect(ObjCBuiltInFunctions.builtInProtocols, yamlProtocols); }); + test('ObjCBuiltInFunctions.builtInCategories', () { + expect(ObjCBuiltInFunctions.builtInCategories, yamlCategories); + }); + test('package:objective_c exports all the interfaces', () { final exportFile = File('lib/objective_c.dart').readAsStringSync(); for (final intf in yamlInterfaces) { @@ -95,6 +105,13 @@ void main() { } }); + test('package:objective_c exports all the categories', () { + final exportFile = File('lib/objective_c.dart').readAsStringSync(); + for (final category in yamlCategories) { + expect(exportFile, contains(RegExp('\\W$category\\W'))); + } + }); + test('All code genned interfaces are included in the list', () { final classNameRegExp = RegExp(r'^class (\w+) '); final allClassNames = []; @@ -150,5 +167,18 @@ void main() { } expect(allProtocolNames, unorderedEquals(yamlProtocols)); }); + + test('All code genned categories are included in the list', () { + final categoryNameRegExp = RegExp(r'^extension (\w+) on \w+ {'); + final allCategoryNames = []; + for (final line in File('lib/src/objective_c_bindings_generated.dart') + .readAsLinesSync()) { + final match = categoryNameRegExp.firstMatch(line); + if (match != null) { + allCategoryNames.add(match[1]!); + } + } + expect(allCategoryNames, unorderedEquals(yamlCategories)); + }); }); } From 0742fe064797cabbadf4fc08f760770fa53e5c5d Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Thu, 23 Jan 2025 12:12:14 +1100 Subject: [PATCH 5/8] Fix spurious NSObject categories --- pkgs/ffigen/lib/src/header_parser/parser.dart | 13 ++++++++----- .../lib/src/visitor/apply_config_filters.dart | 12 +++++------- .../lib/src/visitor/find_transitive_deps.dart | 8 ++++---- pkgs/ffigen/lib/src/visitor/list_bindings.dart | 6 +++--- .../ffigen/test/native_objc_test/category_test.dart | 2 +- 5 files changed, 21 insertions(+), 20 deletions(-) diff --git a/pkgs/ffigen/lib/src/header_parser/parser.dart b/pkgs/ffigen/lib/src/header_parser/parser.dart index 882e68c3f0..49040af87c 100644 --- a/pkgs/ffigen/lib/src/header_parser/parser.dart +++ b/pkgs/ffigen/lib/src/header_parser/parser.dart @@ -175,8 +175,10 @@ List _transformBindings(Config config, List bindings) { visit(FixOverriddenMethodsVisitation(), bindings); visit(FillMethodDependenciesVisitation(), bindings); - final included = - visit(ApplyConfigFiltersVisitation(config), bindings).included; + final filterResults = visit(ApplyConfigFiltersVisitation(config), bindings); + final directlyIncluded = filterResults.directlyIncluded; + final indirectlyIncluded = filterResults.indirectlyIncluded; + final included = directlyIncluded.union(indirectlyIncluded); final byValueCompounds = visit(FindByValueCompoundsVisitation(), FindByValueCompoundsVisitation.rootNodes(included)) @@ -187,9 +189,10 @@ List _transformBindings(Config config, List bindings) { final transitives = visit(FindTransitiveDepsVisitation(), included).transitives; - final directTransitives = - visit(FindDirectTransitiveDepsVisitation(config, included), included) - .directTransitives; + final directTransitives = visit( + FindDirectTransitiveDepsVisitation(config, directlyIncluded), + included) + .directTransitives; final finalBindings = visit( ListBindingsVisitation( diff --git a/pkgs/ffigen/lib/src/visitor/apply_config_filters.dart b/pkgs/ffigen/lib/src/visitor/apply_config_filters.dart index 6903bf2eda..56b1f60403 100644 --- a/pkgs/ffigen/lib/src/visitor/apply_config_filters.dart +++ b/pkgs/ffigen/lib/src/visitor/apply_config_filters.dart @@ -9,17 +9,15 @@ import 'ast.dart'; class ApplyConfigFiltersVisitation extends Visitation { final Config config; - final _directlyIncluded = {}; - final _superTypes = {}; + final directlyIncluded = {}; + final indirectlyIncluded = {}; ApplyConfigFiltersVisitation(this.config); - Set get included => _directlyIncluded.union(_superTypes); - void _visitImpl(Binding node, DeclarationFilters filters) { node.visitChildren(visitor); if (node.originalName == '') return; if (config.usrTypeMappings.containsKey(node.usr)) return; - if (filters.shouldInclude(node)) _directlyIncluded.add(node); + if (filters.shouldInclude(node)) directlyIncluded.add(node); } @override @@ -45,9 +43,9 @@ class ApplyConfigFiltersVisitation extends Visitation { _visitImpl(node, config.objcInterfaces); // If this node is included, include all its super types. - if (_directlyIncluded.contains(node)) { + if (directlyIncluded.contains(node)) { for (ObjCInterface? t = node; t != null; t = t.superType) { - if (!_superTypes.add(t)) break; + if (!indirectlyIncluded.add(t)) break; } } } diff --git a/pkgs/ffigen/lib/src/visitor/find_transitive_deps.dart b/pkgs/ffigen/lib/src/visitor/find_transitive_deps.dart index ed87e85254..19444e1aa7 100644 --- a/pkgs/ffigen/lib/src/visitor/find_transitive_deps.dart +++ b/pkgs/ffigen/lib/src/visitor/find_transitive_deps.dart @@ -20,15 +20,15 @@ class FindTransitiveDepsVisitation extends Visitation { class FindDirectTransitiveDepsVisitation extends Visitation { final Config config; - final Set includes; + final Set directIncludes; final directTransitives = {}; - FindDirectTransitiveDepsVisitation(this.config, this.includes); + FindDirectTransitiveDepsVisitation(this.config, this.directIncludes); void _visitImpl(Binding node, bool forceVisitChildren) { if (node.isObjCImport) return; directTransitives.add(node); - if (forceVisitChildren || includes.contains(node)) { + if (forceVisitChildren || directIncludes.contains(node)) { node.visitChildren(visitor); } } @@ -44,7 +44,7 @@ class FindDirectTransitiveDepsVisitation extends Visitation { // Visit the categories of built-in interfaces that have been explicitly // included. https://github.com/dart-lang/native/issues/1820 - if (node.isObjCImport && includes.contains(node)) { + if (node.isObjCImport && directIncludes.contains(node)) { visitor.visitAll(node.categories); } } diff --git a/pkgs/ffigen/lib/src/visitor/list_bindings.dart b/pkgs/ffigen/lib/src/visitor/list_bindings.dart index ba88e95df8..8eb0fb0efc 100644 --- a/pkgs/ffigen/lib/src/visitor/list_bindings.dart +++ b/pkgs/ffigen/lib/src/visitor/list_bindings.dart @@ -23,9 +23,9 @@ class ListBindingsVisitation extends Visitation { final Set directTransitives; final bindings = {}; - ListBindingsVisitation( - this.config, this.includes, Set indirectTransitives, this.directTransitives) : - transitives = {...indirectTransitives, ...directTransitives}; + ListBindingsVisitation(this.config, this.includes, + Set indirectTransitives, this.directTransitives) + : transitives = {...indirectTransitives, ...directTransitives}; void _add(Binding node) { node.visitChildren(visitor); diff --git a/pkgs/ffigen/test/native_objc_test/category_test.dart b/pkgs/ffigen/test/native_objc_test/category_test.dart index 504b80d049..4d296b4b74 100644 --- a/pkgs/ffigen/test/native_objc_test/category_test.dart +++ b/pkgs/ffigen/test/native_objc_test/category_test.dart @@ -82,7 +82,7 @@ void main() { // Don't include transitive category of built-in type that hasn't been // explicitly included. final bindings = File('test/native_objc_test/category_bindings.dart') - .readAsStringSync(); + .readAsStringSync(); expect(bindings, isNot(contains('excludedExtensionMethod'))); // This method is from an NSObject extension, which shouldn't be included. From 41dff3fe042215e79de460a9efdc1a19f5a703fb Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Thu, 23 Jan 2025 12:59:25 +1100 Subject: [PATCH 6/8] Fix transitive_test --- pkgs/ffigen/lib/src/header_parser/parser.dart | 5 ++--- pkgs/ffigen/lib/src/visitor/find_transitive_deps.dart | 6 ++++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pkgs/ffigen/lib/src/header_parser/parser.dart b/pkgs/ffigen/lib/src/header_parser/parser.dart index 49040af87c..aad5a05b80 100644 --- a/pkgs/ffigen/lib/src/header_parser/parser.dart +++ b/pkgs/ffigen/lib/src/header_parser/parser.dart @@ -177,8 +177,7 @@ List _transformBindings(Config config, List bindings) { final filterResults = visit(ApplyConfigFiltersVisitation(config), bindings); final directlyIncluded = filterResults.directlyIncluded; - final indirectlyIncluded = filterResults.indirectlyIncluded; - final included = directlyIncluded.union(indirectlyIncluded); + final included = directlyIncluded.union(filterResults.indirectlyIncluded); final byValueCompounds = visit(FindByValueCompoundsVisitation(), FindByValueCompoundsVisitation.rootNodes(included)) @@ -190,7 +189,7 @@ List _transformBindings(Config config, List bindings) { final transitives = visit(FindTransitiveDepsVisitation(), included).transitives; final directTransitives = visit( - FindDirectTransitiveDepsVisitation(config, directlyIncluded), + FindDirectTransitiveDepsVisitation(config, included, directlyIncluded), included) .directTransitives; diff --git a/pkgs/ffigen/lib/src/visitor/find_transitive_deps.dart b/pkgs/ffigen/lib/src/visitor/find_transitive_deps.dart index 19444e1aa7..d28bb37ee6 100644 --- a/pkgs/ffigen/lib/src/visitor/find_transitive_deps.dart +++ b/pkgs/ffigen/lib/src/visitor/find_transitive_deps.dart @@ -20,15 +20,17 @@ class FindTransitiveDepsVisitation extends Visitation { class FindDirectTransitiveDepsVisitation extends Visitation { final Config config; + final Set includes; final Set directIncludes; final directTransitives = {}; - FindDirectTransitiveDepsVisitation(this.config, this.directIncludes); + FindDirectTransitiveDepsVisitation( + this.config, this.includes, this.directIncludes); void _visitImpl(Binding node, bool forceVisitChildren) { if (node.isObjCImport) return; directTransitives.add(node); - if (forceVisitChildren || directIncludes.contains(node)) { + if (forceVisitChildren || includes.contains(node)) { node.visitChildren(visitor); } } From c744145579772f9016cb6d20c0cd2bfa2c295420 Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Thu, 23 Jan 2025 13:02:28 +1100 Subject: [PATCH 7/8] fmt --- pkgs/ffigen/lib/src/header_parser/parser.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkgs/ffigen/lib/src/header_parser/parser.dart b/pkgs/ffigen/lib/src/header_parser/parser.dart index aad5a05b80..8a7601b2ed 100644 --- a/pkgs/ffigen/lib/src/header_parser/parser.dart +++ b/pkgs/ffigen/lib/src/header_parser/parser.dart @@ -189,7 +189,8 @@ List _transformBindings(Config config, List bindings) { final transitives = visit(FindTransitiveDepsVisitation(), included).transitives; final directTransitives = visit( - FindDirectTransitiveDepsVisitation(config, included, directlyIncluded), + FindDirectTransitiveDepsVisitation( + config, included, directlyIncluded), included) .directTransitives; From f776f75585f6ef4124082574c798e11f8e84a747 Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Thu, 23 Jan 2025 13:15:08 +1100 Subject: [PATCH 8/8] changelog --- pkgs/ffigen/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkgs/ffigen/CHANGELOG.md b/pkgs/ffigen/CHANGELOG.md index 963097449a..2db1169bb2 100644 --- a/pkgs/ffigen/CHANGELOG.md +++ b/pkgs/ffigen/CHANGELOG.md @@ -1,6 +1,8 @@ ## 17.0.0-wip - Use package:objective_c 5.0.0 +- Support transitive categories of built-in types: + https://github.com/dart-lang/native/issues/1820 ## 16.1.0