Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Libraries/LibWeb/CSS/Length.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ class WEB_API Length {
m_did_resolve_viewport_relative_length = &did_resolve_viewport_relative_length;
}

[[nodiscard]] bool* viewport_metric_dependency_flag() const
{
return m_did_resolve_viewport_relative_length;
}

void record_viewport_relative_length_resolution() const
{
if (m_did_resolve_viewport_relative_length)
Expand Down
1 change: 1 addition & 0 deletions Libraries/LibWeb/CSS/Rust/src/animation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5238,6 +5238,7 @@ fn animation_length_resolution_context(
root_font_metrics: font_metrics(&animation_context.root_font_metrics),
font_metrics_depend_on_viewport_metrics: animation_context.font_metrics_depend_on_viewport_metrics,
root_font_metrics_depend_on_viewport_metrics: animation_context.root_font_metrics_depend_on_viewport_metrics,
resolved_viewport_relative_length: std::ptr::null_mut(),
})
}

Expand Down
18 changes: 18 additions & 0 deletions Libraries/LibWeb/CSS/Rust/src/style_compute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,19 @@ pub struct FfiLengthResolutionContext {
pub root_font_metrics: FfiFontMetrics,
pub font_metrics_depend_on_viewport_metrics: bool,
pub root_font_metrics_depend_on_viewport_metrics: bool,
/// Optional flag owned by Length::ResolutionContext, set to true whenever a
/// resolution here consumed viewport metrics. Callers that report the
/// dependency through their return value may leave this null.
pub resolved_viewport_relative_length: *mut bool,
}

/// Records a viewport metric dependency on the context's tracking flag, if one is set.
fn record_viewport_relative_length_resolution(context: &FfiLengthResolutionContext) {
if context.resolved_viewport_relative_length.is_null() {
return;
}
// SAFETY: The flag belongs to a Length::ResolutionContext that outlives this call.
unsafe { *context.resolved_viewport_relative_length = true };
}

/// Result of absolutizing a length.
Expand Down Expand Up @@ -251,6 +264,9 @@ fn absolutize_length(value: f64, unit: usize, context: &FfiLengthResolutionConte
} else {
context.font_metrics_depend_on_viewport_metrics
};
if depends_on_viewport {
record_viewport_relative_length_resolution(context);
}
FfiAbsolutizedLength {
handled: true,
changed: true,
Expand All @@ -259,6 +275,7 @@ fn absolutize_length(value: f64, unit: usize, context: &FfiLengthResolutionConte
}
}
LengthUnitKind::ViewportRelative { axis } => {
record_viewport_relative_length_resolution(context);
let basis = match axis {
ViewportAxis::Width => context.viewport_width,
ViewportAxis::Height => context.viewport_height,
Expand Down Expand Up @@ -3840,6 +3857,7 @@ mod tests {
},
font_metrics_depend_on_viewport_metrics: false,
root_font_metrics_depend_on_viewport_metrics: true,
resolved_viewport_relative_length: std::ptr::null_mut(),
}
}

Expand Down
1 change: 1 addition & 0 deletions Libraries/LibWeb/CSS/StyleComputeFFI.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ inline ComputedValuesFFI::FfiLengthResolutionContext to_ffi_length_resolution_co
.root_font_metrics = to_ffi_font_metrics(context.root_font_metrics),
.font_metrics_depend_on_viewport_metrics = context.font_metrics_depend_on_viewport_metrics,
.root_font_metrics_depend_on_viewport_metrics = context.root_font_metrics_depend_on_viewport_metrics,
.resolved_viewport_relative_length = context.viewport_metric_dependency_flag(),
};
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
before resize: plain=200 calc=190 min=200 clamp=200 var=190
after resize: plain=100 calc=90 min=100 clamp=100 var=90
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<!DOCTYPE html>
<meta charset="utf-8">
<script src="../include.js"></script>
<iframe id="frame" width="400" height="400" srcdoc="
<style>
html, body { margin: 0 }
div { background: gray }
#plain { height: 50vh }
#calc { height: calc(50vh - 10px) }
#min { height: min(50vh, 4000px) }
#clamp { height: clamp(10px, 50vh, 4000px) }
#var { --h: calc(50vh - 10px); height: var(--h) }
</style>
<div id=plain></div><div id=calc></div><div id=min></div><div id=clamp></div><div id=var></div>
"></iframe>
<script>
asyncTest(done => {
const frame = document.getElementById("frame");
frame.onload = () => {
const heights = () => {
const document = frame.contentDocument;
return ["plain", "calc", "min", "clamp", "var"]
.map(id => `${id}=${document.getElementById(id).getBoundingClientRect().height}`)
.join(" ");
};

println(`before resize: ${heights()}`);

// Shrinking the iframe resizes the child navigable's viewport. Every viewport-relative
// length must be recomputed, including the ones nested inside math functions.
frame.height = 200;
document.body.offsetWidth;

println(`after resize: ${heights()}`);
done();
};
});
</script>
Loading