JS++ 0.8.1: auto, catch-all, and Time

JS++ 0.8.1 fixes two major bug fixes that appeared when we introduced generics (0.8.0) and introduces some very useful new features. If you come from a C++ background, you might appreciate some of the new syntax :-).

‘auto’ Keyword

With the introduction of generic programming in 0.8.0, we need a more concise syntax to instantiate generic classes. The auto keyword solves this problem.

Now, instead of the following:

VeryLongClassName<string> foo = new VeryLongClassName<string>();

You can instead instantiate classes using auto:

auto foo = new VeryLongClassName<string>();

auto can be used for more than just generic classes though:

class Foo {}

auto foo = new Foo();

The auto keyword can only be used for variable declarations, and it reduces the redundancy of having to specify the type on the left-hand side only to repeat yourself on the right-hand side. This is known as local-variable type inference (to use the Java 10 terminology). For fans of C++, you may recognize this syntax.

Catch-all Clauses

This is another syntax that comes from C++.

Sometimes, you’ll want to catch an exception, but you don’t care to do anything with the exception object. In other cases, you may want to catch a specific type of exception but ignore all other exceptions. The “catch-all” clause can help you:

import System;

try {
    throw new System.Exception();
}
catch(System.Exception e) {
    Console.log(e.getMessage());
}
catch(...) {
    Console.log("The catch-all clause provides no exception object but will catch all exceptions - whether the type of the exception is internal or external.");
}
import Externals.JS;

try {
    throw new ReferenceError();
}
catch(...) {
    Console.log("Do nothing");
}

System.Time.TimeUnits

JS++ has an emphasis on readability. Have you ever seen code that looks like this?

setInterval(function() { /* ... */ }, 3600000);

The System.Time module has been introduced for dealing with time. Specifically, we’ve introduced a TimeUnits module to directly deal with the above case:

import System.Time;
external setInterval;

setInterval(void() { /* ... */ }, TimeUnits.hours(1));

Or, more succinctly:

import System.Time.TimeUnits;
external setInterval;

setInterval(void() { /* ... */ }, hours(1));

As always, we’ve had a focus on readable code. Here’s a preview of how well this composes:

import System;
import System.Time.TimeUnits;

Console.log(hours(1) + minutes(5));

Externals.Time

In JavaScript, functions such as setTimeout and setInterval are not part of the ECMAScript standard; they are provided by the host environment. Web browsers and Node.js ship with these functions, but it would not have been correct to add this to the Externals.JS module. Therefore, we’ve introduced the Externals.Time external module so you can more clearly work with timers.

Bug Fixes

  • Fixed methods with variadic parameters passing by reference
  • Fixed implementing of generic interfaces from generic classes
  • MAJOR BUG FIX: Fixed double calls being generated for getters
  • MAJOR BUG FIX: Fix this binding in code generation

JS++ 0.8.0: Altitude MVC, Generics, System.Dictionary, and More

This is a major update that has been in the works for a while.

Altitude MVC

Altitude MVC

Altitude is an MVC/MVP framework for JS++. It follows a “pure MVC” approach. In other words, the user uses the controller to manipulate the model, the model updates the view, and the view is fed back to the user as explained in this diagram from Wikipedia.

The “pure MVC” approach has historically proven to scale. Internally, we have tested Altitude for an application consisting of 3,000+ lines of JS++ code, and it has served us well.

Lastly, Altitude contains fewer than 100 lines of code (if you remove comments and whitespace). In an age when load times influence search rankings and you can get downgraded to a 2G/3G connection at any time, it’s important for libraries to be as lightweight as possible. However, there is one external JavaScript dependency (Handlebars.js), and, optionally, jQuery.

Despite the small size of the library, we’ve managed to scale it for a relatively large and complex internal email application. Examples are included to get you started. As usual, we also spoil you with documentation.

Download it here.

Generics

The major new language feature is generics (parametric polymorphism). You can now define generic classes in JS++:

class Foo<T>
{
    /* ... */
}

Generic programming allows you to specify “type parameters” for a class. This allows you to create classes that can operate on any data type.

In version 0.8.0, JS++ supports the following generic programming features:

  • Multiple generic arguments
  • Multiple generic constraints
  • Inheritance (including generic from generic)

