forked from swiftwasm/JavaScriptKit
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathJSArray.swift
More file actions
86 lines (72 loc) · 2.16 KB
/
JSArray.swift
File metadata and controls
86 lines (72 loc) · 2.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
public class JSArray {
static let classObject = JSObject.global.Array.function!
static func isArray(_ object: JSObject) -> Bool {
classObject.isArray!(object).boolean!
}
let ref: JSObject
public init?(_ ref: JSObject) {
guard Self.isArray(ref) else { return nil }
self.ref = ref
}
}
extension JSArray: RandomAccessCollection {
public typealias Element = JSValue
public func makeIterator() -> Iterator {
Iterator(ref: ref)
}
public class Iterator: IteratorProtocol {
let ref: JSObject
var index = 0
init(ref: JSObject) {
self.ref = ref
}
public func next() -> Element? {
let currentIndex = index
guard currentIndex < Int(ref.length.number!) else {
return nil
}
index += 1
guard ref.hasOwnProperty!(currentIndex).boolean! else {
return next()
}
let value = ref[currentIndex]
return value
}
}
public subscript(position: Int) -> JSValue {
ref[position]
}
public var startIndex: Int { 0 }
public var endIndex: Int { length }
/// The number of elements in that array including empty hole.
/// Note that `length` respects JavaScript's `Array.prototype.length`
///
/// e.g.
/// ```javascript
/// const array = [1, , 3];
/// ```
/// ```swift
/// let array: JSArray = ...
/// array.length // 3
/// array.count // 2
/// ```
public var length: Int {
return Int(ref.length.number!)
}
/// The number of elements in that array **not** including empty hole.
/// Note that `count` syncs with the number that `Iterator` can iterate.
/// See also: `JSArray.length`
public var count: Int {
return getObjectValuesLength(ref)
}
}
private let alwaysTrue = JSClosure { _ in .boolean(true) }
private func getObjectValuesLength(_ object: JSObject) -> Int {
let values = object.filter!(alwaysTrue).object!
return Int(values.length.number!)
}
extension JSValue {
public var array: JSArray? {
object.flatMap(JSArray.init)
}
}