summaryrefslogtreecommitdiff
path: root/Userland/Libraries
diff options
context:
space:
mode:
authorLinus Groh <mail@linusgroh.de>2021-04-11 22:52:25 +0200
committerAndreas Kling <kling@serenityos.org>2021-04-12 09:38:57 +0200
commit6e9eb0a284661803d634ce0bd8c1656a156878bb (patch)
treebcc26af1379abd9fbb8b978f0402032e875860b4 /Userland/Libraries
parent9ec4defdd2452319ca2a633e56a72e5c836fe22a (diff)
downloadserenity-6e9eb0a284661803d634ce0bd8c1656a156878bb.zip
LibJS: Add Object::get_without_side_effects()
Similar to Value::to_string_without_side_effects() this is mostly a regular object property lookup, but with the guarantee that it will be side-effect free, i.e. no accessors or native property functions will be called. This is needed when we want to access user-controlled object properties for debug logging, for example. The specific use case will be error objects which will soon no longer have internal name/message properties, so we need to guarantee that printing an error, which may already be the result of an exception, won't blow up in our face :^)
Diffstat (limited to 'Userland/Libraries')
-rw-r--r--Userland/Libraries/LibJS/Runtime/Object.cpp21
-rw-r--r--Userland/Libraries/LibJS/Runtime/Object.h5
-rw-r--r--Userland/Libraries/LibJS/Runtime/ProxyObject.cpp6
-rw-r--r--Userland/Libraries/LibJS/Runtime/ProxyObject.h2
4 files changed, 23 insertions, 11 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/Object.cpp b/Userland/Libraries/LibJS/Runtime/Object.cpp
index 0e9bbaac85..634340c0ae 100644
--- a/Userland/Libraries/LibJS/Runtime/Object.cpp
+++ b/Userland/Libraries/LibJS/Runtime/Object.cpp
@@ -234,7 +234,7 @@ bool Object::test_integrity_level(IntegrityLevel level)
return true;
}
-Value Object::get_own_property(const PropertyName& property_name, Value receiver) const
+Value Object::get_own_property(const PropertyName& property_name, Value receiver, bool without_side_effects) const
{
VERIFY(property_name.is_valid());
VERIFY(!receiver.is_empty());
@@ -254,10 +254,12 @@ Value Object::get_own_property(const PropertyName& property_name, Value receiver
}
VERIFY(!value_here.is_empty());
- if (value_here.is_accessor())
- return value_here.as_accessor().call_getter(receiver);
- if (value_here.is_native_property())
- return call_native_property_getter(value_here.as_native_property(), receiver);
+ if (!without_side_effects) {
+ if (value_here.is_accessor())
+ return value_here.as_accessor().call_getter(receiver);
+ if (value_here.is_native_property())
+ return call_native_property_getter(value_here.as_native_property(), receiver);
+ }
return value_here;
}
@@ -769,7 +771,7 @@ Value Object::get_by_index(u32 property_index) const
return {};
}
-Value Object::get(const PropertyName& property_name, Value receiver) const
+Value Object::get(const PropertyName& property_name, Value receiver, bool without_side_effects) const
{
VERIFY(property_name.is_valid());
@@ -788,7 +790,7 @@ Value Object::get(const PropertyName& property_name, Value receiver) const
const Object* object = this;
while (object) {
- auto value = object->get_own_property(property_name, receiver);
+ auto value = object->get_own_property(property_name, receiver, without_side_effects);
if (vm().exception())
return {};
if (!value.is_empty())
@@ -800,6 +802,11 @@ Value Object::get(const PropertyName& property_name, Value receiver) const
return {};
}
+Value Object::get_without_side_effects(const PropertyName& property_name) const
+{
+ return get(property_name, {}, true);
+}
+
bool Object::put_by_index(u32 property_index, Value value)
{
VERIFY(!value.is_empty());
diff --git a/Userland/Libraries/LibJS/Runtime/Object.h b/Userland/Libraries/LibJS/Runtime/Object.h
index 23f5f53e5f..d3f08f6094 100644
--- a/Userland/Libraries/LibJS/Runtime/Object.h
+++ b/Userland/Libraries/LibJS/Runtime/Object.h
@@ -94,14 +94,15 @@ public:
GlobalObject& global_object() const { return *shape().global_object(); }
- virtual Value get(const PropertyName&, Value receiver = {}) const;
+ virtual Value get(const PropertyName&, Value receiver = {}, bool without_side_effects = false) const;
+ Value get_without_side_effects(const PropertyName&) const;
virtual bool has_property(const PropertyName&) const;
bool has_own_property(const PropertyName&) const;
virtual bool put(const PropertyName&, Value, Value receiver = {});
- Value get_own_property(const PropertyName&, Value receiver) const;
+ Value get_own_property(const PropertyName&, Value receiver, bool without_side_effects = false) const;
MarkedValueList get_own_properties(PropertyKind, bool only_enumerable_properties = false, GetOwnPropertyReturnType = GetOwnPropertyReturnType::All) const;
MarkedValueList get_enumerable_own_property_names(PropertyKind) const;
virtual Optional<PropertyDescriptor> get_own_property_descriptor(const PropertyName&) const;
diff --git a/Userland/Libraries/LibJS/Runtime/ProxyObject.cpp b/Userland/Libraries/LibJS/Runtime/ProxyObject.cpp
index 59c3201b5d..ac5ea45fb3 100644
--- a/Userland/Libraries/LibJS/Runtime/ProxyObject.cpp
+++ b/Userland/Libraries/LibJS/Runtime/ProxyObject.cpp
@@ -325,9 +325,13 @@ bool ProxyObject::has_property(const PropertyName& name) const
return trap_result.to_boolean();
}
-Value ProxyObject::get(const PropertyName& name, Value receiver) const
+Value ProxyObject::get(const PropertyName& name, Value receiver, bool without_side_effects) const
{
auto& vm = this->vm();
+ if (without_side_effects) {
+ // Sorry, we're not going to call anything on this proxy.
+ return js_string(vm, "<ProxyObject>");
+ }
if (m_is_revoked) {
vm.throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
return {};
diff --git a/Userland/Libraries/LibJS/Runtime/ProxyObject.h b/Userland/Libraries/LibJS/Runtime/ProxyObject.h
index 046c985c14..a64fd57237 100644
--- a/Userland/Libraries/LibJS/Runtime/ProxyObject.h
+++ b/Userland/Libraries/LibJS/Runtime/ProxyObject.h
@@ -55,7 +55,7 @@ public:
virtual Optional<PropertyDescriptor> get_own_property_descriptor(const PropertyName&) const override;
virtual bool define_property(const StringOrSymbol& property_name, const Object& descriptor, bool throw_exceptions = true) override;
virtual bool has_property(const PropertyName& name) const override;
- virtual Value get(const PropertyName& name, Value receiver) const override;
+ virtual Value get(const PropertyName& name, Value receiver, bool without_side_effects = false) const override;
virtual bool put(const PropertyName& name, Value value, Value receiver) override;
virtual bool delete_property(const PropertyName& name) override;