More advanced generic programming features (such as sound covariance/contravariance) are scheduled for upcoming releases.

System.Dictionary<T>

While generics are a major feature, on a day-to-day basis, the official introduction of System.Dictionary<T> may be more important. Dictionaries are documented here and here. Dictionaries are also known as associative arrays, maps, etc.

Dictionaries allow you to create key-value pairs. The keys must be strings, but the values can be any data type.

import System;

Dictionary<unsigned int> ages = {
    "Steve": 25,
    "David": 31
};

Arbitrary key types will be possible in the future as we continue to expand the Standard Library. It’s going to be so much easier than JavaScript objects with non-string keys.

Multi-line Strings

This feature was available from the last release (0.7.0), but it wasn’t properly announced.

You can create multi-line strings with a syntax similar to Python’s:

string html =
    """
    <!DOCTYPE html>
    <head></head>
    <body>
    <div id="notice the quotes are unescaped">some content goes here</div>
    </body>
    </html>
    """;

Multi-line strings are a useful way to create heredocs. One use case is pasting large blocks of HTML text that you don’t want to manually escape.

System.BoxedExternal

I consider this a critical class. If you understand the JS++ type system, you should understand the difference between “internal” types and “external” types. The BoxedExternal class basically allows you to construct an internal value (with an internal type) using any external value that has an external type.

When you box an external, it has an internal type. When you unbox the boxed external, you get a value with an external type. It’s extremely useful and is one way to achieve safe bi-directional communication between JavaScript and JS++.

Furthermore, if you’re using System.Object in your APIs, it becomes absolutely critical. Sometimes, you might want to define a function that can accept internal or external values.

System.Benchmark

This was a user request. The System.Benchmark class makes it easy for you to benchmark your code.

Here’s an example:

import System;
 
Benchmark bench = new Benchmark();
bench.start();

// ... do stuff
for (int i = 0; i < 500; ++i) {
    Math.sqrt(2);
}

bench.stop();
  
Console.log(bench.duration);

It wasn't that this wasn't possible prior to the Benchmark class being introduced. It was just painful and unreadable. Remember: JS++ has an emphasis on code readability.

Dead Code Elimination (DCE) Improvements

In previous versions of JS++, dead code elimination (DCE) would not eliminate inherited methods. Since 0.8.0, the JS++ compiler supports DCE even in inheritance settings. This reduces the code size and footprint of the final output.

.js++ File Extension

Previously, JS++ supported the .jspp and .jpp file extensions. As of version 0.8.0, the JS++ compiler now officially supports the .js++ file extension too. When you input a directory to the compiler, it will automatically recursively search for .jspp, .jpp, and .js++ files now.

In order to support the new .js++ file extension, you may need to update your editor support.

Warnings

This is probably the biggest release if you've been annoyed with the compiler warnings. We've completely suppressed the warnings for variable shadowing. JSPPW0015 and JSPPW0016 are gone. We're going to see how this goes or at least come up with saner rules before raising warnings. We've had applications internally that were raising hundreds of warnings on source code that otherwise compiled OK.

The #1 design principle here is that excessive warnings cause users to ignore warnings. Thus, we're being extra careful here.

Miscellaneous

  • System.Date copy constructor added
  • Binding on virtual methods
  • Removed System.Object.hashCode
  • Fixed segmentation fault for [].concat(1, 2, 3)
  • Fix segmentation fault for if(foo) where foo is an object
  • Fix closure capturing variable with name arguments
  • Don't cache .length of an array in for-in/each loops, to address potential array modification inside loops
  • Allow implicit conversion for double[] a = [1];
  • Forbid access modifier changes on override
  • Don't generate prototype chain for non-virtual methods
  • Lowest Common Ancestor (LCA) for expressions. This allows the type checker to deduce the type for arrays and dictionaries when polymorphism is present.

Looking Ahead

Expect Standard Library expansion and modifications.

We made changes to the original JavaScript API in our original Standard Library implementation. (Because whose great idea was it to introduce a String.substring and a String.substr in JavaScript?) We're likely going to restore the JavaScript API, and we're going to add data structures such as sets, maps, and more. We're also thinking about popular cryptography algorithms such as MD5, SHA1, and AES.

Meanwhile, generics will continue to be expanded and improved in future short-term releases.