diff options
author | Andreas Kling <kling@serenityos.org> | 2020-03-29 00:37:33 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-03-29 00:37:33 +0100 |
commit | 30440134cbab4851413ea1f0649e5272b50ea48b (patch) | |
tree | ba39e496588531913dd60a5489cf96e65a9571b8 /Libraries/LibJS | |
parent | 56936b97d001bd72bd7ad2f7796f4ec6e171b100 (diff) | |
download | serenity-30440134cbab4851413ea1f0649e5272b50ea48b.zip |
LibJS+LibWeb: Move native properties to separate getters/setters
This was a bit cumbersome now, but it gets us closer to a format suited
for code generation.
Diffstat (limited to 'Libraries/LibJS')
-rw-r--r-- | Libraries/LibJS/Runtime/Array.cpp | 26 | ||||
-rw-r--r-- | Libraries/LibJS/Runtime/Array.h | 3 | ||||
-rw-r--r-- | Libraries/LibJS/Runtime/ErrorPrototype.cpp | 37 | ||||
-rw-r--r-- | Libraries/LibJS/Runtime/ErrorPrototype.h | 3 | ||||
-rw-r--r-- | Libraries/LibJS/Runtime/NativeProperty.cpp | 10 | ||||
-rw-r--r-- | Libraries/LibJS/Runtime/NativeProperty.h | 10 | ||||
-rw-r--r-- | Libraries/LibJS/Runtime/Object.cpp | 28 | ||||
-rw-r--r-- | Libraries/LibJS/Runtime/Object.h | 2 | ||||
-rw-r--r-- | Libraries/LibJS/Runtime/StringPrototype.cpp | 19 | ||||
-rw-r--r-- | Libraries/LibJS/Runtime/StringPrototype.h | 2 |
10 files changed, 94 insertions, 46 deletions
diff --git a/Libraries/LibJS/Runtime/Array.cpp b/Libraries/LibJS/Runtime/Array.cpp index 6d3149f423..019697fe74 100644 --- a/Libraries/LibJS/Runtime/Array.cpp +++ b/Libraries/LibJS/Runtime/Array.cpp @@ -27,20 +27,14 @@ #include <AK/Function.h> #include <LibJS/Interpreter.h> #include <LibJS/Runtime/Array.h> +#include <LibJS/Runtime/Error.h> namespace JS { Array::Array() { set_prototype(interpreter().array_prototype()); - put_native_property( - "length", - [this](Object*) { - return Value(length()); - }, - [](Object*, Value) { - ASSERT_NOT_REACHED(); - }); + put_native_property("length", length_getter, length_setter); } Array::~Array() @@ -96,4 +90,20 @@ bool Array::put_own_property(Object& this_object, const FlyString& property_name } return Object::put_own_property(this_object, property_name, value); } + +Value Array::length_getter(Interpreter& interpreter) +{ + auto* this_object = interpreter.this_value().to_object(interpreter.heap()); + if (!this_object) + return {}; + if (!this_object->is_array()) + return interpreter.throw_exception<Error>("TypeError", "Not an array"); + return Value(static_cast<const Array*>(this_object)->length()); +} + +void Array::length_setter(Interpreter&, Value) +{ + ASSERT_NOT_REACHED(); +} + } diff --git a/Libraries/LibJS/Runtime/Array.h b/Libraries/LibJS/Runtime/Array.h index e43e845526..61c45644a0 100644 --- a/Libraries/LibJS/Runtime/Array.h +++ b/Libraries/LibJS/Runtime/Array.h @@ -50,6 +50,9 @@ private: virtual Optional<Value> get_own_property(const Object& this_object, const FlyString& property_name) const override; virtual bool put_own_property(Object& this_object, const FlyString& property_name, Value) override; + static Value length_getter(Interpreter&); + static void length_setter(Interpreter&, Value); + Vector<Value> m_elements; }; diff --git a/Libraries/LibJS/Runtime/ErrorPrototype.cpp b/Libraries/LibJS/Runtime/ErrorPrototype.cpp index 165dd2d9e7..a15707c0da 100644 --- a/Libraries/LibJS/Runtime/ErrorPrototype.cpp +++ b/Libraries/LibJS/Runtime/ErrorPrototype.cpp @@ -36,25 +36,32 @@ namespace JS { ErrorPrototype::ErrorPrototype() { - put_native_property( - "name", [](Object* this_object) { - ASSERT(this_object); - ASSERT(this_object->is_error()); - return js_string(this_object->heap(), static_cast<const Error*>(this_object)->name()); - }, - nullptr); - - put_native_property( - "message", [](Object* this_object) { - ASSERT(this_object); - ASSERT(this_object->is_error()); - return js_string(this_object->heap(), static_cast<const Error*>(this_object)->message()); - }, - nullptr); + put_native_property("name", name_getter, nullptr); + put_native_property("message", message_getter, nullptr); } ErrorPrototype::~ErrorPrototype() { } +Value ErrorPrototype::name_getter(Interpreter& interpreter) +{ + auto* this_object = interpreter.this_value().to_object(interpreter.heap()); + if (!this_object) + return {}; + if (!this_object->is_error()) + return interpreter.throw_exception<Error>("TypeError", "Not an Error object"); + return js_string(interpreter.heap(), static_cast<const Error*>(this_object)->name()); +} + +Value ErrorPrototype::message_getter(Interpreter& interpreter) +{ + auto* this_object = interpreter.this_value().to_object(interpreter.heap()); + if (!this_object) + return {}; + if (!this_object->is_error()) + return interpreter.throw_exception<Error>("TypeError", "Not an Error object"); + return js_string(interpreter.heap(), static_cast<const Error*>(this_object)->message()); +} + } diff --git a/Libraries/LibJS/Runtime/ErrorPrototype.h b/Libraries/LibJS/Runtime/ErrorPrototype.h index 8775b6aa51..dd334f1cc4 100644 --- a/Libraries/LibJS/Runtime/ErrorPrototype.h +++ b/Libraries/LibJS/Runtime/ErrorPrototype.h @@ -37,6 +37,9 @@ public: private: virtual const char* class_name() const override { return "ErrorPrototype"; } + + static Value name_getter(Interpreter&); + static Value message_getter(Interpreter&); }; } diff --git a/Libraries/LibJS/Runtime/NativeProperty.cpp b/Libraries/LibJS/Runtime/NativeProperty.cpp index 58ea73b9b3..c19a1f1d9d 100644 --- a/Libraries/LibJS/Runtime/NativeProperty.cpp +++ b/Libraries/LibJS/Runtime/NativeProperty.cpp @@ -29,7 +29,7 @@ namespace JS { -NativeProperty::NativeProperty(AK::Function<Value(Object*)> getter, AK::Function<void(Object*, Value)> setter) +NativeProperty::NativeProperty(AK::Function<Value(Interpreter&)> getter, AK::Function<void(Interpreter&, Value)> setter) : m_getter(move(getter)) , m_setter(move(setter)) { @@ -39,18 +39,18 @@ NativeProperty::~NativeProperty() { } -Value NativeProperty::get(Object* object) const +Value NativeProperty::get(Interpreter& interpreter) const { if (!m_getter) return js_undefined(); - return m_getter(object); + return m_getter(interpreter); } -void NativeProperty::set(Object* object, Value value) +void NativeProperty::set(Interpreter& interpreter, Value value) { if (!m_setter) return; - m_setter(object, move(value)); + m_setter(interpreter, move(value)); } } diff --git a/Libraries/LibJS/Runtime/NativeProperty.h b/Libraries/LibJS/Runtime/NativeProperty.h index 0044ac5a0f..0c9619e2bd 100644 --- a/Libraries/LibJS/Runtime/NativeProperty.h +++ b/Libraries/LibJS/Runtime/NativeProperty.h @@ -33,18 +33,18 @@ namespace JS { class NativeProperty final : public Object { public: - NativeProperty(AK::Function<Value(Object*)> getter, AK::Function<void(Object*, Value)> setter); + NativeProperty(AK::Function<Value(Interpreter&)> getter, AK::Function<void(Interpreter&, Value)> setter); virtual ~NativeProperty() override; - Value get(Object*) const; - void set(Object*, Value); + Value get(Interpreter&) const; + void set(Interpreter&, Value); private: virtual bool is_native_property() const override { return true; } virtual const char* class_name() const override { return "NativeProperty"; } - AK::Function<Value(Object*)> m_getter; - AK::Function<void(Object*, Value)> m_setter; + AK::Function<Value(Interpreter&)> m_getter; + AK::Function<void(Interpreter&, Value)> m_setter; }; } diff --git a/Libraries/LibJS/Runtime/Object.cpp b/Libraries/LibJS/Runtime/Object.cpp index da75c7f7c4..d398a7093b 100644 --- a/Libraries/LibJS/Runtime/Object.cpp +++ b/Libraries/LibJS/Runtime/Object.cpp @@ -56,8 +56,15 @@ bool Object::has_prototype(const Object* prototype) const Optional<Value> Object::get_own_property(const Object& this_object, const FlyString& property_name) const { auto value_here = m_properties.get(property_name); - if (value_here.has_value() && value_here.value().is_object() && value_here.value().as_object()->is_native_property()) - return static_cast<NativeProperty*>(value_here.value().as_object())->get(&const_cast<Object&>(this_object)); + if (value_here.has_value() && value_here.value().is_object() && value_here.value().as_object()->is_native_property()) { + auto& native_property = static_cast<const NativeProperty&>(*value_here.value().as_object()); + auto& interpreter = const_cast<Object*>(this)->interpreter(); + auto& call_frame = interpreter.push_call_frame(); + call_frame.this_value = const_cast<Object*>(&this_object); + auto result = native_property.get(interpreter); + interpreter.pop_call_frame(); + return result; + } return value_here; } @@ -65,7 +72,13 @@ bool Object::put_own_property(Object& this_object, const FlyString& property_nam { auto value_here = m_properties.get(property_name); if (value_here.has_value() && value_here.value().is_object() && value_here.value().as_object()->is_native_property()) { - static_cast<NativeProperty*>(value_here.value().as_object())->set(&this_object, value); + auto& native_property = static_cast<NativeProperty&>(*value_here.value().as_object()); + auto& interpreter = const_cast<Object*>(this)->interpreter(); + auto& call_frame = interpreter.push_call_frame(); + call_frame.this_value = &this_object; + dbg() << "put_own_property: " << &this_object << " . " << property_name << " = " << value; + native_property.set(interpreter, value); + interpreter.pop_call_frame(); } else { m_properties.set(property_name, value); } @@ -91,7 +104,12 @@ void Object::put(const FlyString& property_name, Value value) auto value_here = object->m_properties.get(property_name); if (value_here.has_value()) { if (value_here.value().is_object() && value_here.value().as_object()->is_native_property()) { - static_cast<NativeProperty*>(value_here.value().as_object())->set(const_cast<Object*>(this), value); + auto& native_property = static_cast<NativeProperty&>(*value_here.value().as_object()); + auto& interpreter = const_cast<Object*>(this)->interpreter(); + auto& call_frame = interpreter.push_call_frame(); + call_frame.this_value = this; + native_property.set(interpreter, value); + interpreter.pop_call_frame(); return; } if (object->put_own_property(*this, property_name, value)) @@ -107,7 +125,7 @@ void Object::put_native_function(const FlyString& property_name, AK::Function<Va put(property_name, heap().allocate<NativeFunction>(move(native_function))); } -void Object::put_native_property(const FlyString& property_name, AK::Function<Value(Object*)> getter, AK::Function<void(Object*, Value)> setter) +void Object::put_native_property(const FlyString& property_name, AK::Function<Value(Interpreter&)> getter, AK::Function<void(Interpreter&, Value)> setter) { put(property_name, heap().allocate<NativeProperty>(move(getter), move(setter))); } diff --git a/Libraries/LibJS/Runtime/Object.h b/Libraries/LibJS/Runtime/Object.h index 3ac6202662..537037dfa8 100644 --- a/Libraries/LibJS/Runtime/Object.h +++ b/Libraries/LibJS/Runtime/Object.h @@ -47,7 +47,7 @@ public: virtual bool put_own_property(Object& this_object, const FlyString& property_name, Value); void put_native_function(const FlyString& property_name, AK::Function<Value(Interpreter&)>); - void put_native_property(const FlyString& property_name, AK::Function<Value(Object*)> getter, AK::Function<void(Object*, Value)> setter); + void put_native_property(const FlyString& property_name, AK::Function<Value(Interpreter&)> getter, AK::Function<void(Interpreter&, Value)> setter); virtual bool is_error() const { return false; } virtual bool is_array() const { return false; } diff --git a/Libraries/LibJS/Runtime/StringPrototype.cpp b/Libraries/LibJS/Runtime/StringPrototype.cpp index ffdaddd4de..5d05545d05 100644 --- a/Libraries/LibJS/Runtime/StringPrototype.cpp +++ b/Libraries/LibJS/Runtime/StringPrototype.cpp @@ -28,6 +28,7 @@ #include <AK/StringBuilder.h> #include <LibJS/Heap/Heap.h> #include <LibJS/Interpreter.h> +#include <LibJS/Runtime/Error.h> #include <LibJS/Runtime/PrimitiveString.h> #include <LibJS/Runtime/StringObject.h> #include <LibJS/Runtime/StringPrototype.h> @@ -37,13 +38,7 @@ namespace JS { StringPrototype::StringPrototype() { - put_native_property( - "length", [](Object* this_object) { - ASSERT(this_object); - ASSERT(this_object->is_string_object()); - return Value((i32) static_cast<const StringObject*>(this_object)->primitive_string()->string().length()); - }, - nullptr); + put_native_property("length", length_getter, nullptr); put_native_function("charAt", char_at); put_native_function("repeat", repeat); } @@ -88,4 +83,14 @@ Value StringPrototype::repeat(Interpreter& interpreter) return js_string(interpreter.heap(), builder.to_string()); } +Value StringPrototype::length_getter(Interpreter& interpreter) +{ + auto* this_object = interpreter.this_value().to_object(interpreter.heap()); + if (!this_object) + return {}; + if (!this_object->is_string_object()) + return interpreter.throw_exception<Error>("TypeError", "Not a String object"); + return Value((i32) static_cast<const StringObject*>(this_object)->primitive_string()->string().length()); +} + } diff --git a/Libraries/LibJS/Runtime/StringPrototype.h b/Libraries/LibJS/Runtime/StringPrototype.h index 74beb46bdd..b12c674584 100644 --- a/Libraries/LibJS/Runtime/StringPrototype.h +++ b/Libraries/LibJS/Runtime/StringPrototype.h @@ -40,6 +40,8 @@ private: static Value char_at(Interpreter&); static Value repeat(Interpreter&); + + static Value length_getter(Interpreter&); }; } |