diff --git a/ext/canvas/01_image.js b/ext/canvas/01_image.js
index 3018e9e2ac..844650dcb0 100644
--- a/ext/canvas/01_image.js
+++ b/ext/canvas/01_image.js
@@ -13,30 +13,18 @@ const {
SymbolFor,
TypeError,
TypedArrayPrototypeGetBuffer,
- TypedArrayPrototypeGetLength,
- TypedArrayPrototypeGetSymbolToStringTag,
Uint8Array,
- Uint8ClampedArray,
MathCeil,
PromiseResolve,
PromiseReject,
RangeError,
} = primordials;
-
-webidl.converters["PredefinedColorSpace"] = webidl.createEnumConverter(
- "PredefinedColorSpace",
- [
- "srgb",
- "display-p3",
- ],
-);
-
-webidl.converters["ImageDataSettings"] = webidl.createDictionaryConverter(
- "ImageDataSettings",
- [
- { key: "colorSpace", converter: webidl.converters["PredefinedColorSpace"] },
- ],
-);
+import {
+ _data,
+ _height,
+ _width,
+ ImageDataPrototype,
+} from "ext:deno_web/16_image_data.js";
webidl.converters["ImageOrientation"] = webidl.createEnumConverter(
"ImageOrientation",
@@ -115,194 +103,6 @@ webidl.converters["ImageBitmapOptions"] = webidl.createDictionaryConverter(
],
);
-const _data = Symbol("[[data]]");
-const _width = Symbol("[[width]]");
-const _height = Symbol("[[height]]");
-class ImageData {
- /** @type {number} */
- [_width];
- /** @type {height} */
- [_height];
- /** @type {Uint8Array} */
- [_data];
- /** @type {'srgb' | 'display-p3'} */
- #colorSpace;
-
- constructor(arg0, arg1, arg2 = undefined, arg3 = undefined) {
- webidl.requiredArguments(
- arguments.length,
- 2,
- 'Failed to construct "ImageData"',
- );
- this[webidl.brand] = webidl.brand;
-
- let sourceWidth;
- let sourceHeight;
- let data;
- let settings;
- const prefix = "Failed to construct 'ImageData'";
-
- // Overload: new ImageData(data, sw [, sh [, settings ] ])
- if (
- arguments.length > 3 ||
- TypedArrayPrototypeGetSymbolToStringTag(arg0) === "Uint8ClampedArray"
- ) {
- data = webidl.converters.Uint8ClampedArray(arg0, prefix, "Argument 1");
- sourceWidth = webidl.converters["unsigned long"](
- arg1,
- prefix,
- "Argument 2",
- );
- const dataLength = TypedArrayPrototypeGetLength(data);
-
- if (webidl.type(arg2) !== "Undefined") {
- sourceHeight = webidl.converters["unsigned long"](
- arg2,
- prefix,
- "Argument 3",
- );
- }
-
- settings = webidl.converters["ImageDataSettings"](
- arg3,
- prefix,
- "Argument 4",
- );
-
- if (dataLength === 0) {
- throw new DOMException(
- "Failed to construct 'ImageData': The input data has zero elements.",
- "InvalidStateError",
- );
- }
-
- if (dataLength % 4 !== 0) {
- throw new DOMException(
- "Failed to construct 'ImageData': The input data length is not a multiple of 4.",
- "InvalidStateError",
- );
- }
-
- if (sourceWidth < 1) {
- throw new DOMException(
- "Failed to construct 'ImageData': The source width is zero or not a number.",
- "IndexSizeError",
- );
- }
-
- if (webidl.type(sourceHeight) !== "Undefined" && sourceHeight < 1) {
- throw new DOMException(
- "Failed to construct 'ImageData': The source height is zero or not a number.",
- "IndexSizeError",
- );
- }
-
- if (dataLength / 4 % sourceWidth !== 0) {
- throw new DOMException(
- "Failed to construct 'ImageData': The input data length is not a multiple of (4 * width).",
- "IndexSizeError",
- );
- }
-
- if (
- webidl.type(sourceHeight) !== "Undefined" &&
- (sourceWidth * sourceHeight * 4 !== dataLength)
- ) {
- throw new DOMException(
- "Failed to construct 'ImageData': The input data length is not equal to (4 * width * height).",
- "IndexSizeError",
- );
- }
-
- if (webidl.type(sourceHeight) === "Undefined") {
- this[_height] = dataLength / 4 / sourceWidth;
- } else {
- this[_height] = sourceHeight;
- }
-
- this.#colorSpace = settings.colorSpace ?? "srgb";
- this[_width] = sourceWidth;
- this[_data] = data;
- return;
- }
-
- // Overload: new ImageData(sw, sh [, settings])
- sourceWidth = webidl.converters["unsigned long"](
- arg0,
- prefix,
- "Argument 1",
- );
- sourceHeight = webidl.converters["unsigned long"](
- arg1,
- prefix,
- "Argument 2",
- );
-
- settings = webidl.converters["ImageDataSettings"](
- arg2,
- prefix,
- "Argument 3",
- );
-
- if (sourceWidth < 1) {
- throw new DOMException(
- "Failed to construct 'ImageData': The source width is zero or not a number.",
- "IndexSizeError",
- );
- }
-
- if (sourceHeight < 1) {
- throw new DOMException(
- "Failed to construct 'ImageData': The source height is zero or not a number.",
- "IndexSizeError",
- );
- }
-
- this.#colorSpace = settings.colorSpace ?? "srgb";
- this[_width] = sourceWidth;
- this[_height] = sourceHeight;
- this[_data] = new Uint8ClampedArray(sourceWidth * sourceHeight * 4);
- }
-
- get width() {
- webidl.assertBranded(this, ImageDataPrototype);
- return this[_width];
- }
-
- get height() {
- webidl.assertBranded(this, ImageDataPrototype);
- return this[_height];
- }
-
- get data() {
- webidl.assertBranded(this, ImageDataPrototype);
- return this[_data];
- }
-
- get colorSpace() {
- webidl.assertBranded(this, ImageDataPrototype);
- return this.#colorSpace;
- }
-
- [SymbolFor("Deno.privateCustomInspect")](inspect, inspectOptions) {
- return inspect(
- createFilteredInspectProxy({
- object: this,
- evaluate: ObjectPrototypeIsPrototypeOf(ImageDataPrototype, this),
- keys: [
- "data",
- "width",
- "height",
- "colorSpace",
- ],
- }),
- inspectOptions,
- );
- }
-}
-
-const ImageDataPrototype = ImageData.prototype;
-
const _bitmapData = Symbol("[[bitmapData]]");
const _detached = Symbol("[[detached]]");
class ImageBitmap {
@@ -549,4 +349,4 @@ function getBitmapData(imageBitmap) {
internals.getBitmapData = getBitmapData;
-export { _bitmapData, _detached, createImageBitmap, ImageBitmap, ImageData };
+export { _bitmapData, _detached, createImageBitmap, ImageBitmap };
diff --git a/ext/canvas/lib.deno_canvas.d.ts b/ext/canvas/lib.deno_canvas.d.ts
index 28d57d583a..7498429c6e 100644
--- a/ext/canvas/lib.deno_canvas.d.ts
+++ b/ext/canvas/lib.deno_canvas.d.ts
@@ -5,34 +5,6 @@
///
///
-/** @category Web APIs */
-declare type PredefinedColorSpace = "srgb" | "display-p3";
-
-/** @category Web APIs */
-declare interface ImageDataSettings {
- readonly colorSpace?: PredefinedColorSpace;
-}
-
-/** @category Web APIs */
-declare interface ImageData {
- readonly colorSpace: PredefinedColorSpace;
- readonly data: Uint8ClampedArray;
- readonly height: number;
- readonly width: number;
-}
-
-/** @category Web APIs */
-declare var ImageData: {
- prototype: ImageData;
- new (sw: number, sh: number, settings?: ImageDataSettings): ImageData;
- new (
- data: Uint8ClampedArray,
- sw: number,
- sh?: number,
- settings?: ImageDataSettings,
- ): ImageData;
-};
-
/** @category Web APIs */
declare type ColorSpaceConversion = "default" | "none";
diff --git a/ext/web/16_image_data.js b/ext/web/16_image_data.js
new file mode 100644
index 0000000000..43f297a5c4
--- /dev/null
+++ b/ext/web/16_image_data.js
@@ -0,0 +1,219 @@
+// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+
+import { primordials } from "ext:core/mod.js";
+import * as webidl from "ext:deno_webidl/00_webidl.js";
+import { DOMException } from "ext:deno_web/01_dom_exception.js";
+import { createFilteredInspectProxy } from "ext:deno_console/01_console.js";
+const {
+ ObjectPrototypeIsPrototypeOf,
+ Symbol,
+ SymbolFor,
+ TypedArrayPrototypeGetLength,
+ TypedArrayPrototypeGetSymbolToStringTag,
+ Uint8ClampedArray,
+} = primordials;
+
+webidl.converters["PredefinedColorSpace"] = webidl.createEnumConverter(
+ "PredefinedColorSpace",
+ [
+ "srgb",
+ "display-p3",
+ ],
+);
+
+webidl.converters["ImageDataSettings"] = webidl.createDictionaryConverter(
+ "ImageDataSettings",
+ [
+ { key: "colorSpace", converter: webidl.converters["PredefinedColorSpace"] },
+ ],
+);
+
+const _data = Symbol("[[data]]");
+const _width = Symbol("[[width]]");
+const _height = Symbol("[[height]]");
+class ImageData {
+ /** @type {number} */
+ [_width];
+ /** @type {height} */
+ [_height];
+ /** @type {Uint8Array} */
+ [_data];
+ /** @type {'srgb' | 'display-p3'} */
+ #colorSpace;
+
+ constructor(arg0, arg1, arg2 = undefined, arg3 = undefined) {
+ webidl.requiredArguments(
+ arguments.length,
+ 2,
+ 'Failed to construct "ImageData"',
+ );
+ this[webidl.brand] = webidl.brand;
+
+ let sourceWidth;
+ let sourceHeight;
+ let data;
+ let settings;
+ const prefix = "Failed to construct 'ImageData'";
+
+ // Overload: new ImageData(data, sw [, sh [, settings ] ])
+ if (
+ arguments.length > 3 ||
+ TypedArrayPrototypeGetSymbolToStringTag(arg0) === "Uint8ClampedArray"
+ ) {
+ data = webidl.converters.Uint8ClampedArray(arg0, prefix, "Argument 1");
+ sourceWidth = webidl.converters["unsigned long"](
+ arg1,
+ prefix,
+ "Argument 2",
+ );
+ const dataLength = TypedArrayPrototypeGetLength(data);
+
+ if (webidl.type(arg2) !== "Undefined") {
+ sourceHeight = webidl.converters["unsigned long"](
+ arg2,
+ prefix,
+ "Argument 3",
+ );
+ }
+
+ settings = webidl.converters["ImageDataSettings"](
+ arg3,
+ prefix,
+ "Argument 4",
+ );
+
+ if (dataLength === 0) {
+ throw new DOMException(
+ "Failed to construct 'ImageData': The input data has zero elements.",
+ "InvalidStateError",
+ );
+ }
+
+ if (dataLength % 4 !== 0) {
+ throw new DOMException(
+ "Failed to construct 'ImageData': The input data length is not a multiple of 4.",
+ "InvalidStateError",
+ );
+ }
+
+ if (sourceWidth < 1) {
+ throw new DOMException(
+ "Failed to construct 'ImageData': The source width is zero or not a number.",
+ "IndexSizeError",
+ );
+ }
+
+ if (webidl.type(sourceHeight) !== "Undefined" && sourceHeight < 1) {
+ throw new DOMException(
+ "Failed to construct 'ImageData': The source height is zero or not a number.",
+ "IndexSizeError",
+ );
+ }
+
+ if (dataLength / 4 % sourceWidth !== 0) {
+ throw new DOMException(
+ "Failed to construct 'ImageData': The input data length is not a multiple of (4 * width).",
+ "IndexSizeError",
+ );
+ }
+
+ if (
+ webidl.type(sourceHeight) !== "Undefined" &&
+ (sourceWidth * sourceHeight * 4 !== dataLength)
+ ) {
+ throw new DOMException(
+ "Failed to construct 'ImageData': The input data length is not equal to (4 * width * height).",
+ "IndexSizeError",
+ );
+ }
+
+ if (webidl.type(sourceHeight) === "Undefined") {
+ this[_height] = dataLength / 4 / sourceWidth;
+ } else {
+ this[_height] = sourceHeight;
+ }
+
+ this.#colorSpace = settings.colorSpace ?? "srgb";
+ this[_width] = sourceWidth;
+ this[_data] = data;
+ return;
+ }
+
+ // Overload: new ImageData(sw, sh [, settings])
+ sourceWidth = webidl.converters["unsigned long"](
+ arg0,
+ prefix,
+ "Argument 1",
+ );
+ sourceHeight = webidl.converters["unsigned long"](
+ arg1,
+ prefix,
+ "Argument 2",
+ );
+
+ settings = webidl.converters["ImageDataSettings"](
+ arg2,
+ prefix,
+ "Argument 3",
+ );
+
+ if (sourceWidth < 1) {
+ throw new DOMException(
+ "Failed to construct 'ImageData': The source width is zero or not a number.",
+ "IndexSizeError",
+ );
+ }
+
+ if (sourceHeight < 1) {
+ throw new DOMException(
+ "Failed to construct 'ImageData': The source height is zero or not a number.",
+ "IndexSizeError",
+ );
+ }
+
+ this.#colorSpace = settings.colorSpace ?? "srgb";
+ this[_width] = sourceWidth;
+ this[_height] = sourceHeight;
+ this[_data] = new Uint8ClampedArray(sourceWidth * sourceHeight * 4);
+ }
+
+ get width() {
+ webidl.assertBranded(this, ImageDataPrototype);
+ return this[_width];
+ }
+
+ get height() {
+ webidl.assertBranded(this, ImageDataPrototype);
+ return this[_height];
+ }
+
+ get data() {
+ webidl.assertBranded(this, ImageDataPrototype);
+ return this[_data];
+ }
+
+ get colorSpace() {
+ webidl.assertBranded(this, ImageDataPrototype);
+ return this.#colorSpace;
+ }
+
+ [SymbolFor("Deno.privateCustomInspect")](inspect, inspectOptions) {
+ return inspect(
+ createFilteredInspectProxy({
+ object: this,
+ evaluate: ObjectPrototypeIsPrototypeOf(ImageDataPrototype, this),
+ keys: [
+ "data",
+ "width",
+ "height",
+ "colorSpace",
+ ],
+ }),
+ inspectOptions,
+ );
+ }
+}
+
+const ImageDataPrototype = ImageData.prototype;
+
+export { _data, _height, _width, ImageData, ImageDataPrototype };
diff --git a/ext/web/lib.deno_web.d.ts b/ext/web/lib.deno_web.d.ts
index 55048e14e5..d28e33f58d 100644
--- a/ext/web/lib.deno_web.d.ts
+++ b/ext/web/lib.deno_web.d.ts
@@ -1237,3 +1237,31 @@ declare var DecompressionStream: {
declare function reportError(
error: any,
): void;
+
+/** @category Web APIs */
+declare type PredefinedColorSpace = "srgb" | "display-p3";
+
+/** @category Web APIs */
+declare interface ImageDataSettings {
+ readonly colorSpace?: PredefinedColorSpace;
+}
+
+/** @category Web APIs */
+declare interface ImageData {
+ readonly colorSpace: PredefinedColorSpace;
+ readonly data: Uint8ClampedArray;
+ readonly height: number;
+ readonly width: number;
+}
+
+/** @category Web APIs */
+declare var ImageData: {
+ prototype: ImageData;
+ new (sw: number, sh: number, settings?: ImageDataSettings): ImageData;
+ new (
+ data: Uint8ClampedArray,
+ sw: number,
+ sh?: number,
+ settings?: ImageDataSettings,
+ ): ImageData;
+};
diff --git a/ext/web/lib.rs b/ext/web/lib.rs
index 2792212ae3..acac78f562 100644
--- a/ext/web/lib.rs
+++ b/ext/web/lib.rs
@@ -117,6 +117,7 @@ deno_core::extension!(deno_web,
"13_message_port.js",
"14_compression.js",
"15_performance.js",
+ "16_image_data.js",
],
options = {
blob_store: Arc,
diff --git a/runtime/js/98_global_scope_shared.js b/runtime/js/98_global_scope_shared.js
index d139a438b2..aba0f3710f 100644
--- a/runtime/js/98_global_scope_shared.js
+++ b/runtime/js/98_global_scope_shared.js
@@ -30,6 +30,7 @@ import * as messagePort from "ext:deno_web/13_message_port.js";
import * as webidl from "ext:deno_webidl/00_webidl.js";
import { DOMException } from "ext:deno_web/01_dom_exception.js";
import * as abortSignal from "ext:deno_web/03_abort_signal.js";
+import * as imageData from "ext:deno_web/16_image_data.js";
import { loadWebGPU } from "ext:deno_webgpu/00_init.js";
import * as webgpuSurface from "ext:deno_webgpu/02_surface.js";
import { unstableIds } from "ext:runtime/90_deno_ns.js";
@@ -60,10 +61,7 @@ const windowOrWorkerGlobalScope = {
FileReader: core.propNonEnumerable(fileReader.FileReader),
FormData: core.propNonEnumerable(formData.FormData),
Headers: core.propNonEnumerable(headers.Headers),
- ImageData: core.propNonEnumerableLazyLoaded(
- (image) => image.ImageData,
- loadImage,
- ),
+ ImageData: core.propNonEnumerable(imageData.ImageData),
ImageBitmap: core.propNonEnumerableLazyLoaded(
(image) => image.ImageBitmap,
loadImage,
diff --git a/tools/core_import_map.json b/tools/core_import_map.json
index cbae323edb..9e70f52f7f 100644
--- a/tools/core_import_map.json
+++ b/tools/core_import_map.json
@@ -223,6 +223,7 @@
"ext:deno_web/13_message_port.js": "../ext/web/13_message_port.js",
"ext:deno_web/14_compression.js": "../ext/web/14_compression.js",
"ext:deno_web/15_performance.js": "../ext/web/15_performance.js",
+ "ext:deno_web/16_image_data.js": "../ext/web/16_image_data.js",
"ext:deno_webidl/00_webidl.js": "../ext/webidl/00_webidl.js",
"ext:deno_websocket/01_websocket.js": "../ext/websocket/01_websocket.js",
"ext:deno_websocket/02_websocketstream.js": "../ext/websocket/02_websocketstream.js",