Compare commits

..

19 Commits

Author SHA1 Message Date
Sebastian McKenzie
194c080c64 v2.13.5 2015-01-21 13:37:06 +11:00
Sebastian McKenzie
4c6076e529 add 2.13.5 changelog 2015-01-21 13:35:30 +11:00
Sebastian McKenzie
df65ec08a2 support destructuring patterns in rest parameters - fixes #550 2015-01-21 13:35:24 +11:00
Sebastian McKenzie
62f11011b0 upgrade kexec - closes #551 2015-01-21 13:19:24 +11:00
Sebastian McKenzie
9385c7e4ad v2.13.4 2015-01-21 10:27:35 +11:00
Sebastian McKenzie
3c06e68cae fix default parameter node variable name 2015-01-21 10:21:27 +11:00
Sebastian McKenzie
e8810f5124 add 2.13.4 changelog 2015-01-21 10:20:13 +11:00
Sebastian McKenzie
3c258c4716 add proper ordering to function param logic - fixes #549 2015-01-21 10:17:52 +11:00
Sebastian McKenzie
193a3c167e loops should contain their child block let declarations 2015-01-20 19:33:26 +11:00
Sebastian McKenzie
4b525daf72 fix forOf scope declarations not propagating to new for loop - fixes #538 2015-01-20 19:33:05 +11:00
Sebastian McKenzie
e46f42872a add array comprehension collision test #538 2015-01-20 16:52:11 +11:00
Sebastian McKenzie
4790e4068a add for collision test #538 2015-01-20 16:52:00 +11:00
Sebastian McKenzie
26cb5d5a65 add block to for loop scope - fixes #538 2015-01-20 16:48:41 +11:00
Sebastian McKenzie
031bda61cc don't continue let scoping remapping if there are none to be remapped 2015-01-20 16:48:07 +11:00
Sebastian McKenzie
61f1fae83b remove unused template 2015-01-20 16:47:52 +11:00
Sebastian McKenzie
d911bdaf63 add AssignmentPattern support to scope tracking - fixes #537 2015-01-20 08:56:14 +11:00
Sebastian McKenzie
f322252c36 add optional undeclared variable check transformer 2015-01-20 00:17:22 +11:00
Sebastian McKenzie
da16bf1e42 add t.isReferencedIdentifier 2015-01-20 00:17:11 +11:00
Sebastian McKenzie
4a1addc558 better whitespace for VariableDeclarations 2015-01-19 22:09:05 +11:00
25 changed files with 179 additions and 55 deletions

View File

@@ -11,6 +11,23 @@
_Note: Gaps between patch versions are faulty/broken releases._
## 2.13.5
* **Bug Fix**
* Allow rest parameters to be destructuring patterns.
* **Internal**
* Upgrade `kexec` to `1.1.0`.
## 2.13.4
* **Bug Fix**
* Fix ordering of destructuring and default params.
* Fix loop body scope.
* Fix `for...of` transformation not retaining it's scope.
* Add destructuring assignment support to scope tracking.
* **Polish**
* More reliable newlines for pretty printing variable declarations.
## 2.13.3
* **Internal**

View File

