Skip to content

Commit a90f690

Browse files
committed
Redesign DOMList and review its implementations.
DOMList is now no more than an interface for things that have a `length` and index properties. We add a Seq view of all DOMLists in its companion object. We make it read-only and covariant, as its implementations are actually not mutable in the DOM standard. We review all its subclasses and subtraits: * Make them classes iff they are exposed and can be used with `instanceof`. Their constructors are always private. Otherwise, make them traits. * Explicitly declare `item()` iff it is supported in the given class/trait (it used to be in `DOMList`, but not all implementations support `item()`). We make `NodeList` parameterized and covariant in the type of node. We deprecate `NodeListOf` in favor of `NodeList`.
1 parent 79895ee commit a90f690

File tree

8 files changed

+68
-72
lines changed

8 files changed

+68
-72
lines changed

src/main/scala/org/scalajs/dom/CSSTypes.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,9 @@ class CSSPageRule extends CSSRule {
479479
*/
480480
@js.native
481481
@JSGlobal
482-
class CSSRuleList extends DOMList[CSSRule]
482+
class CSSRuleList private[this] () extends DOMList[CSSRule] {
483+
def item(index: Int): CSSRule = js.native
484+
}
483485

484486
/**
485487
* The CSSKeyframesRule interface describes an object representing a complete set

src/main/scala/org/scalajs/dom/HTMLTypes.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1157,7 +1157,8 @@ abstract class HTMLMenuElement extends HTMLElement {
11571157
*/
11581158
@js.native
11591159
@JSGlobal
1160-
abstract class HTMLCollection extends DOMList[Element] {
1160+
class HTMLCollection private[this] () extends DOMList[Element] {
1161+
def item(index: Int): Element = js.native
11611162

11621163
/**
11631164
* Returns the specific node whose ID or, as a fallback, name matches the string

src/main/scala/org/scalajs/dom/SVGTypes.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1244,7 +1244,7 @@ abstract class SVGSVGElement
12441244
* MDN
12451245
*/
12461246
def getIntersectionList(rect: SVGRect,
1247-
referenceElement: SVGElement): NodeList = js.native
1247+
referenceElement: SVGElement): NodeList[Node] = js.native
12481248

12491249
/**
12501250
* Unsuspends (i.e., unpauses) currently running animations that are defined
@@ -1327,7 +1327,7 @@ abstract class SVGSVGElement
13271327
def createSVGAngle(): SVGAngle = js.native
13281328

13291329
def getEnclosureList(rect: SVGRect,
1330-
referenceElement: SVGElement): NodeList = js.native
1330+
referenceElement: SVGElement): NodeList[Node] = js.native
13311331

13321332
/**
13331333
* Creates an SVGTransform object outside of any document trees. The object is

src/main/scala/org/scalajs/dom/ext/Extensions.scala

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,30 +12,6 @@ import scala.scalajs.js.typedarray.TypedArrayBufferOps._
1212
import org.scalajs.dom
1313
import org.scalajs.dom.{Blob, FormData, KeyboardEvent}
1414

15-
/**
16-
* Used to extend out javascript *Collections to make them usable as normal
17-
* Scala Seq[*]s
18-
*/
19-
class EasySeq[T](jsLength: Int, jsApply: Int => T)
20-
extends scala.collection.Seq[T] {
21-
22-
def length = jsLength
23-
24-
def apply(x: Int) = jsApply(x)
25-
26-
def iterator = new Iterator[T] {
27-
var index = 0
28-
29-
def hasNext: scala.Boolean = index < jsLength
30-
31-
def next() = {
32-
val res = jsApply(index)
33-
index += 1
34-
res
35-
}
36-
}
37-
}
38-
3915
/**
4016
* A list of the codes returned by KeyEvents.
4117
*/

src/main/scala/org/scalajs/dom/ext/package.scala

Lines changed: 0 additions & 21 deletions
This file was deleted.

src/main/scala/org/scalajs/dom/lib.scala

Lines changed: 55 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,7 @@ trait NodeSelector extends js.Object {
518518
*
519519
* MDN
520520
*/
521-
def querySelectorAll(selectors: String): NodeList = js.native
521+
def querySelectorAll(selectors: String): NodeList[Node] = js.native
522522

523523
/**
524524
* Returns the first element within the document (using depth-first pre-order
@@ -1134,7 +1134,7 @@ abstract class Node extends EventTarget {
11341134
*
11351135
* MDN
11361136
*/
1137-
def childNodes: NodeList = js.native
1137+
def childNodes: NodeList[Node] = js.native
11381138

11391139
/**
11401140
* Returns a DOMString containing the name of the Node. The structure of the name will
@@ -2977,8 +2977,9 @@ class TouchEvent(typeArg: String, init: js.UndefOr[TouchEventInit])
29772977
* MDN
29782978
*/
29792979
@js.native
2980-
@JSGlobal
2981-
class TouchList extends DOMList[Touch]
2980+
trait TouchList extends DOMList[Touch] {
2981+
def item(index: Int): Touch = js.native
2982+
}
29822983

29832984
/**
29842985
* A Touch object represents a single point of contact between the user and a touch-sensitive
@@ -3337,7 +3338,7 @@ abstract class Document
33373338
*
33383339
* MDN
33393340
*/
3340-
def getElementsByName(elementName: String): NodeList = js.native
3341+
def getElementsByName(elementName: String): NodeList[Node] = js.native
33413342

33423343
/**
33433344
* Returns a HTMLCollection of elements with the given tag name. The complete
@@ -5014,14 +5015,14 @@ trait MutationRecord extends js.Object {
50145015
*
50155016
* MDN
50165017
*/
5017-
def addedNodes: NodeList = js.native
5018+
def addedNodes: NodeList[Node] = js.native
50185019

50195020
/**
50205021
* Return the nodes removed. Will be an empty NodeList if no nodes were removed.
50215022
*
50225023
* MDN
50235024
*/
5024-
def removedNodes: NodeList = js.native
5025+
def removedNodes: NodeList[Node] = js.native
50255026

50265027
/**
50275028
* Return the previous sibling of the added or removed nodes, or null.
@@ -6290,14 +6291,40 @@ class StyleSheet extends js.Object {
62906291
}
62916292

62926293
@js.native
6293-
trait DOMList[T] extends js.Object {
6294+
trait DOMList[+T] extends js.Object {
62946295
def length: Int = js.native
6295-
def item(index: Int): T = js.native
6296-
@scala.scalajs.js.annotation.JSBracketAccess
6296+
6297+
@JSBracketAccess
62976298
def apply(index: Int): T = js.native
6299+
}
62986300

6299-
@scala.scalajs.js.annotation.JSBracketAccess
6300-
def update(index: Int, v: T): Unit = js.native
6301+
object DOMList {
6302+
implicit def domListAsSeq[T](domList: DOMList[T]): scala.collection.Seq[T] =
6303+
new DOMListSeq(domList)
6304+
6305+
private final class DOMListSeq[+T](domList: DOMList[T])
6306+
extends scala.collection.Seq[T] {
6307+
6308+
def length: Int = domList.length
6309+
6310+
def apply(x: Int): T = domList(x)
6311+
6312+
def iterator: Iterator[T] = new DOMListIterator(domList)
6313+
}
6314+
6315+
private final class DOMListIterator[+T](domList: DOMList[T])
6316+
extends Iterator[T] {
6317+
6318+
private[this] var index = 0
6319+
6320+
def hasNext: Boolean = index < domList.length
6321+
6322+
def next(): T = {
6323+
val res = domList(index)
6324+
index += 1
6325+
res
6326+
}
6327+
}
63016328
}
63026329

63036330
/**
@@ -6308,10 +6335,9 @@ trait DOMList[T] extends js.Object {
63086335
*/
63096336
@js.native
63106337
@JSGlobal
6311-
class NodeList extends DOMList[Node]
6312-
6313-
@js.native
6314-
trait NodeListOf[TNode <: Node] extends DOMList[TNode]
6338+
class NodeList[+T <: Node] private[this] () extends DOMList[T] {
6339+
def item(index: Int): T = js.native
6340+
}
63156341

63166342
@js.native
63176343
@JSGlobal
@@ -6832,7 +6858,9 @@ trait TextTrackCue extends EventTarget {
68326858
* MDN
68336859
*/
68346860
@js.native
6835-
trait DOMTokenList extends DOMList[String] {
6861+
@JSGlobal
6862+
class DOMTokenList private[this] extends DOMList[String] {
6863+
def item(index: Int): String = js.native
68366864

68376865
def contains(token: String): Boolean = js.native
68386866

@@ -7205,7 +7233,10 @@ trait ProgressEvent extends Event {
72057233
* MDN
72067234
*/
72077235
@js.native
7208-
trait FileList extends DOMList[File]
7236+
@JSGlobal
7237+
class FileList private[this] () extends DOMList[File] {
7238+
def item(index: Int): File = js.native
7239+
}
72097240

72107241
/**
72117242
* The File interface provides information about -- and access to the contents of --
@@ -7380,7 +7411,8 @@ trait AudioTrack extends js.Object {
73807411
}
73817412

73827413
@js.native
7383-
trait TextTrackCueList extends DOMList[TextTrackCue] {
7414+
@JSGlobal
7415+
class TextTrackCueList private[this] () extends DOMList[TextTrackCue] {
73847416
def getCueById(id: String): TextTrackCue = js.native
73857417
}
73867418

@@ -7572,7 +7604,10 @@ trait WindowBase64 extends js.Object {
75727604
* MDN
75737605
*/
75747606
@js.native
7575-
trait DOMStringList extends DOMList[String] {
7607+
@JSGlobal
7608+
class DOMStringList private[this] () extends DOMList[String] {
7609+
def item(index: Int): String = js.native
7610+
75767611
def contains(str: String): Boolean = js.native
75777612
}
75787613

src/main/scala/org/scalajs/dom/package.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,7 @@ package object dom {
3838

3939
@deprecated("use DOMRectList instead", "2.0.0")
4040
type ClientRectList = DOMRectList
41+
42+
@deprecated("use NodeList[T] instead", "2.0.0")
43+
type NodeListOf[+T <: Node] = NodeList[T]
4144
}

src/main/scala/org/scalajs/dom/raw.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ object raw {
8181
type DOMException = dom.DOMException
8282
type DOMImplementation = dom.DOMImplementation
8383
lazy val DOMException: dom.DOMException.type = dom.DOMException
84-
type DOMList[T] = dom.DOMList[T]
84+
type DOMList[+T] = dom.DOMList[T]
8585
type DOMParser = dom.DOMParser
8686
type DOMRect = dom.DOMRect
8787
type DOMRectList = dom.DOMRectList
@@ -238,8 +238,8 @@ object raw {
238238
type NodeFilter = dom.NodeFilter
239239
lazy val NodeFilter: dom.NodeFilter.type = dom.NodeFilter
240240
type NodeIterator = dom.NodeIterator
241-
type NodeList = dom.NodeList
242-
type NodeListOf[TNode <: Node] = dom.NodeListOf[TNode]
241+
type NodeList[+T <: Node] = dom.NodeList[T]
242+
type NodeListOf[+T <: Node] = NodeList[T]
243243

244244
type OfflineAudioContext = dom.OfflineAudioContext
245245
type OscillatorNode = dom.OscillatorNode

0 commit comments

Comments
 (0)