gervais.b
gervais.b

Reputation: 2347

Is it some alternatives to "implements" traits with ScalaJs and Javascript

I have this code that I would like to be able to execute as Javascript :

@JSExport
class Feeder {

  @JSExport
  def feed(feedable: Feedable): Unit = {
    feedable.feed();
  }
}

trait Feedable {
  def feed()
}

Of course traits cannot be exported, but I expected that a kind of pattern matching was enough. So I tried to create a Javascript object with a feed function but It fail too :

var feeder = new test.Feeder();
var feedable = new function() {
  this.feed = function() {
    console.log('Feeding javascript');
  }
}
feeder.feed(feedable);

But that raise an exception :

scala.scalajs.runtime.UndefinedBehaviorError: An undefined behavior was detected: [object Object] is not an instance of test.Feedable

Is it a way to achieve this behavior ?

Upvotes: 0

Views: 171

Answers (2)

sjrd
sjrd

Reputation: 22105

Here you actually want to declare Feedable as a JavaScript type, not a Scala type. So you have to declare it as extending js.Object like this:

trait Feedable extends js.Object {
  def feed(): Unit = js.native
}

Extending js.Object turns Feedable into a raw JS type, which the Scala.js compiler knows to manipulate with JavaScript semantics instead of Scala semantics.

Upvotes: 0

Justin du Coeur
Justin du Coeur

Reputation: 2659

I can't say I'm 100% certain what you're trying to accomplish, but it looks like you're trying to define the feed function from JavaScript. In which case, you don't want to be exporting a Scala class, you want to define Feedable as a facade instead:

trait Feedable extends js.Object {
  def feed():Unit = js.native
}

That's the only way that this code:

this.feed = function() {
  console.log('Feeding javascript');
}

seems to make any sense.

Facades are how you tell Scala about the structure of JavaScript code, which appears to be what you're trying to do here. See the page on calling JavaScript from Scala for more details...

Upvotes: 3

Related Questions