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

Commit6310307

Browse files
Merge pull request#456 from PassiveLogic/feat/protocol-support-methods
BridgeJS:@js Protocol with methods support
2 parents237097a +7efb593 commit6310307

File tree

37 files changed

+2612
-107
lines changed

37 files changed

+2612
-107
lines changed

‎Benchmarks/Sources/Generated/JavaScript/BridgeJS.ExportSwift.json‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -720,5 +720,8 @@
720720
}
721721
}
722722
],
723-
"moduleName" :"Benchmarks"
723+
"moduleName" :"Benchmarks",
724+
"protocols" : [
725+
726+
]
724727
}

‎Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/JavaScript/BridgeJS.ExportSwift.json‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,5 +138,8 @@
138138
"functions" : [
139139

140140
],
141-
"moduleName" :"PlayBridgeJS"
141+
"moduleName" :"PlayBridgeJS",
142+
"protocols" : [
143+
144+
]
142145
}

‎Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift‎

Lines changed: 343 additions & 79 deletions
Large diffs are not rendered by default.

‎Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,8 @@ extension BridgeType {
435435
case.void:return.void
436436
case.swiftHeapObject:
437437
throwBridgeJSCoreError("swiftHeapObject is not supported in imported signatures")
438+
case.swiftProtocol:
439+
throwBridgeJSCoreError("swiftProtocol is not supported in imported signatures")
438440
case.caseEnum,.rawValueEnum,.associatedValueEnum,.namespaceEnum:
439441
throwBridgeJSCoreError("Enum types are not yet supported in TypeScript imports")
440442
case.optional:
@@ -465,6 +467,8 @@ extension BridgeType {
465467
case.void:return.void
466468
case.swiftHeapObject:
467469
throwBridgeJSCoreError("swiftHeapObject is not supported in imported signatures")
470+
case.swiftProtocol:
471+
throwBridgeJSCoreError("swiftProtocol is not supported in imported signatures")
468472
case.caseEnum,.rawValueEnum,.associatedValueEnum,.namespaceEnum:
469473
throwBridgeJSCoreError("Enum types are not yet supported in TypeScript imports")
470474
case.optional:

‎Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift‎

Lines changed: 75 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,9 @@ struct BridgeJSLink {
240240
enumPropertyPrinter.write("},")
241241

242242
if !property.isReadonly{
243-
letsetterThunkBuilder=ExportedThunkBuilder(effects:Effects(isAsync:false, isThrows:false))
243+
letsetterThunkBuilder=ExportedThunkBuilder(
244+
effects:Effects(isAsync:false, isThrows:false)
245+
)
244246
try setterThunkBuilder.lowerParameter(
245247
param:Parameter(label:"value", name:"value", type: property.type)
246248
)
@@ -300,6 +302,29 @@ struct BridgeJSLink {
300302
data.importObjectBuilders.append(importObjectBuilder)
301303
}
302304

305+
forskeletonin exportedSkeletons{
306+
if !skeleton.protocols.isEmpty{
307+
letimportObjectBuilder:ImportObjectBuilder
308+
iflet existingBuilder= data.importObjectBuilders.first(where:{ $0.moduleName== skeleton.moduleName}
309+
){
310+
importObjectBuilder= existingBuilder
311+
}else{
312+
importObjectBuilder=ImportObjectBuilder(moduleName: skeleton.moduleName)
313+
data.importObjectBuilders.append(importObjectBuilder)
314+
}
315+
316+
forprotoin skeleton.protocols{
317+
formethodin proto.methods{
318+
tryrenderProtocolMethod(
319+
importObjectBuilder: importObjectBuilder,
320+
protocol: proto,
321+
method: method
322+
)
323+
}
324+
}
325+
}
326+
}
327+
303328
return data
304329
}
305330

@@ -572,6 +597,22 @@ struct BridgeJSLink {
572597
"""
573598
letprinter=CodeFragmentPrinter(header: header)
574599
printer.nextLine()
600+
601+
forskeletonin exportedSkeletons{
602+
forprotoin skeleton.protocols{
603+
printer.write("export interface\(proto.name) {")
604+
printer.indent{
605+
formethodin proto.methods{
606+
printer.write(
607+
"\(method.name)\(renderTSSignature(parameters: method.parameters, returnType: method.returnType, effects: method.effects));"
608+
)
609+
}
610+
}
611+
printer.write("}")
612+
printer.nextLine()
613+
}
614+
}
615+
575616
printer.write(lines: data.topLevelDtsEnumLines)
576617

577618
// Generate Object types for const-style enums
@@ -1468,7 +1509,9 @@ extension BridgeJSLink {
14681509

14691510
if !property.isReadonly{
14701511
// Generate setter
1471-
letsetterThunkBuilder=ExportedThunkBuilder(effects:Effects(isAsync:false, isThrows:false))
1512+
letsetterThunkBuilder=ExportedThunkBuilder(
1513+
effects:Effects(isAsync:false, isThrows:false)
1514+
)
14721515
try setterThunkBuilder.lowerParameter(
14731516
param:Parameter(label:"value", name:"value", type: property.type)
14741517
)
@@ -1539,7 +1582,9 @@ extension BridgeJSLink {
15391582

15401583
if !property.isReadonly{
15411584
// Generate setter
1542-
letsetterThunkBuilder=ExportedThunkBuilder(effects:Effects(isAsync:false, isThrows:false))
1585+
letsetterThunkBuilder=ExportedThunkBuilder(
1586+
effects:Effects(isAsync:false, isThrows:false)
1587+
)
15431588
try setterThunkBuilder.lowerParameter(
15441589
param:Parameter(label:"value", name:"value", type: property.type)
15451590
)
@@ -1704,7 +1749,9 @@ extension BridgeJSLink {
17041749

17051750
// Generate static property setter if not readonly
17061751
if !property.isReadonly{
1707-
letsetterThunkBuilder=ExportedThunkBuilder(effects:Effects(isAsync:false, isThrows:false))
1752+
letsetterThunkBuilder=ExportedThunkBuilder(
1753+
effects:Effects(isAsync:false, isThrows:false)
1754+
)
17081755
try setterThunkBuilder.lowerParameter(
17091756
param:Parameter(label:"value", name:"value", type: property.type)
17101757
)
@@ -1752,7 +1799,9 @@ extension BridgeJSLink {
17521799

17531800
// Generate instance property setter if not readonly
17541801
if !property.isReadonly{
1755-
letsetterThunkBuilder=ExportedThunkBuilder(effects:Effects(isAsync:false, isThrows:false))
1802+
letsetterThunkBuilder=ExportedThunkBuilder(
1803+
effects:Effects(isAsync:false, isThrows:false)
1804+
)
17561805
setterThunkBuilder.lowerSelf()
17571806
try setterThunkBuilder.lowerParameter(
17581807
param:Parameter(label:"value", name:"value", type: property.type)
@@ -2367,6 +2416,25 @@ extension BridgeJSLink {
23672416
)
23682417
return(funcLines,[])
23692418
}
2419+
2420+
func renderProtocolMethod(
2421+
importObjectBuilder:ImportObjectBuilder,
2422+
protocol:ExportedProtocol,
2423+
method:ExportedFunction
2424+
)throws{
2425+
letthunkBuilder=ImportedThunkBuilder()
2426+
thunkBuilder.liftSelf()
2427+
forparamin method.parameters{
2428+
try thunkBuilder.liftParameter(param: param)
2429+
}
2430+
letreturnExpr=try thunkBuilder.callMethod(name: method.name, returnType: method.returnType)
2431+
letfuncLines= thunkBuilder.renderFunction(
2432+
name: method.abiName,
2433+
returnExpr: returnExpr,
2434+
returnType: method.returnType
2435+
)
2436+
importObjectBuilder.assignToImportObject(name: method.abiName, function: funcLines)
2437+
}
23702438
}
23712439

23722440
structBridgeJSLinkError:Error{
@@ -2402,6 +2470,8 @@ extension BridgeType {
24022470
return"\(name)Tag"
24032471
case.namespaceEnum(let name):
24042472
return name
2473+
case.swiftProtocol(let name):
2474+
return name
24052475
}
24062476
}
24072477
}

‎Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,25 @@ struct IntrinsicJSFragment: Sendable {
297297
switch wrappedType{
298298
case.swiftHeapObject:
299299
return["+\(isSomeVar)","\(isSomeVar) ?\(value).pointer : 0"]
300+
case.swiftProtocol:
301+
return[
302+
"+\(isSomeVar)",
303+
"\(isSomeVar) ?\(JSGlueVariableScope.reservedSwift).memory.retain(\(value)) : 0",
304+
]
305+
case.jsObject:
306+
letidVar= scope.variable("id")
307+
printer.write("let\(idVar);")
308+
printer.write("if (\(isSomeVar)) {")
309+
printer.indent{
310+
printer.write("\(idVar) =\(JSGlueVariableScope.reservedSwift).memory.retain(\(value));")
311+
}
312+
printer.write("}")
313+
cleanupCode.write("if (\(idVar) !== undefined) {")
314+
cleanupCode.indent{
315+
cleanupCode.write("\(JSGlueVariableScope.reservedSwift).memory.release(\(idVar));")
316+
}
317+
cleanupCode.write("}")
318+
return["+\(isSomeVar)","\(isSomeVar) ?\(idVar) : 0"]
300319
default:
301320
return["+\(isSomeVar)","\(isSomeVar) ?\(value) : 0"]
302321
}
@@ -326,6 +345,9 @@ struct IntrinsicJSFragment: Sendable {
326345
case.string:
327346
printer.write("const\(resultVar) =\(JSGlueVariableScope.reservedStorageToReturnString);")
328347
printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = undefined;")
348+
case.jsObject,.swiftProtocol:
349+
printer.write("const\(resultVar) =\(JSGlueVariableScope.reservedStorageToReturnString);")
350+
printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = undefined;")
329351
case.swiftHeapObject(let className):
330352
letpointerVar= scope.variable("pointer")
331353
printer.write(
@@ -397,6 +419,7 @@ struct IntrinsicJSFragment: Sendable {
397419
case.jsObject:return.jsObjectLowerParameter
398420
case.swiftHeapObject:
399421
return.swiftHeapObjectLowerParameter
422+
case.swiftProtocol:return.jsObjectLowerParameter
400423
case.void:return.void
401424
case.optional(let wrappedType):
402425
returntry.optionalLowerParameter(wrappedType: wrappedType)
@@ -422,6 +445,7 @@ struct IntrinsicJSFragment: Sendable {
422445
case.string:return.stringLiftReturn
423446
case.jsObject:return.jsObjectLiftReturn
424447
case.swiftHeapObject(let name):return.swiftHeapObjectLiftReturn(name)
448+
case.swiftProtocol:return.jsObjectLiftReturn
425449
case.void:return.void
426450
case.optional(let wrappedType):return.optionalLiftReturn(wrappedType: wrappedType)
427451
case.caseEnum:return.identity
@@ -455,6 +479,7 @@ struct IntrinsicJSFragment: Sendable {
455479
message:
456480
"Swift heap objects are not supported to be passed as parameters to imported JS functions:\(name)"
457481
)
482+
case.swiftProtocol:return.jsObjectLiftParameter
458483
case.void:
459484
throwBridgeJSLinkError(
460485
message:"Void can't appear in parameters of imported JS functions"
@@ -494,6 +519,7 @@ struct IntrinsicJSFragment: Sendable {
494519
throwBridgeJSLinkError(
495520
message:"Swift heap objects are not supported to be returned from imported JS functions"
496521
)
522+
case.swiftProtocol:return.jsObjectLowerReturn
497523
case.void:return.void
498524
case.optional(let wrappedType):
499525
throwBridgeJSLinkError(

‎Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift‎

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ public enum BridgeType: Codable, Equatable, Sendable {
7474
case rawValueEnum(String,SwiftEnumRawType)
7575
case associatedValueEnum(String)
7676
case namespaceEnum(String)
77+
case swiftProtocol(String)
7778
}
7879

7980
publicenumWasmCoreType:String,Codable,Sendable{
@@ -269,6 +270,18 @@ public enum EnumType: String, Codable, Sendable {
269270

270271
// MARK: - Exported Skeleton
271272

273+
publicstructExportedProtocol:Codable,Equatable{
274+
publicletname:String
275+
publicletmethods:[ExportedFunction]
276+
publicletnamespace:[String]?
277+
278+
publicinit(name:String, methods:[ExportedFunction], namespace:[String]?=nil){
279+
self.name= name
280+
self.methods= methods
281+
self.namespace= namespace
282+
}
283+
}
284+
272285
publicstructExportedFunction:Codable,Equatable,Sendable{
273286
publicvarname:String
274287
publicvarabiName:String
@@ -407,12 +420,20 @@ public struct ExportedSkeleton: Codable {
407420
publicletfunctions:[ExportedFunction]
408421
publicletclasses:[ExportedClass]
409422
publicletenums:[ExportedEnum]
423+
publicletprotocols:[ExportedProtocol]
410424

411-
publicinit(moduleName:String, functions:[ExportedFunction], classes:[ExportedClass], enums:[ExportedEnum]){
425+
publicinit(
426+
moduleName:String,
427+
functions:[ExportedFunction],
428+
classes:[ExportedClass],
429+
enums:[ExportedEnum],
430+
protocols:[ExportedProtocol]=[]
431+
){
412432
self.moduleName= moduleName
413433
self.functions= functions
414434
self.classes= classes
415435
self.enums= enums
436+
self.protocols= protocols
416437
}
417438
}
418439

@@ -514,6 +535,9 @@ extension BridgeType {
514535
returnnil
515536
case.namespaceEnum:
516537
returnnil
538+
case.swiftProtocol:
539+
// Protocols pass JSObject IDs as Int32
540+
return.i32
517541
}
518542
}
519543

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import JavaScriptKit
2+
3+
@JSprotocolMyViewControllerDelegate{
4+
func onSomethingHappened()
5+
func onValueChanged(_ value:String)
6+
func onCountUpdated(count:Int)->Bool
7+
func onLabelUpdated(_ prefix:String, _ suffix:String)
8+
func isCountEven()->Bool
9+
}
10+
11+
@JSclassMyViewController{
12+
@JS
13+
vardelegate:MyViewControllerDelegate
14+
15+
@JS
16+
varsecondDelegate:MyViewControllerDelegate?
17+
18+
@JSinit(delegate:MyViewControllerDelegate){
19+
self.delegate= delegate
20+
}
21+
22+
@JSfunc triggerEvent(){
23+
delegate.onSomethingHappened()
24+
}
25+
26+
@JSfunc updateValue(_ value:String){
27+
delegate.onValueChanged(value)
28+
}
29+
30+
@JSfunc updateCount(_ count:Int)->Bool{
31+
return delegate.onCountUpdated(count: count)
32+
}
33+
34+
@JSfunc updateLabel(_ prefix:String, _ suffix:String){
35+
delegate.onLabelUpdated(prefix, suffix)
36+
}
37+
38+
@JSfunc checkEvenCount()->Bool{
39+
return delegate.isCountEven()
40+
}
41+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit,
2+
// DO NOT EDIT.
3+
//
4+
// To update this file, just rebuild your project or run
5+
// `swift package bridge-js`.
6+
7+
exportinterfaceMyViewControllerDelegate{
8+
onSomethingHappened():void;
9+
onValueChanged(value:string):void;
10+
onCountUpdated(count:number):boolean;
11+
onLabelUpdated(prefix:string,suffix:string):void;
12+
isCountEven():boolean;
13+
}
14+
15+
/// Represents a Swift heap object like a class instance or an actor instance.
16+
exportinterfaceSwiftHeapObject{
17+
/// Release the heap object.
18+
///
19+
/// Note: Calling this method will release the heap object and it will no longer be accessible.
20+
release():void;
21+
}
22+
exportinterfaceMyViewControllerextendsSwiftHeapObject{
23+
triggerEvent():void;
24+
updateValue(value:string):void;
25+
updateCount(count:number):boolean;
26+
updateLabel(prefix:string,suffix:string):void;
27+
checkEvenCount():boolean;
28+
delegate:MyViewControllerDelegate;
29+
secondDelegate:MyViewControllerDelegate|null;
30+
}
31+
exporttypeExports={
32+
MyViewController:{
33+
new(delegate:MyViewControllerDelegate):MyViewController;
34+
}
35+
}
36+
exporttypeImports={
37+
}
38+
exportfunctioncreateInstantiator(options:{
39+
imports:Imports;
40+
},swift:any):Promise<{
41+
addImports:(importObject:WebAssembly.Imports)=>void;
42+
setInstance:(instance:WebAssembly.Instance)=>void;
43+
createExports:(instance:WebAssembly.Instance)=>Exports;
44+
}>;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp