Skip to content

Commit ed4bedb

Browse files
committed
BridgeJS: Escape reserved words
1 parent dbbfdc3 commit ed4bedb

11 files changed

Lines changed: 605 additions & 13 deletions

File tree

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

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ public class ExportSwift {
216216
let liftingInfo = try param.type.liftParameterInfo()
217217
let argumentsToLift: [String]
218218
if liftingInfo.parameters.count == 1 {
219-
argumentsToLift = [param.name]
219+
argumentsToLift = [param.escapedSwiftIdentifier]
220220
} else {
221221
argumentsToLift = liftingInfo.parameters.map { (name, _) in param.name + name.capitalizedFirstLetter }
222222
}
@@ -227,7 +227,9 @@ public class ExportSwift {
227227
switch param.type {
228228
case .closure(let signature, _):
229229
typeNameForIntrinsic = param.type.swiftType
230-
liftingExpr = ExprSyntax("_BJS_Closure_\(raw: signature.mangleName).bridgeJSLift(\(raw: param.name))")
230+
liftingExpr = ExprSyntax(
231+
"_BJS_Closure_\(raw: signature.mangleName).bridgeJSLift(\(raw: param.escapedSwiftIdentifier))"
232+
)
231233
case .swiftStruct(let structName):
232234
typeNameForIntrinsic = structName
233235
liftingExpr = ExprSyntax("\(raw: structName).bridgeJSLiftParameter()")
@@ -252,7 +254,7 @@ public class ExportSwift {
252254
)
253255
}
254256

255-
parameterBindings.insert("let \(raw: param.name) = \(liftingExpr)", at: 0)
257+
parameterBindings.insert("let \(raw: param.escapedSwiftIdentifier) = \(liftingExpr)", at: 0)
256258
for (name, type) in zip(argumentsToLift, liftingInfo.parameters.map { $0.type }) {
257259
abiParameterSignatures.append((name, type))
258260
}
@@ -268,14 +270,14 @@ public class ExportSwift {
268270
}
269271

270272
private func removeFirstLiftedParameter() -> String {
271-
return parameters.removeFirst().name
273+
return parameters.removeFirst().escapedSwiftIdentifier
272274
}
273275

274276
private func renderCallStatement(callee: ExprSyntax, returnType: BridgeType) -> CodeBlockItemSyntax {
275277
let labeledParams = parameters.map { param in
276278
LabeledExprSyntax(
277279
label: param.label,
278-
expression: DeclReferenceExprSyntax(baseName: .identifier(param.name))
280+
expression: DeclReferenceExprSyntax(baseName: .identifier(param.escapedSwiftIdentifier))
279281
)
280282
}
281283
var callExpr: ExprSyntax =
@@ -1593,6 +1595,12 @@ struct ProtocolCodegen {
15931595
}
15941596
}
15951597

1598+
extension Parameter {
1599+
fileprivate var escapedSwiftIdentifier: String {
1600+
name.backtickIfNeeded()
1601+
}
1602+
}
1603+
15961604
extension WasmCoreType {
15971605
var swiftType: String {
15981606
switch self {

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

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1758,7 +1758,7 @@ public struct BridgeJSLink {
17581758
loweringFragment.parameters.count == 1,
17591759
"Lowering fragment should have exactly one parameter to lower"
17601760
)
1761-
let paramName = scope.variable(param.name)
1761+
let paramName = scope.variable(param.escapedJSIdentifier)
17621762
let loweredValues = try loweringFragment.printCode([paramName], context)
17631763
parameterForwardings.append(contentsOf: loweredValues)
17641764
}
@@ -1950,7 +1950,7 @@ public struct BridgeJSLink {
19501950
}
19511951
let parameterSignatures = parameters.map { param in
19521952
let optional = param.hasDefault ? "?" : ""
1953-
return "\(param.name)\(optional): \(resolveTypeScriptType(param.type))"
1953+
return "\(param.escapedJSIdentifier)\(optional): \(resolveTypeScriptType(param.type))"
19541954
}
19551955
return "(\(parameterSignatures.joined(separator: ", "))): \(returnTypeWithEffect)"
19561956
}
@@ -2669,7 +2669,7 @@ extension BridgeJSLink {
26692669
if let constructor = klass.constructor {
26702670
let paramSignatures = constructor.parameters.map { param in
26712671
let optional = param.hasDefault ? "?" : ""
2672-
return "\(param.name)\(optional): \(resolveTypeScriptType(param.type))"
2672+
return "\(param.escapedJSIdentifier)\(optional): \(resolveTypeScriptType(param.type))"
26732673
}
26742674
printer.write(
26752675
lines: renderJSDoc(documentation: constructor.documentation, parameters: constructor.parameters)
@@ -4321,9 +4321,9 @@ enum DefaultValueUtils {
43214321
return parameters.map { param in
43224322
if let defaultValue = param.defaultValue {
43234323
let defaultJs = format(defaultValue, as: .javascript, resolveTypeName: resolveTypeName)
4324-
return "\(param.name) = \(defaultJs)"
4324+
return "\(param.escapedJSIdentifier) = \(defaultJs)"
43254325
}
4326-
return param.name
4326+
return param.escapedJSIdentifier
43274327
}.joined(separator: ", ")
43284328
}
43294329
}
@@ -4348,11 +4348,11 @@ extension BridgeJSLink {
43484348
}
43494349
switch (docText, defaultValue) {
43504350
case let (.some(text), .some(value)):
4351-
tagLines.append("@param \(parameter.name) \(text) (default: \(value))")
4351+
tagLines.append("@param \(parameter.escapedJSIdentifier) \(text) (default: \(value))")
43524352
case let (.some(text), .none):
4353-
tagLines.append("@param \(parameter.name) \(text)")
4353+
tagLines.append("@param \(parameter.escapedJSIdentifier) \(text)")
43544354
case let (.none, .some(value)):
4355-
tagLines.append("@param \(parameter.name) - Optional parameter (default: \(value))")
4355+
tagLines.append("@param \(parameter.escapedJSIdentifier) - Optional parameter (default: \(value))")
43564356
case (.none, .none):
43574357
continue
43584358
}
@@ -4477,6 +4477,21 @@ struct BridgeJSLinkError: Error {
44774477
let message: String
44784478
}
44794479

4480+
extension Parameter {
4481+
// From: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#reserved_words
4482+
private static let javaScriptReservedWords: Set<String> = [
4483+
"break", "case", "catch", "class", "const", "continue", "debugger", "default", "delete", "do", "else",
4484+
"export", "extends", "false", "finally", "for", "function", "if", "import", "in", "instanceof", "new",
4485+
"null", "return", "super", "switch", "this", "throw", "true", "try", "typeof", "var", "void", "while",
4486+
"with", "let", "static", "yield", "await", "enum", "implements", "interface", "package", "private",
4487+
"protected", "public", "arguments", "eval",
4488+
]
4489+
4490+
fileprivate var escapedJSIdentifier: String {
4491+
Self.javaScriptReservedWords.contains(name) ? "_\(name)" : name
4492+
}
4493+
}
4494+
44804495
extension ClosureSignature {
44814496
fileprivate func renderTSFunctionType(renderType: (BridgeType) -> String) -> String {
44824497
let renderedParameters = parameters.enumerated().map { index, parameter in
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@JS func check(extension: Int, break: Double, function: Bool, in: String) {}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
{
2+
"exported" : {
3+
"aliases" : [
4+
5+
],
6+
"classes" : [
7+
8+
],
9+
"enums" : [
10+
11+
],
12+
"exposeToGlobal" : false,
13+
"functions" : [
14+
{
15+
"abiName" : "bjs_check",
16+
"effects" : {
17+
"isAsync" : false,
18+
"isStatic" : false,
19+
"isThrows" : false
20+
},
21+
"name" : "check",
22+
"parameters" : [
23+
{
24+
"label" : "extension",
25+
"name" : "extension",
26+
"type" : {
27+
"integer" : {
28+
"_0" : {
29+
"isSigned" : true,
30+
"width" : "word"
31+
}
32+
}
33+
}
34+
},
35+
{
36+
"label" : "break",
37+
"name" : "break",
38+
"type" : {
39+
"double" : {
40+
41+
}
42+
}
43+
},
44+
{
45+
"label" : "function",
46+
"name" : "function",
47+
"type" : {
48+
"bool" : {
49+
50+
}
51+
}
52+
},
53+
{
54+
"label" : "in",
55+
"name" : "in",
56+
"type" : {
57+
"string" : {
58+
59+
}
60+
}
61+
}
62+
],
63+
"returnType" : {
64+
"void" : {
65+
66+
}
67+
}
68+
}
69+
],
70+
"protocols" : [
71+
72+
],
73+
"structs" : [
74+
75+
]
76+
},
77+
"moduleName" : "TestModule",
78+
"usedExternalModules" : [
79+
80+
]
81+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
@_expose(wasm, "bjs_check")
2+
@_cdecl("bjs_check")
3+
public func _bjs_check(_ `extension`: Int32, _ `break`: Float64, _ function: Int32, _ inBytes: Int32, _ inLength: Int32) -> Void {
4+
#if arch(wasm32)
5+
let `in` = String.bridgeJSLiftParameter(inBytes, inLength)
6+
let function = Bool.bridgeJSLiftParameter(function)
7+
let `break` = Double.bridgeJSLiftParameter(`break`)
8+
let `extension` = Int.bridgeJSLiftParameter(`extension`)
9+
check(extension: `extension`, break: `break`, function: function, in: `in`)
10+
#else
11+
fatalError("Only available on WebAssembly")
12+
#endif
13+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
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+
export type Exports = {
8+
check(extension: number, _break: number, _function: boolean, _in: string): void;
9+
}
10+
export type Imports = {
11+
}
12+
export function createInstantiator(options: {
13+
imports: Imports;
14+
}, swift: any): Promise<{
15+
addImports: (importObject: WebAssembly.Imports) => void;
16+
setInstance: (instance: WebAssembly.Instance) => void;
17+
createExports: (instance: WebAssembly.Instance) => Exports;
18+
}>;

0 commit comments

Comments
 (0)