diff --git a/src/browser/tests/canvas/canvas_rendering_context_2d.html b/src/browser/tests/canvas/canvas_rendering_context_2d.html
index 22bcaa20..701fbdef 100644
--- a/src/browser/tests/canvas/canvas_rendering_context_2d.html
+++ b/src/browser/tests/canvas/canvas_rendering_context_2d.html
@@ -33,3 +33,58 @@
testing.expectEqual(ctx.fillStyle, "rgba(255, 0, 0, 0.06)");
}
+
+
+
+
+
+
diff --git a/src/browser/tests/image_data.html b/src/browser/tests/image_data.html
index ccaef668..3cf3282e 100644
--- a/src/browser/tests/image_data.html
+++ b/src/browser/tests/image_data.html
@@ -59,10 +59,6 @@
}
-
+
+
diff --git a/src/browser/webapi/ImageData.zig b/src/browser/webapi/ImageData.zig
index 05fcae6c..c9ced5f1 100644
--- a/src/browser/webapi/ImageData.zig
+++ b/src/browser/webapi/ImageData.zig
@@ -58,7 +58,10 @@ pub fn constructor(
maybe_settings: ?ConstructorSettings,
page: *Page,
) !*ImageData {
- if (width == 0 or height == 0) {
+ // Though arguments are unsigned long, these are capped to max. i32 on Chrome.
+ // https://github.com/chromium/chromium/blob/main/third_party/blink/renderer/core/html/canvas/image_data.cc#L61
+ const max_i32 = std.math.maxInt(i32);
+ if (width == 0 or width > max_i32 or height == 0 or height > max_i32) {
return error.IndexSizeError;
}
@@ -70,7 +73,11 @@ pub fn constructor(
return error.TypeError;
}
- const size = width * height * 4;
+ var size, var overflown = @mulWithOverflow(width, height);
+ if (overflown == 1) return error.IndexSizeError;
+ size, overflown = @mulWithOverflow(size, 4);
+ if (overflown == 1) return error.IndexSizeError;
+
return page._factory.create(ImageData{
._width = width,
._height = height,
diff --git a/src/browser/webapi/canvas/CanvasRenderingContext2D.zig b/src/browser/webapi/canvas/CanvasRenderingContext2D.zig
index 0c5ca1e7..f9aa0b18 100644
--- a/src/browser/webapi/canvas/CanvasRenderingContext2D.zig
+++ b/src/browser/webapi/canvas/CanvasRenderingContext2D.zig
@@ -23,6 +23,8 @@ const js = @import("../../js/js.zig");
const color = @import("../../color.zig");
const Page = @import("../../Page.zig");
+const ImageData = @import("../ImageData.zig");
+
/// This class doesn't implement a `constructor`.
/// It can be obtained with a call to `HTMLCanvasElement#getContext`.
/// https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D
@@ -85,6 +87,33 @@ pub fn getTextBaseline(_: *const CanvasRenderingContext2D) []const u8 {
return "alphabetic";
}
+const WidthOrImageData = union(enum) {
+ width: u32,
+ image_data: *ImageData,
+};
+
+pub fn createImageData(
+ _: *const CanvasRenderingContext2D,
+ width_or_image_data: WidthOrImageData,
+ /// If `ImageData` variant preferred, this is null.
+ maybe_height: ?u32,
+ /// Can be used if width and height provided.
+ maybe_settings: ?ImageData.ConstructorSettings,
+ page: *Page,
+) !*ImageData {
+ switch (width_or_image_data) {
+ .width => |width| {
+ const height = maybe_height orelse return error.TypeError;
+ return ImageData.constructor(width, height, maybe_settings, page);
+ },
+ .image_data => |image_data| {
+ return ImageData.constructor(image_data._width, image_data._height, null, page);
+ },
+ }
+}
+
+pub fn putImageData(_: *const CanvasRenderingContext2D, _: *ImageData, _: f64, _: f64, _: ?f64, _: ?f64, _: ?f64, _: ?f64) void {}
+
pub fn save(_: *CanvasRenderingContext2D) void {}
pub fn restore(_: *CanvasRenderingContext2D) void {}
pub fn scale(_: *CanvasRenderingContext2D, _: f64, _: f64) void {}
@@ -131,6 +160,9 @@ pub const JsApi = struct {
pub var class_id: bridge.ClassId = undefined;
};
+ pub const createImageData = bridge.function(CanvasRenderingContext2D.createImageData, .{ .dom_exception = true });
+ pub const putImageData = bridge.function(CanvasRenderingContext2D.putImageData, .{});
+
pub const save = bridge.function(CanvasRenderingContext2D.save, .{});
pub const restore = bridge.function(CanvasRenderingContext2D.restore, .{});