LibJS: Add ObjectPrototype and implement hasOwnProperty()

All Objects will now have ObjectPrototype as their prototype, unless
overridden.
This commit is contained in:
Andreas Kling 2020-03-15 15:25:43 +01:00
parent f1f14945cf
commit 23b1d97b0d
Notes: sideshowbarker 2024-07-19 08:17:46 +09:00
8 changed files with 114 additions and 0 deletions

View file

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

View file

@ -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) {

View file

@ -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 };
};
}

View file

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

View file

@ -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();
}
}

View file

@ -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 };

View file

@ -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()
{
}
}

View file

@ -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"; }
};
}