Description
When building for Embedded Swift, JSValue
and JSObject
don’t support JS function calls with more than 2 arguments. I noticed this when trying to call the fillRect()
method on CanvasRenderingContext2D
. Example:
import JavaScriptKit
let document = JSObject.global.document
let canvas = document.getElementById("canvas")
var ctx: JSValue = canvas.getContext("2d")
// 🔴 Error (in Embedded Swift only): cannot call value of non-function type 'JSValue'
_ = ctx.fillRect(20, 20, 200, 100)
The following works as a workaround but is ugly:
_ = ctx.object!.fillRect.function!(this: ctx.object!, arguments: [20, 20, 200, 100])
The reason that it doesn't work is:
-
Embedded Swift doesn't support existentials, so the general function invocation mechanism of the form
subscript(dynamicMember name: String) -> ((ConvertibleToJSValue...) -> JSValue)
is not available. -
Both
JSValue
andJSObject
only have concrete overloads for up to 2 function call arguments:#if hasFeature(Embedded) public extension JSValue { @_disfavoredOverload subscript(dynamicMember name: String) -> (() -> JSValue) @_disfavoredOverload subscript<A0: ConvertibleToJSValue>(dynamicMember name: String) -> ((A0) -> JSValue) @_disfavoredOverload subscript<A0: ConvertibleToJSValue, A1: ConvertibleToJSValue>(dynamicMember name: String) -> ((A0, A1) -> JSValue) } #endif
Question: Would you be interested in a PR that adds more of these concrete overloads for Embedded Swift? Or do you want to wait for variadic generics support in Embedded Swift to solve this problem "the right way"?
If it's the former, I'm willing to send the PR. In this case, up to how many arguments should I go? Is 4 enough? Or should we go up to, say, 6?