1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 02:27:43 +00:00

LibJS: Add "Heap" and "Runtime" subdirectories

Let's try to keep LibJS tidy as it expands. :^)
This commit is contained in:
Andreas Kling 2020-03-16 14:20:30 +01:00
parent 6780d70fb1
commit 19452230cd
39 changed files with 99 additions and 98 deletions

View file

@ -0,0 +1,60 @@
/*
* 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/LogStream.h>
#include <LibJS/Heap/Heap.h>
#include <LibJS/Heap/HeapBlock.h>
#include <LibJS/Runtime/Cell.h>
#include <LibJS/Runtime/Object.h>
#include <LibJS/Runtime/PrimitiveString.h>
#include <LibJS/Runtime/Value.h>
namespace JS {
void Cell::Visitor::visit(Value value)
{
if (value.is_cell())
visit(value.as_cell());
}
Heap& Cell::heap() const
{
return HeapBlock::from_cell(this)->heap();
}
Interpreter& Cell::interpreter()
{
return heap().interpreter();
}
const LogStream& operator<<(const LogStream& stream, const Cell* cell)
{
if (!cell)
return stream << "Cell{nullptr}";
return stream << cell->class_name() << '{' << static_cast<const void*>(cell) << '}';
}
}

View file

@ -0,0 +1,64 @@
/*
* 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 <AK/Forward.h>
#include <LibJS/Forward.h>
namespace JS {
class Cell {
public:
virtual ~Cell() {}
bool is_marked() const { return m_mark; }
void set_marked(bool b) { m_mark = b; }
bool is_live() const { return m_live; }
void set_live(bool b) { m_live = b; }
virtual const char* class_name() const = 0;
class Visitor {
public:
virtual void visit(Cell*) = 0;
void visit(Value);
};
virtual void visit_children(Visitor&) {}
Heap& heap() const;
Interpreter& interpreter();
private:
bool m_mark { false };
bool m_live { true };
};
const LogStream& operator<<(const LogStream&, const Cell*);
}

View file

@ -0,0 +1,40 @@
/*
* 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 <LibJS/Runtime/Function.h>
#include <LibJS/Runtime/Value.h>
namespace JS {
Function::Function()
{
}
Function::~Function()
{
}
}

View file

@ -0,0 +1,48 @@
/*
* 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 <AK/String.h>
#include <LibJS/Runtime/Object.h>
namespace JS {
class Function : public Object {
public:
virtual ~Function();
virtual Value call(Interpreter&, Vector<Value>) = 0;
protected:
Function();
virtual const char* class_name() const override { return "Function"; }
private:
virtual bool is_function() const final { return true; }
};
}

View file

@ -0,0 +1,31 @@
#include <AK/LogStream.h>
#include <AK/String.h>
#include <LibJS/Heap/Heap.h>
#include <LibJS/Interpreter.h>
#include <LibJS/Runtime/ConsoleObject.h>
#include <LibJS/Runtime/GlobalObject.h>
#include <LibJS/Runtime/NativeFunction.h>
#include <LibJS/Runtime/Value.h>
#include <stdio.h>
namespace JS {
GlobalObject::GlobalObject()
{
put_native_function("print", [](Object*, Vector<Value> arguments) -> Value {
for (auto& argument : arguments)
printf("%s ", argument.to_string().characters());
return js_undefined();
});
put_native_function("gc", [](Object* this_object, Vector<Value>) -> Value {
dbg() << "Forced garbage collection requested!";
this_object->heap().collect_garbage();
return js_undefined();
});
}
GlobalObject::~GlobalObject()
{
}
}

View file

@ -0,0 +1,16 @@
#pragma once
#include <LibJS/Runtime/Object.h>
namespace JS {
class GlobalObject final : public Object {
public:
explicit GlobalObject();
virtual ~GlobalObject() override;
private:
virtual const char* class_name() const override { return "GlobalObject"; }
};
}

View file

@ -0,0 +1,49 @@
/*
* 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 <LibJS/Interpreter.h>
#include <LibJS/Runtime/NativeFunction.h>
#include <LibJS/Runtime/Value.h>
namespace JS {
NativeFunction::NativeFunction(AK::Function<Value(Object*, Vector<Value>)> native_function)
: m_native_function(move(native_function))
{
}
NativeFunction::~NativeFunction()
{
}
Value NativeFunction::call(Interpreter& interpreter, Vector<Value> arguments)
{
auto this_value = interpreter.this_value();
ASSERT(this_value.is_object());
return m_native_function(this_value.as_object(), move(arguments));
}
}

View file

@ -0,0 +1,48 @@
/*
* 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 <AK/Function.h>
#include <LibJS/Runtime/Function.h>
namespace JS {
class NativeFunction final : public Function {
public:
explicit NativeFunction(AK::Function<Value(Object*, Vector<Value>)>);
virtual ~NativeFunction() override;
virtual Value call(Interpreter&, Vector<Value>) override;
private:
virtual bool is_native_function() const override { return true; }
virtual const char* class_name() const override { return "NativeFunction"; }
AK::Function<Value(Object*, Vector<Value>)> m_native_function;
};
}

View file

@ -0,0 +1,56 @@
/*
* 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 <LibJS/Runtime/NativeProperty.h>
#include <LibJS/Runtime/Value.h>
namespace JS {
NativeProperty::NativeProperty(AK::Function<Value(Object*)> getter, AK::Function<void(Object*, Value)> setter)
: m_getter(move(getter))
, m_setter(move(setter))
{
}
NativeProperty::~NativeProperty()
{
}
Value NativeProperty::get(Object* object) const
{
if (!m_getter)
return js_undefined();
return m_getter(object);
}
void NativeProperty::set(Object* object, Value value)
{
if (!m_setter)
return;
m_setter(object, move(value));
}
}

View file

@ -0,0 +1,50 @@
/*
* 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 <AK/Function.h>
#include <LibJS/Runtime/Object.h>
namespace JS {
class NativeProperty final : public Object {
public:
NativeProperty(AK::Function<Value(Object*)> getter, AK::Function<void(Object*, Value)> setter);
virtual ~NativeProperty() override;
Value get(Object*) const;
void set(Object*, 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;
};
}

View file

@ -0,0 +1,120 @@
/*
* 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/String.h>
#include <LibJS/Heap/Heap.h>
#include <LibJS/Interpreter.h>
#include <LibJS/Runtime/NativeFunction.h>
#include <LibJS/Runtime/NativeProperty.h>
#include <LibJS/Runtime/Object.h>
#include <LibJS/Runtime/Value.h>
namespace JS {
Object::Object()
{
set_prototype(interpreter().object_prototype());
}
Object::~Object()
{
}
Value Object::get(String property_name) const
{
const Object* object = this;
while (object) {
auto value = object->m_properties.get(property_name);
if (value.has_value()) {
if (value.value().is_object() && value.value().as_object()->is_native_property())
return static_cast<const NativeProperty*>(value.value().as_object())->get(const_cast<Object*>(this));
return value.value();
}
object = object->prototype();
}
return js_undefined();
}
void Object::put(String property_name, Value value)
{
m_properties.set(property_name, move(value));
}
void Object::put_native_function(String property_name, AK::Function<Value(Object*, Vector<Value>)> native_function)
{
put(property_name, heap().allocate<NativeFunction>(move(native_function)));
}
void Object::put_native_property(String property_name, AK::Function<Value(Object*)> getter, AK::Function<void(Object*, Value)> setter)
{
put(property_name, heap().allocate<NativeProperty>(move(getter), move(setter)));
}
void Object::visit_children(Cell::Visitor& visitor)
{
Cell::visit_children(visitor);
if (m_prototype)
visitor.visit(m_prototype);
for (auto& it : m_properties)
visitor.visit(it.value);
}
bool Object::has_own_property(const String& property_name) const
{
return m_properties.get(property_name).has_value();
}
Value Object::to_primitive(PreferredType preferred_type) const
{
Value result = js_undefined();
switch (preferred_type) {
case PreferredType::Default:
case PreferredType::Number: {
result = value_of();
if (result.is_object()) {
result = to_string();
}
break;
}
case PreferredType::String: {
result = to_string();
if (result.is_object())
result = value_of();
break;
}
}
ASSERT(!result.is_object());
return result;
}
Value Object::to_string() const
{
return js_string(heap(), String::format("[object %s]", class_name()));
}
}

View file

@ -0,0 +1,77 @@
/*
* 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 <AK/HashMap.h>
#include <AK/String.h>
#include <LibJS/Forward.h>
#include <LibJS/Runtime/Cell.h>
#include <LibJS/Runtime/PrimitiveString.h>
#include <LibJS/Runtime/Value.h>
namespace JS {
class Object : public Cell {
public:
Object();
virtual ~Object();
Value get(String property_name) const;
void put(String property_name, Value);
void put_native_function(String property_name, AK::Function<Value(Object*, Vector<Value>)>);
void put_native_property(String property_name, AK::Function<Value(Object*)> getter, AK::Function<void(Object*, Value)> setter);
virtual bool is_function() const { return false; }
virtual bool is_native_function() const { return false; }
virtual bool is_string_object() const { return false; }
virtual bool is_native_property() const { return false; }
virtual const char* class_name() const override { return "Object"; }
virtual void visit_children(Cell::Visitor&) override;
Object* prototype() { return m_prototype; }
const Object* prototype() const { return m_prototype; }
void set_prototype(Object* prototype) { m_prototype = prototype; }
bool has_own_property(const String& property_name) const;
enum class PreferredType {
Default,
String,
Number,
};
virtual Value value_of() const { return Value(const_cast<Object*>(this)); }
virtual Value to_primitive(PreferredType preferred_type = PreferredType::Default) const;
virtual Value to_string() const;
private:
HashMap<String, Value> m_properties;
Object* m_prototype { nullptr };
};
}

View file

@ -0,0 +1,63 @@
/*
* 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/Heap.h>
#include <LibJS/Interpreter.h>
#include <LibJS/Runtime/ObjectPrototype.h>
#include <LibJS/Runtime/Value.h>
namespace JS {
ObjectPrototype::ObjectPrototype()
{
set_prototype(nullptr);
put_native_function("hasOwnProperty", [](Object* this_object, Vector<Value> arguments) -> Value {
ASSERT(this_object);
if (arguments.is_empty())
return js_undefined();
return Value(this_object->has_own_property(arguments[0].to_string()));
});
put_native_function("toString", [](Object* this_object, Vector<Value>) -> Value {
ASSERT(this_object);
return Value(this_object->to_string());
});
put_native_function("valueOf", [](Object* this_object, Vector<Value>) -> Value {
ASSERT(this_object);
return this_object->value_of();
});
}
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/Runtime/Object.h>
namespace JS {
class ObjectPrototype final : public Object {
public:
ObjectPrototype();
virtual ~ObjectPrototype() override;
private:
virtual const char* class_name() const override { return "ObjectPrototype"; }
};
}

View file

@ -0,0 +1,46 @@
/*
* 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 <LibJS/Heap/Heap.h>
#include <LibJS/Runtime/PrimitiveString.h>
namespace JS {
PrimitiveString::PrimitiveString(String string)
: m_string(move(string))
{
}
PrimitiveString::~PrimitiveString()
{
}
PrimitiveString* js_string(Heap& heap, String string)
{
return heap.allocate<PrimitiveString>(move(string));
}
}

View file

@ -0,0 +1,49 @@
/*
* 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 <AK/String.h>
#include <LibJS/Runtime/Cell.h>
namespace JS {
class PrimitiveString final : public Cell {
public:
explicit PrimitiveString(String);
virtual ~PrimitiveString();
const String& string() const { return m_string; }
private:
virtual const char* class_name() const override { return "PrimitiveString"; }
String m_string;
};
PrimitiveString* js_string(Heap&, String);
}

View file

@ -0,0 +1,56 @@
/*
* Copyright (c) 2020, Stephan Unverwerth <s.unverwerth@gmx.de>
* 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 <LibJS/Interpreter.h>
#include <LibJS/Runtime/ScriptFunction.h>
#include <LibJS/Runtime/Value.h>
namespace JS {
ScriptFunction::ScriptFunction(const ScopeNode& body, Vector<String> parameters)
: m_body(body)
, m_parameters(move(parameters))
{
}
ScriptFunction::~ScriptFunction()
{
}
Value ScriptFunction::call(Interpreter& interpreter, Vector<Value> argument_values)
{
Vector<Argument> arguments;
for (size_t i = 0; i < m_parameters.size(); ++i) {
auto name = parameters()[i];
auto value = js_undefined();
if (i < argument_values.size())
value = argument_values[i];
arguments.append({ move(name), move(value) });
}
return interpreter.run(m_body, move(arguments), ScopeType::Function);
}
}

View file

@ -0,0 +1,51 @@
/*
* 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/Runtime/Function.h>
namespace JS {
class ScriptFunction final : public Function {
public:
ScriptFunction(const ScopeNode& body, Vector<String> parameters = {});
virtual ~ScriptFunction();
const ScopeNode& body() const { return m_body; }
const Vector<String>& parameters() const { return m_parameters; };
virtual Value call(Interpreter&, Vector<Value>) override;
private:
virtual bool is_script_function() const final { return true; }
virtual const char* class_name() const override { return "ScriptFunction"; }
const ScopeNode& m_body;
const Vector<String> m_parameters;
};
}

View file

@ -0,0 +1,52 @@
/*
* 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 <LibJS/Heap/Heap.h>
#include <LibJS/Interpreter.h>
#include <LibJS/Runtime/PrimitiveString.h>
#include <LibJS/Runtime/StringObject.h>
#include <LibJS/Runtime/StringPrototype.h>
#include <LibJS/Runtime/Value.h>
namespace JS {
StringObject::StringObject(PrimitiveString* string)
: m_string(string)
{
set_prototype(interpreter().string_prototype());
}
StringObject::~StringObject()
{
}
void StringObject::visit_children(Cell::Visitor& visitor)
{
Object::visit_children(visitor);
visitor.visit(m_string);
}
}

View file

@ -0,0 +1,52 @@
/*
* 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/Runtime/Object.h>
namespace JS {
class StringObject final : public Object {
public:
explicit StringObject(PrimitiveString*);
virtual ~StringObject() override;
virtual void visit_children(Visitor&) override;
const PrimitiveString* primitive_string() const { return m_string; }
virtual Value value_of() const override
{
return Value(m_string);
}
private:
virtual const char* class_name() const override { return "StringObject"; }
virtual bool is_string_object() const override { return true; }
PrimitiveString* m_string { nullptr };
};
}

View file

@ -0,0 +1,80 @@
/*
* 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/StringBuilder.h>
#include <LibJS/Heap/Heap.h>
#include <LibJS/Interpreter.h>
#include <LibJS/Runtime/PrimitiveString.h>
#include <LibJS/Runtime/StringObject.h>
#include <LibJS/Runtime/StringPrototype.h>
#include <LibJS/Runtime/Value.h>
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_function("charAt", [](Object* this_object, Vector<Value> arguments) -> Value {
ASSERT(this_object);
i32 index = 0;
if (!arguments.is_empty())
index = arguments[0].to_i32();
ASSERT(this_object->is_string_object());
auto underlying_string = static_cast<const StringObject*>(this_object)->primitive_string()->string();
if (index < 0 || index >= static_cast<i32>(underlying_string.length()))
return js_string(this_object->heap(), String::empty());
return js_string(this_object->heap(), underlying_string.substring(index, 1));
});
put_native_function("repeat", [](Object* this_object, Vector<Value> arguments) -> Value {
ASSERT(this_object->is_string_object());
if (arguments.is_empty())
return js_string(this_object->heap(), String::empty());
i32 count = 0;
count = arguments[0].to_i32();
if (count < 0) {
// FIXME: throw RangeError
return js_undefined();
}
auto* string_object = static_cast<StringObject*>(this_object);
StringBuilder builder;
for (i32 i = 0; i < count; ++i)
builder.append(string_object->primitive_string()->string());
return js_string(this_object->heap(), builder.to_string());
});
}
StringPrototype::~StringPrototype()
{
}
}

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/Runtime/Object.h>
namespace JS {
class StringPrototype final : public Object {
public:
StringPrototype();
virtual ~StringPrototype() override;
private:
virtual const char* class_name() const override { return "StringPrototype"; }
};
}

View file

@ -0,0 +1,256 @@
/*
* 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/String.h>
#include <LibJS/Heap/Heap.h>
#include <LibJS/Runtime/Object.h>
#include <LibJS/Runtime/PrimitiveString.h>
#include <LibJS/Runtime/StringObject.h>
#include <LibJS/Runtime/Value.h>
namespace JS {
String Value::to_string() const
{
if (is_boolean())
return as_bool() ? "true" : "false";
if (is_null())
return "null";
if (is_undefined())
return "undefined";
if (is_number())
// FIXME: This needs improvement.
return String::number((i32)as_double());
if (is_object())
return as_object()->to_primitive(Object::PreferredType::String).to_string();
if (is_string())
return m_value.as_string->string();
ASSERT_NOT_REACHED();
}
bool Value::to_boolean() const
{
switch (m_type) {
case Type::Boolean:
return m_value.as_bool;
case Type::Number:
return !(m_value.as_double == 0 || m_value.as_double == -0);
case Type::Null:
case Type::Undefined:
return false;
case Type::String:
return !as_string()->string().is_empty();
case Type::Object:
return true;
default:
ASSERT_NOT_REACHED();
}
}
Value Value::to_object(Heap& heap) const
{
if (is_object())
return const_cast<Object*>(as_object());
if (is_string())
return heap.allocate<StringObject>(m_value.as_string);
ASSERT_NOT_REACHED();
}
Value Value::to_number() const
{
switch (m_type) {
case Type::Boolean:
return Value(m_value.as_bool ? 1 : 0);
case Type::Number:
return Value(m_value.as_double);
case Type::Null:
return Value(0);
case Type::String: {
bool ok;
//FIXME: Parse in a better way
auto parsed_int = as_string()->string().to_int(ok);
if (ok)
return Value(parsed_int);
//FIXME: Implement 'NaN'
ASSERT_NOT_REACHED();
break;
}
case Type::Undefined:
//FIXME: Implement 'NaN'
ASSERT_NOT_REACHED();
case Type::Object:
return m_value.as_object->to_primitive(Object::PreferredType::Number).to_number();
}
ASSERT_NOT_REACHED();
}
i32 Value::to_i32() const
{
return static_cast<i32>(to_number().as_double());
}
Value greater_than(Value lhs, Value rhs)
{
return Value(lhs.to_number().as_double() > rhs.to_number().as_double());
}
Value greater_than_equals(Value lhs, Value rhs)
{
return Value(lhs.to_number().as_double() >= rhs.to_number().as_double());
}
Value less_than(Value lhs, Value rhs)
{
return Value(lhs.to_number().as_double() < rhs.to_number().as_double());
}
Value less_than_equals(Value lhs, Value rhs)
{
return Value(lhs.to_number().as_double() <= rhs.to_number().as_double());
}
Value bitwise_and(Value lhs, Value rhs)
{
return Value((i32)lhs.to_number().as_double() & (i32)rhs.to_number().as_double());
}
Value bitwise_or(Value lhs, Value rhs)
{
return Value((i32)lhs.to_number().as_double() | (i32)rhs.to_number().as_double());
}
Value bitwise_xor(Value lhs, Value rhs)
{
return Value((i32)lhs.to_number().as_double() ^ (i32)rhs.to_number().as_double());
}
Value bitwise_not(Value lhs)
{
return Value(~(i32)lhs.to_number().as_double());
}
Value left_shift(Value lhs, Value rhs)
{
return Value((i32)lhs.to_number().as_double() << (i32)rhs.to_number().as_double());
}
Value right_shift(Value lhs, Value rhs)
{
return Value((i32)lhs.to_number().as_double() >> (i32)rhs.to_number().as_double());
}
Value add(Value lhs, Value rhs)
{
if (lhs.is_string() || rhs.is_string())
return js_string((lhs.is_string() ? lhs : rhs).as_string()->heap(), String::format("%s%s", lhs.to_string().characters(), rhs.to_string().characters()));
return Value(lhs.to_number().as_double() + rhs.to_number().as_double());
}
Value sub(Value lhs, Value rhs)
{
return Value(lhs.to_number().as_double() - rhs.to_number().as_double());
}
Value mul(Value lhs, Value rhs)
{
return Value(lhs.to_number().as_double() * rhs.to_number().as_double());
}
Value div(Value lhs, Value rhs)
{
return Value(lhs.to_number().as_double() / rhs.to_number().as_double());
}
Value typed_eq(Value lhs, Value rhs)
{
if (rhs.type() != lhs.type())
return Value(false);
switch (lhs.type()) {
case Value::Type::Undefined:
return Value(true);
case Value::Type::Null:
return Value(true);
case Value::Type::Number:
return Value(lhs.as_double() == rhs.as_double());
case Value::Type::String:
return Value(lhs.as_string()->string() == rhs.as_string()->string());
case Value::Type::Boolean:
return Value(lhs.as_bool() == rhs.as_bool());
case Value::Type::Object:
return Value(lhs.as_object() == rhs.as_object());
}
ASSERT_NOT_REACHED();
}
Value eq(Value lhs, Value rhs)
{
if (lhs.type() == rhs.type())
return typed_eq(lhs, rhs);
if ((lhs.is_undefined() || lhs.is_null()) && (rhs.is_undefined() || rhs.is_null()))
return Value(true);
if (lhs.is_object() && rhs.is_boolean())
return eq(lhs.as_object()->to_primitive(), rhs.to_number());
if (lhs.is_boolean() && rhs.is_object())
return eq(lhs.to_number(), rhs.as_object()->to_primitive());
if (lhs.is_object())
return eq(lhs.as_object()->to_primitive(), rhs);
if (rhs.is_object())
return eq(lhs, rhs.as_object()->to_primitive());
if (lhs.is_number() || rhs.is_number())
return Value(lhs.to_number().as_double() == rhs.to_number().as_double());
if ((lhs.is_string() && rhs.is_boolean()) || (lhs.is_string() && rhs.is_boolean()))
return Value(lhs.to_number().as_double() == rhs.to_number().as_double());
return Value(false);
}
const LogStream& operator<<(const LogStream& stream, const Value& value)
{
return stream << value.to_string();
}
}

View file

@ -0,0 +1,182 @@
/*
* 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 <AK/Assertions.h>
#include <AK/Forward.h>
#include <AK/LogStream.h>
#include <LibJS/Forward.h>
namespace JS {
class Value {
public:
enum class Type {
Undefined,
Null,
Number,
String,
Object,
Boolean,
};
bool is_undefined() const { return m_type == Type::Undefined; }
bool is_null() const { return m_type == Type::Null; }
bool is_number() const { return m_type == Type::Number; }
bool is_string() const { return m_type == Type::String; }
bool is_object() const { return m_type == Type::Object; }
bool is_boolean() const { return m_type == Type::Boolean; }
bool is_cell() const { return is_string() || is_object(); }
explicit Value(bool value)
: m_type(Type::Boolean)
{
m_value.as_bool = value;
}
explicit Value(double value)
: m_type(Type::Number)
{
m_value.as_double = value;
}
explicit Value(i32 value)
: m_type(Type::Number)
{
m_value.as_double = value;
}
Value(Object* object)
: m_type(Type::Object)
{
m_value.as_object = object;
}
Value(PrimitiveString* string)
: m_type(Type::String)
{
m_value.as_string = string;
}
explicit Value(Type type)
: m_type(type)
{
}
Type type() const { return m_type; }
double as_double() const
{
ASSERT(type() == Type::Number);
return m_value.as_double;
}
bool as_bool() const
{
ASSERT(type() == Type::Boolean);
return m_value.as_bool;
}
Object* as_object()
{
ASSERT(type() == Type::Object);
return m_value.as_object;
}
const Object* as_object() const
{
ASSERT(type() == Type::Object);
return m_value.as_object;
}
PrimitiveString* as_string()
{
ASSERT(is_string());
return m_value.as_string;
}
const PrimitiveString* as_string() const
{
ASSERT(is_string());
return m_value.as_string;
}
Cell* as_cell()
{
ASSERT(is_cell());
return m_value.as_cell;
}
String to_string() const;
bool to_boolean() const;
Value to_number() const;
i32 to_i32() const;
Value to_object(Heap&) const;
private:
Type m_type { Type::Undefined };
union {
bool as_bool;
double as_double;
PrimitiveString* as_string;
Object* as_object;
Cell* as_cell;
} m_value;
};
inline Value js_undefined()
{
return Value(Value::Type::Undefined);
}
inline Value js_null()
{
return Value(Value::Type::Null);
}
Value greater_than(Value lhs, Value rhs);
Value greater_than_equals(Value lhs, Value rhs);
Value less_than(Value lhs, Value rhs);
Value less_than_equals(Value lhs, Value rhs);
Value bitwise_and(Value lhs, Value rhs);
Value bitwise_or(Value lhs, Value rhs);
Value bitwise_xor(Value lhs, Value rhs);
Value bitwise_not(Value);
Value left_shift(Value lhs, Value rhs);
Value right_shift(Value lhs, Value rhs);
Value add(Value lhs, Value rhs);
Value sub(Value lhs, Value rhs);
Value mul(Value lhs, Value rhs);
Value div(Value lhs, Value rhs);
Value eq(Value lhs, Value rhs);
Value typed_eq(Value lhs, Value rhs);
const LogStream& operator<<(const LogStream&, const Value&);
}