From 748619d88a53520d0306494a19834232795b393f Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Fri, 17 Jun 2022 10:42:08 +0100 Subject: [PATCH 1/2] Add `(Offscreen)RenderingContext` protocols --- Sources/WebAPIKit/Generated.swift | 179 +------------------------ Sources/WebAPIKit/Support.swift | 46 +++++++ Sources/WebAPIKitDemo/WebGLDemo.swift | 5 +- Sources/WebIDLToSwift/IDLBuilder.swift | 5 +- 4 files changed, 56 insertions(+), 179 deletions(-) diff --git a/Sources/WebAPIKit/Generated.swift b/Sources/WebAPIKit/Generated.swift index 0203bcad..4bb8c190 100644 --- a/Sources/WebAPIKit/Generated.swift +++ b/Sources/WebAPIKit/Generated.swift @@ -11886,10 +11886,7 @@ public class HTMLCanvasElement: HTMLElement { @ReadWriteAttribute public var height: UInt32 - @inlinable public func getContext(contextId: String, options: JSValue? = nil) -> RenderingContext? { - let this = jsObject - return this[Strings.getContext].function!(this: this, arguments: [contextId.jsValue, options?.jsValue ?? .undefined]).fromJSValue()! - } + // XXX: member 'getContext' is ignored @inlinable public func toDataURL(type: String? = nil, quality: JSValue? = nil) -> String { let this = jsObject @@ -18099,10 +18096,7 @@ public class OffscreenCanvas: EventTarget { @ReadWriteAttribute public var height: UInt64 - @inlinable public func getContext(contextId: OffscreenRenderingContextId, options: JSValue? = nil) -> OffscreenRenderingContext? { - let this = jsObject - return this[Strings.getContext].function!(this: this, arguments: [contextId.jsValue, options?.jsValue ?? .undefined]).fromJSValue()! - } + // XXX: member 'getContext' is ignored @inlinable public func transferToImageBitmap() -> ImageBitmap { let this = jsObject @@ -28619,7 +28613,6 @@ public enum console { @usableFromInline static let getClientRects: JSString = "getClientRects" @usableFromInline static let getComputedTiming: JSString = "getComputedTiming" @usableFromInline static let getConstraints: JSString = "getConstraints" - @usableFromInline static let getContext: JSString = "getContext" @usableFromInline static let getContextAttributes: JSString = "getContextAttributes" @usableFromInline static let getCueById: JSString = "getCueById" @usableFromInline static let getCurrentTexture: JSString = "getCurrentTexture" @@ -32066,90 +32059,6 @@ public enum Node_or_String: JSValueCompatible, Any_Node_or_String { } } -public protocol Any_OffscreenRenderingContext: ConvertibleToJSValue {} -extension GPUCanvasContext: Any_OffscreenRenderingContext {} -extension ImageBitmapRenderingContext: Any_OffscreenRenderingContext {} -extension OffscreenCanvasRenderingContext2D: Any_OffscreenRenderingContext {} -extension WebGL2RenderingContext: Any_OffscreenRenderingContext {} -extension WebGLRenderingContext: Any_OffscreenRenderingContext {} - -public enum OffscreenRenderingContext: JSValueCompatible, Any_OffscreenRenderingContext { - case gpuCanvasContext(GPUCanvasContext) - case imageBitmapRenderingContext(ImageBitmapRenderingContext) - case offscreenCanvasRenderingContext2D(OffscreenCanvasRenderingContext2D) - case webGL2RenderingContext(WebGL2RenderingContext) - case webGLRenderingContext(WebGLRenderingContext) - - public var gpuCanvasContext: GPUCanvasContext? { - switch self { - case let .gpuCanvasContext(gpuCanvasContext): return gpuCanvasContext - default: return nil - } - } - - public var imageBitmapRenderingContext: ImageBitmapRenderingContext? { - switch self { - case let .imageBitmapRenderingContext(imageBitmapRenderingContext): return imageBitmapRenderingContext - default: return nil - } - } - - public var offscreenCanvasRenderingContext2D: OffscreenCanvasRenderingContext2D? { - switch self { - case let .offscreenCanvasRenderingContext2D(offscreenCanvasRenderingContext2D): return offscreenCanvasRenderingContext2D - default: return nil - } - } - - public var webGL2RenderingContext: WebGL2RenderingContext? { - switch self { - case let .webGL2RenderingContext(webGL2RenderingContext): return webGL2RenderingContext - default: return nil - } - } - - public var webGLRenderingContext: WebGLRenderingContext? { - switch self { - case let .webGLRenderingContext(webGLRenderingContext): return webGLRenderingContext - default: return nil - } - } - - public static func construct(from value: JSValue) -> Self? { - if let gpuCanvasContext: GPUCanvasContext = value.fromJSValue() { - return .gpuCanvasContext(gpuCanvasContext) - } - if let imageBitmapRenderingContext: ImageBitmapRenderingContext = value.fromJSValue() { - return .imageBitmapRenderingContext(imageBitmapRenderingContext) - } - if let offscreenCanvasRenderingContext2D: OffscreenCanvasRenderingContext2D = value.fromJSValue() { - return .offscreenCanvasRenderingContext2D(offscreenCanvasRenderingContext2D) - } - if let webGL2RenderingContext: WebGL2RenderingContext = value.fromJSValue() { - return .webGL2RenderingContext(webGL2RenderingContext) - } - if let webGLRenderingContext: WebGLRenderingContext = value.fromJSValue() { - return .webGLRenderingContext(webGLRenderingContext) - } - return nil - } - - public var jsValue: JSValue { - switch self { - case let .gpuCanvasContext(gpuCanvasContext): - return gpuCanvasContext.jsValue - case let .imageBitmapRenderingContext(imageBitmapRenderingContext): - return imageBitmapRenderingContext.jsValue - case let .offscreenCanvasRenderingContext2D(offscreenCanvasRenderingContext2D): - return offscreenCanvasRenderingContext2D.jsValue - case let .webGL2RenderingContext(webGL2RenderingContext): - return webGL2RenderingContext.jsValue - case let .webGLRenderingContext(webGLRenderingContext): - return webGLRenderingContext.jsValue - } - } -} - public protocol Any_Path2D_or_String: ConvertibleToJSValue {} extension Path2D: Any_Path2D_or_String {} extension String: Any_Path2D_or_String {} @@ -32276,90 +32185,6 @@ public enum ReadableStreamReader: JSValueCompatible, Any_ReadableStreamReader { } } -public protocol Any_RenderingContext: ConvertibleToJSValue {} -extension CanvasRenderingContext2D: Any_RenderingContext {} -extension GPUCanvasContext: Any_RenderingContext {} -extension ImageBitmapRenderingContext: Any_RenderingContext {} -extension WebGL2RenderingContext: Any_RenderingContext {} -extension WebGLRenderingContext: Any_RenderingContext {} - -public enum RenderingContext: JSValueCompatible, Any_RenderingContext { - case canvasRenderingContext2D(CanvasRenderingContext2D) - case gpuCanvasContext(GPUCanvasContext) - case imageBitmapRenderingContext(ImageBitmapRenderingContext) - case webGL2RenderingContext(WebGL2RenderingContext) - case webGLRenderingContext(WebGLRenderingContext) - - public var canvasRenderingContext2D: CanvasRenderingContext2D? { - switch self { - case let .canvasRenderingContext2D(canvasRenderingContext2D): return canvasRenderingContext2D - default: return nil - } - } - - public var gpuCanvasContext: GPUCanvasContext? { - switch self { - case let .gpuCanvasContext(gpuCanvasContext): return gpuCanvasContext - default: return nil - } - } - - public var imageBitmapRenderingContext: ImageBitmapRenderingContext? { - switch self { - case let .imageBitmapRenderingContext(imageBitmapRenderingContext): return imageBitmapRenderingContext - default: return nil - } - } - - public var webGL2RenderingContext: WebGL2RenderingContext? { - switch self { - case let .webGL2RenderingContext(webGL2RenderingContext): return webGL2RenderingContext - default: return nil - } - } - - public var webGLRenderingContext: WebGLRenderingContext? { - switch self { - case let .webGLRenderingContext(webGLRenderingContext): return webGLRenderingContext - default: return nil - } - } - - public static func construct(from value: JSValue) -> Self? { - if let canvasRenderingContext2D: CanvasRenderingContext2D = value.fromJSValue() { - return .canvasRenderingContext2D(canvasRenderingContext2D) - } - if let gpuCanvasContext: GPUCanvasContext = value.fromJSValue() { - return .gpuCanvasContext(gpuCanvasContext) - } - if let imageBitmapRenderingContext: ImageBitmapRenderingContext = value.fromJSValue() { - return .imageBitmapRenderingContext(imageBitmapRenderingContext) - } - if let webGL2RenderingContext: WebGL2RenderingContext = value.fromJSValue() { - return .webGL2RenderingContext(webGL2RenderingContext) - } - if let webGLRenderingContext: WebGLRenderingContext = value.fromJSValue() { - return .webGLRenderingContext(webGLRenderingContext) - } - return nil - } - - public var jsValue: JSValue { - switch self { - case let .canvasRenderingContext2D(canvasRenderingContext2D): - return canvasRenderingContext2D.jsValue - case let .gpuCanvasContext(gpuCanvasContext): - return gpuCanvasContext.jsValue - case let .imageBitmapRenderingContext(imageBitmapRenderingContext): - return imageBitmapRenderingContext.jsValue - case let .webGL2RenderingContext(webGL2RenderingContext): - return webGL2RenderingContext.jsValue - case let .webGLRenderingContext(webGLRenderingContext): - return webGLRenderingContext.jsValue - } - } -} - public protocol Any_RequestInfo: ConvertibleToJSValue {} extension Request: Any_RequestInfo {} extension String: Any_RequestInfo {} diff --git a/Sources/WebAPIKit/Support.swift b/Sources/WebAPIKit/Support.swift index a4c1aa5e..b4894ea6 100644 --- a/Sources/WebAPIKit/Support.swift +++ b/Sources/WebAPIKit/Support.swift @@ -23,3 +23,49 @@ public typealias HTMLOrSVGScriptElement = HTMLScriptElement public typealias BodyInit = XMLHttpRequestBodyInit public typealias CustomElementConstructor = JSFunction public typealias GLintptr = Int32 + +public protocol RenderingContext: JSValueCompatible {} + +extension GPUCanvasContext: RenderingContext {} +extension ImageBitmapRenderingContext: RenderingContext {} +extension OffscreenCanvasRenderingContext2D: RenderingContext {} +extension WebGL2RenderingContext: RenderingContext {} +extension WebGLRenderingContext: RenderingContext {} + +public protocol OffscreenRenderingContext: JSValueCompatible {} + +extension GPUCanvasContext: OffscreenRenderingContext {} +extension ImageBitmapRenderingContext: OffscreenRenderingContext {} +extension OffscreenCanvasRenderingContext2D: OffscreenRenderingContext {} +extension WebGL2RenderingContext: OffscreenRenderingContext {} +extension WebGLRenderingContext: OffscreenRenderingContext {} + +extension Strings { + @usableFromInline static let getContext: JSString = "getContext" +} + +public extension HTMLCanvasElement { + @inlinable func getContext( + contextId: String, + options: JSValue? = nil + ) -> Context? { + let this = jsObject + return this[Strings.getContext].function!( + this: this, + arguments: [contextId.jsValue, options?.jsValue ?? .undefined] + ).fromJSValue()! + } +} + +public extension OffscreenCanvas { + @inlinable func getContext( + contextId: OffscreenRenderingContextId, + options: JSValue? = nil + ) -> Context? { + let this = jsObject + return this[Strings.getContext].function!( + this: this, + arguments: [contextId.jsValue, options?.jsValue ?? .undefined] + ).fromJSValue()! + } +} diff --git a/Sources/WebAPIKitDemo/WebGLDemo.swift b/Sources/WebAPIKitDemo/WebGLDemo.swift index 454c8c63..ad4ae977 100644 --- a/Sources/WebAPIKitDemo/WebGLDemo.swift +++ b/Sources/WebAPIKitDemo/WebGLDemo.swift @@ -117,7 +117,10 @@ func runWebGLDemo() { // Get A WebGL context let canvas = HTMLCanvasElement(from: document.createElement(localName: "canvas"))! _ = document.body?.appendChild(node: canvas) - let context = canvas.getContext(contextId: "webgl2")!.webGL2RenderingContext! + guard let context: WebGL2RenderingContext = canvas.getContext(contextId: "webgl2") else { + console.error(data: "Failed to create WebGL2 rendering context") + return + } // create GLSL shaders, upload the GLSL source, compile the shaders guard diff --git a/Sources/WebIDLToSwift/IDLBuilder.swift b/Sources/WebIDLToSwift/IDLBuilder.swift index 0ec86fc2..f4073641 100644 --- a/Sources/WebIDLToSwift/IDLBuilder.swift +++ b/Sources/WebIDLToSwift/IDLBuilder.swift @@ -25,6 +25,8 @@ enum IDLBuilder { "BigInt64Array_or_BigUint64Array_or_DataView_or_Float32Array_or_Float64Array_or_Int16Array_or_Int32Array_or_Int8Array_or_Uint16Array_or_Uint32Array_or_Uint8Array_or_Uint8ClampedArray", // RotationMatrixType "DOMMatrix_or_Float32Array_or_Float64Array", + "RenderingContext", + "OffscreenRenderingContext", ] static func writeFile(path: String, content: String) throws { @@ -58,7 +60,7 @@ enum IDLBuilder { "FileSystemEntry": ["getParent"], "FileSystemFileEntry": ["file"], "Geolocation": ["getCurrentPosition", "watchPosition"], - "HTMLCanvasElement": ["toBlob"], + "HTMLCanvasElement": ["toBlob", "getContext"], "HTMLVideoElement": ["requestVideoFrameCallback"], "IntersectionObserver": [""], "LayoutWorkletGlobalScope": ["registerLayout"], @@ -97,6 +99,7 @@ enum IDLBuilder { "HTMLMediaElement": ["srcObject"], "Blob": ["stream"], "Body": ["body"], + "OffscreenCanvas": ["getContext"], ], types: merged.types )) { From b632bfcc29ad86bf82819ecffb9554965dad9818 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Fri, 17 Jun 2022 11:12:37 +0100 Subject: [PATCH 2/2] Refactor context IDs --- Sources/WebAPIKit/Generated.swift | 21 -------- Sources/WebAPIKit/RenderingContext.swift | 69 ++++++++++++++++++++++++ Sources/WebAPIKit/Support.swift | 46 ---------------- Sources/WebAPIKitDemo/WebGLDemo.swift | 2 +- Sources/WebIDLToSwift/IDLBuilder.swift | 1 + 5 files changed, 71 insertions(+), 68 deletions(-) create mode 100644 Sources/WebAPIKit/RenderingContext.swift diff --git a/Sources/WebAPIKit/Generated.swift b/Sources/WebAPIKit/Generated.swift index 4bb8c190..899f294f 100644 --- a/Sources/WebAPIKit/Generated.swift +++ b/Sources/WebAPIKit/Generated.swift @@ -18141,27 +18141,6 @@ public class OffscreenCanvasRenderingContext2D: JSBridgedClass, CanvasState, Can public var canvas: OffscreenCanvas } -public enum OffscreenRenderingContextId: JSString, JSValueCompatible { - case _2d = "2d" - case bitmaprenderer = "bitmaprenderer" - case webgl = "webgl" - case webgl2 = "webgl2" - case webgpu = "webgpu" - - @inlinable public static func construct(from jsValue: JSValue) -> Self? { - if let string = jsValue.jsString { - return Self(rawValue: string) - } - return nil - } - - @inlinable public init?(string: String) { - self.init(rawValue: JSString(string)) - } - - @inlinable public var jsValue: JSValue { rawValue.jsValue } -} - public class OptionalEffectTiming: BridgedDictionary { public convenience init(delay: Double, endDelay: Double, fill: FillMode, iterationStart: Double, iterations: Double, duration: Double_or_String, direction: PlaybackDirection, easing: String) { let object = JSObject.global[Strings.Object].function!.new() diff --git a/Sources/WebAPIKit/RenderingContext.swift b/Sources/WebAPIKit/RenderingContext.swift new file mode 100644 index 00000000..81628ccf --- /dev/null +++ b/Sources/WebAPIKit/RenderingContext.swift @@ -0,0 +1,69 @@ +import JavaScriptKit + +public protocol RenderingContext: JSValueCompatible { + /// Textual identifier of this context type, passed to `getContext` under the hood. + static var contextID: JSString { get } +} + +extension GPUCanvasContext: RenderingContext { + public static var contextID: JSString { "webgpu" } +} + +extension ImageBitmapRenderingContext: RenderingContext { + public static var contextID: JSString { "bitmaprenderer" } +} + +extension CanvasRenderingContext2D: RenderingContext { + public static var contextID: JSString { "2d" } +} + +extension WebGL2RenderingContext: RenderingContext { + public static var contextID: JSString { "webgl2" } +} + +extension WebGLRenderingContext: RenderingContext { + public static var contextID: JSString { "webgl" } +} + +public protocol OffscreenRenderingContext: JSValueCompatible { + static var contextID: JSString { get } +} + +extension GPUCanvasContext: OffscreenRenderingContext {} +extension ImageBitmapRenderingContext: OffscreenRenderingContext {} +extension CanvasRenderingContext2D: OffscreenRenderingContext {} +extension WebGL2RenderingContext: OffscreenRenderingContext {} +extension WebGLRenderingContext: OffscreenRenderingContext {} +extension OffscreenCanvasRenderingContext2D: OffscreenRenderingContext { + public static var contextID: JSString { "2d" } +} + +extension Strings { + @usableFromInline static let getContext: JSString = "getContext" +} + +public extension HTMLCanvasElement { + @inlinable func getContext( + _ contextType: Context.Type, + options: JSValue? = nil + ) -> Context? { + let this = jsObject + return this[Strings.getContext].function!( + this: this, + arguments: [contextType.contextID.jsValue, options?.jsValue ?? .undefined] + ).fromJSValue()! + } +} + +public extension OffscreenCanvas { + @inlinable func getContext( + _ contextType: Context.Type, + options: JSValue? = nil + ) -> Context? { + let this = jsObject + return this[Strings.getContext].function!( + this: this, + arguments: [contextType.contextID.jsValue, options?.jsValue ?? .undefined] + ).fromJSValue()! + } +} diff --git a/Sources/WebAPIKit/Support.swift b/Sources/WebAPIKit/Support.swift index b4894ea6..a4c1aa5e 100644 --- a/Sources/WebAPIKit/Support.swift +++ b/Sources/WebAPIKit/Support.swift @@ -23,49 +23,3 @@ public typealias HTMLOrSVGScriptElement = HTMLScriptElement public typealias BodyInit = XMLHttpRequestBodyInit public typealias CustomElementConstructor = JSFunction public typealias GLintptr = Int32 - -public protocol RenderingContext: JSValueCompatible {} - -extension GPUCanvasContext: RenderingContext {} -extension ImageBitmapRenderingContext: RenderingContext {} -extension OffscreenCanvasRenderingContext2D: RenderingContext {} -extension WebGL2RenderingContext: RenderingContext {} -extension WebGLRenderingContext: RenderingContext {} - -public protocol OffscreenRenderingContext: JSValueCompatible {} - -extension GPUCanvasContext: OffscreenRenderingContext {} -extension ImageBitmapRenderingContext: OffscreenRenderingContext {} -extension OffscreenCanvasRenderingContext2D: OffscreenRenderingContext {} -extension WebGL2RenderingContext: OffscreenRenderingContext {} -extension WebGLRenderingContext: OffscreenRenderingContext {} - -extension Strings { - @usableFromInline static let getContext: JSString = "getContext" -} - -public extension HTMLCanvasElement { - @inlinable func getContext( - contextId: String, - options: JSValue? = nil - ) -> Context? { - let this = jsObject - return this[Strings.getContext].function!( - this: this, - arguments: [contextId.jsValue, options?.jsValue ?? .undefined] - ).fromJSValue()! - } -} - -public extension OffscreenCanvas { - @inlinable func getContext( - contextId: OffscreenRenderingContextId, - options: JSValue? = nil - ) -> Context? { - let this = jsObject - return this[Strings.getContext].function!( - this: this, - arguments: [contextId.jsValue, options?.jsValue ?? .undefined] - ).fromJSValue()! - } -} diff --git a/Sources/WebAPIKitDemo/WebGLDemo.swift b/Sources/WebAPIKitDemo/WebGLDemo.swift index ad4ae977..b73594c4 100644 --- a/Sources/WebAPIKitDemo/WebGLDemo.swift +++ b/Sources/WebAPIKitDemo/WebGLDemo.swift @@ -117,7 +117,7 @@ func runWebGLDemo() { // Get A WebGL context let canvas = HTMLCanvasElement(from: document.createElement(localName: "canvas"))! _ = document.body?.appendChild(node: canvas) - guard let context: WebGL2RenderingContext = canvas.getContext(contextId: "webgl2") else { + guard let context = canvas.getContext(WebGL2RenderingContext.self) else { console.error(data: "Failed to create WebGL2 rendering context") return } diff --git a/Sources/WebIDLToSwift/IDLBuilder.swift b/Sources/WebIDLToSwift/IDLBuilder.swift index f4073641..2d54b304 100644 --- a/Sources/WebIDLToSwift/IDLBuilder.swift +++ b/Sources/WebIDLToSwift/IDLBuilder.swift @@ -27,6 +27,7 @@ enum IDLBuilder { "DOMMatrix_or_Float32Array_or_Float64Array", "RenderingContext", "OffscreenRenderingContext", + "OffscreenRenderingContextId", ] static func writeFile(path: String, content: String) throws {