Skip to content

Commit 646945c

Browse files
tsaichienfacebook-github-bot
authored andcommitted
Add deleteProperty API (#52911)
Summary: Pull Request resolved: #52911 Add a new `deleteProperty` API to JSI. As the name implies, allows users to delete properties from Objects through JSI. The default implementation uses `Reflect.deleteProperty.` For the `PropNameID` overload, convert the propNameID to a String and pass into the `deleteProperty` function. Changelog: [Internal] Reviewed By: dannysu Differential Revision: D79120814 fbshipit-source-id: e30f383247d94bb5971e4909f004c75e8165adda
1 parent da9136f commit 646945c

File tree

5 files changed

+154
-0
lines changed

5 files changed

+154
-0
lines changed

packages/react-native/ReactCommon/jsi/jsi/decorator.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,18 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation {
328328
plain_.setPropertyValue(o, name, value);
329329
};
330330

331+
void deleteProperty(const Object& object, const PropNameID& name) override {
332+
plain_.deleteProperty(object, name);
333+
}
334+
335+
void deleteProperty(const Object& object, const String& name) override {
336+
plain_.deleteProperty(object, name);
337+
}
338+
339+
void deleteProperty(const Object& object, const Value& name) override {
340+
plain_.deleteProperty(object, name);
341+
}
342+
331343
bool isArray(const Object& o) const override {
332344
return plain_.isArray(o);
333345
};
@@ -852,6 +864,21 @@ class WithRuntimeDecorator : public RuntimeDecorator<Plain, Base> {
852864
RD::setPropertyValue(o, name, value);
853865
};
854866

867+
void deleteProperty(const Object& object, const PropNameID& name) override {
868+
Around around{with_};
869+
RD::deleteProperty(object, name);
870+
}
871+
872+
void deleteProperty(const Object& object, const String& name) override {
873+
Around around{with_};
874+
RD::deleteProperty(object, name);
875+
}
876+
877+
void deleteProperty(const Object& object, const Value& name) override {
878+
Around around{with_};
879+
RD::deleteProperty(object, name);
880+
}
881+
855882
bool isArray(const Object& o) const override {
856883
Around around{with_};
857884
return RD::isArray(o);

packages/react-native/ReactCommon/jsi/jsi/jsi-inl.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,23 @@ void Object::setProperty(Runtime& runtime, const PropNameID& name, T&& value)
148148
runtime, name, detail::toValue(runtime, std::forward<T>(value)));
149149
}
150150

