| // 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 'package:analyzer/src/dart/error/ffi_code.dart'; |
| import 'package:test_reflective_loader/test_reflective_loader.dart'; |
| |
| import '../dart/resolution/context_collection_resolution.dart'; |
| |
| main() { |
| defineReflectiveSuite(() { |
| defineReflectiveTests(LeafCallMustNotUseHandle); |
| }); |
| } |
| |
| @reflectiveTest |
| class LeafCallMustNotUseHandle extends PubPackageResolutionTest { |
| test_AsFunctionReturnsHandle() async { |
| await assertErrorsInCode(r''' |
| import 'dart:ffi'; |
| typedef NativeReturnsHandle = Handle Function(); |
| typedef ReturnsHandle = Object Function(); |
| doThings() { |
| Pointer<NativeFunction<NativeReturnsHandle>> p = Pointer.fromAddress(1337); |
| ReturnsHandle f = p.asFunction(isLeaf:true); |
| f(); |
| } |
| ''', [ |
| error(FfiCode.LEAF_CALL_MUST_NOT_RETURN_HANDLE, 224, 10), |
| ]); |
| } |
| |
| test_AsFunctionTakesHandle() async { |
| await assertErrorsInCode(r''' |
| import 'dart:ffi'; |
| typedef NativeTakesHandle = Void Function(Handle); |
| typedef TakesHandle = void Function(Object); |
| class MyClass {} |
| doThings() { |
| Pointer<NativeFunction<NativeTakesHandle>> p = Pointer.fromAddress(1337); |
| TakesHandle f = p.asFunction(isLeaf:true); |
| f(MyClass()); |
| } |
| ''', [ |
| error(FfiCode.LEAF_CALL_MUST_NOT_TAKE_HANDLE, 241, 10), |
| ]); |
| } |
| |
| test_class_getter() async { |
| await assertErrorsInCode(r''' |
| import 'dart:ffi'; |
| |
| base class NativeFieldWrapperClass1 {} |
| |
| base class A extends NativeFieldWrapperClass1 { |
| @Native<Handle Function(Pointer<Void>)>(symbol: 'foo', isLeaf:true) |
| external Object get foo; |
| } |
| ''', [ |
| error(FfiCode.LEAF_CALL_MUST_NOT_RETURN_HANDLE, 200, 3), |
| ]); |
| } |
| |
| test_LookupFunctionReturnsHandle() async { |
| await assertErrorsInCode(r''' |
| import 'dart:ffi'; |
| typedef NativeReturnsHandle = Handle Function(); |
| typedef ReturnsHandle = Object Function(); |
| doThings() { |
| DynamicLibrary l = DynamicLibrary.open("my_lib"); |
| l.lookupFunction<NativeReturnsHandle, ReturnsHandle>("timesFour", isLeaf:true); |
| } |
| ''', [ |
| error(FfiCode.LEAF_CALL_MUST_NOT_RETURN_HANDLE, 195, 19), |
| ]); |
| } |
| |
| test_LookupFunctionTakesHandle() async { |
| await assertErrorsInCode(r''' |
| import 'dart:ffi'; |
| typedef NativeTakesHandle = Void Function(Handle); |
| typedef TakesHandle = void Function(Object); |
| class MyClass {} |
| doThings() { |
| DynamicLibrary l = DynamicLibrary.open("my_lib"); |
| l.lookupFunction<NativeTakesHandle, TakesHandle>("timesFour", isLeaf:true); |
| } |
| ''', [ |
| error(FfiCode.LEAF_CALL_MUST_NOT_TAKE_HANDLE, 216, 17), |
| ]); |
| } |
| |
| test_unit_getter() async { |
| await assertErrorsInCode(r''' |
| import 'dart:ffi'; |
| |
| @Native<Handle Function()>(symbol: 'foo', isLeaf:true) |
| external Object get foo; |
| ''', [ |
| error(FfiCode.LEAF_CALL_MUST_NOT_RETURN_HANDLE, 95, 3), |
| ]); |
| } |
| } |