Join us at the Oolite Anniversary Party -- London, 7th July 2024, 1pm
More details in this thread.

Updated JavaScript and you

Discussion and information relevant to creating special missions, new ships, skins etc.

Moderators: winston, another_commander

Post Reply
User avatar
JensAyton
Grand Admiral Emeritus
Grand Admiral Emeritus
Posts: 6657
Joined: Sat Apr 02, 2005 2:43 pm
Location: Sweden
Contact:

Updated JavaScript and you

Post by JensAyton »

Oolite nightlies are now using an updated JavaScript engine which supports ECMAScript Fifth Edition. Here’s an overview of new features:

Strict mode
Strict mode causes certain bad behaviours to be treated as errors, and potentially lets scripts run a bit faster. To activate strict mode, put the string "use strict" as a statement by itself at the start of your script, or at the start of a function body to use it only in that function:

Code: Select all

this.foo = function ()
{
    "use strict"; // You are now entering the strict zone.
    var x;
    delete x; // Exception in strict mode, warning otherwise.
}
Many of the things that are not allowed in strict mode were already warnings because Oolite ran SpiderMonkey in, er, strict mode. But a different strict mode. For Oolite’s purposes, this SpiderMonkey-specific strict mode has now been renamed “pedantic mode”.

You can read more about strict mode on the interwebs, for instance here. I recommend using it, at least for new scripts. All Oolite’s built-in scripts now do.

JSON
ECMAScript 5 has build-in support for JSON, a common format for representing structures as strings – similar to plists. The obvious use case in Oolite is that it allows you to store structured data in mission variables.

Code: Select all

this.$settings = JSON.parse(missionVariables.mySettings);
if ($settings == null)  $settings =
{
    aString: "Frederick",
    aNumber: 73,
    anObject: { stuff: [ "banana", {}, false ] }
};

this.$saveSettings = function ()
{
    missionVariables.mySettings = JSON.stringify($settings);
}
Array and string extras
A number of higher-order functions for array processing are now standardised. These methods were already supported in Oolite, except for reduce() and reduceRight().

A new function Array.isArray() reliably tests whether an object is a standard array. Note that this is not a method on the object being tested; to see if [i]foo[/i] is an array, call Array.isArray([i]foo[/i]), not [i]foo[/i].isArray().

A new string method trim() deletes whitespace at the beginning and end of strings, so " banana ".trim() becomes "banana". This is already supported in Oolite 1.74 through the global prefix script.

Function.prototype.bind()
Already common in web JS libraries, bind() is a method on functions that defines their this value:

Code: Select all

var foo =
{
    x: 5,
    f: function () { return x + 1; }
}

var f1 = foo.f;
f1(); // Error: x is undefined.
var f2 = foo.f.bind(foo);
f2(); // Works.
This is mostly useful with callback APIs that don’t take a this parameter. All of Oolite’s do, so if this just looks confusing you can ignore it.

Object “meta-control”
The new object and property configuration methods are good additions, but rather abstract, and I’m not going to try to describe them at this time of night. They’re mostly of interest for writing libraries, and if you’re doing that you hopefully don’t get all your JavaScript information from me.

Moar faster
Not actually an ECMAScript 5 feature, the new version of SpiderMonkey includes not one but three JIT compilers¹ – TraceMonkey, JägerMonkey and YARR – and is competitive with the two WebKit JavaScript engines (SquirrelFish and V8) which have been dominating the ongoing speed war for the last few years. In updating to the new engine, several speed improvements have been made in Oolite’s JavaScript-related code as well.

¹However, only one (TraceMonkey) works on PowerPC systems.
User avatar
JensAyton
Grand Admiral Emeritus
Grand Admiral Emeritus
Posts: 6657
Joined: Sat Apr 02, 2005 2:43 pm
Location: Sweden
Contact:

Re: Updated JavaScript and you

Post by JensAyton »

(Might as well put this here too)

Fixed prototype chains
The relationship between Oolite-defined JavaScript objects and their prototypes (from which they inherit behaviour) has been broken ever since JavaScript support was introduced. This has now been fixed. The most important consequence of this is that methods and properties on singleton instances, such as player.ship and system, must now be called on the singleton instance rather than the constructor (PlayerShip and System respectively). Previous versions of Oolite would let you call System.addShips() instead of system.addShips() and PlayerShip.launch() instead of player.ship.launch(); 1.75 will not. (Note that the methods listed under “Static Methods”) on the System reference page are intended to be called on System rather than system, because they deal with systems in general rather than this system.)

As a lesser consequence, the instanceof operator now works properly: player.ship instanceof PlayerShip evaluates to true.
User avatar
Lone_Wolf
---- E L I T E ----
---- E L I T E ----
Posts: 546
Joined: Wed Aug 08, 2007 10:59 pm
Location: Netherlands

Re: Updated JavaScript and you

Post by Lone_Wolf »

Thanks for these informative posts, JensAyton.

Recently i had problems in an oxp, thought oolite js lacked support for accessing objects declared as literals from other scripts.

I looked into Object.defineProperty and the bind option and found them tricky but very interesting.
I was close to using both to solve my problems, started to prepare a post to inform other oxp authors of my findings, then stumbled upon this thread .
It made very clear that oolite JS already supported what i needed.
I checked my code and found my problems were caused by typos.
OS : Arch Linux 64-bit - rolling release

OXPs : My user page

Retired, reachable at [email protected]
Post Reply