151+
inline void Object::deleteProperty(Runtime& runtime, const char* name) const {
152+
deleteProperty(runtime, String::createFromAscii(runtime, name));
153+
}
154+
155+
inline void Object::deleteProperty(Runtime& runtime, const String& name) const {
156+
runtime.deleteProperty(*this, name);
157+
}
158+
159+
inline void Object::deleteProperty(Runtime& runtime, const PropNameID& name)
160+
const {
161+
runtime.deleteProperty(*this, name);
162+
}
163+
164+
inline void Object::deleteProperty(Runtime& runtime, const Value& name) const {
165+
runtime.deleteProperty(*this, name);
166+
}
167+
151168
inline Array Object::getArray(Runtime& runtime) const& {
152169
assert(runtime.isArray(*this));
153170
(void)runtime; // when assert is disabled we need to mark this as used

packages/react-native/ReactCommon/jsi/jsi/jsi.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,37 @@ Object Runtime::createObjectWithPrototype(const Value& prototype) {
416416
return createFn.call(*this, prototype).asObject(*this);
417417
}
418418

419+
void Runtime::deleteProperty(const Object& object, const PropNameID& name) {
420+
auto nameStr = String::createFromUtf16(*this, name.utf16(*this));
421+
auto deleteFn = global()
422+
.getPropertyAsObject(*this, "Reflect")
423+
.getPropertyAsFunction(*this, "deleteProperty");
424+
auto res = deleteFn.call(*this, object, nameStr).getBool();
425+
if (!res) {
426+
throw JSError(*this, "Failed to delete property");
427+
}
428+
}
429+
430+
void Runtime::deleteProperty(const Object& object, const String& name) {
431+
auto deleteFn = global()
432+
.getPropertyAsObject(*this, "Reflect")
433+
.getPropertyAsFunction(*this, "deleteProperty");
434+
auto res = deleteFn.call(*this, object, name).getBool();
435+
if (!res) {
436+
throw JSError(*this, "Failed to delete property");
437+
}
438+
}
439+
440+
void Runtime::deleteProperty(const Object& object, const Value& name) {
441+
auto deleteFn = global()
442+
.getPropertyAsObject(*this, "Reflect")
443+
.getPropertyAsFunction(*this, "deleteProperty");
444+
auto res = deleteFn.call(*this, object, name).getBool();
445+
if (!res) {
446+
throw JSError(*this, "Failed to delete property");
447+
}
448+
}
449+
419450
void Runtime::setRuntimeDataImpl(
420451
const UUID& uuid,
421452
const void* data,

packages/react-native/ReactCommon/jsi/jsi/jsi.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,10 @@ class JSI_EXPORT Runtime : public ICast {
486486
virtual void
487487
setPropertyValue(const Object&, const String& name, const Value& value) = 0;
488488

489+
virtual void deleteProperty(const Object&, const PropNameID& name);
490+
virtual void deleteProperty(const Object&, const String& name);
491+
virtual void deleteProperty(const Object&, const Value& name);
492+
489493
virtual bool isArray(const Object&) const = 0;
490494
virtual bool isArrayBuffer(const Object&) const = 0;
491495
virtual bool isFunction(const Object&) const = 0;
@@ -984,6 +988,22 @@ class JSI_EXPORT Object : public Pointer {
984988
template <typename T>
985989
void setProperty(Runtime& runtime, const PropNameID& name, T&& value) const;
986990

991+
/// Delete the property with the given ascii name. Throws if the deletion
992+
/// failed.
993+
void deleteProperty(Runtime& runtime, const char* name) const;
994+
995+
/// Delete the property with the given String name. Throws if the deletion
996+
/// failed.
997+
void deleteProperty(Runtime& runtime, const String& name) const;
998+
999+
/// Delete the property with the given PropNameID name. Throws if the deletion
1000+
/// failed.
1001+
void deleteProperty(Runtime& runtime, const PropNameID& name) const;
1002+
1003+
/// Delete the property with the given Value name. Throws if the deletion
1004+
/// failed.
1005+
void deleteProperty(Runtime& runtime, const Value& name) const;
1006+
9871007
/// \return true iff JS \c Array.isArray() would return \c true. If
9881008
/// so, then \c getArray() will succeed.
9891009
bool isArray(Runtime& runtime) const {

packages/react-native/ReactCommon/jsi/jsi/test/testlib.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1882,6 +1882,65 @@ TEST_P(JSITest, CastInterface) {
18821882
EXPECT_TRUE(ptr == nullptr);
18831883
}
18841884

1885+
TEST_P(JSITest, DeleteProperty) {
1886+
// This Runtime Decorator is used to test the default implementation of
1887+
// Runtime::deleteProperty
1888+
class RD : public RuntimeDecorator<Runtime, Runtime> {
1889+
public:
1890+
explicit RD(Runtime& rt) : RuntimeDecorator(rt) {}
1891+
1892+
void deleteProperty(const Object& object, const PropNameID& name) override {
1893+
Runtime::deleteProperty(object, name);
1894+
}
1895+
void deleteProperty(const Object& object, const String& name) override {
1896+
Runtime::deleteProperty(object, name);
1897+
}
1898+
void deleteProperty(const Object& object, const Value& name) override {
1899+
Runtime::deleteProperty(object, name);
1900+
}
1901+
};
1902+
RD rd = RD(rt);
1903+
auto obj = eval("obj = {1:2, foo: 'bar', 3: 4, salt:'pepper'}").getObject(rd);
1904+
1905+
auto prop = PropNameID::forAscii(rd, "1");
1906+
auto hasRes = obj.hasProperty(rd, prop);
1907+
EXPECT_TRUE(hasRes);
1908+
obj.deleteProperty(rd, prop);
1909+
hasRes = obj.hasProperty(rd, prop);
1910+
EXPECT_FALSE(hasRes);
1911+
1912+
auto str = String::createFromAscii(rd, "foo");
1913+
hasRes = obj.hasProperty(rd, str);
1914+
EXPECT_TRUE(hasRes);
1915+
obj.deleteProperty(rd, str);
1916+
hasRes = obj.hasProperty(rd, str);
1917+
EXPECT_FALSE(hasRes);
1918+
1919+
auto valProp = Value(3);
1920+
hasRes = obj.hasProperty(rd, "3");
1921+
EXPECT_TRUE(hasRes);
1922+
obj.deleteProperty(rd, valProp);
1923+
auto getRes = obj.getProperty(rd, "3");
1924+
EXPECT_TRUE(getRes.isUndefined());
1925+
1926+
hasRes = obj.hasProperty(rd, "salt");
1927+
EXPECT_TRUE(hasRes);
1928+
obj.deleteProperty(rd, "salt");
1929+
hasRes = obj.hasProperty(rd, "salt");
1930+
EXPECT_FALSE(hasRes);
1931+
1932+
obj = eval(
1933+
"const obj = {};"
1934+
"Object.defineProperty(obj, 'prop', {"
1935+
" value: 10,"
1936+
" configurable: false,});"
1937+
"obj;")
1938+
.getObject(rd);
1939+
EXPECT_THROW(obj.deleteProperty(rd, "prop"), JSError);
1940+
hasRes = obj.hasProperty(rd, "prop");
1941+
EXPECT_TRUE(hasRes);
1942+
}
1943+
18851944
INSTANTIATE_TEST_CASE_P(
18861945
Runtimes,
18871946
JSITest,

0 commit comments

Comments
 (0)