mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 03:37:43 +00:00
LibJS: Remove the NativeProperty mechanism from LibJS
These were an ad-hoc way to implement special behaviour when reading or writing to specific object properties. Because these were effectively replaced by the abillity to override the internal methods of Object, they are no longer needed.
This commit is contained in:
parent
306d59276a
commit
795786387b
11 changed files with 9 additions and 157 deletions
|
@ -82,7 +82,6 @@ set(SOURCES
|
||||||
Runtime/MarkedValueList.cpp
|
Runtime/MarkedValueList.cpp
|
||||||
Runtime/MathObject.cpp
|
Runtime/MathObject.cpp
|
||||||
Runtime/NativeFunction.cpp
|
Runtime/NativeFunction.cpp
|
||||||
Runtime/NativeProperty.cpp
|
|
||||||
Runtime/NumberConstructor.cpp
|
Runtime/NumberConstructor.cpp
|
||||||
Runtime/NumberObject.cpp
|
Runtime/NumberObject.cpp
|
||||||
Runtime/NumberPrototype.cpp
|
Runtime/NumberPrototype.cpp
|
||||||
|
|
|
@ -143,7 +143,6 @@ class HeapBlock;
|
||||||
class Interpreter;
|
class Interpreter;
|
||||||
class MarkedValueList;
|
class MarkedValueList;
|
||||||
class NativeFunction;
|
class NativeFunction;
|
||||||
class NativeProperty;
|
|
||||||
class ObjectEnvironment;
|
class ObjectEnvironment;
|
||||||
class PrimitiveString;
|
class PrimitiveString;
|
||||||
class PromiseReaction;
|
class PromiseReaction;
|
||||||
|
|
|
@ -148,7 +148,7 @@ void MarkupGenerator::error_to_html(const Object& object, StringBuilder& html_ou
|
||||||
auto& vm = object.vm();
|
auto& vm = object.vm();
|
||||||
auto name = object.get_without_side_effects(vm.names.name).value_or(JS::js_undefined());
|
auto name = object.get_without_side_effects(vm.names.name).value_or(JS::js_undefined());
|
||||||
auto message = object.get_without_side_effects(vm.names.message).value_or(JS::js_undefined());
|
auto message = object.get_without_side_effects(vm.names.message).value_or(JS::js_undefined());
|
||||||
if (name.is_accessor() || name.is_native_property() || message.is_accessor() || message.is_native_property()) {
|
if (name.is_accessor() || message.is_accessor()) {
|
||||||
html_output.append(wrap_string_in_style(JS::Value(&object).to_string_without_side_effects(), StyleType::Invalid));
|
html_output.append(wrap_string_in_style(JS::Value(&object).to_string_without_side_effects(), StyleType::Invalid));
|
||||||
} else {
|
} else {
|
||||||
auto name_string = name.to_string_without_side_effects();
|
auto name_string = name.to_string_without_side_effects();
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <LibJS/Runtime/NativeProperty.h>
|
|
||||||
#include <LibJS/Runtime/Value.h>
|
|
||||||
|
|
||||||
namespace JS {
|
|
||||||
|
|
||||||
NativeProperty::NativeProperty(Function<Value(VM&, GlobalObject&)> getter, Function<void(VM&, GlobalObject&, Value)> setter)
|
|
||||||
: m_getter(move(getter))
|
|
||||||
, m_setter(move(setter))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
NativeProperty::~NativeProperty()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Value NativeProperty::get(VM& vm, GlobalObject& global_object) const
|
|
||||||
{
|
|
||||||
if (!m_getter)
|
|
||||||
return js_undefined();
|
|
||||||
return m_getter(vm, global_object);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NativeProperty::set(VM& vm, GlobalObject& global_object, Value value)
|
|
||||||
{
|
|
||||||
if (!m_setter)
|
|
||||||
return;
|
|
||||||
m_setter(vm, global_object, move(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <AK/Function.h>
|
|
||||||
#include <LibJS/Runtime/Object.h>
|
|
||||||
|
|
||||||
namespace JS {
|
|
||||||
|
|
||||||
class NativeProperty final : public Cell {
|
|
||||||
public:
|
|
||||||
NativeProperty(Function<Value(VM&, GlobalObject&)> getter, Function<void(VM&, GlobalObject&, Value)> setter);
|
|
||||||
virtual ~NativeProperty() override;
|
|
||||||
|
|
||||||
Value get(VM&, GlobalObject&) const;
|
|
||||||
void set(VM&, GlobalObject&, Value);
|
|
||||||
|
|
||||||
private:
|
|
||||||
virtual const char* class_name() const override { return "NativeProperty"; }
|
|
||||||
|
|
||||||
Function<Value(VM&, GlobalObject&)> m_getter;
|
|
||||||
Function<void(VM&, GlobalObject&, Value)> m_setter;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
|
@ -15,7 +15,6 @@
|
||||||
#include <LibJS/Runtime/Error.h>
|
#include <LibJS/Runtime/Error.h>
|
||||||
#include <LibJS/Runtime/GlobalObject.h>
|
#include <LibJS/Runtime/GlobalObject.h>
|
||||||
#include <LibJS/Runtime/NativeFunction.h>
|
#include <LibJS/Runtime/NativeFunction.h>
|
||||||
#include <LibJS/Runtime/NativeProperty.h>
|
|
||||||
#include <LibJS/Runtime/Object.h>
|
#include <LibJS/Runtime/Object.h>
|
||||||
#include <LibJS/Runtime/PropertyDescriptor.h>
|
#include <LibJS/Runtime/PropertyDescriptor.h>
|
||||||
#include <LibJS/Runtime/ProxyObject.h>
|
#include <LibJS/Runtime/ProxyObject.h>
|
||||||
|
@ -903,7 +902,7 @@ bool Object::set_immutable_prototype(Object* prototype)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<ValueAndAttributes> Object::storage_get(PropertyName const& property_name, CallNativeProperty call_native_property) const
|
Optional<ValueAndAttributes> Object::storage_get(PropertyName const& property_name) const
|
||||||
{
|
{
|
||||||
VERIFY(property_name.is_valid());
|
VERIFY(property_name.is_valid());
|
||||||
|
|
||||||
|
@ -923,8 +922,6 @@ Optional<ValueAndAttributes> Object::storage_get(PropertyName const& property_na
|
||||||
value = m_storage[metadata->offset];
|
value = m_storage[metadata->offset];
|
||||||
attributes = metadata->attributes;
|
attributes = metadata->attributes;
|
||||||
}
|
}
|
||||||
if (value.is_native_property() && call_native_property == CallNativeProperty::Yes)
|
|
||||||
value = call_native_property_getter(value.as_native_property(), this);
|
|
||||||
return ValueAndAttributes { .value = value, .attributes = attributes };
|
return ValueAndAttributes { .value = value, .attributes = attributes };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -944,15 +941,7 @@ void Object::storage_set(PropertyName const& property_name, ValueAndAttributes c
|
||||||
|
|
||||||
if (property_name.is_number()) {
|
if (property_name.is_number()) {
|
||||||
auto index = property_name.as_number();
|
auto index = property_name.as_number();
|
||||||
if (value.is_native_property()) {
|
m_indexed_properties.put(index, value, attributes);
|
||||||
m_indexed_properties.put(index, value, attributes);
|
|
||||||
} else {
|
|
||||||
auto existing_value = m_indexed_properties.get(index);
|
|
||||||
if (existing_value.has_value() && existing_value->value.is_native_property())
|
|
||||||
call_native_property_setter(existing_value->value.as_native_property(), this, value);
|
|
||||||
else
|
|
||||||
m_indexed_properties.put(index, value, attributes);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -998,15 +987,7 @@ void Object::storage_set(PropertyName const& property_name, ValueAndAttributes c
|
||||||
VERIFY(metadata.has_value());
|
VERIFY(metadata.has_value());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value.is_native_property()) {
|
m_storage[metadata->offset] = value;
|
||||||
m_storage[metadata->offset] = value;
|
|
||||||
} else {
|
|
||||||
auto existing_value = m_storage[metadata->offset];
|
|
||||||
if (existing_value.is_native_property())
|
|
||||||
call_native_property_setter(existing_value.as_native_property(), this, value);
|
|
||||||
else
|
|
||||||
m_storage[metadata->offset] = value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Object::storage_delete(PropertyName const& property_name)
|
void Object::storage_delete(PropertyName const& property_name)
|
||||||
|
@ -1090,7 +1071,7 @@ Value Object::get_without_side_effects(const PropertyName& property_name) const
|
||||||
{
|
{
|
||||||
auto* object = this;
|
auto* object = this;
|
||||||
while (object) {
|
while (object) {
|
||||||
auto value_and_attributes = object->storage_get(property_name, CallNativeProperty::No);
|
auto value_and_attributes = object->storage_get(property_name);
|
||||||
if (value_and_attributes.has_value())
|
if (value_and_attributes.has_value())
|
||||||
return value_and_attributes->value;
|
return value_and_attributes->value;
|
||||||
object = object->prototype();
|
object = object->prototype();
|
||||||
|
@ -1113,11 +1094,6 @@ void Object::define_native_function(PropertyName const& property_name, Function<
|
||||||
define_direct_property(property_name, function, attribute);
|
define_direct_property(property_name, function, attribute);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Object::define_native_property(PropertyName const& property_name, Function<Value(VM&, GlobalObject&)> getter, Function<void(VM&, GlobalObject&, Value)> setter, PropertyAttributes attribute)
|
|
||||||
{
|
|
||||||
define_direct_property(property_name, heap().allocate_without_global_object<NativeProperty>(move(getter), move(setter)), attribute);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 20.1.2.3.1 ObjectDefineProperties ( O, Properties ), https://tc39.es/ecma262/#sec-objectdefineproperties
|
// 20.1.2.3.1 ObjectDefineProperties ( O, Properties ), https://tc39.es/ecma262/#sec-objectdefineproperties
|
||||||
Object* Object::define_properties(Value properties)
|
Object* Object::define_properties(Value properties)
|
||||||
{
|
{
|
||||||
|
@ -1238,35 +1214,4 @@ Value Object::invoke_internal(const StringOrSymbol& property_name, Optional<Mark
|
||||||
return vm.call(property.as_function(), this, move(arguments));
|
return vm.call(property.as_function(), this, move(arguments));
|
||||||
}
|
}
|
||||||
|
|
||||||
Value Object::call_native_property_getter(NativeProperty& property, Value this_value) const
|
|
||||||
{
|
|
||||||
auto& vm = this->vm();
|
|
||||||
ExecutionContext execution_context;
|
|
||||||
if (auto* interpreter = vm.interpreter_if_exists())
|
|
||||||
execution_context.current_node = interpreter->current_node();
|
|
||||||
execution_context.is_strict_mode = vm.in_strict_mode();
|
|
||||||
execution_context.this_value = this_value;
|
|
||||||
vm.push_execution_context(execution_context, global_object());
|
|
||||||
if (vm.exception())
|
|
||||||
return {};
|
|
||||||
auto result = property.get(vm, global_object());
|
|
||||||
vm.pop_execution_context();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Object::call_native_property_setter(NativeProperty& property, Value this_value, Value setter_value) const
|
|
||||||
{
|
|
||||||
auto& vm = this->vm();
|
|
||||||
ExecutionContext execution_context;
|
|
||||||
if (auto* interpreter = vm.interpreter_if_exists())
|
|
||||||
execution_context.current_node = interpreter->current_node();
|
|
||||||
execution_context.is_strict_mode = vm.in_strict_mode();
|
|
||||||
execution_context.this_value = this_value;
|
|
||||||
vm.push_execution_context(execution_context, global_object());
|
|
||||||
if (vm.exception())
|
|
||||||
return;
|
|
||||||
property.set(vm, global_object(), setter_value);
|
|
||||||
vm.pop_execution_context();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,12 +111,7 @@ public:
|
||||||
|
|
||||||
// Implementation-specific storage abstractions
|
// Implementation-specific storage abstractions
|
||||||
|
|
||||||
enum class CallNativeProperty {
|
Optional<ValueAndAttributes> storage_get(PropertyName const&) const;
|
||||||
Yes,
|
|
||||||
No,
|
|
||||||
};
|
|
||||||
|
|
||||||
Optional<ValueAndAttributes> storage_get(PropertyName const&, CallNativeProperty = CallNativeProperty::Yes) const;
|
|
||||||
bool storage_has(PropertyName const&) const;
|
bool storage_has(PropertyName const&) const;
|
||||||
void storage_set(PropertyName const&, ValueAndAttributes const&);
|
void storage_set(PropertyName const&, ValueAndAttributes const&);
|
||||||
void storage_delete(PropertyName const&);
|
void storage_delete(PropertyName const&);
|
||||||
|
@ -129,7 +124,6 @@ public:
|
||||||
void define_direct_accessor(PropertyName const&, FunctionObject* getter, FunctionObject* setter, PropertyAttributes attributes);
|
void define_direct_accessor(PropertyName const&, FunctionObject* getter, FunctionObject* setter, PropertyAttributes attributes);
|
||||||
|
|
||||||
void define_native_function(PropertyName const&, Function<Value(VM&, GlobalObject&)>, i32 length, PropertyAttributes attributes);
|
void define_native_function(PropertyName const&, Function<Value(VM&, GlobalObject&)>, i32 length, PropertyAttributes attributes);
|
||||||
void define_native_property(PropertyName const&, Function<Value(VM&, GlobalObject&)> getter, Function<void(VM&, GlobalObject&, Value)> setter, PropertyAttributes attributes);
|
|
||||||
void define_native_accessor(PropertyName const&, Function<Value(VM&, GlobalObject&)> getter, Function<Value(VM&, GlobalObject&)> setter, PropertyAttributes attributes);
|
void define_native_accessor(PropertyName const&, Function<Value(VM&, GlobalObject&)> getter, Function<Value(VM&, GlobalObject&)> setter, PropertyAttributes attributes);
|
||||||
|
|
||||||
virtual bool is_function() const { return false; }
|
virtual bool is_function() const { return false; }
|
||||||
|
@ -196,9 +190,6 @@ protected:
|
||||||
bool m_has_parameter_map { false };
|
bool m_has_parameter_map { false };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Value call_native_property_getter(NativeProperty& property, Value this_value) const;
|
|
||||||
void call_native_property_setter(NativeProperty& property, Value this_value, Value) const;
|
|
||||||
|
|
||||||
void set_shape(Shape&);
|
void set_shape(Shape&);
|
||||||
|
|
||||||
Object* prototype() { return shape().prototype(); }
|
Object* prototype() { return shape().prototype(); }
|
||||||
|
|
|
@ -318,8 +318,6 @@ String Value::to_string_without_side_effects() const
|
||||||
return String::formatted("[object {}]", as_object().class_name());
|
return String::formatted("[object {}]", as_object().class_name());
|
||||||
case Type::Accessor:
|
case Type::Accessor:
|
||||||
return "<accessor>";
|
return "<accessor>";
|
||||||
case Type::NativeProperty:
|
|
||||||
return "<native-property>";
|
|
||||||
default:
|
default:
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,6 @@ public:
|
||||||
Symbol,
|
Symbol,
|
||||||
Accessor,
|
Accessor,
|
||||||
BigInt,
|
BigInt,
|
||||||
NativeProperty,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class PreferredType {
|
enum class PreferredType {
|
||||||
|
@ -60,9 +59,8 @@ public:
|
||||||
bool is_symbol() const { return m_type == Type::Symbol; }
|
bool is_symbol() const { return m_type == Type::Symbol; }
|
||||||
bool is_accessor() const { return m_type == Type::Accessor; };
|
bool is_accessor() const { return m_type == Type::Accessor; };
|
||||||
bool is_bigint() const { return m_type == Type::BigInt; };
|
bool is_bigint() const { return m_type == Type::BigInt; };
|
||||||
bool is_native_property() const { return m_type == Type::NativeProperty; }
|
|
||||||
bool is_nullish() const { return is_null() || is_undefined(); }
|
bool is_nullish() const { return is_null() || is_undefined(); }
|
||||||
bool is_cell() const { return is_string() || is_accessor() || is_object() || is_bigint() || is_symbol() || is_native_property(); }
|
bool is_cell() const { return is_string() || is_accessor() || is_object() || is_bigint() || is_symbol(); }
|
||||||
bool is_array(GlobalObject&) const;
|
bool is_array(GlobalObject&) const;
|
||||||
bool is_function() const;
|
bool is_function() const;
|
||||||
bool is_constructor() const;
|
bool is_constructor() const;
|
||||||
|
@ -164,12 +162,6 @@ public:
|
||||||
m_value.as_bigint = const_cast<BigInt*>(bigint);
|
m_value.as_bigint = const_cast<BigInt*>(bigint);
|
||||||
}
|
}
|
||||||
|
|
||||||
Value(const NativeProperty* native_property)
|
|
||||||
: m_type(Type::NativeProperty)
|
|
||||||
{
|
|
||||||
m_value.as_native_property = const_cast<NativeProperty*>(native_property);
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit Value(Type type)
|
explicit Value(Type type)
|
||||||
: m_type(type)
|
: m_type(type)
|
||||||
{
|
{
|
||||||
|
@ -245,12 +237,6 @@ public:
|
||||||
return *m_value.as_bigint;
|
return *m_value.as_bigint;
|
||||||
}
|
}
|
||||||
|
|
||||||
NativeProperty& as_native_property()
|
|
||||||
{
|
|
||||||
VERIFY(is_native_property());
|
|
||||||
return *m_value.as_native_property;
|
|
||||||
}
|
|
||||||
|
|
||||||
Array& as_array();
|
Array& as_array();
|
||||||
FunctionObject& as_function();
|
FunctionObject& as_function();
|
||||||
|
|
||||||
|
@ -318,7 +304,6 @@ private:
|
||||||
Cell* as_cell;
|
Cell* as_cell;
|
||||||
Accessor* as_accessor;
|
Accessor* as_accessor;
|
||||||
BigInt* as_bigint;
|
BigInt* as_bigint;
|
||||||
NativeProperty* as_native_property;
|
|
||||||
|
|
||||||
u64 encoded;
|
u64 encoded;
|
||||||
} m_value { .encoded = 0 };
|
} m_value { .encoded = 0 };
|
||||||
|
|
|
@ -646,7 +646,7 @@ JS::Interpreter& Document::interpreter()
|
||||||
auto& object = value.as_object();
|
auto& object = value.as_object();
|
||||||
auto name = object.get_without_side_effects(vm.names.name).value_or(JS::js_undefined());
|
auto name = object.get_without_side_effects(vm.names.name).value_or(JS::js_undefined());
|
||||||
auto message = object.get_without_side_effects(vm.names.message).value_or(JS::js_undefined());
|
auto message = object.get_without_side_effects(vm.names.message).value_or(JS::js_undefined());
|
||||||
if (name.is_accessor() || name.is_native_property() || message.is_accessor() || message.is_native_property()) {
|
if (name.is_accessor() || message.is_accessor()) {
|
||||||
// The result is not going to be useful, let's just print the value. This affects DOMExceptions, for example.
|
// The result is not going to be useful, let's just print the value. This affects DOMExceptions, for example.
|
||||||
dbgln("Unhandled JavaScript exception: {}", value);
|
dbgln("Unhandled JavaScript exception: {}", value);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -255,7 +255,7 @@ static void print_error(JS::Object const& object, HashTable<JS::Object*>& seen_o
|
||||||
{
|
{
|
||||||
auto name = object.get_without_side_effects(vm->names.name).value_or(JS::js_undefined());
|
auto name = object.get_without_side_effects(vm->names.name).value_or(JS::js_undefined());
|
||||||
auto message = object.get_without_side_effects(vm->names.message).value_or(JS::js_undefined());
|
auto message = object.get_without_side_effects(vm->names.message).value_or(JS::js_undefined());
|
||||||
if (name.is_accessor() || name.is_native_property() || message.is_accessor() || message.is_native_property()) {
|
if (name.is_accessor() || message.is_accessor()) {
|
||||||
print_value(&object, seen_objects);
|
print_value(&object, seen_objects);
|
||||||
} else {
|
} else {
|
||||||
auto name_string = name.to_string_without_side_effects();
|
auto name_string = name.to_string_without_side_effects();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue