Skip to content

Commit 41e9a60

Browse files
tsaichienmeta-codesync[bot]
authored andcommitted
Add isInteger to jsi::Value (facebook#56161)
Summary: Pull Request resolved: facebook#56161 Add a `isInteger` method under `jsi::Value` that returns true iff `Number.isInteger` returns true. This can be implemented without relying on the Runtime. Changelog: [Internal] Reviewed By: lavenzg Differential Revision: D96175707
1 parent 712fd05 commit 41e9a60

File tree

2 files changed

+59
-0
lines changed

2 files changed

+59
-0
lines changed

packages/react-native/ReactCommon/jsi/jsi/jsi.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#pragma once
99

1010
#include <cassert>
11+
#include <cmath>
1112
#include <cstdint>
1213
#include <cstring>
1314
#include <exception>
@@ -1899,6 +1900,28 @@ class JSI_EXPORT Value {
18991900
return kind_ == ObjectKind;
19001901
}
19011902

1903+
/// \returns true if `Number.isInteger(value)` returns true, false otherwise.
1904+
bool isInteger() const {
1905+
// 1. If number is an integral Number, return true.
1906+
// 2. Return false.
1907+
1908+
// The spec's definition of integral number:
1909+
// When the term integer is used in this specification, it refers to a
1910+
// mathematical value which is in the set of integers, unless otherwise
1911+
// stated. When the term integral Number is used in this specification, it
1912+
// refers to a finite Number value whose mathematical value is in the set of
1913+
// integers.
1914+
1915+
if (!isNumber()) {
1916+
return false;
1917+
}
1918+
auto number = data_.number;
1919+
if (!std::isfinite(number)) {
1920+
return false;
1921+
}
1922+
return number == std::trunc(number);
1923+
}
1924+
19021925
/// \return the boolean value, or asserts if not a boolean.
19031926
bool getBool() const {
19041927
assert(isBool());

packages/react-native/ReactCommon/jsi/jsi/test/testlib.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -974,6 +974,42 @@ TEST_P(JSITest, ValueTest) {
974974
EXPECT_EQ(eval("['zero',1,2,3]").toString(rt).utf8(rt), "zero,1,2,3");
975975
}
976976

977+
TEST_P(JSITest, IsIntegerTest) {
978+
// Non-number values should return false
979+
EXPECT_FALSE(Value::undefined().isInteger());
980+
EXPECT_FALSE(Value::null().isInteger());
981+
EXPECT_FALSE(Value(true).isInteger());
982+
EXPECT_FALSE(Value(false).isInteger());
983+
EXPECT_FALSE(Value(rt, String::createFromAscii(rt, "42")).isInteger());
984+
EXPECT_FALSE(Value(rt, Object(rt)).isInteger());
985+
986+
// NaN should return false
987+
EXPECT_FALSE(Value(std::numeric_limits<double>::quiet_NaN()).isInteger());
988+
989+
// Infinity should return false
990+
EXPECT_FALSE(Value(std::numeric_limits<double>::infinity()).isInteger());
991+
EXPECT_FALSE(Value(-std::numeric_limits<double>::infinity()).isInteger());
992+
993+
// Non-integer numbers should return false
994+
EXPECT_FALSE(Value(1.5).isInteger());
995+
EXPECT_FALSE(Value(-2.3).isInteger());
996+
EXPECT_FALSE(Value(0.1).isInteger());
997+
998+
// Integer numbers should return true
999+
EXPECT_TRUE(Value(0).isInteger());
1000+
EXPECT_TRUE(Value(0.0).isInteger());
1001+
EXPECT_TRUE(Value(-0.0).isInteger());
1002+
EXPECT_TRUE(Value(1).isInteger());
1003+
EXPECT_TRUE(Value(-1).isInteger());
1004+
EXPECT_TRUE(Value(42).isInteger());
1005+
EXPECT_TRUE(Value(1000000).isInteger());
1006+
EXPECT_TRUE(Value(-999999).isInteger());
1007+
1008+
// Large integers that can be exactly represented as doubles
1009+
EXPECT_TRUE(Value(static_cast<double>(1LL << 52)).isInteger());
1010+
EXPECT_TRUE(Value(static_cast<double>(-(1LL << 52))).isInteger());
1011+
}
1012+
9771013
TEST_P(JSITest, EqualsTest) {
9781014
EXPECT_TRUE(Object::strictEquals(rt, rt.global(), rt.global()));
9791015
EXPECT_TRUE(Value::strictEquals(rt, 1, 1));

0 commit comments

Comments
 (0)