Skip to content

Commit

Permalink
feat(firestore): fix iOS Long/Double conversion #3004
Browse files Browse the repository at this point in the history
  • Loading branch information
Yonom committed Nov 25, 2021
1 parent 3d5d00d commit 88a8259
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public class ReactNativeFirebaseFirestoreSerialize {
private static final int INT_DOCUMENTID = 4;
private static final int INT_BOOLEAN_TRUE = 5;
private static final int INT_BOOLEAN_FALSE = 6;
private static final int INT_NUMBER = 7;
private static final int INT_DOUBLE = 7;
private static final int INT_STRING = 8;
private static final int INT_STRING_EMPTY = 9;
private static final int INT_ARRAY = 10;
Expand All @@ -70,6 +70,7 @@ public class ReactNativeFirebaseFirestoreSerialize {
private static final int INT_BLOB = 14;
private static final int INT_FIELDVALUE = 15;
private static final int INT_OBJECT = 16;
private static final int INT_INTEGER = 17;
private static final int INT_UNKNOWN = -999;

// Keys
Expand Down Expand Up @@ -300,7 +301,7 @@ private static WritableArray buildTypeMap(Object value) {
}

if (value instanceof Integer) {
typeArray.pushInt(INT_NUMBER);
typeArray.pushInt(INT_DOUBLE);
typeArray.pushDouble(((Integer) value).doubleValue());
return typeArray;
}
Expand All @@ -325,19 +326,19 @@ private static WritableArray buildTypeMap(Object value) {
return typeArray;
}

typeArray.pushInt(INT_NUMBER);
typeArray.pushInt(INT_DOUBLE);
typeArray.pushDouble(doubleValue);
return typeArray;
}

if (value instanceof Float) {
typeArray.pushInt(INT_NUMBER);
typeArray.pushInt(INT_DOUBLE);
typeArray.pushDouble(((Float) value).doubleValue());
return typeArray;
}

if (value instanceof Long) {
typeArray.pushInt(INT_NUMBER);
typeArray.pushInt(INT_DOUBLE);
typeArray.pushDouble(((Long) value).doubleValue());
return typeArray;
}
Expand Down Expand Up @@ -461,14 +462,10 @@ static Object parseTypeMap(FirebaseFirestore firestore, ReadableArray typeArray)
return true;
case INT_BOOLEAN_FALSE:
return false;
case INT_NUMBER:
// https://github.com/invertase/react-native-firebase/issues/3004
// Number values come from JS as Strings on Android so we can check for floating points
String numberStringValue = Objects.requireNonNull(typeArray.getString(1));
if (numberStringValue.contains(".")) {
return Double.valueOf(numberStringValue);
}
return Long.valueOf(numberStringValue, 10);
case INT_INTEGER:
return typeArray.getInt(1);
case INT_DOUBLE:
return typeArray.getDouble(1);
case INT_STRING:
return typeArray.getString(1);
case INT_STRING_EMPTY:
Expand Down
9 changes: 6 additions & 3 deletions packages/firestore/ios/RNFBFirestore/RNFBFirestoreSerialize.m
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ @implementation RNFBFirestoreSerialize
INT_DOCUMENTID,
INT_BOOLEAN_TRUE,
INT_BOOLEAN_FALSE,
INT_NUMBER,
INT_DOUBLE,
INT_STRING,
INT_STRING_EMPTY,
INT_ARRAY,
Expand All @@ -56,6 +56,7 @@ @implementation RNFBFirestoreSerialize
INT_BLOB,
INT_FIELDVALUE,
INT_OBJECT,
INT_INTEGER,
INT_UNKNOWN = -999,
};

Expand Down Expand Up @@ -336,7 +337,7 @@ + (NSArray *)buildTypeMap:(id)value {
}

// Number
typeArray[0] = @(INT_NUMBER);
typeArray[0] = @(INT_DOUBLE);
typeArray[1] = value;
return typeArray;
}
Expand Down Expand Up @@ -400,7 +401,9 @@ + (id)parseTypeMap:(FIRFirestore *)firestore typeMap:(NSArray *)typeMap {
return @(YES);
case INT_BOOLEAN_FALSE:
return @(NO);
case INT_NUMBER:
case INT_INTEGER:
return @([typeMap[1] longLongValue]);
case INT_DOUBLE:
return @([typeMap[1] doubleValue]);
case INT_STRING:
return typeMap[1];
Expand Down
13 changes: 8 additions & 5 deletions packages/firestore/lib/utils/serialize.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
*/

import {
isAndroid,
isArray,
isBoolean,
isDate,
Expand Down Expand Up @@ -139,10 +138,13 @@ export function generateNativeData(value, ignoreUndefined) {
}

if (isNumber(value)) {
if (isAndroid) {
return getTypeMapInt('number', value.toString());
// mirror the JS SDK's integer detection algorithm
// https://github.com/firebase/firebase-js-sdk/blob/086df7c7e0299cedd9f3cff9080f46ca25cab7cd/packages/firestore/src/remote/number_serializer.ts#L56
const isNegativeZero = value === 0 && 1 / value === -Infinity;
if (Number.isSafeInteger(value) && !isNegativeZero) {
return getTypeMapInt('integer', value);
}
return getTypeMapInt('number', value);
return getTypeMapInt('double', value);
}

if (isString(value)) {
Expand Down Expand Up @@ -254,7 +256,8 @@ export function parseNativeData(firestore, nativeArray) {
return true;
case 'booleanFalse':
return false;
case 'number':
case 'double':
case 'integer':
case 'string':
return value;
case 'stringEmpty':
Expand Down
3 changes: 2 additions & 1 deletion packages/firestore/lib/utils/typemap.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const MAP = {
documentid: 4, // to native only
booleanTrue: 5,
booleanFalse: 6,
number: 7,
double: 7,
string: 8,
stringEmpty: 9,
array: 10,
Expand All @@ -35,6 +35,7 @@ const MAP = {
blob: 14,
fieldvalue: 15,
object: 16,
integer: 17,
unknown: -999,
};

Expand Down

0 comments on commit 88a8259

Please sign in to comment.