Skip to content

Commit 73742a1

Browse files
committed
Announcing Scala.js 1.20.0.
1 parent fc4f6e3 commit 73742a1

File tree

7 files changed

+164
-8
lines changed

7 files changed

+164
-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.0
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: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
---
2+
layout: post
3+
title: Announcing Scala.js 1.20.0
4+
category: news
5+
tags: [releases]
6+
permalink: /news/2025/09/05/announcing-scalajs-1.20.0/
7+
---
8+
9+
10+
We are pleased to announce the release of Scala.js 1.20.0!
11+
12+
This release mainly comes with many performance improvements to the WebAssembly and JavaScript backends alike.
13+
14+
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.
15+
16+
Read on for more details.
17+
18+
<!--more-->
19+
20+
## Getting started
21+
22+
If you are new to Scala.js, head over to [the tutorial]({{ BASE_PATH }}/tutorial/).
23+
24+
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).
25+
26+
Bug reports can be filed [on GitHub](https://github.com/scala-js/scala-js/issues).
27+
28+
## Release notes
29+
30+
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.
31+
32+
This is a **minor** release:
33+
34+
* 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.0 without change.
35+
* It is *not* forward binary compatible with 1.19.x: libraries compiled with 1.20.0 cannot be used with 1.19.x or earlier.
36+
* 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`).
37+
38+
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.
39+
40+
## Enhancements
41+
42+
### Link-time conditional branching
43+
44+
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.
45+
Typical examples include polyfills, as illustrated in the documentation of [`scala.scalajs.LinkingInfo`](https://javadoc.io/static/org.scala-js/scalajs-library_2.13/1.19.0/scala/scalajs/LinkingInfo$.html#esVersion:Int):
46+
47+
{% highlight scala %}
48+
if (esVersion >= ESVersion.ES2018 || featureTest())
49+
useES2018Feature()
50+
else
51+
usePolyfill()
52+
{% endhighlight %}
53+
54+
which gets folded away to nothing but
55+
56+
{% highlight scala %}
57+
useES2018Feature()
58+
{% endhighlight %}
59+
60+
when optimizing for ES2018+.
61+
62+
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.
63+
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:
64+
65+
{% highlight scala %}
66+
def pow(x: Double, y: Double): Double = {
67+
if (esVersion >= ESVersion.ES2016) {
68+
(x.asInstanceOf[js.Dynamic] ** y.asInstanceOf[js.Dynamic]) // does not link!
69+
.asInstanceOf[Double]
70+
} {
71+
Math.pow(x, y)
72+
}
73+
}
74+
{% endhighlight %}
75+
76+
Scala.js 1.20.0 introduces `scala.scalajs.LinkingInfo.linkTimeIf`, a conditional branch that is *guaranteed* by spec to be resolved at link-time.
77+
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.
78+
79+
{% highlight scala %}
80+
import scala.scalajs.LinkingInfo.linkTimeIf
81+
82+
def pow(x: Double, y: Double): Double = {
83+
linkTimeIf(esVersion >= ESVersion.ES2016) {
84+
// this branch is only *linked* if we are targeting ES2016+
85+
(x.asInstanceOf[js.Dynamic] ** y.asInstanceOf[js.Dynamic])
86+
.asInstanceOf[Double]
87+
} {
88+
Math.pow(x, y)
89+
}
90+
}
91+
{% endhighlight %}
92+
93+
The condition of `linkTimeIf` must be a link-time constant expression.
94+
It can only contain:
95+
96+
* int and boolean literals and constants,
97+
* boolean operators (`!`, `&&` and `||`),
98+
* int comparison operators (such as `==` and `<`),
99+
* link-time properties in the `LinkingInfo` object, notably `esVersion`, `productionMode` and `isWebAssembly`.
100+
101+
### Performance improvements
102+
103+
Scala.js 1.20.0 brings a number of performance improvements.
104+
105+
For both JavaScript and WebAssembly:
106+
107+
* Many low-level methods in `java.lang.Integer`, `Long`, `Float`, `Double`, `Math` and `System` have been micro-optimized.
108+
* Scala `Range`s have a faster initialization path (this particular enhancement is also coming in Scala 2.13.17 for the JVM).
109+
110+
For JavaScript:
111+
112+
* `Long` performance was significantly enhanced, notably additive operations, conversions to strings and conversions to floating-point numbers.
113+
114+
For WebAssembly, performance improvements in the following areas:
115+
116+
* Varargs, when compiled with Scala.js 1.20.0+ on Scala 2, and with the upcoming Scala 3.8.0+ on Scala 3
117+
* `java.util.ArrayList`, `ArrayDeque`, `PriorityQueue` and `java.util.concurrent.CopyOnWriteArrayList`
118+
119+
## Miscellaneous
120+
121+
### New JDK APIs
122+
123+
This release adds support for the following JDK methods:
124+
125+
* In `java.lang.Math`:
126+
* `multiplyFull`
127+
* `multiplyHigh`
128+
* `unsignedMultiplyHigh`
129+
* In `java.lang.Double`:
130+
* `doubleToRawLongBits`
131+
* In `java.lang.Float`:
132+
* `floatToRawIntBits`
133+
* In `java.lang.Integer` and `java.lang.Long`:
134+
* `compress`
135+
* `expand`
136+
137+
## Bug fixes
138+
139+
The following bugs have been fixed in 1.20.0:
140+
141+
* [#5159](https://github.com/scala-js/scala-js/issues/5159) Regression in v1.19.0: `AssertionError` with module splitting on and optimizer off.
142+
* [#5165](https://github.com/scala-js/scala-js/issues/5165) Wasm: `try..finally` with non-nullable reference type produces invalid code.
143+
* [#5208](https://github.com/scala-js/scala-js/issues/5208) `doubleToLongBits` can observe non-canonical NaN bit patterns.
144+
145+
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.0
9+
* [1.20.0 scalajs-library]({{ site.production_url }}/api/scalajs-library/1.20.0/scala/scalajs/js/index.html)
10+
* [1.20.0 scalajs-test-interface]({{ site.production_url }}/api/scalajs-test-interface/1.20.0/)
11+
* [1.20.0 scalajs-javalib-intf]({{ site.production_url }}/api/scalajs-javalib-intf/1.20.0/)
12+
* [1.20.0 scalajs-ir]({{ site.production_url }}/api/scalajs-ir/1.20.0/org/scalajs/ir/index.html)
13+
* [1.20.0 scalajs-linker-interface]({{ site.production_url }}/api/scalajs-linker-interface/1.20.0/org/scalajs/linker/interface/index.html) ([Scala.js version]({{ site.production_url }}/api/scalajs-linker-interface-js/1.20.0/org/scalajs/linker/interface/index.html))
14+
* [1.20.0 scalajs-linker]({{ site.production_url }}/api/scalajs-linker/1.20.0/org/scalajs/linker/index.html) ([Scala.js version]({{ site.production_url }}/api/scalajs-linker-js/1.20.0/org/scalajs/linker/index.html))
15+
* [1.20.0 scalajs-test-adapter]({{ site.production_url }}/api/scalajs-sbt-test-adapter/1.20.0/org/scalajs/testing/adapter/index.html)
16+
* [1.20.0 sbt-scalajs]({{ site.production_url }}/api/sbt-scalajs/1.20.0/#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: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ title: Version history
55

66
## Version history of Scala.js
77

8+
- [1.20.0](/news/2025/09/05/announcing-scalajs-1.20.0/)
89
- [1.19.0](/news/2025/04/21/announcing-scalajs-1.19.0/)
910
- [1.18.2](/news/2025/01/23/announcing-scalajs-1.18.2/)
1011
- [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+
Firefox 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)