Skip to content

Commit 37cc4ee

Browse files
tcl3awesomekling
authored andcommitted
LibWeb: Skip non-rendered elements before querying view transition name
Previously, starting a view transition on an element inside a `display:none` subtree would crash because querying the view transition name unconditionally accessed `computed_properties()`, which is not calculated for these elements unless explicitly requested. We now skip these non-rendered elements early, before querying the view transition name, to avoid the crash.
1 parent b0f926d commit 37cc4ee

3 files changed

Lines changed: 22 additions & 3 deletions

File tree

Libraries/LibWeb/DOM/Element.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4803,7 +4803,9 @@ Optional<FlyString> Element::document_scoped_view_transition_name()
48034803
// To get the document-scoped view transition name for an Element element:
48044804

48054805
// 1. Let scopedViewTransitionName be the computed value of view-transition-name for element.
4806-
auto scoped_view_transition_name = computed_properties()->view_transition_name();
4806+
auto computed_properties = this->computed_properties();
4807+
VERIFY(computed_properties);
4808+
auto scoped_view_transition_name = computed_properties->view_transition_name();
48074809

48084810
// 2. If scopedViewTransitionName is associated with element’s node document, then return
48094811
// scopedViewTransitionName.

Libraries/LibWeb/ViewTransition/ViewTransition.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,11 +251,16 @@ ErrorOr<void> ViewTransition::capture_the_old_state()
251251
// 2. If element has more than one box fragment, then continue.
252252
// FIXME: Implement this once we have fragments.
253253

254+
// OPTIMIZATION: Continue early if the element is not rendered, so we don't have to ensure the computed
255+
// properties are up to date.
256+
if (element.not_rendered())
257+
return TraversalDecision::Continue;
258+
254259
// 3. Let transitionName be the element’s document-scoped view transition name.
255260
auto transition_name = element.document_scoped_view_transition_name();
256261

257262
// 4. If transitionName is none, or element is not rendered, then continue.
258-
if (!transition_name.has_value() || element.not_rendered())
263+
if (!transition_name.has_value())
259264
return TraversalDecision::Continue;
260265

261266
// 5. If usedTransitionNames contains transitionName, then:
@@ -370,11 +375,16 @@ ErrorOr<void> ViewTransition::capture_the_new_state()
370375
auto result = document.document_element()->for_each_in_inclusive_subtree_of_type<DOM::Element>([&](auto& element) {
371376
// NOTE: Step 1 is handled at the end of this function.
372377

378+
// OPTIMIZATION: Continue early if the element is not rendered, so we don't have to ensure the computed
379+
// properties are up to date.
380+
if (element.not_rendered())
381+
return TraversalDecision::Continue;
382+
373383
// 2. Let transitionName be the element’s document-scoped view transition name.
374384
auto transition_name = element.document_scoped_view_transition_name();
375385

376386
// 3. If transitionName is none, or element is not rendered, then continue.
377-
if (!transition_name.has_value() || element.not_rendered())
387+
if (!transition_name.has_value())
378388
return TraversalDecision::Continue;
379389

380390
// 4. If element has more than one box fragment, then continue.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<!DOCTYPE html>
2+
<div id="host" style="display: none"></div>
3+
<script>
4+
document.body.offsetWidth;
5+
host.appendChild(document.createElement("span"));
6+
document.startViewTransition(() => {});
7+
</script>

0 commit comments

Comments
 (0)