1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 10:18:11 +00:00

LibWeb: Add basic support for script string argument to setInterval()

Instead of passing a function it is also possible to pass a string,
which is then evaluated as a classic script.
This commit is contained in:
Linus Groh 2021-10-04 00:15:58 +01:00
parent 9f4ac38f08
commit 7ee3432ab6

View file

@ -231,8 +231,11 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::prompt)
return JS::js_string(vm, response); return JS::js_string(vm, response);
} }
// https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-setinterval
JS_DEFINE_NATIVE_FUNCTION(WindowObject::set_interval) JS_DEFINE_NATIVE_FUNCTION(WindowObject::set_interval)
{ {
// FIXME: Ideally this would share more code with setTimeout() using the "timer initialization steps"
// https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timer-initialisation-steps
auto* impl = impl_from(vm, global_object); auto* impl = impl_from(vm, global_object);
if (!impl) if (!impl)
return {}; return {};
@ -240,12 +243,21 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::set_interval)
vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountAtLeastOne, "setInterval"); vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountAtLeastOne, "setInterval");
return {}; return {};
} }
auto* callback_object = vm.argument(0).to_object(global_object); JS::FunctionObject* callback;
if (!callback_object) if (vm.argument(0).is_function()) {
return {}; callback = &vm.argument(0).as_function();
if (!callback_object->is_function()) { } else {
vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotAFunctionNoParam); auto script_source = vm.argument(0).to_string(global_object);
return {}; if (vm.exception())
return {};
// FIXME: This needs more work once we have a environment settings object.
// The spec wants us to use a task for the "run function or script string" part,
// using a NativeFunction for the latter is a workaround so that we can reuse the
// DOM::Timer API unaltered (always expects a JS::FunctionObject).
callback = JS::NativeFunction::create(global_object, "", [impl, script_source = move(script_source)](auto&, auto&) mutable {
auto script = HTML::ClassicScript::create(impl->associated_document().url().to_string(), script_source, impl->associated_document().realm(), AK::URL());
return script->run();
});
} }
i32 interval = 0; i32 interval = 0;
if (vm.argument_count() >= 2) { if (vm.argument_count() >= 2) {
@ -255,8 +267,8 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::set_interval)
if (interval < 0) if (interval < 0)
interval = 0; interval = 0;
} }
// FIXME: Pass ...arguments to the callback function when it's invoked
auto timer_id = impl->set_interval(*static_cast<JS::FunctionObject*>(callback_object), interval); auto timer_id = impl->set_interval(*callback, interval);
return JS::Value(timer_id); return JS::Value(timer_id);
} }
@ -280,7 +292,7 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::set_timeout)
if (vm.exception()) if (vm.exception())
return {}; return {};
// FIXME: This needs more work once we have a environment settings object. // FIXME: This needs more work once we have a environment settings object.
// The script wants us to use a task for the "run function or script string" part, // The spec wants us to use a task for the "run function or script string" part,
// using a NativeFunction for the latter is a workaround so that we can reuse the // using a NativeFunction for the latter is a workaround so that we can reuse the
// DOM::Timer API unaltered (always expects a JS::FunctionObject). // DOM::Timer API unaltered (always expects a JS::FunctionObject).
callback = JS::NativeFunction::create(global_object, "", [impl, script_source = move(script_source)](auto&, auto&) mutable { callback = JS::NativeFunction::create(global_object, "", [impl, script_source = move(script_source)](auto&, auto&) mutable {