Skip to content

BridgeJS: Escape reserved words in exported function parameters - #822

Open
wfltaylor wants to merge 1 commit into
swiftwasm:mainfrom
wfltaylor:escape-reserved-parameter-names
Open

wfltaylor wants to merge 1 commit into
swiftwasm:mainfrom
wfltaylor:escape-reserved-parameter-names

Conversation

@wfltaylor

Copy link
Copy Markdown
Contributor

Currently parameter names using reserved words, such as extension or break, generate invalid Swift and/or JS. Reserved words are now escaped with backticks in Swift and with a leading underscore in JS. Originally I removed the parameter names from the generated thunks entirely, just using param0 param1 etc., but this made the generated code harder to read.

}

extension Parameter {
fileprivate var escapedSwiftIdentifier: String {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JS func f(_ in: String) still generates invalid Swift and JS, because parseParameters (SwiftToSkeleton.swift:1590) keeps the backticks in param.name:

public func _bjs_f(_ `in`Bytes: Int32, _ `in`Length: Int32) -> Void {
f: function bjs_f(`in`) {
    const `in`Bytes = textEncoder.encode(`in`);

The import path already strips them with normalizeIdentifier. If this path does the same, the escaping in this PR covers both spellings:

let name = SwiftToSkeleton.normalizeIdentifier(param.secondName?.text ?? param.firstName.text)
@JS func checkEscaped(_ `in`: String) {}

"protected", "public", "arguments", "eval",
]

fileprivate var escapedJSIdentifier: String {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For @JS protocol Delegate { func handle(in: Int) } the d.ts now has handle(_in: number), but the glue still uses in:

TestModule["bjs_Delegate_handle"] = function bjs_Delegate_handle(self, in) {
func handle(in: Int) -> Void {
    let inValue = in.bridgeJSLowerParameter()

@JSFunction func f(in: Int) has the same problem. It would be good to resolve in this PR, but follow up is fine as well ✌️ The JS side is in ImportedThunkBuilder.liftParameter:

} else if liftingFragment.parameters.count == 1 {
    let name = scope.variable(param.escapedJSIdentifier)
    parameterNames.append(name)
    valuesToLift = [name]
}

The Swift side needs backtickIfNeeded() where CallJSEmission.lowerParameter reads param.name.

@@ -0,0 +1 @@
@JS func check(extension: Int, break: Double, function: Bool, in: String) {}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR also changes the constructor and method paths. They generate correctly today, and these cases would keep it that way:

@JS class ReservedWordBox {
    @JS init(in: Int) {}
    @JS func run(for: Int) {}
    @JS static func make(default: Int) -> Int { 0 }
}

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants