Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main' into stream
Browse files Browse the repository at this point in the history
  • Loading branch information
brianquinlan committed Sep 26, 2024
2 parents 55788d7 + 46527a8 commit 6c6383d
Show file tree
Hide file tree
Showing 272 changed files with 14,809 additions and 11,439 deletions.
18 changes: 18 additions & 0 deletions .github/workflows/ffigen.yml
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,24 @@ jobs:
github-token: ${{ secrets.GITHUB_TOKEN }}
parallel-finished: true

test-mac-flutter:
needs: analyze
runs-on: 'macos-latest'
defaults:
run:
working-directory: pkgs/ffigen/
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
- uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1
with:
channel: 'stable'
- name: Install dependencies
run: flutter pub get
- name: Build test dylib and bindings
run: dart test/setup.dart
- name: Run Flutter tests
run: flutter test

test-windows:
needs: analyze
runs-on: windows-latest
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ffigen_weekly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,4 @@ jobs:
- name: Build test dylib and bindings
run: dart test/setup.dart
- name: Run VM tests
run: dart test
run: flutter test
22 changes: 11 additions & 11 deletions .github/workflows/jnigen.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ jobs:
- uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018
with:
distribution: 'zulu'
java-version: '11'
java-version: '17'
cache: maven
## Committed bindings are formatted with clang-format.
## So this is required to format generated bindings identically
Expand Down Expand Up @@ -135,7 +135,7 @@ jobs:
- uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018
with:
distribution: 'zulu'
java-version: '11'
java-version: '17'
- uses: axel-op/googlejavaformat-action@fe78db8a90171b6a836449f8d0e982d5d71e5c5a
name: 'Check Java formatting with google-java-format'
with:
Expand Down Expand Up @@ -173,7 +173,7 @@ jobs:
- uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018
with:
distribution: 'zulu'
java-version: '11'
java-version: '17'
- run: |
sudo apt-get update -y
sudo apt-get install -y ninja-build libgtk-3-dev libclang-dev
Expand Down Expand Up @@ -222,7 +222,7 @@ jobs:
- uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018
with:
distribution: 'zulu'
java-version: '11'
java-version: '17'
- run: Add-Content $env:GITHUB_PATH "$env:JAVA_HOME\bin\server"
- run: dart pub get
- run: dart run jni:setup
Expand All @@ -249,7 +249,7 @@ jobs:
- uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018
with:
distribution: 'zulu'
java-version: '11'
java-version: '17'
- run: git config --global core.autocrlf true
- run: Add-Content $env:GITHUB_PATH "$env:JAVA_HOME\bin\server"
- run: dart pub get
Expand All @@ -275,7 +275,7 @@ jobs:
- uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018
with:
distribution: 'temurin'
java-version: '11'
java-version: '17'
- run: dart pub get
- run: dart run jni:setup
- run: dart test --test-randomize-ordering-seed random
Expand All @@ -300,7 +300,7 @@ jobs:
- uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018
with:
distribution: 'temurin'
java-version: '11'
java-version: '17'
- run: git config --global core.autocrlf true
- run: dart pub get
- name: Build summarizer
Expand All @@ -323,7 +323,7 @@ jobs:
- uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018
with:
distribution: 'zulu'
java-version: '11'
java-version: '17'
- run: |
sudo apt-get update -y
sudo apt-get install -y ninja-build libgtk-3-dev
Expand All @@ -347,7 +347,7 @@ jobs:
- uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018
with:
distribution: 'zulu'
java-version: '11'
java-version: '17'
- run: flutter config --enable-windows-desktop
- run: flutter pub get
- run: flutter build windows
Expand All @@ -362,7 +362,7 @@ jobs:
- uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018
with:
distribution: 'zulu'
java-version: '11'
java-version: '17'
- uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1
with:
channel: 'stable'
Expand All @@ -386,7 +386,7 @@ jobs:
- uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018
with:
distribution: 'zulu'
java-version: '11'
java-version: '17'
- run: |
sudo apt-get update -y
sudo apt-get install -y ninja-build libgtk-3-dev clang-format
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/native.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,6 @@ jobs:
- run: dart pub get -C test_data/native_add_duplicate/
if: ${{ matrix.package == 'native_assets_builder' }}

