Skip to content
2 changes: 1 addition & 1 deletion _config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ author :
twitter : sjrdoeraene
feedburner : feedname

scalaJSVersion: 0.5.3
scalaJSVersion: 0.5.4
scalaJSBinaryVersion: 0.5

# The production_url is only used when full-domain names are needed
Expand Down
104 changes: 104 additions & 0 deletions _posts/news/2014-08-29-announcing-scalajs-0.5.4.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
---
layout: post
title: Announcing Scala.js 0.5.4
category: news
tags: [releases]
---
{% include JB/setup %}

We are excited to announce the release of Scala.js 0.5.4!

This release contains various bug fixes and enhancements to both the compiler and the sbt plugin.

Scala.js 0.5.4 is backward binary compatible with older versions of the 0.5.x branch. However, it is *not* forward binary compatible. This means:

- You don't need to re-publish libraries
- You must upgrade to Scala.js 0.5.4 if any library you depend on uses Scala.js 0.5.4

If you choose to re-publish a library, make sure to bump its version.

Please report any issues [on GitHub](https://github.com/scala-js/scala-js/issues).

## Upgrading from 0.5.3 an below

Simply change the version number in `project/plugins.sbt`, as usual.

If you use [uTest](https://github.com/lihaoyi/utest), you need to upgrade it to version 0.2.3 or later.
This is due to a binary incompatible change in the sbt plugin.

## Improvements in the 0.5.4 release

For changes introduced in 0.5.0, how to upgrade, getting started etc. have a look at the [0.5.0 announcement]({{ BASE_PATH }}/news/2014/06/13/announcing-scalajs-0.5.0/) (see also the announcements for [0.5.1]({{ BASE_PATH }}/news/2014/06/30/announcing-scalajs-0.5.1/), [0.5.2]({{ BASE_PATH }}/news/2014/07/09/announcing-scalajs-0.5.2/) and [0.5.3]({{ BASE_PATH }}/news/2014/07/30/announcing-scalajs-0.5.3/)).

### JavaScript Export Facilities

A few improvements have been made to `@JSExport`-related features, to export Scala.js APIs to JavaScript:

* [Export methods with named arguments]({{ BASE_PATH }}/doc/export-to-javascript.html#JSExportNamed)
* [Automatically export all public members of a class/object]({{ BASE_PATH }}/doc/export-to-javascript.html#JSExportAll)
* [Export fields declared as constructor parameters]({{ BASE_PATH }}/doc/export-to-javascript.html#constructor-params)

### PhantomJS

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section and the in-depth documentation should mention that Phantom JS auto terminates unless configured differently via arguments. (autoExit argument)

The interface to the PhantomJS interpreter has been enhanced with two features:

* [Passing command-line arguments to PhantomJS]({{ BASE_PATH }}/doc/sbt/js-envs.html#phantomjs-arguments)
* [Configuring PhantomJS not to terminate automatically when the `main()` method returns]({{ BASE_PATH }}/doc/sbt/js-envs.html#phantomjs-no-auto-terminate)
* You can use `java.lang.System.exit(exitCode)` to explicitly terminate the PhantomJS environment

### Conversions

The new object [JSConverters](http://www.scala-js.org/api/scalajs-library/0.5.4/#scala.scalajs.js.JSConverters$) provides extension methods to convert between JavaScript collections and Scala collections (maps, sequences and option).

[More information in the documentation]({{ BASE_PATH }}/doc/js-interoperability.html)

### Source maps for fullOptJS

Source maps are now generated for `fullOptJS` as well.

To support this, we have changed the way we integrate the Google Closure Compiler.
Should you experience any regression, please file an issue, and use the following fallback to revert to the old mechanism (which will not generate source maps):

{% highlight scala %}
ScalaJSKeys.directFullOptJS := false
{% endhighlight %}

### %%% Cross versioning

The `%%%` operator used to build library dependencies for Scala.js has been enhanced.
It is now able to determine whether it is used inside a Scala.js project or a Scala/JVM project.
In the latter, it will be equivalent to `%%`.
This allows to use `%%%` consistently for cross-compiling projects.

[More information in the documentation]({{ BASE_PATH }}/doc/sbt/depending.html)

### Auto-detect whether the DOM is required

The setting `requiresDOM` will now default to `true` if the special `RuntimeDOM` dependency is listed in the (transitive) `jsDependencies` of your project.
To specify that your library or program depends on the DOM, use the following setting:

{% highlight scala %}
ScalaJSKeys.jsDependencies += scala.scalajs.sbtplugin.RuntimeDOM
{% endhighlight %}

It is still possible to override this behavior by explicitly setting `requiresDOM`, as before.

### Tools.js

Our tools API now cross-compiles for Scala/JVM and Scala.js.
It can therefore be used in Scala.js, for example to link and optimize Scala.js IR on the client.

#### Bugfixes

The following bugs have been fixed since 0.5.3:

- [#897](https://github.com/scala-js/scala-js/issues/897) fastOptJS crash: Invalid lhs for Assign: This()
- [#898](https://github.com/scala-js/scala-js/issues/898) PhantomJS polyfill doesn't work
- [#899](https://github.com/scala-js/scala-js/issues/899) Compiler should always unbox arguments to reflective calls
- [#904](https://github.com/scala-js/scala-js/issues/904) Stack overflow in fast optimizer
- [#906](https://github.com/scala-js/scala-js/issues/906) Assignment to exported var gives "Unhandled type class" warning
- [#907](https://github.com/scala-js/scala-js/issues/907) fastOptJS crash: statements before Dictionary.delete() in exported functions
- [#908](https://github.com/scala-js/scala-js/issues/908) Calling Dictionary.delete() with js.Object property throws RuntimeException
- [#919](https://github.com/scala-js/scala-js/issues/919) sbt: Inspecting does not work with scalaJSSettings
- [#920](https://github.com/scala-js/scala-js/issues/920) Return type lifting for JSExports fails on RefinedTypes
- [#940](https://github.com/scala-js/scala-js/issues/940) Compiler crash on strange pattern match
96 changes: 96 additions & 0 deletions doc/export-to-javascript.md
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,45 @@ gives:
Hint to recognize this error: the methods are named `$js$exported$meth$`
followed by the JavaScript export name.

### <a name="JSExportNamed"></a> Exporting for call with named parameters
It is customary in Scala to call methods with named parameters if this eases understanding of the code or if many arguments with default values are present:

{% highlight scala %}
def foo(x: Int = 1, y: Int = 2, z: Int = 3) = ???

foo(y = 3, x = 2)
{% endhighlight %}

A rough equivalent in JavaScript is to pass an object with the respective properties:
{% highlight javascript %}
foo({
y: 3,
x: 2
});
{% endhighlight %}

The `@JSExportNamed` annotation allows to export Scala methods for use in JavaScript with named parameters:

{% highlight scala %}
class A {
@JSExportNamed
def foo(x: Int, y: Int = 2, z: Int = 3) = ???
}
{% endhighlight %}

Note that default parameters are not required. `foo` can then be called like this:
{% highlight javascript %}
var a = // ...
a.foo({
y: 3,
x: 2
});
{% endhighlight %}

Not specifying `x` in this case will fail at runtime (since it does not have a default value).

Just like `@JSExport`, `@JSExportNamed` takes the name of the exported method as an optional argument.

## Exporting properties

`val`s, `var`s and `def`s without parentheses, as well as `def`s whose name
Expand Down Expand Up @@ -262,6 +301,22 @@ In case you overload properties in a way the compiler cannot
disambiguate, the methods in the error messages will be prefixed by
`$js$exported$prop$`.

### <a name="constructor-params"></a> Export fields directly declared in constructors
If you want to export fields that are directly declared in a class constructor, you'll have to use the `@field` meta annotation to avoid annotating the constructor arguments (exporting an argument is nonsensical and will fail):

{% highlight scala %}
import scala.annotation.meta.field

class Point(
@(JSExport @field) val x: Double,
@(JSExport @field) val y: Double)

// Also applies to case classes
case class Point(
@(JSExport @field) x: Double,
@(JSExport @field) y: Double)
{% endhighlight %}

## Automatically exporting descendent objects
Sometimes it is desirable to automatically export all descendent
objects of a given trait or class. You can use the
Expand Down Expand Up @@ -290,3 +345,44 @@ object Test1 extends Test {
}
}
{% endhighlight %}

## <a name="JSExportAll"></a> Automatically export all members
Instead of writing `@JSExport` on every member of a class or object, you may use the `@JSExportAll` annotation. It is equivalent to adding `@JSExport` on every public (term) member directly declared in the class/object:

{% highlight scala %}
class A {
def mul(x: Int, y: Int): Int = x * y
}

@JSExportAll
class B(val a: Int) extends A {
def sum(x: Int, y: Int): Int = x + y
}
{% endhighlight %}

This is strictly equivalent to writing:

{% highlight scala %}
class A {
def mul(x: Int, y: Int): Int = x * y
}

class B(@(JSExport @field) val a: Int) extends A {
@JSExport
def sum(x: Int, y: Int): Int = x + y
}
{% endhighlight %}

It is important to note that this does **not** export inherited members. If you wish to do so, you'll have to override them explicitly:

{% highlight scala %}
class A {
def mul(x: Int, y: Int): Int = x * y
}

@JSExportAll
class B(val a: Int) extends A {
override def mul(x: Int, y: Int): Int = super.mul(x,y)
def sum(x: Int, y: Int): Int = x + y
}
{% endhighlight %}
8 changes: 7 additions & 1 deletion doc/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,18 @@ Alternatively, create a project with *custom naming* by using this [giter8 templ
* [Cross-Building](./sbt/cross-building.html)
* [Scala.js Cookbook](./cookbook/)

## API
## <a name="api"></a> API

Generated Scaladocs are available here:

### Scala.js

#### Scala.js 0.5.4
* [0.5.4 scalajs-library]({{ BASE_PATH }}/api/scalajs-library/0.5.4/#scala.scalajs.js.package)
* [0.5.4 scalajs-tools]({{ BASE_PATH }}/api/scalajs-tools/0.5.4/) ([Scala.js version]({{ BASE_PATH }}/api/scalajs-tools/0.5.4/))
* [0.5.4 scalajs-test-bridge]({{ BASE_PATH }}/api/scalajs-test-bridge/0.5.4/)
* [0.5.4 scalajs-jasmine-test-framework]({{ BASE_PATH }}/api/scalajs-jasmine-test-framework/0.5.4/)

#### Scala.js 0.5.3
* [0.5.3 scalajs-library]({{ BASE_PATH }}/api/scalajs-library/0.5.3/#scala.scalajs.js.package)
* [0.5.3 scalajs-tools]({{ BASE_PATH }}/api/scalajs-tools/0.5.3/)
Expand Down
65 changes: 65 additions & 0 deletions doc/js-interoperability.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,68 @@ JavaScript code.
</tr>
</tbody>
</table>

On the other hand, some JavaScript (collection) types have similar types in Scala. Instead of mapping them directly, Scala.js provides conversions between them. We show with a couple of snippets how you can convert from JavaScript to Scala types and back. Please refer to the [Scaladocs]({{ BASE_PATH }}/doc/index.html#api) for details.

*** js.Array[T] <--> mutable.Seq[T] ***

{% highlight scala %}
import scala.scalajs.js

val jsArr = js.Array(1, 2, 3)

// Scala style operations on js.Array (returns a js.Array)
val x: js.Array[Int] = jsArr.takeWhile(_ < 3)

// Use a js.Array as a Scala mutable.Seq
val y: mutable.Seq[Int] = jsArr

// toArray (from js.ArrayOps) -- Copy into scala.Array
val z: scala.Array[Int] = jsArr.toArray

import js.JSConverters._

val scSeq = Seq(1, 2, 3)

// Seq to js.Array -- Copy to js.Array
val jsArray: js.Array[Int] = scSeq.toJSArray
{% endhighlight %}

*** js.Dictionary[T] <--> mutable.Map[String, T] ***

{% highlight scala %}
import scala.scalajs.js

val jsDict = js.Dictionary("a" -> 1, "b" -> 2)

// Scala style operations on js.Dictionary (returns mutable.Map)
val x: mutable.Map[String, Int] = jsDict.mapValues(_ * 2)

// Use a js.Dictionary as Scala mutable.Map
val y: mutable.Map[String, Int] = jsDict

import js.JSConverters._

val scMap = Map("a" -> 1, "b" -> 2)

// Map to js.Dictionary -- Copy to js.Dictionary
val jsDictionary: js.Dictionary[Int] = scMap.toJSDictionary
{% endhighlight %}

*** js.UndefOr[T] <--> Option[T] ***

{% highlight scala %}
import scala.scalajs.js

val jsUndefOr: js.UndefOr[Int] = 1

// Convert to scala.Option
val x: Option[Int] = jsUndefOr.toOption

import js.JSConverters._

val opt = Some(1)

// Convert to js.Undefined
val y: js.UndefOr[Int] = opt.orUndefined
{% endhighlight %}
27 changes: 17 additions & 10 deletions doc/sbt/cross-building.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,23 @@ If you do not publish the artifacts, you may choose different names for the proj

## Dependencies

If your cross compiled source depends on libraries, you will have to add the dependencies on the libraries separately for each project (using the `%%%` for the Scala.js project). For example, if your code uses [Scalatags](http://github.com/lihaoyi/scalatags), your project definitions look like this:
If your cross compiled source depends on libraries, you may use `%%%` for both projects. It will automatically determine whether you are in a Scala/JVM or a Scala.js project. For example, if your code uses [Scalatags](http://github.com/lihaoyi/scalatags), your project definitions look like this:

lazy val fooJS = project.in(file("foo-js")).settings(scalaJSSettings: _*).settings(
name := "foo",
unmanagedSourceDirectories in Compile += root.base / "foo-shared" / "src" / "main" / "scala",
libraryDependencies += "com.scalatags" %%% "scalatags" % "0.3.5"
val dependencySettings = Seq(
libraryDependencies += "com.scalatags" %%% "scalatags" % "0.3.5"
)

lazy val fooJVM = project.in(file("foo-jvm")).settings(
name := "foo",
unmanagedSourceDirectories in Compile += root.base / "foo-shared" / "src" / "main" / "scala",
libraryDependencies += "com.scalatags" %% "scalatags" % "0.3.5"
)
lazy val fooJS = project.in(file("foo-js"))
.settings(scalaJSSettings: _*)
.settings(dependencySettings: _*)
.settings(
name := "foo",
unmanagedSourceDirectories in Compile += root.base / "foo-shared" / "src" / "main" / "scala"
)

lazy val fooJVM = project.in(file("foo-jvm"))
.settings(dependencySettings: _*)
.settings(
name := "foo",
unmanagedSourceDirectories in Compile += root.base / "foo-shared" / "src" / "main" / "scala"
)
2 changes: 2 additions & 0 deletions doc/sbt/depending.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ Note the `%%%` (instead of the usual `%%`) which will add the current Scala.js v

Some Scala.js core libraries (such as the Scala.js library itself) do not need the `%%%` since their version number *is* the Scala.js version number itself.

Note that you can also use `%%%` in a Scala/JVM project, in which case it will be the same as `%%`. This allows you to use the same `libraryDependencies` settings when cross compiling Scala/JVM and Scala.js.

## Depending on JavaScript libraries

Thanks to [WebJars](http://www.webjars.org/), you can easily fetch a JavaScript library like so:
Expand Down
26 changes: 26 additions & 0 deletions doc/sbt/js-envs.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,32 @@ For example, to switch to PhantomJS, you can set:

We'd like to stress here again, that you need to separately install Node.js and PhantomJS if you would like to use these environments.

## <a name="phantomjs-no-auto-terminate"></a> Disabling auto-termination of PhantomJS

By default, the PhantomJS interpreter terminates itself as soon as the `main()` method returns.
This may not be what you want, if for example you register time-outs or use WebSockets.
You can disable this behavior with the following setting:

{% highlight scala %}
ScalaJSKeys.postLinkJSEnv := new scala.scalajs.sbtplugin.env.phantomjs.PhantomJSEnv(
autoExit = false)
{% endhighlight %}

You can terminate the interpreter from your Scala code with

{% highlight scala %}
System.exit(0)
{% endhighlight %}

## <a name="phantomjs-arguments"></a> Passing arguments to PhantomJS

You can pass command-line arguments to the PhantomJS interpreter like this:

{% highlight scala %}
ScalaJSKeys.postLinkJSEnv := new scala.scalajs.sbtplugin.env.phantomjs.PhantomJSEnv(
Seq("arg1", "arg2"))
{% endhighlight %}

## <a name="node-on-ubuntu"></a> Node.js on Ubuntu

On Ubuntu, the Node.js command from the [nodejs package](http://packages.ubuntu.com/utopic/nodejs) is called `nodejs` instead of `node` (when installed through the package manager). This will make the Node.js environment fail (since it simply calls `node`).
Expand Down
Loading