{ github, twitter, instagram, facebook }.com/benjamn
But which version of Node?
Fiber
s?
Everyone can agree precisely what will happen when a computer runs a program written in that language.
Though “JavaScript” may be a little vague, a vast audience of programmers still know it by that name, so that's why we keep calling it that.
A big departure from sequential numbering (ECMAScript 4, 5, 6), since it signals an intention to release a new standard every year.
RegExp.escape
revived on
es-discuss
last month, presented in this week's TC39 meeting.
The ecmascript
package will provide any and all
language features that can be faithfully compiled to code that
runs natively in all JavaScript engines.
Code you write in the first stage should not have to be rewritten when the second stage arrives.
meteor
command-line tool has
been using ECMAScript 2015 features for some time now.
And it's great.
function JsFile() {
InputFile.apply(this, arguments);
}
JsFile.prototype = Object.create(InputFile.prototype);
JsFile.prototype.constructor = JsFile;
JsFile.prototype.addJavaScript = function (options) {
this._minifiedFiles.push({
data: options.data,
sourceMap: options.sourceMap,
path: options.path
});
};
exports.JsFile = JsFile;
function JsFile() {
InputFile.apply(this, arguments);
}
Meteor._inherits(JsFile, InputFile);
JsFile.prototype.addJavaScript = function (options) {
this._minifiedFiles.push({
data: options.data,
sourceMap: options.sourceMap,
path: options.path
});
};
exports.JsFile = JsFile;
class JsFile extends InputFile {
constructor() {
InputFile.apply(this, arguments);
}
}
JsFile.prototype.addJavaScript = function (options) {
this._minifiedFiles.push({
data: options.data,
sourceMap: options.sourceMap,
path: options.path
});
};
exports.JsFile = JsFile;
class JsFile extends InputFile {
constructor() {
super(...arguments);
}
}
JsFile.prototype.addJavaScript = function (options) {
this._minifiedFiles.push({
data: options.data,
sourceMap: options.sourceMap,
path: options.path
});
};
exports.JsFile = JsFile;
class JsFile extends InputFile {
constructor() {
super(...arguments);
}
addJavaScript(options) {
this._minifiedFiles.push({
data: options.data,
sourceMap: options.sourceMap,
path: options.path
});
}
}
exports.JsFile = JsFile;
class JsFile extends InputFile {
addJavaScript(options) {
this._minifiedFiles.push({
data: options.data,
sourceMap: options.sourceMap,
path: options.path
});
}
}
exports.JsFile = JsFile;
class JsFile extends InputFile {
addJavaScript(options) {
this._minifiedFiles.push({
data: options.data,
sourceMap: options.sourceMap,
path: options.path
});
}
}
exports.JsFile = JsFile;
class JsFile extends InputFile {
addJavaScript({ data, sourceMap, path }) {
this._minifiedFiles.push({
data: data,
sourceMap: sourceMap,
path: path
});
}
}
exports.JsFile = JsFile;
class JsFile extends InputFile {
addJavaScript({ data, sourceMap, path }) {
this._minifiedFiles.push({
data,
sourceMap,
path,
});
}
}
exports.JsFile = JsFile;
class JsFile extends InputFile {
addJavaScript({ data, sourceMap, path }) {
this._minifiedFiles.push({ data, sourceMap, path });
}
}
exports.JsFile = JsFile;
export class JsFile extends InputFile {
addJavaScript({ data, sourceMap, path }) {
this._minifiedFiles.push({ data, sourceMap, path });
}
}
export class JsFile extends InputFile {
addJavaScript({ data, sourceMap = null, path }) {
this._minifiedFiles.push({ data, sourceMap, path });
}
}
And we want you to have the same development experience.
meteor add ecmascript
Just a package that can be added to any
app
or api.use
d by any
package, and it will be
installed by default for all new apps and packages.
The latest one: ECMAScript 2015+
Whatever we can faithfully transpile.
Whatever will one day be implemented natively.
Whatever helps you write Meteor apps.
for
-of
loops
let sum = 0;
for (let x of arrayOfNumbers) {
sum += x;
}
gets transpiled to
var sum = 0;
var _iter = arrayOfNumbers[Symbol.iterator](), _result;
while (! (_result = _iter.next()).done) {
var x = _result.value;
sum += x;
}
Symbol.iterator
is a special kind of unique
property name that cannot be simulated faithfully.
for
-of
loops
var sum = 0;
var _iter = arrayOfNumbers[Symbol.iterator](), _result;
while (! (_result = _iter.next()).done) {
var x = _result.value;
sum += x;
}
assumes a minimal Symbol
implementation:
if (typeof Symbol === "undefined") {
Symbol = function Symbol() {};
}
for
-of
loops
var sum = 0;
var _iter = arrayOfNumbers[Symbol.iterator](), _result;
while (! (_result = _iter.next()).done) {
var x = _result.value;
sum += x;
}
assumes a minimal Symbol
implementation:
if (typeof Symbol === "undefined") {
Symbol = function Symbol() {};
}
if (! Symbol.iterator) {
Symbol.iterator = "@@iterator";
}
for
-of
loops
var sum = 0;
var _iter = arrayOfNumbers[Symbol.iterator](), _result;
while (! (_result = _iter.next()).done) {
var x = _result.value;
sum += x;
}
assumes a minimal Symbol
implementation:
if (typeof Symbol === "undefined") {
Symbol = function Symbol() {}; // Fake!
}
if (! Symbol.iterator) {
Symbol.iterator = "@@iterator"; // Fake!
}
for
-of
loop works
today in translation, and it will continue
to work natively once it no longer needs to be
translated,
for
-of
loops meet our criteria for
inclusion in the ecmascript
package,
while Symbol
s do not.
Array.prototype
Array
methods
like .forEach
, .map
,
and .reduce
are now available in almost
every JavaScript engine, except
Internet Explorer 8 and earlier.
We use a popular polyfill library called
es5-shim
to implement these methods, but
there is no way to make them non-enumerable
in IE8.
Array.prototype
If you ever use a for
-in
loop to
iterate over an array in IE8, you'll get all those method
names, too!
let sparseArray = [];
sparseArray[0] = "a";
sparseArray[2] = "c";
for (let index in sparseArray) {
console.log(index); // Should log 0 and 2.
}
Normally you would be out of luck, but Meteor can actually fix this for you.
Array.prototype
If you ever use a for
-in
loop to
iterate over an array in IE8, you'll get all those method
names, too!
let sparseArray = [];
sparseArray[0] = "a";
sparseArray[2] = "c";
for (let index in runtime.sanitizeForInObject(sparseArray)) {
console.log(index); // Should log 0 and 2.
}
Normally you would be out of luck, but Meteor can actually fix this for you.
Array.prototype
If you ever use a for
-in
loop to
iterate over an array in IE8, you'll get all those method
names, too!
let sparseArray = [];
sparseArray[0] = "a";
sparseArray[2] = "c";
for (let index in runtime.sanitizeForInObject(sparseArray)) {
console.log(index); // Should log 0 and 2.
}
In most browsers, the sanitizeForInObject
helper
function simply returns its argument.
Array.prototype
If you ever use a for
-in
loop to
iterate over an array in IE8, you'll get all those method
names, too!
let sparseArray = [];
sparseArray[0] = "a";
sparseArray[2] = "c";
for (let index in runtime.sanitizeForInObject(sparseArray)) {
console.log(index); // Should log 0 and 2.
}
In IE8, when the argument is an array, it returns a new object containing only the enumerable keys.
Promise
.Fiber
// Replace Promise.prototype.then with a wrapper that ensures the
// onResolved and onRejected callbacks always run in a Fiber.
var es6PromiseThen = Promise.prototype.then;
Promise.Fiber
// Replace Promise.prototype.then with a wrapper that ensures the
// onResolved and onRejected callbacks always run in a Fiber.
var es6PromiseThen = Promise.prototype.then;
Promise.prototype.then = function then(onResolved, onRejected) {
};
Promise.Fiber
// Replace Promise.prototype.then with a wrapper that ensures the
// onResolved and onRejected callbacks always run in a Fiber.
var es6PromiseThen = Promise.prototype.then;
Promise.prototype.then = function then(onResolved, onRejected) {
var Promise = this.constructor;
};
Promise.Fiber
// Replace Promise.prototype.then with a wrapper that ensures the
// onResolved and onRejected callbacks always run in a Fiber.
var es6PromiseThen = Promise.prototype.then;
Promise.prototype.then = function then(onResolved, onRejected) {
var Promise = this.constructor;
if (typeof Promise.Fiber === "function") {
}
};
Promise.Fiber
// Replace Promise.prototype.then with a wrapper that ensures the
// onResolved and onRejected callbacks always run in a Fiber.
var es6PromiseThen = Promise.prototype.then;
Promise.prototype.then = function then(onResolved, onRejected) {
var Promise = this.constructor;
if (typeof Promise.Fiber === "function") {
return es6PromiseThen.call(
this,
wrapCallback(onResolved, Promise),
wrapCallback(onRejected, Promise)
);
}
};
Promise.Fiber
// Replace Promise.prototype.then with a wrapper that ensures the
// onResolved and onRejected callbacks always run in a Fiber.
var es6PromiseThen = Promise.prototype.then;
Promise.prototype.then = function then(onResolved, onRejected) {
var Promise = this.constructor;
if (typeof Promise.Fiber === "function") {
return es6PromiseThen.call(
this,
wrapCallback(onResolved, Promise),
wrapCallback(onRejected, Promise)
);
}
return es6PromiseThen.call(this, onResolved, onRejected);
};
Good Promise
tutorials:
HTML5Rocks,
2ality
Promise.Fiber
function wrapCallback(callback, Promise) {
var fiber = Promise.Fiber.current;
var dynamics = fiber && fiber._meteorDynamics;
return callback && function (arg) {
return fiberPool.run({
callback: callback,
args: [arg], // Avoid dealing with arguments objects.
dynamics: dynamics
}, Promise);
};
}
Fiber
s are recycled using a
pool,
so a new Fiber
does not have to be created
every time a Promise
callback fires.
Promise.Fiber
function wrapCallback(callback, Promise) {
var fiber = Promise.Fiber.current;
var dynamics = fiber && fiber._meteorDynamics;
return callback && function (arg) {
return fiberPool.run({
callback: callback,
args: [arg], // Avoid dealing with arguments objects.
dynamics: dynamics
}, Promise);
};
}
Even better,
Fiber._meteorDynamics
is
saved and restored when the callback
runs, so you never have to
call Meteor.bindEnvironment
with
Promise
s!
You shouldn't have to wait for universal native support before using the latest ECMAScript features.
Nor should you to have to wonder when it's safe to transition from simulated to native support.
Nor should it be your job to find the best way to integrate
libraries like es5-shim
with tools like Babel.
Because Meteor provides a complete platform out of the box, including compilation, packaging, and delivery of scripts, libraries, source maps, and other assets, we are in an ideal position to make the transition to ECMAScript 2015+ as seamless as possible.
Facebook has these posters up everywhere that say things like “FOCUS ON IMPACT,” so that's what I did.
I believe Meteor has the best chance of providing the best experience for developing apps with the latest version of JavaScript.
And there are a whole lot more of you than there are engineers at Facebook.