- run: dart pub get -C test_data/native_add_v1_0_0/
if: ${{ matrix.package == 'native_assets_builder' }}

- run: dart pub get -C test_data/native_add_add_source/
if: ${{ matrix.package == 'native_assets_builder' }}

Expand Down Expand Up @@ -96,6 +93,9 @@ jobs:
- run: dart pub get -C test_data/add_asset_link/
if: ${{ matrix.package == 'native_assets_builder' }}

- run: dart pub get -C test_data/transformer/
if: ${{ matrix.package == 'native_assets_builder' }}

- run: dart pub get -C test_data/treeshaking_native_libs/
if: ${{ matrix.package == 'native_assets_builder' }}

Expand Down
13 changes: 12 additions & 1 deletion pkgs/ffigen/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
## 15.0.0-wip

- Dedupe `ObjCBlock` trampolines to reduce generated ObjC code.
- Update to latest `package:objective_c`.
- ObjC objects now include the methods from the protocols they implement. Both
required and optional methods are included. Optional methods will throw an
exception if the method isn't implemented.
- __Breaking change__: Only generate ObjC protocol implementation bindings for
protocols that are included by the config filters. This is breaking because
previously super protocols would automatically get implementation bindings,
rather than just being incorporated into the child protocol. If you want those
implementation bindings, you may need to add the super protocol to your
`objc-protocols` filters.
- Fix a bug where ObjC listener blocks could be deleted after being invoked by
ObjC but before the invocation was received by Dart:
https://github.com/dart-lang/native/issues/1571

## 14.0.1

