From af0da6e8a05ef67bd29061eedbb6c5da3efec3fc Mon Sep 17 00:00:00 2001 From: Aakash Patel Date: Wed, 8 Nov 2023 14:22:18 -0800 Subject: [PATCH] Support NativeState in JSC (#1151) (#1151) Summary: Original Author: pieterdb@meta.com Original Git: 2b4f949f6ff4d1de03fbad0dbef9b744153e0adb Original Reviewed By: neildhar Original Revision: D49229022 Pull Request resolved: https://github.com/facebook/hermes/pull/1151 X-link: https://github.com/facebook/react-native/pull/40746 This feature was missing in JSC's JSI implementation, which is preventing from rolling out NativeState-based features in React Native. Changelog: [General][Added] JSC support for the NativeState API in JSI Reviewed By: tmikov Differential Revision: D50992853 fbshipit-source-id: 4b3c57745a9103204c1da30158c0d293d0c8e590 --- API/jsi/jsi/test/testlib.cpp | 68 ++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/API/jsi/jsi/test/testlib.cpp b/API/jsi/jsi/test/testlib.cpp index bbfe8f2c06b..e24284112be 100644 --- a/API/jsi/jsi/test/testlib.cpp +++ b/API/jsi/jsi/test/testlib.cpp @@ -1452,6 +1452,74 @@ TEST_P(JSITest, ArrayBufferSizeTest) { EXPECT_EQ(ab.size(rt), 10); } +namespace { + +struct IntState : public NativeState { + explicit IntState(int value) : value(value) {} + int value; +}; + +} // namespace + +TEST_P(JSITest, NativeState) { + Object holder(rt); + EXPECT_FALSE(holder.hasNativeState(rt)); + + auto stateValue = std::make_shared(42); + holder.setNativeState(rt, stateValue); + EXPECT_TRUE(holder.hasNativeState(rt)); + EXPECT_EQ( + std::dynamic_pointer_cast(holder.getNativeState(rt))->value, + 42); + + stateValue = std::make_shared(21); + holder.setNativeState(rt, stateValue); + EXPECT_TRUE(holder.hasNativeState(rt)); + EXPECT_EQ( + std::dynamic_pointer_cast(holder.getNativeState(rt))->value, + 21); + + // There's currently way to "delete" the native state of a component fully + // Even when reset with nullptr, hasNativeState will still return true + holder.setNativeState(rt, nullptr); + EXPECT_TRUE(holder.hasNativeState(rt)); + EXPECT_TRUE(holder.getNativeState(rt) == nullptr); +} + +TEST_P(JSITest, NativeStateSymbolOverrides) { + Object holder(rt); + + auto stateValue = std::make_shared(42); + holder.setNativeState(rt, stateValue); + + // Attempting to change configurable attribute of unconfigurable property + try { + function( + "function (obj) {" + " var mySymbol = Symbol();" + " obj[mySymbol] = 'foo';" + " var allSymbols = Object.getOwnPropertySymbols(obj);" + " for (var sym of allSymbols) {" + " Object.defineProperty(obj, sym, {configurable: true, writable: true});" + " obj[sym] = 'bar';" + " }" + "}") + .call(rt, holder); + } catch (const JSError& ex) { + // On JSC this throws, but it doesn't on Hermes + std::string exc = ex.what(); + EXPECT_NE( + exc.find( + "Attempting to change configurable attribute of unconfigurable property"), + std::string::npos); + } + + EXPECT_TRUE(holder.hasNativeState(rt)); + EXPECT_EQ( + std::dynamic_pointer_cast(holder.getNativeState(rt))->value, + 42); +} + INSTANTIATE_TEST_CASE_P( Runtimes, JSITest,