Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

BridgeJS: @JS Protocol with methods support#456

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
Show file tree
Hide file tree
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -720,5 +720,8 @@
}
}
],
"moduleName" : "Benchmarks"
"moduleName" : "Benchmarks",
"protocols" : [

]
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -138,5 +138,8 @@
"functions" : [

],
"moduleName" : "PlayBridgeJS"
"moduleName" : "PlayBridgeJS",
"protocols" : [

]
}
422 changes: 343 additions & 79 deletionsPlugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift
View file
Open in desktop

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletionsPlugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -435,6 +435,8 @@ extension BridgeType {
case .void: return .void
case .swiftHeapObject:
throw BridgeJSCoreError("swiftHeapObject is not supported in imported signatures")
case .swiftProtocol:
throw BridgeJSCoreError("swiftProtocol is not supported in imported signatures")
case .caseEnum, .rawValueEnum, .associatedValueEnum, .namespaceEnum:
throw BridgeJSCoreError("Enum types are not yet supported in TypeScript imports")
case .optional:
Expand DownExpand Up@@ -465,6 +467,8 @@ extension BridgeType {
case .void: return .void
case .swiftHeapObject:
throw BridgeJSCoreError("swiftHeapObject is not supported in imported signatures")
case .swiftProtocol:
throw BridgeJSCoreError("swiftProtocol is not supported in imported signatures")
case .caseEnum, .rawValueEnum, .associatedValueEnum, .namespaceEnum:
throw BridgeJSCoreError("Enum types are not yet supported in TypeScript imports")
case .optional:
Expand Down
80 changes: 75 additions & 5 deletionsPlugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -240,7 +240,9 @@ struct BridgeJSLink {
enumPropertyPrinter.write("},")

if !property.isReadonly {
let setterThunkBuilder = ExportedThunkBuilder(effects: Effects(isAsync: false, isThrows: false))
let setterThunkBuilder = ExportedThunkBuilder(
effects: Effects(isAsync: false, isThrows: false)
)
try setterThunkBuilder.lowerParameter(
param: Parameter(label: "value", name: "value", type: property.type)
)
Expand DownExpand Up@@ -300,6 +302,29 @@ struct BridgeJSLink {
data.importObjectBuilders.append(importObjectBuilder)
}

for skeleton in exportedSkeletons {
if !skeleton.protocols.isEmpty {
let importObjectBuilder: ImportObjectBuilder
if let existingBuilder = data.importObjectBuilders.first(where: { $0.moduleName == skeleton.moduleName }
) {
importObjectBuilder = existingBuilder
} else {
importObjectBuilder = ImportObjectBuilder(moduleName: skeleton.moduleName)
data.importObjectBuilders.append(importObjectBuilder)
}

for proto in skeleton.protocols {
for method in proto.methods {
try renderProtocolMethod(
importObjectBuilder: importObjectBuilder,
protocol: proto,
method: method
)
}
}
}
}

return data
}

Expand DownExpand Up@@ -572,6 +597,22 @@ struct BridgeJSLink {
"""
let printer = CodeFragmentPrinter(header: header)
printer.nextLine()

for skeleton in exportedSkeletons {
for proto in skeleton.protocols {
printer.write("export interface \(proto.name) {")
printer.indent {
for method in proto.methods {
printer.write(
"\(method.name)\(renderTSSignature(parameters: method.parameters, returnType: method.returnType, effects: method.effects));"
)
}
}
printer.write("}")
printer.nextLine()
}
}

printer.write(lines: data.topLevelDtsEnumLines)

// Generate Object types for const-style enums
Expand DownExpand Up@@ -1468,7 +1509,9 @@ extension BridgeJSLink {

if !property.isReadonly {
// Generate setter
let setterThunkBuilder = ExportedThunkBuilder(effects: Effects(isAsync: false, isThrows: false))
let setterThunkBuilder = ExportedThunkBuilder(
effects: Effects(isAsync: false, isThrows: false)
)
try setterThunkBuilder.lowerParameter(
param: Parameter(label: "value", name: "value", type: property.type)
)
Expand DownExpand Up@@ -1539,7 +1582,9 @@ extension BridgeJSLink {

if !property.isReadonly {
// Generate setter
let setterThunkBuilder = ExportedThunkBuilder(effects: Effects(isAsync: false, isThrows: false))
let setterThunkBuilder = ExportedThunkBuilder(
effects: Effects(isAsync: false, isThrows: false)
)
try setterThunkBuilder.lowerParameter(
param: Parameter(label: "value", name: "value", type: property.type)
)
Expand DownExpand Up@@ -1704,7 +1749,9 @@ extension BridgeJSLink {

// Generate static property setter if not readonly
if !property.isReadonly {
let setterThunkBuilder = ExportedThunkBuilder(effects: Effects(isAsync: false, isThrows: false))
let setterThunkBuilder = ExportedThunkBuilder(
effects: Effects(isAsync: false, isThrows: false)
)
try setterThunkBuilder.lowerParameter(
param: Parameter(label: "value", name: "value", type: property.type)
)
Expand DownExpand Up@@ -1752,7 +1799,9 @@ extension BridgeJSLink {

// Generate instance property setter if not readonly
if !property.isReadonly {
let setterThunkBuilder = ExportedThunkBuilder(effects: Effects(isAsync: false, isThrows: false))
let setterThunkBuilder = ExportedThunkBuilder(
effects: Effects(isAsync: false, isThrows: false)
)
setterThunkBuilder.lowerSelf()
try setterThunkBuilder.lowerParameter(
param: Parameter(label: "value", name: "value", type: property.type)
Expand DownExpand Up@@ -2367,6 +2416,25 @@ extension BridgeJSLink {
)
return (funcLines, [])
}

func renderProtocolMethod(
importObjectBuilder: ImportObjectBuilder,
protocol: ExportedProtocol,
method: ExportedFunction
) throws {
let thunkBuilder = ImportedThunkBuilder()
thunkBuilder.liftSelf()
for param in method.parameters {
try thunkBuilder.liftParameter(param: param)
}
let returnExpr = try thunkBuilder.callMethod(name: method.name, returnType: method.returnType)
let funcLines = thunkBuilder.renderFunction(
name: method.abiName,
returnExpr: returnExpr,
returnType: method.returnType
)
importObjectBuilder.assignToImportObject(name: method.abiName, function: funcLines)
}
}

struct BridgeJSLinkError: Error {
Expand DownExpand Up@@ -2402,6 +2470,8 @@ extension BridgeType {
return "\(name)Tag"
case .namespaceEnum(let name):
return name
case .swiftProtocol(let name):
return name
}
}
}
Expand Down
26 changes: 26 additions & 0 deletionsPlugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -297,6 +297,25 @@ struct IntrinsicJSFragment: Sendable {
switch wrappedType {
case .swiftHeapObject:
return ["+\(isSomeVar)", "\(isSomeVar) ? \(value).pointer : 0"]
case .swiftProtocol:
return [
"+\(isSomeVar)",
"\(isSomeVar) ? \(JSGlueVariableScope.reservedSwift).memory.retain(\(value)) : 0",
]
case .jsObject:
let idVar = scope.variable("id")
printer.write("let \(idVar);")
printer.write("if (\(isSomeVar)) {")
printer.indent {
printer.write("\(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(value));")
}
printer.write("}")
cleanupCode.write("if (\(idVar) !== undefined) {")
cleanupCode.indent {
cleanupCode.write("\(JSGlueVariableScope.reservedSwift).memory.release(\(idVar));")
}
cleanupCode.write("}")
return ["+\(isSomeVar)", "\(isSomeVar) ? \(idVar) : 0"]
default:
return ["+\(isSomeVar)", "\(isSomeVar) ? \(value) : 0"]
}
Expand DownExpand Up@@ -326,6 +345,9 @@ struct IntrinsicJSFragment: Sendable {
case .string:
printer.write("const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnString);")
printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = undefined;")
case .jsObject, .swiftProtocol:
printer.write("const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnString);")
printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = undefined;")
case .swiftHeapObject(let className):
let pointerVar = scope.variable("pointer")
printer.write(
Expand DownExpand Up@@ -397,6 +419,7 @@ struct IntrinsicJSFragment: Sendable {
case .jsObject: return .jsObjectLowerParameter
case .swiftHeapObject:
return .swiftHeapObjectLowerParameter
case .swiftProtocol: return .jsObjectLowerParameter
case .void: return .void
case .optional(let wrappedType):
return try .optionalLowerParameter(wrappedType: wrappedType)
Expand All@@ -422,6 +445,7 @@ struct IntrinsicJSFragment: Sendable {
case .string: return .stringLiftReturn
case .jsObject: return .jsObjectLiftReturn
case .swiftHeapObject(let name): return .swiftHeapObjectLiftReturn(name)
case .swiftProtocol: return .jsObjectLiftReturn
case .void: return .void
case .optional(let wrappedType): return .optionalLiftReturn(wrappedType: wrappedType)
case .caseEnum: return .identity
Expand DownExpand Up@@ -455,6 +479,7 @@ struct IntrinsicJSFragment: Sendable {
message:
"Swift heap objects are not supported to be passed as parameters to imported JS functions: \(name)"
)
case .swiftProtocol: return .jsObjectLiftParameter
case .void:
throw BridgeJSLinkError(
message: "Void can't appear in parameters of imported JS functions"
Expand DownExpand Up@@ -494,6 +519,7 @@ struct IntrinsicJSFragment: Sendable {
throw BridgeJSLinkError(
message: "Swift heap objects are not supported to be returned from imported JS functions"
)
case .swiftProtocol: return .jsObjectLowerReturn
case .void: return .void
case .optional(let wrappedType):
throw BridgeJSLinkError(
Expand Down
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -74,6 +74,7 @@ public enum BridgeType: Codable, Equatable, Sendable {
case rawValueEnum(String, SwiftEnumRawType)
case associatedValueEnum(String)
case namespaceEnum(String)
case swiftProtocol(String)
}

public enum WasmCoreType: String, Codable, Sendable {
Expand DownExpand Up@@ -269,6 +270,18 @@ public enum EnumType: String, Codable, Sendable {

// MARK: - Exported Skeleton

public struct ExportedProtocol: Codable, Equatable {
public let name: String
public let methods: [ExportedFunction]
public let namespace: [String]?

public init(name: String, methods: [ExportedFunction], namespace: [String]? = nil) {
self.name = name
self.methods = methods
self.namespace = namespace
}
}

public struct ExportedFunction: Codable, Equatable, Sendable {
public var name: String
public var abiName: String
Expand DownExpand Up@@ -407,12 +420,20 @@ public struct ExportedSkeleton: Codable {
public let functions: [ExportedFunction]
public let classes: [ExportedClass]
public let enums: [ExportedEnum]
public let protocols: [ExportedProtocol]

public init(moduleName: String, functions: [ExportedFunction], classes: [ExportedClass], enums: [ExportedEnum]) {
public init(
moduleName: String,
functions: [ExportedFunction],
classes: [ExportedClass],
enums: [ExportedEnum],
protocols: [ExportedProtocol] = []
) {
self.moduleName = moduleName
self.functions = functions
self.classes = classes
self.enums = enums
self.protocols = protocols
}
}

Expand DownExpand Up@@ -514,6 +535,9 @@ extension BridgeType {
return nil
case .namespaceEnum:
return nil
case .swiftProtocol:
// Protocols pass JSObject IDs as Int32
return .i32
}
}

Expand Down
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
import JavaScriptKit

@JS protocol MyViewControllerDelegate {
func onSomethingHappened()
func onValueChanged(_ value: String)
func onCountUpdated(count: Int) -> Bool
func onLabelUpdated(_ prefix: String, _ suffix: String)
func isCountEven() -> Bool
}

@JS class MyViewController {
@JS
var delegate: MyViewControllerDelegate

@JS
var secondDelegate: MyViewControllerDelegate?

@JS init(delegate: MyViewControllerDelegate) {
self.delegate = delegate
}

@JS func triggerEvent() {
delegate.onSomethingHappened()
}

@JS func updateValue(_ value: String) {
delegate.onValueChanged(value)
}

@JS func updateCount(_ count: Int) -> Bool {
return delegate.onCountUpdated(count: count)
}

@JS func updateLabel(_ prefix: String, _ suffix: String) {
delegate.onLabelUpdated(prefix, suffix)
}

@JS func checkEvenCount() -> Bool {
return delegate.isCountEven()
}
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit,
// DO NOT EDIT.
//
// To update this file, just rebuild your project or run
// `swift package bridge-js`.

export interface MyViewControllerDelegate {
onSomethingHappened(): void;
onValueChanged(value: string): void;
onCountUpdated(count: number): boolean;
onLabelUpdated(prefix: string, suffix: string): void;
isCountEven(): boolean;
}

/// Represents a Swift heap object like a class instance or an actor instance.
export interface SwiftHeapObject {
/// Release the heap object.
///
/// Note: Calling this method will release the heap object and it will no longer be accessible.
release(): void;
}
export interface MyViewController extends SwiftHeapObject {
triggerEvent(): void;
updateValue(value: string): void;
updateCount(count: number): boolean;
updateLabel(prefix: string, suffix: string): void;
checkEvenCount(): boolean;
delegate: MyViewControllerDelegate;
secondDelegate: MyViewControllerDelegate | null;
}
export type Exports = {
MyViewController: {
new(delegate: MyViewControllerDelegate): MyViewController;
}
}
export type Imports = {
}
export function createInstantiator(options: {
imports: Imports;
}, swift: any): Promise<{
addImports: (importObject: WebAssembly.Imports) => void;
setInstance: (instance: WebAssembly.Instance) => void;
createExports: (instance: WebAssembly.Instance) => Exports;
}>;
Loading

[8]ページ先頭

©2009-2025 Movatter.jp