Skip to content

Commit 5a77117

Browse files
committed
Announcing Scala.js 1.20.1.
1 parent fc4f6e3 commit 5a77117

File tree

7 files changed

+188
-8
lines changed

7 files changed

+188
-8
lines changed

_config.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ colors: #in hex code if not noted else
6464

6565
### VERSIONS ###
6666
versions:
67-
scalaJS: 1.19.0
67+
scalaJS: 1.20.1
6868
scalaJSBinary: 1
6969
scalaJS06x: 0.6.33
7070
scalaJS06xBinary: 0.6
71-
scalaJSDOM: 2.8.0
71+
scalaJSDOM: 2.8.1

_data/library/versions.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,4 @@
3636
- 1.17.0
3737
- 1.18.0
3838
- 1.19.0
39+
- 1.20.0
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
---
2+
layout: post
3+
title: Announcing Scala.js 1.20.1
4+
category: news
5+
tags: [releases]
6+
permalink: /news/2025/09/06/announcing-scalajs-1.20.1/
7+
---
8+
9+
10+
We are pleased to announce the release of Scala.js 1.20.1!
11+
12+
This is technically a hotfix patch release for 1.20.0, which was discovered to be [severely broken](https://github.com/scala-js/scala-js/issues/5231), and was therefore never announced.
13+
These release notes therefore present it as a "minor release" compared to 1.19.0.
14+
15+
This release mainly comes with many performance improvements to the WebAssembly and JavaScript backends alike.
16+
17+
As of this writing, the latest versions of Firefox (since v131), Safari (since v18.4) and Chrome (since v137) support all the WebAssembly features required to run Scala.js-on-Wasm.
18+
19+
Read on for more details.
20+
21+
<!--more-->
22+
23+
## Getting started
24+
25+
If you are new to Scala.js, head over to [the tutorial]({{ BASE_PATH }}/tutorial/).
26+
27+
If you need help with anything related to Scala.js, you may find our community [in `#scala-js` on Discord](https://discord.com/invite/scala) and [on Stack Overflow](https://stackoverflow.com/questions/tagged/scala.js).
28+
29+
Bug reports can be filed [on GitHub](https://github.com/scala-js/scala-js/issues).
30+
31+
## Release notes
32+
33+
If upgrading from Scala.js 0.6.x, make sure to read [the release notes of Scala.js 1.0.0]({{ BASE_PATH }}/news/2020/02/25/announcing-scalajs-1.0.0/) first, as they contain a host of important information, including breaking changes.
34+
35+
This is a **minor** release, compared to 1.19.0:
36+
37+
* It is backward binary compatible with all earlier versions in the 1.x series: libraries compiled with 1.0.x through 1.19.x can be used with 1.20.x without change.
38+
* It is *not* forward binary compatible with 1.19.x: libraries compiled with 1.20.x cannot be used with 1.19.x or earlier.
39+
* It is *not* entirely backward source compatible: it is not guaranteed that a codebase will compile *as is* when upgrading from 1.19.x (in particular in the presence of `-Xfatal-warnings`).
40+
41+
As a reminder, libraries compiled with 0.6.x cannot be used with Scala.js 1.x; they must be republished with 1.x first.
42+
43+
## Changes with compatibility concerns
44+
45+
### Drop the `performance.webkitNow` fallback of `System.nanoTime()`
46+
47+
`System.nanoTime()` normally uses the JavaScript API `performance.now()` under the hood if it is available, and `Date.now()` otherwise.
48+
Until Scala.js 1.19.0, it also used `performance.webkitNow()` as possible fallback.
49+
Since browsers supporting `webkitNow()` have been supporting the official `performance.now()` method for more than 10 years now, we have dropped that fallback.
50+
51+
This changed allowed to improve the run-time performance of `System.nanoTime()`.
52+
It may degrade its precision on the old browsers that supported `webkitNow()` but not `now()`.
53+
54+
## Enhancements
55+
56+
### Link-time conditional branching
57+
58+
Thanks to our optimizer's ability to inline, constant-fold, and then eliminate dead code, we have been able to write link-time conditional branches for a long time.
59+
Typical examples include polyfills, as illustrated in the documentation of [`scala.scalajs.LinkingInfo`]({{ BASE_PATH }}/api/scalajs-library/1.20.1/scala/scalajs/LinkingInfo$.html#esVersion:Int):
60+
61+
{% highlight scala %}
62+
if (esVersion >= ESVersion.ES2018 || featureTest())
63+
useES2018Feature()
64+
else
65+
usePolyfill()
66+
{% endhighlight %}
67+
68+
which gets folded away to nothing but
69+
70+
{% highlight scala %}
71+
useES2018Feature()
72+
{% endhighlight %}
73+
74+
when optimizing for ES2018+.
75+
76+
However, this only works because both branches can *link* during the initial reachability analysis. We cannot use the same technique when one of the branches would refuse to link in the first place.
77+
The canonical example is the usage of the JS `**` operator, which does not link below ES2016. The following snippet produces good code when linking for ES2016+, but does not link at all for ES2015:
78+
79+
{% highlight scala %}
80+
def pow(x: Double, y: Double): Double = {
81+
if (esVersion >= ESVersion.ES2016) {
82+
(x.asInstanceOf[js.Dynamic] ** y.asInstanceOf[js.Dynamic]) // does not link!
83+
.asInstanceOf[Double]
84+
} else {
85+
Math.pow(x, y)
86+
}
87+
}
88+
{% endhighlight %}
89+
90+
Scala.js 1.20.1 introduces `scala.scalajs.LinkingInfo.linkTimeIf`, a conditional branch that is *guaranteed* by spec to be resolved at link-time.
91+
Using a `linkTimeIf` instead of the `if` in `def pow`, we can successfully link the fallback branch on ES2015, avoiding the linking issue in the then branch.
92+
93+
{% highlight scala %}
94+
import scala.scalajs.LinkingInfo.linkTimeIf
95+
96+
def pow(x: Double, y: Double): Double = {
97+
linkTimeIf(esVersion >= ESVersion.ES2016) {
98+
// this branch is only *linked* if we are targeting ES2016+
99+
(x.asInstanceOf[js.Dynamic] ** y.asInstanceOf[js.Dynamic])
100+
.asInstanceOf[Double]
101+
} {
102+
Math.pow(x, y)
103+
}
104+
}
105+
{% endhighlight %}
106+
107+
The condition of `linkTimeIf` must be a link-time constant expression.
108+
It can only contain:
109+
110+
* int and boolean literals and constants,
111+
* boolean operators (`!`, `&&` and `||`),
112+
* int comparison operators (such as `==` and `<`),
113+
* link-time properties in the `LinkingInfo` object, notably `esVersion`, `productionMode` and `isWebAssembly`.
114+
115+
### Performance improvements
116+
117+
Scala.js 1.20.1 brings a number of performance improvements compared to 1.19.0.
118+
119+
For both JavaScript and WebAssembly:
120+
121+
* Many low-level methods in `java.lang.Integer`, `Long`, `Float`, `Double`, `Math` and `System` have been micro-optimized.
122+
* Scala `Range`s have a faster initialization path (this particular enhancement is also coming in Scala 2.13.17 for the JVM).
123+
124+
For JavaScript:
125+
126+
* `Long` performance was significantly enhanced, notably additive operations, conversions to strings and conversions to floating-point numbers.
127+
128+
For WebAssembly, performance improvements in the following areas:
129+
130+
* Varargs, when compiled with Scala.js 1.20.0+ on Scala 2, and with the upcoming Scala 3.8.0+ on Scala 3
131+
* `java.util.ArrayList`, `ArrayDeque`, `PriorityQueue` and `java.util.concurrent.CopyOnWriteArrayList`
132+
* `java.util.RedBlackTree.fromOrdered`
133+
* Startup time in the presence of large arrays of constants
134+
* Generally, fewer hops across the Wasm-JS boundary
135+
136+
## Miscellaneous
137+
138+
### New JDK APIs
139+
140+
This release adds support for the following JDK methods:
141+
142+
* In `java.lang.Math`:
143+
* `multiplyFull`
144+
* `multiplyHigh`
145+
* `unsignedMultiplyHigh`
146+
* In `java.lang.Double`:
147+
* `doubleToRawLongBits`
148+
* In `java.lang.Float`:
149+
* `floatToRawIntBits`
150+
* In `java.lang.Integer` and `java.lang.Long`:
151+
* `compress`
152+
* `expand`
153+
154+
### Improved debugging experience on Wasm
155+
156+
The Wasm backend now emits more debugging information: the names of types, object fields, local variables and global variables.
157+
This improves the debugging experience when targeting WebAssembly.
158+
159+
## Bug fixes
160+
161+
The following bugs have been fixed in 1.20.0 and 1.20.1:
162+
163+
* [#5159](https://github.com/scala-js/scala-js/issues/5159) Regression in v1.19.0: `AssertionError` with module splitting on and optimizer off.
164+
* [#5165](https://github.com/scala-js/scala-js/issues/5165) Wasm: `try..finally` with non-nullable reference type produces invalid code.
165+
* [#5208](https://github.com/scala-js/scala-js/issues/5208) `doubleToLongBits` can observe non-canonical NaN bit patterns.
166+
* [#5231](https://github.com/scala-js/scala-js/issues/5231) `AssertionError`: rolled-back RuntimeLong inlining (regression in 1.20.0).
167+
168+
You can find the full list [on GitHub](https://github.com/scala-js/scala-js/issues?q=is%3Aissue+milestone%3Av1.20.0+is%3Aclosed).

assets/badges/scalajs-1.20.0.svg

Lines changed: 1 addition & 0 deletions
Loading

doc/all-api.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,16 @@ title: All previous versions of the Scala.js API
55

66
## All previous versions of the API
77

8+
### Scala.js 1.20.1
9+
* [1.20.1 scalajs-library]({{ site.production_url }}/api/scalajs-library/1.20.1/scala/scalajs/js/index.html)
10+
* [1.20.1 scalajs-test-interface]({{ site.production_url }}/api/scalajs-test-interface/1.20.1/)
11+
* [1.20.1 scalajs-javalib-intf]({{ site.production_url }}/api/scalajs-javalib-intf/1.20.1/)
12+
* [1.20.1 scalajs-ir]({{ site.production_url }}/api/scalajs-ir/1.20.1/org/scalajs/ir/index.html)
13+
* [1.20.1 scalajs-linker-interface]({{ site.production_url }}/api/scalajs-linker-interface/1.20.1/org/scalajs/linker/interface/index.html) ([Scala.js version]({{ site.production_url }}/api/scalajs-linker-interface-js/1.20.1/org/scalajs/linker/interface/index.html))
14+
* [1.20.1 scalajs-linker]({{ site.production_url }}/api/scalajs-linker/1.20.1/org/scalajs/linker/index.html) ([Scala.js version]({{ site.production_url }}/api/scalajs-linker-js/1.20.1/org/scalajs/linker/index.html))
15+
* [1.20.1 scalajs-test-adapter]({{ site.production_url }}/api/scalajs-sbt-test-adapter/1.20.1/org/scalajs/testing/adapter/index.html)
16+
* [1.20.1 sbt-scalajs]({{ site.production_url }}/api/sbt-scalajs/1.20.1/#org.scalajs.sbtplugin.package)
17+
818
### Scala.js 1.19.0
919
* [1.19.0 scalajs-library]({{ site.production_url }}/api/scalajs-library/1.19.0/scala/scalajs/js/index.html)
1020
* [1.19.0 scalajs-test-interface]({{ site.production_url }}/api/scalajs-test-interface/1.19.0/)

doc/internals/version-history.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ title: Version history
55

66
## Version history of Scala.js
77

8+
- [1.20.1](/news/2025/09/06/announcing-scalajs-1.20.1/)
9+
- ~~1.20.0~~ ([severely broken](https://github.com/scala-js/scala-js/issues/5231) and therefore never announced)
810
- [1.19.0](/news/2025/04/21/announcing-scalajs-1.19.0/)
911
- [1.18.2](/news/2025/01/23/announcing-scalajs-1.18.2/)
1012
- [1.18.1](/news/2025/01/09/announcing-scalajs-1.18.1/)

doc/project/webassembly.md

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ The Wasm backend emits code with the following requirements:
3232
* Exception handling, including the latest `exnref`-based variant
3333
* The `ESModule` module kind (see [emitting modules](./module.html))
3434

35-
Supported engines include Node.js 23, Chrome, Firefox and Safari.
36-
Node.js and Chrome currently require using some experimental flags (see below).
35+
Supported engines include Node.js 23, Chrome 137, Firefox 131 and Safari 18.4.
36+
Node.js currently requires using some experimental flags (see below).
3737

3838
## Language semantics
3939

@@ -102,9 +102,7 @@ As mentioned above, Node.js 23 and above requires the following flags:
102102

103103
### Chrome
104104

105-
In `chrome://flags/`, enable ["Experimental WebAssembly"](chrome://flags/#enable-experimental-webassembly-features).
106-
107-
For `js.async`/`js.await` support, also enable ["Experimental WebAssembly JavaScript Promise Integration (JSPI)"](chrome://flags/#enable-experimental-webassembly-jspi).
105+
Chrome supports all the features we use since v137.
108106

109107
### Firefox
110108

@@ -123,7 +121,7 @@ Safari supports all the "always required" features since v18.4.
123121

124122
If the performance of your application depends a lot on JavaScript interop, the Wasm output may be (significantly) slower than the JS output.
125123

126-
For applications whose performance is dominated by computions inside Scala code, the Wasm output should be significantly faster than the JS output (geomean 15% lower run time across our benchmarks).
124+
For applications whose performance is dominated by computions inside Scala code, the Wasm output should be significantly faster than the JS output (geomean 30% lower run time across our benchmarks).
127125

128126
Further work on improving performance is ongoing.
129127
Keep in mind that performance work on the Wasm backend is a few months old, compared to a decade of optimizations in the JS backend.

0 commit comments

Comments
 (0)