1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-28 18:55:09 +00:00

LibWeb+LibJS: Move DOM Window object to dedicated classes

LibWeb now creates a WindowObject which inherits from GlobalObject.
Allocation of the global object is moved out of the Interpreter ctor
to allow for specialized construction.

The existing Window interfaces are moved to WindowObject with their
implementation code in the new Window class.
This commit is contained in:
Andreas Kling 2020-04-01 18:53:28 +02:00
parent cd9379dca9
commit d062d7baa7
12 changed files with 368 additions and 72 deletions

View file

@ -48,8 +48,6 @@ Interpreter::Interpreter()
m_array_prototype = heap().allocate<ArrayPrototype>(); m_array_prototype = heap().allocate<ArrayPrototype>();
m_error_prototype = heap().allocate<ErrorPrototype>(); m_error_prototype = heap().allocate<ErrorPrototype>();
m_date_prototype = heap().allocate<DatePrototype>(); m_date_prototype = heap().allocate<DatePrototype>();
m_global_object = heap().allocate<GlobalObject>();
} }
Interpreter::~Interpreter() Interpreter::~Interpreter()

View file

@ -71,6 +71,13 @@ public:
Interpreter(); Interpreter();
~Interpreter(); ~Interpreter();
template<typename T, typename... Args>
void initialize_global_object(Args&&... args)
{
ASSERT(!m_global_object);
m_global_object = heap().allocate<T>(forward<Args>(args)...);
}
Value run(const Statement&, Vector<Argument> = {}, ScopeType = ScopeType::Block); Value run(const Statement&, Vector<Argument> = {}, ScopeType = ScopeType::Block);
Object& global_object() { return *m_global_object; } Object& global_object() { return *m_global_object; }

View file

