Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
763b4caf32 | ||
|
|
c0248cf04c | ||
|
|
a7a6ee80f2 | ||
|
|
aa298b1e0a | ||
|
|
9c0a8e22d2 | ||
|
|
7c1a924ef6 | ||
|
|
1d975a2635 | ||
|
|
67cfdbd447 | ||
|
|
ab02231d39 |
10
CHANGELOG.md
10
CHANGELOG.md
@@ -1,3 +1,13 @@
|
||||
# 1.14.15
|
||||
|
||||
* Add object getter memos and this shorthand to playground.
|
||||
* Fix while loops in let scoping.
|
||||
* Upgrade `acorn-6to5`.
|
||||
|
||||
# 1.14.14
|
||||
|
||||
* Fix template literals escaping.
|
||||
|
||||
# 1.14.13
|
||||
|
||||
* Fix let scoping of `while` loops.
|
||||
|
||||
@@ -17,7 +17,7 @@ var seattlers = [for (c of customers) if (c.city == "Seattle") { name: c.name, a
|
||||
is generated to the following with 6to5:
|
||||
|
||||
```javascript
|
||||
var seattlers = customers.filter(function (c) {
|
||||
var seattlers = Array.from(customers).filter(function (c) {
|
||||
return c.city == "Seattle";
|
||||
}).map(function (c) {
|
||||
return {
|
||||
@@ -51,8 +51,7 @@ As you can tell, it's not very pretty, unreadable even. Instead of mapping
|
||||
directly to a runtime, like other transpilers, 6to5 maps directly to the
|
||||
equivalent ES5.
|
||||
|
||||
I'm not saying 6to5 is for everyone or even suited for everything. Traceur is
|
||||
better suited if you'd like a full ES6 environment with polyfills and all.
|
||||
Sometimes there are little things that 6to5 needs
|
||||
|
||||
## Comparison to other transpilers
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@ to5.transform("code", { playground: true });
|
||||
|
||||
* [Memoization operator](#memoization-operator)
|
||||
* [Method binding](#method-binding)
|
||||
* [Object getter memoisation](#object-getter-memoisation)
|
||||
* [This shorthand](#this-shorthand)
|
||||
|
||||
### Memoization assignment operator
|
||||
|
||||
@@ -66,3 +68,53 @@ var fn = obj.method.bind(obj, "foob");
|
||||
["foo", "bar"].map(function (val) { return val.toUpperCase(); });
|
||||
[1.1234, 23.53245, 3].map(function (val) { return val.toFixed(2); });
|
||||
```
|
||||
|
||||
### Object getter memoisation
|
||||
|
||||
```javascript
|
||||
var foo = {
|
||||
memo bar() {
|
||||
return complex();
|
||||
}
|
||||
};
|
||||
|
||||
class Foo {
|
||||
memo bar() {
|
||||
return complex();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
equivalent to
|
||||
|
||||
```javascript
|
||||
var foo = {
|
||||
get bar() {
|
||||
if (this._barRan) return this._bar;
|
||||
this._barRan = true;
|
||||
return this._bar = complex();
|
||||
}
|
||||
};
|
||||
|
||||
class Foo {
|
||||
get bar() {
|
||||
if (this._barRan) return this._bar;
|
||||
this._barRan = true;
|
||||
return this._bar = complex();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**NOTE:** Memoised functions will return the result of the **first** execution, regardless of arguments.
|
||||
|
||||
### This shorthand
|
||||
|
||||
```javascript
|
||||
@foo
|
||||
```
|
||||
|
||||
equivalent to
|
||||
|
||||
```javascirpt
|
||||
this.foo
|
||||
```
|
||||
|
||||
@@ -29,6 +29,11 @@ transform.moduleFormatters = {
|
||||
};
|
||||
|
||||
_.each({
|
||||
// plyground
|
||||
methodBinding: require("./transformers/playground-method-binding"),
|
||||
memoizationOperator: require("./transformers/playground-memoization-operator"),
|
||||
objectGetterMemoization: require("./transformers/playground-object-getter-memoization"),
|
||||
|
||||
modules: require("./transformers/es6-modules"),
|
||||
propertyNameShorthand: require("./transformers/es6-property-name-shorthand"),
|
||||
arrayComprehension: require("./transformers/es7-array-comprehension"),
|
||||
@@ -56,10 +61,6 @@ _.each({
|
||||
|
||||
generators: require("./transformers/es6-generators"),
|
||||
|
||||
// plyground
|
||||
methodBinding: require("./transformers/playground-method-binding"),
|
||||
memoizationOperator: require("./transformers/playground-memoization-operator"),
|
||||
|
||||
_blockHoist: require("./transformers/_block-hoist"),
|
||||
_declarations: require("./transformers/_declarations"),
|
||||
_aliasFunctions: require("./transformers/_alias-functions"),
|
||||
|
||||
@@ -11,7 +11,7 @@ exports.Function = function (node, parent, file, scope) {
|
||||
return t.getIds(param);
|
||||
});
|
||||
|
||||
var closure = false;
|
||||
var iife = false;
|
||||
|
||||
_.each(node.defaults, function (def, i) {
|
||||
if (!def) return;
|
||||
@@ -29,7 +29,7 @@ exports.Function = function (node, parent, file, scope) {
|
||||
}
|
||||
|
||||
if (scope.has(node.name)) {
|
||||
closure = true;
|
||||
iife = true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -40,7 +40,7 @@ exports.Function = function (node, parent, file, scope) {
|
||||
// we're accessing a variable that's already defined within this function
|
||||
var has = scope.get(param.name);
|
||||
if (has && !_.contains(node.params, has)) {
|
||||
closure = true;
|
||||
iife = true;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -55,7 +55,7 @@ exports.Function = function (node, parent, file, scope) {
|
||||
}, true));
|
||||
});
|
||||
|
||||
if (closure) {
|
||||
if (iife) {
|
||||
var container = t.functionExpression(null, [], node.body, node.generator);
|
||||
container._aliasFunction = true;
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ exports.VariableDeclaration = function (node) {
|
||||
isLet(node);
|
||||
};
|
||||
|
||||
exports.For = function (node, parent, file, scope) {
|
||||
exports.Loop = function (node, parent, file, scope) {
|
||||
var init = node.left || node.init;
|
||||
if (isLet(init)) {
|
||||
t.ensureBlock(node);
|
||||
@@ -49,7 +49,7 @@ exports.For = function (node, parent, file, scope) {
|
||||
};
|
||||
|
||||
exports.BlockStatement = function (block, parent, file, scope) {
|
||||
if (!t.isFor(parent)) {
|
||||
if (!t.isLoop(parent)) {
|
||||
var letScoping = new LetScoping(false, block, parent, file, scope);
|
||||
letScoping.run();
|
||||
}
|
||||
@@ -58,19 +58,19 @@ exports.BlockStatement = function (block, parent, file, scope) {
|
||||
/**
|
||||
* Description
|
||||
*
|
||||
* @param {Boolean|Node} forParent
|
||||
* @param {Boolean|Node} loopParent
|
||||
* @param {Node} block
|
||||
* @param {Node} parent
|
||||
* @param {File} file
|
||||
* @param {Scope} scope
|
||||
*/
|
||||
|
||||
function LetScoping(forParent, block, parent, file, scope) {
|
||||
this.forParent = forParent;
|
||||
this.parent = parent;
|
||||
this.scope = scope;
|
||||
this.block = block;
|
||||
this.file = file;
|
||||
function LetScoping(loopParent, block, parent, file, scope) {
|
||||
this.loopParent = loopParent;
|
||||
this.parent = parent;
|
||||
this.scope = scope;
|
||||
this.block = block;
|
||||
this.file = file;
|
||||
|
||||
this.letReferences = {};
|
||||
this.body = [];
|
||||
@@ -172,11 +172,11 @@ LetScoping.prototype.remap = function () {
|
||||
traverse(node, replace);
|
||||
};
|
||||
|
||||
var forParent = this.forParent;
|
||||
if (forParent) {
|
||||
traverseReplace(forParent.right, forParent);
|
||||
traverseReplace(forParent.test, forParent);
|
||||
traverseReplace(forParent.update, forParent);
|
||||
var loopParent = this.loopParent;
|
||||
if (loopParent) {
|
||||
traverseReplace(loopParent.right, loopParent);
|
||||
traverseReplace(loopParent.test, loopParent);
|
||||
traverseReplace(loopParent.update, loopParent);
|
||||
}
|
||||
|
||||
traverse(block, replace);
|
||||
@@ -365,7 +365,7 @@ LetScoping.prototype.getLetReferences = function () {
|
||||
});
|
||||
|
||||
return false;
|
||||
} else if (t.isFor(node)) {
|
||||
} else if (t.isLoop(node)) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
@@ -428,7 +428,7 @@ LetScoping.prototype.buildHas = function (ret, call) {
|
||||
t.variableDeclarator(ret, call)
|
||||
]));
|
||||
|
||||
var forParent = this.forParent;
|
||||
var loopParent = this.loopParent;
|
||||
var retCheck;
|
||||
var has = this.has;
|
||||
var cases = [];
|
||||
@@ -443,7 +443,7 @@ LetScoping.prototype.buildHas = function (ret, call) {
|
||||
if (has.hasBreak || has.hasContinue) {
|
||||
// ensure that the parent has a label as we're building a switch and we
|
||||
// need to be able to access it
|
||||
var label = forParent.label = forParent.label || this.file.generateUidIdentifier("loop", this.scope);
|
||||
var label = loopParent.label = loopParent.label || this.file.generateUidIdentifier("loop", this.scope);
|
||||
|
||||
if (has.hasBreak) {
|
||||
cases.push(t.switchCase(t.literal("break"), [t.breakStatement(label)]));
|
||||
|
||||
@@ -31,7 +31,7 @@ exports.TemplateLiteral = function (node) {
|
||||
var nodes = [];
|
||||
|
||||
_.each(node.quasis, function (elem) {
|
||||
nodes.push(t.literal(elem.value.raw));
|
||||
nodes.push(t.literal(elem.value.cooked));
|
||||
|
||||
var expr = node.expressions.shift();
|
||||
if (expr) {
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
var traverse = require("../../traverse");
|
||||
var t = require("../../types");
|
||||
|
||||
exports.Property =
|
||||
exports.MethodDefinition = function (node, parent, file, scope) {
|
||||
if (node.kind !== "memo") return;
|
||||
node.kind = "get";
|
||||
|
||||
var value = node.value;
|
||||
t.ensureBlock(value);
|
||||
|
||||
var body = value.body.body;
|
||||
var key = node.key;
|
||||
|
||||
if (t.isIdentifier(key) && !node.computed) {
|
||||
key = "_" + key.name;
|
||||
} else {
|
||||
key = file.generateUid("memo", scope);
|
||||
}
|
||||
|
||||
var memoId = t.memberExpression(t.thisExpression(), t.identifier(key));
|
||||
var doneId = t.memberExpression(t.thisExpression(), t.identifier(key + "Done"));
|
||||
|
||||
traverse(value, function (node) {
|
||||
if (t.isFunction(node)) return;
|
||||
|
||||
if (t.isReturnStatement(node) && node.argument) {
|
||||
node.argument = t.assignmentExpression("=", memoId, node.argument);
|
||||
}
|
||||
});
|
||||
|
||||
// this._barDone = true;
|
||||
body.unshift(t.expressionStatement(t.assignmentExpression("=", doneId, t.literal(true))));
|
||||
|
||||
// if (this._barDone) return this._bar;
|
||||
body.unshift(t.ifStatement(doneId, t.returnStatement(memoId)));
|
||||
};
|
||||
@@ -3,14 +3,14 @@
|
||||
"BreakStatement": ["Statement"],
|
||||
"ContinueStatement": ["Statement"],
|
||||
"DebuggerStatement": ["Statement"],
|
||||
"DoWhileStatement": ["Statement", "Loop", "With"],
|
||||
"DoWhileStatement": ["Statement", "Loop", "While"],
|
||||
"IfStatement": ["Statement"],
|
||||
"ReturnStatement": ["Statement"],
|
||||
"SwitchStatement": ["Statement"],
|
||||
"ThrowStatement": ["Statement"],
|
||||
"TryStatement": ["Statement"],
|
||||
"WhileStatement": ["Statement"],
|
||||
"WithStatement": ["Statement", "Loop", "With"],
|
||||
"WhileStatement": ["Statement", "Loop", "While"],
|
||||
"WithStatement": ["Statement"],
|
||||
"EmptyStatement": ["Statement"],
|
||||
"LabeledStatement": ["Statement"],
|
||||
"VariableDeclaration": ["Statement", "Declaration"],
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "6to5",
|
||||
"description": "Turn ES6 code into readable vanilla ES5 with source maps",
|
||||
"version": "1.14.13",
|
||||
"version": "1.14.15",
|
||||
"author": "Sebastian McKenzie <sebmck@gmail.com>",
|
||||
"homepage": "https://github.com/6to5/6to5",
|
||||
"repository": {
|
||||
|
||||
19
test/fixtures/transformation/playground/object-getter-memoization/actual.js
vendored
Normal file
19
test/fixtures/transformation/playground/object-getter-memoization/actual.js
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
class Foo {
|
||||
memo bar() {
|
||||
return complex();
|
||||
}
|
||||
|
||||
memo [bar]() {
|
||||
return complex();
|
||||
}
|
||||
}
|
||||
|
||||
var foo = {
|
||||
memo bar() {
|
||||
return complex();
|
||||
},
|
||||
|
||||
memo [bar]() {
|
||||
return complex();
|
||||
}
|
||||
};
|
||||
53
test/fixtures/transformation/playground/object-getter-memoization/expected.js
vendored
Normal file
53
test/fixtures/transformation/playground/object-getter-memoization/expected.js
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
"use strict";
|
||||
|
||||
var _classProps = function (child, staticProps, instanceProps) {
|
||||
if (staticProps) Object.defineProperties(child, staticProps);
|
||||
if (instanceProps) Object.defineProperties(child.prototype, instanceProps);
|
||||
};
|
||||
|
||||
var Foo = (function () {
|
||||
var Foo = function Foo() {};
|
||||
|
||||
_classProps(Foo, null, (function (_ref) {
|
||||
_ref[bar] = {
|
||||
get: function () {
|
||||
if (this._memoDone) return this._memo;
|
||||
this._memoDone = true;
|
||||
return this._memo = complex();
|
||||
}
|
||||
};
|
||||
return _ref;
|
||||
})({
|
||||
bar: {
|
||||
get: function () {
|
||||
if (this._barDone) return this._bar;
|
||||
this._barDone = true;
|
||||
return this._bar = complex();
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
return Foo;
|
||||
})();
|
||||
|
||||
var foo = (function (_foo) {
|
||||
_foo[bar] = function () {
|
||||
if (this._memo2Done) return this._memo2;
|
||||
this._memo2Done = true;
|
||||
return this._memo2 = complex();
|
||||
};
|
||||
|
||||
return _foo;
|
||||
})((function (_ref2) {
|
||||
Object.defineProperties(_ref2, {
|
||||
bar: {
|
||||
get: function () {
|
||||
if (this._barDone) return this._bar;
|
||||
this._barDone = true;
|
||||
return this._bar = complex();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return _ref2;
|
||||
})({}));
|
||||
Reference in New Issue
Block a user