diff --git a/Libraries/LibWeb/Bindings/WindowObject.cpp b/Libraries/LibWeb/Bindings/WindowObject.cpp index 537363f6fb..ff6aab0a72 100644 --- a/Libraries/LibWeb/Bindings/WindowObject.cpp +++ b/Libraries/LibWeb/Bindings/WindowObject.cpp @@ -44,6 +44,7 @@ WindowObject::WindowObject(Window& impl) put_native_property("document", document_getter, document_setter); put_native_function("alert", alert); put_native_function("setInterval", set_interval, 1); + put_native_function("setTimeout", set_timeout, 1); put_native_function("requestAnimationFrame", request_animation_frame, 1); put_native_function("cancelAnimationFrame", cancel_animation_frame, 1); @@ -97,6 +98,23 @@ JS::Value WindowObject::set_interval(JS::Interpreter& interpreter) return {}; } +JS::Value WindowObject::set_timeout(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("TypeError", "Not a function"); + impl->set_timeout(*static_cast(callback_object), arguments[1].to_i32()); + return {}; +} + JS::Value WindowObject::request_animation_frame(JS::Interpreter& interpreter) { auto* impl = impl_from(interpreter); diff --git a/Libraries/LibWeb/Bindings/WindowObject.h b/Libraries/LibWeb/Bindings/WindowObject.h index f47c9e5ca1..9f9f4e3256 100644 --- a/Libraries/LibWeb/Bindings/WindowObject.h +++ b/Libraries/LibWeb/Bindings/WindowObject.h @@ -48,6 +48,7 @@ private: static JS::Value alert(JS::Interpreter&); static JS::Value set_interval(JS::Interpreter&); + static JS::Value set_timeout(JS::Interpreter&); static JS::Value request_animation_frame(JS::Interpreter&); static JS::Value cancel_animation_frame(JS::Interpreter&); diff --git a/Libraries/LibWeb/DOM/Window.cpp b/Libraries/LibWeb/DOM/Window.cpp index fb806ce43c..a70aa35b3d 100644 --- a/Libraries/LibWeb/DOM/Window.cpp +++ b/Libraries/LibWeb/DOM/Window.cpp @@ -62,6 +62,17 @@ void Window::set_interval(JS::Function& callback, i32 interval) }).leak_ref(); } +void Window::set_timeout(JS::Function& callback, i32 interval) +{ + // FIXME: This leaks the interval timer and makes it unstoppable. + auto& timer = Core::Timer::construct(interval, [handle = make_handle(&callback)] { + auto* function = const_cast(static_cast(handle.cell())); + auto& interpreter = function->interpreter(); + interpreter.call(function); + }).leak_ref(); + timer.set_single_shot(true); +} + i32 Window::request_animation_frame(JS::Function& callback) { i32 link_id = GUI::DisplayLink::register_callback([handle = make_handle(&callback)](i32 link_id) { diff --git a/Libraries/LibWeb/DOM/Window.h b/Libraries/LibWeb/DOM/Window.h index a3ec299ad6..9390711c84 100644 --- a/Libraries/LibWeb/DOM/Window.h +++ b/Libraries/LibWeb/DOM/Window.h @@ -46,6 +46,7 @@ public: i32 request_animation_frame(JS::Function&); void cancel_animation_frame(i32); void set_interval(JS::Function&, i32); + void set_timeout(JS::Function&, i32); private: explicit Window(Document&);