Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion _config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ assets:
paginate: 6
paginate_path: "/news/page:num"
excerpt_separator: "<!--more-->"
future: true

# Build settings
markdown: kramdown
Expand Down Expand Up @@ -57,7 +58,7 @@ colors: #in hex code if not noted else

### VERSIONS ###
versions:
scalaJS: 0.6.5
scalaJS: 0.6.6
scalaJSBinary: 0.6
scalaJSDOM: 0.8.2

Expand Down
173 changes: 173 additions & 0 deletions _posts/news/2016-01-25-announcing-scalajs-0.6.6.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
---
layout: post
title: Announcing Scala.js 0.6.6
category: news
tags: [releases]
permalink: /news/2016/01/25/announcing-scalajs-0.6.6/
---


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

It has been a long while since the last release, almost 5 months already.
That was too long, and we apologize.
In the future, we hope never to let more than 2 months elapse between consecutive releases.

Besides bug fixes, this release brings several major improvements:

* `js.TupleN`, a JS equivalent of Scala tuples
* Support for JUnit
* Better support of constructors of `@ScalaJSDefined` classes:
they can now have overloads, default parameters and varargs
* A completely redesigned internal API for the linker, whose main visible impact should be reduced memory usage and improved speed
* `js.ConstructorTag[C]`, a `ClassTag` equivalent to `js.constructorOf[C]`

<!--more-->

## Getting started

If you are new to Scala.js, head over to
[the tutorial]({{ BASE_PATH }}/tutorial/).

## Release notes

As a minor release, 0.6.6 is (almost, see Breaking changes below) backward source and binary compatible with previous releases in the 0.6.x series.
Libraries compiled with earlier versions can be used with 0.6.6 without change.
However, it is not forward compatible: libraries compiled with 0.6.6 cannot be used by projects using 0.6.{0-5}.

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

## Breaking changes
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe add to this section that anything in org.scalajs.tools might have experienced a breaking change.

Copy link
Member Author

Choose a reason for hiding this comment

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

OK


### Running in Node.js/PhantomJS

Until Scala.js 0.6.5, the following sbt setting would, as a side-effect, enable Node.js or PhantomJS:

scalaJSStage in Global := FastOptStage

As of Scala.js 0.6.6, this setting is redundant, as it is the default, but `run` and `test` will still use Rhino by default!
To disable Rhino and use Node.js/PhantomJS in 0.6.6, use the following setting instead:

scalaJSUseRhino in Global := false

### Tools API

