LibWeb/HTML: Return Promises from Window scroll methods

A version of this was added in a610639119
and reverted in 70671b4c11. The bugs
there (confusing scroll-to-position and scroll-by-delta, and not having
an execution context in some cases) have been fixed in this version.
This commit is contained in:
Sam Atkins
2026-01-05 19:14:20 +00:00
parent 0a57e1e8ac
commit 8a0ba904b9
Notes: github-actions[bot] 2026-01-08 14:51:21 +00:00
7 changed files with 100 additions and 59 deletions

View File

@@ -2802,13 +2802,13 @@ RefPtr<Gfx::SkiaBackendContext> Navigable::skia_backend_context() const
return m_skia_backend_context;
}
void Navigable::scroll_viewport_by_delta(CSSPixelPoint delta)
GC::Ref<WebIDL::Promise> Navigable::scroll_viewport_by_delta(CSSPixelPoint delta)
{
return perform_a_scroll_of_the_viewport(m_viewport_scroll_offset + delta);
}
// https://drafts.csswg.org/cssom-view/#viewport-perform-a-scroll
void Navigable::perform_a_scroll_of_the_viewport(CSSPixelPoint position)
GC::Ref<WebIDL::Promise> Navigable::perform_a_scroll_of_the_viewport(CSSPixelPoint position)
{
// 1. Let doc be the viewports associated Document.
auto doc = active_document();
@@ -2850,19 +2850,38 @@ void Navigable::perform_a_scroll_of_the_viewport(CSSPixelPoint position)
// 13. Let element be docs root element if there is one, null otherwise.
// 14. Perform a scroll of the viewports scrolling box to its current scroll position + (layout dx, layout dy) with element as the associated element, and behavior as the scroll behavior.
// 14. Perform a scroll of the viewports scrolling box to its current scroll position + (layout dx, layout dy)
// with element as the associated element, and behavior as the scroll behavior. Let scrollPromise1 be the
// Promise returned from this step.
TemporaryExecutionContext temporary_execution_context { doc->realm() };
// AD-HOC: Skip scrolling unscrollable boxes.
if (!doc->paintable_box()->could_be_scrolled_by_wheel_event())
return;
return WebIDL::create_resolved_promise(doc->realm(), JS::js_undefined());
auto scrolling_area = doc->paintable_box()->scrollable_overflow_rect()->to_type<float>();
auto new_viewport_scroll_offset = m_viewport_scroll_offset.to_type<double>() + Gfx::Point(layout_dx, layout_dy);
// NOTE: Clamp to the scrolling area.
new_viewport_scroll_offset.set_x(max(0.0, min(new_viewport_scroll_offset.x(), scrolling_area.width() - viewport_size().width().to_double())));
new_viewport_scroll_offset.set_y(max(0.0, min(new_viewport_scroll_offset.y(), scrolling_area.height() - viewport_size().height().to_double())));
// FIXME: Get a Promise from this.
perform_scroll_of_viewport_scrolling_box(new_viewport_scroll_offset.to_type<CSSPixels>());
// 15. Perform a scroll of vvs scrolling box to its current scroll position + (visual dx, visual dy) with element as the associated element, and behavior as the scroll behavior.
// 15. Perform a scroll of vvs scrolling box to its current scroll position + (visual dx, visual dy) with element
// as the associated element, and behavior as the scroll behavior. Let scrollPromise2 be the Promise returned
// from this step.
// FIXME: Get a Promise from this.
vv->scroll_by({ visual_dx, visual_dy });
doc->set_needs_display(InvalidateDisplayList::No);
// 16. Let scrollPromise be a new Promise.
auto scroll_promise = WebIDL::create_promise(doc->realm());
// 17. Return scrollPromise, and run the remaining steps in parallel.
// 18. Resolve scrollPromise when both scrollPromise1 and scrollPromise2 have settled.
// FIXME: Actually wait for scroll to occur. For now, all our scrolls are instant.
WebIDL::resolve_promise(doc->realm(), scroll_promise);
return scroll_promise;
}
void Navigable::reset_zoom()