diff options
author | Linus Groh <mail@linusgroh.de> | 2021-04-11 22:52:25 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-04-12 09:38:57 +0200 |
commit | 6e9eb0a284661803d634ce0bd8c1656a156878bb (patch) | |
tree | bcc26af1379abd9fbb8b978f0402032e875860b4 /Userland/Libraries | |
parent | 9ec4defdd2452319ca2a633e56a72e5c836fe22a (diff) | |
download | serenity-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.cpp | 21 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/Object.h | 5 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/ProxyObject.cpp | 6 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/ProxyObject.h | 2 |
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; |