The [Tools API]({{ site.production_url }}/api/scalajs-tools/0.6.6/#org.scalajs.core.tools.package),
(the API to the Scala.js linker and optimizer) have been completely redesigned.
Users of this API, such as [Scala.jsFiddle](http://www.scala-js-fiddle.com/), will experience breakages.
Contact us if you need help porting your code.

## Improvements

### JavaScript Tuple types

In the same spirit as `js.Function`s, `js.Array`, etc., we have added a series of types representing JavaScript "tuples": `js.Tuple2` to `js.Tuple22`.
The JavaScript representation of a tuple is, in fact, a heterogeneous array of fixed length.

For example, the value

val t = js.Tuple2(45, "hello")

corresponds the JavaScript value

[45, "hello"]

You should use `js.Tuple`s in facades to JavaScript libraries that take and return tuples as heterogeneous arrays.

JavaScript tuples are convertible back and forth to Scala tuples, and you can use deconstruction to extract all values of a JavaScript at the same time.
For example:

val scalaT: (Int, String) = t
val t2: js.Tuple2[Int, String] = scalaT
val js.Tuple2(a, b) = t2

### Support for JUnit

It is now possible to write JUnit tests for Scala.js!
We have ported the JUnit API to Scala.js, so that it is now possible to write cross-compiling unit tests with JUnit.

To enable JUnit on your Scala.js project, add the appropriate sbt AutoPlugin using

enablePlugins(ScalaJSJUnitPlugin)

(like you would with the basic `ScalaJSPlugin`).
For a `crossProject`, this must be enabled only on the JS variant.
For the JVM variant, use the usual `libraryDependencies` setting:

{% highlight scala %}
lazy val myCrossProject = crossProject.
jsConfigure(_.enablePlugins(ScalaJSJUnitPlugin)).
jvmSettings(
libraryDependencies +=
"com.novocode" % "junit-interface" % "0.9" % "test"
)
{% endhighlight %}

### `js.ConstructorTag[C]`

[`js.ConstructorTag[C]`]({{ site.production_url }}/api/scalajs-library/0.6.6/#scala.scalajs.js.ConstructorTag) is to [`js.constructorOf[C]`]({{ site.production_url }}/api/scalajs-library/0.6.6/#scala.scalajs.js.package@constructorOf[T<:scala.scalajs.js.Any]:scala.scalajs.js.Dynamic) as `ClassTag[C]` is to `classOf[C]`, i.e., you can use an `implicit` parameter of type `js.ConstructorTag[C]` to implicitly get a `js.constructorOf[C]`.
For example:

{% highlight scala %}
def instantiate[C <: js.Any : js.ConstructorTag]: C =
js.Dynamic.newInstance(js.constructorTag[C].constructor)().asInstanceOf[C]

val newEmptyJSArray = instantiate[js.Array[Int]]
{% endhighlight %}

Implicit expansion will desugar the above code into:

{% highlight scala %}
def instantiate[C <: js.Any](implicit tag: js.ConstructorTag[C]): C =
js.Dynamic.newInstance(tag.constructor)().asInstanceOf[C]

val newEmptyJSArray = instantiate[js.Array[Int]](
new js.ConstructorTag[C](js.constructorOf[js.Array[Int]]))
{% endhighlight %}

although you cannot write the desugared version in user code because the constructor of `js.ConstructorTag` is private.

This feature is particularly useful for Scala.js libraries wrapping JavaScript frameworks expecting to receive JavaScript constructors as parameters.

### Query for Development versus Production mode

The new methods `isDevelopmentMode` and `isProductionMode` allow you to query in your code whether you are running in a Development build or a Production build (for all practical purposes, aka `fastOptJS` and `fullOptJS`, resp.).
The methods are located in [`scala.scalajs.LinkingInfo`]({{ site.production_url }}/api/scalajs-library/0.6.6/#scala.scalajs.LinkingInfo$).
These methods can be used by libraries to provide domain-specific "optimizations" for production, e.g., eliminate expensive run-time checks useful for debugging.
Using these methods should be done with great care as, by definition, they will alter the behavior of your program between `fastOpt` and `fullOpt`.

### Java library additions

* Methods of `java.lang.Long` dealing with unsigned values
* Several JDK8 methods of `java.lang.Math`
* `java.util.Comparator.reversed`: the first of the *default* methods of JDK8
* `java.util.ArrayDeque`
* `java.net.URLDecoder`
* `java.util.concurrent.locks.ReentrantLock`
* `java.util.Objects`

## Bug fixes

Among others, the following bugs have been fixed:

* [#1635](https://github.com/scala-js/scala-js/issues/1635) Touching a file in `src/test/resources` triggers `test:fastOptJS`
* [#1891](https://github.com/scala-js/scala-js/issues/1891) Class with constructors with optional parameters can't be embedded in objects that extend `js.Object`
* [#1899](https://github.com/scala-js/scala-js/issues/1899) Some members of `new js.Object {...}` are not visible from JavaScript
* [#1975](https://github.com/scala-js/scala-js/issues/1975) Inner function in `@ScalaJSDefined` method doesn't get parameter
* [#1979](https://github.com/scala-js/scala-js/issues/1979) [#2042](https://github.com/scala-js/scala-js/issues/2042) Bugs in `java.math.BigDecimal.divideToIntegralValue`
* [#1984](https://github.com/scala-js/scala-js/issues/1984) `-8 % 8` evaluates to negative 0, which then blows up if cast to Integer (duplicate [#2068](https://github.com/scala-js/scala-js/issues/2068))
* [#2045](https://github.com/scala-js/scala-js/issues/2045) `BigInt.pow(31)` return the negative of the expected number
* [#2067](https://github.com/scala-js/scala-js/issues/2067) Better implicits for combinations of `js.|` and `js.UndefOr`
* [#2114](https://github.com/scala-js/scala-js/issues/2114) `CharBuffer.wrap(CharSequence,Int,Int)` interprets `end` as `length`
* [#2158](https://github.com/scala-js/scala-js/issues/2158) Parsing very large `Long` does not fail properly
* [#2159](https://github.com/scala-js/scala-js/issues/2159) `java.math.BigInteger` violate equals/hashCode law
* [#2178](https://github.com/scala-js/scala-js/issues/2178) sbt `test:run` on Scala.js projects runs it under the JVM
* [#2180](https://github.com/scala-js/scala-js/issues/2180) `Character.isWhitespace` discrepancies

You can find the full list [on GitHub](https://github.com/scala-js/scala-js/issues?q=is%3Aissue+milestone%3Av0.6.6+is%3Aclosed).

## Known issues

The following issues were discovered too late to be fixed in v0.6.6:

* [#2195](https://github.com/scala-js/scala-js/issues/2195) Source maps to the Scala library are broken
10 changes: 10 additions & 0 deletions doc/all-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@ title: All previous versions of the Scala.js API

## All previous versions of the API

### Scala.js 0.6.6
* [0.6.6 scalajs-library]({{ site.production_url }}/api/scalajs-library/0.6.6/#scala.scalajs.js.package)
* [0.6.6 scalajs-test-interface]({{ site.production_url }}/api/scalajs-test-interface/0.6.6/)
* [0.6.6 scalajs-stubs]({{ site.production_url }}/api/scalajs-stubs/0.6.6/)
* [0.6.6 scalajs-ir]({{ site.production_url }}/api/scalajs-ir/0.6.6/#org.scalajs.core.ir.package)
* [0.6.6 scalajs-tools]({{ site.production_url }}/api/scalajs-tools/0.6.6/#org.scalajs.core.tools.package) ([Scala.js version]({{ site.production_url }}/api/scalajs-tools-js/0.6.6/#org.scalajs.core.tools.package))
* [0.6.6 scalajs-js-envs]({{ site.production_url }}/api/scalajs-js-envs/0.6.6/#org.scalajs.jsenv.package)
* [0.6.6 scalajs-test-adapter]({{ site.production_url }}/api/scalajs-sbt-test-adapter/0.6.6/#org.scalajs.testadapter.package)
* [0.6.6 sbt-scalajs]({{ site.production_url }}/api/sbt-scalajs/0.6.6/#org.scalajs.sbtplugin.package)

### Scala.js 0.6.5
* [0.6.5 scalajs-library]({{ site.production_url }}/api/scalajs-library/0.6.5/#scala.scalajs.js.package)
* [0.6.5 scalajs-test-interface]({{ site.production_url }}/api/scalajs-test-interface/0.6.5/)
Expand Down
6 changes: 6 additions & 0 deletions doc/internals/downloads.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,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.6
* [0.6.6, Scala 2.11 (tgz, 24MB)]({{ site.production_url }}/files/scalajs_2.11-0.6.6.tgz)
* [0.6.6, Scala 2.11 (zip, 24MB)]({{ site.production_url }}/files/scalajs_2.11-0.6.6.zip)
* [0.6.6, Scala 2.10 (tgz, 22MB)]({{ site.production_url }}/files/scalajs_2.10-0.6.6.tgz)
* [0.6.6, Scala 2.10 (zip, 22MB)]({{ site.production_url }}/files/scalajs_2.10-0.6.6.zip)

#### Scala.js 0.6.5
* [0.6.5, Scala 2.11 (tgz, 24MB)]({{ site.production_url }}/files/scalajs_2.11-0.6.5.tgz)
* [0.6.5, Scala 2.11 (zip, 24MB)]({{ site.production_url }}/files/scalajs_2.11-0.6.5.zip)
Expand Down
30 changes: 26 additions & 4 deletions doc/interoperability/sjs-defined-js-classes.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,6 @@ Scala.js-defined JS types have the following restrictions:
* Declaring a method with `@JSBracketSelect` or `@JSBracketCall` is illegal.
* Mixing fields, pairs of getter/setter, and/or methods with the same name is illegal. (For example `def foo: Int` and `def foo(x: Int): Int` cannot both exist in the same class.)

There is also one implementation restriction, which will be lifted in a future version:

* A Scala.js-defined JS class cannot have secondary constructors, and its primary constructor cannot have default parameters nor repeated parameters (varargs).


## Semantics

Expand Down Expand Up @@ -275,3 +271,29 @@ It can be a native JS class or a Scala.js-defined JS class.
The method returns the JavaScript constructor function (aka the class value) for `C`.

This can be useful to give to JavaScript libraries expecting constructor functions rather than instances of the classes.

### `js.ConstructorTag[C]`

[`js.ConstructorTag[C]`]({{ site.production_url }}/api/scalajs-library/latest/#scala.scalajs.js.ConstructorTag) is to [`js.constructorOf[C]`]({{ site.production_url }}/api/scalajs-library/latest/#scala.scalajs.js.package@constructorOf[T<:scala.scalajs.js.Any]:scala.scalajs.js.Dynamic) as `ClassTag[C]` is to `classOf[C]`, i.e., you can use an `implicit` parameter of type `js.ConstructorTag[C]` to implicitly get a `js.constructorOf[C]`.
For example:

{% highlight scala %}
def instantiate[C <: js.Any : js.ConstructorTag]: C =
js.Dynamic.newInstance(js.constructorTag[C].constructor)().asInstanceOf[C]

val newEmptyJSArray = instantiate[js.Array[Int]]
{% endhighlight %}

Implicit expansion will desugar the above code into:

{% highlight scala %}
def instantiate[C <: js.Any](implicit tag: js.ConstructorTag[C]): C =
js.Dynamic.newInstance(tag.constructor)().asInstanceOf[C]

val newEmptyJSArray = instantiate[js.Array[Int]](
new js.ConstructorTag[C](js.constructorOf[js.Array[Int]]))
{% endhighlight %}

although you cannot write the desugared version in user code because the constructor of `js.ConstructorTag` is private.

This feature is particularly useful for Scala.js libraries wrapping JavaScript frameworks expecting to receive JavaScript constructors as parameters.
37 changes: 14 additions & 23 deletions doc/project/building.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,42 +18,33 @@ You now can run your application already by using the `run` task:
This will detect and run classes that extend
[`js.JSApp`]({{ site.production_url }}/api/scalajs-library/{{ site.versions.scalaJS }}/#scala.scalajs.js.JSApp), while optionally prompting the user to choose a class if multiple such classes exist (fails with multiple classes if `persistLauncher := true`, see section below for details).

To run the `.sjsir` files, we invoke the Rhino JavaScript interpreter with a special scope that lazily reads and loads required `.sjsir` files on the fly (much like Java class loading).
By default, to run the `.sjsir` files, we invoke the Rhino JavaScript interpreter with a special scope that lazily reads and loads required `.sjsir` files on the fly (much like Java class loading).
Note that by default, this environment doesn't have a DOM.
If you need it set `jsDependencies += RuntimeDOM` in your settings.

## Fast-Optimize
## Running with Node.js or PhantomJS

To produce a proper JavaScript file from your code, you need to call the linker:

sbt> fastOptJS

This will perform fast Scala.js-specific optimizations and write the resulting code to a single JavaScript file. You can now use this JavaScript file in your HTML page or in whatever way you like. The resulting file in the target folder will have the suffix `-fastopt.js`.
Since Rhino is very slow and limited, we recommend to use [Node.js](http://nodejs.org/) or [PhantomJS](http://phantomjs.org/) instead of Rhino.
You can disable Rhino with the following sbt setting:

If you want to run this code, you can do so by enabling the fastOpt stage with
scalaJSUseRhino in Global := false

sbt> set scalaJSStage in Global := FastOptStage
sbt> run
which you can put in your `build.sbt`, or in a separate `.sbt` file, e.g.,
`local.sbt`, which is not checked in your version control.

This will invoke an external JavaScript interpreter and pass the generated file to it.
Depending on your `requiresDOM` setting (which is derived from the presence of `RuntimeDOM` in your `jsDependencies`), it will either invoke [Node.js](http://nodejs.org/) or [PhantomJS](http://phantomjs.org/).
If `RuntimeDOM` is required, `run` (and `test`) will use PhantomJS.
Otherwise, it will use Node.js.
*You need to install these separately* and make them available on the execution path (i.e. as shell commands `node` and `phantomjs`).

Note that running in the `fastOptStage` is often faster than running just after compilation because:
The section on [JavaScript environments](./js-environments.html) explains more on the topic, including finer-grained configuration.

a. As their name implies, fast optimizations are *really* fast (starting from the second run in an sbt session),
b. External virtual machines are much faster than Rhino, and
c. The code is, well, optimized, so faster itself.
## Produce one JavaScript file

We recommend you to operate in the `fastOpt` stage in your development cycle.
You can enable it by default with the following sbt setting:
To produce a proper JavaScript file from your code, you need to call the linker:

{% highlight scala %}
scalaJSStage in Global := FastOptStage
{% endhighlight %}
sbt> fastOptJS

which you can put in your `build.sbt`, or in a separate `.sbt` file, e.g.,
`local.sbt`, which is not checked in your version control.
This will perform fast Scala.js-specific optimizations and write the resulting code to a single JavaScript file. You can now use this JavaScript file in your HTML page or in whatever way you like. The resulting file in the target folder will have the suffix `-fastopt.js`.

### Disabling the optimizations

Expand Down
15 changes: 6 additions & 9 deletions doc/project/js-environments.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,14 @@ layout: doc
title: JavaScript Environments
---

In order to decide how to run JavaScript code, the Scala.js sbt plugin uses the following two setting keys:

- `preLinkJSEnv`: the JavaScript Environment (i.e. virtual machine) used to run unlinked `.sjsir` files (defaults to Rhino)
- `postLinkJSEnv`: the JavaScript Environment used to run linked JavaScript (defaults to Node.js if DOM is not required, otherwise PhantomJS)

You may change these environments at your discretion. However, note that running Rhino on linked JavaScript and Node.js or PhantomJS on unlinked JavaScript is unlikely to work or at least slow.
In order to decide how to run JavaScript code, the Scala.js sbt plugin uses the setting key `jsEnv`.
If it is not set, Scala.js uses Rhino if `scalaJSUseRhino` is `true`, and to Node.js or PhantomJS otherwise (depending on whether the DOM is required).
You can use `jsEnv` to override this default, or to provide finer-grained configuration, as shown in this section.

For example, to switch to PhantomJS, you can set:

{% highlight scala %}
postLinkJSEnv := PhantomJSEnv().value
jsEnv := PhantomJSEnv().value
{% endhighlight %}

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.
Expand All @@ -25,7 +22,7 @@ This may not be what you want, if for example you register time-outs or use WebS
You can disable this behavior with the following setting:

{% highlight scala %}
postLinkJSEnv := PhantomJSEnv(autoExit = false).value
jsEnv := PhantomJSEnv(autoExit = false).value
{% endhighlight %}

You can terminate the interpreter from your Scala code with
Expand All @@ -39,7 +36,7 @@ System.exit(0)
You can pass command-line arguments to the PhantomJS interpreter like this:

{% highlight scala %}
postLinkJSEnv := PhantomJSEnv(args = Seq("arg1", "arg2")).value
jsEnv := PhantomJSEnv(args = Seq("arg1", "arg2")).value
{% endhighlight %}

For more options of the PhantomJS environment, see
Expand Down
Loading