I am using the Angular version of the $q library however this would also be relevant for the original q library.
Usage example:
$q
.when(someFunction)
.then(function(){
// ..
})
.catch(function(){
// ..
})
.finally(function(){
// ..
});
Unfortunately some function names (e.g. finally
) conflict with javascript keywords.
From the Angular reference:
"Because finally is a reserved word in JavaScript and reserved keywords are not supported as property names by ES3, you'll need to invoke the method like promise['finally'](callback)
to make your code IE8 and Android 2.x compatible."
ECMA-262, the official standard, available at http://www.ecma-international.org/publications/standards/Ecma-262.htm, states:
7.6.1.1 Keywords
The following tokens are ECMAScript keywords and may not be used as Identifiers in ECMAScript programs.
break do instanceof typeof case else new var catch finally return void continue for switch while debugger function this with default if throw delete in try
This means that the first example has to be changed into the following code to get it working with IE8:
$q
.when(someFunction)
.then(function(){
// ..
})
['catch'](function(){
// ..
})
['finally'](function(){
// ..
});
As this code is harder to maintain I am looking for a javascript preprocessor (maybe a grunt task) which turns the first example into the IE8 compatible version.
Is there such a preprocessor?
Your friendly neighborhood Stef Panner created such a tool just for that a few months ago. It's called es3-safe-recast. There is also a grunt task for it.
Let's go through what it does. First it requires the Esprima package for JS syntax tree analysis and recast on top of it that is built for these conversions:
'use strict';
var esprima = require('esprima');
var recast = require('recast');
var Visitor = recast.Visitor;
var types = recast.types;
var namedTypes = types.namedTypes;
var builders = types.builders;
Then it contains a big map of all the identifiers - just like your list:
identifierToLiteral.finally = true; // here is `finally` for example
Here is how it parses the tree and replaces it with a visitor:
var ES6Safe = Visitor.extend({
visitProperty: function(node) { // go through all properties
// check if need to replace name with literal
if (namedTypes.Identifier.check(node.key) && identifierToLiteral[node.key.name]) {
node.key = builders.literal(node.key.name);
}
return this.genericVisit(node);
},
visitMemberExpression: function(node) { // and all member expressions
var property = node.property;
var newNode;
// check if need to replace name with literal
if (namedTypes.Identifier.check(property) && identifierToLiteral[property.name]) {
newNode = builders.memberExpression(node.object, builders.literal(property.name), true);
} else {
newNode = node;
}
return this.genericVisit(newNode);
}
});
Finally, it runs the code through recast:
ast = recast.parse(source, { esprima: esprima } );
new ES6Safe().visit(ast);
code = recast.print(ast).code;
Producing the safe version of the above code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With