JavascriptCore extending Swift class

Is it possible to expose a swift class to JavascriptCore using JSExport and add a javascript subclass? I'm getting this weird behavior:


swift:

@objc protocol Person {

init()

func sayHi()

}

class PersonProxy: NSObject, Person {

required override init() {

super.init()

}


func sayHi() {

print("hi")

}

}

jsContext?.setObject(PersonProxy.self, forKeyedSubscript: "Person" as (NSCopying & NSObjectProtocol)!)


javascript:

class Employee extends Person {

constructor() {

super()

}


sayHello() {

console.log("hello")

}

}


var test = new Employee()

console.log("Is Employee: " + (test instanceof Employee)) // this prints "Is Employee: false"


test.sayHello() // this gives me "JS Exception: TypeError: test.sayHello is not a function"

I'm running into something quite similar, but even without the class extension.


import JavaScriptCore
let context = JSContext()!
@objc protocol PersonJSExports: JSExport {
    static func hi() -> String
}
@objc class Person: NSObject, PersonJSExports {
    class func hi() -> String { return "hello" }
}
context.exceptionHandler = { context, exception in
    print("Custom exception handler: \(exception?.description ?? "unknown error")")
}
context.setObject(Person.self, forKeyedSubscript: "Person" as NSString)
context.evaluateScript("Person.hi()")

// Prints:
// Custom exception handler: TypeError: Person.hi is not a function. (In 'Person.hi()', 'Person.hi' is undefined)


Did you find out what the trouble was?

How are you testing this? I tried your code and it worked for me. Specifically:

  1. I created a new project from the macOS > Command Line Tool template.

  2. I then replaced

    main.swift
    with your code.
  3. I tweaked the last line to print the result of the evaluation.

    let result = context.evaluateScript("Person.hi()")
    print(result)

    .

  4. When I ran the program I saw this:

    Optional(hello)

    .

This is Xcode 9.2 on macOS 10.13.3.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Ah, hmm! I was testing this in a Playground. It appears to work inside an application. That was surprising to me, since most of JavaScriptCore worked flawlessly in the playground. Thanks!

JavascriptCore extending Swift class
 
 
Q