Skip to content

Commit

Permalink
[ffigen] Prepare to publish v15.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
liamappelbe committed Oct 11, 2024
1 parent 9836208 commit 7ad50c2
Show file tree
Hide file tree
Showing 19 changed files with 191 additions and 53 deletions.
2 changes: 1 addition & 1 deletion pkgs/ffigen/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## 15.0.0-wip
## 15.0.0

- Bump minimum Dart version to 3.4.
- Dedupe `ObjCBlock` trampolines to reduce generated ObjC code.
Expand Down
2 changes: 1 addition & 1 deletion pkgs/ffigen/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# BSD-style license that can be found in the LICENSE file.

name: ffigen
version: 15.0.0-wip
version: 15.0.0
description: >
Generator for FFI bindings, using LibClang to parse C, Objective-C, and Swift
files.
Expand Down
1 change: 0 additions & 1 deletion pkgs/ffigen/test/native_objc_test/arc_test.m
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#import <Foundation/NSThread.h>

#include "arc_test.h"
#include "util.h"

#if !__has_feature(objc_arc)
#error "This file must be compiled with ARC enabled"
Expand Down
1 change: 0 additions & 1 deletion pkgs/ffigen/test/native_objc_test/block_annotation_test.m
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#include <stdio.h>

#include "block_annotation_test.h"
#include "util.h"

@implementation EmptyObject
@end
Expand Down
1 change: 0 additions & 1 deletion pkgs/ffigen/test/native_objc_test/block_test.m
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
#import <Foundation/NSThread.h>

#include "block_test.h"
#include "util.h"

@implementation DummyObject

Expand Down
1 change: 0 additions & 1 deletion pkgs/ffigen/test/native_objc_test/global_native_test.m
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#import <Foundation/NSObject.h>

#include "global_test.h"
#include "util.h"

NSString* globalNativeString = @"Hello World";
NSObject* _Nullable globalNativeObject = nil;
Expand Down
1 change: 0 additions & 1 deletion pkgs/ffigen/test/native_objc_test/global_test.m
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#import <Foundation/NSObject.h>

#include "global_test.h"
#include "util.h"

NSString* globalString = @"Hello World";
NSObject* _Nullable globalObject = nil;
Expand Down
1 change: 0 additions & 1 deletion pkgs/ffigen/test/native_objc_test/isolate_test.m
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.

#include "isolate_test.h"
#include "util.h"

@implementation Sendable
@end
1 change: 0 additions & 1 deletion pkgs/ffigen/test/native_objc_test/protocol_test.m
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#import <dispatch/dispatch.h>

#include "protocol_test.h"
#include "util.h"

