From cff8418eb6df1f002013ae065b3208004ee5c24c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Mon, 12 Jan 2015 10:46:57 +0100 Subject: [PATCH 01/16] Update site-wide Scala.js version to 0.6.0. --- _config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_config.yml b/_config.yml index a3666f3e..2c55853d 100644 --- a/_config.yml +++ b/_config.yml @@ -18,8 +18,8 @@ author : twitter : sjrdoeraene feedburner : feedname -scalaJSVersion: 0.5.6 -scalaJSBinaryVersion: 0.5 +scalaJSVersion: 0.6.0 +scalaJSBinaryVersion: 0.6 # The production_url is only used when full-domain names are needed # such as sitemap.txt From aada7636838617d3fba94e88123480a962abf832 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Sat, 10 Jan 2015 22:30:23 +0100 Subject: [PATCH 02/16] Review the Calling JavaScript reference. --- doc/calling-javascript.md | 300 ++++++++++++++++++++------------------ 1 file changed, 160 insertions(+), 140 deletions(-) diff --git a/doc/calling-javascript.md b/doc/calling-javascript.md index 5b4668f2..10d12cbd 100644 --- a/doc/calling-javascript.md +++ b/doc/calling-javascript.md @@ -13,22 +13,24 @@ Because JavaScript is dynamically typed, it is possible to call JS libraries in a dynamically typed way. However, it is also possible to interop with static types, for better leveraging of Scala. -## Primitive JavaScript types +## Pre-defined JavaScript types -The package `scala.scalajs.js` -([code on GitHub](https://github.com/lampepfl/scala-js/tree/master/library/src/main/scala/scala/scalajs/js)) -contains static type definitions for all the types, functions and variables -that are part of the ECMAScript 5 standard library, including the primitive -types. +Primitive JavaScript types (`number`, `boolean`, `string`, `null` and +`undefined`) are represented by their natural equivalent in Scala, as shown +in the [type equivalence table](./js-interoperability.html#type-correspondance). -The core type hierarchy is as follows: +For other pre-defined JavaScript types, such as arrays and functions, the +package `scala.scalajs.js` +([ScalaDoc]({{ site.production_url }}/api/scalajs-library/{{ site.scalaJSVersion }}/#scala.scalajs.js.package)) +provides dedicated definitions. + +The class hierarchy for these standard types is as follows: js.Any +- js.Object | +- js.Date | +- js.RegExp | +- js.Array[A] - | +- js.Dictionary[A] | +- js.Function | +- js.Function0[+R] | +- js.Function1[-T1, +R] @@ -39,97 +41,56 @@ The core type hierarchy is as follows: | +- js.ThisFunction1[-T0, -T1, +R] | +- ... | +- js.ThisFunction21[-T0, ..., -T21, +R] - +- js.prim.Number - +- js.prim.Boolean - +- js.prim.String - +- js.prim.Undefined - - -Note that the types in the `prim` package should not directly be used, -since they have a direct correspondance in Scala (see the -[interoperability](./js-interoperability.html) page). The reason they -exist is that for example a `scala.Double` can be stored in a variable -of type `js.Any` (through implicit conversion to `js.prim.Number`). - -A value of any of these types is encoded as is in JavaScript, without wrapping. -Even when such a value is assigned to a `val` of type `scala.Any` or of a -generic type, there is no boxing. E.g., a `js.Array[js.Date]` is a JavaScript -`Array` which contains JavaScript `Date`'s at runtime. - -These types have all the fields and methods available in the JavaScript API. - -There are implicit conversions from corresponding Scala types and back: - - - - - - - - - - - - - - - -
Scala typeJavaScript type
Byte
Short
Int
Long
Float
Double
js.prim.Number
(from js.prim.Number to Double only)
Booleanjs.prim.Boolean
java.lang.Stringjs.prim.String
Unitjs.prim.Undefined
Array[A]js.Array[A]
FunctionN[T1, ..., TN, R]js.FunctionN[T1, ..., TN, R]
js.ThisFunction{N-1}[T1, ..., TN, R]
- -### Remarks - -There is no type `js.Null`, because `scala.Null` can be used in its stead with -the appropriate semantics. + +- js.Dictionary[A] -`isInstanceOf[T]` is supported for _classes_ inheriting from `js.Object`, e.g., -`js.Date`, `js.Array[_]`, `js.Object` itself, and is implemented with an -`instanceof` test. +Note that most of these types are similar to standard Scala types. For example, +`js.Array[A]` is similar to `scala.Array[A]`, and `js.FunctionN` is similar to +`scala.FunctionN`. +However, they are not completely equivalent, and must not be confused. -`isInstanceOf[T]` for `T` being `js.prim.Number`, `js.prim.Boolean`, -`js.prim.String`, or `js.prim.Undefined`, is supported and is -implemented with a `typeof` test. However, it should be avoided in -preference of `T` being `Double`, `Boolean`, `String` or `Unit`. +With the exception of `js.Array[A]` and `js.Dictionary[A]`, these types have +all the fields and methods available in the JavaScript API. +The collection types feature the standard Scala collection API instead, so that +they can be used idiomatically in Scala code. -`isInstanceOf[T]` is not supported for any other `T` (i.e., traits) inheriting -from `js.Any`. -Consequently, pattern matching for such types is not supported either. - -`asInstanceOf[T]` is completely erased for any `T` inheriting from `js.Any`, -meaning that it does not perform any runtime check. +**0.5.x note**: In Scala.js 0.5.x, `js.Array[A]` and `js.Dictionary[A]` did not +really have the collection API. The methods defined in JavaScript took +precedence. This was changed in 0.6.x to avoid pitfalls when confusing the +APIs, avoiding common JavaScript warts, and improving performance. -The conversions between Scala and JS numbers, booleans, and strings has no -overhead at runtime, since they have exactly the same encoding in JavaScript. -So yes, `java.lang.String` "instances" are actually stored as primitive -strings in JavaScript. +## Function types -The previous remark is however *not true* about function types and arrays. +### `js.Function` and its subtypes -## Literal object construction +`js.FunctionN[T1, ..., TN, R]` is, as expected, the type of a JavaScript +function taking N parameters of types `T1` to `TN`, and returning a value of +type `R`. -Scala.js provides two syntaxes for creating JavaScript objects in a literal -way. The following JavaScript object +There are implicit conversions from `scala.FunctionN` to `js.FunctionN` and +back, with the obvious meaning. +These conversions are the only way to create a `js.FunctionN` in Scala.js. +For example: -{% highlight javascript %} -{foo: 42, bar: "foobar"} +{% highlight scala %} +val f: js.Function1[Double, Double] = { (x: Double) => x*x } {% endhighlight %} -can be written in Scala.js either as +defines a JavaScript `function` object which squares its argument. +This corresponds to the following JavaScript code: -{% highlight scala %} -js.Dynamic.literal(foo = 42, bar = "foobar") +{% highlight javascript %} +var f = function(x) { + return x*x; +}; {% endhighlight %} -or as +You can call a `js.FunctionN` in Scala.js with the usual syntax: {% highlight scala %} -js.Dynamic.literal("foo" -> 42, "bar" -> "foobar") +val y = f(5) {% endhighlight %} -## js.FunctionN and js.ThisFunctionN - -`js.FunctionN[T1, ..., TN, R]` is, as expected, the type of a JavaScript -function taking N parameters of types `T1` to `TN`, and returning a value of -type `R`. Conversions to/from `scala.FunctionN` have the obvious meaning. +### `js.ThisFunction` and its subtypes The series of `js.ThisFunctionN` solve the problem of modeling the `this` value of JavaScript in Scala. Consider the following call to the `each` method @@ -168,7 +129,7 @@ lis.each({ (li: dom.HTMLElement) => }: js.ThisFunction) {% endhighlight %} -Skipping over the irrelevant details, note that we parameter `li` completely +Skipping over the irrelevant details, note that the parameter `li` completely corresponds to the JavaScript `this`. Note also that we have ascribed the lambda with `: js.ThisFunction` explicitly to make sure that the right implicit conversion is being used (by default it would convert it to a `js.Function1`). @@ -194,29 +155,62 @@ var o = new Object(); var x = f.call(o, 4); {% endhighlight %} +## Literal object construction + +Scala.js provides two syntaxes for creating JavaScript objects in a literal +way. The following JavaScript object + +{% highlight javascript %} +{foo: 42, bar: "foobar"} +{% endhighlight %} + +can be written in Scala.js either as + +{% highlight scala %} +js.Dynamic.literal(foo = 42, bar = "foobar") +{% endhighlight %} + +or as + +{% highlight scala %} +js.Dynamic.literal("foo" -> 42, "bar" -> "foobar") +{% endhighlight %} + ## Defining JavaScript interfaces with traits Most JavaScript APIs work with interfaces that are defined structurally. In Scala.js, the corresponding concept are traits. To mark a trait as being a representative of a JavaScript API, it must inherit directly or indirectly -from `js.Object`. +from `js.Any` (usually from `js.Object`). JS traits can contain `val`, `var` and `def` definitions, and the latter can -be overloaded. All definitions should have `???` as body, to soothe the -compiler's soul. E.g., +be overloaded. + +All definitions must have `js.native` as body. +Any other body (including omitting the `=` altogether) will be handled as if +it were `js.native`, and a warning will be emitted. +(In Scala.js 1.0.0, this will become an error.) + +**0.5.x note**: In Scala.js 0.5.x, `js.native` did not exist. The recommended +best practice was to put `???` as body, but this was not enforced by the +compiler. This has been changed to improve intuition and remove warts. + +Here is an example giving types to a small portion of the API of `Window` +objects in browsers. {% highlight scala %} trait Window extends js.Object { - val document: DOMDocument = ??? - var location: js.String = ??? + val document: HTMLDocument = js.native + var location: String = js.native - def innerWidth: js.Number = ??? - def innerHeight: js.Number = ??? + def innerWidth: Int = js.native + def innerHeight: Int = js.native - def alert(message: js.String): Unit = ??? + def alert(message: String): Unit = js.native - def open(url: js.String, target: js.String, features: js.String = ""): Window = ??? - def close(): Unit = ??? + def open(url: String, target: String, + features: String = ""): Window = js.native + def close(): Unit = js.native } {% endhighlight %} @@ -232,8 +226,6 @@ if the result will always be the same (e.g., `document`), and `def` when subsequent accesses to the field might return a different value (e.g., `innerWidth`). -Use Scala primitive types instead of types in `js.prim._`. Use `Byte`, `Short` or `Int` where applicable (attention: `NaN` is not a value of any of these types). Otherwise `Double` should be used. `Long` is opaque to JavaScript and therefore cannot be used. `Float` is the same as `Double` and should generally not be used in JavaScript typings. - Calls to the `apply` method of an object `x` map to calling `x`, i.e., `x(...)` instead of `x.apply(...)`. @@ -254,6 +246,13 @@ It is however allowed to declare a JS trait in a top-level object. Methods can have varargs, denoted by `*` like in regular Scala. They map to JavaScript varargs, i.e., the method is called with more arguments. +`isInstanceOf[T]` is not supported for any trait `T` inheriting from `js.Any`. +Consequently, pattern matching for such types is not supported either. + +`asInstanceOf[T]` is completely erased for any `T` inheriting from `js.Any`, +meaning that it does not perform any runtime check. +It is always valid to cast anything to such a trait. + ## JavaScript field/method names and their Scala counterpart Sometimes, a JavaScript API defines fields and/or methods with names that do @@ -264,8 +263,8 @@ They can be defined in Scala in two ways. The trivial one is simply to use backquotes to escape them in Scala: {% highlight scala %} -def `val`(): js.String -def `val`(v: js.String): this.type +def `val`(): String = js.native +def `val`(v: String): this.type = js.native {% endhighlight %} However, it becomes annoying very quickly. An often better solution is to use @@ -274,9 +273,9 @@ use, which can be different from the Scala name: {% highlight scala %} @JSName("val") -def value(): js.String +def value(): String = js.native @JSName("val") -def value(v: js.String): this.type +def value(v: String): this.type = js.native {% endhighlight %} If necessary, several overloads of a method with the same name can have different @@ -295,9 +294,9 @@ A typical example can be found in the `js.Array[A]` class itself, of course: {% highlight scala %} @JSBracketAccess -def apply(index: js.Number): A +def apply(index: Int): A = js.native @JSBracketAccess -def update(index: js.Number, v: A): Unit +def update(index: Int, v: A): Unit = js.native {% endhighlight %} The Scala method names are irrelevant for the translation to JavaScript. The @@ -307,12 +306,14 @@ access on Scala's side as well, but it is not required to use these names. ## JavaScript classes It is also possible to define JavaScript *classes* as Scala classes inheriting, -directly or indirectly, from `js.Object`. The only difference compared to -traits is that classes have constructors, hence they also provide instantiation -of objects with the `new` keyword. +directly or indirectly, from `js.Any` (like traits, usually from `js.Object`). +The main difference compared to traits is that classes have constructors, hence +they also provide instantiation of objects with the `new` keyword. + +The call `new js.RegExp("[ab]*")` will map to the obvious in JavaScript, i.e., +`new RegExp("[ab]*")`, meaning that the identifier `RegExp` will be looked up +in the global scope. -The call `new RegExp("[ab]*")` will map to exactly the same thing in JavaScript, -meaning that the identifier `RegExp` will be looked up in the global scope. If it is impractical or inconvenient to declare the Scala class with the same name as the JavaScript class (e.g., because it is defined in a namespace, like `THREE.Scene`), the annotation `scala.js.annotation.JSName` can be used @@ -327,35 +328,43 @@ class Scene extends js.Object If the class does not have any constructor without argument, and it has to be subclassed, you may either decide to add a fake protected no-arg constructor, -or call an inherited constructor with `???`s. +or call an inherited constructor with `???`s as parameters. + +`isInstanceOf[C]` is supported for classes inheriting from `js.Any`. +It is implemented with an `instanceof` test. +Pattern matching, including `ClassTag`-based matching, work accordingly. + +As is the case for traits, `asInstanceOf[C]` is completely erased for any class +`C` inheriting from `js.Any`, meaning that it does not perform any runtime +check. +It is always valid to cast anything to such a class. ## Top-level JavaScript objects -JavaScript APIs often expose top-level objects with methods and fields. E.g., -the `Math` object provides methods for standard mathematical functions. These -can be declared in Scala.js with `object`'s inheriting directly or indirectly -from `js.Object`. +JavaScript APIs often expose top-level objects with methods and fields. +For example, the `JSON` object provides methods for parsing and emitting JSON +strings. +These can be declared in Scala.js with `object`'s inheriting directly or +indirectly from `js.Any` (again, often `js.Object`). {% highlight scala %} -object Math extends js.Object { - val E: js.Number = ??? - val PI: js.Number = ??? +object JSON extends js.Object { + def parse(text: String): js.Any = js.native - def sin(x: js.Number): js.Number = ??? - def min(values: js.Number*): js.Number = ??? - - ... + def stringify(value: js.Any): String = js.native } {% endhighlight %} -An access like `Math.sin(a)` will map in JavaScript to the same code, meaning -that the identifier `Math` will be looked up in the global scope. Similarly to -classes, the JavaScript name can be specified with `@JSName`, e.g., +An call like `JSON.parse(text)` will map in JavaScript to the obvious, i.e., +`JSON.parse(text)`, meaning that the identifier `JSON` will be looked up in the +global scope. + +Similarly to classes, the JavaScript name can be specified with `@JSName`, e.g., {% highlight scala %} @JSName("jQuery") object JQuery extends js.Object { - def apply(x: js.Any): JQuery + def apply(x: String): JQuery = js.native } {% endhighlight %} @@ -368,11 +377,10 @@ indirectly from `js.GlobalScope` (which itself extends `js.Object`) are considered to represent the global scope. {% highlight scala %} -object StdGlobalScope extends js.GlobalScope { - val NaN: js.Number = ??? +object DOMGlobalScope extends js.GlobalScope { + val document: HTMLDocument = js.native - def parseInt(s: js.String, radix: js.Number): js.Number = ??? - def parseInt(s: js.String): js.Number = ??? + def alert(message: String): Unit = js.native } {% endhighlight %} @@ -380,26 +388,27 @@ Note that this rule applies to package objects as well. It is often sensible to use package objects for this purpose, e.g., {% highlight scala %} -package scala +package org.scalajs -package object js extends js.GlobalScope { - val NaN: js.Number = ??? +package object dom extends js.GlobalScope { + val document: HTMLDocument = js.native - def parseInt(s: js.String, radix: js.Number): js.Number = ??? - def parseInt(s: js.String): js.Number = ??? + def alert(message: String): Unit = js.native } {% endhighlight %} ## Monkey patching -In JavaScript, a common pattern is monkey patching, where some top-level -object or class' prototype, is meant to be extended by third-party code. This +In JavaScript, monkey patching is a common pattern, where some top-level +object or class' prototype is meant to be extended by third-party code. This pattern is easily encoded in Scala.js' type system with `implicit` conversions. -E.g., in jQuery, `$.fn` can be extended with new methods that will be +For example, in jQuery, `$.fn` can be extended with new methods that will be available to so-called jQuery objects, of type `JQuery`. Such a plugin can be declared in Scala.js with a separate trait, say `JQueryGreenify`, and an implicit conversions from `JQuery` to `JQueryGreenify`. +The implicit conversion is implemented with a hard cast, since in effect we +just want to extend the API, not actually change the value. {% highlight scala %} trait JQueryGreenify extends JQuery { @@ -412,10 +421,13 @@ object JQueryGreenify { } {% endhighlight %} -Recall that `asInstanceOf[JQueryGreenify]` will be erased when mapping to -JavaScript because `JQueryGreenify` in a JS trait. +Recall that `jq.asInstanceOf[JQueryGreenify]` will be erased when mapping to +JavaScript because `JQueryGreenify` is a JS trait. +The implicit conversion is therefore a no-op and can be inlined away, which +means that this pattern does not have any runtime overhead. ## Reflective calls + Scala.js does not support reflective calls on any subtype of `js.Any`. This is mainly due to the `@JSName` annotation. Since we cannot statically enforce this restriction, reflective calls on @@ -423,6 +435,7 @@ subtypes of `js.Any` *will fail at runtime*. Therefore, we recommend to avoid reflective calls altogether. ### What is a reflective call? + Calling a method on a structural type in Scala creates a so-called reflective call. A reflective call is a type-safe method call that uses Java reflection at runtime. The following is an example of a @@ -443,12 +456,13 @@ class A { def foo(x: Int) = s"Input: $x" } print(new A()) {% endhighlight %} Note that `A` does *not* extend `T` but only conforms structurally -(i.e. it has a method `foo` with corresponding signature). +(i.e., it has a method `foo` with a matching signature). The Scala compiler issues a warning for every reflective call, unless the `scala.language.reflectiveCalls` is imported. ### Why do reflective calls not work on `js.Any`? + Since JavaScript is dynamic by nature, a reflective method lookup as in Java is not required for reflective calls. However, in order to generate the right method call, the call-site needs to know the exact @@ -475,7 +489,7 @@ global scope, with `js.Dynamic.global`, which is of type `js.Dynamic`. You can read and write any field of a `js.Dynamic`, as well as call any method with any number of arguments. All input types are assumed to be of type `js.Any`, and all output types are assumed to be of type `js.Dynamic`. This -means that you can assign a `js.Number` (or even an `Int`, through implicit +means that you can assign a `js.Array[A]` (or even an `Int`, through implicit conversion) to a field of a `js.Dynamic`. And when you receive something, you can chain any kind of call and/or field access. @@ -493,8 +507,7 @@ playground.appendChild(newP) In this example, `document`, `playground` and `newP` are all inferred to be of type `js.Dynamic`. When calling `getElementById` or assigning to the field -`innerHTML`, the String is implicitly converted to a `js.String` to conform to -`js.Any`. +`innerHTML`, the `String` is implicitly converted to `js.Any`. And since `js.Dynamic` inherits from `js.Any`, it is also valid to pass `newP` as a parameter to `appendChild`. @@ -524,3 +537,10 @@ import js.Dynamic.{ global => g, newInstance => jsnew } val today = jsnew(g.Date)() {% endhighlight %} + +When using `js.Dynamic`, you are very close to writing raw JavaScript within +Scala.js, with all the warts of the language coming to haunt you. +However, to get the full extent of JavaScriptish code, you can import the +implicit conversions in +[js.DynamicImplicts]({{ BASE_PATH }}/api/scalajs-library/{{ site.scalaJSVersion }}/#scala.scalajs.js.DynamicImplicits$). +Use at your own risk! From a59a83bd214646e699c5aea3c318dde03c0cc45c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Sun, 11 Jan 2015 13:40:06 +0100 Subject: [PATCH 03/16] Update documentation on semantics. --- doc/semantics.md | 174 +++++++++++++++++++++++++++++------------------ 1 file changed, 107 insertions(+), 67 deletions(-) diff --git a/doc/semantics.md b/doc/semantics.md index 73272ffe..858d7f1f 100644 --- a/doc/semantics.md +++ b/doc/semantics.md @@ -5,42 +5,54 @@ tagline: and how they differ from Scala --- {% include JB/setup %} -Because the target platform of Scala.js is quite different from that of Scala, -a few language semantics differences exist. +In general, the semantics of the Scala.js language are the same as Scala on +the JVM. +However, a few differences exist, which we mention here. -## Numbers and characters +## Primitive data types -Numbers and characters have the same semantics as on the JVM -(including overflow and full 64-bit Longs) with the following four -exceptions. For information about how Scala numeric types map to -JavaScript numeric types, have a look at the -[interoparability guide](./js-interoperability.html). +All primitive data types work exactly as on the JVM, with the following three +exceptions. -### Floats may behave like Doubles -Since JavaScript doesn't have a native float type, we sometimes represent Floats -using doubles/numbers, rather than with lower-precision 32-bit floats. +### Floats can behave as Doubles by default -The choice of how to represent floats is up to the implementation. You may not rely on floats providing 64-bit floating point precision. +Scala.js underspecifies the behavior of `Float`s by default. +Any `Float` value can be stored as a `Double` instead, and any operation on +`Float`s can be computed with double precision. +The choice of whether or not to behave as such, when and where, is left to the +implementation. -Float literals are truncated to their (binary) -precision. However, output does not truncate to that precision. This -can lead to the following behavior (this works as expected when using -doubles): +If exact single precision operations are important to your application, you can +enable strict-floats semantics in Scala.js, with the following sbt setting: {% highlight scala %} -println(13.345f) -// Scala: 13.345 -// Scala.js: 13.345000267028809 +scalaJSSemantics ~= { _.withStrictFloats(true) } {% endhighlight %} -### Integer division by 0 is undefined -Unlike the JVM where dividing an integer type by 0 throws an -exception, in Scala.js integer division by 0 is undefined. -This allows for efficient implementation of division. Dividing a -`Double` or `Float` by 0 yields positive or negative infinity as -expected. +Note that this can have a major impact on performance of your application on +JS interpreters that do not support +[the `Math.fround` function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/fround). + +### `toString` of `Float`, `Double` and `Unit` + +`x.toString()` returns slightly different results for floating point numbers +and `()` (`Unit`). + +{% highlight scala %} +().toString // "undefined", instead of "()" +1.0.toString // "1", instead of "1.0" +1.4f.toString // "1.399999976158142" instead of "1.4" +{% endhighlight %} + +In general, a trailing `.0` is omitted. +Floats print in a weird way because they are printed as if they were Doubles, +which means their lack of precision shows up. + +To get sensible and portable string representation of floating point numbers, +use `String.format()` or related methods. + +### Runtime type tests are based on values -### isInstanceOf tests are based on value Instance tests (and consequently pattern matching) on any of `Byte`, `Short`, `Int`, `Float`, `Double` are based on the value and not the type they were created with. The following are examples: @@ -48,44 +60,83 @@ type they were created with. The following are examples: - 1 matches `Byte`, `Short`, `Int`, `Float`, `Double` - 128 (`> Byte.MaxValue`) matches `Short`, `Int`, `Float`, `Double` - 32768 (`> Short.MaxValue`) matches `Int`, `Float`, `Double` +- 2147483647 matches `Int`, `Double` if strict-floats are enabled + (because that number cannot be represented in a strict 32-bit `Float`), + otherwise `Int`, `Float` and `Double` - 2147483648 (`> Int.MaxValue`) matches `Float`, `Double` -- 1.2 matches `Float`, `Double` +- 1.5 matches `Float`, `Double` +- 1.4 matches `Double` only if strict-floats are enabled, + otherwise `Float` and `Double` + (unlike 1.5, the value 1.4 cannot be represented in a strict 32-bit `Float`) +- `NaN`, `Infinity`, `-Infinity` and `-0.0` match `Float`, `Double` + +As a consequence, the following apparent subtyping relationships hold: + + Byte <:< Short <:< Int <:< Double + <:< Float <:< -As a consequence, the following apparent subtyping relationship holds: +if strict-floats are enabled, or Byte <:< Short <:< Int <:< Float =:= Double -### toString for integral Floats and Doubles -Calling `toString` on a Float or a Double that holds an integral -value, will not append ".0" to that value: +otherwise. -{% highlight scala %} -println(1.0) -// Scala: 1.0 -// Scala.js: 1 -{% endhighlight %} +## Undefined behaviors -This is due to how numeric values are represented at runtime in -Scala.js. Use a formatting interpolator if you always want to show -decimals: +The JVM is a very well specified environment, which even specifies how some +bugs are reported as exceptions. +Some examples are: -{% highlight scala %} -val x = 1.0 -println(f"$x%.1f") -// Scala: 1.0 -// Scala.js: 1.0 -{% endhighlight %} +* `NullPointerException` +* `ArrayIndexOutOfBoundsException` and `StringIndexOutOfBoundsException` +* `ClassCastException` +* `ArithmeticException` (such as integer division by 0) +* `StackOverflowError` and other `VirtualMachineError`s + +Because Scala.js does not receive VM support to detect such erroneous +conditions, checking them is typically too expensive. + +Therefore, all of these are considered +[undefined behavior](http://en.wikipedia.org/wiki/Undefined_behavior). + +Some of these, however, can be configured to be compliant with the JVM +specification using sbt settings. +Currently, only `ClassCastException`s (thrown by invalid `asInstanceOf` calls) +are configurable, but the list will probably expand in future versions. -## Unit -`scala.Unit` is represented using JavaScript's `undefined`. Therefore, -calling `toString()` on `Unit` will return `undefined` rather than -`()`. +Every configurable undefined behavior has 3 possible modes: -## Strings +* `Compliant`: behaves as specified on a JVM +* `Unchecked`: completely unchecked and undefined +* `Fatal`: checked, but throws + [`UndefinedBehaviorError`s]({{ BASE_PATH }}/api/scalajs-library/{{ site.scalaJSVersion }}/#scala.scalajs.runtime.UndefinedBehaviorError) + instead of the specified exception. -JavaScript uses UCS-2 for encoding strings and does not support -conversion to or from other character sets. As a result, `String` -constructors taking `Byte` arrays are not supported by Scala.js. +By default, undefined behaviors are in `Fatal` mode for `fastOptJS` and in +`Unchecked` mode for `fullOptJS`. +This is so that bugs can be detected more easily during development, with +predictable exceptions and stack traces. +In production code (`fullOptJS`), the checks are removed for maximum +efficiency. + +`UndefinedBehaviorError`s are *fatal* in the sense that they are not matched by +`case NonFatal(e)` handlers. +This makes sure that they always crash your program as early as possible, so +that you can detect and fix the bug. +It is *never* OK to catch an `UndefinedBehaviorError` (other than in a testing +framework), since that means your program will behave differently in `fullOpt` +stage than in `fastOpt`. + +If you need a particular kind of exception to be thrown in compliance with the +JVM semantics, you can do so with an sbt setting. +For example, this setting enables compliant `asInstanceOf`s: + +{% highlight scala %} +scalaJSSemantics ~= { _.withAsInstanceOfs( + org.scalajs.core.tools.sem.CheckedBehavior.Compliant) } +{% endhighlight %} + +Note that this will have (potentially major) performance impacts. ## JavaScript interoperability @@ -99,17 +150,6 @@ Java reflection and, a fortiori, Scala reflection, are not supported. There is limited support for `java.lang.Class`, e.g., `obj.getClass.getName` will work for any Scala.js object (not for objects that come from JavaScript interop). -## Exceptions - -In general, Scala.js supports exceptions, including catching them based on their -type. However, exceptions that are typically triggered by the JVM have flaky -semantics, in particular: - -- `ArrayIndexOutOfBoundsException` is never thrown. -- `NullPointerException` is reported as JavaScript `TypeError` instead. -- `StackOverflowError` is unsupported since the underlying JavaScript exception - type varies based on the browser. - ## Regular expressions [JavaScript regular expressions](http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Guide:Regular_Expressions) @@ -129,7 +169,7 @@ affected is given here: `scala.Symbol` is supported, but is a potential source of memory leaks in applications that make heavy use of symbols. The main reason is that JavaScript does not support weak references, causing all symbols created -by Scala.js tow remain in memory throughout the lifetime of the application. +by Scala.js to remain in memory throughout the lifetime of the application. ## Enumerations @@ -151,12 +191,12 @@ are statically rewritten to (a slightly more complicated version of): {% highlight scala %} val = Value("") -val = Value(,"") +val = Value(, "") {% endhighlight %} Note that this also includes calls like {% highlight scala %} -val A,B,C,D = Value +val A, B, C, D = Value {% endhighlight %} since they are desugared into separate val definitions. From f72e1d9ccd5d679c7b09c00a37510a106a3d2413 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Sun, 11 Jan 2015 15:13:33 +0100 Subject: [PATCH 04/16] Update the tutorial for 0.6.0. --- doc/tutorial.md | 147 ++++++++++++++++++++++++++---------------------- 1 file changed, 81 insertions(+), 66 deletions(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index 95b1175b..6b522785 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -18,38 +18,34 @@ First create a new folder where your sbt project will go. To setup Scala.js in a new sbt project, we need to do two things: -1. Add the Scala.js sbt plugin -2. Apply the Scala.js specific settings to the project +1. Add the Scala.js sbt plugin to the build +2. Enable the plugin in the project Adding the Scala.js sbt plugin is a one-liner in `project/plugins.sbt` (all file names we write in this tutorial are relative to the project root): {% highlight scala %} -addSbtPlugin("org.scala-lang.modules.scalajs" % "scalajs-sbt-plugin" % "{{ site.scalaJSVersion }}") +addSbtPlugin("org.scala-js" % "sbt-scalajs" % "{{ site.scalaJSVersion }}") {% endhighlight %} -We also setup basic project settings and Scala.js settings in the sbt build file (`build.sbt`, in the project root directory): +We also setup basic project settings and enable this plugin in the sbt build file (`build.sbt`, in the project root directory): {% highlight scala %} -scalaJSSettings +enablePlugins(ScalaJSPlugin) name := "Scala.js Tutorial" -scalaVersion := "2.11.2" +scalaVersion := "2.11.5" // or any other Scala version >= 2.10.2 {% endhighlight %} -Last, we need a `project/build.properties` to specify the sbt version: +Last, we need a `project/build.properties` to specify the sbt version (>= 0.13.7): {% highlight scala %} -sbt.version=0.13.5 +sbt.version=0.13.7 {% endhighlight %} That is all we need to configure the build. -If at this point you prefer to use Eclipse or IDEA as your IDE, you may use [sbteclipse](https://github.com/typesafehub/sbteclipse/wiki/Using-sbteclipse) or [sbt-idea](https://github.com/mpeltonen/sbt-idea) project files for the IDE. Note that for compiling and running your application, you will still need to use sbt from the command line. - -#### Alternative versions - -You may instead use 2.10.2, 2.10.3, 2.10.4, 2.11.0 or 2.11.1 for `scalaVersion` if you so wish. Similarly, any 0.13.x version of sbt should work without itch, for example 0.13.5. +If at this point you prefer to use Eclipse or IDEA as your IDE, you may use [sbteclipse](https://github.com/typesafehub/sbteclipse/wiki/Using-sbteclipse) to generate an Eclipse project, or import the sbt build from IDEA. Note that for compiling and running your application, you will still need to use sbt from the command line. ### HelloWorld application @@ -78,17 +74,52 @@ As you expect, this will simply print "HelloWorld" when run. To run this, simply **Troubleshooting**: Should you experience errors with the `PermGen` size of the JVM at this point, you can increase it. Refer, for example, to [this StackOverflow question](http://stackoverflow.com/questions/8331135/transient-outofmemoryerror-when-compiling-scala-classes). -Congratulations! You have successfully compiled and run your first Scala.js application. The code is actually run by a JavaScript interpreter. If you do not believe this (it happens to us occasionally), you can use sbt's `last`: +Congratulations! You have successfully compiled and run your first Scala.js application. The code is actually run by a JavaScript interpreter. If you do not believe this (it happens to us occasionally), you can use the `last` command in sbt: > last (...) [info] Running tutorial.webapp.TutorialApp - [debug] with JSEnv of type class scala.scalajs.sbtplugin.env.rhino.RhinoJSEnv - [debug] with classpath of type class scala.scalajs.tools.classpath.CompleteIRClasspath + [debug] with JSEnv of type class org.scalajs.jsenv.rhino.RhinoJSEnv + [debug] with classpath of type class org.scalajs.core.tools.classpath.IRClasspath [success] (...) So your code has actually been executed by the [Rhino](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Rhino) JavaScript interpreter. +### Run with Node.js (optional, but recommended) + +Rhino is cool because it runs out of the box, without having to install anything. +But it is *terribly* slow. +In general, you do not want to use it for your day-to-day development. + +[Node.js](http://nodejs.org/) is a much more performant JavaScript engine. +To run your code with Node.js, you need to install it, and enable +`FastOptStage` in sbt using this command: + + > set scalaJSStage in Global := FastOptStage + > run + [info] Fast optimizing C:\Users\Sepi\Documents\Projets\scalajs-tutorial\target\scala-2.11\scala-js-tutorial-fastopt.js + [info] Running tutorial.webapp.TutorialApp + Hello world! + [success] (...) + +The `last` command now shows that this was run with Node.js: + + > last + (...) + [info] Running tutorial.webapp.TutorialApp + [debug] with JSEnv of type class org.scalajs.jsenv.nodejs.NodeJSEnv + [debug] with classpath of type class org.scalajs.core.tools.classpath.LinkedClasspath + [success] (...) + +The stage needs to be set once per sbt session. +Alternatively, you can include the setting directly in your `build.sbt`, or, +in order not to disturb your teammates, in a separate `.sbt` file (say, +`local.sbt`): + + scalaJSStage in Global := FastOptStage + +This will enable the fastOpt stage by default when launching sbt. + ## Step 2: Integrating with HTML Now that we have a simple JavaScript application, we would like to use it in an HTML page. To do this, we need two steps: @@ -106,9 +137,11 @@ To generate a single JavaScript file using sbt, just use the `fastOptJS` task: This will perform some fast optimizations and generate the `target/scala-2.11/scala-js-tutorial-fastopt.js` file containing the JavaScript code. +(It is possible that the `[info]` does not appear, if you have just run the program in fastOpt mode.) + ### Create the HTML Page -To load and launch the created JavaScript, you will need an HTML file. Create the file `scalajs-tutorial-fastopt.html` (or whatever name you prefer, for example `index-fastopt.html`) in the project root with the following content. We will go in the details right after. +To load and launch the created JavaScript, you will need an HTML file. Create the file `scalajs-tutorial-fastopt.html` (or whatever name you prefer, for example `index-dev.html`) in the project root with the following content. We will go in the details right after. {% highlight html %} @@ -138,14 +171,15 @@ If you now open the newly created HTML page in your favorite browser, you will s ## Step 3: Using the DOM -As the last step has shown, running JavaScript inside a HTML page is not particularly useful if you cannot interact with the page. JavaScript provides the DOM API to interact with the page. +As the last step has shown, running JavaScript inside an HTML page is not particularly useful if you cannot interact with the page. +That's what the DOM API is for. ### Adding the DOM Library To use the DOM, it is best to use the statically typed Scala.js DOM library. To add it to your sbt project, add the following line to your `build.sbt`: {% highlight scala %} - libraryDependencies += "org.scala-lang.modules.scalajs" %%% "scalajs-dom" % "0.6" +libraryDependencies += "org.scala-js" %%% "scalajs-dom" % "0.7.0" {% endhighlight %} sbt-savvy folks will notice the `%%%` instead of the usual `%%`. It means we are using a Scala.js library and not a normal Scala library. Have a look at the [Depending on Libraries](./sbt/depending.html) guide for details. Don't forget to reload the build file if sbt is still running: @@ -168,7 +202,8 @@ import org.scalajs.dom import dom.document {% endhighlight %} -`dom` is the root of the JavaScript DOM and corresponds to the `window` object in JavaScript. We additionally import `document` (which corresponds to `document` in JavaScript) for convenience. +`dom` is the root of the JavaScript DOM and corresponds to the global scope of Script (aka the `window` object). +We additionally import `document` (which corresponds to `document` in JavaScript) for convenience. We now create a method that allows us to append a `

