aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bun.js/api/bun.zig46
-rw-r--r--src/bun.js/api/canvas.classes.ts73
-rw-r--r--src/bun.js/api/canvas.zig806
-rw-r--r--src/bun.js/bindings/BunObject+exports.h1
-rw-r--r--src/bun.js/bindings/BunObject.cpp1
-rw-r--r--src/bun.js/bindings/BunObject.lut.h131
-rw-r--r--src/bun.js/bindings/ZigGeneratedClasses+DOMClientIsoSubspaces.h4
-rw-r--r--src/bun.js/bindings/ZigGeneratedClasses+DOMIsoSubspaces.h4
-rw-r--r--src/bun.js/bindings/ZigGeneratedClasses+lazyStructureHeader.h8
-rw-r--r--src/bun.js/bindings/ZigGeneratedClasses+lazyStructureImpl.h14
-rw-r--r--src/bun.js/bindings/ZigGeneratedClasses.cpp892
-rw-r--r--src/bun.js/bindings/ZigGeneratedClasses.h131
-rw-r--r--src/bun.js/bindings/generated_classes.zig194
-rw-r--r--src/bun.js/bindings/generated_classes_list.zig2
m---------src/deps/SDL0
-rw-r--r--src/jsc.zig2
-rw-r--r--src/string.zig2
17 files changed, 2238 insertions, 73 deletions
diff --git a/src/bun.js/api/bun.zig b/src/bun.js/api/bun.zig
index 21c2ecd0e..4c13214b3 100644
--- a/src/bun.js/api/bun.zig
+++ b/src/bun.js/api/bun.zig
@@ -57,6 +57,7 @@ pub const BunObject = struct {
pub const SHA512_256 = Crypto.SHA512_256.getter;
pub const TOML = Bun.getTOMLObject;
pub const Transpiler = Bun.getTranspilerConstructor;
+ pub const Canvas = Bun.getCanvasConstructor;
pub const argv = Bun.getArgv;
pub const assetPrefix = Bun.getAssetPrefix;
pub const cwd = Bun.getCWD;
@@ -102,6 +103,7 @@ pub const BunObject = struct {
@export(BunObject.SHA512_256, .{ .name = getterName("SHA512_256") });
@export(BunObject.TOML, .{ .name = getterName("TOML") });
@export(BunObject.Transpiler, .{ .name = getterName("Transpiler") });
+ @export(BunObject.Canvas, .{ .name = getterName("Canvas") });
@export(BunObject.argv, .{ .name = getterName("argv") });
@export(BunObject.assetPrefix, .{ .name = getterName("assetPrefix") });
@export(BunObject.cwd, .{ .name = getterName("cwd") });
@@ -2827,6 +2829,13 @@ pub fn getTranspilerConstructor(
return JSC.API.JSTranspiler.getConstructor(globalThis);
}
+pub fn getCanvasConstructor(
+ globalThis: *JSC.JSGlobalObject,
+ _: *JSC.JSObject,
+) callconv(.C) JSC.JSValue {
+ return JSC.API.Canvas.getConstructor(globalThis);
+}
+
pub fn getFileSystemRouter(
globalThis: *JSC.JSGlobalObject,
_: *JSC.JSObject,
@@ -3715,6 +3724,22 @@ pub const Timer = struct {
return TimerObject.init(globalThis, id, .setTimeout, interval, wrappedCallback, arguments);
}
+
+ pub fn setImmediate(
+ globalThis: *JSGlobalObject,
+ callback: JSValue,
+ arguments: JSValue,
+ ) callconv(.C) JSValue {
+ JSC.markBinding(@src());
+ const id = globalThis.bunVM().timer.last_id;
+ globalThis.bunVM().timer.last_id +%= 1;
+
+ const wrappedCallback = callback.withAsyncContextIfNeeded(globalThis);
+ Timer.set(id, globalThis, wrappedCallback, 0, arguments, false) catch return .undefined;
+
+ return TimerObject.init(globalThis, id, .setImmediate, 0, wrappedCallback, arguments);
+ }
+
pub fn setInterval(
globalThis: *JSGlobalObject,
callback: JSValue,
@@ -3739,10 +3764,9 @@ pub const Timer = struct {
return TimerObject.init(globalThis, id, .setInterval, interval, wrappedCallback, arguments);
}
- pub fn clearTimer(timer_id_value: JSValue, globalThis: *JSGlobalObject, repeats: bool) void {
+ pub fn clearTimer(timer_id_value: JSValue, globalThis: *JSGlobalObject, kind: Timeout.Kind) void {
JSC.markBinding(@src());
- const kind: Timeout.Kind = if (repeats) .setInterval else .setTimeout;
var vm = globalThis.bunVM();
var map = vm.timer.maps.get(kind);
@@ -3781,16 +3805,26 @@ pub const Timer = struct {
id: JSValue,
) callconv(.C) JSValue {
JSC.markBinding(@src());
- Timer.clearTimer(id, globalThis, false);
- return JSValue.jsUndefined();
+ Timer.clearTimer(id, globalThis, .setTimeout);
+ return .undefined;
+ }
+
+ pub fn clearImmediate(
+ globalThis: *JSGlobalObject,
+ id: JSValue,
+ ) callconv(.C) JSValue {
+ JSC.markBinding(@src());
+ Timer.clearTimer(id, globalThis, .setImmediate);
+ return .undefined;
}
+
pub fn clearInterval(
globalThis: *JSGlobalObject,
id: JSValue,
) callconv(.C) JSValue {
JSC.markBinding(@src());
- Timer.clearTimer(id, globalThis, true);
- return JSValue.jsUndefined();
+ Timer.clearTimer(id, globalThis, .setInterval);
+ return .undefined;
}
const Shimmer = @import("../bindings/shimmer.zig").Shimmer;
diff --git a/src/bun.js/api/canvas.classes.ts b/src/bun.js/api/canvas.classes.ts
new file mode 100644
index 000000000..ce3cac6c3
--- /dev/null
+++ b/src/bun.js/api/canvas.classes.ts
@@ -0,0 +1,73 @@
+import { define } from "../scripts/class-definitions";
+
+export default [
+ define({
+ name: "Canvas",
+ construct: true,
+ finalize: true,
+ hasPendingActivity: true,
+ configurable: false,
+ klass: {},
+ JSType: "0b11101110",
+ proto: {
+ width: {
+ getter: "getWidth",
+ setter: "setWidth",
+ },
+ height: {
+ getter: "getHeight",
+ setter: "setHeight",
+ },
+ x: {
+ getter: "getX",
+ setter: "setX",
+ },
+ y: {
+ getter: "getY",
+ setter: "setY",
+ },
+ animate: {
+ fn: "animate",
+ length: 1,
+ },
+ close: {
+ fn: "close",
+ length: 0,
+ },
+ getContext: {
+ fn: "getContext",
+ length: 1,
+ },
+ },
+ }),
+ define({
+ name: "CanvasRenderingContext2D",
+ construct: true,
+ finalize: false,
+ configurable: false,
+ klass: {},
+ JSType: "0b11101110",
+ proto: {
+ strokeStyle: {
+ getter: "getStrokeStyle",
+ setter: "setStrokeStyle",
+ },
+ fillStyle: {
+ getter: "getFillStyle",
+ setter: "setFillStyle",
+ },
+ clearRect: {
+ fn: "clearRect",
+ length: 4,
+ },
+ fillRect: {
+ fn: "fillRect",
+ length: 4,
+ },
+ strokeRect: {
+ fn: "strokeRect",
+ length: 4,
+ },
+ },
+ }),
+];
diff --git a/src/bun.js/api/canvas.zig b/src/bun.js/api/canvas.zig
new file mode 100644
index 000000000..2134aa933
--- /dev/null
+++ b/src/bun.js/api/canvas.zig
@@ -0,0 +1,806 @@
+const std = @import("std");
+const bun = @import("root").bun;
+const strings = bun.strings;
+const string = bun.string;
+const Output = bun.Output;
+const JSC = bun.JSC;
+const JSValue = JSC.JSValue;
+const JSGlobalObject = JSC.JSGlobalObject;
+const CallFrame = JSC.CallFrame;
+const Timer = JSC.BunTimer;
+const ZigString = JSC.ZigString;
+
+// for now cInclude, later add a SDL wrapper
+const c = @cImport({
+ @cInclude("SDL.h");
+});
+
+var initializeSDL = std.once(struct {
+ pub fn call() void {
+ _ = c.SDL_Init(c.SDL_INIT_VIDEO);
+ }
+}.call);
+
+const Color = union(enum) {
+ rgba: u32,
+ argb: u32,
+
+ pub fn a(this: Color) u8 {
+ return switch (this) {
+ .rgba => |color| @truncate(color),
+ .argb => |color| @truncate(color >> 24),
+ };
+ }
+
+ pub fn r(this: Color) u8 {
+ return switch (this) {
+ .rgba => |color| @truncate(color >> 24),
+ .argb => |color| @truncate(color >> 16),
+ };
+ }
+
+ pub fn g(this: Color) u8 {
+ return switch (this) {
+ .rgba => |color| @truncate(color >> 16),
+ .argb => |color| @truncate(color >> 8),
+ };
+ }
+
+ fn shift(this: Color, comptime p: @TypeOf(.enum_literal)) u5 {
+ return switch (this) {
+ .rgba => switch (p) {
+ .r => 24,
+ .g => 16,
+ .b => 8,
+ .a => 0,
+ else => @compileError("must be r, g, b, or a"),
+ },
+ .argb => switch (p) {
+ .a => 24,
+ .r => 16,
+ .g => 8,
+ .b => 0,
+ else => @compileError("must be r, g, b, or a"),
+ },
+ };
+ }
+
+ pub fn b(this: Color) u8 {
+ return switch (this) {
+ .rgba => |color| @truncate(color >> 8),
+ .argb => |color| @truncate(color),
+ };
+ }
+
+ pub fn get(this: Color) u32 {
+ return switch (this) {
+ inline else => |color| color,
+ };
+ }
+
+ pub fn rgba(color: u32) Color {
+ return .{ .rgba = color };
+ }
+
+ pub fn argb(color: u32) Color {
+ return .{ .argb = color };
+ }
+
+ pub fn rgb(color: u32) Color {
+ return .{ .argb = 0xff000000 | color };
+ }
+
+ pub fn fromJS(value: JSValue, global: *JSGlobalObject) ?Color {
+ if (bun.String.tryFromJS(value, global)) |str| {
+ if (str.inMapCaseInsensitive(Names)) |color| {
+ return color;
+ }
+
+ const length = str.length();
+ if (length >= 4 and str.hasPrefixComptime("#")) brk: {
+ const hex_length = length - 1;
+ if (hex_length != 3 and hex_length != 4 and hex_length != 6 and hex_length != 8) break :brk;
+ if (str.is8Bit()) {
+ var hex = str.byteSlice()[1..];
+ var hex_value: u32 = 0;
+ for (hex) |digit| {
+ if (!std.ascii.isHex(digit)) break :brk;
+ hex_value <<= 4;
+ hex_value |= if (digit < 'A') digit - '0' else (digit - 'A' + 10) & 0xf;
+ }
+ switch (hex_length) {
+ 3 => {
+ std.debug.print("TODO: hex colors with 3 digits\n", .{});
+ break :brk;
+ },
+ 4 => {
+ std.debug.print("TODO: hex colors with 4 digits\n", .{});
+ break :brk;
+ },
+ 6 => return rgb(hex_value),
+ 8 => return rgba(hex_value),
+ else => unreachable,
+ }
+ }
+ }
+
+ if (str.hasPrefixComptime("rgba(")) {
+ // parse rgba color
+ }
+
+ // assume never in quirks mode
+ // if (str.hasPrefixComptime("rgb(")) {}
+
+ }
+
+ return null;
+ }
+
+ pub fn maybeRGB(comptime T: type, characters: []T) bool {
+ _ = characters;
+ }
+
+ pub const Names = bun.ComptimeStringMap(Color, .{
+ .{ "aliceblue", argb(0xfff0f8ff) },
+ .{ "alpha", argb(0x00000000) },
+ .{ "antiquewhite", argb(0xfffaebd7) },
+ .{ "aqua", argb(0xff00ffff) },
+ .{ "aquamarine", argb(0xff7fffd4) },
+ .{ "azure", argb(0xfff0ffff) },
+ .{ "beige", argb(0xfff5f5dc) },
+ .{ "bisque", argb(0xffffe4c4) },
+ .{ "black", argb(0xff000000) },
+ .{ "blanchedalmond", argb(0xffffebcd) },
+ .{ "blue", argb(0xff0000ff) },
+ .{ "blueviolet", argb(0xff8a2be2) },
+ .{ "brown", argb(0xffa52a2a) },
+ .{ "burlywood", argb(0xffdeb887) },
+ .{ "cadetblue", argb(0xff5f9ea0) },
+ .{ "chartreuse", argb(0xff7fff00) },
+ .{ "chocolate", argb(0xffd2691e) },
+ .{ "coral", argb(0xffff7f50) },
+ .{ "cornflowerblue", argb(0xff6495ed) },
+ .{ "cornsilk", argb(0xfffff8dc) },
+ .{ "crimson", argb(0xffdc143c) },
+ .{ "cyan", argb(0xff00ffff) },
+ .{ "darkblue", argb(0xff00008b) },
+ .{ "darkcyan", argb(0xff008b8b) },
+ .{ "darkgoldenrod", argb(0xffb8860b) },
+ .{ "darkgray", argb(0xffa9a9a9) },
+ .{ "darkgrey", argb(0xffa9a9a9) },
+ .{ "darkgreen", argb(0xff006400) },
+ .{ "darkkhaki", argb(0xffbdb76b) },
+ .{ "darkmagenta", argb(0xff8b008b) },
+ .{ "darkolivegreen", argb(0xff556b2f) },
+ .{ "darkorange", argb(0xffff8c00) },
+ .{ "darkorchid", argb(0xff9932cc) },
+ .{ "darkred", argb(0xff8b0000) },
+ .{ "darksalmon", argb(0xffe9967a) },
+ .{ "darkseagreen", argb(0xff8fbc8f) },
+ .{ "darkslateblue", argb(0xff483d8b) },
+ .{ "darkslategray", argb(0xff2f4f4f) },
+ .{ "darkslategrey", argb(0xff2f4f4f) },
+ .{ "darkturquoise", argb(0xff00ced1) },
+ .{ "darkviolet", argb(0xff9400d3) },
+ .{ "deeppink", argb(0xffff1493) },
+ .{ "deepskyblue", argb(0xff00bfff) },
+ .{ "dimgray", argb(0xff696969) },
+ .{ "dimgrey", argb(0xff696969) },
+ .{ "dodgerblue", argb(0xff1e90ff) },
+ .{ "firebrick", argb(0xffb22222) },
+ .{ "floralwhite", argb(0xfffffaf0) },
+ .{ "forestgreen", argb(0xff228b22) },
+ .{ "fuchsia", argb(0xffff00ff) },
+ .{ "gainsboro", argb(0xffdcdcdc) },
+ .{ "ghostwhite", argb(0xfff8f8ff) },
+ .{ "gold", argb(0xffffd700) },
+ .{ "goldenrod", argb(0xffdaa520) },
+ .{ "gray", argb(0xff808080) },
+ .{ "grey", argb(0xff808080) },
+ .{ "green", argb(0xff008000) },
+ .{ "greenyellow", argb(0xffadff2f) },
+ .{ "honeydew", argb(0xfff0fff0) },
+ .{ "hotpink", argb(0xffff69b4) },
+ .{ "indianred", argb(0xffcd5c5c) },
+ .{ "indigo", argb(0xff4b0082) },
+ .{ "ivory", argb(0xfffffff0) },
+ .{ "khaki", argb(0xfff0e68c) },
+ .{ "lavender", argb(0xffe6e6fa) },
+ .{ "lavenderblush", argb(0xfffff0f5) },
+ .{ "lawngreen", argb(0xff7cfc00) },
+ .{ "lemonchiffon", argb(0xfffffacd) },
+ .{ "lightblue", argb(0xffadd8e6) },
+ .{ "lightcoral", argb(0xfff08080) },
+ .{ "lightcyan", argb(0xffe0ffff) },
+ .{ "lightgoldenrodyellow", argb(0xfffafad2) },
+ .{ "lightgray", argb(0xffd3d3d3) },
+ .{ "lightgrey", argb(0xffd3d3d3) },
+ .{ "lightgreen", argb(0xff90ee90) },
+ .{ "lightpink", argb(0xffffb6c1) },
+ .{ "lightsalmon", argb(0xffffa07a) },
+ .{ "lightseagreen", argb(0xff20b2aa) },
+ .{ "lightskyblue", argb(0xff87cefa) },
+ .{ "lightslateblue", argb(0xff8470ff) },
+ .{ "lightslategray", argb(0xff778899) },
+ .{ "lightslategrey", argb(0xff778899) },
+ .{ "lightsteelblue", argb(0xffb0c4de) },
+ .{ "lightyellow", argb(0xffffffe0) },
+ .{ "lime", argb(0xff00ff00) },
+ .{ "limegreen", argb(0xff32cd32) },
+ .{ "linen", argb(0xfffaf0e6) },
+ .{ "magenta", argb(0xffff00ff) },
+ .{ "maroon", argb(0xff800000) },
+ .{ "mediumaquamarine", argb(0xff66cdaa) },
+ .{ "mediumblue", argb(0xff0000cd) },
+ .{ "mediumorchid", argb(0xffba55d3) },
+ .{ "mediumpurple", argb(0xff9370db) },
+ .{ "mediumseagreen", argb(0xff3cb371) },
+ .{ "mediumslateblue", argb(0xff7b68ee) },
+ .{ "mediumspringgreen", argb(0xff00fa9a) },
+ .{ "mediumturquoise", argb(0xff48d1cc) },
+ .{ "mediumvioletred", argb(0xffc71585) },
+ .{ "midnightblue", argb(0xff191970) },
+ .{ "mintcream", argb(0xfff5fffa) },
+ .{ "mistyrose", argb(0xffffe4e1) },
+ .{ "moccasin", argb(0xffffe4b5) },
+ .{ "navajowhite", argb(0xffffdead) },
+ .{ "navy", argb(0xff000080) },
+ .{ "oldlace", argb(0xfffdf5e6) },
+ .{ "olive", argb(0xff808000) },
+ .{ "olivedrab", argb(0xff6b8e23) },
+ .{ "orange", argb(0xffffa500) },
+ .{ "orangered", argb(0xffff4500) },
+ .{ "orchid", argb(0xffda70d6) },
+ .{ "palegoldenrod", argb(0xffeee8aa) },
+ .{ "palegreen", argb(0xff98fb98) },
+ .{ "paleturquoise", argb(0xffafeeee) },
+ .{ "palevioletred", argb(0xffdb7093) },
+ .{ "papayawhip", argb(0xffffefd5) },
+ .{ "peachpuff", argb(0xffffdab9) },
+ .{ "peru", argb(0xffcd853f) },
+ .{ "pink", argb(0xffffc0cb) },
+ .{ "plum", argb(0xffdda0dd) },
+ .{ "powderblue", argb(0xffb0e0e6) },
+ .{ "purple", argb(0xff800080) },
+ .{ "rebeccapurple", argb(0xff663399) },
+ .{ "red", argb(0xffff0000) },
+ .{ "rosybrown", argb(0xffbc8f8f) },
+ .{ "royalblue", argb(0xff4169e1) },
+ .{ "saddlebrown", argb(0xff8b4513) },
+ .{ "salmon", argb(0xfffa8072) },
+ .{ "sandybrown", argb(0xfff4a460) },
+ .{ "seagreen", argb(0xff2e8b57) },
+ .{ "seashell", argb(0xfffff5ee) },
+ .{ "sienna", argb(0xffa0522d) },
+ .{ "silver", argb(0xffc0c0c0) },
+ .{ "skyblue", argb(0xff87ceeb) },
+ .{ "slateblue", argb(0xff6a5acd) },
+ .{ "slategray", argb(0xff708090) },
+ .{ "slategrey", argb(0xff708090) },
+ .{ "snow", argb(0xfffffafa) },
+ .{ "springgreen", argb(0xff00ff7f) },
+ .{ "steelblue", argb(0xff4682b4) },
+ .{ "tan", argb(0xffd2b48c) },
+ .{ "teal", argb(0xff008080) },
+ .{ "thistle", argb(0xffd8bfd8) },
+ .{ "tomato", argb(0xffff6347) },
+ .{ "transparent", argb(0x00000000) },
+ .{ "turquoise", argb(0xff40e0d0) },
+ .{ "violet", argb(0xffee82ee) },
+ .{ "violetred", argb(0xffd02090) },
+ .{ "wheat", argb(0xfff5deb3) },
+ .{ "white", argb(0xffffffff) },
+ .{ "whitesmoke", argb(0xfff5f5f5) },
+ .{ "yellow", argb(0xffffff00) },
+ .{ "yellowgreen", argb(0xff9acd32) },
+ });
+};
+
+pub const Canvas = struct {
+ const log = Output.scoped(.Canvas, false);
+ pub usingnamespace JSC.Codegen.JSCanvas;
+
+ running: bool = true,
+ width: i32 = 640,
+ width_value: JSValue = .zero,
+ height: i32 = 480,
+ height_value: JSValue = .zero,
+ x: i32 = c.SDL_WINDOWPOS_UNDEFINED,
+ x_value: JSValue = .zero,
+ y: i32 = c.SDL_WINDOWPOS_UNDEFINED,
+ y_value: JSValue = .zero,
+
+ timer_id: ?JSValue = null,
+ _animate_callback_wrapper_value: ?JSValue = null,
+
+ previous_time: f64 = 0.0,
+
+ window: *c.SDL_Window = undefined,
+ renderer: *c.SDL_Renderer = undefined,
+
+ fps: struct {
+ pub const max_ticks = 100;
+ ticks: [max_ticks]f64 = .{0} ** max_ticks,
+ index: usize = 0,
+ sum: f64 = 0,
+
+ pub fn get(this: *@This(), tick: f64) f64 {
+ this.sum -= this.ticks[this.index];
+ this.sum += tick;
+ this.ticks[this.index] = tick;
+ this.index += 1;
+ if (this.index == max_ticks) {
+ this.index = 0;
+ }
+
+ return this.sum / @as(f64, @floatFromInt(max_ticks));
+ }
+ },
+
+ pub fn constructor(global: *JSGlobalObject, callFrame: *CallFrame) callconv(.C) ?*Canvas {
+ log("Canvas.constructor", .{});
+
+ const args = callFrame.arguments(5).slice();
+
+ var canvas = Canvas{
+ .fps = .{},
+ };
+
+ switch (args.len) {
+ 0, 1 => {},
+ else => brk: {
+ if (args[1].isInt32()) {
+ canvas.width = args[1].asInt32();
+ } else {
+ global.throw("Canvas constructor expects width to be a number", .{});
+ return null;
+ }
+
+ if (args.len == 2) break :brk;
+
+ if (args[2].isInt32()) {
+ canvas.height = args[2].asInt32();
+ } else {
+ global.throw("Canvas constructor expects height to be a number", .{});
+ return null;
+ }
+
+ if (args.len == 3) break :brk;
+
+ if (args[3].isInt32()) {
+ canvas.x = args[3].asInt32();
+ } else {
+ global.throw("Canvas constructor expects x to be a number", .{});
+ return null;
+ }
+
+ if (args.len == 4) break :brk;
+
+ if (args[4].isInt32()) {
+ canvas.y = args[4].asInt32();
+ } else {
+ global.throw("Canvas constructor expects y to be a number", .{});
+ return null;
+ }
+ },
+ }
+
+ initializeSDL.call();
+
+ if (c.SDL_CreateWindow(
+ "bun bun bun",
+ canvas.x,
+ canvas.y,
+ canvas.width,
+ canvas.height,
+ c.SDL_WINDOW_SHOWN,
+ )) |window| {
+ canvas.window = window;
+ } else {
+ global.throw("Failed to create window", .{});
+ return null;
+ }
+
+ if (canvas.x == c.SDL_WINDOWPOS_UNDEFINED or canvas.y == c.SDL_WINDOWPOS_UNDEFINED) {
+ c.SDL_GetWindowPosition(canvas.window, &canvas.x, &canvas.y);
+ }
+
+ canvas.width_value = JSValue.jsNumber(canvas.width);
+ canvas.height_value = JSValue.jsNumber(canvas.height);
+ canvas.x_value = JSValue.jsNumber(canvas.x);
+ canvas.y_value = JSValue.jsNumber(canvas.y);
+
+ var _canvas = bun.default_allocator.create(Canvas) catch unreachable;
+ _canvas.* = canvas;
+
+ return _canvas;
+ }
+
+ fn animateCallbackWrapper(global: *JSGlobalObject, callFrame: *CallFrame) callconv(.C) JSValue {
+ const args = callFrame.arguments(2).slice();
+ const canvas = Canvas.fromJS(args[0]) orelse {
+ global.throw("Failed to get canvas from value", .{});
+ return .undefined;
+ };
+ const callback = args[1];
+
+ var event: c.SDL_Event = undefined;
+ while (c.SDL_PollEvent(&event) != 0) {
+ switch (event.type) {
+ c.SDL_QUIT => canvas.running = false,
+ c.SDL_KEYDOWN => {
+ // for debugging
+ if (event.key.keysym.sym == c.SDLK_ESCAPE) {
+ canvas.running = false;
+ }
+ },
+ else => {},
+ }
+ }
+
+ const current_time: f64 = @floatFromInt(global.bunVM().origin_timer.read());
+ const fps = canvas.fps.get(current_time - canvas.previous_time);
+ const delta = (current_time - canvas.previous_time) / @as(f64, 1000000000.0);
+ canvas.previous_time = current_time;
+
+ var buf: [1000:0]u8 = undefined;
+ c.SDL_SetWindowTitle(canvas.window, std.fmt.bufPrintZ(&buf, "fps: {d}", .{fps}) catch unreachable);
+
+ const res = callback.call(global, &[_]JSValue{JSValue.jsNumber(delta)});
+ if (res.isException(global.vm())) {
+ const err = res.toError() orelse return .zero;
+ global.throwValue(err);
+ return .zero;
+ }
+
+ // queue up the next animation frame callback if needed
+ if (canvas.running) {
+ canvas.timer_id = Timer.setImmediate(
+ global,
+ canvas.getAnimateCallbackWrapper(global),
+ JSC.JSArray.from(global, &[_]JSValue{ canvas.toJS(global), callback }),
+ );
+ }
+
+ c.SDL_RenderPresent(canvas.renderer);
+
+ return .undefined;
+ }
+
+ fn getAnimateCallbackWrapper(this: *Canvas, global: *JSGlobalObject) callconv(.C) JSValue {
+ return this._animate_callback_wrapper_value orelse {
+ const cb = JSC.createCallback(global, ZigString.static("animateCallbackWrapper"), 2, animateCallbackWrapper);
+ this._animate_callback_wrapper_value = cb;
+ return this._animate_callback_wrapper_value.?;
+ };
+ }
+
+ pub fn animate(this: *Canvas, global: *JSGlobalObject, callFrame: *CallFrame) callconv(.C) JSValue {
+ log("Canvas.animate", .{});
+
+ const args = callFrame.arguments(1).slice();
+ if (args.len == 0 or !args[0].isCallable(global.vm())) {
+ global.throw("Expected first argument to be a callback", .{});
+ return .zero;
+ }
+
+ const callback = args[0];
+
+ this.previous_time = @floatFromInt(global.bunVM().origin_timer.read());
+
+ this.timer_id = Timer.setImmediate(
+ global,
+ this.getAnimateCallbackWrapper(global),
+ JSC.JSArray.from(global, &[_]JSValue{ this.toJS(global), callback }),
+ );
+
+ return .undefined;
+ }
+
+ pub fn close(this: *Canvas, global: *JSGlobalObject, _: *CallFrame) callconv(.C) JSValue {
+ log("Canvas.close", .{});
+
+ if (this.timer_id) |timer_id| {
+ _ = Timer.clearImmediate(global, timer_id);
+ this.timer_id = null;
+ }
+ this.running = false;
+
+ return .undefined;
+ }
+
+ pub fn getContext(this: *Canvas, global: *JSGlobalObject, callFrame: *CallFrame) callconv(.C) JSValue {
+ log("Canvas.getContext", .{});
+
+ const args = callFrame.arguments(1).slice();
+ if (args.len == 0) {
+ global.throw("getContext expects one argument, received 0", .{});
+ return .zero;
+ }
+
+ if (!args[0].isString()) {
+ global.throw("getContext expected argument to be string", .{});
+ return .zero;
+ }
+
+ const context_type_string = args[0].toBunString(global);
+
+ if (!context_type_string.eqlComptime("2d")) {
+ global.throw("getContext unsupported context type: {}", .{context_type_string});
+ return .zero;
+ }
+
+ if (c.SDL_CreateRenderer(this.window, -1, c.SDL_RENDERER_ACCELERATED)) |renderer| {
+ this.renderer = renderer;
+ } else {
+ global.throw("Failed to create renderer", .{});
+ return .zero;
+ }
+
+ if (c.SDL_SetRenderDrawBlendMode(this.renderer, c.SDL_BLENDMODE_BLEND) < 0) {
+ global.throw("Failed to set render blend mode", .{});
+ return .zero;
+ }
+
+ const context = CanvasRenderingContext2D.create(this.window, this.renderer) orelse {
+ global.throw("Failed to create 2d rendering context", .{});
+ return .zero;
+ };
+
+ return context.toJS(global);
+ }
+
+ pub fn finalize(this: *Canvas) callconv(.C) void {
+ log("Canvas.finalize", .{});
+ bun.default_allocator.destroy(this);
+ }
+
+ pub fn hasPendingActivity(this: *Canvas) callconv(.C) bool {
+ return this.timer_id != null and this.running;
+ }
+
+ pub fn getHeight(this: *Canvas, globalObject: *JSGlobalObject) callconv(.C) JSValue {
+ _ = globalObject;
+
+ return this.height_value;
+ }
+
+ pub fn setHeight(this: *Canvas, globalObject: *JSGlobalObject, value: JSValue) callconv(.C) bool {
+ _ = globalObject;
+
+ this.height_value = value;
+
+ if (value.isInt32()) {
+ this.height = value.asInt32();
+ c.SDL_SetWindowSize(this.window, this.width, this.height);
+ }
+
+ return true;
+ }
+
+ pub fn getWidth(this: *Canvas, globalObject: *JSGlobalObject) callconv(.C) JSValue {
+ _ = globalObject;
+
+ return this.width_value;
+ }
+
+ pub fn setWidth(this: *Canvas, globalObject: *JSGlobalObject, value: JSValue) callconv(.C) bool {
+ _ = globalObject;
+
+ this.width_value = value;
+
+ if (value.isInt32()) {
+ this.width = value.asInt32();
+ c.SDL_SetWindowSize(this.window, this.width, this.height);
+ }
+
+ return true;
+ }
+
+ pub fn getX(this: *Canvas, global: *JSGlobalObject) callconv(.C) JSValue {
+ _ = global;
+
+ return this.x_value;
+ }
+
+ pub fn setX(this: *Canvas, global: *JSGlobalObject, value: JSValue) callconv(.C) bool {
+ _ = global;
+
+ this.x_value = value;
+
+ if (value.isInt32()) {
+ this.x = value.toInt32();
+ c.SDL_SetWindowPosition(this.window, this.x, this.y);
+ }
+
+ return true;
+ }
+
+ pub fn getY(this: *Canvas, global: *JSGlobalObject) callconv(.C) JSValue {
+ _ = global;
+
+ return this.y_value;
+ }
+
+ pub fn setY(this: *Canvas, global: *JSGlobalObject, value: JSValue) callconv(.C) bool {
+ _ = global;
+
+ this.y_value = value;
+
+ if (value.isInt32()) {
+ this.y = value.toInt32();
+ c.SDL_SetWindowPosition(this.window, this.x, this.y);
+ }
+
+ return true;
+ }
+};
+
+pub const CanvasRenderingContext2D = struct {
+ const log = Output.scoped(.CanvasRenderingContext2D, false);
+ pub usingnamespace JSC.Codegen.JSCanvasRenderingContext2D;
+
+ window: *c.SDL_Window,
+ renderer: *c.SDL_Renderer,
+
+ stroke_style: JSValue = .undefined,
+ cached_stroke_color: ?Color = null,
+ fill_style: JSValue = .undefined,
+ cached_fill_color: ?Color = null,
+
+ const clear_color = Color.rgb(0xffffff);
+ const default_color = Color.rgba(0x000000ff);
+
+ pub fn create(window: *c.SDL_Window, renderer: *c.SDL_Renderer) ?*CanvasRenderingContext2D {
+ log("create", .{});
+
+ var context = bun.default_allocator.create(CanvasRenderingContext2D) catch unreachable;
+ context.* = CanvasRenderingContext2D{
+ .window = window,
+ .renderer = renderer,
+ };
+
+ return context;
+ }
+
+ pub fn constructor(global: *JSGlobalObject, callFrame: *CallFrame) callconv(.C) ?*CanvasRenderingContext2D {
+ _ = callFrame;
+ log("constructor", .{});
+ global.throw("Illegal constructor: CanvasRenderingContext2D cannot be constructed", .{});
+ return null;
+ }
+
+ pub fn getStrokeStyle(this: *CanvasRenderingContext2D, global: *JSGlobalObject) callconv(.C) JSValue {
+ _ = global;
+
+ return this.stroke_style;
+ }
+
+ pub fn setStrokeStyle(this: *CanvasRenderingContext2D, global: *JSGlobalObject, value: JSValue) callconv(.C) bool {
+ _ = global;
+ this.stroke_style = value;
+ this.cached_stroke_color = null;
+ return true;
+ }
+
+ pub fn getFillStyle(this: *CanvasRenderingContext2D, global: *JSGlobalObject) callconv(.C) JSValue {
+ _ = global;
+ return this.fill_style;
+ }
+
+ pub fn setFillStyle(this: *CanvasRenderingContext2D, global: *JSGlobalObject, value: JSValue) callconv(.C) bool {
+ _ = global;
+ this.fill_style = value;
+ this.cached_fill_color = null;
+ return true;
+ }
+
+ pub fn clearRect(this: *CanvasRenderingContext2D, global: *JSGlobalObject, callFrame: *CallFrame) callconv(.C) JSValue {
+ const args = callFrame.arguments(4).slice();
+ if (args.len < 4) {
+ global.throw("clearRect expects at least four arguments, received {d}", .{args.len});
+ return .zero;
+ }
+
+ const rect = c.SDL_FRect{
+ .x = @floatCast(args[0].asNumber()),
+ .y = @floatCast(args[1].asNumber()),
+ .w = @floatCast(args[2].asNumber()),
+ .h = @floatCast(args[3].asNumber()),
+ };
+
+ if (c.SDL_SetRenderDrawColor(this.renderer, clear_color.r(), clear_color.g(), clear_color.b(), clear_color.a()) < 0) {
+ global.throw("clearRect failed to set draw color", .{});
+ return .zero;
+ }
+
+ if (c.SDL_RenderFillRectF(this.renderer, &rect) < 0) {
+ global.throw("clearRect failed to fill rect", .{});
+ return .zero;
+ }
+
+ return .undefined;
+ }
+
+ fn getFillColor(this: *CanvasRenderingContext2D, global: *JSGlobalObject) ?Color {
+ return brk: {
+ if (this.cached_fill_color) |color| break :brk color;
+
+ if (Color.fromJS(this.fill_style, global)) |color| {
+ this.cached_fill_color = color;
+ break :brk color;
+ }
+
+ break :brk null;
+ };
+ }
+
+ fn getStrokeColor(this: *CanvasRenderingContext2D, global: *JSGlobalObject) ?Color {
+ return brk: {
+ if (this.cached_stroke_color) |color| break :brk color;
+
+ if (Color.fromJS(this.stroke_style, global)) |color| {
+ this.cached_stroke_color = color;
+ break :brk color;
+ }
+
+ break :brk null;
+ };
+ }
+
+ pub fn fillRect(this: *CanvasRenderingContext2D, global: *JSGlobalObject, callFrame: *CallFrame) callconv(.C) JSValue {
+ const args = callFrame.arguments(4).slice();
+ if (args.len < 4) {
+ global.throw("fillRect expects at least four arguments, received {d}", .{args.len});
+ return .zero;
+ }
+
+ const rect = c.SDL_FRect{
+ .x = @floatCast(args[0].asNumber()),
+ .y = @floatCast(args[1].asNumber()),
+ .w = @floatCast(args[2].asNumber()),
+ .h = @floatCast(args[3].asNumber()),
+ };
+
+ const fill_color = this.getFillColor(global) orelse default_color;
+ if (c.SDL_SetRenderDrawColor(this.renderer, fill_color.r(), fill_color.g(), fill_color.b(), fill_color.a()) < 0) {
+ global.throw("fillRect failed to set fill color", .{});
+ return .zero;
+ }
+
+ if (c.SDL_RenderFillRectF(this.renderer, &rect) < 0) {
+ global.throw("fillRect failed to fill rect", .{});
+ return .zero;
+ }
+
+ return .undefined;
+ }
+
+ pub fn strokeRect(this: *CanvasRenderingContext2D, global: *JSGlobalObject, callFrame: *CallFrame) callconv(.C) JSValue {
+ const args = callFrame.arguments(4).slice();
+ if (args.len < 4) {
+ global.throw("strokeRect expects at least four arguments, received {d}", .{args.len});
+ return .zero;
+ }
+
+ const rect = c.SDL_FRect{
+ .x = @floatCast(args[0].asNumber()),
+ .y = @floatCast(args[1].asNumber()),
+ .w = @floatCast(args[2].asNumber()),
+ .h = @floatCast(args[3].asNumber()),
+ };
+
+ const stroke_color = this.getStrokeColor(global) orelse default_color;
+ if (c.SDL_SetRenderDrawColor(this.renderer, stroke_color.r(), stroke_color.g(), stroke_color.b(), stroke_color.a()) < 0) {
+ global.throw("strokeRect failed to set fill color", .{});
+ return .zero;
+ }
+
+ if (c.SDL_RenderDrawRectF(this.renderer, &rect) < 0) {
+ global.throw("strokeRect failed to fill rect", .{});
+ return .zero;
+ }
+
+ return .undefined;
+ }
+};
diff --git a/src/bun.js/bindings/BunObject+exports.h b/src/bun.js/bindings/BunObject+exports.h
index b805b90d8..ac405e9b9 100644
--- a/src/bun.js/bindings/BunObject+exports.h
+++ b/src/bun.js/bindings/BunObject+exports.h
@@ -15,6 +15,7 @@
macro(SHA512_256) \
macro(TOML) \
macro(Transpiler) \
+ macro(Canvas) \
macro(argv) \
macro(assetPrefix) \
macro(cwd) \
diff --git a/src/bun.js/bindings/BunObject.cpp b/src/bun.js/bindings/BunObject.cpp
index 9d8ce6674..2f5811349 100644
--- a/src/bun.js/bindings/BunObject.cpp
+++ b/src/bun.js/bindings/BunObject.cpp
@@ -577,6 +577,7 @@ JSC_DEFINE_HOST_FUNCTION(functionHashCode,
SHA512_256 BunObject_getter_wrap_SHA512_256 DontDelete|PropertyCallback
TOML BunObject_getter_wrap_TOML DontDelete|PropertyCallback
Transpiler BunObject_getter_wrap_Transpiler DontDelete|PropertyCallback
+ Canvas BunObject_getter_wrap_Canvas DontDelete|PropertyCallback
_Os BunObject_callback__Os DontEnum|DontDelete|Function 1
_Path BunObject_callback__Path DontEnum|DontDelete|Function 1
allocUnsafe BunObject_callback_allocUnsafe DontDelete|Function 1
diff --git a/src/bun.js/bindings/BunObject.lut.h b/src/bun.js/bindings/BunObject.lut.h
index a2aa95fda..b6d53472b 100644
--- a/src/bun.js/bindings/BunObject.lut.h
+++ b/src/bun.js/bindings/BunObject.lut.h
@@ -1,6 +1,6 @@
// File generated via `make static-hash-table` / `make cpp`
static const struct CompactHashIndex bunObjectTableIndex[269] = {
- { 75, -1 },
+ { 76, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
@@ -10,21 +10,21 @@ static const struct CompactHashIndex bunObjectTableIndex[269] = {
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 38, -1 },
+ { 39, -1 },
{ -1, -1 },
- { 44, -1 },
+ { 45, -1 },
{ -1, -1 },
{ -1, -1 },
{ 4, -1 },
{ -1, -1 },
{ 2, -1 },
- { 48, -1 },
- { 34, 261 },
+ { 49, -1 },
+ { 35, 261 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 71, -1 },
- { 79, -1 },
+ { 72, -1 },
+ { 80, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
@@ -42,19 +42,18 @@ static const struct CompactHashIndex bunObjectTableIndex[269] = {
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 60, -1 },
+ { 61, -1 },
{ -1, -1 },
{ -1, -1 },
{ 11, 258 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 45, 264 },
- { -1, -1 },
+ { 46, 264 },
{ -1, -1 },
{ -1, -1 },
- { 67, -1 },
{ -1, -1 },
+ { 68, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
@@ -62,17 +61,18 @@ static const struct CompactHashIndex bunObjectTableIndex[269] = {
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 59, -1 },
{ -1, -1 },
+ { 60, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
+ { 15, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 47, 265 },
- { 32, -1 },
+ { 48, 265 },
+ { 33, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
@@ -81,20 +81,20 @@ static const struct CompactHashIndex bunObjectTableIndex[269] = {
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 70, -1 },
- { 65, -1 },
+ { 71, -1 },
+ { 66, -1 },
{ -1, -1 },
{ 14, -1 },
- { 23, -1 },
+ { 24, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 43, -1 },
+ { 44, -1 },
{ -1, -1 },
- { 52, -1 },
+ { 53, -1 },
{ -1, -1 },
{ -1, -1 },
- { 37, -1 },
+ { 38, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
@@ -109,20 +109,20 @@ static const struct CompactHashIndex bunObjectTableIndex[269] = {
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 64, -1 },
+ { 65, -1 },
{ -1, -1 },
- { 20, 256 },
+ { 21, 256 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 73, -1 },
+ { 74, -1 },
{ -1, -1 },
- { 77, -1 },
+ { 78, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 74, -1 },
- { 22, 259 },
+ { 75, -1 },
+ { 23, 259 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
@@ -130,30 +130,30 @@ static const struct CompactHashIndex bunObjectTableIndex[269] = {
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 53, -1 },
+ { 54, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 40, -1 },
+ { 41, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 29, -1 },
+ { 30, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 63, -1 },
- { 35, 266 },
+ { 64, -1 },
+ { 36, 266 },
{ -1, -1 },
- { 33, -1 },
- { 54, -1 },
+ { 34, -1 },
+ { 55, -1 },
{ -1, -1 },
- { 26, -1 },
- { 15, -1 },
+ { 27, -1 },
+ { 16, -1 },
{ -1, -1 },
{ -1, -1 },
{ 6, -1 },
@@ -161,7 +161,7 @@ static const struct CompactHashIndex bunObjectTableIndex[269] = {
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 18, -1 },
+ { 19, -1 },
{ -1, -1 },
{ -1, -1 },
{ 0, -1 },
@@ -173,66 +173,66 @@ static const struct CompactHashIndex bunObjectTableIndex[269] = {
{ -1, -1 },
{ -1, -1 },
{ 5, -1 },
- { 16, -1 },
+ { 17, -1 },
{ -1, -1 },
{ -1, -1 },
- { 24, -1 },
+ { 25, -1 },
{ 1, -1 },
- { 31, 267 },
+ { 32, 267 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 46, -1 },
+ { 47, -1 },
{ -1, -1 },
{ -1, -1 },
{ 8, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 69, -1 },
+ { 70, -1 },
{ -1, -1 },
- { 76, 268 },
+ { 77, 268 },
{ -1, -1 },
- { 36, -1 },
+ { 37, -1 },
{ -1, -1 },
{ -1, -1 },
- { 39, 260 },
+ { 40, 260 },
{ -1, -1 },
{ -1, -1 },
{ 7, 262 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 66, -1 },
+ { 67, -1 },
{ 3, -1 },
{ -1, -1 },
- { 61, -1 },
+ { 62, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 28, -1 },
- { 19, 257 },
+ { 29, -1 },
+ { 20, 257 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
{ 9, -1 },
{ -1, -1 },
{ -1, -1 },
- { 49, -1 },
+ { 50, -1 },
{ 12, -1 },
{ -1, -1 },
- { 80, -1 },
+ { 81, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 17, -1 },
+ { 18, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 27, -1 },
+ { 28, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
@@ -240,10 +240,10 @@ static const struct CompactHashIndex bunObjectTableIndex[269] = {
{ 13, -1 },
{ -1, -1 },
{ -1, -1 },
- { 25, -1 },
+ { 26, -1 },
{ -1, -1 },
{ -1, -1 },
- { 42, 263 },
+ { 43, 263 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
@@ -256,22 +256,22 @@ static const struct CompactHashIndex bunObjectTableIndex[269] = {
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
- { 21, -1 },
- { 30, -1 },
- { 41, -1 },
- { 50, -1 },
+ { 22, -1 },
+ { 31, -1 },
+ { 42, -1 },
{ 51, -1 },
- { 55, -1 },
+ { 52, -1 },
{ 56, -1 },
{ 57, -1 },
{ 58, -1 },
- { 62, -1 },
- { 68, -1 },
- { 72, -1 },
- { 78, -1 },
+ { 59, -1 },
+ { 63, -1 },
+ { 69, -1 },
+ { 73, -1 },
+ { 79, -1 },
};
-static const struct HashTableValue bunObjectTableValues[81] = {
+static const struct HashTableValue bunObjectTableValues[82] = {
{ "ArrayBufferSink"_s, static_cast<unsigned>(PropertyAttribute::DontDelete|PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, BunObject_getter_wrap_ArrayBufferSink } },
{ "CryptoHasher"_s, static_cast<unsigned>(PropertyAttribute::DontDelete|PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, BunObject_getter_wrap_CryptoHasher } },
{ "DO_NOT_USE_OR_YOU_WILL_BE_FIRED_mimalloc_dump"_s, static_cast<unsigned>(PropertyAttribute::DontEnum|PropertyAttribute::DontDelete|PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, BunObject_callback_DO_NOT_USE_OR_YOU_WILL_BE_FIRED_mimalloc_dump, 1 } },
@@ -287,6 +287,7 @@ static const struct HashTableValue bunObjectTableValues[81] = {
{ "SHA512_256"_s, static_cast<unsigned>(PropertyAttribute::DontDelete|PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, BunObject_getter_wrap_SHA512_256 } },
{ "TOML"_s, static_cast<unsigned>(PropertyAttribute::DontDelete|PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, BunObject_getter_wrap_TOML } },
{ "Transpiler"_s, static_cast<unsigned>(PropertyAttribute::DontDelete|PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, BunObject_getter_wrap_Transpiler } },
+ { "Canvas"_s, static_cast<unsigned>(PropertyAttribute::DontDelete|PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, BunObject_getter_wrap_Canvas } },
{ "_Os"_s, static_cast<unsigned>(PropertyAttribute::DontEnum|PropertyAttribute::DontDelete|PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, BunObject_callback__Os, 1 } },
{ "_Path"_s, static_cast<unsigned>(PropertyAttribute::DontEnum|PropertyAttribute::DontDelete|PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, BunObject_callback__Path, 1 } },
{ "allocUnsafe"_s, static_cast<unsigned>(PropertyAttribute::DontDelete|PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, BunObject_callback_allocUnsafe, 1 } },
@@ -356,4 +357,4 @@ static const struct HashTableValue bunObjectTableValues[81] = {
};
static const struct HashTable bunObjectTable =
- { 81, 255, false, nullptr, bunObjectTableValues, bunObjectTableIndex };
+ { 82, 255, false, nullptr, bunObjectTableValues, bunObjectTableIndex };
diff --git a/src/bun.js/bindings/ZigGeneratedClasses+DOMClientIsoSubspaces.h b/src/bun.js/bindings/ZigGeneratedClasses+DOMClientIsoSubspaces.h
index cef5c512a..9aff90e18 100644
--- a/src/bun.js/bindings/ZigGeneratedClasses+DOMClientIsoSubspaces.h
+++ b/src/bun.js/bindings/ZigGeneratedClasses+DOMClientIsoSubspaces.h
@@ -3,7 +3,9 @@ std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForBigIntStats;
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForBigIntStatsConstructor;std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForBlob;
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForBlobConstructor;std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForBuildArtifact;
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForBuildMessage;
-std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForBuildMessageConstructor;std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForComment;
+std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForBuildMessageConstructor;std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForCanvas;
+std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForCanvasConstructor;std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForCanvasRenderingContext2D;
+std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForCanvasRenderingContext2DConstructor;std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForComment;
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForCrypto;
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForCryptoConstructor;std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForCryptoHasher;
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForCryptoHasherConstructor;std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForDebugHTTPSServer;
diff --git a/src/bun.js/bindings/ZigGeneratedClasses+DOMIsoSubspaces.h b/src/bun.js/bindings/ZigGeneratedClasses+DOMIsoSubspaces.h
index d06451eda..457aa4120 100644
--- a/src/bun.js/bindings/ZigGeneratedClasses+DOMIsoSubspaces.h
+++ b/src/bun.js/bindings/ZigGeneratedClasses+DOMIsoSubspaces.h
@@ -3,7 +3,9 @@ std::unique_ptr<IsoSubspace> m_subspaceForBigIntStats;
std::unique_ptr<IsoSubspace> m_subspaceForBigIntStatsConstructor;std::unique_ptr<IsoSubspace> m_subspaceForBlob;
std::unique_ptr<IsoSubspace> m_subspaceForBlobConstructor;std::unique_ptr<IsoSubspace> m_subspaceForBuildArtifact;
std::unique_ptr<IsoSubspace> m_subspaceForBuildMessage;
-std::unique_ptr<IsoSubspace> m_subspaceForBuildMessageConstructor;std::unique_ptr<IsoSubspace> m_subspaceForComment;
+std::unique_ptr<IsoSubspace> m_subspaceForBuildMessageConstructor;std::unique_ptr<IsoSubspace> m_subspaceForCanvas;
+std::unique_ptr<IsoSubspace> m_subspaceForCanvasConstructor;std::unique_ptr<IsoSubspace> m_subspaceForCanvasRenderingContext2D;
+std::unique_ptr<IsoSubspace> m_subspaceForCanvasRenderingContext2DConstructor;std::unique_ptr<IsoSubspace> m_subspaceForComment;
std::unique_ptr<IsoSubspace> m_subspaceForCrypto;
std::unique_ptr<IsoSubspace> m_subspaceForCryptoConstructor;std::unique_ptr<IsoSubspace> m_subspaceForCryptoHasher;
std::unique_ptr<IsoSubspace> m_subspaceForCryptoHasherConstructor;std::unique_ptr<IsoSubspace> m_subspaceForDebugHTTPSServer;
diff --git a/src/bun.js/bindings/ZigGeneratedClasses+lazyStructureHeader.h b/src/bun.js/bindings/ZigGeneratedClasses+lazyStructureHeader.h
index 381378262..7a7245689 100644
--- a/src/bun.js/bindings/ZigGeneratedClasses+lazyStructureHeader.h
+++ b/src/bun.js/bindings/ZigGeneratedClasses+lazyStructureHeader.h
@@ -18,6 +18,14 @@ JSC::Structure* JSBuildMessageStructure() { return m_JSBuildMessage.getInitializ
JSC::JSObject* JSBuildMessageConstructor() { return m_JSBuildMessage.constructorInitializedOnMainThread(this); }
JSC::JSValue JSBuildMessagePrototype() { return m_JSBuildMessage.prototypeInitializedOnMainThread(this); }
JSC::LazyClassStructure m_JSBuildMessage;
+JSC::Structure* JSCanvasStructure() { return m_JSCanvas.getInitializedOnMainThread(this); }
+ JSC::JSObject* JSCanvasConstructor() { return m_JSCanvas.constructorInitializedOnMainThread(this); }
+ JSC::JSValue JSCanvasPrototype() { return m_JSCanvas.prototypeInitializedOnMainThread(this); }
+ JSC::LazyClassStructure m_JSCanvas;
+JSC::Structure* JSCanvasRenderingContext2DStructure() { return m_JSCanvasRenderingContext2D.getInitializedOnMainThread(this); }
+ JSC::JSObject* JSCanvasRenderingContext2DConstructor() { return m_JSCanvasRenderingContext2D.constructorInitializedOnMainThread(this); }
+ JSC::JSValue JSCanvasRenderingContext2DPrototype() { return m_JSCanvasRenderingContext2D.prototypeInitializedOnMainThread(this); }
+ JSC::LazyClassStructure m_JSCanvasRenderingContext2D;
JSC::Structure* JSCommentStructure() { return m_JSComment.getInitializedOnMainThread(this); }
JSC::JSObject* JSCommentConstructor() { return m_JSComment.constructorInitializedOnMainThread(this); }
JSC::JSValue JSCommentPrototype() { return m_JSComment.prototypeInitializedOnMainThread(this); }
diff --git a/src/bun.js/bindings/ZigGeneratedClasses+lazyStructureImpl.h b/src/bun.js/bindings/ZigGeneratedClasses+lazyStructureImpl.h
index 84d3df7a0..d4c4a8574 100644
--- a/src/bun.js/bindings/ZigGeneratedClasses+lazyStructureImpl.h
+++ b/src/bun.js/bindings/ZigGeneratedClasses+lazyStructureImpl.h
@@ -29,6 +29,18 @@ ALWAYS_INLINE void GlobalObject::initGeneratedLazyClasses() {
init.setStructure(WebCore::JSBuildMessage::createStructure(init.vm, init.global, init.prototype));
init.setConstructor(WebCore::JSBuildMessage::createConstructor(init.vm, init.global, init.prototype));
});
+ m_JSCanvas.initLater(
+ [](LazyClassStructure::Initializer& init) {
+ init.setPrototype(WebCore::JSCanvas::createPrototype(init.vm, reinterpret_cast<Zig::GlobalObject*>(init.global)));
+ init.setStructure(WebCore::JSCanvas::createStructure(init.vm, init.global, init.prototype));
+ init.setConstructor(WebCore::JSCanvas::createConstructor(init.vm, init.global, init.prototype));
+ });
+ m_JSCanvasRenderingContext2D.initLater(
+ [](LazyClassStructure::Initializer& init) {
+ init.setPrototype(WebCore::JSCanvasRenderingContext2D::createPrototype(init.vm, reinterpret_cast<Zig::GlobalObject*>(init.global)));
+ init.setStructure(WebCore::JSCanvasRenderingContext2D::createStructure(init.vm, init.global, init.prototype));
+ init.setConstructor(WebCore::JSCanvasRenderingContext2D::createConstructor(init.vm, init.global, init.prototype));
+ });
m_JSComment.initLater(
[](LazyClassStructure::Initializer& init) {
init.setPrototype(WebCore::JSComment::createPrototype(init.vm, reinterpret_cast<Zig::GlobalObject*>(init.global)));
@@ -314,6 +326,8 @@ void GlobalObject::visitGeneratedLazyClasses(GlobalObject *thisObject, Visitor&
thisObject->m_JSBlob.visit(visitor);
thisObject->m_JSBuildArtifact.visit(visitor);
thisObject->m_JSBuildMessage.visit(visitor);
+ thisObject->m_JSCanvas.visit(visitor);
+ thisObject->m_JSCanvasRenderingContext2D.visit(visitor);
thisObject->m_JSComment.visit(visitor);
thisObject->m_JSCrypto.visit(visitor);
thisObject->m_JSCryptoHasher.visit(visitor);
diff --git a/src/bun.js/bindings/ZigGeneratedClasses.cpp b/src/bun.js/bindings/ZigGeneratedClasses.cpp
index 6e3a2e1e5..ea4ec2cb2 100644
--- a/src/bun.js/bindings/ZigGeneratedClasses.cpp
+++ b/src/bun.js/bindings/ZigGeneratedClasses.cpp
@@ -2935,6 +2935,898 @@ void JSBuildMessage::visitOutputConstraintsImpl(JSCell* cell, Visitor& visitor)
}
DEFINE_VISIT_OUTPUT_CONSTRAINTS(JSBuildMessage);
+class JSCanvasPrototype final : public JSC::JSNonFinalObject {
+public:
+ using Base = JSC::JSNonFinalObject;
+
+ static JSCanvasPrototype* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure)
+ {
+ JSCanvasPrototype* ptr = new (NotNull, JSC::allocateCell<JSCanvasPrototype>(vm)) JSCanvasPrototype(vm, globalObject, structure);
+ ptr->finishCreation(vm, globalObject);
+ return ptr;
+ }
+
+ DECLARE_INFO;
+ template<typename CellType, JSC::SubspaceAccess>
+ static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
+ {
+ return &vm.plainObjectSpace();
+ }
+ static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
+ {
+ return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
+ }
+
+private:
+ JSCanvasPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure)
+ : Base(vm, structure)
+ {
+ }
+
+ void finishCreation(JSC::VM&, JSC::JSGlobalObject*);
+};
+
+class JSCanvasConstructor final : public JSC::InternalFunction {
+public:
+ using Base = JSC::InternalFunction;
+ static JSCanvasConstructor* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSCanvasPrototype* prototype);
+
+ static constexpr unsigned StructureFlags = Base::StructureFlags;
+ static constexpr bool needsDestruction = false;
+
+ static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
+ {
+ return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info());
+ }
+
+ template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
+ {
+ if constexpr (mode == JSC::SubspaceAccess::Concurrently)
+ return nullptr;
+ return WebCore::subspaceForImpl<JSCanvasConstructor, WebCore::UseCustomHeapCellType::No>(
+ vm,
+ [](auto& spaces) { return spaces.m_clientSubspaceForCanvasConstructor.get(); },
+ [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForCanvasConstructor = std::forward<decltype(space)>(space); },
+ [](auto& spaces) { return spaces.m_subspaceForCanvasConstructor.get(); },
+ [](auto& spaces, auto&& space) { spaces.m_subspaceForCanvasConstructor = std::forward<decltype(space)>(space); });
+ }
+
+ void initializeProperties(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSCanvasPrototype* prototype);
+
+ // Must be defined for each specialization class.
+ static JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES construct(JSC::JSGlobalObject*, JSC::CallFrame*);
+
+ DECLARE_EXPORT_INFO;
+
+private:
+ JSCanvasConstructor(JSC::VM& vm, JSC::Structure* structure);
+ void finishCreation(JSC::VM&, JSC::JSGlobalObject* globalObject, JSCanvasPrototype* prototype);
+};
+
+extern "C" void* CanvasClass__construct(JSC::JSGlobalObject*, JSC::CallFrame*);
+JSC_DECLARE_CUSTOM_GETTER(jsCanvasConstructor);
+
+extern "C" void CanvasClass__finalize(void*);
+
+extern "C" EncodedJSValue CanvasPrototype__animate(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame);
+JSC_DECLARE_HOST_FUNCTION(CanvasPrototype__animateCallback);
+
+extern "C" EncodedJSValue CanvasPrototype__close(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame);
+JSC_DECLARE_HOST_FUNCTION(CanvasPrototype__closeCallback);
+
+extern "C" EncodedJSValue CanvasPrototype__getContext(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame);
+JSC_DECLARE_HOST_FUNCTION(CanvasPrototype__getContextCallback);
+
+extern "C" JSC::EncodedJSValue CanvasPrototype__getHeight(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject);
+JSC_DECLARE_CUSTOM_GETTER(CanvasPrototype__heightGetterWrap);
+
+extern "C" bool CanvasPrototype__setHeight(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::EncodedJSValue value);
+JSC_DECLARE_CUSTOM_SETTER(CanvasPrototype__heightSetterWrap);
+
+extern "C" JSC::EncodedJSValue CanvasPrototype__getWidth(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject);
+JSC_DECLARE_CUSTOM_GETTER(CanvasPrototype__widthGetterWrap);
+
+extern "C" bool CanvasPrototype__setWidth(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::EncodedJSValue value);
+JSC_DECLARE_CUSTOM_SETTER(CanvasPrototype__widthSetterWrap);
+
+extern "C" JSC::EncodedJSValue CanvasPrototype__getX(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject);
+JSC_DECLARE_CUSTOM_GETTER(CanvasPrototype__xGetterWrap);
+
+extern "C" bool CanvasPrototype__setX(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::EncodedJSValue value);
+JSC_DECLARE_CUSTOM_SETTER(CanvasPrototype__xSetterWrap);
+
+extern "C" JSC::EncodedJSValue CanvasPrototype__getY(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject);
+JSC_DECLARE_CUSTOM_GETTER(CanvasPrototype__yGetterWrap);
+
+extern "C" bool CanvasPrototype__setY(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::EncodedJSValue value);
+JSC_DECLARE_CUSTOM_SETTER(CanvasPrototype__ySetterWrap);
+
+STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSCanvasPrototype, JSCanvasPrototype::Base);
+
+static const HashTableValue JSCanvasPrototypeTableValues[] = {
+ { "animate"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, CanvasPrototype__animateCallback, 1 } },
+ { "close"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, CanvasPrototype__closeCallback, 0 } },
+ { "getContext"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, CanvasPrototype__getContextCallback, 1 } },
+ { "height"_s, static_cast<unsigned>(JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, CanvasPrototype__heightGetterWrap, CanvasPrototype__heightSetterWrap } },
+ { "width"_s, static_cast<unsigned>(JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, CanvasPrototype__widthGetterWrap, CanvasPrototype__widthSetterWrap } },
+ { "x"_s, static_cast<unsigned>(JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, CanvasPrototype__xGetterWrap, CanvasPrototype__xSetterWrap } },
+ { "y"_s, static_cast<unsigned>(JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, CanvasPrototype__yGetterWrap, CanvasPrototype__ySetterWrap } }
+};
+
+const ClassInfo JSCanvasPrototype::s_info = { "Canvas"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSCanvasPrototype) };
+
+JSC_DEFINE_CUSTOM_GETTER(jsCanvasConstructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName))
+{
+ VM& vm = JSC::getVM(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ auto* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject);
+ auto* prototype = jsDynamicCast<JSCanvasPrototype*>(JSValue::decode(thisValue));
+
+ if (UNLIKELY(!prototype))
+ return throwVMTypeError(lexicalGlobalObject, throwScope, "Cannot get constructor for Canvas"_s);
+ return JSValue::encode(globalObject->JSCanvasConstructor());
+}
+
+JSC_DEFINE_HOST_FUNCTION(CanvasPrototype__animateCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
+{
+ auto& vm = lexicalGlobalObject->vm();
+
+ JSCanvas* thisObject = jsDynamicCast<JSCanvas*>(callFrame->thisValue());
+
+ if (UNLIKELY(!thisObject)) {
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ throwVMTypeError(lexicalGlobalObject, throwScope, "Expected 'this' to be instanceof Canvas"_s);
+ return JSValue::encode({});
+ }
+
+ JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
+
+#ifdef BUN_DEBUG
+ /** View the file name of the JS file that called this function
+ * from a debugger */
+ SourceOrigin sourceOrigin = callFrame->callerSourceOrigin(vm);
+ const char* fileName = sourceOrigin.string().utf8().data();
+ static const char* lastFileName = nullptr;
+ if (lastFileName != fileName) {
+ lastFileName = fileName;
+ }
+#endif
+
+ return CanvasPrototype__animate(thisObject->wrapped(), lexicalGlobalObject, callFrame);
+}
+
+JSC_DEFINE_HOST_FUNCTION(CanvasPrototype__closeCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
+{
+ auto& vm = lexicalGlobalObject->vm();
+
+ JSCanvas* thisObject = jsDynamicCast<JSCanvas*>(callFrame->thisValue());
+
+ if (UNLIKELY(!thisObject)) {
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ throwVMTypeError(lexicalGlobalObject, throwScope, "Expected 'this' to be instanceof Canvas"_s);
+ return JSValue::encode({});
+ }
+
+ JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
+
+#ifdef BUN_DEBUG
+ /** View the file name of the JS file that called this function
+ * from a debugger */
+ SourceOrigin sourceOrigin = callFrame->callerSourceOrigin(vm);
+ const char* fileName = sourceOrigin.string().utf8().data();
+ static const char* lastFileName = nullptr;
+ if (lastFileName != fileName) {
+ lastFileName = fileName;
+ }
+#endif
+
+ return CanvasPrototype__close(thisObject->wrapped(), lexicalGlobalObject, callFrame);
+}
+
+JSC_DEFINE_HOST_FUNCTION(CanvasPrototype__getContextCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
+{
+ auto& vm = lexicalGlobalObject->vm();
+
+ JSCanvas* thisObject = jsDynamicCast<JSCanvas*>(callFrame->thisValue());
+
+ if (UNLIKELY(!thisObject)) {
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ throwVMTypeError(lexicalGlobalObject, throwScope, "Expected 'this' to be instanceof Canvas"_s);
+ return JSValue::encode({});
+ }
+
+ JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
+
+#ifdef BUN_DEBUG
+ /** View the file name of the JS file that called this function
+ * from a debugger */
+ SourceOrigin sourceOrigin = callFrame->callerSourceOrigin(vm);
+ const char* fileName = sourceOrigin.string().utf8().data();
+ static const char* lastFileName = nullptr;
+ if (lastFileName != fileName) {
+ lastFileName = fileName;
+ }
+#endif
+
+ return CanvasPrototype__getContext(thisObject->wrapped(), lexicalGlobalObject, callFrame);
+}
+
+JSC_DEFINE_CUSTOM_GETTER(CanvasPrototype__heightGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName))
+{
+ auto& vm = lexicalGlobalObject->vm();
+ Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ JSCanvas* thisObject = jsCast<JSCanvas*>(JSValue::decode(thisValue));
+ JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
+ JSC::EncodedJSValue result = CanvasPrototype__getHeight(thisObject->wrapped(), globalObject);
+ RETURN_IF_EXCEPTION(throwScope, {});
+ RELEASE_AND_RETURN(throwScope, result);
+}
+
+JSC_DEFINE_CUSTOM_SETTER(CanvasPrototype__heightSetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, EncodedJSValue encodedValue, PropertyName attributeName))
+{
+ auto& vm = lexicalGlobalObject->vm();
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ JSCanvas* thisObject = jsCast<JSCanvas*>(JSValue::decode(thisValue));
+ JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
+ auto result = CanvasPrototype__setHeight(thisObject->wrapped(), lexicalGlobalObject, encodedValue);
+
+ RELEASE_AND_RETURN(throwScope, result);
+}
+
+JSC_DEFINE_CUSTOM_GETTER(CanvasPrototype__widthGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName))
+{
+ auto& vm = lexicalGlobalObject->vm();
+ Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ JSCanvas* thisObject = jsCast<JSCanvas*>(JSValue::decode(thisValue));
+ JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
+ JSC::EncodedJSValue result = CanvasPrototype__getWidth(thisObject->wrapped(), globalObject);
+ RETURN_IF_EXCEPTION(throwScope, {});
+ RELEASE_AND_RETURN(throwScope, result);
+}
+
+JSC_DEFINE_CUSTOM_SETTER(CanvasPrototype__widthSetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, EncodedJSValue encodedValue, PropertyName attributeName))
+{
+ auto& vm = lexicalGlobalObject->vm();
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ JSCanvas* thisObject = jsCast<JSCanvas*>(JSValue::decode(thisValue));
+ JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
+ auto result = CanvasPrototype__setWidth(thisObject->wrapped(), lexicalGlobalObject, encodedValue);
+
+ RELEASE_AND_RETURN(throwScope, result);
+}
+
+JSC_DEFINE_CUSTOM_GETTER(CanvasPrototype__xGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName))
+{
+ auto& vm = lexicalGlobalObject->vm();
+ Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ JSCanvas* thisObject = jsCast<JSCanvas*>(JSValue::decode(thisValue));
+ JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
+ JSC::EncodedJSValue result = CanvasPrototype__getX(thisObject->wrapped(), globalObject);
+ RETURN_IF_EXCEPTION(throwScope, {});
+ RELEASE_AND_RETURN(throwScope, result);
+}
+
+JSC_DEFINE_CUSTOM_SETTER(CanvasPrototype__xSetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, EncodedJSValue encodedValue, PropertyName attributeName))
+{
+ auto& vm = lexicalGlobalObject->vm();
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ JSCanvas* thisObject = jsCast<JSCanvas*>(JSValue::decode(thisValue));
+ JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
+ auto result = CanvasPrototype__setX(thisObject->wrapped(), lexicalGlobalObject, encodedValue);
+
+ RELEASE_AND_RETURN(throwScope, result);
+}
+
+JSC_DEFINE_CUSTOM_GETTER(CanvasPrototype__yGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName))
+{
+ auto& vm = lexicalGlobalObject->vm();
+ Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ JSCanvas* thisObject = jsCast<JSCanvas*>(JSValue::decode(thisValue));
+ JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
+ JSC::EncodedJSValue result = CanvasPrototype__getY(thisObject->wrapped(), globalObject);
+ RETURN_IF_EXCEPTION(throwScope, {});
+ RELEASE_AND_RETURN(throwScope, result);
+}
+
+JSC_DEFINE_CUSTOM_SETTER(CanvasPrototype__ySetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, EncodedJSValue encodedValue, PropertyName attributeName))
+{
+ auto& vm = lexicalGlobalObject->vm();
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ JSCanvas* thisObject = jsCast<JSCanvas*>(JSValue::decode(thisValue));
+ JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
+ auto result = CanvasPrototype__setY(thisObject->wrapped(), lexicalGlobalObject, encodedValue);
+
+ RELEASE_AND_RETURN(throwScope, result);
+}
+
+void JSCanvasPrototype::finishCreation(JSC::VM& vm, JSC::JSGlobalObject* globalObject)
+{
+ Base::finishCreation(vm);
+ reifyStaticProperties(vm, JSCanvas::info(), JSCanvasPrototypeTableValues, *this);
+ JSC_TO_STRING_TAG_WITHOUT_TRANSITION();
+}
+
+void JSCanvasConstructor::finishCreation(VM& vm, JSC::JSGlobalObject* globalObject, JSCanvasPrototype* prototype)
+{
+ Base::finishCreation(vm, 0, "Canvas"_s, PropertyAdditionMode::WithoutStructureTransition);
+
+ putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly);
+ ASSERT(inherits(info()));
+}
+
+JSCanvasConstructor::JSCanvasConstructor(JSC::VM& vm, JSC::Structure* structure)
+ : Base(vm, structure, construct, construct)
+{
+}
+
+JSCanvasConstructor* JSCanvasConstructor::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSCanvasPrototype* prototype)
+{
+ JSCanvasConstructor* ptr = new (NotNull, JSC::allocateCell<JSCanvasConstructor>(vm)) JSCanvasConstructor(vm, structure);
+ ptr->finishCreation(vm, globalObject, prototype);
+ return ptr;
+}
+
+JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSCanvasConstructor::construct(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame)
+{
+ Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject);
+ JSC::VM& vm = globalObject->vm();
+ JSObject* newTarget = asObject(callFrame->newTarget());
+ auto* constructor = globalObject->JSCanvasConstructor();
+ Structure* structure = globalObject->JSCanvasStructure();
+ if (constructor != newTarget) {
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ auto* functionGlobalObject = reinterpret_cast<Zig::GlobalObject*>(
+ // ShadowRealm functions belong to a different global object.
+ getFunctionRealm(globalObject, newTarget));
+ RETURN_IF_EXCEPTION(scope, {});
+ structure = InternalFunction::createSubclassStructure(
+ globalObject,
+ newTarget,
+ functionGlobalObject->JSCanvasStructure());
+ }
+
+ void* ptr = CanvasClass__construct(globalObject, callFrame);
+
+ if (UNLIKELY(!ptr)) {
+ return JSValue::encode(JSC::jsUndefined());
+ }
+
+ JSCanvas* instance = JSCanvas::create(vm, globalObject, structure, ptr);
+
+ return JSValue::encode(instance);
+}
+
+void JSCanvasConstructor::initializeProperties(VM& vm, JSC::JSGlobalObject* globalObject, JSCanvasPrototype* prototype)
+{
+}
+
+const ClassInfo JSCanvasConstructor::s_info = { "Function"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSCanvasConstructor) };
+
+extern "C" EncodedJSValue Canvas__getConstructor(Zig::GlobalObject* globalObject)
+{
+ return JSValue::encode(globalObject->JSCanvasConstructor());
+}
+
+extern "C" bool Canvas__hasPendingActivity(void* ptr);
+bool JSCanvas::hasPendingActivity(void* ctx)
+{
+ return Canvas__hasPendingActivity(ctx);
+}
+
+JSCanvas::~JSCanvas()
+{
+ if (m_ctx) {
+ CanvasClass__finalize(m_ctx);
+ }
+}
+void JSCanvas::destroy(JSCell* cell)
+{
+ static_cast<JSCanvas*>(cell)->JSCanvas::~JSCanvas();
+}
+
+const ClassInfo JSCanvas::s_info = { "Canvas"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSCanvas) };
+
+void JSCanvas::finishCreation(VM& vm)
+{
+ Base::finishCreation(vm);
+ ASSERT(inherits(info()));
+}
+
+JSCanvas* JSCanvas::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx)
+{
+ JSCanvas* ptr = new (NotNull, JSC::allocateCell<JSCanvas>(vm)) JSCanvas(vm, structure, ctx);
+ ptr->finishCreation(vm);
+ return ptr;
+}
+
+extern "C" void* Canvas__fromJS(JSC::EncodedJSValue value)
+{
+ JSC::JSValue decodedValue = JSC::JSValue::decode(value);
+ if (decodedValue.isEmpty() || !decodedValue.isCell())
+ return nullptr;
+
+ JSC::JSCell* cell = decodedValue.asCell();
+ JSCanvas* object = JSC::jsDynamicCast<JSCanvas*>(cell);
+
+ if (!object)
+ return nullptr;
+
+ return object->wrapped();
+}
+
+extern "C" bool Canvas__dangerouslySetPtr(JSC::EncodedJSValue value, void* ptr)
+{
+ JSCanvas* object = JSC::jsDynamicCast<JSCanvas*>(JSValue::decode(value));
+ if (!object)
+ return false;
+
+ object->m_ctx = ptr;
+ return true;
+}
+
+extern "C" const size_t Canvas__ptrOffset = JSCanvas::offsetOfWrapped();
+
+void JSCanvas::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer)
+{
+ auto* thisObject = jsCast<JSCanvas*>(cell);
+ if (void* wrapped = thisObject->wrapped()) {
+ // if (thisObject->scriptExecutionContext())
+ // analyzer.setLabelForCell(cell, "url " + thisObject->scriptExecutionContext()->url().string());
+ }
+ Base::analyzeHeap(cell, analyzer);
+}
+
+JSObject* JSCanvas::createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+{
+ return WebCore::JSCanvasConstructor::create(vm, globalObject, WebCore::JSCanvasConstructor::createStructure(vm, globalObject, globalObject->functionPrototype()), jsCast<WebCore::JSCanvasPrototype*>(prototype));
+}
+
+JSObject* JSCanvas::createPrototype(VM& vm, JSDOMGlobalObject* globalObject)
+{
+ return JSCanvasPrototype::create(vm, globalObject, JSCanvasPrototype::createStructure(vm, globalObject, globalObject->objectPrototype()));
+}
+
+extern "C" EncodedJSValue Canvas__create(Zig::GlobalObject* globalObject, void* ptr)
+{
+ auto& vm = globalObject->vm();
+ JSC::Structure* structure = globalObject->JSCanvasStructure();
+ JSCanvas* instance = JSCanvas::create(vm, globalObject, structure, ptr);
+
+ return JSValue::encode(instance);
+}
+
+template<typename Visitor>
+void JSCanvas::visitChildrenImpl(JSCell* cell, Visitor& visitor)
+{
+ JSCanvas* thisObject = jsCast<JSCanvas*>(cell);
+ ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+ Base::visitChildren(thisObject, visitor);
+
+ thisObject->visitAdditionalChildren<Visitor>(visitor);
+}
+
+DEFINE_VISIT_CHILDREN(JSCanvas);
+
+template<typename Visitor>
+void JSCanvas::visitAdditionalChildren(Visitor& visitor)
+{
+ JSCanvas* thisObject = this;
+ ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+
+ visitor.addOpaqueRoot(this->wrapped());
+}
+
+DEFINE_VISIT_ADDITIONAL_CHILDREN(JSCanvas);
+
+template<typename Visitor>
+void JSCanvas::visitOutputConstraintsImpl(JSCell* cell, Visitor& visitor)
+{
+ JSCanvas* thisObject = jsCast<JSCanvas*>(cell);
+ ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+ thisObject->visitAdditionalChildren<Visitor>(visitor);
+}
+
+DEFINE_VISIT_OUTPUT_CONSTRAINTS(JSCanvas);
+class JSCanvasRenderingContext2DPrototype final : public JSC::JSNonFinalObject {
+public:
+ using Base = JSC::JSNonFinalObject;
+
+ static JSCanvasRenderingContext2DPrototype* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure)
+ {
+ JSCanvasRenderingContext2DPrototype* ptr = new (NotNull, JSC::allocateCell<JSCanvasRenderingContext2DPrototype>(vm)) JSCanvasRenderingContext2DPrototype(vm, globalObject, structure);
+ ptr->finishCreation(vm, globalObject);
+ return ptr;
+ }
+
+ DECLARE_INFO;
+ template<typename CellType, JSC::SubspaceAccess>
+ static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
+ {
+ return &vm.plainObjectSpace();
+ }
+ static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
+ {
+ return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
+ }
+
+private:
+ JSCanvasRenderingContext2DPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure)
+ : Base(vm, structure)
+ {
+ }
+
+ void finishCreation(JSC::VM&, JSC::JSGlobalObject*);
+};
+
+class JSCanvasRenderingContext2DConstructor final : public JSC::InternalFunction {
+public:
+ using Base = JSC::InternalFunction;
+ static JSCanvasRenderingContext2DConstructor* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSCanvasRenderingContext2DPrototype* prototype);
+
+ static constexpr unsigned StructureFlags = Base::StructureFlags;
+ static constexpr bool needsDestruction = false;
+
+ static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
+ {
+ return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info());
+ }
+
+ template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
+ {
+ if constexpr (mode == JSC::SubspaceAccess::Concurrently)
+ return nullptr;
+ return WebCore::subspaceForImpl<JSCanvasRenderingContext2DConstructor, WebCore::UseCustomHeapCellType::No>(
+ vm,
+ [](auto& spaces) { return spaces.m_clientSubspaceForCanvasRenderingContext2DConstructor.get(); },
+ [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForCanvasRenderingContext2DConstructor = std::forward<decltype(space)>(space); },
+ [](auto& spaces) { return spaces.m_subspaceForCanvasRenderingContext2DConstructor.get(); },
+ [](auto& spaces, auto&& space) { spaces.m_subspaceForCanvasRenderingContext2DConstructor = std::forward<decltype(space)>(space); });
+ }
+
+ void initializeProperties(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSCanvasRenderingContext2DPrototype* prototype);
+
+ // Must be defined for each specialization class.
+ static JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES construct(JSC::JSGlobalObject*, JSC::CallFrame*);
+
+ DECLARE_EXPORT_INFO;
+
+private:
+ JSCanvasRenderingContext2DConstructor(JSC::VM& vm, JSC::Structure* structure);
+ void finishCreation(JSC::VM&, JSC::JSGlobalObject* globalObject, JSCanvasRenderingContext2DPrototype* prototype);
+};
+
+extern "C" void* CanvasRenderingContext2DClass__construct(JSC::JSGlobalObject*, JSC::CallFrame*);
+JSC_DECLARE_CUSTOM_GETTER(jsCanvasRenderingContext2DConstructor);
+
+extern "C" void CanvasRenderingContext2DClass__finalize(void*);
+
+extern "C" EncodedJSValue CanvasRenderingContext2DPrototype__clearRect(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame);
+JSC_DECLARE_HOST_FUNCTION(CanvasRenderingContext2DPrototype__clearRectCallback);
+
+extern "C" EncodedJSValue CanvasRenderingContext2DPrototype__fillRect(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame);
+JSC_DECLARE_HOST_FUNCTION(CanvasRenderingContext2DPrototype__fillRectCallback);
+
+extern "C" JSC::EncodedJSValue CanvasRenderingContext2DPrototype__getFillStyle(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject);
+JSC_DECLARE_CUSTOM_GETTER(CanvasRenderingContext2DPrototype__fillStyleGetterWrap);
+
+extern "C" bool CanvasRenderingContext2DPrototype__setFillStyle(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::EncodedJSValue value);
+JSC_DECLARE_CUSTOM_SETTER(CanvasRenderingContext2DPrototype__fillStyleSetterWrap);
+
+extern "C" EncodedJSValue CanvasRenderingContext2DPrototype__strokeRect(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame);
+JSC_DECLARE_HOST_FUNCTION(CanvasRenderingContext2DPrototype__strokeRectCallback);
+
+extern "C" JSC::EncodedJSValue CanvasRenderingContext2DPrototype__getStrokeStyle(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject);
+JSC_DECLARE_CUSTOM_GETTER(CanvasRenderingContext2DPrototype__strokeStyleGetterWrap);
+
+extern "C" bool CanvasRenderingContext2DPrototype__setStrokeStyle(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::EncodedJSValue value);
+JSC_DECLARE_CUSTOM_SETTER(CanvasRenderingContext2DPrototype__strokeStyleSetterWrap);
+
+STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSCanvasRenderingContext2DPrototype, JSCanvasRenderingContext2DPrototype::Base);
+
+static const HashTableValue JSCanvasRenderingContext2DPrototypeTableValues[] = {
+ { "clearRect"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, CanvasRenderingContext2DPrototype__clearRectCallback, 4 } },
+ { "fillRect"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, CanvasRenderingContext2DPrototype__fillRectCallback, 4 } },
+ { "fillStyle"_s, static_cast<unsigned>(JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, CanvasRenderingContext2DPrototype__fillStyleGetterWrap, CanvasRenderingContext2DPrototype__fillStyleSetterWrap } },
+ { "strokeRect"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, CanvasRenderingContext2DPrototype__strokeRectCallback, 4 } },
+ { "strokeStyle"_s, static_cast<unsigned>(JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, CanvasRenderingContext2DPrototype__strokeStyleGetterWrap, CanvasRenderingContext2DPrototype__strokeStyleSetterWrap } }
+};
+
+const ClassInfo JSCanvasRenderingContext2DPrototype::s_info = { "CanvasRenderingContext2D"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSCanvasRenderingContext2DPrototype) };
+
+JSC_DEFINE_CUSTOM_GETTER(jsCanvasRenderingContext2DConstructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName))
+{
+ VM& vm = JSC::getVM(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ auto* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject);
+ auto* prototype = jsDynamicCast<JSCanvasRenderingContext2DPrototype*>(JSValue::decode(thisValue));
+
+ if (UNLIKELY(!prototype))
+ return throwVMTypeError(lexicalGlobalObject, throwScope, "Cannot get constructor for CanvasRenderingContext2D"_s);
+ return JSValue::encode(globalObject->JSCanvasRenderingContext2DConstructor());
+}
+
+JSC_DEFINE_HOST_FUNCTION(CanvasRenderingContext2DPrototype__clearRectCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
+{
+ auto& vm = lexicalGlobalObject->vm();
+
+ JSCanvasRenderingContext2D* thisObject = jsDynamicCast<JSCanvasRenderingContext2D*>(callFrame->thisValue());
+
+ if (UNLIKELY(!thisObject)) {
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ throwVMTypeError(lexicalGlobalObject, throwScope, "Expected 'this' to be instanceof CanvasRenderingContext2D"_s);
+ return JSValue::encode({});
+ }
+
+ JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
+
+#ifdef BUN_DEBUG
+ /** View the file name of the JS file that called this function
+ * from a debugger */
+ SourceOrigin sourceOrigin = callFrame->callerSourceOrigin(vm);
+ const char* fileName = sourceOrigin.string().utf8().data();
+ static const char* lastFileName = nullptr;
+ if (lastFileName != fileName) {
+ lastFileName = fileName;
+ }
+#endif
+
+ return CanvasRenderingContext2DPrototype__clearRect(thisObject->wrapped(), lexicalGlobalObject, callFrame);
+}
+
+JSC_DEFINE_HOST_FUNCTION(CanvasRenderingContext2DPrototype__fillRectCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
+{
+ auto& vm = lexicalGlobalObject->vm();
+
+ JSCanvasRenderingContext2D* thisObject = jsDynamicCast<JSCanvasRenderingContext2D*>(callFrame->thisValue());
+
+ if (UNLIKELY(!thisObject)) {
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ throwVMTypeError(lexicalGlobalObject, throwScope, "Expected 'this' to be instanceof CanvasRenderingContext2D"_s);
+ return JSValue::encode({});
+ }
+
+ JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
+
+#ifdef BUN_DEBUG
+ /** View the file name of the JS file that called this function
+ * from a debugger */
+ SourceOrigin sourceOrigin = callFrame->callerSourceOrigin(vm);
+ const char* fileName = sourceOrigin.string().utf8().data();
+ static const char* lastFileName = nullptr;
+ if (lastFileName != fileName) {
+ lastFileName = fileName;
+ }
+#endif
+
+ return CanvasRenderingContext2DPrototype__fillRect(thisObject->wrapped(), lexicalGlobalObject, callFrame);
+}
+
+JSC_DEFINE_CUSTOM_GETTER(CanvasRenderingContext2DPrototype__fillStyleGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName))
+{
+ auto& vm = lexicalGlobalObject->vm();
+ Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ JSCanvasRenderingContext2D* thisObject = jsCast<JSCanvasRenderingContext2D*>(JSValue::decode(thisValue));
+ JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
+ JSC::EncodedJSValue result = CanvasRenderingContext2DPrototype__getFillStyle(thisObject->wrapped(), globalObject);
+ RETURN_IF_EXCEPTION(throwScope, {});
+ RELEASE_AND_RETURN(throwScope, result);
+}
+
+JSC_DEFINE_CUSTOM_SETTER(CanvasRenderingContext2DPrototype__fillStyleSetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, EncodedJSValue encodedValue, PropertyName attributeName))
+{
+ auto& vm = lexicalGlobalObject->vm();
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ JSCanvasRenderingContext2D* thisObject = jsCast<JSCanvasRenderingContext2D*>(JSValue::decode(thisValue));
+ JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
+ auto result = CanvasRenderingContext2DPrototype__setFillStyle(thisObject->wrapped(), lexicalGlobalObject, encodedValue);
+
+ RELEASE_AND_RETURN(throwScope, result);
+}
+
+JSC_DEFINE_HOST_FUNCTION(CanvasRenderingContext2DPrototype__strokeRectCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
+{
+ auto& vm = lexicalGlobalObject->vm();
+
+ JSCanvasRenderingContext2D* thisObject = jsDynamicCast<JSCanvasRenderingContext2D*>(callFrame->thisValue());
+
+ if (UNLIKELY(!thisObject)) {
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ throwVMTypeError(lexicalGlobalObject, throwScope, "Expected 'this' to be instanceof CanvasRenderingContext2D"_s);
+ return JSValue::encode({});
+ }
+
+ JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
+
+#ifdef BUN_DEBUG
+ /** View the file name of the JS file that called this function
+ * from a debugger */
+ SourceOrigin sourceOrigin = callFrame->callerSourceOrigin(vm);
+ const char* fileName = sourceOrigin.string().utf8().data();
+ static const char* lastFileName = nullptr;
+ if (lastFileName != fileName) {
+ lastFileName = fileName;
+ }
+#endif
+
+ return CanvasRenderingContext2DPrototype__strokeRect(thisObject->wrapped(), lexicalGlobalObject, callFrame);
+}
+
+JSC_DEFINE_CUSTOM_GETTER(CanvasRenderingContext2DPrototype__strokeStyleGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName))
+{
+ auto& vm = lexicalGlobalObject->vm();
+ Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ JSCanvasRenderingContext2D* thisObject = jsCast<JSCanvasRenderingContext2D*>(JSValue::decode(thisValue));
+ JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
+ JSC::EncodedJSValue result = CanvasRenderingContext2DPrototype__getStrokeStyle(thisObject->wrapped(), globalObject);
+ RETURN_IF_EXCEPTION(throwScope, {});
+ RELEASE_AND_RETURN(throwScope, result);
+}
+
+JSC_DEFINE_CUSTOM_SETTER(CanvasRenderingContext2DPrototype__strokeStyleSetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, EncodedJSValue encodedValue, PropertyName attributeName))
+{
+ auto& vm = lexicalGlobalObject->vm();
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ JSCanvasRenderingContext2D* thisObject = jsCast<JSCanvasRenderingContext2D*>(JSValue::decode(thisValue));
+ JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
+ auto result = CanvasRenderingContext2DPrototype__setStrokeStyle(thisObject->wrapped(), lexicalGlobalObject, encodedValue);
+
+ RELEASE_AND_RETURN(throwScope, result);
+}
+
+void JSCanvasRenderingContext2DPrototype::finishCreation(JSC::VM& vm, JSC::JSGlobalObject* globalObject)
+{
+ Base::finishCreation(vm);
+ reifyStaticProperties(vm, JSCanvasRenderingContext2D::info(), JSCanvasRenderingContext2DPrototypeTableValues, *this);
+ JSC_TO_STRING_TAG_WITHOUT_TRANSITION();
+}
+
+void JSCanvasRenderingContext2DConstructor::finishCreation(VM& vm, JSC::JSGlobalObject* globalObject, JSCanvasRenderingContext2DPrototype* prototype)
+{
+ Base::finishCreation(vm, 0, "CanvasRenderingContext2D"_s, PropertyAdditionMode::WithoutStructureTransition);
+
+ putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly);
+ ASSERT(inherits(info()));
+}
+
+JSCanvasRenderingContext2DConstructor::JSCanvasRenderingContext2DConstructor(JSC::VM& vm, JSC::Structure* structure)
+ : Base(vm, structure, construct, construct)
+{
+}
+
+JSCanvasRenderingContext2DConstructor* JSCanvasRenderingContext2DConstructor::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSCanvasRenderingContext2DPrototype* prototype)
+{
+ JSCanvasRenderingContext2DConstructor* ptr = new (NotNull, JSC::allocateCell<JSCanvasRenderingContext2DConstructor>(vm)) JSCanvasRenderingContext2DConstructor(vm, structure);
+ ptr->finishCreation(vm, globalObject, prototype);
+ return ptr;
+}
+
+JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSCanvasRenderingContext2DConstructor::construct(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame)
+{
+ Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject);
+ JSC::VM& vm = globalObject->vm();
+ JSObject* newTarget = asObject(callFrame->newTarget());
+ auto* constructor = globalObject->JSCanvasRenderingContext2DConstructor();
+ Structure* structure = globalObject->JSCanvasRenderingContext2DStructure();
+ if (constructor != newTarget) {
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ auto* functionGlobalObject = reinterpret_cast<Zig::GlobalObject*>(
+ // ShadowRealm functions belong to a different global object.
+ getFunctionRealm(globalObject, newTarget));
+ RETURN_IF_EXCEPTION(scope, {});
+ structure = InternalFunction::createSubclassStructure(
+ globalObject,
+ newTarget,
+ functionGlobalObject->JSCanvasRenderingContext2DStructure());
+ }
+
+ void* ptr = CanvasRenderingContext2DClass__construct(globalObject, callFrame);
+
+ if (UNLIKELY(!ptr)) {
+ return JSValue::encode(JSC::jsUndefined());
+ }
+
+ JSCanvasRenderingContext2D* instance = JSCanvasRenderingContext2D::create(vm, globalObject, structure, ptr);
+
+ return JSValue::encode(instance);
+}
+
+void JSCanvasRenderingContext2DConstructor::initializeProperties(VM& vm, JSC::JSGlobalObject* globalObject, JSCanvasRenderingContext2DPrototype* prototype)
+{
+}
+
+const ClassInfo JSCanvasRenderingContext2DConstructor::s_info = { "Function"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSCanvasRenderingContext2DConstructor) };
+
+extern "C" EncodedJSValue CanvasRenderingContext2D__getConstructor(Zig::GlobalObject* globalObject)
+{
+ return JSValue::encode(globalObject->JSCanvasRenderingContext2DConstructor());
+}
+
+JSCanvasRenderingContext2D::~JSCanvasRenderingContext2D()
+{
+}
+void JSCanvasRenderingContext2D::destroy(JSCell* cell)
+{
+ static_cast<JSCanvasRenderingContext2D*>(cell)->JSCanvasRenderingContext2D::~JSCanvasRenderingContext2D();
+}
+
+const ClassInfo JSCanvasRenderingContext2D::s_info = { "CanvasRenderingContext2D"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSCanvasRenderingContext2D) };
+
+void JSCanvasRenderingContext2D::finishCreation(VM& vm)
+{
+ Base::finishCreation(vm);
+ ASSERT(inherits(info()));
+}
+
+JSCanvasRenderingContext2D* JSCanvasRenderingContext2D::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx)
+{
+ JSCanvasRenderingContext2D* ptr = new (NotNull, JSC::allocateCell<JSCanvasRenderingContext2D>(vm)) JSCanvasRenderingContext2D(vm, structure, ctx);
+ ptr->finishCreation(vm);
+ return ptr;
+}
+
+extern "C" void* CanvasRenderingContext2D__fromJS(JSC::EncodedJSValue value)
+{
+ JSC::JSValue decodedValue = JSC::JSValue::decode(value);
+ if (decodedValue.isEmpty() || !decodedValue.isCell())
+ return nullptr;
+
+ JSC::JSCell* cell = decodedValue.asCell();
+ JSCanvasRenderingContext2D* object = JSC::jsDynamicCast<JSCanvasRenderingContext2D*>(cell);
+
+ if (!object)
+ return nullptr;
+
+ return object->wrapped();
+}
+
+extern "C" bool CanvasRenderingContext2D__dangerouslySetPtr(JSC::EncodedJSValue value, void* ptr)
+{
+ JSCanvasRenderingContext2D* object = JSC::jsDynamicCast<JSCanvasRenderingContext2D*>(JSValue::decode(value));
+ if (!object)
+ return false;
+
+ object->m_ctx = ptr;
+ return true;
+}
+
+extern "C" const size_t CanvasRenderingContext2D__ptrOffset = JSCanvasRenderingContext2D::offsetOfWrapped();
+
+void JSCanvasRenderingContext2D::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer)
+{
+ auto* thisObject = jsCast<JSCanvasRenderingContext2D*>(cell);
+ if (void* wrapped = thisObject->wrapped()) {
+ // if (thisObject->scriptExecutionContext())
+ // analyzer.setLabelForCell(cell, "url " + thisObject->scriptExecutionContext()->url().string());
+ }
+ Base::analyzeHeap(cell, analyzer);
+}
+
+JSObject* JSCanvasRenderingContext2D::createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+{
+ return WebCore::JSCanvasRenderingContext2DConstructor::create(vm, globalObject, WebCore::JSCanvasRenderingContext2DConstructor::createStructure(vm, globalObject, globalObject->functionPrototype()), jsCast<WebCore::JSCanvasRenderingContext2DPrototype*>(prototype));
+}
+
+JSObject* JSCanvasRenderingContext2D::createPrototype(VM& vm, JSDOMGlobalObject* globalObject)
+{
+ return JSCanvasRenderingContext2DPrototype::create(vm, globalObject, JSCanvasRenderingContext2DPrototype::createStructure(vm, globalObject, globalObject->objectPrototype()));
+}
+
+extern "C" EncodedJSValue CanvasRenderingContext2D__create(Zig::GlobalObject* globalObject, void* ptr)
+{
+ auto& vm = globalObject->vm();
+ JSC::Structure* structure = globalObject->JSCanvasRenderingContext2DStructure();
+ JSCanvasRenderingContext2D* instance = JSCanvasRenderingContext2D::create(vm, globalObject, structure, ptr);
+
+ return JSValue::encode(instance);
+}
class JSCommentPrototype final : public JSC::JSNonFinalObject {
public:
using Base = JSC::JSNonFinalObject;
diff --git a/src/bun.js/bindings/ZigGeneratedClasses.h b/src/bun.js/bindings/ZigGeneratedClasses.h
index 33aa58487..db80b6c60 100644
--- a/src/bun.js/bindings/ZigGeneratedClasses.h
+++ b/src/bun.js/bindings/ZigGeneratedClasses.h
@@ -300,6 +300,137 @@ public:
mutable JSC::WriteBarrier<JSC::Unknown> m_position;
};
+class JSCanvas final : public JSC::JSDestructibleObject {
+public:
+ using Base = JSC::JSDestructibleObject;
+ static JSCanvas* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx);
+
+ DECLARE_EXPORT_INFO;
+ template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
+ {
+ if constexpr (mode == JSC::SubspaceAccess::Concurrently)
+ return nullptr;
+ return WebCore::subspaceForImpl<JSCanvas, WebCore::UseCustomHeapCellType::No>(
+ vm,
+ [](auto& spaces) { return spaces.m_clientSubspaceForCanvas.get(); },
+ [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForCanvas = std::forward<decltype(space)>(space); },
+ [](auto& spaces) { return spaces.m_subspaceForCanvas.get(); },
+ [](auto& spaces, auto&& space) { spaces.m_subspaceForCanvas = std::forward<decltype(space)>(space); });
+ }
+
+ static void destroy(JSC::JSCell*);
+ static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
+ {
+ return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info());
+ }
+
+ static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject);
+ static JSObject* createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype);
+
+ ~JSCanvas();
+
+ void* wrapped() const { return m_ctx; }
+
+ void detach()
+ {
+ m_ctx = nullptr;
+ }
+
+ static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&);
+ static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSCanvas, m_ctx); }
+
+ void* m_ctx { nullptr };
+
+ JSCanvas(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr)
+ : Base(vm, structure)
+ {
+ m_ctx = sinkPtr;
+ m_weakThis = JSC::Weak<JSCanvas>(this, getOwner());
+ }
+
+ void finishCreation(JSC::VM&);
+
+ JSC::Weak<JSCanvas> m_weakThis;
+
+ static bool hasPendingActivity(void* ctx);
+
+ class Owner final : public JSC::WeakHandleOwner {
+ public:
+ bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void* context, JSC::AbstractSlotVisitor& visitor, const char** reason) final
+ {
+ auto* controller = JSC::jsCast<JSCanvas*>(handle.slot()->asCell());
+ if (JSCanvas::hasPendingActivity(controller->wrapped())) {
+ if (UNLIKELY(reason))
+ *reason = "has pending activity";
+ return true;
+ }
+
+ return visitor.containsOpaqueRoot(context);
+ }
+ void finalize(JSC::Handle<JSC::Unknown>, void* context) final {}
+ };
+
+ static JSC::WeakHandleOwner* getOwner()
+ {
+ static NeverDestroyed<Owner> m_owner;
+ return &m_owner.get();
+ }
+
+ DECLARE_VISIT_CHILDREN;
+ template<typename Visitor> void visitAdditionalChildren(Visitor&);
+ DECLARE_VISIT_OUTPUT_CONSTRAINTS;
+};
+
+class JSCanvasRenderingContext2D final : public JSC::JSDestructibleObject {
+public:
+ using Base = JSC::JSDestructibleObject;
+ static JSCanvasRenderingContext2D* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx);
+
+ DECLARE_EXPORT_INFO;
+ template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
+ {
+ if constexpr (mode == JSC::SubspaceAccess::Concurrently)
+ return nullptr;
+ return WebCore::subspaceForImpl<JSCanvasRenderingContext2D, WebCore::UseCustomHeapCellType::No>(
+ vm,
+ [](auto& spaces) { return spaces.m_clientSubspaceForCanvasRenderingContext2D.get(); },
+ [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForCanvasRenderingContext2D = std::forward<decltype(space)>(space); },
+ [](auto& spaces) { return spaces.m_subspaceForCanvasRenderingContext2D.get(); },
+ [](auto& spaces, auto&& space) { spaces.m_subspaceForCanvasRenderingContext2D = std::forward<decltype(space)>(space); });
+ }
+
+ static void destroy(JSC::JSCell*);
+ static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
+ {
+ return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info());
+ }
+
+ static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject);
+ static JSObject* createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype);
+
+ ~JSCanvasRenderingContext2D();
+
+ void* wrapped() const { return m_ctx; }
+
+ void detach()
+ {
+ m_ctx = nullptr;
+ }
+
+ static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&);
+ static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSCanvasRenderingContext2D, m_ctx); }
+
+ void* m_ctx { nullptr };
+
+ JSCanvasRenderingContext2D(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr)
+ : Base(vm, structure)
+ {
+ m_ctx = sinkPtr;
+ }
+
+ void finishCreation(JSC::VM&);
+};
+
class JSComment final : public JSC::JSDestructibleObject {
public:
using Base = JSC::JSDestructibleObject;
diff --git a/src/bun.js/bindings/generated_classes.zig b/src/bun.js/bindings/generated_classes.zig
index c44d554fc..4e5e2df15 100644
--- a/src/bun.js/bindings/generated_classes.zig
+++ b/src/bun.js/bindings/generated_classes.zig
@@ -922,6 +922,198 @@ pub const JSBuildMessage = struct {
}
}
};
+pub const JSCanvas = struct {
+ const Canvas = Classes.Canvas;
+ const GetterType = fn (*Canvas, *JSC.JSGlobalObject) callconv(.C) JSC.JSValue;
+ const GetterTypeWithThisValue = fn (*Canvas, JSC.JSValue, *JSC.JSGlobalObject) callconv(.C) JSC.JSValue;
+ const SetterType = fn (*Canvas, *JSC.JSGlobalObject, JSC.JSValue) callconv(.C) bool;
+ const SetterTypeWithThisValue = fn (*Canvas, JSC.JSValue, *JSC.JSGlobalObject, JSC.JSValue) callconv(.C) bool;
+ const CallbackType = fn (*Canvas, *JSC.JSGlobalObject, *JSC.CallFrame) callconv(.C) JSC.JSValue;
+
+ /// Return the pointer to the wrapped object.
+ /// If the object does not match the type, return null.
+ pub fn fromJS(value: JSC.JSValue) ?*Canvas {
+ JSC.markBinding(@src());
+ return Canvas__fromJS(value);
+ }
+
+ /// Get the Canvas constructor value.
+ /// This loads lazily from the global object.
+ pub fn getConstructor(globalObject: *JSC.JSGlobalObject) JSC.JSValue {
+ JSC.markBinding(@src());
+ return Canvas__getConstructor(globalObject);
+ }
+
+ /// Create a new instance of Canvas
+ pub fn toJS(this: *Canvas, globalObject: *JSC.JSGlobalObject) JSC.JSValue {
+ JSC.markBinding(@src());
+ if (comptime Environment.allow_assert) {
+ const value__ = Canvas__create(globalObject, this);
+ std.debug.assert(value__.as(Canvas).? == this); // If this fails, likely a C ABI issue.
+ return value__;
+ } else {
+ return Canvas__create(globalObject, this);
+ }
+ }
+
+ /// Modify the internal ptr to point to a new instance of Canvas.
+ pub fn dangerouslySetPtr(value: JSC.JSValue, ptr: ?*Canvas) bool {
+ JSC.markBinding(@src());
+ return Canvas__dangerouslySetPtr(value, ptr);
+ }
+
+ /// Detach the ptr from the thisValue
+ pub fn detachPtr(_: *Canvas, value: JSC.JSValue) void {
+ JSC.markBinding(@src());
+ std.debug.assert(Canvas__dangerouslySetPtr(value, null));
+ }
+
+ extern fn Canvas__fromJS(JSC.JSValue) ?*Canvas;
+ extern fn Canvas__getConstructor(*JSC.JSGlobalObject) JSC.JSValue;
+
+ extern fn Canvas__create(globalObject: *JSC.JSGlobalObject, ptr: ?*Canvas) JSC.JSValue;
+
+ extern fn Canvas__dangerouslySetPtr(JSC.JSValue, ?*Canvas) bool;
+
+ comptime {
+ if (@TypeOf(Canvas.constructor) != (fn (*JSC.JSGlobalObject, *JSC.CallFrame) callconv(.C) ?*Canvas)) {
+ @compileLog("Canvas.constructor is not a constructor");
+ }
+
+ if (@TypeOf(Canvas.finalize) != (fn (*Canvas) callconv(.C) void)) {
+ @compileLog("Canvas.finalize is not a finalizer");
+ }
+
+ if (@TypeOf(Canvas.animate) != CallbackType)
+ @compileLog("Expected Canvas.animate to be a callback but received " ++ @typeName(@TypeOf(Canvas.animate)));
+ if (@TypeOf(Canvas.close) != CallbackType)
+ @compileLog("Expected Canvas.close to be a callback but received " ++ @typeName(@TypeOf(Canvas.close)));
+ if (@TypeOf(Canvas.getContext) != CallbackType)
+ @compileLog("Expected Canvas.getContext to be a callback but received " ++ @typeName(@TypeOf(Canvas.getContext)));
+ if (@TypeOf(Canvas.getHeight) != GetterType)
+ @compileLog("Expected Canvas.getHeight to be a getter");
+
+ if (@TypeOf(Canvas.setHeight) != SetterType)
+ @compileLog("Expected Canvas.setHeight to be a setter");
+ if (@TypeOf(Canvas.getWidth) != GetterType)
+ @compileLog("Expected Canvas.getWidth to be a getter");
+
+ if (@TypeOf(Canvas.setWidth) != SetterType)
+ @compileLog("Expected Canvas.setWidth to be a setter");
+ if (@TypeOf(Canvas.getX) != GetterType)
+ @compileLog("Expected Canvas.getX to be a getter");
+
+ if (@TypeOf(Canvas.setX) != SetterType)
+ @compileLog("Expected Canvas.setX to be a setter");
+ if (@TypeOf(Canvas.getY) != GetterType)
+ @compileLog("Expected Canvas.getY to be a getter");
+
+ if (@TypeOf(Canvas.setY) != SetterType)
+ @compileLog("Expected Canvas.setY to be a setter");
+ if (!JSC.is_bindgen) {
+ @export(Canvas.animate, .{ .name = "CanvasPrototype__animate" });
+ @export(Canvas.close, .{ .name = "CanvasPrototype__close" });
+ @export(Canvas.constructor, .{ .name = "CanvasClass__construct" });
+ @export(Canvas.finalize, .{ .name = "CanvasClass__finalize" });
+ @export(Canvas.getContext, .{ .name = "CanvasPrototype__getContext" });
+ @export(Canvas.getHeight, .{ .name = "CanvasPrototype__getHeight" });
+ @export(Canvas.getWidth, .{ .name = "CanvasPrototype__getWidth" });
+ @export(Canvas.getX, .{ .name = "CanvasPrototype__getX" });
+ @export(Canvas.getY, .{ .name = "CanvasPrototype__getY" });
+ @export(Canvas.hasPendingActivity, .{ .name = "Canvas__hasPendingActivity" });
+ @export(Canvas.setHeight, .{ .name = "CanvasPrototype__setHeight" });
+ @export(Canvas.setWidth, .{ .name = "CanvasPrototype__setWidth" });
+ @export(Canvas.setX, .{ .name = "CanvasPrototype__setX" });
+ @export(Canvas.setY, .{ .name = "CanvasPrototype__setY" });
+ }
+ }
+};
+pub const JSCanvasRenderingContext2D = struct {
+ const CanvasRenderingContext2D = Classes.CanvasRenderingContext2D;
+ const GetterType = fn (*CanvasRenderingContext2D, *JSC.JSGlobalObject) callconv(.C) JSC.JSValue;
+ const GetterTypeWithThisValue = fn (*CanvasRenderingContext2D, JSC.JSValue, *JSC.JSGlobalObject) callconv(.C) JSC.JSValue;
+ const SetterType = fn (*CanvasRenderingContext2D, *JSC.JSGlobalObject, JSC.JSValue) callconv(.C) bool;
+ const SetterTypeWithThisValue = fn (*CanvasRenderingContext2D, JSC.JSValue, *JSC.JSGlobalObject, JSC.JSValue) callconv(.C) bool;
+ const CallbackType = fn (*CanvasRenderingContext2D, *JSC.JSGlobalObject, *JSC.CallFrame) callconv(.C) JSC.JSValue;
+
+ /// Return the pointer to the wrapped object.
+ /// If the object does not match the type, return null.
+ pub fn fromJS(value: JSC.JSValue) ?*CanvasRenderingContext2D {
+ JSC.markBinding(@src());
+ return CanvasRenderingContext2D__fromJS(value);
+ }
+
+ /// Get the CanvasRenderingContext2D constructor value.
+ /// This loads lazily from the global object.
+ pub fn getConstructor(globalObject: *JSC.JSGlobalObject) JSC.JSValue {
+ JSC.markBinding(@src());
+ return CanvasRenderingContext2D__getConstructor(globalObject);
+ }
+
+ /// Create a new instance of CanvasRenderingContext2D
+ pub fn toJS(this: *CanvasRenderingContext2D, globalObject: *JSC.JSGlobalObject) JSC.JSValue {
+ JSC.markBinding(@src());
+ if (comptime Environment.allow_assert) {
+ const value__ = CanvasRenderingContext2D__create(globalObject, this);
+ std.debug.assert(value__.as(CanvasRenderingContext2D).? == this); // If this fails, likely a C ABI issue.
+ return value__;
+ } else {
+ return CanvasRenderingContext2D__create(globalObject, this);
+ }
+ }
+
+ /// Modify the internal ptr to point to a new instance of CanvasRenderingContext2D.
+ pub fn dangerouslySetPtr(value: JSC.JSValue, ptr: ?*CanvasRenderingContext2D) bool {
+ JSC.markBinding(@src());
+ return CanvasRenderingContext2D__dangerouslySetPtr(value, ptr);
+ }
+
+ /// Detach the ptr from the thisValue
+ pub fn detachPtr(_: *CanvasRenderingContext2D, value: JSC.JSValue) void {
+ JSC.markBinding(@src());
+ std.debug.assert(CanvasRenderingContext2D__dangerouslySetPtr(value, null));
+ }
+
+ extern fn CanvasRenderingContext2D__fromJS(JSC.JSValue) ?*CanvasRenderingContext2D;
+ extern fn CanvasRenderingContext2D__getConstructor(*JSC.JSGlobalObject) JSC.JSValue;
+
+ extern fn CanvasRenderingContext2D__create(globalObject: *JSC.JSGlobalObject, ptr: ?*CanvasRenderingContext2D) JSC.JSValue;
+
+ extern fn CanvasRenderingContext2D__dangerouslySetPtr(JSC.JSValue, ?*CanvasRenderingContext2D) bool;
+
+ comptime {
+ if (@TypeOf(CanvasRenderingContext2D.constructor) != (fn (*JSC.JSGlobalObject, *JSC.CallFrame) callconv(.C) ?*CanvasRenderingContext2D)) {
+ @compileLog("CanvasRenderingContext2D.constructor is not a constructor");
+ }
+
+ if (@TypeOf(CanvasRenderingContext2D.clearRect) != CallbackType)
+ @compileLog("Expected CanvasRenderingContext2D.clearRect to be a callback but received " ++ @typeName(@TypeOf(CanvasRenderingContext2D.clearRect)));
+ if (@TypeOf(CanvasRenderingContext2D.fillRect) != CallbackType)
+ @compileLog("Expected CanvasRenderingContext2D.fillRect to be a callback but received " ++ @typeName(@TypeOf(CanvasRenderingContext2D.fillRect)));
+ if (@TypeOf(CanvasRenderingContext2D.getFillStyle) != GetterType)
+ @compileLog("Expected CanvasRenderingContext2D.getFillStyle to be a getter");
+
+ if (@TypeOf(CanvasRenderingContext2D.setFillStyle) != SetterType)
+ @compileLog("Expected CanvasRenderingContext2D.setFillStyle to be a setter");
+ if (@TypeOf(CanvasRenderingContext2D.strokeRect) != CallbackType)
+ @compileLog("Expected CanvasRenderingContext2D.strokeRect to be a callback but received " ++ @typeName(@TypeOf(CanvasRenderingContext2D.strokeRect)));
+ if (@TypeOf(CanvasRenderingContext2D.getStrokeStyle) != GetterType)
+ @compileLog("Expected CanvasRenderingContext2D.getStrokeStyle to be a getter");
+
+ if (@TypeOf(CanvasRenderingContext2D.setStrokeStyle) != SetterType)
+ @compileLog("Expected CanvasRenderingContext2D.setStrokeStyle to be a setter");
+ if (!JSC.is_bindgen) {
+ @export(CanvasRenderingContext2D.clearRect, .{ .name = "CanvasRenderingContext2DPrototype__clearRect" });
+ @export(CanvasRenderingContext2D.constructor, .{ .name = "CanvasRenderingContext2DClass__construct" });
+ @export(CanvasRenderingContext2D.fillRect, .{ .name = "CanvasRenderingContext2DPrototype__fillRect" });
+ @export(CanvasRenderingContext2D.getFillStyle, .{ .name = "CanvasRenderingContext2DPrototype__getFillStyle" });
+ @export(CanvasRenderingContext2D.getStrokeStyle, .{ .name = "CanvasRenderingContext2DPrototype__getStrokeStyle" });
+ @export(CanvasRenderingContext2D.setFillStyle, .{ .name = "CanvasRenderingContext2DPrototype__setFillStyle" });
+ @export(CanvasRenderingContext2D.setStrokeStyle, .{ .name = "CanvasRenderingContext2DPrototype__setStrokeStyle" });
+ @export(CanvasRenderingContext2D.strokeRect, .{ .name = "CanvasRenderingContext2DPrototype__strokeRect" });
+ }
+ }
+};
pub const JSComment = struct {
const Comment = Classes.Comment;
const GetterType = fn (*Comment, *JSC.JSGlobalObject) callconv(.C) JSC.JSValue;
@@ -7093,6 +7285,8 @@ comptime {
_ = JSBlob;
_ = JSBuildArtifact;
_ = JSBuildMessage;
+ _ = JSCanvas;
+ _ = JSCanvasRenderingContext2D;
_ = JSComment;
_ = JSCrypto;
_ = JSCryptoHasher;
diff --git a/src/bun.js/bindings/generated_classes_list.zig b/src/bun.js/bindings/generated_classes_list.zig
index 3b45f33b8..5fc87b64b 100644
--- a/src/bun.js/bindings/generated_classes_list.zig
+++ b/src/bun.js/bindings/generated_classes_list.zig
@@ -55,4 +55,6 @@ pub const Classes = struct {
pub const DebugHTTPSServer = JSC.API.DebugHTTPSServer;
pub const Crypto = JSC.WebCore.Crypto;
pub const FFI = JSC.FFI;
+ pub const Canvas = JSC.API.Canvas;
+ pub const CanvasRenderingContext2D = JSC.API.CanvasRenderingContext2D;
};
diff --git a/src/deps/SDL b/src/deps/SDL
new file mode 160000
+Subproject cc016b0046d563287f0aa9f09b958b5e70d4369
diff --git a/src/jsc.zig b/src/jsc.zig
index 5cdf739b3..5883bc234 100644
--- a/src/jsc.zig
+++ b/src/jsc.zig
@@ -32,6 +32,8 @@ pub const API = struct {
pub const JSBundler = @import("./bun.js/api/JSBundler.zig").JSBundler;
pub const BuildArtifact = @import("./bun.js/api/JSBundler.zig").BuildArtifact;
pub const JSTranspiler = @import("./bun.js/api/JSTranspiler.zig");
+ pub const Canvas = @import("./bun.js/api/canvas.zig").Canvas;
+ pub const CanvasRenderingContext2D = @import("./bun.js/api/canvas.zig").CanvasRenderingContext2D;
pub const HTTPServer = @import("./bun.js/api/server.zig").HTTPServer;
pub const ServerConfig = @import("./bun.js/api/server.zig").ServerConfig;
pub const ServerWebSocket = @import("./bun.js/api/server.zig").ServerWebSocket;
diff --git a/src/string.zig b/src/string.zig
index 1305e5884..c90efa044 100644
--- a/src/string.zig
+++ b/src/string.zig
@@ -786,6 +786,8 @@ pub const String = extern struct {
}
pub fn indexOfComptimeArrayCaseInsensitiveSameLength(this: String, comptime values: []const []const u8) ?usize {
+ if (values.len == 0) return null;
+
if (this.is8Bit()) {
const bytes = this.byteSlice();