@@ -169,20 +169,19 @@ exports.DebuggerStatement = function () {
exports.VariableDeclaration = function (node, print, parent) {
this.push(node.kind + " ");
var inits = 0;
var noInits = 0;
var hasInits = false;
// don't add whitespace to loop heads
if (!t.isFor(parent)) {
for (var i = 0; i < node.declarations.length; i++) {
if (node.declarations[i].init) {
inits++;
} else {
noInits++;
// has an init so let's split it up over multiple lines
hasInits = true;
}
}
}
var sep = ",";
if (inits > noInits) { // more inits than no inits so let's add a newline
if (hasInits) {
sep += "\n" + util.repeat(node.kind.length + 1);
} else {
sep += " ";

View File

@@ -1,3 +0,0 @@
ARRAY.forEach(function (KEY) {
});

View File

@@ -71,8 +71,9 @@ _.each({
templateLiterals: require("./transformers/es6-template-literals"),
propertyMethodAssignment: require("./transformers/es6-property-method-assignment"),
computedPropertyNames: require("./transformers/es6-computed-property-names"),
destructuring: require("./transformers/es6-destructuring"),
defaultParameters: require("./transformers/es6-default-parameters"),
restParameters: require("./transformers/es6-rest-parameters"),
destructuring: require("./transformers/es6-destructuring"),
forOf: require("./transformers/es6-for-of"),
unicodeRegex: require("./transformers/es6-unicode-regex"),
abstractReferences: require("./transformers/es7-abstract-references"),
@@ -84,7 +85,6 @@ _.each({
_blockHoist: require("./transformers/_block-hoist"),
generators: require("./transformers/es6-generators"),
restParameters: require("./transformers/es6-rest-parameters"),
protoToAssign: require("./transformers/optional-proto-to-assign"),
@@ -98,6 +98,7 @@ _.each({
typeofSymbol: require("./transformers/optional-typeof-symbol"),
coreAliasing: require("./transformers/optional-core-aliasing"),
undefinedToVoid: require("./transformers/optional-undefined-to-void"),
undeclaredVariableCheck: require("./transformers/optional-undeclared-variable-check"),
// spec
specPropertyLiterals: require("./transformers/spec-property-literals"),

View File

@@ -15,9 +15,9 @@ exports.Function = function (node, parent, scope, context, file) {
var iife = false;
var def;
var checkTDZ = function (ids) {
var checkTDZ = function (param, def, ids) {
var check = function (node, parent) {
if (!t.isIdentifier(node) || !t.isReferenced(node, parent)) return;
if (!t.isReferencedIdentifier(node, parent)) return;
if (ids.indexOf(node.name) >= 0) {
throw file.errorWithNode(node, "Temporal dead zone - accessing a variable before it's initialized");
@@ -29,7 +29,10 @@ exports.Function = function (node, parent, scope, context, file) {
};
check(def, node);
traverse(def, { enter: check });
if (!t.isPattern(param)) {
traverse(def, { enter: check });
}
};
for (var i = 0; i < node.defaults.length; i++) {
@@ -42,7 +45,7 @@ exports.Function = function (node, parent, scope, context, file) {
// are to the right - ie. uninitialized parameters
var rightIds = ids.slice(i);
for (var i2 = 0; i2 < rightIds.length; i2++) {
checkTDZ(rightIds[i2]);
checkTDZ(param, def, rightIds[i2]);
}
// we're accessing a variable that's already defined within this function
@@ -66,12 +69,14 @@ exports.Function = function (node, parent, scope, context, file) {
continue;
}
body.push(util.template("default-parameter", {
var defNode = util.template("default-parameter", {
VARIABLE_NAME: node.params[i],
DEFAULT_VALUE: def,
ARGUMENT_KEY: t.literal(+i),
ARGUMENTS: argsIdentifier
}, true));
}, true);
defNode._blockHoist = node.defaults.length - i;
body.push(defNode);
}
// we need to cut off all trailing default parameters

View File

@@ -8,13 +8,27 @@ var buildVariableAssign = function (opts, id, init) {
var op = opts.operator;
if (t.isMemberExpression(id)) op = "=";
var node;
if (op) {
return t.expressionStatement(t.assignmentExpression(op, id, init));
node = t.expressionStatement(t.assignmentExpression(op, id, init));
} else {
return t.variableDeclaration(opts.kind, [
node = t.variableDeclaration(opts.kind, [
t.variableDeclarator(id, init)
]);
}
node._blockHoist = opts.blockHoist;
return node;
};
var buildVariableDeclar = function (opts, id, init) {
var declar = t.variableDeclaration("var", [
t.variableDeclarator(id, init)
]);
declar._blockHoist = opts.blockHoist;
return declar;
};
var push = function (opts, nodes, elem, parentId) {
@@ -100,9 +114,7 @@ var pushArrayPattern = function (opts, nodes, pattern, parentId) {
var toArray = opts.file.toArray(parentId, !hasSpreadElement && pattern.elements.length);
var _parentId = opts.scope.generateUidBasedOnNode(parentId, opts.file);
nodes.push(t.variableDeclaration("var", [
t.variableDeclarator(_parentId, toArray)
]));
nodes.push(buildVariableDeclar(opts, _parentId, toArray));
parentId = _parentId;
for (i = 0; i < pattern.elements.length; i++) {
@@ -138,11 +150,7 @@ var pushPattern = function (opts) {
if (!t.isArrayExpression(parentId) && !t.isMemberExpression(parentId) && !t.isIdentifier(parentId)) {
var key = scope.generateUidBasedOnNode(parentId, file);
nodes.push(t.variableDeclaration("var", [
t.variableDeclarator(key, parentId)
]));
nodes.push(buildVariableDeclar(opts, key, parentId));
parentId = key;
}
@@ -181,19 +189,20 @@ exports.Function = function (node, parent, scope, context, file) {
var hasDestructuring = false;
node.params = node.params.map(function (pattern) {
node.params = node.params.map(function (pattern, i) {
if (!t.isPattern(pattern)) return pattern;
hasDestructuring = true;
var parentId = file.generateUidIdentifier("ref", scope);
pushPattern({
kind: "var",
nodes: nodes,
pattern: pattern,
id: parentId,
file: file,
scope: scope
blockHoist: node.params.length - i,
pattern: pattern,
nodes: nodes,
scope: scope,
file: file,
kind: "var",
id: parentId
});
return parentId;
@@ -294,12 +303,12 @@ exports.VariableDeclaration = function (node, parent, scope, context, file) {
var patternId = declar.init;
var pattern = declar.id;
var opts = {
kind: node.kind,
nodes: nodes,
pattern: pattern,
id: patternId,
nodes: nodes,
scope: scope,
kind: node.kind,
file: file,
scope: scope
id: patternId,
};
if (t.isPattern(pattern) && patternId) {

View File

@@ -30,6 +30,9 @@ exports.ForOfStatement = function (node, parent, scope, context, file) {
// push the rest of the original loop body onto our new body
block.body = block.body.concat(node.body.body);
// todo: find out why this is necessary? #538
loop._scopeInfo = node._scopeInfo;
return loop;
};

View File

@@ -117,9 +117,10 @@ LetScoping.prototype.run = function () {
*/
LetScoping.prototype.remap = function () {
var letRefs = this.letReferences;
var scope = this.scope;
var file = this.file;
var hasRemaps = false;
var letRefs = this.letReferences;
var scope = this.scope;
var file = this.file;
// alright, so since we aren't wrapping this block in a closure
// we have to check if any of our let variables collide with
@@ -136,6 +137,7 @@ LetScoping.prototype.remap = function () {
var uid = file.generateUidIdentifier(ref.name, scope).name;
ref.name = uid;
hasRemaps = true;
remaps[key] = remaps[uid] = {
node: ref,
uid: uid
@@ -143,11 +145,12 @@ LetScoping.prototype.remap = function () {
}
}
if (!hasRemaps) return;
//
var replace = function (node, parent, scope, context, remaps) {
if (!t.isIdentifier(node)) return;
if (!t.isReferenced(node, parent)) return;
if (!t.isReferencedIdentifier(node, parent)) return;
var remap = remaps[node.name];
if (!remap) return;
@@ -266,11 +269,8 @@ LetScoping.prototype.getLetReferences = function () {
if (t.isFunction(node)) {
traverse(node, {
enter: function (node, parent) {
// not an identifier so we have no use
if (!t.isIdentifier(node)) return;
// not a direct reference
if (!t.isReferenced(node, parent)) return;
if (!t.isReferencedIdentifier(node, parent)) return;
// this scope has a variable with the same name so it couldn't belong
// to our let scope

View File

@@ -41,6 +41,22 @@ exports.Function = function (node, parent, scope, context, file) {
);
}
// support patterns
if (t.isPattern(rest)) {
var pattern = rest;
rest = file.generateUidIdentifier("ref", scope);
// let the destructuring transformer handle this
var restDeclar = t.variableDeclaration("var", [
t.variableDeclarator(pattern, rest)
]);
// retain evaluation position
restDeclar._blockHoist = node.params.length + 1;
node.body.body.unshift(restDeclar);
}
node.body.body.unshift(
util.template("rest", {
ARGUMENTS: argsId,

View File

@@ -16,8 +16,7 @@ exports.BlockStatement = function (node, parent, scope, context, file) {
traverse(node, {
enter: function (node, parent, scope, context, state) {
if (!t.isIdentifier(node)) return;
if (!t.isReferenced(node, parent)) return;
if (!t.isReferencedIdentifier(node, parent)) return;
var declared = state.letRefs[node.name];
if (!declared) return;

View File

@@ -42,7 +42,7 @@ exports.ast = {
context.skip();
return t.prependToMemberExpression(node, file._coreId);
}
} else if (t.isIdentifier(node) && !t.isMemberExpression(parent) && t.isReferenced(node, parent) && _.contains(ALIASABLE_CONSTRUCTORS, node.name)) {
} else if (t.isReferencedIdentifier(node, parent) && !t.isMemberExpression(parent) && _.contains(ALIASABLE_CONSTRUCTORS, node.name)) {
// Symbol() -> _core.Symbol(); new Promise -> new _core.Promise
return t.memberExpression(file._coreId, node);
} else if (t.isCallExpression(node)) {

View File

@@ -0,0 +1,7 @@
exports.optional = true;
exports.Identifier = function (node, parent, scope, context, file) {
if (!scope.has(node.name, true)) {
throw file.errorWithNode(node, "Reference to undeclared variable");
}
};

View File

@@ -120,6 +120,7 @@ Scope.prototype.generateTempBasedOnNode = function (node, file) {
};
Scope.prototype.getInfo = function () {
var parent = this.parent;
var block = this.block;
if (block._scopeInfo) return block._scopeInfo;
@@ -132,6 +133,10 @@ Scope.prototype.getInfo = function () {
if (!reference) Scope.add(node, declarations);
};
if (parent && t.isBlockStatement(block) && t.isFor(parent.block)) {
return info;
}
// ForStatement - left, init
if (t.isFor(block)) {
@@ -139,6 +144,10 @@ Scope.prototype.getInfo = function () {
var node = block[key];
if (t.isBlockScoped(node)) add(node);
});
if (t.isBlockStatement(block.body)) {
block = block.body;
}
}
// Program, BlockStatement - let variables

View File

@@ -263,6 +263,18 @@ t.isReferenced = function (node, parent) {
return false;
};
/**
* Description
*
* @param {Object} node
* @param {Object} parent
* @returns {Boolean}
*/
t.isReferencedIdentifier = function (node, parent) {
return t.isIdentifier(node) && t.isReferenced(node, parent);
};
/**
* Description
*
@@ -475,7 +487,8 @@ t.getIds.nodes = {
MemeberExpression: ["object"],
SpreadElement: ["argument"],
Property: ["value"],
ComprehensionBlock: ["left"]
ComprehensionBlock: ["left"],
AssignmentPattern: ["left"]
};
t.getIds.arrays = {

View File

@@ -1,7 +1,7 @@
{
"name": "6to5",
"description": "Turn ES6 code into readable vanilla ES5 with source maps",
"version": "2.13.3",
"version": "2.13.5",
"author": "Sebastian McKenzie <sebmck@gmail.com>",
"homepage": "https://6to5.org/",
"repository": "6to5/6to5",
@@ -63,6 +63,6 @@
"uglify-js": "2.4.16"
},
"optionalDependencies": {
"kexec": "0.2.0"
"kexec": "1.1.0"
}
}

View File

@@ -5,8 +5,10 @@ let foo = "foo";
var foo = "bar";
const foo = "foo";
let foo, bar = "bar";
var foo, bar = "bar";
let foo,
bar = "bar";
var foo,
bar = "bar";
let foo = "foo",
bar = "bar";

View File

@@ -0,0 +1,19 @@
function required(msg) {
throw new Error(msg);
}
function sum(
{ arr = required('arr is required') } = { arr: arr = [] },
length = arr.length
) {
let i = 0;
let acc = 0;
for (let item of arr) {
if (i >= length) return acc;
acc += item;
i++;
}
return acc;
}
assert.equal(sum({arr:[1,2]}), 3);

View File

@@ -0,0 +1,2 @@
var foo = [];
assert.deepEqual([for (foo of [1, 2, 3]) foo], [1, 2, 3]);

View File

@@ -0,0 +1,3 @@
{
"experimental": true
}

View File

@@ -0,0 +1,6 @@
let x = 0;
for (;;) {
let x = 1;
assert.equal(x, 1);
break;
}

View File

@@ -0,0 +1,5 @@
var fields = [{ name: "title" }, { name: "content" }];
for (let { name, value = "Default value" } of fields) {
assert.equal(value, "Default value");
}

View File

@@ -0,0 +1,5 @@
function foo() {
}
foo();

View File

@@ -0,0 +1,3 @@
{
"optional": ["undeclaredVariableCheck"]
}

View File

@@ -0,0 +1 @@
foo();

View File

@@ -0,0 +1,3 @@
{
"throws": "Reference to undeclared variable"
}