diff --git a/API/hermes/hermes.cpp b/API/hermes/hermes.cpp index 22b3d4c3e6d..f5e6c29c719 100644 --- a/API/hermes/hermes.cpp +++ b/API/hermes/hermes.cpp @@ -659,6 +659,10 @@ class HermesRuntimeImpl final : public HermesRuntime, bool isHostFunction(const jsi::Function &) const override; jsi::Array getPropertyNames(const jsi::Object &) override; + void setPrototypeOf(const jsi::Object &object, const jsi::Value &prototype) + override; + jsi::Value getPrototypeOf(const jsi::Object &object) override; + jsi::WeakObject createWeakObject(const jsi::Object &) override; jsi::Value lockWeakObject(const jsi::WeakObject &) override; @@ -2018,6 +2022,32 @@ void HermesRuntimeImpl::setExternalMemoryPressure( ns->setContext(reinterpret_cast(amt)); } +void HermesRuntimeImpl::setPrototypeOf( + const jsi::Object &object, + const jsi::Value &prototype) { + if (!prototype.isObject() && !prototype.isNull()) { + throw jsi::JSError( + *this, "Object prototype argument must be an Object or null"); + } + + auto cr = vm::JSObject::setParent( + vm::vmcast(phv(object)), + runtime_, + vm::dyn_vmcast(hvFromValue(prototype)), + vm::PropOpFlags().plusThrowOnError()); + checkStatus(cr.getStatus()); +} + +jsi::Value HermesRuntimeImpl::getPrototypeOf(const jsi::Object &object) { + vm::CallResult> cr = + vm::JSObject::getPrototypeOf(handle(object), runtime_); + checkStatus(cr.getStatus()); + if (!*cr) { + return jsi::Value::null(); + } + return valueFromHermesValue(cr->getHermesValue()); +} + jsi::Value HermesRuntimeImpl::getProperty( const jsi::Object &obj, const jsi::String &name) { diff --git a/unittests/API/APITest.cpp b/unittests/API/APITest.cpp index 19cf3fb866a..afc1d94959a 100644 --- a/unittests/API/APITest.cpp +++ b/unittests/API/APITest.cpp @@ -1274,6 +1274,26 @@ TEST_P(HermesRuntimeTest, GetPropNameIdDataTest) { buf.clear(); } +TEST_P(HermesRuntimeTest, SetPrototypeOf) { + Object prototypeObj(*rt); + prototypeObj.setProperty(*rt, "someProperty", 123); + Value prototype(*rt, prototypeObj); + + Object child(*rt); + child.setPrototype(*rt, prototype); + EXPECT_EQ(child.getProperty(*rt, "someProperty").getNumber(), 123); + + auto getPrototypeRes = child.getPrototype(*rt).asObject(*rt); + EXPECT_EQ(getPrototypeRes.getProperty(*rt, "someProperty").getNumber(), 123); + + // Tests null value as prototype + child.setPrototype(*rt, Value::null()); + EXPECT_TRUE(child.getPrototype(*rt).isNull()); + + // Throw when prototype is neither an Object nor null + EXPECT_THROW(child.setPrototype(*rt, Value(1)), JSError); +} + INSTANTIATE_TEST_CASE_P( Runtimes, HermesRuntimeTest,