Expand Down
72 changes: 43 additions & 29 deletions pkgs/ffigen/lib/src/code_generator/objc_block.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,16 @@ class ObjCBlock extends BindingType {
required bool returnsRetained,
required ObjCBuiltInFunctions builtInFunctions,
}) {
final usr = _getBlockUsr(returnType, params, returnsRetained);
final renamedParams = [
for (var i = 0; i < params.length; ++i)
Parameter(
name: 'arg$i',
type: params[i].type,
objCConsumed: params[i].objCConsumed,
),
];

final usr = _getBlockUsr(returnType, renamedParams, returnsRetained);

final oldBlock = bindingsIndex.getSeenObjCBlock(usr);
if (oldBlock != null) {
Expand All @@ -30,9 +39,9 @@ class ObjCBlock extends BindingType {

final block = ObjCBlock._(
usr: usr,
name: _getBlockName(returnType, params.map((a) => a.type)),
name: _getBlockName(returnType, renamedParams.map((a) => a.type)),
returnType: returnType,
params: params,
params: renamedParams,
returnsRetained: returnsRetained,
builtInFunctions: builtInFunctions,
);
Expand Down Expand Up @@ -103,11 +112,18 @@ class ObjCBlock extends BindingType {
w.topLevelUniqueNamer.makeUnique('_${name}_fnPtrTrampoline');
final closureTrampoline =
w.topLevelUniqueNamer.makeUnique('_${name}_closureTrampoline');
final funcPtrCallable =
w.topLevelUniqueNamer.makeUnique('_${name}_fnPtrCallable');
final closureCallable =
w.topLevelUniqueNamer.makeUnique('_${name}_closureCallable');
final listenerCallable =
w.topLevelUniqueNamer.makeUnique('_${name}_listenerCallable');
final callExtension =
w.topLevelUniqueNamer.makeUnique('${name}_CallExtension');
final newPointerBlock = ObjCBuiltInFunctions.newPointerBlock.gen(w);
final newClosureBlock = ObjCBuiltInFunctions.newClosureBlock.gen(w);
final getBlockClosure = ObjCBuiltInFunctions.getBlockClosure.gen(w);
final releaseFn = ObjCBuiltInFunctions.objectRelease.gen(w);
final trampFuncType = FunctionType(returnType: returnType, parameters: [
Parameter(type: blockPtr, name: 'block', objCConsumed: false),
...params
Expand All @@ -124,6 +140,8 @@ class ObjCBlock extends BindingType {
final returnFfiDartType = returnType.getFfiDartType(w);
final blockCType = blockPtr.getCType(w);
final blockType = _blockType(w);
final defaultValue = returnType.getDefaultValue(w);
final exceptionalReturn = defaultValue == null ? '' : ', $defaultValue';

final paramsNameOnly = params.map((p) => p.name).join(', ');
final paramsFfiDartType =
Expand All @@ -136,13 +154,28 @@ class ObjCBlock extends BindingType {
$returnFfiDartType $funcPtrTrampoline($blockCType block, $paramsFfiDartType) =>
block.ref.target.cast<${natFnType.getFfiDartType(w)}>()
.asFunction<$funcFfiDartType>()($paramsNameOnly);
$voidPtr $funcPtrCallable = ${w.ffiLibraryPrefix}.Pointer.fromFunction<
$trampFuncCType>($funcPtrTrampoline $exceptionalReturn).cast();
''');

// Write the closure based trampoline function.
s.write('''
$returnFfiDartType $closureTrampoline($blockCType block, $paramsFfiDartType) =>
($getBlockClosure(block) as $funcFfiDartType)($paramsNameOnly);
$voidPtr $closureCallable = ${w.ffiLibraryPrefix}.Pointer.fromFunction<
$trampFuncCType>($closureTrampoline $exceptionalReturn).cast();
''');

if (hasListener) {
// Write the listener trampoline function.
s.write('''
$nativeCallableType $listenerCallable = $nativeCallableType.listener(
($blockCType block, $paramsFfiDartType) {
($getBlockClosure(block) as $funcFfiDartType)($paramsNameOnly);
$releaseFn(block.cast());
} $exceptionalReturn)..keepIsolateAlive = false;
''');
}

// Snippet that converts a Dart typed closure to FfiDart type. This snippet
// is used below. Note that the closure being converted is called `fn`.
Expand All @@ -162,8 +195,6 @@ $returnFfiDartType $closureTrampoline($blockCType block, $paramsFfiDartType) =>
final convFn = '($paramsFfiDartType) => $convFnInvocation';

// Write the wrapper class.
final defaultValue = returnType.getDefaultValue(w);
final exceptionalReturn = defaultValue == null ? '' : ', $defaultValue';
s.write('''
/// Construction methods for `$blockType`.
Expand All @@ -179,24 +210,17 @@ abstract final class $name {
/// the isolate that registered it. Invoking the block on the wrong thread
/// will result in a crash.
static $blockType fromFunctionPointer($natFnPtr ptr) =>
$blockType($newPointerBlock(
_cFuncTrampoline ??= ${w.ffiLibraryPrefix}.Pointer.fromFunction<
$trampFuncCType>($funcPtrTrampoline
$exceptionalReturn).cast(), ptr.cast()),
$blockType($newPointerBlock($funcPtrCallable, ptr.cast()),
retain: false, release: true);
static $voidPtr? _cFuncTrampoline;
/// Creates a block from a Dart function.
///
/// This block must be invoked by native code running on the same thread as
/// the isolate that registered it. Invoking the block on the wrong thread
/// will result in a crash.
static $blockType fromFunction($funcDartType fn) =>
$blockType($newClosureBlock(
_dartFuncTrampoline ??= ${w.ffiLibraryPrefix}.Pointer.fromFunction<
$trampFuncCType>($closureTrampoline $exceptionalReturn).cast(),
$convFn), retain: false, release: true);
static $voidPtr? _dartFuncTrampoline;
$blockType($newClosureBlock($closureCallable, $convFn),
retain: false, release: true);
''');

// Listener block constructor is only available for void blocks.
Expand All @@ -216,8 +240,7 @@ abstract final class $name {
);
final listenerConvFn =
'($paramsFfiDartType) => $listenerConvFnInvocation';
final wrapFn = _wrapListenerBlock?.func.name;
final releaseFn = ObjCBuiltInFunctions.objectRelease.gen(w);
final wrapFn = _wrapListenerBlock!.func.name;

s.write('''
Expand All @@ -232,21 +255,11 @@ abstract final class $name {
/// blocks do not keep the isolate alive.
static $blockType listener($funcDartType fn) {
final raw = $newClosureBlock(
(_dartFuncListenerTrampoline ??= $nativeCallableType.listener(
$closureTrampoline $exceptionalReturn)..keepIsolateAlive =
false).nativeFunction.cast(), $listenerConvFn);''');
if (wrapFn != null) {
s.write('''
$listenerCallable.nativeFunction.cast(), $listenerConvFn);
final wrapper = $wrapFn(raw);
$releaseFn(raw.cast());
return $blockType(wrapper, retain: false, release: true);''');
} else {
s.write('''
return $blockType(raw, retain: false, release: true);''');
}
s.write('''
return $blockType(wrapper, retain: false, release: true);
}
static $nativeCallableType? _dartFuncListenerTrampoline;
''');
}
s.write('}\n\n');
Expand Down Expand Up @@ -303,6 +316,7 @@ ref.pointer.ref.invoke.cast<$natTrampFnType>().asFunction<$trampFuncFfiDartType>
typedef $blockTypedef;
$blockName $fnName($blockName block) NS_RETURNS_RETAINED {
return ^void($argStr) {
${generateRetain('block')};
block(${retains.join(', ')});
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class ObjCBuiltInFunctions {
static const msgSendFpretPointer = ObjCImport('msgSendFpretPointer');
static const msgSendStretPointer = ObjCImport('msgSendStretPointer');
static const useMsgSendVariants = ObjCImport('useMsgSendVariants');
static const respondsToSelector = ObjCImport('respondsToSelector');
static const newPointerBlock = ObjCImport('newPointerBlock');
static const newClosureBlock = ObjCImport('newClosureBlock');
static const getBlockClosure = ObjCImport('getBlockClosure');
Expand All @@ -37,6 +38,8 @@ class ObjCBuiltInFunctions {
ObjCImport('ObjCProtocolListenableMethod');
static const protocolBuilder = ObjCImport('ObjCProtocolBuilder');
static const dartProxy = ObjCImport('DartProxy');
static const unimplementedOptionalMethodException =
ObjCImport('UnimplementedOptionalMethodException');

// Keep in sync with pkgs/objective_c/ffigen_objc.yaml.
static const builtInInterfaces = {
Expand Down Expand Up @@ -145,21 +148,16 @@ class ObjCBuiltInFunctions {
ObjCListenerBlockTrampoline? getListenerBlockTrampoline(ObjCBlock block) {
assert(!_depsAdded);

var needsTrampoline = false;
final paramIds = <String>[];
for (final param in block.params) {
final retainFunc = param.type.generateRetain('');
if (retainFunc != null) {
needsTrampoline = true;
}

// The trampoline ID is based on the getNativeType of the param. Objects
// and blocks both have `id` as their native type, but need separate
// trampolines since they have different retain functions. So add the
// retainFunc (if any) to all the param IDs.
paramIds.add('${param.getNativeType()}-${retainFunc ?? ''}');
}
if (!needsTrampoline) return null;
final id = paramIds.join(',');

return _blockTrampolines[id] ??= ObjCListenerBlockTrampoline(Func(
Expand Down
Loading

0 comments on commit 6c6383d

Please sign in to comment.