From 33ac72be1f2104da0afa8922d02b763cb917e0c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Sun, 21 Dec 2014 18:26:59 +0100 Subject: [PATCH] Announcing Scala.js 0.6.0-M3. --- .../2014-12-22-announcing-scalajs-0.6.0-M3.md | 255 ++++++++++++++++++ doc/index.md | 10 + downloads.md | 6 + index.md | 1 + 4 files changed, 272 insertions(+) create mode 100644 _posts/news/2014-12-22-announcing-scalajs-0.6.0-M3.md diff --git a/_posts/news/2014-12-22-announcing-scalajs-0.6.0-M3.md b/_posts/news/2014-12-22-announcing-scalajs-0.6.0-M3.md new file mode 100644 index 00000000..ad882915 --- /dev/null +++ b/_posts/news/2014-12-22-announcing-scalajs-0.6.0-M3.md @@ -0,0 +1,255 @@ +--- +layout: post +title: Announcing Scala.js 0.6.0-M3 +category: news +tags: [releases] +--- +{% include JB/setup %} + +We are excited to announce the third milestone of Scala.js 0.6.0, aka 0.6.0-M3! +This release is mostly about the (hopefully) last binary incompatible changes for the 0.6.x series. +It also substantially reworks the `scala.scalajs.js` package to simplify it (see below for details). + +Scala.js 0.6.0-M3 is not forward nor backward binary compatible with M1/M2. +We expect that all subsequent milestones and RCs for 0.6.x will stay binary compatible with M3, though. + +To upgrade from 0.6.0-M1/M2, simply change the version number. +You might need to address some compilation errors regarding the `js` package, but it should be straightforward. +Should you encounter any trouble, do not hesitate to ask. + +The rest of this announcement is cumulative with the changes introduced in M1 and M2. + +This development release is mostly intended for testing purposes, and as a synchronization point with library authors so that they can start upgrading in preparation for the final release. + +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-M3 to be compatible. + +More importantly, this release is not source compatible with 0.5.x either. +We expect, however, that further milestones and 0.6.x will stay source compatible with this milestone. + +Please report any issues [on GitHub](https://github.com/scala-js/scala-js/issues). + +The following libraries and testing frameworks have already been upgraded and published for 0.6.0-M3: + +* [DOM types](https://github.com/scala-js/scala-js-dom): 0.7.0 +* [jQuery types](https://github.com/scala-js/scala-js-jquery): `"be.doeraene" %%% "scalajs-jquery" % "0.7.0"` +* [Scala.rx](https://github.com/lihaoyi/scala.rx): 0.2.7-M3 +* [ScalaTags](https://github.com/lihaoyi/scalatags): 0.4.3-M3 +* [Autowire](https://github.com/lihaoyi/autowire): 0.2.4-M3 +* [µPickle](https://github.com/lihaoyi/upickle): 0.2.6-M3 +* [µTest](https://github.com/lihaoyi/utest): 0.2.5-M3 +* [MiniTest](https://github.com/monifu/minitest): 0.6 + +**NOT DONE YET** + + +## Preparations before upgrading from 0.6.x + +### Upgrade to 0.5.6 if not already done + +Before upgrading to 0.6.0-M3, **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 Jasmine test framework + +If you use the Jasmine test framework, migrate away from it to one of the other testing frameworks for Scala.js. +The Jasmine test framework is *not* a good testing framework for Scala.js code, and is being *removed* in 0.6.x. + +Possible replacements: + +* [uTest](https://github.com/lihaoyi/utest) +* [Little Spec](https://github.com/eecolor/little-spec) +* [otest](https://github.com/cgta/otest) +* [MiniTest](https://github.com/monifu/minitest) + +Note that these testing frameworks also need to upgrade to 0.6.0-M3 before you can use them. +You might need to disable your testing infrastructure in the meantime, if you want to start using 0.6.0-M3 before they are ready. + +## Upgrade to 0.6.0-M3 from 0.5.6 + +Basically, you need to apply the same kind of changes to your build files as in [this commit](https://github.com/sjrd/scala-js-example-app/commit/11c56d9700eff3922fb98472ebcf5e9b19f18e1e), which mostly consists in: + +* Upgrade to sbt >= 0.13.6 (the current version is 0.13.7). +* Adaptations to new groupId and artifact names for Scala.js packages. +* Adaptation to the new `AutoPlugin` infrastructure of the sbt plugin. +* Drop the prefix `ScalaJSKeys.` for Scala.js-specific sbt keys, as they are not needed anymore. +* Upgrade to 0.6.0-M3-enabled versions of your dependencies. + +On the sbt command line, not much changes, except the way you use the `fastOpt` and `fullOpt` mode. +In Scala 0.5.x, you could run in `fastOpt` mode with: + + > fastOptStage::run + +In 0.6.x, the mode is regulated by the setting `scalaJSStage`, which is one of: + +* `PreLinkStage` (default): uses Rhino +* `FastOptStage`: `fastOpt` mode, uses Node.js or PhantomJS +* `FullOptStage`: `fullOpt` mode, 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 `in Global`: + + > set scalaJSStage in Global := FastOptStage + +## Major changes + +This section discusses major changes affecting 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. +Until 0.5.x, `ClassCastException`s 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 fastOpt mode*, by throwing an `UndefinedBehaviorError` if you perform an invalid cast (instead of a `ClassCastException`). +`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 fastOpt mode than in fullOpt. +The idea of `UndefinedBehaviorError` is that you can enjoy strict checks and stack traces while developing. + +If you really want `ClassCastException`s to be thrown reliably (both in fastOpt and fullOpt modes), you can enable them in your application, at the expense of runtime performance, with the following sbt setting: + +{% highlight scala %} +scalaJSSemantics ~= { _.withAsInstanceOfs(org.scalajs.core.tools.sem.CheckedBehavior.Compliant) } +{% endhighlight %} + +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 sensical. + +### The `scala.scalajs.js` 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.String`, `js.Boolean`, `js.Number` and `js.Undefined` have been removed, as well as their `js.prim.*` equivalent. + `String`, `Boolean`, `Double` and `Unit` should be used instead. +* `js.parseInt(s)` and `js.parseFloat(s)` should be replaced by `s.toInt` and `s.toDouble`. +* `js.NaN`, `js.Infinity` should be replaced by `Double.NaN` and `Double.PositiveInfinity`. +* `js.isNaN(x)` should be replaced by `x.isNaN`. +* `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: + +{% highlight scala %} +import js.JSStringOps._ +import js.JSNumberOps._ +{% endhighlight %} + +### `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: + +{% highlight scala %} +trait Foo extends js.Object { + var bar: Int = js.native + def foobar(x: Int): String = js.native +} +{% endhighlight %} + +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 `object` or `class` changes meaning between 0.5.x and 0.6.x. +Consider this code: + +{% highlight scala %} +package babar + +@JSExport +class Foo +{% endhighlight %} + +In 0.5.x, `Foo` is exported as `Foo`. +In 0.6.x, it is exported as `babar.Foo` instead. + +### 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. +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](https://github.com/scala-js/scala-js/tree/v0.6.0-M3/sbt-plugin-test). +Some highlights: + +* [Build definition for the cross-compiling framework](https://github.com/scala-js/scala-js/blob/v0.6.0-M3/sbt-plugin-test/build.sbt#L47-L62) +* [(Cross-compiling) source code of the testing framework](https://github.com/scala-js/scala-js/tree/v0.6.0-M3/sbt-plugin-test/testFramework/src/main/scala/sbttest/framework) +* [Build definition for a cross-compiling project using the framework](https://github.com/scala-js/scala-js/blob/v0.6.0-M3/sbt-plugin-test/build.sbt#L64-L84) +* [Source code of the project using the framework](https://github.com/scala-js/scala-js/tree/v0.6.0-M3/sbt-plugin-test/multiTest) + +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](https://github.com/lihaoyi/utest/pull/45) to migrate to Scala.js 0.6.x. + +Should you run into trouble, don't hesitate to ask on the mailing list! + +## Enhancements + +### Defining cross-compiling projects with `crossProject` + +When writing cross-compiling code, we need to have two separate projects in sbt for the JVM target and the JS target. +The new `CrossProject` type, and its `crossProject` builder, helps in defining these pairs of projects in a DRY way. + +See the [documentation of `CrossProject`]({{ BASE_PATH }}/api/sbt-scalajs/0.6.0-M3/#org.scalajs.sbtplugin.cross.CrossProject) for more information and examples. + +### Faster! + +Scala.js 0.6.x benefits from many performance improvements, most notably: + +* `asInstanceOf`s are unchecked (see above), giving `fullOpt` code 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 `while` loop. +* Higher-order operations on `js.Array`s (such as `foreach`, `map`, etc.) are inlined away as `while` loops. +* Various improvements to the optimizer. + +### Scala collection API for `js.Array[A]` and `js.Dictionary[A]` + +The title says it all: `js.Array[A]` and `js.Dictionary[A]` receive the entire Scala collection API, respectively of `mutable.Buffer[A]` and `mutable.Map[String, A]`. + +`js.Array` becomes the default implementation of `mutable.Buffer`, i.e., `mutable.Buffer.empty` returns a `js.Array` wrapped in a `js.WrappedArray`. + +### Implicits to make "writing JavaScript" easier + +Sometimes, for example when porting existing JavaScript code, we want to just "write JavaScript" inside our Scala.js code. +A new object `js.DynamicImplicits` ([API](http://www.scala-js.org/api/scalajs-library/0.6.0-M3/#scala.scalajs.js.DynamicImplicits$) provides implicit conversions that allow to write dynamically typed JavaScriptish code directly in Scala.js with a mimimal amount of boilerplate. +Needless to say, these implicits should be handled with care, but they can come in handy. + +### On-demand strict floats + +Scala.js under-specifies `Float` operations by default, saying that they can sometimes behave as if they were `Double`s. +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 `.toString()`). +The following sbt setting enables this: + +{% highlight scala %} +scalaJSSemantics ~= { _.withStrictFloats(true) } +{% endhighlight %} + +Beware that this can have a major impact on performance on VMs that do not support the [`Math.fround`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/fround) function. + +### We publish to Maven Central + +This should probably not affect sbt users, but it now becomes possible to imagine a Maven plugin 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 user could therefore build a Maven plugin with relatively few lines of code. +As a measurable figure, the code specific to sbt contains only 1,211 lines of code. + +## Bugfixes + +Amongst others, the following bugs have been fixed since 0.5.6: + +* [#1324](https://github.com/scala-js/scala-js/issues/1324) Date.parse should return a Double, not an Int +* [#1349](https://github.com/scala-js/scala-js/issues/1349) Auto-completion in runMain task does not work +* [#1192](https://github.com/scala-js/scala-js/issues/1192) hashCode for floating points has a very bad distribution +* [#1402](https://github.com/scala-js/scala-js/issues/1402) `Traversers` does not handle the case of `Debugger` diff --git a/doc/index.md b/doc/index.md index 89f8bda5..1650aba0 100644 --- a/doc/index.md +++ b/doc/index.md @@ -31,6 +31,16 @@ Generated Scaladocs are available here: ### Scala.js +#### Scala.js 0.6.0-M3 +* [0.6.0-M3 scalajs-library]({{ BASE_PATH }}/api/scalajs-library/0.6.0-M3/#scala.scalajs.js.package) +* [0.6.6-M3 scalajs-test-interface]({{ BASE_PATH }}/api/scalajs-test-interface/0.6.0-M3/) +* [0.6.0-M3 scalajs-stubs]({{ BASE_PATH }}/api/scalajs-stubs/0.6.0-M3/) +* [0.6.0-M3 scalajs-ir]({{ BASE_PATH }}/api/scalajs-ir/0.6.0-M2/#org.scalajs.core.ir.package) +* [0.6.0-M3 scalajs-tools]({{ BASE_PATH }}/api/scalajs-tools/0.6.0-M3/#org.scalajs.core.tools.package) ([Scala.js version]({{ BASE_PATH }}/api/scalajs-tools-js/0.6.0-M3/#org.scalajs.core.tools.package)) +* [0.6.0-M3 scalajs-js-envs]({{ BASE_PATH }}/api/scalajs-js-envs/0.6.0-M3/#org.scalajs.jsenv.package) +* [0.6.0-M3 scalajs-test-adapter]({{ BASE_PATH }}/api/scalajs-test-adapter/0.6.0-M3/#org.scalajs.testadapter.package) +* [0.6.0-M3 sbt-scalajs]({{ BASE_PATH }}/api/sbt-scalajs/0.6.0-M3/#org.scalajs.sbtplugin.package) + #### Scala.js 0.6.0-M2 * [0.6.0-M2 scalajs-library]({{ BASE_PATH }}/api/scalajs-library/0.6.0-M2/#scala.scalajs.js.package) * [0.6.6-M2 scalajs-test-interface]({{ BASE_PATH }}/api/scalajs-test-interface/0.6.0-M2/) diff --git a/downloads.md b/downloads.md index b9a00f7c..c050b77c 100644 --- a/downloads.md +++ b/downloads.md @@ -9,6 +9,12 @@ We strongly recommend using the SBT plugin, as shown in the [bootstrapping skele The CLI distribution requires `scala` and `scalac` (of the right major version) to be on the execution path. Unpack it wherever you like and add the `bin/` folder to your execution path. +#### Scala.js 0.6.0-M3 +* [0.6.0-M3, Scala 2.11 (tgz, 18MB)]({{ BASE_PATH }}/files/scalajs_2.11-0.6.0-M3.tgz) +* [0.6.0-M3, Scala 2.11 (zip, 18MB)]({{ BASE_PATH }}/files/scalajs_2.11-0.6.0-M3.zip) +* [0.6.0-M3, Scala 2.10 (tgz, 18MB)]({{ BASE_PATH }}/files/scalajs_2.10-0.6.0-M3.tgz) +* [0.6.0-M3, Scala 2.10 (zip, 18MB)]({{ BASE_PATH }}/files/scalajs_2.10-0.6.0-M3.zip) + #### Scala.js 0.6.0-M2 * [0.6.0-M2, Scala 2.11 (tgz, 18MB)]({{ BASE_PATH }}/files/scalajs_2.11-0.6.0-M2.tgz) * [0.6.0-M2, Scala 2.11 (zip, 18MB)]({{ BASE_PATH }}/files/scalajs_2.11-0.6.0-M2.zip) diff --git a/index.md b/index.md index e1741035..1cc21b01 100644 --- a/index.md +++ b/index.md @@ -285,6 +285,7 @@ List of websites using Scala.js: ## Version History +- [0.6.0-M3](/news/2014/12/22/announcing-scalajs-0.6.0-M3/) - [0.6.0-M2](/news/2014/12/05/announcing-scalajs-0.6.0-M2/) - [0.6.0-M1](/news/2014/12/01/announcing-scalajs-0.6.0-M1/) - [0.5.6](/news/2014/11/19/announcing-scalajs-0.5.6/)