diff --git a/packages/react-native/ReactCommon/jsi/jsi/decorator.h b/packages/react-native/ReactCommon/jsi/jsi/decorator.h index 7afe5b1db15da9..8fd3101980c51b 100644 --- a/packages/react-native/ReactCommon/jsi/jsi/decorator.h +++ b/packages/react-native/ReactCommon/jsi/jsi/decorator.h @@ -232,6 +232,10 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation { return plain_.utf16(sym); } + Object createObjectWithPrototype(const Value& prototype) override { + return plain_.createObjectWithPrototype(prototype); + } + Object createObject() override { return plain_.createObject(); }; @@ -703,6 +707,11 @@ class WithRuntimeDecorator : public RuntimeDecorator { return RD::createValueFromJsonUtf8(json, length); }; + Object createObjectWithPrototype(const Value& prototype) override { + Around around{with_}; + return RD::createObjectWithPrototype(prototype); + } + Object createObject() override { Around around{with_}; return RD::createObject(); diff --git a/packages/react-native/ReactCommon/jsi/jsi/jsi.cpp b/packages/react-native/ReactCommon/jsi/jsi/jsi.cpp index f228dc351e2fc9..ab414c3e22fb1d 100644 --- a/packages/react-native/ReactCommon/jsi/jsi/jsi.cpp +++ b/packages/react-native/ReactCommon/jsi/jsi/jsi.cpp @@ -272,6 +272,13 @@ Value Runtime::getPrototypeOf(const Object& object) { return setPrototypeOfFn.call(*this, object); } +Object Runtime::createObjectWithPrototype(const Value& prototype) { + auto createFn = global() + .getPropertyAsObject(*this, "Object") + .getPropertyAsFunction(*this, "create"); + return createFn.call(*this, prototype).asObject(*this); +} + Pointer& Pointer::operator=(Pointer&& other) noexcept { if (ptr_) { ptr_->invalidate(); diff --git a/packages/react-native/ReactCommon/jsi/jsi/jsi.h b/packages/react-native/ReactCommon/jsi/jsi/jsi.h index 74ee3ace8b8734..f11afbf0329095 100644 --- a/packages/react-native/ReactCommon/jsi/jsi/jsi.h +++ b/packages/react-native/ReactCommon/jsi/jsi/jsi.h @@ -333,6 +333,9 @@ class JSI_EXPORT Runtime { virtual std::shared_ptr getHostObject(const jsi::Object&) = 0; virtual HostFunctionType& getHostFunction(const jsi::Function&) = 0; + // Creates a new Object with the custom prototype + virtual Object createObjectWithPrototype(const Value& prototype); + virtual bool hasNativeState(const jsi::Object&) = 0; virtual std::shared_ptr getNativeState(const jsi::Object&) = 0; virtual void setNativeState( @@ -691,6 +694,11 @@ class JSI_EXPORT Object : public Pointer { return runtime.createObject(ho); } + /// Creates a new Object with the custom prototype + static Object create(Runtime& runtime, const Value& prototype) { + return runtime.createObjectWithPrototype(prototype); + } + /// \return whether this and \c obj are the same JSObject or not. static bool strictEquals(Runtime& runtime, const Object& a, const Object& b) { return runtime.strictEquals(a, b); diff --git a/packages/react-native/ReactCommon/jsi/jsi/test/testlib.cpp b/packages/react-native/ReactCommon/jsi/jsi/test/testlib.cpp index 5ec67889c111f0..c871c42228b0f6 100644 --- a/packages/react-native/ReactCommon/jsi/jsi/test/testlib.cpp +++ b/packages/react-native/ReactCommon/jsi/jsi/test/testlib.cpp @@ -1667,6 +1667,31 @@ TEST_P(JSITest, ObjectSetPrototype) { EXPECT_EQ(child.getProperty(rd, "someProperty").getNumber(), 123); } +TEST_P(JSITest, ObjectCreateWithPrototype) { + // This Runtime Decorator is used to test the default implementation of + // Object.create(prototype) + class RD : public RuntimeDecorator { + public: + RD(Runtime& rt) : RuntimeDecorator(rt) {} + + Object createObjectWithPrototype(const Value& prototype) override { + return Runtime::createObjectWithPrototype(prototype); + } + }; + + RD rd = RD(rt); + Object prototypeObj(rd); + prototypeObj.setProperty(rd, "someProperty", 123); + Value prototype(rd, prototypeObj); + + Object child = Object::create(rd, prototype); + EXPECT_EQ(child.getProperty(rd, "someProperty").getNumber(), 123); + + // Tests null value as prototype + child = Object::create(rd, Value::null()); + EXPECT_TRUE(child.getPrototype(rd).isNull()); +} + INSTANTIATE_TEST_CASE_P( Runtimes, JSITest,