canvas: Use non rooted variant of HTMLCanvasElementOrOffscreenCanvas type (#38970)

Any RenderingContext/OffscreenRenderingContext type has readonly
"canvas" attribute
and associated native-code DOM context objects have reference to target
DOM canvas objects.
https://html.spec.whatwg.org/multipage/canvas.html#renderingcontext
https://html.spec.whatwg.org/multipage/canvas.html#offscreenrenderingcontext

And currently the reference to DOM canvas object is the rooting pointer
on the stack,
which leads to the circular reference problem.

The SpiderMonkey's (SM) garbage collector will not be able to free the
DOM canvas and context
objects (unreacheble from JS) because of the rooting pointer on stack
(see STACK_ROOTS).

And these objects will be stored until the associated script
runtime/thread will be terminated.

SM -> JS Roots -> DOM Canvas* (on heap) -> DOM Context (on heap)
SM -> Rust Roots -> Dom Canvas* (on stack) <- as "canvas" member field

Let's replace the rooting pointer to the traceble pointer (DomRoot ->
Dom)
in the "canvas" member field of DOM context object, which allows to
broke circular referencing problem.

Testing: No changes in existed tests

Signed-off-by: Andrei Volykhin <volykhin.andrei@huawei.com>
Co-authored-by: Andrei Volykhin <volykhin.andrei@huawei.com>
This commit is contained in:
Andrei Volykhin 2025-09-03 22:24:48 +03:00 committed by GitHub
parent 2c7866eb24
commit 8a62984c2f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 191 additions and 116 deletions

View file

@ -13,19 +13,23 @@ use servo_url::ServoUrl;
use webrender_api::ImageKey; use webrender_api::ImageKey;
use super::canvas_state::CanvasState; use super::canvas_state::CanvasState;
use crate::canvas_context::{CanvasContext, CanvasHelpers, LayoutCanvasRenderingContextHelpers}; use crate::canvas_context::{
CanvasContext, CanvasHelpers, HTMLCanvasElementOrOffscreenCanvas,
LayoutCanvasRenderingContextHelpers,
};
use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::{ use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::{
CanvasDirection, CanvasFillRule, CanvasImageSource, CanvasLineCap, CanvasLineJoin, CanvasDirection, CanvasFillRule, CanvasImageSource, CanvasLineCap, CanvasLineJoin,
CanvasRenderingContext2DMethods, CanvasTextAlign, CanvasTextBaseline, CanvasRenderingContext2DMethods, CanvasTextAlign, CanvasTextBaseline,
}; };
use crate::dom::bindings::codegen::Bindings::DOMMatrixBinding::DOMMatrix2DInit; use crate::dom::bindings::codegen::Bindings::DOMMatrixBinding::DOMMatrix2DInit;
use crate::dom::bindings::codegen::UnionTypes::{ use crate::dom::bindings::codegen::UnionTypes::{
HTMLCanvasElementOrOffscreenCanvas, StringOrCanvasGradientOrCanvasPattern, HTMLCanvasElementOrOffscreenCanvas as RootedHTMLCanvasElementOrOffscreenCanvas,
StringOrCanvasGradientOrCanvasPattern,
}; };
use crate::dom::bindings::error::{ErrorResult, Fallible}; use crate::dom::bindings::error::{ErrorResult, Fallible};
use crate::dom::bindings::num::Finite; use crate::dom::bindings::num::Finite;
use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object}; use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object};
use crate::dom::bindings::root::{DomRoot, LayoutDom}; use crate::dom::bindings::root::{Dom, DomRoot, LayoutDom};
use crate::dom::bindings::str::DOMString; use crate::dom::bindings::str::DOMString;
use crate::dom::canvasgradient::CanvasGradient; use crate::dom::canvasgradient::CanvasGradient;
use crate::dom::canvaspattern::CanvasPattern; use crate::dom::canvaspattern::CanvasPattern;
@ -62,19 +66,18 @@ impl CanvasRenderingContext2D {
}) })
} }
#[cfg_attr(crown, allow(crown::unrooted_must_root))]
pub(crate) fn new( pub(crate) fn new(
global: &GlobalScope, global: &GlobalScope,
canvas: &HTMLCanvasElement, canvas: &HTMLCanvasElement,
size: Size2D<u32>, size: Size2D<u32>,
can_gc: CanGc, can_gc: CanGc,
) -> Option<DomRoot<CanvasRenderingContext2D>> { ) -> Option<DomRoot<CanvasRenderingContext2D>> {
let boxed = Box::new(CanvasRenderingContext2D::new_inherited( CanvasRenderingContext2D::new_inherited(
global, global,
HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(DomRoot::from_ref(canvas)), HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(Dom::from_ref(canvas)),
size, size,
)?); )
Some(reflect_dom_object(boxed, global, can_gc)) .map(|context| reflect_dom_object(Box::new(context), global, can_gc))
} }
// https://html.spec.whatwg.org/multipage/#reset-the-rendering-context-to-its-default-state // https://html.spec.whatwg.org/multipage/#reset-the-rendering-context-to-its-default-state
@ -119,8 +122,8 @@ impl CanvasContext for CanvasRenderingContext2D {
self.canvas_state.get_canvas_id() self.canvas_state.get_canvas_id()
} }
fn canvas(&self) -> Option<HTMLCanvasElementOrOffscreenCanvas> { fn canvas(&self) -> Option<RootedHTMLCanvasElementOrOffscreenCanvas> {
Some(self.canvas.clone()) Some(RootedHTMLCanvasElementOrOffscreenCanvas::from(&self.canvas))
} }
fn update_rendering(&self, canvas_epoch: Epoch) -> bool { fn update_rendering(&self, canvas_epoch: Epoch) -> bool {
@ -178,7 +181,7 @@ impl CanvasRenderingContext2DMethods<crate::DomTypeHolder> for CanvasRenderingCo
// https://html.spec.whatwg.org/multipage/#dom-context-2d-canvas // https://html.spec.whatwg.org/multipage/#dom-context-2d-canvas
fn Canvas(&self) -> DomRoot<HTMLCanvasElement> { fn Canvas(&self) -> DomRoot<HTMLCanvasElement> {
match &self.canvas { match &self.canvas {
HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas) => canvas.clone(), HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas) => canvas.as_rooted(),
_ => panic!("Should not be called from offscreen canvas"), _ => panic!("Should not be called from offscreen canvas"),
} }
} }

View file

