ECMAScript.next: new details, reacting to Dart complaints

[2011-09-25] esnext, dev, javascript
(Ad, please don’t block)
On September 18, 2011, Brendan Eich held a talk at CapitolJS. In it, he covered more details on what will be in ECMAScript.next; how to react to the complaints voiced by Dart’s creators; and RiverTrail, a JavaScript extensions for parallel programming. This post summarizes the highlights of the first two topics.

News about ECMAScript.next features

Things that are new with regard to 2ality’s previous coverage (which you should read first):
  • dom.js: Currently, the DOM is a C++ API, specified in the C++-centric WebIDL (Web Interface Definition Language) and clumsily bound to JavaScript. This makes it both slow and difficult to use. It is widely considered the part of the web stack that most needs fixing [1]. Implementing the DOM in pure JavaScript is a first step towards improving it. dom.js is an attempt to comply 100% with the WebIDL specification. And it needs ECMAScript.next features (Proxies and WeakMaps) to achieve that goal. Quoting Eich:
    BTW, dom.js [...] is going great, with David Flanagan and Donovan Preston among others hacking away on it, and (this is important) providing feedback to WebIDL’s editor, Cameron McCormack.
    An episode of “A Minute With Brendan Eich” provides background information on dom.js.
  • Can we call it ECMAScript 6, yet? The next version of ECMAScript will almost certainly be called ECMAScript 6. However, it is still better to use the term ECMAScript.next for the set of features currently under discussion at the Ecma TC39 wiki. The reason is that much can still change and saying that a feature is “in ECMAScript 6” might be confusing. Instead, Allen Wirfs-Brock suggests to only use that phrase for features that appear in the draft ECMAScript 6 specification that he is currently writing. Consult [2] for the difference between ECMAScript.next and ECMAScript Harmony (the former is a subset of the latter).
  • Private properties: Initially, private properties were part of the class literal proposal, but they are now handled by a combination of two constructs.

    Construct 1: private name objects.

        module name from "@name";
        let key = name.create();
        function MyClass(privateData) {
            this[key] = privateData;
        }
    
    Private names are hidden from mechanisms such as
    • Object.getOwnPropertyNames()
    • for...in

    Construct 2: computed keys in object literals.

        const __password = Name.create();
        var obj = {
            [__password]: "my secret",
            unlock: function(pwd) {
                if (pwd === this[__password]) {
                    ...
                }
            }
        };
    
    Putting an expression in square brackets allows you to compute the name of a property in an object literal.
  • Shorter function expressions: There are currently two competing proposals.
    1. Arrow function syntax, inspired by CoffeeScript.
      let square = (x) -> (x * x); // expression body
      let range = (start, end) { // statement body
          var result = [];
          for(; start < end; start++) {
              result.push(start);
          }
          return result;
      };
      // fat arrow: use "this" of surrounding function
      callback = (msg) => ( this.vmail.push(msg) );
      
    2. Block lambdas.
      let empty = {||};
      let square = {|x| x * x };
      
      // paren-free call to mimic control structure syntax.
      // Therefore: no semicolon at the end.
      let a = [1, 2, 3];
      let b = a.map { |e| e * e }; // [1, 4, 9]
      
      // Bonus: break, continue, return leave the block
      // (unlike in function expressions)
      Boolean.prototype.thenElse = function(ifTrue, ifFalse) {
          return this ? ifTrue() : ifFalse();
      }
      function getElement(arr, index) {
          (index < 0).thenElse {||
              return arr[arr.length + index];
          } {||
              return arr[index];
          }
      }
      
    So far, TC39 has only decided that the proposals are mutually exclusive, they won’t both be adopted. But it is not clear if either one will make it into ECMAScript and if so, which one. Eich prefers block lambdas:
    I’ve been clear about preferring block-lambdas over arrows for their added semantic value and compelling syntax mimicking control statements. It’s good to hear @jashkenas [CoffeeScript creator Jeremy Ashkenas] agree in effect.

    [...] JS syntax is not a problem for some (perhaps many) users. For others, it’s a hardship. Adding block-lambdas helps that cohort, adds value for code generators (see Harmony Goals above), and on balance improves the language in my view. It won my straw show-of-hands poll at CapitolJS against all of arrows, vaguer alternatives, and doing nothing.

    I agree with Eich’s choice. When used as an argument for a function, a block lambda has lexical “this”this in a block lambda refers to the object on which the surrounding method has been invoked. That will eliminate a frequent source of errors that sometimes even tricks experts. With block lambdas, JavaScript newbies will automatically do the right thing.

Dart versus ECMAScript.next

What is currently known about Dart’s rationale for replacing JavaScript is simplistic [3]. But Eich cautions:
Still, I think we should react to valid complaints about JS, whatever the source.
Some of the complaints, with reactions:
  • We need static compiler optimizations. The performance of JavaScript engines is still improving, much can be done via type inference, and there is a proposal for optional runtime guards (that can help static optimization).
  • There is only a single number primitive. This does hurt JavaScript performance and there is currently no proposal for fixing this. Eich mentions the following idea:
    • Suffixes: 304i + 1i
    • Promotion rules as in C, but with dynamic types [convert to higher precision depending on the current operation].
    Eich finds this too problematic and prefers a pragma to control arithmetic – use bignum arithmetic; use int arithmetic; etc.:
    This would have to affect Number and Math, but lexically — no dynamic scope. Still a bit hairy, and not yet on the boards for Harmony. But perhaps it ought to be.
    I don’t find this solution particularly intuitive. Maybe one could use an object-oriented solution that is compiled to something more efficient.
        var a = new BigNum(344);
        var b = BigNum.parse(inputString);
        var c = a.times(b);
    
    The above is a bit like the pragma, but allows one to mix different arithmetics.
  • ECMAScript is not evolving fast enough. Eich makes several points (quoted verbatim):
    • My suggestion is to prototype in SpiderMonkey and V8 some of the strawman proposals that did not make ES6 now, and see if any deserve promotion to ES6.
    • Coordinated strawman prototyping in SpiderMonkey and V8 is a tall order. Perhaps we need a separate jswg.org, as whatwg.org is to the w3c, to run ahead? I’ve been told I should be BDFL [Benevolent Dictator For Life] of such an org. Would this work? Comments welcome.
    • [...] would the jswg.org have to produce a JS’ to JS compiler, or even patches for the three open source engines? I’d need to organize some savvy, socially adept hackers to do the latter.
    I think that TC39 is moving fast enough with ECMAScript.next. Remember that the rest of the world is still catching up with ECMAScript 5 and getting over their opinion that JavaScript is a toy language. The stability created by not going too fast has its own merits and ECMAScript is currently progressing much faster than Java ever did.

References

  1. Google’s Alex Russell on JavaScript versus Dart
  2. JavaScript: how it all began
  3. Google Dart to “ultimately ... replace JavaScript”