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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
|
package scala.scalajs
import scala.annotation.tailrec
import scala.collection.GenTraversableOnce
package object runtime {
def wrapJavaScriptException(e: Any): Throwable = e match {
case e: Throwable => e
case _ => js.JavaScriptException(e)
}
def unwrapJavaScriptException(th: Throwable): Any = th match {
case js.JavaScriptException(e) => e
case _ => th
}
def cloneObject(from: js.Object): js.Object = {
val ctor = ({ (self: js.Dictionary[js.Any], from: js.Dictionary[js.Any]) =>
for (key <- from.keys)
self(key) = from(key)
}: js.ThisFunction).asInstanceOf[js.Dynamic]
ctor.prototype = js.Object.getPrototypeOf(from)
js.Dynamic.newInstance(ctor)(from)
}
@inline final def genTraversableOnce2jsArray[A](
col: GenTraversableOnce[A]): js.Array[A] = {
col match {
case col: js.ArrayOps[A] => col.result()
case col: js.WrappedArray[A] => col.array
case _ =>
val result = new js.Array[A]
col.foreach(x => result.push(x))
result
}
}
/** Instantiates a JS object with variadic arguments to the constructor. */
def newJSObjectWithVarargs(ctor: js.Dynamic, args: js.Array[_]): js.Any = {
// Not really "possible" in JavaScript, so we emulate what it would be.
val c = ((() => ()): js.Function).asInstanceOf[js.Dynamic]
c.prototype = ctor.prototype
val instance = js.Dynamic.newInstance(c)()
val result = ctor.applyDynamic("apply")(instance, args)
(result: js.Any) match {
case _:js.prim.Undefined | _:js.prim.Number | _:js.prim.Boolean |
_:js.prim.String | null =>
instance
case _ =>
result
}
}
/** Returns an array of the enumerable properties in an object's prototype
* chain.
*
* This is the implementation of [[js.Object.properties]].
*/
def propertiesOf(obj: js.Any): js.Array[String] = {
// See http://stackoverflow.com/questions/26445248/
if (obj == null || js.isUndefined(obj)) {
js.Array()
} else {
val result = new js.Array[String]
val alreadySeen = js.Dictionary.empty[Boolean]
@tailrec
def loop(obj: js.Object): Unit = {
if (obj != null) {
// Add own enumerable properties that have not been seen yet
val enumProps = js.Object.keys(obj)
val enumPropsLen = enumProps.length
var i = 0
while (i < enumPropsLen) {
val prop = enumProps(i)
if (!alreadySeen.get(prop).isDefined)
result.push(prop)
i += 1
}
/* Add all own properties to the alreadySeen set, including
* non-enumerable ones.
*/
val allProps = js.Object.getOwnPropertyNames(obj)
val allPropsLen = allProps.length
var j = 0
while (j < allPropsLen) {
alreadySeen(allProps(j)) = true
j += 1
}
// Continue with the next object in the prototype chain
loop(js.Object.getPrototypeOf(obj))
}
}
loop(js.Object(obj))
result
}
}
/** Information about the environment Scala.js runs in. */
def environmentInfo: js.Dynamic = sys.error("stub")
/** Polyfill for fround in case we use strict Floats and even Typed Arrays
* are not available.
* Note: this method returns a Double, even though the value is meant
* to be a Float. It cannot return a Float because that would require to
* do `x.toFloat` somewhere in here, which would itself, in turn, call this
* method.
*/
def froundPolyfill(v: Double): Double = {
/* Originally inspired by the Typed Array polyfills written by Joshua Bell:
* https://github.com/inexorabletash/polyfill/blob/a682f42c1092280bb01907c245979fb07219513d/typedarray.js#L150-L255
* Then simplified quite a lot because
* 1) we do not need to produce the actual bit string that serves as
* storage of the floats, and
* 2) we are only interested in the float32 case.
*/
import Math._
// Special cases
if (v.isNaN || v == 0.0 || v.isInfinite) {
v
} else {
val LN2 = 0.6931471805599453
val ebits = 8
val fbits = 23
val bias = (1 << (ebits-1)) - 1
val twoPowFbits = (1 << fbits).toDouble
val SubnormalThreshold = 1.1754943508222875E-38 // pow(2, 1-bias)
val isNegative = v < 0
val av = if (isNegative) -v else v
val absResult = if (av >= SubnormalThreshold) {
val e0 = floor(log(av) / LN2)
// 1-bias <= e0 <= 1024
if (e0 > bias) {
// Overflow
Double.PositiveInfinity
} else {
val twoPowE0 = pow(2, e0)
val f0 = Bits.roundToEven(av / twoPowE0 * twoPowFbits)
if (f0 / twoPowFbits >= 2) {
//val e = e0 + 1.0 // not used
val f = 1.0
if (e0 > bias-1) { // === (e > bias) because e0 is whole
// Overflow
Double.PositiveInfinity
} else {
// Normalized case 1
val twoPowE = 2*twoPowE0
twoPowE * (1.0 + (f - twoPowFbits) / twoPowFbits)
}
} else {
// Normalized case 2
// val e = e0 // not used
val f = f0
val twoPowE = twoPowE0
twoPowE * (1.0 + (f - twoPowFbits) / twoPowFbits)
}
}
} else {
// Subnormal
val rounder = Float.MinPositiveValue.toDouble
Bits.roundToEven(av / rounder) * rounder
}
if (isNegative) -absResult else absResult
}
}
}
|