` tag with a given text to a given node: @@ -223,7 +258,7 @@ def addClickedMessage(): Unit = { } {% endhighlight %} -You will notice the `@JSExport` annotation. It tells the Scala.js compiler to make a method callable from JavaScript. We must also import this annotation: +You will notice the `@JSExport` annotation. It tells the Scala.js compiler to make that method callable from JavaScript. We must also import this annotation: {% highlight scala %} import scala.scalajs.js.annotation.JSExport @@ -245,10 +280,10 @@ Larger web applications have a tendency to set up reactions to events in JavaScr ### Depending on jQuery -Just like for the DOM, there is a typed library for jQuery, especially packaged for Scala.js. Replace the `libraryDependencies += ...` line in your `build.sbt` by: +Just like for the DOM, there is a typed library for jQuery available in Scala.js. Replace the `libraryDependencies += ...` line in your `build.sbt` by: {% highlight scala %} - libraryDependencies += "org.scala-lang.modules.scalajs" %%% "scalajs-jquery" % "0.6" +libraryDependencies += "be.doeraene" %%% "scalajs-jquery" % "0.7.0" {% endhighlight %} Since we won't be using the DOM directly, we don't need the old library anymore. Note that the jQuery library internally depends on the DOM, but we don't have to care about this. sbt takes care of it automatically. @@ -289,16 +324,14 @@ An option is to include `jquery.js` from an external source, such as [jsDelivr]( {% endhighlight %} -This can easily become very cumbersome, if you depend on multiple libraries. The Scala.js sbt plugin provides a mechanism for libraries to declare the plain JavaScript libraries they depend on and bundle them in single file. All you have to do is activate this and then include the file. +This can easily become very cumbersome, if you depend on multiple libraries. The Scala.js sbt plugin provides a mechanism for libraries to declare the plain JavaScript libraries they depend on and bundle them in a single file. All you have to do is activate this and then include the file. In your `build.sbt`, set: {% highlight scala %} - skip in ScalaJSKeys.packageJSDependencies := false +skip in packageJSDependencies := false {% endhighlight %} -As an alternative to prefixing with `ScalaJSKeys`, you may import all its members (`import ScalaJSKeys._`). Most of the documentation omits the `ScalaJSKeys` prefix for brevity. - After reloading and rerunning `fastOptJS`, this will create `scala-js-tutorial-jsdeps.js` containing all JavaScript libraries next to the main JavaScript file. We can then simply include this file and don't need to worry about JavaScript libraries anymore: {% highlight html %} @@ -333,7 +366,8 @@ We now have an application whose UI is completely setup from within Scala.js. Th ## Step 6: Testing -In this section we will show how such an application can be tested using [uTest](http://github.com/lihaoyi/utest), a tiny testing framework which compiles to both Scala.js and Scala JVM. As a note aside, this framework is also a good choice to test libraries that cross compile. See our [cross compiliation guide](./sbt/cross-building.html) for details. +In this section we will show how such an application can be tested using [uTest](http://github.com/lihaoyi/utest), a tiny testing framework which compiles to both Scala.js and Scala JVM. +As a note aside, this framework is also a good choice to test libraries that cross compile. See our [cross compilation guide](./sbt/cross-building.html) for details. ### Supporting the DOM @@ -347,55 +381,34 @@ Before we start writing tests which we will be able to run through the sbt conso [error] (compile:run) Exception while running JS code: ReferenceError: "window" is not defined. (/home/ts/.ivy2/cache/org.webjars/jquery/jars/jquery-1.10.2.jar#META-INF/resources/webjars/jquery/1.10.2/jquery.js#14) [error] (...) -What basically happens here, is that jQuery (yes, it is included automatically) tries to access the `window` object of the DOM, which doesn't exist by default in the Rhino runner. To make the DOM available in Rhino, add the following to your `build.sbt`: +What basically happens here is that jQuery (yes, it is included automatically) tries to access the `window` object of the DOM, which doesn't exist by default in the Rhino and Node.js runners. +To make the DOM available, add the following to your `build.sbt`: {% highlight scala %} -ScalaJSKeys.jsDependencies += scala.scalajs.sbtplugin.RuntimeDOM +jsDependencies += RuntimeDOM {% endhighlight %} +If you use the fastOpt stage, this will switch to running your code with [PhantomJS](http://phantomjs.org/) instead of Node.js, which you need to install. +Otherwise, in Rhino, a fake DOM is automatically made available. + After reloading, you can invoke `run` successfully: > run [info] Running tutorial.webapp.TutorialApp [success] (...) -Just like other library dependencies, this setting applies transitively: if you depend on a library that depends on the DOM, the you depend on the DOM as well. - -### Running with Node.js or PhantomJS - -This step is optional and requires installing PhantomJS. You may skip it if you like. - -You can run your Scala.js code after the fast-optimization stage using [Node.js](http://nodejs.org/) or [PhantomJS](http://phantomjs.org/). The sbt plugin defaults to Node.js and only runs PhantomJS if the project depends on `RuntimeDOM`. Note that you need to install Node.js and/or PhantomJS separately for this to work (also see the note about running [Node.js on Ubuntu](./sbt/js-envs.html#node-on-ubuntu)). - -After installing [PhantomJS](http://phantomjs.org/), you can invoke: - - > fastOptStage::run - [info] Running tutorial.webapp.TutorialApp - [success] (...) - -If you remember the `last` command from the beginning, you can use it to check that we are actually running PhantomJS: - - > last - (...) - [debug] with JSEnv of type class scala.scalajs.sbtplugin.env.phantomjs.PhantomJSEnv - [debug] with classpath of type class scala.scalajs.tools.classpath.CompleteCIClasspath$SimpleCompleteCIClasspath - [debug] PhantomJS using webpage launcher at: /tmp/phantomjs-launcher-webpage2065180431563237581.html - [success] (...) - -This even shows you the temporary webpage the plugin generates to launch PhantomJS. This can be useful for debugging. +Just like other library dependencies, this setting applies transitively: if you depend on a library that depends on the DOM, then you depend on the DOM as well. ### Adding uTest -According to the [explanation in uTest's readme](http://github.com/lihaoyi/utest#scalajs-and-sbt), we add the following to our `build.sbt`: +Using a testing framework in Scala.js is not much different than on the JVM. +It typically boils down to two sbt settings in the `build.sbt` file. +For uTest, these are: {% highlight scala %} -utest.jsrunner.Plugin.utestJsSettings -{% endhighlight %} +libraryDependencies += "com.lihaoyi" %%% "utest" % "0.2.5" % "test" -And the following to our `project/plugins.sbt`: - -{% highlight scala %} -addSbtPlugin("com.lihaoyi" % "utest-js-plugin" % "0.2.3") +testFrameworks += new TestFramework("utest.runner.Framework") {% endhighlight %} We are now ready to add a first simple test suite (`src/test/scala/tutorial/webapp/TutorialTest.scala`): @@ -438,11 +451,12 @@ To run this test, simply invoke the `test` task: [info] Failed: 0 [success] (...) -We have successfully created a simple test. Note that just like for `run`, you can run `fastOptStage::test`. Of course you'll need PhantomJS installed. It is possible that you see some warnings from the fast-optimizer, these come from uTest: It references Java classes which do not exist in Scala.js (mainly concurrency related). +We have successfully created a simple test. +Just like `run`, the `test` task uses Rhino by default, or Node.js/PhantomJS in fastOpt stage. ### A more complex test -We also would like to test the functionality of our button. For this we face another small issue: The button doesn't exist when testing, since the tests start with an empty DOM tree. To solve this, we create the button in the `setupUI` method and remove it from the HTML: +We also would like to test the functionality of our button. For this we face another small issue: the button doesn't exist when testing, since the tests start with an empty DOM tree. To solve this, we create the button in the `setupUI` method and remove it from the HTML: {% highlight scala %} jQuery("""""") @@ -505,16 +519,17 @@ Size is critical for JavaScript code on the web. To compress the compiled code e [info] Closure: 0 error(s), 0 warning(s) [success] (...) -Note that this can take a while on a larger project (tens of seconds) we do therefore not recommend to use `fullOptJS` during development. If you have used the `fastOptStage` before, there is an equivalent `fullOptStage` to run code after full optimization. +Note that this can take a while on a larger project (tens of seconds), which is why we typically don't use `fullOptJS` during development, but `fastOptJS` instead. +If you have used the `FastOptStage` before, there is a corresponding `FullOptStage` to run code after full optimization. ### Automatically Creating a Launcher Before creating another HTML file which includes the fully optimized JavaScript, we are going to introduce another feature of the sbt plugin. Since the sbt plugin is able to detect the `JSApp` object of the application, there is no need to repeat this in the HTML file. If you add the following setting to your `build.sbt`, sbt will create a `scala-js-tutorial-launcher.js` file which calls the main method: {% highlight scala %} - ScalaJSKeys.persistLauncher in Compile := true +persistLauncher in Compile := true - ScalaJSKeys.persistLauncher in Test := false +persistLauncher in Test := false {% endhighlight %} We set `persistLauncher` to false for testing, since we do not have an application to run. In our HTML page, we can now include this file instead of the manual launcher: From ea16b161447f86cd4b2df8cb690e4da0b019c1a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Sun, 11 Jan 2015 20:56:08 +0100 Subject: [PATCH 05/16] Update the sbt plugin documentation. --- doc/sbt/cross-building.md | 108 ++++++++++++++++++++++---------------- doc/sbt/depending.md | 14 ++--- doc/sbt/js-envs.md | 23 +++++--- doc/sbt/run.md | 60 ++++++++++++--------- doc/sbt/setup.md | 21 ++++---- 5 files changed, 129 insertions(+), 97 deletions(-) diff --git a/doc/sbt/cross-building.md b/doc/sbt/cross-building.md index 9504a3bb..431fac4f 100644 --- a/doc/sbt/cross-building.md +++ b/doc/sbt/cross-building.md @@ -3,48 +3,64 @@ layout: page title: Cross-Building --- -Sometimes it is desirable to compile the same source code with Scala.js and Scala JVM. In order to do this, you need two different projects, one for Scala.js and one for Scala JVM and a folder with the shared source code. You then can tell sbt to use the shared source folder in addition to the normal source locations. +It is often desirable to compile the same source code with Scala.js and Scala JVM. +In order to do this, you need two different projects, one for Scala.js and one for Scala JVM and a folder with the shared source code. +You can then tell sbt to use the shared source folder in addition to the normal source locations. + +To do this, we provide a builder, `crossProject`, which constructs two related sbt projects, one for the JVM, and one for JS. +See [the ScalaDoc of `CrossProject`]({{ BASE_PATH }}/api/sbt-scalajs/{{ site.scalaJSVersion }}/#org.scalajs.sbtplugin.cross.CrossProject) +for examples and documentation. We give a simple example of how such a project, we call it `foo`, could look. You can find this project on [GitHub](https://github.com/scala-js/scalajs-cross-compile-example). ## Directory Structure - +- foo-jvm + +- jvm | +- src/main/scala - +- foo-js + +- js | +- src/main/scala - +- foo-shared + +- shared +- src/main/scala -In `foo-shared/src/main/scala` are the shared source files. In `foo-{js|jvm}/src/main/scala` are the source files specific to the respective platform (these folders are optional). +In `shared/src/main/scala` are the shared source files. +In `{js|jvm}/src/main/scala` are the source files specific to the respective platform (these folders are optional). ## sbt Build File -Starting from sbt 0.13, you can write a multi-project build in a `.sbt` file. This is an example how your `build.sbt` could look like: - - name := "Foo root project" - - version := "0.1" - - lazy val root = project.in(file(".")).aggregate() - - lazy val fooJS = project.in(file("foo-js")).settings(scalaJSSettings: _*).settings( - name := "foo", - unmanagedSourceDirectories in Compile += - (baseDirectory in root).value / "foo-shared" / "src" / "main" / "scala" - ) - - lazy val fooJVM = project.in(file("foo-jvm")).settings( - name := "foo", - unmanagedSourceDirectories in Compile += - (baseDirectory in root).value / "foo-shared" / "src" / "main" / "scala" - ) +This is an example how your `build.sbt` could look like: + +{% highlight scala %} +name := "Foo root project" + +lazy val root = project.in(file(".")). + aggregate(fooJS, fooJVM). + settings( + publish := {}, + publishLocal := {} + ) + +lazy val foo = crossProject.in(file(".")). + settings( + name := "foo", + version := "0.1-SNAPSHOT", + scalaVersion := "2.11.5" + ). + jvmSettings( + // Add JVM-specific settings here + ). + jsSettings( + // Add JS-specific settings here + ) + +lazy val fooJVM = foo.jvm +lazy val fooJS = foo.js +{% endhighlight %} You now have separate projects to compile towards Scala.js and Scala JVM. Note the same name given to both projects, this allows them to be published with corresponding artifact names: -- `foo_2.10-0.1-SNAPSHOT.jar` -- `foo_sjs{{ site.scalaJSBinaryVersion }}_2.10-0.1-SNAPSHOT.jar` +- `foo_2.11-0.1-SNAPSHOT.jar` +- `foo_sjs{{ site.scalaJSBinaryVersion }}_2.11-0.1-SNAPSHOT.jar` If you do not publish the artifacts, you may choose different names for the projects. @@ -52,21 +68,25 @@ If you do not publish the artifacts, you may choose different names for the proj 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: - val dependencySettings = Seq( - 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" - ) +{% highlight scala %} +lazy val foo = crossProject.in(file(".")). + settings( + // other settings + libraryDependencies += "com.lihaoyi" %%% "scalatags" % "0.4.3" + ) +{% endhighlight %} + +instead of the more repetitive variant: + +{% highlight scala %} +lazy val foo = crossProject.in(file(".")). + settings( + // other settings + ). + jvmSettings( + libraryDependencies += "com.lihaoyi" %% "scalatags" % "0.4.3" + ). + jsSettings( + libraryDependencies += "com.lihaoyi" %%% "scalatags" % "0.4.3" + ) +{% endhighlight %} diff --git a/doc/sbt/depending.md b/doc/sbt/depending.md index 90f19311..a7e6bd4d 100644 --- a/doc/sbt/depending.md +++ b/doc/sbt/depending.md @@ -8,13 +8,13 @@ title: Depending on Libraries To be able to use a Scala library in Scala.js, it has to be separately compiled for Scala.js. You then can add it to your library dependencies as follows: {% highlight scala %} -libraryDependencies += "org.scala-lang.modules.scalajs" %%% "scalajs-dom" % "0.6" +libraryDependencies += "org.scala-js" %%% "scalajs-dom" % "0.7.0" {% endhighlight %} Note the `%%%` (instead of the usual `%%`) which will add the current Scala.js version to the artifact name. This allows to - Cross-publish libraries to different Scala.js versions -- Disambiguate Scala.js from Scala JVM libraries +- Disambiguate Scala.js artifacts from their JVM counterparts 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. @@ -32,12 +32,6 @@ This will fetch the required JAR containing jQuery. However, it will not include The Scala.js sbt plugin has `jsDependencies` for this purpose. You can write: -{% highlight scala %} -ScalaJSKeys.jsDependencies += "org.webjars" % "jquery" % "1.10.2" / "jquery.js" -{% endhighlight %} - -or, with `import ScalaJSKeys._`: - {% highlight scala %} jsDependencies += "org.webjars" % "jquery" % "1.10.2" / "jquery.js" {% endhighlight %} @@ -48,7 +42,7 @@ This will make your project depend on the respective WebJar and include a file n {% endhighlight %} -All `jsDependencies` and associated metadata (e.g. for ordering) are persisted in a file (called `JS_DEPENDENCIES`) and shipped with the artifact your project publishes. For example, if you depend on the `jasmine-test-framework` package for Scala.js (a thin wrapper around Jasmine), you do not need to explicitly depend or include `jasmine.js`; this mechanism does it for you. +All `jsDependencies` and associated metadata (e.g. for ordering) are persisted in a file (called `JS_DEPENDENCIES`) and shipped with the artifact your project publishes. For example, if you depend on the `scalajs-jquery` package for Scala.js, you do not need to explicitly depend or include `jquery.js`; this mechanism does it for you. Note: This will **not** dump the JavaScript libraries in the file containing your compiled Scala.js code as this would not work across all JavaScript virtual machines. However, the Scala.js plugin can generate a separate file that contains all raw JavaScript dependencies (see [below](#packageJSDependencies)). @@ -95,7 +89,7 @@ This will look for `myJSLibrary.js` in the resources and include it. It is an er If you want all JavaScript dependencies to be concatenated to a single file (for easy inclusion into a HTML file for example), you can set: {% highlight scala %} -skip in ScalaJSKeys.packageJSDependencies := false +skip in packageJSDependencies := false {% endhighlight %} in your project settings. The resulting file in the target folder will have the suffix `-jsdeps.js`. diff --git a/doc/sbt/js-envs.md b/doc/sbt/js-envs.md index ea10c6e9..b623a58f 100644 --- a/doc/sbt/js-envs.md +++ b/doc/sbt/js-envs.md @@ -5,14 +5,16 @@ title: JavaScript Environments In order to decide how to run JavaScript code, the Scala.js sbt plugin uses the following two setting keys: -- `ScalaJSKeys.preLinkJSEnv` the JavaScript Environment (i.e. virtual machine) used to run unlinked `.sjsir` files (defaults to Rhino) -- `ScalaJSKeys.postLinkJSEnv` the JavaScript Environment used to run linked JavaScript (defaults to Node.js if DOM is not required, otherwise PhantomJS) +- `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. For example, to switch to PhantomJS, you can set: - ScalaJSKeys.postLinkJSEnv := new scala.scalajs.sbtplugin.env.phantomjs.PhantomJSEnv +{% highlight scala %} +postLinkJSEnv := 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. @@ -23,8 +25,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 %} -ScalaJSKeys.postLinkJSEnv := new scala.scalajs.sbtplugin.env.phantomjs.PhantomJSEnv( - autoExit = false) +postLinkJSEnv := PhantomJSEnv(autoExit = false).value {% endhighlight %} You can terminate the interpreter from your Scala code with @@ -38,10 +39,12 @@ System.exit(0) 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")) +postLinkJSEnv := PhantomJSEnv(args = Seq("arg1", "arg2")).value {% endhighlight %} +For more options of the PhantomJS environment, see +[the ScalaDoc of `PhantomJSEnv`]({{ BASE_PATH }}/api/sbt-scalajs/{{ site.scalaJSVersion }}/#org.scalajs.sbtplugin.ScalaJSPlugin$$AutoImport$). + ## 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`). @@ -51,5 +54,9 @@ You have two options to solve this: 1. Install [nodejs-legacy](http://packages.ubuntu.com/utopic/nodejs-legacy) which will add an alias called `node` 2. Explicitly tell the Node.js environment the name of the command: - ScalaJSKeys.postLinkJSEnv := new scala.scalajs.sbtplugin.env.nodejs.NodeJSEnv("nodejs") +{% highlight scala %} +postLinkJSEnv := NodeJSEnv(executable = "nodejs").value +{% endhighlight %} +For more options of the Node.js environment, see +[the ScalaDoc of `NodeJSEnv`]({{ BASE_PATH }}/api/sbt-scalajs/{{ site.scalaJSVersion }}/#org.scalajs.sbtplugin.ScalaJSPlugin$$AutoImport$). diff --git a/doc/sbt/run.md b/doc/sbt/run.md index 1ff19049..73d23825 100644 --- a/doc/sbt/run.md +++ b/doc/sbt/run.md @@ -15,9 +15,12 @@ You now can run your application already by using the `run` task: sbt> run -This will detect and run classes that extend `scala.scalajs.js.JSApp`, while optionally prompting the user to choose a class if multiple such classes exist (fails with multiple classes if `ScalaJSKeys.persistLauncher := true`, see section below for details). +This will detect and run classes that extend +[`js.JSApp`]({{ BASE_PATH }}/api/scalajs-library/{{ site.scalaJSVersion }}/#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). Note that by default, this environment doesn't have a DOM. If you need it set `ScalaJSKeys.requiresDOM := true` in your settings. +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 @@ -27,54 +30,59 @@ To produce a proper JavaScript file from your code, you need to call the linker: 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`. -If you want to run this code, you can tell sbt to run after the linking stage: +If you want to run this code, you can do so by enabling the fastOpt stage with - sbt> fastOptStage::run + sbt> set scalaJSStage in Global := FastOptStage + sbt> run -This will invoke an external JavaScript interpreter and pass the generated file to it. Depending on your `requiresDOM` setting, it will either invoke Node.js or PhantomJS. *You need to install these separately* and make them available on the execution path (i.e. as shell commands `node` and `phantomjs`). +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/). +*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 +Note that running in the `fastOptStage` is often faster than running just after compilation because: 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. -We recommend you to operate in the `fastOptStage` in your development cycle. - -#### Disabling the optimizations - -If, for some reason, you want to disable the optimizations of the fast-optimizer (while still enjoying its other advantages: one small .js file, running an external VM), you can do so with the following sbt setting: +We recommend you to operate in the `fastOpt` stage in your development cycle. +You can enable it by default with the following sbt setting: {% highlight scala %} -ScalaJSKeys.inliningMode := scala.scalajs.sbtplugin.InliningMode.Off +scalaJSStage in Global := FastOptStage {% endhighlight %} -Alternatively, you can force the optimizer to run in batch mode (non incremental) on every run with the following setting: +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. + +### Disabling the optimizations + +If, for some reason (for example, to make stepping through the code with a debugger more predictable), you want to disable the optimizations, you can do so with the following sbt setting: {% highlight scala %} -ScalaJSKeys.inliningMode := scala.scalajs.sbtplugin.InliningMode.Batch +scalaJSOptimizerOptions ~= { _.withDisableOptimizer(true) } {% endhighlight %} +`scalaJSOptimizerOptions` contains various other options controlling the optimizer. +See [the ScalaDoc]({{ BASE_PATH }}/api/sbt-scalajs/{{ site.scalaJSVersion }}/#org.scalajs.sbtplugin.OptimizerOptions) +for details. + ## Full-Optimize To make the resulting JavaScript even smaller (and usually faster as well), the sbt plugin integrates the Google Closure Compiler under the so-called full-optimizations. You can use them by issuing: sbt> fullOptJS -This will call the Google Closure Compiler on the result of the fast-optimizations stage. Note that this can take a while and is therefore not recommended in the development cycle. The resulting file in the target folder will have the suffix `-opt.js`. +This will produce another single JavaScript file that is fully optimized. +Note that this can take a while and is therefore not recommended in the development cycle. +The resulting file in the target folder will have the suffix `-opt.js`. -Equivalent to the `fastOptStage` you can run your JavaScript code after the `fullOptStage`: +You can run your code and tests in fullOpt stage with the following command: - sbt> fullOptStage::run - -The same stage commands can be applied to the command `test` (have a look at the [bootstrapping skeleton](https://github.com/sjrd/scala-js-example-app) for a testing example). - -Since 0.5.4, Scala.js directly passes ASTs to the Google Closure Compiler. In case this fails and you experience regression, you may fallback to the old behavior (write file, read file) by setting `directFullOptJS` to false: - -{% highlight scala %} -ScalaJSKeys.directFullOptJS := false -{% endhighlight %} + sbt> set scalaJSStage in Global := FullOptStage ## Writing Launcher Code -If you want the code which is used to run the main class to be written to a file, you can set `ScalaJSKeys.persistLauncher := true`. Note that this will require your main class to be either unique or explicitly set (`mainClass := Some()`). The resulting file in the target folder will have the suffix `-launcher.js`. +If you want the code which is used to run the main class to be written to a file, you can set `persistLauncher := true`. +Note that this will require your main class to be either unique or explicitly set (`mainClass := Some()`). +The resulting file in the target folder will have the suffix `-launcher.js`. diff --git a/doc/sbt/setup.md b/doc/sbt/setup.md index 66dc587b..df624904 100644 --- a/doc/sbt/setup.md +++ b/doc/sbt/setup.md @@ -5,17 +5,20 @@ title: Scala.js sbt Setup Load the sbt plugin (`project/plugins.sbt`) - addSbtPlugin("org.scala-lang.modules.scalajs" % "scalajs-sbt-plugin" % "{{ site.scalaJSVersion }}") +{% highlight scala %} +addSbtPlugin("org.scala-js" % "sbt-scalajs" % "{{ site.scalaJSVersion }}") +{% endhighlight %} -Add Scala.js settings (`build.sbt`): +Enable the plugin on the sbt project (`build.sbt`): - scalaJSSettings +{% highlight scala %} +lazy val root = project. + enablePlugins(ScalaJSPlugin) +{% endhighlight %} If you are using a `Build.scala` definition, import the following: - import scala.scalajs.sbtplugin.ScalaJSPlugin._ - -Either way, you might want to add the following import for some of the keys -specific to Scala.js to be available in the scope of your build: - - import ScalaJSKeys._ +{% highlight scala %} +import org.scalajs.sbtplugin.ScalaJSPlugin +import org.scalajs.sbtplugin.ScalaJSPlugin.autoImport._ +{% endhighlight %} From ec67823b4d11b5eabb1c5b07d99ea0e0967168c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Mon, 12 Jan 2015 10:59:18 +0100 Subject: [PATCH 06/16] Use site.production_url instead of BASE_PATH for /api/ and /files/. Since those are only on the production server. This gives proper links when building locally. --- .../2014-06-30-announcing-scalajs-0.5.1.md | 2 +- .../2014-09-18-announcing-scalajs-0.5.5.md | 2 +- .../2014-11-19-announcing-scalajs-0.5.6.md | 2 +- .../2014-12-05-announcing-scalajs-0.6.0-M2.md | 2 +- .../2014-12-22-announcing-scalajs-0.6.0-M3.md | 2 +- ...2015-01-12-announcing-scalajs-0.6.0-RC1.md | 4 +- ...2015-01-23-announcing-scalajs-0.6.0-RC2.md | 4 +- doc/calling-javascript.md | 2 +- doc/index.md | 146 +++++++++--------- doc/sbt/cross-building.md | 2 +- doc/sbt/js-envs.md | 4 +- doc/sbt/run.md | 4 +- doc/semantics.md | 2 +- downloads.md | 96 ++++++------ 14 files changed, 137 insertions(+), 137 deletions(-) diff --git a/_posts/news/2014-06-30-announcing-scalajs-0.5.1.md b/_posts/news/2014-06-30-announcing-scalajs-0.5.1.md index 6d8b9484..d4efd6ea 100644 --- a/_posts/news/2014-06-30-announcing-scalajs-0.5.1.md +++ b/_posts/news/2014-06-30-announcing-scalajs-0.5.1.md @@ -42,7 +42,7 @@ The new sbt setting `jsDependencyFilter` can be used to modify the dependencies jsDependencyFilter := (_.filter(_.resourceName != "jquery.js")) -The above would prevent "jquery.js" from being included by the sbt runners. See [FlatJSDependency]({{ BASE_PATH }}/api/scalajs-tools/0.5.1/#scala.scalajs.tools.jsdep.FlatJSDependency) for fields that you can use. +The above would prevent "jquery.js" from being included by the sbt runners. See [FlatJSDependency]({{ site.production_url }}/api/scalajs-tools/0.5.1/#scala.scalajs.tools.jsdep.FlatJSDependency) for fields that you can use. #### Ordered testing output diff --git a/_posts/news/2014-09-18-announcing-scalajs-0.5.5.md b/_posts/news/2014-09-18-announcing-scalajs-0.5.5.md index bfe13425..499f6cda 100644 --- a/_posts/news/2014-09-18-announcing-scalajs-0.5.5.md +++ b/_posts/news/2014-09-18-announcing-scalajs-0.5.5.md @@ -57,7 +57,7 @@ Note that these conversions apply equally to other Scala collections like `Seq` #### packageJS `packageJS` has been deprecated in favor of `fastOptJS`. -Its providing tasks (`packageExternalDepsJS`, `packageInternalDepsJS` and `packageExportedProductsJS`) have been deprecated without replacement. If such a mechanism is required, [`ScalaJSPackager`]({{ BASE_PATH }}/api/scalajs-tools/0.5.5/#scala.scalajs.tools.packager.ScalaJSPackager) should be used directly. +Its providing tasks (`packageExternalDepsJS`, `packageInternalDepsJS` and `packageExportedProductsJS`) have been deprecated without replacement. If such a mechanism is required, [`ScalaJSPackager`]({{ site.production_url }}/api/scalajs-tools/0.5.5/#scala.scalajs.tools.packager.ScalaJSPackager) should be used directly. #### sbt Task Renamings diff --git a/_posts/news/2014-11-19-announcing-scalajs-0.5.6.md b/_posts/news/2014-11-19-announcing-scalajs-0.5.6.md index 3369e657..76b5b94c 100644 --- a/_posts/news/2014-11-19-announcing-scalajs-0.5.6.md +++ b/_posts/news/2014-11-19-announcing-scalajs-0.5.6.md @@ -40,7 +40,7 @@ The following features of the Java library have been added: Scala.js now supports the [standard charset conversions](https://docs.oracle.com/javase/7/docs/api/index.html?java/nio/charset/StandardCharsets.html) that every JRE supports. You can now pass instances of `Charset` to methods that convert bytes to characters and vice versa. -Note that you should avoid using `Charset.forName` (and methods that take charsets as strings in general), since they will make all `Charset` implementations reachable and hence explode your code size. If you compile on JDK6 (which does not have `StandardCharsets`), you may use [`scala.scalajs.niocharset.StandardCharsets`]({{ BASE_PATH }}/api/scalajs-library/0.5.6/#scala.scalajs.niocharset.StandardCharsets) to retrieve an instance of the desired `Charset`. +Note that you should avoid using `Charset.forName` (and methods that take charsets as strings in general), since they will make all `Charset` implementations reachable and hence explode your code size. If you compile on JDK6 (which does not have `StandardCharsets`), you may use [`scala.scalajs.niocharset.StandardCharsets`]({{ site.production_url }}/api/scalajs-library/0.5.6/#scala.scalajs.niocharset.StandardCharsets) to retrieve an instance of the desired `Charset`. This also allowed to implement `String.getBytes` ([#1087](https://github.com/scala-js/scala-js/issues/1087)). diff --git a/_posts/news/2014-12-05-announcing-scalajs-0.6.0-M2.md b/_posts/news/2014-12-05-announcing-scalajs-0.6.0-M2.md index c4aa6600..79dc8c8f 100644 --- a/_posts/news/2014-12-05-announcing-scalajs-0.6.0-M2.md +++ b/_posts/news/2014-12-05-announcing-scalajs-0.6.0-M2.md @@ -176,7 +176,7 @@ 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. 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-M2/#org.scalajs.sbtplugin.cross.CrossProject) for more information and examples. +See the [documentation of `CrossProject`]({{ site.production_url }}/api/sbt-scalajs/0.6.0-M2/#org.scalajs.sbtplugin.cross.CrossProject) for more information and examples. ### Faster! 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 index ad882915..bfc9e6d0 100644 --- 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 @@ -203,7 +203,7 @@ 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. 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. +See the [documentation of `CrossProject`]({{ site.production_url }}/api/sbt-scalajs/0.6.0-M3/#org.scalajs.sbtplugin.cross.CrossProject) for more information and examples. ### Faster! diff --git a/_posts/news/2015-01-12-announcing-scalajs-0.6.0-RC1.md b/_posts/news/2015-01-12-announcing-scalajs-0.6.0-RC1.md index 3914c54a..a59f1406 100644 --- a/_posts/news/2015-01-12-announcing-scalajs-0.6.0-RC1.md +++ b/_posts/news/2015-01-12-announcing-scalajs-0.6.0-RC1.md @@ -195,7 +195,7 @@ 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. 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-RC1/#org.scalajs.sbtplugin.cross.CrossProject) for more information and examples. +See the [documentation of `CrossProject`]({{ site.production_url }}/api/sbt-scalajs/0.6.0-RC1/#org.scalajs.sbtplugin.cross.CrossProject) for more information and examples. ### Faster! @@ -215,7 +215,7 @@ The title says it all: `js.Array[A]` and `js.Dictionary[A]` receive the entire S ### 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]({{ BASE_PATH }}/api/scalajs-library/0.6.0-RC1/#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. +A new object `js.DynamicImplicits` ([API]({{ site.production_url }}/api/scalajs-library/0.6.0-RC1/#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 diff --git a/_posts/news/2015-01-23-announcing-scalajs-0.6.0-RC2.md b/_posts/news/2015-01-23-announcing-scalajs-0.6.0-RC2.md index 4ade9805..8382c167 100644 --- a/_posts/news/2015-01-23-announcing-scalajs-0.6.0-RC2.md +++ b/_posts/news/2015-01-23-announcing-scalajs-0.6.0-RC2.md @@ -205,7 +205,7 @@ 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. 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-RC2/#org.scalajs.sbtplugin.cross.CrossProject) for more information and examples. +See the [documentation of `CrossProject`]({{ site.production_url }}/api/sbt-scalajs/0.6.0-RC2/#org.scalajs.sbtplugin.cross.CrossProject) for more information and examples. ### Faster! @@ -225,7 +225,7 @@ The title says it all: `js.Array[A]` and `js.Dictionary[A]` receive the entire S ### 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]({{ BASE_PATH }}/api/scalajs-library/0.6.0-RC2/#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. +A new object `js.DynamicImplicits` ([API]({{ site.production_url }}/api/scalajs-library/0.6.0-RC2/#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 diff --git a/doc/calling-javascript.md b/doc/calling-javascript.md index 10d12cbd..4ca90b37 100644 --- a/doc/calling-javascript.md +++ b/doc/calling-javascript.md @@ -542,5 +542,5 @@ When using `js.Dynamic`, you are very close to writing raw JavaScript within Scala.js, with all the warts of the language coming to haunt you. However, to get the full extent of JavaScriptish code, you can import the implicit conversions in -[js.DynamicImplicts]({{ BASE_PATH }}/api/scalajs-library/{{ site.scalaJSVersion }}/#scala.scalajs.js.DynamicImplicits$). +[js.DynamicImplicts]({{ site.production_url }}/api/scalajs-library/{{ site.scalaJSVersion }}/#scala.scalajs.js.DynamicImplicits$). Use at your own risk! diff --git a/doc/index.md b/doc/index.md index b4620249..8d5102b9 100644 --- a/doc/index.md +++ b/doc/index.md @@ -32,109 +32,109 @@ Generated Scaladocs are available here: ### Scala.js #### Scala.js 0.6.0-RC2 -* [0.6.0-RC2 scalajs-library]({{ BASE_PATH }}/api/scalajs-library/0.6.0-RC2/#scala.scalajs.js.package) -* [0.6.6-RC2 scalajs-test-interface]({{ BASE_PATH }}/api/scalajs-test-interface/0.6.0-RC2/) -* [0.6.0-RC2 scalajs-stubs]({{ BASE_PATH }}/api/scalajs-stubs/0.6.0-RC2/) -* [0.6.0-RC2 scalajs-ir]({{ BASE_PATH }}/api/scalajs-ir/0.6.0-RC2/#org.scalajs.core.ir.package) -* [0.6.0-RC2 scalajs-tools]({{ BASE_PATH }}/api/scalajs-tools/0.6.0-RC2/#org.scalajs.core.tools.package) ([Scala.js version]({{ BASE_PATH }}/api/scalajs-tools-js/0.6.0-RC2/#org.scalajs.core.tools.package)) -* [0.6.0-RC2 scalajs-js-envs]({{ BASE_PATH }}/api/scalajs-js-envs/0.6.0-RC2/#org.scalajs.jsenv.package) -* [0.6.0-RC2 scalajs-test-adapter]({{ BASE_PATH }}/api/scalajs-sbt-test-adapter/0.6.0-RC2/#org.scalajs.testadapter.package) -* [0.6.0-RC2 sbt-scalajs]({{ BASE_PATH }}/api/sbt-scalajs/0.6.0-RC2/#org.scalajs.sbtplugin.package) +* [0.6.0-RC2 scalajs-library]({{ site.production_url }}/api/scalajs-library/0.6.0-RC2/#scala.scalajs.js.package) +* [0.6.6-RC2 scalajs-test-interface]({{ site.production_url }}/api/scalajs-test-interface/0.6.0-RC2/) +* [0.6.0-RC2 scalajs-stubs]({{ site.production_url }}/api/scalajs-stubs/0.6.0-RC2/) +* [0.6.0-RC2 scalajs-ir]({{ site.production_url }}/api/scalajs-ir/0.6.0-RC2/#org.scalajs.core.ir.package) +* [0.6.0-RC2 scalajs-tools]({{ site.production_url }}/api/scalajs-tools/0.6.0-RC2/#org.scalajs.core.tools.package) ([Scala.js version]({{ site.production_url }}/api/scalajs-tools-js/0.6.0-RC2/#org.scalajs.core.tools.package)) +* [0.6.0-RC2 scalajs-js-envs]({{ site.production_url }}/api/scalajs-js-envs/0.6.0-RC2/#org.scalajs.jsenv.package) +* [0.6.0-RC2 scalajs-test-adapter]({{ site.production_url }}/api/scalajs-sbt-test-adapter/0.6.0-RC2/#org.scalajs.testadapter.package) +* [0.6.0-RC2 sbt-scalajs]({{ site.production_url }}/api/sbt-scalajs/0.6.0-RC2/#org.scalajs.sbtplugin.package) #### Scala.js 0.6.0-RC1 -* [0.6.0-RC1 scalajs-library]({{ BASE_PATH }}/api/scalajs-library/0.6.0-RC1/#scala.scalajs.js.package) -* [0.6.6-RC1 scalajs-test-interface]({{ BASE_PATH }}/api/scalajs-test-interface/0.6.0-RC1/) -* [0.6.0-RC1 scalajs-stubs]({{ BASE_PATH }}/api/scalajs-stubs/0.6.0-RC1/) -* [0.6.0-RC1 scalajs-ir]({{ BASE_PATH }}/api/scalajs-ir/0.6.0-RC1/#org.scalajs.core.ir.package) -* [0.6.0-RC1 scalajs-tools]({{ BASE_PATH }}/api/scalajs-tools/0.6.0-RC1/#org.scalajs.core.tools.package) ([Scala.js version]({{ BASE_PATH }}/api/scalajs-tools-js/0.6.0-RC1/#org.scalajs.core.tools.package)) -* [0.6.0-RC1 scalajs-js-envs]({{ BASE_PATH }}/api/scalajs-js-envs/0.6.0-RC1/#org.scalajs.jsenv.package) -* [0.6.0-RC1 scalajs-test-adapter]({{ BASE_PATH }}/api/scalajs-sbt-test-adapter/0.6.0-RC1/#org.scalajs.testadapter.package) -* [0.6.0-RC1 sbt-scalajs]({{ BASE_PATH }}/api/sbt-scalajs/0.6.0-RC1/#org.scalajs.sbtplugin.package) +* [0.6.0-RC1 scalajs-library]({{ site.production_url }}/api/scalajs-library/0.6.0-RC1/#scala.scalajs.js.package) +* [0.6.6-RC1 scalajs-test-interface]({{ site.production_url }}/api/scalajs-test-interface/0.6.0-RC1/) +* [0.6.0-RC1 scalajs-stubs]({{ site.production_url }}/api/scalajs-stubs/0.6.0-RC1/) +* [0.6.0-RC1 scalajs-ir]({{ site.production_url }}/api/scalajs-ir/0.6.0-RC1/#org.scalajs.core.ir.package) +* [0.6.0-RC1 scalajs-tools]({{ site.production_url }}/api/scalajs-tools/0.6.0-RC1/#org.scalajs.core.tools.package) ([Scala.js version]({{ site.production_url }}/api/scalajs-tools-js/0.6.0-RC1/#org.scalajs.core.tools.package)) +* [0.6.0-RC1 scalajs-js-envs]({{ site.production_url }}/api/scalajs-js-envs/0.6.0-RC1/#org.scalajs.jsenv.package) +* [0.6.0-RC1 scalajs-test-adapter]({{ site.production_url }}/api/scalajs-sbt-test-adapter/0.6.0-RC1/#org.scalajs.testadapter.package) +* [0.6.0-RC1 sbt-scalajs]({{ site.production_url }}/api/sbt-scalajs/0.6.0-RC1/#org.scalajs.sbtplugin.package) #### 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-M3/#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) +* [0.6.0-M3 scalajs-library]({{ site.production_url }}/api/scalajs-library/0.6.0-M3/#scala.scalajs.js.package) +* [0.6.6-M3 scalajs-test-interface]({{ site.production_url }}/api/scalajs-test-interface/0.6.0-M3/) +* [0.6.0-M3 scalajs-stubs]({{ site.production_url }}/api/scalajs-stubs/0.6.0-M3/) +* [0.6.0-M3 scalajs-ir]({{ site.production_url }}/api/scalajs-ir/0.6.0-M3/#org.scalajs.core.ir.package) +* [0.6.0-M3 scalajs-tools]({{ site.production_url }}/api/scalajs-tools/0.6.0-M3/#org.scalajs.core.tools.package) ([Scala.js version]({{ site.production_url }}/api/scalajs-tools-js/0.6.0-M3/#org.scalajs.core.tools.package)) +* [0.6.0-M3 scalajs-js-envs]({{ site.production_url }}/api/scalajs-js-envs/0.6.0-M3/#org.scalajs.jsenv.package) +* [0.6.0-M3 scalajs-test-adapter]({{ site.production_url }}/api/scalajs-test-adapter/0.6.0-M3/#org.scalajs.testadapter.package) +* [0.6.0-M3 sbt-scalajs]({{ site.production_url }}/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/) -* [0.6.0-M2 scalajs-stubs]({{ BASE_PATH }}/api/scalajs-stubs/0.6.0-M2/) -* [0.6.0-M2 scalajs-ir]({{ BASE_PATH }}/api/scalajs-ir/0.6.0-M2/#org.scalajs.core.ir.package) -* [0.6.0-M2 scalajs-tools]({{ BASE_PATH }}/api/scalajs-tools/0.6.0-M2/#org.scalajs.core.tools.package) ([Scala.js version]({{ BASE_PATH }}/api/scalajs-tools-js/0.6.0-M2/#org.scalajs.core.tools.package)) -* [0.6.0-M2 scalajs-js-envs]({{ BASE_PATH }}/api/scalajs-js-envs/0.6.0-M2/#org.scalajs.jsenv.package) -* [0.6.0-M2 scalajs-test-adapter]({{ BASE_PATH }}/api/scalajs-test-adapter/0.6.0-M2/#org.scalajs.testadapter.package) -* [0.6.0-M2 sbt-scalajs]({{ BASE_PATH }}/api/sbt-scalajs/0.6.0-M2/#org.scalajs.sbtplugin.package) +* [0.6.0-M2 scalajs-library]({{ site.production_url }}/api/scalajs-library/0.6.0-M2/#scala.scalajs.js.package) +* [0.6.6-M2 scalajs-test-interface]({{ site.production_url }}/api/scalajs-test-interface/0.6.0-M2/) +* [0.6.0-M2 scalajs-stubs]({{ site.production_url }}/api/scalajs-stubs/0.6.0-M2/) +* [0.6.0-M2 scalajs-ir]({{ site.production_url }}/api/scalajs-ir/0.6.0-M2/#org.scalajs.core.ir.package) +* [0.6.0-M2 scalajs-tools]({{ site.production_url }}/api/scalajs-tools/0.6.0-M2/#org.scalajs.core.tools.package) ([Scala.js version]({{ site.production_url }}/api/scalajs-tools-js/0.6.0-M2/#org.scalajs.core.tools.package)) +* [0.6.0-M2 scalajs-js-envs]({{ site.production_url }}/api/scalajs-js-envs/0.6.0-M2/#org.scalajs.jsenv.package) +* [0.6.0-M2 scalajs-test-adapter]({{ site.production_url }}/api/scalajs-test-adapter/0.6.0-M2/#org.scalajs.testadapter.package) +* [0.6.0-M2 sbt-scalajs]({{ site.production_url }}/api/sbt-scalajs/0.6.0-M2/#org.scalajs.sbtplugin.package) #### Scala.js 0.6.0-M1 -* [0.6.0-M1 scalajs-library]({{ BASE_PATH }}/api/scalajs-library/0.6.0-M1/#scala.scalajs.js.package) -* [0.6.6-M1 scalajs-test-interface]({{ BASE_PATH }}/api/scalajs-test-interface/0.6.0-M1/) -* [0.6.0-M1 scalajs-stubs]({{ BASE_PATH }}/api/scalajs-stubs/0.6.0-M1/) -* [0.6.0-M1 scalajs-ir]({{ BASE_PATH }}/api/scalajs-ir/0.6.0-M1/#org.scalajs.core.ir.package) -* [0.6.0-M1 scalajs-tools]({{ BASE_PATH }}/api/scalajs-tools/0.6.0-M1/#org.scalajs.core.tools.package) ([Scala.js version]({{ BASE_PATH }}/api/scalajs-tools-js/0.6.0-M1/#org.scalajs.core.tools.package)) -* [0.6.0-M1 scalajs-js-envs]({{ BASE_PATH }}/api/scalajs-js-envs/0.6.0-M1/#org.scalajs.jsenv.package) -* [0.6.0-M1 scalajs-test-adapter]({{ BASE_PATH }}/api/scalajs-test-adapter/0.6.0-M1/#org.scalajs.testadapter.package) +* [0.6.0-M1 scalajs-library]({{ site.production_url }}/api/scalajs-library/0.6.0-M1/#scala.scalajs.js.package) +* [0.6.6-M1 scalajs-test-interface]({{ site.production_url }}/api/scalajs-test-interface/0.6.0-M1/) +* [0.6.0-M1 scalajs-stubs]({{ site.production_url }}/api/scalajs-stubs/0.6.0-M1/) +* [0.6.0-M1 scalajs-ir]({{ site.production_url }}/api/scalajs-ir/0.6.0-M1/#org.scalajs.core.ir.package) +* [0.6.0-M1 scalajs-tools]({{ site.production_url }}/api/scalajs-tools/0.6.0-M1/#org.scalajs.core.tools.package) ([Scala.js version]({{ site.production_url }}/api/scalajs-tools-js/0.6.0-M1/#org.scalajs.core.tools.package)) +* [0.6.0-M1 scalajs-js-envs]({{ site.production_url }}/api/scalajs-js-envs/0.6.0-M1/#org.scalajs.jsenv.package) +* [0.6.0-M1 scalajs-test-adapter]({{ site.production_url }}/api/scalajs-test-adapter/0.6.0-M1/#org.scalajs.testadapter.package) #### Scala.js 0.5.6 -* [0.5.6 scalajs-library]({{ BASE_PATH }}/api/scalajs-library/0.5.6/#scala.scalajs.js.package) -* [0.5.6 scalajs-tools]({{ BASE_PATH }}/api/scalajs-tools/0.5.6/) ([Scala.js version]({{ BASE_PATH }}/api/scalajs-tools/0.5.6/)) -* [0.5.6 scalajs-test-bridge]({{ BASE_PATH }}/api/scalajs-test-bridge/0.5.6/) -* [0.5.6 scalajs-jasmine-test-framework]({{ BASE_PATH }}/api/scalajs-jasmine-test-framework/0.5.6/) +* [0.5.6 scalajs-library]({{ site.production_url }}/api/scalajs-library/0.5.6/#scala.scalajs.js.package) +* [0.5.6 scalajs-tools]({{ site.production_url }}/api/scalajs-tools/0.5.6/) ([Scala.js version]({{ site.production_url }}/api/scalajs-tools/0.5.6/)) +* [0.5.6 scalajs-test-bridge]({{ site.production_url }}/api/scalajs-test-bridge/0.5.6/) +* [0.5.6 scalajs-jasmine-test-framework]({{ site.production_url }}/api/scalajs-jasmine-test-framework/0.5.6/) #### Scala.js 0.5.5 -* [0.5.5 scalajs-library]({{ BASE_PATH }}/api/scalajs-library/0.5.5/#scala.scalajs.js.package) -* [0.5.5 scalajs-tools]({{ BASE_PATH }}/api/scalajs-tools/0.5.5/) ([Scala.js version]({{ BASE_PATH }}/api/scalajs-tools/0.5.5/)) -* [0.5.5 scalajs-test-bridge]({{ BASE_PATH }}/api/scalajs-test-bridge/0.5.5/) -* [0.5.5 scalajs-jasmine-test-framework]({{ BASE_PATH }}/api/scalajs-jasmine-test-framework/0.5.5/) +* [0.5.5 scalajs-library]({{ site.production_url }}/api/scalajs-library/0.5.5/#scala.scalajs.js.package) +* [0.5.5 scalajs-tools]({{ site.production_url }}/api/scalajs-tools/0.5.5/) ([Scala.js version]({{ site.production_url }}/api/scalajs-tools/0.5.5/)) +* [0.5.5 scalajs-test-bridge]({{ site.production_url }}/api/scalajs-test-bridge/0.5.5/) +* [0.5.5 scalajs-jasmine-test-framework]({{ site.production_url }}/api/scalajs-jasmine-test-framework/0.5.5/) #### 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/) +* [0.5.4 scalajs-library]({{ site.production_url }}/api/scalajs-library/0.5.4/#scala.scalajs.js.package) +* [0.5.4 scalajs-tools]({{ site.production_url }}/api/scalajs-tools/0.5.4/) ([Scala.js version]({{ site.production_url }}/api/scalajs-tools/0.5.4/)) +* [0.5.4 scalajs-test-bridge]({{ site.production_url }}/api/scalajs-test-bridge/0.5.4/) +* [0.5.4 scalajs-jasmine-test-framework]({{ site.production_url }}/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/) -* [0.5.3 scalajs-test-bridge]({{ BASE_PATH }}/api/scalajs-test-bridge/0.5.3/) -* [0.5.3 scalajs-jasmine-test-framework]({{ BASE_PATH }}/api/scalajs-jasmine-test-framework/0.5.3/) +* [0.5.3 scalajs-library]({{ site.production_url }}/api/scalajs-library/0.5.3/#scala.scalajs.js.package) +* [0.5.3 scalajs-tools]({{ site.production_url }}/api/scalajs-tools/0.5.3/) +* [0.5.3 scalajs-test-bridge]({{ site.production_url }}/api/scalajs-test-bridge/0.5.3/) +* [0.5.3 scalajs-jasmine-test-framework]({{ site.production_url }}/api/scalajs-jasmine-test-framework/0.5.3/) #### Scala.js 0.5.2 -* [0.5.2 scalajs-library]({{ BASE_PATH }}/api/scalajs-library/0.5.2/#scala.scalajs.js.package) -* [0.5.2 scalajs-tools]({{ BASE_PATH }}/api/scalajs-tools/0.5.2/) -* [0.5.2 scalajs-test-bridge]({{ BASE_PATH }}/api/scalajs-test-bridge/0.5.2/) -* [0.5.2 scalajs-jasmine-test-framework]({{ BASE_PATH }}/api/scalajs-jasmine-test-framework/0.5.2/) +* [0.5.2 scalajs-library]({{ site.production_url }}/api/scalajs-library/0.5.2/#scala.scalajs.js.package) +* [0.5.2 scalajs-tools]({{ site.production_url }}/api/scalajs-tools/0.5.2/) +* [0.5.2 scalajs-test-bridge]({{ site.production_url }}/api/scalajs-test-bridge/0.5.2/) +* [0.5.2 scalajs-jasmine-test-framework]({{ site.production_url }}/api/scalajs-jasmine-test-framework/0.5.2/) #### Scala.js 0.5.1 -* [0.5.1 scalajs-library]({{ BASE_PATH }}/api/scalajs-library/0.5.1/#scala.scalajs.js.package) -* [0.5.1 scalajs-tools]({{ BASE_PATH }}/api/scalajs-tools/0.5.1/) -* [0.5.1 scalajs-test-bridge]({{ BASE_PATH }}/api/scalajs-test-bridge/0.5.1/) -* [0.5.1 scalajs-jasmine-test-framework]({{ BASE_PATH }}/api/scalajs-jasmine-test-framework/0.5.1/) +* [0.5.1 scalajs-library]({{ site.production_url }}/api/scalajs-library/0.5.1/#scala.scalajs.js.package) +* [0.5.1 scalajs-tools]({{ site.production_url }}/api/scalajs-tools/0.5.1/) +* [0.5.1 scalajs-test-bridge]({{ site.production_url }}/api/scalajs-test-bridge/0.5.1/) +* [0.5.1 scalajs-jasmine-test-framework]({{ site.production_url }}/api/scalajs-jasmine-test-framework/0.5.1/) #### Scala.js 0.5.0 -* [0.5.0 scalajs-library]({{ BASE_PATH }}/api/scalajs-library/0.5.0/#scala.scalajs.js.package) -* [0.5.0 scalajs-tools]({{ BASE_PATH }}/api/scalajs-tools/0.5.0/) -* [0.5.0 scalajs-test-bridge]({{ BASE_PATH }}/api/scalajs-test-bridge/0.5.0/) -* [0.5.0 scalajs-jasmine-test-framework]({{ BASE_PATH }}/api/scalajs-jasmine-test-framework/0.5.0/) +* [0.5.0 scalajs-library]({{ site.production_url }}/api/scalajs-library/0.5.0/#scala.scalajs.js.package) +* [0.5.0 scalajs-tools]({{ site.production_url }}/api/scalajs-tools/0.5.0/) +* [0.5.0 scalajs-test-bridge]({{ site.production_url }}/api/scalajs-test-bridge/0.5.0/) +* [0.5.0 scalajs-jasmine-test-framework]({{ site.production_url }}/api/scalajs-jasmine-test-framework/0.5.0/) #### Scala.js 0.4.4 -* [0.4.4 scalajs-library]({{ BASE_PATH }}/api/scalajs-library/0.4.4/#scala.scalajs.js.package) -* [0.4.4 scalajs-tools]({{ BASE_PATH }}/api/scalajs-tools/0.4.4/) -* [0.4.4 scalajs-jasmine-test-framework]({{ BASE_PATH }}/api/scalajs-jasmine-test-framework/0.4.4/) +* [0.4.4 scalajs-library]({{ site.production_url }}/api/scalajs-library/0.4.4/#scala.scalajs.js.package) +* [0.4.4 scalajs-tools]({{ site.production_url }}/api/scalajs-tools/0.4.4/) +* [0.4.4 scalajs-jasmine-test-framework]({{ site.production_url }}/api/scalajs-jasmine-test-framework/0.4.4/) ### JavaScript APIs #### DOM API -* [0.7.x scalajs-dom]({{ BASE_PATH }}/api/scalajs-dom/0.7/#org.scalajs.dom.package) -* [0.6 scalajs-dom]({{ BASE_PATH }}/api/scalajs-dom/0.6/#org.scalajs.dom.package) +* [0.7.x scalajs-dom]({{ site.production_url }}/api/scalajs-dom/0.7/#org.scalajs.dom.package) +* [0.6 scalajs-dom]({{ site.production_url }}/api/scalajs-dom/0.6/#org.scalajs.dom.package) #### jQuery API -* [0.6 scalajs-jquery]({{ BASE_PATH }}/api/scalajs-jquery/0.6/#org.scalajs.jquery.package) +* [0.6 scalajs-jquery]({{ site.production_url }}/api/scalajs-jquery/0.6/#org.scalajs.jquery.package) ## FAQ diff --git a/doc/sbt/cross-building.md b/doc/sbt/cross-building.md index 431fac4f..9a63e320 100644 --- a/doc/sbt/cross-building.md +++ b/doc/sbt/cross-building.md @@ -8,7 +8,7 @@ In order to do this, you need two different projects, one for Scala.js and one f You can then tell sbt to use the shared source folder in addition to the normal source locations. To do this, we provide a builder, `crossProject`, which constructs two related sbt projects, one for the JVM, and one for JS. -See [the ScalaDoc of `CrossProject`]({{ BASE_PATH }}/api/sbt-scalajs/{{ site.scalaJSVersion }}/#org.scalajs.sbtplugin.cross.CrossProject) +See [the ScalaDoc of `CrossProject`]({{ site.production_url }}/api/sbt-scalajs/{{ site.scalaJSVersion }}/#org.scalajs.sbtplugin.cross.CrossProject) for examples and documentation. We give a simple example of how such a project, we call it `foo`, could look. You can find this project on [GitHub](https://github.com/scala-js/scalajs-cross-compile-example). diff --git a/doc/sbt/js-envs.md b/doc/sbt/js-envs.md index b623a58f..9268d52d 100644 --- a/doc/sbt/js-envs.md +++ b/doc/sbt/js-envs.md @@ -43,7 +43,7 @@ postLinkJSEnv := PhantomJSEnv(args = Seq("arg1", "arg2")).value {% endhighlight %} For more options of the PhantomJS environment, see -[the ScalaDoc of `PhantomJSEnv`]({{ BASE_PATH }}/api/sbt-scalajs/{{ site.scalaJSVersion }}/#org.scalajs.sbtplugin.ScalaJSPlugin$$AutoImport$). +[the ScalaDoc of `PhantomJSEnv`]({{ site.production_url }}/api/sbt-scalajs/{{ site.scalaJSVersion }}/#org.scalajs.sbtplugin.ScalaJSPlugin$$AutoImport$). ## Node.js on Ubuntu @@ -59,4 +59,4 @@ postLinkJSEnv := NodeJSEnv(executable = "nodejs").value {% endhighlight %} For more options of the Node.js environment, see -[the ScalaDoc of `NodeJSEnv`]({{ BASE_PATH }}/api/sbt-scalajs/{{ site.scalaJSVersion }}/#org.scalajs.sbtplugin.ScalaJSPlugin$$AutoImport$). +[the ScalaDoc of `NodeJSEnv`]({{ site.production_url }}/api/sbt-scalajs/{{ site.scalaJSVersion }}/#org.scalajs.sbtplugin.ScalaJSPlugin$$AutoImport$). diff --git a/doc/sbt/run.md b/doc/sbt/run.md index 73d23825..c6b19d9d 100644 --- a/doc/sbt/run.md +++ b/doc/sbt/run.md @@ -16,7 +16,7 @@ You now can run your application already by using the `run` task: sbt> run This will detect and run classes that extend -[`js.JSApp`]({{ BASE_PATH }}/api/scalajs-library/{{ site.scalaJSVersion }}/#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). +[`js.JSApp`]({{ site.production_url }}/api/scalajs-library/{{ site.scalaJSVersion }}/#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). Note that by default, this environment doesn't have a DOM. @@ -64,7 +64,7 @@ scalaJSOptimizerOptions ~= { _.withDisableOptimizer(true) } {% endhighlight %} `scalaJSOptimizerOptions` contains various other options controlling the optimizer. -See [the ScalaDoc]({{ BASE_PATH }}/api/sbt-scalajs/{{ site.scalaJSVersion }}/#org.scalajs.sbtplugin.OptimizerOptions) +See [the ScalaDoc]({{ site.production_url }}/api/sbt-scalajs/{{ site.scalaJSVersion }}/#org.scalajs.sbtplugin.OptimizerOptions) for details. ## Full-Optimize diff --git a/doc/semantics.md b/doc/semantics.md index 858d7f1f..034ce3a1 100644 --- a/doc/semantics.md +++ b/doc/semantics.md @@ -109,7 +109,7 @@ Every configurable undefined behavior has 3 possible modes: * `Compliant`: behaves as specified on a JVM * `Unchecked`: completely unchecked and undefined * `Fatal`: checked, but throws - [`UndefinedBehaviorError`s]({{ BASE_PATH }}/api/scalajs-library/{{ site.scalaJSVersion }}/#scala.scalajs.runtime.UndefinedBehaviorError) + [`UndefinedBehaviorError`s]({{ site.production_url }}/api/scalajs-library/{{ site.scalaJSVersion }}/#scala.scalajs.runtime.UndefinedBehaviorError) instead of the specified exception. By default, undefined behaviors are in `Fatal` mode for `fastOptJS` and in diff --git a/downloads.md b/downloads.md index 409a2e70..d14bfa3c 100644 --- a/downloads.md +++ b/downloads.md @@ -10,73 +10,73 @@ 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-RC2 -* [0.6.0-RC2, Scala 2.11 (tgz, 20MB)]({{ BASE_PATH }}/files/scalajs_2.11-0.6.0-RC2.tgz) -* [0.6.0-RC2, Scala 2.11 (zip, 20MB)]({{ BASE_PATH }}/files/scalajs_2.11-0.6.0-RC2.zip) -* [0.6.0-RC2, Scala 2.10 (tgz, 18MB)]({{ BASE_PATH }}/files/scalajs_2.10-0.6.0-RC2.tgz) -* [0.6.0-RC2, Scala 2.10 (zip, 18MB)]({{ BASE_PATH }}/files/scalajs_2.10-0.6.0-RC2.zip) +* [0.6.0-RC2, Scala 2.11 (tgz, 20MB)]({{ site.production_url }}/files/scalajs_2.11-0.6.0-RC2.tgz) +* [0.6.0-RC2, Scala 2.11 (zip, 20MB)]({{ site.production_url }}/files/scalajs_2.11-0.6.0-RC2.zip) +* [0.6.0-RC2, Scala 2.10 (tgz, 18MB)]({{ site.production_url }}/files/scalajs_2.10-0.6.0-RC2.tgz) +* [0.6.0-RC2, Scala 2.10 (zip, 18MB)]({{ site.production_url }}/files/scalajs_2.10-0.6.0-RC2.zip) #### Scala.js 0.6.0-RC1 -* [0.6.0-RC1, Scala 2.11 (tgz, 20MB)]({{ BASE_PATH }}/files/scalajs_2.11-0.6.0-RC1.tgz) -* [0.6.0-RC1, Scala 2.11 (zip, 20MB)]({{ BASE_PATH }}/files/scalajs_2.11-0.6.0-RC1.zip) -* [0.6.0-RC1, Scala 2.10 (tgz, 18MB)]({{ BASE_PATH }}/files/scalajs_2.10-0.6.0-RC1.tgz) -* [0.6.0-RC1, Scala 2.10 (zip, 18MB)]({{ BASE_PATH }}/files/scalajs_2.10-0.6.0-RC1.zip) +* [0.6.0-RC1, Scala 2.11 (tgz, 20MB)]({{ site.production_url }}/files/scalajs_2.11-0.6.0-RC1.tgz) +* [0.6.0-RC1, Scala 2.11 (zip, 20MB)]({{ site.production_url }}/files/scalajs_2.11-0.6.0-RC1.zip) +* [0.6.0-RC1, Scala 2.10 (tgz, 18MB)]({{ site.production_url }}/files/scalajs_2.10-0.6.0-RC1.tgz) +* [0.6.0-RC1, Scala 2.10 (zip, 18MB)]({{ site.production_url }}/files/scalajs_2.10-0.6.0-RC1.zip) #### 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) +* [0.6.0-M3, Scala 2.11 (tgz, 18MB)]({{ site.production_url }}/files/scalajs_2.11-0.6.0-M3.tgz) +* [0.6.0-M3, Scala 2.11 (zip, 18MB)]({{ site.production_url }}/files/scalajs_2.11-0.6.0-M3.zip) +* [0.6.0-M3, Scala 2.10 (tgz, 18MB)]({{ site.production_url }}/files/scalajs_2.10-0.6.0-M3.tgz) +* [0.6.0-M3, Scala 2.10 (zip, 18MB)]({{ site.production_url }}/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) -* [0.6.0-M2, Scala 2.10 (tgz, 18MB)]({{ BASE_PATH }}/files/scalajs_2.10-0.6.0-M2.tgz) -* [0.6.0-M2, Scala 2.10 (zip, 18MB)]({{ BASE_PATH }}/files/scalajs_2.10-0.6.0-M2.zip) +* [0.6.0-M2, Scala 2.11 (tgz, 18MB)]({{ site.production_url }}/files/scalajs_2.11-0.6.0-M2.tgz) +* [0.6.0-M2, Scala 2.11 (zip, 18MB)]({{ site.production_url }}/files/scalajs_2.11-0.6.0-M2.zip) +* [0.6.0-M2, Scala 2.10 (tgz, 18MB)]({{ site.production_url }}/files/scalajs_2.10-0.6.0-M2.tgz) +* [0.6.0-M2, Scala 2.10 (zip, 18MB)]({{ site.production_url }}/files/scalajs_2.10-0.6.0-M2.zip) #### Scala.js 0.6.0-M1 -* [0.6.0-M1, Scala 2.11 (tgz, 18MB)]({{ BASE_PATH }}/files/scalajs_2.11-0.6.0-M1.tgz) -* [0.6.0-M1, Scala 2.11 (zip, 18MB)]({{ BASE_PATH }}/files/scalajs_2.11-0.6.0-M1.zip) -* [0.6.0-M1, Scala 2.10 (tgz, 18MB)]({{ BASE_PATH }}/files/scalajs_2.10-0.6.0-M1.tgz) -* [0.6.0-M1, Scala 2.10 (zip, 18MB)]({{ BASE_PATH }}/files/scalajs_2.10-0.6.0-M1.zip) +* [0.6.0-M1, Scala 2.11 (tgz, 18MB)]({{ site.production_url }}/files/scalajs_2.11-0.6.0-M1.tgz) +* [0.6.0-M1, Scala 2.11 (zip, 18MB)]({{ site.production_url }}/files/scalajs_2.11-0.6.0-M1.zip) +* [0.6.0-M1, Scala 2.10 (tgz, 18MB)]({{ site.production_url }}/files/scalajs_2.10-0.6.0-M1.tgz) +* [0.6.0-M1, Scala 2.10 (zip, 18MB)]({{ site.production_url }}/files/scalajs_2.10-0.6.0-M1.zip) #### Scala.js 0.5.6 -* [0.5.6, Scala 2.11 (tgz, 17MB)]({{ BASE_PATH }}/files/scalajs_2.11-0.5.6.tgz) -* [0.5.6, Scala 2.11 (zip, 17MB)]({{ BASE_PATH }}/files/scalajs_2.11-0.5.6.zip) -* [0.5.6, Scala 2.10 (tgz, 16MB)]({{ BASE_PATH }}/files/scalajs_2.10-0.5.6.tgz) -* [0.5.6, Scala 2.10 (zip, 16MB)]({{ BASE_PATH }}/files/scalajs_2.10-0.5.6.zip) +* [0.5.6, Scala 2.11 (tgz, 17MB)]({{ site.production_url }}/files/scalajs_2.11-0.5.6.tgz) +* [0.5.6, Scala 2.11 (zip, 17MB)]({{ site.production_url }}/files/scalajs_2.11-0.5.6.zip) +* [0.5.6, Scala 2.10 (tgz, 16MB)]({{ site.production_url }}/files/scalajs_2.10-0.5.6.tgz) +* [0.5.6, Scala 2.10 (zip, 16MB)]({{ site.production_url }}/files/scalajs_2.10-0.5.6.zip) #### Scala.js 0.5.5 -* [0.5.5, Scala 2.11 (tgz, 15MB)]({{ BASE_PATH }}/files/scalajs_2.11-0.5.5.tgz) -* [0.5.5, Scala 2.11 (zip, 15MB)]({{ BASE_PATH }}/files/scalajs_2.11-0.5.5.zip) -* [0.5.5, Scala 2.10 (tgz, 16MB)]({{ BASE_PATH }}/files/scalajs_2.10-0.5.5.tgz) -* [0.5.5, Scala 2.10 (zip, 16MB)]({{ BASE_PATH }}/files/scalajs_2.10-0.5.5.zip) +* [0.5.5, Scala 2.11 (tgz, 15MB)]({{ site.production_url }}/files/scalajs_2.11-0.5.5.tgz) +* [0.5.5, Scala 2.11 (zip, 15MB)]({{ site.production_url }}/files/scalajs_2.11-0.5.5.zip) +* [0.5.5, Scala 2.10 (tgz, 16MB)]({{ site.production_url }}/files/scalajs_2.10-0.5.5.tgz) +* [0.5.5, Scala 2.10 (zip, 16MB)]({{ site.production_url }}/files/scalajs_2.10-0.5.5.zip) #### Scala.js 0.5.4 -* [0.5.4, Scala 2.11 (tgz, 15MB)]({{ BASE_PATH }}/files/scalajs_2.11-0.5.4.tgz) -* [0.5.4, Scala 2.11 (zip, 15MB)]({{ BASE_PATH }}/files/scalajs_2.11-0.5.4.zip) -* [0.5.4, Scala 2.10 (tgz, 16MB)]({{ BASE_PATH }}/files/scalajs_2.10-0.5.4.tgz) -* [0.5.4, Scala 2.10 (zip, 16MB)]({{ BASE_PATH }}/files/scalajs_2.10-0.5.4.zip) +* [0.5.4, Scala 2.11 (tgz, 15MB)]({{ site.production_url }}/files/scalajs_2.11-0.5.4.tgz) +* [0.5.4, Scala 2.11 (zip, 15MB)]({{ site.production_url }}/files/scalajs_2.11-0.5.4.zip) +* [0.5.4, Scala 2.10 (tgz, 16MB)]({{ site.production_url }}/files/scalajs_2.10-0.5.4.tgz) +* [0.5.4, Scala 2.10 (zip, 16MB)]({{ site.production_url }}/files/scalajs_2.10-0.5.4.zip) #### Scala.js 0.5.3 -* [0.5.3, Scala 2.11 (tgz, 15MB)]({{ BASE_PATH }}/files/scalajs_2.11-0.5.3.tgz) -* [0.5.3, Scala 2.11 (zip, 15MB)]({{ BASE_PATH }}/files/scalajs_2.11-0.5.3.zip) -* [0.5.3, Scala 2.10 (tgz, 16MB)]({{ BASE_PATH }}/files/scalajs_2.10-0.5.3.tgz) -* [0.5.3, Scala 2.10 (zip, 16MB)]({{ BASE_PATH }}/files/scalajs_2.10-0.5.3.zip) +* [0.5.3, Scala 2.11 (tgz, 15MB)]({{ site.production_url }}/files/scalajs_2.11-0.5.3.tgz) +* [0.5.3, Scala 2.11 (zip, 15MB)]({{ site.production_url }}/files/scalajs_2.11-0.5.3.zip) +* [0.5.3, Scala 2.10 (tgz, 16MB)]({{ site.production_url }}/files/scalajs_2.10-0.5.3.tgz) +* [0.5.3, Scala 2.10 (zip, 16MB)]({{ site.production_url }}/files/scalajs_2.10-0.5.3.zip) #### Scala.js 0.5.2 -* [0.5.2, Scala 2.11 (tgz, 14MB)]({{ BASE_PATH }}/files/scalajs_2.11-0.5.2.tgz) -* [0.5.2, Scala 2.11 (zip, 14MB)]({{ BASE_PATH }}/files/scalajs_2.11-0.5.2.zip) -* [0.5.2, Scala 2.10 (tgz, 15MB)]({{ BASE_PATH }}/files/scalajs_2.10-0.5.2.tgz) -* [0.5.2, Scala 2.10 (zip, 15MB)]({{ BASE_PATH }}/files/scalajs_2.10-0.5.2.zip) +* [0.5.2, Scala 2.11 (tgz, 14MB)]({{ site.production_url }}/files/scalajs_2.11-0.5.2.tgz) +* [0.5.2, Scala 2.11 (zip, 14MB)]({{ site.production_url }}/files/scalajs_2.11-0.5.2.zip) +* [0.5.2, Scala 2.10 (tgz, 15MB)]({{ site.production_url }}/files/scalajs_2.10-0.5.2.tgz) +* [0.5.2, Scala 2.10 (zip, 15MB)]({{ site.production_url }}/files/scalajs_2.10-0.5.2.zip) #### Scala.js 0.5.1 -* [0.5.1, Scala 2.11 (tgz, 13MB)]({{ BASE_PATH }}/files/scalajs_2.11-0.5.1.tgz) -* [0.5.1, Scala 2.11 (zip, 13MB)]({{ BASE_PATH }}/files/scalajs_2.11-0.5.1.zip) -* [0.5.1, Scala 2.10 (tgz, 15MB)]({{ BASE_PATH }}/files/scalajs_2.10-0.5.1.tgz) -* [0.5.1, Scala 2.10 (zip, 15MB)]({{ BASE_PATH }}/files/scalajs_2.10-0.5.1.zip) +* [0.5.1, Scala 2.11 (tgz, 13MB)]({{ site.production_url }}/files/scalajs_2.11-0.5.1.tgz) +* [0.5.1, Scala 2.11 (zip, 13MB)]({{ site.production_url }}/files/scalajs_2.11-0.5.1.zip) +* [0.5.1, Scala 2.10 (tgz, 15MB)]({{ site.production_url }}/files/scalajs_2.10-0.5.1.tgz) +* [0.5.1, Scala 2.10 (zip, 15MB)]({{ site.production_url }}/files/scalajs_2.10-0.5.1.zip) #### Scala.js 0.5.0 -* [0.5.0, Scala 2.11 (tgz, 13MB)]({{ BASE_PATH }}/files/scalajs_2.11-0.5.0.tgz) -* [0.5.0, Scala 2.11 (zip, 13MB)]({{ BASE_PATH }}/files/scalajs_2.11-0.5.0.zip) -* [0.5.0, Scala 2.10 (tgz, 15MB)]({{ BASE_PATH }}/files/scalajs_2.10-0.5.0.tgz) -* [0.5.0, Scala 2.10 (zip, 15MB)]({{ BASE_PATH }}/files/scalajs_2.10-0.5.0.zip) +* [0.5.0, Scala 2.11 (tgz, 13MB)]({{ site.production_url }}/files/scalajs_2.11-0.5.0.tgz) +* [0.5.0, Scala 2.11 (zip, 13MB)]({{ site.production_url }}/files/scalajs_2.11-0.5.0.zip) +* [0.5.0, Scala 2.10 (tgz, 15MB)]({{ site.production_url }}/files/scalajs_2.10-0.5.0.tgz) +* [0.5.0, Scala 2.10 (zip, 15MB)]({{ site.production_url }}/files/scalajs_2.10-0.5.0.zip) From f610df7e210d97a9cfded0a4faf8940367d5d9fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Mon, 12 Jan 2015 11:29:30 +0100 Subject: [PATCH 07/16] Remove the cookbook. It was nearly empty. Everything it contained was obsolete, and new and accurate information is in the tutorial or in the reference. --- doc/cookbook/index.md | 72 ------------- .../interop/accessing-global-scope.md | 48 --------- doc/cookbook/interop/passing-basic-types.md | 40 ------- doc/cookbook/setup/customize-app.md | 102 ------------------ doc/cookbook/setup/example-app.md | 25 ----- doc/cookbook/setup/giter8.md | 77 ------------- doc/index.md | 1 - 7 files changed, 365 deletions(-) delete mode 100644 doc/cookbook/index.md delete mode 100644 doc/cookbook/interop/accessing-global-scope.md delete mode 100644 doc/cookbook/interop/passing-basic-types.md delete mode 100644 doc/cookbook/setup/customize-app.md delete mode 100644 doc/cookbook/setup/example-app.md delete mode 100644 doc/cookbook/setup/giter8.md diff --git a/doc/cookbook/index.md b/doc/cookbook/index.md deleted file mode 100644 index f9d8d7e6..00000000 --- a/doc/cookbook/index.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -layout: page -title: Cookbook ---- -{% include JB/setup %} - -# Project Setup - -* Creating a Scala.js project from scratch -* [Cloning the example application](./setup/example-app.html) -* [Customizing the example application](./setup/customize-app.html) -* [Creating a Scala.js project with giter8](./setup/giter8.html) -* Including 3rd party JavaScript libraries -* Including the DOM wrapper -* Including the jQuery wrapper -* Setting up a multi-module project - -# Development Tasks - -* Using incremental compilation -* Setting breakpoints on the browser -* Logging on the browser -* Using 3rd party JavaScript libraries -* Generating production / optimized code -* Troubleshooting Google's Closure compiler optimizations - -# JavaScript Interop - -* Overview of js.Scala types -* Understanding the implicit conversions - -## Calling JavaScript from Scala - -* [Accessing the JavaScript global scope](./interop/accessing-global-scope.html) -* [Passing basic types to JavaScript](./interop/passing-basic-types.html) -* Passing collections to JavaScript -* Passing anonymous functions to JavaScript -* Constructing JavaScript object-literals -* Dealing with JavaScript return values - -## Calling Scala from JavaScript - -* Scala.js calling convention -* Finding Scala object instances -* Passing basic JavaScript types to Scala -* Passing JavaScript collections to Scala -* Passing JavaScript functions to Scala -* Passing JavaScript object-literals to Scala -* Dealing with Scala return values - -## Writing type-safe wrappers - -* Wrapping JavaScript with traits -* Returning the same type (via `this.type`) -* Mapping variable parameters -* Mapping JavaScript's "new" - -# jQuery - -* Accessing the global jQuery object -* Registering to UI events -* Performing DOM queries -* Manipulating the DOM -* Performing AJAX calls -* Using jQuery UI - -# Testing - -* Set-up project for testing -* Writing Jasmine tests -* Testing non-UI code -* Testing UI functionality diff --git a/doc/cookbook/interop/accessing-global-scope.md b/doc/cookbook/interop/accessing-global-scope.md deleted file mode 100644 index 7f456888..00000000 --- a/doc/cookbook/interop/accessing-global-scope.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -layout: page -title: Accesing the JavaScript global scope ---- -{% include JB/setup %} - -## Problem - -You need to access the JavaScript global scope from Scala.js, in order to call functions like `alert`, `prompt`, `console`, etc. - -## Solution - -What we need is the `global` value, which is a "view" of the JavaScript global scope. - -It can be imported like this: - -{% highlight scala %} -import scala.scalajs.js.Dynamic.global -{% endhighlight %} - -Alternatively, you can import it like this: - -{% highlight scala %} -import scala.scalajs.js -import js.Dynamic.{ global => g } -{% endhighlight %} - -The latter might be more convenient way, since it imports the whole `js` package and renames `global` to something more easy to use (just `g`). - -Now let's issue an alert from Scala. Import the global scope and add this to your main class: - -{% highlight scala %} -def main(): Unit = { - g.alert("Hello from Scala") -} -{% endhighlight %} - -After re-compiling and re-loading the host page, you should see the corresponding browser alert. - -Let's write something to the JavaScript console. Change your main class to look like this: - -{% highlight scala %} -def main(): Unit = { - g.console.log("Logged a message from Scala") -} -{% endhighlight %} - -Re-compile and re-load. If you open your JavaScript console, you should see the message. diff --git a/doc/cookbook/interop/passing-basic-types.md b/doc/cookbook/interop/passing-basic-types.md deleted file mode 100644 index 2778e53d..00000000 --- a/doc/cookbook/interop/passing-basic-types.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -layout: page -title: Passing basic types to JavaScript ---- -{% include JB/setup %} - -## Problem - -You need to pass simple types (String, Int, Boolean) to JavaScript functions. - -## Solution - -Let us illustrate the case by writing some functions on the host-page. - -Edit `index-dev.html` and add the following function: - -{% highlight scala %} -function happyNew(name, year) { - alert("Hey " + name + ", happy new " + year + "!"); -} -{% endhighlight %} - -As we saw in the recipe of [accessing the global scope][1], we need to make the following import: - -{% highlight scala %} -import scala.scalajs.js -import js.Dynamic.{ global => g } -{% endhighlight %} - -Now on the Scala side you can call it like this: - -{% highlight scala %} -def main(): Unit = { - g.happyNew("Martin", 2014) -} -{% endhighlight %} - -Which will result in the values being used and the corresponding alert being shown. - -[1]: ./accessing-global-scope.html diff --git a/doc/cookbook/setup/customize-app.md b/doc/cookbook/setup/customize-app.md deleted file mode 100644 index b3f99aba..00000000 --- a/doc/cookbook/setup/customize-app.md +++ /dev/null @@ -1,102 +0,0 @@ ---- -layout: page -title: Customizing the example application ---- -{% include JB/setup %} - -## Problem - -You [cloned the example application](./example-app.html), but would like to have custom package and class names. - -For this recipe we'll assume that your organization is `com.mycompany` and your project is called `My Cool Project`. - -## Solution - -### Changing the project name - -Edit the `buid.sbt` and change the name to `My Cool Project`: - -{% highlight scala %} -name := "My Cool Project" -{% endhighlight %} - -### Renaming the packages - -Renaming the packages might be easier to accomplish from within an IDE than directly manipulating directories. - -In this case you should generate the IDE project first, and then import it (using the SBT plugins for either Eclipse or IntelliJ). - -After having imported the project to your IDE, rename the package `example` -(in "main" and in "test") to `com.mycompany.mycoolproject`. In the end, the -directory structure should match this: - - src/main/scala/com/mycompany/mycoolproject/ScalaJSExample.scala - src/test/scala/com/mycompany/mycoolproject/ScalaJSExampleTest.scala - -And the the Scala classes should refer to the new package: - -{% highlight scala %} -package com.mycompany.mycoolproject -{% endhighlight %} - -### Renaming the classes - -Rename both file-names and classes: - -1. from `ScalaJSExample(.scala)` to `MyCoolProject(.scala)`. -2. from `ScalaJSExampleTest(.scala)` to `MyCoolProjectTest(.scala)`. - -Make sure that you rename both files and classes, as in Scala they do not need -to match. - -Also watch out for the test class, since it references (imports) the main class. -If your IDE did not pick up the rename, you will have to fix it yourself: - -{% highlight scala %} -it("should implement square()") { - import MyCoolProject._ -{% endhighlight %} - -Lastly, though not critical, it would also be correct to change this line in the test class: - -{% highlight scala %} -describe("ScalaJSExample") { -{% endhighlight %} - -to: - -{% highlight scala %} -describe("MyCoolProject") { -{% endhighlight %} - -### Fixing the JavaScript file-references - -The HTML files `index-dev.html`, `index-preopt.html` and `index.html` are used -to "host" the Scala.js application. They load the generated JavaScript files, -which the SBT plugin generates somewhere under `target`, then fire up the -`main()` method. - -Since the generated file names correspond to the SBT-project's name (which we -renamed), the HTML files need to be updated. - -In `index-dev.html` you need to change: - -1. `example-extdeps.js` to `my-cool-project-extdeps.js` -2. `example-intdeps.js` to `my-cool-project-intdeps.js` -3. `example.js` to `my-cool-project.js` - -In `index-preopt.html`: - -1. `example-preopt.js` to `my-cool-project-preopt.js` - -And in `index.html`: - -1. `example-opt.js` to `my-cool-project-opt.js` - -Also, in all three HTML files, the inline script must call the new object: - -{% highlight html %} - -{% endhighlight %} diff --git a/doc/cookbook/setup/example-app.md b/doc/cookbook/setup/example-app.md deleted file mode 100644 index 0664d294..00000000 --- a/doc/cookbook/setup/example-app.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -layout: page -title: Cloning the example application ---- -{% include JB/setup %} - -## Problem - -You want to get started quickly with Scala.js, if possible from some existing pre-configured project. - -## Solution - -One good way is to clone the example application provided by Sébastien Doeraene. - -The project is located here: - -[https://github.com/sjrd/scala-js-example-app](https://github.com/sjrd/scala-js-example-app) - -This application has the following already set-up for you: - -* SBT settings for Scala.js -* HTML pages for development and production -* Jasmine testing -* Main and test classes -* Sample code \ No newline at end of file diff --git a/doc/cookbook/setup/giter8.md b/doc/cookbook/setup/giter8.md deleted file mode 100644 index fa632310..00000000 --- a/doc/cookbook/setup/giter8.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -layout: page -title: Creating a Scala.js project with giter8 ---- -{% include JB/setup %} - -## Problem - -You want to get started quickly with Scala.js from some existing pre-configured project, where you can specify custom names for packages and classes. - -## Solution - -Install [giter8](https://github.com/n8han/giter8) and use the [template for Scala.js](https://github.com/sebnozzi/scala-js.g8) projects. - -What is giter8? - -> "Giter8 is a command line tool to generate files and directories from templates published on github or any other git repository" - -Using the [giter8 template](https://github.com/sebnozzi/scala-js.g8) you can easily generate a [Scala.js](http://www.scala-js.org/) project where this is set-up automatically for you: - -* a custom **name** -* a custom **package structure** - -It saves you the work of having to [manually update](./customize-app.html) the directory structure, Scala classes, HTML and JavaScript files. - -### Installation - -#### Installing giter8 - -To install giter8 for the first time, follow the [installation instructions](https://github.com/n8han/giter8#installation) on the official page. - -If you _already_ have giter8 installed, but it's from before **17th Jan 2014**, you need to **upgrade** (if in doubt, upgrade). - -First, clean-up the [conscript](https://github.com/n8han/conscript) cache with: - - cs --clean-boot - -Afterwards, re-install giter8 with: - - cs n8han/giter8 - -### Usage - -#### Creating Scala.js projects - -From the command line, run: - - g8 sebnozzi/scala-js.g8 - -(Note that this schema refers to the [project on github](https://github.com/sebnozzi/scala-js.g8)) - -You will be asked for: - -1. Version, -1. Organization and -1. Name - -of your project. - -After enter the requested information your project structure will be created (note that in the example above the version was left blank and thus default value was taken). - -Sample session: - - # g8 sebnozzi/scala-js.g8 - - Scala.js Project - - version [0.1-SNAPSHOT]: - organization [org.example]: com.sebnozzi - name [ScalaJS Example]: My Cool Project - - Template applied in ./my-cool-project - - # cd my-cool-project - # sbt - -You can now use you Scala.js project as expected: `packageJS`, `test`, `optimizeJS` should all work from SBT. \ No newline at end of file diff --git a/doc/index.md b/doc/index.md index 8d5102b9..db0b18d8 100644 --- a/doc/index.md +++ b/doc/index.md @@ -23,7 +23,6 @@ Alternatively, create a project with *custom naming* by using this [giter8 templ * [Depending on Libraries](./sbt/depending.html) * [JavaScript Environments](./sbt/js-envs.html) * [Cross-Building](./sbt/cross-building.html) -* [Scala.js Cookbook](./cookbook/) ## API From 4af5134acdd02b5c05b5ea8b19c5adc314b48722 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Mon, 12 Jan 2015 11:31:17 +0100 Subject: [PATCH 08/16] Remove mention of the giter8 template. It's a bit obsolete and unmaintained. Moreover, set up a Scala.js project now requires so few boilerplate that it's best doing it from scratch. --- doc/index.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/doc/index.md b/doc/index.md index db0b18d8..a30cb2fd 100644 --- a/doc/index.md +++ b/doc/index.md @@ -9,8 +9,6 @@ title: Documentation Get started with Scala.js by following our [tutorial](./tutorial.html) or by forking off our [barebone skeleton](https://github.com/sjrd/scala-js-example-app). -Alternatively, create a project with *custom naming* by using this [giter8 template](https://github.com/sebnozzi/scala-js.g8). - ## Reference * [Differences between the semantics of Scala and Scala.js](./semantics.html) From 88b5bc783f8510bf6286fb89f17ab703168a163c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Mon, 12 Jan 2015 11:41:41 +0100 Subject: [PATCH 09/16] Strip down the list of presentations featured on the front page. Just showing the most recent ones among those that can convince people to use Scala.js. --- index.md | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/index.md b/index.md index 583ab7b2..6ae36daa 100644 --- a/index.md +++ b/index.md @@ -52,15 +52,10 @@ and not part of any of their support contracts. You have been warned!

