From a942ef374897d85da38e9c8904574f8376555388 Mon Sep 17 00:00:00 2001 From: Chi Tsai Date: Thu, 9 Jan 2025 05:15:51 -0800 Subject: [PATCH] Add Hermes implementation for Object.create with prototype Summary: Adds the implementation `createObjectWithPrototype` JSI method for Hermes runtime. Grafted from 1053185886992b918021c4d2578a0807f797dd00 (D66487948) - Grafted path xplat/static_h to xplat/hermes Reviewed By: tmikov Differential Revision: D67412929 fbshipit-source-id: a283ffc775494f7df2bdcf9a91ada188b673c071 --- API/hermes/hermes.cpp | 14 ++++++++++++++ unittests/API/APITest.cpp | 16 ++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/API/hermes/hermes.cpp b/API/hermes/hermes.cpp index f5e6c29c719..0fec8a6637b 100644 --- a/API/hermes/hermes.cpp +++ b/API/hermes/hermes.cpp @@ -632,6 +632,7 @@ class HermesRuntimeImpl final : public HermesRuntime, jsi::Object createObject() override; jsi::Object createObject(std::shared_ptr ho) override; std::shared_ptr getHostObject(const jsi::Object &) override; + jsi::Object createObjectWithPrototype(const jsi::Value &prototype) override; jsi::HostFunctionType &getHostFunction(const jsi::Function &) override; bool hasNativeState(const jsi::Object &) override; std::shared_ptr getNativeState( @@ -1874,6 +1875,19 @@ jsi::Object HermesRuntimeImpl::createObject( return add(*objRes); } +jsi::Object HermesRuntimeImpl::createObjectWithPrototype( + const jsi::Value &prototype) { + if (!prototype.isObject() && !prototype.isNull()) { + throw jsi::JSError( + *this, "Object prototype argument must be an Object or null"); + } + + auto object = vm::JSObject::create( + runtime_, + vm::Handle::dyn_vmcast(vmHandleFromValue(prototype))); + return add(object.getHermesValue()); +} + std::shared_ptr HermesRuntimeImpl::getHostObject( const jsi::Object &obj) { const vm::HostObjectProxy *proxy = diff --git a/unittests/API/APITest.cpp b/unittests/API/APITest.cpp index afc1d94959a..c3928848549 100644 --- a/unittests/API/APITest.cpp +++ b/unittests/API/APITest.cpp @@ -1294,6 +1294,22 @@ TEST_P(HermesRuntimeTest, SetPrototypeOf) { EXPECT_THROW(child.setPrototype(*rt, Value(1)), JSError); } +TEST_P(HermesRuntimeTest, CreateObjectWithPrototype) { + Object prototypeObj(*rt); + prototypeObj.setProperty(*rt, "someProperty", 123); + Value prototype(*rt, prototypeObj); + + Object child = Object::create(*rt, prototype); + EXPECT_EQ(child.getProperty(*rt, "someProperty").getNumber(), 123); + + // Tests null value as prototype + child = Object::create(*rt, Value::null()); + EXPECT_TRUE(child.getPrototype(*rt).isNull()); + + // Throw when prototype is neither an Object nor null + EXPECT_THROW(Object::create(*rt, Value(1)), JSError); +} + INSTANTIATE_TEST_CASE_P( Runtimes, HermesRuntimeTest,