@implementation ProtocolConsumer : NSObject
- (NSString*)callInstanceMethod:(id<MyProtocol>)protocol {
Expand Down
2 changes: 0 additions & 2 deletions pkgs/ffigen/test/native_objc_test/ref_count_test.m
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
#import <Foundation/NSObject.h>
#import <Foundation/NSAutoreleasePool.h>

#include "util.h"

#if __has_feature(objc_arc)
#error "This file must be compiled with ARC disabled"
#endif
Expand Down
2 changes: 0 additions & 2 deletions pkgs/ffigen/test/native_objc_test/static_func_test.m
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

#import <Foundation/NSString.h>

#include "util.h"

void *objc_autoreleasePoolPush();
void objc_autoreleasePoolPop(void *pool);

Expand Down
8 changes: 4 additions & 4 deletions pkgs/ffigen/test/native_objc_test/util.dart
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,15 @@ Future<void> flutterDoGC() async {
await Future<void>.delayed(Duration(milliseconds: 500));
}

@Native<Bool Function(Pointer<Void>)>(isLeaf: true, symbol: 'isReadableMemory')
external bool _isReadableMemory(Pointer<Void> ptr);
@Native<Int Function(Pointer<Void>)>(isLeaf: true, symbol: 'isReadableMemory')
external int _isReadableMemory(Pointer<Void> ptr);

@Native<Uint64 Function(Pointer<Void>)>(
isLeaf: true, symbol: 'getBlockRetainCount')
external int _getBlockRetainCount(Pointer<Void> block);

int blockRetainCount(Pointer<ObjCBlockImpl> block) {
if (!_isReadableMemory(block.cast())) return 0;
if (_isReadableMemory(block.cast()) == 0) return 0;
if (!internal_for_testing.isValidBlock(block)) return 0;
return _getBlockRetainCount(block.cast());
}
Expand All @@ -71,7 +71,7 @@ int blockRetainCount(Pointer<ObjCBlockImpl> block) {
external int _getObjectRetainCount(Pointer<Void> object);

int objectRetainCount(Pointer<ObjCObject> object) {
if (!_isReadableMemory(object.cast())) return 0;
if (_isReadableMemory(object.cast()) == 0) return 0;
final header = object.cast<Uint64>().value;

// package:objective_c's isValidObject function internally calls
Expand Down
2 changes: 1 addition & 1 deletion pkgs/objective_c/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## 3.0.0-wip
## 3.0.0

- Add the following stream-related types to the core package:
- `NSInputStream`
Expand Down
5 changes: 5 additions & 0 deletions pkgs/objective_c/lib/src/ns_input_stream.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,26 @@ extension NSInputStreamStreamExtension on Stream<List<int>> {
late final StreamSubscription<dynamic> dataSubscription;

dataSubscription = listen((data) {
print("NSInputStream: 0");
if (inputStream.addData_(data.toNSData()) > maxReadAheadSize) {
dataSubscription.pause();
}
}, onError: (Object e) {
print("NSInputStream: 1 $e");
final d = NSMutableDictionary.new1();
d.setObject_forKey_(e.toString().toNSString(), NSLocalizedDescriptionKey);
inputStream.setError_(NSError.errorWithDomain_code_userInfo_(
'DartError'.toNSString(), 0, d));
port.close();
}, onDone: () {
print("NSInputStream: 2");
inputStream.setDone();
port.close();
}, cancelOnError: true);

dataSubscription.pause();
port.listen((count) {
print("NSInputStream: 3 $count");
// -1 indicates that the `NSInputStream` is closed. All other values
// indicate that the `NSInputStream` needs more data.
if (count == -1) {
Expand All @@ -49,6 +53,7 @@ extension NSInputStreamStreamExtension on Stream<List<int>> {
dataSubscription.resume();
}
}, onDone: () {
print("NSInputStream: 4");
dataSubscription.cancel();
});

Expand Down
2 changes: 1 addition & 1 deletion pkgs/objective_c/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

name: objective_c
description: 'A library to access Objective C from Flutter that acts as a support library for package:ffigen.'
version: 3.0.0-wip
version: 3.0.0
repository: https://github.com/dart-lang/native/tree/main/pkgs/objective_c

topics:
Expand Down
131 changes: 106 additions & 25 deletions pkgs/objective_c/test/ns_input_stream_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import 'package:objective_c/objective_c.dart';
import 'package:objective_c/src/objective_c_bindings_generated.dart';
import 'package:test/test.dart';

import 'util.dart';

Future<(int, Uint8List, bool, NSStreamStatus, NSError?)> read(
NSInputStream stream, int size) async {
// TODO(https://github.com/dart-lang/tools/issues/520):
Expand Down Expand Up @@ -242,38 +244,117 @@ void main() {
'localizedDescription', contains('some exception message'))
.having((e) => e.domain.toString(), 'domain', 'DartError'));
});
});

group('delegate', () {
late DartInputStreamAdapter inputStream;
group('delegate', () {
late DartInputStreamAdapter inputStream;

setUp(() {
inputStream = Stream.fromIterable([
[1, 2, 3],
]).toNSInputStream() as DartInputStreamAdapter;
});
setUp(() {
inputStream = Stream.fromIterable([
[1, 2, 3],
]).toNSInputStream() as DartInputStreamAdapter;
});

test('default delegate', () async {
expect(inputStream.delegate, inputStream);
inputStream.stream_handleEvent_(
inputStream, NSStreamEvent.NSStreamEventOpenCompleted);
});
test('default delegate', () async {
expect(inputStream.delegate, inputStream);
inputStream.stream_handleEvent_(
inputStream, NSStreamEvent.NSStreamEventOpenCompleted);
});

test('non-self delegate', () async {
final protoBuilder = ObjCProtocolBuilder();
final events = <NSStreamEvent>[];
test('non-self delegate', () async {
final protoBuilder = ObjCProtocolBuilder();
final events = <NSStreamEvent>[];

NSStreamDelegate.addToBuilder(protoBuilder,
stream_handleEvent_: (stream, event) => events.add(event));
inputStream.delegate = protoBuilder.build();
inputStream.stream_handleEvent_(
inputStream, NSStreamEvent.NSStreamEventOpenCompleted);
expect(events, [NSStreamEvent.NSStreamEventOpenCompleted]);
NSStreamDelegate.addToBuilder(protoBuilder,
stream_handleEvent_: (stream, event) => events.add(event));
inputStream.delegate = protoBuilder.build();
inputStream.stream_handleEvent_(
inputStream, NSStreamEvent.NSStreamEventOpenCompleted);
expect(events, [NSStreamEvent.NSStreamEventOpenCompleted]);
});

test('assign to null', () async {
inputStream.delegate = null;
expect(inputStream.delegate, inputStream);
});
});

test('assign to null', () async {
inputStream.delegate = null;
expect(inputStream.delegate, inputStream);
group('ref counting', () {
test('with self delegate', () async {
DartInputStreamAdapter? inputStream = Stream.fromIterable([
[1, 2, 3],
]).toNSInputStream() as DartInputStreamAdapter;

expect(inputStream.delegate, inputStream);

final ptr = inputStream.ref.pointer;
expect(objectRetainCount(ptr), greaterThan(0));

inputStream.open();
inputStream.close();
inputStream = null;

doGC();
await Future<void>.delayed(Duration.zero);
doGC();
await Future<void>.delayed(Duration.zero);
doGC();
await Future<void>.delayed(Duration.zero);
doGC();
await Future<void>.delayed(Duration.zero);
doGC();
await Future<void>.delayed(Duration.zero);
doGC();
await Future<void>.delayed(Duration.zero);
doGC();
await Future<void>.delayed(Duration.zero);
doGC();
await Future<void>.delayed(Duration.zero);
doGC();

expect(objectRetainCount(ptr), 0);
});

test('with non-self delegate', () async {
DartInputStreamAdapter? inputStream = Stream.fromIterable([
[1, 2, 3],
]).toNSInputStream() as DartInputStreamAdapter;

inputStream.delegate = NSObject.new1();
expect(inputStream.delegate, isNot(inputStream));

final ptr = inputStream.ref.pointer;
expect(objectRetainCount(ptr), greaterThan(0));

inputStream.open();
while (true) {
final (count, data, hasBytesAvailable, status, error) =
await read(inputStream, 6);
if (count == 0) {
break;
}
}
inputStream = null;

doGC();
await Future<void>.delayed(Duration.zero);
doGC();
await Future<void>.delayed(Duration.zero);
doGC();
await Future<void>.delayed(Duration.zero);
doGC();
await Future<void>.delayed(Duration.zero);
doGC();
await Future<void>.delayed(Duration.zero);
doGC();
await Future<void>.delayed(Duration.zero);
doGC();
await Future<void>.delayed(Duration.zero);
doGC();
await Future<void>.delayed(Duration.zero);
doGC();

expect(objectRetainCount(ptr), 0);
});
});
});
}
6 changes: 5 additions & 1 deletion pkgs/objective_c/test/setup.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ import 'dart:io';

import 'package:args/args.dart';

const cFiles = ['src/objective_c.c', 'src/include/dart_api_dl.c'];
const cFiles = [
'src/objective_c.c',
'src/include/dart_api_dl.c',
'test/util.c',
];
const objCFiles = [
'src/input_stream_adapter.m',
'src/objective_c.m',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
// 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.

#ifndef _TEST_UTIL_H_
#define _TEST_UTIL_H_

#include <mach/mach.h>
#include <mach/mach_vm.h>

Expand Down Expand Up @@ -33,7 +30,7 @@ uint64_t getObjectRetainCount(ObjectRefCountExtractor* object) {
return count < 0x80 ? count : k128OrMore;
}

bool isReadableMemory(void* ptr) {
int isReadableMemory(void* ptr) {
vm_map_t task = mach_task_self();
mach_vm_address_t address = (mach_vm_address_t)ptr;
mach_vm_size_t size = 0;
Expand All @@ -43,9 +40,7 @@ bool isReadableMemory(void* ptr) {
kern_return_t status =
mach_vm_region(task, &address, &size, VM_REGION_BASIC_INFO_64,
(vm_region_info_t)&info, &count, &object_name);
if (status != KERN_SUCCESS) return false;
if (status != KERN_SUCCESS) return 0;
return ((mach_vm_address_t)ptr) >= address &&
(info.protection & VM_PROT_READ);
}

#endif // _TEST_UTIL_H_
Loading

0 comments on commit 7ad50c2

Please sign in to comment.