Selaa lähdekoodia

LibJS: Add ObjectPrototype and implement hasOwnProperty()

All Objects will now have ObjectPrototype as their prototype, unless
overridden.
Andreas Kling 5 vuotta sitten
vanhempi
commit
23b1d97b0d

+ 2 - 0
Base/home/anon/js/hasOwnProperty.js

@@ -0,0 +1,2 @@
+var x = "foobar";
+print(x.hasOwnProperty("length"));

+ 3 - 0
Libraries/LibJS/Interpreter.cpp

@@ -30,6 +30,7 @@
 #include <LibJS/Interpreter.h>
 #include <LibJS/NativeFunction.h>
 #include <LibJS/Object.h>
+#include <LibJS/ObjectPrototype.h>
 #include <LibJS/StringPrototype.h>
 #include <LibJS/Value.h>
 
@@ -39,6 +40,7 @@ Interpreter::Interpreter()
     : m_heap(*this)
 {
     m_global_object = heap().allocate<GlobalObject>();
+    m_object_prototype = heap().allocate<ObjectPrototype>();
     m_string_prototype = heap().allocate<StringPrototype>();
 }
 
@@ -140,6 +142,7 @@ void Interpreter::gather_roots(Badge<Heap>, HashTable<Cell*>& roots)
 {
     roots.set(m_global_object);
     roots.set(m_string_prototype);
+    roots.set(m_object_prototype);
 
     for (auto& scope : m_scope_stack) {
         for (auto& it : scope.variables) {

+ 2 - 0
Libraries/LibJS/Interpreter.h

@@ -89,6 +89,7 @@ public:
     }
 
     Object* string_prototype() { return m_string_prototype; }
+    Object* object_prototype() { return m_object_prototype; }
 
 private:
     Heap m_heap;
@@ -98,6 +99,7 @@ private:
 
     Object* m_global_object { nullptr };
     Object* m_string_prototype { nullptr };
+    Object* m_object_prototype { nullptr };
 };
 
 }

+ 1 - 0
Libraries/LibJS/Makefile

@@ -9,6 +9,7 @@ OBJS = \
     Lexer.o \
     NativeFunction.o \
     Object.o \
+    ObjectPrototype.o \
     Parser.o \
     PrimitiveString.o \
     ScriptFunction.o \

+ 8 - 0
Libraries/LibJS/Object.cpp

@@ -26,6 +26,7 @@
 
 #include <AK/String.h>
 #include <LibJS/Heap.h>
+#include <LibJS/Interpreter.h>
 #include <LibJS/NativeFunction.h>
 #include <LibJS/Object.h>
 #include <LibJS/Value.h>
@@ -34,6 +35,7 @@ namespace JS {
 
 Object::Object()
 {
+    set_prototype(interpreter().object_prototype());
 }
 
 Object::~Object()
@@ -44,6 +46,7 @@ Value Object::get(String property_name) const
 {
     const Object* object = this;
     while (object) {
+        dbg() << "Object::get() trying '" << property_name << "' in " << object->class_name();
         auto value = object->m_properties.get(property_name);
         if (value.has_value())
             return value.value();
@@ -71,4 +74,9 @@ void Object::visit_children(Cell::Visitor& visitor)
         visitor.visit(it.value);
 }
 
+bool Object::has_own_property(const String& property_name) const
+{
+    return m_properties.get(property_name).has_value();
+}
+
 }

+ 2 - 0
Libraries/LibJS/Object.h

@@ -54,6 +54,8 @@ public:
     const Object* prototype() const { return m_prototype; }
     void set_prototype(Object* prototype) { m_prototype = prototype; }
 
+    bool has_own_property(const String& property_name) const;
+
 private:
     HashMap<String, Value> m_properties;
     Object* m_prototype { nullptr };

+ 54 - 0
Libraries/LibJS/ObjectPrototype.cpp

@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <AK/Function.h>
+#include <AK/String.h>
+#include <LibJS/Heap.h>
+#include <LibJS/Interpreter.h>
+#include <LibJS/ObjectPrototype.h>
+#include <LibJS/Value.h>
+
+namespace JS {
+
+ObjectPrototype::ObjectPrototype()
+{
+    set_prototype(nullptr);
+
+    put_native_function("hasOwnProperty", [](Interpreter& interpreter, Vector<Value> arguments) -> Value {
+        dbg() << "hasOwnProperty";
+        if (arguments.is_empty())
+            return js_undefined();
+        Value this_value = interpreter.this_value();
+        ASSERT(this_value.is_object());
+        return Value(this_value.as_object()->has_own_property(arguments[0].to_string()));
+    });
+}
+
+ObjectPrototype::~ObjectPrototype()
+{
+}
+
+}

+ 42 - 0
Libraries/LibJS/ObjectPrototype.h

@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <LibJS/Object.h>
+
+namespace JS {
+
+class ObjectPrototype final : public Object {
+public:
+    ObjectPrototype();
+    virtual ~ObjectPrototype() override;
+
+private:
+    virtual const char* class_name() const override { return "ObjectPrototype"; }
+};
+
+}