script: check if the canvas is paintable before measuring text (#38664)

The `Canvas2dMsg::MeasureText` is dropped inside `send_canvas_2d_msg` if
the canvas is not paintable,
leading to a panic on the receiving end. Checking the paint-ability
before sending the message prevents this panic, and if the canvas is not
pain-table, a default text metrics is used.

Testing: Manual testing of the minimal test case in the associated
issue, and crash test added.
Fixes: https://github.com/servo/servo/issues/36845

---------

Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
This commit is contained in:
Gregory Terzian 2025-08-14 20:48:56 +08:00 committed by GitHub
parent cf866d12b4
commit be5e7a982b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 29 additions and 8 deletions

View file

@ -1427,13 +1427,21 @@ impl CanvasState {
self.set_font(canvas, CanvasContextState::DEFAULT_FONT_STYLE.into());
}
let metrics = {
if !self.is_paintable() {
CanvasTextMetrics::default()
} else {
let (sender, receiver) = ipc::channel::<CanvasTextMetrics>().unwrap();
self.send_canvas_2d_msg(Canvas2dMsg::MeasureText(
text.into(),
sender,
self.state.borrow().text_options(),
));
let metrics = receiver.recv().unwrap();
receiver
.recv()
.expect("Failed to receive response from canvas paint thread")
}
};
TextMetrics::new(
global,

View file

@ -8083,7 +8083,14 @@
{}
]
]
}
},
"text-metrics-for-unpaintable-crash.html": [
"5acecfd691acec60a155c1ec1ab571e0a8efb471",
[
null,
{}
]
]
},
"dom": {
"elements": {

View file

@ -0,0 +1,6 @@
<!DOCTYPE html>
<!-- https://github.com/servo/servo/issues/36845 -->
<canvas id="canvas" height="0"></canvas>
<script>
canvas.getContext("2d").measureText("1");
</script>