Skip to content

Commit b2882e4

Browse files
tsaichienfacebook-github-bot
authored andcommitted
Fix JSI isArray method to match JS Array.isArray
Summary: There is currently an assumption that JSI arrays are always `vm::JSArrays`, and thus JSI method `isArray` only return true if it is an `vm::JSArray` . However, the JSI spec states `isArray` should follow JS `Array.isArray`. This diff fixes this and treats `JSI::Array` as normal objects. Reviewed By: tmikov Differential Revision: D67408956 fbshipit-source-id: 1b61dd500b2b3bdab4771663672c375d7ed1b7d6
1 parent bedb6ca commit b2882e4

File tree

2 files changed

+46
-9
lines changed

2 files changed

+46
-9
lines changed

API/hermes/hermes.cpp

+28-9
Original file line numberDiff line numberDiff line change
@@ -494,11 +494,6 @@ class HermesRuntimeImpl final : public HermesRuntime,
494494
return ::hermes::vm::Handle<::hermes::vm::JSObject>::vmcast(&phv(obj));
495495
}
496496

497-
static ::hermes::vm::Handle<::hermes::vm::JSArray> arrayHandle(
498-
const jsi::Array &arr) {
499-
return ::hermes::vm::Handle<::hermes::vm::JSArray>::vmcast(&phv(arr));
500-
}
501-
502497
static ::hermes::vm::Handle<::hermes::vm::JSArrayBuffer> arrayBufferHandle(
503498
const jsi::ArrayBuffer &arr) {
504499
return ::hermes::vm::Handle<::hermes::vm::JSArrayBuffer>::vmcast(&phv(arr));
@@ -2192,7 +2187,12 @@ void HermesRuntimeImpl::setPropertyValue(
21922187
}
21932188

21942189
bool HermesRuntimeImpl::isArray(const jsi::Object &obj) const {
2195-
return vm::vmisa<vm::JSArray>(phv(obj));
2190+
if (vm::vmisa<vm::JSArray>(phv(obj))) {
2191+
return true;
2192+
}
2193+
auto cr = vm::isArray(runtime_, vm::vmcast<vm::JSObject>(phv(obj)));
2194+
const_cast<HermesRuntimeImpl *>(this)->checkStatus(cr.getStatus());
2195+
return *cr;
21962196
}
21972197

21982198
bool HermesRuntimeImpl::isArrayBuffer(const jsi::Object &obj) const {
@@ -2291,7 +2291,26 @@ jsi::ArrayBuffer HermesRuntimeImpl::createArrayBuffer(
22912291
}
22922292

22932293
size_t HermesRuntimeImpl::size(const jsi::Array &arr) {
2294-
return vm::JSArray::getLength(*arrayHandle(arr), runtime_);
2294+
if (LLVM_LIKELY(vm::vmisa<vm::JSArray>(phv(arr)))) {
2295+
return vm::JSArray::getLength(vm::vmcast<vm::JSArray>(phv(arr)), runtime_);
2296+
}
2297+
2298+
vm::GCScope gcScope(runtime_);
2299+
struct : vm::Locals {
2300+
vm::PinnedValue<> lenProp;
2301+
} lv;
2302+
vm::LocalsRAII lraii{runtime_, &lv};
2303+
auto cr = vm::JSObject::getNamed_RJS(
2304+
handle(arr),
2305+
runtime_,
2306+
vm::Predefined::getSymbolID(vm::Predefined::length));
2307+
checkStatus(cr.getStatus());
2308+
2309+
lv.lenProp = std::move(*cr);
2310+
auto lenRes = toLength(runtime_, lv.lenProp);
2311+
checkStatus(lenRes.getStatus());
2312+
2313+
return lenRes->getNumber();
22952314
}
22962315

22972316
size_t HermesRuntimeImpl::size(const jsi::ArrayBuffer &arr) {
@@ -2316,7 +2335,7 @@ jsi::Value HermesRuntimeImpl::getValueAtIndex(const jsi::Array &arr, size_t i) {
23162335
}
23172336

23182337
auto res = vm::JSObject::getComputed_RJS(
2319-
arrayHandle(arr),
2338+
handle(arr),
23202339
runtime_,
23212340
runtime_.makeHandle(vm::HermesValue::encodeTrustedNumberValue(i)));
23222341
checkStatus(res.getStatus());
@@ -2335,7 +2354,7 @@ void HermesRuntimeImpl::setValueAtIndexImpl(
23352354
}
23362355

23372356
auto res = vm::JSObject::putComputed_RJS(
2338-
arrayHandle(arr),
2357+
handle(arr),
23392358
runtime_,
23402359
runtime_.makeHandle(vm::HermesValue::encodeTrustedNumberValue(i)),
23412360
vmHandleFromValue(value));

unittests/API/APITest.cpp

+18
Original file line numberDiff line numberDiff line change
@@ -927,6 +927,24 @@ assert(arrayEqual(symArr, [abcSym, hoDefSym, defSym, numberSym]),
927927
)");
928928
}
929929

930+
TEST_P(HermesRuntimeTest, ArrayTest) {
931+
auto array = eval("[1, 2, 3]").getObject(*rt);
932+
EXPECT_TRUE(array.isArray(*rt));
933+
auto jsiArray = array.getArray(*rt);
934+
EXPECT_EQ(jsiArray.size(*rt), 3);
935+
EXPECT_EQ(jsiArray.getValueAtIndex(*rt, 0).asNumber(), 1);
936+
jsiArray.setValueAtIndex(*rt, 1, 0);
937+
EXPECT_EQ(jsiArray.getValueAtIndex(*rt, 1).asNumber(), 0);
938+
939+
array = eval("new Proxy([4, 5, 6], {})").getObject(*rt);
940+
EXPECT_TRUE(array.isArray(*rt));
941+
jsiArray = array.getArray(*rt);
942+
EXPECT_EQ(jsiArray.size(*rt), 3);
943+
EXPECT_EQ(jsiArray.getValueAtIndex(*rt, 0).asNumber(), 4);
944+
jsiArray.setValueAtIndex(*rt, 1, 0);
945+
EXPECT_EQ(jsiArray.getValueAtIndex(*rt, 1).asNumber(), 0);
946+
}
947+
930948
TEST_P(HermesRuntimeTest, HasComputedTest) {
931949
// The only use of JSObject::hasComputed() is in HermesRuntimeImpl,
932950
// so we test its Proxy support here, instead of from JS.

0 commit comments

Comments
 (0)