mirror of
https://github.com/servo/servo.git
synced 2025-09-30 08:39:16 +01:00
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:
parent
2c7866eb24
commit
8a62984c2f
11 changed files with 191 additions and 116 deletions
|
@ -13,19 +13,23 @@ use servo_url::ServoUrl;
|
|||
use webrender_api::ImageKey;
|
||||
|
||||
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::{
|
||||
CanvasDirection, CanvasFillRule, CanvasImageSource, CanvasLineCap, CanvasLineJoin,
|
||||
CanvasRenderingContext2DMethods, CanvasTextAlign, CanvasTextBaseline,
|
||||
};
|
||||
use crate::dom::bindings::codegen::Bindings::DOMMatrixBinding::DOMMatrix2DInit;
|
||||
use crate::dom::bindings::codegen::UnionTypes::{
|
||||
HTMLCanvasElementOrOffscreenCanvas, StringOrCanvasGradientOrCanvasPattern,
|
||||
HTMLCanvasElementOrOffscreenCanvas as RootedHTMLCanvasElementOrOffscreenCanvas,
|
||||
StringOrCanvasGradientOrCanvasPattern,
|
||||
};
|
||||
use crate::dom::bindings::error::{ErrorResult, Fallible};
|
||||
use crate::dom::bindings::num::Finite;
|
||||
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::canvasgradient::CanvasGradient;
|
||||
use crate::dom::canvaspattern::CanvasPattern;
|
||||
|
@ -62,19 +66,18 @@ impl CanvasRenderingContext2D {
|
|||
})
|
||||
}
|
||||
|
||||
#[cfg_attr(crown, allow(crown::unrooted_must_root))]
|
||||
pub(crate) fn new(
|
||||
global: &GlobalScope,
|
||||
canvas: &HTMLCanvasElement,
|
||||
size: Size2D<u32>,
|
||||
can_gc: CanGc,
|
||||
) -> Option<DomRoot<CanvasRenderingContext2D>> {
|
||||
let boxed = Box::new(CanvasRenderingContext2D::new_inherited(
|
||||
CanvasRenderingContext2D::new_inherited(
|
||||
global,
|
||||
HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(DomRoot::from_ref(canvas)),
|
||||
HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(Dom::from_ref(canvas)),
|
||||
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
|
||||
|
@ -119,8 +122,8 @@ impl CanvasContext for CanvasRenderingContext2D {
|
|||
self.canvas_state.get_canvas_id()
|
||||
}
|
||||
|
||||
fn canvas(&self) -> Option<HTMLCanvasElementOrOffscreenCanvas> {
|
||||
Some(self.canvas.clone())
|
||||
fn canvas(&self) -> Option<RootedHTMLCanvasElementOrOffscreenCanvas> {
|
||||
Some(RootedHTMLCanvasElementOrOffscreenCanvas::from(&self.canvas))
|
||||
}
|
||||
|
||||
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
|
||||
fn Canvas(&self) -> DomRoot<HTMLCanvasElement> {
|
||||
match &self.canvas {
|
||||
HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas) => canvas.clone(),
|
||||
HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas) => canvas.as_rooted(),
|
||||
_ => panic!("Should not be called from offscreen canvas"),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,27 +2,30 @@
|
|||
* 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/. */
|
||||
|
||||
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 dom_struct::dom_struct;
|
||||
use euclid::default::Size2D;
|
||||
use pixels::Snapshot;
|
||||
|
||||
use crate::canvas_context::{CanvasContext, HTMLCanvasElementOrOffscreenCanvas};
|
||||
use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::{
|
||||
CanvasDirection, CanvasFillRule, CanvasImageSource, CanvasLineCap, CanvasLineJoin,
|
||||
CanvasTextAlign, CanvasTextBaseline,
|
||||
CanvasRenderingContext2DMethods, CanvasTextAlign, CanvasTextBaseline,
|
||||
};
|
||||
use crate::dom::bindings::codegen::Bindings::DOMMatrixBinding::DOMMatrix2DInit;
|
||||
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::num::Finite;
|
||||
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::canvasgradient::CanvasGradient;
|
||||
use crate::dom::canvaspattern::CanvasPattern;
|
||||
use crate::dom::canvasrenderingcontext2d::CanvasRenderingContext2D;
|
||||
use crate::dom::dommatrix::DOMMatrix;
|
||||
use crate::dom::globalscope::GlobalScope;
|
||||
use crate::dom::imagedata::ImageData;
|
||||
|
@ -31,8 +34,6 @@ use crate::dom::path2d::Path2D;
|
|||
use crate::dom::textmetrics::TextMetrics;
|
||||
use crate::script_runtime::CanGc;
|
||||
|
||||
use super::canvasrenderingcontext2d::CanvasRenderingContext2D;
|
||||
|
||||
#[dom_struct]
|
||||
pub(crate) struct OffscreenCanvasRenderingContext2D {
|
||||
context: CanvasRenderingContext2D,
|
||||
|
@ -42,28 +43,26 @@ impl OffscreenCanvasRenderingContext2D {
|
|||
#[cfg_attr(crown, allow(crown::unrooted_must_root))]
|
||||
fn new_inherited(
|
||||
global: &GlobalScope,
|
||||
canvas: &OffscreenCanvas,
|
||||
canvas: HTMLCanvasElementOrOffscreenCanvas,
|
||||
size: Size2D<u32>,
|
||||
) -> Option<OffscreenCanvasRenderingContext2D> {
|
||||
let size = canvas.get_size().cast();
|
||||
Some(OffscreenCanvasRenderingContext2D {
|
||||
context: CanvasRenderingContext2D::new_inherited(
|
||||
global,
|
||||
HTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(DomRoot::from_ref(canvas)),
|
||||
size,
|
||||
)?,
|
||||
context: CanvasRenderingContext2D::new_inherited(global, canvas, size)?,
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg_attr(crown, allow(crown::unrooted_must_root))]
|
||||
pub(crate) fn new(
|
||||
global: &GlobalScope,
|
||||
canvas: &OffscreenCanvas,
|
||||
size: Size2D<u32>,
|
||||
can_gc: CanGc,
|
||||
) -> Option<DomRoot<OffscreenCanvasRenderingContext2D>> {
|
||||
let boxed = Box::new(OffscreenCanvasRenderingContext2D::new_inherited(
|
||||
global, canvas,
|
||||
)?);
|
||||
Some(reflect_dom_object(boxed, global, can_gc))
|
||||
OffscreenCanvasRenderingContext2D::new_inherited(
|
||||
global,
|
||||
HTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(Dom::from_ref(canvas)),
|
||||
size,
|
||||
)
|
||||
.map(|context| reflect_dom_object(Box::new(context), global, can_gc))
|
||||
}
|
||||
|
||||
pub(crate) fn send_canvas_2d_msg(&self, msg: Canvas2dMsg) {
|
||||
|
@ -78,7 +77,7 @@ impl CanvasContext for OffscreenCanvasRenderingContext2D {
|
|||
self.context.context_id()
|
||||
}
|
||||
|
||||
fn canvas(&self) -> Option<HTMLCanvasElementOrOffscreenCanvas> {
|
||||
fn canvas(&self) -> Option<RootedHTMLCanvasElementOrOffscreenCanvas> {
|
||||
self.context.canvas()
|
||||
}
|
||||
|
||||
|
@ -109,7 +108,7 @@ impl OffscreenCanvasRenderingContext2DMethods<crate::DomTypeHolder>
|
|||
// https://html.spec.whatwg.org/multipage/offscreencontext2d-canvas
|
||||
fn Canvas(&self) -> DomRoot<OffscreenCanvas> {
|
||||
match self.context.canvas() {
|
||||
Some(HTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas)) => canvas,
|
||||
Some(RootedHTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas)) => canvas,
|
||||
_ => panic!("Should not be called from onscreen canvas"),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue