JavaScript extensions in Squish 7.0

Last edited on

Squish 7.0 ships with several extensions to the JavaScript support. The main ones are described below.

The earlier additional of classes and modules has been documented in a separate article for Squish 6.6 .

New Operators

Added new null coalescing operators and others from ECMAScript 2021: ??, ??=, &&= and ||=.

The ?? operator, for example, provides a shorthand for checking a value for null or undefined. Instead of checking a value like this

let result = someFunction();
if (result == null || typeof result == "undefined")
    result = "default";

the check can be shortened to:

let result = someFunction() ?? "default";

Sealing and Freezing of Objects

Added Object.seal() and Object.isSealed() as well as Object.freeze() and Object.isFrozen().

The behavior of Object.preventExtensions() and Object.isExtendible() got adapted to ECMAScript 2015. Both functions will not throw an error on non-object type arguments anymore.

The difference between these three concepts is not easy to understand. A brief summary:

Module exports

Previously, the only way to export classes from a module involved a two-step approach: the declaration class C { ... }and a separate export { C }declaration. The following shortcut notation is possible now:

export class C {
    // ...
};

In addition, a 'deferred' default export can be achieved with the following syntax now: First, declare the entry:

class C {
    // ...
}

Then, export the entry with the magic default name:

export { x as default };

New Object Literals

Added additional types of object literal have been added. Next to {a: b, c: d} that is: {x}, {a: b,}, {[expr]: value]}, {f() { return 1;}}, {get x() { }) and {set x(v) { }}. Some examples are listed below.

Expand an identifier and its associated value:

let one = 1;
let unity = { one }; // { one: 1 }

A property's identifier can be specified by an arbitrary expression when surrounded by square brackets:

let msg = { [uk ? "colour" : "color"] : "red" };

Shorthand for a function definition without usage of the function keyword:

let cm = { factor: 100, fromMeters(m) { return m * 100; }}
cm.fromMeters(2); // 200

Shorthands for getter and setter functions:

let distance = { l: 0,
                 get length() { return this.l },
                 set length(v) { this.l = v < 0 ? -v : v }};
distance.length = -10;
test.log(distance.length); // prints 10

Spread Operator

Support the spread operator for function call arguments: (foo(...args)), array literals [...e] and object literals {...x}. The new ... operator expands any iterable object (like an array) into list that will be passed as e.g. function arguments. Example:

function sum(a, b, c) {
    return a + b + c;
}
let x = [1, 2, 3];
test.log(...x); // will print 6

Arrays can be constructed from other arrays like this:

let d2 = [10, 20];
let d3 = [..d2, 30]; // expanded to [10, 20, 30]

Spreading is not limited to arrays. Any object with iterable items work. Like a string:

let chars = [..."red"]; // expanded to ["r", "e", "d"]

Object literals can make use of the operator as well:

let a = { x: 1, y: 2};
let b = { ...a, z: 3}; // expanded to { x: 1, y: 2, z: 3 }

Bugfix

Fixed this value in function called via a super reference. It pointed to a wrong object before.

Note on IDE Support

Some of the recently added features go beyond what the 3rd party JavaScript editor from Eclipse is able to support. Script code that will work fine in SquishRunner may have incomplete syntax highlighting or code completion in the IDE. We are investigating a replacement of the editor with completely different implementation.