monnef monnef - 1 year ago 61
Scala Question

Scala.js and ClassTag results in crash

I have following code in Scala and it works fine:

object TestVanilla {
def callMe[A: ClassTag](f: Int => A): Array[A] = Array(f(4))

val res = TestVanilla.callMe(_ + "x");
println(res.mkString(", "));



full code:

I rewrote it to ScalaJS, but it seems to be crashing on the tag:

@JSExport("Test") object TestScalaJs {
@JSExport def callMe[A: ClassTag](f: js.Function1[Int, A]): Array[A] = Array(f(4))

Call from JS:

var res = Test().callMe(function(x) {return x + 'x';});
console.log('TestScalaJs:', res.join(', '));


$c_jl_Throwable.fillInStackTrace__jl_Throwable @ VM153:4161
$c_sjsr_UndefinedBehaviorError.fillInStackTrace__jl_Throwable @ VM153:9241
$c_jl_Throwable.init___T__jl_Throwable @ VM153:4177
$c_sjsr_UndefinedBehaviorError.init___T__jl_Throwable @ VM153:9248
$c_sjsr_UndefinedBehaviorError.init___jl_Throwable @ VM153:9244
$throwClassCastException @ VM153:196
$as_s_reflect_ClassTag @ VM153:7824
$c_LTestScalaJs$.callMe @ VM153:2061
(anonymous function) @ VM155:2
$s_Lscalatags_jsdom_Frag$class__applyTo__Lscalatags_jsdom_Frag__Lorg_scalajs_dom_raw_Element__V @ VM153:1108
$c_Lscalatags_JsDom$TypedTag.applyTo__O__V @ VM153:9981
$c_Lfiddle_Fiddle$.println__sc_Seq__V @ VM153:2113
$c_LScalaFiddle$.init___ @ VM153:2021
$m_LScalaFiddle$ @ VM153:2034
(anonymous function) @ VM154:1
(anonymous function) @ VM77 resultframe?theme=light:32

full code:

Scala.js doesn't support
s? Or am I doing something wrong?

EDIT2: Created a follow up question. This one is answered, even though it didn't actually solve anything for me - my bad, I asked poorly.

Don't answer the EDIT1 here please, but rather in the follow-up question.

EDIT1: I didn't make myself clear. The code is a simplified issue from tiny library I wanted to write in ScalaJS and the library is meant to be used from JavaScript. I am looking for a way how to solve this rather trivial looking issue - creation of type-safe array and in a same time allowing JS to actually be able to easily call the method. Maybe some proxy/facade can be used?

Answer Source

Scala.js does support ClassTags. Your issue is that you're expecting JavaScript to fill in Scala implicit parameters, which it cannot do. Your method definition

@JSExport def callMe[A: ClassTag](f: js.Function1[Int, A]): Array[A] = Array(f(4))

is, as usual in Scala, equivalent to

@JSExport def callMe[A](f: js.Function1[Int, A])(implicit ct: ClassTag[A]): Array[A] = Array(f(4))

which clearly highlights that there are 2 parameters to callMe. The Scala typechecker can automatically fill in the second (implicit) parameter, but JavaScript cannot do that. From JavaScript, you would have to explicitly pass the second parameter.