@ -2,27 +2,30 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use crate::dom::bindings::codegen::GenericBindings::CanvasRenderingContext2DBinding::CanvasRenderingContext2D_Binding::CanvasRenderingContext2DMethods;
use crate::canvas_context::CanvasContext;
use crate::dom::bindings::codegen::UnionTypes::HTMLCanvasElementOrOffscreenCanvas;
use canvas_traits::canvas::Canvas2dMsg; use canvas_traits::canvas::Canvas2dMsg;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use euclid::default::Size2D;
use pixels::Snapshot; use pixels::Snapshot;
use crate::canvas_context::{CanvasContext, HTMLCanvasElementOrOffscreenCanvas};
use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::{ use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::{
CanvasDirection, CanvasFillRule, CanvasImageSource, CanvasLineCap, CanvasLineJoin, CanvasDirection, CanvasFillRule, CanvasImageSource, CanvasLineCap, CanvasLineJoin,
CanvasTextAlign, CanvasTextBaseline, CanvasRenderingContext2DMethods, CanvasTextAlign, CanvasTextBaseline,
}; };
use crate::dom::bindings::codegen::Bindings::DOMMatrixBinding::DOMMatrix2DInit; use crate::dom::bindings::codegen::Bindings::DOMMatrixBinding::DOMMatrix2DInit;
use crate::dom::bindings::codegen::Bindings::OffscreenCanvasRenderingContext2DBinding::OffscreenCanvasRenderingContext2DMethods; use crate::dom::bindings::codegen::Bindings::OffscreenCanvasRenderingContext2DBinding::OffscreenCanvasRenderingContext2DMethods;
use crate::dom::bindings::codegen::UnionTypes::StringOrCanvasGradientOrCanvasPattern; use crate::dom::bindings::codegen::UnionTypes::{
HTMLCanvasElementOrOffscreenCanvas as RootedHTMLCanvasElementOrOffscreenCanvas,
StringOrCanvasGradientOrCanvasPattern,
};
use crate::dom::bindings::error::{ErrorResult, Fallible}; use crate::dom::bindings::error::{ErrorResult, Fallible};
use crate::dom::bindings::num::Finite; use crate::dom::bindings::num::Finite;
use crate::dom::bindings::reflector::reflect_dom_object; use crate::dom::bindings::reflector::reflect_dom_object;
use crate::dom::bindings::root::DomRoot; use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::bindings::str::DOMString; use crate::dom::bindings::str::DOMString;
use crate::dom::canvasgradient::CanvasGradient; use crate::dom::canvasgradient::CanvasGradient;
use crate::dom::canvaspattern::CanvasPattern; use crate::dom::canvaspattern::CanvasPattern;
use crate::dom::canvasrenderingcontext2d::CanvasRenderingContext2D;
use crate::dom::dommatrix::DOMMatrix; use crate::dom::dommatrix::DOMMatrix;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::imagedata::ImageData; use crate::dom::imagedata::ImageData;
@ -31,8 +34,6 @@ use crate::dom::path2d::Path2D;
use crate::dom::textmetrics::TextMetrics; use crate::dom::textmetrics::TextMetrics;
use crate::script_runtime::CanGc; use crate::script_runtime::CanGc;
use super::canvasrenderingcontext2d::CanvasRenderingContext2D;
#[dom_struct] #[dom_struct]
pub(crate) struct OffscreenCanvasRenderingContext2D { pub(crate) struct OffscreenCanvasRenderingContext2D {
context: CanvasRenderingContext2D, context: CanvasRenderingContext2D,
@ -42,28 +43,26 @@ impl OffscreenCanvasRenderingContext2D {
#[cfg_attr(crown, allow(crown::unrooted_must_root))] #[cfg_attr(crown, allow(crown::unrooted_must_root))]
fn new_inherited( fn new_inherited(
global: &GlobalScope, global: &GlobalScope,
canvas: &OffscreenCanvas, canvas: HTMLCanvasElementOrOffscreenCanvas,
size: Size2D<u32>,
) -> Option<OffscreenCanvasRenderingContext2D> { ) -> Option<OffscreenCanvasRenderingContext2D> {
let size = canvas.get_size().cast();
Some(OffscreenCanvasRenderingContext2D { Some(OffscreenCanvasRenderingContext2D {
context: CanvasRenderingContext2D::new_inherited( context: CanvasRenderingContext2D::new_inherited(global, canvas, size)?,
global,
HTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(DomRoot::from_ref(canvas)),
size,
)?,
}) })
} }
#[cfg_attr(crown, allow(crown::unrooted_must_root))]
pub(crate) fn new( pub(crate) fn new(
global: &GlobalScope, global: &GlobalScope,
canvas: &OffscreenCanvas, canvas: &OffscreenCanvas,
size: Size2D<u32>,
can_gc: CanGc, can_gc: CanGc,
) -> Option<DomRoot<OffscreenCanvasRenderingContext2D>> { ) -> Option<DomRoot<OffscreenCanvasRenderingContext2D>> {
let boxed = Box::new(OffscreenCanvasRenderingContext2D::new_inherited( OffscreenCanvasRenderingContext2D::new_inherited(
global, canvas, global,
)?); HTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(Dom::from_ref(canvas)),
Some(reflect_dom_object(boxed, global, can_gc)) size,
)
.map(|context| reflect_dom_object(Box::new(context), global, can_gc))
} }
pub(crate) fn send_canvas_2d_msg(&self, msg: Canvas2dMsg) { pub(crate) fn send_canvas_2d_msg(&self, msg: Canvas2dMsg) {
@ -78,7 +77,7 @@ impl CanvasContext for OffscreenCanvasRenderingContext2D {
self.context.context_id() self.context.context_id()
} }
fn canvas(&self) -> Option<HTMLCanvasElementOrOffscreenCanvas> { fn canvas(&self) -> Option<RootedHTMLCanvasElementOrOffscreenCanvas> {
self.context.canvas() self.context.canvas()
} }
@ -109,7 +108,7 @@ impl OffscreenCanvasRenderingContext2DMethods<crate::DomTypeHolder>
// https://html.spec.whatwg.org/multipage/offscreencontext2d-canvas // https://html.spec.whatwg.org/multipage/offscreencontext2d-canvas
fn Canvas(&self) -> DomRoot<OffscreenCanvas> { fn Canvas(&self) -> DomRoot<OffscreenCanvas> {
match self.context.canvas() { match self.context.canvas() {
Some(HTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas)) => canvas, Some(RootedHTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas)) => canvas,
_ => panic!("Should not be called from onscreen canvas"), _ => panic!("Should not be called from onscreen canvas"),
} }
} }

View file

@ -6,19 +6,17 @@
use base::Epoch; use base::Epoch;
use euclid::default::Size2D; use euclid::default::Size2D;
use layout_api::HTMLCanvasData;
use pixels::Snapshot; use pixels::Snapshot;
use script_bindings::root::{Dom, DomRoot}; use script_bindings::root::{Dom, DomRoot};
use webrender_api::ImageKey; use webrender_api::ImageKey;
use crate::dom::bindings::codegen::UnionTypes::HTMLCanvasElementOrOffscreenCanvas; use crate::dom::bindings::codegen::UnionTypes::HTMLCanvasElementOrOffscreenCanvas as RootedHTMLCanvasElementOrOffscreenCanvas;
use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::inheritance::Castable;
use crate::dom::html::htmlcanvaselement::HTMLCanvasElement;
use crate::dom::node::{Node, NodeDamage}; use crate::dom::node::{Node, NodeDamage};
#[cfg(feature = "webgpu")] #[cfg(feature = "webgpu")]
use crate::dom::types::GPUCanvasContext; use crate::dom::types::GPUCanvasContext;
use crate::dom::types::{ use crate::dom::types::{
CanvasRenderingContext2D, ImageBitmapRenderingContext, OffscreenCanvas, CanvasRenderingContext2D, HTMLCanvasElement, ImageBitmapRenderingContext, OffscreenCanvas,
OffscreenCanvasRenderingContext2D, WebGL2RenderingContext, WebGLRenderingContext, OffscreenCanvasRenderingContext2D, WebGL2RenderingContext, WebGLRenderingContext,
}; };
@ -27,8 +25,45 @@ pub(crate) trait LayoutCanvasRenderingContextHelpers {
fn canvas_data_source(self) -> Option<ImageKey>; fn canvas_data_source(self) -> Option<ImageKey>;
} }
pub(crate) trait LayoutHTMLCanvasElementHelpers { /// Non rooted variant of [`crate::dom::bindings::codegen::UnionTypes::HTMLCanvasElementOrOffscreenCanvas`]
fn data(self) -> HTMLCanvasData; #[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
#[derive(Clone, JSTraceable, MallocSizeOf)]
pub(crate) enum HTMLCanvasElementOrOffscreenCanvas {
HTMLCanvasElement(Dom<HTMLCanvasElement>),
OffscreenCanvas(Dom<OffscreenCanvas>),
}
impl From<&RootedHTMLCanvasElementOrOffscreenCanvas> for HTMLCanvasElementOrOffscreenCanvas {
/// Returns a traced version suitable for use as member of other DOM objects.
#[cfg_attr(crown, allow(crown::unrooted_must_root))]
fn from(
value: &RootedHTMLCanvasElementOrOffscreenCanvas,
) -> HTMLCanvasElementOrOffscreenCanvas {
match value {
RootedHTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas) => {
HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas.as_traced())
},
RootedHTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas) => {
HTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas.as_traced())
},
}
}
}
impl From<&HTMLCanvasElementOrOffscreenCanvas> for RootedHTMLCanvasElementOrOffscreenCanvas {
/// Returns a rooted version suitable for use on the stack.
fn from(
value: &HTMLCanvasElementOrOffscreenCanvas,
) -> RootedHTMLCanvasElementOrOffscreenCanvas {
match value {
HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas) => {
RootedHTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas.as_rooted())
},
HTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas) => {
RootedHTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas.as_rooted())
},
}
}
} }
pub(crate) trait CanvasContext { pub(crate) trait CanvasContext {
@ -36,7 +71,7 @@ pub(crate) trait CanvasContext {
fn context_id(&self) -> Self::ID; fn context_id(&self) -> Self::ID;
fn canvas(&self) -> Option<HTMLCanvasElementOrOffscreenCanvas>; fn canvas(&self) -> Option<RootedHTMLCanvasElementOrOffscreenCanvas>;
fn resize(&self); fn resize(&self);
@ -61,7 +96,8 @@ pub(crate) trait CanvasContext {
} }
fn mark_as_dirty(&self) { fn mark_as_dirty(&self) {
if let Some(HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas)) = &self.canvas() if let Some(RootedHTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas)) =
self.canvas()
{ {
canvas.upcast::<Node>().dirty(NodeDamage::Other); canvas.upcast::<Node>().dirty(NodeDamage::Other);
} }
@ -82,12 +118,12 @@ pub(crate) trait CanvasContext {
}; };
match canvas { match canvas {
HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(ref canvas) => { RootedHTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas) => {
canvas.upcast::<Node>().is_connected() canvas.upcast::<Node>().is_connected()
}, },
// FIXME(34628): Offscreen canvases should be considered offscreen if a placeholder is set. // FIXME(34628): Offscreen canvases should be considered offscreen if a placeholder is set.
// <https://www.w3.org/TR/webgpu/#abstract-opdef-updating-the-rendering-of-a-webgpu-canvas> // <https://www.w3.org/TR/webgpu/#abstract-opdef-updating-the-rendering-of-a-webgpu-canvas>
HTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(_) => false, RootedHTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(_) => false,
} }
} }
} }
@ -109,12 +145,36 @@ impl CanvasHelpers for HTMLCanvasElementOrOffscreenCanvas {
fn canvas(&self) -> Option<DomRoot<HTMLCanvasElement>> { fn canvas(&self) -> Option<DomRoot<HTMLCanvasElement>> {
match self { match self {
HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas) => Some(canvas.clone()), HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas) => {
Some(canvas.as_rooted())
},
HTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas) => canvas.placeholder(), HTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas) => canvas.placeholder(),
} }
} }
} }
impl CanvasHelpers for RootedHTMLCanvasElementOrOffscreenCanvas {
fn size(&self) -> Size2D<u32> {
match self {
RootedHTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas) => {
canvas.get_size().cast()
},
RootedHTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas) => canvas.get_size(),
}
}
fn canvas(&self) -> Option<DomRoot<HTMLCanvasElement>> {
match self {
RootedHTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas) => {
Some(canvas.clone())
},
RootedHTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas) => {
canvas.placeholder()
},
}
}
}
/// Non rooted variant of [`crate::dom::bindings::codegen::Bindings::HTMLCanvasElementBinding::RenderingContext`] /// Non rooted variant of [`crate::dom::bindings::codegen::Bindings::HTMLCanvasElementBinding::RenderingContext`]
#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)] #[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
#[derive(Clone, JSTraceable, MallocSizeOf)] #[derive(Clone, JSTraceable, MallocSizeOf)]
@ -133,7 +193,7 @@ impl CanvasContext for RenderingContext {
fn context_id(&self) -> Self::ID {} fn context_id(&self) -> Self::ID {}
fn canvas(&self) -> Option<HTMLCanvasElementOrOffscreenCanvas> { fn canvas(&self) -> Option<RootedHTMLCanvasElementOrOffscreenCanvas> {
match self { match self {
RenderingContext::Placeholder(offscreen_canvas) => offscreen_canvas.context()?.canvas(), RenderingContext::Placeholder(offscreen_canvas) => offscreen_canvas.context()?.canvas(),
RenderingContext::Context2d(context) => context.canvas(), RenderingContext::Context2d(context) => context.canvas(),
@ -297,7 +357,7 @@ impl CanvasContext for OffscreenRenderingContext {
fn context_id(&self) -> Self::ID {} fn context_id(&self) -> Self::ID {}
fn canvas(&self) -> Option<HTMLCanvasElementOrOffscreenCanvas> { fn canvas(&self) -> Option<RootedHTMLCanvasElementOrOffscreenCanvas> {
match self { match self {
OffscreenRenderingContext::Context2d(context) => context.canvas(), OffscreenRenderingContext::Context2d(context) => context.canvas(),
OffscreenRenderingContext::BitmapRenderer(context) => context.canvas(), OffscreenRenderingContext::BitmapRenderer(context) => context.canvas(),

View file

@ -9,11 +9,14 @@ use euclid::default::Size2D;
use pixels::Snapshot; use pixels::Snapshot;
use webrender_api::ImageKey; use webrender_api::ImageKey;
use crate::canvas_context::{CanvasContext, CanvasHelpers, LayoutCanvasRenderingContextHelpers}; use crate::canvas_context::{
CanvasContext, CanvasHelpers, HTMLCanvasElementOrOffscreenCanvas,
LayoutCanvasRenderingContextHelpers,
};
use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::ImageBitmapBinding::ImageBitmapMethods; use crate::dom::bindings::codegen::Bindings::ImageBitmapBinding::ImageBitmapMethods;
use crate::dom::bindings::codegen::Bindings::ImageBitmapRenderingContextBinding::ImageBitmapRenderingContextMethods; use crate::dom::bindings::codegen::Bindings::ImageBitmapRenderingContextBinding::ImageBitmapRenderingContextMethods;
use crate::dom::bindings::codegen::UnionTypes::HTMLCanvasElementOrOffscreenCanvas; use crate::dom::bindings::codegen::UnionTypes::HTMLCanvasElementOrOffscreenCanvas as RootedHTMLCanvasElementOrOffscreenCanvas;
use crate::dom::bindings::error::{Error, Fallible}; use crate::dom::bindings::error::{Error, Fallible};
use crate::dom::bindings::reflector::{Reflector, reflect_dom_object}; use crate::dom::bindings::reflector::{Reflector, reflect_dom_object};
use crate::dom::bindings::root::{DomRoot, LayoutDom}; use crate::dom::bindings::root::{DomRoot, LayoutDom};
@ -37,6 +40,7 @@ pub(crate) struct ImageBitmapRenderingContext {
impl ImageBitmapRenderingContext { impl ImageBitmapRenderingContext {
/// <https://html.spec.whatwg.org/multipage/#imagebitmaprenderingcontext-creation-algorithm> /// <https://html.spec.whatwg.org/multipage/#imagebitmaprenderingcontext-creation-algorithm>
#[cfg_attr(crown, allow(crown::unrooted_must_root))]
fn new_inherited(canvas: HTMLCanvasElementOrOffscreenCanvas) -> ImageBitmapRenderingContext { fn new_inherited(canvas: HTMLCanvasElementOrOffscreenCanvas) -> ImageBitmapRenderingContext {
ImageBitmapRenderingContext { ImageBitmapRenderingContext {
reflector_: Reflector::new(), reflector_: Reflector::new(),
@ -48,11 +52,13 @@ impl ImageBitmapRenderingContext {
pub(crate) fn new( pub(crate) fn new(
global: &GlobalScope, global: &GlobalScope,
canvas: HTMLCanvasElementOrOffscreenCanvas, canvas: &RootedHTMLCanvasElementOrOffscreenCanvas,
can_gc: CanGc, can_gc: CanGc,
) -> DomRoot<ImageBitmapRenderingContext> { ) -> DomRoot<ImageBitmapRenderingContext> {
reflect_dom_object( reflect_dom_object(
Box::new(ImageBitmapRenderingContext::new_inherited(canvas)), Box::new(ImageBitmapRenderingContext::new_inherited(
HTMLCanvasElementOrOffscreenCanvas::from(canvas),
)),
global, global,
can_gc, can_gc,
) )
@ -99,8 +105,8 @@ impl CanvasContext for ImageBitmapRenderingContext {
fn context_id(&self) -> Self::ID {} fn context_id(&self) -> Self::ID {}
fn canvas(&self) -> Option<HTMLCanvasElementOrOffscreenCanvas> { fn canvas(&self) -> Option<RootedHTMLCanvasElementOrOffscreenCanvas> {
Some(self.canvas.clone()) Some(RootedHTMLCanvasElementOrOffscreenCanvas::from(&self.canvas))
} }
/// <https://html.spec.whatwg.org/multipage/#the-canvas-element:concept-canvas-bitmaprenderer> /// <https://html.spec.whatwg.org/multipage/#the-canvas-element:concept-canvas-bitmaprenderer>
@ -158,8 +164,8 @@ impl CanvasContext for ImageBitmapRenderingContext {
impl ImageBitmapRenderingContextMethods<crate::DomTypeHolder> for ImageBitmapRenderingContext { impl ImageBitmapRenderingContextMethods<crate::DomTypeHolder> for ImageBitmapRenderingContext {
/// <https://html.spec.whatwg.org/multipage/#dom-imagebitmaprenderingcontext-canvas> /// <https://html.spec.whatwg.org/multipage/#dom-imagebitmaprenderingcontext-canvas>
fn Canvas(&self) -> HTMLCanvasElementOrOffscreenCanvas { fn Canvas(&self) -> RootedHTMLCanvasElementOrOffscreenCanvas {
self.canvas.clone() RootedHTMLCanvasElementOrOffscreenCanvas::from(&self.canvas)
} }
/// <https://html.spec.whatwg.org/multipage/#dom-imagebitmaprenderingcontext-transferfromimagebitmap> /// <https://html.spec.whatwg.org/multipage/#dom-imagebitmaprenderingcontext-transferfromimagebitmap>

View file

@ -20,7 +20,7 @@ use crate::dom::bindings::codegen::Bindings::OffscreenCanvasBinding::{
ImageEncodeOptions, OffscreenCanvasMethods, ImageEncodeOptions, OffscreenCanvasMethods,
OffscreenRenderingContext as RootedOffscreenRenderingContext, OffscreenRenderingContext as RootedOffscreenRenderingContext,
}; };
use crate::dom::bindings::codegen::UnionTypes::HTMLCanvasElementOrOffscreenCanvas; use crate::dom::bindings::codegen::UnionTypes::HTMLCanvasElementOrOffscreenCanvas as RootedHTMLCanvasElementOrOffscreenCanvas;
use crate::dom::bindings::error::{Error, Fallible}; use crate::dom::bindings::error::{Error, Fallible};
use crate::dom::bindings::refcounted::{Trusted, TrustedPromise}; use crate::dom::bindings::refcounted::{Trusted, TrustedPromise};
use crate::dom::bindings::reflector::{DomGlobal, reflect_dom_object_with_proto}; use crate::dom::bindings::reflector::{DomGlobal, reflect_dom_object_with_proto};
@ -135,7 +135,8 @@ impl OffscreenCanvas {
_ => None, _ => None,
}; };
} }
let context = OffscreenCanvasRenderingContext2D::new(&self.global(), self, can_gc)?; let context =
OffscreenCanvasRenderingContext2D::new(&self.global(), self, self.get_size(), can_gc)?;
*self.context.borrow_mut() = Some(OffscreenRenderingContext::Context2d(Dom::from_ref( *self.context.borrow_mut() = Some(OffscreenRenderingContext::Context2d(Dom::from_ref(
&*context, &*context,
))); )));
@ -159,11 +160,10 @@ impl OffscreenCanvas {
// Step 1. Let context be the result of running the // Step 1. Let context be the result of running the
// ImageBitmapRenderingContext creation algorithm given this and // ImageBitmapRenderingContext creation algorithm given this and
// options. // options.
let context = ImageBitmapRenderingContext::new( let canvas =
&self.global(), RootedHTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(DomRoot::from_ref(self));
HTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(DomRoot::from_ref(self)),
can_gc, let context = ImageBitmapRenderingContext::new(&self.global(), &canvas, can_gc);
);
// Step 2. Set this's context mode to bitmaprenderer. // Step 2. Set this's context mode to bitmaprenderer.
*self.context.borrow_mut() = Some(OffscreenRenderingContext::BitmapRenderer( *self.context.borrow_mut() = Some(OffscreenRenderingContext::BitmapRenderer(

View file

@ -2,15 +2,14 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use base::Epoch;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use webrender_api::ImageKey; use webrender_api::ImageKey;
use crate::canvas_context::LayoutCanvasRenderingContextHelpers;
use crate::dom::bindings::codegen::Bindings::GPUCanvasContextBinding::GPUCanvasContextMethods; use crate::dom::bindings::codegen::Bindings::GPUCanvasContextBinding::GPUCanvasContextMethods;
use crate::dom::bindings::codegen::UnionTypes; use crate::dom::bindings::codegen::UnionTypes::HTMLCanvasElementOrOffscreenCanvas as RootedHTMLCanvasElementOrOffscreenCanvas;
use crate::dom::bindings::reflector::Reflector; use crate::dom::bindings::reflector::Reflector;
use crate::dom::bindings::root::LayoutDom; use crate::dom::bindings::root::LayoutDom;
use crate::dom::html::htmlcanvaselement::LayoutCanvasRenderingContextHelpers;
#[dom_struct] #[dom_struct]
pub(crate) struct GPUCanvasContext { pub(crate) struct GPUCanvasContext {
@ -26,7 +25,7 @@ impl GPUCanvasContext {
impl GPUCanvasContextMethods<crate::DomTypeHolder> for GPUCanvasContext { impl GPUCanvasContextMethods<crate::DomTypeHolder> for GPUCanvasContext {
/// <https://gpuweb.github.io/gpuweb/#dom-gpucanvascontext-canvas> /// <https://gpuweb.github.io/gpuweb/#dom-gpucanvascontext-canvas>
fn Canvas(&self) -> UnionTypes::HTMLCanvasElementOrOffscreenCanvas { fn Canvas(&self) -> RootedHTMLCanvasElementOrOffscreenCanvas {
unimplemented!() unimplemented!()
} }
} }

View file

@ -24,7 +24,7 @@ use servo_media::streams::MediaStreamType;
use servo_media::streams::registry::MediaStreamId; use servo_media::streams::registry::MediaStreamId;
use style::attr::AttrValue; use style::attr::AttrValue;
pub(crate) use crate::canvas_context::*; use crate::canvas_context::{CanvasContext, LayoutCanvasRenderingContextHelpers, RenderingContext};
use crate::conversions::Convert; use crate::conversions::Convert;
use crate::dom::attr::Attr; use crate::dom::attr::Attr;
use crate::dom::bindings::callback::ExceptionHandling; use crate::dom::bindings::callback::ExceptionHandling;
@ -34,7 +34,7 @@ use crate::dom::bindings::codegen::Bindings::HTMLCanvasElementBinding::{
}; };
use crate::dom::bindings::codegen::Bindings::MediaStreamBinding::MediaStreamMethods; use crate::dom::bindings::codegen::Bindings::MediaStreamBinding::MediaStreamMethods;
use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLContextAttributes; use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLContextAttributes;
use crate::dom::bindings::codegen::UnionTypes::HTMLCanvasElementOrOffscreenCanvas; use crate::dom::bindings::codegen::UnionTypes::HTMLCanvasElementOrOffscreenCanvas as RootedHTMLCanvasElementOrOffscreenCanvas;
use crate::dom::bindings::conversions::ConversionResult; use crate::dom::bindings::conversions::ConversionResult;
use crate::dom::bindings::error::{Error, Fallible}; use crate::dom::bindings::error::{Error, Fallible};
use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::inheritance::Castable;
@ -156,6 +156,10 @@ impl HTMLCanvasElement {
} }
} }
pub(crate) trait LayoutHTMLCanvasElementHelpers {
fn data(self) -> HTMLCanvasData;
}
impl LayoutHTMLCanvasElementHelpers for LayoutDom<'_, HTMLCanvasElement> { impl LayoutHTMLCanvasElementHelpers for LayoutDom<'_, HTMLCanvasElement> {
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn data(self) -> HTMLCanvasData { fn data(self) -> HTMLCanvasData {
@ -227,11 +231,10 @@ impl HTMLCanvasElement {
// Step 1. Let context be the result of running the // Step 1. Let context be the result of running the
// ImageBitmapRenderingContext creation algorithm given this and // ImageBitmapRenderingContext creation algorithm given this and
// options. // options.
let context = ImageBitmapRenderingContext::new( let canvas =
&self.owner_global(), RootedHTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(DomRoot::from_ref(self));
HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(DomRoot::from_ref(self)),
can_gc, let context = ImageBitmapRenderingContext::new(&self.owner_global(), &canvas, can_gc);
);
// Step 2. Set this's context mode to bitmaprenderer. // Step 2. Set this's context mode to bitmaprenderer.
*self.context_mode.borrow_mut() = *self.context_mode.borrow_mut() =
@ -254,9 +257,10 @@ impl HTMLCanvasElement {
}; };
} }
let window = self.owner_window(); let window = self.owner_window();
let canvas =
RootedHTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(DomRoot::from_ref(self));
let size = self.get_size(); let size = self.get_size();
let attrs = Self::get_gl_attributes(cx, options)?; let attrs = Self::get_gl_attributes(cx, options)?;
let canvas = HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(DomRoot::from_ref(self));
let context = WebGLRenderingContext::new( let context = WebGLRenderingContext::new(
&window, &window,
&canvas, &canvas,
@ -286,9 +290,10 @@ impl HTMLCanvasElement {
}; };
} }
let window = self.owner_window(); let window = self.owner_window();
let canvas =
RootedHTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(DomRoot::from_ref(self));
let size = self.get_size(); let size = self.get_size();
let attrs = Self::get_gl_attributes(cx, options)?; let attrs = Self::get_gl_attributes(cx, options)?;
let canvas = HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(DomRoot::from_ref(self));
let context = WebGL2RenderingContext::new(&window, &canvas, size, attrs, can_gc)?; let context = WebGL2RenderingContext::new(&window, &canvas, size, attrs, can_gc)?;
*self.context_mode.borrow_mut() = Some(RenderingContext::WebGL2(Dom::from_ref(&*context))); *self.context_mode.borrow_mut() = Some(RenderingContext::WebGL2(Dom::from_ref(&*context)));
Some(context) Some(context)

View file

@ -29,7 +29,7 @@ use url::Host;
use webrender_api::ImageKey; use webrender_api::ImageKey;
use super::validations::types::TexImageTarget; use super::validations::types::TexImageTarget;
use crate::canvas_context::CanvasContext; use crate::canvas_context::{CanvasContext, LayoutCanvasRenderingContextHelpers};
use crate::dom::bindings::codegen::Bindings::WebGL2RenderingContextBinding::{ use crate::dom::bindings::codegen::Bindings::WebGL2RenderingContextBinding::{
WebGL2RenderingContextConstants as constants, WebGL2RenderingContextMethods, WebGL2RenderingContextConstants as constants, WebGL2RenderingContextMethods,
}; };
@ -38,15 +38,14 @@ use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::{
}; };
use crate::dom::bindings::codegen::UnionTypes::{ use crate::dom::bindings::codegen::UnionTypes::{
ArrayBufferViewOrArrayBuffer, Float32ArrayOrUnrestrictedFloatSequence, ArrayBufferViewOrArrayBuffer, Float32ArrayOrUnrestrictedFloatSequence,
HTMLCanvasElementOrOffscreenCanvas, Int32ArrayOrLongSequence, HTMLCanvasElementOrOffscreenCanvas as RootedHTMLCanvasElementOrOffscreenCanvas,
Uint32ArrayOrUnsignedLongSequence, Int32ArrayOrLongSequence, Uint32ArrayOrUnsignedLongSequence,
}; };
use crate::dom::bindings::error::{ErrorResult, Fallible}; use crate::dom::bindings::error::{ErrorResult, Fallible};
use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object}; use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object};
use crate::dom::bindings::root::{Dom, DomRoot, LayoutDom, MutNullableDom, ToLayout}; use crate::dom::bindings::root::{Dom, DomRoot, LayoutDom, MutNullableDom, ToLayout};
use crate::dom::bindings::str::DOMString; use crate::dom::bindings::str::DOMString;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::html::htmlcanvaselement::LayoutCanvasRenderingContextHelpers;
#[cfg(feature = "webxr")] #[cfg(feature = "webxr")]
use crate::dom::promise::Promise; use crate::dom::promise::Promise;
use crate::dom::webgl::validations::WebGLValidator; use crate::dom::webgl::validations::WebGLValidator;
@ -133,7 +132,7 @@ struct ReadPixelsSizes {
impl WebGL2RenderingContext { impl WebGL2RenderingContext {
fn new_inherited( fn new_inherited(
window: &Window, window: &Window,
canvas: &HTMLCanvasElementOrOffscreenCanvas, canvas: &RootedHTMLCanvasElementOrOffscreenCanvas,
size: Size2D<u32>, size: Size2D<u32>,
attrs: GLContextAttributes, attrs: GLContextAttributes,
can_gc: CanGc, can_gc: CanGc,
@ -179,10 +178,9 @@ impl WebGL2RenderingContext {
}) })
} }
#[cfg_attr(crown, allow(crown::unrooted_must_root))]
pub(crate) fn new( pub(crate) fn new(
window: &Window, window: &Window,
canvas: &HTMLCanvasElementOrOffscreenCanvas, canvas: &RootedHTMLCanvasElementOrOffscreenCanvas,
size: Size2D<u32>, size: Size2D<u32>,
attrs: GLContextAttributes, attrs: GLContextAttributes,
can_gc: CanGc, can_gc: CanGc,
@ -973,8 +971,8 @@ impl CanvasContext for WebGL2RenderingContext {
self.base.context_id() self.base.context_id()
} }
fn canvas(&self) -> Option<HTMLCanvasElementOrOffscreenCanvas> { fn canvas(&self) -> Option<RootedHTMLCanvasElementOrOffscreenCanvas> {
self.base.canvas().clone() self.base.canvas()
} }
fn resize(&self) { fn resize(&self) {
@ -1000,7 +998,7 @@ impl CanvasContext for WebGL2RenderingContext {
impl WebGL2RenderingContextMethods<crate::DomTypeHolder> for WebGL2RenderingContext { impl WebGL2RenderingContextMethods<crate::DomTypeHolder> for WebGL2RenderingContext {
/// <https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.1> /// <https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.1>
fn Canvas(&self) -> HTMLCanvasElementOrOffscreenCanvas { fn Canvas(&self) -> RootedHTMLCanvasElementOrOffscreenCanvas {
self.base.Canvas() self.base.Canvas()
} }

View file

@ -35,7 +35,9 @@ use serde::{Deserialize, Serialize};
use servo_config::pref; use servo_config::pref;
use webrender_api::ImageKey; use webrender_api::ImageKey;
use crate::canvas_context::CanvasContext; use crate::canvas_context::{
CanvasContext, HTMLCanvasElementOrOffscreenCanvas, LayoutCanvasRenderingContextHelpers,
};
use crate::dom::bindings::cell::{DomRefCell, Ref, RefMut}; use crate::dom::bindings::cell::{DomRefCell, Ref, RefMut};
use crate::dom::bindings::codegen::Bindings::ANGLEInstancedArraysBinding::ANGLEInstancedArraysConstants; use crate::dom::bindings::codegen::Bindings::ANGLEInstancedArraysBinding::ANGLEInstancedArraysConstants;
use crate::dom::bindings::codegen::Bindings::EXTBlendMinmaxBinding::EXTBlendMinmaxConstants; use crate::dom::bindings::codegen::Bindings::EXTBlendMinmaxBinding::EXTBlendMinmaxConstants;
@ -47,7 +49,8 @@ use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::{
}; };
use crate::dom::bindings::codegen::UnionTypes::{ use crate::dom::bindings::codegen::UnionTypes::{
ArrayBufferViewOrArrayBuffer, Float32ArrayOrUnrestrictedFloatSequence, ArrayBufferViewOrArrayBuffer, Float32ArrayOrUnrestrictedFloatSequence,
HTMLCanvasElementOrOffscreenCanvas, Int32ArrayOrLongSequence, HTMLCanvasElementOrOffscreenCanvas as RootedHTMLCanvasElementOrOffscreenCanvas,
Int32ArrayOrLongSequence,
}; };
use crate::dom::bindings::conversions::DerivedFrom; use crate::dom::bindings::conversions::DerivedFrom;
use crate::dom::bindings::error::{Error, ErrorResult, Fallible}; use crate::dom::bindings::error::{Error, ErrorResult, Fallible};
@ -56,7 +59,6 @@ use crate::dom::bindings::reflector::{DomGlobal, DomObject, Reflector, reflect_d
use crate::dom::bindings::root::{DomOnceCell, DomRoot, LayoutDom, MutNullableDom}; use crate::dom::bindings::root::{DomOnceCell, DomRoot, LayoutDom, MutNullableDom};
use crate::dom::bindings::str::DOMString; use crate::dom::bindings::str::DOMString;
use crate::dom::event::{Event, EventBubbles, EventCancelable}; use crate::dom::event::{Event, EventBubbles, EventCancelable};
use crate::dom::html::htmlcanvaselement::LayoutCanvasRenderingContextHelpers;
use crate::dom::node::{Node, NodeDamage, NodeTraits}; use crate::dom::node::{Node, NodeDamage, NodeTraits};
#[cfg(feature = "webxr")] #[cfg(feature = "webxr")]
use crate::dom::promise::Promise; use crate::dom::promise::Promise;
@ -216,9 +218,10 @@ pub(crate) struct WebGLRenderingContext {
} }
impl WebGLRenderingContext { impl WebGLRenderingContext {
#[cfg_attr(crown, allow(crown::unrooted_must_root))]
pub(crate) fn new_inherited( pub(crate) fn new_inherited(
window: &Window, window: &Window,
canvas: &HTMLCanvasElementOrOffscreenCanvas, canvas: HTMLCanvasElementOrOffscreenCanvas,
webgl_version: WebGLVersion, webgl_version: WebGLVersion,
size: Size2D<u32>, size: Size2D<u32>,
attrs: GLContextAttributes, attrs: GLContextAttributes,
@ -248,7 +251,7 @@ impl WebGLRenderingContext {
webgl_version, webgl_version,
glsl_version: ctx_data.glsl_version, glsl_version: ctx_data.glsl_version,
limits: ctx_data.limits, limits: ctx_data.limits,
canvas: canvas.clone(), canvas,
last_error: Cell::new(None), last_error: Cell::new(None),
texture_packing_alignment: Cell::new(4), texture_packing_alignment: Cell::new(4),
texture_unpacking_settings: Cell::new(TextureUnpacking::CONVERT_COLORSPACE), texture_unpacking_settings: Cell::new(TextureUnpacking::CONVERT_COLORSPACE),
@ -285,13 +288,19 @@ impl WebGLRenderingContext {
#[cfg_attr(crown, allow(crown::unrooted_must_root))] #[cfg_attr(crown, allow(crown::unrooted_must_root))]
pub(crate) fn new( pub(crate) fn new(
window: &Window, window: &Window,
canvas: &HTMLCanvasElementOrOffscreenCanvas, canvas: &RootedHTMLCanvasElementOrOffscreenCanvas,
webgl_version: WebGLVersion, webgl_version: WebGLVersion,
size: Size2D<u32>, size: Size2D<u32>,
attrs: GLContextAttributes, attrs: GLContextAttributes,
can_gc: CanGc, can_gc: CanGc,
) -> Option<DomRoot<WebGLRenderingContext>> { ) -> Option<DomRoot<WebGLRenderingContext>> {
match WebGLRenderingContext::new_inherited(window, canvas, webgl_version, size, attrs) { match WebGLRenderingContext::new_inherited(
window,
HTMLCanvasElementOrOffscreenCanvas::from(canvas),
webgl_version,
size,
attrs,
) {
Ok(ctx) => Some(reflect_dom_object(Box::new(ctx), window, can_gc)), Ok(ctx) => Some(reflect_dom_object(Box::new(ctx), window, can_gc)),
Err(msg) => { Err(msg) => {
error!("Couldn't create WebGLRenderingContext: {}", msg); error!("Couldn't create WebGLRenderingContext: {}", msg);
@ -304,10 +313,10 @@ impl WebGLRenderingContext {
can_gc, can_gc,
); );
match canvas { match canvas {
HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas) => { RootedHTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas) => {
event.upcast::<Event>().fire(canvas.upcast(), can_gc); event.upcast::<Event>().fire(canvas.upcast(), can_gc);
}, },
HTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas) => { RootedHTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas) => {
event.upcast::<Event>().fire(canvas.upcast(), can_gc); event.upcast::<Event>().fire(canvas.upcast(), can_gc);
}, },
} }
@ -1930,8 +1939,8 @@ impl CanvasContext for WebGLRenderingContext {
self.webgl_sender.context_id() self.webgl_sender.context_id()
} }
fn canvas(&self) -> Option<HTMLCanvasElementOrOffscreenCanvas> { fn canvas(&self) -> Option<RootedHTMLCanvasElementOrOffscreenCanvas> {
Some(self.canvas.clone()) Some(RootedHTMLCanvasElementOrOffscreenCanvas::from(&self.canvas))
} }
fn resize(&self) { fn resize(&self) {
@ -2075,8 +2084,8 @@ impl Drop for WebGLRenderingContext {
impl WebGLRenderingContextMethods<crate::DomTypeHolder> for WebGLRenderingContext { impl WebGLRenderingContextMethods<crate::DomTypeHolder> for WebGLRenderingContext {
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.1 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.1
fn Canvas(&self) -> HTMLCanvasElementOrOffscreenCanvas { fn Canvas(&self) -> RootedHTMLCanvasElementOrOffscreenCanvas {
self.canvas.clone() RootedHTMLCanvasElementOrOffscreenCanvas::from(&self.canvas)
} }
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.11 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.11

View file

@ -20,7 +20,10 @@ use wgpu_core::id;
use super::gpuconvert::convert_texture_descriptor; use super::gpuconvert::convert_texture_descriptor;
use super::gputexture::GPUTexture; use super::gputexture::GPUTexture;
use crate::canvas_context::{CanvasContext, CanvasHelpers}; use crate::canvas_context::{
CanvasContext, CanvasHelpers, HTMLCanvasElementOrOffscreenCanvas,
LayoutCanvasRenderingContextHelpers,
};
use crate::conversions::Convert; use crate::conversions::Convert;
use crate::dom::bindings::codegen::Bindings::GPUCanvasContextBinding::GPUCanvasContextMethods; use crate::dom::bindings::codegen::Bindings::GPUCanvasContextBinding::GPUCanvasContextMethods;
use crate::dom::bindings::codegen::Bindings::WebGPUBinding::GPUTexture_Binding::GPUTextureMethods; use crate::dom::bindings::codegen::Bindings::WebGPUBinding::GPUTexture_Binding::GPUTextureMethods;
@ -29,15 +32,15 @@ use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{
GPUObjectDescriptorBase, GPUTextureDescriptor, GPUTextureDimension, GPUTextureFormat, GPUObjectDescriptorBase, GPUTextureDescriptor, GPUTextureDimension, GPUTextureFormat,
GPUTextureUsageConstants, GPUTextureUsageConstants,
}; };
use crate::dom::bindings::codegen::UnionTypes::HTMLCanvasElementOrOffscreenCanvas; use crate::dom::bindings::codegen::UnionTypes::HTMLCanvasElementOrOffscreenCanvas as RootedHTMLCanvasElementOrOffscreenCanvas;
use crate::dom::bindings::error::{Error, Fallible}; use crate::dom::bindings::error::{Error, Fallible};
use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object}; use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object};
use crate::dom::bindings::root::{DomRoot, LayoutDom, MutNullableDom}; use crate::dom::bindings::root::{Dom, DomRoot, LayoutDom, MutNullableDom};
use crate::dom::bindings::str::USVString; use crate::dom::bindings::str::USVString;
use crate::dom::bindings::weakref::WeakRef; use crate::dom::bindings::weakref::WeakRef;
use crate::dom::document::WebGPUContextsMap; use crate::dom::document::WebGPUContextsMap;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::html::htmlcanvaselement::{HTMLCanvasElement, LayoutCanvasRenderingContextHelpers}; use crate::dom::html::htmlcanvaselement::HTMLCanvasElement;
use crate::dom::node::NodeTraits; use crate::dom::node::NodeTraits;
use crate::script_runtime::CanGc; use crate::script_runtime::CanGc;
@ -91,6 +94,7 @@ pub(crate) struct GPUCanvasContext {
} }
impl GPUCanvasContext { impl GPUCanvasContext {
#[cfg_attr(crown, allow(crown::unrooted_must_root))]
fn new_inherited( fn new_inherited(
global: &GlobalScope, global: &GlobalScope,
canvas: HTMLCanvasElementOrOffscreenCanvas, canvas: HTMLCanvasElementOrOffscreenCanvas,
@ -139,7 +143,7 @@ impl GPUCanvasContext {
let this = reflect_dom_object( let this = reflect_dom_object(
Box::new(GPUCanvasContext::new_inherited( Box::new(GPUCanvasContext::new_inherited(
global, global,
HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(DomRoot::from_ref(canvas)), HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(Dom::from_ref(canvas)),
channel, channel,
document.webgpu_contexts(), document.webgpu_contexts(),
)), )),
@ -328,8 +332,8 @@ impl CanvasContext for GPUCanvasContext {
}) })
} }
fn canvas(&self) -> Option<HTMLCanvasElementOrOffscreenCanvas> { fn canvas(&self) -> Option<RootedHTMLCanvasElementOrOffscreenCanvas> {
Some(self.canvas.clone()) Some(RootedHTMLCanvasElementOrOffscreenCanvas::from(&self.canvas))
} }
} }
@ -341,8 +345,8 @@ impl LayoutCanvasRenderingContextHelpers for LayoutDom<'_, GPUCanvasContext> {
impl GPUCanvasContextMethods<crate::DomTypeHolder> for GPUCanvasContext { impl GPUCanvasContextMethods<crate::DomTypeHolder> for GPUCanvasContext {
/// <https://gpuweb.github.io/gpuweb/#dom-gpucanvascontext-canvas> /// <https://gpuweb.github.io/gpuweb/#dom-gpucanvascontext-canvas>
fn Canvas(&self) -> HTMLCanvasElementOrOffscreenCanvas { fn Canvas(&self) -> RootedHTMLCanvasElementOrOffscreenCanvas {
self.canvas.clone() RootedHTMLCanvasElementOrOffscreenCanvas::from(&self.canvas)
} }
/// <https://gpuweb.github.io/gpuweb/#dom-gpucanvascontext-configure> /// <https://gpuweb.github.io/gpuweb/#dom-gpucanvascontext-configure>

View file

@ -10,14 +10,13 @@ use euclid::{Rect, Size2D};
use js::rust::HandleObject; use js::rust::HandleObject;
use webxr_api::{ContextId as WebXRContextId, LayerId, LayerInit, Viewport}; use webxr_api::{ContextId as WebXRContextId, LayerId, LayerInit, Viewport};
use crate::canvas_context::CanvasContext as _; use crate::canvas_context::CanvasContext;
use crate::conversions::Convert; use crate::conversions::Convert;
use crate::dom::bindings::codegen::Bindings::WebGL2RenderingContextBinding::WebGL2RenderingContextConstants as constants; use crate::dom::bindings::codegen::Bindings::WebGL2RenderingContextBinding::WebGL2RenderingContextConstants as constants;
use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextMethods; use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextMethods;
use crate::dom::bindings::codegen::Bindings::XRWebGLLayerBinding::{ use crate::dom::bindings::codegen::Bindings::XRWebGLLayerBinding::{
XRWebGLLayerInit, XRWebGLLayerMethods, XRWebGLRenderingContext, XRWebGLLayerInit, XRWebGLLayerMethods, XRWebGLRenderingContext,
}; };
use crate::dom::bindings::codegen::UnionTypes::HTMLCanvasElementOrOffscreenCanvas;
use crate::dom::bindings::error::{Error, Fallible}; use crate::dom::bindings::error::{Error, Fallible};
use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::num::Finite; use crate::dom::bindings::num::Finite;
@ -125,14 +124,7 @@ impl XRWebGLLayer {
size.1.try_into().unwrap_or(0), size.1.try_into().unwrap_or(0),
) )
} else { } else {
let size = match self.context().Canvas() { Size2D::from_untyped(self.context().size())
HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas) => canvas.get_size(),
HTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas) => {
let size = canvas.get_size();
Size2D::new(size.width, size.height)
},
};
Size2D::from_untyped(size)
} }
} }