ClojureScript

1.10.439 Release

02 November 2018
ClojureScript Team

Noteworthy Changes

Closure Compiler has been upgraded to v20180805.

The :npm-deps compiler option now defaults to false. Previously, :npm-deps defaulted to true.

Improved Compiler Performance

The compiler is now much faster when compared with the 1.10.339 release for both regular builds and when :parallel-build is set to true.

Warnings on Private Var Use

ClojureScript will now warn on private var use.

Let’s say you have a function intended for private use in a namespace:

(ns foo.core)

(defn- some-impl [x]
  (inc x))

and you inadvertently use it from some other namespace, as in

(ns bar.core
 (:require [foo.core]))

(foo.core/some-impl 3)

The compiler will now emit a helpful diagnostic:

WARNING: var: foo.core/some-impl is not public

This is only a warning; the ClojureScript compiler continues to allow private var use, but now emits a new analysis warning, controllable via :private-var-access.

If var indirection is used instead, no warning will be emitted:

(#'foo.core/some-impl 3)

Function Return Type Inference

ClojureScript now infers function return types, propagating this information to call sites.

Consider these predicates:

(defn finite? [x]
  (not (infinite? x)))

(defn big? [x]
  (and (pos? x)
       (finite? x)))

Previously, code like the following

(if (big? 11)
  "hi"
  "bye")

would emit defensive JavaScript that coerces the return value of big? to a Boolean by using cljs.core.truth_:

(cljs.core.truth_(cljs.user.big_QMARK_.call(null,(11)))?"hi":"bye")

Now, the compiler instead infers that finite? always returns a Boolean value, and therefore so does big?, and emits more efficient code:

((cljs.user.big_QMARK_.call(null,(11)))?"hi":"bye")

With inference like this, it is no longer necessary to manually add a ^boolean type hint to a predicate used in performance-critical code, so long as the return value can be infered from the predicate function body.

In general, any inferred types will automatically flow from function bodies outward, such as an inferred numeric type in the following example:

(defn foo [x]
  (+ x 3))

If foo is used in a context where types are checked, as in

(+ (foo 1) "a")

you will now see a warning that properly reflects the type:

WARNING: cljs.core/+, all arguments must be numbers, got [number string] instead

Previously, without a type hint on foo, the compiler would produce a warning that indicates a type of any instead of number.

Graal.JS REPL Environment

ClojureScript now ships with a Graal.JS REPL environment. This is a new Java-based REPL environment which is similar to the existing Nashorn REPL environment, but instead uses the new Graal.JS JavaScript engine that ships as part of GraalVM.

The Graal.JS REPL environment automatically configures the Graal.JS engine to allow Polyglot calls to other languages that may be installed.

If you have the GraalVM version of Java on your path, to use this new REPL environment with cljs.main, simply specify --repl-env graaljs:

$ clj --main cljs.main --repl-env graaljs --repl
ClojureScript 1.10.439
cljs.user=> (.eval js/Polyglot "R" "sum(1:100)")
5050
cljs.user=> (.eval js/Polyglot "ruby" "(1..100).reduce(:+)")
5050

In addition to Polyglot support, the Graal.JS engine is much faster than Nashorn, approaching the performance of the other leading JavaScript engines, especially when warmed up and the JVM has had an opportunity to optimize hotspots.

Since GraalVM hasn’t yet been released and things could still change, this new REPL environment should be considered beta. We encourage you to give it a try!

Updates to Spec

This release includes many updates to Spec, bringing changes and fixes that have been made to the Clojure implementation of Spec to ClojureScript.

Updates to AST Representation

The internal AST representation has been updated to match tools.analyzer. This will simplify things for tooling that works with the AST generated by ClojureScript.

Change List

For a complete list of updates in ClojureScript 1.10.439 see Changes.

Contributors

Thanks to all of the community members who contributed to ClojureScript 1.10.439:

  • Ambrose Bonnaire-Sergeant

  • Erik Assum

  • Eugene Kostenko

  • Henry Widd

  • Jordan Biserkov

  • Juho Teperi

  • Mike Fikes

  • Oliver Eidel

  • Ray McDermott

  • Thomas Spellman

Grant Support

Thanks to Clojurists Together and its supporting members for funding a significant amount of work that went into this release!

For details see