diff --git a/.github/labeler.yml b/.github/labeler.yml index 2d7ab38a7..f67662f37 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -27,3 +27,7 @@ 'package:native_toolchain_c': - changed-files: - any-glob-to-any-file: 'pkgs/native_toolchain_c/**' + +'package:objective_c': + - changed-files: + - any-glob-to-any-file: 'pkgs/objective_c/**' diff --git a/.github/workflows/objective_c.yaml b/.github/workflows/objective_c.yaml index 2ecdc59bf..136c3993d 100644 --- a/.github/workflows/objective_c.yaml +++ b/.github/workflows/objective_c.yaml @@ -57,6 +57,9 @@ jobs: channel: 'stable' - name: Install dependencies run: flutter pub get + - name: Build test dylib + # TODO(https://github.com/dart-lang/native/issues/1068): Remove this. + run: dart test/setup.dart - name: Run VM tests run: dart test - name: Collect coverage diff --git a/pkgs/ffigen/.gitignore b/pkgs/ffigen/.gitignore index d9616e8fa..e1f3703d7 100644 --- a/pkgs/ffigen/.gitignore +++ b/pkgs/ffigen/.gitignore @@ -4,6 +4,8 @@ .dart_tool/ .packages pubspec.lock +.flutter-plugins +.flutter-plugins-dependencies # IDE and debugger files. .clangd diff --git a/pkgs/ffigen/CHANGELOG.md b/pkgs/ffigen/CHANGELOG.md index 8bb233101..2c5010d9a 100644 --- a/pkgs/ffigen/CHANGELOG.md +++ b/pkgs/ffigen/CHANGELOG.md @@ -27,6 +27,8 @@ generated bindings. - Add --[no-]format option to ffigen command line, which controls whether the formatting step happens. Defaults to true. +- Delete Dart functions associated with ObjC closure blocks when the block is + destroyed. Fixes https://github.com/dart-lang/native/issues/204 ## 11.0.0 diff --git a/pkgs/ffigen/lib/src/code_generator/objc_block.dart b/pkgs/ffigen/lib/src/code_generator/objc_block.dart index 4d1fc3a0f..9422e87c8 100644 --- a/pkgs/ffigen/lib/src/code_generator/objc_block.dart +++ b/pkgs/ffigen/lib/src/code_generator/objc_block.dart @@ -58,12 +58,9 @@ class ObjCBlock extends BindingType { w.topLevelUniqueNamer.makeUnique('_${name}_fnPtrTrampoline'); final closureTrampoline = w.topLevelUniqueNamer.makeUnique('_${name}_closureTrampoline'); - final registerClosure = - w.topLevelUniqueNamer.makeUnique('_${name}_registerClosure'); - final closureRegistry = - w.topLevelUniqueNamer.makeUnique('_${name}_closureRegistry'); - final closureRegistryIndex = - w.topLevelUniqueNamer.makeUnique('_${name}_closureRegistryIndex'); + final newPointerBlock = ObjCBuiltInFunctions.newPointerBlock.gen(w); + final newClosureBlock = ObjCBuiltInFunctions.newClosureBlock.gen(w); + final getBlockClosure = ObjCBuiltInFunctions.getBlockClosure.gen(w); final trampFuncType = FunctionType( returnType: returnType, parameters: [Parameter(type: blockPtr, name: 'block'), ...params]); @@ -92,21 +89,10 @@ $returnFfiDartType $funcPtrTrampoline($blockCType block, $paramsFfiDartType) => .asFunction<$funcFfiDartType>()($paramsNameOnly); '''); - // Write the closure registry function. - s.write(''' -final $closureRegistry = {}; -int $closureRegistryIndex = 0; -$voidPtr $registerClosure($funcFfiDartType fn) { - final id = ++$closureRegistryIndex; - $closureRegistry[id] = fn; - return $voidPtr.fromAddress(id); -} -'''); - // Write the closure based trampoline function. s.write(''' $returnFfiDartType $closureTrampoline($blockCType block, $paramsFfiDartType) => - $closureRegistry[block.ref.target.address]!($paramsNameOnly); + ($getBlockClosure(block) as $funcFfiDartType)($paramsNameOnly); '''); // Snippet that converts a Dart typed closure to FfiDart type. This snippet @@ -141,7 +127,7 @@ class $name extends ${ObjCBuiltInFunctions.blockBase.gen(w)} { /// the isolate that registered it. Invoking the block on the wrong thread /// will result in a crash. $name.fromFunctionPointer($natFnPtr ptr) : - this._(${ObjCBuiltInFunctions.newBlock.gen(w)}( + this._($newPointerBlock( _cFuncTrampoline ??= ${w.ffiLibraryPrefix}.Pointer.fromFunction< $trampFuncCType>($funcPtrTrampoline $exceptionalReturn).cast(), ptr.cast())); @@ -153,10 +139,10 @@ class $name extends ${ObjCBuiltInFunctions.blockBase.gen(w)} { /// the isolate that registered it. Invoking the block on the wrong thread /// will result in a crash. $name.fromFunction($funcDartType fn) : - this._(${ObjCBuiltInFunctions.newBlock.gen(w)}( + this._($newClosureBlock( _dartFuncTrampoline ??= ${w.ffiLibraryPrefix}.Pointer.fromFunction< - $trampFuncCType>($closureTrampoline - $exceptionalReturn).cast(), $registerClosure($convFn))); + $trampFuncCType>($closureTrampoline $exceptionalReturn).cast(), + $convFn)); static $voidPtr? _dartFuncTrampoline; '''); @@ -174,11 +160,10 @@ class $name extends ${ObjCBuiltInFunctions.blockBase.gen(w)} { /// Note that unlike the default behavior of NativeCallable.listener, listener /// blocks do not keep the isolate alive. $name.listener($funcDartType fn) : - this._(${ObjCBuiltInFunctions.newBlock.gen(w)}( + this._($newClosureBlock( (_dartFuncListenerTrampoline ??= $nativeCallableType.listener( $closureTrampoline $exceptionalReturn)..keepIsolateAlive = - false).nativeFunction.cast(), - $registerClosure($convFn))); + false).nativeFunction.cast(), $convFn)); static $nativeCallableType? _dartFuncListenerTrampoline; '''); 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 7c6028054..5bdac34d3 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 @@ -19,7 +19,9 @@ class ObjCBuiltInFunctions { static const msgSendFpretPointer = ObjCImport('msgSendFpretPointer'); static const msgSendStretPointer = ObjCImport('msgSendStretPointer'); static const useMsgSendVariants = ObjCImport('useMsgSendVariants'); - static const newBlock = ObjCImport('newBlock'); + static const newPointerBlock = ObjCImport('newPointerBlock'); + static const newClosureBlock = ObjCImport('newClosureBlock'); + static const getBlockClosure = ObjCImport('getBlockClosure'); static const objectBase = ObjCImport('ObjCObjectBase'); static const blockBase = ObjCImport('ObjCBlockBase'); diff --git a/pkgs/ffigen/test/native_objc_test/automated_ref_count_test.dart b/pkgs/ffigen/test/native_objc_test/automated_ref_count_test.dart index 38e99f449..2e0f7891c 100644 --- a/pkgs/ffigen/test/native_objc_test/automated_ref_count_test.dart +++ b/pkgs/ffigen/test/native_objc_test/automated_ref_count_test.dart @@ -23,6 +23,8 @@ void main() { group('Automatic reference counting', () { setUpAll(() { logWarnings(); + // TODO(https://github.com/dart-lang/native/issues/1068): Remove this. + DynamicLibrary.open('../objective_c/test/objective_c.dylib'); final dylib = File('test/native_objc_test/automated_ref_count_test.dylib'); verifySetupFile(dylib); diff --git a/pkgs/ffigen/test/native_objc_test/bad_method_test.dart b/pkgs/ffigen/test/native_objc_test/bad_method_test.dart index e351d1a8e..67d6398ac 100644 --- a/pkgs/ffigen/test/native_objc_test/bad_method_test.dart +++ b/pkgs/ffigen/test/native_objc_test/bad_method_test.dart @@ -17,6 +17,8 @@ void main() { group('bad_method_test', () { setUpAll(() { logWarnings(); + // TODO(https://github.com/dart-lang/native/issues/1068): Remove this. + DynamicLibrary.open('../objective_c/test/objective_c.dylib'); final dylib = File('test/native_objc_test/bad_method_test.dylib'); verifySetupFile(dylib); DynamicLibrary.open(dylib.absolute.path); diff --git a/pkgs/ffigen/test/native_objc_test/block_test.dart b/pkgs/ffigen/test/native_objc_test/block_test.dart index 792ea16ad..8e2174cba 100644 --- a/pkgs/ffigen/test/native_objc_test/block_test.dart +++ b/pkgs/ffigen/test/native_objc_test/block_test.dart @@ -12,6 +12,8 @@ import 'dart:ffi'; import 'dart:io'; import 'package:ffi/ffi.dart'; +import 'package:objective_c/src/internal.dart' as internal_for_testing + show blockHasRegisteredClosure; import 'package:test/test.dart'; import '../test_utils.dart'; @@ -34,6 +36,8 @@ void main() { group('Blocks', () { setUpAll(() { logWarnings(); + // TODO(https://github.com/dart-lang/native/issues/1068): Remove this. + DynamicLibrary.open('../objective_c/test/objective_c.dylib'); final dylib = File('test/native_objc_test/block_test.dylib'); verifySetupFile(dylib); lib = BlockTestObjCLibrary(DynamicLibrary.open(dylib.absolute.path)); @@ -229,6 +233,8 @@ void main() { Pointer funcPointerBlockRefCountTest() { final block = IntBlock.fromFunctionPointer(Pointer.fromFunction(_add100, 999)); + expect( + internal_for_testing.blockHasRegisteredClosure(block.pointer), false); expect(lib.getBlockRetainCount(block.pointer.cast()), 1); return block.pointer.cast(); } @@ -241,18 +247,25 @@ void main() { Pointer funcBlockRefCountTest() { final block = IntBlock.fromFunction(makeAdder(4000)); + expect( + internal_for_testing.blockHasRegisteredClosure(block.pointer), true); expect(lib.getBlockRetainCount(block.pointer.cast()), 1); return block.pointer.cast(); } - test('Function block ref counting', () { + test('Function block ref counting', () async { final rawBlock = funcBlockRefCountTest(); doGC(); + await Future.delayed(Duration.zero); // Let dispose message arrive. expect(lib.getBlockRetainCount(rawBlock), 0); + expect(internal_for_testing.blockHasRegisteredClosure(rawBlock.cast()), + false); }); Pointer blockManualRetainRefCountTest() { final block = IntBlock.fromFunction(makeAdder(4000)); + expect( + internal_for_testing.blockHasRegisteredClosure(block.pointer), true); expect(lib.getBlockRetainCount(block.pointer.cast()), 1); final rawBlock = block.retainAndReturnPointer().cast(); expect(lib.getBlockRetainCount(rawBlock.cast()), 2); @@ -265,13 +278,16 @@ void main() { return lib.getBlockRetainCount(block.pointer.cast()); } - test('Block ref counting with manual retain and release', () { + test('Block ref counting with manual retain and release', () async { final rawBlock = blockManualRetainRefCountTest(); doGC(); expect(lib.getBlockRetainCount(rawBlock), 1); expect(blockManualRetainRefCountTest2(rawBlock), 1); doGC(); + await Future.delayed(Duration.zero); // Let dispose message arrive. expect(lib.getBlockRetainCount(rawBlock), 0); + expect(internal_for_testing.blockHasRegisteredClosure(rawBlock.cast()), + false); }); (Pointer, Pointer, Pointer) @@ -474,7 +490,7 @@ void main() { expect(descPtr.ref.reserved, 0); expect(descPtr.ref.size, isNot(0)); expect(descPtr.ref.copy_helper, nullptr); - expect(descPtr.ref.dispose_helper, nullptr); + expect(descPtr.ref.dispose_helper, isNot(nullptr)); expect(descPtr.ref.signature, nullptr); }); }); diff --git a/pkgs/ffigen/test/native_objc_test/cast_test.dart b/pkgs/ffigen/test/native_objc_test/cast_test.dart index 9025f78d2..aa765d67b 100644 --- a/pkgs/ffigen/test/native_objc_test/cast_test.dart +++ b/pkgs/ffigen/test/native_objc_test/cast_test.dart @@ -21,6 +21,8 @@ void main() { group('cast', () { setUpAll(() { logWarnings(); + // TODO(https://github.com/dart-lang/native/issues/1068): Remove this. + DynamicLibrary.open('../objective_c/test/objective_c.dylib'); final dylib = File('test/native_objc_test/cast_test.dylib'); verifySetupFile(dylib); DynamicLibrary.open(dylib.absolute.path); diff --git a/pkgs/ffigen/test/native_objc_test/category_test.dart b/pkgs/ffigen/test/native_objc_test/category_test.dart index bdc139482..c2a8ce8df 100644 --- a/pkgs/ffigen/test/native_objc_test/category_test.dart +++ b/pkgs/ffigen/test/native_objc_test/category_test.dart @@ -19,6 +19,8 @@ void main() { group('categories', () { setUpAll(() { logWarnings(); + // TODO(https://github.com/dart-lang/native/issues/1068): Remove this. + DynamicLibrary.open('../objective_c/test/objective_c.dylib'); final dylib = File('test/native_objc_test/category_test.dylib'); verifySetupFile(dylib); DynamicLibrary.open(dylib.absolute.path); diff --git a/pkgs/ffigen/test/native_objc_test/forward_decl_test.dart b/pkgs/ffigen/test/native_objc_test/forward_decl_test.dart index fb487fd40..9f5b91561 100644 --- a/pkgs/ffigen/test/native_objc_test/forward_decl_test.dart +++ b/pkgs/ffigen/test/native_objc_test/forward_decl_test.dart @@ -17,6 +17,8 @@ void main() { group('forward decl', () { setUpAll(() { logWarnings(); + // TODO(https://github.com/dart-lang/native/issues/1068): Remove this. + DynamicLibrary.open('../objective_c/test/objective_c.dylib'); final dylib = File('test/native_objc_test/forward_decl_test.dylib'); verifySetupFile(dylib); DynamicLibrary.open(dylib.absolute.path); diff --git a/pkgs/ffigen/test/native_objc_test/inherited_instancetype_test.dart b/pkgs/ffigen/test/native_objc_test/inherited_instancetype_test.dart index fc5cfc854..95cacf0f5 100644 --- a/pkgs/ffigen/test/native_objc_test/inherited_instancetype_test.dart +++ b/pkgs/ffigen/test/native_objc_test/inherited_instancetype_test.dart @@ -19,6 +19,8 @@ void main() { group('inheritedInstancetype', () { setUpAll(() { logWarnings(); + // TODO(https://github.com/dart-lang/native/issues/1068): Remove this. + DynamicLibrary.open('../objective_c/test/objective_c.dylib'); final dylib = File('test/native_objc_test/inherited_instancetype_test.dylib'); verifySetupFile(dylib); diff --git a/pkgs/ffigen/test/native_objc_test/is_instance_test.dart b/pkgs/ffigen/test/native_objc_test/is_instance_test.dart index de8beeea4..183134002 100644 --- a/pkgs/ffigen/test/native_objc_test/is_instance_test.dart +++ b/pkgs/ffigen/test/native_objc_test/is_instance_test.dart @@ -20,6 +20,8 @@ void main() { group('isInstance', () { setUpAll(() { logWarnings(); + // TODO(https://github.com/dart-lang/native/issues/1068): Remove this. + DynamicLibrary.open('../objective_c/test/objective_c.dylib'); final dylib = File('test/native_objc_test/is_instance_test.dylib'); verifySetupFile(dylib); DynamicLibrary.open(dylib.absolute.path); diff --git a/pkgs/ffigen/test/native_objc_test/method_test.dart b/pkgs/ffigen/test/native_objc_test/method_test.dart index fccb5f8ea..c6cb15988 100644 --- a/pkgs/ffigen/test/native_objc_test/method_test.dart +++ b/pkgs/ffigen/test/native_objc_test/method_test.dart @@ -20,6 +20,8 @@ void main() { group('method calls', () { setUpAll(() { logWarnings(); + // TODO(https://github.com/dart-lang/native/issues/1068): Remove this. + DynamicLibrary.open('../objective_c/test/objective_c.dylib'); final dylib = File('test/native_objc_test/method_test.dylib'); verifySetupFile(dylib); DynamicLibrary.open(dylib.absolute.path); diff --git a/pkgs/ffigen/test/native_objc_test/native_objc_test.dart b/pkgs/ffigen/test/native_objc_test/native_objc_test.dart index 77d8829ba..711a59749 100644 --- a/pkgs/ffigen/test/native_objc_test/native_objc_test.dart +++ b/pkgs/ffigen/test/native_objc_test/native_objc_test.dart @@ -18,6 +18,8 @@ void main() { group('native_objc_test', () { setUpAll(() { logWarnings(); + // TODO(https://github.com/dart-lang/native/issues/1068): Remove this. + DynamicLibrary.open('../objective_c/test/objective_c.dylib'); final dylib = File('test/native_objc_test/native_objc_test.dylib'); verifySetupFile(dylib); DynamicLibrary.open(dylib.absolute.path); diff --git a/pkgs/ffigen/test/native_objc_test/nullable_inheritance_test.dart b/pkgs/ffigen/test/native_objc_test/nullable_inheritance_test.dart index 06dd6a756..6c5df3f11 100644 --- a/pkgs/ffigen/test/native_objc_test/nullable_inheritance_test.dart +++ b/pkgs/ffigen/test/native_objc_test/nullable_inheritance_test.dart @@ -22,6 +22,8 @@ void main() { group('Nullable inheritance', () { setUpAll(() { logWarnings(); + // TODO(https://github.com/dart-lang/native/issues/1068): Remove this. + DynamicLibrary.open('../objective_c/test/objective_c.dylib'); final dylib = File('test/native_objc_test/nullable_inheritance_test.dylib'); verifySetupFile(dylib); diff --git a/pkgs/ffigen/test/native_objc_test/nullable_test.dart b/pkgs/ffigen/test/native_objc_test/nullable_test.dart index 134048e41..6b184095d 100644 --- a/pkgs/ffigen/test/native_objc_test/nullable_test.dart +++ b/pkgs/ffigen/test/native_objc_test/nullable_test.dart @@ -21,6 +21,8 @@ void main() { group('Nullability', () { setUpAll(() { logWarnings(); + // TODO(https://github.com/dart-lang/native/issues/1068): Remove this. + DynamicLibrary.open('../objective_c/test/objective_c.dylib'); final dylib = File('test/native_objc_test/nullable_test.dylib'); verifySetupFile(dylib); DynamicLibrary.open(dylib.absolute.path); diff --git a/pkgs/ffigen/test/native_objc_test/property_test.dart b/pkgs/ffigen/test/native_objc_test/property_test.dart index 490c305c0..fe0b0addd 100644 --- a/pkgs/ffigen/test/native_objc_test/property_test.dart +++ b/pkgs/ffigen/test/native_objc_test/property_test.dart @@ -20,6 +20,8 @@ void main() { group('properties', () { setUpAll(() { logWarnings(); + // TODO(https://github.com/dart-lang/native/issues/1068): Remove this. + DynamicLibrary.open('../objective_c/test/objective_c.dylib'); final dylib = File('test/native_objc_test/property_test.dylib'); verifySetupFile(dylib); DynamicLibrary.open(dylib.absolute.path); diff --git a/pkgs/ffigen/test/native_objc_test/rename_test.dart b/pkgs/ffigen/test/native_objc_test/rename_test.dart index 4d5d5e81c..451f934dc 100644 --- a/pkgs/ffigen/test/native_objc_test/rename_test.dart +++ b/pkgs/ffigen/test/native_objc_test/rename_test.dart @@ -17,6 +17,8 @@ void main() { group('rename_test', () { setUpAll(() { logWarnings(); + // TODO(https://github.com/dart-lang/native/issues/1068): Remove this. + DynamicLibrary.open('../objective_c/test/objective_c.dylib'); final dylib = File('test/native_objc_test/rename_test.dylib'); verifySetupFile(dylib); DynamicLibrary.open(dylib.absolute.path); diff --git a/pkgs/ffigen/test/native_objc_test/setup.dart b/pkgs/ffigen/test/native_objc_test/setup.dart index 8e74d878d..faa2d4329 100644 --- a/pkgs/ffigen/test/native_objc_test/setup.dart +++ b/pkgs/ffigen/test/native_objc_test/setup.dart @@ -48,21 +48,24 @@ Future _buildSwift( print('Generated files: $outputHeader and $outputLib'); } -Future _generateBindings(String config) async { - final args = [ - 'run', - 'ffigen', - '--config', - 'test/native_objc_test/$config', - ]; +Future _runDart(List args) async { final process = await Process.start(Platform.executable, args, workingDirectory: '../..'); unawaited(stdout.addStream(process.stdout)); unawaited(stderr.addStream(process.stderr)); final result = await process.exitCode; if (result != 0) { - throw ProcessException('dart', args, 'Generating bindings', result); + throw ProcessException('dart', args, 'Running Dart command', result); } +} + +Future _generateBindings(String config) async { + await _runDart([ + 'run', + 'ffigen', + '--config', + 'test/native_objc_test/$config', + ]); print('Generated bindings for: $config'); } @@ -129,5 +132,6 @@ Future main(List arguments) async { return await clean(_getTestNames()); } + await _runDart(['../objective_c/test/setup.dart']); return await build(arguments.isNotEmpty ? arguments : _getTestNames()); } diff --git a/pkgs/ffigen/test/native_objc_test/static_func_native_test.dart b/pkgs/ffigen/test/native_objc_test/static_func_native_test.dart index 12839ffee..a8f677779 100644 --- a/pkgs/ffigen/test/native_objc_test/static_func_native_test.dart +++ b/pkgs/ffigen/test/native_objc_test/static_func_native_test.dart @@ -26,6 +26,8 @@ void main() { group('static functions', () { setUpAll(() { logWarnings(); + // TODO(https://github.com/dart-lang/native/issues/1068): Remove this. + DynamicLibrary.open('../objective_c/test/objective_c.dylib'); final dylib = File('test/native_objc_test/static_func_test.dylib'); verifySetupFile(dylib); DynamicLibrary.open(dylib.absolute.path); diff --git a/pkgs/ffigen/test/native_objc_test/static_func_test.dart b/pkgs/ffigen/test/native_objc_test/static_func_test.dart index 08efc60f6..0b6fc21ff 100644 --- a/pkgs/ffigen/test/native_objc_test/static_func_test.dart +++ b/pkgs/ffigen/test/native_objc_test/static_func_test.dart @@ -28,6 +28,8 @@ void main() { group('static functions', () { setUpAll(() { logWarnings(); + // TODO(https://github.com/dart-lang/native/issues/1068): Remove this. + DynamicLibrary.open('../objective_c/test/objective_c.dylib'); final dylib = File('test/native_objc_test/static_func_test.dylib'); verifySetupFile(dylib); lib = StaticFuncTestObjCLibrary(DynamicLibrary.open(dylib.absolute.path)); diff --git a/pkgs/ffigen/test/native_objc_test/string_test.dart b/pkgs/ffigen/test/native_objc_test/string_test.dart index fc429763b..c5beccd69 100644 --- a/pkgs/ffigen/test/native_objc_test/string_test.dart +++ b/pkgs/ffigen/test/native_objc_test/string_test.dart @@ -19,6 +19,8 @@ void main() { group('string', () { setUpAll(() { logWarnings(); + // TODO(https://github.com/dart-lang/native/issues/1068): Remove this. + DynamicLibrary.open('../objective_c/test/objective_c.dylib'); final dylib = File('test/native_objc_test/string_test.dylib'); verifySetupFile(dylib); DynamicLibrary.open(dylib.absolute.path); diff --git a/pkgs/ffigen/test/native_objc_test/swift_class_test.dart b/pkgs/ffigen/test/native_objc_test/swift_class_test.dart index ec8e35a9c..e91ca95c8 100644 --- a/pkgs/ffigen/test/native_objc_test/swift_class_test.dart +++ b/pkgs/ffigen/test/native_objc_test/swift_class_test.dart @@ -17,6 +17,8 @@ void main() { group('swift_class_test', () { setUpAll(() { logWarnings(); + // TODO(https://github.com/dart-lang/native/issues/1068): Remove this. + DynamicLibrary.open('../objective_c/test/objective_c.dylib'); final dylib = File('test/native_objc_test/swift_class_test.dylib'); verifySetupFile(dylib); DynamicLibrary.open(dylib.absolute.path); diff --git a/pkgs/ffigen/test/native_objc_test/typedef_test.dart b/pkgs/ffigen/test/native_objc_test/typedef_test.dart index d94eeaf6b..af12934c3 100644 --- a/pkgs/ffigen/test/native_objc_test/typedef_test.dart +++ b/pkgs/ffigen/test/native_objc_test/typedef_test.dart @@ -17,6 +17,8 @@ void main() { group('typedef', () { setUpAll(() { logWarnings(); + // TODO(https://github.com/dart-lang/native/issues/1068): Remove this. + DynamicLibrary.open('../objective_c/test/objective_c.dylib'); final dylib = File('test/native_objc_test/typedef_test.dylib'); verifySetupFile(dylib); DynamicLibrary.open(dylib.absolute.path); diff --git a/pkgs/objective_c/.gitignore b/pkgs/objective_c/.gitignore index ac5aa9893..17e8ef64a 100644 --- a/pkgs/objective_c/.gitignore +++ b/pkgs/objective_c/.gitignore @@ -3,6 +3,7 @@ *.log *.pyc *.swp +*.dylib .DS_Store .atom/ .buildlog/ diff --git a/pkgs/objective_c/CHANGELOG.md b/pkgs/objective_c/CHANGELOG.md index 73ec74755..0c2a4a189 100644 --- a/pkgs/objective_c/CHANGELOG.md +++ b/pkgs/objective_c/CHANGELOG.md @@ -4,3 +4,5 @@ `ObjCObjectBase`, and `ObjCBlockBase`, as well as the core Objective C runtime functions (except `objc_msgSend`, which is library specific). - Move core ObjC classes such as `NSString` into this package. +- Delete Dart functions associated with ObjC closure blocks when the block is + destroyed. Fixes https://github.com/dart-lang/native/issues/204 diff --git a/pkgs/objective_c/example/.gitignore b/pkgs/objective_c/example/.gitignore new file mode 100644 index 000000000..29a3a5017 --- /dev/null +++ b/pkgs/objective_c/example/.gitignore @@ -0,0 +1,43 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.pub-cache/ +.pub/ +/build/ + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/pkgs/objective_c/example/README.md b/pkgs/objective_c/example/README.md new file mode 100644 index 000000000..1690cef71 --- /dev/null +++ b/pkgs/objective_c/example/README.md @@ -0,0 +1,3 @@ +# objective_c example + +Demonstrates how to use the objective_c plugin. diff --git a/pkgs/objective_c/example/analysis_options.yaml b/pkgs/objective_c/example/analysis_options.yaml new file mode 100644 index 000000000..22c406e13 --- /dev/null +++ b/pkgs/objective_c/example/analysis_options.yaml @@ -0,0 +1,6 @@ +include: package:flutter_lints/flutter.yaml + +analyzer: + language: + strict-casts: true + strict-inference: true diff --git a/pkgs/objective_c/example/ios/.gitignore b/pkgs/objective_c/example/ios/.gitignore new file mode 100644 index 000000000..7a7f9873a --- /dev/null +++ b/pkgs/objective_c/example/ios/.gitignore @@ -0,0 +1,34 @@ +**/dgph +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/ephemeral/ +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/pkgs/objective_c/example/ios/Flutter/AppFrameworkInfo.plist b/pkgs/objective_c/example/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 000000000..7c5696400 --- /dev/null +++ b/pkgs/objective_c/example/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 12.0 + + diff --git a/pkgs/objective_c/example/ios/Flutter/Debug.xcconfig b/pkgs/objective_c/example/ios/Flutter/Debug.xcconfig new file mode 100644 index 000000000..ec97fc6f3 --- /dev/null +++ b/pkgs/objective_c/example/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/pkgs/objective_c/example/ios/Flutter/Release.xcconfig b/pkgs/objective_c/example/ios/Flutter/Release.xcconfig new file mode 100644 index 000000000..c4855bfe2 --- /dev/null +++ b/pkgs/objective_c/example/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/pkgs/objective_c/example/ios/Podfile b/pkgs/objective_c/example/ios/Podfile new file mode 100644 index 000000000..d97f17e22 --- /dev/null +++ b/pkgs/objective_c/example/ios/Podfile @@ -0,0 +1,44 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '12.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/pkgs/objective_c/example/ios/Podfile.lock b/pkgs/objective_c/example/ios/Podfile.lock new file mode 100644 index 000000000..339f20a54 --- /dev/null +++ b/pkgs/objective_c/example/ios/Podfile.lock @@ -0,0 +1,22 @@ +PODS: + - Flutter (1.0.0) + - objective_c (0.0.1): + - Flutter + +DEPENDENCIES: + - Flutter (from `Flutter`) + - objective_c (from `.symlinks/plugins/objective_c/ios`) + +EXTERNAL SOURCES: + Flutter: + :path: Flutter + objective_c: + :path: ".symlinks/plugins/objective_c/ios" + +SPEC CHECKSUMS: + Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 + objective_c: 77e887b5ba1827970907e10e832eec1683f3431d + +PODFILE CHECKSUM: 819463e6a0290f5a72f145ba7cde16e8b6ef0796 + +COCOAPODS: 1.11.2 diff --git a/pkgs/objective_c/example/ios/Runner.xcodeproj/project.pbxproj b/pkgs/objective_c/example/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 000000000..8f49bdf9e --- /dev/null +++ b/pkgs/objective_c/example/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,728 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 0016C0D0D056FCD78A6A33E8 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5349C2B3D454EF3220FB3306 /* Pods_RunnerTests.framework */; }; + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 4D7C7CB911925A31801A2F1E /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0B910B6B0374F2338E70D6AC /* Pods_Runner.framework */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 97C146ED1CF9000F007C117D; + remoteInfo = Runner; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 0B910B6B0374F2338E70D6AC /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 5349C2B3D454EF3220FB3306 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 5898EAFA36C90FEB069D15C8 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; + 5E623BDE574BD3F02055F373 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + 6F2BCFFFCABF2D8A79F17D26 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + B6F1E5A6A7CC24D81665E0BA /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + F794A460162AE19694C18D43 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + FFB0D24362152330E942673E /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4D7C7CB911925A31801A2F1E /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B209388E6951AC88C18EE569 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 0016C0D0D056FCD78A6A33E8 /* Pods_RunnerTests.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 2961EE994295B641DF59D533 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 0B910B6B0374F2338E70D6AC /* Pods_Runner.framework */, + 5349C2B3D454EF3220FB3306 /* Pods_RunnerTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 331C8082294A63A400263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C807B294A618700263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + 331C8082294A63A400263BE5 /* RunnerTests */, + 97F4D88CC18AF014179906AC /* Pods */, + 2961EE994295B641DF59D533 /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + 331C8081294A63A400263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; + 97F4D88CC18AF014179906AC /* Pods */ = { + isa = PBXGroup; + children = ( + FFB0D24362152330E942673E /* Pods-Runner.debug.xcconfig */, + 6F2BCFFFCABF2D8A79F17D26 /* Pods-Runner.release.xcconfig */, + B6F1E5A6A7CC24D81665E0BA /* Pods-Runner.profile.xcconfig */, + 5E623BDE574BD3F02055F373 /* Pods-RunnerTests.debug.xcconfig */, + F794A460162AE19694C18D43 /* Pods-RunnerTests.release.xcconfig */, + 5898EAFA36C90FEB069D15C8 /* Pods-RunnerTests.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C8080294A63A400263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 11218719EF64897AFE1F9EE8 /* [CP] Check Pods Manifest.lock */, + 331C807D294A63A400263BE5 /* Sources */, + 331C807F294A63A400263BE5 /* Resources */, + B209388E6951AC88C18EE569 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 331C8086294A63A400263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + E0D32FA7EF8A23FC0FD30465 /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 98CA06E4ED3E0BFB8A3C613F /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastUpgradeCheck = 1510; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C8080294A63A400263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 97C146ED1CF9000F007C117D; + }; + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + 331C8080294A63A400263BE5 /* RunnerTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C807F294A63A400263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 11218719EF64897AFE1F9EE8 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; + 98CA06E4ED3E0BFB8A3C613F /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + E0D32FA7EF8A23FC0FD30465 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C807D294A63A400263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 97C146ED1CF9000F007C117D /* Runner */; + targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.github.dartlang.objectiveCExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 331C8088294A63A400263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5E623BDE574BD3F02055F373 /* Pods-RunnerTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.github.dartlang.objectiveCExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Debug; + }; + 331C8089294A63A400263BE5 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F794A460162AE19694C18D43 /* Pods-RunnerTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.github.dartlang.objectiveCExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Release; + }; + 331C808A294A63A400263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5898EAFA36C90FEB069D15C8 /* Pods-RunnerTests.profile.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.github.dartlang.objectiveCExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.github.dartlang.objectiveCExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.github.dartlang.objectiveCExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C8088294A63A400263BE5 /* Debug */, + 331C8089294A63A400263BE5 /* Release */, + 331C808A294A63A400263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/pkgs/objective_c/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/pkgs/objective_c/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/pkgs/objective_c/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/pkgs/objective_c/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/pkgs/objective_c/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/pkgs/objective_c/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/pkgs/objective_c/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/pkgs/objective_c/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 000000000..f9b0d7c5e --- /dev/null +++ b/pkgs/objective_c/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/pkgs/objective_c/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/pkgs/objective_c/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 000000000..8e3ca5dfe --- /dev/null +++ b/pkgs/objective_c/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pkgs/objective_c/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/pkgs/objective_c/example/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..21a3cc14c --- /dev/null +++ b/pkgs/objective_c/example/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/pkgs/objective_c/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/pkgs/objective_c/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/pkgs/objective_c/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/pkgs/objective_c/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/pkgs/objective_c/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 000000000..f9b0d7c5e --- /dev/null +++ b/pkgs/objective_c/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/pkgs/objective_c/example/ios/Runner/AppDelegate.swift b/pkgs/objective_c/example/ios/Runner/AppDelegate.swift new file mode 100644 index 000000000..9074fee92 --- /dev/null +++ b/pkgs/objective_c/example/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import Flutter +import UIKit + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..d36b1fab2 --- /dev/null +++ b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 000000000..dc9ada472 Binary files /dev/null and b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 000000000..7353c41ec Binary files /dev/null and b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 000000000..797d452e4 Binary files /dev/null and b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 000000000..6ed2d933e Binary files /dev/null and b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 000000000..4cd7b0099 Binary files /dev/null and b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 000000000..fe730945a Binary files /dev/null and b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100644 index 000000000..321773cd8 Binary files /dev/null and b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100644 index 000000000..797d452e4 Binary files /dev/null and b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 000000000..502f463a9 Binary files /dev/null and b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 000000000..0ec303439 Binary files /dev/null and b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 000000000..0ec303439 Binary files /dev/null and b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 000000000..e9f5fea27 Binary files /dev/null and b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 000000000..84ac32ae7 Binary files /dev/null and b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100644 index 000000000..8953cba09 Binary files /dev/null and b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 000000000..0467bf12a Binary files /dev/null and b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/pkgs/objective_c/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100644 index 000000000..0bedcf2fd --- /dev/null +++ b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/pkgs/objective_c/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100644 index 000000000..9da19eaca Binary files /dev/null and b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ diff --git a/pkgs/objective_c/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 000000000..9da19eaca Binary files /dev/null and b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ diff --git a/pkgs/objective_c/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 000000000..9da19eaca Binary files /dev/null and b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ diff --git a/pkgs/objective_c/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 000000000..89c2725b7 --- /dev/null +++ b/pkgs/objective_c/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/pkgs/objective_c/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/pkgs/objective_c/example/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 000000000..f2e259c7c --- /dev/null +++ b/pkgs/objective_c/example/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pkgs/objective_c/example/ios/Runner/Base.lproj/Main.storyboard b/pkgs/objective_c/example/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 000000000..f3c28516f --- /dev/null +++ b/pkgs/objective_c/example/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pkgs/objective_c/example/ios/Runner/Info.plist b/pkgs/objective_c/example/ios/Runner/Info.plist new file mode 100644 index 000000000..8bbbc6dc9 --- /dev/null +++ b/pkgs/objective_c/example/ios/Runner/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Objective C + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + objective_c_example + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + CADisableMinimumFrameDurationOnPhone + + UIApplicationSupportsIndirectInputEvents + + + diff --git a/pkgs/objective_c/example/ios/Runner/Runner-Bridging-Header.h b/pkgs/objective_c/example/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 000000000..308a2a560 --- /dev/null +++ b/pkgs/objective_c/example/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/pkgs/objective_c/example/ios/RunnerTests/RunnerTests.swift b/pkgs/objective_c/example/ios/RunnerTests/RunnerTests.swift new file mode 100644 index 000000000..86a7c3b1b --- /dev/null +++ b/pkgs/objective_c/example/ios/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import Flutter +import UIKit +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/pkgs/objective_c/example/lib/main.dart b/pkgs/objective_c/example/lib/main.dart new file mode 100644 index 000000000..1c2d1d35b --- /dev/null +++ b/pkgs/objective_c/example/lib/main.dart @@ -0,0 +1,37 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:flutter/material.dart'; +import 'package:objective_c/objective_c.dart'; + +void main() { + runApp(const MaterialApp(home: MainApp())); +} + +class MainApp extends StatefulWidget { + const MainApp({super.key}); + + @override + State createState() => _MainAppState(); +} + +class _MainAppState extends State { + late final String message; + + @override + void initState() { + super.initState(); + + message = NSString('Hello World!').toString(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Center( + child: Text(message), + ), + ); + } +} diff --git a/pkgs/objective_c/example/macos/.gitignore b/pkgs/objective_c/example/macos/.gitignore new file mode 100644 index 000000000..746adbb6b --- /dev/null +++ b/pkgs/objective_c/example/macos/.gitignore @@ -0,0 +1,7 @@ +# Flutter-related +**/Flutter/ephemeral/ +**/Pods/ + +# Xcode-related +**/dgph +**/xcuserdata/ diff --git a/pkgs/objective_c/example/macos/Flutter/Flutter-Debug.xcconfig b/pkgs/objective_c/example/macos/Flutter/Flutter-Debug.xcconfig new file mode 100644 index 000000000..4b81f9b2d --- /dev/null +++ b/pkgs/objective_c/example/macos/Flutter/Flutter-Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/pkgs/objective_c/example/macos/Flutter/Flutter-Release.xcconfig b/pkgs/objective_c/example/macos/Flutter/Flutter-Release.xcconfig new file mode 100644 index 000000000..5caa9d157 --- /dev/null +++ b/pkgs/objective_c/example/macos/Flutter/Flutter-Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/pkgs/objective_c/example/macos/Flutter/GeneratedPluginRegistrant.swift b/pkgs/objective_c/example/macos/Flutter/GeneratedPluginRegistrant.swift new file mode 100644 index 000000000..cccf817a5 --- /dev/null +++ b/pkgs/objective_c/example/macos/Flutter/GeneratedPluginRegistrant.swift @@ -0,0 +1,10 @@ +// +// Generated file. Do not edit. +// + +import FlutterMacOS +import Foundation + + +func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { +} diff --git a/pkgs/objective_c/example/macos/Podfile b/pkgs/objective_c/example/macos/Podfile new file mode 100644 index 000000000..c795730db --- /dev/null +++ b/pkgs/objective_c/example/macos/Podfile @@ -0,0 +1,43 @@ +platform :osx, '10.14' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_macos_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_macos_build_settings(target) + end +end diff --git a/pkgs/objective_c/example/macos/Runner.xcodeproj/project.pbxproj b/pkgs/objective_c/example/macos/Runner.xcodeproj/project.pbxproj new file mode 100644 index 000000000..f6e37da45 --- /dev/null +++ b/pkgs/objective_c/example/macos/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,705 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXAggregateTarget section */ + 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; + buildPhases = ( + 33CC111E2044C6BF0003C045 /* ShellScript */, + ); + dependencies = ( + ); + name = "Flutter Assemble"; + productName = FLX; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; }; + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC10EC2044A3C60003C045; + remoteInfo = Runner; + }; + 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC111A2044C6BA0003C045; + remoteInfo = FLX; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 33CC110E2044A8840003C045 /* Bundle Framework */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Bundle Framework"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; + 33CC10ED2044A3C60003C045 /* objective_c_example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "objective_c_example.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; + 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; + 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; + 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; + 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 331C80D2294CF70F00263BE5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EA2044A3C60003C045 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 331C80D6294CF71000263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C80D7294CF71000263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 33BA886A226E78AF003329D5 /* Configs */ = { + isa = PBXGroup; + children = ( + 33E5194F232828860026EE4D /* AppInfo.xcconfig */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, + ); + path = Configs; + sourceTree = ""; + }; + 33CC10E42044A3C60003C045 = { + isa = PBXGroup; + children = ( + 33FAB671232836740065AC1E /* Runner */, + 33CEB47122A05771004F2AC0 /* Flutter */, + 331C80D6294CF71000263BE5 /* RunnerTests */, + 33CC10EE2044A3C60003C045 /* Products */, + D73912EC22F37F3D000D13A0 /* Frameworks */, + ); + sourceTree = ""; + }; + 33CC10EE2044A3C60003C045 /* Products */ = { + isa = PBXGroup; + children = ( + 33CC10ED2044A3C60003C045 /* objective_c_example.app */, + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 33CC11242044D66E0003C045 /* Resources */ = { + isa = PBXGroup; + children = ( + 33CC10F22044A3C60003C045 /* Assets.xcassets */, + 33CC10F42044A3C60003C045 /* MainMenu.xib */, + 33CC10F72044A3C60003C045 /* Info.plist */, + ); + name = Resources; + path = ..; + sourceTree = ""; + }; + 33CEB47122A05771004F2AC0 /* Flutter */ = { + isa = PBXGroup; + children = ( + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, + ); + path = Flutter; + sourceTree = ""; + }; + 33FAB671232836740065AC1E /* Runner */ = { + isa = PBXGroup; + children = ( + 33CC10F02044A3C60003C045 /* AppDelegate.swift */, + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, + 33E51913231747F40026EE4D /* DebugProfile.entitlements */, + 33E51914231749380026EE4D /* Release.entitlements */, + 33CC11242044D66E0003C045 /* Resources */, + 33BA886A226E78AF003329D5 /* Configs */, + ); + path = Runner; + sourceTree = ""; + }; + D73912EC22F37F3D000D13A0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C80D4294CF70F00263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 331C80D1294CF70F00263BE5 /* Sources */, + 331C80D2294CF70F00263BE5 /* Frameworks */, + 331C80D3294CF70F00263BE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 331C80DA294CF71000263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 33CC10EC2044A3C60003C045 /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 33CC10E92044A3C60003C045 /* Sources */, + 33CC10EA2044A3C60003C045 /* Frameworks */, + 33CC10EB2044A3C60003C045 /* Resources */, + 33CC110E2044A8840003C045 /* Bundle Framework */, + 3399D490228B24CF009A79C7 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + 33CC11202044C79F0003C045 /* PBXTargetDependency */, + ); + name = Runner; + productName = Runner; + productReference = 33CC10ED2044A3C60003C045 /* objective_c_example.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 33CC10E52044A3C60003C045 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastSwiftUpdateCheck = 0920; + LastUpgradeCheck = 1510; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C80D4294CF70F00263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 33CC10EC2044A3C60003C045; + }; + 33CC10EC2044A3C60003C045 = { + CreatedOnToolsVersion = 9.2; + LastSwiftMigration = 1100; + ProvisioningStyle = Automatic; + SystemCapabilities = { + com.apple.Sandbox = { + enabled = 1; + }; + }; + }; + 33CC111A2044C6BA0003C045 = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Manual; + }; + }; + }; + buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 33CC10E42044A3C60003C045; + productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 33CC10EC2044A3C60003C045 /* Runner */, + 331C80D4294CF70F00263BE5 /* RunnerTests */, + 33CC111A2044C6BA0003C045 /* Flutter Assemble */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C80D3294CF70F00263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EB2044A3C60003C045 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3399D490228B24CF009A79C7 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; + }; + 33CC111E2044C6BF0003C045 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + Flutter/ephemeral/FlutterInputs.xcfilelist, + ); + inputPaths = ( + Flutter/ephemeral/tripwire, + ); + outputFileListPaths = ( + Flutter/ephemeral/FlutterOutputs.xcfilelist, + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C80D1294CF70F00263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10E92044A3C60003C045 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C80DA294CF71000263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC10EC2044A3C60003C045 /* Runner */; + targetProxy = 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */; + }; + 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; + targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 33CC10F52044A3C60003C045 /* Base */, + ); + name = MainMenu.xib; + path = Runner; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 331C80DB294CF71000263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.github.dartlang.objectiveCExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/objective_c_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/objective_c_example"; + }; + name = Debug; + }; + 331C80DC294CF71000263BE5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.github.dartlang.objectiveCExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/objective_c_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/objective_c_example"; + }; + name = Release; + }; + 331C80DD294CF71000263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.github.dartlang.objectiveCExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/objective_c_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/objective_c_example"; + }; + name = Profile; + }; + 338D0CE9231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Profile; + }; + 338D0CEA231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Profile; + }; + 338D0CEB231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Profile; + }; + 33CC10F92044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 33CC10FA2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + 33CC10FC2044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 33CC10FD2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 33CC111C2044C6BA0003C045 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 33CC111D2044C6BA0003C045 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C80DB294CF71000263BE5 /* Debug */, + 331C80DC294CF71000263BE5 /* Release */, + 331C80DD294CF71000263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10F92044A3C60003C045 /* Debug */, + 33CC10FA2044A3C60003C045 /* Release */, + 338D0CE9231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10FC2044A3C60003C045 /* Debug */, + 33CC10FD2044A3C60003C045 /* Release */, + 338D0CEA231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC111C2044C6BA0003C045 /* Debug */, + 33CC111D2044C6BA0003C045 /* Release */, + 338D0CEB231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 33CC10E52044A3C60003C045 /* Project object */; +} diff --git a/pkgs/objective_c/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/pkgs/objective_c/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/pkgs/objective_c/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/pkgs/objective_c/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/pkgs/objective_c/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 000000000..c87f47847 --- /dev/null +++ b/pkgs/objective_c/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pkgs/objective_c/example/macos/Runner.xcworkspace/contents.xcworkspacedata b/pkgs/objective_c/example/macos/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..1d526a16e --- /dev/null +++ b/pkgs/objective_c/example/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/pkgs/objective_c/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/pkgs/objective_c/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/pkgs/objective_c/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/pkgs/objective_c/example/macos/Runner/AppDelegate.swift b/pkgs/objective_c/example/macos/Runner/AppDelegate.swift new file mode 100644 index 000000000..d53ef6437 --- /dev/null +++ b/pkgs/objective_c/example/macos/Runner/AppDelegate.swift @@ -0,0 +1,9 @@ +import Cocoa +import FlutterMacOS + +@NSApplicationMain +class AppDelegate: FlutterAppDelegate { + override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { + return true + } +} diff --git a/pkgs/objective_c/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/pkgs/objective_c/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..a2ec33f19 --- /dev/null +++ b/pkgs/objective_c/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_16.png", + "scale" : "1x" + }, + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "2x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "1x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_64.png", + "scale" : "2x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_128.png", + "scale" : "1x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "2x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "1x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "2x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_1024.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/pkgs/objective_c/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/pkgs/objective_c/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png new file mode 100644 index 000000000..82b6f9d9a Binary files /dev/null and b/pkgs/objective_c/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png differ diff --git a/pkgs/objective_c/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/pkgs/objective_c/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png new file mode 100644 index 000000000..13b35eba5 Binary files /dev/null and b/pkgs/objective_c/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png differ diff --git a/pkgs/objective_c/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/pkgs/objective_c/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png new file mode 100644 index 000000000..0a3f5fa40 Binary files /dev/null and b/pkgs/objective_c/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png differ diff --git a/pkgs/objective_c/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/pkgs/objective_c/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png new file mode 100644 index 000000000..bdb57226d Binary files /dev/null and b/pkgs/objective_c/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png differ diff --git a/pkgs/objective_c/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/pkgs/objective_c/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png new file mode 100644 index 000000000..f083318e0 Binary files /dev/null and b/pkgs/objective_c/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png differ diff --git a/pkgs/objective_c/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/pkgs/objective_c/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png new file mode 100644 index 000000000..326c0e72c Binary files /dev/null and b/pkgs/objective_c/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png differ diff --git a/pkgs/objective_c/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/pkgs/objective_c/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png new file mode 100644 index 000000000..2f1632cfd Binary files /dev/null and b/pkgs/objective_c/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png differ diff --git a/pkgs/objective_c/example/macos/Runner/Base.lproj/MainMenu.xib b/pkgs/objective_c/example/macos/Runner/Base.lproj/MainMenu.xib new file mode 100644 index 000000000..80e867a4e --- /dev/null +++ b/pkgs/objective_c/example/macos/Runner/Base.lproj/MainMenu.xib @@ -0,0 +1,343 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pkgs/objective_c/example/macos/Runner/Configs/AppInfo.xcconfig b/pkgs/objective_c/example/macos/Runner/Configs/AppInfo.xcconfig new file mode 100644 index 000000000..50d7b8686 --- /dev/null +++ b/pkgs/objective_c/example/macos/Runner/Configs/AppInfo.xcconfig @@ -0,0 +1,14 @@ +// Application-level settings for the Runner target. +// +// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the +// future. If not, the values below would default to using the project name when this becomes a +// 'flutter create' template. + +// The application's name. By default this is also the title of the Flutter window. +PRODUCT_NAME = objective_c_example + +// The application's bundle identifier +PRODUCT_BUNDLE_IDENTIFIER = com.github.dartlang.objectiveCExample + +// The copyright displayed in application information +PRODUCT_COPYRIGHT = Copyright © 2024 com.github.dart_lang. All rights reserved. diff --git a/pkgs/objective_c/example/macos/Runner/Configs/Debug.xcconfig b/pkgs/objective_c/example/macos/Runner/Configs/Debug.xcconfig new file mode 100644 index 000000000..36b0fd946 --- /dev/null +++ b/pkgs/objective_c/example/macos/Runner/Configs/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Debug.xcconfig" +#include "Warnings.xcconfig" diff --git a/pkgs/objective_c/example/macos/Runner/Configs/Release.xcconfig b/pkgs/objective_c/example/macos/Runner/Configs/Release.xcconfig new file mode 100644 index 000000000..dff4f4956 --- /dev/null +++ b/pkgs/objective_c/example/macos/Runner/Configs/Release.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Release.xcconfig" +#include "Warnings.xcconfig" diff --git a/pkgs/objective_c/example/macos/Runner/Configs/Warnings.xcconfig b/pkgs/objective_c/example/macos/Runner/Configs/Warnings.xcconfig new file mode 100644 index 000000000..42bcbf478 --- /dev/null +++ b/pkgs/objective_c/example/macos/Runner/Configs/Warnings.xcconfig @@ -0,0 +1,13 @@ +WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings +GCC_WARN_UNDECLARED_SELECTOR = YES +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE +CLANG_WARN__DUPLICATE_METHOD_MATCH = YES +CLANG_WARN_PRAGMA_PACK = YES +CLANG_WARN_STRICT_PROTOTYPES = YES +CLANG_WARN_COMMA = YES +GCC_WARN_STRICT_SELECTOR_MATCH = YES +CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES +CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES +GCC_WARN_SHADOW = YES +CLANG_WARN_UNREACHABLE_CODE = YES diff --git a/pkgs/objective_c/example/macos/Runner/DebugProfile.entitlements b/pkgs/objective_c/example/macos/Runner/DebugProfile.entitlements new file mode 100644 index 000000000..dddb8a30c --- /dev/null +++ b/pkgs/objective_c/example/macos/Runner/DebugProfile.entitlements @@ -0,0 +1,12 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.cs.allow-jit + + com.apple.security.network.server + + + diff --git a/pkgs/objective_c/example/macos/Runner/Info.plist b/pkgs/objective_c/example/macos/Runner/Info.plist new file mode 100644 index 000000000..4789daa6a --- /dev/null +++ b/pkgs/objective_c/example/macos/Runner/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + $(PRODUCT_COPYRIGHT) + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/pkgs/objective_c/example/macos/Runner/MainFlutterWindow.swift b/pkgs/objective_c/example/macos/Runner/MainFlutterWindow.swift new file mode 100644 index 000000000..3cc05eb23 --- /dev/null +++ b/pkgs/objective_c/example/macos/Runner/MainFlutterWindow.swift @@ -0,0 +1,15 @@ +import Cocoa +import FlutterMacOS + +class MainFlutterWindow: NSWindow { + override func awakeFromNib() { + let flutterViewController = FlutterViewController() + let windowFrame = self.frame + self.contentViewController = flutterViewController + self.setFrame(windowFrame, display: true) + + RegisterGeneratedPlugins(registry: flutterViewController) + + super.awakeFromNib() + } +} diff --git a/pkgs/objective_c/example/macos/Runner/Release.entitlements b/pkgs/objective_c/example/macos/Runner/Release.entitlements new file mode 100644 index 000000000..852fa1a47 --- /dev/null +++ b/pkgs/objective_c/example/macos/Runner/Release.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.security.app-sandbox + + + diff --git a/pkgs/objective_c/example/macos/RunnerTests/RunnerTests.swift b/pkgs/objective_c/example/macos/RunnerTests/RunnerTests.swift new file mode 100644 index 000000000..61f3bd1fc --- /dev/null +++ b/pkgs/objective_c/example/macos/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import Cocoa +import FlutterMacOS +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/pkgs/objective_c/example/pubspec.lock b/pkgs/objective_c/example/pubspec.lock new file mode 100644 index 000000000..0dce9eae5 --- /dev/null +++ b/pkgs/objective_c/example/pubspec.lock @@ -0,0 +1,236 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + async: + dependency: transitive + description: + name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" + source: hosted + version: "2.11.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + characters: + dependency: transitive + description: + name: characters + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + clock: + dependency: transitive + description: + name: clock + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" + source: hosted + version: "1.1.1" + collection: + dependency: transitive + description: + name: collection + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + url: "https://pub.dev" + source: hosted + version: "1.18.0" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + ffi: + dependency: "direct main" + description: + name: ffi + sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: "9e8c3858111da373efc5aa341de011d9bd23e2c5c5e0c62bccf32438e192d7b1" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" + url: "https://pub.dev" + source: hosted + version: "10.0.4" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" + url: "https://pub.dev" + source: hosted + version: "3.0.3" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + url: "https://pub.dev" + source: hosted + version: "3.0.1" + lints: + dependency: transitive + description: + name: lints + sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290 + url: "https://pub.dev" + source: hosted + version: "3.0.0" + matcher: + dependency: transitive + description: + name: matcher + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + url: "https://pub.dev" + source: hosted + version: "0.12.16+1" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" + url: "https://pub.dev" + source: hosted + version: "0.8.0" + meta: + dependency: transitive + description: + name: meta + sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" + url: "https://pub.dev" + source: hosted + version: "1.12.0" + objective_c: + dependency: "direct main" + description: + path: ".." + relative: true + source: path + version: "0.0.1-wip" + path: + dependency: transitive + description: + name: path + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + url: "https://pub.dev" + source: hosted + version: "1.9.0" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" + source: hosted + version: "2.1.8" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_span: + dependency: transitive + description: + name: source_span + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" + source: hosted + version: "1.10.0" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + url: "https://pub.dev" + source: hosted + version: "1.11.1" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + url: "https://pub.dev" + source: hosted + version: "2.1.2" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + test_api: + dependency: transitive + description: + name: test_api + sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" + url: "https://pub.dev" + source: hosted + version: "0.7.0" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: a2662fb1f114f4296cf3f5a50786a2d888268d7776cf681aa17d660ffa23b246 + url: "https://pub.dev" + source: hosted + version: "14.0.0" + yaml: + dependency: transitive + description: + name: yaml + sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" + url: "https://pub.dev" + source: hosted + version: "3.1.2" +sdks: + dart: ">=3.3.0 <4.0.0" + flutter: ">=3.18.0-18.0.pre.54" diff --git a/pkgs/objective_c/example/pubspec.yaml b/pkgs/objective_c/example/pubspec.yaml new file mode 100644 index 000000000..f5312e8a3 --- /dev/null +++ b/pkgs/objective_c/example/pubspec.yaml @@ -0,0 +1,27 @@ +# Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +# for details. All rights reserved. Use of this source code is governed by a +# BSD-style license that can be found in the LICENSE file. + +name: example +description: "Demonstrates using package:objective_c" +publish_to: 'none' +version: 0.1.0 + +environment: + sdk: '>=3.3.0 <4.0.0' + flutter: '>=3.3.0' + +dependencies: + ffi: ^2.1.0 + flutter: + sdk: flutter + objective_c: + path: .. + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^3.0.0 + +flutter: + uses-material-design: true diff --git a/pkgs/objective_c/ffigen_c.yaml b/pkgs/objective_c/ffigen_c.yaml index 7e2c98baa..a95e28293 100644 --- a/pkgs/objective_c/ffigen_c.yaml +++ b/pkgs/objective_c/ffigen_c.yaml @@ -4,11 +4,21 @@ name: CBindings output: 'lib/src/c_bindings_generated.dart' headers: entry-points: + - 'src/include/dart_api_dl.h' - 'src/objective_c.h' - - 'src/objective_c_runtime.h' + - 'src/objective_c_runtime_types.h' + - 'src/objective_c_runtime_functions.h' ffi-native: + assetId: 'objective_c.framework/objective_c' +exclude-all-by-default: true generate-for-package-objective-c: true functions: + include: + - 'objc_.*' + - 'sel_registerName' + - '_Block_.*' + - 'disposeObjCBlockWithClosure' + - 'Dart_InitializeApiDL' leaf: include: - '(?!objc_msgSend).*' @@ -27,6 +37,9 @@ globals: - _NSConcreteGlobalBlock rename: '_(.*)': '$1' +typedefs: + include: + - 'ObjC.*' preamble: | // Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a diff --git a/pkgs/objective_c/ios/Classes/objective_c.c b/pkgs/objective_c/ios/Classes/objective_c.c index ddf898c3b..83496a45f 100644 --- a/pkgs/objective_c/ios/Classes/objective_c.c +++ b/pkgs/objective_c/ios/Classes/objective_c.c @@ -5,3 +5,4 @@ // Relative import to be able to reuse the C sources. // See the comment in ../{projectName}}.podspec for more information. #include "../../src/objective_c.c" +#include "../../src/include/dart_api_dl.c" diff --git a/pkgs/objective_c/lib/objective_c.dart b/pkgs/objective_c/lib/objective_c.dart index 6d1677e96..41f473af5 100644 --- a/pkgs/objective_c/lib/objective_c.dart +++ b/pkgs/objective_c/lib/objective_c.dart @@ -2,7 +2,7 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -export 'src/core.dart'; +export 'src/internal.dart' hide blockHasRegisteredClosure; export 'src/ns_data.dart'; export 'src/ns_string.dart'; export 'src/c_bindings_generated.dart' diff --git a/pkgs/objective_c/lib/src/c_bindings_generated.dart b/pkgs/objective_c/lib/src/c_bindings_generated.dart index d2282d69b..5f75847c1 100644 --- a/pkgs/objective_c/lib/src/c_bindings_generated.dart +++ b/pkgs/objective_c/lib/src/c_bindings_generated.dart @@ -14,8 +14,33 @@ // // Generated by `package:ffigen`. // ignore_for_file: type=lint +@ffi.DefaultAsset('objective_c.framework/objective_c') +library; + import 'dart:ffi' as ffi; +/// \mainpage Dynamically Linked Dart API +/// +/// This exposes a subset of symbols from dart_api.h and dart_native_api.h +/// available in every Dart embedder through dynamic linking. +/// +/// All symbols are postfixed with _DL to indicate that they are dynamically +/// linked and to prevent conflicts with the original symbol. +/// +/// Link `dart_api_dl.c` file into your library and invoke +/// `Dart_InitializeApiDL` with `NativeApi.initializeApiDLData`. +/// +/// Returns 0 on success. +@ffi.Native)>(isLeaf: true) +external int Dart_InitializeApiDL( + ffi.Pointer data, +); + +@ffi.Native)>(isLeaf: true) +external void disposeObjCBlockWithClosure( + ffi.Pointer block, +); + @ffi.Native Function(ffi.Pointer)>( symbol: "sel_registerName", isLeaf: true) external ffi.Pointer registerName( @@ -64,12 +89,28 @@ external void blockRelease( ffi.Pointer object, ); -final class _ObjCSelector extends ffi.Opaque {} +typedef ObjCBlock = _ObjCBlock; -final class _ObjCObject extends ffi.Opaque {} +final class _ObjCBlock extends ffi.Struct { + external ffi.Pointer isa; -typedef ObjCSelector = _ObjCSelector; -typedef ObjCObject = _ObjCObject; + @ffi.Int() + external int flags; + + @ffi.Int() + external int reserved; + + external ffi.Pointer invoke; + + external ffi.Pointer descriptor; + + external ffi.Pointer target; + + @ffi.Int64() + external int dispose_port; +} + +typedef ObjCBlockDesc = _ObjCBlockDesc; final class _ObjCBlockDesc extends ffi.Struct { @ffi.UnsignedLong() @@ -91,21 +132,10 @@ final class _ObjCBlockDesc extends ffi.Struct { external ffi.Pointer signature; } -final class _ObjCBlock extends ffi.Struct { - external ffi.Pointer isa; - - @ffi.Int() - external int flags; - - @ffi.Int() - external int reserved; - - external ffi.Pointer invoke; +typedef ObjCSelector = _ObjCSelector; - external ffi.Pointer descriptor; +final class _ObjCSelector extends ffi.Opaque {} - external ffi.Pointer target; -} +typedef ObjCObject = _ObjCObject; -typedef ObjCBlockDesc = _ObjCBlockDesc; -typedef ObjCBlock = _ObjCBlock; +final class _ObjCObject extends ffi.Opaque {} diff --git a/pkgs/objective_c/lib/src/core.dart b/pkgs/objective_c/lib/src/internal.dart similarity index 62% rename from pkgs/objective_c/lib/src/core.dart rename to pkgs/objective_c/lib/src/internal.dart index 8fccdab20..1b2b02817 100644 --- a/pkgs/objective_c/lib/src/core.dart +++ b/pkgs/objective_c/lib/src/internal.dart @@ -3,11 +3,13 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:ffi'; +import 'dart:isolate'; import 'package:ffi/ffi.dart'; import 'c_bindings_generated.dart' as c; +/// Only for use by ffigen bindings. Pointer registerName(String name) { final cstr = name.toNativeUtf8(); final sel = c.registerName(cstr.cast()); @@ -15,6 +17,7 @@ Pointer registerName(String name) { return sel; } +/// Only for use by ffigen bindings. Pointer getClass(String name) { final cstr = name.toNativeUtf8(); final clazz = c.getClass(cstr.cast()); @@ -25,13 +28,19 @@ Pointer getClass(String name) { return clazz; } +/// Only for use by ffigen bindings. final msgSendPointer = Native.addressOf>(c.msgSend); + +/// Only for use by ffigen bindings. final msgSendFpretPointer = Native.addressOf>(c.msgSendFpret); + +/// Only for use by ffigen bindings. final msgSendStretPointer = Native.addressOf>(c.msgSendStret); +/// Only for use by ffigen bindings. final useMsgSendVariants = Abi.current() == Abi.iosX64 || Abi.current() == Abi.macosX64; @@ -87,6 +96,7 @@ class _ObjCFinalizable implements Finalizable { void _release(Pointer ptr) => throw UnimplementedError(); } +/// Only for use by ffigen bindings. class ObjCObjectBase extends _ObjCFinalizable { ObjCObjectBase(super.ptr, {required super.retain, required super.release}); @@ -105,6 +115,7 @@ class ObjCObjectBase extends _ObjCFinalizable { void _release(Pointer ptr) => c.objectRelease(ptr); } +/// Only for use by ffigen bindings. class ObjCBlockBase extends _ObjCFinalizable { ObjCBlockBase(super.ptr, {required super.retain, required super.release}); @@ -123,27 +134,78 @@ class ObjCBlockBase extends _ObjCFinalizable { void _release(Pointer ptr) => c.blockRelease(ptr); } -Pointer _newBlockDesc() { +Pointer _newBlockDesc( + Pointer)>> + disposeHelper) { final desc = calloc.allocate(sizeOf()); desc.ref.reserved = 0; desc.ref.size = sizeOf(); desc.ref.copy_helper = nullptr; - desc.ref.dispose_helper = nullptr; + desc.ref.dispose_helper = disposeHelper.cast(); desc.ref.signature = nullptr; return desc; } -final _blockDesc = _newBlockDesc(); +final _pointerBlockDesc = _newBlockDesc(nullptr); +final _closureBlockDesc = _newBlockDesc( + Native.addressOf)>>( + c.disposeObjCBlockWithClosure)); -Pointer newBlock(Pointer invoke, Pointer target) { +Pointer _newBlock(Pointer invoke, Pointer target, + Pointer descriptor, int disposePort, int flags) { final b = calloc.allocate(sizeOf()); b.ref.isa = c.NSConcreteGlobalBlock; - b.ref.flags = 0; + b.ref.flags = flags; b.ref.reserved = 0; b.ref.invoke = invoke; b.ref.target = target; - b.ref.descriptor = _blockDesc; + b.ref.dispose_port = disposePort; + b.ref.descriptor = descriptor; final copy = c.blockCopy(b.cast()).cast(); calloc.free(b); return copy; } + +const int _blockHasCopyDispose = 1 << 25; + +/// Only for use by ffigen bindings. +Pointer newClosureBlock(Pointer invoke, Function fn) => + _newBlock(invoke, _registerBlockClosure(fn), _closureBlockDesc, + _blockClosureDisposer.sendPort.nativePort, _blockHasCopyDispose); + +/// Only for use by ffigen bindings. +Pointer newPointerBlock( + Pointer invoke, Pointer target) => + _newBlock(invoke, target, _pointerBlockDesc, 0, 0); + +final _blockClosureRegistry = {}; + +int _blockClosureRegistryLastId = 0; + +final _blockClosureDisposer = () { + c.Dart_InitializeApiDL(NativeApi.initializeApiDLData); + return RawReceivePort((dynamic msg) { + final id = msg as int; + assert(_blockClosureRegistry.containsKey(id)); + _blockClosureRegistry.remove(id); + }, "ObjCBlockClosureDisposer") + ..keepIsolateAlive = false; +}(); + +Pointer _registerBlockClosure(Function closure) { + ++_blockClosureRegistryLastId; + assert(!_blockClosureRegistry.containsKey(_blockClosureRegistryLastId)); + _blockClosureRegistry[_blockClosureRegistryLastId] = closure; + return Pointer.fromAddress(_blockClosureRegistryLastId); +} + +/// Only for use by ffigen bindings. +Function getBlockClosure(Pointer block) { + int id = block.ref.target.address; + assert(_blockClosureRegistry.containsKey(id)); + return _blockClosureRegistry[id]!; +} + +// Not exported by ../objective_c.dart, because it's only for testing. +bool blockHasRegisteredClosure(Pointer block) => + _blockClosureRegistry.containsKey(block.ref.target.address); diff --git a/pkgs/objective_c/lib/src/ns_data.dart b/pkgs/objective_c/lib/src/ns_data.dart index d8f8f404d..0284d9718 100644 --- a/pkgs/objective_c/lib/src/ns_data.dart +++ b/pkgs/objective_c/lib/src/ns_data.dart @@ -42,6 +42,9 @@ extension NSDataListExtension on List { final buffer = malloc(length); buffer.asTypedList(length).setAll(0, this); - return NSData.dataWithBytesNoCopy_length_(buffer.cast(), length); + final nsData = NSData.dataWithBytes_length_(buffer.cast(), length); + malloc.free(buffer); + + return nsData; } } 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 3dff896c0..265402289 100644 --- a/pkgs/objective_c/lib/src/objective_c_bindings_generated.dart +++ b/pkgs/objective_c/lib/src/objective_c_bindings_generated.dart @@ -5926,22 +5926,12 @@ void _ObjCBlock_ffiVoid_ffiUnsignedLong_bool_fnPtrTrampoline( ffi.Void Function( ffi.UnsignedLong arg0, ffi.Pointer arg1)>>() .asFunction)>()(arg0, arg1); -final _ObjCBlock_ffiVoid_ffiUnsignedLong_bool_closureRegistry = - )>{}; -int _ObjCBlock_ffiVoid_ffiUnsignedLong_bool_closureRegistryIndex = 0; -ffi.Pointer _ObjCBlock_ffiVoid_ffiUnsignedLong_bool_registerClosure( - void Function(int, ffi.Pointer) fn) { - final id = ++_ObjCBlock_ffiVoid_ffiUnsignedLong_bool_closureRegistryIndex; - _ObjCBlock_ffiVoid_ffiUnsignedLong_bool_closureRegistry[id] = fn; - return ffi.Pointer.fromAddress(id); -} - void _ObjCBlock_ffiVoid_ffiUnsignedLong_bool_closureTrampoline( ffi.Pointer block, int arg0, ffi.Pointer arg1) => - _ObjCBlock_ffiVoid_ffiUnsignedLong_bool_closureRegistry[ - block.ref.target.address]!(arg0, arg1); + (objc.getBlockClosure(block) as void Function(int, ffi.Pointer))( + arg0, arg1); class ObjCBlock_ffiVoid_ffiUnsignedLong_bool extends objc.ObjCBlockBase { ObjCBlock_ffiVoid_ffiUnsignedLong_bool._(ffi.Pointer pointer, @@ -5968,7 +5958,7 @@ class ObjCBlock_ffiVoid_ffiUnsignedLong_bool extends objc.ObjCBlockBase { ffi.Void Function( ffi.UnsignedLong arg0, ffi.Pointer arg1)>> ptr) - : this._(objc.newBlock( + : this._(objc.newPointerBlock( _cFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Void Function(ffi.Pointer, ffi.UnsignedLong, ffi.Pointer)>( @@ -5984,14 +5974,13 @@ class ObjCBlock_ffiVoid_ffiUnsignedLong_bool extends objc.ObjCBlockBase { /// will result in a crash. ObjCBlock_ffiVoid_ffiUnsignedLong_bool.fromFunction( void Function(int, ffi.Pointer) fn) - : this._(objc.newBlock( + : this._(objc.newClosureBlock( _dartFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Void Function(ffi.Pointer, ffi.UnsignedLong, ffi.Pointer)>( _ObjCBlock_ffiVoid_ffiUnsignedLong_bool_closureTrampoline) .cast(), - _ObjCBlock_ffiVoid_ffiUnsignedLong_bool_registerClosure( - (int arg0, ffi.Pointer arg1) => fn(arg0, arg1)))); + (int arg0, ffi.Pointer arg1) => fn(arg0, arg1))); static ffi.Pointer? _dartFuncTrampoline; /// Creates a listener block from a Dart function. @@ -6005,7 +5994,7 @@ class ObjCBlock_ffiVoid_ffiUnsignedLong_bool extends objc.ObjCBlockBase { /// blocks do not keep the isolate alive. ObjCBlock_ffiVoid_ffiUnsignedLong_bool.listener( void Function(int, ffi.Pointer) fn) - : this._(objc.newBlock( + : this._(objc.newClosureBlock( (_dartFuncListenerTrampoline ??= ffi.NativeCallable< ffi.Void Function(ffi.Pointer, ffi.UnsignedLong, ffi.Pointer)>.listener( @@ -6013,8 +6002,7 @@ class ObjCBlock_ffiVoid_ffiUnsignedLong_bool extends objc.ObjCBlockBase { ..keepIsolateAlive = false) .nativeFunction .cast(), - _ObjCBlock_ffiVoid_ffiUnsignedLong_bool_registerClosure( - (int arg0, ffi.Pointer arg1) => fn(arg0, arg1)))); + (int arg0, ffi.Pointer arg1) => fn(arg0, arg1))); static ffi.NativeCallable< ffi.Void Function(ffi.Pointer, ffi.UnsignedLong, ffi.Pointer)>? _dartFuncListenerTrampoline; @@ -6089,22 +6077,12 @@ bool _ObjCBlock_bool_ffiUnsignedLong_bool_fnPtrTrampoline( ffi.Bool Function( ffi.UnsignedLong arg0, ffi.Pointer arg1)>>() .asFunction)>()(arg0, arg1); -final _ObjCBlock_bool_ffiUnsignedLong_bool_closureRegistry = - )>{}; -int _ObjCBlock_bool_ffiUnsignedLong_bool_closureRegistryIndex = 0; -ffi.Pointer _ObjCBlock_bool_ffiUnsignedLong_bool_registerClosure( - bool Function(int, ffi.Pointer) fn) { - final id = ++_ObjCBlock_bool_ffiUnsignedLong_bool_closureRegistryIndex; - _ObjCBlock_bool_ffiUnsignedLong_bool_closureRegistry[id] = fn; - return ffi.Pointer.fromAddress(id); -} - bool _ObjCBlock_bool_ffiUnsignedLong_bool_closureTrampoline( ffi.Pointer block, int arg0, ffi.Pointer arg1) => - _ObjCBlock_bool_ffiUnsignedLong_bool_closureRegistry[ - block.ref.target.address]!(arg0, arg1); + (objc.getBlockClosure(block) as bool Function(int, ffi.Pointer))( + arg0, arg1); class ObjCBlock_bool_ffiUnsignedLong_bool extends objc.ObjCBlockBase { ObjCBlock_bool_ffiUnsignedLong_bool._(ffi.Pointer pointer, @@ -6132,7 +6110,7 @@ class ObjCBlock_bool_ffiUnsignedLong_bool extends objc.ObjCBlockBase { ffi.Bool Function( ffi.UnsignedLong arg0, ffi.Pointer arg1)>> ptr) - : this._(objc.newBlock( + : this._(objc.newPointerBlock( _cFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Bool Function(ffi.Pointer, ffi.UnsignedLong, ffi.Pointer)>( @@ -6148,15 +6126,14 @@ class ObjCBlock_bool_ffiUnsignedLong_bool extends objc.ObjCBlockBase { /// will result in a crash. ObjCBlock_bool_ffiUnsignedLong_bool.fromFunction( bool Function(int, ffi.Pointer) fn) - : this._(objc.newBlock( + : this._(objc.newClosureBlock( _dartFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Bool Function(ffi.Pointer, ffi.UnsignedLong, ffi.Pointer)>( _ObjCBlock_bool_ffiUnsignedLong_bool_closureTrampoline, false) .cast(), - _ObjCBlock_bool_ffiUnsignedLong_bool_registerClosure( - (int arg0, ffi.Pointer arg1) => fn(arg0, arg1)))); + (int arg0, ffi.Pointer arg1) => fn(arg0, arg1))); static ffi.Pointer? _dartFuncTrampoline; bool call(int arg0, ffi.Pointer arg1) => pointer.ref.invoke @@ -6265,22 +6242,12 @@ void _ObjCBlock_ffiVoid_NSRange_bool_fnPtrTrampoline( ffi.Void Function(_NSRange arg0, ffi.Pointer arg1)>>() .asFunction< void Function(_NSRange, ffi.Pointer)>()(arg0, arg1); -final _ObjCBlock_ffiVoid_NSRange_bool_closureRegistry = - )>{}; -int _ObjCBlock_ffiVoid_NSRange_bool_closureRegistryIndex = 0; -ffi.Pointer _ObjCBlock_ffiVoid_NSRange_bool_registerClosure( - void Function(_NSRange, ffi.Pointer) fn) { - final id = ++_ObjCBlock_ffiVoid_NSRange_bool_closureRegistryIndex; - _ObjCBlock_ffiVoid_NSRange_bool_closureRegistry[id] = fn; - return ffi.Pointer.fromAddress(id); -} - void _ObjCBlock_ffiVoid_NSRange_bool_closureTrampoline( ffi.Pointer block, _NSRange arg0, ffi.Pointer arg1) => - _ObjCBlock_ffiVoid_NSRange_bool_closureRegistry[block.ref.target.address]!( - arg0, arg1); + (objc.getBlockClosure(block) as void Function( + _NSRange, ffi.Pointer))(arg0, arg1); class ObjCBlock_ffiVoid_NSRange_bool extends objc.ObjCBlockBase { ObjCBlock_ffiVoid_NSRange_bool._(ffi.Pointer pointer, @@ -6306,7 +6273,7 @@ class ObjCBlock_ffiVoid_NSRange_bool extends objc.ObjCBlockBase { ffi.NativeFunction< ffi.Void Function(_NSRange arg0, ffi.Pointer arg1)>> ptr) - : this._(objc.newBlock( + : this._(objc.newPointerBlock( _cFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Void Function(ffi.Pointer, _NSRange, ffi.Pointer)>( @@ -6322,15 +6289,13 @@ class ObjCBlock_ffiVoid_NSRange_bool extends objc.ObjCBlockBase { /// will result in a crash. ObjCBlock_ffiVoid_NSRange_bool.fromFunction( void Function(_NSRange, ffi.Pointer) fn) - : this._(objc.newBlock( + : this._(objc.newClosureBlock( _dartFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Void Function(ffi.Pointer, _NSRange, ffi.Pointer)>( _ObjCBlock_ffiVoid_NSRange_bool_closureTrampoline) .cast(), - _ObjCBlock_ffiVoid_NSRange_bool_registerClosure( - (_NSRange arg0, ffi.Pointer arg1) => - fn(arg0, arg1)))); + (_NSRange arg0, ffi.Pointer arg1) => fn(arg0, arg1))); static ffi.Pointer? _dartFuncTrampoline; /// Creates a listener block from a Dart function. @@ -6344,7 +6309,7 @@ class ObjCBlock_ffiVoid_NSRange_bool extends objc.ObjCBlockBase { /// blocks do not keep the isolate alive. ObjCBlock_ffiVoid_NSRange_bool.listener( void Function(_NSRange, ffi.Pointer) fn) - : this._(objc.newBlock( + : this._(objc.newClosureBlock( (_dartFuncListenerTrampoline ??= ffi.NativeCallable< ffi.Void Function(ffi.Pointer, _NSRange, ffi.Pointer)>.listener( @@ -6352,9 +6317,7 @@ class ObjCBlock_ffiVoid_NSRange_bool extends objc.ObjCBlockBase { ..keepIsolateAlive = false) .nativeFunction .cast(), - _ObjCBlock_ffiVoid_NSRange_bool_registerClosure( - (_NSRange arg0, ffi.Pointer arg1) => - fn(arg0, arg1)))); + (_NSRange arg0, ffi.Pointer arg1) => fn(arg0, arg1))); static ffi.NativeCallable< ffi.Void Function( ffi.Pointer, _NSRange, ffi.Pointer)>? @@ -6440,30 +6403,13 @@ void _ObjCBlock_ffiVoid_objcObjCObject_ffiUnsignedLong_bool_fnPtrTrampoline( .asFunction< void Function(ffi.Pointer, int, ffi.Pointer)>()(arg0, arg1, arg2); -final _ObjCBlock_ffiVoid_objcObjCObject_ffiUnsignedLong_bool_closureRegistry = - , int, ffi.Pointer)>{}; -int _ObjCBlock_ffiVoid_objcObjCObject_ffiUnsignedLong_bool_closureRegistryIndex = - 0; -ffi.Pointer - _ObjCBlock_ffiVoid_objcObjCObject_ffiUnsignedLong_bool_registerClosure( - void Function(ffi.Pointer, int, ffi.Pointer) - fn) { - final id = - ++_ObjCBlock_ffiVoid_objcObjCObject_ffiUnsignedLong_bool_closureRegistryIndex; - _ObjCBlock_ffiVoid_objcObjCObject_ffiUnsignedLong_bool_closureRegistry[id] = - fn; - return ffi.Pointer.fromAddress(id); -} - void _ObjCBlock_ffiVoid_objcObjCObject_ffiUnsignedLong_bool_closureTrampoline( ffi.Pointer block, ffi.Pointer arg0, int arg1, ffi.Pointer arg2) => - _ObjCBlock_ffiVoid_objcObjCObject_ffiUnsignedLong_bool_closureRegistry[ - block.ref.target.address]!(arg0, arg1, arg2); + (objc.getBlockClosure(block) as void Function(ffi.Pointer, + int, ffi.Pointer))(arg0, arg1, arg2); class ObjCBlock_ffiVoid_objcObjCObject_ffiUnsignedLong_bool extends objc.ObjCBlockBase { @@ -6493,7 +6439,7 @@ class ObjCBlock_ffiVoid_objcObjCObject_ffiUnsignedLong_bool ffi.Void Function(ffi.Pointer arg0, ffi.UnsignedLong arg1, ffi.Pointer arg2)>> ptr) - : this._(objc.newBlock( + : this._(objc.newPointerBlock( _cFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Void Function( ffi.Pointer, @@ -6512,7 +6458,7 @@ class ObjCBlock_ffiVoid_objcObjCObject_ffiUnsignedLong_bool /// will result in a crash. ObjCBlock_ffiVoid_objcObjCObject_ffiUnsignedLong_bool.fromFunction( void Function(NSObject, int, ffi.Pointer) fn) - : this._(objc.newBlock( + : this._(objc.newClosureBlock( _dartFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Void Function( ffi.Pointer, @@ -6521,10 +6467,9 @@ class ObjCBlock_ffiVoid_objcObjCObject_ffiUnsignedLong_bool ffi.Pointer)>( _ObjCBlock_ffiVoid_objcObjCObject_ffiUnsignedLong_bool_closureTrampoline) .cast(), - _ObjCBlock_ffiVoid_objcObjCObject_ffiUnsignedLong_bool_registerClosure( - (ffi.Pointer arg0, int arg1, - ffi.Pointer arg2) => - fn(NSObject.castFromPointer(arg0, retain: true, release: true), arg1, arg2)))); + (ffi.Pointer arg0, int arg1, ffi.Pointer arg2) => + fn(NSObject.castFromPointer(arg0, retain: true, release: true), + arg1, arg2))); static ffi.Pointer? _dartFuncTrampoline; /// Creates a listener block from a Dart function. @@ -6538,7 +6483,7 @@ class ObjCBlock_ffiVoid_objcObjCObject_ffiUnsignedLong_bool /// blocks do not keep the isolate alive. ObjCBlock_ffiVoid_objcObjCObject_ffiUnsignedLong_bool.listener( void Function(NSObject, int, ffi.Pointer) fn) - : this._(objc.newBlock( + : this._(objc.newClosureBlock( (_dartFuncListenerTrampoline ??= ffi.NativeCallable< ffi.Void Function( ffi.Pointer, @@ -6549,10 +6494,10 @@ class ObjCBlock_ffiVoid_objcObjCObject_ffiUnsignedLong_bool ..keepIsolateAlive = false) .nativeFunction .cast(), - _ObjCBlock_ffiVoid_objcObjCObject_ffiUnsignedLong_bool_registerClosure( - (ffi.Pointer arg0, int arg1, - ffi.Pointer arg2) => - fn(NSObject.castFromPointer(arg0, retain: true, release: true), arg1, arg2)))); + (ffi.Pointer arg0, int arg1, + ffi.Pointer arg2) => + fn(NSObject.castFromPointer(arg0, retain: true, release: true), + arg1, arg2))); static ffi.NativeCallable< ffi.Void Function( ffi.Pointer, @@ -6634,29 +6579,13 @@ bool _ObjCBlock_bool_objcObjCObject_ffiUnsignedLong_bool_fnPtrTrampoline( .asFunction< bool Function(ffi.Pointer, int, ffi.Pointer)>()(arg0, arg1, arg2); -final _ObjCBlock_bool_objcObjCObject_ffiUnsignedLong_bool_closureRegistry = - , int, ffi.Pointer)>{}; -int _ObjCBlock_bool_objcObjCObject_ffiUnsignedLong_bool_closureRegistryIndex = - 0; -ffi.Pointer - _ObjCBlock_bool_objcObjCObject_ffiUnsignedLong_bool_registerClosure( - bool Function(ffi.Pointer, int, ffi.Pointer) - fn) { - final id = - ++_ObjCBlock_bool_objcObjCObject_ffiUnsignedLong_bool_closureRegistryIndex; - _ObjCBlock_bool_objcObjCObject_ffiUnsignedLong_bool_closureRegistry[id] = fn; - return ffi.Pointer.fromAddress(id); -} - bool _ObjCBlock_bool_objcObjCObject_ffiUnsignedLong_bool_closureTrampoline( ffi.Pointer block, ffi.Pointer arg0, int arg1, ffi.Pointer arg2) => - _ObjCBlock_bool_objcObjCObject_ffiUnsignedLong_bool_closureRegistry[ - block.ref.target.address]!(arg0, arg1, arg2); + (objc.getBlockClosure(block) as bool Function(ffi.Pointer, + int, ffi.Pointer))(arg0, arg1, arg2); class ObjCBlock_bool_objcObjCObject_ffiUnsignedLong_bool extends objc.ObjCBlockBase { @@ -6686,7 +6615,7 @@ class ObjCBlock_bool_objcObjCObject_ffiUnsignedLong_bool ffi.Bool Function(ffi.Pointer arg0, ffi.UnsignedLong arg1, ffi.Pointer arg2)>> ptr) - : this._(objc.newBlock( + : this._(objc.newPointerBlock( _cFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Bool Function( ffi.Pointer, @@ -6706,18 +6635,19 @@ class ObjCBlock_bool_objcObjCObject_ffiUnsignedLong_bool /// will result in a crash. ObjCBlock_bool_objcObjCObject_ffiUnsignedLong_bool.fromFunction( bool Function(NSObject, int, ffi.Pointer) fn) - : this._(objc.newBlock( + : this._(objc.newClosureBlock( _dartFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Bool Function( ffi.Pointer, ffi.Pointer, ffi.UnsignedLong, ffi.Pointer)>( - _ObjCBlock_bool_objcObjCObject_ffiUnsignedLong_bool_closureTrampoline, false) + _ObjCBlock_bool_objcObjCObject_ffiUnsignedLong_bool_closureTrampoline, + false) .cast(), - _ObjCBlock_bool_objcObjCObject_ffiUnsignedLong_bool_registerClosure( - (ffi.Pointer arg0, int arg1, ffi.Pointer arg2) => - fn(NSObject.castFromPointer(arg0, retain: true, release: true), arg1, arg2)))); + (ffi.Pointer arg0, int arg1, + ffi.Pointer arg2) => + fn(NSObject.castFromPointer(arg0, retain: true, release: true), arg1, arg2))); static ffi.Pointer? _dartFuncTrampoline; bool call(NSObject arg0, int arg1, ffi.Pointer arg2) => @@ -6837,29 +6767,12 @@ int _ObjCBlock_NSComparisonResult_objcObjCObject_objcObjCObject_fnPtrTrampoline( .asFunction< int Function(ffi.Pointer, ffi.Pointer)>()(arg0, arg1); -final _ObjCBlock_NSComparisonResult_objcObjCObject_objcObjCObject_closureRegistry = - , ffi.Pointer)>{}; -int _ObjCBlock_NSComparisonResult_objcObjCObject_objcObjCObject_closureRegistryIndex = - 0; -ffi.Pointer - _ObjCBlock_NSComparisonResult_objcObjCObject_objcObjCObject_registerClosure( - int Function(ffi.Pointer, ffi.Pointer) - fn) { - final id = - ++_ObjCBlock_NSComparisonResult_objcObjCObject_objcObjCObject_closureRegistryIndex; - _ObjCBlock_NSComparisonResult_objcObjCObject_objcObjCObject_closureRegistry[ - id] = fn; - return ffi.Pointer.fromAddress(id); -} - int _ObjCBlock_NSComparisonResult_objcObjCObject_objcObjCObject_closureTrampoline( ffi.Pointer block, ffi.Pointer arg0, ffi.Pointer arg1) => - _ObjCBlock_NSComparisonResult_objcObjCObject_objcObjCObject_closureRegistry[ - block.ref.target.address]!(arg0, arg1); + (objc.getBlockClosure(block) as int Function(ffi.Pointer, + ffi.Pointer))(arg0, arg1); class ObjCBlock_NSComparisonResult_objcObjCObject_objcObjCObject extends objc.ObjCBlockBase { @@ -6888,7 +6801,7 @@ class ObjCBlock_NSComparisonResult_objcObjCObject_objcObjCObject ffi.Int32 Function(ffi.Pointer arg0, ffi.Pointer arg1)>> ptr) - : this._(objc.newBlock( + : this._(objc.newPointerBlock( _cFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Int32 Function( ffi.Pointer, @@ -6907,7 +6820,7 @@ class ObjCBlock_NSComparisonResult_objcObjCObject_objcObjCObject /// will result in a crash. ObjCBlock_NSComparisonResult_objcObjCObject_objcObjCObject.fromFunction( int Function(NSObject, NSObject) fn) - : this._(objc.newBlock( + : this._(objc.newClosureBlock( _dartFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Int32 Function( ffi.Pointer, @@ -6915,9 +6828,9 @@ class ObjCBlock_NSComparisonResult_objcObjCObject_objcObjCObject ffi.Pointer)>( _ObjCBlock_NSComparisonResult_objcObjCObject_objcObjCObject_closureTrampoline, 0) .cast(), - _ObjCBlock_NSComparisonResult_objcObjCObject_objcObjCObject_registerClosure( - (ffi.Pointer arg0, ffi.Pointer arg1) => - fn(NSObject.castFromPointer(arg0, retain: true, release: true), NSObject.castFromPointer(arg1, retain: true, release: true))))); + (ffi.Pointer arg0, ffi.Pointer arg1) => fn( + NSObject.castFromPointer(arg0, retain: true, release: true), + NSObject.castFromPointer(arg1, retain: true, release: true)))); static ffi.Pointer? _dartFuncTrampoline; int call(NSObject arg0, NSObject arg1) => pointer.ref.invoke @@ -7077,27 +6990,12 @@ bool _ObjCBlock_bool_objcObjCObject_objcObjCObject_fnPtrTrampoline( .asFunction< bool Function(ffi.Pointer, ffi.Pointer)>()(arg0, arg1); -final _ObjCBlock_bool_objcObjCObject_objcObjCObject_closureRegistry = , ffi.Pointer)>{}; -int _ObjCBlock_bool_objcObjCObject_objcObjCObject_closureRegistryIndex = 0; -ffi.Pointer - _ObjCBlock_bool_objcObjCObject_objcObjCObject_registerClosure( - bool Function( - ffi.Pointer, ffi.Pointer) - fn) { - final id = - ++_ObjCBlock_bool_objcObjCObject_objcObjCObject_closureRegistryIndex; - _ObjCBlock_bool_objcObjCObject_objcObjCObject_closureRegistry[id] = fn; - return ffi.Pointer.fromAddress(id); -} - bool _ObjCBlock_bool_objcObjCObject_objcObjCObject_closureTrampoline( ffi.Pointer block, ffi.Pointer arg0, ffi.Pointer arg1) => - _ObjCBlock_bool_objcObjCObject_objcObjCObject_closureRegistry[ - block.ref.target.address]!(arg0, arg1); + (objc.getBlockClosure(block) as bool Function(ffi.Pointer, + ffi.Pointer))(arg0, arg1); class ObjCBlock_bool_objcObjCObject_objcObjCObject extends objc.ObjCBlockBase { ObjCBlock_bool_objcObjCObject_objcObjCObject._( @@ -7126,7 +7024,7 @@ class ObjCBlock_bool_objcObjCObject_objcObjCObject extends objc.ObjCBlockBase { ffi.Bool Function(ffi.Pointer arg0, ffi.Pointer arg1)>> ptr) - : this._(objc.newBlock( + : this._(objc.newPointerBlock( _cFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Bool Function( ffi.Pointer, @@ -7145,7 +7043,7 @@ class ObjCBlock_bool_objcObjCObject_objcObjCObject extends objc.ObjCBlockBase { /// will result in a crash. ObjCBlock_bool_objcObjCObject_objcObjCObject.fromFunction( bool Function(NSObject, NSObject) fn) - : this._(objc.newBlock( + : this._(objc.newClosureBlock( _dartFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Bool Function( ffi.Pointer, @@ -7153,9 +7051,9 @@ class ObjCBlock_bool_objcObjCObject_objcObjCObject extends objc.ObjCBlockBase { ffi.Pointer)>( _ObjCBlock_bool_objcObjCObject_objcObjCObject_closureTrampoline, false) .cast(), - _ObjCBlock_bool_objcObjCObject_objcObjCObject_registerClosure( - (ffi.Pointer arg0, ffi.Pointer arg1) => - fn(NSObject.castFromPointer(arg0, retain: true, release: true), NSObject.castFromPointer(arg1, retain: true, release: true))))); + (ffi.Pointer arg0, ffi.Pointer arg1) => fn( + NSObject.castFromPointer(arg0, retain: true, release: true), + NSObject.castFromPointer(arg1, retain: true, release: true)))); static ffi.Pointer? _dartFuncTrampoline; bool call(NSObject arg0, NSObject arg1) => pointer.ref.invoke @@ -7966,31 +7864,13 @@ void _ObjCBlock_ffiVoid_objcObjCObject_objcObjCObject_bool_fnPtrTrampoline( ffi.Pointer, ffi.Pointer, ffi.Pointer)>()(arg0, arg1, arg2); -final _ObjCBlock_ffiVoid_objcObjCObject_objcObjCObject_bool_closureRegistry = - , - ffi.Pointer, ffi.Pointer)>{}; -int _ObjCBlock_ffiVoid_objcObjCObject_objcObjCObject_bool_closureRegistryIndex = - 0; -ffi.Pointer - _ObjCBlock_ffiVoid_objcObjCObject_objcObjCObject_bool_registerClosure( - void Function(ffi.Pointer, - ffi.Pointer, ffi.Pointer) - fn) { - final id = - ++_ObjCBlock_ffiVoid_objcObjCObject_objcObjCObject_bool_closureRegistryIndex; - _ObjCBlock_ffiVoid_objcObjCObject_objcObjCObject_bool_closureRegistry[id] = - fn; - return ffi.Pointer.fromAddress(id); -} - void _ObjCBlock_ffiVoid_objcObjCObject_objcObjCObject_bool_closureTrampoline( ffi.Pointer block, ffi.Pointer arg0, ffi.Pointer arg1, ffi.Pointer arg2) => - _ObjCBlock_ffiVoid_objcObjCObject_objcObjCObject_bool_closureRegistry[ - block.ref.target.address]!(arg0, arg1, arg2); + (objc.getBlockClosure(block) as void Function(ffi.Pointer, + ffi.Pointer, ffi.Pointer))(arg0, arg1, arg2); class ObjCBlock_ffiVoid_objcObjCObject_objcObjCObject_bool extends objc.ObjCBlockBase { @@ -8022,7 +7902,7 @@ class ObjCBlock_ffiVoid_objcObjCObject_objcObjCObject_bool ffi.Pointer arg1, ffi.Pointer arg2)>> ptr) - : this._(objc.newBlock( + : this._(objc.newPointerBlock( _cFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Void Function( ffi.Pointer, @@ -8041,7 +7921,7 @@ class ObjCBlock_ffiVoid_objcObjCObject_objcObjCObject_bool /// will result in a crash. ObjCBlock_ffiVoid_objcObjCObject_objcObjCObject_bool.fromFunction( void Function(NSObject, NSObject, ffi.Pointer) fn) - : this._(objc.newBlock( + : this._(objc.newClosureBlock( _dartFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Void Function( ffi.Pointer, @@ -8050,11 +7930,11 @@ class ObjCBlock_ffiVoid_objcObjCObject_objcObjCObject_bool ffi.Pointer)>( _ObjCBlock_ffiVoid_objcObjCObject_objcObjCObject_bool_closureTrampoline) .cast(), - _ObjCBlock_ffiVoid_objcObjCObject_objcObjCObject_bool_registerClosure( - (ffi.Pointer arg0, - ffi.Pointer arg1, - ffi.Pointer arg2) => - fn(NSObject.castFromPointer(arg0, retain: true, release: true), NSObject.castFromPointer(arg1, retain: true, release: true), arg2)))); + (ffi.Pointer arg0, ffi.Pointer arg1, ffi.Pointer arg2) => + fn( + NSObject.castFromPointer(arg0, retain: true, release: true), + NSObject.castFromPointer(arg1, retain: true, release: true), + arg2))); static ffi.Pointer? _dartFuncTrampoline; /// Creates a listener block from a Dart function. @@ -8068,7 +7948,7 @@ class ObjCBlock_ffiVoid_objcObjCObject_objcObjCObject_bool /// blocks do not keep the isolate alive. ObjCBlock_ffiVoid_objcObjCObject_objcObjCObject_bool.listener( void Function(NSObject, NSObject, ffi.Pointer) fn) - : this._(objc.newBlock( + : this._(objc.newClosureBlock( (_dartFuncListenerTrampoline ??= ffi.NativeCallable< ffi.Void Function( ffi.Pointer, @@ -8079,11 +7959,11 @@ class ObjCBlock_ffiVoid_objcObjCObject_objcObjCObject_bool ..keepIsolateAlive = false) .nativeFunction .cast(), - _ObjCBlock_ffiVoid_objcObjCObject_objcObjCObject_bool_registerClosure( - (ffi.Pointer arg0, - ffi.Pointer arg1, - ffi.Pointer arg2) => - fn(NSObject.castFromPointer(arg0, retain: true, release: true), NSObject.castFromPointer(arg1, retain: true, release: true), arg2)))); + (ffi.Pointer arg0, ffi.Pointer arg1, ffi.Pointer arg2) => + fn( + NSObject.castFromPointer(arg0, retain: true, release: true), + NSObject.castFromPointer(arg1, retain: true, release: true), + arg2))); static ffi.NativeCallable< ffi.Void Function( ffi.Pointer, @@ -8156,28 +8036,13 @@ bool _ObjCBlock_bool_objcObjCObject_objcObjCObject_bool_fnPtrTrampoline( ffi.Pointer, ffi.Pointer, ffi.Pointer)>()(arg0, arg1, arg2); -final _ObjCBlock_bool_objcObjCObject_objcObjCObject_bool_closureRegistry = , ffi.Pointer, - ffi.Pointer)>{}; -int _ObjCBlock_bool_objcObjCObject_objcObjCObject_bool_closureRegistryIndex = 0; -ffi.Pointer - _ObjCBlock_bool_objcObjCObject_objcObjCObject_bool_registerClosure( - bool Function(ffi.Pointer, - ffi.Pointer, ffi.Pointer) - fn) { - final id = - ++_ObjCBlock_bool_objcObjCObject_objcObjCObject_bool_closureRegistryIndex; - _ObjCBlock_bool_objcObjCObject_objcObjCObject_bool_closureRegistry[id] = fn; - return ffi.Pointer.fromAddress(id); -} - bool _ObjCBlock_bool_objcObjCObject_objcObjCObject_bool_closureTrampoline( ffi.Pointer block, ffi.Pointer arg0, ffi.Pointer arg1, ffi.Pointer arg2) => - _ObjCBlock_bool_objcObjCObject_objcObjCObject_bool_closureRegistry[ - block.ref.target.address]!(arg0, arg1, arg2); + (objc.getBlockClosure(block) as bool Function(ffi.Pointer, + ffi.Pointer, ffi.Pointer))(arg0, arg1, arg2); class ObjCBlock_bool_objcObjCObject_objcObjCObject_bool extends objc.ObjCBlockBase { @@ -8209,7 +8074,7 @@ class ObjCBlock_bool_objcObjCObject_objcObjCObject_bool ffi.Pointer arg1, ffi.Pointer arg2)>> ptr) - : this._(objc.newBlock( + : this._(objc.newPointerBlock( _cFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Bool Function( ffi.Pointer, @@ -8229,7 +8094,7 @@ class ObjCBlock_bool_objcObjCObject_objcObjCObject_bool /// will result in a crash. ObjCBlock_bool_objcObjCObject_objcObjCObject_bool.fromFunction( bool Function(NSObject, NSObject, ffi.Pointer) fn) - : this._(objc.newBlock( + : this._(objc.newClosureBlock( _dartFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Bool Function( ffi.Pointer, @@ -8238,10 +8103,10 @@ class ObjCBlock_bool_objcObjCObject_objcObjCObject_bool ffi.Pointer)>( _ObjCBlock_bool_objcObjCObject_objcObjCObject_bool_closureTrampoline, false) .cast(), - _ObjCBlock_bool_objcObjCObject_objcObjCObject_bool_registerClosure((ffi.Pointer arg0, - ffi.Pointer arg1, - ffi.Pointer arg2) => - fn(NSObject.castFromPointer(arg0, retain: true, release: true), NSObject.castFromPointer(arg1, retain: true, release: true), arg2)))); + (ffi.Pointer arg0, ffi.Pointer arg1, ffi.Pointer arg2) => fn( + NSObject.castFromPointer(arg0, retain: true, release: true), + NSObject.castFromPointer(arg1, retain: true, release: true), + arg2))); static ffi.Pointer? _dartFuncTrampoline; bool call(NSObject arg0, NSObject arg1, ffi.Pointer arg2) => @@ -8975,23 +8840,13 @@ void _ObjCBlock_ffiVoid_ffiVoid_NSRange_bool_fnPtrTrampoline( .asFunction< void Function(ffi.Pointer, _NSRange, ffi.Pointer)>()(arg0, arg1, arg2); -final _ObjCBlock_ffiVoid_ffiVoid_NSRange_bool_closureRegistry = , _NSRange, ffi.Pointer)>{}; -int _ObjCBlock_ffiVoid_ffiVoid_NSRange_bool_closureRegistryIndex = 0; -ffi.Pointer _ObjCBlock_ffiVoid_ffiVoid_NSRange_bool_registerClosure( - void Function(ffi.Pointer, _NSRange, ffi.Pointer) fn) { - final id = ++_ObjCBlock_ffiVoid_ffiVoid_NSRange_bool_closureRegistryIndex; - _ObjCBlock_ffiVoid_ffiVoid_NSRange_bool_closureRegistry[id] = fn; - return ffi.Pointer.fromAddress(id); -} - void _ObjCBlock_ffiVoid_ffiVoid_NSRange_bool_closureTrampoline( ffi.Pointer block, ffi.Pointer arg0, _NSRange arg1, ffi.Pointer arg2) => - _ObjCBlock_ffiVoid_ffiVoid_NSRange_bool_closureRegistry[ - block.ref.target.address]!(arg0, arg1, arg2); + (objc.getBlockClosure(block) as void Function(ffi.Pointer, + _NSRange, ffi.Pointer))(arg0, arg1, arg2); class ObjCBlock_ffiVoid_ffiVoid_NSRange_bool extends objc.ObjCBlockBase { ObjCBlock_ffiVoid_ffiVoid_NSRange_bool._(ffi.Pointer pointer, @@ -9018,7 +8873,7 @@ class ObjCBlock_ffiVoid_ffiVoid_NSRange_bool extends objc.ObjCBlockBase { ffi.Void Function(ffi.Pointer arg0, _NSRange arg1, ffi.Pointer arg2)>> ptr) - : this._(objc.newBlock( + : this._(objc.newPointerBlock( _cFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Void Function( ffi.Pointer, @@ -9037,7 +8892,7 @@ class ObjCBlock_ffiVoid_ffiVoid_NSRange_bool extends objc.ObjCBlockBase { /// will result in a crash. ObjCBlock_ffiVoid_ffiVoid_NSRange_bool.fromFunction( void Function(ffi.Pointer, _NSRange, ffi.Pointer) fn) - : this._(objc.newBlock( + : this._(objc.newClosureBlock( _dartFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Void Function( ffi.Pointer, @@ -9046,10 +8901,9 @@ class ObjCBlock_ffiVoid_ffiVoid_NSRange_bool extends objc.ObjCBlockBase { ffi.Pointer)>( _ObjCBlock_ffiVoid_ffiVoid_NSRange_bool_closureTrampoline) .cast(), - _ObjCBlock_ffiVoid_ffiVoid_NSRange_bool_registerClosure( - (ffi.Pointer arg0, _NSRange arg1, - ffi.Pointer arg2) => - fn(arg0, arg1, arg2)))); + (ffi.Pointer arg0, _NSRange arg1, + ffi.Pointer arg2) => + fn(arg0, arg1, arg2))); static ffi.Pointer? _dartFuncTrampoline; /// Creates a listener block from a Dart function. @@ -9063,7 +8917,7 @@ class ObjCBlock_ffiVoid_ffiVoid_NSRange_bool extends objc.ObjCBlockBase { /// blocks do not keep the isolate alive. ObjCBlock_ffiVoid_ffiVoid_NSRange_bool.listener( void Function(ffi.Pointer, _NSRange, ffi.Pointer) fn) - : this._(objc.newBlock( + : this._(objc.newClosureBlock( (_dartFuncListenerTrampoline ??= ffi.NativeCallable< ffi.Void Function( ffi.Pointer, @@ -9074,10 +8928,9 @@ class ObjCBlock_ffiVoid_ffiVoid_NSRange_bool extends objc.ObjCBlockBase { ..keepIsolateAlive = false) .nativeFunction .cast(), - _ObjCBlock_ffiVoid_ffiVoid_NSRange_bool_registerClosure( - (ffi.Pointer arg0, _NSRange arg1, - ffi.Pointer arg2) => - fn(arg0, arg1, arg2)))); + (ffi.Pointer arg0, _NSRange arg1, + ffi.Pointer arg2) => + fn(arg0, arg1, arg2))); static ffi.NativeCallable< ffi.Void Function(ffi.Pointer, ffi.Pointer, _NSRange, ffi.Pointer)>? _dartFuncListenerTrampoline; @@ -9220,23 +9073,12 @@ void _ObjCBlock_ffiVoid_ffiVoid_ffiUnsignedLong_fnPtrTrampoline( ffi.Void Function( ffi.Pointer arg0, ffi.UnsignedLong arg1)>>() .asFunction, int)>()(arg0, arg1); -final _ObjCBlock_ffiVoid_ffiVoid_ffiUnsignedLong_closureRegistry = - , int)>{}; -int _ObjCBlock_ffiVoid_ffiVoid_ffiUnsignedLong_closureRegistryIndex = 0; -ffi.Pointer - _ObjCBlock_ffiVoid_ffiVoid_ffiUnsignedLong_registerClosure( - void Function(ffi.Pointer, int) fn) { - final id = ++_ObjCBlock_ffiVoid_ffiVoid_ffiUnsignedLong_closureRegistryIndex; - _ObjCBlock_ffiVoid_ffiVoid_ffiUnsignedLong_closureRegistry[id] = fn; - return ffi.Pointer.fromAddress(id); -} - void _ObjCBlock_ffiVoid_ffiVoid_ffiUnsignedLong_closureTrampoline( ffi.Pointer block, ffi.Pointer arg0, int arg1) => - _ObjCBlock_ffiVoid_ffiVoid_ffiUnsignedLong_closureRegistry[ - block.ref.target.address]!(arg0, arg1); + (objc.getBlockClosure(block) as void Function(ffi.Pointer, int))( + arg0, arg1); class ObjCBlock_ffiVoid_ffiVoid_ffiUnsignedLong extends objc.ObjCBlockBase { ObjCBlock_ffiVoid_ffiVoid_ffiUnsignedLong._( @@ -9265,7 +9107,7 @@ class ObjCBlock_ffiVoid_ffiVoid_ffiUnsignedLong extends objc.ObjCBlockBase { ffi.Void Function( ffi.Pointer arg0, ffi.UnsignedLong arg1)>> ptr) - : this._(objc.newBlock( + : this._(objc.newPointerBlock( _cFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.UnsignedLong)>( @@ -9281,14 +9123,13 @@ class ObjCBlock_ffiVoid_ffiVoid_ffiUnsignedLong extends objc.ObjCBlockBase { /// will result in a crash. ObjCBlock_ffiVoid_ffiVoid_ffiUnsignedLong.fromFunction( void Function(ffi.Pointer, int) fn) - : this._(objc.newBlock( + : this._(objc.newClosureBlock( _dartFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.UnsignedLong)>( _ObjCBlock_ffiVoid_ffiVoid_ffiUnsignedLong_closureTrampoline) .cast(), - _ObjCBlock_ffiVoid_ffiVoid_ffiUnsignedLong_registerClosure( - (ffi.Pointer arg0, int arg1) => fn(arg0, arg1)))); + (ffi.Pointer arg0, int arg1) => fn(arg0, arg1))); static ffi.Pointer? _dartFuncTrampoline; /// Creates a listener block from a Dart function. @@ -9302,7 +9143,7 @@ class ObjCBlock_ffiVoid_ffiVoid_ffiUnsignedLong extends objc.ObjCBlockBase { /// blocks do not keep the isolate alive. ObjCBlock_ffiVoid_ffiVoid_ffiUnsignedLong.listener( void Function(ffi.Pointer, int) fn) - : this._(objc.newBlock( + : this._(objc.newClosureBlock( (_dartFuncListenerTrampoline ??= ffi.NativeCallable< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.UnsignedLong)>.listener( @@ -9310,8 +9151,7 @@ class ObjCBlock_ffiVoid_ffiVoid_ffiUnsignedLong extends objc.ObjCBlockBase { ..keepIsolateAlive = false) .nativeFunction .cast(), - _ObjCBlock_ffiVoid_ffiVoid_ffiUnsignedLong_registerClosure( - (ffi.Pointer arg0, int arg1) => fn(arg0, arg1)))); + (ffi.Pointer arg0, int arg1) => fn(arg0, arg1))); static ffi.NativeCallable< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.UnsignedLong)>? _dartFuncListenerTrampoline; @@ -9765,29 +9605,14 @@ void _ObjCBlock_ffiVoid_NSString_NSRange_NSRange_bool_fnPtrTrampoline( .asFunction< void Function(ffi.Pointer, _NSRange, _NSRange, ffi.Pointer)>()(arg0, arg1, arg2, arg3); -final _ObjCBlock_ffiVoid_NSString_NSRange_NSRange_bool_closureRegistry = , _NSRange, _NSRange, - ffi.Pointer)>{}; -int _ObjCBlock_ffiVoid_NSString_NSRange_NSRange_bool_closureRegistryIndex = 0; -ffi.Pointer - _ObjCBlock_ffiVoid_NSString_NSRange_NSRange_bool_registerClosure( - void Function(ffi.Pointer, _NSRange, _NSRange, - ffi.Pointer) - fn) { - final id = - ++_ObjCBlock_ffiVoid_NSString_NSRange_NSRange_bool_closureRegistryIndex; - _ObjCBlock_ffiVoid_NSString_NSRange_NSRange_bool_closureRegistry[id] = fn; - return ffi.Pointer.fromAddress(id); -} - void _ObjCBlock_ffiVoid_NSString_NSRange_NSRange_bool_closureTrampoline( ffi.Pointer block, ffi.Pointer arg0, _NSRange arg1, _NSRange arg2, ffi.Pointer arg3) => - _ObjCBlock_ffiVoid_NSString_NSRange_NSRange_bool_closureRegistry[ - block.ref.target.address]!(arg0, arg1, arg2, arg3); + (objc.getBlockClosure(block) as void Function(ffi.Pointer, + _NSRange, _NSRange, ffi.Pointer))(arg0, arg1, arg2, arg3); class ObjCBlock_ffiVoid_NSString_NSRange_NSRange_bool extends objc.ObjCBlockBase { @@ -9820,7 +9645,7 @@ class ObjCBlock_ffiVoid_NSString_NSRange_NSRange_bool _NSRange arg2, ffi.Pointer arg3)>> ptr) - : this._(objc.newBlock( + : this._(objc.newPointerBlock( _cFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Void Function( ffi.Pointer, @@ -9840,7 +9665,7 @@ class ObjCBlock_ffiVoid_NSString_NSRange_NSRange_bool /// will result in a crash. ObjCBlock_ffiVoid_NSString_NSRange_NSRange_bool.fromFunction( void Function(NSString?, _NSRange, _NSRange, ffi.Pointer) fn) - : this._(objc.newBlock( + : this._(objc.newClosureBlock( _dartFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Void Function( ffi.Pointer, @@ -9850,10 +9675,9 @@ class ObjCBlock_ffiVoid_NSString_NSRange_NSRange_bool ffi.Pointer)>( _ObjCBlock_ffiVoid_NSString_NSRange_NSRange_bool_closureTrampoline) .cast(), - _ObjCBlock_ffiVoid_NSString_NSRange_NSRange_bool_registerClosure( - (ffi.Pointer arg0, _NSRange arg1, - _NSRange arg2, ffi.Pointer arg3) => - fn(arg0.address == 0 ? null : NSString.castFromPointer(arg0, retain: true, release: true), arg1, arg2, arg3)))); + (ffi.Pointer arg0, _NSRange arg1, _NSRange arg2, + ffi.Pointer arg3) => + fn(arg0.address == 0 ? null : NSString.castFromPointer(arg0, retain: true, release: true), arg1, arg2, arg3))); static ffi.Pointer? _dartFuncTrampoline; /// Creates a listener block from a Dart function. @@ -9867,7 +9691,7 @@ class ObjCBlock_ffiVoid_NSString_NSRange_NSRange_bool /// blocks do not keep the isolate alive. ObjCBlock_ffiVoid_NSString_NSRange_NSRange_bool.listener( void Function(NSString?, _NSRange, _NSRange, ffi.Pointer) fn) - : this._(objc.newBlock( + : this._(objc.newClosureBlock( (_dartFuncListenerTrampoline ??= ffi.NativeCallable< ffi.Void Function( ffi.Pointer, @@ -9879,9 +9703,9 @@ class ObjCBlock_ffiVoid_NSString_NSRange_NSRange_bool ..keepIsolateAlive = false) .nativeFunction .cast(), - _ObjCBlock_ffiVoid_NSString_NSRange_NSRange_bool_registerClosure((ffi.Pointer arg0, - _NSRange arg1, _NSRange arg2, ffi.Pointer arg3) => - fn(arg0.address == 0 ? null : NSString.castFromPointer(arg0, retain: true, release: true), arg1, arg2, arg3)))); + (ffi.Pointer arg0, _NSRange arg1, _NSRange arg2, + ffi.Pointer arg3) => + fn(arg0.address == 0 ? null : NSString.castFromPointer(arg0, retain: true, release: true), arg1, arg2, arg3))); static ffi.NativeCallable< ffi.Void Function( ffi.Pointer, @@ -9941,22 +9765,12 @@ void _ObjCBlock_ffiVoid_NSString_bool_fnPtrTrampoline( .asFunction< void Function(ffi.Pointer, ffi.Pointer)>()(arg0, arg1); -final _ObjCBlock_ffiVoid_NSString_bool_closureRegistry = - , ffi.Pointer)>{}; -int _ObjCBlock_ffiVoid_NSString_bool_closureRegistryIndex = 0; -ffi.Pointer _ObjCBlock_ffiVoid_NSString_bool_registerClosure( - void Function(ffi.Pointer, ffi.Pointer) fn) { - final id = ++_ObjCBlock_ffiVoid_NSString_bool_closureRegistryIndex; - _ObjCBlock_ffiVoid_NSString_bool_closureRegistry[id] = fn; - return ffi.Pointer.fromAddress(id); -} - void _ObjCBlock_ffiVoid_NSString_bool_closureTrampoline( ffi.Pointer block, ffi.Pointer arg0, ffi.Pointer arg1) => - _ObjCBlock_ffiVoid_NSString_bool_closureRegistry[block.ref.target.address]!( - arg0, arg1); + (objc.getBlockClosure(block) as void Function( + ffi.Pointer, ffi.Pointer))(arg0, arg1); class ObjCBlock_ffiVoid_NSString_bool extends objc.ObjCBlockBase { ObjCBlock_ffiVoid_NSString_bool._(ffi.Pointer pointer, @@ -9985,7 +9799,7 @@ class ObjCBlock_ffiVoid_NSString_bool extends objc.ObjCBlockBase { ptr) : this._( objc - .newBlock( + .newPointerBlock( _cFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Void Function( ffi.Pointer, @@ -10003,7 +9817,7 @@ class ObjCBlock_ffiVoid_NSString_bool extends objc.ObjCBlockBase { /// will result in a crash. ObjCBlock_ffiVoid_NSString_bool.fromFunction( void Function(NSString, ffi.Pointer) fn) - : this._(objc.newBlock( + : this._(objc.newClosureBlock( _dartFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Void Function( ffi.Pointer, @@ -10011,10 +9825,9 @@ class ObjCBlock_ffiVoid_NSString_bool extends objc.ObjCBlockBase { ffi.Pointer)>( _ObjCBlock_ffiVoid_NSString_bool_closureTrampoline) .cast(), - _ObjCBlock_ffiVoid_NSString_bool_registerClosure( - (ffi.Pointer arg0, - ffi.Pointer arg1) => - fn(NSString.castFromPointer(arg0, retain: true, release: true), arg1)))); + (ffi.Pointer arg0, ffi.Pointer arg1) => + fn(NSString.castFromPointer(arg0, retain: true, release: true), + arg1))); static ffi.Pointer? _dartFuncTrampoline; /// Creates a listener block from a Dart function. @@ -10028,7 +9841,7 @@ class ObjCBlock_ffiVoid_NSString_bool extends objc.ObjCBlockBase { /// blocks do not keep the isolate alive. ObjCBlock_ffiVoid_NSString_bool.listener( void Function(NSString, ffi.Pointer) fn) - : this._(objc.newBlock( + : this._(objc.newClosureBlock( (_dartFuncListenerTrampoline ??= ffi.NativeCallable< ffi.Void Function( ffi.Pointer, @@ -10038,10 +9851,9 @@ class ObjCBlock_ffiVoid_NSString_bool extends objc.ObjCBlockBase { ..keepIsolateAlive = false) .nativeFunction .cast(), - _ObjCBlock_ffiVoid_NSString_bool_registerClosure( - (ffi.Pointer arg0, - ffi.Pointer arg1) => - fn(NSString.castFromPointer(arg0, retain: true, release: true), arg1)))); + (ffi.Pointer arg0, ffi.Pointer arg1) => + fn(NSString.castFromPointer(arg0, retain: true, release: true), + arg1))); static ffi.NativeCallable< ffi.Void Function( ffi.Pointer, @@ -10387,25 +10199,12 @@ void _ObjCBlock_ffiVoid_ffiUnsignedShort_ffiUnsignedLong_fnPtrTrampoline( ffi.UnsignedLong arg1)>>() .asFunction, int)>()( arg0, arg1); -final _ObjCBlock_ffiVoid_ffiUnsignedShort_ffiUnsignedLong_closureRegistry = - , int)>{}; -int _ObjCBlock_ffiVoid_ffiUnsignedShort_ffiUnsignedLong_closureRegistryIndex = - 0; -ffi.Pointer - _ObjCBlock_ffiVoid_ffiUnsignedShort_ffiUnsignedLong_registerClosure( - void Function(ffi.Pointer, int) fn) { - final id = - ++_ObjCBlock_ffiVoid_ffiUnsignedShort_ffiUnsignedLong_closureRegistryIndex; - _ObjCBlock_ffiVoid_ffiUnsignedShort_ffiUnsignedLong_closureRegistry[id] = fn; - return ffi.Pointer.fromAddress(id); -} - void _ObjCBlock_ffiVoid_ffiUnsignedShort_ffiUnsignedLong_closureTrampoline( ffi.Pointer block, ffi.Pointer arg0, int arg1) => - _ObjCBlock_ffiVoid_ffiUnsignedShort_ffiUnsignedLong_closureRegistry[ - block.ref.target.address]!(arg0, arg1); + (objc.getBlockClosure(block) as void Function( + ffi.Pointer, int))(arg0, arg1); class ObjCBlock_ffiVoid_ffiUnsignedShort_ffiUnsignedLong extends objc.ObjCBlockBase { @@ -10437,7 +10236,7 @@ class ObjCBlock_ffiVoid_ffiUnsignedShort_ffiUnsignedLong ffi.Void Function(ffi.Pointer arg0, ffi.UnsignedLong arg1)>> ptr) - : this._(objc.newBlock( + : this._(objc.newPointerBlock( _cFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.UnsignedLong)>( @@ -10453,15 +10252,13 @@ class ObjCBlock_ffiVoid_ffiUnsignedShort_ffiUnsignedLong /// will result in a crash. ObjCBlock_ffiVoid_ffiUnsignedShort_ffiUnsignedLong.fromFunction( void Function(ffi.Pointer, int) fn) - : this._(objc.newBlock( + : this._(objc.newClosureBlock( _dartFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.UnsignedLong)>( _ObjCBlock_ffiVoid_ffiUnsignedShort_ffiUnsignedLong_closureTrampoline) .cast(), - _ObjCBlock_ffiVoid_ffiUnsignedShort_ffiUnsignedLong_registerClosure( - (ffi.Pointer arg0, int arg1) => - fn(arg0, arg1)))); + (ffi.Pointer arg0, int arg1) => fn(arg0, arg1))); static ffi.Pointer? _dartFuncTrampoline; /// Creates a listener block from a Dart function. @@ -10475,7 +10272,7 @@ class ObjCBlock_ffiVoid_ffiUnsignedShort_ffiUnsignedLong /// blocks do not keep the isolate alive. ObjCBlock_ffiVoid_ffiUnsignedShort_ffiUnsignedLong.listener( void Function(ffi.Pointer, int) fn) - : this._(objc.newBlock( + : this._(objc.newClosureBlock( (_dartFuncListenerTrampoline ??= ffi.NativeCallable< ffi.Void Function( ffi.Pointer, @@ -10485,9 +10282,7 @@ class ObjCBlock_ffiVoid_ffiUnsignedShort_ffiUnsignedLong ..keepIsolateAlive = false) .nativeFunction .cast(), - _ObjCBlock_ffiVoid_ffiUnsignedShort_ffiUnsignedLong_registerClosure( - (ffi.Pointer arg0, int arg1) => - fn(arg0, arg1)))); + (ffi.Pointer arg0, int arg1) => fn(arg0, arg1))); static ffi.NativeCallable< ffi.Void Function( ffi.Pointer, @@ -13160,22 +12955,12 @@ void _ObjCBlock_ffiVoid_objcObjCObject_bool_fnPtrTrampoline( .asFunction< void Function(ffi.Pointer, ffi.Pointer)>()(arg0, arg1); -final _ObjCBlock_ffiVoid_objcObjCObject_bool_closureRegistry = - , ffi.Pointer)>{}; -int _ObjCBlock_ffiVoid_objcObjCObject_bool_closureRegistryIndex = 0; -ffi.Pointer _ObjCBlock_ffiVoid_objcObjCObject_bool_registerClosure( - void Function(ffi.Pointer, ffi.Pointer) fn) { - final id = ++_ObjCBlock_ffiVoid_objcObjCObject_bool_closureRegistryIndex; - _ObjCBlock_ffiVoid_objcObjCObject_bool_closureRegistry[id] = fn; - return ffi.Pointer.fromAddress(id); -} - void _ObjCBlock_ffiVoid_objcObjCObject_bool_closureTrampoline( ffi.Pointer block, ffi.Pointer arg0, ffi.Pointer arg1) => - _ObjCBlock_ffiVoid_objcObjCObject_bool_closureRegistry[ - block.ref.target.address]!(arg0, arg1); + (objc.getBlockClosure(block) as void Function( + ffi.Pointer, ffi.Pointer))(arg0, arg1); class ObjCBlock_ffiVoid_objcObjCObject_bool extends objc.ObjCBlockBase { ObjCBlock_ffiVoid_objcObjCObject_bool._(ffi.Pointer pointer, @@ -13203,7 +12988,7 @@ class ObjCBlock_ffiVoid_objcObjCObject_bool extends objc.ObjCBlockBase { ffi.Pointer arg1)>> ptr) : this._( - objc.newBlock( + objc.newPointerBlock( _cFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Void Function( ffi.Pointer, @@ -13221,7 +13006,7 @@ class ObjCBlock_ffiVoid_objcObjCObject_bool extends objc.ObjCBlockBase { /// will result in a crash. ObjCBlock_ffiVoid_objcObjCObject_bool.fromFunction( void Function(NSObject, ffi.Pointer) fn) - : this._(objc.newBlock( + : this._(objc.newClosureBlock( _dartFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Void Function( ffi.Pointer, @@ -13229,10 +13014,9 @@ class ObjCBlock_ffiVoid_objcObjCObject_bool extends objc.ObjCBlockBase { ffi.Pointer)>( _ObjCBlock_ffiVoid_objcObjCObject_bool_closureTrampoline) .cast(), - _ObjCBlock_ffiVoid_objcObjCObject_bool_registerClosure( - (ffi.Pointer arg0, - ffi.Pointer arg1) => - fn(NSObject.castFromPointer(arg0, retain: true, release: true), arg1)))); + (ffi.Pointer arg0, ffi.Pointer arg1) => + fn(NSObject.castFromPointer(arg0, retain: true, release: true), + arg1))); static ffi.Pointer? _dartFuncTrampoline; /// Creates a listener block from a Dart function. @@ -13246,7 +13030,7 @@ class ObjCBlock_ffiVoid_objcObjCObject_bool extends objc.ObjCBlockBase { /// blocks do not keep the isolate alive. ObjCBlock_ffiVoid_objcObjCObject_bool.listener( void Function(NSObject, ffi.Pointer) fn) - : this._(objc.newBlock( + : this._(objc.newClosureBlock( (_dartFuncListenerTrampoline ??= ffi.NativeCallable< ffi.Void Function( ffi.Pointer, @@ -13256,10 +13040,9 @@ class ObjCBlock_ffiVoid_objcObjCObject_bool extends objc.ObjCBlockBase { ..keepIsolateAlive = false) .nativeFunction .cast(), - _ObjCBlock_ffiVoid_objcObjCObject_bool_registerClosure( - (ffi.Pointer arg0, - ffi.Pointer arg1) => - fn(NSObject.castFromPointer(arg0, retain: true, release: true), arg1)))); + (ffi.Pointer arg0, ffi.Pointer arg1) => + fn(NSObject.castFromPointer(arg0, retain: true, release: true), + arg1))); static ffi.NativeCallable< ffi.Void Function( ffi.Pointer, @@ -13314,22 +13097,12 @@ bool _ObjCBlock_bool_objcObjCObject_bool_fnPtrTrampoline( .asFunction< bool Function(ffi.Pointer, ffi.Pointer)>()(arg0, arg1); -final _ObjCBlock_bool_objcObjCObject_bool_closureRegistry = - , ffi.Pointer)>{}; -int _ObjCBlock_bool_objcObjCObject_bool_closureRegistryIndex = 0; -ffi.Pointer _ObjCBlock_bool_objcObjCObject_bool_registerClosure( - bool Function(ffi.Pointer, ffi.Pointer) fn) { - final id = ++_ObjCBlock_bool_objcObjCObject_bool_closureRegistryIndex; - _ObjCBlock_bool_objcObjCObject_bool_closureRegistry[id] = fn; - return ffi.Pointer.fromAddress(id); -} - bool _ObjCBlock_bool_objcObjCObject_bool_closureTrampoline( ffi.Pointer block, ffi.Pointer arg0, ffi.Pointer arg1) => - _ObjCBlock_bool_objcObjCObject_bool_closureRegistry[ - block.ref.target.address]!(arg0, arg1); + (objc.getBlockClosure(block) as bool Function( + ffi.Pointer, ffi.Pointer))(arg0, arg1); class ObjCBlock_bool_objcObjCObject_bool extends objc.ObjCBlockBase { ObjCBlock_bool_objcObjCObject_bool._(ffi.Pointer pointer, @@ -13356,7 +13129,7 @@ class ObjCBlock_bool_objcObjCObject_bool extends objc.ObjCBlockBase { ffi.Bool Function(ffi.Pointer arg0, ffi.Pointer arg1)>> ptr) - : this._(objc.newBlock( + : this._(objc.newPointerBlock( _cFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Bool Function( ffi.Pointer, @@ -13374,7 +13147,7 @@ class ObjCBlock_bool_objcObjCObject_bool extends objc.ObjCBlockBase { /// will result in a crash. ObjCBlock_bool_objcObjCObject_bool.fromFunction( bool Function(NSObject, ffi.Pointer) fn) - : this._(objc.newBlock( + : this._(objc.newClosureBlock( _dartFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Bool Function( ffi.Pointer, @@ -13382,10 +13155,9 @@ class ObjCBlock_bool_objcObjCObject_bool extends objc.ObjCBlockBase { ffi.Pointer)>( _ObjCBlock_bool_objcObjCObject_bool_closureTrampoline, false) .cast(), - _ObjCBlock_bool_objcObjCObject_bool_registerClosure( - (ffi.Pointer arg0, - ffi.Pointer arg1) => - fn(NSObject.castFromPointer(arg0, retain: true, release: true), arg1)))); + (ffi.Pointer arg0, ffi.Pointer arg1) => + fn(NSObject.castFromPointer(arg0, retain: true, release: true), + arg1))); static ffi.Pointer? _dartFuncTrampoline; bool call(NSObject arg0, ffi.Pointer arg1) => pointer.ref.invoke @@ -13914,23 +13686,12 @@ ffi.Pointer .asFunction< ffi.Pointer Function( ffi.Pointer)>()(arg0); -final _ObjCBlock_NSProgress_ffiVoidNSDataNSError_closureRegistry = - Function(ffi.Pointer)>{}; -int _ObjCBlock_NSProgress_ffiVoidNSDataNSError_closureRegistryIndex = 0; -ffi.Pointer - _ObjCBlock_NSProgress_ffiVoidNSDataNSError_registerClosure( - ffi.Pointer Function(ffi.Pointer) fn) { - final id = ++_ObjCBlock_NSProgress_ffiVoidNSDataNSError_closureRegistryIndex; - _ObjCBlock_NSProgress_ffiVoidNSDataNSError_closureRegistry[id] = fn; - return ffi.Pointer.fromAddress(id); -} - ffi.Pointer _ObjCBlock_NSProgress_ffiVoidNSDataNSError_closureTrampoline( ffi.Pointer block, ffi.Pointer arg0) => - _ObjCBlock_NSProgress_ffiVoidNSDataNSError_closureRegistry[ - block.ref.target.address]!(arg0); + (objc.getBlockClosure(block) as ffi.Pointer Function( + ffi.Pointer))(arg0); class ObjCBlock_NSProgress_ffiVoidNSDataNSError extends objc.ObjCBlockBase { ObjCBlock_NSProgress_ffiVoidNSDataNSError._( @@ -13959,7 +13720,7 @@ class ObjCBlock_NSProgress_ffiVoidNSDataNSError extends objc.ObjCBlockBase { ffi.Pointer Function( ffi.Pointer arg0)>> ptr) - : this._(objc.newBlock( + : this._(objc.newPointerBlock( _cFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Pointer Function( ffi.Pointer, @@ -13976,18 +13737,17 @@ class ObjCBlock_NSProgress_ffiVoidNSDataNSError extends objc.ObjCBlockBase { /// will result in a crash. ObjCBlock_NSProgress_ffiVoidNSDataNSError.fromFunction( NSProgress? Function(ObjCBlock_ffiVoid_NSData_NSError) fn) - : this._(objc.newBlock( + : this._(objc.newClosureBlock( _dartFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer)>( + ffi.Pointer, ffi.Pointer)>( _ObjCBlock_NSProgress_ffiVoidNSDataNSError_closureTrampoline) .cast(), - _ObjCBlock_NSProgress_ffiVoidNSDataNSError_registerClosure( - (ffi.Pointer arg0) => - fn(ObjCBlock_ffiVoid_NSData_NSError.castFromPointer(arg0, retain: true, release: true)) - ?.retainAndReturnPointer() ?? - ffi.nullptr))); + (ffi.Pointer arg0) => + fn(ObjCBlock_ffiVoid_NSData_NSError.castFromPointer(arg0, + retain: true, release: true)) + ?.retainAndReturnPointer() ?? + ffi.nullptr)); static ffi.Pointer? _dartFuncTrampoline; NSProgress? call(ObjCBlock_ffiVoid_NSData_NSError arg0) => pointer.ref.invoke @@ -14042,24 +13802,12 @@ void _ObjCBlock_ffiVoid_NSData_NSError_fnPtrTrampoline( .asFunction< void Function(ffi.Pointer, ffi.Pointer)>()(arg0, arg1); -final _ObjCBlock_ffiVoid_NSData_NSError_closureRegistry = , ffi.Pointer)>{}; -int _ObjCBlock_ffiVoid_NSData_NSError_closureRegistryIndex = 0; -ffi.Pointer _ObjCBlock_ffiVoid_NSData_NSError_registerClosure( - void Function(ffi.Pointer, ffi.Pointer) - fn) { - final id = ++_ObjCBlock_ffiVoid_NSData_NSError_closureRegistryIndex; - _ObjCBlock_ffiVoid_NSData_NSError_closureRegistry[id] = fn; - return ffi.Pointer.fromAddress(id); -} - void _ObjCBlock_ffiVoid_NSData_NSError_closureTrampoline( ffi.Pointer block, ffi.Pointer arg0, ffi.Pointer arg1) => - _ObjCBlock_ffiVoid_NSData_NSError_closureRegistry[ - block.ref.target.address]!(arg0, arg1); + (objc.getBlockClosure(block) as void Function(ffi.Pointer, + ffi.Pointer))(arg0, arg1); class ObjCBlock_ffiVoid_NSData_NSError extends objc.ObjCBlockBase { ObjCBlock_ffiVoid_NSData_NSError._(ffi.Pointer pointer, @@ -14086,7 +13834,7 @@ class ObjCBlock_ffiVoid_NSData_NSError extends objc.ObjCBlockBase { ffi.Void Function(ffi.Pointer arg0, ffi.Pointer arg1)>> ptr) - : this._(objc.newBlock( + : this._(objc.newPointerBlock( _cFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Void Function( ffi.Pointer, @@ -14103,7 +13851,7 @@ class ObjCBlock_ffiVoid_NSData_NSError extends objc.ObjCBlockBase { /// the isolate that registered it. Invoking the block on the wrong thread /// will result in a crash. ObjCBlock_ffiVoid_NSData_NSError.fromFunction(void Function(NSData?, NSError?) fn) - : this._(objc.newBlock( + : this._(objc.newClosureBlock( _dartFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Void Function( ffi.Pointer, @@ -14111,10 +13859,13 @@ class ObjCBlock_ffiVoid_NSData_NSError extends objc.ObjCBlockBase { ffi.Pointer)>( _ObjCBlock_ffiVoid_NSData_NSError_closureTrampoline) .cast(), - _ObjCBlock_ffiVoid_NSData_NSError_registerClosure( - (ffi.Pointer arg0, ffi.Pointer arg1) => fn( - arg0.address == 0 ? null : NSData.castFromPointer(arg0, retain: true, release: true), - arg1.address == 0 ? null : NSError.castFromPointer(arg1, retain: true, release: true))))); + (ffi.Pointer arg0, ffi.Pointer arg1) => fn( + arg0.address == 0 + ? null + : NSData.castFromPointer(arg0, retain: true, release: true), + arg1.address == 0 + ? null + : NSError.castFromPointer(arg1, retain: true, release: true)))); static ffi.Pointer? _dartFuncTrampoline; /// Creates a listener block from a Dart function. @@ -14127,22 +13878,23 @@ class ObjCBlock_ffiVoid_NSData_NSError extends objc.ObjCBlockBase { /// Note that unlike the default behavior of NativeCallable.listener, listener /// blocks do not keep the isolate alive. ObjCBlock_ffiVoid_NSData_NSError.listener(void Function(NSData?, NSError?) fn) - : this._(objc.newBlock( - (_dartFuncListenerTrampoline ??= - ffi.NativeCallable, ffi.Pointer, ffi.Pointer)>.listener( - _ObjCBlock_ffiVoid_NSData_NSError_closureTrampoline) - ..keepIsolateAlive = false) + : this._(objc.newClosureBlock( + (_dartFuncListenerTrampoline ??= ffi.NativeCallable< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer)>.listener( + _ObjCBlock_ffiVoid_NSData_NSError_closureTrampoline) + ..keepIsolateAlive = false) .nativeFunction .cast(), - _ObjCBlock_ffiVoid_NSData_NSError_registerClosure( - (ffi.Pointer arg0, ffi.Pointer arg1) => fn( - arg0.address == 0 - ? null - : NSData.castFromPointer(arg0, - retain: true, release: true), - arg1.address == 0 - ? null - : NSError.castFromPointer(arg1, retain: true, release: true))))); + (ffi.Pointer arg0, ffi.Pointer arg1) => fn( + arg0.address == 0 + ? null + : NSData.castFromPointer(arg0, retain: true, release: true), + arg1.address == 0 + ? null + : NSError.castFromPointer(arg1, retain: true, release: true)))); static ffi.NativeCallable< ffi.Void Function( ffi.Pointer, @@ -14200,24 +13952,12 @@ ffi.Pointer .asFunction< ffi.Pointer Function( ffi.Pointer)>()(arg0); -final _ObjCBlock_NSProgress_ffiVoidNSURLboolNSError_closureRegistry = - Function(ffi.Pointer)>{}; -int _ObjCBlock_NSProgress_ffiVoidNSURLboolNSError_closureRegistryIndex = 0; -ffi.Pointer - _ObjCBlock_NSProgress_ffiVoidNSURLboolNSError_registerClosure( - ffi.Pointer Function(ffi.Pointer) fn) { - final id = - ++_ObjCBlock_NSProgress_ffiVoidNSURLboolNSError_closureRegistryIndex; - _ObjCBlock_NSProgress_ffiVoidNSURLboolNSError_closureRegistry[id] = fn; - return ffi.Pointer.fromAddress(id); -} - ffi.Pointer _ObjCBlock_NSProgress_ffiVoidNSURLboolNSError_closureTrampoline( ffi.Pointer block, ffi.Pointer arg0) => - _ObjCBlock_NSProgress_ffiVoidNSURLboolNSError_closureRegistry[ - block.ref.target.address]!(arg0); + (objc.getBlockClosure(block) as ffi.Pointer Function( + ffi.Pointer))(arg0); class ObjCBlock_NSProgress_ffiVoidNSURLboolNSError extends objc.ObjCBlockBase { ObjCBlock_NSProgress_ffiVoidNSURLboolNSError._( @@ -14246,7 +13986,7 @@ class ObjCBlock_NSProgress_ffiVoidNSURLboolNSError extends objc.ObjCBlockBase { ffi.Pointer Function( ffi.Pointer arg0)>> ptr) - : this._(objc.newBlock( + : this._(objc.newPointerBlock( _cFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Pointer Function( ffi.Pointer, @@ -14263,18 +14003,17 @@ class ObjCBlock_NSProgress_ffiVoidNSURLboolNSError extends objc.ObjCBlockBase { /// will result in a crash. ObjCBlock_NSProgress_ffiVoidNSURLboolNSError.fromFunction( NSProgress? Function(ObjCBlock_ffiVoid_NSURL_bool_NSError) fn) - : this._(objc.newBlock( + : this._(objc.newClosureBlock( _dartFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>( _ObjCBlock_NSProgress_ffiVoidNSURLboolNSError_closureTrampoline) .cast(), - _ObjCBlock_NSProgress_ffiVoidNSURLboolNSError_registerClosure( - (ffi.Pointer arg0) => - fn(ObjCBlock_ffiVoid_NSURL_bool_NSError.castFromPointer(arg0, retain: true, release: true)) - ?.retainAndReturnPointer() ?? - ffi.nullptr))); + (ffi.Pointer arg0) => + fn(ObjCBlock_ffiVoid_NSURL_bool_NSError.castFromPointer(arg0, retain: true, release: true)) + ?.retainAndReturnPointer() ?? + ffi.nullptr)); static ffi.Pointer? _dartFuncTrampoline; NSProgress? call(ObjCBlock_ffiVoid_NSURL_bool_NSError arg0) => pointer.ref.invoke @@ -14309,26 +14048,13 @@ void _ObjCBlock_ffiVoid_NSURL_bool_NSError_fnPtrTrampoline( .asFunction< void Function(ffi.Pointer, bool, ffi.Pointer)>()(arg0, arg1, arg2); -final _ObjCBlock_ffiVoid_NSURL_bool_NSError_closureRegistry = , bool, ffi.Pointer)>{}; -int _ObjCBlock_ffiVoid_NSURL_bool_NSError_closureRegistryIndex = 0; -ffi.Pointer _ObjCBlock_ffiVoid_NSURL_bool_NSError_registerClosure( - void Function( - ffi.Pointer, bool, ffi.Pointer) - fn) { - final id = ++_ObjCBlock_ffiVoid_NSURL_bool_NSError_closureRegistryIndex; - _ObjCBlock_ffiVoid_NSURL_bool_NSError_closureRegistry[id] = fn; - return ffi.Pointer.fromAddress(id); -} - void _ObjCBlock_ffiVoid_NSURL_bool_NSError_closureTrampoline( ffi.Pointer block, ffi.Pointer arg0, bool arg1, ffi.Pointer arg2) => - _ObjCBlock_ffiVoid_NSURL_bool_NSError_closureRegistry[ - block.ref.target.address]!(arg0, arg1, arg2); + (objc.getBlockClosure(block) as void Function(ffi.Pointer, + bool, ffi.Pointer))(arg0, arg1, arg2); class ObjCBlock_ffiVoid_NSURL_bool_NSError extends objc.ObjCBlockBase { ObjCBlock_ffiVoid_NSURL_bool_NSError._(ffi.Pointer pointer, @@ -14356,7 +14082,7 @@ class ObjCBlock_ffiVoid_NSURL_bool_NSError extends objc.ObjCBlockBase { ffi.Bool arg1, ffi.Pointer arg2)>> ptr) : this._( - objc.newBlock( + objc.newPointerBlock( _cFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Void Function( ffi.Pointer, @@ -14373,9 +14099,8 @@ class ObjCBlock_ffiVoid_NSURL_bool_NSError extends objc.ObjCBlockBase { /// 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. - ObjCBlock_ffiVoid_NSURL_bool_NSError.fromFunction( - void Function(NSURL?, bool, NSError?) fn) - : this._(objc.newBlock( + ObjCBlock_ffiVoid_NSURL_bool_NSError.fromFunction(void Function(NSURL?, bool, NSError?) fn) + : this._(objc.newClosureBlock( _dartFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Void Function( ffi.Pointer, @@ -14384,10 +14109,12 @@ class ObjCBlock_ffiVoid_NSURL_bool_NSError extends objc.ObjCBlockBase { ffi.Pointer)>( _ObjCBlock_ffiVoid_NSURL_bool_NSError_closureTrampoline) .cast(), - _ObjCBlock_ffiVoid_NSURL_bool_NSError_registerClosure( - (ffi.Pointer arg0, bool arg1, - ffi.Pointer arg2) => - fn(arg0.address == 0 ? null : NSURL.castFromPointer(arg0, retain: true, release: true), arg1, arg2.address == 0 ? null : NSError.castFromPointer(arg2, retain: true, release: true))))); + (ffi.Pointer arg0, bool arg1, ffi.Pointer arg2) => fn( + arg0.address == 0 + ? null + : NSURL.castFromPointer(arg0, retain: true, release: true), + arg1, + arg2.address == 0 ? null : NSError.castFromPointer(arg2, retain: true, release: true)))); static ffi.Pointer? _dartFuncTrampoline; /// Creates a listener block from a Dart function. @@ -14399,23 +14126,23 @@ class ObjCBlock_ffiVoid_NSURL_bool_NSError extends objc.ObjCBlockBase { /// /// Note that unlike the default behavior of NativeCallable.listener, listener /// blocks do not keep the isolate alive. - ObjCBlock_ffiVoid_NSURL_bool_NSError.listener(void Function(NSURL?, bool, NSError?) fn) - : this._(objc.newBlock( - (_dartFuncListenerTrampoline ??= - ffi.NativeCallable, ffi.Pointer, ffi.Bool, ffi.Pointer)>.listener( - _ObjCBlock_ffiVoid_NSURL_bool_NSError_closureTrampoline) - ..keepIsolateAlive = false) + ObjCBlock_ffiVoid_NSURL_bool_NSError.listener( + void Function(NSURL?, bool, NSError?) fn) + : this._(objc.newClosureBlock( + (_dartFuncListenerTrampoline ??= ffi.NativeCallable< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Bool, + ffi.Pointer)>.listener( + _ObjCBlock_ffiVoid_NSURL_bool_NSError_closureTrampoline) + ..keepIsolateAlive = false) .nativeFunction .cast(), - _ObjCBlock_ffiVoid_NSURL_bool_NSError_registerClosure( - (ffi.Pointer arg0, bool arg1, - ffi.Pointer arg2) => - fn( - arg0.address == 0 - ? null - : NSURL.castFromPointer(arg0, retain: true, release: true), - arg1, - arg2.address == 0 ? null : NSError.castFromPointer(arg2, retain: true, release: true))))); + (ffi.Pointer arg0, bool arg1, ffi.Pointer arg2) => fn( + arg0.address == 0 ? null : NSURL.castFromPointer(arg0, retain: true, release: true), + arg1, + arg2.address == 0 ? null : NSError.castFromPointer(arg2, retain: true, release: true)))); static ffi.NativeCallable< ffi.Void Function( ffi.Pointer, @@ -14520,24 +14247,12 @@ void _ObjCBlock_ffiVoid_NSURL_NSError_fnPtrTrampoline( .asFunction< void Function(ffi.Pointer, ffi.Pointer)>()(arg0, arg1); -final _ObjCBlock_ffiVoid_NSURL_NSError_closureRegistry = , ffi.Pointer)>{}; -int _ObjCBlock_ffiVoid_NSURL_NSError_closureRegistryIndex = 0; -ffi.Pointer _ObjCBlock_ffiVoid_NSURL_NSError_registerClosure( - void Function(ffi.Pointer, ffi.Pointer) - fn) { - final id = ++_ObjCBlock_ffiVoid_NSURL_NSError_closureRegistryIndex; - _ObjCBlock_ffiVoid_NSURL_NSError_closureRegistry[id] = fn; - return ffi.Pointer.fromAddress(id); -} - void _ObjCBlock_ffiVoid_NSURL_NSError_closureTrampoline( ffi.Pointer block, ffi.Pointer arg0, ffi.Pointer arg1) => - _ObjCBlock_ffiVoid_NSURL_NSError_closureRegistry[block.ref.target.address]!( - arg0, arg1); + (objc.getBlockClosure(block) as void Function(ffi.Pointer, + ffi.Pointer))(arg0, arg1); class ObjCBlock_ffiVoid_NSURL_NSError extends objc.ObjCBlockBase { ObjCBlock_ffiVoid_NSURL_NSError._(ffi.Pointer pointer, @@ -14564,7 +14279,7 @@ class ObjCBlock_ffiVoid_NSURL_NSError extends objc.ObjCBlockBase { ffi.Void Function(ffi.Pointer arg0, ffi.Pointer arg1)>> ptr) - : this._(objc.newBlock( + : this._(objc.newPointerBlock( _cFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Void Function( ffi.Pointer, @@ -14580,8 +14295,9 @@ class ObjCBlock_ffiVoid_NSURL_NSError extends objc.ObjCBlockBase { /// 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. - ObjCBlock_ffiVoid_NSURL_NSError.fromFunction(void Function(NSURL?, NSError?) fn) - : this._(objc.newBlock( + ObjCBlock_ffiVoid_NSURL_NSError.fromFunction( + void Function(NSURL?, NSError?) fn) + : this._(objc.newClosureBlock( _dartFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Void Function( ffi.Pointer, @@ -14589,9 +14305,11 @@ class ObjCBlock_ffiVoid_NSURL_NSError extends objc.ObjCBlockBase { ffi.Pointer)>( _ObjCBlock_ffiVoid_NSURL_NSError_closureTrampoline) .cast(), - _ObjCBlock_ffiVoid_NSURL_NSError_registerClosure((ffi.Pointer arg0, ffi.Pointer arg1) => fn( - arg0.address == 0 ? null : NSURL.castFromPointer(arg0, retain: true, release: true), - arg1.address == 0 ? null : NSError.castFromPointer(arg1, retain: true, release: true))))); + (ffi.Pointer arg0, ffi.Pointer arg1) => fn( + arg0.address == 0 + ? null + : NSURL.castFromPointer(arg0, retain: true, release: true), + arg1.address == 0 ? null : NSError.castFromPointer(arg1, retain: true, release: true)))); static ffi.Pointer? _dartFuncTrampoline; /// Creates a listener block from a Dart function. @@ -14604,22 +14322,23 @@ class ObjCBlock_ffiVoid_NSURL_NSError extends objc.ObjCBlockBase { /// Note that unlike the default behavior of NativeCallable.listener, listener /// blocks do not keep the isolate alive. ObjCBlock_ffiVoid_NSURL_NSError.listener(void Function(NSURL?, NSError?) fn) - : this._(objc.newBlock( - (_dartFuncListenerTrampoline ??= - ffi.NativeCallable, ffi.Pointer, ffi.Pointer)>.listener( - _ObjCBlock_ffiVoid_NSURL_NSError_closureTrampoline) - ..keepIsolateAlive = false) + : this._(objc.newClosureBlock( + (_dartFuncListenerTrampoline ??= ffi.NativeCallable< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer)>.listener( + _ObjCBlock_ffiVoid_NSURL_NSError_closureTrampoline) + ..keepIsolateAlive = false) .nativeFunction .cast(), - _ObjCBlock_ffiVoid_NSURL_NSError_registerClosure( - (ffi.Pointer arg0, ffi.Pointer arg1) => fn( - arg0.address == 0 - ? null - : NSURL.castFromPointer(arg0, - retain: true, release: true), - arg1.address == 0 - ? null - : NSError.castFromPointer(arg1, retain: true, release: true))))); + (ffi.Pointer arg0, ffi.Pointer arg1) => fn( + arg0.address == 0 + ? null + : NSURL.castFromPointer(arg0, retain: true, release: true), + arg1.address == 0 + ? null + : NSError.castFromPointer(arg1, retain: true, release: true)))); static ffi.NativeCallable< ffi.Void Function( ffi.Pointer, @@ -14716,24 +14435,12 @@ ffi.Pointer .asFunction< ffi.Pointer Function( ffi.Pointer)>()(arg0); -final _ObjCBlock_NSProgress_ffiVoidobjcObjCObjectNSError_closureRegistry = - Function(ffi.Pointer)>{}; -int _ObjCBlock_NSProgress_ffiVoidobjcObjCObjectNSError_closureRegistryIndex = 0; -ffi.Pointer - _ObjCBlock_NSProgress_ffiVoidobjcObjCObjectNSError_registerClosure( - ffi.Pointer Function(ffi.Pointer) fn) { - final id = - ++_ObjCBlock_NSProgress_ffiVoidobjcObjCObjectNSError_closureRegistryIndex; - _ObjCBlock_NSProgress_ffiVoidobjcObjCObjectNSError_closureRegistry[id] = fn; - return ffi.Pointer.fromAddress(id); -} - ffi.Pointer _ObjCBlock_NSProgress_ffiVoidobjcObjCObjectNSError_closureTrampoline( ffi.Pointer block, ffi.Pointer arg0) => - _ObjCBlock_NSProgress_ffiVoidobjcObjCObjectNSError_closureRegistry[ - block.ref.target.address]!(arg0); + (objc.getBlockClosure(block) as ffi.Pointer Function( + ffi.Pointer))(arg0); class ObjCBlock_NSProgress_ffiVoidobjcObjCObjectNSError extends objc.ObjCBlockBase { @@ -14763,7 +14470,7 @@ class ObjCBlock_NSProgress_ffiVoidobjcObjCObjectNSError ffi.Pointer Function( ffi.Pointer arg0)>> ptr) - : this._(objc.newBlock( + : this._(objc.newPointerBlock( _cFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Pointer Function( ffi.Pointer, @@ -14780,18 +14487,17 @@ class ObjCBlock_NSProgress_ffiVoidobjcObjCObjectNSError /// will result in a crash. ObjCBlock_NSProgress_ffiVoidobjcObjCObjectNSError.fromFunction( NSProgress? Function(ObjCBlock_ffiVoid_objcObjCObject_NSError) fn) - : this._(objc.newBlock( + : this._(objc.newClosureBlock( _dartFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>( _ObjCBlock_NSProgress_ffiVoidobjcObjCObjectNSError_closureTrampoline) .cast(), - _ObjCBlock_NSProgress_ffiVoidobjcObjCObjectNSError_registerClosure( - (ffi.Pointer arg0) => - fn(ObjCBlock_ffiVoid_objcObjCObject_NSError.castFromPointer(arg0, retain: true, release: true)) - ?.retainAndReturnPointer() ?? - ffi.nullptr))); + (ffi.Pointer arg0) => + fn(ObjCBlock_ffiVoid_objcObjCObject_NSError.castFromPointer(arg0, retain: true, release: true)) + ?.retainAndReturnPointer() ?? + ffi.nullptr)); static ffi.Pointer? _dartFuncTrampoline; NSProgress? call(ObjCBlock_ffiVoid_objcObjCObject_NSError arg0) => pointer.ref.invoke @@ -14825,24 +14531,12 @@ void _ObjCBlock_ffiVoid_objcObjCObject_NSError_fnPtrTrampoline( .asFunction< void Function(ffi.Pointer, ffi.Pointer)>()(arg0, arg1); -final _ObjCBlock_ffiVoid_objcObjCObject_NSError_closureRegistry = , ffi.Pointer)>{}; -int _ObjCBlock_ffiVoid_objcObjCObject_NSError_closureRegistryIndex = 0; -ffi.Pointer _ObjCBlock_ffiVoid_objcObjCObject_NSError_registerClosure( - void Function(ffi.Pointer, ffi.Pointer) - fn) { - final id = ++_ObjCBlock_ffiVoid_objcObjCObject_NSError_closureRegistryIndex; - _ObjCBlock_ffiVoid_objcObjCObject_NSError_closureRegistry[id] = fn; - return ffi.Pointer.fromAddress(id); -} - void _ObjCBlock_ffiVoid_objcObjCObject_NSError_closureTrampoline( ffi.Pointer block, ffi.Pointer arg0, ffi.Pointer arg1) => - _ObjCBlock_ffiVoid_objcObjCObject_NSError_closureRegistry[ - block.ref.target.address]!(arg0, arg1); + (objc.getBlockClosure(block) as void Function(ffi.Pointer, + ffi.Pointer))(arg0, arg1); class ObjCBlock_ffiVoid_objcObjCObject_NSError extends objc.ObjCBlockBase { ObjCBlock_ffiVoid_objcObjCObject_NSError._( @@ -14873,7 +14567,7 @@ class ObjCBlock_ffiVoid_objcObjCObject_NSError extends objc.ObjCBlockBase { ffi.Void Function(ffi.Pointer arg0, ffi.Pointer arg1)>> ptr) - : this._(objc.newBlock( + : this._(objc.newPointerBlock( _cFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Void Function( ffi.Pointer, @@ -14891,7 +14585,7 @@ class ObjCBlock_ffiVoid_objcObjCObject_NSError extends objc.ObjCBlockBase { /// will result in a crash. ObjCBlock_ffiVoid_objcObjCObject_NSError.fromFunction( void Function(NSObject?, NSError?) fn) - : this._(objc.newBlock( + : this._(objc.newClosureBlock( _dartFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Void Function( ffi.Pointer, @@ -14899,10 +14593,11 @@ class ObjCBlock_ffiVoid_objcObjCObject_NSError extends objc.ObjCBlockBase { ffi.Pointer)>( _ObjCBlock_ffiVoid_objcObjCObject_NSError_closureTrampoline) .cast(), - _ObjCBlock_ffiVoid_objcObjCObject_NSError_registerClosure( - (ffi.Pointer arg0, - ffi.Pointer arg1) => - fn(arg0.address == 0 ? null : NSObject.castFromPointer(arg0, retain: true, release: true), arg1.address == 0 ? null : NSError.castFromPointer(arg1, retain: true, release: true))))); + (ffi.Pointer arg0, ffi.Pointer arg1) => fn( + arg0.address == 0 + ? null + : NSObject.castFromPointer(arg0, retain: true, release: true), + arg1.address == 0 ? null : NSError.castFromPointer(arg1, retain: true, release: true)))); static ffi.Pointer? _dartFuncTrampoline; /// Creates a listener block from a Dart function. @@ -14915,22 +14610,21 @@ class ObjCBlock_ffiVoid_objcObjCObject_NSError extends objc.ObjCBlockBase { /// Note that unlike the default behavior of NativeCallable.listener, listener /// blocks do not keep the isolate alive. ObjCBlock_ffiVoid_objcObjCObject_NSError.listener(void Function(NSObject?, NSError?) fn) - : this._(objc.newBlock( - (_dartFuncListenerTrampoline ??= - ffi.NativeCallable, ffi.Pointer, ffi.Pointer)>.listener( - _ObjCBlock_ffiVoid_objcObjCObject_NSError_closureTrampoline) - ..keepIsolateAlive = false) + : this._(objc.newClosureBlock( + (_dartFuncListenerTrampoline ??= ffi.NativeCallable< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer)>.listener( + _ObjCBlock_ffiVoid_objcObjCObject_NSError_closureTrampoline) + ..keepIsolateAlive = false) .nativeFunction .cast(), - _ObjCBlock_ffiVoid_objcObjCObject_NSError_registerClosure( - (ffi.Pointer arg0, ffi.Pointer arg1) => fn( - arg0.address == 0 - ? null - : NSObject.castFromPointer(arg0, - retain: true, release: true), - arg1.address == 0 - ? null - : NSError.castFromPointer(arg1, retain: true, release: true))))); + (ffi.Pointer arg0, ffi.Pointer arg1) => fn( + arg0.address == 0 + ? null + : NSObject.castFromPointer(arg0, retain: true, release: true), + arg1.address == 0 ? null : NSError.castFromPointer(arg1, retain: true, release: true)))); static ffi.NativeCallable< ffi.Void Function( ffi.Pointer, @@ -15022,31 +14716,16 @@ void ffi.Pointer, ffi.Pointer, ffi.Pointer)>()(arg0, arg1, arg2); -final _ObjCBlock_ffiVoid_ffiVoidobjcObjCObjectNSError_objcObjCObject_NSDictionary_closureRegistry = - , ffi.Pointer, - ffi.Pointer)>{}; -int _ObjCBlock_ffiVoid_ffiVoidobjcObjCObjectNSError_objcObjCObject_NSDictionary_closureRegistryIndex = - 0; -ffi.Pointer - _ObjCBlock_ffiVoid_ffiVoidobjcObjCObjectNSError_objcObjCObject_NSDictionary_registerClosure( - void Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer) - fn) { - final id = - ++_ObjCBlock_ffiVoid_ffiVoidobjcObjCObjectNSError_objcObjCObject_NSDictionary_closureRegistryIndex; - _ObjCBlock_ffiVoid_ffiVoidobjcObjCObjectNSError_objcObjCObject_NSDictionary_closureRegistry[ - id] = fn; - return ffi.Pointer.fromAddress(id); -} - -void _ObjCBlock_ffiVoid_ffiVoidobjcObjCObjectNSError_objcObjCObject_NSDictionary_closureTrampoline( - ffi.Pointer block, - ffi.Pointer arg0, - ffi.Pointer arg1, - ffi.Pointer arg2) => - _ObjCBlock_ffiVoid_ffiVoidobjcObjCObjectNSError_objcObjCObject_NSDictionary_closureRegistry[ - block.ref.target.address]!(arg0, arg1, arg2); +void + _ObjCBlock_ffiVoid_ffiVoidobjcObjCObjectNSError_objcObjCObject_NSDictionary_closureTrampoline( + ffi.Pointer block, + ffi.Pointer arg0, + ffi.Pointer arg1, + ffi.Pointer arg2) => + (objc.getBlockClosure(block) as void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer))(arg0, arg1, arg2); class ObjCBlock_ffiVoid_ffiVoidobjcObjCObjectNSError_objcObjCObject_NSDictionary extends objc.ObjCBlockBase { @@ -15077,7 +14756,7 @@ class ObjCBlock_ffiVoid_ffiVoidobjcObjCObjectNSError_objcObjCObject_NSDictionary ffi.Pointer arg1, ffi.Pointer arg2)>> ptr) - : this._(objc.newBlock( + : this._(objc.newPointerBlock( _cFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Void Function( ffi.Pointer, @@ -15094,20 +14773,20 @@ class ObjCBlock_ffiVoid_ffiVoidobjcObjCObjectNSError_objcObjCObject_NSDictionary /// 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. - ObjCBlock_ffiVoid_ffiVoidobjcObjCObjectNSError_objcObjCObject_NSDictionary.fromFunction( - void Function(ObjCBlock_ffiVoid_objcObjCObject_NSError1, NSObject, NSDictionary) - fn) - : this._(objc.newBlock( - _dartFuncTrampoline ??= ffi.Pointer.fromFunction, ffi.Pointer, ffi.Pointer, ffi.Pointer)>(_ObjCBlock_ffiVoid_ffiVoidobjcObjCObjectNSError_objcObjCObject_NSDictionary_closureTrampoline) + ObjCBlock_ffiVoid_ffiVoidobjcObjCObjectNSError_objcObjCObject_NSDictionary.fromFunction(void Function(ObjCBlock_ffiVoid_objcObjCObject_NSError1, NSObject, NSDictionary) fn) + : this._(objc.newClosureBlock( + _dartFuncTrampoline ??= ffi.Pointer.fromFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer)>( + _ObjCBlock_ffiVoid_ffiVoidobjcObjCObjectNSError_objcObjCObject_NSDictionary_closureTrampoline) .cast(), - _ObjCBlock_ffiVoid_ffiVoidobjcObjCObjectNSError_objcObjCObject_NSDictionary_registerClosure( - (ffi.Pointer arg0, - ffi.Pointer arg1, - ffi.Pointer arg2) => - fn( - ObjCBlock_ffiVoid_objcObjCObject_NSError1.castFromPointer(arg0, retain: true, release: true), - NSObject.castFromPointer(arg1, retain: true, release: true), - NSDictionary.castFromPointer(arg2, retain: true, release: true))))); + (ffi.Pointer arg0, ffi.Pointer arg1, ffi.Pointer arg2) => fn( + ObjCBlock_ffiVoid_objcObjCObject_NSError1.castFromPointer(arg0, retain: true, release: true), + NSObject.castFromPointer(arg1, retain: true, release: true), + NSDictionary.castFromPointer(arg2, retain: true, release: true)))); static ffi.Pointer? _dartFuncTrampoline; /// Creates a listener block from a Dart function. @@ -15120,20 +14799,22 @@ class ObjCBlock_ffiVoid_ffiVoidobjcObjCObjectNSError_objcObjCObject_NSDictionary /// Note that unlike the default behavior of NativeCallable.listener, listener /// blocks do not keep the isolate alive. ObjCBlock_ffiVoid_ffiVoidobjcObjCObjectNSError_objcObjCObject_NSDictionary.listener( - void Function( - ObjCBlock_ffiVoid_objcObjCObject_NSError1, NSObject, NSDictionary) + void Function(ObjCBlock_ffiVoid_objcObjCObject_NSError1, NSObject, NSDictionary) fn) - : this._(objc.newBlock( - (_dartFuncListenerTrampoline ??= ffi.NativeCallable, ffi.Pointer, ffi.Pointer, ffi.Pointer)>.listener( - _ObjCBlock_ffiVoid_ffiVoidobjcObjCObjectNSError_objcObjCObject_NSDictionary_closureTrampoline) - ..keepIsolateAlive = false) + : this._(objc.newClosureBlock( + (_dartFuncListenerTrampoline ??= + ffi.NativeCallable, ffi.Pointer, ffi.Pointer, ffi.Pointer)>.listener( + _ObjCBlock_ffiVoid_ffiVoidobjcObjCObjectNSError_objcObjCObject_NSDictionary_closureTrampoline) + ..keepIsolateAlive = false) .nativeFunction .cast(), - _ObjCBlock_ffiVoid_ffiVoidobjcObjCObjectNSError_objcObjCObject_NSDictionary_registerClosure( - (ffi.Pointer arg0, ffi.Pointer arg1, ffi.Pointer arg2) => fn( + (ffi.Pointer arg0, + ffi.Pointer arg1, + ffi.Pointer arg2) => + fn( ObjCBlock_ffiVoid_objcObjCObject_NSError1.castFromPointer(arg0, retain: true, release: true), NSObject.castFromPointer(arg1, retain: true, release: true), - NSDictionary.castFromPointer(arg2, retain: true, release: true))))); + NSDictionary.castFromPointer(arg2, retain: true, release: true)))); static ffi.NativeCallable< ffi.Void Function( ffi.Pointer, @@ -15172,26 +14853,12 @@ void _ObjCBlock_ffiVoid_objcObjCObject_NSError1_fnPtrTrampoline( .asFunction< void Function(ffi.Pointer, ffi.Pointer)>()(arg0, arg1); -final _ObjCBlock_ffiVoid_objcObjCObject_NSError1_closureRegistry = , ffi.Pointer)>{}; -int _ObjCBlock_ffiVoid_objcObjCObject_NSError1_closureRegistryIndex = 0; -ffi.Pointer - _ObjCBlock_ffiVoid_objcObjCObject_NSError1_registerClosure( - void Function( - ffi.Pointer, ffi.Pointer) - fn) { - final id = ++_ObjCBlock_ffiVoid_objcObjCObject_NSError1_closureRegistryIndex; - _ObjCBlock_ffiVoid_objcObjCObject_NSError1_closureRegistry[id] = fn; - return ffi.Pointer.fromAddress(id); -} - void _ObjCBlock_ffiVoid_objcObjCObject_NSError1_closureTrampoline( ffi.Pointer block, ffi.Pointer arg0, ffi.Pointer arg1) => - _ObjCBlock_ffiVoid_objcObjCObject_NSError1_closureRegistry[ - block.ref.target.address]!(arg0, arg1); + (objc.getBlockClosure(block) as void Function(ffi.Pointer, + ffi.Pointer))(arg0, arg1); class ObjCBlock_ffiVoid_objcObjCObject_NSError1 extends objc.ObjCBlockBase { ObjCBlock_ffiVoid_objcObjCObject_NSError1._( @@ -15220,7 +14887,7 @@ class ObjCBlock_ffiVoid_objcObjCObject_NSError1 extends objc.ObjCBlockBase { ffi.Void Function(ffi.Pointer arg0, ffi.Pointer arg1)>> ptr) - : this._(objc.newBlock( + : this._(objc.newPointerBlock( _cFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Void Function( ffi.Pointer, @@ -15238,7 +14905,7 @@ class ObjCBlock_ffiVoid_objcObjCObject_NSError1 extends objc.ObjCBlockBase { /// will result in a crash. ObjCBlock_ffiVoid_objcObjCObject_NSError1.fromFunction( void Function(NSObject?, NSError) fn) - : this._(objc.newBlock( + : this._(objc.newClosureBlock( _dartFuncTrampoline ??= ffi.Pointer.fromFunction< ffi.Void Function( ffi.Pointer, @@ -15246,10 +14913,11 @@ class ObjCBlock_ffiVoid_objcObjCObject_NSError1 extends objc.ObjCBlockBase { ffi.Pointer)>( _ObjCBlock_ffiVoid_objcObjCObject_NSError1_closureTrampoline) .cast(), - _ObjCBlock_ffiVoid_objcObjCObject_NSError1_registerClosure( - (ffi.Pointer arg0, - ffi.Pointer arg1) => - fn(arg0.address == 0 ? null : NSObject.castFromPointer(arg0, retain: true, release: true), NSError.castFromPointer(arg1, retain: true, release: true))))); + (ffi.Pointer arg0, ffi.Pointer arg1) => fn( + arg0.address == 0 + ? null + : NSObject.castFromPointer(arg0, retain: true, release: true), + NSError.castFromPointer(arg1, retain: true, release: true)))); static ffi.Pointer? _dartFuncTrampoline; /// Creates a listener block from a Dart function. @@ -15261,22 +14929,22 @@ class ObjCBlock_ffiVoid_objcObjCObject_NSError1 extends objc.ObjCBlockBase { /// /// Note that unlike the default behavior of NativeCallable.listener, listener /// blocks do not keep the isolate alive. - ObjCBlock_ffiVoid_objcObjCObject_NSError1.listener( - void Function(NSObject?, NSError) fn) - : this._(objc.newBlock( - (_dartFuncListenerTrampoline ??= - ffi.NativeCallable, ffi.Pointer, ffi.Pointer)>.listener( - _ObjCBlock_ffiVoid_objcObjCObject_NSError1_closureTrampoline) - ..keepIsolateAlive = false) + ObjCBlock_ffiVoid_objcObjCObject_NSError1.listener(void Function(NSObject?, NSError) fn) + : this._(objc.newClosureBlock( + (_dartFuncListenerTrampoline ??= ffi.NativeCallable< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer)>.listener( + _ObjCBlock_ffiVoid_objcObjCObject_NSError1_closureTrampoline) + ..keepIsolateAlive = false) .nativeFunction .cast(), - _ObjCBlock_ffiVoid_objcObjCObject_NSError1_registerClosure( - (ffi.Pointer arg0, ffi.Pointer arg1) => fn( - arg0.address == 0 - ? null - : NSObject.castFromPointer(arg0, - retain: true, release: true), - NSError.castFromPointer(arg1, retain: true, release: true))))); + (ffi.Pointer arg0, ffi.Pointer arg1) => fn( + arg0.address == 0 + ? null + : NSObject.castFromPointer(arg0, retain: true, release: true), + NSError.castFromPointer(arg1, retain: true, release: true)))); static ffi.NativeCallable< ffi.Void Function( ffi.Pointer, diff --git a/pkgs/objective_c/macos/Classes/objective_c.c b/pkgs/objective_c/macos/Classes/objective_c.c index 7e5b54067..83496a45f 100644 --- a/pkgs/objective_c/macos/Classes/objective_c.c +++ b/pkgs/objective_c/macos/Classes/objective_c.c @@ -1,3 +1,8 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + // Relative import to be able to reuse the C sources. // See the comment in ../{projectName}}.podspec for more information. #include "../../src/objective_c.c" +#include "../../src/include/dart_api_dl.c" diff --git a/pkgs/objective_c/src/CMakeLists.txt b/pkgs/objective_c/src/CMakeLists.txt index 5280751ef..5988f69f1 100644 --- a/pkgs/objective_c/src/CMakeLists.txt +++ b/pkgs/objective_c/src/CMakeLists.txt @@ -7,8 +7,11 @@ project(objective_c_library VERSION 0.0.1 LANGUAGES C) add_library(objective_c SHARED "objective_c.c" + "include/dart_api_dl.c" ) +target_link_options(objective_c PRIVATE "-undefined dynamic_lookup") + set_target_properties(objective_c PROPERTIES PUBLIC_HEADER objective_c.h OUTPUT_NAME "objective_c" diff --git a/pkgs/objective_c/src/foundation.h b/pkgs/objective_c/src/foundation.h index d3a32ad3b..05eb71f55 100644 --- a/pkgs/objective_c/src/foundation.h +++ b/pkgs/objective_c/src/foundation.h @@ -2,6 +2,9 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +#ifndef OBJECTIVE_C_SRC_FOUNDATION_H_ +#define OBJECTIVE_C_SRC_FOUNDATION_H_ + #import #import #import @@ -12,3 +15,5 @@ #import #import #import + +#endif // OBJECTIVE_C_SRC_FOUNDATION_H_ diff --git a/pkgs/objective_c/src/include/BUILD.gn b/pkgs/objective_c/src/include/BUILD.gn new file mode 100644 index 000000000..2b10262f8 --- /dev/null +++ b/pkgs/objective_c/src/include/BUILD.gn @@ -0,0 +1,23 @@ +# Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file +# for details. All rights reserved. Use of this source code is governed by a +# BSD-style license that can be found in the LICENSE file. + +import("../../sdk_args.gni") + +# This rule copies header files to include/ +copy("copy_headers") { + visibility = [ "../../sdk:copy_headers" ] + + sources = [ + "dart_api.h", + "dart_api_dl.c", + "dart_api_dl.h", + "dart_native_api.h", + "dart_tools_api.h", + "dart_version.h", + "internal/dart_api_dl_impl.h", + ] + + outputs = + [ "$root_out_dir/$dart_sdk_output/include/{{source_target_relative}}" ] +} diff --git a/pkgs/objective_c/src/include/analyze_snapshot_api.h b/pkgs/objective_c/src/include/analyze_snapshot_api.h new file mode 100644 index 000000000..38b58e0b3 --- /dev/null +++ b/pkgs/objective_c/src/include/analyze_snapshot_api.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file + * for details. All rights reserved. Use of this source code is governed by a + * BSD-style license that can be found in the LICENSE file. + */ + +#ifndef RUNTIME_INCLUDE_ANALYZE_SNAPSHOT_API_H_ +#define RUNTIME_INCLUDE_ANALYZE_SNAPSHOT_API_H_ + +#include +#include + +namespace dart { +namespace snapshot_analyzer { +typedef struct { + const uint8_t* vm_snapshot_data; + const uint8_t* vm_snapshot_instructions; + const uint8_t* vm_isolate_data; + const uint8_t* vm_isolate_instructions; +} Dart_SnapshotAnalyzerInformation; + +void Dart_DumpSnapshotInformationAsJson( + const Dart_SnapshotAnalyzerInformation& info, + char** buffer, + intptr_t* buffer_length); + +} // namespace snapshot_analyzer +} // namespace dart + +#endif // RUNTIME_INCLUDE_ANALYZE_SNAPSHOT_API_H_ diff --git a/pkgs/objective_c/src/include/bin/dart_io_api.h b/pkgs/objective_c/src/include/bin/dart_io_api.h new file mode 100644 index 000000000..e863d8b9f --- /dev/null +++ b/pkgs/objective_c/src/include/bin/dart_io_api.h @@ -0,0 +1,69 @@ +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +#ifndef RUNTIME_INCLUDE_BIN_DART_IO_API_H_ +#define RUNTIME_INCLUDE_BIN_DART_IO_API_H_ + +#include "../dart_tools_api.h" + +namespace dart { +namespace bin { + +// Bootstraps 'dart:io'. +void BootstrapDartIo(); + +// Cleans up 'dart:io'. +void CleanupDartIo(); + +// Lets dart:io know where the system temporary directory is located. +// Currently only wired up on Android. +void SetSystemTempDirectory(const char* system_temp); + +// Tells the system whether to capture Stdout events. +void SetCaptureStdout(bool value); + +// Tells the system whether to capture Stderr events. +void SetCaptureStderr(bool value); + +// Should Stdout events be captured? +bool ShouldCaptureStdout(); + +// Should Stderr events be captured? +bool ShouldCaptureStderr(); + +// Set the executable name used by Platform.executable. +void SetExecutableName(const char* executable_name); + +// Set the arguments used by Platform.executableArguments. +void SetExecutableArguments(int script_index, char** argv); + +// Set dart:io implementation specific fields of Dart_EmbedderInformation. +void GetIOEmbedderInformation(Dart_EmbedderInformation* info); + +// Appropriate to assign to Dart_InitializeParams.file_open/read/write/close. +void* OpenFile(const char* name, bool write); +void ReadFile(uint8_t** data, intptr_t* file_len, void* stream); +void WriteFile(const void* buffer, intptr_t num_bytes, void* stream); +void CloseFile(void* stream); + +// Generates 'length' random bytes into 'buffer'. Returns true on success +// and false on failure. This is appropriate to assign to +// Dart_InitializeParams.entropy_source. +bool GetEntropy(uint8_t* buffer, intptr_t length); + +// Performs a lookup of the I/O Dart_NativeFunction with a specified 'name' and +// 'argument_count'. Returns NULL if no I/O native function with a matching +// name and parameter count is found. +Dart_NativeFunction LookupIONative(Dart_Handle name, + int argument_count, + bool* auto_setup_scope); + +// Returns the symbol for I/O native function 'nf'. Returns NULL if 'nf' is not +// a valid I/O native function. +const uint8_t* LookupIONativeSymbol(Dart_NativeFunction nf); + +} // namespace bin +} // namespace dart + +#endif // RUNTIME_INCLUDE_BIN_DART_IO_API_H_ diff --git a/pkgs/objective_c/src/include/dart_api.h b/pkgs/objective_c/src/include/dart_api.h new file mode 100644 index 000000000..6abe8c35d --- /dev/null +++ b/pkgs/objective_c/src/include/dart_api.h @@ -0,0 +1,4097 @@ +/* + * Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file + * for details. All rights reserved. Use of this source code is governed by a + * BSD-style license that can be found in the LICENSE file. + */ + +#ifndef RUNTIME_INCLUDE_DART_API_H_ +#define RUNTIME_INCLUDE_DART_API_H_ + +/** \mainpage Dart Embedding API Reference + * + * This reference describes the Dart Embedding API, which is used to embed the + * Dart Virtual Machine within C/C++ applications. + * + * This reference is generated from the header include/dart_api.h. + */ + +/* __STDC_FORMAT_MACROS has to be defined before including to + * enable platform independent printf format specifiers. */ +#ifndef __STDC_FORMAT_MACROS +#define __STDC_FORMAT_MACROS +#endif + +#include +#include +#include + +#if defined(__Fuchsia__) +#include +#endif + +#ifdef __cplusplus +#define DART_EXTERN_C extern "C" +#else +#define DART_EXTERN_C extern +#endif + +#if defined(__CYGWIN__) +#error Tool chain and platform not supported. +#elif defined(_WIN32) +#if defined(DART_SHARED_LIB) +#define DART_EXPORT DART_EXTERN_C __declspec(dllexport) +#else +#define DART_EXPORT DART_EXTERN_C +#endif +#else +#if __GNUC__ >= 4 +#if defined(DART_SHARED_LIB) +#define DART_EXPORT \ + DART_EXTERN_C __attribute__((visibility("default"))) __attribute((used)) +#else +#define DART_EXPORT DART_EXTERN_C +#endif +#else +#error Tool chain not supported. +#endif +#endif + +#if __GNUC__ +#define DART_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) +#define DART_DEPRECATED(msg) __attribute__((deprecated(msg))) +#elif _MSC_VER +#define DART_WARN_UNUSED_RESULT _Check_return_ +#define DART_DEPRECATED(msg) __declspec(deprecated(msg)) +#else +#define DART_WARN_UNUSED_RESULT +#define DART_DEPRECATED(msg) +#endif + +/* + * ======= + * Handles + * ======= + */ + +/** + * An isolate is the unit of concurrency in Dart. Each isolate has + * its own memory and thread of control. No state is shared between + * isolates. Instead, isolates communicate by message passing. + * + * Each thread keeps track of its current isolate, which is the + * isolate which is ready to execute on the current thread. The + * current isolate may be NULL, in which case no isolate is ready to + * execute. Most of the Dart apis require there to be a current + * isolate in order to function without error. The current isolate is + * set by any call to Dart_CreateIsolateGroup or Dart_EnterIsolate. + */ +typedef struct _Dart_Isolate* Dart_Isolate; +typedef struct _Dart_IsolateGroup* Dart_IsolateGroup; + +/** + * An object reference managed by the Dart VM garbage collector. + * + * Because the garbage collector may move objects, it is unsafe to + * refer to objects directly. Instead, we refer to objects through + * handles, which are known to the garbage collector and updated + * automatically when the object is moved. Handles should be passed + * by value (except in cases like out-parameters) and should never be + * allocated on the heap. + * + * Most functions in the Dart Embedding API return a handle. When a + * function completes normally, this will be a valid handle to an + * object in the Dart VM heap. This handle may represent the result of + * the operation or it may be a special valid handle used merely to + * indicate successful completion. Note that a valid handle may in + * some cases refer to the null object. + * + * --- Error handles --- + * + * When a function encounters a problem that prevents it from + * completing normally, it returns an error handle (See Dart_IsError). + * An error handle has an associated error message that gives more + * details about the problem (See Dart_GetError). + * + * There are four kinds of error handles that can be produced, + * depending on what goes wrong: + * + * - Api error handles are produced when an api function is misused. + * This happens when a Dart embedding api function is called with + * invalid arguments or in an invalid context. + * + * - Unhandled exception error handles are produced when, during the + * execution of Dart code, an exception is thrown but not caught. + * Prototypically this would occur during a call to Dart_Invoke, but + * it can occur in any function which triggers the execution of Dart + * code (for example, Dart_ToString). + * + * An unhandled exception error provides access to an exception and + * stacktrace via the functions Dart_ErrorGetException and + * Dart_ErrorGetStackTrace. + * + * - Compilation error handles are produced when, during the execution + * of Dart code, a compile-time error occurs. As above, this can + * occur in any function which triggers the execution of Dart code. + * + * - Fatal error handles are produced when the system wants to shut + * down the current isolate. + * + * --- Propagating errors --- + * + * When an error handle is returned from the top level invocation of + * Dart code in a program, the embedder must handle the error as they + * see fit. Often, the embedder will print the error message produced + * by Dart_Error and exit the program. + * + * When an error is returned while in the body of a native function, + * it can be propagated up the call stack by calling + * Dart_PropagateError, Dart_SetReturnValue, or Dart_ThrowException. + * Errors should be propagated unless there is a specific reason not + * to. If an error is not propagated then it is ignored. For + * example, if an unhandled exception error is ignored, that + * effectively "catches" the unhandled exception. Fatal errors must + * always be propagated. + * + * When an error is propagated, any current scopes created by + * Dart_EnterScope will be exited. + * + * Using Dart_SetReturnValue to propagate an exception is somewhat + * more convenient than using Dart_PropagateError, and should be + * preferred for reasons discussed below. + * + * Dart_PropagateError and Dart_ThrowException do not return. Instead + * they transfer control non-locally using a setjmp-like mechanism. + * This can be inconvenient if you have resources that you need to + * clean up before propagating the error. + * + * When relying on Dart_PropagateError, we often return error handles + * rather than propagating them from helper functions. Consider the + * following contrived example: + * + * 1 Dart_Handle isLongStringHelper(Dart_Handle arg) { + * 2 intptr_t* length = 0; + * 3 result = Dart_StringLength(arg, &length); + * 4 if (Dart_IsError(result)) { + * 5 return result; + * 6 } + * 7 return Dart_NewBoolean(length > 100); + * 8 } + * 9 + * 10 void NativeFunction_isLongString(Dart_NativeArguments args) { + * 11 Dart_EnterScope(); + * 12 AllocateMyResource(); + * 13 Dart_Handle arg = Dart_GetNativeArgument(args, 0); + * 14 Dart_Handle result = isLongStringHelper(arg); + * 15 if (Dart_IsError(result)) { + * 16 FreeMyResource(); + * 17 Dart_PropagateError(result); + * 18 abort(); // will not reach here + * 19 } + * 20 Dart_SetReturnValue(result); + * 21 FreeMyResource(); + * 22 Dart_ExitScope(); + * 23 } + * + * In this example, we have a native function which calls a helper + * function to do its work. On line 5, the helper function could call + * Dart_PropagateError, but that would not give the native function a + * chance to call FreeMyResource(), causing a leak. Instead, the + * helper function returns the error handle to the caller, giving the + * caller a chance to clean up before propagating the error handle. + * + * When an error is propagated by calling Dart_SetReturnValue, the + * native function will be allowed to complete normally and then the + * exception will be propagated only once the native call + * returns. This can be convenient, as it allows the C code to clean + * up normally. + * + * The example can be written more simply using Dart_SetReturnValue to + * propagate the error. + * + * 1 Dart_Handle isLongStringHelper(Dart_Handle arg) { + * 2 intptr_t* length = 0; + * 3 result = Dart_StringLength(arg, &length); + * 4 if (Dart_IsError(result)) { + * 5 return result + * 6 } + * 7 return Dart_NewBoolean(length > 100); + * 8 } + * 9 + * 10 void NativeFunction_isLongString(Dart_NativeArguments args) { + * 11 Dart_EnterScope(); + * 12 AllocateMyResource(); + * 13 Dart_Handle arg = Dart_GetNativeArgument(args, 0); + * 14 Dart_SetReturnValue(isLongStringHelper(arg)); + * 15 FreeMyResource(); + * 16 Dart_ExitScope(); + * 17 } + * + * In this example, the call to Dart_SetReturnValue on line 14 will + * either return the normal return value or the error (potentially + * generated on line 3). The call to FreeMyResource on line 15 will + * execute in either case. + * + * --- Local and persistent handles --- + * + * Local handles are allocated within the current scope (see + * Dart_EnterScope) and go away when the current scope exits. Unless + * otherwise indicated, callers should assume that all functions in + * the Dart embedding api return local handles. + * + * Persistent handles are allocated within the current isolate. They + * can be used to store objects across scopes. Persistent handles have + * the lifetime of the current isolate unless they are explicitly + * deallocated (see Dart_DeletePersistentHandle). + * The type Dart_Handle represents a handle (both local and persistent). + * The type Dart_PersistentHandle is a Dart_Handle and it is used to + * document that a persistent handle is expected as a parameter to a call + * or the return value from a call is a persistent handle. + * + * FinalizableHandles are persistent handles which are auto deleted when + * the object is garbage collected. It is never safe to use these handles + * unless you know the object is still reachable. + * + * WeakPersistentHandles are persistent handles which are automatically set + * to point Dart_Null when the object is garbage collected. They are not auto + * deleted, so it is safe to use them after the object has become unreachable. + */ +typedef struct _Dart_Handle* Dart_Handle; +typedef Dart_Handle Dart_PersistentHandle; +typedef struct _Dart_WeakPersistentHandle* Dart_WeakPersistentHandle; +typedef struct _Dart_FinalizableHandle* Dart_FinalizableHandle; +// These structs are versioned by DART_API_DL_MAJOR_VERSION, bump the +// version when changing this struct. + +typedef void (*Dart_HandleFinalizer)(void* isolate_callback_data, void* peer); + +/** + * Is this an error handle? + * + * Requires there to be a current isolate. + */ +DART_EXPORT bool Dart_IsError(Dart_Handle handle); + +/** + * Is this an api error handle? + * + * Api error handles are produced when an api function is misused. + * This happens when a Dart embedding api function is called with + * invalid arguments or in an invalid context. + * + * Requires there to be a current isolate. + */ +DART_EXPORT bool Dart_IsApiError(Dart_Handle handle); + +/** + * Is this an unhandled exception error handle? + * + * Unhandled exception error handles are produced when, during the + * execution of Dart code, an exception is thrown but not caught. + * This can occur in any function which triggers the execution of Dart + * code. + * + * See Dart_ErrorGetException and Dart_ErrorGetStackTrace. + * + * Requires there to be a current isolate. + */ +DART_EXPORT bool Dart_IsUnhandledExceptionError(Dart_Handle handle); + +/** + * Is this a compilation error handle? + * + * Compilation error handles are produced when, during the execution + * of Dart code, a compile-time error occurs. This can occur in any + * function which triggers the execution of Dart code. + * + * Requires there to be a current isolate. + */ +DART_EXPORT bool Dart_IsCompilationError(Dart_Handle handle); + +/** + * Is this a fatal error handle? + * + * Fatal error handles are produced when the system wants to shut down + * the current isolate. + * + * Requires there to be a current isolate. + */ +DART_EXPORT bool Dart_IsFatalError(Dart_Handle handle); + +/** + * Gets the error message from an error handle. + * + * Requires there to be a current isolate. + * + * \return A C string containing an error message if the handle is + * error. An empty C string ("") if the handle is valid. This C + * String is scope allocated and is only valid until the next call + * to Dart_ExitScope. +*/ +DART_EXPORT const char* Dart_GetError(Dart_Handle handle); + +/** + * Is this an error handle for an unhandled exception? + */ +DART_EXPORT bool Dart_ErrorHasException(Dart_Handle handle); + +/** + * Gets the exception Object from an unhandled exception error handle. + */ +DART_EXPORT Dart_Handle Dart_ErrorGetException(Dart_Handle handle); + +/** + * Gets the stack trace Object from an unhandled exception error handle. + */ +DART_EXPORT Dart_Handle Dart_ErrorGetStackTrace(Dart_Handle handle); + +/** + * Produces an api error handle with the provided error message. + * + * Requires there to be a current isolate. + * + * \param error the error message. + */ +DART_EXPORT Dart_Handle Dart_NewApiError(const char* error); +DART_EXPORT Dart_Handle Dart_NewCompilationError(const char* error); + +/** + * Produces a new unhandled exception error handle. + * + * Requires there to be a current isolate. + * + * \param exception An instance of a Dart object to be thrown or + * an ApiError or CompilationError handle. + * When an ApiError or CompilationError handle is passed in + * a string object of the error message is created and it becomes + * the Dart object to be thrown. + */ +DART_EXPORT Dart_Handle Dart_NewUnhandledExceptionError(Dart_Handle exception); + +/** + * Propagates an error. + * + * If the provided handle is an unhandled exception error, this + * function will cause the unhandled exception to be rethrown. This + * will proceed in the standard way, walking up Dart frames until an + * appropriate 'catch' block is found, executing 'finally' blocks, + * etc. + * + * If the error is not an unhandled exception error, we will unwind + * the stack to the next C frame. Intervening Dart frames will be + * discarded; specifically, 'finally' blocks will not execute. This + * is the standard way that compilation errors (and the like) are + * handled by the Dart runtime. + * + * In either case, when an error is propagated any current scopes + * created by Dart_EnterScope will be exited. + * + * See the additional discussion under "Propagating Errors" at the + * beginning of this file. + * + * \param handle An error handle (See Dart_IsError) + * + * On success, this function does not return. On failure, the + * process is terminated. + */ +DART_EXPORT void Dart_PropagateError(Dart_Handle handle); + +/** + * Converts an object to a string. + * + * May generate an unhandled exception error. + * + * \return The converted string if no error occurs during + * the conversion. If an error does occur, an error handle is + * returned. + */ +DART_EXPORT Dart_Handle Dart_ToString(Dart_Handle object); + +/** + * Checks to see if two handles refer to identically equal objects. + * + * If both handles refer to instances, this is equivalent to using the top-level + * function identical() from dart:core. Otherwise, returns whether the two + * argument handles refer to the same object. + * + * \param obj1 An object to be compared. + * \param obj2 An object to be compared. + * + * \return True if the objects are identically equal. False otherwise. + */ +DART_EXPORT bool Dart_IdentityEquals(Dart_Handle obj1, Dart_Handle obj2); + +/** + * Allocates a handle in the current scope from a persistent handle. + */ +DART_EXPORT Dart_Handle Dart_HandleFromPersistent(Dart_PersistentHandle object); + +/** + * Allocates a handle in the current scope from a weak persistent handle. + * + * This will be a handle to Dart_Null if the object has been garbage collected. + */ +DART_EXPORT Dart_Handle +Dart_HandleFromWeakPersistent(Dart_WeakPersistentHandle object); + +/** + * Allocates a persistent handle for an object. + * + * This handle has the lifetime of the current isolate unless it is + * explicitly deallocated by calling Dart_DeletePersistentHandle. + * + * Requires there to be a current isolate. + */ +DART_EXPORT Dart_PersistentHandle Dart_NewPersistentHandle(Dart_Handle object); + +/** + * Assign value of local handle to a persistent handle. + * + * Requires there to be a current isolate. + * + * \param obj1 A persistent handle whose value needs to be set. + * \param obj2 An object whose value needs to be set to the persistent handle. + */ +DART_EXPORT void Dart_SetPersistentHandle(Dart_PersistentHandle obj1, + Dart_Handle obj2); + +/** + * Deallocates a persistent handle. + * + * Requires there to be a current isolate group. + */ +DART_EXPORT void Dart_DeletePersistentHandle(Dart_PersistentHandle object); + +/** + * Allocates a weak persistent handle for an object. + * + * This handle has the lifetime of the current isolate. The handle can also be + * explicitly deallocated by calling Dart_DeleteWeakPersistentHandle. + * + * If the object becomes unreachable the callback is invoked with the peer as + * argument. The callback can be executed on any thread, will have a current + * isolate group, but will not have a current isolate. The callback can only + * call Dart_DeletePersistentHandle or Dart_DeleteWeakPersistentHandle. This + * gives the embedder the ability to cleanup data associated with the object. + * The handle will point to the Dart_Null object after the finalizer has been + * run. It is illegal to call into the VM with any other Dart_* functions from + * the callback. If the handle is deleted before the object becomes + * unreachable, the callback is never invoked. + * + * Requires there to be a current isolate. + * + * \param object An object with identity. + * \param peer A pointer to a native object or NULL. This value is + * provided to callback when it is invoked. + * \param external_allocation_size The number of externally allocated + * bytes for peer. Used to inform the garbage collector. + * \param callback A function pointer that will be invoked sometime + * after the object is garbage collected, unless the handle has been deleted. + * A valid callback needs to be specified it cannot be NULL. + * + * \return The weak persistent handle or NULL. NULL is returned in case of bad + * parameters. + */ +DART_EXPORT Dart_WeakPersistentHandle +Dart_NewWeakPersistentHandle(Dart_Handle object, + void* peer, + intptr_t external_allocation_size, + Dart_HandleFinalizer callback); + +/** + * Deletes the given weak persistent [object] handle. + * + * Requires there to be a current isolate group. + */ +DART_EXPORT void Dart_DeleteWeakPersistentHandle( + Dart_WeakPersistentHandle object); + +/** + * Allocates a finalizable handle for an object. + * + * This handle has the lifetime of the current isolate group unless the object + * pointed to by the handle is garbage collected, in this case the VM + * automatically deletes the handle after invoking the callback associated + * with the handle. The handle can also be explicitly deallocated by + * calling Dart_DeleteFinalizableHandle. + * + * If the object becomes unreachable the callback is invoked with the + * the peer as argument. The callback can be executed on any thread, will have + * an isolate group, but will not have a current isolate. The callback can only + * call Dart_DeletePersistentHandle or Dart_DeleteWeakPersistentHandle. + * This gives the embedder the ability to cleanup data associated with the + * object and clear out any cached references to the handle. All references to + * this handle after the callback will be invalid. It is illegal to call into + * the VM with any other Dart_* functions from the callback. If the handle is + * deleted before the object becomes unreachable, the callback is never + * invoked. + * + * Requires there to be a current isolate. + * + * \param object An object with identity. + * \param peer A pointer to a native object or NULL. This value is + * provided to callback when it is invoked. + * \param external_allocation_size The number of externally allocated + * bytes for peer. Used to inform the garbage collector. + * \param callback A function pointer that will be invoked sometime + * after the object is garbage collected, unless the handle has been deleted. + * A valid callback needs to be specified it cannot be NULL. + * + * \return The finalizable handle or NULL. NULL is returned in case of bad + * parameters. + */ +DART_EXPORT Dart_FinalizableHandle +Dart_NewFinalizableHandle(Dart_Handle object, + void* peer, + intptr_t external_allocation_size, + Dart_HandleFinalizer callback); + +/** + * Deletes the given finalizable [object] handle. + * + * The caller has to provide the actual Dart object the handle was created from + * to prove the object (and therefore the finalizable handle) is still alive. + * + * Requires there to be a current isolate. + */ +DART_EXPORT void Dart_DeleteFinalizableHandle(Dart_FinalizableHandle object, + Dart_Handle strong_ref_to_object); + +/* + * ========================== + * Initialization and Globals + * ========================== + */ + +/** + * Gets the version string for the Dart VM. + * + * The version of the Dart VM can be accessed without initializing the VM. + * + * \return The version string for the embedded Dart VM. + */ +DART_EXPORT const char* Dart_VersionString(void); + +/** + * Isolate specific flags are set when creating a new isolate using the + * Dart_IsolateFlags structure. + * + * Current version of flags is encoded in a 32-bit integer with 16 bits used + * for each part. + */ + +#define DART_FLAGS_CURRENT_VERSION (0x0000000d) + +typedef struct { + int32_t version; + bool enable_asserts; + bool use_field_guards; + bool use_osr; + bool obfuscate; + bool load_vmservice_library; + bool null_safety; + bool is_system_isolate; + bool is_service_isolate; + bool is_kernel_isolate; + bool snapshot_is_dontneed_safe; + bool branch_coverage; +} Dart_IsolateFlags; + +/** + * Initialize Dart_IsolateFlags with correct version and default values. + */ +DART_EXPORT void Dart_IsolateFlagsInitialize(Dart_IsolateFlags* flags); + +/** + * An isolate creation and initialization callback function. + * + * This callback, provided by the embedder, is called when the VM + * needs to create an isolate. The callback should create an isolate + * by calling Dart_CreateIsolateGroup and load any scripts required for + * execution. + * + * This callback may be called on a different thread than the one + * running the parent isolate. + * + * When the function returns NULL, it is the responsibility of this + * function to ensure that Dart_ShutdownIsolate has been called if + * required (for example, if the isolate was created successfully by + * Dart_CreateIsolateGroup() but the root library fails to load + * successfully, then the function should call Dart_ShutdownIsolate + * before returning). + * + * When the function returns NULL, the function should set *error to + * a malloc-allocated buffer containing a useful error message. The + * caller of this function (the VM) will make sure that the buffer is + * freed. + * + * \param script_uri The uri of the main source file or snapshot to load. + * Either the URI of the parent isolate set in Dart_CreateIsolateGroup for + * Isolate.spawn, or the argument to Isolate.spawnUri canonicalized by the + * library tag handler of the parent isolate. + * The callback is responsible for loading the program by a call to + * Dart_LoadScriptFromKernel. + * \param main The name of the main entry point this isolate will + * eventually run. This is provided for advisory purposes only to + * improve debugging messages. The main function is not invoked by + * this function. + * \param package_root Ignored. + * \param package_config Uri of the package configuration file (either in format + * of .packages or .dart_tool/package_config.json) for this isolate + * to resolve package imports against. If this parameter is not passed the + * package resolution of the parent isolate should be used. + * \param flags Default flags for this isolate being spawned. Either inherited + * from the spawning isolate or passed as parameters when spawning the + * isolate from Dart code. + * \param isolate_data The isolate data which was passed to the + * parent isolate when it was created by calling Dart_CreateIsolateGroup(). + * \param error A structure into which the embedder can place a + * C string containing an error message in the case of failures. + * + * \return The embedder returns NULL if the creation and + * initialization was not successful and the isolate if successful. + */ +typedef Dart_Isolate (*Dart_IsolateGroupCreateCallback)( + const char* script_uri, + const char* main, + const char* package_root, + const char* package_config, + Dart_IsolateFlags* flags, + void* isolate_data, + char** error); + +/** + * An isolate initialization callback function. + * + * This callback, provided by the embedder, is called when the VM has created an + * isolate within an existing isolate group (i.e. from the same source as an + * existing isolate). + * + * The callback should setup native resolvers and might want to set a custom + * message handler via [Dart_SetMessageNotifyCallback] and mark the isolate as + * runnable. + * + * This callback may be called on a different thread than the one + * running the parent isolate. + * + * When the function returns `false`, it is the responsibility of this + * function to ensure that `Dart_ShutdownIsolate` has been called. + * + * When the function returns `false`, the function should set *error to + * a malloc-allocated buffer containing a useful error message. The + * caller of this function (the VM) will make sure that the buffer is + * freed. + * + * \param child_isolate_data The callback data to associate with the new + * child isolate. + * \param error A structure into which the embedder can place a + * C string containing an error message in the case the initialization fails. + * + * \return The embedder returns true if the initialization was successful and + * false otherwise (in which case the VM will terminate the isolate). + */ +typedef bool (*Dart_InitializeIsolateCallback)(void** child_isolate_data, + char** error); + +/** + * An isolate shutdown callback function. + * + * This callback, provided by the embedder, is called before the vm + * shuts down an isolate. The isolate being shutdown will be the current + * isolate. It is safe to run Dart code. + * + * This function should be used to dispose of native resources that + * are allocated to an isolate in order to avoid leaks. + * + * \param isolate_group_data The same callback data which was passed to the + * isolate group when it was created. + * \param isolate_data The same callback data which was passed to the isolate + * when it was created. + */ +typedef void (*Dart_IsolateShutdownCallback)(void* isolate_group_data, + void* isolate_data); + +/** + * An isolate cleanup callback function. + * + * This callback, provided by the embedder, is called after the vm + * shuts down an isolate. There will be no current isolate and it is *not* + * safe to run Dart code. + * + * This function should be used to dispose of native resources that + * are allocated to an isolate in order to avoid leaks. + * + * \param isolate_group_data The same callback data which was passed to the + * isolate group when it was created. + * \param isolate_data The same callback data which was passed to the isolate + * when it was created. + */ +typedef void (*Dart_IsolateCleanupCallback)(void* isolate_group_data, + void* isolate_data); + +/** + * An isolate group cleanup callback function. + * + * This callback, provided by the embedder, is called after the vm + * shuts down an isolate group. + * + * This function should be used to dispose of native resources that + * are allocated to an isolate in order to avoid leaks. + * + * \param isolate_group_data The same callback data which was passed to the + * isolate group when it was created. + * + */ +typedef void (*Dart_IsolateGroupCleanupCallback)(void* isolate_group_data); + +/** + * A thread start callback function. + * This callback, provided by the embedder, is called after a thread in the + * vm thread pool starts. + * This function could be used to adjust thread priority or attach native + * resources to the thread. + */ +typedef void (*Dart_ThreadStartCallback)(void); + +/** + * A thread death callback function. + * This callback, provided by the embedder, is called before a thread in the + * vm thread pool exits. + * This function could be used to dispose of native resources that + * are associated and attached to the thread, in order to avoid leaks. + */ +typedef void (*Dart_ThreadExitCallback)(void); + +/** + * Opens a file for reading or writing. + * + * Callback provided by the embedder for file operations. If the + * embedder does not allow file operations this callback can be + * NULL. + * + * \param name The name of the file to open. + * \param write A boolean variable which indicates if the file is to + * opened for writing. If there is an existing file it needs to truncated. + */ +typedef void* (*Dart_FileOpenCallback)(const char* name, bool write); + +/** + * Read contents of file. + * + * Callback provided by the embedder for file operations. If the + * embedder does not allow file operations this callback can be + * NULL. + * + * \param data Buffer allocated in the callback into which the contents + * of the file are read into. It is the responsibility of the caller to + * free this buffer. + * \param file_length A variable into which the length of the file is returned. + * In the case of an error this value would be -1. + * \param stream Handle to the opened file. + */ +typedef void (*Dart_FileReadCallback)(uint8_t** data, + intptr_t* file_length, + void* stream); + +/** + * Write data into file. + * + * Callback provided by the embedder for file operations. If the + * embedder does not allow file operations this callback can be + * NULL. + * + * \param data Buffer which needs to be written into the file. + * \param length Length of the buffer. + * \param stream Handle to the opened file. + */ +typedef void (*Dart_FileWriteCallback)(const void* data, + intptr_t length, + void* stream); + +/** + * Closes the opened file. + * + * Callback provided by the embedder for file operations. If the + * embedder does not allow file operations this callback can be + * NULL. + * + * \param stream Handle to the opened file. + */ +typedef void (*Dart_FileCloseCallback)(void* stream); + +typedef bool (*Dart_EntropySource)(uint8_t* buffer, intptr_t length); + +/** + * Callback provided by the embedder that is used by the vmservice isolate + * to request the asset archive. The asset archive must be an uncompressed tar + * archive that is stored in a Uint8List. + * + * If the embedder has no vmservice isolate assets, the callback can be NULL. + * + * \return The embedder must return a handle to a Uint8List containing an + * uncompressed tar archive or null. + */ +typedef Dart_Handle (*Dart_GetVMServiceAssetsArchive)(void); + +/** + * The current version of the Dart_InitializeFlags. Should be incremented every + * time Dart_InitializeFlags changes in a binary incompatible way. + */ +#define DART_INITIALIZE_PARAMS_CURRENT_VERSION (0x00000008) + +/** Forward declaration */ +struct Dart_CodeObserver; + +/** + * Callback provided by the embedder that is used by the VM to notify on code + * object creation, *before* it is invoked the first time. + * This is useful for embedders wanting to e.g. keep track of PCs beyond + * the lifetime of the garbage collected code objects. + * Note that an address range may be used by more than one code object over the + * lifecycle of a process. Clients of this function should record timestamps for + * these compilation events and when collecting PCs to disambiguate reused + * address ranges. + */ +typedef void (*Dart_OnNewCodeCallback)(struct Dart_CodeObserver* observer, + const char* name, + uintptr_t base, + uintptr_t size); + +typedef struct Dart_CodeObserver { + void* data; + + Dart_OnNewCodeCallback on_new_code; +} Dart_CodeObserver; + +/** + * Optional callback provided by the embedder that is used by the VM to + * implement registration of kernel blobs for the subsequent Isolate.spawnUri + * If no callback is provided, the registration of kernel blobs will throw + * an error. + * + * \param kernel_buffer A buffer which contains a kernel program. Callback + * should copy the contents of `kernel_buffer` as + * it may be freed immediately after registration. + * \param kernel_buffer_size The size of `kernel_buffer`. + * + * \return A C string representing URI which can be later used + * to spawn a new isolate. This C String should be scope allocated + * or owned by the embedder. + * Returns NULL if embedder runs out of memory. + */ +typedef const char* (*Dart_RegisterKernelBlobCallback)( + const uint8_t* kernel_buffer, + intptr_t kernel_buffer_size); + +/** + * Optional callback provided by the embedder that is used by the VM to + * unregister kernel blobs. + * If no callback is provided, the unregistration of kernel blobs will throw + * an error. + * + * \param kernel_blob_uri URI of the kernel blob to unregister. + */ +typedef void (*Dart_UnregisterKernelBlobCallback)(const char* kernel_blob_uri); + +/** + * Describes how to initialize the VM. Used with Dart_Initialize. + */ +typedef struct { + /** + * Identifies the version of the struct used by the client. + * should be initialized to DART_INITIALIZE_PARAMS_CURRENT_VERSION. + */ + int32_t version; + + /** + * A buffer containing snapshot data, or NULL if no snapshot is provided. + * + * If provided, the buffer must remain valid until Dart_Cleanup returns. + */ + const uint8_t* vm_snapshot_data; + + /** + * A buffer containing a snapshot of precompiled instructions, or NULL if + * no snapshot is provided. + * + * If provided, the buffer must remain valid until Dart_Cleanup returns. + */ + const uint8_t* vm_snapshot_instructions; + + /** + * A function to be called during isolate group creation. + * See Dart_IsolateGroupCreateCallback. + */ + Dart_IsolateGroupCreateCallback create_group; + + /** + * A function to be called during isolate + * initialization inside an existing isolate group. + * See Dart_InitializeIsolateCallback. + */ + Dart_InitializeIsolateCallback initialize_isolate; + + /** + * A function to be called right before an isolate is shutdown. + * See Dart_IsolateShutdownCallback. + */ + Dart_IsolateShutdownCallback shutdown_isolate; + + /** + * A function to be called after an isolate was shutdown. + * See Dart_IsolateCleanupCallback. + */ + Dart_IsolateCleanupCallback cleanup_isolate; + + /** + * A function to be called after an isolate group is + * shutdown. See Dart_IsolateGroupCleanupCallback. + */ + Dart_IsolateGroupCleanupCallback cleanup_group; + + Dart_ThreadStartCallback thread_start; + Dart_ThreadExitCallback thread_exit; + Dart_FileOpenCallback file_open; + Dart_FileReadCallback file_read; + Dart_FileWriteCallback file_write; + Dart_FileCloseCallback file_close; + Dart_EntropySource entropy_source; + + /** + * A function to be called by the service isolate when it requires the + * vmservice assets archive. See Dart_GetVMServiceAssetsArchive. + */ + Dart_GetVMServiceAssetsArchive get_service_assets; + + bool start_kernel_isolate; + + /** + * An external code observer callback function. The observer can be invoked + * as early as during the Dart_Initialize() call. + */ + Dart_CodeObserver* code_observer; + + /** + * Kernel blob registration callback function. See Dart_RegisterKernelBlobCallback. + */ + Dart_RegisterKernelBlobCallback register_kernel_blob; + + /** + * Kernel blob unregistration callback function. See Dart_UnregisterKernelBlobCallback. + */ + Dart_UnregisterKernelBlobCallback unregister_kernel_blob; + +#if defined(__Fuchsia__) + /** + * The resource needed to use zx_vmo_replace_as_executable. Can be + * ZX_HANDLE_INVALID if the process has ambient-replace-as-executable or if + * executable memory is not needed (e.g., this is an AOT runtime). + */ + zx_handle_t vmex_resource; +#endif +} Dart_InitializeParams; + +/** + * Initializes the VM. + * + * \param params A struct containing initialization information. The version + * field of the struct must be DART_INITIALIZE_PARAMS_CURRENT_VERSION. + * + * \return NULL if initialization is successful. Returns an error message + * otherwise. The caller is responsible for freeing the error message. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT char* Dart_Initialize( + Dart_InitializeParams* params); + +/** + * Cleanup state in the VM before process termination. + * + * \return NULL if cleanup is successful. Returns an error message otherwise. + * The caller is responsible for freeing the error message. + * + * NOTE: This function must not be called on a thread that was created by the VM + * itself. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT char* Dart_Cleanup(void); + +/** + * Sets command line flags. Should be called before Dart_Initialize. + * + * \param argc The length of the arguments array. + * \param argv An array of arguments. + * + * \return NULL if successful. Returns an error message otherwise. + * The caller is responsible for freeing the error message. + * + * NOTE: This call does not store references to the passed in c-strings. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT char* Dart_SetVMFlags(int argc, + const char** argv); + +/** + * Returns true if the named VM flag is of boolean type, specified, and set to + * true. + * + * \param flag_name The name of the flag without leading punctuation + * (example: "enable_asserts"). + */ +DART_EXPORT bool Dart_IsVMFlagSet(const char* flag_name); + +/* + * ======== + * Isolates + * ======== + */ + +/** + * Creates a new isolate. The new isolate becomes the current isolate. + * + * A snapshot can be used to restore the VM quickly to a saved state + * and is useful for fast startup. If snapshot data is provided, the + * isolate will be started using that snapshot data. Requires a core snapshot or + * an app snapshot created by Dart_CreateSnapshot or + * Dart_CreatePrecompiledSnapshot* from a VM with the same version. + * + * Requires there to be no current isolate. + * + * \param script_uri The main source file or snapshot this isolate will load. + * The VM will provide this URI to the Dart_IsolateGroupCreateCallback when a + * child isolate is created by Isolate.spawn. The embedder should use a URI + * that allows it to load the same program into such a child isolate. + * \param name A short name for the isolate to improve debugging messages. + * Typically of the format 'foo.dart:main()'. + * \param isolate_snapshot_data Buffer containing the snapshot data of the + * isolate or NULL if no snapshot is provided. If provided, the buffer must + * remain valid until the isolate shuts down. + * \param isolate_snapshot_instructions Buffer containing the snapshot + * instructions of the isolate or NULL if no snapshot is provided. If + * provided, the buffer must remain valid until the isolate shuts down. + * \param flags Pointer to VM specific flags or NULL for default flags. + * \param isolate_group_data Embedder group data. This data can be obtained + * by calling Dart_IsolateGroupData and will be passed to the + * Dart_IsolateShutdownCallback, Dart_IsolateCleanupCallback, and + * Dart_IsolateGroupCleanupCallback. + * \param isolate_data Embedder data. This data will be passed to + * the Dart_IsolateGroupCreateCallback when new isolates are spawned from + * this parent isolate. + * \param error Returns NULL if creation is successful, an error message + * otherwise. The caller is responsible for calling free() on the error + * message. + * + * \return The new isolate on success, or NULL if isolate creation failed. + */ +DART_EXPORT Dart_Isolate +Dart_CreateIsolateGroup(const char* script_uri, + const char* name, + const uint8_t* isolate_snapshot_data, + const uint8_t* isolate_snapshot_instructions, + Dart_IsolateFlags* flags, + void* isolate_group_data, + void* isolate_data, + char** error); +/** + * Creates a new isolate inside the isolate group of [group_member]. + * + * Requires there to be no current isolate. + * + * \param group_member An isolate from the same group into which the newly created + * isolate should be born into. Other threads may not have entered / enter this + * member isolate. + * \param name A short name for the isolate for debugging purposes. + * \param shutdown_callback A callback to be called when the isolate is being + * shutdown (may be NULL). + * \param cleanup_callback A callback to be called when the isolate is being + * cleaned up (may be NULL). + * \param child_isolate_data The embedder-specific data associated with this isolate. + * \param error Set to NULL if creation is successful, set to an error + * message otherwise. The caller is responsible for calling free() on the + * error message. + * + * \return The newly created isolate on success, or NULL if isolate creation + * failed. + * + * If successful, the newly created isolate will become the current isolate. + */ +DART_EXPORT Dart_Isolate +Dart_CreateIsolateInGroup(Dart_Isolate group_member, + const char* name, + Dart_IsolateShutdownCallback shutdown_callback, + Dart_IsolateCleanupCallback cleanup_callback, + void* child_isolate_data, + char** error); + +/* TODO(turnidge): Document behavior when there is already a current + * isolate. */ + +/** + * Creates a new isolate from a Dart Kernel file. The new isolate + * becomes the current isolate. + * + * Requires there to be no current isolate. + * + * \param script_uri The main source file or snapshot this isolate will load. + * The VM will provide this URI to the Dart_IsolateGroupCreateCallback when a + * child isolate is created by Isolate.spawn. The embedder should use a URI that + * allows it to load the same program into such a child isolate. + * \param name A short name for the isolate to improve debugging messages. + * Typically of the format 'foo.dart:main()'. + * \param kernel_buffer A buffer which contains a kernel/DIL program. Must + * remain valid until isolate shutdown. + * \param kernel_buffer_size The size of `kernel_buffer`. + * \param flags Pointer to VM specific flags or NULL for default flags. + * \param isolate_group_data Embedder group data. This data can be obtained + * by calling Dart_IsolateGroupData and will be passed to the + * Dart_IsolateShutdownCallback, Dart_IsolateCleanupCallback, and + * Dart_IsolateGroupCleanupCallback. + * \param isolate_data Embedder data. This data will be passed to + * the Dart_IsolateGroupCreateCallback when new isolates are spawned from + * this parent isolate. + * \param error Returns NULL if creation is successful, an error message + * otherwise. The caller is responsible for calling free() on the error + * message. + * + * \return The new isolate on success, or NULL if isolate creation failed. + */ +DART_EXPORT Dart_Isolate +Dart_CreateIsolateGroupFromKernel(const char* script_uri, + const char* name, + const uint8_t* kernel_buffer, + intptr_t kernel_buffer_size, + Dart_IsolateFlags* flags, + void* isolate_group_data, + void* isolate_data, + char** error); +/** + * Shuts down the current isolate. After this call, the current isolate is NULL. + * Any current scopes created by Dart_EnterScope will be exited. Invokes the + * shutdown callback and any callbacks of remaining weak persistent handles. + * + * Requires there to be a current isolate. + */ +DART_EXPORT void Dart_ShutdownIsolate(void); +/* TODO(turnidge): Document behavior when there is no current isolate. */ + +/** + * Returns the current isolate. Will return NULL if there is no + * current isolate. + */ +DART_EXPORT Dart_Isolate Dart_CurrentIsolate(void); + +/** + * Returns the callback data associated with the current isolate. This + * data was set when the isolate got created or initialized. + */ +DART_EXPORT void* Dart_CurrentIsolateData(void); + +/** + * Returns the callback data associated with the given isolate. This + * data was set when the isolate got created or initialized. + */ +DART_EXPORT void* Dart_IsolateData(Dart_Isolate isolate); + +/** + * Returns the current isolate group. Will return NULL if there is no + * current isolate group. + */ +DART_EXPORT Dart_IsolateGroup Dart_CurrentIsolateGroup(void); + +/** + * Returns the callback data associated with the current isolate group. This + * data was passed to the isolate group when it was created. + */ +DART_EXPORT void* Dart_CurrentIsolateGroupData(void); + +/** + * Gets an id that uniquely identifies current isolate group. + * + * It is the responsibility of the caller to free the returned ID. + */ +typedef int64_t Dart_IsolateGroupId; +DART_EXPORT Dart_IsolateGroupId Dart_CurrentIsolateGroupId(void); + +/** + * Returns the callback data associated with the specified isolate group. This + * data was passed to the isolate when it was created. + * The embedder is responsible for ensuring the consistency of this data + * with respect to the lifecycle of an isolate group. + */ +DART_EXPORT void* Dart_IsolateGroupData(Dart_Isolate isolate); + +/** + * Returns the debugging name for the current isolate. + * + * This name is unique to each isolate and should only be used to make + * debugging messages more comprehensible. + */ +DART_EXPORT Dart_Handle Dart_DebugName(void); + +/** + * Returns the debugging name for the current isolate. + * + * This name is unique to each isolate and should only be used to make + * debugging messages more comprehensible. + * + * The returned string is scope allocated and is only valid until the next call + * to Dart_ExitScope. + */ +DART_EXPORT const char* Dart_DebugNameToCString(void); + +/** + * Returns the ID for an isolate which is used to query the service protocol. + * + * It is the responsibility of the caller to free the returned ID. + */ +DART_EXPORT const char* Dart_IsolateServiceId(Dart_Isolate isolate); + +/** + * Enters an isolate. After calling this function, + * the current isolate will be set to the provided isolate. + * + * Requires there to be no current isolate. Multiple threads may not be in + * the same isolate at once. + */ +DART_EXPORT void Dart_EnterIsolate(Dart_Isolate isolate); + +/** + * Kills the given isolate. + * + * This function has the same effect as dart:isolate's + * Isolate.kill(priority:immediate). + * It can interrupt ordinary Dart code but not native code. If the isolate is + * in the middle of a long running native function, the isolate will not be + * killed until control returns to Dart. + * + * Does not require a current isolate. It is safe to kill the current isolate if + * there is one. + */ +DART_EXPORT void Dart_KillIsolate(Dart_Isolate isolate); + +/** + * Notifies the VM that the embedder expects to be idle until |deadline|. The VM + * may use this time to perform garbage collection or other tasks to avoid + * delays during execution of Dart code in the future. + * + * |deadline| is measured in microseconds against the system's monotonic time. + * This clock can be accessed via Dart_TimelineGetMicros(). + * + * Requires there to be a current isolate. + */ +DART_EXPORT void Dart_NotifyIdle(int64_t deadline); + +typedef void (*Dart_HeapSamplingReportCallback)(void* context, void* data); + +typedef void* (*Dart_HeapSamplingCreateCallback)( + Dart_Isolate isolate, + Dart_IsolateGroup isolate_group, + const char* cls_name, + intptr_t allocation_size); +typedef void (*Dart_HeapSamplingDeleteCallback)(void* data); + +/** + * Starts the heap sampling profiler for each thread in the VM. + */ +DART_EXPORT void Dart_EnableHeapSampling(void); + +/* + * Stops the heap sampling profiler for each thread in the VM. + */ +DART_EXPORT void Dart_DisableHeapSampling(void); + +/* Registers callbacks are invoked once per sampled allocation upon object + * allocation and garbage collection. + * + * |create_callback| can be used to associate additional data with the sampled + * allocation, such as a stack trace. This data pointer will be passed to + * |delete_callback| to allow for proper disposal when the object associated + * with the allocation sample is collected. + * + * The provided callbacks must not call into the VM and should do as little + * work as possible to avoid performance penalities during object allocation and + * garbage collection. + * + * NOTE: It is a fatal error to set either callback to null once they have been + * initialized. + */ +DART_EXPORT void Dart_RegisterHeapSamplingCallback( + Dart_HeapSamplingCreateCallback create_callback, + Dart_HeapSamplingDeleteCallback delete_callback); + +/* + * Reports the surviving allocation samples for all live isolate groups in the + * VM. + * + * When the callback is invoked: + * - |context| will be the context object provided when invoking + * |Dart_ReportSurvivingAllocations|. This can be safely set to null if not + * required. + * - |heap_size| will be equal to the size of the allocated object associated + * with the sample. + * - |cls_name| will be a C String representing + * the class name of the allocated object. This string is valid for the + * duration of the call to Dart_ReportSurvivingAllocations and can be + * freed by the VM at any point after the method returns. + * - |data| will be set to the data associated with the sample by + * |Dart_HeapSamplingCreateCallback|. + * + * If |force_gc| is true, a full GC will be performed before reporting the + * allocations. + */ +DART_EXPORT void Dart_ReportSurvivingAllocations( + Dart_HeapSamplingReportCallback callback, + void* context, + bool force_gc); + +/* + * Sets the average heap sampling rate based on a number of |bytes| for each + * thread. + * + * In other words, approximately every |bytes| allocated will create a sample. + * Defaults to 512 KiB. + */ +DART_EXPORT void Dart_SetHeapSamplingPeriod(intptr_t bytes); + +/** + * Notifies the VM that the embedder expects the application's working set has + * recently shrunk significantly and is not expected to rise in the near future. + * The VM may spend O(heap-size) time performing clean up work. + * + * Requires there to be a current isolate. + */ +DART_EXPORT void Dart_NotifyDestroyed(void); + +/** + * Notifies the VM that the system is running low on memory. + * + * Does not require a current isolate. Only valid after calling Dart_Initialize. + */ +DART_EXPORT void Dart_NotifyLowMemory(void); + +typedef enum { + /** + * Balanced + */ + Dart_PerformanceMode_Default, + /** + * Optimize for low latency, at the expense of throughput and memory overhead + * by performing work in smaller batches (requiring more overhead) or by + * delaying work (requiring more memory). An embedder should not remain in + * this mode indefinitely. + */ + Dart_PerformanceMode_Latency, + /** + * Optimize for high throughput, at the expense of latency and memory overhead + * by performing work in larger batches with more intervening growth. + */ + Dart_PerformanceMode_Throughput, + /** + * Optimize for low memory, at the expensive of throughput and latency by more + * frequently performing work. + */ + Dart_PerformanceMode_Memory, +} Dart_PerformanceMode; + +/** + * Set the desired performance trade-off. + * + * Requires a current isolate. + * + * Returns the previous performance mode. + */ +DART_EXPORT Dart_PerformanceMode +Dart_SetPerformanceMode(Dart_PerformanceMode mode); + +/** + * Starts the CPU sampling profiler. + */ +DART_EXPORT void Dart_StartProfiling(void); + +/** + * Stops the CPU sampling profiler. + * + * Note that some profile samples might still be taken after this function + * returns due to the asynchronous nature of the implementation on some + * platforms. + */ +DART_EXPORT void Dart_StopProfiling(void); + +/** + * Notifies the VM that the current thread should not be profiled until a + * matching call to Dart_ThreadEnableProfiling is made. + * + * NOTE: By default, if a thread has entered an isolate it will be profiled. + * This function should be used when an embedder knows a thread is about + * to make a blocking call and wants to avoid unnecessary interrupts by + * the profiler. + */ +DART_EXPORT void Dart_ThreadDisableProfiling(void); + +/** + * Notifies the VM that the current thread should be profiled. + * + * NOTE: It is only legal to call this function *after* calling + * Dart_ThreadDisableProfiling. + * + * NOTE: By default, if a thread has entered an isolate it will be profiled. + */ +DART_EXPORT void Dart_ThreadEnableProfiling(void); + +/** + * Register symbol information for the Dart VM's profiler and crash dumps. + * + * This consumes the output of //topaz/runtime/dart/profiler_symbols, which + * should be treated as opaque. + */ +DART_EXPORT void Dart_AddSymbols(const char* dso_name, + void* buffer, + intptr_t buffer_size); + +/** + * Exits an isolate. After this call, Dart_CurrentIsolate will + * return NULL. + * + * Requires there to be a current isolate. + */ +DART_EXPORT void Dart_ExitIsolate(void); +/* TODO(turnidge): We don't want users of the api to be able to exit a + * "pure" dart isolate. Implement and document. */ + +/** + * Creates a full snapshot of the current isolate heap. + * + * A full snapshot is a compact representation of the dart vm isolate heap + * and dart isolate heap states. These snapshots are used to initialize + * the vm isolate on startup and fast initialization of an isolate. + * A Snapshot of the heap is created before any dart code has executed. + * + * Requires there to be a current isolate. Not available in the precompiled + * runtime (check Dart_IsPrecompiledRuntime). + * + * \param vm_snapshot_data_buffer Returns a pointer to a buffer containing the + * vm snapshot. This buffer is scope allocated and is only valid + * until the next call to Dart_ExitScope. + * \param vm_snapshot_data_size Returns the size of vm_snapshot_data_buffer. + * \param isolate_snapshot_data_buffer Returns a pointer to a buffer containing + * the isolate snapshot. This buffer is scope allocated and is only valid + * until the next call to Dart_ExitScope. + * \param isolate_snapshot_data_size Returns the size of + * isolate_snapshot_data_buffer. + * \param is_core Create a snapshot containing core libraries. + * Such snapshot should be agnostic to null safety mode. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_CreateSnapshot(uint8_t** vm_snapshot_data_buffer, + intptr_t* vm_snapshot_data_size, + uint8_t** isolate_snapshot_data_buffer, + intptr_t* isolate_snapshot_data_size, + bool is_core); + +/** + * Returns whether the buffer contains a kernel file. + * + * \param buffer Pointer to a buffer that might contain a kernel binary. + * \param buffer_size Size of the buffer. + * + * \return Whether the buffer contains a kernel binary (full or partial). + */ +DART_EXPORT bool Dart_IsKernel(const uint8_t* buffer, intptr_t buffer_size); + +/** + * Make isolate runnable. + * + * When isolates are spawned, this function is used to indicate that + * the creation and initialization (including script loading) of the + * isolate is complete and the isolate can start. + * This function expects there to be no current isolate. + * + * \param isolate The isolate to be made runnable. + * + * \return NULL if successful. Returns an error message otherwise. The caller + * is responsible for freeing the error message. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT char* Dart_IsolateMakeRunnable( + Dart_Isolate isolate); + +/* + * ================== + * Messages and Ports + * ================== + */ + +/** + * A port is used to send or receive inter-isolate messages + */ +typedef int64_t Dart_Port; + +/** + * ILLEGAL_PORT is a port number guaranteed never to be associated with a valid + * port. + */ +#define ILLEGAL_PORT ((Dart_Port)0) + +/** + * A message notification callback. + * + * This callback allows the embedder to provide a custom wakeup mechanism for + * the delivery of inter-isolate messages. This function is called once per + * message on an arbitrary thread. It is the responsibility of the embedder to + * eventually call Dart_HandleMessage once per callback received with the + * destination isolate set as the current isolate to process the message. + */ +typedef void (*Dart_MessageNotifyCallback)(Dart_Isolate destination_isolate); + +/** + * Allows embedders to provide a custom wakeup mechanism for the delivery of + * inter-isolate messages. This setting only applies to the current isolate. + * + * This mechanism is optional: if not provided, the isolate will be scheduled on + * a VM-managed thread pool. An embedder should provide this callback if it + * wants to run an isolate on a specific thread or to interleave handling of + * inter-isolate messages with other event sources. + * + * Most embedders will only call this function once, before isolate + * execution begins. If this function is called after isolate + * execution begins, the embedder is responsible for threading issues. + */ +DART_EXPORT void Dart_SetMessageNotifyCallback( + Dart_MessageNotifyCallback message_notify_callback); +/* TODO(turnidge): Consider moving this to isolate creation so that it + * is impossible to mess up. */ + +/** + * Query the current message notify callback for the isolate. + * + * \return The current message notify callback for the isolate. + */ +DART_EXPORT Dart_MessageNotifyCallback Dart_GetMessageNotifyCallback(void); + +/** + * The VM's default message handler supports pausing an isolate before it + * processes the first message and right after the it processes the isolate's + * final message. This can be controlled for all isolates by two VM flags: + * + * `--pause-isolates-on-start` + * `--pause-isolates-on-exit` + * + * Additionally, Dart_SetShouldPauseOnStart and Dart_SetShouldPauseOnExit can be + * used to control this behaviour on a per-isolate basis. + * + * When an embedder is using a Dart_MessageNotifyCallback the embedder + * needs to cooperate with the VM so that the service protocol can report + * accurate information about isolates and so that tools such as debuggers + * work reliably. + * + * The following functions can be used to implement pausing on start and exit. + */ + +/** + * If the VM flag `--pause-isolates-on-start` was passed this will be true. + * + * \return A boolean value indicating if pause on start was requested. + */ +DART_EXPORT bool Dart_ShouldPauseOnStart(void); + +/** + * Override the VM flag `--pause-isolates-on-start` for the current isolate. + * + * \param should_pause Should the isolate be paused on start? + * + * NOTE: This must be called before Dart_IsolateMakeRunnable. + */ +DART_EXPORT void Dart_SetShouldPauseOnStart(bool should_pause); + +/** + * Is the current isolate paused on start? + * + * \return A boolean value indicating if the isolate is paused on start. + */ +DART_EXPORT bool Dart_IsPausedOnStart(void); + +/** + * Called when the embedder has paused the current isolate on start and when + * the embedder has resumed the isolate. + * + * \param paused Is the isolate paused on start? + */ +DART_EXPORT void Dart_SetPausedOnStart(bool paused); + +/** + * If the VM flag `--pause-isolates-on-exit` was passed this will be true. + * + * \return A boolean value indicating if pause on exit was requested. + */ +DART_EXPORT bool Dart_ShouldPauseOnExit(void); + +/** + * Override the VM flag `--pause-isolates-on-exit` for the current isolate. + * + * \param should_pause Should the isolate be paused on exit? + * + */ +DART_EXPORT void Dart_SetShouldPauseOnExit(bool should_pause); + +/** + * Is the current isolate paused on exit? + * + * \return A boolean value indicating if the isolate is paused on exit. + */ +DART_EXPORT bool Dart_IsPausedOnExit(void); + +/** + * Called when the embedder has paused the current isolate on exit and when + * the embedder has resumed the isolate. + * + * \param paused Is the isolate paused on exit? + */ +DART_EXPORT void Dart_SetPausedOnExit(bool paused); + +/** + * Called when the embedder has caught a top level unhandled exception error + * in the current isolate. + * + * NOTE: It is illegal to call this twice on the same isolate without first + * clearing the sticky error to null. + * + * \param error The unhandled exception error. + */ +DART_EXPORT void Dart_SetStickyError(Dart_Handle error); + +/** + * Does the current isolate have a sticky error? + */ +DART_EXPORT bool Dart_HasStickyError(void); + +/** + * Gets the sticky error for the current isolate. + * + * \return A handle to the sticky error object or null. + */ +DART_EXPORT Dart_Handle Dart_GetStickyError(void); + +/** + * Handles the next pending message for the current isolate. + * + * May generate an unhandled exception error. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_HandleMessage(void); + +/** + * Handles any pending messages for the vm service for the current + * isolate. + * + * This function may be used by an embedder at a breakpoint to avoid + * pausing the vm service. + * + * This function can indirectly cause the message notify callback to + * be called. + * + * \return true if the vm service requests the program resume + * execution, false otherwise + */ +DART_EXPORT bool Dart_HandleServiceMessages(void); + +/** + * Does the current isolate have pending service messages? + * + * \return true if the isolate has pending service messages, false otherwise. + */ +DART_EXPORT bool Dart_HasServiceMessages(void); + +/** + * Processes any incoming messages for the current isolate. + * + * This function may only be used when the embedder has not provided + * an alternate message delivery mechanism with + * Dart_SetMessageCallbacks. It is provided for convenience. + * + * This function waits for incoming messages for the current + * isolate. As new messages arrive, they are handled using + * Dart_HandleMessage. The routine exits when all ports to the + * current isolate are closed. + * + * \return A valid handle if the run loop exited successfully. If an + * exception or other error occurs while processing messages, an + * error handle is returned. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_RunLoop(void); + +/** + * Lets the VM run message processing for the isolate. + * + * This function expects there to a current isolate and the current isolate + * must not have an active api scope. The VM will take care of making the + * isolate runnable (if not already), handles its message loop and will take + * care of shutting the isolate down once it's done. + * + * \param errors_are_fatal Whether uncaught errors should be fatal. + * \param on_error_port A port to notify on uncaught errors (or ILLEGAL_PORT). + * \param on_exit_port A port to notify on exit (or ILLEGAL_PORT). + * \param error A non-NULL pointer which will hold an error message if the call + * fails. The error has to be free()ed by the caller. + * + * \return If successful the VM takes ownership of the isolate and takes care + * of its message loop. If not successful the caller retains ownership of the + * isolate. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT bool Dart_RunLoopAsync( + bool errors_are_fatal, + Dart_Port on_error_port, + Dart_Port on_exit_port, + char** error); + +/* TODO(turnidge): Should this be removed from the public api? */ + +/** + * Gets the main port id for the current isolate. + */ +DART_EXPORT Dart_Port Dart_GetMainPortId(void); + +/** + * Does the current isolate have live ReceivePorts? + * + * A ReceivePort is live when it has not been closed. + */ +DART_EXPORT bool Dart_HasLivePorts(void); + +/** + * Posts a message for some isolate. The message is a serialized + * object. + * + * Requires there to be a current isolate. + * + * For posting messages outside of an isolate see \ref Dart_PostCObject. + * + * \param port_id The destination port. + * \param object An object from the current isolate. + * + * \return True if the message was posted. + */ +DART_EXPORT bool Dart_Post(Dart_Port port_id, Dart_Handle object); + +/** + * Returns a new SendPort with the provided port id. + * + * \param port_id The destination port. + * + * \return A new SendPort if no errors occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle Dart_NewSendPort(Dart_Port port_id); + +/** + * Gets the SendPort id for the provided SendPort. + * \param port A SendPort object whose id is desired. + * \param port_id Returns the id of the SendPort. + * \return Success if no error occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle Dart_SendPortGetId(Dart_Handle port, + Dart_Port* port_id); + +/* + * ====== + * Scopes + * ====== + */ + +/** + * Enters a new scope. + * + * All new local handles will be created in this scope. Additionally, + * some functions may return "scope allocated" memory which is only + * valid within this scope. + * + * Requires there to be a current isolate. + */ +DART_EXPORT void Dart_EnterScope(void); + +/** + * Exits a scope. + * + * The previous scope (if any) becomes the current scope. + * + * Requires there to be a current isolate. + */ +DART_EXPORT void Dart_ExitScope(void); + +/** + * The Dart VM uses "zone allocation" for temporary structures. Zones + * support very fast allocation of small chunks of memory. The chunks + * cannot be deallocated individually, but instead zones support + * deallocating all chunks in one fast operation. + * + * This function makes it possible for the embedder to allocate + * temporary data in the VMs zone allocator. + * + * Zone allocation is possible: + * 1. when inside a scope where local handles can be allocated + * 2. when processing a message from a native port in a native port + * handler + * + * All the memory allocated this way will be reclaimed either on the + * next call to Dart_ExitScope or when the native port handler exits. + * + * \param size Size of the memory to allocate. + * + * \return A pointer to the allocated memory. NULL if allocation + * failed. Failure might due to is no current VM zone. + */ +DART_EXPORT uint8_t* Dart_ScopeAllocate(intptr_t size); + +/* + * ======= + * Objects + * ======= + */ + +/** + * Returns the null object. + * + * \return A handle to the null object. + */ +DART_EXPORT Dart_Handle Dart_Null(void); + +/** + * Is this object null? + */ +DART_EXPORT bool Dart_IsNull(Dart_Handle object); + +/** + * Returns the empty string object. + * + * \return A handle to the empty string object. + */ +DART_EXPORT Dart_Handle Dart_EmptyString(void); + +/** + * Returns types that are not classes, and which therefore cannot be looked up + * as library members by Dart_GetType. + * + * \return A handle to the dynamic, void or Never type. + */ +DART_EXPORT Dart_Handle Dart_TypeDynamic(void); +DART_EXPORT Dart_Handle Dart_TypeVoid(void); +DART_EXPORT Dart_Handle Dart_TypeNever(void); + +/** + * Checks if the two objects are equal. + * + * The result of the comparison is returned through the 'equal' + * parameter. The return value itself is used to indicate success or + * failure, not equality. + * + * May generate an unhandled exception error. + * + * \param obj1 An object to be compared. + * \param obj2 An object to be compared. + * \param equal Returns the result of the equality comparison. + * + * \return A valid handle if no error occurs during the comparison. + */ +DART_EXPORT Dart_Handle Dart_ObjectEquals(Dart_Handle obj1, + Dart_Handle obj2, + bool* equal); + +/** + * Is this object an instance of some type? + * + * The result of the test is returned through the 'instanceof' parameter. + * The return value itself is used to indicate success or failure. + * + * \param object An object. + * \param type A type. + * \param instanceof Return true if 'object' is an instance of type 'type'. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT Dart_Handle Dart_ObjectIsType(Dart_Handle object, + Dart_Handle type, + bool* instanceof); + +/** + * Query object type. + * + * \param object Some Object. + * + * \return true if Object is of the specified type. + */ +DART_EXPORT bool Dart_IsInstance(Dart_Handle object); +DART_EXPORT bool Dart_IsNumber(Dart_Handle object); +DART_EXPORT bool Dart_IsInteger(Dart_Handle object); +DART_EXPORT bool Dart_IsDouble(Dart_Handle object); +DART_EXPORT bool Dart_IsBoolean(Dart_Handle object); +DART_EXPORT bool Dart_IsString(Dart_Handle object); +DART_EXPORT bool Dart_IsStringLatin1(Dart_Handle object); /* (ISO-8859-1) */ +DART_EXPORT bool Dart_IsList(Dart_Handle object); +DART_EXPORT bool Dart_IsMap(Dart_Handle object); +DART_EXPORT bool Dart_IsLibrary(Dart_Handle object); +DART_EXPORT bool Dart_IsType(Dart_Handle handle); +DART_EXPORT bool Dart_IsFunction(Dart_Handle handle); +DART_EXPORT bool Dart_IsVariable(Dart_Handle handle); +DART_EXPORT bool Dart_IsTypeVariable(Dart_Handle handle); +DART_EXPORT bool Dart_IsClosure(Dart_Handle object); +DART_EXPORT bool Dart_IsTypedData(Dart_Handle object); +DART_EXPORT bool Dart_IsByteBuffer(Dart_Handle object); +DART_EXPORT bool Dart_IsFuture(Dart_Handle object); + +/* + * ========= + * Instances + * ========= + */ + +/* + * For the purposes of the embedding api, not all objects returned are + * Dart language objects. Within the api, we use the term 'Instance' + * to indicate handles which refer to true Dart language objects. + * + * TODO(turnidge): Reorganize the "Object" section above, pulling down + * any functions that more properly belong here. */ + +/** + * Gets the type of a Dart language object. + * + * \param instance Some Dart object. + * + * \return If no error occurs, the type is returned. Otherwise an + * error handle is returned. + */ +DART_EXPORT Dart_Handle Dart_InstanceGetType(Dart_Handle instance); + +/** + * Returns the name for the provided class type. + * + * \return A valid string handle if no error occurs during the + * operation. + */ +DART_EXPORT Dart_Handle Dart_ClassName(Dart_Handle cls_type); + +/** + * Returns the name for the provided function or method. + * + * \return A valid string handle if no error occurs during the + * operation. + */ +DART_EXPORT Dart_Handle Dart_FunctionName(Dart_Handle function); + +/** + * Returns a handle to the owner of a function. + * + * The owner of an instance method or a static method is its defining + * class. The owner of a top-level function is its defining + * library. The owner of the function of a non-implicit closure is the + * function of the method or closure that defines the non-implicit + * closure. + * + * \return A valid handle to the owner of the function, or an error + * handle if the argument is not a valid handle to a function. + */ +DART_EXPORT Dart_Handle Dart_FunctionOwner(Dart_Handle function); + +/** + * Determines whether a function handle refers to a static function + * of method. + * + * For the purposes of the embedding API, a top-level function is + * implicitly declared static. + * + * \param function A handle to a function or method declaration. + * \param is_static Returns whether the function or method is declared static. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT Dart_Handle Dart_FunctionIsStatic(Dart_Handle function, + bool* is_static); + +/** + * Is this object a closure resulting from a tear-off (closurized method)? + * + * Returns true for closures produced when an ordinary method is accessed + * through a getter call. Returns false otherwise, in particular for closures + * produced from local function declarations. + * + * \param object Some Object. + * + * \return true if Object is a tear-off. + */ +DART_EXPORT bool Dart_IsTearOff(Dart_Handle object); + +/** + * Retrieves the function of a closure. + * + * \return A handle to the function of the closure, or an error handle if the + * argument is not a closure. + */ +DART_EXPORT Dart_Handle Dart_ClosureFunction(Dart_Handle closure); + +/** + * Returns a handle to the library which contains class. + * + * \return A valid handle to the library with owns class, null if the class + * has no library or an error handle if the argument is not a valid handle + * to a class type. + */ +DART_EXPORT Dart_Handle Dart_ClassLibrary(Dart_Handle cls_type); + +/* + * ============================= + * Numbers, Integers and Doubles + * ============================= + */ + +/** + * Does this Integer fit into a 64-bit signed integer? + * + * \param integer An integer. + * \param fits Returns true if the integer fits into a 64-bit signed integer. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT Dart_Handle Dart_IntegerFitsIntoInt64(Dart_Handle integer, + bool* fits); + +/** + * Does this Integer fit into a 64-bit unsigned integer? + * + * \param integer An integer. + * \param fits Returns true if the integer fits into a 64-bit unsigned integer. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT Dart_Handle Dart_IntegerFitsIntoUint64(Dart_Handle integer, + bool* fits); + +/** + * Returns an Integer with the provided value. + * + * \param value The value of the integer. + * + * \return The Integer object if no error occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle Dart_NewInteger(int64_t value); + +/** + * Returns an Integer with the provided value. + * + * \param value The unsigned value of the integer. + * + * \return The Integer object if no error occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle Dart_NewIntegerFromUint64(uint64_t value); + +/** + * Returns an Integer with the provided value. + * + * \param value The value of the integer represented as a C string + * containing a hexadecimal number. + * + * \return The Integer object if no error occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle Dart_NewIntegerFromHexCString(const char* value); + +/** + * Gets the value of an Integer. + * + * The integer must fit into a 64-bit signed integer, otherwise an error occurs. + * + * \param integer An Integer. + * \param value Returns the value of the Integer. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT Dart_Handle Dart_IntegerToInt64(Dart_Handle integer, + int64_t* value); + +/** + * Gets the value of an Integer. + * + * The integer must fit into a 64-bit unsigned integer, otherwise an + * error occurs. + * + * \param integer An Integer. + * \param value Returns the value of the Integer. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT Dart_Handle Dart_IntegerToUint64(Dart_Handle integer, + uint64_t* value); + +/** + * Gets the value of an integer as a hexadecimal C string. + * + * \param integer An Integer. + * \param value Returns the value of the Integer as a hexadecimal C + * string. This C string is scope allocated and is only valid until + * the next call to Dart_ExitScope. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT Dart_Handle Dart_IntegerToHexCString(Dart_Handle integer, + const char** value); + +/** + * Returns a Double with the provided value. + * + * \param value A double. + * + * \return The Double object if no error occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle Dart_NewDouble(double value); + +/** + * Gets the value of a Double + * + * \param double_obj A Double + * \param value Returns the value of the Double. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT Dart_Handle Dart_DoubleValue(Dart_Handle double_obj, double* value); + +/** + * Returns a closure of static function 'function_name' in the class 'class_name' + * in the exported namespace of specified 'library'. + * + * \param library Library object + * \param cls_type Type object representing a Class + * \param function_name Name of the static function in the class + * + * \return A valid Dart instance if no error occurs during the operation. + */ +DART_EXPORT Dart_Handle Dart_GetStaticMethodClosure(Dart_Handle library, + Dart_Handle cls_type, + Dart_Handle function_name); + +/* + * ======== + * Booleans + * ======== + */ + +/** + * Returns the True object. + * + * Requires there to be a current isolate. + * + * \return A handle to the True object. + */ +DART_EXPORT Dart_Handle Dart_True(void); + +/** + * Returns the False object. + * + * Requires there to be a current isolate. + * + * \return A handle to the False object. + */ +DART_EXPORT Dart_Handle Dart_False(void); + +/** + * Returns a Boolean with the provided value. + * + * \param value true or false. + * + * \return The Boolean object if no error occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle Dart_NewBoolean(bool value); + +/** + * Gets the value of a Boolean + * + * \param boolean_obj A Boolean + * \param value Returns the value of the Boolean. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT Dart_Handle Dart_BooleanValue(Dart_Handle boolean_obj, bool* value); + +/* + * ======= + * Strings + * ======= + */ + +/** + * Gets the length of a String. + * + * \param str A String. + * \param length Returns the length of the String. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT Dart_Handle Dart_StringLength(Dart_Handle str, intptr_t* length); + +/** + * Gets the length of UTF-8 encoded representation for a string. + * + * \param str A String. + * \param length Returns the length of UTF-8 encoded representation for string. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT Dart_Handle Dart_StringUTF8Length(Dart_Handle str, + intptr_t* length); + +/** + * Returns a String built from the provided C string + * (There is an implicit assumption that the C string passed in contains + * UTF-8 encoded characters and '\0' is considered as a termination + * character). + * + * \param str A C String + * + * \return The String object if no error occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle Dart_NewStringFromCString(const char* str); +/* TODO(turnidge): Document what happens when we run out of memory + * during this call. */ + +/** + * Returns a String built from an array of UTF-8 encoded characters. + * + * \param utf8_array An array of UTF-8 encoded characters. + * \param length The length of the codepoints array. + * + * \return The String object if no error occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle Dart_NewStringFromUTF8(const uint8_t* utf8_array, + intptr_t length); + +/** + * Returns a String built from an array of UTF-16 encoded characters. + * + * \param utf16_array An array of UTF-16 encoded characters. + * \param length The length of the codepoints array. + * + * \return The String object if no error occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle Dart_NewStringFromUTF16(const uint16_t* utf16_array, + intptr_t length); + +/** + * Returns a String built from an array of UTF-32 encoded characters. + * + * \param utf32_array An array of UTF-32 encoded characters. + * \param length The length of the codepoints array. + * + * \return The String object if no error occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle Dart_NewStringFromUTF32(const int32_t* utf32_array, + intptr_t length); + +/** + * Gets the C string representation of a String. + * (It is a sequence of UTF-8 encoded values with a '\0' termination.) + * + * \param str A string. + * \param cstr Returns the String represented as a C string. + * This C string is scope allocated and is only valid until + * the next call to Dart_ExitScope. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT Dart_Handle Dart_StringToCString(Dart_Handle str, + const char** cstr); + +/** + * Gets a UTF-8 encoded representation of a String. + * + * Any unpaired surrogate code points in the string will be converted as + * replacement characters (U+FFFD, 0xEF 0xBF 0xBD in UTF-8). If you need + * to preserve unpaired surrogates, use the Dart_StringToUTF16 function. + * + * \param str A string. + * \param utf8_array Returns the String represented as UTF-8 code + * units. This UTF-8 array is scope allocated and is only valid + * until the next call to Dart_ExitScope. + * \param length Used to return the length of the array which was + * actually used. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT Dart_Handle Dart_StringToUTF8(Dart_Handle str, + uint8_t** utf8_array, + intptr_t* length); + +/** + * Copies the UTF-8 encoded representation of a String into specified buffer. + * + * Any unpaired surrogate code points in the string will be converted as + * replacement characters (U+FFFD, 0xEF 0xBF 0xBD in UTF-8). + * + * \param str A string. + * \param utf8_array Buffer into which the UTF-8 encoded representation of + * the string is copied into. + * The buffer is allocated and managed by the caller. + * \param length Specifies the length of the buffer passed in. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT Dart_Handle Dart_CopyUTF8EncodingOfString(Dart_Handle str, + uint8_t* utf8_array, + intptr_t length); + +/** + * Gets the data corresponding to the string object. This function returns + * the data only for Latin-1 (ISO-8859-1) string objects. For all other + * string objects it returns an error. + * + * \param str A string. + * \param latin1_array An array allocated by the caller, used to return + * the string data. + * \param length Used to pass in the length of the provided array. + * Used to return the length of the array which was actually used. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT Dart_Handle Dart_StringToLatin1(Dart_Handle str, + uint8_t* latin1_array, + intptr_t* length); + +/** + * Gets the UTF-16 encoded representation of a string. + * + * \param str A string. + * \param utf16_array An array allocated by the caller, used to return + * the array of UTF-16 encoded characters. + * \param length Used to pass in the length of the provided array. + * Used to return the length of the array which was actually used. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT Dart_Handle Dart_StringToUTF16(Dart_Handle str, + uint16_t* utf16_array, + intptr_t* length); + +/** + * Gets the storage size in bytes of a String. + * + * \param str A String. + * \param size Returns the storage size in bytes of the String. + * This is the size in bytes needed to store the String. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT Dart_Handle Dart_StringStorageSize(Dart_Handle str, intptr_t* size); + +/** + * Retrieves some properties associated with a String. + * Properties retrieved are: + * - character size of the string (one or two byte) + * - length of the string + * - peer pointer of string if it is an external string. + * \param str A String. + * \param char_size Returns the character size of the String. + * \param str_len Returns the length of the String. + * \param peer Returns the peer pointer associated with the String or 0 if + * there is no peer pointer for it. + * \return Success if no error occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle Dart_StringGetProperties(Dart_Handle str, + intptr_t* char_size, + intptr_t* str_len, + void** peer); + +/* + * ===== + * Lists + * ===== + */ + +/** + * Returns a List of the desired length. + * + * \param length The length of the list. + * + * \return The List object if no error occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle Dart_NewList(intptr_t length); + +typedef enum { + Dart_CoreType_Dynamic, + Dart_CoreType_Int, + Dart_CoreType_String, +} Dart_CoreType_Id; + +// TODO(bkonyi): convert this to use nullable types once NNBD is enabled. +/** + * Returns a List of the desired length with the desired legacy element type. + * + * \param element_type_id The type of elements of the list. + * \param length The length of the list. + * + * \return The List object if no error occurs. Otherwise returns an error + * handle. + */ +DART_EXPORT Dart_Handle Dart_NewListOf(Dart_CoreType_Id element_type_id, + intptr_t length); + +/** + * Returns a List of the desired length with the desired element type. + * + * \param element_type Handle to a nullable type object. E.g., from + * Dart_GetType or Dart_GetNullableType. + * + * \param length The length of the list. + * + * \return The List object if no error occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle Dart_NewListOfType(Dart_Handle element_type, + intptr_t length); + +/** + * Returns a List of the desired length with the desired element type, filled + * with the provided object. + * + * \param element_type Handle to a type object. E.g., from Dart_GetType. + * + * \param fill_object Handle to an object of type 'element_type' that will be + * used to populate the list. This parameter can only be Dart_Null() if the + * length of the list is 0 or 'element_type' is a nullable type. + * + * \param length The length of the list. + * + * \return The List object if no error occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle Dart_NewListOfTypeFilled(Dart_Handle element_type, + Dart_Handle fill_object, + intptr_t length); + +/** + * Gets the length of a List. + * + * May generate an unhandled exception error. + * + * \param list A List. + * \param length Returns the length of the List. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT Dart_Handle Dart_ListLength(Dart_Handle list, intptr_t* length); + +/** + * Gets the Object at some index of a List. + * + * If the index is out of bounds, an error occurs. + * + * May generate an unhandled exception error. + * + * \param list A List. + * \param index A valid index into the List. + * + * \return The Object in the List at the specified index if no error + * occurs. Otherwise returns an error handle. + */ +DART_EXPORT Dart_Handle Dart_ListGetAt(Dart_Handle list, intptr_t index); + +/** +* Gets a range of Objects from a List. +* +* If any of the requested index values are out of bounds, an error occurs. +* +* May generate an unhandled exception error. +* +* \param list A List. +* \param offset The offset of the first item to get. +* \param length The number of items to get. +* \param result A pointer to fill with the objects. +* +* \return Success if no error occurs during the operation. +*/ +DART_EXPORT Dart_Handle Dart_ListGetRange(Dart_Handle list, + intptr_t offset, + intptr_t length, + Dart_Handle* result); + +/** + * Sets the Object at some index of a List. + * + * If the index is out of bounds, an error occurs. + * + * May generate an unhandled exception error. + * + * \param list A List. + * \param index A valid index into the List. + * \param value The Object to put in the List. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT Dart_Handle Dart_ListSetAt(Dart_Handle list, + intptr_t index, + Dart_Handle value); + +/** + * May generate an unhandled exception error. + */ +DART_EXPORT Dart_Handle Dart_ListGetAsBytes(Dart_Handle list, + intptr_t offset, + uint8_t* native_array, + intptr_t length); + +/** + * May generate an unhandled exception error. + */ +DART_EXPORT Dart_Handle Dart_ListSetAsBytes(Dart_Handle list, + intptr_t offset, + const uint8_t* native_array, + intptr_t length); + +/* + * ==== + * Maps + * ==== + */ + +/** + * Gets the Object at some key of a Map. + * + * May generate an unhandled exception error. + * + * \param map A Map. + * \param key An Object. + * + * \return The value in the map at the specified key, null if the map does not + * contain the key, or an error handle. + */ +DART_EXPORT Dart_Handle Dart_MapGetAt(Dart_Handle map, Dart_Handle key); + +/** + * Returns whether the Map contains a given key. + * + * May generate an unhandled exception error. + * + * \param map A Map. + * + * \return A handle on a boolean indicating whether map contains the key. + * Otherwise returns an error handle. + */ +DART_EXPORT Dart_Handle Dart_MapContainsKey(Dart_Handle map, Dart_Handle key); + +/** + * Gets the list of keys of a Map. + * + * May generate an unhandled exception error. + * + * \param map A Map. + * + * \return The list of key Objects if no error occurs. Otherwise returns an + * error handle. + */ +DART_EXPORT Dart_Handle Dart_MapKeys(Dart_Handle map); + +/* + * ========== + * Typed Data + * ========== + */ + +typedef enum { + Dart_TypedData_kByteData = 0, + Dart_TypedData_kInt8, + Dart_TypedData_kUint8, + Dart_TypedData_kUint8Clamped, + Dart_TypedData_kInt16, + Dart_TypedData_kUint16, + Dart_TypedData_kInt32, + Dart_TypedData_kUint32, + Dart_TypedData_kInt64, + Dart_TypedData_kUint64, + Dart_TypedData_kFloat32, + Dart_TypedData_kFloat64, + Dart_TypedData_kInt32x4, + Dart_TypedData_kFloat32x4, + Dart_TypedData_kFloat64x2, + Dart_TypedData_kInvalid +} Dart_TypedData_Type; + +/** + * Return type if this object is a TypedData object. + * + * \return kInvalid if the object is not a TypedData object or the appropriate + * Dart_TypedData_Type. + */ +DART_EXPORT Dart_TypedData_Type Dart_GetTypeOfTypedData(Dart_Handle object); + +/** + * Return type if this object is an external TypedData object. + * + * \return kInvalid if the object is not an external TypedData object or + * the appropriate Dart_TypedData_Type. + */ +DART_EXPORT Dart_TypedData_Type +Dart_GetTypeOfExternalTypedData(Dart_Handle object); + +/** + * Returns a TypedData object of the desired length and type. + * + * \param type The type of the TypedData object. + * \param length The length of the TypedData object (length in type units). + * + * \return The TypedData object if no error occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle Dart_NewTypedData(Dart_TypedData_Type type, + intptr_t length); + +/** + * Returns a TypedData object which references an external data array. + * + * \param type The type of the data array. + * \param data A data array. This array must not move. + * \param length The length of the data array (length in type units). + * + * \return The TypedData object if no error occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle Dart_NewExternalTypedData(Dart_TypedData_Type type, + void* data, + intptr_t length); + +/** + * Returns a TypedData object which references an external data array. + * + * \param type The type of the data array. + * \param data A data array. This array must not move. + * \param length The length of the data array (length in type units). + * \param peer A pointer to a native object or NULL. This value is + * provided to callback when it is invoked. + * \param external_allocation_size The number of externally allocated + * bytes for peer. Used to inform the garbage collector. + * \param callback A function pointer that will be invoked sometime + * after the object is garbage collected, unless the handle has been deleted. + * A valid callback needs to be specified it cannot be NULL. + * + * \return The TypedData object if no error occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle +Dart_NewExternalTypedDataWithFinalizer(Dart_TypedData_Type type, + void* data, + intptr_t length, + void* peer, + intptr_t external_allocation_size, + Dart_HandleFinalizer callback); +DART_EXPORT Dart_Handle Dart_NewUnmodifiableExternalTypedDataWithFinalizer( + Dart_TypedData_Type type, + const void* data, + intptr_t length, + void* peer, + intptr_t external_allocation_size, + Dart_HandleFinalizer callback); + +/** + * Returns a ByteBuffer object for the typed data. + * + * \param typed_data The TypedData object. + * + * \return The ByteBuffer object if no error occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle Dart_NewByteBuffer(Dart_Handle typed_data); + +/** + * Acquires access to the internal data address of a TypedData object. + * + * \param object The typed data object whose internal data address is to + * be accessed. + * \param type The type of the object is returned here. + * \param data The internal data address is returned here. + * \param len Size of the typed array is returned here. + * + * Notes: + * When the internal address of the object is acquired any calls to a + * Dart API function that could potentially allocate an object or run + * any Dart code will return an error. + * + * Any Dart API functions for accessing the data should not be called + * before the corresponding release. In particular, the object should + * not be acquired again before its release. This leads to undefined + * behavior. + * + * \return Success if the internal data address is acquired successfully. + * Otherwise, returns an error handle. + */ +DART_EXPORT Dart_Handle Dart_TypedDataAcquireData(Dart_Handle object, + Dart_TypedData_Type* type, + void** data, + intptr_t* len); + +/** + * Releases access to the internal data address that was acquired earlier using + * Dart_TypedDataAcquireData. + * + * \param object The typed data object whose internal data address is to be + * released. + * + * \return Success if the internal data address is released successfully. + * Otherwise, returns an error handle. + */ +DART_EXPORT Dart_Handle Dart_TypedDataReleaseData(Dart_Handle object); + +/** + * Returns the TypedData object associated with the ByteBuffer object. + * + * \param byte_buffer The ByteBuffer object. + * + * \return The TypedData object if no error occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle Dart_GetDataFromByteBuffer(Dart_Handle byte_buffer); + +/* + * ============================================================ + * Invoking Constructors, Methods, Closures and Field accessors + * ============================================================ + */ + +/** + * Invokes a constructor, creating a new object. + * + * This function allows hidden constructors (constructors with leading + * underscores) to be called. + * + * \param type Type of object to be constructed. + * \param constructor_name The name of the constructor to invoke. Use + * Dart_Null() or Dart_EmptyString() to invoke the unnamed constructor. + * This name should not include the name of the class. + * \param number_of_arguments Size of the arguments array. + * \param arguments An array of arguments to the constructor. + * + * \return If the constructor is called and completes successfully, + * then the new object. If an error occurs during execution, then an + * error handle is returned. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_New(Dart_Handle type, + Dart_Handle constructor_name, + int number_of_arguments, + Dart_Handle* arguments); + +/** + * Allocate a new object without invoking a constructor. + * + * \param type The type of an object to be allocated. + * + * \return The new object. If an error occurs during execution, then an + * error handle is returned. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_Allocate(Dart_Handle type); + +/** + * Allocate a new object without invoking a constructor, and sets specified + * native fields. + * + * \param type The type of an object to be allocated. + * \param num_native_fields The number of native fields to set. + * \param native_fields An array containing the value of native fields. + * + * \return The new object. If an error occurs during execution, then an + * error handle is returned. + */ +DART_EXPORT Dart_Handle +Dart_AllocateWithNativeFields(Dart_Handle type, + intptr_t num_native_fields, + const intptr_t* native_fields); + +/** + * Invokes a method or function. + * + * The 'target' parameter may be an object, type, or library. If + * 'target' is an object, then this function will invoke an instance + * method. If 'target' is a type, then this function will invoke a + * static method. If 'target' is a library, then this function will + * invoke a top-level function from that library. + * NOTE: This API call cannot be used to invoke methods of a type object. + * + * This function ignores visibility (leading underscores in names). + * + * May generate an unhandled exception error. + * + * \param target An object, type, or library. + * \param name The name of the function or method to invoke. + * \param number_of_arguments Size of the arguments array. + * \param arguments An array of arguments to the function. + * + * \return If the function or method is called and completes + * successfully, then the return value is returned. If an error + * occurs during execution, then an error handle is returned. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_Invoke(Dart_Handle target, + Dart_Handle name, + int number_of_arguments, + Dart_Handle* arguments); +/* TODO(turnidge): Document how to invoke operators. */ + +/** + * Invokes a Closure with the given arguments. + * + * May generate an unhandled exception error. + * + * \return If no error occurs during execution, then the result of + * invoking the closure is returned. If an error occurs during + * execution, then an error handle is returned. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_InvokeClosure(Dart_Handle closure, + int number_of_arguments, + Dart_Handle* arguments); + +/** + * Invokes a Generative Constructor on an object that was previously + * allocated using Dart_Allocate/Dart_AllocateWithNativeFields. + * + * The 'object' parameter must be an object. + * + * This function ignores visibility (leading underscores in names). + * + * May generate an unhandled exception error. + * + * \param object An object. + * \param name The name of the constructor to invoke. + * Use Dart_Null() or Dart_EmptyString() to invoke the unnamed constructor. + * \param number_of_arguments Size of the arguments array. + * \param arguments An array of arguments to the function. + * + * \return If the constructor is called and completes + * successfully, then the object is returned. If an error + * occurs during execution, then an error handle is returned. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_InvokeConstructor(Dart_Handle object, + Dart_Handle name, + int number_of_arguments, + Dart_Handle* arguments); + +/** + * Gets the value of a field. + * + * The 'container' parameter may be an object, type, or library. If + * 'container' is an object, then this function will access an + * instance field. If 'container' is a type, then this function will + * access a static field. If 'container' is a library, then this + * function will access a top-level variable. + * NOTE: This API call cannot be used to access fields of a type object. + * + * This function ignores field visibility (leading underscores in names). + * + * May generate an unhandled exception error. + * + * \param container An object, type, or library. + * \param name A field name. + * + * \return If no error occurs, then the value of the field is + * returned. Otherwise an error handle is returned. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_GetField(Dart_Handle container, Dart_Handle name); + +/** + * Sets the value of a field. + * + * The 'container' parameter may actually be an object, type, or + * library. If 'container' is an object, then this function will + * access an instance field. If 'container' is a type, then this + * function will access a static field. If 'container' is a library, + * then this function will access a top-level variable. + * NOTE: This API call cannot be used to access fields of a type object. + * + * This function ignores field visibility (leading underscores in names). + * + * May generate an unhandled exception error. + * + * \param container An object, type, or library. + * \param name A field name. + * \param value The new field value. + * + * \return A valid handle if no error occurs. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_SetField(Dart_Handle container, Dart_Handle name, Dart_Handle value); + +/* + * ========== + * Exceptions + * ========== + */ + +/* + * TODO(turnidge): Remove these functions from the api and replace all + * uses with Dart_NewUnhandledExceptionError. */ + +/** + * Throws an exception. + * + * This function causes a Dart language exception to be thrown. This + * will proceed in the standard way, walking up Dart frames until an + * appropriate 'catch' block is found, executing 'finally' blocks, + * etc. + * + * If an error handle is passed into this function, the error is + * propagated immediately. See Dart_PropagateError for a discussion + * of error propagation. + * + * If successful, this function does not return. Note that this means + * that the destructors of any stack-allocated C++ objects will not be + * called. If there are no Dart frames on the stack, an error occurs. + * + * \return An error handle if the exception was not thrown. + * Otherwise the function does not return. + */ +DART_EXPORT Dart_Handle Dart_ThrowException(Dart_Handle exception); + +/** + * Rethrows an exception. + * + * Rethrows an exception, unwinding all dart frames on the stack. If + * successful, this function does not return. Note that this means + * that the destructors of any stack-allocated C++ objects will not be + * called. If there are no Dart frames on the stack, an error occurs. + * + * \return An error handle if the exception was not thrown. + * Otherwise the function does not return. + */ +DART_EXPORT Dart_Handle Dart_ReThrowException(Dart_Handle exception, + Dart_Handle stacktrace); + +/* + * =========================== + * Native fields and functions + * =========================== + */ + +/** + * Gets the number of native instance fields in an object. + */ +DART_EXPORT Dart_Handle Dart_GetNativeInstanceFieldCount(Dart_Handle obj, + int* count); + +/** + * Gets the value of a native field. + * + * TODO(turnidge): Document. + */ +DART_EXPORT Dart_Handle Dart_GetNativeInstanceField(Dart_Handle obj, + int index, + intptr_t* value); + +/** + * Sets the value of a native field. + * + * TODO(turnidge): Document. + */ +DART_EXPORT Dart_Handle Dart_SetNativeInstanceField(Dart_Handle obj, + int index, + intptr_t value); + +/** + * The arguments to a native function. + * + * This object is passed to a native function to represent its + * arguments and return value. It allows access to the arguments to a + * native function by index. It also allows the return value of a + * native function to be set. + */ +typedef struct _Dart_NativeArguments* Dart_NativeArguments; + +/** + * Extracts current isolate group data from the native arguments structure. + */ +DART_EXPORT void* Dart_GetNativeIsolateGroupData(Dart_NativeArguments args); + +typedef enum { + Dart_NativeArgument_kBool = 0, + Dart_NativeArgument_kInt32, + Dart_NativeArgument_kUint32, + Dart_NativeArgument_kInt64, + Dart_NativeArgument_kUint64, + Dart_NativeArgument_kDouble, + Dart_NativeArgument_kString, + Dart_NativeArgument_kInstance, + Dart_NativeArgument_kNativeFields, +} Dart_NativeArgument_Type; + +typedef struct _Dart_NativeArgument_Descriptor { + uint8_t type; + uint8_t index; +} Dart_NativeArgument_Descriptor; + +typedef union _Dart_NativeArgument_Value { + bool as_bool; + int32_t as_int32; + uint32_t as_uint32; + int64_t as_int64; + uint64_t as_uint64; + double as_double; + struct { + Dart_Handle dart_str; + void* peer; + } as_string; + struct { + intptr_t num_fields; + intptr_t* values; + } as_native_fields; + Dart_Handle as_instance; +} Dart_NativeArgument_Value; + +enum { + kNativeArgNumberPos = 0, + kNativeArgNumberSize = 8, + kNativeArgTypePos = kNativeArgNumberPos + kNativeArgNumberSize, + kNativeArgTypeSize = 8, +}; + +#define BITMASK(size) ((1 << size) - 1) +#define DART_NATIVE_ARG_DESCRIPTOR(type, position) \ + (((type & BITMASK(kNativeArgTypeSize)) << kNativeArgTypePos) | \ + (position & BITMASK(kNativeArgNumberSize))) + +/** + * Gets the native arguments based on the types passed in and populates + * the passed arguments buffer with appropriate native values. + * + * \param args the Native arguments block passed into the native call. + * \param num_arguments length of argument descriptor array and argument + * values array passed in. + * \param arg_descriptors an array that describes the arguments that + * need to be retrieved. For each argument to be retrieved the descriptor + * contains the argument number (0, 1 etc.) and the argument type + * described using Dart_NativeArgument_Type, e.g: + * DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kBool, 1) indicates + * that the first argument is to be retrieved and it should be a boolean. + * \param arg_values array into which the native arguments need to be + * extracted into, the array is allocated by the caller (it could be + * stack allocated to avoid the malloc/free performance overhead). + * + * \return Success if all the arguments could be extracted correctly, + * returns an error handle if there were any errors while extracting the + * arguments (mismatched number of arguments, incorrect types, etc.). + */ +DART_EXPORT Dart_Handle +Dart_GetNativeArguments(Dart_NativeArguments args, + int num_arguments, + const Dart_NativeArgument_Descriptor* arg_descriptors, + Dart_NativeArgument_Value* arg_values); + +/** + * Gets the native argument at some index. + */ +DART_EXPORT Dart_Handle Dart_GetNativeArgument(Dart_NativeArguments args, + int index); +/* TODO(turnidge): Specify the behavior of an out-of-bounds access. */ + +/** + * Gets the number of native arguments. + */ +DART_EXPORT int Dart_GetNativeArgumentCount(Dart_NativeArguments args); + +/** + * Gets all the native fields of the native argument at some index. + * \param args Native arguments structure. + * \param arg_index Index of the desired argument in the structure above. + * \param num_fields size of the intptr_t array 'field_values' passed in. + * \param field_values intptr_t array in which native field values are returned. + * \return Success if the native fields where copied in successfully. Otherwise + * returns an error handle. On success the native field values are copied + * into the 'field_values' array, if the argument at 'arg_index' is a + * null object then 0 is copied as the native field values into the + * 'field_values' array. + */ +DART_EXPORT Dart_Handle +Dart_GetNativeFieldsOfArgument(Dart_NativeArguments args, + int arg_index, + int num_fields, + intptr_t* field_values); + +/** + * Gets the native field of the receiver. + */ +DART_EXPORT Dart_Handle Dart_GetNativeReceiver(Dart_NativeArguments args, + intptr_t* value); + +/** + * Gets a string native argument at some index. + * \param args Native arguments structure. + * \param arg_index Index of the desired argument in the structure above. + * \param peer Returns the peer pointer if the string argument has one. + * \return Success if the string argument has a peer, if it does not + * have a peer then the String object is returned. Otherwise returns + * an error handle (argument is not a String object). + */ +DART_EXPORT Dart_Handle Dart_GetNativeStringArgument(Dart_NativeArguments args, + int arg_index, + void** peer); + +/** + * Gets an integer native argument at some index. + * \param args Native arguments structure. + * \param index Index of the desired argument in the structure above. + * \param value Returns the integer value if the argument is an Integer. + * \return Success if no error occurs. Otherwise returns an error handle. + */ +DART_EXPORT Dart_Handle Dart_GetNativeIntegerArgument(Dart_NativeArguments args, + int index, + int64_t* value); + +/** + * Gets a boolean native argument at some index. + * \param args Native arguments structure. + * \param index Index of the desired argument in the structure above. + * \param value Returns the boolean value if the argument is a Boolean. + * \return Success if no error occurs. Otherwise returns an error handle. + */ +DART_EXPORT Dart_Handle Dart_GetNativeBooleanArgument(Dart_NativeArguments args, + int index, + bool* value); + +/** + * Gets a double native argument at some index. + * \param args Native arguments structure. + * \param index Index of the desired argument in the structure above. + * \param value Returns the double value if the argument is a double. + * \return Success if no error occurs. Otherwise returns an error handle. + */ +DART_EXPORT Dart_Handle Dart_GetNativeDoubleArgument(Dart_NativeArguments args, + int index, + double* value); + +/** + * Sets the return value for a native function. + * + * If retval is an Error handle, then error will be propagated once + * the native functions exits. See Dart_PropagateError for a + * discussion of how different types of errors are propagated. + */ +DART_EXPORT void Dart_SetReturnValue(Dart_NativeArguments args, + Dart_Handle retval); + +DART_EXPORT void Dart_SetWeakHandleReturnValue(Dart_NativeArguments args, + Dart_WeakPersistentHandle rval); + +DART_EXPORT void Dart_SetBooleanReturnValue(Dart_NativeArguments args, + bool retval); + +DART_EXPORT void Dart_SetIntegerReturnValue(Dart_NativeArguments args, + int64_t retval); + +DART_EXPORT void Dart_SetDoubleReturnValue(Dart_NativeArguments args, + double retval); + +/** + * A native function. + */ +typedef void (*Dart_NativeFunction)(Dart_NativeArguments arguments); + +/** + * Native entry resolution callback. + * + * For libraries and scripts which have native functions, the embedder + * can provide a native entry resolver. This callback is used to map a + * name/arity to a Dart_NativeFunction. If no function is found, the + * callback should return NULL. + * + * The parameters to the native resolver function are: + * \param name a Dart string which is the name of the native function. + * \param num_of_arguments is the number of arguments expected by the + * native function. + * \param auto_setup_scope is a boolean flag that can be set by the resolver + * to indicate if this function needs a Dart API scope (see Dart_EnterScope/ + * Dart_ExitScope) to be setup automatically by the VM before calling into + * the native function. By default most native functions would require this + * to be true but some light weight native functions which do not call back + * into the VM through the Dart API may not require a Dart scope to be + * setup automatically. + * + * \return A valid Dart_NativeFunction which resolves to a native entry point + * for the native function. + * + * See Dart_SetNativeResolver. + */ +typedef Dart_NativeFunction (*Dart_NativeEntryResolver)(Dart_Handle name, + int num_of_arguments, + bool* auto_setup_scope); +/* TODO(turnidge): Consider renaming to NativeFunctionResolver or + * NativeResolver. */ + +/** + * Native entry symbol lookup callback. + * + * For libraries and scripts which have native functions, the embedder + * can provide a callback for mapping a native entry to a symbol. This callback + * maps a native function entry PC to the native function name. If no native + * entry symbol can be found, the callback should return NULL. + * + * The parameters to the native reverse resolver function are: + * \param nf A Dart_NativeFunction. + * + * \return A const UTF-8 string containing the symbol name or NULL. + * + * See Dart_SetNativeResolver. + */ +typedef const uint8_t* (*Dart_NativeEntrySymbol)(Dart_NativeFunction nf); + +/** + * FFI Native C function pointer resolver callback. + * + * See Dart_SetFfiNativeResolver. + */ +typedef void* (*Dart_FfiNativeResolver)(const char* name, uintptr_t args_n); + +/* + * =========== + * Environment + * =========== + */ + +/** + * An environment lookup callback function. + * + * \param name The name of the value to lookup in the environment. + * + * \return A valid handle to a string if the name exists in the + * current environment or Dart_Null() if not. + */ +typedef Dart_Handle (*Dart_EnvironmentCallback)(Dart_Handle name); + +/** + * Sets the environment callback for the current isolate. This + * callback is used to lookup environment values by name in the + * current environment. This enables the embedder to supply values for + * the const constructors bool.fromEnvironment, int.fromEnvironment + * and String.fromEnvironment. + */ +DART_EXPORT Dart_Handle +Dart_SetEnvironmentCallback(Dart_EnvironmentCallback callback); + +/** + * Sets the callback used to resolve native functions for a library. + * + * \param library A library. + * \param resolver A native entry resolver. + * + * \return A valid handle if the native resolver was set successfully. + */ +DART_EXPORT Dart_Handle +Dart_SetNativeResolver(Dart_Handle library, + Dart_NativeEntryResolver resolver, + Dart_NativeEntrySymbol symbol); +/* TODO(turnidge): Rename to Dart_LibrarySetNativeResolver? */ + +/** + * Returns the callback used to resolve native functions for a library. + * + * \param library A library. + * \param resolver a pointer to a Dart_NativeEntryResolver + * + * \return A valid handle if the library was found. + */ +DART_EXPORT Dart_Handle +Dart_GetNativeResolver(Dart_Handle library, Dart_NativeEntryResolver* resolver); + +/** + * Returns the callback used to resolve native function symbols for a library. + * + * \param library A library. + * \param resolver a pointer to a Dart_NativeEntrySymbol. + * + * \return A valid handle if the library was found. + */ +DART_EXPORT Dart_Handle Dart_GetNativeSymbol(Dart_Handle library, + Dart_NativeEntrySymbol* resolver); + +/** + * Sets the callback used to resolve FFI native functions for a library. + * The resolved functions are expected to be a C function pointer of the + * correct signature (as specified in the `@Native()` function + * annotation in Dart code). + * + * NOTE: This is an experimental feature and might change in the future. + * + * \param library A library. + * \param resolver A native function resolver. + * + * \return A valid handle if the native resolver was set successfully. + */ +DART_EXPORT Dart_Handle +Dart_SetFfiNativeResolver(Dart_Handle library, Dart_FfiNativeResolver resolver); + +/* + * ===================== + * Scripts and Libraries + * ===================== + */ + +typedef enum { + Dart_kCanonicalizeUrl = 0, + Dart_kImportTag, + Dart_kKernelTag, +} Dart_LibraryTag; + +/** + * The library tag handler is a multi-purpose callback provided by the + * embedder to the Dart VM. The embedder implements the tag handler to + * provide the ability to load Dart scripts and imports. + * + * -- TAGS -- + * + * Dart_kCanonicalizeUrl + * + * This tag indicates that the embedder should canonicalize 'url' with + * respect to 'library'. For most embedders, the + * Dart_DefaultCanonicalizeUrl function is a sufficient implementation + * of this tag. The return value should be a string holding the + * canonicalized url. + * + * Dart_kImportTag + * + * This tag is used to load a library from IsolateMirror.loadUri. The embedder + * should call Dart_LoadLibraryFromKernel to provide the library to the VM. The + * return value should be an error or library (the result from + * Dart_LoadLibraryFromKernel). + * + * Dart_kKernelTag + * + * This tag is used to load the intermediate file (kernel) generated by + * the Dart front end. This tag is typically used when a 'hot-reload' + * of an application is needed and the VM is 'use dart front end' mode. + * The dart front end typically compiles all the scripts, imports and part + * files into one intermediate file hence we don't use the source/import or + * script tags. The return value should be an error or a TypedData containing + * the kernel bytes. + * + */ +typedef Dart_Handle (*Dart_LibraryTagHandler)( + Dart_LibraryTag tag, + Dart_Handle library_or_package_map_url, + Dart_Handle url); + +/** + * Sets library tag handler for the current isolate. This handler is + * used to handle the various tags encountered while loading libraries + * or scripts in the isolate. + * + * \param handler Handler code to be used for handling the various tags + * encountered while loading libraries or scripts in the isolate. + * + * \return If no error occurs, the handler is set for the isolate. + * Otherwise an error handle is returned. + * + * TODO(turnidge): Document. + */ +DART_EXPORT Dart_Handle +Dart_SetLibraryTagHandler(Dart_LibraryTagHandler handler); + +/** + * Handles deferred loading requests. When this handler is invoked, it should + * eventually load the deferred loading unit with the given id and call + * Dart_DeferredLoadComplete or Dart_DeferredLoadCompleteError. It is + * recommended that the loading occur asynchronously, but it is permitted to + * call Dart_DeferredLoadComplete or Dart_DeferredLoadCompleteError before the + * handler returns. + * + * If an error is returned, it will be propagated through + * `prefix.loadLibrary()`. This is useful for synchronous + * implementations, which must propagate any unwind errors from + * Dart_DeferredLoadComplete or Dart_DeferredLoadComplete. Otherwise the handler + * should return a non-error such as `Dart_Null()`. + */ +typedef Dart_Handle (*Dart_DeferredLoadHandler)(intptr_t loading_unit_id); + +/** + * Sets the deferred load handler for the current isolate. This handler is + * used to handle loading deferred imports in an AppJIT or AppAOT program. + */ +DART_EXPORT Dart_Handle +Dart_SetDeferredLoadHandler(Dart_DeferredLoadHandler handler); + +/** + * Notifies the VM that a deferred load completed successfully. This function + * will eventually cause the corresponding `prefix.loadLibrary()` futures to + * complete. + * + * Requires the current isolate to be the same current isolate during the + * invocation of the Dart_DeferredLoadHandler. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_DeferredLoadComplete(intptr_t loading_unit_id, + const uint8_t* snapshot_data, + const uint8_t* snapshot_instructions); + +/** + * Notifies the VM that a deferred load failed. This function + * will eventually cause the corresponding `prefix.loadLibrary()` futures to + * complete with an error. + * + * If `transient` is true, future invocations of `prefix.loadLibrary()` will + * trigger new load requests. If false, futures invocation will complete with + * the same error. + * + * Requires the current isolate to be the same current isolate during the + * invocation of the Dart_DeferredLoadHandler. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_DeferredLoadCompleteError(intptr_t loading_unit_id, + const char* error_message, + bool transient); + +/** + * Canonicalizes a url with respect to some library. + * + * The url is resolved with respect to the library's url and some url + * normalizations are performed. + * + * This canonicalization function should be sufficient for most + * embedders to implement the Dart_kCanonicalizeUrl tag. + * + * \param base_url The base url relative to which the url is + * being resolved. + * \param url The url being resolved and canonicalized. This + * parameter is a string handle. + * + * \return If no error occurs, a String object is returned. Otherwise + * an error handle is returned. + */ +DART_EXPORT Dart_Handle Dart_DefaultCanonicalizeUrl(Dart_Handle base_url, + Dart_Handle url); + +/** + * Loads the root library for the current isolate. + * + * Requires there to be no current root library. + * + * \param kernel_buffer A buffer which contains a kernel binary (see + * pkg/kernel/binary.md). Must remain valid until isolate group shutdown. + * \param kernel_size Length of the passed in buffer. + * + * \return A handle to the root library, or an error. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_LoadScriptFromKernel(const uint8_t* kernel_buffer, intptr_t kernel_size); + +/** + * Gets the library for the root script for the current isolate. + * + * If the root script has not yet been set for the current isolate, + * this function returns Dart_Null(). This function never returns an + * error handle. + * + * \return Returns the root Library for the current isolate or Dart_Null(). + */ +DART_EXPORT Dart_Handle Dart_RootLibrary(void); + +/** + * Sets the root library for the current isolate. + * + * \return Returns an error handle if `library` is not a library handle. + */ +DART_EXPORT Dart_Handle Dart_SetRootLibrary(Dart_Handle library); + +/** + * Lookup or instantiate a legacy type by name and type arguments from a + * Library. + * + * \param library The library containing the class or interface. + * \param class_name The class name for the type. + * \param number_of_type_arguments Number of type arguments. + * For non parametric types the number of type arguments would be 0. + * \param type_arguments Pointer to an array of type arguments. + * For non parametric types a NULL would be passed in for this argument. + * + * \return If no error occurs, the type is returned. + * Otherwise an error handle is returned. + */ +DART_EXPORT Dart_Handle Dart_GetType(Dart_Handle library, + Dart_Handle class_name, + intptr_t number_of_type_arguments, + Dart_Handle* type_arguments); + +/** + * Lookup or instantiate a nullable type by name and type arguments from + * Library. + * + * \param library The library containing the class or interface. + * \param class_name The class name for the type. + * \param number_of_type_arguments Number of type arguments. + * For non parametric types the number of type arguments would be 0. + * \param type_arguments Pointer to an array of type arguments. + * For non parametric types a NULL would be passed in for this argument. + * + * \return If no error occurs, the type is returned. + * Otherwise an error handle is returned. + */ +DART_EXPORT Dart_Handle Dart_GetNullableType(Dart_Handle library, + Dart_Handle class_name, + intptr_t number_of_type_arguments, + Dart_Handle* type_arguments); + +/** + * Lookup or instantiate a non-nullable type by name and type arguments from + * Library. + * + * \param library The library containing the class or interface. + * \param class_name The class name for the type. + * \param number_of_type_arguments Number of type arguments. + * For non parametric types the number of type arguments would be 0. + * \param type_arguments Pointer to an array of type arguments. + * For non parametric types a NULL would be passed in for this argument. + * + * \return If no error occurs, the type is returned. + * Otherwise an error handle is returned. + */ +DART_EXPORT Dart_Handle +Dart_GetNonNullableType(Dart_Handle library, + Dart_Handle class_name, + intptr_t number_of_type_arguments, + Dart_Handle* type_arguments); + +/** + * Creates a nullable version of the provided type. + * + * \param type The type to be converted to a nullable type. + * + * \return If no error occurs, a nullable type is returned. + * Otherwise an error handle is returned. + */ +DART_EXPORT Dart_Handle Dart_TypeToNullableType(Dart_Handle type); + +/** + * Creates a non-nullable version of the provided type. + * + * \param type The type to be converted to a non-nullable type. + * + * \return If no error occurs, a non-nullable type is returned. + * Otherwise an error handle is returned. + */ +DART_EXPORT Dart_Handle Dart_TypeToNonNullableType(Dart_Handle type); + +/** + * A type's nullability. + * + * \param type A Dart type. + * \param result An out parameter containing the result of the check. True if + * the type is of the specified nullability, false otherwise. + * + * \return Returns an error handle if type is not of type Type. + */ +DART_EXPORT Dart_Handle Dart_IsNullableType(Dart_Handle type, bool* result); +DART_EXPORT Dart_Handle Dart_IsNonNullableType(Dart_Handle type, bool* result); +DART_EXPORT Dart_Handle Dart_IsLegacyType(Dart_Handle type, bool* result); + +/** + * Lookup a class or interface by name from a Library. + * + * \param library The library containing the class or interface. + * \param class_name The name of the class or interface. + * + * \return If no error occurs, the class or interface is + * returned. Otherwise an error handle is returned. + */ +DART_EXPORT Dart_Handle Dart_GetClass(Dart_Handle library, + Dart_Handle class_name); +/* TODO(asiva): The above method needs to be removed once all uses + * of it are removed from the embedder code. */ + +/** + * Returns an import path to a Library, such as "file:///test.dart" or + * "dart:core". + */ +DART_EXPORT Dart_Handle Dart_LibraryUrl(Dart_Handle library); + +/** + * Returns a URL from which a Library was loaded. + */ +DART_EXPORT Dart_Handle Dart_LibraryResolvedUrl(Dart_Handle library); + +/** + * \return An array of libraries. + */ +DART_EXPORT Dart_Handle Dart_GetLoadedLibraries(void); + +DART_EXPORT Dart_Handle Dart_LookupLibrary(Dart_Handle url); +/* TODO(turnidge): Consider returning Dart_Null() when the library is + * not found to distinguish that from a true error case. */ + +/** + * Report an loading error for the library. + * + * \param library The library that failed to load. + * \param error The Dart error instance containing the load error. + * + * \return If the VM handles the error, the return value is + * a null handle. If it doesn't handle the error, the error + * object is returned. + */ +DART_EXPORT Dart_Handle Dart_LibraryHandleError(Dart_Handle library, + Dart_Handle error); + +/** + * Called by the embedder to load a partial program. Does not set the root + * library. + * + * \param kernel_buffer A buffer which contains a kernel binary (see + * pkg/kernel/binary.md). Must remain valid until isolate shutdown. + * \param kernel_buffer_size Length of the passed in buffer. + * + * \return A handle to the main library of the compilation unit, or an error. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_LoadLibraryFromKernel(const uint8_t* kernel_buffer, + intptr_t kernel_buffer_size); +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_LoadLibrary(Dart_Handle kernel_buffer); + +/** + * Indicates that all outstanding load requests have been satisfied. + * This finalizes all the new classes loaded and optionally completes + * deferred library futures. + * + * Requires there to be a current isolate. + * + * \param complete_futures Specify true if all deferred library + * futures should be completed, false otherwise. + * + * \return Success if all classes have been finalized and deferred library + * futures are completed. Otherwise, returns an error. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_FinalizeLoading(bool complete_futures); + +/* + * ===== + * Peers + * ===== + */ + +/** + * The peer field is a lazily allocated field intended for storage of + * an uncommonly used values. Most instances types can have a peer + * field allocated. The exceptions are subtypes of Null, num, and + * bool. + */ + +/** + * Returns the value of peer field of 'object' in 'peer'. + * + * \param object An object. + * \param peer An out parameter that returns the value of the peer + * field. + * + * \return Returns an error if 'object' is a subtype of Null, num, or + * bool. + */ +DART_EXPORT Dart_Handle Dart_GetPeer(Dart_Handle object, void** peer); + +/** + * Sets the value of the peer field of 'object' to the value of + * 'peer'. + * + * \param object An object. + * \param peer A value to store in the peer field. + * + * \return Returns an error if 'object' is a subtype of Null, num, or + * bool. + */ +DART_EXPORT Dart_Handle Dart_SetPeer(Dart_Handle object, void* peer); + +/* + * ====== + * Kernel + * ====== + */ + +/** + * Experimental support for Dart to Kernel parser isolate. + * + * TODO(hausner): Document finalized interface. + * + */ + +// TODO(33433): Remove kernel service from the embedding API. + +typedef enum { + Dart_KernelCompilationStatus_Unknown = -1, + Dart_KernelCompilationStatus_Ok = 0, + Dart_KernelCompilationStatus_Error = 1, + Dart_KernelCompilationStatus_Crash = 2, + Dart_KernelCompilationStatus_MsgFailed = 3, +} Dart_KernelCompilationStatus; + +typedef struct { + Dart_KernelCompilationStatus status; + char* error; + uint8_t* kernel; + intptr_t kernel_size; +} Dart_KernelCompilationResult; + +typedef enum { + Dart_KernelCompilationVerbosityLevel_Error = 0, + Dart_KernelCompilationVerbosityLevel_Warning, + Dart_KernelCompilationVerbosityLevel_Info, + Dart_KernelCompilationVerbosityLevel_All, +} Dart_KernelCompilationVerbosityLevel; + +DART_EXPORT bool Dart_IsKernelIsolate(Dart_Isolate isolate); +DART_EXPORT bool Dart_KernelIsolateIsRunning(void); +DART_EXPORT Dart_Port Dart_KernelPort(void); + +/** + * Compiles the given `script_uri` to a kernel file. + * + * \param platform_kernel A buffer containing the kernel of the platform (e.g. + * `vm_platform_strong.dill`). The VM does not take ownership of this memory. + * + * \param platform_kernel_size The length of the platform_kernel buffer. + * + * \param snapshot_compile Set to `true` when the compilation is for a snapshot. + * This is used by the frontend to determine if compilation related information + * should be printed to console (e.g., null safety mode). + * + * \param embed_sources Set to `true` when sources should be embedded in the + * kernel file. + * + * \param verbosity Specifies the logging behavior of the kernel compilation + * service. + * + * \return Returns the result of the compilation. + * + * On a successful compilation the returned [Dart_KernelCompilationResult] has + * a status of [Dart_KernelCompilationStatus_Ok] and the `kernel`/`kernel_size` + * fields are set. The caller takes ownership of the malloc()ed buffer. + * + * On a failed compilation the `error` might be set describing the reason for + * the failed compilation. The caller takes ownership of the malloc()ed + * error. + * + * Requires there to be a current isolate. + */ +DART_EXPORT Dart_KernelCompilationResult +Dart_CompileToKernel(const char* script_uri, + const uint8_t* platform_kernel, + const intptr_t platform_kernel_size, + bool incremental_compile, + bool snapshot_compile, + bool embed_sources, + const char* package_config, + Dart_KernelCompilationVerbosityLevel verbosity); + +typedef struct { + const char* uri; + const char* source; +} Dart_SourceFile; + +DART_EXPORT Dart_KernelCompilationResult Dart_KernelListDependencies(void); + +/** + * Sets the kernel buffer which will be used to load Dart SDK sources + * dynamically at runtime. + * + * \param platform_kernel A buffer containing kernel which has sources for the + * Dart SDK populated. Note: The VM does not take ownership of this memory. + * + * \param platform_kernel_size The length of the platform_kernel buffer. + */ +DART_EXPORT void Dart_SetDartLibrarySourcesKernel( + const uint8_t* platform_kernel, + const intptr_t platform_kernel_size); + +/** + * Always return true as the VM only supports strong null safety. + */ +DART_EXPORT bool Dart_DetectNullSafety(const char* script_uri, + const char* package_config, + const char* original_working_directory, + const uint8_t* snapshot_data, + const uint8_t* snapshot_instructions, + const uint8_t* kernel_buffer, + intptr_t kernel_buffer_size); + +#define DART_KERNEL_ISOLATE_NAME "kernel-service" + +/* + * ======= + * Service + * ======= + */ + +#define DART_VM_SERVICE_ISOLATE_NAME "vm-service" + +/** + * Returns true if isolate is the service isolate. + * + * \param isolate An isolate + * + * \return Returns true if 'isolate' is the service isolate. + */ +DART_EXPORT bool Dart_IsServiceIsolate(Dart_Isolate isolate); + +/** + * Writes the CPU profile to the timeline as a series of 'instant' events. + * + * Note that this is an expensive operation. + * + * \param main_port The main port of the Isolate whose profile samples to write. + * \param error An optional error, must be free()ed by caller. + * + * \return Returns true if the profile is successfully written and false + * otherwise. + */ +DART_EXPORT bool Dart_WriteProfileToTimeline(Dart_Port main_port, char** error); + +/* + * ============== + * Precompilation + * ============== + */ + +/** + * Compiles all functions reachable from entry points and marks + * the isolate to disallow future compilation. + * + * Entry points should be specified using `@pragma("vm:entry-point")` + * annotation. + * + * \return An error handle if a compilation error or runtime error running const + * constructors was encountered. + */ +DART_EXPORT Dart_Handle Dart_Precompile(void); + +typedef void (*Dart_CreateLoadingUnitCallback)( + void* callback_data, + intptr_t loading_unit_id, + void** write_callback_data, + void** write_debug_callback_data); +typedef void (*Dart_StreamingWriteCallback)(void* callback_data, + const uint8_t* buffer, + intptr_t size); +typedef void (*Dart_StreamingCloseCallback)(void* callback_data); + +DART_EXPORT Dart_Handle Dart_LoadingUnitLibraryUris(intptr_t loading_unit_id); + +// On Darwin systems, 'dlsym' adds an '_' to the beginning of the symbol name. +// Use the '...CSymbol' definitions for resolving through 'dlsym'. The actual +// symbol names in the objects are given by the '...AsmSymbol' definitions. +#if defined(__APPLE__) +#define kSnapshotBuildIdCSymbol "kDartSnapshotBuildId" +#define kVmSnapshotDataCSymbol "kDartVmSnapshotData" +#define kVmSnapshotInstructionsCSymbol "kDartVmSnapshotInstructions" +#define kVmSnapshotBssCSymbol "kDartVmSnapshotBss" +#define kIsolateSnapshotDataCSymbol "kDartIsolateSnapshotData" +#define kIsolateSnapshotInstructionsCSymbol "kDartIsolateSnapshotInstructions" +#define kIsolateSnapshotBssCSymbol "kDartIsolateSnapshotBss" +#else +#define kSnapshotBuildIdCSymbol "_kDartSnapshotBuildId" +#define kVmSnapshotDataCSymbol "_kDartVmSnapshotData" +#define kVmSnapshotInstructionsCSymbol "_kDartVmSnapshotInstructions" +#define kVmSnapshotBssCSymbol "_kDartVmSnapshotBss" +#define kIsolateSnapshotDataCSymbol "_kDartIsolateSnapshotData" +#define kIsolateSnapshotInstructionsCSymbol "_kDartIsolateSnapshotInstructions" +#define kIsolateSnapshotBssCSymbol "_kDartIsolateSnapshotBss" +#endif + +#define kSnapshotBuildIdAsmSymbol "_kDartSnapshotBuildId" +#define kVmSnapshotDataAsmSymbol "_kDartVmSnapshotData" +#define kVmSnapshotInstructionsAsmSymbol "_kDartVmSnapshotInstructions" +#define kVmSnapshotBssAsmSymbol "_kDartVmSnapshotBss" +#define kIsolateSnapshotDataAsmSymbol "_kDartIsolateSnapshotData" +#define kIsolateSnapshotInstructionsAsmSymbol \ + "_kDartIsolateSnapshotInstructions" +#define kIsolateSnapshotBssAsmSymbol "_kDartIsolateSnapshotBss" + +/** + * Creates a precompiled snapshot. + * - A root library must have been loaded. + * - Dart_Precompile must have been called. + * + * Outputs an assembly file defining the symbols listed in the definitions + * above. + * + * The assembly should be compiled as a static or shared library and linked or + * loaded by the embedder. Running this snapshot requires a VM compiled with + * DART_PRECOMPILED_SNAPSHOT. The kDartVmSnapshotData and + * kDartVmSnapshotInstructions should be passed to Dart_Initialize. The + * kDartIsolateSnapshotData and kDartIsolateSnapshotInstructions should be + * passed to Dart_CreateIsolateGroup. + * + * The callback will be invoked one or more times to provide the assembly code. + * + * If stripped is true, then the assembly code will not include DWARF + * debugging sections. + * + * If debug_callback_data is provided, debug_callback_data will be used with + * the callback to provide separate debugging information. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_CreateAppAOTSnapshotAsAssembly(Dart_StreamingWriteCallback callback, + void* callback_data, + bool stripped, + void* debug_callback_data); +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_CreateAppAOTSnapshotAsAssemblies( + Dart_CreateLoadingUnitCallback next_callback, + void* next_callback_data, + bool stripped, + Dart_StreamingWriteCallback write_callback, + Dart_StreamingCloseCallback close_callback); + +/** + * Creates a precompiled snapshot. + * - A root library must have been loaded. + * - Dart_Precompile must have been called. + * + * Outputs an ELF shared library defining the symbols + * - _kDartVmSnapshotData + * - _kDartVmSnapshotInstructions + * - _kDartIsolateSnapshotData + * - _kDartIsolateSnapshotInstructions + * + * The shared library should be dynamically loaded by the embedder. + * Running this snapshot requires a VM compiled with DART_PRECOMPILED_SNAPSHOT. + * The kDartVmSnapshotData and kDartVmSnapshotInstructions should be passed to + * Dart_Initialize. The kDartIsolateSnapshotData and + * kDartIsolateSnapshotInstructions should be passed to Dart_CreateIsolate. + * + * The callback will be invoked one or more times to provide the binary output. + * + * If stripped is true, then the binary output will not include DWARF + * debugging sections. + * + * If debug_callback_data is provided, debug_callback_data will be used with + * the callback to provide separate debugging information. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_CreateAppAOTSnapshotAsElf(Dart_StreamingWriteCallback callback, + void* callback_data, + bool stripped, + void* debug_callback_data); +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_CreateAppAOTSnapshotAsElfs(Dart_CreateLoadingUnitCallback next_callback, + void* next_callback_data, + bool stripped, + Dart_StreamingWriteCallback write_callback, + Dart_StreamingCloseCallback close_callback); + +/** + * Like Dart_CreateAppAOTSnapshotAsAssembly, but only includes + * kDartVmSnapshotData and kDartVmSnapshotInstructions. It also does + * not strip DWARF information from the generated assembly or allow for + * separate debug information. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_CreateVMAOTSnapshotAsAssembly(Dart_StreamingWriteCallback callback, + void* callback_data); + +/** + * Sorts the class-ids in depth first traversal order of the inheritance + * tree. This is a costly operation, but it can make method dispatch + * more efficient and is done before writing snapshots. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_SortClasses(void); + +/** + * Creates a snapshot that caches compiled code and type feedback for faster + * startup and quicker warmup in a subsequent process. + * + * Outputs a snapshot in two pieces. The pieces should be passed to + * Dart_CreateIsolateGroup in a VM using the same VM snapshot pieces used in the + * current VM. The instructions piece must be loaded with read and execute + * permissions; the data piece may be loaded as read-only. + * + * - Requires the VM to have not been started with --precompilation. + * - Not supported when targeting IA32. + * - The VM writing the snapshot and the VM reading the snapshot must be the + * same version, must be built in the same DEBUG/RELEASE/PRODUCT mode, must + * be targeting the same architecture, and must both be in checked mode or + * both in unchecked mode. + * + * The buffers are scope allocated and are only valid until the next call to + * Dart_ExitScope. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_CreateAppJITSnapshotAsBlobs(uint8_t** isolate_snapshot_data_buffer, + intptr_t* isolate_snapshot_data_size, + uint8_t** isolate_snapshot_instructions_buffer, + intptr_t* isolate_snapshot_instructions_size); + +/** + * Get obfuscation map for precompiled code. + * + * Obfuscation map is encoded as a JSON array of pairs (original name, + * obfuscated name). + * + * \return Returns an error handler if the VM was built in a mode that does not + * support obfuscation. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_GetObfuscationMap(uint8_t** buffer, intptr_t* buffer_length); + +/** + * Returns whether the VM only supports running from precompiled snapshots and + * not from any other kind of snapshot or from source (that is, the VM was + * compiled with DART_PRECOMPILED_RUNTIME). + */ +DART_EXPORT bool Dart_IsPrecompiledRuntime(void); + +/** + * Print a native stack trace. Used for crash handling. + * + * If context is NULL, prints the current stack trace. Otherwise, context + * should be a CONTEXT* (Windows) or ucontext_t* (POSIX) from a signal handler + * running on the current thread. + */ +DART_EXPORT void Dart_DumpNativeStackTrace(void* context); + +/** + * Indicate that the process is about to abort, and the Dart VM should not + * attempt to cleanup resources. + */ +DART_EXPORT void Dart_PrepareToAbort(void); + +/** + * Callback provided by the embedder that is used by the VM to + * produce footnotes appended to DWARF stack traces. + * + * Whenever VM formats a stack trace as a string it would call this callback + * passing raw program counters for each frame in the stack trace. + * + * Embedder can then return a string which if not-null will be appended to the + * formatted stack trace. + * + * Returned string is expected to be `malloc()` allocated. VM takes ownership + * of the returned string and will `free()` it. + * + * \param addresses raw program counter addresses for each frame + * \param count number of elements in the addresses array + */ +typedef char* (*Dart_DwarfStackTraceFootnoteCallback)(void* addresses[], + intptr_t count); + +/** + * Configure DWARF stack trace footnote callback. + */ +DART_EXPORT void Dart_SetDwarfStackTraceFootnoteCallback( + Dart_DwarfStackTraceFootnoteCallback callback); + +#endif /* INCLUDE_DART_API_H_ */ /* NOLINT */ diff --git a/pkgs/objective_c/src/include/dart_api_dl.c b/pkgs/objective_c/src/include/dart_api_dl.c new file mode 100644 index 000000000..48fb54e7b --- /dev/null +++ b/pkgs/objective_c/src/include/dart_api_dl.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file + * for details. All rights reserved. Use of this source code is governed by a + * BSD-style license that can be found in the LICENSE file. + */ + +#include "dart_api_dl.h" /* NOLINT */ +#include "dart_version.h" /* NOLINT */ +#include "internal/dart_api_dl_impl.h" /* NOLINT */ + +#include +#include + +#define DART_API_DL_DEFINITIONS(name, R, A) name##_Type name##_DL = NULL; + +DART_API_ALL_DL_SYMBOLS(DART_API_DL_DEFINITIONS) +DART_API_DEPRECATED_DL_SYMBOLS(DART_API_DL_DEFINITIONS) + +#undef DART_API_DL_DEFINITIONS + +typedef void* DartApiEntry_function; + +DartApiEntry_function FindFunctionPointer(const DartApiEntry* entries, + const char* name) { + while (entries->name != NULL) { + if (strcmp(entries->name, name) == 0) return entries->function; + entries++; + } + return NULL; +} + +DART_EXPORT void Dart_UpdateExternalSize_Deprecated( + Dart_WeakPersistentHandle object, intptr_t external_size) { + printf("Dart_UpdateExternalSize is a nop, it has been deprecated\n"); +} + +DART_EXPORT void Dart_UpdateFinalizableExternalSize_Deprecated( + Dart_FinalizableHandle object, + Dart_Handle strong_ref_to_object, + intptr_t external_allocation_size) { + printf("Dart_UpdateFinalizableExternalSize is a nop, " + "it has been deprecated\n"); +} + +intptr_t Dart_InitializeApiDL(void* data) { + DartApi* dart_api_data = (DartApi*)data; + + if (dart_api_data->major != DART_API_DL_MAJOR_VERSION) { + // If the DartVM we're running on does not have the same version as this + // file was compiled against, refuse to initialize. The symbols are not + // compatible. + return -1; + } + // Minor versions are allowed to be different. + // If the DartVM has a higher minor version, it will provide more symbols + // than we initialize here. + // If the DartVM has a lower minor version, it will not provide all symbols. + // In that case, we leave the missing symbols un-initialized. Those symbols + // should not be used by the Dart and native code. The client is responsible + // for checking the minor version number himself based on which symbols it + // is using. + // (If we would error out on this case, recompiling native code against a + // newer SDK would break all uses on older SDKs, which is too strict.) + + const DartApiEntry* dart_api_function_pointers = dart_api_data->functions; + +#define DART_API_DL_INIT(name, R, A) \ + name##_DL = \ + (name##_Type)(FindFunctionPointer(dart_api_function_pointers, #name)); + DART_API_ALL_DL_SYMBOLS(DART_API_DL_INIT) +#undef DART_API_DL_INIT + +#define DART_API_DEPRECATED_DL_INIT(name, R, A) \ + name##_DL = name##_Deprecated; + DART_API_DEPRECATED_DL_SYMBOLS(DART_API_DEPRECATED_DL_INIT) +#undef DART_API_DEPRECATED_DL_INIT + + return 0; +} diff --git a/pkgs/objective_c/src/include/dart_api_dl.h b/pkgs/objective_c/src/include/dart_api_dl.h new file mode 100644 index 000000000..5088b4337 --- /dev/null +++ b/pkgs/objective_c/src/include/dart_api_dl.h @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file + * for details. All rights reserved. Use of this source code is governed by a + * BSD-style license that can be found in the LICENSE file. + */ + +#ifndef RUNTIME_INCLUDE_DART_API_DL_H_ +#define RUNTIME_INCLUDE_DART_API_DL_H_ + +#include "dart_api.h" /* NOLINT */ +#include "dart_native_api.h" /* NOLINT */ + +/** \mainpage Dynamically Linked Dart API + * + * This exposes a subset of symbols from dart_api.h and dart_native_api.h + * available in every Dart embedder through dynamic linking. + * + * All symbols are postfixed with _DL to indicate that they are dynamically + * linked and to prevent conflicts with the original symbol. + * + * Link `dart_api_dl.c` file into your library and invoke + * `Dart_InitializeApiDL` with `NativeApi.initializeApiDLData`. + * + * Returns 0 on success. + */ + +DART_EXPORT intptr_t Dart_InitializeApiDL(void* data); + +// ============================================================================ +// IMPORTANT! Never update these signatures without properly updating +// DART_API_DL_MAJOR_VERSION and DART_API_DL_MINOR_VERSION. +// +// Verbatim copy of `dart_native_api.h` and `dart_api.h` symbol names and types +// to trigger compile-time errors if the symbols in those files are updated +// without updating these. +// +// Function return and argument types, and typedefs are carbon copied. Structs +// are typechecked nominally in C/C++, so they are not copied, instead a +// comment is added to their definition. +typedef int64_t Dart_Port_DL; + +typedef void (*Dart_NativeMessageHandler_DL)(Dart_Port_DL dest_port_id, + Dart_CObject* message); + +// dart_native_api.h symbols can be called on any thread. +#define DART_NATIVE_API_DL_SYMBOLS(F) \ + /***** dart_native_api.h *****/ \ + /* Dart_Port */ \ + F(Dart_PostCObject, bool, (Dart_Port_DL port_id, Dart_CObject * message)) \ + F(Dart_PostInteger, bool, (Dart_Port_DL port_id, int64_t message)) \ + F(Dart_NewNativePort, Dart_Port_DL, \ + (const char* name, Dart_NativeMessageHandler_DL handler, \ + bool handle_concurrently)) \ + F(Dart_CloseNativePort, bool, (Dart_Port_DL native_port_id)) + +// dart_api.h symbols can only be called on Dart threads. +#define DART_API_DL_SYMBOLS(F) \ + /***** dart_api.h *****/ \ + /* Errors */ \ + F(Dart_IsError, bool, (Dart_Handle handle)) \ + F(Dart_IsApiError, bool, (Dart_Handle handle)) \ + F(Dart_IsUnhandledExceptionError, bool, (Dart_Handle handle)) \ + F(Dart_IsCompilationError, bool, (Dart_Handle handle)) \ + F(Dart_IsFatalError, bool, (Dart_Handle handle)) \ + F(Dart_GetError, const char*, (Dart_Handle handle)) \ + F(Dart_ErrorHasException, bool, (Dart_Handle handle)) \ + F(Dart_ErrorGetException, Dart_Handle, (Dart_Handle handle)) \ + F(Dart_ErrorGetStackTrace, Dart_Handle, (Dart_Handle handle)) \ + F(Dart_NewApiError, Dart_Handle, (const char* error)) \ + F(Dart_NewCompilationError, Dart_Handle, (const char* error)) \ + F(Dart_NewUnhandledExceptionError, Dart_Handle, (Dart_Handle exception)) \ + F(Dart_PropagateError, void, (Dart_Handle handle)) \ + /* Dart_Handle, Dart_PersistentHandle, Dart_WeakPersistentHandle */ \ + F(Dart_HandleFromPersistent, Dart_Handle, (Dart_PersistentHandle object)) \ + F(Dart_HandleFromWeakPersistent, Dart_Handle, \ + (Dart_WeakPersistentHandle object)) \ + F(Dart_NewPersistentHandle, Dart_PersistentHandle, (Dart_Handle object)) \ + F(Dart_SetPersistentHandle, void, \ + (Dart_PersistentHandle obj1, Dart_Handle obj2)) \ + F(Dart_DeletePersistentHandle, void, (Dart_PersistentHandle object)) \ + F(Dart_NewWeakPersistentHandle, Dart_WeakPersistentHandle, \ + (Dart_Handle object, void* peer, intptr_t external_allocation_size, \ + Dart_HandleFinalizer callback)) \ + F(Dart_DeleteWeakPersistentHandle, void, (Dart_WeakPersistentHandle object)) \ + F(Dart_NewFinalizableHandle, Dart_FinalizableHandle, \ + (Dart_Handle object, void* peer, intptr_t external_allocation_size, \ + Dart_HandleFinalizer callback)) \ + F(Dart_DeleteFinalizableHandle, void, \ + (Dart_FinalizableHandle object, Dart_Handle strong_ref_to_object)) \ + /* Isolates */ \ + F(Dart_CurrentIsolate, Dart_Isolate, (void)) \ + F(Dart_ExitIsolate, void, (void)) \ + F(Dart_EnterIsolate, void, (Dart_Isolate)) \ + /* Dart_Port */ \ + F(Dart_Post, bool, (Dart_Port_DL port_id, Dart_Handle object)) \ + F(Dart_NewSendPort, Dart_Handle, (Dart_Port_DL port_id)) \ + F(Dart_SendPortGetId, Dart_Handle, \ + (Dart_Handle port, Dart_Port_DL * port_id)) \ + /* Scopes */ \ + F(Dart_EnterScope, void, (void)) \ + F(Dart_ExitScope, void, (void)) \ + /* Objects */ \ + F(Dart_IsNull, bool, (Dart_Handle)) \ + F(Dart_Null, Dart_Handle, (void)) + +// dart_api.h symbols that have been deprecated but are retained here +// until we can make a breaking change bumping the major version number +// (DART_API_DL_MAJOR_VERSION) +#define DART_API_DEPRECATED_DL_SYMBOLS(F) \ + F(Dart_UpdateExternalSize, void, \ + (Dart_WeakPersistentHandle object, intptr_t external_allocation_size)) \ + F(Dart_UpdateFinalizableExternalSize, void, \ + (Dart_FinalizableHandle object, Dart_Handle strong_ref_to_object, \ + intptr_t external_allocation_size)) + +#define DART_API_ALL_DL_SYMBOLS(F) \ + DART_NATIVE_API_DL_SYMBOLS(F) \ + DART_API_DL_SYMBOLS(F) +// IMPORTANT! Never update these signatures without properly updating +// DART_API_DL_MAJOR_VERSION and DART_API_DL_MINOR_VERSION. +// +// End of verbatim copy. +// ============================================================================ + +// Copy of definition of DART_EXPORT without 'used' attribute. +// +// The 'used' attribute cannot be used with DART_API_ALL_DL_SYMBOLS because +// they are not function declarations, but variable declarations with a +// function pointer type. +// +// The function pointer variables are initialized with the addresses of the +// functions in the VM. If we were to use function declarations instead, we +// would need to forward the call to the VM adding indirection. +#if defined(__CYGWIN__) +#error Tool chain and platform not supported. +#elif defined(_WIN32) +#if defined(DART_SHARED_LIB) +#define DART_EXPORT_DL DART_EXTERN_C __declspec(dllexport) +#else +#define DART_EXPORT_DL DART_EXTERN_C +#endif +#else +#if __GNUC__ >= 4 +#if defined(DART_SHARED_LIB) +#define DART_EXPORT_DL DART_EXTERN_C __attribute__((visibility("default"))) +#else +#define DART_EXPORT_DL DART_EXTERN_C +#endif +#else +#error Tool chain not supported. +#endif +#endif + +#define DART_API_DL_DECLARATIONS(name, R, A) \ + typedef R(*name##_Type) A; \ + DART_EXPORT_DL name##_Type name##_DL; + +DART_API_ALL_DL_SYMBOLS(DART_API_DL_DECLARATIONS) +DART_API_DEPRECATED_DL_SYMBOLS(DART_API_DL_DECLARATIONS) + +#undef DART_API_DL_DECLARATIONS + +#undef DART_EXPORT_DL + +#endif /* RUNTIME_INCLUDE_DART_API_DL_H_ */ /* NOLINT */ diff --git a/pkgs/objective_c/src/include/dart_embedder_api.h b/pkgs/objective_c/src/include/dart_embedder_api.h new file mode 100644 index 000000000..bc0377340 --- /dev/null +++ b/pkgs/objective_c/src/include/dart_embedder_api.h @@ -0,0 +1,105 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +#ifndef RUNTIME_INCLUDE_DART_EMBEDDER_API_H_ +#define RUNTIME_INCLUDE_DART_EMBEDDER_API_H_ + +#include "include/dart_api.h" +#include "include/dart_tools_api.h" + +namespace dart { +namespace embedder { + +// Initialize all subsystems of the embedder. +// +// Must be called before the `Dart_Initialize()` call to initialize the +// Dart VM. +// +// Returns true on success and false otherwise, in which case error would +// contain error message. +DART_WARN_UNUSED_RESULT bool InitOnce(char** error); + +// Cleans up all subsystems of the embedder. +// +// Must be called after the `Dart_Cleanup()` call to initialize the +// Dart VM. +void Cleanup(); + +// Common arguments that are passed to isolate creation callback and to +// API methods that create isolates. +struct IsolateCreationData { + // URI for the main script that will be running in the isolate. + const char* script_uri; + + // Advisory name of the main method that will be run by isolate. + // Only used for error messages. + const char* main; + + // Isolate creation flags. Might be absent. + Dart_IsolateFlags* flags; + + // Isolate group callback data. + void* isolate_group_data; + + // Isolate callback data. + void* isolate_data; +}; + +// Create and initialize kernel-service isolate. This method should be used +// when VM invokes isolate creation callback with DART_KERNEL_ISOLATE_NAME as +// script_uri. +// The isolate is created from the given snapshot (might be kernel data or +// app-jit snapshot). +DART_WARN_UNUSED_RESULT Dart_Isolate +CreateKernelServiceIsolate(const IsolateCreationData& data, + const uint8_t* buffer, + intptr_t buffer_size, + char** error); + +// Service isolate configuration. +struct VmServiceConfiguration { + enum { kBindHttpServerToAFreePort = 0, kDoNotAutoStartHttpServer = -1 }; + + // Address to which HTTP server will be bound. + const char* ip; + + // Default port. See enum above for special values. + int port; + + // If non-null, connection information for the VM service will be output to a + // file in JSON format at the location specified. + const char* write_service_info_filename; + + // TODO(vegorov) document these ones. + bool dev_mode; + bool deterministic; + bool disable_auth_codes; +}; + +// Create and initialize vm-service isolate from the given AOT snapshot, which +// is expected to contain all necessary 'vm-service' libraries. +// This method should be used when VM invokes isolate creation callback with +// DART_VM_SERVICE_ISOLATE_NAME as script_uri. +DART_WARN_UNUSED_RESULT Dart_Isolate +CreateVmServiceIsolate(const IsolateCreationData& data, + const VmServiceConfiguration& config, + const uint8_t* isolate_data, + const uint8_t* isolate_instr, + char** error); + +// Create and initialize vm-service isolate from the given kernel binary, which +// is expected to contain all necessary 'vm-service' libraries. +// This method should be used when VM invokes isolate creation callback with +// DART_VM_SERVICE_ISOLATE_NAME as script_uri. +DART_WARN_UNUSED_RESULT Dart_Isolate +CreateVmServiceIsolateFromKernel(const IsolateCreationData& data, + const VmServiceConfiguration& config, + const uint8_t* kernel_buffer, + intptr_t kernel_buffer_size, + char** error); + +} // namespace embedder +} // namespace dart + +#endif // RUNTIME_INCLUDE_DART_EMBEDDER_API_H_ diff --git a/pkgs/objective_c/src/include/dart_native_api.h b/pkgs/objective_c/src/include/dart_native_api.h new file mode 100644 index 000000000..79194e03b --- /dev/null +++ b/pkgs/objective_c/src/include/dart_native_api.h @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file + * for details. All rights reserved. Use of this source code is governed by a + * BSD-style license that can be found in the LICENSE file. + */ + +#ifndef RUNTIME_INCLUDE_DART_NATIVE_API_H_ +#define RUNTIME_INCLUDE_DART_NATIVE_API_H_ + +#include "dart_api.h" /* NOLINT */ + +/* + * ========================================== + * Message sending/receiving from native code + * ========================================== + */ + +/** + * A Dart_CObject is used for representing Dart objects as native C + * data outside the Dart heap. These objects are totally detached from + * the Dart heap. Only a subset of the Dart objects have a + * representation as a Dart_CObject. + * + * The string encoding in the 'value.as_string' is UTF-8. + * + * All the different types from dart:typed_data are exposed as type + * kTypedData. The specific type from dart:typed_data is in the type + * field of the as_typed_data structure. The length in the + * as_typed_data structure is always in bytes. + * + * The data for kTypedData is copied on message send and ownership remains with + * the caller. The ownership of data for kExternalTyped is passed to the VM on + * message send and returned when the VM invokes the + * Dart_HandleFinalizer callback; a non-NULL callback must be provided. + * + * Note that Dart_CObject_kNativePointer is intended for internal use by + * dart:io implementation and has no connection to dart:ffi Pointer class. + * It represents a pointer to a native resource of a known type. + * The receiving side will only see this pointer as an integer and will not + * see the specified finalizer. + * The specified finalizer will only be invoked if the message is not delivered. + */ +typedef enum { + Dart_CObject_kNull = 0, + Dart_CObject_kBool, + Dart_CObject_kInt32, + Dart_CObject_kInt64, + Dart_CObject_kDouble, + Dart_CObject_kString, + Dart_CObject_kArray, + Dart_CObject_kTypedData, + Dart_CObject_kExternalTypedData, + Dart_CObject_kSendPort, + Dart_CObject_kCapability, + Dart_CObject_kNativePointer, + Dart_CObject_kUnsupported, + Dart_CObject_kUnmodifiableExternalTypedData, + Dart_CObject_kNumberOfTypes +} Dart_CObject_Type; +// This enum is versioned by DART_API_DL_MAJOR_VERSION, only add at the end +// and bump the DART_API_DL_MINOR_VERSION. + +typedef struct _Dart_CObject { + Dart_CObject_Type type; + union { + bool as_bool; + int32_t as_int32; + int64_t as_int64; + double as_double; + const char* as_string; + struct { + Dart_Port id; + Dart_Port origin_id; + } as_send_port; + struct { + int64_t id; + } as_capability; + struct { + intptr_t length; + struct _Dart_CObject** values; + } as_array; + struct { + Dart_TypedData_Type type; + intptr_t length; /* in elements, not bytes */ + const uint8_t* values; + } as_typed_data; + struct { + Dart_TypedData_Type type; + intptr_t length; /* in elements, not bytes */ + uint8_t* data; + void* peer; + Dart_HandleFinalizer callback; + } as_external_typed_data; + struct { + intptr_t ptr; + intptr_t size; + Dart_HandleFinalizer callback; + } as_native_pointer; + } value; +} Dart_CObject; +// This struct is versioned by DART_API_DL_MAJOR_VERSION, bump the version when +// changing this struct. + +/** + * Posts a message on some port. The message will contain the Dart_CObject + * object graph rooted in 'message'. + * + * While the message is being sent the state of the graph of Dart_CObject + * structures rooted in 'message' should not be accessed, as the message + * generation will make temporary modifications to the data. When the message + * has been sent the graph will be fully restored. + * + * If true is returned, the message was enqueued, and finalizers for external + * typed data will eventually run, even if the receiving isolate shuts down + * before processing the message. If false is returned, the message was not + * enqueued and ownership of external typed data in the message remains with the + * caller. + * + * This function may be called on any thread when the VM is running (that is, + * after Dart_Initialize has returned and before Dart_Cleanup has been called). + * + * \param port_id The destination port. + * \param message The message to send. + * + * \return True if the message was posted. + */ +DART_EXPORT bool Dart_PostCObject(Dart_Port port_id, Dart_CObject* message); + +/** + * Posts a message on some port. The message will contain the integer 'message'. + * + * \param port_id The destination port. + * \param message The message to send. + * + * \return True if the message was posted. + */ +DART_EXPORT bool Dart_PostInteger(Dart_Port port_id, int64_t message); + +/** + * A native message handler. + * + * This handler is associated with a native port by calling + * Dart_NewNativePort. + * + * The message received is decoded into the message structure. The + * lifetime of the message data is controlled by the caller. All the + * data references from the message are allocated by the caller and + * will be reclaimed when returning to it. + */ +typedef void (*Dart_NativeMessageHandler)(Dart_Port dest_port_id, + Dart_CObject* message); + +/** + * Creates a new native port. When messages are received on this + * native port, then they will be dispatched to the provided native + * message handler. + * + * \param name The name of this port in debugging messages. + * \param handler The C handler to run when messages arrive on the port. + * \param handle_concurrently Is it okay to process requests on this + * native port concurrently? + * + * \return If successful, returns the port id for the native port. In + * case of error, returns ILLEGAL_PORT. + */ +DART_EXPORT Dart_Port Dart_NewNativePort(const char* name, + Dart_NativeMessageHandler handler, + bool handle_concurrently); +/* TODO(turnidge): Currently handle_concurrently is ignored. */ + +/** + * Closes the native port with the given id. + * + * The port must have been allocated by a call to Dart_NewNativePort. + * + * \param native_port_id The id of the native port to close. + * + * \return Returns true if the port was closed successfully. + */ +DART_EXPORT bool Dart_CloseNativePort(Dart_Port native_port_id); + +/* + * ================== + * Verification Tools + * ================== + */ + +/** + * Forces all loaded classes and functions to be compiled eagerly in + * the current isolate.. + * + * TODO(turnidge): Document. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_CompileAll(void); + +/** + * Finalizes all classes. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_FinalizeAllClasses(void); + +/* This function is intentionally undocumented. + * + * It should not be used outside internal tests. + */ +DART_EXPORT void* Dart_ExecuteInternalCommand(const char* command, void* arg); + +#endif /* INCLUDE_DART_NATIVE_API_H_ */ /* NOLINT */ diff --git a/pkgs/objective_c/src/include/dart_tools_api.h b/pkgs/objective_c/src/include/dart_tools_api.h new file mode 100644 index 000000000..c118bc46d --- /dev/null +++ b/pkgs/objective_c/src/include/dart_tools_api.h @@ -0,0 +1,627 @@ +// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +#ifndef RUNTIME_INCLUDE_DART_TOOLS_API_H_ +#define RUNTIME_INCLUDE_DART_TOOLS_API_H_ + +#include "dart_api.h" /* NOLINT */ + +/** \mainpage Dart Tools Embedding API Reference + * + * This reference describes the Dart embedding API for tools. Tools include + * a debugger, service protocol, and timeline. + * + * NOTE: The APIs described in this file are unstable and subject to change. + * + * This reference is generated from the header include/dart_tools_api.h. + */ + +/* + * ======== + * Debugger + * ======== + */ + +/** + * ILLEGAL_ISOLATE_ID is a number guaranteed never to be associated with a + * valid isolate. + */ +#define ILLEGAL_ISOLATE_ID ILLEGAL_PORT + +/** + * ILLEGAL_ISOLATE_GROUP_ID is a number guaranteed never to be associated with a + * valid isolate group. + */ +#define ILLEGAL_ISOLATE_GROUP_ID 0 + +/* + * ======= + * Service + * ======= + */ + +/** + * A service request callback function. + * + * These callbacks, registered by the embedder, are called when the VM receives + * a service request it can't handle and the service request command name + * matches one of the embedder registered handlers. + * + * The return value of the callback indicates whether the response + * should be used as a regular result or an error result. + * Specifically, if the callback returns true, a regular JSON-RPC + * response is built in the following way: + * + * { + * "jsonrpc": "2.0", + * "result": , + * "id": , + * } + * + * If the callback returns false, a JSON-RPC error is built like this: + * + * { + * "jsonrpc": "2.0", + * "error": , + * "id": , + * } + * + * \param method The rpc method name. + * \param param_keys Service requests can have key-value pair parameters. The + * keys and values are flattened and stored in arrays. + * \param param_values The values associated with the keys. + * \param num_params The length of the param_keys and param_values arrays. + * \param user_data The user_data pointer registered with this handler. + * \param result A C string containing a valid JSON object. The returned + * pointer will be freed by the VM by calling free. + * + * \return True if the result is a regular JSON-RPC response, false if the + * result is a JSON-RPC error. + */ +typedef bool (*Dart_ServiceRequestCallback)(const char* method, + const char** param_keys, + const char** param_values, + intptr_t num_params, + void* user_data, + const char** json_object); + +/** + * Register a Dart_ServiceRequestCallback to be called to handle + * requests for the named rpc on a specific isolate. The callback will + * be invoked with the current isolate set to the request target. + * + * \param method The name of the method that this callback is responsible for. + * \param callback The callback to invoke. + * \param user_data The user data passed to the callback. + * + * NOTE: If multiple callbacks with the same name are registered, only + * the last callback registered will be remembered. + */ +DART_EXPORT void Dart_RegisterIsolateServiceRequestCallback( + const char* method, + Dart_ServiceRequestCallback callback, + void* user_data); + +/** + * Register a Dart_ServiceRequestCallback to be called to handle + * requests for the named rpc. The callback will be invoked without a + * current isolate. + * + * \param method The name of the command that this callback is responsible for. + * \param callback The callback to invoke. + * \param user_data The user data passed to the callback. + * + * NOTE: If multiple callbacks with the same name are registered, only + * the last callback registered will be remembered. + */ +DART_EXPORT void Dart_RegisterRootServiceRequestCallback( + const char* method, + Dart_ServiceRequestCallback callback, + void* user_data); + +/** + * Embedder information which can be requested by the VM for internal or + * reporting purposes. + * + * The pointers in this structure are not going to be cached or freed by the VM. + */ + +#define DART_EMBEDDER_INFORMATION_CURRENT_VERSION (0x00000001) + +typedef struct { + int32_t version; + const char* name; // [optional] The name of the embedder + int64_t current_rss; // [optional] the current RSS of the embedder + int64_t max_rss; // [optional] the maximum RSS of the embedder +} Dart_EmbedderInformation; + +/** + * Callback provided by the embedder that is used by the VM to request + * information. + * + * \return Returns a pointer to a Dart_EmbedderInformation structure. + * The embedder keeps the ownership of the structure and any field in it. + * The embedder must ensure that the structure will remain valid until the + * next invocation of the callback. + */ +typedef void (*Dart_EmbedderInformationCallback)( + Dart_EmbedderInformation* info); + +/** + * Register a Dart_ServiceRequestCallback to be called to handle + * requests for the named rpc. The callback will be invoked without a + * current isolate. + * + * \param method The name of the command that this callback is responsible for. + * \param callback The callback to invoke. + * \param user_data The user data passed to the callback. + * + * NOTE: If multiple callbacks are registered, only the last callback registered + * will be remembered. + */ +DART_EXPORT void Dart_SetEmbedderInformationCallback( + Dart_EmbedderInformationCallback callback); + +/** + * Invoke a vm-service method and wait for its result. + * + * \param request_json The utf8-encoded json-rpc request. + * \param request_json_length The length of the json-rpc request. + * + * \param response_json The returned utf8-encoded json response, must be + * free()ed by caller. + * \param response_json_length The length of the returned json response. + * \param error An optional error, must be free()ed by caller. + * + * \return Whether the call was successfully performed. + * + * NOTE: This method does not need a current isolate and must not have the + * vm-isolate being the current isolate. It must be called after + * Dart_Initialize() and before Dart_Cleanup(). + */ +DART_EXPORT bool Dart_InvokeVMServiceMethod(uint8_t* request_json, + intptr_t request_json_length, + uint8_t** response_json, + intptr_t* response_json_length, + char** error); + +/* + * ======== + * Event Streams + * ======== + */ + +/** + * A callback invoked when the VM service gets a request to listen to + * some stream. + * + * \return Returns true iff the embedder supports the named stream id. + */ +typedef bool (*Dart_ServiceStreamListenCallback)(const char* stream_id); + +/** + * A callback invoked when the VM service gets a request to cancel + * some stream. + */ +typedef void (*Dart_ServiceStreamCancelCallback)(const char* stream_id); + +/** + * Adds VM service stream callbacks. + * + * \param listen_callback A function pointer to a listen callback function. + * A listen callback function should not be already set when this function + * is called. A NULL value removes the existing listen callback function + * if any. + * + * \param cancel_callback A function pointer to a cancel callback function. + * A cancel callback function should not be already set when this function + * is called. A NULL value removes the existing cancel callback function + * if any. + * + * \return Success if the callbacks were added. Otherwise, returns an + * error handle. + */ +DART_EXPORT char* Dart_SetServiceStreamCallbacks( + Dart_ServiceStreamListenCallback listen_callback, + Dart_ServiceStreamCancelCallback cancel_callback); + +/** + * Sends a data event to clients of the VM Service. + * + * A data event is used to pass an array of bytes to subscribed VM + * Service clients. For example, in the standalone embedder, this is + * function used to provide WriteEvents on the Stdout and Stderr + * streams. + * + * If the embedder passes in a stream id for which no client is + * subscribed, then the event is ignored. + * + * \param stream_id The id of the stream on which to post the event. + * + * \param event_kind A string identifying what kind of event this is. + * For example, 'WriteEvent'. + * + * \param bytes A pointer to an array of bytes. + * + * \param bytes_length The length of the byte array. + * + * \return NULL if the arguments are well formed. Otherwise, returns an + * error string. The caller is responsible for freeing the error message. + */ +DART_EXPORT char* Dart_ServiceSendDataEvent(const char* stream_id, + const char* event_kind, + const uint8_t* bytes, + intptr_t bytes_length); + +/* + * ======== + * Reload support + * ======== + * + * These functions are used to implement reloading in the Dart VM. + * This is an experimental feature, so embedders should be prepared + * for these functions to change. + */ + +/** + * A callback which determines whether the file at some url has been + * modified since some time. If the file cannot be found, true should + * be returned. + */ +typedef bool (*Dart_FileModifiedCallback)(const char* url, int64_t since); + +DART_EXPORT char* Dart_SetFileModifiedCallback( + Dart_FileModifiedCallback file_modified_callback); + +/** + * Returns true if isolate is currently reloading. + */ +DART_EXPORT bool Dart_IsReloading(); + +/* + * ======== + * Timeline + * ======== + */ + +/** + * Enable tracking of specified timeline category. This is operational + * only when systrace timeline functionality is turned on. + * + * \param categories A comma separated list of categories that need to + * be enabled, the categories are + * "all" : All categories + * "API" - Execution of Dart C API functions + * "Compiler" - Execution of Dart JIT compiler + * "CompilerVerbose" - More detailed Execution of Dart JIT compiler + * "Dart" - Execution of Dart code + * "Debugger" - Execution of Dart debugger + * "Embedder" - Execution of Dart embedder code + * "GC" - Execution of Dart Garbage Collector + * "Isolate" - Dart Isolate lifecycle execution + * "VM" - Execution in Dart VM runtime code + * "" - None + * + * When "all" is specified all the categories are enabled. + * When a comma separated list of categories is specified, the categories + * that are specified will be enabled and the rest will be disabled. + * When "" is specified all the categories are disabled. + * The category names are case sensitive. + * eg: Dart_EnableTimelineCategory("all"); + * Dart_EnableTimelineCategory("GC,API,Isolate"); + * Dart_EnableTimelineCategory("GC,Debugger,Dart"); + * + * \return True if the categories were successfully enabled, False otherwise. + */ +DART_EXPORT bool Dart_SetEnabledTimelineCategory(const char* categories); + +/** + * Returns a timestamp in microseconds. This timestamp is suitable for + * passing into the timeline system, and uses the same monotonic clock + * as dart:developer's Timeline.now. + * + * \return A timestamp that can be passed to the timeline system. + */ +DART_EXPORT int64_t Dart_TimelineGetMicros(); + +/** + * Returns a raw timestamp in from the monotonic clock. + * + * \return A raw timestamp from the monotonic clock. + */ +DART_EXPORT int64_t Dart_TimelineGetTicks(); + +/** + * Returns the frequency of the monotonic clock. + * + * \return The frequency of the monotonic clock. + */ +DART_EXPORT int64_t Dart_TimelineGetTicksFrequency(); + +typedef enum { + Dart_Timeline_Event_Begin, // Phase = 'B'. + Dart_Timeline_Event_End, // Phase = 'E'. + Dart_Timeline_Event_Instant, // Phase = 'i'. + Dart_Timeline_Event_Duration, // Phase = 'X'. + Dart_Timeline_Event_Async_Begin, // Phase = 'b'. + Dart_Timeline_Event_Async_End, // Phase = 'e'. + Dart_Timeline_Event_Async_Instant, // Phase = 'n'. + Dart_Timeline_Event_Counter, // Phase = 'C'. + Dart_Timeline_Event_Flow_Begin, // Phase = 's'. + Dart_Timeline_Event_Flow_Step, // Phase = 't'. + Dart_Timeline_Event_Flow_End, // Phase = 'f'. +} Dart_Timeline_Event_Type; + +/** + * Add a timeline event to the embedder stream. + * + * Note regarding flow events: events must be associated with flow IDs in two + * different ways to allow flow events to be serialized correctly in both + * Chrome's JSON trace event format and Perfetto's proto trace format. Events + * of type |Dart_Timeline_Event_Flow_Begin|, |Dart_Timeline_Event_Flow_Step|, + * and |Dart_Timeline_Event_Flow_End| must be reported to support serialization + * in Chrome's trace format. The |flow_ids| argument must be supplied when + * reporting events of type |Dart_Timeline_Event_Begin|, + * |Dart_Timeline_Event_Duration|, |Dart_Timeline_Event_Instant|, + * |Dart_Timeline_Event_Async_Begin|, and |Dart_Timeline_Event_Async_Instant| to + * support serialization in Perfetto's proto format. + * + * The Dart VM can use various underlying recorders depending on configuration + * and operating system. Many recorders do not support all event types; + * unsupported event types are siliently dropped. Some recorders do not accept + * timestamps as input, instead implicitly using the time the event is recorded. + * For maximum compatibility, record events with the Begin and End types as they + * occur instead of using the Duration type or buffering. + * + * \param label The name of the event. Its lifetime must extend at least until + * Dart_Cleanup. + * \param timestamp0 The first timestamp of the event. + * \param timestamp1_or_id When reporting an event of type + * |Dart_Timeline_Event_Duration|, the second (end) timestamp of the event + * should be passed through |timestamp1_or_id|. When reporting an event of + * type |Dart_Timeline_Event_Async_Begin|, |Dart_Timeline_Event_Async_End|, + * or |Dart_Timeline_Event_Async_Instant|, the async ID associated with the + * event should be passed through |timestamp1_or_id|. When reporting an + * event of type |Dart_Timeline_Event_Flow_Begin|, + * |Dart_Timeline_Event_Flow_Step|, or |Dart_Timeline_Event_Flow_End|, the + * flow ID associated with the event should be passed through + * |timestamp1_or_id|. When reporting an event of type + * |Dart_Timeline_Event_Begin| or |Dart_Timeline_Event_End|, the event ID + * associated with the event should be passed through |timestamp1_or_id|. + * Note that this event ID will only be used by the MacOS recorder. The + * argument to |timestamp1_or_id| will not be used when reporting events of + * other types. + * \param flow_id_count The number of flow IDs associated with this event. + * \param flow_ids An array of flow IDs associated with this event. The array + * may be reclaimed when this call returns. + * \param argument_count The number of argument names and values. + * \param argument_names An array of names of the arguments. The lifetime of the + * names must extend at least until Dart_Cleanup. The array may be reclaimed + * when this call returns. + * \param argument_values An array of values of the arguments. The values and + * the array may be reclaimed when this call returns. + */ +DART_EXPORT void Dart_RecordTimelineEvent(const char* label, + int64_t timestamp0, + int64_t timestamp1_or_id, + intptr_t flow_id_count, + const int64_t* flow_ids, + Dart_Timeline_Event_Type type, + intptr_t argument_count, + const char** argument_names, + const char** argument_values); + +/** + * Associates a name with the current thread. This name will be used to name + * threads in the timeline. Can only be called after a call to Dart_Initialize. + * + * \param name The name of the thread. + */ +DART_EXPORT void Dart_SetThreadName(const char* name); + +typedef struct { + const char* name; + const char* value; +} Dart_TimelineRecorderEvent_Argument; + +#define DART_TIMELINE_RECORDER_CURRENT_VERSION (0x00000002) + +typedef struct { + /* Set to DART_TIMELINE_RECORDER_CURRENT_VERSION */ + int32_t version; + + /* The event's type / phase. */ + Dart_Timeline_Event_Type type; + + /* The event's timestamp according to the same clock as + * Dart_TimelineGetMicros. For a duration event, this is the beginning time. + */ + int64_t timestamp0; + + /** + * For a duration event, this is the end time. For an async event, this is the + * async ID. For a flow event, this is the flow ID. For a begin or end event, + * this is the event ID (which is only referenced by the MacOS recorder). + */ + int64_t timestamp1_or_id; + + /* The current isolate of the event, as if by Dart_GetMainPortId, or + * ILLEGAL_PORT if the event had no current isolate. */ + Dart_Port isolate; + + /* The current isolate group of the event, as if by + * Dart_CurrentIsolateGroupId, or ILLEGAL_PORT if the event had no current + * isolate group. */ + Dart_IsolateGroupId isolate_group; + + /* The callback data associated with the isolate if any. */ + void* isolate_data; + + /* The callback data associated with the isolate group if any. */ + void* isolate_group_data; + + /* The name / label of the event. */ + const char* label; + + /* The stream / category of the event. */ + const char* stream; + + intptr_t argument_count; + Dart_TimelineRecorderEvent_Argument* arguments; +} Dart_TimelineRecorderEvent; + +/** + * Callback provided by the embedder to handle the completion of timeline + * events. + * + * \param event A timeline event that has just been completed. The VM keeps + * ownership of the event and any field in it (i.e., the embedder should copy + * any values it needs after the callback returns). + */ +typedef void (*Dart_TimelineRecorderCallback)( + Dart_TimelineRecorderEvent* event); + +/** + * Register a `Dart_TimelineRecorderCallback` to be called as timeline events + * are completed. + * + * The callback will be invoked without a current isolate. + * + * The callback will be invoked on the thread completing the event. Because + * `Dart_RecordTimelineEvent` may be called by any thread, the callback may be + * called on any thread. + * + * The callback may be invoked at any time after `Dart_Initialize` is called and + * before `Dart_Cleanup` returns. + * + * If multiple callbacks are registered, only the last callback registered + * will be remembered. Providing a NULL callback will clear the registration + * (i.e., a NULL callback produced a no-op instead of a crash). + * + * Setting a callback is insufficient to receive events through the callback. The + * VM flag `timeline_recorder` must also be set to `callback`. + */ +DART_EXPORT void Dart_SetTimelineRecorderCallback( + Dart_TimelineRecorderCallback callback); + +/* + * ======= + * Metrics + * ======= + */ + +/** + * Return metrics gathered for the VM and individual isolates. + */ +DART_EXPORT int64_t +Dart_IsolateGroupHeapOldUsedMetric(Dart_IsolateGroup group); // Byte +DART_EXPORT int64_t +Dart_IsolateGroupHeapOldCapacityMetric(Dart_IsolateGroup group); // Byte +DART_EXPORT int64_t +Dart_IsolateGroupHeapOldExternalMetric(Dart_IsolateGroup group); // Byte +DART_EXPORT int64_t +Dart_IsolateGroupHeapNewUsedMetric(Dart_IsolateGroup group); // Byte +DART_EXPORT int64_t +Dart_IsolateGroupHeapNewCapacityMetric(Dart_IsolateGroup group); // Byte +DART_EXPORT int64_t +Dart_IsolateGroupHeapNewExternalMetric(Dart_IsolateGroup group); // Byte + +/* + * ======== + * UserTags + * ======== + */ + +/* + * Gets the current isolate's currently set UserTag instance. + * + * \return The currently set UserTag instance. + */ +DART_EXPORT Dart_Handle Dart_GetCurrentUserTag(); + +/* + * Gets the current isolate's default UserTag instance. + * + * \return The default UserTag with label 'Default' + */ +DART_EXPORT Dart_Handle Dart_GetDefaultUserTag(); + +/* + * Creates a new UserTag instance. + * + * \param label The name of the new UserTag. + * + * \return The newly created UserTag instance or an error handle. + */ +DART_EXPORT Dart_Handle Dart_NewUserTag(const char* label); + +/* + * Updates the current isolate's UserTag to a new value. + * + * \param user_tag The UserTag to be set as the current UserTag. + * + * \return The previously set UserTag instance or an error handle. + */ +DART_EXPORT Dart_Handle Dart_SetCurrentUserTag(Dart_Handle user_tag); + +/* + * Returns the label of a given UserTag instance. + * + * \param user_tag The UserTag from which the label will be retrieved. + * + * \return The UserTag's label. NULL if the user_tag is invalid. The caller is + * responsible for freeing the returned label. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT char* Dart_GetUserTagLabel( + Dart_Handle user_tag); + +/* + * ======= + * Heap Snapshot + * ======= + */ + +/** + * Callback provided by the caller of `Dart_WriteHeapSnapshot` which is + * used to write out chunks of the requested heap snapshot. + * + * \param context An opaque context which was passed to `Dart_WriteHeapSnapshot` + * together with this callback. + * + * \param buffer Pointer to the buffer containing a chunk of the snapshot. + * The callback owns the buffer and needs to `free` it. + * + * \param size Number of bytes in the `buffer` to be written. + * + * \param is_last Set to `true` for the last chunk. The callback will not + * be invoked again after it was invoked once with `is_last` set to `true`. + */ +typedef void (*Dart_HeapSnapshotWriteChunkCallback)(void* context, + uint8_t* buffer, + intptr_t size, + bool is_last); + +/** + * Generate heap snapshot of the current isolate group and stream it into the + * given `callback`. VM would produce snapshot in chunks and send these chunks + * one by one back to the embedder by invoking the provided `callback`. + * + * This API enables embedder to stream snapshot into a file or socket without + * allocating a buffer to hold the whole snapshot in memory. + * + * The isolate group will be paused for the duration of this operation. + * + * \param write Callback used to write chunks of the heap snapshot. + * + * \param context Opaque context which would be passed on each invocation of + * `write` callback. + * + * \returns `nullptr` if the operation is successful otherwise error message. + * Caller owns error message string and needs to `free` it. + */ +DART_EXPORT char* Dart_WriteHeapSnapshot( + Dart_HeapSnapshotWriteChunkCallback write, + void* context); + +#endif // RUNTIME_INCLUDE_DART_TOOLS_API_H_ diff --git a/pkgs/objective_c/src/include/dart_version.h b/pkgs/objective_c/src/include/dart_version.h new file mode 100644 index 000000000..cb343c0d3 --- /dev/null +++ b/pkgs/objective_c/src/include/dart_version.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file + * for details. All rights reserved. Use of this source code is governed by a + * BSD-style license that can be found in the LICENSE file. + */ + +#ifndef RUNTIME_INCLUDE_DART_VERSION_H_ +#define RUNTIME_INCLUDE_DART_VERSION_H_ + +// On breaking changes the major version is increased. +// On backwards compatible changes the minor version is increased. +// The versioning covers the symbols exposed in dart_api_dl.h +#define DART_API_DL_MAJOR_VERSION 2 +#define DART_API_DL_MINOR_VERSION 4 + +#endif /* RUNTIME_INCLUDE_DART_VERSION_H_ */ /* NOLINT */ diff --git a/pkgs/objective_c/src/include/internal/dart_api_dl_impl.h b/pkgs/objective_c/src/include/internal/dart_api_dl_impl.h new file mode 100644 index 000000000..e4a568931 --- /dev/null +++ b/pkgs/objective_c/src/include/internal/dart_api_dl_impl.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file + * for details. All rights reserved. Use of this source code is governed by a + * BSD-style license that can be found in the LICENSE file. + */ + +#ifndef RUNTIME_INCLUDE_INTERNAL_DART_API_DL_IMPL_H_ +#define RUNTIME_INCLUDE_INTERNAL_DART_API_DL_IMPL_H_ + +typedef struct { + const char* name; + void (*function)(void); +} DartApiEntry; + +typedef struct { + const int major; + const int minor; + const DartApiEntry* const functions; +} DartApi; + +#endif /* RUNTIME_INCLUDE_INTERNAL_DART_API_DL_IMPL_H_ */ /* NOLINT */ diff --git a/pkgs/objective_c/src/objective_c.c b/pkgs/objective_c/src/objective_c.c index 2b31b25a0..85bc0bc58 100644 --- a/pkgs/objective_c/src/objective_c.c +++ b/pkgs/objective_c/src/objective_c.c @@ -2,4 +2,12 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +#include "include/dart_api_dl.h" #include "objective_c.h" +#include "objective_c_runtime_types.h" + +// Dispose helper for ObjC blocks that wrap a Dart closure. For these blocks, +// the target is an int ID, and the dispose_port is listening for these IDs. +void disposeObjCBlockWithClosure(ObjCBlock* block) { + Dart_PostInteger_DL(block->dispose_port, (int64_t)block->target); +} diff --git a/pkgs/objective_c/src/objective_c.h b/pkgs/objective_c/src/objective_c.h index 72f84ea5f..cfa43a640 100644 --- a/pkgs/objective_c/src/objective_c.h +++ b/pkgs/objective_c/src/objective_c.h @@ -2,4 +2,12 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -#include "objective_c_runtime.h" +#ifndef OBJECTIVE_C_SRC_OBJECTIVE_C_H_ +#define OBJECTIVE_C_SRC_OBJECTIVE_C_H_ + +#include "objective_c_runtime_types.h" + +// Dispose helper for ObjC blocks that wrap a Dart closure. +void disposeObjCBlockWithClosure(ObjCBlock* block); + +#endif // OBJECTIVE_C_SRC_OBJECTIVE_C_H_ diff --git a/pkgs/objective_c/src/objective_c_runtime_functions.h b/pkgs/objective_c/src/objective_c_runtime_functions.h new file mode 100644 index 000000000..0df7ddfea --- /dev/null +++ b/pkgs/objective_c/src/objective_c_runtime_functions.h @@ -0,0 +1,31 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// This file exposes a subset of the Objective C runtime. Ideally we'd just run +// ffigen directly on the runtime headers that come with XCode, but those +// headers don't have everything we need (e.g. the ObjCBlock struct). + +#ifndef OBJECTIVE_C_SRC_OBJECTIVE_C_RUNTIME_FUNCTIONS_H_ +#define OBJECTIVE_C_SRC_OBJECTIVE_C_RUNTIME_FUNCTIONS_H_ + +#include "include/dart_api_dl.h" +#include "objective_c_runtime_types.h" + +ObjCSelector* sel_registerName(const char *name); +ObjCObject* objc_getClass(const char *name); +ObjCObject* objc_retain(ObjCObject* object); +void objc_release(ObjCObject* object); + +// The signature of this function is just a placeholder. This function is used by +// every method invocation, and is cast to every signature we need. +void objc_msgSend(); +void objc_msgSend_fpret(); +void objc_msgSend_stret(); + +extern void* const _NSConcreteGlobalBlock; + +ObjCBlock* _Block_copy(ObjCBlock* object); +void _Block_release(ObjCBlock* object); + +#endif // OBJECTIVE_C_SRC_OBJECTIVE_C_RUNTIME_FUNCTIONS_H_ diff --git a/pkgs/objective_c/src/objective_c_runtime.h b/pkgs/objective_c/src/objective_c_runtime_types.h similarity index 67% rename from pkgs/objective_c/src/objective_c_runtime.h rename to pkgs/objective_c/src/objective_c_runtime_types.h index 15c778335..0499da5e4 100644 --- a/pkgs/objective_c/src/objective_c_runtime.h +++ b/pkgs/objective_c/src/objective_c_runtime_types.h @@ -6,19 +6,13 @@ // ffigen directly on the runtime headers that come with XCode, but those // headers don't have everything we need (e.g. the ObjCBlock struct). -typedef struct _ObjCSelector ObjCSelector; -typedef struct _ObjCObject ObjCObject; +#ifndef OBJECTIVE_C_SRC_OBJECTIVE_C_RUNTIME_TYPES_H_ +#define OBJECTIVE_C_SRC_OBJECTIVE_C_RUNTIME_TYPES_H_ -ObjCSelector* sel_registerName(const char *name); -ObjCObject* objc_getClass(const char *name); -ObjCObject* objc_retain(ObjCObject* object); -void objc_release(ObjCObject* object); +#include "include/dart_api_dl.h" -// The signature of this function is just a placeholder. This function is used by -// every method invocation, and is cast to every signature we need. -void objc_msgSend(); -void objc_msgSend_fpret(); -void objc_msgSend_stret(); +typedef struct _ObjCSelector ObjCSelector; +typedef struct _ObjCObject ObjCObject; // See https://clang.llvm.org/docs/Block-ABI-Apple.html typedef struct _ObjCBlockDesc { @@ -29,8 +23,6 @@ typedef struct _ObjCBlockDesc { const char *signature; } ObjCBlockDesc; -extern void* const _NSConcreteGlobalBlock; - typedef struct _ObjCBlock { void *isa; // _NSConcreteGlobalBlock int flags; @@ -40,7 +32,7 @@ typedef struct _ObjCBlock { // Captured variables follow. These are specific to our use case. void* target; + Dart_Port dispose_port; } ObjCBlock; -ObjCBlock* _Block_copy(ObjCBlock* object); -void _Block_release(ObjCBlock* object); +#endif // OBJECTIVE_C_SRC_OBJECTIVE_C_RUNTIME_TYPES_H_ diff --git a/pkgs/objective_c/test/nsdata_test.dart b/pkgs/objective_c/test/nsdata_test.dart index cd4fb80d4..c2b07c9ed 100644 --- a/pkgs/objective_c/test/nsdata_test.dart +++ b/pkgs/objective_c/test/nsdata_test.dart @@ -13,6 +13,11 @@ import 'package:test/test.dart'; void main() { group('NSData', () { + setUpAll(() { + // TODO(https://github.com/dart-lang/native/issues/1068): Remove this. + DynamicLibrary.open('test/objective_c.dylib'); + }); + group('toNSData', () { test('empty', () { final data = [].toNSData(); diff --git a/pkgs/objective_c/test/nsstring_test.dart b/pkgs/objective_c/test/nsstring_test.dart index 198ba02d7..78714b8ce 100644 --- a/pkgs/objective_c/test/nsstring_test.dart +++ b/pkgs/objective_c/test/nsstring_test.dart @@ -5,11 +5,18 @@ // Objective C support is only available on mac. @TestOn('mac-os') +import 'dart:ffi'; + import 'package:objective_c/objective_c.dart'; import 'package:test/test.dart'; void main() { group('NSString', () { + setUpAll(() { + // TODO(https://github.com/dart-lang/native/issues/1068): Remove this. + DynamicLibrary.open('test/objective_c.dylib'); + }); + for (final s in ['Hello', '🇵🇬', 'Embedded\u0000Null']) { test('NSString to/from Dart string [$s]', () { final ns1 = NSString(s); diff --git a/pkgs/objective_c/test/setup.dart b/pkgs/objective_c/test/setup.dart new file mode 100644 index 000000000..441dc7fb2 --- /dev/null +++ b/pkgs/objective_c/test/setup.dart @@ -0,0 +1,46 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// When users import package:objective_c as a plugin, Flutter builds our native +// code automatically. But we want to be able to run tests using `dart test`, so +// we can't use Flutter's build system. So this script builds a dylib containing +// all that native code. + +// ignore_for_file: avoid_print + +import 'dart:ffi'; +import 'dart:io'; + +const inputFiles = ['src/objective_c.c', 'src/include/dart_api_dl.c']; +const outputFile = 'test/objective_c.dylib'; + +void _buildLib(List inputs, String output) { + final args = [ + '-shared', + '-fpic', + ...inputs, + '-I', + 'src', + '-o', + output, + ]; + const exec = 'clang'; + print('Running: $exec ${args.join(" ")}'); + final proc = Process.runSync(exec, args); + if (proc.exitCode != 0) { + exitCode = proc.exitCode; + print(proc.stdout); + print(proc.stderr); + throw Exception('Command failed: $exec ${args.join(" ")}'); + } + print('Generated $output'); +} + +void main() { + Directory.current = Platform.script.resolve('..').path; + _buildLib(inputFiles, outputFile); + + // Sanity check that the dylib was created correctly. + DynamicLibrary.open(outputFile).lookup('disposeObjCBlockWithClosure'); +}