From 8b3293018f16038e368023dfa4a76e712324e748 Mon Sep 17 00:00:00 2001 From: ZHANG Yi Date: Wed, 21 Aug 2024 19:46:15 +0800 Subject: [PATCH] Makes HermesRuntimeImpl::isArray proxy-compatible When using hermes engine, [`dynamicFromValue` in React Native](https://github.com/facebook/hermes/blob/main/API/jsi/jsi/JSIDynamic.cpp#L166) calls `isArray` here to check if the input object is an array. Consider this piece of code: ```js const list = ['a', 'b', 'c', 'd']; const proxyed_list = new Proxy(list, {}); ``` The `proxyed_list` behaves exactly the same as list in Javascript. But when been passed to native and converted to `folly::dynamic` by `dynamicFromValue`, `proxyed_list` will be converted to `{"0": "a", "1": "b", "2": "c", "3": "d"}` but not the expected `["a", "b", "c", "d"]`. This patch implements similar routines in commit [26840ed441d614a07809c612521074ca9544086c](https://github.com/facebook/hermes/commit/26840ed441d614a07809c612521074ca9544086c#diff-059b8f2fcb0235b35582efc591e065bd8caa898c3ea2ef2a3e453bff97584e4dR1575) and makes `isArray` proxy-compatible. --- API/hermes/hermes.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/API/hermes/hermes.cpp b/API/hermes/hermes.cpp index f7d4791c306..fb9eecf8d39 100644 --- a/API/hermes/hermes.cpp +++ b/API/hermes/hermes.cpp @@ -29,6 +29,8 @@ #include "hermes/VM/JSArrayBuffer.h" #include "hermes/VM/JSLib.h" #include "hermes/VM/JSLib/RuntimeJSONUtils.h" +#include "hermes/VM/JSObject.h" +#include "hermes/VM/JSProxy.h" #include "hermes/VM/NativeState.h" #include "hermes/VM/Operations.h" #include "hermes/VM/Profiler/CodeCoverageProfiler.h" @@ -1996,7 +1998,20 @@ void HermesRuntimeImpl::setPropertyValue( } bool HermesRuntimeImpl::isArray(const jsi::Object &obj) const { - return vm::vmisa(phv(obj)); + vm::JSObject *jsobj = static_cast(phv(obj).getPointer()); + while (true) { + if (vm::vmisa(jsobj)) { + return true; + } + if (LLVM_LIKELY(!jsobj->isProxyObject())) { + return false; + } + if (vm::JSProxy::isRevoked(jsobj, runtime_)) { + return false; + } + jsobj = vm::JSProxy::getTarget(jsobj, runtime_).get(); + assert(jsobj && "target of non-revoked Proxy is null"); + } } bool HermesRuntimeImpl::isArrayBuffer(const jsi::Object &obj) const {