Skip to content
This repository has been archived by the owner on Apr 29, 2024. It is now read-only.

Dart exceptions #376

Merged
merged 10 commits into from
Aug 29, 2023
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion jni/example/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ if (localPropertiesFile.exists()) {

def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
throw new FileNotFoundException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}

def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
Expand Down
11 changes: 10 additions & 1 deletion jni/java/src/main/java/com/github/dart_lang/jni/PortProxy.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,19 @@ public static Object newInstance(String binaryName, long port, long isolateId, l
return obj;
}

private static final class DartException extends Exception {
private DartException(String message) {
super(message);
}
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) {
public Object invoke(Object proxy, Method method, Object[] args) throws DartException {
Object[] result = _invoke(port, isolateId, functionPtr, proxy, getDescriptor(method), args);
_cleanUp((Long) result[0]);
if (result[1] instanceof DartException) {
throw (DartException) result[1];
}
return result[1];
}

Expand Down
27 changes: 18 additions & 9 deletions jni/lib/src/jni.dart
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,13 @@ extension ProtectedJniExtensions on Jni {
return lookup;
}

/// Returns a new DartException.
static JObjectPtr newDartException(String message) {
return Jni._bindings
.DartException__ctor(Jni.env.toJStringPtr(message))
.object;
}

/// Returns a new PortContinuation.
static JObjectPtr newPortContinuation(ReceivePort port) {
return Jni._bindings
Expand All @@ -323,7 +330,7 @@ extension ProtectedJniExtensions on Jni {
.object;
}

/// Return the result of a callback..
/// Returns the result of a callback..
static void returnResult(
Pointer<CallbackResult> result, JObjectPtr object) async {
Jni._bindings.resultFor(result, object);
Expand All @@ -334,28 +341,30 @@ extension AdditionalEnvMethods on GlobalJniEnv {
/// Convenience method for converting a [JStringPtr]
/// to dart string.
/// if [deleteOriginal] is specified, jstring passed will be deleted using
/// DeleteLocalRef.
/// DeleteGlobalRef.
String toDartString(JStringPtr jstringPtr, {bool deleteOriginal = false}) {
if (jstringPtr == nullptr) {
throw const JNullException();
}
final chars = GetStringUTFChars(jstringPtr, nullptr);
final chars = GetStringChars(jstringPtr, nullptr);
if (chars == nullptr) {
throw InvalidJStringException(jstringPtr);
}
final result = chars.cast<Utf8>().toDartString();
ReleaseStringUTFChars(jstringPtr, chars);
final result = chars.cast<Utf16>().toDartString();
ReleaseStringChars(jstringPtr, chars);
if (deleteOriginal) {
DeleteGlobalRef(jstringPtr);
}
return result;
}

/// Return a new [JStringPtr] from contents of [s].
/// Returns a new [JStringPtr] from contents of [s].
JStringPtr toJStringPtr(String s) => using((arena) {
final utf = s.toNativeUtf8().cast<Char>();
final result = NewStringUTF(utf);
malloc.free(utf);
final utf = s.toNativeUtf16(allocator: arena).cast<Uint16>();
final result = NewString(utf, s.length);
if (utf == nullptr) {
throw 'Fatal: cannot convert string to Java string: $s';
}
return result;
});

Expand Down
11 changes: 1 addition & 10 deletions jni/lib/src/lang/jstring.dart
Original file line number Diff line number Diff line change
Expand Up @@ -47,20 +47,11 @@ class JString extends JObject {
/// Construct a new [JString] with [reference] as its underlying reference.
JString.fromRef(JStringPtr reference) : super.fromRef(reference);

static JStringPtr _toJavaString(String s) => using((arena) {
final chars = s.toNativeUtf16(allocator: arena).cast<Uint16>();
final jstr = Jni.env.NewString(chars, s.length);
if (jstr == nullptr) {
throw 'Fatal: cannot convert string to Java string: $s';
}
return jstr;
});

/// The number of Unicode characters in this Java string.
int get length => Jni.env.GetStringLength(reference);

/// Construct a [JString] from the contents of Dart string [s].
JString.fromString(String s) : super.fromRef(_toJavaString(s));
JString.fromString(String s) : super.fromRef(Jni.env.toJStringPtr(s));

/// Returns the contents as a Dart String.
///
Expand Down
38 changes: 26 additions & 12 deletions jni/lib/src/third_party/jni_bindings_generated.dart
Original file line number Diff line number Diff line change
Expand Up @@ -178,22 +178,19 @@ class JniBindings {
late final _InitDartApiDL =
_InitDartApiDLPtr.asFunction<int Function(ffi.Pointer<ffi.Void>)>();

void resultFor(
ffi.Pointer<CallbackResult> result,
JObjectPtr object,
JniResult DartException__ctor(
JStringPtr message,
) {
return _resultFor(
result,
object,
return _DartException__ctor(
message,
);
}

late final _resultForPtr = _lookup<
ffi.NativeFunction<
ffi.Void Function(
ffi.Pointer<CallbackResult>, JObjectPtr)>>('resultFor');
late final _resultFor = _resultForPtr
.asFunction<void Function(ffi.Pointer<CallbackResult>, JObjectPtr)>();
late final _DartException__ctorPtr =
_lookup<ffi.NativeFunction<JniResult Function(JStringPtr)>>(
'DartException__ctor');
late final _DartException__ctor =
_DartException__ctorPtr.asFunction<JniResult Function(JStringPtr)>();

JniResult PortContinuation__ctor(
int j,
Expand Down Expand Up @@ -228,6 +225,23 @@ class JniBindings {
late final _PortProxy__newInstance = _PortProxy__newInstancePtr.asFunction<
JniResult Function(JObjectPtr, int, int)>();

void resultFor(
ffi.Pointer<CallbackResult> result,
JObjectPtr object,
) {
return _resultFor(
result,
object,
);
}

late final _resultForPtr = _lookup<
ffi.NativeFunction<
ffi.Void Function(
ffi.Pointer<CallbackResult>, JObjectPtr)>>('resultFor');
late final _resultFor = _resultForPtr
.asFunction<void Function(ffi.Pointer<CallbackResult>, JObjectPtr)>();

ffi.Pointer<GlobalJniEnvStruct> GetGlobalEnv() {
return _GetGlobalEnv();
}
Expand Down
23 changes: 23 additions & 0 deletions jni/src/dartjni.c
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,29 @@ FFI_PLUGIN_EXPORT intptr_t InitDartApiDL(void* data) {
return Dart_InitializeApiDL(data);
}

// com.github.dart_lang.jni.DartException
jclass _c_DartException = NULL;

jmethodID _m_DartException__ctor = NULL;
FFI_PLUGIN_EXPORT JniResult DartException__ctor(jstring message) {
attach_thread();
load_class_global_ref(&_c_DartException,
"com/github/dart_lang/jni/PortProxy$DartException");
if (_c_DartException == NULL)
return (JniResult){.value = {.j = 0}, .exception = check_exception()};
load_method(_c_DartException, &_m_DartException__ctor, "<init>",
"(Ljava/lang/String;)V");
if (_m_DartException__ctor == NULL)
return (JniResult){.value = {.j = 0}, .exception = check_exception()};
jobject _result = (*jniEnv)->NewObject(jniEnv, _c_DartException,
_m_DartException__ctor, message);
jthrowable exception = check_exception();
if (exception == NULL) {
_result = to_global_ref(_result);
}
return (JniResult){.value = {.l = _result}, .exception = check_exception()};
}

JNIEXPORT void JNICALL
Java_com_github_dart_1lang_jni_PortContinuation__1resumeWith(JNIEnv* env,
jclass clazz,
Expand Down
5 changes: 4 additions & 1 deletion jni/src/dartjni.h
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,8 @@ static inline JniResult to_global_ref_result(jobject ref) {

FFI_PLUGIN_EXPORT intptr_t InitDartApiDL(void* data);

FFI_PLUGIN_EXPORT void resultFor(CallbackResult* result, jobject object);
FFI_PLUGIN_EXPORT
JniResult DartException__ctor(jstring message);

FFI_PLUGIN_EXPORT
JniResult PortContinuation__ctor(int64_t j);
Expand All @@ -419,3 +420,5 @@ FFI_PLUGIN_EXPORT
JniResult PortProxy__newInstance(jobject binaryName,
int64_t port,
int64_t functionPtr);

FFI_PLUGIN_EXPORT void resultFor(CallbackResult* result, jobject object);
2 changes: 1 addition & 1 deletion jnigen/android_test_runner/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ if (localPropertiesFile.exists()) {

def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
throw new FileNotFoundException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}

def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
Expand Down
2 changes: 1 addition & 1 deletion jnigen/example/in_app_java/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ if (localPropertiesFile.exists()) {

def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
throw new FileNotFoundException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}

def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
Expand Down
5 changes: 4 additions & 1 deletion jnigen/example/in_app_java/src/android_utils/dartjni.h
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,8 @@ static inline JniResult to_global_ref_result(jobject ref) {

FFI_PLUGIN_EXPORT intptr_t InitDartApiDL(void* data);

FFI_PLUGIN_EXPORT void resultFor(CallbackResult* result, jobject object);
FFI_PLUGIN_EXPORT
JniResult DartException__ctor(jstring message);

FFI_PLUGIN_EXPORT
JniResult PortContinuation__ctor(int64_t j);
Expand All @@ -419,3 +420,5 @@ FFI_PLUGIN_EXPORT
JniResult PortProxy__newInstance(jobject binaryName,
int64_t port,
int64_t functionPtr);

FFI_PLUGIN_EXPORT void resultFor(CallbackResult* result, jobject object);
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ if (localPropertiesFile.exists()) {

def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
throw new FileNotFoundException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}

def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
Expand Down
5 changes: 4 additions & 1 deletion jnigen/example/kotlin_plugin/src/dartjni.h
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,8 @@ static inline JniResult to_global_ref_result(jobject ref) {

FFI_PLUGIN_EXPORT intptr_t InitDartApiDL(void* data);

FFI_PLUGIN_EXPORT void resultFor(CallbackResult* result, jobject object);
FFI_PLUGIN_EXPORT
JniResult DartException__ctor(jstring message);

FFI_PLUGIN_EXPORT
JniResult PortContinuation__ctor(int64_t j);
Expand All @@ -419,3 +420,5 @@ FFI_PLUGIN_EXPORT
JniResult PortProxy__newInstance(jobject binaryName,
int64_t port,
int64_t functionPtr);

FFI_PLUGIN_EXPORT void resultFor(CallbackResult* result, jobject object);
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ if (localPropertiesFile.exists()) {

def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
throw new FileNotFoundException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}

def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
Expand Down
5 changes: 4 additions & 1 deletion jnigen/example/notification_plugin/src/dartjni.h
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,8 @@ static inline JniResult to_global_ref_result(jobject ref) {

FFI_PLUGIN_EXPORT intptr_t InitDartApiDL(void* data);

FFI_PLUGIN_EXPORT void resultFor(CallbackResult* result, jobject object);
FFI_PLUGIN_EXPORT
JniResult DartException__ctor(jstring message);

FFI_PLUGIN_EXPORT
JniResult PortContinuation__ctor(int64_t j);
Expand All @@ -419,3 +420,5 @@ FFI_PLUGIN_EXPORT
JniResult PortProxy__newInstance(jobject binaryName,
int64_t port,
int64_t functionPtr);

FFI_PLUGIN_EXPORT void resultFor(CallbackResult* result, jobject object);
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ if (localPropertiesFile.exists()) {

def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
throw new FileNotFoundException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}

def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
Expand Down
5 changes: 4 additions & 1 deletion jnigen/example/pdfbox_plugin/src/third_party/dartjni.h
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,8 @@ static inline JniResult to_global_ref_result(jobject ref) {

FFI_PLUGIN_EXPORT intptr_t InitDartApiDL(void* data);

FFI_PLUGIN_EXPORT void resultFor(CallbackResult* result, jobject object);
FFI_PLUGIN_EXPORT
JniResult DartException__ctor(jstring message);

FFI_PLUGIN_EXPORT
JniResult PortContinuation__ctor(int64_t j);
Expand All @@ -419,3 +420,5 @@ FFI_PLUGIN_EXPORT
JniResult PortProxy__newInstance(jobject binaryName,
int64_t port,
int64_t functionPtr);

FFI_PLUGIN_EXPORT void resultFor(CallbackResult* result, jobject object);
36 changes: 19 additions & 17 deletions jnigen/lib/src/bindings/dart_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -439,14 +439,18 @@ class $name$typeParamsDef extends $superName {
int $p,
$MethodInvocation $i,
) {
final $d = $i.methodDescriptor.toDartString(deleteOriginal: true);
final $a = $i.args;
try {
final $d = $i.methodDescriptor.toDartString(deleteOriginal: true);
final $a = $i.args;
''');
final proxyMethodIf = _InterfaceMethodIf(resolver, s);
for (final method in node.methods) {
method.accept(proxyMethodIf);
}
s.write('''
} catch (e) {
return $_protectedExtension.newDartException(e.toString());
}
return jni.nullptr;
}

Expand All @@ -469,19 +473,17 @@ class $name$typeParamsDef extends $superName {
).._\$p = \$p;
final \$a = \$p.sendPort.nativePort;
_\$impls[\$a] = \$impl;
''');
s.write(r'''
$p.listen(($m) {
if ($m == null) {
_$impls.remove($p.sendPort.nativePort);
$p.close();
\$p.listen((\$m) {
if (\$m == null) {
_\$impls.remove(\$p.sendPort.nativePort);
\$p.close();
return;
}
final $i = $MethodInvocation.fromMessage($m);
final $r = _$invokeMethod($p.sendPort.nativePort, $i);
ProtectedJniExtensions.returnResult($i.result, $r);
final \$i = \$MethodInvocation.fromMessage(\$m);
final \$r = _\$invokeMethod(\$p.sendPort.nativePort, \$i);
$_protectedExtension.returnResult(\$i.result, \$r);
});
return $x;
return \$x;
}
''');
}
Expand Down Expand Up @@ -1645,17 +1647,17 @@ class _InterfaceMethodIf extends Visitor<Method, void> {
final saveResult = isVoid ? '' : 'final \$r = ';
final name = node.finalName;
s.write('''
if (\$d == r"$signature") {
${saveResult}_\$impls[\$p]!.$name(
if (\$d == r"$signature") {
${saveResult}_\$impls[\$p]!.$name(
''');
for (var i = 0; i < node.params.length; ++i) {
node.params[i].accept(_InterfaceParamCast(resolver, s, paramIndex: i));
}
const returnBox = _InterfaceReturnBox();
s.write('''
);
return ${node.returnType.accept(returnBox)};
}
);
return ${node.returnType.accept(returnBox)};
}
''');
}
}
Expand Down
Loading
Loading