Skip to content

Instantly share code, notes, and snippets.

@kateinoigakukun
Created January 4, 2022 06:56
Show Gist options
  • Save kateinoigakukun/886f5d70587af8c7775c69a2d205726d to your computer and use it in GitHub Desktop.
Save kateinoigakukun/886f5d70587af8c7775c69a2d205726d to your computer and use it in GitHub Desktop.
import JavaScriptKit
public protocol JSBackend {
associatedtype ValueType: JSValueProtocol where ValueType.Backend == Self
associatedtype ObjectType: JSObjectProtocol where ObjectType.Backend == Self
associatedtype FunctionType: JSFunctionProtocol where FunctionType.Backend == Self
}
@dynamicMemberLookup
public protocol JSObjectProtocol {
associatedtype Backend: JSBackend
subscript(_ name: String) -> ((ConvertibleToJSValue...) -> Backend.ValueType)? { get }
subscript(dynamicMember name: String) -> ((ConvertibleToJSValue...) -> Backend.ValueType)? { get }
subscript(dynamicMember name: String) -> Backend.ValueType { get }
subscript(_ name: String) -> Backend.ValueType { get }
subscript(_ name: JSString) -> Backend.ValueType { get }
subscript(_ index: Int) -> Backend.ValueType { get }
}
public protocol JSValueProtocol {
associatedtype Backend: JSBackend
var object: Backend.ObjectType? { get }
static func object(_ object: Backend.ObjectType) -> Self
static func string(_ string: String) -> Self
var function: Backend.FunctionType? { get }
}
public protocol JSFunctionProtocol {
associatedtype Backend: JSBackend
@discardableResult
func callAsFunction(_ arguments: Backend.ValueType...) -> Backend.ValueType
}
struct NativeBackend: JSBackend {
typealias ValueType = NativeJSValue
typealias ObjectType = NativeJSObject
typealias FunctionType = NativeJSFunction
}
struct NativeJSObject: JSObjectProtocol {
typealias Backend = NativeBackend
subscript(name: String) -> ((ConvertibleToJSValue...) -> NativeJSValue)? {
return { (_: ConvertibleToJSValue...) in return NativeJSValue() }
}
subscript(dynamicMember name: String) -> ((ConvertibleToJSValue...) -> NativeJSValue)? {
return { (_: ConvertibleToJSValue...) in return NativeJSValue() }
}
subscript(dynamicMember name: String) -> NativeJSValue {
return NativeJSValue()
}
subscript(name: String) -> NativeJSValue {
return NativeJSValue()
}
subscript(name: JSString) -> NativeJSValue {
return NativeJSValue()
}
subscript(index: Int) -> NativeJSValue {
return NativeJSValue()
}
}
struct NativeJSValue: JSValueProtocol {
typealias Backend = NativeBackend
init() {}
var object: NativeJSObject? {
// TODO
return nil
}
static func object(_ object: NativeJSObject) -> NativeJSValue {
return NativeJSValue()
}
static func string(_ string: String) -> NativeJSValue {
return NativeJSValue()
}
var function: NativeJSFunction? {
// TODO
return nil
}
}
struct NativeJSFunction: JSFunctionProtocol {
typealias Backend = NativeBackend
func callAsFunction(_ arguments: NativeJSValue...) -> NativeJSValue {
return NativeJSValue()
}
}
public struct WasmBackend: JSBackend {
public typealias ValueType = JSValue
public typealias ObjectType = JSObject
public typealias FunctionType = JSFunction
}
extension JSValue: JSValueProtocol {
public typealias Backend = WasmBackend
}
extension JSObject: JSObjectProtocol {
public typealias Backend = WasmBackend
}
extension JSFunction: JSFunctionProtocol {
public typealias Backend = WasmBackend
public func callAsFunction(_ arguments: JSValue...) -> JSValue {
self.callAsFunction(this: nil, arguments: arguments)
}
}
struct Logger<Backend: JSBackend> {
let console: Backend.ObjectType
func fooPrint(_ message: String) {
console.info.function?(.string("[Foo] \(message)"))
}
}
extension Logger where Backend == WasmBackend {
init(console: JSObject = JSObject.global.console.object!) {
self.console = console
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment