summaryrefslogtreecommitdiff
path: root/test-suite/src/test/scala/scala/scalajs/testsuite/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'test-suite/src/test/scala/scala/scalajs/testsuite/compiler')
-rw-r--r--test-suite/src/test/scala/scala/scalajs/testsuite/compiler/BooleanTest.scala41
-rw-r--r--test-suite/src/test/scala/scala/scalajs/testsuite/compiler/ByteTest.scala40
-rw-r--r--test-suite/src/test/scala/scala/scalajs/testsuite/compiler/CharTest.scala40
-rw-r--r--test-suite/src/test/scala/scala/scalajs/testsuite/compiler/FloatTest.scala73
-rw-r--r--test-suite/src/test/scala/scala/scalajs/testsuite/compiler/InstanceTestsHijackedBoxedClassesTest.scala98
-rw-r--r--test-suite/src/test/scala/scala/scalajs/testsuite/compiler/IntTest.scala206
-rw-r--r--test-suite/src/test/scala/scala/scalajs/testsuite/compiler/InteroperabilityTest.scala528
-rw-r--r--test-suite/src/test/scala/scala/scalajs/testsuite/compiler/LongTest.scala159
-rw-r--r--test-suite/src/test/scala/scala/scalajs/testsuite/compiler/OptimizerTest.scala43
-rw-r--r--test-suite/src/test/scala/scala/scalajs/testsuite/compiler/ReflectionTest.scala69
-rw-r--r--test-suite/src/test/scala/scala/scalajs/testsuite/compiler/ReflectiveCallTest.scala330
-rw-r--r--test-suite/src/test/scala/scala/scalajs/testsuite/compiler/RegressionTest.scala287
-rw-r--r--test-suite/src/test/scala/scala/scalajs/testsuite/compiler/RuntimeTypesTest.scala77
-rw-r--r--test-suite/src/test/scala/scala/scalajs/testsuite/compiler/ShortTest.scala38
-rw-r--r--test-suite/src/test/scala/scala/scalajs/testsuite/compiler/UnitTest.scala47
15 files changed, 2076 insertions, 0 deletions
diff --git a/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/BooleanTest.scala b/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/BooleanTest.scala
new file mode 100644
index 0000000..8343244
--- /dev/null
+++ b/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/BooleanTest.scala
@@ -0,0 +1,41 @@
+/* __ *\
+** ________ ___ / / ___ __ ____ Scala.js Test Suite **
+** / __/ __// _ | / / / _ | __ / // __/ (c) 2013, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ **
+** /____/\___/_/ |_/____/_/ | |__/ /____/ **
+** |/____/ **
+\* */
+package scala.scalajs.testsuite.compiler
+
+import org.scalajs.jasminetest.JasmineTest
+import scala.scalajs.js
+
+object BooleanTest extends JasmineTest {
+
+ describe("Boolean primitives") {
+
+ it("&, | and ^ on booleans should return booleans") {
+ expect(js.typeOf(true & false)).toEqual("boolean")
+ expect(js.typeOf(true | false)).toEqual("boolean")
+ expect(js.typeOf(true ^ false)).toEqual("boolean")
+ }
+
+ it("&, | and ^ on booleans should return correct results") {
+ expect(false & false).toBeFalsy
+ expect(false & true).toBeFalsy
+ expect(true & false).toBeFalsy
+ expect(true & true).toBeTruthy
+
+ expect(false | false).toBeFalsy
+ expect(true | false).toBeTruthy
+ expect(false | true).toBeTruthy
+ expect(true | true).toBeTruthy
+
+ expect(false ^ false).toBeFalsy
+ expect(true ^ false).toBeTruthy
+ expect(false ^ true).toBeTruthy
+ expect(true ^ true).toBeFalsy
+ }
+
+ }
+}
diff --git a/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/ByteTest.scala b/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/ByteTest.scala
new file mode 100644
index 0000000..9f48993
--- /dev/null
+++ b/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/ByteTest.scala
@@ -0,0 +1,40 @@
+/* __ *\
+** ________ ___ / / ___ __ ____ Scala.js Test Suite **
+** / __/ __// _ | / / / _ | __ / // __/ (c) 2013, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ **
+** /____/\___/_/ |_/____/_/ | |__/ /____/ **
+** |/____/ **
+\* */
+package scala.scalajs.testsuite.compiler
+
+import org.scalajs.jasminetest.JasmineTest
+import scala.scalajs.js
+
+object ByteTest extends JasmineTest {
+
+ describe("Byte primitives") {
+
+ it("should always be in their range") {
+ def test(x: Int, y: Byte): Unit =
+ expect(x.toByte).toEqual(y)
+
+ test(0, 0)
+ test(127, 127)
+ test(128, -128)
+ test(-128, -128)
+ test(-500, 12)
+ test(-90000, 112)
+ test(123456789, 21)
+ test(-40000, -64)
+ test(65536, 0)
+ test(32768, 0)
+
+ def testC(x: Char, y: Byte): Unit =
+ expect(x.toByte).toEqual(y)
+
+ testC(-1.toChar, -1)
+ testC(200.toChar, -56)
+ }
+
+ }
+}
diff --git a/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/CharTest.scala b/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/CharTest.scala
new file mode 100644
index 0000000..edc2660
--- /dev/null
+++ b/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/CharTest.scala
@@ -0,0 +1,40 @@
+/* __ *\
+** ________ ___ / / ___ __ ____ Scala.js Test Suite **
+** / __/ __// _ | / / / _ | __ / // __/ (c) 2013, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ **
+** /____/\___/_/ |_/____/_/ | |__/ /____/ **
+** |/____/ **
+\* */
+package scala.scalajs.testsuite.compiler
+
+import org.scalajs.jasminetest.JasmineTest
+import scala.scalajs.js.Any.fromInt
+
+object CharTest extends JasmineTest {
+
+ describe("Char primitives") {
+
+ it("should always be positive (when coerced)") {
+ expect(-3.toByte.toChar.toInt).toEqual(65533)
+ expect(-100.toShort.toChar.toInt).toEqual(65436)
+ expect(-66000.toChar.toInt).toEqual(65072)
+ expect(-4567L.toChar.toInt).toEqual(60969)
+ expect(-5.3f.toChar.toInt).toEqual(65531)
+ expect(-7.9.toChar.toInt).toEqual(65529)
+ }
+
+ it("should overflow (when coerced)") {
+ expect(347876543.toChar.toInt).toEqual(11455)
+ expect(34234567876543L.toChar.toInt).toEqual(57279)
+ }
+
+ it("should overflow with *") {
+ def test(a: Char, b: Char, expected: Int): Unit =
+ expect(a * b).toEqual(expected)
+
+ // note: expected values are constant-folded by the compiler on the JVM
+ test(Char.MaxValue, Char.MaxValue, Char.MaxValue * Char.MaxValue)
+ }
+
+ }
+}
diff --git a/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/FloatTest.scala b/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/FloatTest.scala
new file mode 100644
index 0000000..5eda04a
--- /dev/null
+++ b/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/FloatTest.scala
@@ -0,0 +1,73 @@
+/* __ *\
+** ________ ___ / / ___ __ ____ Scala.js Test Suite **
+** / __/ __// _ | / / / _ | __ / // __/ (c) 2013, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ **
+** /____/\___/_/ |_/____/_/ | |__/ /____/ **
+** |/____/ **
+\* */
+package scala.scalajs.testsuite.compiler
+
+import org.scalajs.jasminetest.JasmineTest
+
+object FloatTest extends JasmineTest {
+
+ def froundNotInlined(x: Double): Float = {
+ val y = x // so you don't inline me
+ y.toFloat
+ }
+
+ when("strict-floats").
+ describe("Strict floats") {
+
+ it("fround for special values") {
+ expect(froundNotInlined(Double.NaN).isNaN).toBeTruthy
+ expect(1 / froundNotInlined(0.0).toDouble).toBe(Double.PositiveInfinity)
+ expect(1 / froundNotInlined(-0.0).toDouble).toBe(Double.NegativeInfinity)
+ expect(froundNotInlined(Double.PositiveInfinity)).toBe(Float.PositiveInfinity)
+ expect(froundNotInlined(Double.NegativeInfinity)).toBe(Float.NegativeInfinity)
+ }
+
+ it("fround overflows") {
+ expect(froundNotInlined(1e200)).toBe(Double.PositiveInfinity)
+ expect(froundNotInlined(-1e200)).toBe(Double.NegativeInfinity)
+ }
+
+ it("fround underflows") {
+ expect(1 / froundNotInlined(1e-300).toDouble).toBe(Double.PositiveInfinity)
+ expect(1 / froundNotInlined(-1e-300).toDouble).toBe(Double.NegativeInfinity)
+ }
+
+ it("fround normal cases") {
+ def test(input: Double, expected: Double): Unit =
+ expect(input.toFloat.toDouble).toBe(expected)
+
+ // From MDN documentation
+ test(0.0, 0.0)
+ test(1.0, 1.0)
+ test(1.5, 1.5)
+ test(1.337, 1.3370000123977661)
+ test(-4.3, -4.300000190734863)
+
+ // Some bounds
+ test(Float.MinPositiveValue.toDouble, Float.MinPositiveValue.toDouble)
+ test(Float.MaxValue.toDouble, Float.MaxValue.toDouble)
+ test(Float.MinValue.toDouble, Float.MinValue.toDouble)
+
+ // Randomly generated Doubles
+ test(2.705609035558863E20, 2.7056090763400262E20)
+ test(-1.447710531503027E15, -1.447710532042752E15)
+ test(-5.1970024617732836E13, -5.1970022834176E13)
+ test(1.627661085098256E31, 1.6276610930768024E31)
+ test(-3.7731947682593834E-32, -3.7731946313230934E-32)
+ test(34.48229849163326, 34.4822998046875)
+ test(26.62034396181652, 26.620344161987305)
+ test(8.198435190113375E-24, 8.198434961596576E-24)
+ test(-6.079928908440255E-23, -6.079928963558556E-23)
+ test(3.3756949828462674E-13, 3.37569490589662E-13)
+ test(-1.2599049874324274E33, -1.2599049641449257E33)
+ test(6.08574575776438E-10, 6.085745796191588E-10)
+ test(1.973497969450596E-21, 1.973498047135062E-21)
+ }
+
+ }
+}
diff --git a/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/InstanceTestsHijackedBoxedClassesTest.scala b/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/InstanceTestsHijackedBoxedClassesTest.scala
new file mode 100644
index 0000000..1379b80
--- /dev/null
+++ b/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/InstanceTestsHijackedBoxedClassesTest.scala
@@ -0,0 +1,98 @@
+/* __ *\
+** ________ ___ / / ___ __ ____ Scala.js Test Suite **
+** / __/ __// _ | / / / _ | __ / // __/ (c) 2013, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ **
+** /____/\___/_/ |_/____/_/ | |__/ /____/ **
+** |/____/ **
+\* */
+package scala.scalajs.testsuite.compiler
+
+import org.scalajs.jasminetest.JasmineTest
+import scala.scalajs.js
+
+object InstanceTestsHijackedBoxedClassesTest extends JasmineTest {
+
+ describe("Instance tests for hijacked boxed classes") {
+
+ it("should support isInstanceOf (positive)") {
+ expect((() : Any).isInstanceOf[Unit] ).toBeTruthy
+ expect((false : Any).isInstanceOf[Boolean]).toBeTruthy
+ expect(('a' : Any).isInstanceOf[Char] ).toBeTruthy
+ expect((65.toByte : Any).isInstanceOf[Byte] ).toBeTruthy
+ expect((654.toShort: Any).isInstanceOf[Short] ).toBeTruthy
+ expect((-4321 : Any).isInstanceOf[Int] ).toBeTruthy
+ expect((684321L : Any).isInstanceOf[Long] ).toBeTruthy
+ expect((3.14f : Any).isInstanceOf[Float] ).toBeTruthy
+ expect((3.14 : Any).isInstanceOf[Double] ).toBeTruthy
+ }
+
+ it("should support isInstanceOf (negative)") {
+ expect((12345: Any).isInstanceOf[Unit] ).toBeFalsy
+ expect((12345: Any).isInstanceOf[Boolean]).toBeFalsy
+ expect((12345: Any).isInstanceOf[Char] ).toBeFalsy
+ expect(('a' : Any).isInstanceOf[Byte] ).toBeFalsy
+ expect(('b' : Any).isInstanceOf[Short] ).toBeFalsy
+ expect(('c' : Any).isInstanceOf[Int] ).toBeFalsy
+ expect(('d' : Any).isInstanceOf[Long] ).toBeFalsy
+ expect(('f' : Any).isInstanceOf[Float] ).toBeFalsy
+ expect(('g' : Any).isInstanceOf[Double] ).toBeFalsy
+ }
+
+ it("should support asInstanceOf (positive)") {
+ def swallow(x: Any): Unit = ()
+ swallow((() : Any).asInstanceOf[Unit] )
+ swallow((false : Any).asInstanceOf[Boolean])
+ swallow(('a' : Any).asInstanceOf[Char] )
+ swallow((65.toByte : Any).asInstanceOf[Byte] )
+ swallow((654.toShort: Any).asInstanceOf[Short] )
+ swallow((-4321 : Any).asInstanceOf[Int] )
+ swallow((684321L : Any).asInstanceOf[Long] )
+ swallow((3.14f : Any).asInstanceOf[Float] )
+ swallow((3.14 : Any).asInstanceOf[Double] )
+ }
+
+ when("compliant-asinstanceof").
+ it("should support asInstanceOf (negative)") {
+ expect(() => (12345: Any).asInstanceOf[Unit] ).toThrow
+ expect(() => (12345: Any).asInstanceOf[Boolean]).toThrow
+ expect(() => (12345: Any).asInstanceOf[Char] ).toThrow
+ expect(() => ('a' : Any).asInstanceOf[Byte] ).toThrow
+ expect(() => ('b' : Any).asInstanceOf[Short] ).toThrow
+ expect(() => ('c' : Any).asInstanceOf[Int] ).toThrow
+ expect(() => ('d' : Any).asInstanceOf[Long] ).toThrow
+ expect(() => ('f' : Any).asInstanceOf[Float] ).toThrow
+ expect(() => ('g' : Any).asInstanceOf[Double] ).toThrow
+ }
+
+ it("should support isInstanceOf via java.lang.Class (positive)") {
+ def test(x: Any, clazz: Class[_]): Unit =
+ expect(clazz.isInstance(x)).toBeTruthy
+
+ test(() , classOf[scala.runtime.BoxedUnit])
+ test(false , classOf[java.lang.Boolean])
+ test('a' , classOf[java.lang.Character])
+ test(65.toByte , classOf[java.lang.Byte])
+ test(654.toShort, classOf[java.lang.Short])
+ test(-4321 , classOf[java.lang.Integer])
+ test(684321L , classOf[java.lang.Long])
+ test(3.14f , classOf[java.lang.Float])
+ test(3.14 , classOf[java.lang.Double])
+ }
+
+ it("should support isInstanceOf via java.lang.Class (negative)") {
+ def test(x: Any, clazz: Class[_]): Unit =
+ expect(clazz.isInstance(x)).toBeFalsy
+
+ test(12345, classOf[scala.runtime.BoxedUnit])
+ test(12345, classOf[java.lang.Boolean])
+ test(12345, classOf[java.lang.Character])
+ test('a' , classOf[java.lang.Byte])
+ test('b' , classOf[java.lang.Short])
+ test('c' , classOf[java.lang.Integer])
+ test('d' , classOf[java.lang.Long])
+ test('e' , classOf[java.lang.Float])
+ test('f' , classOf[java.lang.Double])
+ }
+
+ }
+}
diff --git a/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/IntTest.scala b/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/IntTest.scala
new file mode 100644
index 0000000..60f8773
--- /dev/null
+++ b/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/IntTest.scala
@@ -0,0 +1,206 @@
+/* __ *\
+** ________ ___ / / ___ __ ____ Scala.js Test Suite **
+** / __/ __// _ | / / / _ | __ / // __/ (c) 2013, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ **
+** /____/\___/_/ |_/____/_/ | |__/ /____/ **
+** |/____/ **
+\* */
+package scala.scalajs.testsuite.compiler
+
+import org.scalajs.jasminetest.JasmineTest
+
+object IntTest extends JasmineTest {
+
+ /* General note on the way these tests are written:
+ * We leverage the constant folding applied by the Scala compiler to write
+ * sound tests. We always perform the same operation, on the same operands,
+ * once in a way constant folding understands, and once in a way it doesn't.
+ * Since constant folding is performed on the JVM, we know it has the right
+ * semantics.
+ */
+
+ // final val without type ascription to make sure these are constant-folded
+ final val MinVal = Int.MinValue
+ final val MaxVal = Int.MaxValue
+ final val AlmostMinVal = Int.MinValue + 43
+ final val AlmostMaxVal = Int.MaxValue - 36
+
+ describe("Int primitives") {
+
+ it("should support unary -") {
+ def test(a: Int, expected: Int): Unit =
+ expect(-a).toEqual(expected)
+
+ test(56, -56)
+ test(0, 0)
+ test(-36, 36)
+
+ test(MaxVal, -MaxVal)
+ test(MinVal, -MinVal)
+ test(-MaxVal, MaxVal)
+ test(AlmostMinVal, -AlmostMinVal)
+ test(AlmostMaxVal, -AlmostMaxVal)
+ }
+
+ it("should support +") {
+ def test(a: Int, b: Int, expected: Int): Unit =
+ expect(a + b).toEqual(expected)
+
+ test(56, 654, 56 + 654)
+ test(0, 25, 0 + 25)
+ test(-36, 13, -36 + 13)
+
+ test(MaxVal, 1, MaxVal + 1)
+ test(MinVal, -1, MinVal - 1)
+ test(MaxVal, MinVal, MaxVal + MinVal)
+ test(AlmostMinVal, -100, AlmostMinVal - 100)
+ test(AlmostMaxVal, 123, AlmostMaxVal + 123)
+ }
+
+ it("should support -") {
+ def test(a: Int, b: Int, expected: Int): Unit =
+ expect(a - b).toEqual(expected)
+
+ test(56, 654, 56 - 654)
+ test(0, 25, 0 - 25)
+ test(-36, 13, -36 - 13)
+
+ test(MaxVal, -1, MaxVal + 1)
+ test(MinVal, 1, MinVal - 1)
+ test(MaxVal, MinVal, MaxVal - MinVal)
+ test(AlmostMinVal, 100, AlmostMinVal - 100)
+ test(AlmostMaxVal, -123, AlmostMaxVal + 123)
+ }
+
+ it("should support *") {
+ def test(a: Int, b: Int, expected: Int): Unit =
+ expect(a * b).toEqual(expected)
+
+ test(56, 654, 56 * 654)
+ test(0, 25, 0 * 25)
+ test(-36, 13, -36 * 13)
+ test(-5, -6, -5 * -6)
+
+ test(MinVal, 1, MinVal * 1)
+ test(MinVal, -1, MinVal * -1)
+ test(MaxVal, 1, MaxVal * 1)
+ test(MaxVal, -1, MaxVal * -1)
+
+ test(MaxVal, MinVal, MaxVal * MinVal)
+ test(MaxVal, MaxVal, MaxVal * MaxVal)
+ test(MinVal, MaxVal, MinVal * MaxVal)
+ test(MinVal, MinVal, MinVal * MinVal)
+
+ test(AlmostMaxVal, 2, AlmostMaxVal * 2)
+ test(AlmostMaxVal, 5, AlmostMaxVal * 5)
+ test(AlmostMaxVal, -7, AlmostMaxVal * -7)
+ test(AlmostMaxVal, -14, AlmostMaxVal * -14)
+ test(AlmostMinVal, 100, AlmostMinVal * 100)
+ test(AlmostMaxVal, -123, AlmostMaxVal * -123)
+ }
+
+ it("should support /") {
+ def test(a: Int, b: Int, expected: Int): Unit =
+ expect(a / b).toEqual(expected)
+
+ test(654, 56, 654 / 56)
+ test(0, 25, 0 / 25)
+ test(-36, 13, -36 / 13)
+ test(-55, -6, -55 / -6)
+
+ test(MinVal, 1, MinVal / 1)
+ test(MinVal, -1, MinVal / -1)
+ test(MaxVal, 1, MaxVal / 1)
+ test(MaxVal, -1, MaxVal / -1)
+
+ test(MaxVal, MinVal, MaxVal / MinVal)
+ test(MaxVal, MaxVal, MaxVal / MaxVal)
+ test(MinVal, MaxVal, MinVal / MaxVal)
+ test(MinVal, MinVal, MinVal / MinVal)
+
+ test(AlmostMaxVal, 2, AlmostMaxVal / 2)
+ test(AlmostMaxVal, 5, AlmostMaxVal / 5)
+ test(AlmostMaxVal, -7, AlmostMaxVal / -7)
+ test(AlmostMaxVal, -14, AlmostMaxVal / -14)
+ test(AlmostMinVal, 100, AlmostMinVal / 100)
+ test(AlmostMaxVal, -123, AlmostMaxVal / -123)
+ }
+
+ unless("phantomjs"). // see #593
+ it("should support %") {
+ def test(a: Int, b: Int, expected: Int): Unit =
+ expect(a % b).toEqual(expected)
+
+ test(654, 56, 654 % 56)
+ test(0, 25, 0 % 25)
+ test(-36, 13, -36 % 13)
+ test(-55, -6, -55 % -6)
+
+ test(MinVal, 1, MinVal % 1)
+ test(MinVal, -1, MinVal % -1)
+ test(MaxVal, 1, MaxVal % 1)
+ test(MaxVal, -1, MaxVal % -1)
+
+ test(MaxVal, MinVal, MaxVal % MinVal)
+ test(MaxVal, MaxVal, MaxVal % MaxVal)
+ test(MinVal, MaxVal, MinVal % MaxVal)
+ test(MinVal, MinVal, MinVal % MinVal)
+
+ test(AlmostMaxVal, 2, AlmostMaxVal % 2)
+ test(AlmostMaxVal, 5, AlmostMaxVal % 5)
+ test(AlmostMaxVal, -7, AlmostMaxVal % -7)
+ test(AlmostMaxVal, -14, AlmostMaxVal % -14)
+ test(AlmostMinVal, 100, AlmostMinVal % 100)
+ test(AlmostMaxVal, -123, AlmostMaxVal % -123)
+ }
+
+ it("should support <<") {
+ def test(a: Int, b: Int, expected: Int): Unit =
+ expect(a << b).toEqual(expected)
+
+ test(0, 5, 0 << 5)
+ test(1, 5, 1 << 5)
+ test(13, 4, 13 << 4)
+ test(-35, 5, -35 << 5)
+ test(345, 0, 345 << 0)
+
+ test(MinVal, 0, MinVal << 0)
+ test(MaxVal, 0, MaxVal << 0)
+ test(MinVal, 1, MinVal << 1)
+ test(MaxVal, 1, MaxVal << 1)
+ }
+
+ it("should support >>") {
+ def test(a: Int, b: Int, expected: Int): Unit =
+ expect(a >> b).toEqual(expected)
+
+ test(0, 5, 0 >> 5)
+ test(32, 5, 32 >> 5)
+ test(31, 4, 31 >> 4)
+ test(-355, 5, -355 >> 5)
+ test(345, 0, 345 >> 0)
+
+ test(MinVal, 0, MinVal >> 0)
+ test(MaxVal, 0, MaxVal >> 0)
+ test(MinVal, 1, MinVal >> 1)
+ test(MaxVal, 1, MaxVal >> 1)
+ }
+
+ it("should support >>>") {
+ def test(a: Int, b: Int, expected: Int): Unit =
+ expect(a >>> b).toEqual(expected)
+
+ test(0, 5, 0 >>> 5)
+ test(32, 5, 32 >>> 5)
+ test(31, 4, 31 >>> 4)
+ test(-355, 5, -355 >>> 5)
+ test(345, 0, 345 >>> 0)
+
+ test(MinVal, 0, MinVal >>> 0)
+ test(MaxVal, 0, MaxVal >>> 0)
+ test(MinVal, 1, MinVal >>> 1)
+ test(MaxVal, 1, MaxVal >>> 1)
+ }
+
+ }
+}
diff --git a/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/InteroperabilityTest.scala b/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/InteroperabilityTest.scala
new file mode 100644
index 0000000..594345a
--- /dev/null
+++ b/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/InteroperabilityTest.scala
@@ -0,0 +1,528 @@
+/* __ *\
+** ________ ___ / / ___ __ ____ Scala.js Test Suite **
+** / __/ __// _ | / / / _ | __ / // __/ (c) 2013, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ **
+** /____/\___/_/ |_/____/_/ | |__/ /____/ **
+** |/____/ **
+\* */
+package scala.scalajs.testsuite.compiler
+
+import scala.scalajs.js
+import org.scalajs.jasminetest.{JasmineTest, JasmineTestFramework}
+import scala.scalajs.js.annotation._
+
+/*
+ * Based on examples in:
+ * http://lampwww.epfl.ch/~doeraene/scala-js/doc/js-interoperability.html
+ */
+object InteroperabilityTest extends JasmineTest {
+
+ describe("JavaScript interoperability") {
+
+ it("should support backquotes to escape Scala fields") {
+ val obj = js.eval("""
+ var interoperabilityTestFieldEscape = {
+ def: 0,
+ val: function(x) { if (x) this.def = x; return this.def; }
+ };
+ interoperabilityTestFieldEscape;
+ """).asInstanceOf[InteroperabilityTestFieldEscape]
+
+ obj.`def` = 7357
+ expect(obj.`def`).toEqual(7357)
+ expect(obj.`val`()).toEqual(7357)
+ expect(obj.`val`(42)).toEqual(42)
+ }
+
+ it("should support @JSName to specify the JavaScript name for fields") {
+ val obj = js.eval("""
+ var interoperabilityTestJSName = {
+ def: 42,
+ val: function(x) { if (x) this.def = x; return this.def; }
+ };
+ interoperabilityTestJSName;
+ """).asInstanceOf[InteroperabilityTestJSName]
+
+ expect(obj.value()).toEqual(42)
+ expect(obj.value(7357)).toEqual(7357)
+ }
+
+ it("should translate explicit getter and setter names to field access") {
+ val obj = js.eval("""
+ var interoperabilityTestProperty = { a: 1 };
+ interoperabilityTestProperty;
+ """).asInstanceOf[InteroperabilityTestProperty]
+
+ expect(obj.a).toEqual(1)
+ obj.a = 100
+ expect(obj.a).toEqual(100)
+ }
+
+ it("should support @JSName together with field access") {
+ val obj = js.eval("""
+ var interoperabilityTestProperty = { b: 1 };
+ interoperabilityTestProperty;
+ """).asInstanceOf[InteroperabilityTestPropertyNamed]
+
+ expect(obj.a).toEqual(1)
+ obj.a = 100
+ expect(obj.a).toEqual(100)
+ expect(obj.b).toEqual(100)
+ }
+
+ it("should support @JSBracketAccess to specify access using []-subscription") {
+ val obj = js.eval("""
+ var interoperabilityTestJSBracketAccess = [ 0, 1, 7357 ];
+ interoperabilityTestJSBracketAccess;
+ """).asInstanceOf[InteroperabilityTestJSBracketAccess]
+
+ expect(obj(2)).toEqual(7357)
+ obj(2) = 42
+ expect(obj(2)).toEqual(42)
+ }
+
+ it("should allow instanciation of JS classes inheriting from js.Object") {
+ js.eval("""
+ var InteroperabilityTestInherit = {
+ Pattern: function(x) {
+ this.field = 42;
+ this.method = function() {
+ return '42';
+ };
+ this.getConstructorParam = function() {
+ return x;
+ };
+ }
+ }
+ """)
+
+ val obj = new InteroperabilityTestPattern("Scala.js")
+ expect(obj.field).toEqual(42)
+ expect(obj.method).toEqual("42")
+ expect(obj.getConstructorParam).toEqual("Scala.js")
+ }
+
+ it("should acces top-level JS objects via Scala objects inheriting from js.Object") {
+ js.eval("""
+ var InteroperabilityTestTopLevelObject = function(value) {
+ return {
+ value: value,
+ valueAsInt: function() {
+ return parseInt(value);
+ }
+ };
+ }
+ """)
+
+ // Use alias for convenience: see end of file for definition
+ val TopLevel = InteroperabilityTestTopLevel
+
+ val obj = TopLevel("7357")
+ expect(obj.value).toEqual("7357")
+ expect(obj.valueAsInt).toEqual(7357)
+ }
+
+ it("should allow to call JS methods with variadic parameters") {
+ val obj = js.eval("""
+ var obj = {
+ foo: function() {
+ var args = new Array(arguments.length);
+ for (var i = 0; i < arguments.length; i++)
+ args[i] = arguments[i];
+ return args;
+ }
+ };
+ obj;
+ """)
+
+ val elems = Seq[js.Any]("plop", 42, 51)
+
+ val dyn = obj.asInstanceOf[js.Dynamic]
+ expect(dyn.foo()).toEqual(js.Array())
+ expect(dyn.foo(3, 6)).toEqual(js.Array(3, 6))
+ expect(dyn.foo("hello", false)).toEqual(js.Array("hello", false))
+ expect(dyn.applyDynamic("foo")(elems: _*)).toEqual(js.Array("plop", 42, 51))
+
+ val stat = obj.asInstanceOf[InteroperabilityTestVariadicMethod]
+ expect(stat.foo()).toEqual(js.Array())
+ expect(stat.foo(3, 6)).toEqual(js.Array(3, 6))
+ expect(stat.foo("hello", false)).toEqual(js.Array("hello", false))
+ expect(stat.foo(elems: _*)).toEqual(js.Array("plop", 42, 51))
+ }
+
+ it("should allow to call JS constructors with variadic parameters") {
+ import js.Dynamic.{newInstance => jsnew}
+
+ js.eval("""
+ var InteroperabilityTestVariadicCtor = function() {
+ var args = new Array(arguments.length);
+ for (var i = 0; i < arguments.length; i++)
+ args[i] = arguments[i];
+ this.args = args;
+ };
+ """)
+
+ val elems = Seq[js.Any]("plop", 42, 51)
+
+ val ctor = js.Dynamic.global.InteroperabilityTestVariadicCtor
+ expect(jsnew(ctor)().args).toEqual(js.Array())
+ expect(jsnew(ctor)(3, 6).args).toEqual(js.Array(3, 6))
+ expect(jsnew(ctor)("hello", false).args).toEqual(js.Array("hello", false))
+ expect(jsnew(ctor)(elems: _*).args).toEqual(js.Array("plop", 42, 51))
+
+ import scala.scalajs.testsuite.compiler.{InteroperabilityTestVariadicCtor => C}
+ expect(new C().args).toEqual(js.Array())
+ expect(new C(3, 6).args).toEqual(js.Array(3, 6))
+ expect(new C("hello", false).args).toEqual(js.Array("hello", false))
+ expect(new C(elems: _*).args).toEqual(js.Array("plop", 42, 51))
+ }
+
+ it("should acces top-level JS objects via Scala object inheriting from js.GlobalScope") {
+ js.eval("""
+ var interoperabilityTestGlobalScopeValue = "7357";
+ var interoperabilityTestGlobalScopeValueAsInt = function() {
+ return parseInt(interoperabilityTestGlobalScopeValue);
+ };
+ """)
+
+ // Use alias for convenience: see end of file for definition
+ val Global = InteroperabilityTestGlobalScope
+
+ expect(Global.interoperabilityTestGlobalScopeValue).toEqual("7357")
+ expect(Global.interoperabilityTestGlobalScopeValueAsInt).toEqual(7357)
+
+ Global.interoperabilityTestGlobalScopeValue = "42"
+ expect(Global.interoperabilityTestGlobalScopeValueAsInt).toEqual(42)
+ }
+
+ it("should protect receiver of raw JS apply if it's a select - #804") {
+ val rawReceiver = js.eval("""
+ var interoperabilityTestRawReceiver = {
+ member: 0xbad,
+ check: function(raw) { return this.member ? this.member : raw; }
+ };
+ interoperabilityTestRawReceiver;
+ """).asInstanceOf[InteroperabilityTestRawReceiver]
+
+ expect(rawReceiver.check(7357)).toEqual(7357)
+
+ val check = rawReceiver.check
+ expect(check(0x600d)).toEqual(0x600d)
+
+ class InScalaSelect(check: js.Function1[Int, Int]) {
+ @JSExport
+ val member: Int = 0xbad2
+ def test(): Unit = expect(check(5894)).toEqual(5894)
+ }
+ new InScalaSelect(check).test()
+ }
+
+ it("should properly handle default parameters") {
+ val obj = js.eval("""
+ var interoperabilityTestDefaultParam = {
+ fun: function() { return arguments; }
+ };
+ interoperabilityTestDefaultParam;
+ """).asInstanceOf[InteroperabilityTestDefaultParam]
+
+ // Helpers
+ import js.Dynamic.{literal => args}
+ val undef = js.undefined
+
+ expect(obj.simple(1)).toEqual(args(`0` = 1))
+ expect(obj.simple(1,5)).toEqual(args(`0` = 1, `1` = 5))
+ expect(obj.named(y = 5)).toEqual(args(`0` = undef, `1` = 5))
+ expect(obj.named(x = 5)).toEqual(args(`0` = 5))
+ expect(obj.multi()(1,2,3,4)()).toEqual(args(
+ `0` = undef,
+ `1` = 1,
+ `2` = 2,
+ `3` = 3,
+ `4` = 4))
+ expect(obj.multi(2)()(5)).toEqual(args(
+ `0` = 2,
+ `1` = 5))
+ }
+
+ it("should properly handle default parameters for constructors - #791") {
+ js.eval("""
+ var InteroperabilityTestCtor = function(x,y) {
+ this.values = Array(x || 6, y || 8)
+ }
+ """);
+
+ expect(new InteroperabilityTestCtor().values).toEqual(js.Array(6,8))
+ expect(new InteroperabilityTestCtor(y = 7).values).toEqual(js.Array(6,7))
+ expect(new InteroperabilityTestCtor(3).values).toEqual(js.Array(3,8))
+ expect(new InteroperabilityTestCtor(10, 2).values).toEqual(js.Array(10,2))
+ }
+
+ it("should generate exports for methods inherited from traits - #178") {
+ import js.annotation.JSExport
+
+ trait Foo {
+ @JSExport
+ def theValue = 1
+ }
+ class Bar extends Foo
+
+ val x = (new Bar).asInstanceOf[js.Dynamic]
+
+ // Call the export by using js.Dynamic
+ expect(x.theValue).toEqual(1)
+ }
+
+ it("should allow constructor params that are vals/vars in facades - #1277") {
+ js.eval("""
+ var InteroparabilityCtorInlineValue = function(x,y) {
+ this.x = x;
+ this.y = y;
+ }
+ """)
+
+ val obj = new InteroparabilityCtorInlineValue(10, -1)
+
+ expect(obj.x).toEqual(10)
+ expect(obj.y).toEqual(-1)
+
+ obj.y = 100
+
+ expect(obj.x).toEqual(10)
+ expect(obj.y).toEqual(100)
+ }
+
+ it("should unbox Chars received from calling a JS interop method") {
+ val obj = js.eval("""
+ var obj = {
+ get: function() { return JSUtils().stringToChar('e'); }
+ };
+ obj;
+ """).asInstanceOf[InteroperabilityTestCharResult]
+
+ expect(obj.get().toInt).toEqual('e'.toInt)
+ }
+
+ it("should box Chars given to a JS interop method") {
+ val obj = js.eval("""
+ var obj = {
+ twice: function(c) { c = JSUtils().charToString(c); return c+c; }
+ };
+ obj;
+ """).asInstanceOf[InteroperabilityTestCharParam]
+
+ expect(obj.twice('x')).toEqual("xx")
+ }
+
+ it("should unbox value classes received from calling a JS interop method") {
+ val obj = js.eval("""
+ var obj = {
+ test: function(vc) { return vc; }
+ };
+ obj;
+ """).asInstanceOf[InteroperabilityTestValueClassResult]
+
+ val r = obj.test(new SomeValueClass(5))
+ expect(r.i).toEqual(5)
+ }
+
+ it("should box value classes given to a JS interop method") {
+ val obj = js.eval("""
+ var obj = {
+ stringOf: function(vc) { return vc.toString(); }
+ };
+ obj;
+ """).asInstanceOf[InteroperabilityTestValueClassParam]
+
+ val vc = new SomeValueClass(7)
+ expect(obj.stringOf(vc)).toEqual("SomeValueClass(7)")
+ }
+
+ it("should not unbox values received from JS method in statement position") {
+ /* To test this, we verify that a purposefully ill-typed facade does not
+ * throw a ClassCastException when called in statement position.
+ */
+ val obj = js.eval("""
+ var obj = {
+ test: function() { return 4; } // typed as String in the trait
+ };
+ obj;
+ """).asInstanceOf[InteroperabilityTestNoUnboxResultInStatement]
+ obj.test() // in statement position, should not throw
+ if (JasmineTestFramework.hasTag("compliant-asinstanceof"))
+ expect(() => obj.test()).toThrow // in expression position, should throw
+ }
+
+ when("compliant-asinstanceof").
+ it("should protect conversions from JS types to Scala types") {
+ class Foo
+ val foo: Any = new Foo
+
+ val invalidNumber: js.prim.Number = foo.asInstanceOf[js.prim.Number]
+ val nullNumber: js.prim.Number = null
+ expect(() => invalidNumber: Double).toThrow
+ expect(nullNumber: Double).toEqual(0)
+
+ val invalidBoolean: js.prim.Boolean = foo.asInstanceOf[js.prim.Boolean]
+ val nullBoolean: js.prim.Boolean = null
+ expect(() => invalidBoolean: Boolean).toThrow
+ expect(nullBoolean: Boolean).toEqual(false)
+
+ val invalidString: js.prim.String = foo.asInstanceOf[js.prim.String]
+ val nullString: js.prim.String = null
+ expect(() => invalidString: String).toThrow
+ expect(nullString: String).toBeNull
+ }
+
+ when("compliant-asinstanceof").
+ it("should asInstanceOf values received from calling a JS interop method") {
+ val obj = js.eval("""
+ var obj = {
+ testChar: function() { return 5; },
+ testInt: function() { return 6.4; },
+ testShort: function() { return 60000; },
+ testDouble: function() { return JSUtils().stringToChar('e'); },
+ testString: function() { return {}; },
+ testValueClass: function() { return "hello"; },
+ testNormalClass: function() { return 45; },
+ testAny: function() { return {}; }
+ };
+ obj;
+ """).asInstanceOf[InteroperabilityTestAsInstanceOfResult]
+
+ expect(() => obj.testChar()).toThrow
+ expect(() => obj.testInt()).toThrow
+ expect(() => obj.testShort()).toThrow
+ expect(() => obj.testDouble()).toThrow
+ expect(() => obj.testString()).toThrow
+ expect(() => obj.testValueClass()).toThrow
+ expect(() => obj.testNormalClass()).toThrow
+ expect(() => obj.testAny()).not.toThrow
+ }
+
+ }
+
+ trait InteroperabilityTestFieldEscape extends js.Object {
+ var `def`: Int = js.native
+ def `val`(): Int = js.native
+ def `val`(n: Int): Int = js.native
+ }
+
+ trait InteroperabilityTestJSName extends js.Object {
+ @JSName("val")
+ def value(): Int = js.native
+ @JSName("val")
+ def value(n: Int): Int = js.native
+ }
+
+ trait InteroperabilityTestProperty extends js.Object {
+ def a_=(x: Int): Unit = js.native
+ def a: Int = js.native
+ }
+
+ trait InteroperabilityTestPropertyNamed extends js.Object {
+ @JSName("b")
+ def a_=(x: Int): Unit = js.native
+ @JSName("b")
+ def a: Int = js.native
+ def b: Int = js.native
+ }
+
+ trait InteroperabilityTestJSBracketAccess extends js.Object {
+ @JSBracketAccess
+ def apply(index: Int): Int = js.native
+ @JSBracketAccess
+ def update(index: Int, v: Int): Unit = js.native
+ }
+
+ trait InteroperabilityTestRawReceiver extends js.Object {
+ val check: js.Function1[Int, Int] = js.native
+ }
+
+ /** Trait with different method signatures, all forwarded to the same
+ * JS raw function that returns the argument list for inspection
+ */
+ trait InteroperabilityTestDefaultParam extends js.Object {
+ @JSName("fun")
+ def simple(x: Int, y: Int = 5): js.Any = js.native
+ @JSName("fun")
+ def named(x: Int = 1, y: Int = 1, z: Int = 1): js.Any = js.native
+ @JSName("fun")
+ def multi(x: Int = 1)(ys: Int*)(z: Int = 1): js.Any = js.native
+ }
+
+ trait InteroperabilityTestCharResult extends js.Object {
+ def get(): Char = js.native
+ }
+
+ trait InteroperabilityTestCharParam extends js.Object {
+ def twice(c: Char): String = js.native
+ }
+
+ trait InteroperabilityTestValueClassResult extends js.Object {
+ def test(vc: Any): SomeValueClass = js.native
+ }
+
+ trait InteroperabilityTestValueClassParam extends js.Object {
+ def stringOf(vc: SomeValueClass): String = js.native
+ }
+
+ trait InteroperabilityTestNoUnboxResultInStatement extends js.Object {
+ def test(): String = js.native
+ }
+
+ trait InteroperabilityTestAsInstanceOfResult extends js.Object {
+ def testChar(): Char = js.native
+ def testInt(): Int = js.native
+ def testShort(): Short = js.native
+ def testDouble(): Double = js.native
+ def testString(): String = js.native
+ def testValueClass(): SomeValueClass = js.native
+ def testNormalClass(): List[Int] = js.native
+ def testAny(): Any = js.native
+ }
+}
+
+/*
+ * Helper classes, traits and objects defined here since they cannot be nested.
+ */
+
+@JSName("InteroperabilityTestInherit.Pattern")
+class InteroperabilityTestPattern protected () extends js.Object {
+ def this(pattern: String) = this()
+ val field: Int = js.native
+ def method(): String = js.native
+ def getConstructorParam(): String = js.native
+}
+
+trait InteroperabilityTestTopLevel extends js.Object {
+ val value: String = js.native
+ def valueAsInt(): Int = js.native
+}
+
+@JSName("InteroperabilityTestTopLevelObject")
+object InteroperabilityTestTopLevel extends js.Object {
+ def apply(value: String): InteroperabilityTestTopLevel = js.native
+}
+
+trait InteroperabilityTestVariadicMethod extends js.Object {
+ def foo(args: Any*): js.Array[Any] = js.native
+}
+
+class InteroperabilityTestVariadicCtor(inargs: Any*) extends js.Object {
+ val args: js.Array[Any] = js.native
+}
+
+object InteroperabilityTestGlobalScope extends js.GlobalScope {
+ var interoperabilityTestGlobalScopeValue: String = js.native
+ def interoperabilityTestGlobalScopeValueAsInt(): Int = js.native
+}
+
+class SomeValueClass(val i: Int) extends AnyVal {
+ override def toString(): String = s"SomeValueClass($i)"
+}
+
+class InteroperabilityTestCtor(x: Int = 5, y: Int = ???) extends js.Object {
+ def values: js.Array[Int] = js.native
+}
+
+class InteroparabilityCtorInlineValue(val x: Int, var y: Int) extends js.Object
diff --git a/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/LongTest.scala b/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/LongTest.scala
new file mode 100644
index 0000000..01d6f6e
--- /dev/null
+++ b/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/LongTest.scala
@@ -0,0 +1,159 @@
+/* __ *\
+** ________ ___ / / ___ __ ____ Scala.js Test Suite **
+** / __/ __// _ | / / / _ | __ / // __/ (c) 2013, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ **
+** /____/\___/_/ |_/____/_/ | |__/ /____/ **
+** |/____/ **
+\* */
+package scala.scalajs.testsuite.compiler
+
+import scala.scalajs.js
+
+import org.scalajs.jasminetest.JasmineTest
+
+/**
+ * tests the compiler re-patching of native longs to
+ * scala.scalajs.runtime.Long
+ * see scala.scalajs.testsuite.jsinterop.RuntimeLongTest
+ * for a test of the implementation itself
+ */
+object LongTest extends JasmineTest {
+
+ describe("JavaScript 64-bit long compatibility") {
+ it("should correctly handle literals") {
+ expect(5L + 100L == 105L).toBeTruthy
+ expect(2147483649L + 2L == 2147483651L).toBeTruthy
+ expect(-2147483648L * 4 == -8589934592L).toBeTruthy
+ expect(4503599627370510L * (-4) == -18014398509482040L).toBeTruthy
+ }
+
+ it("should correctly dispatch unary ops on Longs") {
+ val x = 10L
+ expect(-x == -10L).toBeTruthy
+ val y = 5L
+ expect(-y == -5L).toBeTruthy
+ expect(+y == 5L).toBeTruthy
+ expect(~y == -6L).toBeTruthy
+ }
+
+ it("should correctly dispatch binary ops on Longs") {
+ expect(5L * 5F == 25F).toBeTruthy
+ expect(5L % 4F == 1F).toBeTruthy
+ expect(5F * 4L == 20F).toBeTruthy
+ }
+
+ it("should support shifts with Longs - #622") {
+ def l(x: Long): Long = x
+ def i(x: Int): Int = x
+
+ expect(l(-7L) >>> 100L == 268435455L).toBeTruthy
+ expect(l(-7L) >> 100L == -1L).toBeTruthy
+ expect(l(-7L) >> 100 == -1L).toBeTruthy
+ expect(l(-7L) >>> 100 == 268435455).toBeTruthy
+ expect(l(-7L) << 100L == -481036337152L).toBeTruthy
+ expect(l(-7L) << 100 == -481036337152L).toBeTruthy
+ expect(l(7L) << 100L == 481036337152L).toBeTruthy
+ expect(l(8L) << 100L == 549755813888L).toBeTruthy
+ expect(l(-7L) >>> 4 == 1152921504606846975L).toBeTruthy
+
+ expect(i(7) << 100).toEqual(112)
+ expect(i(-7) >> 100).toEqual(-1)
+ expect(i(-7) >>> 100).toEqual(268435455)
+ expect(i(-65) >> 100).toEqual(-5)
+ expect(i(-65) >> 4).toEqual(-5)
+ }
+
+ it("primitives should convert to Long") {
+ // Byte
+ expect(112.toByte.toLong == 112L).toBeTruthy
+ // Short
+ expect((-10).toShort.toLong == -10L).toBeTruthy
+ // Char
+ expect('A'.toLong == 65L).toBeTruthy
+ // Int
+ expect(5.toLong == 5L).toBeTruthy
+ // Long
+ expect(10L.toLong == 10L).toBeTruthy
+ // Float
+ expect(100000.6f.toLong == 100000L).toBeTruthy
+ // Double
+ expect(100000.6.toLong == 100000L).toBeTruthy
+ }
+
+ it("should support hashCode()") {
+ expect(0L .hashCode()).toEqual(0)
+ expect(55L .hashCode()).toEqual(55)
+ expect((-12L) .hashCode()).toEqual(11)
+ expect(10006548L .hashCode()).toEqual(10006548)
+ expect((-1098748L).hashCode()).toEqual(1098747)
+
+ expect(613354684553L .hashCode()).toEqual(-825638905)
+ expect(9863155567412L .hashCode()).toEqual(1910653900)
+ expect(3632147899696541255L.hashCode()).toEqual(1735398658)
+ expect(7632147899696541255L.hashCode()).toEqual(-1689438124)
+ }
+
+ it("should support ##") {
+ expect(0L .##).toEqual(0)
+ expect(55L .##).toEqual(55)
+ expect((-12L) .##).toEqual(-12)
+ expect(10006548L .##).toEqual(10006548)
+ expect((-1098748L).##).toEqual(-1098748)
+
+ expect(9863155567412L .##).toEqual(1910653900)
+ expect(3632147899696541255L.##).toEqual(1735398658)
+
+ // These two (correctly) give different results on 2.10 and 2.11
+ //expect(613354684553L .##).toEqual(-825638905) // xx06 on 2.10
+ //expect(7632147899696541255L.##).toEqual(-1689438124) // xx25 on 2.10
+ }
+
+ it("should correctly concat to string") {
+ val x = 20L
+ expect("asdf" + 5L + x + "hello").toEqual("asdf520hello")
+ expect(x + "hello").toEqual("20hello")
+ }
+
+ it("string should convert to Long") {
+ expect("45678901234567890".toLong == 45678901234567890L).toBeTruthy
+ }
+
+ it("should convert from and to js.prim.Number") {
+ val x = 5: js.prim.Number
+ expect((5L: js.prim.Number) == x).toBeTruthy
+ expect(x.toLong == 5L).toBeTruthy
+ }
+
+ it("should correctly implement is/asInstanceOf Longs") {
+ val dyn: Any = 5L
+ val stat: Long = 5L
+
+ expect(stat.asInstanceOf[Long]).toEqual(5L)
+ // models current scala behavior. See SI-1448
+ expect(stat.asInstanceOf[Int]).toEqual(5)
+
+ expect(stat.isInstanceOf[Long]).toBeTruthy
+ expect(stat.isInstanceOf[Int]).toBeFalsy
+
+ expect(dyn.asInstanceOf[Long]).toEqual(5L)
+
+ expect(dyn.isInstanceOf[Long]).toBeTruthy
+ expect(dyn.isInstanceOf[Int]).toBeFalsy
+ }
+
+ when("compliant-asinstanceof").
+ it("should correctly implement asInstanceOf Longs (negative)") {
+ val dyn: Any = 5L
+
+ expect(() => dyn.asInstanceOf[Int]).toThrow
+ }
+
+ it("should correctly compare to other numeric types") {
+ expect(5L == 5).toBeTruthy
+ expect(5 == 5L).toBeTruthy
+ expect(4 == 5l).toBeFalsy
+ expect('A' == 65L).toBeTruthy
+ }
+ }
+
+}
diff --git a/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/OptimizerTest.scala b/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/OptimizerTest.scala
new file mode 100644
index 0000000..986c25a
--- /dev/null
+++ b/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/OptimizerTest.scala
@@ -0,0 +1,43 @@
+/* __ *\
+** ________ ___ / / ___ __ ____ Scala.js Test Suite **
+** / __/ __// _ | / / / _ | __ / // __/ (c) 2013, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ **
+** /____/\___/_/ |_/____/_/ | |__/ /____/ **
+** |/____/ **
+\* */
+package scala.scalajs.testsuite.compiler
+
+import org.scalajs.jasminetest.JasmineTest
+
+object OptimizerTest extends JasmineTest {
+
+ describe("Inlineable classes") {
+
+ it("must update fields of `this` in the computation of other fields - #1153") {
+ val foo = new InlineClassDependentFields(5)
+ expect(foo.x).toEqual(5)
+ expect(foo.b).toBeTruthy
+ expect(foo.y).toEqual(11)
+ }
+
+ it("must not break code that assigns `this` to a field") {
+ val foo = new InlineClassThisAlias(5)
+ expect(foo.z).toEqual(5)
+ }
+
+ }
+
+ @inline
+ class InlineClassDependentFields(val x: Int) {
+ val b = x > 3
+ val y = if (b) x + 6 else x-2
+ }
+
+ @inline
+ class InlineClassThisAlias(val x: Int) {
+ val t = this
+ val y = x
+ val z = t.y
+ }
+
+}
diff --git a/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/ReflectionTest.scala b/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/ReflectionTest.scala
new file mode 100644
index 0000000..3e1d7a2
--- /dev/null
+++ b/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/ReflectionTest.scala
@@ -0,0 +1,69 @@
+/* __ *\
+** ________ ___ / / ___ __ ____ Scala.js Test Suite **
+** / __/ __// _ | / / / _ | __ / // __/ (c) 2013, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ **
+** /____/\___/_/ |_/____/_/ | |__/ /____/ **
+** |/____/ **
+\* */
+package scala.scalajs.testsuite.compiler
+
+import scala.language.implicitConversions
+
+import scala.scalajs.js
+
+import org.scalajs.jasminetest.JasmineTest
+
+/** Tests the little reflection we support */
+object ReflectionTest extends JasmineTest {
+
+ describe("Scala.js Reflection (through java.lang.Class)") {
+ it("should append $ to class name of objects") {
+ expect(TestObject.getClass.getName).toEqual(
+ "scala.scalajs.testsuite.compiler.ReflectionTest$TestObject$")
+ }
+
+ it("should support isInstance") {
+ class A
+ class B extends A
+ val b = new B
+ expect(classOf[A].isInstance(b)).toBeTruthy
+ expect(classOf[A].isInstance("hello")).toBeFalsy
+ }
+
+ it("getClass() for normal types") {
+ class Foo {
+ def bar() = super.getClass()
+ }
+ val foo = new Foo
+ expect(foo.getClass() eq classOf[Foo]).toBeTruthy
+ expect(foo.bar() eq classOf[Foo]).toBeTruthy
+ }
+
+ it("getClass() for anti-boxed primitive types") {
+ implicit def classAsAny(c: java.lang.Class[_]): js.Any =
+ c.asInstanceOf[js.Any]
+ expect((false: Any).getClass).toBe(classOf[java.lang.Boolean])
+ expect(('a': Any).getClass).toBe(classOf[java.lang.Character])
+ expect((1.toByte: Any).getClass).toBe(classOf[java.lang.Byte])
+ expect((1.toShort: Any).getClass).toBe(classOf[java.lang.Byte])
+ expect((1: Any).getClass).toBe(classOf[java.lang.Byte])
+ expect((1L: Any).getClass).toBe(classOf[java.lang.Long])
+ expect((1.5f: Any).getClass).toBe(classOf[java.lang.Float])
+ expect((1.5: Any).getClass).toBe(classOf[java.lang.Float])
+ expect(((): Any).getClass).toBe(classOf[scala.runtime.BoxedUnit])
+ }
+
+ it("Class.isAssignableFrom should mimic runtime type tests behavior - #879") {
+ expect(classOf[Short].isAssignableFrom(classOf[Byte])).toBeTruthy
+ expect(classOf[Byte].isAssignableFrom(classOf[Byte])).toBeTruthy
+ expect(classOf[Byte].isAssignableFrom(classOf[Short])).toBeFalsy
+ expect(classOf[Int].isAssignableFrom(classOf[Byte])).toBeTruthy
+ expect(classOf[Double].isAssignableFrom(classOf[Int])).toBeTruthy
+ expect(classOf[Int].isAssignableFrom(classOf[Double])).toBeFalsy
+ expect(classOf[Long].isAssignableFrom(classOf[Int])).toBeFalsy
+ }
+ }
+
+ object TestObject
+
+}
diff --git a/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/ReflectiveCallTest.scala b/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/ReflectiveCallTest.scala
new file mode 100644
index 0000000..6020a5f
--- /dev/null
+++ b/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/ReflectiveCallTest.scala
@@ -0,0 +1,330 @@
+/* __ *\
+** ________ ___ / / ___ __ ____ Scala.js Test Suite **
+** / __/ __// _ | / / / _ | __ / // __/ (c) 2013, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ **
+** /____/\___/_/ |_/____/_/ | |__/ /____/ **
+** |/____/ **
+\* */
+package scala.scalajs.testsuite.compiler
+
+import scala.scalajs.js
+import org.scalajs.jasminetest.JasmineTest
+
+import language.reflectiveCalls
+
+import java.lang.{Float => JFloat, Double => JDouble}
+
+object ReflectiveCallTest extends JasmineTest {
+
+ describe("Reflective Calls") {
+ it("should allow subtyping in return types") {
+ class A { def x = 1 }
+ class B extends A { override def x = 2 }
+
+ object Generator {
+ def generate(): B = new B
+ }
+
+ def f(x: { def generate(): A }) = x.generate
+
+ expect(f(Generator).x).toEqual(2)
+ }
+
+ it("should allow this.type in return types") {
+ type valueType = { def value: this.type }
+ def f(x: valueType) = x.value
+
+ class StringValue(x: String) {
+ def value: this.type = this
+ override def toString = s"StringValue($x)"
+ }
+
+ expect(f(new StringValue("foo")).toString).toEqual("StringValue(foo)")
+ }
+
+ it("should allow generic return types") {
+ case class Tata(name: String)
+
+ object Rec {
+ def e(x: Tata) = new Tata("iei")
+ }
+
+ def m[T](r: Object { def e(x: Tata): T}) =
+ r.e(new Tata("foo"))
+
+ expect(m[Tata](Rec).toString).toEqual("Tata(iei)")
+ }
+
+ it("should work with unary methods on primitive types") {
+ def fInt(x: Any { def unary_- :Int }) = -x
+ expect(fInt(1.toByte)).toEqual(-1)
+ expect(fInt(1.toShort)).toEqual(-1)
+ expect(fInt(1.toChar)).toEqual(-1)
+ expect(fInt(1)).toEqual(-1)
+
+ def fLong(x: Any { def unary_- :Long }) = -x
+ expect(fLong(1L)).toEqual(-1L)
+
+ def fFloat(x: Any { def unary_- :Float}) = -x
+ expect(fFloat(1.5f)).toEqual(-1.5f)
+
+ def fDouble(x: Any { def unary_- :Double }) = -x
+ expect(fDouble(1.5)).toEqual(-1.5)
+
+ def fBoolean(x: Any { def unary_! :Boolean }) = !x
+ expect(fBoolean(false)).toBeTruthy
+ expect(fBoolean(true)).toBeFalsy
+ }
+
+ it("should work with binary operators on primitive types") {
+ def fLong(x: Any { def +(x: Long): Long }) = x + 5L
+ expect(fLong(5.toByte)).toEqual(10L)
+ expect(fLong(10.toShort)).toEqual(15L)
+ expect(fLong(10.toChar)).toEqual(15L)
+ expect(fLong(-1)).toEqual(4L)
+ expect(fLong(17L)).toEqual(22L)
+
+ def fInt(x: Any { def /(x: Int): Int }) = x / 7
+ expect(fInt(65.toByte)).toEqual(9)
+ expect(fInt(15.toShort)).toEqual(2)
+ expect(fInt(25.toChar)).toEqual(3)
+ expect(fInt(-40)).toEqual(-5)
+
+ def fShort(x: Any { def +(x: Short): Int }) = x + 6.toShort
+ expect(fShort(65.toByte)).toEqual(71)
+ expect(fShort(15.toShort)).toEqual(21)
+ expect(fShort(25.toChar)).toEqual(31)
+ expect(fShort(-40)).toEqual(-34)
+
+ def fFloat(x: Any { def %(x: Float): Float}) = x % 3.4f
+ expect(fFloat(5.5f)).toEqual(2.1f)
+
+ def fDouble(x: Any { def /(x: Double): Double }) = x / 1.4
+ expect(fDouble(-1.5)).toEqual(-1.0714285714285714)
+
+ def fBoolean(x: Any { def &&(x: Boolean): Boolean }) = x && true
+ expect(fBoolean(false)).toBeFalsy
+ expect(fBoolean(true)).toBeTruthy
+ }
+
+ it("should work with equality operators on primitive types") {
+ def fNum(obj: Any { def ==(x: Int): Boolean }) = obj == 5
+ expect(fNum(5.toByte)).toBeTruthy
+ expect(fNum(6.toByte)).toBeFalsy
+ expect(fNum(5.toShort)).toBeTruthy
+ expect(fNum(7.toShort)).toBeFalsy
+ expect(fNum(5.toChar)).toBeTruthy
+ expect(fNum('r')).toBeFalsy
+ expect(fNum(5)).toBeTruthy
+ expect(fNum(-4)).toBeFalsy
+ expect(fNum(5L)).toBeTruthy
+ expect(fNum(400L)).toBeFalsy
+ expect(fNum(5.0f)).toBeTruthy
+ expect(fNum(5.6f)).toBeFalsy
+ expect(fNum(5.0)).toBeTruthy
+ expect(fNum(7.9)).toBeFalsy
+ def fBool(obj: Any { def ==(x: Boolean): Boolean }) = obj == false
+ expect(fBool(true)).toBeFalsy
+ expect(fBool(false)).toBeTruthy
+
+ def fNumN(obj: Any { def !=(x: Int): Boolean }) = obj != 5
+ expect(fNumN(5.toByte)).toBeFalsy
+ expect(fNumN(6.toByte)).toBeTruthy
+ expect(fNumN(5.toShort)).toBeFalsy
+ expect(fNumN(7.toShort)).toBeTruthy
+ expect(fNumN(5.toChar)).toBeFalsy
+ expect(fNumN('r')).toBeTruthy
+ expect(fNumN(5)).toBeFalsy
+ expect(fNumN(-4)).toBeTruthy
+ expect(fNumN(5L)).toBeFalsy
+ expect(fNumN(400L)).toBeTruthy
+ expect(fNumN(5.0f)).toBeFalsy
+ expect(fNumN(5.6f)).toBeTruthy
+ expect(fNumN(5.0)).toBeFalsy
+ expect(fNumN(7.9)).toBeTruthy
+ def fBoolN(obj: Any { def !=(x: Boolean): Boolean }) = obj != false
+ expect(fBoolN(true)).toBeTruthy
+ expect(fBoolN(false)).toBeFalsy
+
+ }
+
+ it("should work with Arrays") {
+ type UPD = { def update(i: Int, x: String): Unit }
+ type APL = { def apply(i: Int): String }
+ type LEN = { def length: Int }
+ type CLONE = Any { def clone(): Object }
+ def upd(obj: UPD, i: Int, x: String) = obj.update(i,x)
+ def apl(obj: APL, i: Int) = obj.apply(i)
+ def len(obj: LEN) = obj.length
+ def clone(obj: CLONE) = obj.clone
+
+ val x = Array("asdf","foo","bar")
+ val y = clone(x).asInstanceOf[Array[String]]
+
+ expect(len(x)).toEqual(3)
+ expect(apl(x,0)).toEqual("asdf")
+ upd(x,1,"2foo")
+ expect(x(1)).toEqual("2foo")
+ expect(y(1)).toEqual("foo")
+ }
+
+ it("should work with Arrays of primitive values") {
+ type UPD = { def update(i: Int, x: Int): Unit }
+ type APL = { def apply(i: Int): Int}
+ type LEN = { def length: Int }
+ type CLONE = Any { def clone(): Object }
+ def upd(obj: UPD, i: Int, x: Int) = obj.update(i,x)
+ def apl(obj: APL, i: Int) = obj.apply(i)
+ def len(obj: LEN) = obj.length
+ def clone(obj: CLONE) = obj.clone
+
+ val x = Array(5,2,8)
+ val y = clone(x).asInstanceOf[Array[Int]]
+
+ expect(len(x)).toEqual(3)
+ expect(apl(x,0)).toEqual(5)
+ upd(x,1,1000)
+ expect(x(1)).toEqual(1000)
+ expect(y(1)).toEqual(2)
+ }
+
+ it("should work with Strings") {
+ def get(obj: { def codePointAt(str: Int): Int }) =
+ obj.codePointAt(1)
+ expect(get("Hi")).toEqual('i'.toInt)
+
+ def sub(x: { def substring(x: Int): AnyRef }) = x.substring(5)
+ expect(sub("asdfasdfasdf") == "sdfasdf").toBeTruthy
+
+ type LEN_A = { def length: Any }
+ def lenA(x: LEN_A) = x.length
+ expect(lenA("asdf") == 4).toBeTruthy
+ }
+
+ it("should properly generate forwarders for inherited methods") {
+ trait A {
+ def foo: Int
+ }
+
+ abstract class B extends A
+
+ class C extends B {
+ def foo = 1
+ }
+
+ def call(x: { def foo: Int }) = x.foo
+
+ expect(call(new C)).toEqual(1)
+ }
+
+ it("should work on java.lang.Object.{ notify, notifyAll } - #303") {
+ type ObjNotifyLike = Any {
+ def notify(): Unit
+ def notifyAll(): Unit
+ }
+ def objNotifyTest(obj: ObjNotifyLike) = {
+ obj.notify()
+ obj.notifyAll()
+ 1
+ }
+
+ class A
+
+ expect(objNotifyTest(new A())).toEqual(1)
+ }
+
+ it("should work on java.lang.Object.clone - #303") {
+ type ObjCloneLike = Any { def clone(): AnyRef }
+ def objCloneTest(obj: ObjCloneLike) = obj.clone()
+
+ class B(val x: Int) extends Cloneable {
+ override def clone() = super.clone
+ }
+
+ val b = new B(1)
+ val bClone = objCloneTest(b).asInstanceOf[B]
+
+ expect(b eq bClone).toBeFalsy
+ expect(bClone.x).toEqual(1)
+ }
+
+ it("should work on scala.AnyRef.{ eq, ne } - #303") {
+ type ObjEqLike = Any {
+ def eq(that: AnyRef): Boolean
+ def ne(that: AnyRef): Boolean
+ }
+ def objEqTest(obj: ObjEqLike, that: AnyRef) = obj eq that
+ def objNeTest(obj: ObjEqLike, that: AnyRef) = obj ne that
+
+ class A
+
+ val a1 = new A
+ val a2 = new A
+
+ expect(objEqTest(a1,a2)).toBeFalsy
+ expect(objEqTest(a1,a1)).toBeTruthy
+
+ expect(objNeTest(a1,a2)).toBeTruthy
+ expect(objNeTest(a1,a1)).toBeFalsy
+ }
+
+ it("should work on java.lang.{Float,Double}.{isNaN,isInfinite}") {
+ type FloatingNumberLike = Any {
+ def isNaN(): Boolean
+ def isInfinite(): Boolean
+ }
+ def test(x: FloatingNumberLike, isNaN: Boolean,
+ isInfinite: Boolean) = {
+ expect(x.isNaN()).toEqual(isNaN)
+ expect(x.isInfinite()).toEqual(isInfinite)
+ }
+
+ test(new JFloat(Float.NaN), true, false)
+ test(new JFloat(Float.PositiveInfinity), false, true)
+ test(new JFloat(Float.NegativeInfinity), false, true)
+ test(new JFloat(54.67), false, false)
+
+ test(new JDouble(Double.NaN), true, false)
+ test(new JDouble(Double.PositiveInfinity), false, true)
+ test(new JDouble(Double.NegativeInfinity), false, true)
+ test(new JDouble(54.67), false, false)
+ }
+
+ it("should work with default arguments - #390") {
+ def pimpIt(a: Int) = new {
+ def foo(b: Int, c: Int = 1): Int = a + b + c
+ }
+
+ expect(pimpIt(1).foo(2)).toEqual(4)
+ expect(pimpIt(2).foo(2,4)).toEqual(8)
+ }
+
+ it("should unbox all types of arguments - #899") {
+ class Foo {
+ def makeInt: Int = 5
+ def testInt(x: Int): Unit = expect(x).toEqual(5)
+
+ def makeRef: Option[String] = Some("hi")
+ def testRef(x: Option[String]): Unit = expect(x == Some("hi")).toBeTruthy
+ }
+
+ /* Note: we should also test with value classes, except that Scala itself
+ * does not support value classes as parameters or result type of
+ * methods in structural types.
+ */
+
+ def test(foo: {
+ def makeInt: Int
+ def testInt(x: Int): Unit
+ def makeRef: Option[String]
+ def testRef(x: Option[String]): Unit
+ }): Unit = {
+ foo.testInt(foo.makeInt)
+ foo.testRef(foo.makeRef)
+ }
+
+ test(new Foo)
+ }
+
+ }
+}
diff --git a/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/RegressionTest.scala b/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/RegressionTest.scala
new file mode 100644
index 0000000..19cceb2
--- /dev/null
+++ b/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/RegressionTest.scala
@@ -0,0 +1,287 @@
+/* __ *\
+** ________ ___ / / ___ __ ____ Scala.js Test Suite **
+** / __/ __// _ | / / / _ | __ / // __/ (c) 2013, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ **
+** /____/\___/_/ |_/____/_/ | |__/ /____/ **
+** |/____/ **
+\* */
+package scala.scalajs.testsuite.compiler
+
+import scala.annotation.tailrec
+
+import scala.scalajs.js
+import org.scalajs.jasminetest.JasmineTest
+
+object RegressionTest extends JasmineTest {
+
+ class Bug218Foo[T](val x: T) extends AnyVal
+
+ describe("Scala.js compiler regression tests") {
+
+ it("Wrong division conversion (7 / 2.0) - #18") {
+ val div = 7 / 2.0
+ expect(div).toEqual(3.5)
+ expect(div.getClass.getName).toEqual("double")
+
+ val mod = 7 % 2.0
+ expect(mod).toEqual(1.0)
+ expect(mod.getClass.getName).toEqual("double")
+ }
+
+ it("js.prim.String + js.prim.String is ambiguous - #20") {
+ val a: js.prim.String = "a"
+ val b: js.prim.String = "b"
+ val c: js.prim.String = a + b
+ expect(c).toEqual("ab")
+ }
+
+ it("Abort with some pattern match guards - #22") {
+ object PatternMatchGuards {
+ def go(f: Int => Int) = f(1)
+ def main(): Unit = {
+ go {
+ case x if false => x
+ }
+ }
+ }
+ // Nothing to check
+ }
+
+ it("Bad encoding for characters spanning 2 UTF-16 chars - #23") {
+ val str = "A∀\uD835\uDCAB"
+ var s: String = ""
+ for (c <- str) {
+ val code: Int = c
+ s = s + code + " "
+ }
+ expect(s).toEqual("65 8704 55349 56491 ")
+ }
+
+ it("String concatenation with null - #26") {
+ val x: Object = null
+ expect(x + "check").toEqual("nullcheck")
+ }
+
+ class Bug66A(s: String, e: Object) {
+ def this(e: Object) = this("", e)
+ def this(s: String) = this(s, "")
+ }
+ class Bug66B(s: String, e: Object) extends Bug66A(s)
+
+ it("should emit static calls when forwarding to another constructor - #66") {
+ new Bug66B("", "")
+ }
+
+ it("should not swallow Unit expressions when converting to js.prim.Undefined - #83") {
+ var effectHappened = false
+ def doEffect(): Unit = effectHappened = true
+ def f(): js.prim.Undefined = doEffect()
+ f()
+ expect(effectHappened).toBeTruthy
+ }
+
+ it("should correctly call subSequence on non-string CharSequences - #55") {
+ val arr: CharSequence = Array('a','b','c','d')
+ val ss = arr.subSequence(2,3)
+ expect(ss.length()).toEqual(1)
+ expect(ss.charAt(0)).toEqual('c')
+ }
+
+ it("should correctly concat primitive values to strings - #113") {
+ expect(4 + "foo").toEqual("4foo")
+ expect('a' + "foo").toEqual("afoo")
+ }
+
+ it("should resolve overloads on scala.Function.apply when converting to js.Function - #125") {
+ class Fct extends Function1[Int,Any] {
+ def apply(n: Int) = n
+ }
+
+ val scalaFunction = new Fct
+ val jsFunction: js.Any = scalaFunction
+ val thisFunction: js.ThisFunction = scalaFunction
+ }
+
+ it("should correctly dispatch calls on private functions - #165") {
+ class A {
+ private def x = 1
+ def value = x
+ }
+ class B extends A {
+ private def x = 2
+ }
+ expect(new B().value).toEqual(1)
+ }
+
+ it("should correctly mangle JavaScript reserved identifiers - #153") {
+ // Class name
+ class break {
+ // class variable
+ var continue = 1
+ // method name
+ def switch = {
+ // local name
+ val default = 2
+ default
+ }
+ }
+ trait Foo {
+ // static member (through mixin)
+ def function = 3
+ }
+
+ val x = new break with Foo
+ expect(x.continue).toEqual(1)
+ expect(x.switch).toEqual(2)
+ expect(x.function).toEqual(3)
+ }
+
+ it("should correctly mangle identifiers starting with a digit - #153") {
+ // Class name
+ class `0` {
+ // class variable
+ var `1` = 1
+ // method name
+ def `2` = {
+ // local name
+ val `22` = 2
+ `22`
+ }
+ }
+ trait Foo {
+ // static member (through mixin)
+ def `3` = 3
+ }
+
+ val x = new `0` with Foo
+ expect(x.`1`).toEqual(1)
+ expect(x.`2`).toEqual(2)
+ expect(x.`3`).toEqual(3)
+ }
+
+ it("should reserve `eval` and `arguments` - #743") {
+ val eval = 5
+ expect(eval).toEqual(5)
+ val arguments = "hello"
+ expect(arguments).toEqual("hello")
+ }
+
+ it("should support class literals for existential value types - #218") {
+ expect(scala.reflect.classTag[Bug218Foo[_]].toString).toEqual(
+ "scala.scalajs.testsuite.compiler.RegressionTest$Bug218Foo")
+ }
+
+ it("should support Buffer - #268") {
+ val a = scala.collection.mutable.Buffer.empty[Int]
+ a.insert(0, 0)
+ a.remove(0)
+ for (i <- 0 to 10) {
+ a.insert(a.length / 2, i)
+ }
+ expect(a.mkString(", ")).toEqual("1, 3, 5, 7, 9, 10, 8, 6, 4, 2, 0")
+ }
+
+ it("should not call equals when comparing with a literal null - #362") {
+ class A { override def equals(x: Any) = !(this == null) }
+
+ val x = new A
+ val y = new A
+
+ // If the null comparisons actually call equals, the following two will
+ // cause infinite recursion
+ expect(x == y).toBeTruthy
+ expect(y == x).toBeTruthy
+ }
+
+ it("should unbox null to the zero of types - #674") {
+ class Box[A] {
+ var value: A = _
+ }
+ def zero[A]: A = new Box[A].value
+
+ /* Note: the same shape of test for Unit does not work, but it seems to
+ * be a problem in scalac because it does not work on the JVM either.
+ */
+
+ val bool = zero[Boolean]
+ expect((bool: Any).isInstanceOf[Boolean]).toBeTruthy
+ expect(bool == false).toBeTruthy
+
+ val char = zero[Char]
+ expect((char: Any).isInstanceOf[Char]).toBeTruthy
+ expect(char == '\u0000').toBeTruthy
+
+ val byte = zero[Byte]
+ expect((byte: Any).isInstanceOf[Byte]).toBeTruthy
+ expect(byte == 0.toByte).toBeTruthy
+
+ val short = zero[Short]
+ expect((short: Any).isInstanceOf[Short]).toBeTruthy
+ expect(short == 0.toShort).toBeTruthy
+
+ val int = zero[Int]
+ expect((int: Any).isInstanceOf[Int]).toBeTruthy
+ expect(int == 0).toBeTruthy
+
+ val long = zero[Long]
+ expect((long: Any).isInstanceOf[Long]).toBeTruthy
+ expect(long == 0L).toBeTruthy
+
+ val float = zero[Float]
+ expect((float: Any).isInstanceOf[Float]).toBeTruthy
+ expect(float == 0.0f).toBeTruthy
+
+ val double = zero[Double]
+ expect((double: Any).isInstanceOf[Double]).toBeTruthy
+ expect(double == 0.0).toBeTruthy
+
+ val ref = zero[AnyRef]
+ expect(ref == null).toBeTruthy
+ }
+
+ it("Param defs in tailrec methods should be considered mutable - #825") {
+ @tailrec
+ def foo(x: Int, y: Int): Unit = {
+ if (x < y) foo(y, x)
+ else {
+ expect(x).toEqual(4)
+ expect(y).toEqual(2)
+ }
+ }
+ foo(2, 4)
+ }
+
+ it("null.synchronized should throw - #874") {
+ expect(() => null.synchronized(5)).toThrow
+ }
+
+ it("x.synchronized should preserve side-effects of x") {
+ var c = 0
+ def x = { c += 1; this }
+ expect(x.synchronized(5)).toEqual(5)
+ expect(c).toEqual(1)
+ }
+
+ it("IR checker should allow Apply/Select on NullType and NothingType - #1123") {
+ def giveMeANull(): Null = null
+ expect(() => (giveMeANull(): StringBuilder).append(5)).toThrow
+ expect(() => (giveMeANull(): scala.runtime.IntRef).elem).toThrow
+
+ def giveMeANothing(): Nothing = sys.error("boom")
+ expect(() => (giveMeANothing(): StringBuilder).append(5)).toThrow
+ expect(() => (giveMeANothing(): scala.runtime.IntRef).elem).toThrow
+ }
+
+ it("should not put bad flags on caseaccessor export forwarders - #1191") {
+ // This test used to choke patmat
+
+ @scala.scalajs.js.annotation.JSExportAll
+ case class T(one: Int, two: Int)
+
+ val T(a, b) = T(1, 2)
+
+ expect(a).toEqual(1)
+ expect(b).toEqual(2)
+ }
+ }
+}
diff --git a/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/RuntimeTypesTest.scala b/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/RuntimeTypesTest.scala
new file mode 100644
index 0000000..b1a32c4
--- /dev/null
+++ b/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/RuntimeTypesTest.scala
@@ -0,0 +1,77 @@
+/* __ *\
+** ________ ___ / / ___ __ ____ Scala.js Test Suite **
+** / __/ __// _ | / / / _ | __ / // __/ (c) 2013, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ **
+** /____/\___/_/ |_/____/_/ | |__/ /____/ **
+** |/____/ **
+\* */
+package scala.scalajs.testsuite.compiler
+
+import scala.scalajs.js
+import org.scalajs.jasminetest.JasmineTest
+
+import scala.util.{ Try, Failure }
+
+object RuntimeTypesTest extends JasmineTest {
+
+ describe("scala.Nothing") {
+
+ when("compliant-asinstanceof").
+ it("casts to scala.Nothing should fail") {
+ val msg = Try("a".asInstanceOf[Nothing]) match {
+ case Failure(thr: ClassCastException) => thr.getMessage
+ case _ => "not failed"
+ }
+ expect(msg).toEqual("a is not an instance of scala.runtime.Nothing$")
+ }
+
+ it("Array[Nothing] should be allowed to exists and be castable") {
+ val arr = Array[Nothing]()
+ arr.asInstanceOf[Array[Nothing]]
+ }
+
+ it("Array[Array[Nothing]], too") {
+ val arr = Array[Array[Nothing]]()
+ arr.asInstanceOf[Array[Array[Nothing]]]
+ // This apparently works too... Dunno why
+ arr.asInstanceOf[Array[Nothing]]
+ }
+
+ }
+
+ describe("scala.Null") {
+
+ when("compliant-asinstanceof").
+ it("casts to scala.Null should fail for everything else but null") {
+ val msg = Try("a".asInstanceOf[Null]) match {
+ case Failure(thr: ClassCastException) => thr.getMessage
+ case _ => "not failed"
+ }
+ expect(msg).toEqual("a is not an instance of scala.runtime.Null$")
+ }
+
+ it("classTag of scala.Null should contain proper Class[_] - #297") {
+ val tag = scala.reflect.classTag[Null]
+ expect(tag.runtimeClass != null).toBeTruthy
+ expect(tag.runtimeClass.getName).toEqual("scala.runtime.Null$")
+ }
+
+ it("casts to scala.Null should succeed on null") {
+ null.asInstanceOf[Null]
+ }
+
+ it("Array[Null] should be allowed to exist and be castable") {
+ val arr = Array.fill[Null](5)(null)
+ arr.asInstanceOf[Array[Null]]
+ }
+
+ it("Array[Array[Null]] too") {
+ val arr = Array.fill[Null](5,5)(null)
+ arr.asInstanceOf[Array[Array[Null]]]
+ // This apparently works too... Dunno why
+ arr.asInstanceOf[Array[Null]]
+ }
+
+ }
+
+}
diff --git a/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/ShortTest.scala b/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/ShortTest.scala
new file mode 100644
index 0000000..10746ba
--- /dev/null
+++ b/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/ShortTest.scala
@@ -0,0 +1,38 @@
+/* __ *\
+** ________ ___ / / ___ __ ____ Scala.js Test Suite **
+** / __/ __// _ | / / / _ | __ / // __/ (c) 2013, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ **
+** /____/\___/_/ |_/____/_/ | |__/ /____/ **
+** |/____/ **
+\* */
+package scala.scalajs.testsuite.compiler
+
+import org.scalajs.jasminetest.JasmineTest
+import scala.scalajs.js
+
+object ShortTest extends JasmineTest {
+
+ describe("Short primitives") {
+
+ it("should always be in their range") {
+ def test(x: Int, y: Short): Unit =
+ expect(x.toShort).toEqual(y)
+
+ test(0, 0)
+ test(-500, -500)
+ test(-90000, -24464)
+ test(123456789, -13035)
+ test(-40000, 25536)
+ test(65536, 0)
+ test(32768, -32768)
+
+ def testC(x: Char, y: Short): Unit =
+ expect(x.toShort).toEqual(y)
+
+ testC(-1.toChar, -1)
+ testC(200.toChar, 200)
+ testC(60000.toChar, -5536)
+ }
+
+ }
+}
diff --git a/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/UnitTest.scala b/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/UnitTest.scala
new file mode 100644
index 0000000..8e2be64
--- /dev/null
+++ b/test-suite/src/test/scala/scala/scalajs/testsuite/compiler/UnitTest.scala
@@ -0,0 +1,47 @@
+/* __ *\
+** ________ ___ / / ___ __ ____ Scala.js Test Suite **
+** / __/ __// _ | / / / _ | __ / // __/ (c) 2013, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ **
+** /____/\___/_/ |_/____/_/ | |__/ /____/ **
+** |/____/ **
+\* */
+package scala.scalajs.testsuite.compiler
+
+import org.scalajs.jasminetest.JasmineTest
+import scala.scalajs.js
+
+object UnitTest extends JasmineTest {
+
+ describe("Unit primitive") {
+
+ it("should have toString()") {
+ expect(().toString()).toEqual("undefined")
+ expect(((): Any).toString()).toEqual("undefined")
+ }
+
+ it("should have hashCode()") {
+ expect(().hashCode()).toEqual(0)
+ expect(((): Any).hashCode()).toEqual(0)
+ expect(().##).toEqual(0)
+ }
+
+ it("should equal itself") {
+ expect(().equals(())).toBeTruthy
+ expect(((): Any).equals((): Any)).toBeTruthy
+ }
+
+ it("should not equal other values") {
+ def testAgainst(v: Any): Unit = {
+ expect(().equals(v)).toBeFalsy
+ expect(((): Any).equals(v)).toBeFalsy
+ }
+
+ testAgainst(0)
+ testAgainst(1)
+ testAgainst(null)
+ testAgainst(false)
+ testAgainst("")
+ }
+
+ }
+}