mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Add default implementation for Object.getPrototypeOf and Object.setPrototypeOf (#47996)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/47996 Getting and setting an Object's prototype is convoluted. Users have to call into the global object to get the method, then call it. This diff adds a JSI API for Object.getPrototype and Object.setPrototype to make it easy for users. Changelog: [Internal] Reviewed By: fbmal7 Differential Revision: D66562549 fbshipit-source-id: 85a2e49deb9d00500544de4cc5ab123c4717398e
This commit is contained in:
committed by
Facebook GitHub Bot
parent
07d723cb72
commit
04f33ecd58
@@ -282,6 +282,14 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation {
|
||||
plain_.setExternalMemoryPressure(obj, amt);
|
||||
}
|
||||
|
||||
void setPrototypeOf(const Object& object, const Value& prototype) override {
|
||||
plain_.setPrototypeOf(object, prototype);
|
||||
}
|
||||
|
||||
Value getPrototypeOf(const Object& object) override {
|
||||
return plain_.getPrototypeOf(object);
|
||||
}
|
||||
|
||||
Value getProperty(const Object& o, const PropNameID& name) override {
|
||||
return plain_.getProperty(o, name);
|
||||
};
|
||||
@@ -760,6 +768,16 @@ class WithRuntimeDecorator : public RuntimeDecorator<Plain, Base> {
|
||||
RD::setNativeState(o, state);
|
||||
};
|
||||
|
||||
void setPrototypeOf(const Object& object, const Value& prototype) override {
|
||||
Around around{with_};
|
||||
RD::setPrototypeOf(object, prototype);
|
||||
}
|
||||
|
||||
Value getPrototypeOf(const Object& object) override {
|
||||
Around around{with_};
|
||||
return RD::getPrototypeOf(object);
|
||||
}
|
||||
|
||||
Value getProperty(const Object& o, const PropNameID& name) override {
|
||||
Around around{with_};
|
||||
return RD::getProperty(o, name);
|
||||
|
||||
@@ -84,6 +84,10 @@ inline const Runtime::PointerValue* Runtime::getPointerValue(
|
||||
return value.data_.pointer.ptr_;
|
||||
}
|
||||
|
||||
Value Object::getPrototype(Runtime& runtime) const {
|
||||
return runtime.getPrototypeOf(*this);
|
||||
}
|
||||
|
||||
inline Value Object::getProperty(Runtime& runtime, const char* name) const {
|
||||
return getProperty(runtime, String::createFromAscii(runtime, name));
|
||||
}
|
||||
|
||||
@@ -274,6 +274,20 @@ void Runtime::getPropNameIdData(
|
||||
cb(ctx, false, utf16Str.data(), utf16Str.size());
|
||||
}
|
||||
|
||||
void Runtime::setPrototypeOf(const Object& object, const Value& prototype) {
|
||||
auto setPrototypeOfFn = global()
|
||||
.getPropertyAsObject(*this, "Object")
|
||||
.getPropertyAsFunction(*this, "setPrototypeOf");
|
||||
setPrototypeOfFn.call(*this, object, prototype).asObject(*this);
|
||||
}
|
||||
|
||||
Value Runtime::getPrototypeOf(const Object& object) {
|
||||
auto setPrototypeOfFn = global()
|
||||
.getPropertyAsObject(*this, "Object")
|
||||
.getPropertyAsFunction(*this, "getPrototypeOf");
|
||||
return setPrototypeOfFn.call(*this, object);
|
||||
}
|
||||
|
||||
Pointer& Pointer::operator=(Pointer&& other) noexcept {
|
||||
if (ptr_) {
|
||||
ptr_->invalidate();
|
||||
|
||||
@@ -339,6 +339,9 @@ class JSI_EXPORT Runtime {
|
||||
const jsi::Object&,
|
||||
std::shared_ptr<NativeState> state) = 0;
|
||||
|
||||
virtual void setPrototypeOf(const Object& object, const Value& prototype);
|
||||
virtual Value getPrototypeOf(const Object& object);
|
||||
|
||||
virtual Value getProperty(const Object&, const PropNameID& name) = 0;
|
||||
virtual Value getProperty(const Object&, const String& name) = 0;
|
||||
virtual bool hasProperty(const Object&, const PropNameID& name) = 0;
|
||||
@@ -758,6 +761,16 @@ class JSI_EXPORT Object : public Pointer {
|
||||
return rt.instanceOf(*this, ctor);
|
||||
}
|
||||
|
||||
/// Sets \p prototype as the prototype of the object. The prototype must be
|
||||
/// either an Object or null. If the prototype was not set successfully, this
|
||||
/// method will throw.
|
||||
void setPrototype(Runtime& runtime, const Value& prototype) const {
|
||||
return runtime.setPrototypeOf(*this, prototype);
|
||||
}
|
||||
|
||||
/// \return the prototype of the object
|
||||
inline Value getPrototype(Runtime& runtime) const;
|
||||
|
||||
/// \return the property of the object with the given ascii name.
|
||||
/// If the name isn't a property on the object, returns the
|
||||
/// undefined value.
|
||||
|
||||
@@ -1664,6 +1664,40 @@ TEST_P(JSITest, GetStringDataTest) {
|
||||
EXPECT_EQ(buf, str.utf16(rd));
|
||||
}
|
||||
|
||||
TEST_P(JSITest, ObjectSetPrototype) {
|
||||
// This Runtime Decorator is used to test the default implementation of
|
||||
// Object.setPrototypeOf
|
||||
class RD : public RuntimeDecorator<Runtime, Runtime> {
|
||||
public:
|
||||
explicit RD(Runtime& rt) : RuntimeDecorator(rt) {}
|
||||
|
||||
void setPrototypeOf(const Object& object, const Value& prototype) override {
|
||||
return Runtime::setPrototypeOf(object, prototype);
|
||||
}
|
||||
|
||||
Value getPrototypeOf(const Object& object) override {
|
||||
return Runtime::getPrototypeOf(object);
|
||||
}
|
||||
};
|
||||
|
||||
RD rd = RD(rt);
|
||||
Object child(rd);
|
||||
|
||||
// Tests null value as prototype
|
||||
child.setPrototype(rd, Value::null());
|
||||
EXPECT_TRUE(child.getPrototype(rd).isNull());
|
||||
|
||||
Object prototypeObj(rd);
|
||||
prototypeObj.setProperty(rd, "someProperty", 123);
|
||||
Value prototype(rd, prototypeObj);
|
||||
|
||||
child.setPrototype(rd, prototype);
|
||||
EXPECT_EQ(child.getProperty(rd, "someProperty").getNumber(), 123);
|
||||
|
||||
auto getPrototypeRes = child.getPrototype(rd).asObject(rd);
|
||||
EXPECT_EQ(getPrototypeRes.getProperty(rd, "someProperty").getNumber(), 123);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
Runtimes,
|
||||
JSITest,
|
||||
|
||||
Reference in New Issue
Block a user