track arrays to avoid turning something into an array multiple times - closes #757
This commit is contained in:
parent
e9cfd2df3e
commit
e7f6572a3b
@ -226,24 +226,6 @@ File.prototype.debug = function (msg) {
|
|||||||
util.debug(parts);
|
util.debug(parts);
|
||||||
};
|
};
|
||||||
|
|
||||||
File.prototype.toArray = function (node, i, forceHelperName) {
|
|
||||||
if (t.isArrayExpression(node)) {
|
|
||||||
return node;
|
|
||||||
} else if (t.isIdentifier(node) && node.name === "arguments") {
|
|
||||||
return t.callExpression(t.memberExpression(this.addHelper("slice"), t.identifier("call")), [node]);
|
|
||||||
} else {
|
|
||||||
var helperName = "to-array";
|
|
||||||
var args = [node];
|
|
||||||
if (i === true) {
|
|
||||||
helperName = "to-consumable-array";
|
|
||||||
} else if (i) {
|
|
||||||
args.push(t.literal(i));
|
|
||||||
helperName = "sliced-to-array";
|
|
||||||
}
|
|
||||||
return t.callExpression(this.addHelper(helperName), args);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
File.prototype.getModuleFormatter = function (type) {
|
File.prototype.getModuleFormatter = function (type) {
|
||||||
var ModuleFormatter = isFunction(type) ? type : transform.moduleFormatters[type];
|
var ModuleFormatter = isFunction(type) ? type : transform.moduleFormatters[type];
|
||||||
|
|
||||||
|
|||||||
@ -144,12 +144,14 @@ DestructuringTransformer.prototype.pushArrayPattern = function (pattern, parentI
|
|||||||
// if we have a rest then we need all the elements
|
// if we have a rest then we need all the elements
|
||||||
var count = !hasRest(pattern) && pattern.elements.length;
|
var count = !hasRest(pattern) && pattern.elements.length;
|
||||||
|
|
||||||
var toArray = this.file.toArray(parentId, count);
|
var toArray = this.scope.toArray(parentId, count);
|
||||||
|
|
||||||
var _parentId = this.scope.generateUidBasedOnNode(parentId, this.file);
|
var _parentId = this.scope.generateUidBasedOnNode(parentId);
|
||||||
this.nodes.push(this.buildVariableDeclaration(_parentId, toArray));
|
this.nodes.push(this.buildVariableDeclaration(_parentId, toArray));
|
||||||
parentId = _parentId;
|
parentId = _parentId;
|
||||||
|
|
||||||
|
this.scope.assignTypeGeneric(parentId.name, "Array");
|
||||||
|
|
||||||
for (var i = 0; i < pattern.elements.length; i++) {
|
for (var i = 0; i < pattern.elements.length; i++) {
|
||||||
var elem = pattern.elements[i];
|
var elem = pattern.elements[i];
|
||||||
|
|
||||||
@ -159,7 +161,7 @@ DestructuringTransformer.prototype.pushArrayPattern = function (pattern, parentI
|
|||||||
var newPatternId;
|
var newPatternId;
|
||||||
|
|
||||||
if (t.isRestElement(elem)) {
|
if (t.isRestElement(elem)) {
|
||||||
newPatternId = this.file.toArray(parentId);
|
newPatternId = this.scope.toArray(parentId);
|
||||||
|
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
newPatternId = t.callExpression(t.memberExpression(newPatternId, t.identifier("slice")), [t.literal(i)]);
|
newPatternId = t.callExpression(t.memberExpression(newPatternId, t.identifier("slice")), [t.literal(i)]);
|
||||||
|
|||||||
@ -60,6 +60,8 @@ exports.Function = function (node, parent, scope) {
|
|||||||
node.body.body.unshift(restDeclar);
|
node.body.body.unshift(restDeclar);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scope.assignTypeGeneric(rest.name, "Array");
|
||||||
|
|
||||||
var loop = util.template("rest", {
|
var loop = util.template("rest", {
|
||||||
ARGUMENTS: argsId,
|
ARGUMENTS: argsId,
|
||||||
ARRAY_KEY: arrKey,
|
ARRAY_KEY: arrKey,
|
||||||
|
|||||||
@ -5,8 +5,8 @@ var t = require("../../../types");
|
|||||||
|
|
||||||
exports.check = t.isSpreadElement;
|
exports.check = t.isSpreadElement;
|
||||||
|
|
||||||
var getSpreadLiteral = function (spread, file) {
|
var getSpreadLiteral = function (spread, scope) {
|
||||||
return file.toArray(spread.argument, true);
|
return scope.toArray(spread.argument, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
var hasSpread = function (nodes) {
|
var hasSpread = function (nodes) {
|
||||||
@ -18,7 +18,7 @@ var hasSpread = function (nodes) {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
var build = function (props, file) {
|
var build = function (props, scope) {
|
||||||
var nodes = [];
|
var nodes = [];
|
||||||
|
|
||||||
var _props = [];
|
var _props = [];
|
||||||
@ -33,7 +33,7 @@ var build = function (props, file) {
|
|||||||
var prop = props[i];
|
var prop = props[i];
|
||||||
if (t.isSpreadElement(prop)) {
|
if (t.isSpreadElement(prop)) {
|
||||||
push();
|
push();
|
||||||
nodes.push(getSpreadLiteral(prop, file));
|
nodes.push(getSpreadLiteral(prop, scope));
|
||||||
} else {
|
} else {
|
||||||
_props.push(prop);
|
_props.push(prop);
|
||||||
}
|
}
|
||||||
@ -44,11 +44,11 @@ var build = function (props, file) {
|
|||||||
return nodes;
|
return nodes;
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.ArrayExpression = function (node, parent, scope, file) {
|
exports.ArrayExpression = function (node, parent, scope) {
|
||||||
var elements = node.elements;
|
var elements = node.elements;
|
||||||
if (!hasSpread(elements)) return;
|
if (!hasSpread(elements)) return;
|
||||||
|
|
||||||
var nodes = build(elements, file);
|
var nodes = build(elements, scope);
|
||||||
var first = nodes.shift();
|
var first = nodes.shift();
|
||||||
|
|
||||||
if (!t.isArrayExpression(first)) {
|
if (!t.isArrayExpression(first)) {
|
||||||
@ -59,7 +59,7 @@ exports.ArrayExpression = function (node, parent, scope, file) {
|
|||||||
return t.callExpression(t.memberExpression(first, t.identifier("concat")), nodes);
|
return t.callExpression(t.memberExpression(first, t.identifier("concat")), nodes);
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.CallExpression = function (node, parent, scope, file) {
|
exports.CallExpression = function (node, parent, scope) {
|
||||||
var args = node.arguments;
|
var args = node.arguments;
|
||||||
if (!hasSpread(args)) return;
|
if (!hasSpread(args)) return;
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ exports.CallExpression = function (node, parent, scope, file) {
|
|||||||
if (args.length === 1 && args[0].argument.name === "arguments") {
|
if (args.length === 1 && args[0].argument.name === "arguments") {
|
||||||
nodes = [args[0].argument];
|
nodes = [args[0].argument];
|
||||||
} else {
|
} else {
|
||||||
nodes = build(args, file);
|
nodes = build(args, scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
var first = nodes.shift();
|
var first = nodes.shift();
|
||||||
@ -105,7 +105,7 @@ exports.NewExpression = function (node, parent, scope, file) {
|
|||||||
|
|
||||||
var nativeType = t.isIdentifier(node.callee) && includes(t.NATIVE_TYPE_NAMES, node.callee.name);
|
var nativeType = t.isIdentifier(node.callee) && includes(t.NATIVE_TYPE_NAMES, node.callee.name);
|
||||||
|
|
||||||
var nodes = build(args, file);
|
var nodes = build(args, scope);
|
||||||
|
|
||||||
if (nativeType) {
|
if (nativeType) {
|
||||||
nodes.unshift(t.arrayExpression([t.literal(null)]));
|
nodes.unshift(t.arrayExpression([t.literal(null)]));
|
||||||
|
|||||||
@ -31,7 +31,6 @@ module.exports = {
|
|||||||
"es6.objectSuper": require("./es6/object-super"),
|
"es6.objectSuper": require("./es6/object-super"),
|
||||||
"es7.objectRestSpread": require("./es7/object-rest-spread"),
|
"es7.objectRestSpread": require("./es7/object-rest-spread"),
|
||||||
"es7.exponentiationOperator": require("./es7/exponentiation-operator"),
|
"es7.exponentiationOperator": require("./es7/exponentiation-operator"),
|
||||||
"es6.spread": require("./es6/spread"),
|
|
||||||
"es6.templateLiterals": require("./es6/template-literals"),
|
"es6.templateLiterals": require("./es6/template-literals"),
|
||||||
|
|
||||||
"es5.properties.mutators": require("./es5/properties.mutators"),
|
"es5.properties.mutators": require("./es5/properties.mutators"),
|
||||||
@ -50,6 +49,9 @@ module.exports = {
|
|||||||
// needs to be before `es6.parameters.default` as default parameters will destroy the rest param
|
// needs to be before `es6.parameters.default` as default parameters will destroy the rest param
|
||||||
"es6.parameters.rest": require("./es6/parameters.rest"),
|
"es6.parameters.rest": require("./es6/parameters.rest"),
|
||||||
|
|
||||||
|
// needs to be after `es6.parameters.rest` as we use `toArray` and avoid turning an already known array into one
|
||||||
|
"es6.spread": require("./es6/spread"),
|
||||||
|
|
||||||
// needs to be before `es6.blockScoping` as default parameters have a TDZ
|
// needs to be before `es6.blockScoping` as default parameters have a TDZ
|
||||||
"es6.parameters.default": require("./es6/parameters.default"),
|
"es6.parameters.default": require("./es6/parameters.default"),
|
||||||
|
|
||||||
|
|||||||
@ -198,6 +198,25 @@ Scope.prototype.inferType = function (node) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Scope.prototype.isTypeGeneric = function (name, genericName) {
|
||||||
|
var info = this.getBindingInfo(name);
|
||||||
|
if (!info) return false;
|
||||||
|
|
||||||
|
var type = info.typeAnnotation;
|
||||||
|
return t.isGenericTypeAnnotation(type) && t.isIdentifier(type.id, { name: genericName });
|
||||||
|
};
|
||||||
|
|
||||||
|
Scope.prototype.assignTypeGeneric = function (name, type) {
|
||||||
|
this.assignType(name, t.genericTypeAnnotation(t.identifier(type)));
|
||||||
|
};
|
||||||
|
|
||||||
|
Scope.prototype.assignType = function (name, type) {
|
||||||
|
var info = this.getBindingInfo(name);
|
||||||
|
if (!info) return;
|
||||||
|
|
||||||
|
info.identifier.typeAnnotation = info.typeAnnotation = type;
|
||||||
|
};
|
||||||
|
|
||||||
Scope.prototype.getTypeAnnotation = function (key, id, node) {
|
Scope.prototype.getTypeAnnotation = function (key, id, node) {
|
||||||
var type;
|
var type;
|
||||||
|
|
||||||
@ -215,6 +234,32 @@ Scope.prototype.getTypeAnnotation = function (key, id, node) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Scope.prototype.toArray = function (node, i) {
|
||||||
|
var file = this.file;
|
||||||
|
|
||||||
|
if (t.isIdentifier(node) && this.isTypeGeneric(node.name, "Array")) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t.isArrayExpression(node)) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t.isIdentifier(node, { name: "arguments" })) {
|
||||||
|
return t.callExpression(t.memberExpression(file.addHelper("slice"), t.identifier("call")), [node]);
|
||||||
|
}
|
||||||
|
|
||||||
|
var helperName = "to-array";
|
||||||
|
var args = [node];
|
||||||
|
if (i === true) {
|
||||||
|
helperName = "to-consumable-array";
|
||||||
|
} else if (i) {
|
||||||
|
args.push(t.literal(i));
|
||||||
|
helperName = "sliced-to-array";
|
||||||
|
}
|
||||||
|
return t.callExpression(file.addHelper(helperName), args);
|
||||||
|
};
|
||||||
|
|
||||||
Scope.prototype.clearOwnBinding = function (name) {
|
Scope.prototype.clearOwnBinding = function (name) {
|
||||||
delete this.bindings[name];
|
delete this.bindings[name];
|
||||||
};
|
};
|
||||||
|
|||||||
@ -59,6 +59,11 @@
|
|||||||
"generator": false
|
"generator": false
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"GenericTypeAnnotation": {
|
||||||
|
"id": null,
|
||||||
|
"typeParameters": null
|
||||||
|
},
|
||||||
|
|
||||||
"Identifier": {
|
"Identifier": {
|
||||||
"name": null
|
"name": null
|
||||||
},
|
},
|
||||||
|
|||||||
1
test/fixtures/transformation/es6-destructuring/known-array/actual.js
vendored
Normal file
1
test/fixtures/transformation/es6-destructuring/known-array/actual.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
let [x, ...y] = z;
|
||||||
8
test/fixtures/transformation/es6-destructuring/known-array/expected.js
vendored
Normal file
8
test/fixtures/transformation/es6-destructuring/known-array/expected.js
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
var _toArray = function (arr) { return Array.isArray(arr) ? arr : Array.from(arr); };
|
||||||
|
|
||||||
|
var _z = _toArray(z);
|
||||||
|
|
||||||
|
var x = _z[0];
|
||||||
|
var y = _z.slice(1);
|
||||||
@ -7,9 +7,9 @@ var isSorted = function (_ref) {
|
|||||||
|
|
||||||
var x = _ref2[0];
|
var x = _ref2[0];
|
||||||
var y = _ref2[1];
|
var y = _ref2[1];
|
||||||
var wow = _toArray(_ref2).slice(2);
|
var wow = _ref2.slice(2);
|
||||||
|
|
||||||
if (!zs.length) return true;
|
if (!zs.length) return true;
|
||||||
if (y > x) return isSorted(zs);
|
if (y > x) return isSorted(zs);
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,14 +1,11 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var _slicedToArray = function (arr, i) { if (Array.isArray(arr)) { return arr; } else { var _arr = []; for (var _iterator = arr[Symbol.iterator](), _step; !(_step = _iterator.next()).done;) { _arr.push(_step.value); if (i && _arr.length === i) break; } return _arr; } };
|
|
||||||
|
|
||||||
var foo = function () {
|
var foo = function () {
|
||||||
for (var _len = arguments.length, _ref = Array(_len), _key = 0; _key < _len; _key++) {
|
for (var _len = arguments.length, _ref = Array(_len), _key = 0; _key < _len; _key++) {
|
||||||
_ref[_key] = arguments[_key];
|
_ref[_key] = arguments[_key];
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ref2 = _slicedToArray(_ref, 2);
|
var _ref2 = _ref;
|
||||||
|
|
||||||
var a = _ref2[0];
|
var a = _ref2[0];
|
||||||
var b = _ref2[1];
|
var b = _ref2[1];
|
||||||
};
|
};
|
||||||
|
|||||||
2
test/fixtures/transformation/es6-spread/known-array/actual.js
vendored
Normal file
2
test/fixtures/transformation/es6-spread/known-array/actual.js
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
var arr: Array = bar;
|
||||||
|
[...arr];
|
||||||
4
test/fixtures/transformation/es6-spread/known-array/expected.js
vendored
Normal file
4
test/fixtures/transformation/es6-spread/known-array/expected.js
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
var arr = bar;
|
||||||
|
[].concat(arr);
|
||||||
3
test/fixtures/transformation/es6-spread/known-rest/actual.js
vendored
Normal file
3
test/fixtures/transformation/es6-spread/known-rest/actual.js
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
function foo(...bar) {
|
||||||
|
return [...bar];
|
||||||
|
}
|
||||||
9
test/fixtures/transformation/es6-spread/known-rest/expected.js
vendored
Normal file
9
test/fixtures/transformation/es6-spread/known-rest/expected.js
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
function foo() {
|
||||||
|
for (var _len = arguments.length, bar = Array(_len), _key = 0; _key < _len; _key++) {
|
||||||
|
bar[_key] = arguments[_key];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [].concat(bar);
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user