mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
canvas: prevent unwrap on offscreen canvas (#37460)
Remove all unwrap usage on offscreen canvas to prevent panic. Testing: `tests/wpt/tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfercontrol.to.offscreen-crash.html` Fixes: #37415 --------- Signed-off-by: Wu Yu Wei <yuweiwu@pm.me> Signed-off-by: Yu Wei Wu <yuweiwu@YunoMacBook-Air.local> Co-authored-by: Yu Wei Wu <yuweiwu@YunoMacBook-Air.local>
This commit is contained in:
parent
f8f7c6ebd1
commit
e69962e646
8 changed files with 58 additions and 26 deletions
|
@ -35,7 +35,7 @@ pub(crate) trait CanvasContext {
|
|||
|
||||
fn context_id(&self) -> Self::ID;
|
||||
|
||||
fn canvas(&self) -> HTMLCanvasElementOrOffscreenCanvas;
|
||||
fn canvas(&self) -> Option<HTMLCanvasElementOrOffscreenCanvas>;
|
||||
|
||||
fn resize(&self);
|
||||
|
||||
|
@ -49,11 +49,14 @@ pub(crate) trait CanvasContext {
|
|||
}
|
||||
|
||||
fn size(&self) -> Size2D<u32> {
|
||||
self.canvas().size()
|
||||
self.canvas()
|
||||
.map(|canvas| canvas.size())
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
fn mark_as_dirty(&self) {
|
||||
if let HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas) = &self.canvas() {
|
||||
if let Some(HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas)) = &self.canvas()
|
||||
{
|
||||
canvas.upcast::<Node>().dirty(NodeDamage::Other);
|
||||
}
|
||||
}
|
||||
|
@ -61,7 +64,11 @@ pub(crate) trait CanvasContext {
|
|||
fn update_rendering(&self) {}
|
||||
|
||||
fn onscreen(&self) -> bool {
|
||||
match self.canvas() {
|
||||
let Some(canvas) = self.canvas() else {
|
||||
return false;
|
||||
};
|
||||
|
||||
match canvas {
|
||||
HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(ref canvas) => {
|
||||
canvas.upcast::<Node>().is_connected()
|
||||
},
|
||||
|
@ -112,9 +119,9 @@ impl CanvasContext for RenderingContext {
|
|||
|
||||
fn context_id(&self) -> Self::ID {}
|
||||
|
||||
fn canvas(&self) -> HTMLCanvasElementOrOffscreenCanvas {
|
||||
fn canvas(&self) -> Option<HTMLCanvasElementOrOffscreenCanvas> {
|
||||
match self {
|
||||
RenderingContext::Placeholder(context) => (*context.context().unwrap()).canvas(),
|
||||
RenderingContext::Placeholder(offscreen_canvas) => offscreen_canvas.context()?.canvas(),
|
||||
RenderingContext::Context2d(context) => context.canvas(),
|
||||
RenderingContext::WebGL(context) => context.canvas(),
|
||||
RenderingContext::WebGL2(context) => context.canvas(),
|
||||
|
@ -140,8 +147,8 @@ impl CanvasContext for RenderingContext {
|
|||
|
||||
fn get_image_data(&self) -> Option<Snapshot> {
|
||||
match self {
|
||||
RenderingContext::Placeholder(context) => {
|
||||
(*context.context().unwrap()).get_image_data()
|
||||
RenderingContext::Placeholder(offscreen_canvas) => {
|
||||
offscreen_canvas.context()?.get_image_data()
|
||||
},
|
||||
RenderingContext::Context2d(context) => context.get_image_data(),
|
||||
RenderingContext::WebGL(context) => context.get_image_data(),
|
||||
|
@ -153,9 +160,9 @@ impl CanvasContext for RenderingContext {
|
|||
|
||||
fn origin_is_clean(&self) -> bool {
|
||||
match self {
|
||||
RenderingContext::Placeholder(context) => {
|
||||
(*context.context().unwrap()).origin_is_clean()
|
||||
},
|
||||
RenderingContext::Placeholder(offscreen_canvas) => offscreen_canvas
|
||||
.context()
|
||||
.is_none_or(|context| context.origin_is_clean()),
|
||||
RenderingContext::Context2d(context) => context.origin_is_clean(),
|
||||
RenderingContext::WebGL(context) => context.origin_is_clean(),
|
||||
RenderingContext::WebGL2(context) => context.origin_is_clean(),
|
||||
|
@ -166,7 +173,10 @@ impl CanvasContext for RenderingContext {
|
|||
|
||||
fn size(&self) -> Size2D<u32> {
|
||||
match self {
|
||||
RenderingContext::Placeholder(context) => (*context.context().unwrap()).size(),
|
||||
RenderingContext::Placeholder(offscreen_canvas) => offscreen_canvas
|
||||
.context()
|
||||
.map(|context| context.size())
|
||||
.unwrap_or_default(),
|
||||
RenderingContext::Context2d(context) => context.size(),
|
||||
RenderingContext::WebGL(context) => context.size(),
|
||||
RenderingContext::WebGL2(context) => context.size(),
|
||||
|
@ -177,7 +187,11 @@ impl CanvasContext for RenderingContext {
|
|||
|
||||
fn mark_as_dirty(&self) {
|
||||
match self {
|
||||
RenderingContext::Placeholder(context) => (*context.context().unwrap()).mark_as_dirty(),
|
||||
RenderingContext::Placeholder(offscreen_canvas) => {
|
||||
if let Some(context) = offscreen_canvas.context() {
|
||||
context.mark_as_dirty()
|
||||
}
|
||||
},
|
||||
RenderingContext::Context2d(context) => context.mark_as_dirty(),
|
||||
RenderingContext::WebGL(context) => context.mark_as_dirty(),
|
||||
RenderingContext::WebGL2(context) => context.mark_as_dirty(),
|
||||
|
@ -188,8 +202,10 @@ impl CanvasContext for RenderingContext {
|
|||
|
||||
fn update_rendering(&self) {
|
||||
match self {
|
||||
RenderingContext::Placeholder(context) => {
|
||||
(*context.context().unwrap()).update_rendering()
|
||||
RenderingContext::Placeholder(offscreen_canvas) => {
|
||||
if let Some(context) = offscreen_canvas.context() {
|
||||
context.update_rendering()
|
||||
}
|
||||
},
|
||||
RenderingContext::Context2d(context) => context.update_rendering(),
|
||||
RenderingContext::WebGL(context) => context.update_rendering(),
|
||||
|
@ -201,7 +217,9 @@ impl CanvasContext for RenderingContext {
|
|||
|
||||
fn onscreen(&self) -> bool {
|
||||
match self {
|
||||
RenderingContext::Placeholder(context) => (*context.context().unwrap()).onscreen(),
|
||||
RenderingContext::Placeholder(offscreen_canvas) => offscreen_canvas
|
||||
.context()
|
||||
.is_some_and(|context| context.onscreen()),
|
||||
RenderingContext::Context2d(context) => context.onscreen(),
|
||||
RenderingContext::WebGL(context) => context.onscreen(),
|
||||
RenderingContext::WebGL2(context) => context.onscreen(),
|
||||
|
@ -227,7 +245,7 @@ impl CanvasContext for OffscreenRenderingContext {
|
|||
|
||||
fn context_id(&self) -> Self::ID {}
|
||||
|
||||
fn canvas(&self) -> HTMLCanvasElementOrOffscreenCanvas {
|
||||
fn canvas(&self) -> Option<HTMLCanvasElementOrOffscreenCanvas> {
|
||||
match self {
|
||||
OffscreenRenderingContext::Context2d(context) => context.canvas(),
|
||||
}
|
||||
|
|
|
@ -140,8 +140,8 @@ impl CanvasContext for CanvasRenderingContext2D {
|
|||
self.canvas_state.get_canvas_id()
|
||||
}
|
||||
|
||||
fn canvas(&self) -> HTMLCanvasElementOrOffscreenCanvas {
|
||||
self.canvas.clone()
|
||||
fn canvas(&self) -> Option<HTMLCanvasElementOrOffscreenCanvas> {
|
||||
Some(self.canvas.clone())
|
||||
}
|
||||
|
||||
fn update_rendering(&self) {
|
||||
|
|
|
@ -75,7 +75,7 @@ impl CanvasContext for OffscreenCanvasRenderingContext2D {
|
|||
self.context.context_id()
|
||||
}
|
||||
|
||||
fn canvas(&self) -> HTMLCanvasElementOrOffscreenCanvas {
|
||||
fn canvas(&self) -> Option<HTMLCanvasElementOrOffscreenCanvas> {
|
||||
self.context.canvas()
|
||||
}
|
||||
|
||||
|
@ -98,7 +98,7 @@ impl OffscreenCanvasRenderingContext2DMethods<crate::DomTypeHolder>
|
|||
// https://html.spec.whatwg.org/multipage/offscreencontext2d-canvas
|
||||
fn Canvas(&self) -> DomRoot<OffscreenCanvas> {
|
||||
match self.context.canvas() {
|
||||
HTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas) => canvas,
|
||||
Some(HTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas)) => canvas,
|
||||
_ => panic!("Should not be called from onscreen canvas"),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -908,7 +908,7 @@ impl CanvasContext for WebGL2RenderingContext {
|
|||
self.base.context_id()
|
||||
}
|
||||
|
||||
fn canvas(&self) -> HTMLCanvasElementOrOffscreenCanvas {
|
||||
fn canvas(&self) -> Option<HTMLCanvasElementOrOffscreenCanvas> {
|
||||
self.base.canvas().clone()
|
||||
}
|
||||
|
||||
|
|
|
@ -1914,8 +1914,8 @@ impl CanvasContext for WebGLRenderingContext {
|
|||
self.webgl_sender.context_id()
|
||||
}
|
||||
|
||||
fn canvas(&self) -> HTMLCanvasElementOrOffscreenCanvas {
|
||||
self.canvas.clone()
|
||||
fn canvas(&self) -> Option<HTMLCanvasElementOrOffscreenCanvas> {
|
||||
Some(self.canvas.clone())
|
||||
}
|
||||
|
||||
fn resize(&self) {
|
||||
|
|
|
@ -294,8 +294,8 @@ impl CanvasContext for GPUCanvasContext {
|
|||
})
|
||||
}
|
||||
|
||||
fn canvas(&self) -> HTMLCanvasElementOrOffscreenCanvas {
|
||||
self.canvas.clone()
|
||||
fn canvas(&self) -> Option<HTMLCanvasElementOrOffscreenCanvas> {
|
||||
Some(self.canvas.clone())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue