diff --git a/Libraries/StyleSheet/processColor.js b/Libraries/StyleSheet/processColor.js index 059450c15..34f4df5fe 100644 --- a/Libraries/StyleSheet/processColor.js +++ b/Libraries/StyleSheet/processColor.js @@ -11,6 +11,7 @@ 'use strict'; var tinycolor = require('tinycolor2'); +var Platform = require('Platform'); function processColor(color) { if (!color || typeof color === 'number') { @@ -19,7 +20,15 @@ function processColor(color) { return color.map(processColor); } else { var hexString = tinycolor(color).toHex8(); - return parseInt(hexString, 16); + var colorInt = parseInt(hexString, 16); + if (Platform.OS === 'android') { + // Android use 32 bit *signed* integer to represent the color + // We utilize the fact that bitwise operations in JS also operates on + // signed 32 bit integers, so that we can use those to convert from + // *unsiged* to *signed* 32bit int that way. + colorInt = colorInt | 0x0; + } + return colorInt; } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableArray.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableArray.java index 5bb5faf20..47e5ed30c 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableArray.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableArray.java @@ -20,8 +20,6 @@ public interface ReadableArray { boolean getBoolean(int index); double getDouble(int index); int getInt(int index); - // Check CatalystStylesDiffMap#getColorInt() to see why this is needed - int getColorInt(int index); String getString(int index); ReadableArray getArray(int index); ReadableMap getMap(int index); diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableMap.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableMap.java index 22b8a8312..5aa5adb43 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableMap.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableMap.java @@ -20,8 +20,6 @@ public interface ReadableMap { boolean getBoolean(String name); double getDouble(String name); int getInt(String name); - // Check CatalystStylesDiffMap#getColorInt() to see why this is needed - int getColorInt(String name); String getString(String name); ReadableArray getArray(String name); ReadableMap getMap(String name); diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeArray.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeArray.java index 388e66553..cf4a31cb4 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeArray.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeArray.java @@ -32,6 +32,8 @@ public class ReadableNativeArray extends NativeArray implements ReadableArray { @Override public native double getDouble(int index); @Override + public native int getInt(int index); + @Override public native String getString(int index); @Override public native ReadableNativeArray getArray(int index); @@ -39,15 +41,4 @@ public class ReadableNativeArray extends NativeArray implements ReadableArray { public native ReadableNativeMap getMap(int index); @Override public native ReadableType getType(int index); - - @Override - public int getInt(int index) { - return (int) getDouble(index); - } - - // Check CatalystStylesDiffMap#getColorInt() to see why this is needed - @Override - public int getColorInt(int index) { - return (int) (long) getDouble(index); - } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeMap.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeMap.java index b819a79cb..ac1eabbb1 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeMap.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeMap.java @@ -33,6 +33,8 @@ public class ReadableNativeMap extends NativeMap implements ReadableMap { @Override public native double getDouble(String name); @Override + public native int getInt(String name); + @Override public native String getString(String name); @Override public native ReadableNativeArray getArray(String name); @@ -46,16 +48,6 @@ public class ReadableNativeMap extends NativeMap implements ReadableMap { return new ReadableNativeMapKeySeyIterator(this); } - @Override - public int getInt(String name) { - return (int) getDouble(name); - } - - // Check CatalystStylesDiffMap#getColorInt() to see why this is needed - @Override - public int getColorInt(String name) { - return (int) (long) getDouble(name); - } /** * Implementation of a {@link ReadableNativeMap} iterator in native memory. */ diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/WritableNativeArray.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/WritableNativeArray.java index e10a0b57d..ce748c0db 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/WritableNativeArray.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/WritableNativeArray.java @@ -32,12 +32,9 @@ public class WritableNativeArray extends ReadableNativeArray implements Writable @Override public native void pushDouble(double value); @Override - public native void pushString(String value); - + public native void pushInt(int value); @Override - public void pushInt(int value) { - pushDouble(value); - } + public native void pushString(String value); // Note: this consumes the map so do not reuse it. @Override diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/WritableNativeMap.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/WritableNativeMap.java index c630a59b5..1388be0ce 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/WritableNativeMap.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/WritableNativeMap.java @@ -30,15 +30,12 @@ public class WritableNativeMap extends ReadableNativeMap implements WritableMap @Override public native void putDouble(String key, double value); @Override + public native void putInt(String key, int value); + @Override public native void putString(String key, String value); @Override public native void putNull(String key); - @Override - public void putInt(String key, int value) { - putDouble(key, value); - } - // Note: this consumes the map so do not reuse it. @Override public void putMap(String key, WritableMap value) { diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewPropertyApplicator.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewPropertyApplicator.java index aa8019057..2b2b0b0f7 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewPropertyApplicator.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewPropertyApplicator.java @@ -73,7 +73,7 @@ public class BaseViewPropertyApplicator { public static void applyCommonViewProperties(View view, CatalystStylesDiffMap props) { if (props.hasKey(ViewProps.BACKGROUND_COLOR)) { - final int backgroundColor = props.getColorInt(ViewProps.BACKGROUND_COLOR, Color.TRANSPARENT); + final int backgroundColor = props.getInt(ViewProps.BACKGROUND_COLOR, Color.TRANSPARENT); view.setBackgroundColor(backgroundColor); } if (props.hasKey(PROP_DECOMPOSED_MATRIX)) { diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/CSSColorUtil.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/CSSColorUtil.java deleted file mode 100644 index e61150ba9..000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/CSSColorUtil.java +++ /dev/null @@ -1,155 +0,0 @@ -/** - * 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.uimanager; - -import java.util.HashMap; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import android.graphics.Color; - -import com.facebook.react.bridge.JSApplicationIllegalArgumentException; -import com.facebook.react.common.annotations.VisibleForTesting; - -/** - * Translates the different color formats to their actual colors. - */ -public class CSSColorUtil { - - static final Pattern RGB_COLOR_PATTERN = - Pattern.compile("rgb\\(\\s*([0-9]{1,3}),\\s*([0-9]{1,3}),\\s*([0-9]{1,3})\\s*\\)"); - - static final Pattern RGBA_COLOR_PATTERN = Pattern.compile( - "rgba\\(\\s*([0-9]{1,3}),\\s*([0-9]{1,3}),\\s*([0-9]{1,3})\\s*,\\s*(0*(\\.\\d{1,3})?|1(\\.0+)?)\\)"); - - private static final HashMap sColorNameMap = new HashMap(); - - static { - // List of HTML4 colors: http://www.w3.org/TR/css3-color/#html4 - sColorNameMap.put("black", Color.argb(255, 0, 0, 0)); - sColorNameMap.put("silver", Color.argb(255, 192, 192, 192)); - sColorNameMap.put("gray", Color.argb(255, 128, 128, 128)); - sColorNameMap.put("grey", Color.argb(255, 128, 128, 128)); - sColorNameMap.put("white", Color.argb(255, 255, 255, 255)); - sColorNameMap.put("maroon", Color.argb(255, 128, 0, 0)); - sColorNameMap.put("red", Color.argb(255, 255, 0, 0)); - sColorNameMap.put("purple", Color.argb(255, 128, 0, 128)); - sColorNameMap.put("fuchsia", Color.argb(255, 255, 0, 255)); - sColorNameMap.put("green", Color.argb(255, 0, 128, 0)); - sColorNameMap.put("lime", Color.argb(255, 0, 255, 0)); - sColorNameMap.put("olive", Color.argb(255, 128, 128, 0)); - sColorNameMap.put("yellow", Color.argb(255, 255, 255, 0)); - sColorNameMap.put("navy", Color.argb(255, 0, 0, 128)); - sColorNameMap.put("blue", Color.argb(255, 0, 0, 255)); - sColorNameMap.put("teal", Color.argb(255, 0, 128, 128)); - sColorNameMap.put("aqua", Color.argb(255, 0, 255, 255)); - - // Extended colors - sColorNameMap.put("orange", Color.argb(255, 255, 165, 0)); - sColorNameMap.put("transparent", Color.argb(0, 0, 0, 0)); - } - - /** - * Parses the given color string and returns the corresponding color int value. - * - * The following color formats are supported: - * - * @param colorString the string representation of the color - * @return the color int - */ - public static int getColor(String colorString) { - if (colorString.startsWith("rgb(")) { - Matcher rgbMatcher = RGB_COLOR_PATTERN.matcher(colorString); - if (rgbMatcher.matches()) { - return Color.rgb( - validateColorComponent(Integer.parseInt(rgbMatcher.group(1))), - validateColorComponent(Integer.parseInt(rgbMatcher.group(2))), - validateColorComponent(Integer.parseInt(rgbMatcher.group(3)))); - } else { - throw new JSApplicationIllegalArgumentException("Invalid color: " + colorString); - } - } else if (colorString.startsWith("rgba(")) { - Matcher rgbaMatcher = RGBA_COLOR_PATTERN.matcher(colorString); - if (rgbaMatcher.matches()) { - return Color.argb( - (int) (Float.parseFloat(rgbaMatcher.group(4)) * 255), - validateColorComponent(Integer.parseInt(rgbaMatcher.group(1))), - validateColorComponent(Integer.parseInt(rgbaMatcher.group(2))), - validateColorComponent(Integer.parseInt(rgbaMatcher.group(3)))); - } else { - throw new JSApplicationIllegalArgumentException("Invalid color: " + colorString); - } - } else if (colorString.startsWith("#")) { - if (colorString.length() == 4) { - int r = parseHexChar(colorString.charAt(1)); - int g = parseHexChar(colorString.charAt(2)); - int b = parseHexChar(colorString.charAt(3)); - - // double the character - // since parseHexChar only returns values from 0-15, we don't need & 0xff - r = r | (r << 4); - g = g | (g << 4); - b = b | (b << 4); - return Color.rgb(r, g, b); - } else { - // check if we have #RRGGBB - if (colorString.length() == 7) { - // Color.parseColor(...) can throw an IllegalArgumentException("Unknown color"). - // For consistency, we hide the original exception and throw our own exception instead. - try { - return Color.parseColor(colorString); - } catch (IllegalArgumentException ex) { - throw new JSApplicationIllegalArgumentException("Invalid color: " + colorString); - } - } else { - throw new JSApplicationIllegalArgumentException("Invalid color: " + colorString); - } - } - } else { - Integer color = sColorNameMap.get(colorString.toLowerCase()); - if (color != null) { - return color; - } - throw new JSApplicationIllegalArgumentException("Unknown color: " + colorString); - } - } - - /** - * Convert a single hex character (0-9, a-f, A-F) to a number (0-15). - * - * @param hexChar the hex character to convert - * @return the value between 0 and 15 - */ - @VisibleForTesting - /*package*/ static int parseHexChar(char hexChar) { - if (hexChar >= '0' && hexChar <= '9') { - return hexChar - '0'; - } else if (hexChar >= 'A' && hexChar <= 'F') { - return hexChar - 'A' + 10; - } else if (hexChar >= 'a' && hexChar <= 'f') { - return hexChar - 'a' + 10; - } - throw new JSApplicationIllegalArgumentException("Invalid hex character: " + hexChar); - } - - private static int validateColorComponent(int color) { - if (color < 0 || color > 255) { - throw new JSApplicationIllegalArgumentException("Invalid color component: " + color); - } - return color; - } - -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/CatalystStylesDiffMap.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/CatalystStylesDiffMap.java index 4ae0dadc2..e2a01ea62 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/CatalystStylesDiffMap.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/CatalystStylesDiffMap.java @@ -64,18 +64,7 @@ public class CatalystStylesDiffMap { } public int getInt(String name, int restoreNullToDefaultValue) { - return mBackingMap.isNull(name) ? restoreNullToDefaultValue : (int) mBackingMap.getDouble(name); - } - - // Colors have values between 0x00000000 and 0xFFFFFFFF, which fits in an integer, but is sent as - // a double over the bridge. Because color values can be higher than Integer.MAX_VALUE, it is not - // correct to convert doubles to int directly, since they can be truncated to Integer.MAX_VALUE - // instead of being converted to negative values. Converting from double to long maintains the - // initial value, and is then correctly converted to int. This is the expected behavior according - // to the java spec, see http://stackoverflow.com/questions/10641559 for more. - public int getColorInt(String name, int restoreNullToDefaultValue) { - return mBackingMap.isNull(name) ? restoreNullToDefaultValue : - (int) (long) mBackingMap.getDouble(name); + return mBackingMap.isNull(name) ? restoreNullToDefaultValue : mBackingMap.getInt(name); } @Nullable diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageManager.java index a3e64df44..ec4907487 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageManager.java @@ -80,7 +80,7 @@ public class ReactImageManager extends SimpleViewManager { if (props.isNull(PROP_TINT_COLOR)) { view.clearColorFilter(); } else { - final int tintColor = props.getColorInt(PROP_TINT_COLOR, Color.TRANSPARENT); + final int tintColor = props.getInt(PROP_TINT_COLOR, Color.TRANSPARENT); view.setColorFilter(tintColor); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextShadowNode.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextShadowNode.java index e50fd7e02..8fb0ee4d6 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextShadowNode.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextShadowNode.java @@ -310,7 +310,7 @@ public class ReactTextShadowNode extends ReactShadowNode { if (styles.isNull(ViewProps.COLOR)) { mIsColorSet = false; } else { - mColor = styles.getColorInt(ViewProps.COLOR, Color.TRANSPARENT); + mColor = styles.getInt(ViewProps.COLOR, Color.TRANSPARENT); mIsColorSet = true; } markUpdated(); @@ -319,7 +319,7 @@ public class ReactTextShadowNode extends ReactShadowNode { if (styles.isNull(ViewProps.BACKGROUND_COLOR)) { mIsBackgroundColorSet = false; } else { - mBackgroundColor = styles.getColorInt(ViewProps.BACKGROUND_COLOR, Color.TRANSPARENT); + mBackgroundColor = styles.getInt(ViewProps.BACKGROUND_COLOR, Color.TRANSPARENT); mIsBackgroundColorSet = true; } markUpdated(); diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java index 81ea5eded..1ec44e25d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java @@ -195,7 +195,7 @@ public class ReactTextInputManager extends ViewManager { toolbar.setSubtitle(props.getString(PROP_SUBTITLE)); } if (props.hasKey(PROP_SUBTITLE_COLOR)) { - final int subtitleColor = props.getColorInt(PROP_SUBTITLE_COLOR, defaultColors[1]); + final int subtitleColor = props.getInt(PROP_SUBTITLE_COLOR, defaultColors[1]); toolbar.setSubtitleTextColor(subtitleColor); } if (props.hasKey(PROP_TITLE)) { toolbar.setTitle(props.getString(PROP_TITLE)); } if (props.hasKey(PROP_TITLE_COLOR)) { - final int titleColor = props.getColorInt(PROP_TITLE_COLOR, defaultColors[0]); + final int titleColor = props.getInt(PROP_TITLE_COLOR, defaultColors[0]); toolbar.setTitleTextColor(titleColor); } if (props.hasKey(PROP_NAV_ICON)) { diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactDrawableHelper.java b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactDrawableHelper.java index 80b5fbbaf..8cf2d3e26 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactDrawableHelper.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactDrawableHelper.java @@ -63,7 +63,7 @@ import com.facebook.react.uimanager.ViewProps; int color; if (drawableDescriptionDict.hasKey(ViewProps.COLOR) && !drawableDescriptionDict.isNull(ViewProps.COLOR)) { - color = drawableDescriptionDict.getColorInt(ViewProps.COLOR); + color = drawableDescriptionDict.getInt(ViewProps.COLOR); } else { if (context.getTheme().resolveAttribute( android.R.attr.colorControlHighlight, diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java index f2dbb325c..2b4c425d6 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java @@ -106,7 +106,7 @@ public class ReactViewManager extends ViewGroupManager { float color = CSSConstants.UNDEFINED; if (!props.isNull(PROPS_BORDER_COLOR[i])) { // Check CatalystStylesDiffMap#getColorInt() to see why this is needed - int colorInt = props.getColorInt(PROPS_BORDER_COLOR[i], Color.TRANSPARENT); + int colorInt = props.getInt(PROPS_BORDER_COLOR[i], Color.TRANSPARENT); color = colorInt; } view.setBorderColor(SPACING_TYPES[i], color); diff --git a/ReactAndroid/src/main/jni/react/jni/OnLoad.cpp b/ReactAndroid/src/main/jni/react/jni/OnLoad.cpp index 76114c310..c471480ed 100644 --- a/ReactAndroid/src/main/jni/react/jni/OnLoad.cpp +++ b/ReactAndroid/src/main/jni/react/jni/OnLoad.cpp @@ -27,7 +27,7 @@ static jmethodID gReadableNativeMapCtor; namespace exceptions { -static const char *gUnknownNativeTypeExceptionClass = +static const char *gUnexpectedNativeTypeExceptionClass = "com/facebook/react/bridge/UnexpectedNativeTypeException"; template @@ -65,7 +65,7 @@ static jobject createReadableNativeMapWithContents(JNIEnv* env, folly::dynamic m } if (!map.isObject()) { - throwNewJavaException(exceptions::gUnknownNativeTypeExceptionClass, + throwNewJavaException(exceptions::gUnexpectedNativeTypeExceptionClass, "expected Map, got a %s", map.typeName()); } @@ -120,7 +120,7 @@ static jobject getType(folly::dynamic::Type type) { case folly::dynamic::Type::ARRAY: return type::gTypeArrayValue; default: - throwNewJavaException(exceptions::gUnknownNativeTypeExceptionClass, "Unknown type"); + throwNewJavaException(exceptions::gUnexpectedNativeTypeExceptionClass, "Unknown type"); } } @@ -129,7 +129,7 @@ static jobject getType(folly::dynamic::Type type) { struct ReadableNativeArray : public NativeArray { static void mapException(const std::exception& ex) { if (dynamic_cast(&ex) != 0) { - throwNewJavaException(exceptions::gUnknownNativeTypeExceptionClass, ex.what()); + throwNewJavaException(exceptions::gUnexpectedNativeTypeExceptionClass, ex.what()); } } @@ -153,6 +153,17 @@ struct ReadableNativeArray : public NativeArray { return val.getDouble(); } + jint getInt(jint index) { + auto integer = array.at(index).getInt(); + jint javaint = static_cast(integer); + if (integer != javaint) { + throwNewJavaException( + exceptions::gUnexpectedNativeTypeExceptionClass, + "Value '%lld' doesn't fit into a 32 bit signed int", integer); + } + return javaint; + } + jstring getString(jint index) { const folly::dynamic& dyn = array.at(index); if (dyn.isNull()) { @@ -179,6 +190,7 @@ struct ReadableNativeArray : public NativeArray { makeNativeMethod("isNull", ReadableNativeArray::isNull), makeNativeMethod("getBoolean", ReadableNativeArray::getBoolean), makeNativeMethod("getDouble", ReadableNativeArray::getDouble), + makeNativeMethod("getInt", ReadableNativeArray::getInt), makeNativeMethod("getString", ReadableNativeArray::getString), makeNativeMethod("getArray", "(I)Lcom/facebook/react/bridge/ReadableNativeArray;", ReadableNativeArray::getArray), @@ -206,6 +218,11 @@ struct WritableNativeArray : public ReadableNativeArray { array.push_back(value); } + void pushInt(jint value) { + exceptions::throwIfObjectAlreadyConsumed(this, "Receiving array already consumed"); + array.push_back(value); + } + void pushString(jstring value) { if (value == NULL) { pushNull(); @@ -243,6 +260,7 @@ struct WritableNativeArray : public ReadableNativeArray { makeNativeMethod("pushNull", WritableNativeArray::pushNull), makeNativeMethod("pushBoolean", WritableNativeArray::pushBoolean), makeNativeMethod("pushDouble", WritableNativeArray::pushDouble), + makeNativeMethod("pushInt", WritableNativeArray::pushInt), makeNativeMethod("pushString", WritableNativeArray::pushString), makeNativeMethod("pushNativeArray", "(Lcom/facebook/react/bridge/WritableNativeArray;)V", WritableNativeArray::pushArray), @@ -287,6 +305,12 @@ static void putDouble(JNIEnv* env, jobject obj, jstring key, jdouble value) { map->map.insert(fromJString(env, key), value); } +static void putInt(JNIEnv* env, jobject obj, jstring key, jint value) { + auto map = extractRefPtr(env, obj); + exceptions::throwIfObjectAlreadyConsumed(map, "Receiving map already consumed"); + map->map.insert(fromJString(env, key), value); +} + static void putString(JNIEnv* env, jobject obj, jstring key, jstring value) { if (value == NULL) { putNull(env, obj, key); @@ -368,7 +392,7 @@ static jboolean getBooleanKey(JNIEnv* env, jobject obj, jstring keyName) { try { return getMapValue(env, obj, keyName).getBool() ? JNI_TRUE : JNI_FALSE; } catch (const folly::TypeError& ex) { - throwNewJavaException(exceptions::gUnknownNativeTypeExceptionClass, ex.what()); + throwNewJavaException(exceptions::gUnexpectedNativeTypeExceptionClass, ex.what()); } } @@ -380,7 +404,22 @@ static jdouble getDoubleKey(JNIEnv* env, jobject obj, jstring keyName) { try { return val.getDouble(); } catch (const folly::TypeError& ex) { - throwNewJavaException(exceptions::gUnknownNativeTypeExceptionClass, ex.what()); + throwNewJavaException(exceptions::gUnexpectedNativeTypeExceptionClass, ex.what()); + } +} + +static jint getIntKey(JNIEnv* env, jobject obj, jstring keyName) { + try { + auto integer = getMapValue(env, obj, keyName).getInt(); + jint javaint = static_cast(integer); + if (integer != javaint) { + throwNewJavaException( + exceptions::gUnexpectedNativeTypeExceptionClass, + "Value '%lld' doesn't fit into a 32 bit signed int", integer); + } + return javaint; + } catch (const folly::TypeError& ex) { + throwNewJavaException(exceptions::gUnexpectedNativeTypeExceptionClass, ex.what()); } } @@ -393,7 +432,7 @@ static jstring getStringKey(JNIEnv* env, jobject obj, jstring keyName) { LocalString value(val.getString().c_str()); return static_cast(env->NewLocalRef(value.string())); } catch (const folly::TypeError& ex) { - throwNewJavaException(exceptions::gUnknownNativeTypeExceptionClass, ex.what()); + throwNewJavaException(exceptions::gUnexpectedNativeTypeExceptionClass, ex.what()); } } @@ -651,6 +690,7 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { makeNativeMethod("isNull", map::readable::isNull), makeNativeMethod("getBoolean", map::readable::getBooleanKey), makeNativeMethod("getDouble", map::readable::getDoubleKey), + makeNativeMethod("getInt", map::readable::getIntKey), makeNativeMethod("getString", map::readable::getStringKey), makeNativeMethod( "getArray", "(Ljava/lang/String;)Lcom/facebook/react/bridge/ReadableNativeArray;", @@ -667,6 +707,7 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { makeNativeMethod("putNull", map::writable::putNull), makeNativeMethod("putBoolean", map::writable::putBoolean), makeNativeMethod("putDouble", map::writable::putDouble), + makeNativeMethod("putInt", map::writable::putInt), makeNativeMethod("putString", map::writable::putString), makeNativeMethod( "putNativeArray", "(Ljava/lang/String;Lcom/facebook/react/bridge/WritableNativeArray;)V",