8000 Fix #1115: Enrich js.WrappedArray with Buffer and BufferLike. · scala-js/scala-js@afc9695 · GitHub
[go: up one dir, main page]

Skip to content

Commit afc9695

Browse files
committed
Fix #1115: Enrich js.WrappedArray with Buffer and BufferLike.
This basically turns it into a full-blown Scala collection, whose implementation happens to use a js.Array. We also mark it @inline, because it gives the BufferLike interface to js.Array, which js.ArrayOps cannot provide due to the type parameters of BufferLike being too restrictive.
1 parent 2a2e6c4 commit afc9695

File tree

2 files changed

+80
-18
lines changed

2 files changed

+80
-18
lines changed

library/src/main/scala/scala/scalajs/js/WrappedArray.scala

Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,29 +8,34 @@
88

99
package scala.scalajs.js
1010

11+
import scala.language.implicitConversions
12+
1113
import scala.collection.mutable
1214
import mutable.Builder
1315

14-
import scala.collection.generic.CanBuildFrom
16+
import scala.collection.generic.{CanBuildFrom, GenericCompanion, SeqFactory}
1517

1618
/** Equivalent of scm.WrappedArray for js.Array */
17-
class WrappedArray[A](val array: Array[A])
19+
@inline
20+
final class WrappedArray[A](val array: Array[A])
1821
extends mutable.AbstractSeq[A]
22+
with scala.collection.generic.GenericTraversableTemplate[A, WrappedArray]
1923
with mutable.IndexedSeq[A]
24+
with mutable.Buffer[A]
25+
with mutable.BufferLike[A, WrappedArray[A]]
2026
with mutable.ArrayLike[A, WrappedArray[A]]
2127
with Builder[A, WrappedArray[A]] {
2228

2329
/** Creates a new empty [[WrappedArray]]. */
2430
def this() = this(Array())
2531

26-
// IndexedSeq interface
32+
override def companion: GenericCompanion[WrappedArray] = WrappedArray
2733

28-
def update(index: Int, elem: A): Unit = array(index) = elem
29-
def apply(index: Int): A = array(index)
30-
def length: Int = array.length
34+
// IndexedSeq interface
3135

32-
override protected[this] def newBuilder: Builder[A, WrappedArray[A]] =
33-
new WrappedArray[A]
36+
@inline def update(index: Int, elem: A): Unit = array(index) = elem
37+
@inline def apply(index: Int): A = array(index)
38+
@inline def length: Int = array.length
3439

3540
// Builder interface
3641

@@ -44,19 +49,45 @@ class WrappedArray[A](val array: Array[A])
4449

4550
@inline override def result(): WrappedArray[A] = this
4651

47-
}
52+
// Rest of BufferLike interface
4853

49-
object WrappedArray {
54+
@inline override def +=:(elem: A): this.type = {
55+
array.unshift(elem)
56+
this
57+
}
5058

51-
def empty[A]: WrappedArray[A] = new WrappedArray[A]
59+
@inline override def ++=:(xs: TraversableOnce[A]): this.type = {
60+
array.unshift(xs.toSeq: _*)
61+
this
62+
}
5263

53-
implicit def canBuildFrom[A]: CanBuildFrom[WrappedArray[_], A, WrappedArray[A]] = {
54-
new CanBuildFrom[WrappedArray[_], A, WrappedArray[A]] {
55-
def apply(from: WrappedArray[_]): Builder[A, WrappedArray[A]] =
56-
new WrappedArray[A]
57-
def apply: Builder[A, WrappedArray[A]] =
58-
new WrappedArray[A]
59-
}
64+
@inline override def insertAll(n: Int,
65+
elems: scala.collection.Traversable[A]): Unit = {
66+
array.splice(n, 0, elems.toSeq: _*)
6067
}
6168

69+
@inline override def remove(n: Int): A =
70+
array.splice(n, 1)(0)
71+
72+
@inline override def remove(n: Int, count: Int): Unit =
73+
array.splice(n, count)
74+
75+
@inline override def stringPrefix: String = "WrappedArray"
76+
77+
}
78+
79+
/** $factoryInfo
80+
* @define coll wrapped array
81+
* @define Coll `WrappedArray`
82+
*/
83+
object WrappedArray extends SeqFactory[WrappedArray] {
84+
/** $genericCanBuildFromInfo */
85+
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, WrappedArray[A]] =
86+
ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]
87+
88+
def newBuilder[A]: Builder[A, WrappedArray[A]] = new WrappedArray[A]
89+
90+
implicit def toJSArray[A](wrappedArray: WrappedArray[A]): Array[A] =
91+
wrappedArray.array
92+
6293
}

test-suite/src/test/scala/scala/scalajs/testsuite/library/WrappedArrayTest.scala

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,37 @@ object WrappedArrayTest extends JasmineTest {
5050
expect(seq.length).toEqual(7)
5151
}
5252

53+
it("should implement +=:") {
54+
val array = js.Array(5, 8, 9)
55+
3 +=: array
56+
expect(array).toEqual(js.Array(3, 5, 8, 9))
57+
}
58+
59+
it("should implement ++=:") {
60+
val array = js.Array(5, 8, 9)
61+
js.Array(2, 0) ++=: array
62+
expect(array).toEqual(js.Array(2, 0, 5, 8, 9))
63+
Seq(-3, -45, 1) ++=: array
64+
expect(array).toEqual(js.Array(-3, -45, 1, 2, 0, 3, 5, 8, 9))
65+
}
66+
67+
it("should implement insertAll") {
68+
val array = js.Array(5, 8, 9)
69+
array.insertAll(2, js.Array(2, 0))
70+
expect(array).toEqual(js.Array(5, 8, 2, 0, 9))
71+
array.insertAll(1, Seq(-3, -45, 1))
72+
expect(array).toEqual(js.Array(3, -3, -45, 1, 5, 8, 2, 0, 9))
73+
}
74+
75+
it("should implement remove") {
76+
val array = js.Array(5, 8, 2, 0, 9)
77+
expect(array.remove(1)).toEqual(8)
78+
expect(array).toEqual(js.Array(5, 2, 0, 9))
79+
80+
array.remove(0, 3)
81+
expect(array).toEqual(js.Array(9))
82+
}
83+
5384
// Some arbitrary methods to test the builders
5485

5586
it("should implement collect") {

0 commit comments

Comments
 (0)
0