mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-03-31 01:28:55 +00:00
fix: cache canvas 2D context and lock context type per spec
Per the HTML spec, HTMLCanvasElement.getContext() should:
1. Return the same object on repeated calls with the same type
2. Return null if a different context type was already requested
Previously, every getContext("2d") call created a new
CanvasRenderingContext2D object. This caused issues with code
that relies on identity checks (ctx === canvas.getContext("2d"))
and wasted memory by allocating duplicate contexts.
The fix caches the 2D context and tracks which context type was
first requested, returning null for incompatible subsequent calls.
This commit is contained in:
@@ -30,6 +30,13 @@ const OffscreenCanvas = @import("../../canvas/OffscreenCanvas.zig");
|
||||
const Canvas = @This();
|
||||
_proto: *HtmlElement,
|
||||
|
||||
/// Cached context type. Once set, requesting a different type returns null (per spec).
|
||||
_context_type: ContextType = .none,
|
||||
/// Cached 2D rendering context (same object returned on repeated getContext("2d") calls).
|
||||
_ctx_2d: ?*CanvasRenderingContext2D = null,
|
||||
|
||||
const ContextType = enum { none, @"2d", webgl };
|
||||
|
||||
pub fn asElement(self: *Canvas) *Element {
|
||||
return self._proto._proto;
|
||||
}
|
||||
@@ -69,12 +76,23 @@ const DrawingContext = union(enum) {
|
||||
|
||||
pub fn getContext(self: *Canvas, context_type: []const u8, page: *Page) !?DrawingContext {
|
||||
if (std.mem.eql(u8, context_type, "2d")) {
|
||||
// Return cached context if available.
|
||||
if (self._ctx_2d) |cached| return .{ .@"2d" = cached };
|
||||
// Per spec: return null if a different context type was already requested.
|
||||
if (self._context_type != .none) return null;
|
||||
|
||||
const ctx = try page._factory.create(CanvasRenderingContext2D{ ._canvas = self });
|
||||
self._ctx_2d = ctx;
|
||||
self._context_type = .@"2d";
|
||||
return .{ .@"2d" = ctx };
|
||||
}
|
||||
|
||||
if (std.mem.eql(u8, context_type, "webgl") or std.mem.eql(u8, context_type, "experimental-webgl")) {
|
||||
// Per spec: return null if a different context type was already requested.
|
||||
if (self._context_type != .none and self._context_type != .webgl) return null;
|
||||
|
||||
const ctx = try page._factory.create(WebGLRenderingContext{});
|
||||
self._context_type = .webgl;
|
||||
return .{ .webgl = ctx };
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user