* [Official mailing list](https://groups.google.com/forum/?fromgroups#!forum/scala-js): for general discussion, ideas, announcements of your libraries, etc. * [Gitter chat room](https://gitter.im/scala-js/scala-js): come and meet the community of Scala.js users. -Presentations: - -* [Hands-on Scala.js](http://vimeo.com/111978847) at PNWScala, by Li Haoyi -* [Cross-Platform Development in Scala.js](https://www.youtube.com/watch?v=Ksoi6AG9nbA), by Li Haoyi -* [Scala's evolving ecosystem- Introduction to Scala.js](http://blog.knoldus.com/2014/09/03/meet-up-on-scalas-evolving-ecosystem-introduction-to-scala-js/), by [Ayush Mishra](https://www.linkedin.com/pub/ayush-mishra/23/87b/a27), [Knoldus Software LLP](http://www.knoldus.com/home.knol) -* [Scala.js at Scaladays 2014](http://www.parleys.com/play/53a7d2cbe4b0543940d9e555), by Sébastien Doeraene -* [Live Coding Scala.js at SF Scala 2014](http://vimeo.com/87845442) by Li Haoyi -* [Live-coding with Scala.js at Scala eXchange 2013](http://skillsmatter.com/podcast/scala/scala-js-write-in-scala-for-the-browser-4567) -* [Presentation of Scala.js at Scala Days 2013](http://www.parleys.com/play/51c380bfe4b0ed8770356866) (older and somewhat obsolete) +Featured presentations to get you convinced: + +* [Hands-on Scala.js](http://vimeo.com/111978847) at Pacific North-West Scala 2014, by Li Haoyi +* [Cross-Platform Development in Scala.js](https://www.youtube.com/watch?v=Ksoi6AG9nbA) at Scala by the Bay 2014, by Li Haoyi ## Libraries From 72ce35d1d84c742acfce645ffbcbec4dd5ac710b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Fri, 23 Jan 2015 10:53:28 +0100 Subject: [PATCH 10/16] Change tagline from 'a' to '*the* Scala to JS compiler'. --- index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.md b/index.md index 6ae36daa..dd15bd49 100644 --- a/index.md +++ b/index.md @@ -1,7 +1,7 @@ --- layout: page title: Scala.js -tagline: A Scala to JavaScript compiler +tagline: the Scala to JavaScript compiler --- {% include JB/setup %} From 8c03b99c74fe459f094fb53730794dda109c9411 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Fri, 23 Jan 2015 16:51:16 +0100 Subject: [PATCH 11/16] Remove the Contribute section. This belongs to the contributing guide on GitHub. --- contribute/index.md | 24 ------------------------ contribute/javalib.md | 28 ---------------------------- index.md | 3 --- 3 files changed, 55 deletions(-) delete mode 100644 contribute/index.md delete mode 100644 contribute/javalib.md diff --git a/contribute/index.md b/contribute/index.md deleted file mode 100644 index 146e4efd..00000000 --- a/contribute/index.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -layout: page -title: Contribute -tagline: to Scala.js ---- -{% include JB/setup %} - -Scala.js is a fairly young project. Currently, it has a working core compiler, -and a minimal sbt plugin. But there is a lot more to do, and you can help! - -* Improve this website and the documentation by - [forking it on GitHub](https://github.com/scala-js/scala-js-website) -* [Port the Java library](javalib.html): - expand the port of the Java library written in Scala.js -* Check out the [ideas](https://github.com/scala-js/scala-js/issues?labels=ideas&page=1&state=open) on - the issue tracker for other cool things you could work on, - like [Play! Integration](https://github.com/scala-js/scala-js/issues/188) or a - [Testing Suite](https://github.com/scala-js/scala-js/issues/96) - -If you start seriously on something, make sure to -[mention it on the mailing list](https://groups.google.com/forum/?fromgroups#!forum/scala-js) -to avoid duplicating efforts. - -If you think about something else, come and discuss on the mailing list too! diff --git a/contribute/javalib.md b/contribute/javalib.md deleted file mode 100644 index 29da911e..00000000 --- a/contribute/javalib.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -layout: page -title: Port the Java library ---- -{% include JB/setup %} - -Scala is built on top of Java and its standard library. Therefore, Scala.js -needs some parts of the Java library to work. This port of the Java library -is itself written in Scala.js. - -Currently, only a very small portion is implemented. A very simple, although -sometimes tedious, thing that will help Scala.js is to expand this port. It -basically boils down to - -1. Identifying what classes are needed (either because they are used by the - Scala library, or because their are generally useful) -2. Implement their specification in Scala -3. "Native" methods in Java are typically implemented in Scala.js using the - interoperability with JavaScript. - -For license considerations, this must be a clean room implementation with -respect to most existing implementations. -However, as far as I understand it, the -[Apache Harmony](http://harmony.apache.org/) implementation, although -discontinued since 2011, can be used, since its license is compatible with -the BSD-style license of Scala.js. - -See [the JavaLib subdirectory on GitHub](https://github.com/scala-js/scala-js/tree/master/javalib/src/main/scala/java). diff --git a/index.md b/index.md index dd15bd49..067357fa 100644 --- a/index.md +++ b/index.md @@ -136,9 +136,6 @@ All these testing frameworks cross-compile on the JVM and JS. * [Scala.js on GitHub](https://github.com/scala-js/scala-js) -Want to contribute to Scala.js? Check out the -[list of contributing opportunities](./contribute/). - ## Built with Scala.js List of websites using Scala.js: From 843bab6379c8697917cb062b93ac4fb38f52af38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Fri, 23 Jan 2015 16:54:24 +0100 Subject: [PATCH 12/16] Update link to the benchmarks. --- index.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/index.md b/index.md index 067357fa..fe37784d 100644 --- a/index.md +++ b/index.md @@ -129,8 +129,7 @@ All these testing frameworks cross-compile on the JVM and JS. ## Miscellaneous -* [Port of the Dart benchmark harness](https://github.com/jonas/scala-js-benchmarks) - by Jonas Fonseca +* [Port of the Dart benchmark harness](https://github.com/sjrd/scalajs-benchmarks) ## Contribute From c860eb5ce71c37ac6eda0450ac05657e20b82477 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Mon, 26 Jan 2015 14:28:40 +0100 Subject: [PATCH 13/16] Remove the experimental notice. Replace it with a note saying it's not part of the Typesafe Reactive platform, and hence is not commercially supported. --- index.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/index.md b/index.md index fe37784d..301ad9fc 100644 --- a/index.md +++ b/index.md @@ -22,10 +22,8 @@ and follow the instructions in its readme or [try it out in the browser](http:// We also have a [standalone distribution](./downloads.html) that doesn't require SBT. -

Important notice! Scala.js is still experimental! -Although this is a project of LAMP/EPFL for which we will continue to provide -best-effort improvements and bug fixes, it is not supported by Typesafe, -and not part of any of their support contracts. You have been warned!

+_Note that Scala.js is not part of the Typesafe Reactive platform. +Thus, although we consider Scala.js production-ready, Typesafe does not provide any commercial support for it._ ## Noteworthy features From 16db226776779e11d6560af0156b593fdb4ff67c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Mon, 26 Jan 2015 14:32:12 +0100 Subject: [PATCH 14/16] Add performance to the list of noteworthy features. --- index.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/index.md b/index.md index 301ad9fc..6108cc2f 100644 --- a/index.md +++ b/index.md @@ -42,6 +42,8 @@ Thus, although we consider Scala.js production-ready, Typesafe does not provide your browser supporting source maps) * Integrates [Google Closure Compiler](https://developers.google.com/closure/compiler/) for producing minimal code for production. Compiled blobs range from 170-400kb +* Produces (very) efficient JavaScript code + ([benchmarks](https://github.com/sjrd/scalajs-benchmarks)) ## Resources From 834bc1e2a68b2720995bc8276068271f2b691be5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Mon, 2 Feb 2015 21:02:18 +0100 Subject: [PATCH 15/16] Updates for scalajs-{dom,jquery} 0.8.0. --- doc/index.md | 3 +++ doc/sbt/depending.md | 2 +- doc/tutorial.md | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/doc/index.md b/doc/index.md index a30cb2fd..7ddfb060 100644 --- a/doc/index.md +++ b/doc/index.md @@ -127,10 +127,13 @@ Generated Scaladocs are available here: ### JavaScript APIs #### DOM API +* [0.8.x scalajs-dom]({{ site.production_url }}/api/scalajs-dom/0.8/#org.scalajs.dom.package) * [0.7.x scalajs-dom]({{ site.production_url }}/api/scalajs-dom/0.7/#org.scalajs.dom.package) * [0.6 scalajs-dom]({{ site.production_url }}/api/scalajs-dom/0.6/#org.scalajs.dom.package) #### jQuery API +* [0.8.x scalajs-jquery]({{ site.production_url }}/api/scalajs-jquery/0.8/#org.scalajs.jquery.package) +* [0.7.x scalajs-jquery]({{ site.production_url }}/api/scalajs-jquery/0.8/#org.scalajs.jquery.package) * [0.6 scalajs-jquery]({{ site.production_url }}/api/scalajs-jquery/0.6/#org.scalajs.jquery.package) ## FAQ diff --git a/doc/sbt/depending.md b/doc/sbt/depending.md index a7e6bd4d..b8695c8c 100644 --- a/doc/sbt/depending.md +++ b/doc/sbt/depending.md @@ -8,7 +8,7 @@ title: Depending on Libraries To be able to use a Scala library in Scala.js, it has to be separately compiled for Scala.js. You then can add it to your library dependencies as follows: {% highlight scala %} -libraryDependencies += "org.scala-js" %%% "scalajs-dom" % "0.7.0" +libraryDependencies += "org.scala-js" %%% "scalajs-dom" % "0.8.0" {% endhighlight %} Note the `%%%` (instead of the usual `%%`) which will add the current Scala.js version to the artifact name. This allows to diff --git a/doc/tutorial.md b/doc/tutorial.md index 6b522785..2bd49fbd 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -179,7 +179,7 @@ That's what the DOM API is for. To use the DOM, it is best to use the statically typed Scala.js DOM library. To add it to your sbt project, add the following line to your `build.sbt`: {% highlight scala %} -libraryDependencies += "org.scala-js" %%% "scalajs-dom" % "0.7.0" +libraryDependencies += "org.scala-js" %%% "scalajs-dom" % "0.8.0" {% endhighlight %} sbt-savvy folks will notice the `%%%` instead of the usual `%%`. It means we are using a Scala.js library and not a normal Scala library. Have a look at the [Depending on Libraries](./sbt/depending.html) guide for details. Don't forget to reload the build file if sbt is still running: @@ -283,7 +283,7 @@ Larger web applications have a tendency to set up reactions to events in JavaScr Just like for the DOM, there is a typed library for jQuery available in Scala.js. Replace the `libraryDependencies += ...` line in your `build.sbt` by: {% highlight scala %} -libraryDependencies += "be.doeraene" %%% "scalajs-jquery" % "0.7.0" +libraryDependencies += "be.doeraene" %%% "scalajs-jquery" % "0.8.0" {% endhighlight %} Since we won't be using the DOM directly, we don't need the old library anymore. Note that the jQuery library internally depends on the DOM, but we don't have to care about this. sbt takes care of it automatically. From 7e97316612f506eb4fe2bfc3e0604ad3633449c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Mon, 26 Jan 2015 17:20:18 +0100 Subject: [PATCH 16/16] Announcing Scala.js 0.6.0. --- .../2015-02-05-announcing-scalajs-0.6.0.md | 296 ++++++++++++++++++ doc/index.md | 10 + downloads.md | 6 + index.md | 1 + 4 files changed, 313 insertions(+) create mode 100644 _posts/news/2015-02-05-announcing-scalajs-0.6.0.md diff --git a/_posts/news/2015-02-05-announcing-scalajs-0.6.0.md b/_posts/news/2015-02-05-announcing-scalajs-0.6.0.md new file mode 100644 index 00000000..6f884150 --- /dev/null +++ b/_posts/news/2015-02-05-announcing-scalajs-0.6.0.md @@ -0,0 +1,296 @@ +--- +layout: post +title: Announcing Scala.js 0.6.0 +category: news +tags: [releases] +--- +{% include JB/setup %} + +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](https://github.com/scala-js/scala-js/commit/9ad7627c2418e5d345375705ca087a60e3aa2c22) was pushed on February 5, 2013. + +## Getting started + +If you are new to Scala.js, head over to +[the tutorial]({{ BASE_PATH }}/doc/tutorial.html). + +## Release notes + +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](https://github.com/scala-js/scala-js/issues). + +The following libraries have already been upgraded and published for 0.6.0: + +* [DOM types](https://github.com/scala-js/scala-js-dom): `"org.scala-js" %%% "scalajs-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): `"com.lihaoyi" %%% "scalarx" % "0.2.7"` +* [µPickle](https://github.com/lihaoyi/upickle): `"com.lihaoyi" %%% "upickle" % "0.2.6"` +* [Autowire](https://github.com/lihaoyi/autowire): `"com.lihaoyi" %%% "autowire" % "0.2.4"` +* [scalajs-angulate](https://github.com/jokade/scalajs-angulate): `"biz.enef" %%% "scalajs-angulate" % "0.1"` +* [scalajs-angular](https://github.com/greencatsoft/scalajs-angular): `"com.greencatsoft" %%% "scalajs-angular" % "0.3"` +* [scalaz](https://github.com/japgolly/scalaz): `"com.github.inthenow" %%% "scalaz" % "7.1.0-4"` (via [@japgolly](https://github.com/japgolly)) + +The following testing frameworks are available: + +* [µTest](https://github.com/lihaoyi/utest): `"com.lihaoyi" %%% "utest" % "0.3.0" % "test"` +* [MiniTest](https://github.com/monifu/minitest): `"org.monifu" %%% "minitest" % "0.11" % "test"` +* [Greenlight](https://github.com/greencatsoft/greenlight) +* [ScalaCheck](https://github.com/rickynils/scalacheck): `"com.github.inthenow" %%% "scalacheck" % "1.12.2" % "test"` +* [zCheck](https://github.com/InTheNow/zcheck): `"com.github.inthenow" %%% "zcheck" % "0.6.0" % "test"` + +And the following helper sbt plugins as well: + +* [Workbench](https://github.com/lihaoyi/workbench): `addSbtPlugin("com.lihaoyi" % "workbench" % "0.2.3")` +* @InTheNow's [sbt-scalajs](https://github.com/InTheNow/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](https://github.com/scala-js/scala-js-dom): `"org.scala-js" %%% "scalajs-dom" % "0.8.0"` +* [jQuery types](https://github.com/scala-js/scala-js-jquery): `"be.doeraene" %%% "scalajs-jquery" % "0.8.0"` +* [ScalaTags](https://github.com/lihaoyi/scalatags): `"com.lihaoyi" %%% "scalatags" % "0.4.5"` +* [scalajs-angulate](https://github.com/jokade/scalajs-angulate) and [scalajs-angular](https://github.com/greencatsoft/scalajs-angular): not yet published + +To start a Play! project with Scala.js, have a look at [play-with-scalajs-example](https://github.com/vmunier/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. + +Possible replacements: + +* [uTest](https://github.com/lihaoyi/utest) +* [MiniTest](https://github.com/monifu/minitest) +* [Greenlight](https://github.com/greencatsoft/greenlight) +* [otest](https://github.com/cgta/otest) + +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](https://github.com/sjrd/scala-js-example-app/commit/6ccd5f64c3d46b203685a3c0762142513f5cc3e9), 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 `AutoPlugin` infrastructure 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 `fastOpt` and `fullOpt` stages. +In Scala 0.5.x, you could run in the `fastOpt` stage with: + + > fastOptStage::run + +In 0.6.x, the stage 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 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. +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 the PreLink and FastOpt stages*, 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 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 `ClassCastException`s 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: + +{% 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 sound. + +### The `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.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, respectively. +* `js.parseInt(s)` and `js.parseFloat(s)` should be replaced by `s.toInt` and `s.toDouble`, respectively. +* `js.NaN`, `js.Infinity` should be replaced by `Double.NaN` and `Double.PositiveInfinity`, respectively. +* `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, 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](https://github.com/scala-js/scala-js/tree/v0.6.0/sbt-plugin-test). +Some highlights: + +* [Build definition for the cross-compiling framework](https://github.com/scala-js/scala-js/blob/v0.6.0/sbt-plugin-test/build.sbt#L49-L64) +* [(Cross-compiling) source code of the testing framework](https://github.com/scala-js/scala-js/tree/v0.6.0/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/sbt-plugin-test/build.sbt#L66-L86) +* [Source code of the project using the framework](https://github.com/scala-js/scala-js/tree/v0.6.0/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`]({{ site.production_url }}/api/sbt-scalajs/0.6.0/#org.scalajs.sbtplugin.cross.CrossProject) for more information and examples. + +### Faster! + +Scala.js 0.6.0 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 and `js.Dictionary`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]({{ site.production_url }}/api/scalajs-library/0.6.0/#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. + +### Obfuscation of class names + +The `scalaJSSemantics` option also allows to obfuscate or otherwise rename the class names in the emitted .js file, as was requested in [#1113](https://github.com/scala-js/scala-js/issues/1113). +For example, this sbt setting empties out all class names in the package `my.company`: + +{% highlight scala %} +scalaJSSemantics ~= (_.withRuntimeClassName { linkedClass => + val fullName = linkedClass.fullName + if (fullName.startsWith("my.company.")) "" + else fullName +}) +{% endhighlight %} + +This changes the value returned by `x.getClass.getName` or `classOf[C].getName`. + +### 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. + +## Bugfixes + +Amongst others, the following bugs have been fixed since 0.5.6: + +* [#1430](https://github.com/scala-js/scala-js/issues/1430) `ClassTag.unapply` method (for deconstruction) fails for raw JS classes +* [#1423](https://github.com/scala-js/scala-js/issues/1423) String.getBytes returns trailing zeroes +* [#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` +* [#1451](https://github.com/scala-js/scala-js/issues/1451) ScalaDoc run crashes with property `@JSExports` +* [#1455](https://github.com/scala-js/scala-js/issues/1455) Runs for ScalaDoc complain about `@JSExport(SomeFinalVal)` +* [#1458](https://github.com/scala-js/scala-js/issues/1458) PhantomJS 2 expects a scheme name (`file:///`) for all urls, not just a path to local files diff --git a/doc/index.md b/doc/index.md index 7ddfb060..ec1f0074 100644 --- a/doc/index.md +++ b/doc/index.md @@ -28,6 +28,16 @@ Generated Scaladocs are available here: ### Scala.js +#### Scala.js 0.6.0 +* [0.6.0 scalajs-library]({{ site.production_url }}/api/scalajs-library/0.6.0/#scala.scalajs.js.package) +* [0.6.6 scalajs-test-interface]({{ site.production_url }}/api/scalajs-test-interface/0.6.0/) +* [0.6.0 scalajs-stubs]({{ site.production_url }}/api/scalajs-stubs/0.6.0/) +* [0.6.0 scalajs-ir]({{ site.production_url }}/api/scalajs-ir/0.6.0/#org.scalajs.core.ir.package) +* [0.6.0 scalajs-tools]({{ site.production_url }}/api/scalajs-tools/0.6.0/#org.scalajs.core.tools.package) ([Scala.js version]({{ site.production_url }}/api/scalajs-tools-js/0.6.0/#org.scalajs.core.tools.package)) +* [0.6.0 scalajs-js-envs]({{ site.production_url }}/api/scalajs-js-envs/0.6.0/#org.scalajs.jsenv.package) +* [0.6.0 scalajs-test-adapter]({{ site.production_url }}/api/scalajs-sbt-test-adapter/0.6.0/#org.scalajs.testadapter.package) +* [0.6.0 sbt-scalajs]({{ site.production_url }}/api/sbt-scalajs/0.6.0/#org.scalajs.sbtplugin.package) + #### Scala.js 0.6.0-RC2 * [0.6.0-RC2 scalajs-library]({{ site.production_url }}/api/scalajs-library/0.6.0-RC2/#scala.scalajs.js.package) * [0.6.6-RC2 scalajs-test-interface]({{ site.production_url }}/api/scalajs-test-interface/0.6.0-RC2/) diff --git a/downloads.md b/downloads.md index d14bfa3c..fcbf0381 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 +* [0.6.0, Scala 2.11 (tgz, 20MB)]({{ site.production_url }}/files/scalajs_2.11-0.6.0.tgz) +* [0.6.0, Scala 2.11 (zip, 20MB)]({{ site.production_url }}/files/scalajs_2.11-0.6.0.zip) +* [0.6.0, Scala 2.10 (tgz, 18MB)]({{ site.production_url }}/files/scalajs_2.10-0.6.0.tgz) +* [0.6.0, Scala 2.10 (zip, 18MB)]({{ site.production_url }}/files/scalajs_2.10-0.6.0.zip) + #### Scala.js 0.6.0-RC2 * [0.6.0-RC2, Scala 2.11 (tgz, 20MB)]({{ site.production_url }}/files/scalajs_2.11-0.6.0-RC2.tgz) * [0.6.0-RC2, Scala 2.11 (zip, 20MB)]({{ site.production_url }}/files/scalajs_2.11-0.6.0-RC2.zip) diff --git a/index.md b/index.md index 6108cc2f..148ffa66 100644 --- a/index.md +++ b/index.md @@ -174,6 +174,7 @@ List of websites using Scala.js: ## Version History +- [0.6.0](/news/2015/02/05/announcing-scalajs-0.6.0/) - [0.6.0-RC2](/news/2015/01/23/announcing-scalajs-0.6.0-RC2/) - [0.6.0-RC1](/news/2015/01/12/announcing-scalajs-0.6.0-RC1/) - [0.6.0-M3](/news/2014/12/22/announcing-scalajs-0.6.0-M3/)