Announcing Scala.js 0.6.0
Announcing Scala.js 0.6.0
Feb 5, 2015.
We are thrilled to announce the final release of Scala.js 0.6.0!
As of this version, we do not consider Scala.js to be experimental anymore. We believe it has reached maturity, and from now on, the language semantics as well as the APIs will only evolve in backward compatible ways, or go through proper deprecation cycles.
Today is also the 2-year anniversary of Scala.js! The first commit was pushed on February 5, 2013.
If you are new to Scala.js, head over to the tutorial.
As the change in “major” version number witnesses, this release is not binary compatible with 0.5.x. Libraries need to be recompiled and republished using 0.6.0 to be compatible. More importantly, this release is not source compatible with 0.5.x either.
Please report any issues on GitHub.
The following libraries have already been upgraded and published for 0.6.0:
- DOM types:
"org.scala-js" %%% "scalajs-dom" % "0.7.0"
- jQuery types:
"be.doeraene" %%% "scalajs-jquery" % "0.7.0"
"com.lihaoyi" %%% "scalarx" % "0.2.7"
"com.lihaoyi" %%% "upickle" % "0.2.6"
"com.lihaoyi" %%% "autowire" % "0.2.4"
"biz.enef" %%% "scalajs-angulate" % "0.1"
"com.greencatsoft" %%% "scalajs-angular" % "0.3"
"com.github.japgolly.fork.scalaz" %%% "scalaz-core" % "7.1.0-4"(plus other modules + version 7.1.1)
"com.github.japgolly.fork.monocle" %%% "monocle-core" % "1.0.1"(plus other modules)
"com.github.japgolly.fork.nicta" %%% "rng" % "1.3.0"
"com.github.japgolly.fork.shapeless" %%% "shapeless" % "2.0.0"
"com.github.japgolly.scalajs-react" %%% "core" % "0.7.2"(plus other modules)
"com.github.japgolly.nyaya" %%% "nyaya-core" % "0.5.2"
The following testing frameworks are available:
"com.lihaoyi" %%% "utest" % "0.3.0" % "test"
"org.monifu" %%% "minitest" % "0.11" % "test"
"com.greencatsoft" %%% "greenlight" % "0.1-SNAPSHOT" % "test"
"com.github.inthenow" %%% "scalacheck" % "1.12.2" % "test"
"com.github.inthenow" %%% "zcheck" % "0.6.0" % "test"
And the following helper sbt plugins as well:
addSbtPlugin("com.lihaoyi" % "workbench" % "0.2.3")
- @InTheNow’s sbt-scalajs:
addSbtPlugin("com.github.inthenow" % "sbt-scalajs" % "0.6.0")
There is also a new–and incompatible–version of the DOM API. We recommend that you first upgrade to 0.7.0 and the above libraries while upgrading to Scala.js 0.6.0. As a second step, you can upgrade to the DOM API version 0.8.0. Libraries depending on the DOM API must also be republished against this version of the DOM API, since it is by and large incompatible with 0.7.0. Here are the 0.8.0 versions of said libraries:
- DOM types:
"org.scala-js" %%% "scalajs-dom" % "0.8.0"
- jQuery types:
"be.doeraene" %%% "scalajs-jquery" % "0.8.0"
"com.lihaoyi" %%% "scalatags" % "0.4.5"
- scalajs-angulate and scalajs-angular: not yet published
"com.github.japgolly.scalajs-react" %%% "core" % "0.8.0"(plus other modules)
To start a Play! project with Scala.js, have a look at play-with-scalajs-example.
Preparations before upgrading from 0.5.x
Upgrade to 0.5.6 if not already done
Before upgrading to 0.6.0, we strongly recommend that you upgrade to Scala.js 0.5.6, and address all deprecation warnings. Scala.js 0.5.6 contains warnings for the most vicious breaking changes of 0.6.x.
Migrate away from the Scala.js Jasmine test framework
If you use the Jasmine test framework wrapper for Scala.js (
scalajs-jasmine-test-framework), migrate away from it to one of the other testing frameworks for Scala.js.
The Jasmine test framework wrapper is not a good testing framework for Scala.js code, and is being removed in 0.6.x.
Note that these testing frameworks also need to upgrade to 0.6.0 before you can use them.
Upgrade to 0.6.0 from 0.5.6
Basically, you need to apply the same kind of changes to your build files as in this commit, which mostly consists in:
- Upgrade to sbt >= 0.13.7.
- Adaptations to new groupId and artifact names for Scala.js packages.
- Adaptation to the new
AutoPlugininfrastructure of the sbt plugin.
- Drop the prefix
ScalaJSKeys.for Scala.js-specific sbt keys.
- Upgrade to 0.6.0-enabled versions of your dependencies.
On the sbt command line, not much changes, except the way you use the
In Scala 0.5.x, you could run in the
fastOpt stage with:
In 0.6.x, the stage is regulated by the setting
scalaJSStage, which is one of:
PreLinkStage(default): uses Rhino
fastOptmode, uses Node.js or PhantomJS
fullOptmode, uses Node.js or PhantomJS
You can change it from the command line with
> set scalaJSStage := FastOptStage > run # runs in fastOpt mode
In a multi-project build, you’ll want to change it for all projects, which can be done with
> set scalaJSStage in Global := FastOptStage
This section discusses major changes affecting source compatibility, which may or may not apply to your project.
ClassCastException becomes an undefined behavior
The JVM, in its incommensurable magnanimity, throws nicely specified exceptions when you do something bad with your code.
For example, it will nicely throw a
ClassCastException if you perform an invalid
.asInstanceOf, or an
ArithmeticException if you divide an integer by 0.
Since the beginning of time, Scala.js has handled most of these things as undefined behavior, i.e., anything can happen if these cases happen.
ClassCastExceptions were properly reported, though.
We have found, however, that checking these buggy cases costs up to 100% overhead to the overall execution time of a Scala.js program.
In Scala.js 0.6.x, therefore, invalid casts become an undefined behavior as well.
However, the compiler will still be nice with you in the PreLink and FastOpt stages, by throwing an
UndefinedBehaviorError if you perform an invalid cast (instead of a
UndefinedBehaviorError is a fatal error, meaning it won’t be caught by
case NonFatal(e) handlers.
In fullOpt mode, the checks are removed for maximum efficiency.
You must not catch
UndefinedBehaviorError, since that would cause your program to behave differently in the fullOpt stage than in the other stages.
The idea of
UndefinedBehaviorError is that you can enjoy strict checks and stack traces while developing.
If you really want
ClassCastExceptions to be thrown reliably (in all stages), you can enable them in your application, at the expense of runtime performance, with the following sbt setting:
This applies to the entire application, including dependencies. There is no way to select parts of the application where this applies, because there is no way to make that sound.
scala.scalajs.js package has been simplified
We have removed a lot of historical warts from the
scala.scalajs.js package, mostly types and APIs with equivalents among normal Scala types and libraries:
js.Undefinedhave been removed, as well as their
Unitshould be used instead, respectively.
js.parseFloat(s)should be replaced by
js.Infinityshould be replaced by
js.isNaN(x)should be replaced by
js.isFinite(x)should be replaced by
!x.isNaN && !x.isInfinite.
Methods provided by ECMAScript 5.1 on primitive strings and numbers can be enabled by importing the following implicit conversions:
js.native in facade types
When writing facade types, it was previously recommended to use
??? as a fake body for fields and methods.
You should now use
js.native instead, as in:
The compiler will emit a warning if you use any other body. The warning will become an error in 1.0.0.
@JSExport exports to fully qualified names by default
As announced by deprecation warnings in the 0.5.6 compiler, putting
@JSExport without an explicit name on an
class changes meaning between 0.5.x and 0.6.x.
Consider this code:
Foo is exported as
In 0.6.x, it is exported as
Testing frameworks adaptations
If you are not a testing framework implementor, this section does not apply to you. Please follow the migration guidelines of any testing framework you may use.
Until 0.5.x, Scala.js had a custom, ad-hoc substitute for the sbt testing interface, which allows testing frameworks to integrate with sbt. Although quite good in its own right, it suffered from several limitations, including the inability for one project to use more than one testing framework at the same time, and severe discrepencies with the JVM sbt testing interface. Scala.js 0.6.x now supports its JS version of the original sbt testing interface, with all its power, API, and usability features. We also offer tools to make your testing framework fully source-compatible with the JVM and JS variants of the testing interface, without a single line of platform-specific source code.
An existing barebone cross-compiling testing framework can be found in our tests. Some highlights:
- Build definition for the cross-compiling framework
- (Cross-compiling) source code of the testing framework
- Build definition for a cross-compiling project using the framework
- Source code of the project using the framework
Adapting your testing framework to follow this structure is likely to be the easiest path of migration. You may also want to take a look at the PR we made to uTest to migrate to Scala.js 0.6.x.
Should you run into trouble, don’t hesitate to ask on the mailing list!
When writing cross-compiling code, we need to have two separate projects in sbt for the JVM target and the JS target.
CrossProject type, and its
crossProject builder, helps in defining these pairs of projects in a DRY way.
See the documentation of
CrossProject for more information and examples.
Scala.js 0.6.0 benefits from many performance improvements, most notably:
asInstanceOfs are unchecked (see above), giving
fullOptcode up to twice as fast as before
Range.foreach, aka the
for (i <- 0 until n)kind of loops, is inlined away, giving the same performance as an explicit
- Higher-order operations on
js.Dictionarys (such as
map, etc.) are inlined away as
- Various improvements to the optimizer.
Scala collection API for
The title says it all:
js.Dictionary[A] receive the entire Scala collection API, respectively of
js.Array becomes the default implementation of
mutable.Buffer.empty returns a
js.Array wrapped in a
A new object
Needless to say, these implicits should be handled with care, but they can come in handy.
On-demand strict floats
Float operations by default, saying that they can sometimes behave as if they were
In 0.6.x, you can configure your application to use strict-float semantics, guaranteeing that all
Float operations behave as on the JVM, with the appropriate truncation of precision (with the notable exception of
The following sbt setting enables this:
Beware that this can have a major impact on performance on VMs that do not support the
Obfuscation of class names
scalaJSSemantics option also allows to obfuscate or otherwise rename the class names in the emitted .js file, as was requested in #1113.
For example, this sbt setting empties out all class names in the package
This changes the value returned by
We publish to Maven Central
This should probably not affect sbt users, but it now becomes possible to imagine Maven and Gradle plugins for Scala.js. To this effect, the sbt plugin codebase has also been refactored, and all parts that are not strictly bound to sbt as a build tool have been extracted in Mavenized artifacts. An enthusiast Maven/Gradle user could therefore build a Maven/Gradle plugin with relatively few lines of code. As a measurable figure, the code specific to sbt contains only 1,686 lines of code.
Amongst others, the following bugs have been fixed since 0.5.6:
ClassTag.unapplymethod (for deconstruction) fails for raw JS classes
- #1423 String.getBytes returns trailing zeroes
- #1324 Date.parse should return a Double, not an Int
- #1349 Auto-completion in runMain task does not work
- #1192 hashCode for floating points has a very bad distribution
Traversersdoes not handle the case of
- #1451 ScalaDoc run crashes with property
- #1455 Runs for ScalaDoc complain about
- #1458 PhantomJS 2 expects a scheme name (
file:///) for all urls, not just a path to local files