forked from scala-js/scala-js
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathLinkingInfo.scala
295 lines (279 loc) · 8.97 KB
/
LinkingInfo.scala
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
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
/*
* Scala.js (https://www.scala-js.org/)
*
* Copyright EPFL.
*
* Licensed under Apache License 2.0
* (https://www.apache.org/licenses/LICENSE-2.0).
*
* See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.
*/
package scala.scalajs
object LinkingInfo {
import scala.scalajs.runtime.linkingInfo
/** Returns true if we are linking for production, false otherwise.
*
* `productionMode` is always equal to `!developmentMode`.
*
* This ends up being constant-folded to a constant at link-time. So
* constant-folding, inlining, and other local optimizations can be
* leveraged with this "constant" to write code that should only be
* executed in production mode or development mode.
*
* A typical usage of this method is:
* {{{
* val warningsLogger =
* if (productionMode) new NullLogger
* else new ConsoleLogger
* }}}
*
* At link-time, `productionMode` will either be a constant true, in which
* case the above snippet folds into
* {{{
* val warningsLogger = new NullLogger
* }}}
* or a constant false, in which case it folds into
* {{{
* val warningsLogger = new ConsoleLogger.
* }}}
*
* @see [[developmentMode]]
*/
@inline
def productionMode: Boolean =
linkingInfo.productionMode
/** Returns true if we are linking for development, false otherwise.
*
* `developmentMode` is always equal to `!productionMode`.
*
* This ends up being constant-folded to a constant at link-time. So
* constant-folding, inlining, and other local optimizations can be
* leveraged with this "constant" to write code that should only be
* executed in production mode or development mode.
*
* A typical usage of this method is:
* {{{
* if (developmentMode) {
* performExpensiveSanityChecks()
* }
* }}}
*
* At link-time, `developmentMode` will either be a constant true, in which
* case the above snippet folds into
* {{{
* performExpensiveSanityChecks()
* }}}
* or a constant false, in which case it is dead-code-eliminated away,
* yielding maximum performance in production.
*
* @see [[productionMode]]
*/
@inline
def developmentMode: Boolean =
!productionMode
/** Version (edition) of the ECMAScript Language Specification that is
* assumed to be supported by the runtime.
*
* This is an integer that represents the *edition* of the ECMAScript
* Language Specification. For example, ECMAScript 2015 is represented with
* the value `6`.
*
* As an exception, ECMAScript 5.1 is represented with the value `5`.
*
* This value can be used to:
*
* - avoid feature tests and dead-code-eliminate polyfills (see below), or
* - conditionally offer library features that depend on underlying
* ECMAScript support.
*
* ---
*
* This ends up being constant-folded to a constant at link-time. So
* constant-folding, inlining, and other local optimizations can be
* leveraged with this "constant" to write polyfills that can be
* dead-code-eliminated.
*
* A typical usage of this method is:
* {{{
* if (esVersion >= ESVersion.ES2018 || featureTest())
* useES2018Feature()
* else
* usePolyfill()
* }}}
*
* At link-time, `esVersion` will either be a constant less than
* `ESVersion.ES2018`, in which case the above snippet folds into
* {{{
* if (featureTest())
* useES2018Feature()
* else
* usePolyfill()
* }}}
* or a constant greater or equal to `ESVersion.ES2018`, in which case it
* folds into
* {{{
* useES2018Feature()
* }}}
*/
@inline
def esVersion: Int =
linkingInfo.esVersion
/** Returns true if we are assuming that the target platform supports
* ECMAScript 6, false otherwise.
*
* This is `true` if and only if `esVersion >= ESVersion.ES2015`.
*
* ---
*
* This ends up being constant-folded to a constant at link-time. So
* constant-folding, inlining, and other local optimizations can be
* leveraged with this "constant" to write polyfills that can be
* dead-code-eliminated.
*
* A typical usage of this method is:
* {{{
* if (assumingES6 || featureTest())
* useES6Feature()
* else
* usePolyfill()
* }}}
*
* At link-time, `assumingES6` will either be a constant false, in which
* case the above snippet folds into
* {{{
* if (featureTest())
* useES6Feature()
* else
* usePolyfill()
* }}}
* or a constant true, in which case it folds into
* {{{
* useES6Feature()
* }}}
*/
@deprecated("use esVersion >= ESVersion.ES2015 instead", "1.6.0")
@inline
def assumingES6: Boolean =
esVersion >= ESVersion.ES2015
/** Whether Scala.js language features use ECMAScript 2015 (edition 6)
* semantics or not.
*
* When `true`, the following semantics apply:
*
* - JavaScript classes are true `class`'es, therefore a) they can extend
* native JavaScript `class`'es and b) they inherit static members from
* their parent class.
* - Lambdas for `js.Function`s that are not also `js.ThisFunction`s are
* JavaScript arrow functions (`=>`). Lambdas for `js.ThisFunction`s are
* `function` functions.
* - Throwable classes are proper JavaScript error classes, recognized as
* such by debuggers.
* - In Script (`NoModule`) mode, top-level exports are defined as `let`s.
*
* When `false`, the following semantics apply:
*
* - All classes defined in Scala.js are `function`s instead of `class`'es.
* Non-native JS classes cannot extend native JS `class`'es and they do
* not inherit static members from their parent class.
* - All lambdas for `js.Function`s are `function`s.
* - Throwable classes have JavaScript's `Error.prototype` in their
* prototype chain, but they are not considered proper error classes.
* - In Script (`NoModule`) mode, top-level exports are defined as `var`s.
*
* Prefer reading this value instead of `esVersion` to determine which
* semantics apply.
*
* For example, it can be used in tests whose results depend on which
* semantics are used.
*
* ---
*
* This ends up being constant-folded to a constant at link-time. So
* constant-folding, inlining, and other local optimizations can be
* leveraged with this "constant" to write alternatives that can be
* dead-code-eliminated.
*
* A typical usage of this method is:
* {{{
* if (useECMAScript2015Semantics)
* implementationWithES2015Semantics()
* else
* implementationWithoutES2015Semantics()
* }}}
*
* At link-time, `useECMAScript2015Semantics` will either be a constant
* true, in which case the above snippet folds into
* {{{
* implementationWithES2015Semantics()
* }}}
* or a constant false, in which case it folds into
* {{{
* implementationWithoutES2015Semantics()
* }}}
*/
@inline
def useECMAScript2015Semantics: Boolean =
linkingInfo.assumingES6 // name mismatch for historical reasons
/** Constants for the value of `esVersion`. */
object ESVersion {
/** ECMAScrîpt 5.1. */
final val ES5_1 = 5
/** ECMAScript 2015 (6th edition). */
final val ES2015 = 6
/** ECMAScript 2016 (7th edition).
*
* Contains the following notable features:
*
* - The `**` operator for numbers
* - `async`/`await`
*/
final val ES2016 = 7
/** ECMAScript 2017 (8th edition).
*
* Contains the following notable features:
*
* - Async functions
* - Shared Memory and Atomics (via `SharedArrayBuffer`)
* - `Object.values`, `Object.entries`, and `Object.getOwnPropertyDescriptors`
*/
final val ES2017 = 8
/** ECMAScript 2018 (9th edition).
*
* Contains the following notable features:
*
* - Asynchronous iteration via the `AsyncIterator` protocol and async generators
* - Regular expression features: the dotAll flag `'s'`, named capture groups,
* Unicode property escapes (`\p{}` and `\P{}`) and look-behind assertions
* - Rest parameter and spread operator support for object properties
*/
final val ES2018 = 9
/** ECMAScript 2019 (10th edition).
*
* Contains the following notable features:
*
* - Minor additions to the built-in library functions
*/
final val ES2019 = 10
/** ECMAScript 2020 (11th edition).
*
* Contains the following notable features:
*
* - Dynamic `import()` calls
* - `BigInt`
* - `globalThis`
* - `export * as ns from 'module'`
* - `import.meta`
*/
final val ES2020 = 11
/** ECMAScript 2021 (12th edition).
*
* Contains the following notable features:
*
* - `WeakRef` and `FinalizationRegistry`
* - `AggregateError`
* - Separators for numeric literals (e.g., `1_000`)
*/
final val ES2021 = 12
}
}