summaryrefslogtreecommitdiff
path: root/Libraries/LibJS/Runtime
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-03-29 00:37:33 +0100
committerAndreas Kling <kling@serenityos.org>2020-03-29 00:37:33 +0100
commit30440134cbab4851413ea1f0649e5272b50ea48b (patch)
treeba39e496588531913dd60a5489cf96e65a9571b8 /Libraries/LibJS/Runtime
parent56936b97d001bd72bd7ad2f7796f4ec6e171b100 (diff)
downloadserenity-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/Runtime')
-rw-r--r--Libraries/LibJS/Runtime/Array.cpp26
-rw-r--r--Libraries/LibJS/Runtime/Array.h3
-rw-r--r--Libraries/LibJS/Runtime/ErrorPrototype.cpp37
-rw-r--r--Libraries/LibJS/Runtime/ErrorPrototype.h3
-rw-r--r--Libraries/LibJS/Runtime/NativeProperty.cpp10
-rw-r--r--Libraries/LibJS/Runtime/NativeProperty.h10
-rw-r--r--Libraries/LibJS/Runtime/Object.cpp28
-rw-r--r--Libraries/LibJS/Runtime/Object.h2
-rw-r--r--Libraries/LibJS/Runtime/StringPrototype.cpp19
-rw-r--r--Libraries/LibJS/Runtime/StringPrototype.h2
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&);
};
}