diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bun.js/api/bun.zig | 46 | ||||
-rw-r--r-- | src/bun.js/api/canvas.classes.ts | 73 | ||||
-rw-r--r-- | src/bun.js/api/canvas.zig | 806 | ||||
-rw-r--r-- | src/bun.js/bindings/BunObject+exports.h | 1 | ||||
-rw-r--r-- | src/bun.js/bindings/BunObject.cpp | 1 | ||||
-rw-r--r-- | src/bun.js/bindings/BunObject.lut.h | 131 | ||||
-rw-r--r-- | src/bun.js/bindings/ZigGeneratedClasses+DOMClientIsoSubspaces.h | 4 | ||||
-rw-r--r-- | src/bun.js/bindings/ZigGeneratedClasses+DOMIsoSubspaces.h | 4 | ||||
-rw-r--r-- | src/bun.js/bindings/ZigGeneratedClasses+lazyStructureHeader.h | 8 | ||||
-rw-r--r-- | src/bun.js/bindings/ZigGeneratedClasses+lazyStructureImpl.h | 14 | ||||
-rw-r--r-- | src/bun.js/bindings/ZigGeneratedClasses.cpp | 892 | ||||
-rw-r--r-- | src/bun.js/bindings/ZigGeneratedClasses.h | 131 | ||||
-rw-r--r-- | src/bun.js/bindings/generated_classes.zig | 194 | ||||
-rw-r--r-- | src/bun.js/bindings/generated_classes_list.zig | 2 | ||||
m--------- | src/deps/SDL | 0 | ||||
-rw-r--r-- | src/jsc.zig | 2 | ||||
-rw-r--r-- | src/string.zig | 2 |
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(); |