From af6586dcb565165cc856bb66c589fbbed5c8a391 Mon Sep 17 00:00:00 2001 From: Felipe Lima Date: Sun, 11 Sep 2016 19:11:31 -0300 Subject: [PATCH 1/5] [WIP] Expose ArgumentExtractor --- .../facebook/react/bridge/BaseJavaModule.java | 79 +++++++++++++------ 1 file changed, 55 insertions(+), 24 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/BaseJavaModule.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/BaseJavaModule.java index 2ea0cb4d1fc5b3..af29484ad3dbd4 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/BaseJavaModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/BaseJavaModule.java @@ -9,16 +9,19 @@ package com.facebook.react.bridge; -import javax.annotation.Nullable; +import com.facebook.infer.annotation.Assertions; +import com.facebook.systrace.Systrace; +import com.facebook.systrace.SystraceMessage; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; -import com.facebook.infer.annotation.Assertions; -import com.facebook.systrace.Systrace; -import com.facebook.systrace.SystraceMessage; +import javax.annotation.Nullable; import static com.facebook.infer.annotation.Assertions.assertNotNull; import static com.facebook.systrace.Systrace.TRACE_TAG_REACT_JAVA_BRIDGE; @@ -49,9 +52,18 @@ */ public abstract class BaseJavaModule implements NativeModule { // taken from Libraries/Utilities/MessageQueue.js - static final public String METHOD_TYPE_ASYNC = "async"; - static final public String METHOD_TYPE_PROMISE= "promise"; + private static final String METHOD_TYPE_ASYNC = "async"; + private static final String METHOD_TYPE_PROMISE= "promise"; static final public String METHOD_TYPE_SYNC = "sync"; + private final List mArgumentExtractorFactories; + + public BaseJavaModule() { + this(Collections.emptyList()); + } + + public BaseJavaModule(List argumentExtractorFactories) { + mArgumentExtractorFactories = argumentExtractorFactories; + } private static abstract class ArgumentExtractor { public int getJSArgumentsNeeded() { @@ -60,6 +72,10 @@ public int getJSArgumentsNeeded() { public abstract @Nullable T extractArgument( CatalystInstance catalystInstance, ExecutorToken executorToken, ReadableNativeArray jsArguments, int atIndex); + + interface Factory { + ArgumentExtractor get(Type type); + } } static final private ArgumentExtractor ARGUMENT_EXTRACTOR_BOOLEAN = @@ -159,17 +175,17 @@ public Promise extractArgument( public class JavaMethod implements NativeMethod { - private Method mMethod; - private final ArgumentExtractor[] mArgumentExtractors; + private final Method mMethod; + private final ArgumentExtractor[] mArgumentExtractors; private final String mSignature; private final Object[] mArguments; private String mType = METHOD_TYPE_ASYNC; private final int mJSArgumentsNeeded; private final String mTraceName; - public JavaMethod(Method method) { + JavaMethod(Method method) { mMethod = method; - Class[] parameterTypes = method.getParameterTypes(); + Class[] parameterTypes = method.getParameterTypes(); mArgumentExtractors = buildArgumentExtractors(parameterTypes); mSignature = buildSignature(parameterTypes); // Since native methods are invoked from a message queue executed on a single thread, it is @@ -187,11 +203,11 @@ public String getSignature() { return mSignature; } - private String buildSignature(Class[] paramTypes) { + private String buildSignature(Class[] paramTypes) { StringBuilder builder = new StringBuilder(paramTypes.length); builder.append("v."); for (int i = 0; i < paramTypes.length; i++) { - Class paramClass = paramTypes[i]; + Class paramClass = paramTypes[i]; if (paramClass == ExecutorToken.class) { if (!BaseJavaModule.this.supportsWebWorkers()) { throw new RuntimeException( @@ -220,7 +236,7 @@ private String buildSignature(Class[] paramTypes) { return builder.toString(); } - private ArgumentExtractor[] buildArgumentExtractors(Class[] paramTypes) { + private ArgumentExtractor[] buildArgumentExtractors(Class[] paramTypes) { // Modules that support web workers are expected to take an ExecutorToken as the first // parameter to all their @ReactMethod-annotated methods. We compensate for that here. int executorTokenOffset = 0; @@ -233,10 +249,10 @@ private ArgumentExtractor[] buildArgumentExtractors(Class[] paramTypes) { executorTokenOffset = 1; } - ArgumentExtractor[] argumentExtractors = new ArgumentExtractor[paramTypes.length - executorTokenOffset]; + ArgumentExtractor[] argumentExtractors = new ArgumentExtractor[paramTypes.length - executorTokenOffset]; for (int i = 0; i < paramTypes.length - executorTokenOffset; i += argumentExtractors[i].getJSArgumentsNeeded()) { int paramIndex = i + executorTokenOffset; - Class argumentClass = paramTypes[paramIndex]; + Class argumentClass = paramTypes[paramIndex]; if (argumentClass == Boolean.class || argumentClass == boolean.class) { argumentExtractors[i] = ARGUMENT_EXTRACTOR_BOOLEAN; } else if (argumentClass == Integer.class || argumentClass == int.class) { @@ -259,16 +275,31 @@ private ArgumentExtractor[] buildArgumentExtractors(Class[] paramTypes) { } else if (argumentClass == ReadableArray.class) { argumentExtractors[i] = ARGUMENT_EXTRACTOR_ARRAY; } else { - throw new RuntimeException( + ArgumentExtractor argumentExtractor = findArgumentExtractorForType(argumentClass); + if (argumentExtractor != null) { + argumentExtractors[i] = argumentExtractor; + } else { + throw new RuntimeException( "Got unknown argument class: " + argumentClass.getSimpleName()); + } } } return argumentExtractors; } + private ArgumentExtractor findArgumentExtractorForType(Class argumentClass) { + for (ArgumentExtractor.Factory argumentExtractorFactory : mArgumentExtractorFactories) { + ArgumentExtractor argumentExtractor = argumentExtractorFactory.get(argumentClass); + if (argumentExtractor != null) { + return argumentExtractor; + } + } + return null; + } + private int calculateJSArgumentsNeeded() { int n = 0; - for (ArgumentExtractor extractor : mArgumentExtractors) { + for (ArgumentExtractor extractor : mArgumentExtractors) { n += extractor.getJSArgumentsNeeded(); } return n; @@ -349,10 +380,10 @@ public String getType() { public class SyncJavaHook implements SyncNativeHook { - private Method mMethod; + private final Method mMethod; private final String mSignature; - public SyncJavaHook(Method method) { + SyncJavaHook(Method method) { mMethod = method; mSignature = buildSignature(method); } @@ -366,14 +397,14 @@ public String getSignature() { } private String buildSignature(Method method) { - Class[] paramTypes = method.getParameterTypes(); + Class[] paramTypes = method.getParameterTypes(); StringBuilder builder = new StringBuilder(paramTypes.length + 2); builder.append(returnTypeToChar(method.getReturnType())); builder.append('.'); for (int i = 0; i < paramTypes.length; i++) { - Class paramClass = paramTypes[i]; + Class paramClass = paramTypes[i]; if (paramClass == ExecutorToken.class) { if (!BaseJavaModule.this.supportsWebWorkers()) { throw new RuntimeException( @@ -467,7 +498,7 @@ public boolean supportsWebWorkers() { return false; } - private static char paramTypeToChar(Class paramClass) { + private static char paramTypeToChar(Class paramClass) { char tryCommon = commonTypeToChar(paramClass); if (tryCommon != '\0') { return tryCommon; @@ -488,7 +519,7 @@ private static char paramTypeToChar(Class paramClass) { } } - private static char returnTypeToChar(Class returnClass) { + private static char returnTypeToChar(Class returnClass) { char tryCommon = commonTypeToChar(returnClass); if (tryCommon != '\0') { return tryCommon; @@ -505,7 +536,7 @@ private static char returnTypeToChar(Class returnClass) { } } - private static char commonTypeToChar(Class typeClass) { + private static char commonTypeToChar(Class typeClass) { if (typeClass == boolean.class) { return 'z'; } else if (typeClass == Boolean.class) { From de8663cd7145db6f494a105d2df5bc34d83d3f1f Mon Sep 17 00:00:00 2001 From: Felipe Lima Date: Mon, 12 Sep 2016 10:20:31 -0700 Subject: [PATCH 2/5] Unit tests WIP --- ...alystNativeJSToJavaParametersTestCase.java | 70 ++++++++++++++++--- .../facebook/react/bridge/BaseJavaModule.java | 15 ++-- 2 files changed, 71 insertions(+), 14 deletions(-) diff --git a/ReactAndroid/src/androidTest/java/com/facebook/react/tests/CatalystNativeJSToJavaParametersTestCase.java b/ReactAndroid/src/androidTest/java/com/facebook/react/tests/CatalystNativeJSToJavaParametersTestCase.java index 06ff91a0cfa626..9516a044952669 100644 --- a/ReactAndroid/src/androidTest/java/com/facebook/react/tests/CatalystNativeJSToJavaParametersTestCase.java +++ b/ReactAndroid/src/androidTest/java/com/facebook/react/tests/CatalystNativeJSToJavaParametersTestCase.java @@ -8,25 +8,21 @@ package com.facebook.react.tests; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - import com.facebook.react.bridge.BaseJavaModule; import com.facebook.react.bridge.CatalystInstance; -import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.bridge.ExecutorToken; import com.facebook.react.bridge.InvalidIteratorException; import com.facebook.react.bridge.JavaScriptModule; import com.facebook.react.bridge.NoSuchKeyException; +import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.bridge.ReadableType; -import com.facebook.react.bridge.ReadableNativeMap; import com.facebook.react.bridge.ReadableMapKeySetIterator; -import com.facebook.react.bridge.UnexpectedNativeTypeException; +import com.facebook.react.bridge.ReadableNativeArray; +import com.facebook.react.bridge.ReadableNativeMap; +import com.facebook.react.bridge.ReadableType; import com.facebook.react.bridge.UiThreadUtil; +import com.facebook.react.bridge.UnexpectedNativeTypeException; import com.facebook.react.bridge.WritableMap; import com.facebook.react.bridge.WritableNativeMap; import com.facebook.react.modules.systeminfo.AndroidInfoModule; @@ -38,6 +34,18 @@ import com.facebook.react.uimanager.ViewManager; import com.facebook.react.views.view.ReactViewManager; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.annotation.Nullable; + +import static android.R.attr.type; + /** * Integration test to verify passing various types of parameters from JS to Java works */ @@ -299,6 +307,10 @@ public void testGetTypeFromArray() { assertEquals(ReadableType.Null, array.getType(6)); } + public void testCustomTypeViaArgumentExtractor() { + mCatalystInstance.getJSModule(TestJSToJavaParametersModule.class).returnCustomType(); + } + public void testGetTypeFromMap() { mCatalystInstance.getJSModule(TestJSToJavaParametersModule.class) .returnMapWithStringDoubleIntMapArrayBooleanNull(); @@ -668,11 +680,44 @@ private void mapGetByType(ReadableMap map, String key, String typeToAskFor) { } } + private static class CustomType { + private final int foo; + private final String bar; + private final boolean baz; + + CustomType(int foo, String bar, boolean baz) { + this.foo = foo; + this.bar = bar; + this.baz = baz; + } + } + private class RecordingTestModule extends BaseJavaModule { + RecordingTestModule() { + super(Collections.singletonList(new ArgumentExtractor.Factory() { + @Nullable @Override public ArgumentExtractor get(Class type) { + if (CustomType.class.isAssignableFrom(type)) { + return new ArgumentExtractor() { + @Nullable @Override + public CustomType extractArgument( + CatalystInstance catalystInstance, ExecutorToken executorToken, + ReadableNativeArray jsArguments, int atIndex) { + ReadableNativeMap map = jsArguments.getMap(0); + return new CustomType(map.getInt("foo"), map.getString("bar"), + map.getBoolean("baz")); + } + }; + } else { + return null; + } + } + })); + } private final List mBasicTypesCalls = new ArrayList(); private final List mArrayCalls = new ArrayList(); private final List mMapCalls = new ArrayList(); + private final List mCustomTypeCalls = new ArrayList<>(); @Override public String getName() { @@ -689,6 +734,11 @@ public void receiveArray(ReadableArray array) { mArrayCalls.add(array); } + @ReactMethod + public void receiveCustomType(CustomType type) { + mCustomTypeCalls.add(type); + } + @ReactMethod public void receiveMap(ReadableMap map) { mMapCalls.add(map); diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/BaseJavaModule.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/BaseJavaModule.java index af29484ad3dbd4..6d3bc3c2fa1198 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/BaseJavaModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/BaseJavaModule.java @@ -41,7 +41,9 @@ * 2/ {@link String} mapped from JS string * 3/ {@link ReadableArray} mapped from JS Array * 4/ {@link ReadableMap} mapped from JS Object - * 5/ {@link Callback} mapped from js function and can be used only as a last parameter or in the + * 5/ Any {@link Type} that can be handled by a {@link ArgumentExtractor.Factory} that was + * previously registered via this module's constructor. + * 6/ {@link Callback} mapped from js function and can be used only as a last parameter or in the * case when it express success & error callback pair as two last arguments respecively. * * All methods exposed as native to JS with {@link ReactMethod} annotation must return @@ -65,7 +67,7 @@ public BaseJavaModule(List argumentExtracto mArgumentExtractorFactories = argumentExtractorFactories; } - private static abstract class ArgumentExtractor { + public static abstract class ArgumentExtractor { public int getJSArgumentsNeeded() { return 1; } @@ -73,8 +75,13 @@ public int getJSArgumentsNeeded() { public abstract @Nullable T extractArgument( CatalystInstance catalystInstance, ExecutorToken executorToken, ReadableNativeArray jsArguments, int atIndex); - interface Factory { - ArgumentExtractor get(Type type); + /** + * Returns an instance of {@link ArgumentExtractor} that is able to handle extracting arguments + * to {@link ReactMethod} annotated methods with the given {@code Type}. Return {@code null} if + * this factory can't handle the provided type. + */ + public interface Factory { + @Nullable ArgumentExtractor get(Class type); } } From 7ed62c3c86148f96cd7418a22d2cbc7c84bfc503 Mon Sep 17 00:00:00 2001 From: Felipe Lima Date: Sun, 25 Sep 2016 11:03:28 -0700 Subject: [PATCH 3/5] Adds integration test --- ...alystNativeJSToJavaParametersTestCase.java | 69 ++++++++++++++----- .../js/TestJSToJavaParametersModule.js | 12 ++++ 2 files changed, 65 insertions(+), 16 deletions(-) diff --git a/ReactAndroid/src/androidTest/java/com/facebook/react/tests/CatalystNativeJSToJavaParametersTestCase.java b/ReactAndroid/src/androidTest/java/com/facebook/react/tests/CatalystNativeJSToJavaParametersTestCase.java index 9516a044952669..178f5d4e5c5670 100644 --- a/ReactAndroid/src/androidTest/java/com/facebook/react/tests/CatalystNativeJSToJavaParametersTestCase.java +++ b/ReactAndroid/src/androidTest/java/com/facebook/react/tests/CatalystNativeJSToJavaParametersTestCase.java @@ -34,7 +34,6 @@ import com.facebook.react.uimanager.ViewManager; import com.facebook.react.views.view.ReactViewManager; -import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -44,8 +43,6 @@ import javax.annotation.Nullable; -import static android.R.attr.type; - /** * Integration test to verify passing various types of parameters from JS to Java works */ @@ -55,24 +52,34 @@ private interface TestJSToJavaParametersModule extends JavaScriptModule { void returnBasicTypes(); void returnArrayWithBasicTypes(); + void returnNestedArray(); + void returnArrayWithMaps(); void returnMapWithBasicTypes(); + void returnNestedMap(); + void returnMapWithArrays(); void returnArrayWithStringDoubleIntMapArrayBooleanNull(); + void returnMapWithStringDoubleIntMapArrayBooleanNull(); void returnMapForMerge1(); + void returnMapForMerge2(); void returnMapWithMultibyteUTF8CharacterString(); + void returnArrayWithMultibyteUTF8CharacterString(); void returnArrayWithLargeInts(); + void returnMapWithLargeInts(); + + void returnCustomType(); } private RecordingTestModule mRecordingTestModule; @@ -309,11 +316,26 @@ public void testGetTypeFromArray() { public void testCustomTypeViaArgumentExtractor() { mCatalystInstance.getJSModule(TestJSToJavaParametersModule.class).returnCustomType(); + waitForBridgeAndUIIdle(); + + List calls = mRecordingTestModule.getCustomTypeCalls(); + assertEquals(1, calls.size()); + CustomType obj = calls.get(0); + + assertEquals(obj.foo, 1); + assertEquals(obj.bar, "string"); + assertEquals(obj.baz, true); + assertEquals(obj.obj.innerBool, true); + assertEquals(obj.obj.innerStr, "other string"); + assertEquals(obj.arr.size(), 3); + assertEquals(obj.arr.getInt(0), 1); + assertEquals(obj.arr.getString(1), "foo"); + assertEquals(obj.arr.getString(2), "bar"); } public void testGetTypeFromMap() { mCatalystInstance.getJSModule(TestJSToJavaParametersModule.class) - .returnMapWithStringDoubleIntMapArrayBooleanNull(); + .returnMapWithStringDoubleIntMapArrayBooleanNull(); waitForBridgeAndUIIdle(); List calls = mRecordingTestModule.getMapCalls(); @@ -684,11 +706,25 @@ private static class CustomType { private final int foo; private final String bar; private final boolean baz; + private final Obj obj; + private final ReadableArray arr; + + CustomType(ReadableMap map) { + foo = map.getInt("foo"); + bar = map.getString("bar"); + baz = map.getBoolean("baz"); + obj = new CustomType.Obj(map.getMap("obj")); + arr = map.getArray("arr"); + } + + static class Obj { + private final String innerStr; + private final boolean innerBool; - CustomType(int foo, String bar, boolean baz) { - this.foo = foo; - this.bar = bar; - this.baz = baz; + Obj(ReadableMap obj) { + this.innerStr = obj.getString("innerStr"); + this.innerBool = obj.getBoolean("innerBool"); + } } } @@ -698,13 +734,10 @@ private class RecordingTestModule extends BaseJavaModule { @Nullable @Override public ArgumentExtractor get(Class type) { if (CustomType.class.isAssignableFrom(type)) { return new ArgumentExtractor() { - @Nullable @Override - public CustomType extractArgument( + @Nullable @Override public CustomType extractArgument( CatalystInstance catalystInstance, ExecutorToken executorToken, ReadableNativeArray jsArguments, int atIndex) { - ReadableNativeMap map = jsArguments.getMap(0); - return new CustomType(map.getInt("foo"), map.getString("bar"), - map.getBoolean("baz")); + return new CustomType(jsArguments.getMap(0)); } }; } else { @@ -714,9 +747,9 @@ public CustomType extractArgument( })); } - private final List mBasicTypesCalls = new ArrayList(); - private final List mArrayCalls = new ArrayList(); - private final List mMapCalls = new ArrayList(); + private final List mBasicTypesCalls = new ArrayList<>(); + private final List mArrayCalls = new ArrayList<>(); + private final List mMapCalls = new ArrayList<>(); private final List mCustomTypeCalls = new ArrayList<>(); @Override @@ -755,5 +788,9 @@ public List getArrayCalls() { public List getMapCalls() { return mMapCalls; } + + public List getCustomTypeCalls() { + return mCustomTypeCalls; + } } } diff --git a/ReactAndroid/src/androidTest/js/TestJSToJavaParametersModule.js b/ReactAndroid/src/androidTest/js/TestJSToJavaParametersModule.js index 57380f3bcba5d7..ef858539e8d09c 100644 --- a/ReactAndroid/src/androidTest/js/TestJSToJavaParametersModule.js +++ b/ReactAndroid/src/androidTest/js/TestJSToJavaParametersModule.js @@ -107,6 +107,18 @@ var TestJSToJavaParametersModule = { '\u017C\u00F3\u0142\u0107 g\u0119\u015Bl\u0105 \u6211 \uD83D\uDE0E ja\u017A\u0107' ]); }, + returnCustomType: function() { + Recording.receiveCustomType({ + foo: 1, + bar: "string", + baz: true, + obj: { + innerStr: 'other string', + innerBool: true + }, + arr: [1,'foo','bar'], + }); + }, }; BatchedBridge.registerCallableModule( From 8d9d8ca9ddc42d824ca8801bcd0a2db7a8e70252 Mon Sep 17 00:00:00 2001 From: Felipe Lima Date: Sun, 25 Sep 2016 19:05:27 -0700 Subject: [PATCH 4/5] Fix failing tests --- .../react/tests/CatalystNativeJSToJavaParametersTestCase.java | 2 +- .../main/java/com/facebook/react/bridge/BaseJavaModule.java | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/ReactAndroid/src/androidTest/java/com/facebook/react/tests/CatalystNativeJSToJavaParametersTestCase.java b/ReactAndroid/src/androidTest/java/com/facebook/react/tests/CatalystNativeJSToJavaParametersTestCase.java index 178f5d4e5c5670..81e7e61c174a70 100644 --- a/ReactAndroid/src/androidTest/java/com/facebook/react/tests/CatalystNativeJSToJavaParametersTestCase.java +++ b/ReactAndroid/src/androidTest/java/com/facebook/react/tests/CatalystNativeJSToJavaParametersTestCase.java @@ -702,7 +702,7 @@ private void mapGetByType(ReadableMap map, String key, String typeToAskFor) { } } - private static class CustomType { + static class CustomType { private final int foo; private final String bar; private final boolean baz; diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/BaseJavaModule.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/BaseJavaModule.java index 6d3bc3c2fa1198..b94a97a2692876 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/BaseJavaModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/BaseJavaModule.java @@ -521,8 +521,7 @@ private static char paramTypeToChar(Class paramClass) { } else if (paramClass == ReadableArray.class) { return 'A'; } else { - throw new RuntimeException( - "Got unknown param class: " + paramClass.getSimpleName()); + return 'M'; } } From 42e37f0d45b7086f8fab423f5140af8be1d3f908 Mon Sep 17 00:00:00 2001 From: Felipe Lima Date: Sat, 12 Nov 2016 10:39:48 -0800 Subject: [PATCH 5/5] Nits --- .../main/java/com/facebook/react/bridge/BaseJavaModule.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/BaseJavaModule.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/BaseJavaModule.java index a80a89c39bf330..80d8608460198e 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/BaseJavaModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/BaseJavaModule.java @@ -56,7 +56,7 @@ public abstract class BaseJavaModule implements NativeModule { // taken from Libraries/Utilities/MessageQueue.js private static final String METHOD_TYPE_ASYNC = "async"; private static final String METHOD_TYPE_PROMISE= "promise"; - static final public String METHOD_TYPE_SYNC = "sync"; + public static final String METHOD_TYPE_SYNC = "sync"; public static abstract class ArgumentExtractor { public int getJSArgumentsNeeded() { @@ -295,7 +295,7 @@ private ArgumentExtractor findArgumentExtractorForType(Class argumentClass private int calculateJSArgumentsNeeded() { int n = 0; - for (ArgumentExtractor extractor : mArgumentExtractors) { + for (ArgumentExtractor extractor : mArgumentExtractors) { n += extractor.getJSArgumentsNeeded(); } return n;