Add dynamic type for javascript arguments passed over bridge with unkown type
Reviewed By: astreet Differential Revision: D4380882 fbshipit-source-id: f1b9fb9cf727d003dcc2264626e75fc300a47dee
This commit is contained in:
parent
3b5f04b002
commit
e3c8d80b3c
|
@ -16,6 +16,7 @@ import java.util.Set;
|
|||
|
||||
import com.facebook.react.bridge.BaseJavaModule;
|
||||
import com.facebook.react.bridge.CatalystInstance;
|
||||
import com.facebook.react.bridge.Dynamic;
|
||||
import com.facebook.react.bridge.InvalidIteratorException;
|
||||
import com.facebook.react.bridge.JavaScriptModule;
|
||||
import com.facebook.react.bridge.NoSuchKeyException;
|
||||
|
@ -45,6 +46,7 @@ public class CatalystNativeJSToJavaParametersTestCase extends ReactIntegrationTe
|
|||
|
||||
private interface TestJSToJavaParametersModule extends JavaScriptModule {
|
||||
void returnBasicTypes();
|
||||
void returnDynamicTypes();
|
||||
|
||||
void returnArrayWithBasicTypes();
|
||||
void returnNestedArray();
|
||||
|
@ -113,6 +115,17 @@ public class CatalystNativeJSToJavaParametersTestCase extends ReactIntegrationTe
|
|||
assertNull(args[3]);
|
||||
}
|
||||
|
||||
public void testDynamicType() {
|
||||
mCatalystInstance.getJSModule(TestJSToJavaParametersModule.class).returnDynamicTypes();
|
||||
waitForBridgeAndUIIdle();
|
||||
|
||||
List<Dynamic> dynamicCalls = mRecordingTestModule.getDynamicCalls();
|
||||
assertEquals(2, dynamicCalls.size());
|
||||
|
||||
assertEquals("foo", dynamicCalls.get(0).asString());
|
||||
assertEquals(3.14, dynamicCalls.get(1).asDouble());
|
||||
}
|
||||
|
||||
public void testArrayWithBasicTypes() {
|
||||
mCatalystInstance.getJSModule(TestJSToJavaParametersModule.class).returnArrayWithBasicTypes();
|
||||
waitForBridgeAndUIIdle();
|
||||
|
@ -673,6 +686,7 @@ public class CatalystNativeJSToJavaParametersTestCase extends ReactIntegrationTe
|
|||
private final List<Object[]> mBasicTypesCalls = new ArrayList<Object[]>();
|
||||
private final List<ReadableArray> mArrayCalls = new ArrayList<ReadableArray>();
|
||||
private final List<ReadableMap> mMapCalls = new ArrayList<ReadableMap>();
|
||||
private final List<Dynamic> mDynamicCalls = new ArrayList<Dynamic>();
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
|
@ -694,6 +708,11 @@ public class CatalystNativeJSToJavaParametersTestCase extends ReactIntegrationTe
|
|||
mMapCalls.add(map);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void receiveDynamic(Dynamic dynamic) {
|
||||
mDynamicCalls.add(dynamic);
|
||||
}
|
||||
|
||||
public List<Object[]> getBasicTypesCalls() {
|
||||
return mBasicTypesCalls;
|
||||
}
|
||||
|
@ -705,5 +724,9 @@ public class CatalystNativeJSToJavaParametersTestCase extends ReactIntegrationTe
|
|||
public List<ReadableMap> getMapCalls() {
|
||||
return mMapCalls;
|
||||
}
|
||||
|
||||
public List<Dynamic> getDynamicCalls() {
|
||||
return mDynamicCalls;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,10 @@ var TestJSToJavaParametersModule = {
|
|||
returnBasicTypes: function() {
|
||||
Recording.receiveBasicTypes('foo', 3.14, true, null);
|
||||
},
|
||||
returnDynamicTypes: function() {
|
||||
Recording.receiveDynamic('foo');
|
||||
Recording.receiveDynamic(3.14);
|
||||
},
|
||||
returnArrayWithBasicTypes: function() {
|
||||
Recording.receiveArray(['foo', 3.14, -111, true, null]);
|
||||
},
|
||||
|
|
|
@ -116,6 +116,15 @@ public abstract class BaseJavaModule implements NativeModule {
|
|||
}
|
||||
};
|
||||
|
||||
static final private ArgumentExtractor<Dynamic> ARGUMENT_EXTRACTOR_DYNAMIC =
|
||||
new ArgumentExtractor<Dynamic>() {
|
||||
@Override
|
||||
public Dynamic extractArgument(
|
||||
CatalystInstance catalystInstance, ExecutorToken executorToken, ReadableNativeArray jsArguments, int atIndex) {
|
||||
return new DynamicFromArray(jsArguments, atIndex);
|
||||
}
|
||||
};
|
||||
|
||||
static final private ArgumentExtractor<ReadableMap> ARGUMENT_EXTRACTOR_MAP =
|
||||
new ArgumentExtractor<ReadableMap>() {
|
||||
@Override
|
||||
|
@ -259,6 +268,8 @@ public abstract class BaseJavaModule implements NativeModule {
|
|||
argumentExtractors[i] = ARGUMENT_EXTRACTOR_MAP;
|
||||
} else if (argumentClass == ReadableArray.class) {
|
||||
argumentExtractors[i] = ARGUMENT_EXTRACTOR_ARRAY;
|
||||
} else if (argumentClass == Dynamic.class) {
|
||||
argumentExtractors[i] = ARGUMENT_EXTRACTOR_DYNAMIC;
|
||||
} else {
|
||||
throw new RuntimeException(
|
||||
"Got unknown argument class: " + argumentClass.getSimpleName());
|
||||
|
@ -484,6 +495,8 @@ public abstract class BaseJavaModule implements NativeModule {
|
|||
return 'M';
|
||||
} else if (paramClass == ReadableArray.class) {
|
||||
return 'A';
|
||||
} else if (paramClass == Dynamic.class) {
|
||||
return 'Y';
|
||||
} else {
|
||||
throw new RuntimeException(
|
||||
"Got unknown param class: " + paramClass.getSimpleName());
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package com.facebook.react.bridge;
|
||||
|
||||
/**
|
||||
* Type representing a piece of data with unkown runtime type. Useful for allowing javascript to
|
||||
* pass one of multiple types down to the native layer.
|
||||
*/
|
||||
public interface Dynamic {
|
||||
boolean asBoolean();
|
||||
double asDouble();
|
||||
int asInt();
|
||||
String asString();
|
||||
ReadableArray asArray();
|
||||
ReadableMap asMap();
|
||||
ReadableType getType();
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package com.facebook.react.bridge;
|
||||
|
||||
/**
|
||||
* Implementation of Dynamic wrapping a ReadableArray.
|
||||
*/
|
||||
public class DynamicFromArray implements Dynamic {
|
||||
|
||||
private final ReadableArray mArray;
|
||||
private final int mIndex;
|
||||
|
||||
public DynamicFromArray(ReadableArray array, int index) {
|
||||
mArray = array;
|
||||
mIndex = index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean asBoolean() {
|
||||
return mArray.getBoolean(mIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double asDouble() {
|
||||
return mArray.getDouble(mIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int asInt() {
|
||||
return mArray.getInt(mIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asString() {
|
||||
return mArray.getString(mIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadableArray asArray() {
|
||||
return mArray.getArray(mIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadableMap asMap() {
|
||||
return mArray.getMap(mIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadableType getType() {
|
||||
return mArray.getType(mIndex);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package com.facebook.react.bridge;
|
||||
|
||||
/**
|
||||
* Implementation of Dynamic wrapping a ReadableMap.
|
||||
*/
|
||||
public class DynamicFromMap implements Dynamic {
|
||||
|
||||
private final ReadableMap mMap;
|
||||
private final String mName;
|
||||
|
||||
public DynamicFromMap(ReadableMap map, String name) {
|
||||
mMap = map;
|
||||
mName = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean asBoolean() {
|
||||
return mMap.getBoolean(mName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double asDouble() {
|
||||
return mMap.getDouble(mName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int asInt() {
|
||||
return mMap.getInt(mName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asString() {
|
||||
return mMap.getString(mName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadableArray asArray() {
|
||||
return mMap.getArray(mName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadableMap asMap() {
|
||||
return mMap.getMap(mName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadableType getType() {
|
||||
return mMap.getType(mName);
|
||||
}
|
||||
}
|
|
@ -88,6 +88,11 @@ public class JavaOnlyArray implements ReadableArray, WritableArray {
|
|||
return (JavaOnlyMap) mBackingList.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dynamic getDynamic(int index) {
|
||||
return new DynamicFromArray(this, index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadableType getType(int index) {
|
||||
Object object = mBackingList.get(index);
|
||||
|
|
|
@ -88,6 +88,11 @@ public class JavaOnlyMap implements ReadableMap, WritableMap {
|
|||
return (JavaOnlyArray) mBackingMap.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dynamic getDynamic(String name) {
|
||||
return new DynamicFromMap(this, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadableType getType(String name) {
|
||||
Object value = mBackingMap.get(name);
|
||||
|
@ -103,6 +108,8 @@ public class JavaOnlyMap implements ReadableMap, WritableMap {
|
|||
return ReadableType.Map;
|
||||
} else if (value instanceof ReadableArray) {
|
||||
return ReadableType.Array;
|
||||
} else if (value instanceof Dynamic) {
|
||||
return ((Dynamic) value).getType();
|
||||
} else {
|
||||
throw new IllegalArgumentException("Invalid value " + value.toString() + " for key " + name +
|
||||
"contained in JavaOnlyMap");
|
||||
|
|
|
@ -23,5 +23,6 @@ public interface ReadableArray {
|
|||
String getString(int index);
|
||||
ReadableArray getArray(int index);
|
||||
ReadableMap getMap(int index);
|
||||
Dynamic getDynamic(int index);
|
||||
ReadableType getType(int index);
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ public interface ReadableMap {
|
|||
String getString(String name);
|
||||
ReadableArray getArray(String name);
|
||||
ReadableMap getMap(String name);
|
||||
Dynamic getDynamic(String name);
|
||||
ReadableType getType(String name);
|
||||
ReadableMapKeySetIterator keySetIterator();
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ package com.facebook.react.bridge;
|
|||
|
||||
import com.facebook.jni.HybridData;
|
||||
import com.facebook.proguard.annotations.DoNotStrip;
|
||||
import com.facebook.soloader.SoLoader;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
|
@ -48,6 +47,11 @@ public class ReadableNativeArray extends NativeArray implements ReadableArray {
|
|||
@Override
|
||||
public native ReadableType getType(int index);
|
||||
|
||||
@Override
|
||||
public Dynamic getDynamic(int index) {
|
||||
return new DynamicFromArray(this, index);
|
||||
}
|
||||
|
||||
public ArrayList<Object> toArrayList() {
|
||||
ArrayList<Object> arrayList = new ArrayList<>();
|
||||
|
||||
|
|
|
@ -11,11 +11,9 @@ package com.facebook.react.bridge;
|
|||
|
||||
import com.facebook.jni.HybridData;
|
||||
import com.facebook.proguard.annotations.DoNotStrip;
|
||||
import com.facebook.soloader.SoLoader;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of a read-only map in native memory. This will generally be constructed and filled
|
||||
* in native code so you shouldn't construct one yourself.
|
||||
|
@ -49,6 +47,11 @@ public class ReadableNativeMap extends NativeMap implements ReadableMap {
|
|||
@Override
|
||||
public native ReadableType getType(String name);
|
||||
|
||||
@Override
|
||||
public Dynamic getDynamic(String name) {
|
||||
return new DynamicFromMap(this, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadableMapKeySetIterator keySetIterator() {
|
||||
return new ReadableNativeMapKeySetIterator(this);
|
||||
|
|
|
@ -33,6 +33,7 @@ import java.util.Set;
|
|||
import com.facebook.infer.annotation.SuppressFieldNotInitialized;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.bridge.Dynamic;
|
||||
import com.facebook.react.uimanager.annotations.ReactPropertyHolder;
|
||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
import com.facebook.react.uimanager.annotations.ReactPropGroup;
|
||||
|
@ -68,6 +69,7 @@ public class ReactPropertyProcessor extends AbstractProcessor {
|
|||
private static final TypeName STRING_TYPE = TypeName.get(String.class);
|
||||
private static final TypeName READABLE_MAP_TYPE = TypeName.get(ReadableMap.class);
|
||||
private static final TypeName READABLE_ARRAY_TYPE = TypeName.get(ReadableArray.class);
|
||||
private static final TypeName DYNAMIC_TYPE = TypeName.get(Dynamic.class);
|
||||
|
||||
private static final TypeName VIEW_MANAGER_TYPE =
|
||||
ClassName.get("com.facebook.react.uimanager", "ViewManager");
|
||||
|
@ -118,6 +120,7 @@ public class ReactPropertyProcessor extends AbstractProcessor {
|
|||
DEFAULT_TYPES.put(STRING_TYPE, "String");
|
||||
DEFAULT_TYPES.put(READABLE_ARRAY_TYPE, "Array");
|
||||
DEFAULT_TYPES.put(READABLE_MAP_TYPE, "Map");
|
||||
DEFAULT_TYPES.put(DYNAMIC_TYPE, "Dynamic");
|
||||
|
||||
BOXED_PRIMITIVES = new HashSet<>();
|
||||
BOXED_PRIMITIVES.add(TypeName.BOOLEAN.box());
|
||||
|
@ -365,6 +368,8 @@ public class ReactPropertyProcessor extends AbstractProcessor {
|
|||
return builder.add("props.getArray(name)");
|
||||
} else if (propertyType.equals(READABLE_MAP_TYPE)) {
|
||||
return builder.add("props.getMap(name)");
|
||||
} else if (propertyType.equals(DYNAMIC_TYPE)) {
|
||||
return builder.add("props.getDynamic(name)");
|
||||
}
|
||||
|
||||
if (BOXED_PRIMITIVES.contains(propertyType)) {
|
||||
|
|
|
@ -15,6 +15,7 @@ import android.view.View;
|
|||
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.bridge.Dynamic;
|
||||
|
||||
/**
|
||||
* Wrapper for {@link ReadableMap} which should be used for styles property map. It extends
|
||||
|
@ -82,6 +83,11 @@ public class ReactStylesDiffMap {
|
|||
return mBackingMap.getMap(key);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Dynamic getDynamic(String key) {
|
||||
return mBackingMap.getDynamic(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{ " + getClass().getSimpleName() + ": " + mBackingMap.toString() + " }";
|
||||
|
|
Loading…
Reference in New Issue