Monday, January 30, 2023

Using JavaScript in a Swift App

Douglas Hill:

If you’re writing an iOS app using Swift and trying to solve a problem you’re sure has been solved before, you may look for existing code that solves that problem. It’s likely you’ll first think of looking for open source code written in Swift[…] However, we don’t need to limit ourselves to Swift. […] In this article, we’ll look at how to call JavaScript code from Swift using JavaScriptCore.

[…]

This sort of code is inviting code injection security vulnerabilities. Instead, we can set our input URL as a variable in the JavaScript environment and then reference it by name.

JSContext lets us read variables (in Swift) from JavaScript using objectForKeyedSubscript(_:) and set variables using setObject(_:forKeyedSubscript). Oddly, this API is nicer to use in Objective-C since these map to subscript syntax so you can read and set values like in a dictionary. Subscript syntax doesn’t seem to work in Swift here.

1 Comment RSS · Twitter · Mastodon

To get keyed subscripts, I suppose a simple Swift extension on JSContext would do? Like

extension JSContext {
  subscript(_ key: String) -> JSValue? {
    set { setObject(newValue, forKeyedSubscript: key) }
    get { objectForKeyedSubscript(key) }
  }
  subscript(_ key: Int) -> JSValue? {
    set { setObject(newValue, forKeyedSubscript: key) }
    get { objectForKeyedSubscript(key) }
  }
}

And maybe even little convenience extension to extract actual values, like:

extension JSContext {
  subscript(int key: String) -> Int? {
    set { self[key] = newValue }
    get { (self[key] as? NSNumber)?.intValue }
  }
}

etc...

Leave a Comment