diff --git a/library-js/src/scala/App.scala b/library-js/src/scala/App.scala
new file mode 100644
index 000000000000..bbba62bbf350
--- /dev/null
+++ b/library-js/src/scala/App.scala
@@ -0,0 +1,85 @@
+/*
+ * Scala (https://www.scala-lang.org)
+ *
+ * Copyright EPFL and Lightbend, Inc.
+ *
+ * Licensed under Apache License 2.0
+ * (http://www.apache.org/licenses/LICENSE-2.0).
+ *
+ * See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ */
+
+package scala
+
+import java.lang.System.{currentTimeMillis => currentTime}
+import scala.collection.mutable.ListBuffer
+
+/** The `App` trait can be used to quickly turn objects
+ * into executable programs. Here is an example:
+ * {{{
+ * object Main extends App {
+ * Console.println("Hello World: " + (args mkString ", "))
+ * }
+ * }}}
+ *
+ * No explicit `main` method is needed. Instead,
+ * the whole class body becomes the “main method”.
+ *
+ * `args` returns the current command line arguments as an array.
+ *
+ * ==Caveats==
+ *
+ * '''''It should be noted that this trait is implemented using the [[DelayedInit]]
+ * functionality, which means that fields of the object will not have been initialized
+ * before the main method has been executed.'''''
+ *
+ * Future versions of this trait will no longer extend `DelayedInit`.
+ *
+ * @author Martin Odersky
+ * @since 2.1
+ */
+trait App extends DelayedInit {
+
+ /** The time when the execution of this program started, in milliseconds since 1
+ * January 1970 UTC. */
+ final val executionStart: Long = currentTime
+
+ /** The command line arguments passed to the application's `main` method.
+ */
+ protected final def args: Array[String] = _args
+
+ private[this] var _args: Array[String] = _
+
+ private[this] val initCode = new ListBuffer[() => Unit]
+
+ /** The init hook. This saves all initialization code for execution within `main`.
+ * This method is normally never called directly from user code.
+ * Instead it is called as compiler-generated code for those classes and objects
+ * (but not traits) that inherit from the `DelayedInit` trait and that do not
+ * themselves define a `delayedInit` method.
+ * @param body the initialization code to be stored for later execution
+ */
+ @deprecated("the delayedInit mechanism will disappear", "2.11.0")
+ override def delayedInit(body: => Unit): Unit = {
+ initCode += (() => body)
+ }
+
+ /** The main method.
+ * This stores all arguments so that they can be retrieved with `args`
+ * and then executes all initialization code segments in the order in which
+ * they were passed to `delayedInit`.
+ * @param args the arguments passed to the main method
+ */
+ final def main(args: Array[String]) = {
+ this._args = args
+ for (proc <- initCode) proc()
+
+ /* DELETED for Scala.js
+ if (util.Properties.propIsSet("scala.time")) {
+ val total = currentTime - executionStart
+ Console.println("[total " + total + "ms]")
+ }
+ */
+ }
+}
diff --git a/library-js/src/scala/Array.scala b/library-js/src/scala/Array.scala
new file mode 100644
index 000000000000..5559b6650c25
--- /dev/null
+++ b/library-js/src/scala/Array.scala
@@ -0,0 +1,691 @@
+/*
+ * Scala (https://www.scala-lang.org)
+ *
+ * Copyright EPFL and Lightbend, Inc.
+ *
+ * Licensed under Apache License 2.0
+ * (http://www.apache.org/licenses/LICENSE-2.0).
+ *
+ * See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ */
+
+package scala
+
+//import scala.collection.generic._
+import scala.collection.{Factory, immutable, mutable}
+import mutable.ArrayBuilder
+import immutable.ArraySeq
+import scala.language.implicitConversions
+import scala.reflect.ClassTag
+import scala.runtime.{BoxedUnit, ScalaRunTime}
+import scala.runtime.ScalaRunTime.{array_apply, array_update}
+
+/** Utility methods for operating on arrays.
+ * For example:
+ * {{{
+ * val a = Array(1, 2)
+ * val b = Array.ofDim[Int](2)
+ * val c = Array.concat(a, b)
+ * }}}
+ * where the array objects `a`, `b` and `c` have respectively the values
+ * `Array(1, 2)`, `Array(0, 0)` and `Array(1, 2, 0, 0)`.
+ *
+ * @author Martin Odersky
+ * @since 1.0
+ */
+object Array {
+ def emptyBooleanArray = EmptyArrays.emptyBooleanArray
+ def emptyByteArray = EmptyArrays.emptyByteArray
+ def emptyCharArray = EmptyArrays.emptyCharArray
+ def emptyDoubleArray = EmptyArrays.emptyDoubleArray
+ def emptyFloatArray = EmptyArrays.emptyFloatArray
+ def emptyIntArray = EmptyArrays.emptyIntArray
+ def emptyLongArray = EmptyArrays.emptyLongArray
+ def emptyShortArray = EmptyArrays.emptyShortArray
+ def emptyObjectArray = EmptyArrays.emptyObjectArray
+
+ private object EmptyArrays {
+ val emptyBooleanArray = new Array[Boolean](0)
+ val emptyByteArray = new Array[Byte](0)
+ val emptyCharArray = new Array[Char](0)
+ val emptyDoubleArray = new Array[Double](0)
+ val emptyFloatArray = new Array[Float](0)
+ val emptyIntArray = new Array[Int](0)
+ val emptyLongArray = new Array[Long](0)
+ val emptyShortArray = new Array[Short](0)
+ val emptyObjectArray = new Array[Object](0)
+ }
+
+ /** Provides an implicit conversion from the Array object to a collection Factory */
+ implicit def toFactory[A : ClassTag](dummy: Array.type): Factory[A, Array[A]] = new ArrayFactory(dummy)
+ @SerialVersionUID(3L)
+ private class ArrayFactory[A : ClassTag](dummy: Array.type) extends Factory[A, Array[A]] with Serializable {
+ def fromSpecific(it: IterableOnce[A]): Array[A] = Array.from[A](it)
+ def newBuilder: mutable.Builder[A, Array[A]] = Array.newBuilder[A]
+ }
+
+ /**
+ * Returns a new [[scala.collection.mutable.ArrayBuilder]].
+ */
+ def newBuilder[T](implicit t: ClassTag[T]): ArrayBuilder[T] = ArrayBuilder.make[T](t)
+
+ def from[A : ClassTag](it: IterableOnce[A]): Array[A] = {
+ val n = it.knownSize
+ if (n > -1) {
+ val elements = new Array[A](n)
+ val iterator = it.iterator
+ var i = 0
+ while (i < n) {
+ ScalaRunTime.array_update(elements, i, iterator.next())
+ i = i + 1
+ }
+ elements
+ } else {
+ val b = ArrayBuilder.make[A]
+ val iterator = it.iterator
+ while (iterator.hasNext)
+ b += iterator.next()
+ b.result()
+ }
+ }
+
+ private def slowcopy(src : AnyRef,
+ srcPos : Int,
+ dest : AnyRef,
+ destPos : Int,
+ length : Int): Unit = {
+ var i = srcPos
+ var j = destPos
+ val srcUntil = srcPos + length
+ while (i < srcUntil) {
+ array_update(dest, j, array_apply(src, i))
+ i += 1
+ j += 1
+ }
+ }
+
+ /** Copy one array to another.
+ * Equivalent to Java's
+ * `System.arraycopy(src, srcPos, dest, destPos, length)`,
+ * except that this also works for polymorphic and boxed arrays.
+ *
+ * Note that the passed-in `dest` array will be modified by this call.
+ *
+ * @param src the source array.
+ * @param srcPos starting position in the source array.
+ * @param dest destination array.
+ * @param destPos starting position in the destination array.
+ * @param length the number of array elements to be copied.
+ *
+ * @see `java.lang.System#arraycopy`
+ */
+ def copy(src: AnyRef, srcPos: Int, dest: AnyRef, destPos: Int, length: Int): Unit = {
+ val srcClass = src.getClass
+ if (srcClass.isArray && dest.getClass.isAssignableFrom(srcClass))
+ java.lang.System.arraycopy(src, srcPos, dest, destPos, length)
+ else
+ slowcopy(src, srcPos, dest, destPos, length)
+ }
+
+ /** Copy one array to another, truncating or padding with default values (if
+ * necessary) so the copy has the specified length.
+ *
+ * Equivalent to Java's
+ * `java.util.Arrays.copyOf(original, newLength)`,
+ * except that this works for primitive and object arrays in a single method.
+ *
+ * @see `java.util.Arrays#copyOf`
+ */
+ def copyOf[A](original: Array[A], newLength: Int): Array[A] = (original match {
+ case x: Array[BoxedUnit] => newUnitArray(newLength).asInstanceOf[Array[A]]
+ case x: Array[AnyRef] => java.util.Arrays.copyOf(x, newLength)
+ case x: Array[Int] => java.util.Arrays.copyOf(x, newLength)
+ case x: Array[Double] => java.util.Arrays.copyOf(x, newLength)
+ case x: Array[Long] => java.util.Arrays.copyOf(x, newLength)
+ case x: Array[Float] => java.util.Arrays.copyOf(x, newLength)
+ case x: Array[Char] => java.util.Arrays.copyOf(x, newLength)
+ case x: Array[Byte] => java.util.Arrays.copyOf(x, newLength)
+ case x: Array[Short] => java.util.Arrays.copyOf(x, newLength)
+ case x: Array[Boolean] => java.util.Arrays.copyOf(x, newLength)
+ }).asInstanceOf[Array[A]]
+
+ /** Copy one array to another, truncating or padding with default values (if
+ * necessary) so the copy has the specified length. The new array can have
+ * a different type than the original one as long as the values are
+ * assignment-compatible. When copying between primitive and object arrays,
+ * boxing and unboxing are supported.
+ *
+ * Equivalent to Java's
+ * `java.util.Arrays.copyOf(original, newLength, newType)`,
+ * except that this works for all combinations of primitive and object arrays
+ * in a single method.
+ *
+ * @see `java.util.Arrays#copyOf`
+ */
+ def copyAs[A](original: Array[_], newLength: Int)(implicit ct: ClassTag[A]): Array[A] = {
+ val runtimeClass = ct.runtimeClass
+ if (runtimeClass == Void.TYPE) newUnitArray(newLength).asInstanceOf[Array[A]]
+ else {
+ val destClass = runtimeClass.asInstanceOf[Class[A]]
+ if (destClass.isAssignableFrom(original.getClass.getComponentType)) {
+ if (destClass.isPrimitive) copyOf[A](original.asInstanceOf[Array[A]], newLength)
+ else {
+ val destArrayClass = java.lang.reflect.Array.newInstance(destClass, 0).getClass.asInstanceOf[Class[Array[AnyRef]]]
+ java.util.Arrays.copyOf(original.asInstanceOf[Array[AnyRef]], newLength, destArrayClass).asInstanceOf[Array[A]]
+ }
+ } else {
+ val dest = new Array[A](newLength)
+ Array.copy(original, 0, dest, 0, original.length)
+ dest
+ }
+ }
+ }
+
+ private def newUnitArray(len: Int): Array[Unit] = {
+ val result = new Array[Unit](len)
+ java.util.Arrays.fill(result.asInstanceOf[Array[AnyRef]], ())
+ result
+ }
+
+ /** Returns an array of length 0 */
+ def empty[T: ClassTag]: Array[T] = new Array[T](0)
+
+ /** Creates an array with given elements.
+ *
+ * @param xs the elements to put in the array
+ * @return an array containing all elements from xs.
+ */
+ // Subject to a compiler optimization in Cleanup.
+ // Array(e0, ..., en) is translated to { val a = new Array(3); a(i) = ei; a }
+ def apply[T: ClassTag](xs: T*): Array[T] = {
+ val array = new Array[T](xs.length)
+ val iterator = xs.iterator
+ var i = 0
+ while (iterator.hasNext) {
+ array(i) = iterator.next(); i += 1
+ }
+ array
+ }
+
+ /** Creates an array of `Boolean` objects */
+ // Subject to a compiler optimization in Cleanup, see above.
+ def apply(x: Boolean, xs: Boolean*): Array[Boolean] = {
+ val array = new Array[Boolean](xs.length + 1)
+ array(0) = x
+ val iterator = xs.iterator
+ var i = 1
+ while (iterator.hasNext) {
+ array(i) = iterator.next(); i += 1
+ }
+ array
+ }
+
+ /** Creates an array of `Byte` objects */
+ // Subject to a compiler optimization in Cleanup, see above.
+ def apply(x: Byte, xs: Byte*): Array[Byte] = {
+ val array = new Array[Byte](xs.length + 1)
+ array(0) = x
+ val iterator = xs.iterator
+ var i = 1
+ while (iterator.hasNext) {
+ array(i) = iterator.next(); i += 1
+ }
+ array
+ }
+
+ /** Creates an array of `Short` objects */
+ // Subject to a compiler optimization in Cleanup, see above.
+ def apply(x: Short, xs: Short*): Array[Short] = {
+ val array = new Array[Short](xs.length + 1)
+ array(0) = x
+ val iterator = xs.iterator
+ var i = 1
+ while (iterator.hasNext) {
+ array(i) = iterator.next(); i += 1
+ }
+ array
+ }
+
+ /** Creates an array of `Char` objects */
+ // Subject to a compiler optimization in Cleanup, see above.
+ def apply(x: Char, xs: Char*): Array[Char] = {
+ val array = new Array[Char](xs.length + 1)
+ array(0) = x
+ val iterator = xs.iterator
+ var i = 1
+ while (iterator.hasNext) {
+ array(i) = iterator.next(); i += 1
+ }
+ array
+ }
+
+ /** Creates an array of `Int` objects */
+ // Subject to a compiler optimization in Cleanup, see above.
+ def apply(x: Int, xs: Int*): Array[Int] = {
+ val array = new Array[Int](xs.length + 1)
+ array(0) = x
+ val iterator = xs.iterator
+ var i = 1
+ while (iterator.hasNext) {
+ array(i) = iterator.next(); i += 1
+ }
+ array
+ }
+
+ /** Creates an array of `Long` objects */
+ // Subject to a compiler optimization in Cleanup, see above.
+ def apply(x: Long, xs: Long*): Array[Long] = {
+ val array = new Array[Long](xs.length + 1)
+ array(0) = x
+ val iterator = xs.iterator
+ var i = 1
+ while (iterator.hasNext) {
+ array(i) = iterator.next(); i += 1
+ }
+ array
+ }
+
+ /** Creates an array of `Float` objects */
+ // Subject to a compiler optimization in Cleanup, see above.
+ def apply(x: Float, xs: Float*): Array[Float] = {
+ val array = new Array[Float](xs.length + 1)
+ array(0) = x
+ val iterator = xs.iterator
+ var i = 1
+ while (iterator.hasNext) {
+ array(i) = iterator.next(); i += 1
+ }
+ array
+ }
+
+ /** Creates an array of `Double` objects */
+ // Subject to a compiler optimization in Cleanup, see above.
+ def apply(x: Double, xs: Double*): Array[Double] = {
+ val array = new Array[Double](xs.length + 1)
+ array(0) = x
+ val iterator = xs.iterator
+ var i = 1
+ while (iterator.hasNext) {
+ array(i) = iterator.next(); i += 1
+ }
+ array
+ }
+
+ /** Creates an array of `Unit` objects */
+ def apply(x: Unit, xs: Unit*): Array[Unit] = {
+ val array = new Array[Unit](xs.length + 1)
+ array(0) = x
+ val iterator = xs.iterator
+ var i = 1
+ while (iterator.hasNext) {
+ array(i) = iterator.next(); i += 1
+ }
+ array
+ }
+
+ /** Creates array with given dimensions */
+ def ofDim[T: ClassTag](n1: Int): Array[T] =
+ new Array[T](n1)
+ /** Creates a 2-dimensional array */
+ def ofDim[T: ClassTag](n1: Int, n2: Int): Array[Array[T]] = {
+ val arr: Array[Array[T]] = (new Array[Array[T]](n1): Array[Array[T]])
+ for (i <- 0 until n1) arr(i) = new Array[T](n2)
+ arr
+ // tabulate(n1)(_ => ofDim[T](n2))
+ }
+ /** Creates a 3-dimensional array */
+ def ofDim[T: ClassTag](n1: Int, n2: Int, n3: Int): Array[Array[Array[T]]] =
+ tabulate(n1)(_ => ofDim[T](n2, n3))
+ /** Creates a 4-dimensional array */
+ def ofDim[T: ClassTag](n1: Int, n2: Int, n3: Int, n4: Int): Array[Array[Array[Array[T]]]] =
+ tabulate(n1)(_ => ofDim[T](n2, n3, n4))
+ /** Creates a 5-dimensional array */
+ def ofDim[T: ClassTag](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int): Array[Array[Array[Array[Array[T]]]]] =
+ tabulate(n1)(_ => ofDim[T](n2, n3, n4, n5))
+
+ /** Concatenates all arrays into a single array.
+ *
+ * @param xss the given arrays
+ * @return the array created from concatenating `xss`
+ */
+ def concat[T: ClassTag](xss: Array[T]*): Array[T] = {
+ val b = newBuilder[T]
+ b.sizeHint(xss.map(_.length).sum)
+ for (xs <- xss) b ++= xs
+ b.result()
+ }
+
+ /** Returns an array that contains the results of some element computation a number
+ * of times.
+ *
+ * Note that this means that `elem` is computed a total of n times:
+ * {{{
+ * scala> Array.fill(3){ math.random }
+ * res3: Array[Double] = Array(0.365461167592537, 1.550395944913685E-4, 0.7907242137333306)
+ * }}}
+ *
+ * @param n the number of elements desired
+ * @param elem the element computation
+ * @return an Array of size n, where each element contains the result of computing
+ * `elem`.
+ */
+ def fill[T: ClassTag](n: Int)(elem: => T): Array[T] = {
+ if (n <= 0) {
+ empty[T]
+ } else {
+ val array = new Array[T](n)
+ var i = 0
+ while (i < n) {
+ array(i) = elem
+ i += 1
+ }
+ array
+ }
+ }
+
+ /** Returns a two-dimensional array that contains the results of some element
+ * computation a number of times.
+ *
+ * @param n1 the number of elements in the 1st dimension
+ * @param n2 the number of elements in the 2nd dimension
+ * @param elem the element computation
+ */
+ def fill[T: ClassTag](n1: Int, n2: Int)(elem: => T): Array[Array[T]] =
+ tabulate(n1)(_ => fill(n2)(elem))
+
+ /** Returns a three-dimensional array that contains the results of some element
+ * computation a number of times.
+ *
+ * @param n1 the number of elements in the 1st dimension
+ * @param n2 the number of elements in the 2nd dimension
+ * @param n3 the number of elements in the 3rd dimension
+ * @param elem the element computation
+ */
+ def fill[T: ClassTag](n1: Int, n2: Int, n3: Int)(elem: => T): Array[Array[Array[T]]] =
+ tabulate(n1)(_ => fill(n2, n3)(elem))
+
+ /** Returns a four-dimensional array that contains the results of some element
+ * computation a number of times.
+ *
+ * @param n1 the number of elements in the 1st dimension
+ * @param n2 the number of elements in the 2nd dimension
+ * @param n3 the number of elements in the 3rd dimension
+ * @param n4 the number of elements in the 4th dimension
+ * @param elem the element computation
+ */
+ def fill[T: ClassTag](n1: Int, n2: Int, n3: Int, n4: Int)(elem: => T): Array[Array[Array[Array[T]]]] =
+ tabulate(n1)(_ => fill(n2, n3, n4)(elem))
+
+ /** Returns a five-dimensional array that contains the results of some element
+ * computation a number of times.
+ *
+ * @param n1 the number of elements in the 1st dimension
+ * @param n2 the number of elements in the 2nd dimension
+ * @param n3 the number of elements in the 3rd dimension
+ * @param n4 the number of elements in the 4th dimension
+ * @param n5 the number of elements in the 5th dimension
+ * @param elem the element computation
+ */
+ def fill[T: ClassTag](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(elem: => T): Array[Array[Array[Array[Array[T]]]]] =
+ tabulate(n1)(_ => fill(n2, n3, n4, n5)(elem))
+
+ /** Returns an array containing values of a given function over a range of integer
+ * values starting from 0.
+ *
+ * @param n The number of elements in the array
+ * @param f The function computing element values
+ * @return A traversable consisting of elements `f(0),f(1), ..., f(n - 1)`
+ */
+ def tabulate[T: ClassTag](n: Int)(f: Int => T): Array[T] = {
+ if (n <= 0) {
+ empty[T]
+ } else {
+ val array = new Array[T](n)
+ var i = 0
+ while (i < n) {
+ array(i) = f(i)
+ i += 1
+ }
+ array
+ }
+ }
+
+ /** Returns a two-dimensional array containing values of a given function
+ * over ranges of integer values starting from `0`.
+ *
+ * @param n1 the number of elements in the 1st dimension
+ * @param n2 the number of elements in the 2nd dimension
+ * @param f The function computing element values
+ */
+ def tabulate[T: ClassTag](n1: Int, n2: Int)(f: (Int, Int) => T): Array[Array[T]] =
+ tabulate(n1)(i1 => tabulate(n2)(f(i1, _)))
+
+ /** Returns a three-dimensional array containing values of a given function
+ * over ranges of integer values starting from `0`.
+ *
+ * @param n1 the number of elements in the 1st dimension
+ * @param n2 the number of elements in the 2nd dimension
+ * @param n3 the number of elements in the 3rd dimension
+ * @param f The function computing element values
+ */
+ def tabulate[T: ClassTag](n1: Int, n2: Int, n3: Int)(f: (Int, Int, Int) => T): Array[Array[Array[T]]] =
+ tabulate(n1)(i1 => tabulate(n2, n3)(f(i1, _, _)))
+
+ /** Returns a four-dimensional array containing values of a given function
+ * over ranges of integer values starting from `0`.
+ *
+ * @param n1 the number of elements in the 1st dimension
+ * @param n2 the number of elements in the 2nd dimension
+ * @param n3 the number of elements in the 3rd dimension
+ * @param n4 the number of elements in the 4th dimension
+ * @param f The function computing element values
+ */
+ def tabulate[T: ClassTag](n1: Int, n2: Int, n3: Int, n4: Int)(f: (Int, Int, Int, Int) => T): Array[Array[Array[Array[T]]]] =
+ tabulate(n1)(i1 => tabulate(n2, n3, n4)(f(i1, _, _, _)))
+
+ /** Returns a five-dimensional array containing values of a given function
+ * over ranges of integer values starting from `0`.
+ *
+ * @param n1 the number of elements in the 1st dimension
+ * @param n2 the number of elements in the 2nd dimension
+ * @param n3 the number of elements in the 3rd dimension
+ * @param n4 the number of elements in the 4th dimension
+ * @param n5 the number of elements in the 5th dimension
+ * @param f The function computing element values
+ */
+ def tabulate[T: ClassTag](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(f: (Int, Int, Int, Int, Int) => T): Array[Array[Array[Array[Array[T]]]]] =
+ tabulate(n1)(i1 => tabulate(n2, n3, n4, n5)(f(i1, _, _, _, _)))
+
+ /** Returns an array containing a sequence of increasing integers in a range.
+ *
+ * @param start the start value of the array
+ * @param end the end value of the array, exclusive (in other words, this is the first value '''not''' returned)
+ * @return the array with values in range `start, start + 1, ..., end - 1`
+ * up to, but excluding, `end`.
+ */
+ def range(start: Int, end: Int): Array[Int] = range(start, end, 1)
+
+ /** Returns an array containing equally spaced values in some integer interval.
+ *
+ * @param start the start value of the array
+ * @param end the end value of the array, exclusive (in other words, this is the first value '''not''' returned)
+ * @param step the increment value of the array (may not be zero)
+ * @return the array with values in `start, start + step, ...` up to, but excluding `end`
+ */
+ def range(start: Int, end: Int, step: Int): Array[Int] = {
+ if (step == 0) throw new IllegalArgumentException("zero step")
+ val array = new Array[Int](immutable.Range.count(start, end, step, isInclusive = false))
+
+ var n = 0
+ var i = start
+ while (if (step < 0) end < i else i < end) {
+ array(n) = i
+ i += step
+ n += 1
+ }
+ array
+ }
+
+ /** Returns an array containing repeated applications of a function to a start value.
+ *
+ * @param start the start value of the array
+ * @param len the number of elements returned by the array
+ * @param f the function that is repeatedly applied
+ * @return the array returning `len` values in the sequence `start, f(start), f(f(start)), ...`
+ */
+ def iterate[T: ClassTag](start: T, len: Int)(f: T => T): Array[T] = {
+ if (len > 0) {
+ val array = new Array[T](len)
+ var acc = start
+ var i = 1
+ array(0) = acc
+
+ while (i < len) {
+ acc = f(acc)
+ array(i) = acc
+ i += 1
+ }
+ array
+ } else {
+ empty[T]
+ }
+ }
+
+ def equals(xs: Array[AnyRef], ys: Array[AnyRef]): Boolean = {
+ if (xs eq ys)
+ return true
+ if (xs.length != ys.length)
+ return false
+
+ val len = xs.length
+ var i = 0
+ while (i < len) {
+ if (xs(i) != ys(i))
+ return false
+ i += 1
+ }
+ true
+ }
+
+ /** Called in a pattern match like `{ case Array(x,y,z) => println('3 elements')}`.
+ *
+ * @param x the selector value
+ * @return sequence wrapped in a [[scala.Some]], if `x` is an Array, otherwise `None`
+ */
+ def unapplySeq[T](x: Array[T]): UnapplySeqWrapper[T] = new UnapplySeqWrapper(x)
+
+ final class UnapplySeqWrapper[T](private val a: Array[T]) extends AnyVal {
+ def isEmpty: Boolean = false
+ def get: UnapplySeqWrapper[T] = this
+ def lengthCompare(len: Int): Int = a.lengthCompare(len)
+ def apply(i: Int): T = a(i)
+ def drop(n: Int): scala.Seq[T] = ArraySeq.unsafeWrapArray(a.drop(n)) // clones the array, also if n == 0
+ def toSeq: scala.Seq[T] = a.toSeq // clones the array
+ }
+}
+
+/** Arrays are mutable, indexed collections of values. `Array[T]` is Scala's representation
+ * for Java's `T[]`.
+ *
+ * {{{
+ * val numbers = Array(1, 2, 3, 4)
+ * val first = numbers(0) // read the first element
+ * numbers(3) = 100 // replace the 4th array element with 100
+ * val biggerNumbers = numbers.map(_ * 2) // multiply all numbers by two
+ * }}}
+ *
+ * Arrays make use of two common pieces of Scala syntactic sugar, shown on lines 2 and 3 of the above
+ * example code.
+ * Line 2 is translated into a call to `apply(Int)`, while line 3 is translated into a call to
+ * `update(Int, T)`.
+ *
+ * Two implicit conversions exist in [[scala.Predef]] that are frequently applied to arrays: a conversion
+ * to [[scala.collection.ArrayOps]] (shown on line 4 of the example above) and a conversion
+ * to [[scala.collection.mutable.ArraySeq]] (a subtype of [[scala.collection.Seq]]).
+ * Both types make available many of the standard operations found in the Scala collections API.
+ * The conversion to `ArrayOps` is temporary, as all operations defined on `ArrayOps` return an `Array`,
+ * while the conversion to `ArraySeq` is permanent as all operations return a `ArraySeq`.
+ *
+ * The conversion to `ArrayOps` takes priority over the conversion to `ArraySeq`. For instance,
+ * consider the following code:
+ *
+ * {{{
+ * val arr = Array(1, 2, 3)
+ * val arrReversed = arr.reverse
+ * val seqReversed : collection.Seq[Int] = arr.reverse
+ * }}}
+ *
+ * Value `arrReversed` will be of type `Array[Int]`, with an implicit conversion to `ArrayOps` occurring
+ * to perform the `reverse` operation. The value of `seqReversed`, on the other hand, will be computed
+ * by converting to `ArraySeq` first and invoking the variant of `reverse` that returns another
+ * `ArraySeq`.
+ *
+ * @author Martin Odersky
+ * @since 1.0
+ * @see [[http://www.scala-lang.org/files/archive/spec/2.13/ Scala Language Specification]], for in-depth information on the transformations the Scala compiler makes on Arrays (Sections 6.6 and 6.15 respectively.)
+ * @see [[http://docs.scala-lang.org/sips/completed/scala-2-8-arrays.html "Scala 2.8 Arrays"]] the Scala Improvement Document detailing arrays since Scala 2.8.
+ * @see [[http://docs.scala-lang.org/overviews/collections/arrays.html "The Scala 2.8 Collections' API"]] section on `Array` by Martin Odersky for more information.
+ * @hideImplicitConversion scala.Predef.booleanArrayOps
+ * @hideImplicitConversion scala.Predef.byteArrayOps
+ * @hideImplicitConversion scala.Predef.charArrayOps
+ * @hideImplicitConversion scala.Predef.doubleArrayOps
+ * @hideImplicitConversion scala.Predef.floatArrayOps
+ * @hideImplicitConversion scala.Predef.intArrayOps
+ * @hideImplicitConversion scala.Predef.longArrayOps
+ * @hideImplicitConversion scala.Predef.refArrayOps
+ * @hideImplicitConversion scala.Predef.shortArrayOps
+ * @hideImplicitConversion scala.Predef.unitArrayOps
+ * @hideImplicitConversion scala.LowPriorityImplicits.wrapRefArray
+ * @hideImplicitConversion scala.LowPriorityImplicits.wrapIntArray
+ * @hideImplicitConversion scala.LowPriorityImplicits.wrapDoubleArray
+ * @hideImplicitConversion scala.LowPriorityImplicits.wrapLongArray
+ * @hideImplicitConversion scala.LowPriorityImplicits.wrapFloatArray
+ * @hideImplicitConversion scala.LowPriorityImplicits.wrapCharArray
+ * @hideImplicitConversion scala.LowPriorityImplicits.wrapByteArray
+ * @hideImplicitConversion scala.LowPriorityImplicits.wrapShortArray
+ * @hideImplicitConversion scala.LowPriorityImplicits.wrapBooleanArray
+ * @hideImplicitConversion scala.LowPriorityImplicits.wrapUnitArray
+ * @hideImplicitConversion scala.LowPriorityImplicits.genericWrapArray
+ * @define coll array
+ * @define Coll `Array`
+ * @define orderDependent
+ * @define orderDependentFold
+ * @define mayNotTerminateInf
+ * @define willNotTerminateInf
+ * @define collectExample
+ * @define undefinedorder
+ */
+final class Array[T](_length: Int) extends java.io.Serializable with java.lang.Cloneable {
+
+ /** The length of the array */
+ def length: Int = throw new Error()
+
+ /** The element at given index.
+ *
+ * Indices start at `0`; `xs.apply(0)` is the first element of array `xs`.
+ * Note the indexing syntax `xs(i)` is a shorthand for `xs.apply(i)`.
+ *
+ * @param i the index
+ * @return the element at the given index
+ * @throws ArrayIndexOutOfBoundsException if `i < 0` or `length <= i`
+ */
+ def apply(i: Int): T = throw new Error()
+
+ /** Update the element at given index.
+ *
+ * Indices start at `0`; `xs.update(i, x)` replaces the i^th^ element in the array.
+ * Note the syntax `xs(i) = x` is a shorthand for `xs.update(i, x)`.
+ *
+ * @param i the index
+ * @param x the value to be written at index `i`
+ * @throws ArrayIndexOutOfBoundsException if `i < 0` or `length <= i`
+ */
+ def update(i: Int, x: T): Unit = { throw new Error() }
+
+ /** Clone the Array.
+ *
+ * @return A clone of the Array.
+ */
+ override def clone(): Array[T] = throw new Error()
+}
diff --git a/library-js/src/scala/Console.scala b/library-js/src/scala/Console.scala
new file mode 100644
index 000000000000..443c838462a6
--- /dev/null
+++ b/library-js/src/scala/Console.scala
@@ -0,0 +1,284 @@
+/*
+ * Scala (https://www.scala-lang.org)
+ *
+ * Copyright EPFL and Lightbend, Inc.
+ *
+ * Licensed under Apache License 2.0
+ * (http://www.apache.org/licenses/LICENSE-2.0).
+ *
+ * See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ */
+
+package scala
+
+import java.io.{ BufferedReader, InputStream, InputStreamReader, OutputStream, PrintStream, Reader }
+import scala.io.AnsiColor
+import scala.util.DynamicVariable
+
+/** Implements functionality for printing Scala values on the terminal. For reading values
+ * use [[scala.io.StdIn$ StdIn]].
+ * Also defines constants for marking up text on ANSI terminals.
+ *
+ * == Console Output ==
+ *
+ * Use the print methods to output text.
+ * {{{
+ * scala> Console.printf(
+ * "Today the outside temperature is a balmy %.1f°C. %<.1f°C beats the previous record of %.1f°C.\n",
+ * -137.0,
+ * -135.05)
+ * Today the outside temperature is a balmy -137.0°C. -137.0°C beats the previous record of -135.1°C.
+ * }}}
+ *
+ * == ANSI escape codes ==
+ * Use the ANSI escape codes for colorizing console output either to STDOUT or STDERR.
+ * {{{
+ * import Console.{GREEN, RED, RESET, YELLOW_B, UNDERLINED}
+ *
+ * object PrimeTest {
+ *
+ * def isPrime(): Unit = {
+ *
+ * val candidate = io.StdIn.readInt().ensuring(_ > 1)
+ *
+ * val prime = (2 to candidate - 1).forall(candidate % _ != 0)
+ *
+ * if (prime)
+ * Console.println(s"${RESET}${GREEN}yes${RESET}")
+ * else
+ * Console.err.println(s"${RESET}${YELLOW_B}${RED}${UNDERLINED}NO!${RESET}")
+ * }
+ *
+ * def main(args: Array[String]): Unit = isPrime()
+ *
+ * }
+ * }}}
+ *
+ *
+ * $ scala PrimeTest |
+ * 1234567891 |
+ * yes |
+ * $ scala PrimeTest |
+ * 56474 |
+ * NO! |
+ *
+ *
+ * == IO redefinition ==
+ *
+ * Use IO redefinition to temporarily swap in a different set of input and/or output streams. In this example the stream based
+ * method above is wrapped into a function.
+ *
+ * {{{
+ * import java.io.{ByteArrayOutputStream, StringReader}
+ *
+ * object FunctionalPrimeTest {
+ *
+ * def isPrime(candidate: Int): Boolean = {
+ *
+ * val input = new StringReader(s"$candidate\n")
+ * val outCapture = new ByteArrayOutputStream
+ * val errCapture = new ByteArrayOutputStream
+ *
+ * Console.withIn(input) {
+ * Console.withOut(outCapture) {
+ * Console.withErr(errCapture) {
+ * PrimeTest.isPrime()
+ * }
+ * }
+ * }
+ *
+ * if (outCapture.toByteArray.nonEmpty) // "yes"
+ * true
+ * else if (errCapture.toByteArray.nonEmpty) // "NO!"
+ * false
+ * else throw new IllegalArgumentException(candidate.toString)
+ * }
+ *
+ * def main(args: Array[String]): Unit = {
+ * val primes = (2 to 50) filter (isPrime)
+ * println(s"First primes: $primes")
+ * }
+ *
+ * }
+ * }}}
+ *
+ *
+ *
+ * $ scala FunctionalPrimeTest |
+ * First primes: Vector(2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47) |
+ *
+ *
+ * @author Matthias Zenger
+ * @since 1.0
+ *
+ * @groupname console-output Console Output
+ * @groupprio console-output 30
+ * @groupdesc console-output These methods provide output via the console.
+ *
+ * @groupname io-default IO Defaults
+ * @groupprio io-default 50
+ * @groupdesc io-default These values provide direct access to the standard IO channels
+ *
+ * @groupname io-redefinition IO Redefinition
+ * @groupprio io-redefinition 60
+ * @groupdesc io-redefinition These methods allow substituting alternative streams for the duration of
+ * a body of code. Threadsafe by virtue of [[scala.util.DynamicVariable]].
+ *
+ */
+object Console extends AnsiColor {
+ private[this] val outVar = new DynamicVariable[PrintStream](java.lang.System.out)
+ private[this] val errVar = new DynamicVariable[PrintStream](java.lang.System.err)
+ private[this] val inVar = new DynamicVariable[BufferedReader](null)
+ //new BufferedReader(new InputStreamReader(java.lang.System.in)))
+
+ protected def setOutDirect(out: PrintStream): Unit = outVar.value = out
+ protected def setErrDirect(err: PrintStream): Unit = errVar.value = err
+ protected def setInDirect(in: BufferedReader): Unit = inVar.value = in
+
+ /** The default output, can be overridden by `withOut`
+ * @group io-default
+ */
+ def out = outVar.value
+ /** The default error, can be overridden by `withErr`
+ * @group io-default
+ */
+ def err = errVar.value
+ /** The default input, can be overridden by `withIn`
+ * @group io-default
+ */
+ def in = inVar.value
+
+ /** Sets the default output stream for the duration
+ * of execution of one thunk.
+ *
+ * @example {{{
+ * withOut(Console.err) { println("This goes to default _error_") }
+ * }}}
+ *
+ * @param out the new output stream.
+ * @param thunk the code to execute with
+ * the new output stream active
+ * @return the results of `thunk`
+ * @see `withOut[T](out:OutputStream)(thunk: => T)`
+ * @group io-redefinition
+ */
+ def withOut[T](out: PrintStream)(thunk: =>T): T =
+ outVar.withValue(out)(thunk)
+
+ /** Sets the default output stream for the duration
+ * of execution of one thunk.
+ *
+ * @param out the new output stream.
+ * @param thunk the code to execute with
+ * the new output stream active
+ * @return the results of `thunk`
+ * @see `withOut[T](out:PrintStream)(thunk: => T)`
+ * @group io-redefinition
+ */
+ def withOut[T](out: OutputStream)(thunk: =>T): T =
+ withOut(new PrintStream(out))(thunk)
+
+ /** Set the default error stream for the duration
+ * of execution of one thunk.
+ * @example {{{
+ * withErr(Console.out) { err.println("This goes to default _out_") }
+ * }}}
+ *
+ * @param err the new error stream.
+ * @param thunk the code to execute with
+ * the new error stream active
+ * @return the results of `thunk`
+ * @see `withErr[T](err:OutputStream)(thunk: =>T)`
+ * @group io-redefinition
+ */
+ def withErr[T](err: PrintStream)(thunk: =>T): T =
+ errVar.withValue(err)(thunk)
+
+ /** Sets the default error stream for the duration
+ * of execution of one thunk.
+ *
+ * @param err the new error stream.
+ * @param thunk the code to execute with
+ * the new error stream active
+ * @return the results of `thunk`
+ * @see `withErr[T](err:PrintStream)(thunk: =>T)`
+ * @group io-redefinition
+ */
+ def withErr[T](err: OutputStream)(thunk: =>T): T =
+ withErr(new PrintStream(err))(thunk)
+
+ /** Sets the default input stream for the duration
+ * of execution of one thunk.
+ *
+ * @example {{{
+ * val someFile:Reader = openFile("file.txt")
+ * withIn(someFile) {
+ * // Reads a line from file.txt instead of default input
+ * println(readLine)
+ * }
+ * }}}
+ *
+ * @param thunk the code to execute with
+ * the new input stream active
+ *
+ * @return the results of `thunk`
+ * @see `withIn[T](in:InputStream)(thunk: =>T)`
+ * @group io-redefinition
+ */
+ def withIn[T](reader: Reader)(thunk: =>T): T =
+ inVar.withValue(new BufferedReader(reader))(thunk)
+
+ /** Sets the default input stream for the duration
+ * of execution of one thunk.
+ *
+ * @param in the new input stream.
+ * @param thunk the code to execute with
+ * the new input stream active
+ * @return the results of `thunk`
+ * @see `withIn[T](reader:Reader)(thunk: =>T)`
+ * @group io-redefinition
+ */
+ def withIn[T](in: InputStream)(thunk: =>T): T =
+ withIn(new InputStreamReader(in))(thunk)
+
+ /** Prints an object to `out` using its `toString` method.
+ *
+ * @param obj the object to print; may be null.
+ * @group console-output
+ */
+ def print(obj: Any): Unit = {
+ out.print(if (null == obj) "null" else obj.toString())
+ }
+
+ /** Flushes the output stream. This function is required when partial
+ * output (i.e. output not terminated by a newline character) has
+ * to be made visible on the terminal.
+ * @group console-output
+ */
+ def flush(): Unit = { out.flush() }
+
+ /** Prints a newline character on the default output.
+ * @group console-output
+ */
+ def println(): Unit = { out.println() }
+
+ /** Prints out an object to the default output, followed by a newline character.
+ *
+ * @param x the object to print.
+ * @group console-output
+ */
+ def println(x: Any): Unit = { out.println(x) }
+
+ /** Prints its arguments as a formatted string to the default output,
+ * based on a string pattern (in a fashion similar to printf in C).
+ *
+ * The interpretation of the formatting patterns is described in [[java.util.Formatter]].
+ *
+ * @param text the pattern for formatting the arguments.
+ * @param args the arguments used to instantiating the pattern.
+ * @throws java.lang.IllegalArgumentException if there was a problem with the format string or arguments
+ * @group console-output
+ */
+ def printf(text: String, args: Any*): Unit = { out.print(text format (args : _*)) }
+}
diff --git a/library-js/src/scala/Enumeration.scala b/library-js/src/scala/Enumeration.scala
new file mode 100644
index 000000000000..d2d379245d96
--- /dev/null
+++ b/library-js/src/scala/Enumeration.scala
@@ -0,0 +1,330 @@
+/*
+ * Scala (https://www.scala-lang.org)
+ *
+ * Copyright EPFL and Lightbend, Inc.
+ *
+ * Licensed under Apache License 2.0
+ * (http://www.apache.org/licenses/LICENSE-2.0).
+ *
+ * See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ */
+
+package scala
+
+import scala.collection.{SpecificIterableFactory, StrictOptimizedIterableOps, View, immutable, mutable}
+import java.lang.reflect.{Field => JField, Method => JMethod}
+
+import scala.annotation.implicitNotFound
+import scala.reflect.NameTransformer._
+import scala.util.matching.Regex
+
+/** Defines a finite set of values specific to the enumeration. Typically
+ * these values enumerate all possible forms something can take and provide
+ * a lightweight alternative to case classes.
+ *
+ * Each call to a `Value` method adds a new unique value to the enumeration.
+ * To be accessible, these values are usually defined as `val` members of
+ * the enumeration.
+ *
+ * All values in an enumeration share a common, unique type defined as the
+ * `Value` type member of the enumeration (`Value` selected on the stable
+ * identifier path of the enumeration instance).
+ *
+ * Values SHOULD NOT be added to an enumeration after its construction;
+ * doing so makes the enumeration thread-unsafe. If values are added to an
+ * enumeration from multiple threads (in a non-synchronized fashion) after
+ * construction, the behavior of the enumeration is undefined.
+ *
+ * @example {{{
+ * // Define a new enumeration with a type alias and work with the full set of enumerated values
+ * object WeekDay extends Enumeration {
+ * type WeekDay = Value
+ * val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
+ * }
+ * import WeekDay._
+ *
+ * def isWorkingDay(d: WeekDay) = ! (d == Sat || d == Sun)
+ *
+ * WeekDay.values filter isWorkingDay foreach println
+ * // output:
+ * // Mon
+ * // Tue
+ * // Wed
+ * // Thu
+ * // Fri
+ * }}}
+ *
+ * @example {{{
+ * // Example of adding attributes to an enumeration by extending the Enumeration.Val class
+ * object Planet extends Enumeration {
+ * protected case class Val(mass: Double, radius: Double) extends super.Val {
+ * def surfaceGravity: Double = Planet.G * mass / (radius * radius)
+ * def surfaceWeight(otherMass: Double): Double = otherMass * surfaceGravity
+ * }
+ * import scala.language.implicitConversions
+ * implicit def valueToPlanetVal(x: Value): Val = x.asInstanceOf[Val]
+ *
+ * val G: Double = 6.67300E-11
+ * val Mercury = Val(3.303e+23, 2.4397e6)
+ * val Venus = Val(4.869e+24, 6.0518e6)
+ * val Earth = Val(5.976e+24, 6.37814e6)
+ * val Mars = Val(6.421e+23, 3.3972e6)
+ * val Jupiter = Val(1.9e+27, 7.1492e7)
+ * val Saturn = Val(5.688e+26, 6.0268e7)
+ * val Uranus = Val(8.686e+25, 2.5559e7)
+ * val Neptune = Val(1.024e+26, 2.4746e7)
+ * }
+ *
+ * println(Planet.values.filter(_.radius > 7.0e6))
+ * // output:
+ * // Planet.ValueSet(Jupiter, Saturn, Uranus, Neptune)
+ * }}}
+ *
+ * @param initial The initial value from which to count the integers that
+ * identifies values at run-time.
+ * @author Matthias Zenger
+ */
+@SerialVersionUID(8476000850333817230L)
+abstract class Enumeration (initial: Int) extends Serializable {
+ thisenum =>
+
+ def this() = this(0)
+
+ /* Note that `readResolve` cannot be private, since otherwise
+ the JVM does not invoke it when deserializing subclasses. */
+ protected def readResolve(): AnyRef = ???
+
+ /** The name of this enumeration.
+ */
+ override def toString =
+ (getClass.getName.stripSuffix("$").split('.')).last.split('$').last
+
+ /** The mapping from the integer used to identify values to the actual
+ * values. */
+ private val vmap: mutable.Map[Int, Value] = new mutable.HashMap
+
+ /** The cache listing all values of this enumeration. */
+ @transient private var vset: ValueSet = null
+ @transient @volatile private var vsetDefined = false
+
+ /** The mapping from the integer used to identify values to their
+ * names. */
+ private[this] val nmap: mutable.Map[Int, String] = new mutable.HashMap
+
+ /** The values of this enumeration as a set.
+ */
+ def values: ValueSet = {
+ if (!vsetDefined) {
+ vset = (ValueSet.newBuilder ++= vmap.values).result()
+ vsetDefined = true
+ }
+ vset
+ }
+
+ /** The integer to use to identify the next created value. */
+ protected var nextId: Int = initial
+
+ /** The string to use to name the next created value. */
+ protected var nextName: Iterator[String] = _
+
+ private def nextNameOrNull =
+ if (nextName != null && nextName.hasNext) nextName.next() else null
+
+ /** The highest integer amongst those used to identify values in this
+ * enumeration. */
+ private[this] var topId = initial
+
+ /** The lowest integer amongst those used to identify values in this
+ * enumeration, but no higher than 0. */
+ private[this] var bottomId = if(initial < 0) initial else 0
+
+ /** The one higher than the highest integer amongst those used to identify
+ * values in this enumeration. */
+ final def maxId = topId
+
+ /** The value of this enumeration with given id `x`
+ */
+ final def apply(x: Int): Value = vmap(x)
+
+ /** Return a `Value` from this `Enumeration` whose name matches
+ * the argument `s`. The names are determined automatically via reflection.
+ *
+ * @param s an `Enumeration` name
+ * @return the `Value` of this `Enumeration` if its name matches `s`
+ * @throws NoSuchElementException if no `Value` with a matching
+ * name is in this `Enumeration`
+ */
+ final def withName(s: String): Value = {
+ val (unnamed, named) = values partition {
+ _.toString().startsWith(" v
+ // If we have unnamed values, we issue a detailed error message
+ case None if unnamed.nonEmpty =>
+ throw new NoSuchElementException(
+ s"""Couldn't find enum field with name $s.
+ |However, there were the following unnamed fields:
+ |${unnamed.mkString(" ","\n ","")}""".stripMargin)
+ // Normal case (no unnamed Values)
+ case _ => None.get
+ }
+ }
+
+ /** Creates a fresh value, part of this enumeration. */
+ protected final def Value: Value = Value(nextId)
+
+ /** Creates a fresh value, part of this enumeration, identified by the
+ * integer `i`.
+ *
+ * @param i An integer that identifies this value at run-time. It must be
+ * unique amongst all values of the enumeration.
+ * @return Fresh value identified by `i`.
+ */
+ protected final def Value(i: Int): Value = Value(i, nextNameOrNull)
+
+ /** Creates a fresh value, part of this enumeration, called `name`.
+ *
+ * @param name A human-readable name for that value.
+ * @return Fresh value called `name`.
+ */
+ protected final def Value(name: String): Value = Value(nextId, name)
+
+ /** Creates a fresh value, part of this enumeration, called `name`
+ * and identified by the integer `i`.
+ *
+ * @param i An integer that identifies this value at run-time. It must be
+ * unique amongst all values of the enumeration.
+ * @param name A human-readable name for that value.
+ * @return Fresh value with the provided identifier `i` and name `name`.
+ */
+ protected final def Value(i: Int, name: String): Value = new Val(i, name)
+
+ /** The type of the enumerated values. */
+ @SerialVersionUID(7091335633555234129L)
+ abstract class Value extends Ordered[Value] with Serializable {
+ /** the id and bit location of this enumeration value */
+ def id: Int
+ /** a marker so we can tell whose values belong to whom come reflective-naming time */
+ private[Enumeration] val outerEnum = thisenum
+
+ override def compare(that: Value): Int =
+ if (this.id < that.id) -1
+ else if (this.id == that.id) 0
+ else 1
+ override def equals(other: Any) = other match {
+ case that: Enumeration#Value => (outerEnum eq that.outerEnum) && (id == that.id)
+ case _ => false
+ }
+ override def hashCode: Int = id.##
+
+ /** Create a ValueSet which contains this value and another one */
+ def + (v: Value) = ValueSet(this, v)
+ }
+
+ /** A class implementing the [[scala.Enumeration.Value]] type. This class
+ * can be overridden to change the enumeration's naming and integer
+ * identification behaviour.
+ */
+ @SerialVersionUID(0 - 3501153230598116017L)
+ protected class Val(i: Int, name: String) extends Value with Serializable {
+ def this(i: Int) = this(i, nextNameOrNull)
+ def this(name: String) = this(nextId, name)
+ def this() = this(nextId)
+
+ assert(!vmap.isDefinedAt(i), "Duplicate id: " + i)
+ vmap(i) = this
+ vsetDefined = false
+ nextId = i + 1
+ if (nextId > topId) topId = nextId
+ if (i < bottomId) bottomId = i
+ def id = i
+ override def toString() =
+ if (name != null) name
+ // Scala.js specific
+ else s""
+
+ protected def readResolve(): AnyRef = {
+ val enumeration = thisenum.readResolve().asInstanceOf[Enumeration]
+ if (enumeration.vmap == null) this
+ else enumeration.vmap(i)
+ }
+ }
+
+ /** An ordering by id for values of this set */
+ implicit object ValueOrdering extends Ordering[Value] {
+ def compare(x: Value, y: Value): Int = x compare y
+ }
+
+ /** A class for sets of values.
+ * Iterating through this set will yield values in increasing order of their ids.
+ *
+ * @param nnIds The set of ids of values (adjusted so that the lowest value does
+ * not fall below zero), organized as a `BitSet`.
+ * @define Coll `collection.immutable.SortedSet`
+ */
+ class ValueSet private[ValueSet] (private[this] var nnIds: immutable.BitSet)
+ extends immutable.AbstractSet[Value]
+ with immutable.SortedSet[Value]
+ with immutable.SortedSetOps[Value, immutable.SortedSet, ValueSet]
+ with StrictOptimizedIterableOps[Value, immutable.Set, ValueSet]
+ with Serializable {
+
+ implicit def ordering: Ordering[Value] = ValueOrdering
+ def rangeImpl(from: Option[Value], until: Option[Value]): ValueSet =
+ new ValueSet(nnIds.rangeImpl(from.map(_.id - bottomId), until.map(_.id - bottomId)))
+
+ override def empty = ValueSet.empty
+ override def knownSize: Int = nnIds.size
+ override def isEmpty: Boolean = nnIds.isEmpty
+ def contains(v: Value) = nnIds contains (v.id - bottomId)
+ def incl (value: Value) = new ValueSet(nnIds + (value.id - bottomId))
+ def excl (value: Value) = new ValueSet(nnIds - (value.id - bottomId))
+ def iterator = nnIds.iterator map (id => thisenum.apply(bottomId + id))
+ override def iteratorFrom(start: Value) = nnIds iteratorFrom start.id map (id => thisenum.apply(bottomId + id))
+ override def className = s"$thisenum.ValueSet"
+ /** Creates a bit mask for the zero-adjusted ids in this set as a
+ * new array of longs */
+ def toBitMask: Array[Long] = nnIds.toBitMask
+
+ override protected def fromSpecific(coll: IterableOnce[Value]) = ValueSet.fromSpecific(coll)
+ override protected def newSpecificBuilder = ValueSet.newBuilder
+
+ def map(f: Value => Value): ValueSet = fromSpecific(new View.Map(this, f))
+ def flatMap(f: Value => IterableOnce[Value]): ValueSet = fromSpecific(new View.FlatMap(this, f))
+
+ // necessary for disambiguation:
+ override def map[B](f: Value => B)(implicit @implicitNotFound(ValueSet.ordMsg) ev: Ordering[B]): immutable.SortedSet[B] =
+ super[SortedSet].map[B](f)
+ override def flatMap[B](f: Value => IterableOnce[B])(implicit @implicitNotFound(ValueSet.ordMsg) ev: Ordering[B]): immutable.SortedSet[B] =
+ super[SortedSet].flatMap[B](f)
+ override def zip[B](that: IterableOnce[B])(implicit @implicitNotFound(ValueSet.zipOrdMsg) ev: Ordering[(Value, B)]): immutable.SortedSet[(Value, B)] =
+ super[SortedSet].zip[B](that)
+ override def collect[B](pf: PartialFunction[Value, B])(implicit @implicitNotFound(ValueSet.ordMsg) ev: Ordering[B]): immutable.SortedSet[B] =
+ super[SortedSet].collect[B](pf)
+ }
+
+ /** A factory object for value sets */
+ @SerialVersionUID(3L)
+ object ValueSet extends SpecificIterableFactory[Value, ValueSet] {
+ private final val ordMsg = "No implicit Ordering[${B}] found to build a SortedSet[${B}]. You may want to upcast to a Set[Value] first by calling `unsorted`."
+ private final val zipOrdMsg = "No implicit Ordering[${B}] found to build a SortedSet[(Value, ${B})]. You may want to upcast to a Set[Value] first by calling `unsorted`."
+
+ /** The empty value set */
+ val empty = new ValueSet(immutable.BitSet.empty)
+ /** A value set containing all the values for the zero-adjusted ids
+ * corresponding to the bits in an array */
+ def fromBitMask(elems: Array[Long]): ValueSet = new ValueSet(immutable.BitSet.fromBitMask(elems))
+ /** A builder object for value sets */
+ def newBuilder: mutable.Builder[Value, ValueSet] = new mutable.Builder[Value, ValueSet] {
+ private[this] val b = new mutable.BitSet
+ def addOne (x: Value) = { b += (x.id - bottomId); this }
+ def clear() = b.clear()
+ def result() = new ValueSet(b.toImmutable)
+ }
+ def fromSpecific(it: IterableOnce[Value]): ValueSet =
+ newBuilder.addAll(it).result()
+ }
+}
diff --git a/library-js/src/scala/Symbol.scala b/library-js/src/scala/Symbol.scala
new file mode 100644
index 000000000000..d656129ae2b3
--- /dev/null
+++ b/library-js/src/scala/Symbol.scala
@@ -0,0 +1,113 @@
+/*
+ * Scala (https://www.scala-lang.org)
+ *
+ * Copyright EPFL and Lightbend, Inc.
+ *
+ * Licensed under Apache License 2.0
+ * (http://www.apache.org/licenses/LICENSE-2.0).
+ *
+ * See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ */
+
+package scala
+
+import scala.scalajs.js
+
+/** This class provides a simple way to get unique objects for equal strings.
+ * Since symbols are interned, they can be compared using reference equality.
+ * Instances of `Symbol` can be created easily with Scala's built-in quote
+ * mechanism.
+ *
+ * For instance, the Scala term `'mysym` will
+ * invoke the constructor of the `Symbol` class in the following way:
+ * `Symbol("mysym")`.
+ *
+ * @author Martin Odersky, Iulian Dragos
+ * @since 1.7
+ */
+final class Symbol private (val name: String) extends Serializable {
+ /** Converts this symbol to a string.
+ */
+ override def toString(): String = "Symbol(" + name + ")"
+
+ @throws(classOf[java.io.ObjectStreamException])
+ private def readResolve(): Any = Symbol.apply(name)
+ override def hashCode = name.hashCode()
+ override def equals(other: Any) = this eq other.asInstanceOf[AnyRef]
+}
+
+// Modified to use Scala.js specific cache
+object Symbol extends JSUniquenessCache[Symbol] {
+ override def apply(name: String): Symbol = super.apply(name)
+ protected def valueFromKey(name: String): Symbol = new Symbol(name)
+ protected def keyFromValue(sym: Symbol): Option[String] = Some(sym.name)
+}
+
+private[scala] abstract class JSUniquenessCache[V]
+{
+ private val cache = js.Dictionary.empty[V]
+
+ protected def valueFromKey(k: String): V
+ protected def keyFromValue(v: V): Option[String]
+
+ def apply(name: String): V =
+ cache.getOrElseUpdate(name, valueFromKey(name))
+
+ def unapply(other: V): Option[String] = keyFromValue(other)
+}
+
+/** This is private so it won't appear in the library API, but
+ * abstracted to offer some hope of reusability. */
+/* DELETED for Scala.js
+private[scala] abstract class UniquenessCache[K >: js.String, V >: Null]
+{
+
+ import java.lang.ref.WeakReference
+ import java.util.WeakHashMap
+ import java.util.concurrent.locks.ReentrantReadWriteLock
+
+ private[this] val rwl = new ReentrantReadWriteLock()
+ private[this] val rlock = rwl.readLock
+ private[this] val wlock = rwl.writeLock
+ private[this] val map = new WeakHashMap[K, WeakReference[V]]
+
+ protected def valueFromKey(k: K): V
+ protected def keyFromValue(v: V): Option[K]
+
+ def apply(name: K): V = {
+ def cached(): V = {
+ rlock.lock
+ try {
+ val reference = map get name
+ if (reference == null) null
+ else reference.get // will be null if we were gc-ed
+ }
+ finally rlock.unlock
+ }
+ def updateCache(): V = {
+ wlock.lock
+ try {
+ val res = cached()
+ if (res != null) res
+ else {
+ // If we don't remove the old String key from the map, we can
+ // wind up with one String as the key and a different String as
+ // the name field in the Symbol, which can lead to surprising GC
+ // behavior and duplicate Symbols. See scala/bug#6706.
+ map remove name
+ val sym = valueFromKey(name)
+ map.put(name, new WeakReference(sym))
+ sym
+ }
+ }
+ finally wlock.unlock
+ }
+
+ val res = cached()
+ if (res == null) updateCache()
+ else res
+ }
+ def unapply(other: V): Option[K] = keyFromValue(other)
+}
+*/
diff --git a/library-js/src/scala/collection/immutable/NumericRange.scala b/library-js/src/scala/collection/immutable/NumericRange.scala
new file mode 100644
index 000000000000..c12e85e5e349
--- /dev/null
+++ b/library-js/src/scala/collection/immutable/NumericRange.scala
@@ -0,0 +1,497 @@
+/*
+ * Scala (https://www.scala-lang.org)
+ *
+ * Copyright EPFL and Lightbend, Inc.
+ *
+ * Licensed under Apache License 2.0
+ * (http://www.apache.org/licenses/LICENSE-2.0).
+ *
+ * See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ */
+
+package scala.collection.immutable
+
+import scala.collection.Stepper.EfficientSplit
+import scala.collection.{AbstractIterator, AnyStepper, IterableFactoryDefaults, Iterator, Stepper, StepperShape}
+
+/** `NumericRange` is a more generic version of the
+ * `Range` class which works with arbitrary types.
+ * It must be supplied with an `Integral` implementation of the
+ * range type.
+ *
+ * Factories for likely types include `Range.BigInt`, `Range.Long`,
+ * and `Range.BigDecimal`. `Range.Int` exists for completeness, but
+ * the `Int`-based `scala.Range` should be more performant.
+ *
+ * {{{
+ * val r1 = Range(0, 100, 1)
+ * val veryBig = Int.MaxValue.toLong + 1
+ * val r2 = Range.Long(veryBig, veryBig + 100, 1)
+ * assert(r1 sameElements r2.map(_ - veryBig))
+ * }}}
+ *
+ * @define Coll `NumericRange`
+ * @define coll numeric range
+ * @define mayNotTerminateInf
+ * @define willNotTerminateInf
+ */
+@SerialVersionUID(3L)
+sealed class NumericRange[T](
+ val start: T,
+ val end: T,
+ val step: T,
+ val isInclusive: Boolean
+)(implicit
+ num: Integral[T]
+)
+ extends AbstractSeq[T]
+ with IndexedSeq[T]
+ with IndexedSeqOps[T, IndexedSeq, IndexedSeq[T]]
+ with StrictOptimizedSeqOps[T, IndexedSeq, IndexedSeq[T]]
+ with IterableFactoryDefaults[T, IndexedSeq]
+ with Serializable { self =>
+
+ override def iterator: Iterator[T] = new NumericRange.NumericRangeIterator(this, num)
+
+ override def stepper[S <: Stepper[_]](implicit shape: StepperShape[T, S]): S with EfficientSplit = {
+ import scala.collection.convert._
+ import impl._
+ val s = shape.shape match {
+ case StepperShape.IntShape => new IntNumericRangeStepper (this.asInstanceOf[NumericRange[Int]], 0, length)
+ case StepperShape.LongShape => new LongNumericRangeStepper (this.asInstanceOf[NumericRange[Long]], 0, length)
+ case _ => shape.parUnbox(new AnyNumericRangeStepper[T](this, 0, length).asInstanceOf[AnyStepper[T] with EfficientSplit])
+ }
+ s.asInstanceOf[S with EfficientSplit]
+ }
+
+
+ /** Note that NumericRange must be invariant so that constructs
+ * such as "1L to 10 by 5" do not infer the range type as AnyVal.
+ */
+ import num._
+
+ // See comment in Range for why this must be lazy.
+ override lazy val length: Int = NumericRange.count(start, end, step, isInclusive)
+ override lazy val isEmpty: Boolean = (
+ (num.gt(start, end) && num.gt(step, num.zero))
+ || (num.lt(start, end) && num.lt(step, num.zero))
+ || (num.equiv(start, end) && !isInclusive)
+ )
+ override def last: T =
+ if (isEmpty) Nil.head
+ else locationAfterN(length - 1)
+ override def init: NumericRange[T] =
+ if (isEmpty) Nil.init
+ else new NumericRange(start, end - step, step, isInclusive)
+
+ override def head: T = if (isEmpty) Nil.head else start
+ override def tail: NumericRange[T] =
+ if (isEmpty) Nil.tail
+ else if(isInclusive) new NumericRange.Inclusive(start + step, end, step)
+ else new NumericRange.Exclusive(start + step, end, step)
+
+ /** Create a new range with the start and end values of this range and
+ * a new `step`.
+ */
+ def by(newStep: T): NumericRange[T] = copy(start, end, newStep)
+
+
+ /** Create a copy of this range.
+ */
+ def copy(start: T, end: T, step: T): NumericRange[T] =
+ new NumericRange(start, end, step, isInclusive)
+
+ @throws[IndexOutOfBoundsException]
+ def apply(idx: Int): T = {
+ if (idx < 0 || idx >= length) throw new IndexOutOfBoundsException(s"$idx is out of bounds (min 0, max ${length - 1})")
+ else locationAfterN(idx)
+ }
+
+ override def foreach[@specialized(Specializable.Unit) U](f: T => U): Unit = {
+ var count = 0
+ var current = start
+ while (count < length) {
+ f(current)
+ current += step
+ count += 1
+ }
+ }
+
+ // TODO: these private methods are straight copies from Range, duplicated
+ // to guard against any (most likely illusory) performance drop. They should
+ // be eliminated one way or another.
+
+ // Tests whether a number is within the endpoints, without testing
+ // whether it is a member of the sequence (i.e. when step > 1.)
+ private def isWithinBoundaries(elem: T) = !isEmpty && (
+ (step > zero && start <= elem && elem <= last ) ||
+ (step < zero && last <= elem && elem <= start)
+ )
+ // Methods like apply throw exceptions on invalid n, but methods like take/drop
+ // are forgiving: therefore the checks are with the methods.
+ private def locationAfterN(n: Int): T = start + (step * fromInt(n))
+
+ private def crossesTheEndAfterN(n: Int): Boolean = {
+ // if we're sure that subtraction in the context of T won't overflow, we use this function
+ // to calculate the length of the range
+ def unsafeRangeLength(r: NumericRange[T]): T = {
+ val diff = num.minus(r.end, r.start)
+ val quotient = num.quot(diff, r.step)
+ val remainder = num.rem(diff, r.step)
+ if (!r.isInclusive && num.equiv(remainder, num.zero))
+ num.max(quotient, num.zero)
+ else
+ num.max(num.plus(quotient, num.one), num.zero)
+ }
+
+ // detects whether value can survive a bidirectional trip to -and then from- Int.
+ def fitsInInteger(value: T): Boolean = num.equiv(num.fromInt(num.toInt(value)), value)
+
+ val stepIsInTheSameDirectionAsStartToEndVector =
+ (num.gt(end, start) && num.gt(step, num.zero)) || (num.lt(end, start) && num.sign(step) == -num.one)
+
+ if (num.equiv(start, end) || n <= 0 || !stepIsInTheSameDirectionAsStartToEndVector) return n >= 1
+
+ val sameSign = num.equiv(num.sign(start), num.sign(end))
+
+ if (sameSign) { // subtraction is safe
+ val len = unsafeRangeLength(this)
+ if (fitsInInteger(len)) n >= num.toInt(len) else num.gteq(num.fromInt(n), len)
+ } else {
+ // split to two ranges, which subtraction is safe in both of them (around zero)
+ val stepsRemainderToZero = num.rem(start, step)
+ val walksOnZero = num.equiv(stepsRemainderToZero, num.zero)
+ val closestToZero = if (walksOnZero) -step else stepsRemainderToZero
+
+ /*
+ When splitting into two ranges, we should be super-careful about one of the sides hitting MinValue of T,
+ so we take two steps smaller than zero to ensure unsafeRangeLength won't overflow (taking one step may overflow depending on the step).
+ Same thing happens for MaxValue from zero, so we take one step further to ensure the safety of unsafeRangeLength.
+ After performing such operation, there are some elements remaining in between and around zero,
+ which their length is represented by carry.
+ */
+ val (l: NumericRange[T], r: NumericRange[T], carry: Int) =
+ if (num.lt(start, num.zero)) {
+ if (walksOnZero) {
+ val twoStepsAfterLargestNegativeNumber = num.plus(closestToZero, num.times(step, num.fromInt(2)))
+ (NumericRange(start, closestToZero, step), copy(twoStepsAfterLargestNegativeNumber, end, step), 2)
+ } else {
+ (NumericRange(start, closestToZero, step), copy(num.plus(closestToZero, step), end, step), 1)
+ }
+ } else {
+ if (walksOnZero) {
+ val twoStepsAfterZero = num.times(step, num.fromInt(2))
+ (copy(twoStepsAfterZero, end, step), NumericRange.inclusive(start, -step, step), 2)
+ } else {
+ val twoStepsAfterSmallestPositiveNumber = num.plus(closestToZero, num.times(step, num.fromInt(2)))
+ (copy(twoStepsAfterSmallestPositiveNumber, end, step), NumericRange.inclusive(start, closestToZero, step), 2)
+ }
+ }
+
+ val leftLength = unsafeRangeLength(l)
+ val rightLength = unsafeRangeLength(r)
+
+ // instead of `n >= rightLength + leftLength + curry` which may cause addition overflow,
+ // this can be used `(n - leftLength - curry) >= rightLength` (Both in Int and T, depends on whether the lengths fit in Int)
+ if (fitsInInteger(leftLength) && fitsInInteger(rightLength))
+ n - num.toInt(leftLength) - carry >= num.toInt(rightLength)
+ else
+ num.gteq(num.minus(num.minus(num.fromInt(n), leftLength), num.fromInt(carry)), rightLength)
+ }
+ }
+
+ // When one drops everything. Can't ever have unchecked operations
+ // like "end + 1" or "end - 1" because ranges involving Int.{ MinValue, MaxValue }
+ // will overflow. This creates an exclusive range where start == end
+ // based on the given value.
+ private def newEmptyRange(value: T) = NumericRange(value, value, step)
+
+ override def take(n: Int): NumericRange[T] = {
+ if (n <= 0 || isEmpty) newEmptyRange(start)
+ else if (crossesTheEndAfterN(n)) this
+ else new NumericRange.Inclusive(start, locationAfterN(n - 1), step)
+ }
+
+ override def drop(n: Int): NumericRange[T] = {
+ if (n <= 0 || isEmpty) this
+ else if (crossesTheEndAfterN(n)) newEmptyRange(end)
+ else copy(locationAfterN(n), end, step)
+ }
+
+ override def splitAt(n: Int): (NumericRange[T], NumericRange[T]) = (take(n), drop(n))
+
+ override def reverse: NumericRange[T] =
+ if (isEmpty) this
+ else {
+ val newStep = -step
+ if (num.sign(newStep) == num.sign(step)) {
+ throw new ArithmeticException("number type is unsigned, and .reverse requires a negative step")
+ } else new NumericRange.Inclusive(last, start, newStep)
+ }
+
+ import NumericRange.defaultOrdering
+
+ override def min[T1 >: T](implicit ord: Ordering[T1]): T =
+ // We can take the fast path:
+ // - If the Integral of this NumericRange is also the requested Ordering
+ // (Integral <: Ordering). This can happen for custom Integral types.
+ // - The Ordering is the default Ordering of a well-known Integral type.
+ if ((ord eq num) || defaultOrdering.get(num).exists(ord eq _)) {
+ if (num.sign(step) > zero) head
+ else last
+ } else super.min(ord)
+
+ override def max[T1 >: T](implicit ord: Ordering[T1]): T =
+ // See comment for fast path in min().
+ if ((ord eq num) || defaultOrdering.get(num).exists(ord eq _)) {
+ if (num.sign(step) > zero) last
+ else head
+ } else super.max(ord)
+
+ // a well-typed contains method.
+ def containsTyped(x: T): Boolean =
+ isWithinBoundaries(x) && (((x - start) % step) == zero)
+
+ override def contains[A1 >: T](x: A1): Boolean =
+ try containsTyped(x.asInstanceOf[T])
+ catch { case _: ClassCastException => false }
+
+ override def sum[B >: T](implicit num: Numeric[B]): B = {
+ if (isEmpty) num.zero
+ else if (size == 1) head
+ else {
+ // If there is no overflow, use arithmetic series formula
+ // a + ... (n terms total) ... + b = n*(a+b)/2
+ if ((num eq scala.math.Numeric.IntIsIntegral)||
+ (num eq scala.math.Numeric.ShortIsIntegral)||
+ (num eq scala.math.Numeric.ByteIsIntegral)||
+ (num eq scala.math.Numeric.CharIsIntegral)) {
+ // We can do math with no overflow in a Long--easy
+ val exact = (size * ((num toLong head) + (num toInt last))) / 2
+ num fromInt exact.toInt
+ }
+ else if (num eq scala.math.Numeric.LongIsIntegral) {
+ // Uh-oh, might be overflow, so we have to divide before we overflow.
+ // Either numRangeElements or (head + last) must be even, so divide the even one before multiplying
+ val a = head.toLong
+ val b = last.toLong
+ val ans =
+ if ((size & 1) == 0) (size / 2) * (a + b)
+ else size * {
+ // Sum is even, but we might overflow it, so divide in pieces and add back remainder
+ val ha = a/2
+ val hb = b/2
+ ha + hb + ((a - 2*ha) + (b - 2*hb)) / 2
+ }
+ ans.asInstanceOf[B]
+ }
+ else {
+ // User provided custom Numeric, so we cannot rely on arithmetic series formula (e.g. won't work on something like Z_6)
+ if (isEmpty) num.zero
+ else {
+ var acc = num.zero
+ var i = head
+ var idx = 0
+ while(idx < length) {
+ acc = num.plus(acc, i)
+ i = i + step
+ idx = idx + 1
+ }
+ acc
+ }
+ }
+ }
+ }
+
+ override lazy val hashCode: Int = super.hashCode()
+ override protected final def applyPreferredMaxLength: Int = Int.MaxValue
+
+ override def equals(other: Any): Boolean = other match {
+ case x: NumericRange[_] =>
+ (x canEqual this) && (length == x.length) && (
+ (isEmpty) || // all empty sequences are equal
+ (start == x.start && last == x.last) // same length and same endpoints implies equality
+ )
+ case _ =>
+ super.equals(other)
+ }
+
+ override def toString: String = {
+ val empty = if (isEmpty) "empty " else ""
+ val preposition = if (isInclusive) "to" else "until"
+ val stepped = if (step == 1) "" else s" by $step"
+ s"${empty}NumericRange $start $preposition $end$stepped"
+ }
+
+ override protected[this] def className = "NumericRange"
+}
+
+/** A companion object for numeric ranges.
+ * @define Coll `NumericRange`
+ * @define coll numeric range
+ */
+object NumericRange {
+ private def bigDecimalCheckUnderflow[T](start: T, end: T, step: T)(implicit num: Integral[T]): Unit = {
+ def FAIL(boundary: T, step: T): Unit = {
+ val msg = boundary match {
+ case bd: BigDecimal => s"Precision ${bd.mc.getPrecision}"
+ case _ => "Precision"
+ }
+ throw new IllegalArgumentException(
+ s"$msg inadequate to represent steps of size $step near $boundary"
+ )
+ }
+ if (num.minus(num.plus(start, step), start) != step) FAIL(start, step)
+ if (num.minus(end, num.minus(end, step)) != step) FAIL(end, step)
+ }
+
+ /** Calculates the number of elements in a range given start, end, step, and
+ * whether or not it is inclusive. Throws an exception if step == 0 or
+ * the number of elements exceeds the maximum Int.
+ */
+ def count[T](start: T, end: T, step: T, isInclusive: Boolean)(implicit num: Integral[T]): Int = {
+ val zero = num.zero
+ val upward = num.lt(start, end)
+ val posStep = num.gt(step, zero)
+
+ if (step == zero) throw new IllegalArgumentException("step cannot be 0.")
+ else if (start == end) if (isInclusive) 1 else 0
+ else if (upward != posStep) 0
+ else {
+ /* We have to be frightfully paranoid about running out of range.
+ * We also can't assume that the numbers will fit in a Long.
+ * We will assume that if a > 0, -a can be represented, and if
+ * a < 0, -a+1 can be represented. We also assume that if we
+ * can't fit in Int, we can represent 2*Int.MaxValue+3 (at least).
+ * And we assume that numbers wrap rather than cap when they overflow.
+ */
+ // Check whether we can short-circuit by deferring to Int range.
+ val startint = num.toInt(start)
+ if (start == num.fromInt(startint)) {
+ val endint = num.toInt(end)
+ if (end == num.fromInt(endint)) {
+ val stepint = num.toInt(step)
+ if (step == num.fromInt(stepint)) {
+ return {
+ if (isInclusive) Range.inclusive(startint, endint, stepint).length
+ else Range (startint, endint, stepint).length
+ }
+ }
+ }
+ }
+ // If we reach this point, deferring to Int failed.
+ // Numbers may be big.
+ if (num.isInstanceOf[Numeric.BigDecimalAsIfIntegral]) {
+ bigDecimalCheckUnderflow(start, end, step) // Throw exception if math is inaccurate (including no progress at all)
+ }
+ val one = num.one
+ val limit = num.fromInt(Int.MaxValue)
+ def check(t: T): T =
+ if (num.gt(t, limit)) throw new IllegalArgumentException("More than Int.MaxValue elements.")
+ else t
+ // If the range crosses zero, it might overflow when subtracted
+ val startside = num.sign(start)
+ val endside = num.sign(end)
+ num.toInt{
+ if (num.gteq(num.times(startside, endside), zero)) {
+ // We're sure we can subtract these numbers.
+ // Note that we do not use .rem because of different conventions for Long and BigInt
+ val diff = num.minus(end, start)
+ val quotient = check(num.quot(diff, step))
+ val remainder = num.minus(diff, num.times(quotient, step))
+ if (!isInclusive && zero == remainder) quotient else check(num.plus(quotient, one))
+ }
+ else {
+ // We might not even be able to subtract these numbers.
+ // Jump in three pieces:
+ // * start to -1 or 1, whichever is closer (waypointA)
+ // * one step, which will take us at least to 0 (ends at waypointB)
+ // * (except with really small numbers)
+ // * there to the end
+ val negone = num.fromInt(-1)
+ val startlim = if (posStep) negone else one
+ //Use start value if the start value is closer to zero than startlim
+ // * e.g. .5 is closer to zero than 1 and -.5 is closer to zero than -1
+ val startdiff = {
+ if ((posStep && num.lt(startlim, start)) || (!posStep && num.gt(startlim, start)))
+ start
+ else
+ num.minus(startlim, start)
+ }
+ val startq = check(num.quot(startdiff, step))
+ val waypointA = if (startq == zero) start else num.plus(start, num.times(startq, step))
+ val waypointB = num.plus(waypointA, step)
+ check {
+ if (num.lt(waypointB, end) != upward) {
+ // No last piece
+ if (isInclusive && waypointB == end) num.plus(startq, num.fromInt(2))
+ else num.plus(startq, one)
+ }
+ else {
+ // There is a last piece
+ val enddiff = num.minus(end,waypointB)
+ val endq = check(num.quot(enddiff, step))
+ val last = if (endq == zero) waypointB else num.plus(waypointB, num.times(endq, step))
+ // Now we have to tally up all the pieces
+ // 1 for the initial value
+ // startq steps to waypointA
+ // 1 step to waypointB
+ // endq steps to the end (one less if !isInclusive and last==end)
+ num.plus(startq, num.plus(endq, if (!isInclusive && last==end) one else num.fromInt(2)))
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @SerialVersionUID(3L)
+ class Inclusive[T](start: T, end: T, step: T)(implicit num: Integral[T])
+ extends NumericRange(start, end, step, true) {
+ override def copy(start: T, end: T, step: T): Inclusive[T] =
+ NumericRange.inclusive(start, end, step)
+
+ def exclusive: Exclusive[T] = NumericRange(start, end, step)
+ }
+
+ @SerialVersionUID(3L)
+ class Exclusive[T](start: T, end: T, step: T)(implicit num: Integral[T])
+ extends NumericRange(start, end, step, false) {
+ override def copy(start: T, end: T, step: T): Exclusive[T] =
+ NumericRange(start, end, step)
+
+ def inclusive: Inclusive[T] = NumericRange.inclusive(start, end, step)
+ }
+
+ def apply[T](start: T, end: T, step: T)(implicit num: Integral[T]): Exclusive[T] =
+ new Exclusive(start, end, step)
+ def inclusive[T](start: T, end: T, step: T)(implicit num: Integral[T]): Inclusive[T] =
+ new Inclusive(start, end, step)
+
+ private[collection] val defaultOrdering = Map[Numeric[_], Ordering[_]](
+ Numeric.IntIsIntegral -> Ordering.Int,
+ Numeric.ShortIsIntegral -> Ordering.Short,
+ Numeric.ByteIsIntegral -> Ordering.Byte,
+ Numeric.CharIsIntegral -> Ordering.Char,
+ Numeric.LongIsIntegral -> Ordering.Long
+ )
+
+ @SerialVersionUID(3L)
+ private final class NumericRangeIterator[T](self: NumericRange[T], num: Integral[T]) extends AbstractIterator[T] with Serializable {
+ import num.mkNumericOps
+
+ private[this] var _hasNext = !self.isEmpty
+ private[this] var _next: T = self.start
+ private[this] val lastElement: T = if (_hasNext) self.last else self.start
+ override def knownSize: Int = if (_hasNext) num.toInt((lastElement - _next) / self.step) + 1 else 0
+ def hasNext: Boolean = _hasNext
+ def next(): T = {
+ if (!_hasNext) Iterator.empty.next()
+ val value = _next
+ _hasNext = value != lastElement
+ _next = num.plus(value, self.step)
+ value
+ }
+ }
+}
diff --git a/library-js/src/scala/collection/immutable/Range.scala b/library-js/src/scala/collection/immutable/Range.scala
new file mode 100644
index 000000000000..310c45c07918
--- /dev/null
+++ b/library-js/src/scala/collection/immutable/Range.scala
@@ -0,0 +1,680 @@
+/*
+ * Scala (https://www.scala-lang.org)
+ *
+ * Copyright EPFL and Lightbend, Inc.
+ *
+ * Licensed under Apache License 2.0
+ * (http://www.apache.org/licenses/LICENSE-2.0).
+ *
+ * See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ */
+
+package scala
+package collection.immutable
+
+import scala.collection.Stepper.EfficientSplit
+import scala.collection.convert.impl.RangeStepper
+import scala.collection.{AbstractIterator, AnyStepper, IterableFactoryDefaults, Iterator, Stepper, StepperShape}
+import scala.util.hashing.MurmurHash3
+
+/** The `Range` class represents integer values in range
+ * ''[start;end)'' with non-zero step value `step`.
+ * It's a special case of an indexed sequence.
+ * For example:
+ *
+ * {{{
+ * val r1 = 0 until 10
+ * val r2 = r1.start until r1.end by r1.step + 1
+ * println(r2.length) // = 5
+ * }}}
+ *
+ * Ranges that contain more than `Int.MaxValue` elements can be created, but
+ * these overfull ranges have only limited capabilities. Any method that
+ * could require a collection of over `Int.MaxValue` length to be created, or
+ * could be asked to index beyond `Int.MaxValue` elements will throw an
+ * exception. Overfull ranges can safely be reduced in size by changing
+ * the step size (e.g. `by 3`) or taking/dropping elements. `contains`,
+ * `equals`, and access to the ends of the range (`head`, `last`, `tail`,
+ * `init`) are also permitted on overfull ranges.
+ *
+ * @param start the start of this range.
+ * @param end the end of the range. For exclusive ranges, e.g.
+ * `Range(0,3)` or `(0 until 3)`, this is one
+ * step past the last one in the range. For inclusive
+ * ranges, e.g. `Range.inclusive(0,3)` or `(0 to 3)`,
+ * it may be in the range if it is not skipped by the step size.
+ * To find the last element inside a non-empty range,
+ * use `last` instead.
+ * @param step the step for the range.
+ *
+ * @define coll range
+ * @define mayNotTerminateInf
+ * @define willNotTerminateInf
+ * @define doesNotUseBuilders
+ * '''Note:''' this method does not use builders to construct a new range,
+ * and its complexity is O(1).
+ */
+@SerialVersionUID(3L)
+sealed abstract class Range(
+ val start: Int,
+ val end: Int,
+ val step: Int
+)
+ extends AbstractSeq[Int]
+ with IndexedSeq[Int]
+ with IndexedSeqOps[Int, IndexedSeq, IndexedSeq[Int]]
+ with StrictOptimizedSeqOps[Int, IndexedSeq, IndexedSeq[Int]]
+ with IterableFactoryDefaults[Int, IndexedSeq]
+ with Serializable { range =>
+
+ final override def iterator: Iterator[Int] = new RangeIterator(start, step, lastElement, isEmpty)
+
+ override final def stepper[S <: Stepper[_]](implicit shape: StepperShape[Int, S]): S with EfficientSplit = {
+ val st = new RangeStepper(start, step, 0, length)
+ val r =
+ if (shape.shape == StepperShape.IntShape) st
+ else {
+ assert(shape.shape == StepperShape.ReferenceShape, s"unexpected StepperShape: $shape")
+ AnyStepper.ofParIntStepper(st)
+ }
+ r.asInstanceOf[S with EfficientSplit]
+ }
+
+ private[this] def gap = end.toLong - start.toLong
+ private[this] def isExact = gap % step == 0
+ private[this] def hasStub = isInclusive || !isExact
+ private[this] def longLength = gap / step + ( if (hasStub) 1 else 0 )
+
+ def isInclusive: Boolean
+
+ final override val isEmpty: Boolean = (
+ (start > end && step > 0)
+ || (start < end && step < 0)
+ || (start == end && !isInclusive)
+ )
+
+ private[this] val numRangeElements: Int = {
+ if (step == 0) throw new IllegalArgumentException("step cannot be 0.")
+ else if (isEmpty) 0
+ else {
+ val len = longLength
+ if (len > scala.Int.MaxValue) -1
+ else len.toInt
+ }
+ }
+
+ final def length = if (numRangeElements < 0) fail() else numRangeElements
+
+ // This field has a sensible value only for non-empty ranges
+ private[this] val lastElement = step match {
+ case 1 => if (isInclusive) end else end-1
+ case -1 => if (isInclusive) end else end+1
+ case _ =>
+ val remainder = (gap % step).toInt
+ if (remainder != 0) end - remainder
+ else if (isInclusive) end
+ else end - step
+ }
+
+ /** The last element of this range. This method will return the correct value
+ * even if there are too many elements to iterate over.
+ */
+ final override def last: Int =
+ if (isEmpty) throw Range.emptyRangeError("last") else lastElement
+ final override def head: Int =
+ if (isEmpty) throw Range.emptyRangeError("head") else start
+
+ /** Creates a new range containing all the elements of this range except the last one.
+ *
+ * $doesNotUseBuilders
+ *
+ * @return a new range consisting of all the elements of this range except the last one.
+ */
+ final override def init: Range =
+ if (isEmpty) throw Range.emptyRangeError("init") else dropRight(1)
+
+ /** Creates a new range containing all the elements of this range except the first one.
+ *
+ * $doesNotUseBuilders
+ *
+ * @return a new range consisting of all the elements of this range except the first one.
+ */
+ final override def tail: Range = {
+ if (isEmpty) throw Range.emptyRangeError("tail")
+ if (numRangeElements == 1) newEmptyRange(end)
+ else if(isInclusive) new Range.Inclusive(start + step, end, step)
+ else new Range.Exclusive(start + step, end, step)
+ }
+
+ override def map[B](f: Int => B): IndexedSeq[B] = {
+ validateMaxLength()
+ super.map(f)
+ }
+
+ final protected def copy(start: Int = start, end: Int = end, step: Int = step, isInclusive: Boolean = isInclusive): Range =
+ if(isInclusive) new Range.Inclusive(start, end, step) else new Range.Exclusive(start, end, step)
+
+ /** Create a new range with the `start` and `end` values of this range and
+ * a new `step`.
+ *
+ * @return a new range with a different step
+ */
+ final def by(step: Int): Range = copy(start, end, step)
+
+ // Check cannot be evaluated eagerly because we have a pattern where
+ // ranges are constructed like: "x to y by z" The "x to y" piece
+ // should not trigger an exception. So the calculation is delayed,
+ // which means it will not fail fast for those cases where failing was
+ // correct.
+ private[this] def validateMaxLength(): Unit = {
+ if (numRangeElements < 0)
+ fail()
+ }
+ private[this] def fail() = Range.fail(start, end, step, isInclusive)
+
+ @throws[IndexOutOfBoundsException]
+ final def apply(idx: Int): Int = {
+ validateMaxLength()
+ if (idx < 0 || idx >= numRangeElements) throw new IndexOutOfBoundsException(s"$idx is out of bounds (min 0, max ${numRangeElements-1})")
+ else start + (step * idx)
+ }
+
+ /*@`inline`*/ final override def foreach[@specialized(Unit) U](f: Int => U): Unit = {
+ // Implementation chosen on the basis of favorable microbenchmarks
+ // Note--initialization catches step == 0 so we don't need to here
+ if (!isEmpty) {
+ var i = start
+ while (true) {
+ f(i)
+ if (i == lastElement) return
+ i += step
+ }
+ }
+ }
+
+ override final def indexOf[@specialized(Int) B >: Int](elem: B, from: Int = 0): Int =
+ elem match {
+ case i: Int =>
+ val pos = posOf(i)
+ if (pos >= from) pos else -1
+ case _ => super.indexOf(elem, from)
+ }
+
+ override final def lastIndexOf[@specialized(Int) B >: Int](elem: B, end: Int = length - 1): Int =
+ elem match {
+ case i: Int =>
+ val pos = posOf(i)
+ if (pos <= end) pos else -1
+ case _ => super.lastIndexOf(elem, end)
+ }
+
+ private[this] def posOf(i: Int): Int =
+ if (contains(i)) (i - start) / step else -1
+
+ override def sameElements[B >: Int](that: IterableOnce[B]): Boolean = that match {
+ case other: Range =>
+ (this.length : @annotation.switch) match {
+ case 0 => other.isEmpty
+ case 1 => other.length == 1 && this.start == other.start
+ case n => other.length == n && (
+ (this.start == other.start)
+ && (this.step == other.step)
+ )
+ }
+ case _ => super.sameElements(that)
+ }
+
+ /** Creates a new range containing the first `n` elements of this range.
+ *
+ * @param n the number of elements to take.
+ * @return a new range consisting of `n` first elements.
+ */
+ final override def take(n: Int): Range =
+ if (n <= 0 || isEmpty) newEmptyRange(start)
+ else if (n >= numRangeElements && numRangeElements >= 0) this
+ else {
+ // May have more than Int.MaxValue elements in range (numRangeElements < 0)
+ // but the logic is the same either way: take the first n
+ new Range.Inclusive(start, locationAfterN(n - 1), step)
+ }
+
+ /** Creates a new range containing all the elements of this range except the first `n` elements.
+ *
+ * @param n the number of elements to drop.
+ * @return a new range consisting of all the elements of this range except `n` first elements.
+ */
+ final override def drop(n: Int): Range =
+ if (n <= 0 || isEmpty) this
+ else if (n >= numRangeElements && numRangeElements >= 0) newEmptyRange(end)
+ else {
+ // May have more than Int.MaxValue elements (numRangeElements < 0)
+ // but the logic is the same either way: go forwards n steps, keep the rest
+ copy(locationAfterN(n), end, step)
+ }
+
+ /** Creates a new range consisting of the last `n` elements of the range.
+ *
+ * $doesNotUseBuilders
+ */
+ final override def takeRight(n: Int): Range = {
+ if (n <= 0) newEmptyRange(start)
+ else if (numRangeElements >= 0) drop(numRangeElements - n)
+ else {
+ // Need to handle over-full range separately
+ val y = last
+ val x = y - step.toLong*(n-1)
+ if ((step > 0 && x < start) || (step < 0 && x > start)) this
+ else Range.inclusive(x.toInt, y, step)
+ }
+ }
+
+ /** Creates a new range consisting of the initial `length - n` elements of the range.
+ *
+ * $doesNotUseBuilders
+ */
+ final override def dropRight(n: Int): Range = {
+ if (n <= 0) this
+ else if (numRangeElements >= 0) take(numRangeElements - n)
+ else {
+ // Need to handle over-full range separately
+ val y = last - step.toInt*n
+ if ((step > 0 && y < start) || (step < 0 && y > start)) newEmptyRange(start)
+ else Range.inclusive(start, y.toInt, step)
+ }
+ }
+
+ // Advance from the start while we meet the given test
+ private[this] def argTakeWhile(p: Int => Boolean): Long = {
+ if (isEmpty) start
+ else {
+ var current = start
+ val stop = last
+ while (current != stop && p(current)) current += step
+ if (current != stop || !p(current)) current
+ else current.toLong + step
+ }
+ }
+
+ final override def takeWhile(p: Int => Boolean): Range = {
+ val stop = argTakeWhile(p)
+ if (stop==start) newEmptyRange(start)
+ else {
+ val x = (stop - step).toInt
+ if (x == last) this
+ else Range.inclusive(start, x, step)
+ }
+ }
+
+ final override def dropWhile(p: Int => Boolean): Range = {
+ val stop = argTakeWhile(p)
+ if (stop == start) this
+ else {
+ val x = (stop - step).toInt
+ if (x == last) newEmptyRange(last)
+ else Range.inclusive(x + step, last, step)
+ }
+ }
+
+ final override def span(p: Int => Boolean): (Range, Range) = {
+ val border = argTakeWhile(p)
+ if (border == start) (newEmptyRange(start), this)
+ else {
+ val x = (border - step).toInt
+ if (x == last) (this, newEmptyRange(last))
+ else (Range.inclusive(start, x, step), Range.inclusive(x+step, last, step))
+ }
+ }
+
+ /** Creates a new range containing the elements starting at `from` up to but not including `until`.
+ *
+ * $doesNotUseBuilders
+ *
+ * @param from the element at which to start
+ * @param until the element at which to end (not included in the range)
+ * @return a new range consisting of a contiguous interval of values in the old range
+ */
+ final override def slice(from: Int, until: Int): Range =
+ if (from <= 0) take(until)
+ else if (until >= numRangeElements && numRangeElements >= 0) drop(from)
+ else {
+ val fromValue = locationAfterN(from)
+ if (from >= until) newEmptyRange(fromValue)
+ else Range.inclusive(fromValue, locationAfterN(until-1), step)
+ }
+
+ // Overridden only to refine the return type
+ final override def splitAt(n: Int): (Range, Range) = (take(n), drop(n))
+
+ // Methods like apply throw exceptions on invalid n, but methods like take/drop
+ // are forgiving: therefore the checks are with the methods.
+ private[this] def locationAfterN(n: Int) = start + (step * n)
+
+ // When one drops everything. Can't ever have unchecked operations
+ // like "end + 1" or "end - 1" because ranges involving Int.{ MinValue, MaxValue }
+ // will overflow. This creates an exclusive range where start == end
+ // based on the given value.
+ private[this] def newEmptyRange(value: Int) = new Range.Exclusive(value, value, step)
+
+ /** Returns the reverse of this range.
+ */
+ final override def reverse: Range =
+ if (isEmpty) this
+ else new Range.Inclusive(last, start, -step)
+
+ /** Make range inclusive.
+ */
+ final def inclusive: Range =
+ if (isInclusive) this
+ else new Range.Inclusive(start, end, step)
+
+ final def contains(x: Int) = {
+ if (x == end && !isInclusive) false
+ else if (step > 0) {
+ if (x < start || x > end) false
+ else (step == 1) || (Integer.remainderUnsigned(x - start, step) == 0)
+ }
+ else {
+ if (x < end || x > start) false
+ else (step == -1) || (Integer.remainderUnsigned(start - x, -step) == 0)
+ }
+ }
+ /* Seq#contains has a type parameter so the optimised contains above doesn't override it */
+ override final def contains[B >: Int](elem: B): Boolean = elem match {
+ case i: Int => this.contains(i)
+ case _ => super.contains(elem)
+ }
+
+ final override def sum[B >: Int](implicit num: Numeric[B]): Int = {
+ if (num eq scala.math.Numeric.IntIsIntegral) {
+ // this is normal integer range with usual addition. arithmetic series formula can be used
+ if (isEmpty) 0
+ else if (size == 1) head
+ else ((size * (head.toLong + last)) / 2).toInt
+ } else {
+ // user provided custom Numeric, we cannot rely on arithmetic series formula
+ if (isEmpty) num.toInt(num.zero)
+ else {
+ var acc = num.zero
+ var i = head
+ while (true) {
+ acc = num.plus(acc, i)
+ if (i == lastElement) return num.toInt(acc)
+ i = i + step
+ }
+ 0 // Never hit this--just to satisfy compiler since it doesn't know while(true) has type Nothing
+ }
+ }
+ }
+
+ final override def min[A1 >: Int](implicit ord: Ordering[A1]): Int =
+ if (ord eq Ordering.Int) {
+ if (step > 0) head
+ else last
+ } else if (Ordering.Int isReverseOf ord) {
+ if (step > 0) last
+ else head
+ } else super.min(ord)
+
+ final override def max[A1 >: Int](implicit ord: Ordering[A1]): Int =
+ if (ord eq Ordering.Int) {
+ if (step > 0) last
+ else head
+ } else if (Ordering.Int isReverseOf ord) {
+ if (step > 0) head
+ else last
+ } else super.max(ord)
+
+ override def tails: Iterator[Range] =
+ new AbstractIterator[Range] {
+ private[this] var i = 0
+ override def hasNext = i <= Range.this.length
+ override def next() = {
+ if (hasNext) {
+ val res = Range.this.drop(i)
+ i += 1
+ res
+ } else {
+ Iterator.empty.next()
+ }
+ }
+ }
+
+ override def inits: Iterator[Range] =
+ new AbstractIterator[Range] {
+ private[this] var i = 0
+ override def hasNext = i <= Range.this.length
+ override def next() = {
+ if (hasNext) {
+ val res = Range.this.dropRight(i)
+ i += 1
+ res
+ } else {
+ Iterator.empty.next()
+ }
+ }
+ }
+ override protected final def applyPreferredMaxLength: Int = Int.MaxValue
+
+ final override def equals(other: Any) = other match {
+ case x: Range =>
+ // Note: this must succeed for overfull ranges (length > Int.MaxValue)
+ if (isEmpty) x.isEmpty // empty sequences are equal
+ else // this is non-empty...
+ x.nonEmpty && start == x.start && { // ...so other must contain something and have same start
+ val l0 = last
+ (l0 == x.last && ( // And same end
+ start == l0 || step == x.step // And either the same step, or not take any steps
+ ))
+ }
+ case _ =>
+ super.equals(other)
+ }
+
+ final override def hashCode: Int =
+ if(length >= 2) MurmurHash3.rangeHash(start, step, lastElement)
+ else super.hashCode
+
+ final override def toString: String = {
+ val preposition = if (isInclusive) "to" else "until"
+ val stepped = if (step == 1) "" else s" by $step"
+ val prefix = if (isEmpty) "empty " else if (!isExact) "inexact " else ""
+ s"${prefix}Range $start $preposition $end$stepped"
+ }
+
+ override protected[this] def className = "Range"
+
+ override def distinct: Range = this
+
+ override def grouped(size: Int): Iterator[Range] = {
+ require(size >= 1, f"size=$size%d, but size must be positive")
+ if (isEmpty) {
+ Iterator.empty
+ } else {
+ val s = size
+ new AbstractIterator[Range] {
+ private[this] var i = 0
+ override def hasNext = Range.this.length > i
+ override def next() =
+ if (hasNext) {
+ val x = Range.this.slice(i, i + s)
+ i += s
+ x
+ } else {
+ Iterator.empty.next()
+ }
+ }
+ }
+ }
+
+ override def sorted[B >: Int](implicit ord: Ordering[B]): IndexedSeq[Int] =
+ if (ord eq Ordering.Int) {
+ if (step > 0) {
+ this
+ } else {
+ reverse
+ }
+ } else {
+ super.sorted(ord)
+ }
+}
+
+/**
+ * Companion object for ranges.
+ * @define Coll `Range`
+ * @define coll range
+ */
+object Range {
+
+ private def description(start: Int, end: Int, step: Int, isInclusive: Boolean) =
+ start + (if (isInclusive) " to " else " until ") + end + " by " + step
+
+ private def fail(start: Int, end: Int, step: Int, isInclusive: Boolean) =
+ throw new IllegalArgumentException(description(start, end, step, isInclusive) +
+ ": seqs cannot contain more than Int.MaxValue elements.")
+
+ /** Counts the number of range elements.
+ * precondition: step != 0
+ * If the size of the range exceeds Int.MaxValue, the
+ * result will be negative.
+ */
+ def count(start: Int, end: Int, step: Int, isInclusive: Boolean): Int = {
+ if (step == 0)
+ throw new IllegalArgumentException("step cannot be 0.")
+
+ val isEmpty =
+ if (start == end) !isInclusive
+ else if (start < end) step < 0
+ else step > 0
+
+ if (isEmpty) 0
+ else {
+ // Counts with Longs so we can recognize too-large ranges.
+ val gap: Long = end.toLong - start.toLong
+ val jumps: Long = gap / step
+ // Whether the size of this range is one larger than the
+ // number of full-sized jumps.
+ val hasStub = isInclusive || (gap % step != 0)
+ val result: Long = jumps + ( if (hasStub) 1 else 0 )
+
+ if (result > scala.Int.MaxValue) -1
+ else result.toInt
+ }
+ }
+ def count(start: Int, end: Int, step: Int): Int =
+ count(start, end, step, isInclusive = false)
+
+ /** Make a range from `start` until `end` (exclusive) with given step value.
+ * @note step != 0
+ */
+ def apply(start: Int, end: Int, step: Int): Range.Exclusive = new Range.Exclusive(start, end, step)
+
+ /** Make a range from `start` until `end` (exclusive) with step value 1.
+ */
+ def apply(start: Int, end: Int): Range.Exclusive = new Range.Exclusive(start, end, 1)
+
+ /** Make an inclusive range from `start` to `end` with given step value.
+ * @note step != 0
+ */
+ def inclusive(start: Int, end: Int, step: Int): Range.Inclusive = new Range.Inclusive(start, end, step)
+
+ /** Make an inclusive range from `start` to `end` with step value 1.
+ */
+ def inclusive(start: Int, end: Int): Range.Inclusive = new Range.Inclusive(start, end, 1)
+
+ @SerialVersionUID(3L)
+ @inline
+ final class Inclusive(start: Int, end: Int, step: Int) extends Range(start, end, step) {
+ def isInclusive = true
+ }
+
+ @SerialVersionUID(3L)
+ @inline
+ final class Exclusive(start: Int, end: Int, step: Int) extends Range(start, end, step) {
+ def isInclusive = false
+ }
+
+ // BigInt and Long are straightforward generic ranges.
+ object BigInt {
+ def apply(start: BigInt, end: BigInt, step: BigInt) = NumericRange(start, end, step)
+ def inclusive(start: BigInt, end: BigInt, step: BigInt) = NumericRange.inclusive(start, end, step)
+ }
+
+ object Long {
+ def apply(start: Long, end: Long, step: Long) = NumericRange(start, end, step)
+ def inclusive(start: Long, end: Long, step: Long) = NumericRange.inclusive(start, end, step)
+ }
+
+ // BigDecimal uses an alternative implementation of Numeric in which
+ // it pretends to be Integral[T] instead of Fractional[T]. See Numeric for
+ // details. The intention is for it to throw an exception anytime
+ // imprecision or surprises might result from anything, although this may
+ // not yet be fully implemented.
+ object BigDecimal {
+ implicit val bigDecAsIntegral: Numeric.BigDecimalAsIfIntegral = Numeric.BigDecimalAsIfIntegral
+
+ def apply(start: BigDecimal, end: BigDecimal, step: BigDecimal) =
+ NumericRange(start, end, step)
+ def inclusive(start: BigDecimal, end: BigDecimal, step: BigDecimal) =
+ NumericRange.inclusive(start, end, step)
+ }
+
+ // As there is no appealing default step size for not-really-integral ranges,
+ // we offer a partially constructed object.
+ class Partial[T, U](private val f: T => U) extends AnyVal {
+ def by(x: T): U = f(x)
+ override def toString = "Range requires step"
+ }
+
+ // Illustrating genericity with Int Range, which should have the same behavior
+ // as the original Range class. However we leave the original Range
+ // indefinitely, for performance and because the compiler seems to bootstrap
+ // off it and won't do so with our parameterized version without modifications.
+ object Int {
+ def apply(start: Int, end: Int, step: Int) = NumericRange(start, end, step)
+ def inclusive(start: Int, end: Int, step: Int) = NumericRange.inclusive(start, end, step)
+ }
+
+ private def emptyRangeError(what: String): Throwable =
+ new NoSuchElementException(what + " on empty Range")
+}
+
+/**
+ * @param lastElement The last element included in the Range
+ * @param initiallyEmpty Whether the Range was initially empty or not
+ */
+@SerialVersionUID(3L)
+private class RangeIterator(
+ start: Int,
+ step: Int,
+ lastElement: Int,
+ initiallyEmpty: Boolean
+) extends AbstractIterator[Int] with Serializable {
+ private[this] var _hasNext: Boolean = !initiallyEmpty
+ private[this] var _next: Int = start
+ override def knownSize: Int = if (_hasNext) (lastElement - _next) / step + 1 else 0
+ def hasNext: Boolean = _hasNext
+ @throws[NoSuchElementException]
+ def next(): Int = {
+ if (!_hasNext) Iterator.empty.next()
+ val value = _next
+ _hasNext = value != lastElement
+ _next = value + step
+ value
+ }
+
+ override def drop(n: Int): Iterator[Int] = {
+ if (n > 0) {
+ val longPos = _next.toLong + step * n
+ if (step > 0) {
+ _next = Math.min(lastElement, longPos).toInt
+ _hasNext = longPos <= lastElement
+ }
+ else if (step < 0) {
+ _next = Math.max(lastElement, longPos).toInt
+ _hasNext = longPos >= lastElement
+ }
+ }
+ this
+ }
+}
diff --git a/library-js/src/scala/collection/mutable/ArrayBuilder.scala b/library-js/src/scala/collection/mutable/ArrayBuilder.scala
new file mode 100644
index 000000000000..531a6438a2f1
--- /dev/null
+++ b/library-js/src/scala/collection/mutable/ArrayBuilder.scala
@@ -0,0 +1,646 @@
+/*
+ * Scala (https://www.scala-lang.org)
+ *
+ * Copyright EPFL and Lightbend, Inc.
+ *
+ * Licensed under Apache License 2.0
+ * (http://www.apache.org/licenses/LICENSE-2.0).
+ *
+ * See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ */
+
+package scala.collection
+package mutable
+
+import scala.reflect.ClassTag
+import scala.runtime.BoxedUnit
+
+import scala.scalajs.js
+import scala.scalajs.LinkingInfo
+
+/** A builder class for arrays.
+ *
+ * @since 2.8
+ *
+ * @tparam T the type of the elements for the builder.
+ */
+@SerialVersionUID(3L)
+sealed abstract class ArrayBuilder[T]
+ extends ReusableBuilder[T, Array[T]]
+ with Serializable {
+ protected[this] var capacity: Int = 0
+ protected[this] def elems: Array[T]
+ protected var size: Int = 0
+
+ def length: Int = size
+
+ override def knownSize: Int = size
+
+ protected[this] final def ensureSize(size: Int): Unit = {
+ if (capacity < size || capacity == 0) {
+ var newsize = if (capacity == 0) 16 else capacity * 2
+ while (newsize < size) newsize *= 2
+ resize(newsize)
+ }
+ }
+
+ override final def sizeHint(size: Int): Unit =
+ if (capacity < size) resize(size)
+
+ def clear(): Unit = size = 0
+
+ protected[this] def resize(size: Int): Unit
+
+ /** Add all elements of an array */
+ def addAll(xs: Array[_ <: T]): this.type = addAll(xs, 0, xs.length)
+
+ /** Add a slice of an array */
+ def addAll(xs: Array[_ <: T], offset: Int, length: Int): this.type = {
+ ensureSize(this.size + length)
+ Array.copy(xs, offset, elems, this.size, length)
+ size += length
+ this
+ }
+
+ override def addAll(xs: IterableOnce[T]): this.type = {
+ val k = xs.knownSize
+ if(k > 0) {
+ ensureSize(this.size + k)
+ xs match {
+ case xs: Iterable[T] => xs.copyToArray(elems, this.size)
+ case _ => xs.iterator.copyToArray(elems, this.size)
+ }
+ size += k
+ } else if(k < 0) super.addAll(xs)
+ this
+ }
+}
+
+/** A companion object for array builders.
+ *
+ * @since 2.8
+ */
+object ArrayBuilder {
+
+ /** Creates a new arraybuilder of type `T`.
+ *
+ * @tparam T type of the elements for the array builder, with a `ClassTag` context bound.
+ * @return a new empty array builder.
+ */
+ @inline
+ def make[T: ClassTag]: ArrayBuilder[T] =
+ if (LinkingInfo.isWebAssembly) makeForWasm
+ else makeForJS
+
+ /** Implementation of `make` for JS. */
+ @inline
+ private def makeForJS[T: ClassTag]: ArrayBuilder[T] =
+ new ArrayBuilder.generic[T](implicitly[ClassTag[T]].runtimeClass)
+
+ /** Implementation of `make` for Wasm.
+ *
+ * This is the original upstream implementation.
+ */
+ @inline
+ private def makeForWasm[T: ClassTag]: ArrayBuilder[T] = {
+ val tag = implicitly[ClassTag[T]]
+ tag.runtimeClass match {
+ case java.lang.Byte.TYPE => new ArrayBuilder.ofByte().asInstanceOf[ArrayBuilder[T]]
+ case java.lang.Short.TYPE => new ArrayBuilder.ofShort().asInstanceOf[ArrayBuilder[T]]
+ case java.lang.Character.TYPE => new ArrayBuilder.ofChar().asInstanceOf[ArrayBuilder[T]]
+ case java.lang.Integer.TYPE => new ArrayBuilder.ofInt().asInstanceOf[ArrayBuilder[T]]
+ case java.lang.Long.TYPE => new ArrayBuilder.ofLong().asInstanceOf[ArrayBuilder[T]]
+ case java.lang.Float.TYPE => new ArrayBuilder.ofFloat().asInstanceOf[ArrayBuilder[T]]
+ case java.lang.Double.TYPE => new ArrayBuilder.ofDouble().asInstanceOf[ArrayBuilder[T]]
+ case java.lang.Boolean.TYPE => new ArrayBuilder.ofBoolean().asInstanceOf[ArrayBuilder[T]]
+ case java.lang.Void.TYPE => new ArrayBuilder.ofUnit().asInstanceOf[ArrayBuilder[T]]
+ case _ => new ArrayBuilder.ofRef[T with AnyRef]()(tag.asInstanceOf[ClassTag[T with AnyRef]]).asInstanceOf[ArrayBuilder[T]]
+ }
+ }
+
+ /** A generic ArrayBuilder optimized for Scala.js.
+ *
+ * @tparam T type of elements for the array builder.
+ * @param elementClass runtime class of the elements in the array.
+ */
+ @inline
+ private final class generic[T](elementClass: Class[_]) extends ArrayBuilder[T] {
+
+ private val isCharArrayBuilder = classOf[Char] == elementClass
+ protected[this] def elems: Array[T] = throw new Error("unreachable")
+ private var jsElems: js.Array[Any] = js.Array()
+
+ override def length: Int = jsElems.length
+
+ override def knownSize: Int = jsElems.length
+
+ def addOne(elem: T): this.type = {
+ val unboxedElem =
+ if (isCharArrayBuilder) elem.asInstanceOf[Char].toInt
+ else if (elem == null) zeroOf(elementClass)
+ else elem
+ jsElems.push(unboxedElem)
+ this
+ }
+
+ /** Add a slice of an array */
+ override def addAll(xs: Array[_ <: T], offset: Int, length: Int): this.type = {
+ val end = offset + length
+ var i = offset
+ while (i < end) {
+ this += xs(i)
+ i += 1
+ }
+ this
+ }
+
+ override def addAll(xs: IterableOnce[T]): this.type = {
+ val it = xs.iterator
+ while (it.hasNext) {
+ this += it.next()
+ }
+ this
+ }
+
+ override def clear(): Unit =
+ jsElems = js.Array()
+
+ protected[this] def resize(size: Int): Unit = ()
+
+ def result(): Array[T] = {
+ val elemRuntimeClass =
+ if (classOf[Unit] == elementClass) classOf[BoxedUnit]
+ else if (classOf[Null] == elementClass || classOf[Nothing] == elementClass) classOf[Object]
+ else elementClass
+ genericArrayBuilderResult(elemRuntimeClass, jsElems)
+ }
+
+ override def toString(): String = "ArrayBuilder.generic"
+ }
+
+ // Intrinsic
+ private def zeroOf(runtimeClass: Class[_]): Any = runtimeClass match {
+ case java.lang.Byte.TYPE => 0.toByte
+ case java.lang.Short.TYPE => 0.toShort
+ case java.lang.Character.TYPE => 0 // yes, as an Int
+ case java.lang.Integer.TYPE => 0
+ case java.lang.Long.TYPE => 0L
+ case java.lang.Float.TYPE => 0.0f
+ case java.lang.Double.TYPE => 0.0
+ case java.lang.Boolean.TYPE => false
+ case java.lang.Void.TYPE => ()
+ case _ => null
+ }
+
+ // Intrinsic
+ private def genericArrayBuilderResult[T](runtimeClass: Class[_],
+ a: js.Array[Any]): Array[T] = {
+ val len = a.length
+
+ if (classOf[Char] == runtimeClass) {
+ val result = new Array[Char](len)
+ var i = 0
+ while (i != len) {
+ result(i) = a(i).asInstanceOf[Int].toChar
+ i += 1
+ }
+ result.asInstanceOf[Array[T]]
+ } else {
+ val result: Array[T] = java.lang.reflect.Array.newInstance(
+ runtimeClass, len).asInstanceOf[Array[T]]
+ var i = 0
+ while (i != len) {
+ result(i) = a(i).asInstanceOf[T]
+ i += 1
+ }
+ result
+ }
+ }
+
+ /** A class for array builders for arrays of reference types.
+ *
+ * This builder can be reused.
+ *
+ * @tparam T type of elements for the array builder, subtype of `AnyRef` with a `ClassTag` context bound.
+ */
+ @SerialVersionUID(3L)
+ final class ofRef[T <: AnyRef](implicit ct: ClassTag[T]) extends ArrayBuilder[T] {
+
+ protected var elems: Array[T] = _
+
+ private def mkArray(size: Int): Array[T] = {
+ if (capacity == size && capacity > 0) elems
+ else if (elems eq null) new Array[T](size)
+ else java.util.Arrays.copyOf[T](elems, size)
+ }
+
+ protected[this] def resize(size: Int): Unit = {
+ elems = mkArray(size)
+ capacity = size
+ }
+
+ def addOne(elem: T): this.type = {
+ ensureSize(size + 1)
+ elems(size) = elem
+ size += 1
+ this
+ }
+
+ def result() = {
+ if (capacity != 0 && capacity == size) {
+ capacity = 0
+ val res = elems
+ elems = null
+ res
+ }
+ else mkArray(size)
+ }
+
+ override def clear(): Unit = {
+ super.clear()
+ if(elems ne null) java.util.Arrays.fill(elems.asInstanceOf[Array[AnyRef]], null)
+ }
+
+ override def equals(other: Any): Boolean = other match {
+ case x: ofRef[_] => (size == x.size) && (elems == x.elems)
+ case _ => false
+ }
+
+ override def toString = "ArrayBuilder.ofRef"
+ }
+
+ /** A class for array builders for arrays of `byte`s. It can be reused. */
+ @SerialVersionUID(3L)
+ final class ofByte extends ArrayBuilder[Byte] {
+
+ protected var elems: Array[Byte] = _
+
+ private def mkArray(size: Int): Array[Byte] = {
+ val newelems = new Array[Byte](size)
+ if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size)
+ newelems
+ }
+
+ protected[this] def resize(size: Int): Unit = {
+ elems = mkArray(size)
+ capacity = size
+ }
+
+ def addOne(elem: Byte): this.type = {
+ ensureSize(size + 1)
+ elems(size) = elem
+ size += 1
+ this
+ }
+
+ def result() = {
+ if (capacity != 0 && capacity == size) {
+ capacity = 0
+ val res = elems
+ elems = null
+ res
+ }
+ else mkArray(size)
+ }
+
+ override def equals(other: Any): Boolean = other match {
+ case x: ofByte => (size == x.size) && (elems == x.elems)
+ case _ => false
+ }
+
+ override def toString = "ArrayBuilder.ofByte"
+ }
+
+ /** A class for array builders for arrays of `short`s. It can be reused. */
+ @SerialVersionUID(3L)
+ final class ofShort extends ArrayBuilder[Short] {
+
+ protected var elems: Array[Short] = _
+
+ private def mkArray(size: Int): Array[Short] = {
+ val newelems = new Array[Short](size)
+ if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size)
+ newelems
+ }
+
+ protected[this] def resize(size: Int): Unit = {
+ elems = mkArray(size)
+ capacity = size
+ }
+
+ def addOne(elem: Short): this.type = {
+ ensureSize(size + 1)
+ elems(size) = elem
+ size += 1
+ this
+ }
+
+ def result() = {
+ if (capacity != 0 && capacity == size) {
+ capacity = 0
+ val res = elems
+ elems = null
+ res
+ }
+ else mkArray(size)
+ }
+
+ override def equals(other: Any): Boolean = other match {
+ case x: ofShort => (size == x.size) && (elems == x.elems)
+ case _ => false
+ }
+
+ override def toString = "ArrayBuilder.ofShort"
+ }
+
+ /** A class for array builders for arrays of `char`s. It can be reused. */
+ @SerialVersionUID(3L)
+ final class ofChar extends ArrayBuilder[Char] {
+
+ protected var elems: Array[Char] = _
+
+ private def mkArray(size: Int): Array[Char] = {
+ val newelems = new Array[Char](size)
+ if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size)
+ newelems
+ }
+
+ protected[this] def resize(size: Int): Unit = {
+ elems = mkArray(size)
+ capacity = size
+ }
+
+ def addOne(elem: Char): this.type = {
+ ensureSize(size + 1)
+ elems(size) = elem
+ size += 1
+ this
+ }
+
+ def result() = {
+ if (capacity != 0 && capacity == size) {
+ capacity = 0
+ val res = elems
+ elems = null
+ res
+ }
+ else mkArray(size)
+ }
+
+ override def equals(other: Any): Boolean = other match {
+ case x: ofChar => (size == x.size) && (elems == x.elems)
+ case _ => false
+ }
+
+ override def toString = "ArrayBuilder.ofChar"
+ }
+
+ /** A class for array builders for arrays of `int`s. It can be reused. */
+ @SerialVersionUID(3L)
+ final class ofInt extends ArrayBuilder[Int] {
+
+ protected var elems: Array[Int] = _
+
+ private def mkArray(size: Int): Array[Int] = {
+ val newelems = new Array[Int](size)
+ if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size)
+ newelems
+ }
+
+ protected[this] def resize(size: Int): Unit = {
+ elems = mkArray(size)
+ capacity = size
+ }
+
+ def addOne(elem: Int): this.type = {
+ ensureSize(size + 1)
+ elems(size) = elem
+ size += 1
+ this
+ }
+
+ def result() = {
+ if (capacity != 0 && capacity == size) {
+ capacity = 0
+ val res = elems
+ elems = null
+ res
+ }
+ else mkArray(size)
+ }
+
+ override def equals(other: Any): Boolean = other match {
+ case x: ofInt => (size == x.size) && (elems == x.elems)
+ case _ => false
+ }
+
+ override def toString = "ArrayBuilder.ofInt"
+ }
+
+ /** A class for array builders for arrays of `long`s. It can be reused. */
+ @SerialVersionUID(3L)
+ final class ofLong extends ArrayBuilder[Long] {
+
+ protected var elems: Array[Long] = _
+
+ private def mkArray(size: Int): Array[Long] = {
+ val newelems = new Array[Long](size)
+ if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size)
+ newelems
+ }
+
+ protected[this] def resize(size: Int): Unit = {
+ elems = mkArray(size)
+ capacity = size
+ }
+
+ def addOne(elem: Long): this.type = {
+ ensureSize(size + 1)
+ elems(size) = elem
+ size += 1
+ this
+ }
+
+ def result() = {
+ if (capacity != 0 && capacity == size) {
+ capacity = 0
+ val res = elems
+ elems = null
+ res
+ }
+ else mkArray(size)
+ }
+
+ override def equals(other: Any): Boolean = other match {
+ case x: ofLong => (size == x.size) && (elems == x.elems)
+ case _ => false
+ }
+
+ override def toString = "ArrayBuilder.ofLong"
+ }
+
+ /** A class for array builders for arrays of `float`s. It can be reused. */
+ @SerialVersionUID(3L)
+ final class ofFloat extends ArrayBuilder[Float] {
+
+ protected var elems: Array[Float] = _
+
+ private def mkArray(size: Int): Array[Float] = {
+ val newelems = new Array[Float](size)
+ if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size)
+ newelems
+ }
+
+ protected[this] def resize(size: Int): Unit = {
+ elems = mkArray(size)
+ capacity = size
+ }
+
+ def addOne(elem: Float): this.type = {
+ ensureSize(size + 1)
+ elems(size) = elem
+ size += 1
+ this
+ }
+
+ def result() = {
+ if (capacity != 0 && capacity == size) {
+ capacity = 0
+ val res = elems
+ elems = null
+ res
+ }
+ else mkArray(size)
+ }
+
+ override def equals(other: Any): Boolean = other match {
+ case x: ofFloat => (size == x.size) && (elems == x.elems)
+ case _ => false
+ }
+
+ override def toString = "ArrayBuilder.ofFloat"
+ }
+
+ /** A class for array builders for arrays of `double`s. It can be reused. */
+ @SerialVersionUID(3L)
+ final class ofDouble extends ArrayBuilder[Double] {
+
+ protected var elems: Array[Double] = _
+
+ private def mkArray(size: Int): Array[Double] = {
+ val newelems = new Array[Double](size)
+ if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size)
+ newelems
+ }
+
+ protected[this] def resize(size: Int): Unit = {
+ elems = mkArray(size)
+ capacity = size
+ }
+
+ def addOne(elem: Double): this.type = {
+ ensureSize(size + 1)
+ elems(size) = elem
+ size += 1
+ this
+ }
+
+ def result() = {
+ if (capacity != 0 && capacity == size) {
+ capacity = 0
+ val res = elems
+ elems = null
+ res
+ }
+ else mkArray(size)
+ }
+
+ override def equals(other: Any): Boolean = other match {
+ case x: ofDouble => (size == x.size) && (elems == x.elems)
+ case _ => false
+ }
+
+ override def toString = "ArrayBuilder.ofDouble"
+ }
+
+ /** A class for array builders for arrays of `boolean`s. It can be reused. */
+ @SerialVersionUID(3L)
+ class ofBoolean extends ArrayBuilder[Boolean] {
+
+ protected var elems: Array[Boolean] = _
+
+ private def mkArray(size: Int): Array[Boolean] = {
+ val newelems = new Array[Boolean](size)
+ if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size)
+ newelems
+ }
+
+ protected[this] def resize(size: Int): Unit = {
+ elems = mkArray(size)
+ capacity = size
+ }
+
+ def addOne(elem: Boolean): this.type = {
+ ensureSize(size + 1)
+ elems(size) = elem
+ size += 1
+ this
+ }
+
+ def result() = {
+ if (capacity != 0 && capacity == size) {
+ capacity = 0
+ val res = elems
+ elems = null
+ res
+ }
+ else mkArray(size)
+ }
+
+ override def equals(other: Any): Boolean = other match {
+ case x: ofBoolean => (size == x.size) && (elems == x.elems)
+ case _ => false
+ }
+
+ override def toString = "ArrayBuilder.ofBoolean"
+ }
+
+ /** A class for array builders for arrays of `Unit` type. It can be reused. */
+ @SerialVersionUID(3L)
+ final class ofUnit extends ArrayBuilder[Unit] {
+
+ protected def elems: Array[Unit] = throw new UnsupportedOperationException()
+
+ def addOne(elem: Unit): this.type = {
+ size += 1
+ this
+ }
+
+ override def addAll(xs: IterableOnce[Unit]): this.type = {
+ size += xs.iterator.size
+ this
+ }
+
+ override def addAll(xs: Array[_ <: Unit], offset: Int, length: Int): this.type = {
+ size += length
+ this
+ }
+
+ def result() = {
+ val ans = new Array[Unit](size)
+ var i = 0
+ while (i < size) { ans(i) = (); i += 1 }
+ ans
+ }
+
+ override def equals(other: Any): Boolean = other match {
+ case x: ofUnit => (size == x.size)
+ case _ => false
+ }
+
+ protected[this] def resize(size: Int): Unit = ()
+
+ override def toString = "ArrayBuilder.ofUnit"
+ }
+}
diff --git a/library-js/src/scala/collection/mutable/Buffer.scala b/library-js/src/scala/collection/mutable/Buffer.scala
new file mode 100644
index 000000000000..b08e6d6506a6
--- /dev/null
+++ b/library-js/src/scala/collection/mutable/Buffer.scala
@@ -0,0 +1,233 @@
+/*
+ * Scala (https://www.scala-lang.org)
+ *
+ * Copyright EPFL and Lightbend, Inc.
+ *
+ * Licensed under Apache License 2.0
+ * (http://www.apache.org/licenses/LICENSE-2.0).
+ *
+ * See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ */
+
+package scala.collection
+package mutable
+
+import scala.scalajs.js
+
+/** A `Buffer` is a growable and shrinkable `Seq`. */
+trait Buffer[A]
+ extends Seq[A]
+ with SeqOps[A, Buffer, Buffer[A]]
+ with Growable[A]
+ with Shrinkable[A]
+ with IterableFactoryDefaults[A, Buffer] {
+
+ override def iterableFactory: SeqFactory[Buffer] = Buffer
+
+ override def knownSize: Int = super[Seq].knownSize
+
+ //TODO Prepend is a logical choice for a readable name of `+=:` but it conflicts with the renaming of `append` to `add`
+ /** Prepends a single element at the front of this $coll.
+ *
+ * @param elem the element to $add.
+ * @return the $coll itself
+ */
+ def prepend(elem: A): this.type
+
+ /** Appends the given elements to this buffer.
+ *
+ * @param elem the element to append.
+ */
+ @`inline` final def append(elem: A): this.type = addOne(elem)
+
+ @deprecated("Use appendAll instead", "2.13.0")
+ @`inline` final def append(elems: A*): this.type = addAll(elems)
+
+ /** Appends the elements contained in a iterable object to this buffer.
+ * @param xs the iterable object containing the elements to append.
+ */
+ @`inline` final def appendAll(xs: IterableOnce[A]): this.type = addAll(xs)
+
+
+ /** Alias for `prepend` */
+ @`inline` final def +=: (elem: A): this.type = prepend(elem)
+
+ def prependAll(elems: IterableOnce[A]): this.type = { insertAll(0, elems); this }
+
+ @deprecated("Use prependAll instead", "2.13.0")
+ @`inline` final def prepend(elems: A*): this.type = prependAll(elems)
+
+ /** Alias for `prependAll` */
+ @inline final def ++=:(elems: IterableOnce[A]): this.type = prependAll(elems)
+
+ /** Inserts a new element at a given index into this buffer.
+ *
+ * @param idx the index where the new elements is inserted.
+ * @param elem the element to insert.
+ * @throws IndexOutOfBoundsException if the index `idx` is not in the valid range
+ * `0 <= idx <= length`.
+ */
+ @throws[IndexOutOfBoundsException]
+ def insert(idx: Int, elem: A): Unit
+
+ /** Inserts new elements at the index `idx`. Opposed to method
+ * `update`, this method will not replace an element with a new
+ * one. Instead, it will insert a new element at index `idx`.
+ *
+ * @param idx the index where a new element will be inserted.
+ * @param elems the iterable object providing all elements to insert.
+ * @throws IndexOutOfBoundsException if `idx` is out of bounds.
+ */
+ @throws[IndexOutOfBoundsException]
+ def insertAll(idx: Int, elems: IterableOnce[A]): Unit
+
+ /** Removes the element at a given index position.
+ *
+ * @param idx the index which refers to the element to delete.
+ * @return the element that was formerly at index `idx`.
+ */
+ @throws[IndexOutOfBoundsException]
+ def remove(idx: Int): A
+
+ /** Removes the element on a given index position. It takes time linear in
+ * the buffer size.
+ *
+ * @param idx the index which refers to the first element to remove.
+ * @param count the number of elements to remove.
+ * @throws IndexOutOfBoundsException if the index `idx` is not in the valid range
+ * `0 <= idx <= length - count` (with `count > 0`).
+ * @throws IllegalArgumentException if `count < 0`.
+ */
+ @throws[IndexOutOfBoundsException]
+ @throws[IllegalArgumentException]
+ def remove(idx: Int, count: Int): Unit
+
+ /** Removes a single element from this buffer, at its first occurrence.
+ * If the buffer does not contain that element, it is unchanged.
+ *
+ * @param x the element to remove.
+ * @return the buffer itself
+ */
+ def subtractOne (x: A): this.type = {
+ val i = indexOf(x)
+ if (i != -1) remove(i)
+ this
+ }
+
+ /** Removes the first ''n'' elements of this buffer.
+ *
+ * @param n the number of elements to remove from the beginning
+ * of this buffer.
+ */
+ def trimStart(n: Int): Unit = remove(0, normalized(n))
+
+ /** Removes the last ''n'' elements of this buffer.
+ *
+ * @param n the number of elements to remove from the end
+ * of this buffer.
+ */
+ def trimEnd(n: Int): Unit = {
+ val norm = normalized(n)
+ remove(length - norm, norm)
+ }
+
+ def patchInPlace(from: Int, patch: scala.collection.IterableOnce[A], replaced: Int): this.type
+
+ // +=, ++=, clear inherited from Growable
+ // Per remark of @ichoran, we should preferably not have these:
+ //
+ // def +=:(elem: A): this.type = { insert(0, elem); this }
+ // def +=:(elem1: A, elem2: A, elems: A*): this.type = elem1 +=: elem2 +=: elems ++=: this
+ // def ++=:(elems: IterableOnce[A]): this.type = { insertAll(0, elems); this }
+
+ def dropInPlace(n: Int): this.type = { remove(0, normalized(n)); this }
+ def dropRightInPlace(n: Int): this.type = {
+ val norm = normalized(n)
+ remove(length - norm, norm)
+ this
+ }
+ def takeInPlace(n: Int): this.type = {
+ val norm = normalized(n)
+ remove(norm, length - norm)
+ this
+ }
+ def takeRightInPlace(n: Int): this.type = { remove(0, length - normalized(n)); this }
+ def sliceInPlace(start: Int, end: Int): this.type = takeInPlace(end).dropInPlace(start)
+ private def normalized(n: Int): Int = math.min(math.max(n, 0), length)
+
+ def dropWhileInPlace(p: A => Boolean): this.type = {
+ val idx = indexWhere(!p(_))
+ if (idx < 0) { clear(); this } else dropInPlace(idx)
+ }
+ def takeWhileInPlace(p: A => Boolean): this.type = {
+ val idx = indexWhere(!p(_))
+ if (idx < 0) this else takeInPlace(idx)
+ }
+ def padToInPlace(len: Int, elem: A): this.type = {
+ while (length < len) +=(elem)
+ this
+ }
+
+ @deprecatedOverriding("Compatibility override", since="2.13.0")
+ override protected[this] def stringPrefix = "Buffer"
+}
+
+trait IndexedBuffer[A] extends IndexedSeq[A]
+ with IndexedSeqOps[A, IndexedBuffer, IndexedBuffer[A]]
+ with Buffer[A]
+ with IterableFactoryDefaults[A, IndexedBuffer] {
+
+ override def iterableFactory: SeqFactory[IndexedBuffer] = IndexedBuffer
+
+ def flatMapInPlace(f: A => IterableOnce[A]): this.type = {
+ // There's scope for a better implementation which copies elements in place.
+ var i = 0
+ val s = size
+ val newElems = new Array[IterableOnce[A]](s)
+ while (i < s) { newElems(i) = f(this(i)); i += 1 }
+ clear()
+ i = 0
+ while (i < s) { ++=(newElems(i)); i += 1 }
+ this
+ }
+
+ def filterInPlace(p: A => Boolean): this.type = {
+ var i, j = 0
+ while (i < size) {
+ if (p(apply(i))) {
+ if (i != j) {
+ this(j) = this(i)
+ }
+ j += 1
+ }
+ i += 1
+ }
+
+ if (i == j) this else takeInPlace(j)
+ }
+
+ def patchInPlace(from: Int, patch: scala.collection.IterableOnce[A], replaced: Int): this.type = {
+ val replaced0 = math.min(math.max(replaced, 0), length)
+ val i = math.min(math.max(from, 0), length)
+ var j = 0
+ val iter = patch.iterator
+ while (iter.hasNext && j < replaced0 && i + j < length) {
+ update(i + j, iter.next())
+ j += 1
+ }
+ if (iter.hasNext) insertAll(i + j, iter)
+ else if (j < replaced0) remove(i + j, math.min(replaced0 - j, length - i - j))
+ this
+ }
+}
+
+@SerialVersionUID(3L)
+object Buffer extends SeqFactory.Delegate[Buffer](js.WrappedArray)
+
+@SerialVersionUID(3L)
+object IndexedBuffer extends SeqFactory.Delegate[IndexedBuffer](js.WrappedArray)
+
+/** Explicit instantiation of the `Buffer` trait to reduce class file size in subclasses. */
+@SerialVersionUID(3L)
+abstract class AbstractBuffer[A] extends AbstractSeq[A] with Buffer[A]
diff --git a/library-js/src/scala/concurrent/ExecutionContext.scala b/library-js/src/scala/concurrent/ExecutionContext.scala
new file mode 100644
index 000000000000..38582321cccd
--- /dev/null
+++ b/library-js/src/scala/concurrent/ExecutionContext.scala
@@ -0,0 +1,227 @@
+/*
+ * Scala (https://www.scala-lang.org)
+ *
+ * Copyright EPFL and Lightbend, Inc.
+ *
+ * Licensed under Apache License 2.0
+ * (http://www.apache.org/licenses/LICENSE-2.0).
+ *
+ * See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ */
+
+package scala.concurrent
+
+
+import java.util.concurrent.{ ExecutorService, Executor }
+import scala.annotation.implicitNotFound
+
+/**
+ * An `ExecutionContext` can execute program logic asynchronously,
+ * typically but not necessarily on a thread pool.
+ *
+ * A general purpose `ExecutionContext` must be asynchronous in executing
+ * any `Runnable` that is passed into its `execute`-method. A special purpose
+ * `ExecutionContext` may be synchronous but must only be passed to code that
+ * is explicitly safe to be run using a synchronously executing `ExecutionContext`.
+ *
+ * APIs such as `Future.onComplete` require you to provide a callback
+ * and an implicit `ExecutionContext`. The implicit `ExecutionContext`
+ * will be used to execute the callback.
+ *
+ * While it is possible to simply import
+ * `scala.concurrent.ExecutionContext.Implicits.global` to obtain an
+ * implicit `ExecutionContext`, application developers should carefully
+ * consider where they want to set execution policy;
+ * ideally, one place per application—or per logically related section of code—
+ * will make a decision about which `ExecutionContext` to use.
+ * That is, you will mostly want to avoid hardcoding, especially via an import,
+ * `scala.concurrent.ExecutionContext.Implicits.global`.
+ * The recommended approach is to add `(implicit ec: ExecutionContext)` to methods,
+ * or class constructor parameters, which need an `ExecutionContext`.
+ *
+ * Then locally import a specific `ExecutionContext` in one place for the entire
+ * application or module, passing it implicitly to individual methods.
+ * Alternatively define a local implicit val with the required `ExecutionContext`.
+ *
+ * A custom `ExecutionContext` may be appropriate to execute code
+ * which blocks on IO or performs long-running computations.
+ * `ExecutionContext.fromExecutorService` and `ExecutionContext.fromExecutor`
+ * are good ways to create a custom `ExecutionContext`.
+ *
+ * The intent of `ExecutionContext` is to lexically scope code execution.
+ * That is, each method, class, file, package, or application determines
+ * how to run its own code. This avoids issues such as running
+ * application callbacks on a thread pool belonging to a networking library.
+ * The size of a networking library's thread pool can be safely configured,
+ * knowing that only that library's network operations will be affected.
+ * Application callback execution can be configured separately.
+ */
+@implicitNotFound("""Cannot find an implicit ExecutionContext. You might pass
+an (implicit ec: ExecutionContext) parameter to your method.
+
+The ExecutionContext is used to configure how and on which
+thread pools Futures will run, so the specific ExecutionContext
+that is selected is important.
+
+If your application does not define an ExecutionContext elsewhere,
+consider using Scala's global ExecutionContext by defining
+the following:
+
+implicit val ec: scala.concurrent.ExecutionContext = scala.concurrent.ExecutionContext.global""")
+trait ExecutionContext {
+
+ /** Runs a block of code on this execution context.
+ *
+ * @param runnable the task to execute
+ */
+ def execute(runnable: Runnable): Unit
+
+ /** Reports that an asynchronous computation failed.
+ *
+ * @param cause the cause of the failure
+ */
+ def reportFailure(@deprecatedName("t") cause: Throwable): Unit
+
+ /** Prepares for the execution of a task. Returns the prepared
+ * execution context. The recommended implementation of
+ * `prepare` is to return `this`.
+ *
+ * This method should no longer be overridden or called. It was
+ * originally expected that `prepare` would be called by
+ * all libraries that consume ExecutionContexts, in order to
+ * capture thread local context. However, this usage has proven
+ * difficult to implement in practice and instead it is
+ * now better to avoid using `prepare` entirely.
+ *
+ * Instead, if an `ExecutionContext` needs to capture thread
+ * local context, it should capture that context when it is
+ * constructed, so that it doesn't need any additional
+ * preparation later.
+ */
+ @deprecated("preparation of ExecutionContexts will be removed", "2.12.0")
+ // This cannot be removed until there is a suitable replacement
+ def prepare(): ExecutionContext = this
+}
+
+/**
+ * An [[ExecutionContext]] that is also a
+ * Java [[http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executor.html Executor]].
+ */
+trait ExecutionContextExecutor extends ExecutionContext with Executor
+
+/**
+ * An [[ExecutionContext]] that is also a
+ * Java [[http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html ExecutorService]].
+ */
+trait ExecutionContextExecutorService extends ExecutionContextExecutor with ExecutorService
+
+
+/** Contains factory methods for creating execution contexts.
+ */
+object ExecutionContext {
+ /**
+ * The explicit global `ExecutionContext`. Invoke `global` when you want to provide the global
+ * `ExecutionContext` explicitly.
+ *
+ * The default `ExecutionContext` implementation is backed by a work-stealing thread pool.
+ * It can be configured via the following [[scala.sys.SystemProperties]]:
+ *
+ * `scala.concurrent.context.minThreads` = defaults to "1"
+ * `scala.concurrent.context.numThreads` = defaults to "x1" (i.e. the current number of available processors * 1)
+ * `scala.concurrent.context.maxThreads` = defaults to "x1" (i.e. the current number of available processors * 1)
+ * `scala.concurrent.context.maxExtraThreads` = defaults to "256"
+ *
+ * The pool size of threads is then `numThreads` bounded by `minThreads` on the lower end and `maxThreads` on the high end.
+ *
+ * The `maxExtraThreads` is the maximum number of extra threads to have at any given time to evade deadlock,
+ * see [[scala.concurrent.BlockContext]].
+ *
+ * @return the global `ExecutionContext`
+ */
+ final lazy val global: ExecutionContextExecutor =
+ scala.scalajs.concurrent.JSExecutionContext.queue
+
+ /**
+ * WARNING: Only ever execute logic which will quickly return control to the caller.
+ *
+ * This `ExecutionContext` steals execution time from other threads by having its
+ * `Runnable`s run on the `Thread` which calls `execute` and then yielding back control
+ * to the caller after *all* its `Runnable`s have been executed.
+ * Nested invocations of `execute` will be trampolined to prevent uncontrolled stack space growth.
+ *
+ * When using `parasitic` with abstractions such as `Future` it will in many cases be non-deterministic
+ * as to which `Thread` will be executing the logic, as it depends on when/if that `Future` is completed.
+ *
+ * Do *not* call any blocking code in the `Runnable`s submitted to this `ExecutionContext`
+ * as it will prevent progress by other enqueued `Runnable`s and the calling `Thread`.
+ *
+ * Symptoms of misuse of this `ExecutionContext` include, but are not limited to, deadlocks
+ * and severe performance problems.
+ *
+ * Any `NonFatal` or `InterruptedException`s will be reported to the `defaultReporter`.
+ */
+ object parasitic extends ExecutionContextExecutor with BatchingExecutor {
+ override final def submitForExecution(runnable: Runnable): Unit = runnable.run()
+ override final def execute(runnable: Runnable): Unit = submitSyncBatched(runnable)
+ override final def reportFailure(t: Throwable): Unit = defaultReporter(t)
+ }
+
+ object Implicits {
+ /**
+ * The implicit global `ExecutionContext`. Import `global` when you want to provide the global
+ * `ExecutionContext` implicitly.
+ *
+ * The default `ExecutionContext` implementation is backed by a work-stealing thread pool. By default,
+ * the thread pool uses a target number of worker threads equal to the number of
+ * [[https://docs.oracle.com/javase/8/docs/api/java/lang/Runtime.html#availableProcessors-- available processors]].
+ */
+ implicit final def global: ExecutionContext = ExecutionContext.global
+ }
+
+ /** Creates an `ExecutionContext` from the given `ExecutorService`.
+ *
+ * @param e the `ExecutorService` to use. If `null`, a new `ExecutorService` is created with [[scala.concurrent.ExecutionContext$.global default configuration]].
+ * @param reporter a function for error reporting
+ * @return the `ExecutionContext` using the given `ExecutorService`
+ */
+ def fromExecutorService(e: ExecutorService, reporter: Throwable => Unit): ExecutionContextExecutorService =
+ impl.ExecutionContextImpl.fromExecutorService(e, reporter)
+
+ /** Creates an `ExecutionContext` from the given `ExecutorService` with the [[scala.concurrent.ExecutionContext$.defaultReporter default reporter]].
+ *
+ * If it is guaranteed that none of the executed tasks are blocking, a single-threaded `ExecutorService`
+ * can be used to create an `ExecutionContext` as follows:
+ *
+ * {{{
+ * import java.util.concurrent.Executors
+ * val ec = ExecutionContext.fromExecutorService(Executors.newSingleThreadExecutor())
+ * }}}
+ *
+ * @param e the `ExecutorService` to use. If `null`, a new `ExecutorService` is created with [[scala.concurrent.ExecutionContext$.global default configuration]].
+ * @return the `ExecutionContext` using the given `ExecutorService`
+ */
+ def fromExecutorService(e: ExecutorService): ExecutionContextExecutorService = fromExecutorService(e, defaultReporter)
+
+ /** Creates an `ExecutionContext` from the given `Executor`.
+ *
+ * @param e the `Executor` to use. If `null`, a new `Executor` is created with [[scala.concurrent.ExecutionContext$.global default configuration]].
+ * @param reporter a function for error reporting
+ * @return the `ExecutionContext` using the given `Executor`
+ */
+ def fromExecutor(e: Executor, reporter: Throwable => Unit): ExecutionContextExecutor =
+ impl.ExecutionContextImpl.fromExecutor(e, reporter)
+
+ /** Creates an `ExecutionContext` from the given `Executor` with the [[scala.concurrent.ExecutionContext$.defaultReporter default reporter]].
+ *
+ * @param e the `Executor` to use. If `null`, a new `Executor` is created with [[scala.concurrent.ExecutionContext$.global default configuration]].
+ * @return the `ExecutionContext` using the given `Executor`
+ */
+ def fromExecutor(e: Executor): ExecutionContextExecutor = fromExecutor(e, defaultReporter)
+
+ /** The default reporter simply prints the stack trace of the `Throwable` to [[http://docs.oracle.com/javase/8/docs/api/java/lang/System.html#err System.err]].
+ *
+ * @return the function for error reporting
+ */
+ final val defaultReporter: Throwable => Unit = _.printStackTrace()
+}
diff --git a/library-js/src/scala/math/ScalaNumber.scala b/library-js/src/scala/math/ScalaNumber.scala
new file mode 100644
index 000000000000..811346d2f869
--- /dev/null
+++ b/library-js/src/scala/math/ScalaNumber.scala
@@ -0,0 +1,21 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+
+
+package scala.math
+
+/** A marker class for Number types introduced by Scala
+ * @author Martin Odersky, Paul Phillips
+ * @version 2.8
+ * @since 2.8
+ */
+abstract class ScalaNumber extends java.lang.Number {
+ protected def isWhole(): Boolean
+ def underlying(): Object
+}
diff --git a/library-js/src/scala/package.scala b/library-js/src/scala/package.scala
new file mode 100644
index 000000000000..c9f1fdf8314e
--- /dev/null
+++ b/library-js/src/scala/package.scala
@@ -0,0 +1,146 @@
+/*
+ * Scala (https://www.scala-lang.org)
+ *
+ * Copyright EPFL and Lightbend, Inc.
+ *
+ * Licensed under Apache License 2.0
+ * (http://www.apache.org/licenses/LICENSE-2.0).
+ *
+ * See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ */
+
+import scala.annotation.migration
+
+/**
+ * Core Scala types. They are always available without an explicit import.
+ * @contentDiagram hideNodes "scala.Serializable"
+ */
+package object scala {
+ type Cloneable = java.lang.Cloneable
+ type Serializable = java.io.Serializable
+
+ type Throwable = java.lang.Throwable
+ type Exception = java.lang.Exception
+ type Error = java.lang.Error
+
+ type RuntimeException = java.lang.RuntimeException
+ type NullPointerException = java.lang.NullPointerException
+ type ClassCastException = java.lang.ClassCastException
+ type IndexOutOfBoundsException = java.lang.IndexOutOfBoundsException
+ type ArrayIndexOutOfBoundsException = java.lang.ArrayIndexOutOfBoundsException
+ type StringIndexOutOfBoundsException = java.lang.StringIndexOutOfBoundsException
+ type UnsupportedOperationException = java.lang.UnsupportedOperationException
+ type IllegalArgumentException = java.lang.IllegalArgumentException
+ type NoSuchElementException = java.util.NoSuchElementException
+ type NumberFormatException = java.lang.NumberFormatException
+ type AbstractMethodError = java.lang.AbstractMethodError
+ type InterruptedException = java.lang.InterruptedException
+
+ // A dummy used by the specialization annotation.
+ val AnyRef = new Specializable {
+ override def toString = "object AnyRef"
+ }
+
+ @deprecated("Use IterableOnce instead of TraversableOnce", "2.13.0")
+ type TraversableOnce[+A] = scala.collection.IterableOnce[A]
+
+ type IterableOnce[+A] = scala.collection.IterableOnce[A]
+
+ @deprecated("Use Iterable instead of Traversable", "2.13.0")
+ type Traversable[+A] = scala.collection.Iterable[A]
+ @deprecated("Use Iterable instead of Traversable", "2.13.0")
+ val Traversable = scala.collection.Iterable
+
+ type Iterable[+A] = scala.collection.Iterable[A]
+ val Iterable = scala.collection.Iterable
+
+ @migration("scala.Seq is now scala.collection.immutable.Seq instead of scala.collection.Seq", "2.13.0")
+ type Seq[+A] = scala.collection.immutable.Seq[A]
+ val Seq = scala.collection.immutable.Seq
+
+ @migration("scala.IndexedSeq is now scala.collection.immutable.IndexedSeq instead of scala.collection.IndexedSeq", "2.13.0")
+ type IndexedSeq[+A] = scala.collection.immutable.IndexedSeq[A]
+ val IndexedSeq = scala.collection.immutable.IndexedSeq
+
+ type Iterator[+A] = scala.collection.Iterator[A]
+ val Iterator = scala.collection.Iterator
+
+ @deprecated("Use scala.collection.BufferedIterator instead of scala.BufferedIterator", "2.13.0")
+ type BufferedIterator[+A] = scala.collection.BufferedIterator[A]
+
+ type List[+A] = scala.collection.immutable.List[A]
+ val List = scala.collection.immutable.List
+
+ val Nil = scala.collection.immutable.Nil
+
+ type ::[A] = scala.collection.immutable.::[A]
+ val :: = scala.collection.immutable.::
+
+ val +: = scala.collection.+:
+ val :+ = scala.collection.:+
+
+ @deprecated("Use LazyList instead of Stream", "2.13.0")
+ type Stream[+A] = scala.collection.immutable.Stream[A]
+ @deprecated("Use LazyList instead of Stream", "2.13.0")
+ val Stream = scala.collection.immutable.Stream
+
+ type LazyList[+A] = scala.collection.immutable.LazyList[A]
+ val LazyList = scala.collection.immutable.LazyList
+ // This should be an alias to LazyList.#:: but we need to support Stream, too
+ //val #:: = scala.collection.immutable.LazyList.#::
+ object #:: {
+ def unapply[A](s: LazyList[A]): Option[(A, LazyList[A])] =
+ if (s.nonEmpty) Some((s.head, s.tail)) else None
+ def unapply[A](s: Stream[A]): Option[(A, Stream[A])] =
+ if (s.nonEmpty) Some((s.head, s.tail)) else None
+ }
+
+ type Vector[+A] = scala.collection.immutable.Vector[A]
+ val Vector = scala.collection.immutable.Vector
+
+ type StringBuilder = scala.collection.mutable.StringBuilder
+ val StringBuilder = scala.collection.mutable.StringBuilder
+
+ type Range = scala.collection.immutable.Range
+ val Range = scala.collection.immutable.Range
+
+ // Numeric types which were moved into scala.math.*
+
+ type BigDecimal = scala.math.BigDecimal
+ lazy val BigDecimal = scala.math.BigDecimal
+
+ type BigInt = scala.math.BigInt
+ lazy val BigInt = scala.math.BigInt
+
+ type Equiv[T] = scala.math.Equiv[T]
+ val Equiv = scala.math.Equiv
+
+ type Fractional[T] = scala.math.Fractional[T]
+ val Fractional = scala.math.Fractional
+
+ type Integral[T] = scala.math.Integral[T]
+ val Integral = scala.math.Integral
+
+ type Numeric[T] = scala.math.Numeric[T]
+ val Numeric = scala.math.Numeric
+
+ type Ordered[T] = scala.math.Ordered[T]
+ val Ordered = scala.math.Ordered
+
+ type Ordering[T] = scala.math.Ordering[T]
+ val Ordering = scala.math.Ordering
+
+ type PartialOrdering[T] = scala.math.PartialOrdering[T]
+ type PartiallyOrdered[T] = scala.math.PartiallyOrdered[T]
+
+ type Either[+A, +B] = scala.util.Either[A, B]
+ val Either = scala.util.Either
+
+ type Left[+A, +B] = scala.util.Left[A, B]
+ val Left = scala.util.Left
+
+ type Right[+A, +B] = scala.util.Right[A, B]
+ val Right = scala.util.Right
+
+}
diff --git a/library-js/src/scala/reflect/ClassTag.scala b/library-js/src/scala/reflect/ClassTag.scala
new file mode 100644
index 000000000000..a66a1a6a8e34
--- /dev/null
+++ b/library-js/src/scala/reflect/ClassTag.scala
@@ -0,0 +1,146 @@
+/*
+ * Scala (https://www.scala-lang.org)
+ *
+ * Copyright EPFL and Lightbend, Inc.
+ *
+ * Licensed under Apache License 2.0
+ * (http://www.apache.org/licenses/LICENSE-2.0).
+ *
+ * See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ */
+
+package scala
+package reflect
+
+import scala.annotation.unchecked.uncheckedStable
+
+import java.lang.{ Class => jClass }
+
+import scala.collection.mutable
+import scala.runtime.BoxedUnit
+
+/**
+ *
+ * A `ClassTag[T]` stores the erased class of a given type `T`, accessible via the `runtimeClass`
+ * field. This is particularly useful for instantiating `Array`s whose element types are unknown
+ * at compile time.
+ *
+ * `ClassTag`s are a weaker special case of [[scala.reflect.api.TypeTags#TypeTag]]s, in that they
+ * wrap only the runtime class of a given type, whereas a `TypeTag` contains all static type
+ * information. That is, `ClassTag`s are constructed from knowing only the top-level class of a
+ * type, without necessarily knowing all of its argument types. This runtime information is enough
+ * for runtime `Array` creation.
+ *
+ * For example:
+ * {{{
+ * scala> def mkArray[T : ClassTag](elems: T*) = Array[T](elems: _*)
+ * mkArray: [T](elems: T*)(implicit evidence$1: scala.reflect.ClassTag[T])Array[T]
+ *
+ * scala> mkArray(42, 13)
+ * res0: Array[Int] = Array(42, 13)
+ *
+ * scala> mkArray("Japan","Brazil","Germany")
+ * res1: Array[String] = Array(Japan, Brazil, Germany)
+ * }}}
+ *
+ * See [[scala.reflect.api.TypeTags]] for more examples, or the
+ * [[http://docs.scala-lang.org/overviews/reflection/typetags-manifests.html Reflection Guide: TypeTags]]
+ * for more details.
+ *
+ */
+@scala.annotation.implicitNotFound(msg = "No ClassTag available for ${T}")
+trait ClassTag[T] extends ClassManifestDeprecatedApis[T] with Equals with Serializable {
+ // please, don't add any APIs here, like it was with `newWrappedArray` and `newArrayBuilder`
+ // class tags, and all tags in general, should be as minimalistic as possible
+
+ /** A class representing the type `U` to which `T` would be erased.
+ * Note that there is no subtyping relationship between `T` and `U`.
+ */
+ def runtimeClass: jClass[_]
+
+ /** Produces a `ClassTag` that knows how to instantiate an `Array[Array[T]]` */
+ def wrap: ClassTag[Array[T]] = ClassTag[Array[T]](arrayClass(runtimeClass))
+
+ /** Produces a new array with element type `T` and length `len` */
+ def newArray(len: Int): Array[T] =
+ java.lang.reflect.Array.newInstance(runtimeClass, len).asInstanceOf[Array[T]]
+
+ /** A ClassTag[T] can serve as an extractor that matches only objects of type T.
+ *
+ * The compiler tries to turn unchecked type tests in pattern matches into checked ones
+ * by wrapping a `(_: T)` type pattern as `ct(_: T)`, where `ct` is the `ClassTag[T]` instance.
+ * Type tests necessary before calling other extractors are treated similarly.
+ * `SomeExtractor(...)` is turned into `ct(SomeExtractor(...))` if `T` in `SomeExtractor.unapply(x: T)`
+ * is uncheckable, but we have an instance of `ClassTag[T]`.
+ */
+ def unapply(x: Any): Option[T] =
+ if (runtimeClass.isInstance(x)) Some(x.asInstanceOf[T])
+ else None
+
+ // case class accessories
+ override def canEqual(x: Any) = x.isInstanceOf[ClassTag[_]]
+ override def equals(x: Any) = x.isInstanceOf[ClassTag[_]] && this.runtimeClass == x.asInstanceOf[ClassTag[_]].runtimeClass
+ override def hashCode = runtimeClass.##
+ override def toString = {
+ def prettyprint(clazz: jClass[_]): String =
+ if (clazz.isArray) s"Array[${prettyprint(clazz.getComponentType)}]" else
+ clazz.getName
+ prettyprint(runtimeClass)
+ }
+}
+
+/**
+ * Class tags corresponding to primitive types and constructor/extractor for ClassTags.
+ */
+object ClassTag {
+ import ManifestFactory._
+
+ val Byte : ByteManifest = ManifestFactory.Byte
+ val Short : ShortManifest = ManifestFactory.Short
+ val Char : CharManifest = ManifestFactory.Char
+ val Int : IntManifest = ManifestFactory.Int
+ val Long : LongManifest = ManifestFactory.Long
+ val Float : FloatManifest = ManifestFactory.Float
+ val Double : DoubleManifest = ManifestFactory.Double
+ val Boolean : BooleanManifest = ManifestFactory.Boolean
+ val Unit : UnitManifest = ManifestFactory.Unit
+ val Any : ClassTag[scala.Any] = ManifestFactory.Any
+ val Object : ClassTag[java.lang.Object] = ManifestFactory.Object
+ val AnyVal : ClassTag[scala.AnyVal] = ManifestFactory.AnyVal
+ val AnyRef : ClassTag[scala.AnyRef] = ManifestFactory.AnyRef
+ val Nothing : ClassTag[scala.Nothing] = ManifestFactory.Nothing
+ val Null : ClassTag[scala.Null] = ManifestFactory.Null
+
+ @inline
+ @SerialVersionUID(1L)
+ private class GenericClassTag[T](val runtimeClass: jClass[_]) extends ClassTag[T] {
+ override def newArray(len: Int): Array[T] = {
+ java.lang.reflect.Array.newInstance(runtimeClass, len).asInstanceOf[Array[T]]
+ }
+ }
+
+ def apply[T](runtimeClass1: jClass[_]): ClassTag[T] =
+ runtimeClass1 match {
+ case java.lang.Byte.TYPE => ClassTag.Byte.asInstanceOf[ClassTag[T]]
+ case java.lang.Short.TYPE => ClassTag.Short.asInstanceOf[ClassTag[T]]
+ case java.lang.Character.TYPE => ClassTag.Char.asInstanceOf[ClassTag[T]]
+ case java.lang.Integer.TYPE => ClassTag.Int.asInstanceOf[ClassTag[T]]
+ case java.lang.Long.TYPE => ClassTag.Long.asInstanceOf[ClassTag[T]]
+ case java.lang.Float.TYPE => ClassTag.Float.asInstanceOf[ClassTag[T]]
+ case java.lang.Double.TYPE => ClassTag.Double.asInstanceOf[ClassTag[T]]
+ case java.lang.Boolean.TYPE => ClassTag.Boolean.asInstanceOf[ClassTag[T]]
+ case java.lang.Void.TYPE => ClassTag.Unit.asInstanceOf[ClassTag[T]]
+ case _ =>
+ if (classOf[java.lang.Object] == runtimeClass1)
+ ClassTag.Object.asInstanceOf[ClassTag[T]]
+ else if (classOf[scala.runtime.Nothing$] == runtimeClass1)
+ ClassTag.Nothing.asInstanceOf[ClassTag[T]]
+ else if (classOf[scala.runtime.Null$] == runtimeClass1)
+ ClassTag.Null.asInstanceOf[ClassTag[T]]
+ else
+ new GenericClassTag[T](runtimeClass1)
+ }
+
+ def unapply[T](ctag: ClassTag[T]): Option[Class[_]] = Some(ctag.runtimeClass)
+}
diff --git a/library-js/src/scala/reflect/Manifest.scala b/library-js/src/scala/reflect/Manifest.scala
new file mode 100644
index 000000000000..faa2fe6f6e5e
--- /dev/null
+++ b/library-js/src/scala/reflect/Manifest.scala
@@ -0,0 +1,461 @@
+/*
+ * Scala (https://www.scala-lang.org)
+ *
+ * Copyright EPFL and Lightbend, Inc.
+ *
+ * Licensed under Apache License 2.0
+ * (http://www.apache.org/licenses/LICENSE-2.0).
+ *
+ * See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ */
+
+package scala
+package reflect
+
+import scala.collection.mutable.{ArrayBuilder, ArraySeq}
+
+/** A `Manifest[T]` is an opaque descriptor for type T. Its supported use
+ * is to give access to the erasure of the type as a `Class` instance, as
+ * is necessary for the creation of native `Arrays` if the class is not
+ * known at compile time.
+ *
+ * The type-relation operators `<:<` and `=:=` should be considered
+ * approximations only, as there are numerous aspects of type conformance
+ * which are not yet adequately represented in manifests.
+ *
+ * Example usages:
+ * {{{
+ * def arr[T] = new Array[T](0) // does not compile
+ * def arr[T](implicit m: Manifest[T]) = new Array[T](0) // compiles
+ * def arr[T: Manifest] = new Array[T](0) // shorthand for the preceding
+ *
+ * // Methods manifest and optManifest are in [[scala.Predef]].
+ * def isApproxSubType[T: Manifest, U: Manifest] = manifest[T] <:< manifest[U]
+ * isApproxSubType[List[String], List[AnyRef]] // true
+ * isApproxSubType[List[String], List[Int]] // false
+ *
+ * def methods[T: Manifest] = manifest[T].runtimeClass.getMethods
+ * def retType[T: Manifest](name: String) =
+ * methods[T] find (_.getName == name) map (_.getGenericReturnType)
+ *
+ * retType[Map[_, _]]("values") // Some(scala.collection.Iterable)
+ * }}}
+ */
+@scala.annotation.implicitNotFound(msg = "No Manifest available for ${T}.")
+// TODO undeprecated until Scala reflection becomes non-experimental
+// @deprecated("use scala.reflect.ClassTag (to capture erasures) or scala.reflect.runtime.universe.TypeTag (to capture types) or both instead", "2.10.0")
+trait Manifest[T] extends ClassManifest[T] with Equals {
+ override def typeArguments: List[Manifest[_]] = Nil
+
+ override def arrayManifest: Manifest[Array[T]] =
+ Manifest.classType[Array[T]](arrayClass[T](runtimeClass), this)
+
+ override def canEqual(that: Any): Boolean = that match {
+ case _: Manifest[_] => true
+ case _ => false
+ }
+ /** Note: testing for erasure here is important, as it is many times
+ * faster than <:< and rules out most comparisons.
+ */
+ override def equals(that: Any): Boolean = that match {
+ case m: Manifest[_] => (m canEqual this) && (this.runtimeClass == m.runtimeClass) && (this <:< m) && (m <:< this)
+ case _ => false
+ }
+ override def hashCode = this.runtimeClass.##
+}
+
+/** The object `Manifest` defines factory methods for manifests.
+ * It is intended for use by the compiler and should not be used in client code.
+ */
+// TODO undeprecated until Scala reflection becomes non-experimental
+// @deprecated("use scala.reflect.ClassTag (to capture erasures), scala.reflect.runtime.universe.TypeTag (to capture types) or both instead", "2.10.0")
+object Manifest {
+ /* Forward all the public members of ManifestFactory, since this object used
+ * to be a `private val Manifest = ManifestFactory` in the package object. It
+ * was moved here because it needs to be in the same file as `trait Manifest`
+ * defined above.
+ */
+
+ def valueManifests: List[AnyValManifest[_]] =
+ ManifestFactory.valueManifests
+
+ val Byte: ManifestFactory.ByteManifest = ManifestFactory.Byte
+ val Short: ManifestFactory.ShortManifest = ManifestFactory.Short
+ val Char: ManifestFactory.CharManifest = ManifestFactory.Char
+ val Int: ManifestFactory.IntManifest = ManifestFactory.Int
+ val Long: ManifestFactory.LongManifest = ManifestFactory.Long
+ val Float: ManifestFactory.FloatManifest = ManifestFactory.Float
+ val Double: ManifestFactory.DoubleManifest = ManifestFactory.Double
+ val Boolean: ManifestFactory.BooleanManifest = ManifestFactory.Boolean
+ val Unit: ManifestFactory.UnitManifest = ManifestFactory.Unit
+
+ val Any: Manifest[scala.Any] = ManifestFactory.Any
+ val Object: Manifest[java.lang.Object] = ManifestFactory.Object
+ val AnyRef: Manifest[scala.AnyRef] = ManifestFactory.AnyRef
+ val AnyVal: Manifest[scala.AnyVal] = ManifestFactory.AnyVal
+ val Null: Manifest[scala.Null] = ManifestFactory.Null
+ val Nothing: Manifest[scala.Nothing] = ManifestFactory.Nothing
+
+ /** Manifest for the singleton type `value.type`. */
+ def singleType[T <: AnyRef](value: AnyRef): Manifest[T] =
+ ManifestFactory.singleType[T](value)
+
+ /** Manifest for the class type `clazz[args]`, where `clazz` is
+ * a top-level or static class.
+ * @note This no-prefix, no-arguments case is separate because we
+ * it's called from ScalaRunTime.boxArray itself. If we
+ * pass varargs as arrays into this, we get an infinitely recursive call
+ * to boxArray. (Besides, having a separate case is more efficient)
+ */
+ def classType[T](clazz: Predef.Class[_]): Manifest[T] =
+ ManifestFactory.classType[T](clazz)
+
+ /** Manifest for the class type `clazz`, where `clazz` is
+ * a top-level or static class and args are its type arguments. */
+ def classType[T](clazz: Predef.Class[T], arg1: Manifest[_], args: Manifest[_]*): Manifest[T] =
+ ManifestFactory.classType[T](clazz, arg1, args: _*)
+
+ /** Manifest for the class type `clazz[args]`, where `clazz` is
+ * a class with non-package prefix type `prefix` and type arguments `args`.
+ */
+ def classType[T](prefix: Manifest[_], clazz: Predef.Class[_], args: Manifest[_]*): Manifest[T] =
+ ManifestFactory.classType[T](prefix, clazz, args: _*)
+
+ def arrayType[T](arg: Manifest[_]): Manifest[Array[T]] =
+ ManifestFactory.arrayType[T](arg)
+
+ /** Manifest for the abstract type `prefix # name`. `upperBound` is not
+ * strictly necessary as it could be obtained by reflection. It was
+ * added so that erasure can be calculated without reflection. */
+ def abstractType[T](prefix: Manifest[_], name: String, upperBound: Predef.Class[_], args: Manifest[_]*): Manifest[T] =
+ ManifestFactory.abstractType[T](prefix, name, upperBound, args: _*)
+
+ /** Manifest for the unknown type `_ >: L <: U` in an existential. */
+ def wildcardType[T](lowerBound: Manifest[_], upperBound: Manifest[_]): Manifest[T] =
+ ManifestFactory.wildcardType[T](lowerBound, upperBound)
+
+ /** Manifest for the intersection type `parents_0 with ... with parents_n`. */
+ def intersectionType[T](parents: Manifest[_]*): Manifest[T] =
+ ManifestFactory.intersectionType[T](parents: _*)
+
+}
+
+// TODO undeprecated until Scala reflection becomes non-experimental
+// @deprecated("use type tags and manually check the corresponding class or type instead", "2.10.0")
+@SerialVersionUID(1L)
+abstract class AnyValManifest[T <: AnyVal](override val toString: String) extends Manifest[T] with Equals {
+ override def <:<(that: ClassManifest[_]): Boolean =
+ (that eq this) || (that eq Manifest.Any) || (that eq Manifest.AnyVal)
+ override def canEqual(other: Any) = other match {
+ case _: AnyValManifest[_] => true
+ case _ => false
+ }
+ override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef]
+ override def hashCode = System.identityHashCode(this)
+}
+
+/** `ManifestFactory` defines factory methods for manifests.
+ * It is intended for use by the compiler and should not be used in client code.
+ *
+ * Unlike `Manifest`, this factory isn't annotated with a deprecation warning.
+ * This is done to prevent avalanches of deprecation warnings in the code that calls methods with manifests.
+ * Why so complicated? Read up the comments for `ClassManifestFactory`.
+ */
+object ManifestFactory {
+ def valueManifests: List[AnyValManifest[_]] =
+ List(Byte, Short, Char, Int, Long, Float, Double, Boolean, Unit)
+
+ @SerialVersionUID(1L)
+ private[reflect] class ByteManifest extends AnyValManifest[scala.Byte]("Byte") {
+ def runtimeClass = java.lang.Byte.TYPE
+ @inline override def newArray(len: Int): Array[Byte] = new Array[Byte](len)
+ override def newWrappedArray(len: Int): ArraySeq[Byte] = new ArraySeq.ofByte(new Array[Byte](len))
+ override def newArrayBuilder(): ArrayBuilder[Byte] = new ArrayBuilder.ofByte()
+ override def unapply(x: Any): Option[Byte] = {
+ x match {
+ case d: Byte => Some(d)
+ case _ => None
+ }
+ }
+ private def readResolve(): Any = Manifest.Byte
+ }
+ private object ByteManifest extends ByteManifest
+ val Byte: ByteManifest = ByteManifest
+
+ @SerialVersionUID(1L)
+ private[reflect] class ShortManifest extends AnyValManifest[scala.Short]("Short") {
+ def runtimeClass = java.lang.Short.TYPE
+ @inline override def newArray(len: Int): Array[Short] = new Array[Short](len)
+ override def newWrappedArray(len: Int): ArraySeq[Short] = new ArraySeq.ofShort(new Array[Short](len))
+ override def newArrayBuilder(): ArrayBuilder[Short] = new ArrayBuilder.ofShort()
+ override def unapply(x: Any): Option[Short] = {
+ x match {
+ case d: Short => Some(d)
+ case _ => None
+ }
+ }
+ private def readResolve(): Any = Manifest.Short
+ }
+ private object ShortManifest extends ShortManifest
+ val Short: ShortManifest = ShortManifest
+
+ @SerialVersionUID(1L)
+ private[reflect] class CharManifest extends AnyValManifest[scala.Char]("Char") {
+ def runtimeClass = java.lang.Character.TYPE
+ @inline override def newArray(len: Int): Array[Char] = new Array[Char](len)
+ override def newWrappedArray(len: Int): ArraySeq[Char] = new ArraySeq.ofChar(new Array[Char](len))
+ override def newArrayBuilder(): ArrayBuilder[Char] = new ArrayBuilder.ofChar()
+ override def unapply(x: Any): Option[Char] = {
+ x match {
+ case d: Char => Some(d)
+ case _ => None
+ }
+ }
+ private def readResolve(): Any = Manifest.Char
+ }
+ private object CharManifest extends CharManifest
+ val Char: CharManifest = CharManifest
+
+ @SerialVersionUID(1L)
+ private[reflect] class IntManifest extends AnyValManifest[scala.Int]("Int") {
+ def runtimeClass = java.lang.Integer.TYPE
+ @inline override def newArray(len: Int): Array[Int] = new Array[Int](len)
+ override def newWrappedArray(len: Int): ArraySeq[Int] = new ArraySeq.ofInt(new Array[Int](len))
+ override def newArrayBuilder(): ArrayBuilder[Int] = new ArrayBuilder.ofInt()
+ override def unapply(x: Any): Option[Int] = {
+ x match {
+ case d: Int => Some(d)
+ case _ => None
+ }
+ }
+ private def readResolve(): Any = Manifest.Int
+ }
+ private object IntManifest extends IntManifest
+ val Int: IntManifest = IntManifest
+
+ @SerialVersionUID(1L)
+ private[reflect] class LongManifest extends AnyValManifest[scala.Long]("Long") {
+ def runtimeClass = java.lang.Long.TYPE
+ @inline override def newArray(len: Int): Array[Long] = new Array[Long](len)
+ override def newWrappedArray(len: Int): ArraySeq[Long] = new ArraySeq.ofLong(new Array[Long](len))
+ override def newArrayBuilder(): ArrayBuilder[Long] = new ArrayBuilder.ofLong()
+ override def unapply(x: Any): Option[Long] = {
+ x match {
+ case d: Long => Some(d)
+ case _ => None
+ }
+ }
+ private def readResolve(): Any = Manifest.Long
+ }
+ private object LongManifest extends LongManifest
+ val Long: LongManifest = LongManifest
+
+ @SerialVersionUID(1L)
+ private[reflect] class FloatManifest extends AnyValManifest[scala.Float]("Float") {
+ def runtimeClass = java.lang.Float.TYPE
+ @inline override def newArray(len: Int): Array[Float] = new Array[Float](len)
+ override def newWrappedArray(len: Int): ArraySeq[Float] = new ArraySeq.ofFloat(new Array[Float](len))
+ override def newArrayBuilder(): ArrayBuilder[Float] = new ArrayBuilder.ofFloat()
+ override def unapply(x: Any): Option[Float] = {
+ x match {
+ case d: Float => Some(d)
+ case _ => None
+ }
+ }
+ private def readResolve(): Any = Manifest.Float
+ }
+ private object FloatManifest extends FloatManifest
+ val Float: FloatManifest = FloatManifest
+
+ @SerialVersionUID(1L)
+ private[reflect] class DoubleManifest extends AnyValManifest[scala.Double]("Double") {
+ def runtimeClass = java.lang.Double.TYPE
+ @inline override def newArray(len: Int): Array[Double] = new Array[Double](len)
+ override def newWrappedArray(len: Int): ArraySeq[Double] = new ArraySeq.ofDouble(new Array[Double](len))
+ override def newArrayBuilder(): ArrayBuilder[Double] = new ArrayBuilder.ofDouble()
+
+ override def unapply(x: Any): Option[Double] = {
+ x match {
+ case d: Double => Some(d)
+ case _ => None
+ }
+ }
+ private def readResolve(): Any = Manifest.Double
+ }
+ private object DoubleManifest extends DoubleManifest
+ val Double: DoubleManifest = DoubleManifest
+
+ @SerialVersionUID(1L)
+ private[reflect] class BooleanManifest extends AnyValManifest[scala.Boolean]("Boolean") {
+ def runtimeClass = java.lang.Boolean.TYPE
+ @inline override def newArray(len: Int): Array[Boolean] = new Array[Boolean](len)
+ override def newWrappedArray(len: Int): ArraySeq[Boolean] = new ArraySeq.ofBoolean(new Array[Boolean](len))
+ override def newArrayBuilder(): ArrayBuilder[Boolean] = new ArrayBuilder.ofBoolean()
+ override def unapply(x: Any): Option[Boolean] = {
+ x match {
+ case d: Boolean => Some(d)
+ case _ => None
+ }
+ }
+ private def readResolve(): Any = Manifest.Boolean
+ }
+ private object BooleanManifest extends BooleanManifest
+ val Boolean: BooleanManifest = BooleanManifest
+
+ @SerialVersionUID(1L)
+ private[reflect] class UnitManifest extends AnyValManifest[scala.Unit]("Unit") {
+ def runtimeClass = java.lang.Void.TYPE
+ @inline override def newArray(len: Int): Array[Unit] = new Array[Unit](len)
+ override def newWrappedArray(len: Int): ArraySeq[Unit] = new ArraySeq.ofUnit(new Array[Unit](len))
+ override def newArrayBuilder(): ArrayBuilder[Unit] = new ArrayBuilder.ofUnit()
+ override protected def arrayClass[T](tp: Class[_]): Class[Array[T]] =
+ if (tp eq runtimeClass) classOf[Array[scala.runtime.BoxedUnit]].asInstanceOf[Class[Array[T]]]
+ else super.arrayClass(tp)
+ override def unapply(x: Any): Option[Unit] = {
+ x match {
+ case d: Unit => Some(d)
+ case _ => None
+ }
+ }
+ private def readResolve(): Any = Manifest.Unit
+ }
+ private object UnitManifest extends UnitManifest
+ val Unit: UnitManifest = UnitManifest
+
+ private object AnyManifest extends PhantomManifest[scala.Any](classOf[java.lang.Object], "Any") {
+ override def runtimeClass = classOf[java.lang.Object]
+ override def newArray(len: Int) = new Array[scala.Any](len)
+ override def <:<(that: ClassManifest[_]): Boolean = (that eq this)
+ private def readResolve(): Any = Manifest.Any
+ }
+ val Any: Manifest[scala.Any] = AnyManifest
+
+ private object ObjectManifest extends PhantomManifest[java.lang.Object](classOf[java.lang.Object], "Object") {
+ override def runtimeClass = classOf[java.lang.Object]
+ override def newArray(len: Int) = new Array[java.lang.Object](len)
+ override def <:<(that: ClassManifest[_]): Boolean = (that eq this) || (that eq Any)
+ private def readResolve(): Any = Manifest.Object
+ }
+ val Object: Manifest[java.lang.Object] = ObjectManifest
+
+ val AnyRef: Manifest[scala.AnyRef] = Object
+
+ private object AnyValManifest extends PhantomManifest[scala.AnyVal](classOf[java.lang.Object], "AnyVal") {
+ override def runtimeClass = classOf[java.lang.Object]
+ override def newArray(len: Int) = new Array[scala.AnyVal](len)
+ override def <:<(that: ClassManifest[_]): Boolean = (that eq this) || (that eq Any)
+ private def readResolve(): Any = Manifest.AnyVal
+ }
+ val AnyVal: Manifest[scala.AnyVal] = AnyValManifest
+
+ private object NullManifest extends PhantomManifest[scala.Null](classOf[scala.runtime.Null$], "Null") {
+ override def runtimeClass = classOf[scala.runtime.Null$]
+ override def newArray(len: Int) = new Array[scala.Null](len)
+ override def <:<(that: ClassManifest[_]): Boolean =
+ (that ne null) && (that ne Nothing) && !(that <:< AnyVal)
+ private def readResolve(): Any = Manifest.Null
+ }
+ val Null: Manifest[scala.Null] = NullManifest
+
+ private object NothingManifest extends PhantomManifest[scala.Nothing](classOf[scala.runtime.Nothing$], "Nothing") {
+ override def runtimeClass = classOf[scala.runtime.Nothing$]
+ override def newArray(len: Int) = new Array[scala.Nothing](len)
+ override def <:<(that: ClassManifest[_]): Boolean = (that ne null)
+ private def readResolve(): Any = Manifest.Nothing
+ }
+ val Nothing: Manifest[scala.Nothing] = NothingManifest
+
+ @SerialVersionUID(1L)
+ private class SingletonTypeManifest[T <: AnyRef](value: AnyRef) extends Manifest[T] {
+ lazy val runtimeClass = value.getClass
+ override lazy val toString = value.toString + ".type"
+ }
+
+ /** Manifest for the singleton type `value.type`. */
+ def singleType[T <: AnyRef](value: AnyRef): Manifest[T] =
+ new SingletonTypeManifest[T](value)
+
+ /** Manifest for the class type `clazz[args]`, where `clazz` is
+ * a top-level or static class.
+ * @note This no-prefix, no-arguments case is separate because we
+ * it's called from ScalaRunTime.boxArray itself. If we
+ * pass varargs as arrays into this, we get an infinitely recursive call
+ * to boxArray. (Besides, having a separate case is more efficient)
+ */
+ def classType[T](clazz: Predef.Class[_]): Manifest[T] =
+ new ClassTypeManifest[T](None, clazz, Nil)
+
+ /** Manifest for the class type `clazz`, where `clazz` is
+ * a top-level or static class and args are its type arguments. */
+ def classType[T](clazz: Predef.Class[T], arg1: Manifest[_], args: Manifest[_]*): Manifest[T] =
+ new ClassTypeManifest[T](None, clazz, arg1 :: args.toList)
+
+ /** Manifest for the class type `clazz[args]`, where `clazz` is
+ * a class with non-package prefix type `prefix` and type arguments `args`.
+ */
+ def classType[T](prefix: Manifest[_], clazz: Predef.Class[_], args: Manifest[_]*): Manifest[T] =
+ new ClassTypeManifest[T](Some(prefix), clazz, args.toList)
+
+ @SerialVersionUID(1L)
+ private abstract class PhantomManifest[T](_runtimeClass: Predef.Class[_],
+ override val toString: String) extends ClassTypeManifest[T](None, _runtimeClass, Nil) {
+ override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef]
+ override def hashCode = System.identityHashCode(this)
+ }
+
+ /** Manifest for the class type `clazz[args]`, where `clazz` is
+ * a top-level or static class. */
+ @SerialVersionUID(1L)
+ private class ClassTypeManifest[T](prefix: Option[Manifest[_]],
+ runtimeClass1: Predef.Class[_],
+ override val typeArguments: List[Manifest[_]]) extends Manifest[T] {
+ def runtimeClass: Predef.Class[_] = runtimeClass1
+ override def toString =
+ (if (prefix.isEmpty) "" else prefix.get.toString+"#") +
+ (if (runtimeClass.isArray) "Array" else runtimeClass.getName) +
+ argString
+ }
+
+ def arrayType[T](arg: Manifest[_]): Manifest[Array[T]] =
+ arg.asInstanceOf[Manifest[T]].arrayManifest
+
+ @SerialVersionUID(1L)
+ private class AbstractTypeManifest[T](prefix: Manifest[_], name: String, upperBound: Predef.Class[_], args: scala.collection.Seq[Manifest[_]]) extends Manifest[T] {
+ def runtimeClass = upperBound
+ override val typeArguments = args.toList
+ override def toString = prefix.toString+"#"+name+argString
+ }
+
+ /** Manifest for the abstract type `prefix # name`. `upperBound` is not
+ * strictly necessary as it could be obtained by reflection. It was
+ * added so that erasure can be calculated without reflection. */
+ def abstractType[T](prefix: Manifest[_], name: String, upperBound: Predef.Class[_], args: Manifest[_]*): Manifest[T] =
+ new AbstractTypeManifest[T](prefix, name, upperBound, args)
+
+ @SerialVersionUID(1L)
+ private class WildcardManifest[T](lowerBound: Manifest[_], upperBound: Manifest[_]) extends Manifest[T] {
+ def runtimeClass = upperBound.runtimeClass
+ override def toString =
+ "_" +
+ (if (lowerBound eq Nothing) "" else " >: "+lowerBound) +
+ (if (upperBound eq Nothing) "" else " <: "+upperBound)
+ }
+
+ /** Manifest for the unknown type `_ >: L <: U` in an existential.
+ */
+ def wildcardType[T](lowerBound: Manifest[_], upperBound: Manifest[_]): Manifest[T] =
+ new WildcardManifest[T](lowerBound, upperBound)
+
+ @SerialVersionUID(1L)
+ private class IntersectionTypeManifest[T](parents: Array[Manifest[_]]) extends Manifest[T] {
+ // We use an `Array` instead of a `Seq` for `parents` to avoid cyclic dependencies during deserialization
+ // which can cause serialization proxies to leak and cause a ClassCastException.
+ def runtimeClass = parents(0).runtimeClass
+ override def toString = parents.mkString(" with ")
+ }
+
+ /** Manifest for the intersection type `parents_0 with ... with parents_n`. */
+ def intersectionType[T](parents: Manifest[_]*): Manifest[T] =
+ new IntersectionTypeManifest[T](parents.toArray)
+}
diff --git a/library-js/src/scala/runtime/BoxesRunTime.scala b/library-js/src/scala/runtime/BoxesRunTime.scala
new file mode 100644
index 000000000000..48412eb77846
--- /dev/null
+++ b/library-js/src/scala/runtime/BoxesRunTime.scala
@@ -0,0 +1,145 @@
+package scala.runtime
+
+import scala.math.ScalaNumber
+
+/* The declaration of the class is only to make the JVM back-end happy when
+ * compiling the scalalib.
+ */
+final class BoxesRunTime
+
+object BoxesRunTime {
+ def boxToBoolean(b: Boolean): java.lang.Boolean =
+ b.asInstanceOf[java.lang.Boolean]
+
+ def boxToCharacter(c: Char): java.lang.Character =
+ c.asInstanceOf[java.lang.Character]
+
+ def boxToByte(b: Byte): java.lang.Boolean =
+ b.asInstanceOf[java.lang.Boolean]
+
+ def boxToShort(s: Short): java.lang.Short =
+ s.asInstanceOf[java.lang.Short]
+
+ def boxToInteger(i: Int): java.lang.Integer =
+ i.asInstanceOf[java.lang.Integer]
+
+ def boxToLong(l: Long): java.lang.Long =
+ l.asInstanceOf[java.lang.Long]
+
+ def boxToFloat(f: Float): java.lang.Float =
+ f.asInstanceOf[java.lang.Float]
+
+ def boxToDouble(d: Double): java.lang.Double =
+ d.asInstanceOf[java.lang.Double]
+
+ def unboxToBoolean(b: Any): Boolean = b.asInstanceOf[Boolean]
+
+ def unboxToChar(c: Any): Char = c.asInstanceOf[Char]
+
+ def unboxToByte(b: Any): Byte = b.asInstanceOf[Byte]
+
+ def unboxToShort(s: Any): Short = s.asInstanceOf[Short]
+
+ def unboxToInt(i: Any): Int = i.asInstanceOf[Int]
+
+ def unboxToLong(l: Any): Long = l.asInstanceOf[Long]
+
+ def unboxToFloat(f: Any): Float = f.asInstanceOf[Float]
+
+ def unboxToDouble(d: Any): Double = d.asInstanceOf[Double]
+
+ def equals(x: Object, y: Object): Boolean =
+ if (scala.scalajs.js.special.strictEquals(x, y)) true
+ else equals2(x, y)
+
+ @inline // only called by equals(), not by codegen
+ def equals2(x: Object, y: Object): Boolean = {
+ x match {
+ case xn: java.lang.Number => equalsNumObject(xn, y)
+ case xc: java.lang.Character => equalsCharObject(xc, y)
+ case null => y eq null
+ case _ => x.equals(y)
+ }
+ }
+
+ def equalsNumObject(xn: java.lang.Number, y: Object): Boolean = {
+ y match {
+ case yn: java.lang.Number => equalsNumNum(xn, yn)
+ case yc: java.lang.Character => equalsNumChar(xn, yc)
+ case _ =>
+ if (xn eq null)
+ y eq null
+ else
+ xn.equals(y)
+ }
+ }
+
+ def equalsNumNum(xn: java.lang.Number, yn: java.lang.Number): Boolean = {
+ (xn: Any) match {
+ case xn: Double =>
+ (yn: Any) match {
+ case yn: Double => xn == yn
+ case yn: Long => xn == yn
+ case yn: ScalaNumber => yn.equals(xn) // xn is not a ScalaNumber
+ case _ => false // xn.equals(yn) must be false here
+ }
+ case xn: Long =>
+ (yn: Any) match {
+ case yn: Long => xn == yn
+ case yn: Double => xn == yn
+ case yn: ScalaNumber => yn.equals(xn) // xn is not a ScalaNumber
+ case _ => false // xn.equals(yn) must be false here
+ }
+ case null => yn eq null
+ case _ => xn.equals(yn)
+ }
+ }
+
+ def equalsCharObject(xc: java.lang.Character, y: Object): Boolean = {
+ y match {
+ case yc: java.lang.Character => xc.charValue() == yc.charValue()
+ case yn: java.lang.Number => equalsNumChar(yn, xc)
+ case _ =>
+ if (xc eq null)
+ y eq null
+ else
+ false // xc.equals(y) must be false here, because y is not a Char
+ }
+ }
+
+ @inline
+ private def equalsNumChar(xn: java.lang.Number, yc: java.lang.Character): Boolean = {
+ (xn: Any) match {
+ case xn: Double => xn == yc.charValue()
+ case xn: Long => xn == yc.charValue()
+ case _ =>
+ if (xn eq null) yc eq null
+ else xn.equals(yc)
+ }
+ }
+
+ @inline
+ def hashFromLong(n: java.lang.Long): Int =
+ Statics.longHash(n.asInstanceOf[Long])
+
+ @inline
+ def hashFromDouble(n: java.lang.Double): Int =
+ Statics.doubleHash(n.asInstanceOf[Double])
+
+ @inline
+ def hashFromFloat(n: java.lang.Float): Int =
+ Statics.floatHash(n.asInstanceOf[Float])
+
+ @inline // called only by ScalaRunTime.hash()
+ def hashFromNumber(n: java.lang.Number): Int = {
+ (n: Any) match {
+ case n: Double => Statics.doubleHash(n)
+ case n: Long => Statics.longHash(n)
+ case n => n.hashCode()
+ }
+ }
+
+ @inline
+ def hashFromObject(a: Object): Int =
+ Statics.anyHash(a)
+}
diff --git a/library-js/src/scala/runtime/ScalaRunTime.scala b/library-js/src/scala/runtime/ScalaRunTime.scala
new file mode 100644
index 000000000000..6e3803675608
--- /dev/null
+++ b/library-js/src/scala/runtime/ScalaRunTime.scala
@@ -0,0 +1,273 @@
+/*
+ * Scala (https://www.scala-lang.org)
+ *
+ * Copyright EPFL and Lightbend, Inc.
+ *
+ * Licensed under Apache License 2.0
+ * (http://www.apache.org/licenses/LICENSE-2.0).
+ *
+ * See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ */
+
+package scala
+package runtime
+
+import scala.collection.{AbstractIterator, AnyConstr, SortedOps, StrictOptimizedIterableOps, StringOps, StringView, View}
+import scala.collection.immutable.{ArraySeq, NumericRange}
+import scala.collection.mutable.StringBuilder
+import scala.reflect.{ClassTag, classTag}
+import java.lang.{Class => jClass}
+import java.lang.reflect.{Method => JMethod}
+
+import scala.collection.generic.IsIterable
+
+/** The object ScalaRunTime provides support methods required by
+ * the scala runtime. All these methods should be considered
+ * outside the API and subject to change or removal without notice.
+ */
+object ScalaRunTime {
+ def isArray(x: Any, atLevel: Int = 1): Boolean =
+ x != null && isArrayClass(x.getClass, atLevel)
+
+ private def isArrayClass(clazz: jClass[_], atLevel: Int): Boolean =
+ clazz != null && clazz.isArray && (atLevel == 1 || isArrayClass(clazz.getComponentType, atLevel - 1))
+
+ // A helper method to make my life in the pattern matcher a lot easier.
+ def drop[Repr](coll: Repr, num: Int)(implicit iterable: IsIterable[Repr] { type C <: Repr }): Repr =
+ iterable(coll) drop num
+
+ /** Return the class object representing an array with element class `clazz`.
+ */
+ def arrayClass(clazz: jClass[_]): jClass[_] = {
+ // newInstance throws an exception if the erasure is Void.TYPE. see scala/bug#5680
+ if (clazz == java.lang.Void.TYPE) classOf[Array[Unit]]
+ else java.lang.reflect.Array.newInstance(clazz, 0).getClass
+ }
+
+ /** Return the class object representing an unboxed value type,
+ * e.g., classOf[int], not classOf[java.lang.Integer]. The compiler
+ * rewrites expressions like 5.getClass to come here.
+ */
+ def anyValClass[T <: AnyVal : ClassTag](value: T): jClass[T] =
+ classTag[T].runtimeClass.asInstanceOf[jClass[T]]
+
+ /** Retrieve generic array element */
+ def array_apply(xs: AnyRef, idx: Int): Any = {
+ xs match {
+ case x: Array[AnyRef] => x(idx).asInstanceOf[Any]
+ case x: Array[Int] => x(idx).asInstanceOf[Any]
+ case x: Array[Double] => x(idx).asInstanceOf[Any]
+ case x: Array[Long] => x(idx).asInstanceOf[Any]
+ case x: Array[Float] => x(idx).asInstanceOf[Any]
+ case x: Array[Char] => x(idx).asInstanceOf[Any]
+ case x: Array[Byte] => x(idx).asInstanceOf[Any]
+ case x: Array[Short] => x(idx).asInstanceOf[Any]
+ case x: Array[Boolean] => x(idx).asInstanceOf[Any]
+ case null => throw new NullPointerException
+ }
+ }
+
+ /** update generic array element */
+ def array_update(xs: AnyRef, idx: Int, value: Any): Unit = {
+ xs match {
+ case x: Array[AnyRef] => x(idx) = value.asInstanceOf[AnyRef]
+ case x: Array[Int] => x(idx) = value.asInstanceOf[Int]
+ case x: Array[Double] => x(idx) = value.asInstanceOf[Double]
+ case x: Array[Long] => x(idx) = value.asInstanceOf[Long]
+ case x: Array[Float] => x(idx) = value.asInstanceOf[Float]
+ case x: Array[Char] => x(idx) = value.asInstanceOf[Char]
+ case x: Array[Byte] => x(idx) = value.asInstanceOf[Byte]
+ case x: Array[Short] => x(idx) = value.asInstanceOf[Short]
+ case x: Array[Boolean] => x(idx) = value.asInstanceOf[Boolean]
+ case null => throw new NullPointerException
+ }
+ }
+
+ /** Get generic array length */
+ @inline def array_length(xs: AnyRef): Int = java.lang.reflect.Array.getLength(xs)
+
+ // TODO: bytecode Object.clone() will in fact work here and avoids
+ // the type switch. See Array_clone comment in BCodeBodyBuilder.
+ def array_clone(xs: AnyRef): AnyRef = xs match {
+ case x: Array[AnyRef] => x.clone()
+ case x: Array[Int] => x.clone()
+ case x: Array[Double] => x.clone()
+ case x: Array[Long] => x.clone()
+ case x: Array[Float] => x.clone()
+ case x: Array[Char] => x.clone()
+ case x: Array[Byte] => x.clone()
+ case x: Array[Short] => x.clone()
+ case x: Array[Boolean] => x.clone()
+ case null => throw new NullPointerException
+ }
+
+ /** Convert an array to an object array.
+ * Needed to deal with vararg arguments of primitive types that are passed
+ * to a generic Java vararg parameter T ...
+ */
+ def toObjectArray(src: AnyRef): Array[Object] = src match {
+ case x: Array[AnyRef] => x
+ case _ =>
+ val length = array_length(src)
+ val dest = new Array[Object](length)
+ for (i <- 0 until length)
+ array_update(dest, i, array_apply(src, i))
+ dest
+ }
+
+ def toArray[T](xs: scala.collection.Seq[T]) = {
+ val arr = new Array[AnyRef](xs.length)
+ var i = 0
+ for (x <- xs) {
+ arr(i) = x.asInstanceOf[AnyRef]
+ i += 1
+ }
+ arr
+ }
+
+ // Java bug: https://bugs.java.com/view_bug.do?bug_id=4071957
+ // More background at ticket #2318.
+ def ensureAccessible(m: JMethod): JMethod = scala.reflect.ensureAccessible(m)
+
+ def _toString(x: Product): String =
+ x.productIterator.mkString(x.productPrefix + "(", ",", ")")
+
+ def _hashCode(x: Product): Int = scala.util.hashing.MurmurHash3.productHash(x)
+
+ /** A helper for case classes. */
+ def typedProductIterator[T](x: Product): Iterator[T] = {
+ new AbstractIterator[T] {
+ private[this] var c: Int = 0
+ private[this] val cmax = x.productArity
+ def hasNext = c < cmax
+ def next() = {
+ val result = x.productElement(c)
+ c += 1
+ result.asInstanceOf[T]
+ }
+ }
+ }
+
+ /** Given any Scala value, convert it to a String.
+ *
+ * The primary motivation for this method is to provide a means for
+ * correctly obtaining a String representation of a value, while
+ * avoiding the pitfalls of naively calling toString on said value.
+ * In particular, it addresses the fact that (a) toString cannot be
+ * called on null and (b) depending on the apparent type of an
+ * array, toString may or may not print it in a human-readable form.
+ *
+ * @param arg the value to stringify
+ * @return a string representation of arg.
+ */
+ def stringOf(arg: Any): String = stringOf(arg, scala.Int.MaxValue)
+ def stringOf(arg: Any, maxElements: Int): String = {
+ def packageOf(x: AnyRef) = x.getClass.getPackage match {
+ case null => ""
+ case p => p.getName
+ }
+ def isScalaClass(x: AnyRef) = packageOf(x) startsWith "scala."
+ def isScalaCompilerClass(x: AnyRef) = packageOf(x) startsWith "scala.tools.nsc."
+
+ // includes specialized subclasses and future proofed against hypothetical TupleN (for N > 22)
+ def isTuple(x: Any) = x != null && x.getClass.getName.startsWith("scala.Tuple")
+
+ // We use reflection because the scala.xml package might not be available
+ def isSubClassOf(potentialSubClass: Class[_], ofClass: String) =
+ try {
+ val classLoader = potentialSubClass.getClassLoader
+ val clazz = Class.forName(ofClass, /*initialize =*/ false, classLoader)
+ clazz.isAssignableFrom(potentialSubClass)
+ } catch {
+ case cnfe: ClassNotFoundException => false
+ }
+ def isXmlNode(potentialSubClass: Class[_]) = isSubClassOf(potentialSubClass, "scala.xml.Node")
+ def isXmlMetaData(potentialSubClass: Class[_]) = isSubClassOf(potentialSubClass, "scala.xml.MetaData")
+
+ // When doing our own iteration is dangerous
+ def useOwnToString(x: Any) = x match {
+ // Range/NumericRange have a custom toString to avoid walking a gazillion elements
+ case _: Range | _: NumericRange[_] => true
+ // Sorted collections to the wrong thing (for us) on iteration - ticket #3493
+ case _: SortedOps[_, _] => true
+ // StringBuilder(a, b, c) and similar not so attractive
+ case _: StringView | _: StringOps | _: StringBuilder => true
+ // Don't want to evaluate any elements in a view
+ case _: View[_] => true
+ // Node extends NodeSeq extends Seq[Node] and MetaData extends Iterable[MetaData]
+ // -> catch those by isXmlNode and isXmlMetaData.
+ // Don't want to a) traverse infinity or b) be overly helpful with peoples' custom
+ // collections which may have useful toString methods - ticket #3710
+ // or c) print AbstractFiles which are somehow also Iterable[AbstractFile]s.
+ case x: Iterable[_] => (!x.isInstanceOf[StrictOptimizedIterableOps[_, AnyConstr, _]]) || !isScalaClass(x) || isScalaCompilerClass(x) || isXmlNode(x.getClass) || isXmlMetaData(x.getClass)
+ // Otherwise, nothing could possibly go wrong
+ case _ => false
+ }
+
+ // A variation on inner for maps so they print -> instead of bare tuples
+ def mapInner(arg: Any): String = arg match {
+ case (k, v) => inner(k) + " -> " + inner(v)
+ case _ => inner(arg)
+ }
+
+ // Special casing Unit arrays, the value class which uses a reference array type.
+ def arrayToString(x: AnyRef) = {
+ if (x.getClass.getComponentType == classOf[BoxedUnit])
+ 0 until (array_length(x) min maxElements) map (_ => "()") mkString ("Array(", ", ", ")")
+ else
+ x.asInstanceOf[Array[_]].iterator.take(maxElements).map(inner).mkString("Array(", ", ", ")")
+ }
+
+ // The recursively applied attempt to prettify Array printing.
+ // Note that iterator is used if possible and foreach is used as a
+ // last resort, because the parallel collections "foreach" in a
+ // random order even on sequences.
+ def inner(arg: Any): String = arg match {
+ case null => "null"
+ case "" => "\"\""
+ case x: String => if (x.head.isWhitespace || x.last.isWhitespace) "\"" + x + "\"" else x
+ case x if useOwnToString(x) => x.toString
+ case x: AnyRef if isArray(x) => arrayToString(x)
+ case x: scala.collection.Map[_, _] => x.iterator take maxElements map mapInner mkString (x.collectionClassName + "(", ", ", ")")
+ case x: Iterable[_] => x.iterator take maxElements map inner mkString (x.collectionClassName + "(", ", ", ")")
+ case x: Product1[_] if isTuple(x) => "(" + inner(x._1) + ",)" // that special trailing comma
+ case x: Product if isTuple(x) => x.productIterator map inner mkString ("(", ",", ")")
+ case x => x.toString
+ }
+
+ // The try/catch is defense against iterables which aren't actually designed
+ // to be iterated, such as some scala.tools.nsc.io.AbstractFile derived classes.
+ try inner(arg)
+ catch {
+ case _: UnsupportedOperationException | _: AssertionError => "" + arg
+ }
+ }
+
+ /** stringOf formatted for use in a repl result. */
+ def replStringOf(arg: Any, maxElements: Int): String =
+ stringOf(arg, maxElements) match {
+ case null => "null toString"
+ case s if s.indexOf('\n') >= 0 => "\n" + s + "\n"
+ case s => s + "\n"
+ }
+
+ // Convert arrays to immutable.ArraySeq for use with Java varargs:
+ def genericWrapArray[T](xs: Array[T]): ArraySeq[T] =
+ if (xs eq null) null
+ else ArraySeq.unsafeWrapArray(xs)
+ def wrapRefArray[T <: AnyRef](xs: Array[T]): ArraySeq[T] = {
+ if (xs eq null) null
+ else if (xs.length == 0) ArraySeq.empty[AnyRef].asInstanceOf[ArraySeq[T]]
+ else new ArraySeq.ofRef[T](xs)
+ }
+ def wrapIntArray(xs: Array[Int]): ArraySeq[Int] = if (xs ne null) new ArraySeq.ofInt(xs) else null
+ def wrapDoubleArray(xs: Array[Double]): ArraySeq[Double] = if (xs ne null) new ArraySeq.ofDouble(xs) else null
+ def wrapLongArray(xs: Array[Long]): ArraySeq[Long] = if (xs ne null) new ArraySeq.ofLong(xs) else null
+ def wrapFloatArray(xs: Array[Float]): ArraySeq[Float] = if (xs ne null) new ArraySeq.ofFloat(xs) else null
+ def wrapCharArray(xs: Array[Char]): ArraySeq[Char] = if (xs ne null) new ArraySeq.ofChar(xs) else null
+ def wrapByteArray(xs: Array[Byte]): ArraySeq[Byte] = if (xs ne null) new ArraySeq.ofByte(xs) else null
+ def wrapShortArray(xs: Array[Short]): ArraySeq[Short] = if (xs ne null) new ArraySeq.ofShort(xs) else null
+ def wrapBooleanArray(xs: Array[Boolean]): ArraySeq[Boolean] = if (xs ne null) new ArraySeq.ofBoolean(xs) else null
+ def wrapUnitArray(xs: Array[Unit]): ArraySeq[Unit] = if (xs ne null) new ArraySeq.ofUnit(xs) else null
+}
diff --git a/library-js/src/scala/util/DynamicVariable.scala b/library-js/src/scala/util/DynamicVariable.scala
new file mode 100644
index 000000000000..b3eb4048499d
--- /dev/null
+++ b/library-js/src/scala/util/DynamicVariable.scala
@@ -0,0 +1,74 @@
+/*
+ * Scala (https://www.scala-lang.org)
+ *
+ * Copyright EPFL and Lightbend, Inc.
+ *
+ * Licensed under Apache License 2.0
+ * (http://www.apache.org/licenses/LICENSE-2.0).
+ *
+ * See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ */
+
+package scala
+package util
+
+import java.lang.InheritableThreadLocal
+
+/** `DynamicVariables` provide a binding mechanism where the current
+ * value is found through dynamic scope, but where access to the
+ * variable itself is resolved through static scope.
+ *
+ * The current value can be retrieved with the value method. New values
+ * should be pushed using the `withValue` method. Values pushed via
+ * `withValue` only stay valid while the `withValue`'s second argument, a
+ * parameterless closure, executes. When the second argument finishes,
+ * the variable reverts to the previous value.
+ *
+ * {{{
+ * someDynamicVariable.withValue(newValue) {
+ * // ... code called in here that calls value ...
+ * // ... will be given back the newValue ...
+ * }
+ * }}}
+ *
+ * Each thread gets its own stack of bindings. When a
+ * new thread is created, the `DynamicVariable` gets a copy
+ * of the stack of bindings from the parent thread, and
+ * from then on the bindings for the new thread
+ * are independent of those for the original thread.
+ *
+ * @author Lex Spoon
+ * @since 2.6
+ */
+class DynamicVariable[T](init: T) {
+ /* Scala.js: replaced InheritableThreadLocal by a simple var.
+ * This removes the dependency on ThreadLocal and InheritableThreadLocal from the
+ * Hello World.
+ */
+ private[this] var v = init
+
+ /** Retrieve the current value */
+ def value: T = v
+
+ /** Set the value of the variable while executing the specified
+ * thunk.
+ *
+ * @param newval The value to which to set the variable
+ * @param thunk The code to evaluate under the new setting
+ */
+ def withValue[S](newval: T)(thunk: => S): S = {
+ val oldval = v
+ v = newval
+
+ try thunk
+ finally v = oldval
+ }
+
+ /** Change the currently bound value, discarding the old value.
+ * Usually withValue() gives better semantics.
+ */
+ def value_=(newval: T) = v = newval
+
+ override def toString: String = "DynamicVariable(" + value + ")"
+}
diff --git a/library-js/src/scala/util/control/NoStackTrace.scala b/library-js/src/scala/util/control/NoStackTrace.scala
new file mode 100644
index 000000000000..046abf2fd830
--- /dev/null
+++ b/library-js/src/scala/util/control/NoStackTrace.scala
@@ -0,0 +1,39 @@
+/*
+ * Scala (https://www.scala-lang.org)
+ *
+ * Copyright EPFL and Lightbend, Inc.
+ *
+ * Licensed under Apache License 2.0
+ * (http://www.apache.org/licenses/LICENSE-2.0).
+ *
+ * See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ */
+
+package scala
+package util.control
+
+/** A trait for exceptions which, for efficiency reasons, do not
+ * fill in the stack trace. Stack trace suppression can be disabled
+ * on a global basis via a system property wrapper in
+ * [[scala.sys.SystemProperties]].
+ *
+ * @note Since JDK 1.7, a similar effect can be achieved with `class Ex extends Throwable(..., writableStackTrace = false)`
+ *
+ * @author Paul Phillips
+ * @since 2.8
+ */
+trait NoStackTrace extends Throwable {
+ override def fillInStackTrace(): Throwable =
+ if (NoStackTrace.noSuppression) super.fillInStackTrace()
+ else this
+}
+
+object NoStackTrace {
+ final def noSuppression = _noSuppression
+
+ // two-stage init to make checkinit happy, since sys.SystemProperties.noTraceSupression.value calls back into NoStackTrace.noSuppression
+ final private var _noSuppression = false
+ // !!! Disabled in Scala.js because SystemProperties is not supported
+ //_noSuppression = System.getProperty("scala.control.noTraceSuppression", "").equalsIgnoreCase("true")
+}