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 all 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