Skip to content

Commit 25eddca

Browse files
authored
Merge pull request #571 from sjrd/scalajs-1.10.0
Announcing Scala.js 1.10.0.
2 parents 79f4fc0 + 813180a commit 25eddca

File tree

5 files changed

+164
-3
lines changed

5 files changed

+164
-3
lines changed

_config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ colors: #in hex code if not noted else
6464

6565
### VERSIONS ###
6666
versions:
67-
scalaJS: 1.9.0
67+
scalaJS: 1.10.0
6868
scalaJSBinary: 1
6969
scalaJS06x: 0.6.33
7070
scalaJS06xBinary: 0.6
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
---
2+
layout: post
3+
title: Announcing Scala.js 1.10.0
4+
category: news
5+
tags: [releases]
6+
permalink: /news/2022/04/04/announcing-scalajs-1.10.0/
7+
---
8+
9+
10+
We are pleased to announce the release of Scala.js 1.10.0!
11+
12+
**This release addresses a security vulnerability in `java.util.UUID.randomUUID()`.**
13+
All versions of Scala.js prior to 1.10.0 are affected, including all 0.6.x versions.
14+
We strongly recommend that all users upgrade to Scala.js 1.10.0 as soon as possible.
15+
Read [the security advisory](https://github.com/scala-js/scala-js/security/advisories/GHSA-j2f9-w8wh-9ww4) for more details.
16+
The issue was registered as [CVE-2022-28355](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-28355).
17+
18+
This release also brings a new mode of module splitting, which creates the smallest possible modules for a given list of packages, and the fewest possible modules for the rest.
19+
20+
Finally, it contains some minor optimizations, notably contributed by [@japgolly](https://github.com/japgolly).
21+
22+
Read on for more details.
23+
24+
<!--more-->
25+
26+
## Getting started
27+
28+
If you are new to Scala.js, head over to [the tutorial]({{ BASE_PATH }}/tutorial/).
29+
30+
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).
31+
32+
Bug reports can be filed [on GitHub](https://github.com/scala-js/scala-js/issues).
33+
34+
## Release notes
35+
36+
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.
37+
38+
This is a **minor** release:
39+
40+
* It is backward binary compatible with all earlier versions in the 1.x series: libraries compiled with 1.0.x through 1.9.x can be used with 1.10.0 without change.
41+
* Despite being a minor release, 1.10.0 is forward binary compatible with 1.8.x and 1.9.x. It is *not* forward binary compatible with 1.7.x. Libraries compiled with 1.10.0 can be used with 1.8.x and 1.9.x but not with 1.7.x or earlier.
42+
* It is *not* entirely backward source compatible: it is not guaranteed that a codebase will compile *as is* when upgrading from 1.9.x (in particular in the presence of `-Xfatal-warnings`).
43+
44+
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.
45+
46+
## Fixes with compatibility concerns
47+
48+
### `java.util.UUID.randomUUID()` now depends on `java.security.SecureRandom`, which is provided by external libraries
49+
50+
Until Scala.js 1.9.x, `java.util.UUID.randomUUID()` was implemented using `java.util.Random`, which is not cryptographically secure.
51+
This is therefore a security issue concerning `randomUUID()`.
52+
To address that, Scala.js 1.10.x uses `java.security.SecureRandom` in the implementation of the latter instead.
53+
`java.util.Random` remains unchanged, since it correctly implements its (deterministic) specification.
54+
55+
However, `SecureRandom` cannot be implemented on all JavaScript environments, as ECMAScript, per se, lacks any primitive to access a good source of entropy.
56+
While it can be implemented on top of browser APIs or Node.js APIs, we have no decent fallback for other cases.
57+
Not fully implementing it correctly for all platforms would go against our policy for the standard library, i.e., that linking code must be correct.
58+
Therefore, Scala.js core does not provide any implementation of `java.security.SecureRandom`.
59+
60+
This means that code that was previously calling `java.util.UUID.randomUUID()` will now fail to link.
61+
To preserve binary compatibility, we introduce two variants of a library that provides `java.security.SecureRandom`:
62+
63+
* [`scalajs-java-securerandom`](https://github.com/scala-js/scala-js-java-securerandom) provides a *correct*, cryptographically secure implementation of `java.security.SecureRandom`, but relies on the Node.js `crypto` module or the Web Crypto API `crypto.getRandomValues` to be available (e.g., in browsers).
64+
* [`scalajs-fake-insecure-securerandom`](https://github.com/scala-js/scala-js-fake-insecure-securerandom) is a fake, *insecure* implementation that works in any ECMAScript environment. The only reason this exists is to unblock migration from Scala.js 1.9.x and earlier, in situations that require `randomUUID()` and can accept that they will be insecure.
65+
66+
Due to the changes in the core library, you may encounter linking errors when upgrading to Scala.js 1.10.0, such as:
67+
68+
{% highlight text %}
69+
[error] Referring to non-existent class java.security.SecureRandom
70+
[error] called from private java.util.UUID$.csprng$lzycompute()java.util.Random
71+
[error] called from private java.util.UUID$.csprng()java.util.Random
72+
[error] called from java.util.UUID$.randomUUID()java.util.UUID
73+
[error] called from static java.util.UUID.randomUUID()java.util.UUID
74+
[error] called from helloworld.HelloWorld$.main([java.lang.String)void
75+
[error] called from static helloworld.HelloWorld.main([java.lang.String)void
76+
[error] called from core module module initializers
77+
[error] involving instantiated classes:
78+
[error] java.util.UUID$
79+
[error] helloworld.HelloWorld$
80+
{% endhighlight %}
81+
82+
You may fix these linking errors by adding the following dependency to your `libraryDependencies`:
83+
84+
{% highlight scala %}
85+
"org.scala-js" %%% "scalajs-java-securerandom" % "1.0.0"
86+
{% endhighlight %}
87+
88+
As mentioned above, this will only work in environments that either provide the Web Crypto API, or Node.js' `crypto` module.
89+
90+
If you need random UUID generation in other environments, we encourage you to implement it yourselves.
91+
Find out if your environment provides a source of cryptographically secure pseudo-random numbers.
92+
If it does, you may want to use it to shim `crypto.getRandomValues`, and/or send a pull request to [`scalajs-java-securerandom`](https://github.com/scala-js/scala-js-java-securerandom).
93+
Otherwise, replace calls to `randomUUID()` with another implementation, in a way that corresponds to your requirements in terms of security and collision likelihood.
94+
95+
If you have **no other choice**, depend on `scalajs-fake-insecure-securerandom` instead.
96+
As its name implies, this is an *insecure* implementation, and you should get rid of this dependency as soon as possible.
97+
98+
## New module split style: `SmallModulesFor(packages)`
99+
100+
Prior to 1.10.0, Scala.js had two opposite module split styles:
101+
102+
* `FewestModules` (the default), which generates as few modules as possible, and
103+
* `SmallestModules`, which generates as many small modules as possible (up to one per class).
104+
105+
As detailed in [#4327](https://github.com/scala-js/scala-js/issues/4327), those two extremes both suffered from issues for iterative development.
106+
107+
Scala.js 1.10.0 introduces a third style, `ModuleSplitStyle.SmallModulesFor(packages: List[String])`.
108+
That style creates as many small modules as possibles for the classes in the listed packages (and their subpackages).
109+
For all other classes, it generates as few modules as possible.
110+
It is a combination of the previously existing styles.
111+
112+
The typical usage pattern is to list the application's packages as argument.
113+
This way, often-changing classes receive independent, small modules, while the stable classes coming from libraries are bundled together as much as possible.
114+
For example, if your application code lives in `com.example.myapp`, you could configure your module split style as:
115+
116+
{% highlight scala %}
117+
import org.scalajs.linker.interface.ModuleSplitStyle
118+
scalaJSLinkerConfig ~= (_.withModuleSplitStyle(ModuleSplitStyle.SmallModulesFor(List("com.example.myapp"))))
119+
{% endhighlight %}
120+
121+
## Miscellaneous
122+
123+
### Optimizations
124+
125+
Scala.js 1.10.0 brings some new optimizations to the produced JavaScript files:
126+
127+
* Closures that do not need to capture anything produce simple lambdas, instead of redundant IIFEs (Immediately Invoked Function Expressions); contributed by [@japgolly](https://github.com/japgolly)
128+
* `js.dynamicImport` blocks that do nothing but access a native JS class, object or member from a JS module avoid creating an intermediate Scala.js-generated module; instead they directly refer to the target JS module in the generated dynamic `import()` call.
129+
130+
## Bug fixes
131+
132+
Among others, the following bugs have been fixed in 1.10.0:
133+
134+
* [#4657](https://github.com/scala-js/scala-js/issues/4657) Scala.js should not provide a cryptographically insecure `UUID.randomUUID()` implementation
135+
136+
You can find the full list [on GitHub](https://github.com/scala-js/scala-js/issues?q=is%3Aissue+milestone%3Av1.10.0+is%3Aclosed).

doc/all-api.md

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

66
## All previous versions of the API
77

8+
### Scala.js 1.10.0
9+
* [1.10.0 scalajs-library]({{ site.production_url }}/api/scalajs-library/1.10.0/scala/scalajs/js/index.html)
10+
* [1.10.0 scalajs-test-interface]({{ site.production_url }}/api/scalajs-test-interface/1.10.0/)
11+
* [1.10.0 scalajs-ir]({{ site.production_url }}/api/scalajs-ir/1.10.0/org/scalajs/ir/index.html)
12+
* [1.10.0 scalajs-linker-interface]({{ site.production_url }}/api/scalajs-linker-interface/1.10.0/org/scalajs/linker/interface/index.html) ([Scala.js version]({{ site.production_url }}/api/scalajs-linker-interface-js/1.10.0/org/scalajs/linker/interface/index.html))
13+
* [1.10.0 scalajs-linker]({{ site.production_url }}/api/scalajs-linker/1.10.0/org/scalajs/linker/index.html) ([Scala.js version]({{ site.production_url }}/api/scalajs-linker-js/1.10.0/org/scalajs/linker/index.html))
14+
* [1.10.0 scalajs-test-adapter]({{ site.production_url }}/api/scalajs-sbt-test-adapter/1.10.0/org/scalajs/testing/adapter/index.html)
15+
* [1.10.0 sbt-scalajs]({{ site.production_url }}/api/sbt-scalajs/1.10.0/#org.scalajs.sbtplugin.package)
16+
817
### Scala.js 1.9.0
918
* [1.9.0 scalajs-library]({{ site.production_url }}/api/scalajs-library/1.9.0/scala/scalajs/js/index.html)
1019
* [1.9.0 scalajs-test-interface]({{ site.production_url }}/api/scalajs-test-interface/1.9.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.10.0](/news/2022/04/04/announcing-scalajs-1.10.0/)
89
- [1.9.0](/news/2022/02/14/announcing-scalajs-1.9.0/)
910
- [1.8.0](/news/2021/12/10/announcing-scalajs-1.8.0/)
1011
- [1.7.1](/news/2021/10/07/announcing-scalajs-1.7.1/)

doc/project/module.md

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ The Scala.js linker can split a full Scala.js application automatically based on
9292

9393
* Entry points (top-level exports and module initializers)
9494
* Dynamic import boundaries (calls to `js.dynamicImport`)
95-
* The split style (fewest modules or smallest modules)
95+
* The split style (fewest modules, smallest modules, or a combination thereof)
9696

9797
### Entry Points
9898

@@ -224,7 +224,7 @@ import org.scalajs.linker.interface.ModuleSplitStyle
224224
scalaJSLinkerConfig ~= (_.withModuleSplitStyle(ModuleSplitStyle.SmallestModules))
225225
{% endhighlight %}
226226

227-
There are currently two module split styles: `FewestModules` and `SmallestModules`.
227+
There are currently three module split styles: `FewestModules`, `SmallestModules` and `SmallModulesFor(packages)`.
228228

229229
#### `FewestModules`
230230

@@ -264,6 +264,21 @@ In the dynamic import example, this would generate:
264264
Generating many small modules can be useful if the output of Scala.js is further processed by downstream JavaScript bundling tools.
265265
In incremental builds, they will not need to reprocess the entire Scala.js-generated .js file, but instead only the small modules that have changed.
266266

267+
#### `SmallModulesFor(packages: List[String])`
268+
269+
Create modules that are as small as possible for the classes in the specified `packages` (and their subpackages).
270+
For all other classes, create as few modules as possible.
271+
This is a combination of the two other split styles.
272+
273+
The typical usage pattern is to list the application's packages as argument.
274+
This way, often-changing classes receive independent, small modules, while the stable classes coming from libraries are bundled together as much as possible.
275+
For example, if your application code lives in `my.app`, you could configure your module split style as:
276+
277+
{% highlight scala %}
278+
import org.scalajs.linker.interface.ModuleSplitStyle
279+
scalaJSLinkerConfig ~= (_.withModuleSplitStyle(ModuleSplitStyle.SmallModulesFor(List("my.app"))))
280+
{% endhighlight %}
281+
267282
### Splitting Granularity
268283

269284
Scala.js only splits modules along class boundaries.

0 commit comments

Comments
 (0)