Skip to content

Commit

Permalink
feat(android): native Promise API
Browse files Browse the repository at this point in the history
Fixes TIMOB-24549
  • Loading branch information
drauggres authored and sgtcoolguy committed Dec 9, 2020
1 parent 7f7813f commit ea75a0f
Show file tree
Hide file tree
Showing 17 changed files with 336 additions and 33 deletions.
2 changes: 1 addition & 1 deletion android/kroll-apt/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,6 @@ jar {

dependencies {
implementation 'com.googlecode.json-simple:json-simple:1.1'
implementation 'org.freemarker:freemarker:2.3.14'
implementation 'org.freemarker:freemarker:2.3.30'
implementation 'log4j:log4j:1.2.17'
}
Binary file removed android/kroll-apt/lib/freemarker.jar
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,18 @@ namespace ${ns?lower_case} {
</#function>

<#assign typeInfo = {
"org.appcelerator.kroll.KrollPromise":{
"jsType":"Object",
"jsConvertType":"Value",
"jsToJavaConverter":"jsObjectToJavaPromise",
"javaToJsConverter":"javaObjectToJsPromise",
"jvalue":"l",
"javaCallMethodType":"Object",
"javaReturnType":"jobject",
"javaValidation":true,
"typeValidation":false,
"defaultValue": "null"
},
"org.appcelerator.kroll.KrollProxy":{
"jsType":"Object",
"jsConvertType":"Value",
Expand Down Expand Up @@ -436,6 +448,10 @@ namespace ${ns?lower_case} {
<#return typeInfo[type]>
</#if>

<#if type?starts_with("org.appcelerator.kroll.KrollPromise")>
<#return typeInfo["org.appcelerator.kroll.KrollPromise"]>
</#if>

<#if type?ends_with("Proxy")>
<#return typeInfo["org.appcelerator.kroll.KrollProxy"]>
</#if>
Expand All @@ -458,6 +474,10 @@ namespace ${ns?lower_case} {
<#-- Look up the type's signature. If it does not exist, this
type is a Java object. Object signatures take a special format
which has the full class name in it (ex: Ljava.lang.Object;) -->
<#if type?starts_with("org.appcelerator.kroll.KrollPromise")>
<#local type = "org.appcelerator.kroll.KrollPromise">
</#if>
<#-- FIXME: We should ideally have a general case check for removing generic type erasures from signatures here -->
<#if typeInfo?keys?seq_contains(type) && typeInfo[type]?keys?seq_contains("signature")>
<#return typeInfo[type].signature>
<#else>
Expand Down Expand Up @@ -643,7 +663,6 @@ fails, a JS exception is returned.
</#if>

<@Proxy.listMethodArguments args=args ; index, info, type, isOptional>

<#if type != "org.appcelerator.kroll.KrollInvocation">
<#if index = varArgsIndex>
<@Proxy.convertToVarArgs args=args start=index/>
Expand Down Expand Up @@ -697,11 +716,10 @@ beprovided to handle the result.
<#if hasResult>
${resultExpr}env->${callExpr}(${argExpr});

<#local jsType = info.jsType>
<#if info?keys?seq_contains("jsConvertType")>
<#local jsType = info.jsConvertType>
</#if>

<#local jsType = info.jsType>
<#if info?keys?seq_contains("jsConvertType")>
<#local jsType = info.jsConvertType>
</#if>
<#else>
env->${callExpr}(${argExpr});
</#if>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.appcelerator.kroll;

import org.appcelerator.kroll.common.TiMessenger;

public interface KrollPromise<V> {

interface OnExecuteCallback<V> {
void onExecute(KrollPromise<V> promise);
}

void resolve(V value);

void reject(Object value);

static <V> KrollPromise<V> create(OnExecuteCallback<V> callback)
{
final KrollPromise<V> promise = KrollRuntime.getInstance().createPromise();
TiMessenger.postOnRuntime(() -> {
callback.onExecute(promise);
});
return promise;
}

static class NullPromise implements KrollPromise
{
@Override
public void resolve(Object value) {}
@Override
public void reject(Object value) {}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import android.os.Handler;
import android.os.Looper;
import android.os.Message;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

/**
Expand Down Expand Up @@ -264,7 +266,7 @@ public void runModule(String source, String filename, KrollProxySupport activity
* Equivalent to <pre>evalString(source, SOURCE_ANONYMOUS)</pre>
* @see #evalString(String, String)
* @param source A string containing Javascript source
* @return The Java representation of the return value of {@link source}, as long as Kroll supports the return value
* @return The Java representation of the return value of {@code source}, as long as Kroll supports the return value
*/
public Object evalString(String source)
{
Expand All @@ -284,8 +286,8 @@ public Object evalString(String source)
* <li>Any Proxy type that extends {@link org.appcelerator.kroll.KrollProxy}</li>
* </ul>
* @param source A string containing Javascript source
* @param filename The name of the filename represented by {@link source}
* @return The Java representation of the return value of {@link source}, as long as Kroll supports the return value
* @param filename The name of the filename represented by {@code source}
* @return The Java representation of the return value of {@code source}, as long as Kroll supports the return value
*/
public Object evalString(String source, String filename)
{
Expand Down Expand Up @@ -608,4 +610,6 @@ private static void onDisposing(KrollRuntime runtime)
public abstract String getRuntimeName();
public abstract void initRuntime();
public abstract void initObject(KrollProxySupport proxy);
@NonNull
public abstract KrollPromise createPromise();
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,25 +86,8 @@ public boolean handleMessage(Message message)
return super.handleMessage(message);
}

@Override
public void doRelease()
{
long functionPointer = getPointer();
if (functionPointer == 0) {
return;
}

nativeRelease(functionPointer);
}

@Override
protected void finalize() throws Throwable
{
super.finalize();
}

// JNI method prototypes
private native Object nativeInvoke(long thisPointer, long functionPointer, Object[] functionArgs);

private static native void nativeRelease(long functionPointer);
protected native boolean nativeRelease(long functionPointer);
}
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ protected void finalize() throws Throwable
// JNI method prototypes
protected static native void nativeInitObject(Class<?> proxyClass, Object proxyObject);

private static native boolean nativeRelease(long ptr);
protected native boolean nativeRelease(long ptr);

private native Object nativeCallProperty(long ptr, String propertyName, Object[] args);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package org.appcelerator.kroll.runtime.v8;

import android.os.Message;

import org.appcelerator.kroll.KrollPromise;
import org.appcelerator.kroll.KrollRuntime;
import org.appcelerator.kroll.common.AsyncResult;
import org.appcelerator.kroll.common.TiMessenger;

/**
* This class wraps an underlying v8::Promise::Resolver which holds
* the Promise but allows us to call resolve/reject on it.
*/
public class V8Promise<V extends Object> extends V8Object implements KrollPromise<V>
{
private static final String TAG = "V8Promise";

protected static final int MSG_RESOLVE = V8Object.MSG_LAST_ID + 100;
protected static final int MSG_REJECT = V8Object.MSG_LAST_ID + 101;
protected static final int MSG_LAST_ID = MSG_REJECT;

public V8Promise()
{
super(nativeCreate());
}

@Override
public void resolve(V value)
{
if (KrollRuntime.getInstance().isRuntimeThread()) {
nativeResolve(getPointer(), value);
} else {
TiMessenger.sendBlockingRuntimeMessage(handler.obtainMessage(MSG_RESOLVE), value);
}
}

@Override
public void reject(Object value)
{
if (KrollRuntime.getInstance().isRuntimeThread()) {
nativeReject(getPointer(), value);
} else {
TiMessenger.sendBlockingRuntimeMessage(handler.obtainMessage(MSG_REJECT), value);
}
}

@Override
public boolean handleMessage(Message message)
{
switch (message.what) {
case MSG_RESOLVE: {
AsyncResult asyncResult = ((AsyncResult) message.obj);
Object value = asyncResult.getArg();
nativeResolve(getPointer(), value);
asyncResult.setResult(null);
return true;
}
case MSG_REJECT: {
AsyncResult asyncResult = ((AsyncResult) message.obj);
Object value = asyncResult.getArg();
nativeReject(getPointer(), value);
asyncResult.setResult(null);
return true;
}
}

return super.handleMessage(message);
}

// JNI method prototypes
private static native long nativeCreate();

private native void nativeResolve(long resolver, Object value);

private native void nativeReject(long resolver, Object value);

protected native boolean nativeRelease(long resolver);
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

import org.appcelerator.kroll.KrollApplication;
import org.appcelerator.kroll.KrollExternalModule;
import org.appcelerator.kroll.KrollPromise;
import org.appcelerator.kroll.KrollProxySupport;
import org.appcelerator.kroll.KrollRuntime;
import org.appcelerator.kroll.common.KrollSourceCodeProvider;
Expand All @@ -26,6 +27,8 @@
import android.os.Looper;
import android.os.MessageQueue.IdleHandler;

import androidx.annotation.NonNull;

public final class V8Runtime extends KrollRuntime implements Handler.Callback
{
private static final String TAG = "KrollV8Runtime";
Expand Down Expand Up @@ -212,6 +215,16 @@ public void setGCFlag()
shouldGC.set(true);
}

@Override
@NonNull
public KrollPromise createPromise()
{
if (KrollRuntime.isDisposed()) {
return new KrollPromise.NullPromise();
}
return new V8Promise();
}

// JNI method prototypes
private native void nativeInit(JSDebugger jsDebugger, boolean DBG, boolean profilerEnabled);

Expand Down
1 change: 1 addition & 0 deletions android/runtime/v8/src/native/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ add_library(
TypeConverter.cpp
V8Function.cpp
V8Object.cpp
V8Promise.cpp
V8Runtime.cpp
V8Util.cpp
modules/APIModule.cpp
Expand Down
4 changes: 4 additions & 0 deletions android/runtime/v8/src/native/JNIUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ jclass JNIUtil::nullPointerException = NULL;
jclass JNIUtil::throwableClass = NULL;
jclass JNIUtil::stackTraceElementClass = NULL;

jclass JNIUtil::v8PromiseClass = NULL;
jclass JNIUtil::v8ObjectClass = NULL;
jclass JNIUtil::v8FunctionClass = NULL;
jclass JNIUtil::krollRuntimeClass = NULL;
Expand Down Expand Up @@ -89,6 +90,7 @@ jmethodID JNIUtil::throwableGetStackTraceMethod = NULL;
jmethodID JNIUtil::stackTraceElementToStringMethod = NULL;

jfieldID JNIUtil::v8ObjectPtrField = NULL;
jmethodID JNIUtil::v8PromiseInitMethod = NULL;
jmethodID JNIUtil::v8ObjectInitMethod = NULL;
jmethodID JNIUtil::v8FunctionInitMethod = NULL;

Expand Down Expand Up @@ -331,6 +333,7 @@ void JNIUtil::initCache()
throwableClass = findClass("java/lang/Throwable");
stackTraceElementClass = findClass("java/lang/StackTraceElement");

v8PromiseClass = findClass("org/appcelerator/kroll/runtime/v8/V8Promise");
v8ObjectClass = findClass("org/appcelerator/kroll/runtime/v8/V8Object");
v8FunctionClass = findClass("org/appcelerator/kroll/runtime/v8/V8Function");
krollRuntimeClass = findClass("org/appcelerator/kroll/KrollRuntime");
Expand Down Expand Up @@ -373,6 +376,7 @@ void JNIUtil::initCache()
stackTraceElementToStringMethod = getMethodID(stackTraceElementClass, "toString", "()Ljava/lang/String;", false);

v8ObjectPtrField = getFieldID(v8ObjectClass, "ptr", "J");
v8PromiseInitMethod = getMethodID(v8PromiseClass, "<init>", "(J)V", false);
v8ObjectInitMethod = getMethodID(v8ObjectClass, "<init>", "(J)V", false);
v8FunctionInitMethod = getMethodID(v8FunctionClass, "<init>", "(J)V", false);

Expand Down
2 changes: 2 additions & 0 deletions android/runtime/v8/src/native/JNIUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ class JNIUtil
static jclass nullPointerException;

// Titanium classes
static jclass v8PromiseClass;
static jclass v8ObjectClass;
static jclass v8FunctionClass;
static jclass krollRuntimeClass;
Expand Down Expand Up @@ -136,6 +137,7 @@ class JNIUtil

// Titanium methods and fields
static jfieldID v8ObjectPtrField;
static jmethodID v8PromiseInitMethod;
static jmethodID v8ObjectInitMethod;
static jmethodID v8FunctionInitMethod;

Expand Down
Loading

0 comments on commit ea75a0f

Please sign in to comment.