@ -4,7 +4,7 @@
namespace JS { namespace JS {
class GlobalObject final : public Object { class GlobalObject : public Object {
public: public:
explicit GlobalObject(); explicit GlobalObject();
virtual ~GlobalObject() override; virtual ~GlobalObject() override;

View file

@ -0,0 +1,144 @@
/*
* 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/FlyString.h>
#include <AK/Function.h>
#include <LibJS/Interpreter.h>
#include <LibJS/Runtime/Error.h>
#include <LibJS/Runtime/Function.h>
#include <LibWeb/Bindings/DocumentWrapper.h>
#include <LibWeb/Bindings/WindowObject.h>
#include <LibWeb/DOM/Document.h>
#include <LibWeb/DOM/Window.h>
namespace Web {
namespace Bindings {
WindowObject::WindowObject(Window& impl)
: m_impl(impl)
{
put_native_property("document", document_getter, document_setter);
put_native_function("alert", alert);
put_native_function("setInterval", set_interval);
put_native_function("requestAnimationFrame", request_animation_frame);
put_native_function("cancelAnimationFrame", cancel_animation_frame);
}
WindowObject::~WindowObject()
{
}
static Window* impl_from(JS::Interpreter& interpreter)
{
auto* this_object = interpreter.this_value().to_object(interpreter.heap());
if (!this_object) {
dbg() << "this_object is null";
ASSERT_NOT_REACHED();
return nullptr;
}
if (StringView("WindowObject") != this_object->class_name()) {
interpreter.throw_exception<JS::Error>("TypeError", "That's not a WindowObject, bro.");
dbg() << "this_object class_name is '" << this_object->class_name() << "'";
return nullptr;
}
return &static_cast<WindowObject*>(this_object)->impl();
}
JS::Value WindowObject::alert(JS::Interpreter& interpreter)
{
dbg() << "alert entry";
auto* impl = impl_from(interpreter);
if (!impl)
return {};
dbg() << "alert2 entry";
auto& arguments = interpreter.call_frame().arguments;
if (arguments.size() < 1)
return {};
impl->alert(arguments[0].to_string());
return {};
}
JS::Value WindowObject::set_interval(JS::Interpreter& interpreter)
{
auto* impl = impl_from(interpreter);
if (!impl)
return {};
auto& arguments = interpreter.call_frame().arguments;
if (arguments.size() < 2)
return {};
auto* callback_object = arguments[0].to_object(interpreter.heap());
if (!callback_object)
return {};
if (!callback_object->is_function())
return interpreter.throw_exception<JS::Error>("TypeError", "Not a function");
impl->set_interval(*static_cast<JS::Function*>(callback_object), arguments[1].to_i32());
return {};
}
JS::Value WindowObject::request_animation_frame(JS::Interpreter& interpreter)
{
auto* impl = impl_from(interpreter);
if (!impl)
return {};
auto& arguments = interpreter.call_frame().arguments;
if (arguments.size() < 1)
return {};
auto* callback_object = arguments[0].to_object(interpreter.heap());
if (!callback_object)
return {};
if (!callback_object->is_function())
return interpreter.throw_exception<JS::Error>("TypeError", "Not a function");
return JS::Value(impl->request_animation_frame(*static_cast<JS::Function*>(callback_object)));
}
JS::Value WindowObject::cancel_animation_frame(JS::Interpreter& interpreter)
{
auto* impl = impl_from(interpreter);
if (!impl)
return {};
auto& arguments = interpreter.call_frame().arguments;
if (arguments.size() < 1)
return {};
impl->cancel_animation_frame(arguments[0].to_i32());
return {};
}
JS::Value WindowObject::document_getter(JS::Interpreter& interpreter)
{
auto* impl = impl_from(interpreter);
if (!impl)
return {};
return wrap(interpreter.heap(), impl->document());
}
void WindowObject::document_setter(JS::Interpreter&, JS::Value)
{
// FIXME: Figure out what we should do here. Just ignore attempts to set window.document for now.
}
}
}

View file

@ -0,0 +1,58 @@
/*
* 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/GlobalObject.h>
#include <LibWeb/Forward.h>
namespace Web {
namespace Bindings {
class WindowObject : public JS::GlobalObject {
public:
explicit WindowObject(Window&);
virtual ~WindowObject() override;
Window& impl() { return *m_impl; }
const Window& impl() const { return *m_impl; }
private:
virtual const char* class_name() const override { return "WindowObject"; }
static JS::Value document_getter(JS::Interpreter&);
static void document_setter(JS::Interpreter&, JS::Value);
static JS::Value alert(JS::Interpreter&);
static JS::Value set_interval(JS::Interpreter&);
static JS::Value request_animation_frame(JS::Interpreter&);
static JS::Value cancel_animation_frame(JS::Interpreter&);
NonnullRefPtr<Window> m_impl;
};
}
}

View file

@ -34,6 +34,7 @@
#include <LibJS/Runtime/Function.h> #include <LibJS/Runtime/Function.h>
#include <LibJS/Runtime/GlobalObject.h> #include <LibJS/Runtime/GlobalObject.h>
#include <LibWeb/Bindings/DocumentWrapper.h> #include <LibWeb/Bindings/DocumentWrapper.h>
#include <LibWeb/Bindings/WindowObject.h>
#include <LibWeb/CSS/SelectorEngine.h> #include <LibWeb/CSS/SelectorEngine.h>
#include <LibWeb/CSS/StyleResolver.h> #include <LibWeb/CSS/StyleResolver.h>
#include <LibWeb/DOM/Document.h> #include <LibWeb/DOM/Document.h>
@ -44,6 +45,7 @@
#include <LibWeb/DOM/HTMLHeadElement.h> #include <LibWeb/DOM/HTMLHeadElement.h>
#include <LibWeb/DOM/HTMLHtmlElement.h> #include <LibWeb/DOM/HTMLHtmlElement.h>
#include <LibWeb/DOM/HTMLTitleElement.h> #include <LibWeb/DOM/HTMLTitleElement.h>
#include <LibWeb/DOM/Window.h>
#include <LibWeb/Dump.h> #include <LibWeb/Dump.h>
#include <LibWeb/Frame.h> #include <LibWeb/Frame.h>
#include <LibWeb/HtmlView.h> #include <LibWeb/HtmlView.h>
@ -57,6 +59,7 @@ namespace Web {
Document::Document() Document::Document()
: ParentNode(*this, NodeType::DOCUMENT_NODE) : ParentNode(*this, NodeType::DOCUMENT_NODE)
, m_style_resolver(make<StyleResolver>(*this)) , m_style_resolver(make<StyleResolver>(*this))
, m_window(Window::create_with_document(*this))
{ {
m_style_update_timer = Core::Timer::construct(); m_style_update_timer = Core::Timer::construct();
m_style_update_timer->set_single_shot(true); m_style_update_timer->set_single_shot(true);
@ -359,65 +362,7 @@ JS::Interpreter& Document::interpreter()
{ {
if (!m_interpreter) { if (!m_interpreter) {
m_interpreter = make<JS::Interpreter>(); m_interpreter = make<JS::Interpreter>();
m_interpreter->initialize_global_object<Bindings::WindowObject>(*m_window);
m_interpreter->global_object().put_native_function("alert", [](JS::Interpreter& interpreter) -> JS::Value {
auto& arguments = interpreter.call_frame().arguments;
if (arguments.size() < 1)
return JS::js_undefined();
GUI::MessageBox::show(arguments[0].to_string(), "Alert", GUI::MessageBox::Type::Information);
return JS::js_undefined();
});
m_interpreter->global_object().put_native_function("setInterval", [this](JS::Interpreter& interpreter) -> JS::Value {
auto& arguments = interpreter.call_frame().arguments;
if (arguments.size() < 2)
return JS::js_undefined();
ASSERT(arguments[0].is_object());
ASSERT(arguments[0].as_object()->is_function());
auto callback = make_handle(const_cast<JS::Object*>(arguments[0].as_object()));
// FIXME: This timer should not be leaked! It should also be removable with clearInterval()!
(void)Core::Timer::construct(
arguments[1].to_i32(), [this, callback] {
auto* function = const_cast<JS::Function*>(static_cast<const JS::Function*>(callback.cell()));
m_interpreter->call(function);
})
.leak_ref();
return JS::js_undefined();
});
m_interpreter->global_object().put_native_function("requestAnimationFrame", [this](JS::Interpreter& interpreter) -> JS::Value {
auto& arguments = interpreter.call_frame().arguments;
if (arguments.size() < 1)
return JS::js_undefined();
ASSERT(arguments[0].is_object());
ASSERT(arguments[0].as_object()->is_function());
auto callback = make_handle(const_cast<JS::Object*>(arguments[0].as_object()));
// FIXME: Don't hand out raw DisplayLink ID's to JavaScript!
i32 link_id = GUI::DisplayLink::register_callback([this, callback](i32 link_id) {
auto* function = const_cast<JS::Function*>(static_cast<const JS::Function*>(callback.cell()));
m_interpreter->call(function);
GUI::DisplayLink::unregister_callback(link_id);
});
return JS::Value(link_id);
});
m_interpreter->global_object().put_native_function("cancelAnimationFrame", [](JS::Interpreter& interpreter) -> JS::Value {
auto& arguments = interpreter.call_frame().arguments;
if (arguments.size() < 1)
return JS::js_undefined();
// FIXME: We should not be passing untrusted numbers to DisplayLink::unregistered_callback()!
GUI::DisplayLink::unregister_callback(arguments[0].to_i32());
return JS::js_undefined();
});
m_interpreter->global_object().put_native_property(
"document",
[this](JS::Interpreter&) {
return wrap(m_interpreter->heap(), *this);
},
nullptr);
} }
return *m_interpreter; return *m_interpreter;
} }

View file

@ -42,15 +42,6 @@
namespace Web { namespace Web {
class Frame;
class HTMLBodyElement;
class HTMLHtmlElement;
class HTMLHeadElement;
class LayoutDocument;
class LayoutNode;
class StyleResolver;
class StyleSheet;
class Document class Document
: public ParentNode : public ParentNode
, public NonElementParentNode<Document> { , public NonElementParentNode<Document> {
@ -140,6 +131,8 @@ private:
WeakPtr<Frame> m_frame; WeakPtr<Frame> m_frame;
URL m_url; URL m_url;
RefPtr<Window> m_window;
RefPtr<LayoutDocument> m_layout_root; RefPtr<LayoutDocument> m_layout_root;
Optional<Color> m_link_color; Optional<Color> m_link_color;

View file

@ -0,0 +1,84 @@
/*
* 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 <LibCore/Timer.h>
#include <LibGUI/DisplayLink.h>
#include <LibGUI/MessageBox.h>
#include <LibJS/Interpreter.h>
#include <LibJS/Runtime/Function.h>
#include <LibWeb/DOM/Window.h>
namespace Web {
NonnullRefPtr<Window> Window::create_with_document(Document& document)
{
return adopt(*new Window(document));
}
Window::Window(Document& document)
: m_document(document)
{
}
Window::~Window()
{
}
void Window::alert(const String& message)
{
GUI::MessageBox::show(message, "Alert", GUI::MessageBox::Type::Information);
}
void Window::set_interval(JS::Function& callback, i32 interval)
{
// FIXME: This leaks the interval timer and makes it unstoppable.
(void)Core::Timer::construct(interval, [handle = make_handle(&callback)] {
auto* function = const_cast<JS::Function*>(static_cast<const JS::Function*>(handle.cell()));
auto& interpreter = function->interpreter();
interpreter.call(function);
}).leak_ref();
}
i32 Window::request_animation_frame(JS::Function& callback)
{
i32 link_id = GUI::DisplayLink::register_callback([handle = make_handle(&callback)](i32 link_id) {
auto* function = const_cast<JS::Function*>(static_cast<const JS::Function*>(handle.cell()));
auto& interpreter = function->interpreter();
interpreter.call(function);
GUI::DisplayLink::unregister_callback(link_id);
});
// FIXME: Don't hand out raw DisplayLink ID's to JavaScript!
return link_id;
}
void Window::cancel_animation_frame(i32 id)
{
// FIXME: We should not be passing untrusted numbers to DisplayLink::unregister_callback()!
GUI::DisplayLink::unregister_callback(id);
}
}

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.
*/
#pragma once
#include <AK/Badge.h>
#include <AK/RefCounted.h>
#include <AK/RefPtr.h>
#include <LibWeb/Bindings/WindowObject.h>
#include <LibWeb/Bindings/Wrappable.h>
namespace Web {
class Window : public RefCounted<Window> {
public:
static NonnullRefPtr<Window> create_with_document(Document&);
~Window();
const Document& document() const { return m_document; }
Document& document() { return m_document; }
void alert(const String&);
i32 request_animation_frame(JS::Function&);
void cancel_animation_frame(i32);
void set_interval(JS::Function&, i32);
private:
explicit Window(Document&);
Document& m_document;
};
}

View file

@ -35,15 +35,21 @@ class Event;
class EventListener; class EventListener;
class EventTarget; class EventTarget;
class Frame; class Frame;
class HTMLBodyElement;
class HTMLCanvasElement; class HTMLCanvasElement;
class HTMLElement; class HTMLElement;
class HTMLHeadElement;
class HTMLHtmlElement;
class HtmlView; class HtmlView;
class LayoutDocument;
class LayoutNode; class LayoutNode;
class MouseEvent; class MouseEvent;
class Node; class Node;
class Selector; class Selector;
class StyleResolver;
class StyleRule; class StyleRule;
class StyleSheet; class StyleSheet;
class Window;
namespace Bindings { namespace Bindings {
@ -56,6 +62,7 @@ class EventTargetWrapper;
class HTMLCanvasElementWrapper; class HTMLCanvasElementWrapper;
class MouseEventWrapper; class MouseEventWrapper;
class NodeWrapper; class NodeWrapper;
class WindowObject;
class Wrappable; class Wrappable;
class Wrapper; class Wrapper;

View file

@ -8,6 +8,7 @@ LIBWEB_OBJS = \
Bindings/HTMLCanvasElementWrapper.o \ Bindings/HTMLCanvasElementWrapper.o \
Bindings/MouseEventWrapper.o \ Bindings/MouseEventWrapper.o \
Bindings/NodeWrapper.o \ Bindings/NodeWrapper.o \
Bindings/WindowObject.o \
Bindings/Wrappable.o \ Bindings/Wrappable.o \
CSS/DefaultStyleSheetSource.o \ CSS/DefaultStyleSheetSource.o \
CSS/PropertyID.o \ CSS/PropertyID.o \
@ -51,6 +52,7 @@ LIBWEB_OBJS = \
DOM/Node.o \ DOM/Node.o \
DOM/ParentNode.o \ DOM/ParentNode.o \
DOM/Text.o \ DOM/Text.o \
DOM/Window.o \
StylePropertiesModel.o \ StylePropertiesModel.o \
DOMTreeModel.o \ DOMTreeModel.o \
Dump.o \ Dump.o \

View file

@ -35,6 +35,7 @@
#include <LibJS/Runtime/Array.h> #include <LibJS/Runtime/Array.h>
#include <LibJS/Runtime/Date.h> #include <LibJS/Runtime/Date.h>
#include <LibJS/Runtime/Function.h> #include <LibJS/Runtime/Function.h>
#include <LibJS/Runtime/GlobalObject.h>
#include <LibJS/Runtime/Object.h> #include <LibJS/Runtime/Object.h>
#include <LibJS/Runtime/PrimitiveString.h> #include <LibJS/Runtime/PrimitiveString.h>
#include <LibJS/Runtime/Value.h> #include <LibJS/Runtime/Value.h>
@ -133,7 +134,7 @@ void print_value(JS::Value value, HashTable<JS::Object*>& seen_objects)
if (value.is_array()) if (value.is_array())
return print_array(static_cast<const JS::Array*>(value.as_object()), seen_objects); return print_array(static_cast<const JS::Array*>(value.as_object()), seen_objects);
if (value.is_object()) { if (value.is_object()) {
auto* object = value.as_object(); auto* object = value.as_object();
if (object->is_function()) if (object->is_function())
@ -198,6 +199,7 @@ int main(int argc, char** argv)
args_parser.parse(argc, argv); args_parser.parse(argc, argv);
JS::Interpreter interpreter; JS::Interpreter interpreter;
interpreter.initialize_global_object<JS::GlobalObject>();
interpreter.heap().set_should_collect_on_every_allocation(gc_on_every_allocation); interpreter.heap().set_should_collect_on_every_allocation(gc_on_every_allocation);
interpreter.global_object().put("global", &interpreter.global_object()); interpreter.global_object().put("global", &interpreter.global_object());