merge es6.parameters.rest and es6.parameters.default transformers

This is necessary in order to retain correct function arity and to have
completely correct semantics. Sometimes features are tied together so much
that they would require so much desugaring to retain the correct semantics
that they'd be equivalent to... the normal transpiled output.
This commit is contained in:
Sebastian McKenzie 2015-06-26 02:20:16 +01:00
parent 579e6fecee
commit c0fd4c1f9e
39 changed files with 86 additions and 15 deletions

View File

@ -8,5 +8,8 @@
"utility.inlineExpressions": "minification.constantFolding",
"utility.deadCodeElimination": "minification.deadCodeElimination",
"utility.removeConsoleCalls": "minification.removeConsole",
"utility.removeDebugger": "minification.removeDebugger"
"utility.removeDebugger": "minification.removeDebugger",
"es6.parameters.rest": "es6.parameters",
"es6.parameters.default": "es6.parameters"
}

View File

@ -70,7 +70,15 @@ export var visitor = {
let pattern = node.params[i];
if (!t.isPattern(pattern)) continue;
var ref = node.params[i] = scope.generateUidIdentifier("ref");
var ref = scope.generateUidIdentifier("ref");
if (t.isAssignmentPattern(pattern)) {
var _pattern = pattern;
pattern = pattern.left;
_pattern.left = ref;
} else {
node.params[i] = ref;
}
t.inherits(ref, pattern);
var destructuring = new DestructuringTransformer({

View File

@ -1,7 +1,7 @@
import callDelegate from "../../helpers/call-delegate";
import getFunctionArity from "../../helpers/get-function-arity";
import * as util from "../../../util";
import * as t from "../../../types";
import callDelegate from "../../../helpers/call-delegate";
import getFunctionArity from "../../../helpers/get-function-arity";
import * as util from "../../../../util";
import * as t from "../../../../types";
var hasDefaults = function (node) {
for (var i = 0; i < node.params.length; i++) {
@ -38,7 +38,7 @@ export var visitor = {
//
var argsIdentifier = t.identifier("arguments");
argsIdentifier._shadowedFunctionLiteral = true;
argsIdentifier._shadowedFunctionLiteral = node;
// push a default parameter definition
function pushDefNode(left, right, i) {

View File

@ -0,0 +1,11 @@
import * as util from "../../../../util";
import * as visitors from "../../../../traversal/visitors";
import * as def from "./default";
import * as rest from "./rest";
export var metadata = {
group: "builtin-advanced"
};
export var visitor = visitors.merge([rest.visitor, def.visitor]);

View File

@ -1,5 +1,5 @@
import * as util from "../../../util";
import * as t from "../../../types";
import * as util from "../../../../util";
import * as t from "../../../../types";
var memberExpressionOptimisationVisitor = {
Scope(node, parent, scope, state) {
@ -84,7 +84,7 @@ export var visitor = {
var argsId = t.identifier("arguments");
// otherwise `arguments` will be remapped in arrow functions
argsId._shadowedFunctionLiteral = true;
argsId._shadowedFunctionLiteral = node;
// support patterns
if (t.isPattern(rest)) {

View File

@ -43,6 +43,10 @@ function build(props, scope) {
return nodes;
}
export var metadata = {
group: "builtin-advanced"
};
export var visitor = {
ArrayExpression(node, parent, scope) {
var elements = node.elements;

View File

@ -211,7 +211,7 @@ class TailCallTransformer {
var decl = t.variableDeclarator(this.argumentsId);
if (this.argumentsId) {
decl.init = t.identifier("arguments");
decl.init._shadowedFunctionLiteral = true;
decl.init._shadowedFunctionLiteral = node;
}
topVars.push(decl);
}

View File

@ -46,9 +46,6 @@ export default {
"es6.regex.sticky": require("./es6/regex.sticky"),
"es6.regex.unicode": require("./es6/regex.unicode"),
"es6.constants": require("./es6/constants"),
"es6.parameters.rest": require("./es6/parameters.rest"),
"es6.spread": require("./es6/spread"),
"es6.parameters.default": require("./es6/parameters.default"),
"es7.exportExtensions": require("./es7/export-extensions"),
"spec.protoToAssign": require("babel-plugin-proto-to-assign"),
"es7.doExpressions": require("./es7/do-expressions"),
@ -57,6 +54,8 @@ export default {
"spec.undefinedToVoid": require("babel-plugin-undefined-to-void"),
//- builtin-advanced
"es6.spread": require("./es6/spread"),
"es6.parameters": require("./es6/parameters"),
"es6.destructuring": require("./es6/destructuring"),
"es6.blockScoping": require("./es6/block-scoping"),
"es6.spec.blockScoping": require("./es6/spec.block-scoping"),

View File

@ -10,6 +10,9 @@ function remap(path, key, create) {
var fnPath = path.findParent((path) => !path.is("shadow") && (path.isFunction() || path.isProgram()));
var shadowed = path.node._shadowedFunctionLiteral;
if (shadowed && shadowed !== fnPath.node) return;
var cached = fnPath.getData(key);
if (cached) return cached;
@ -28,7 +31,7 @@ export var visitor = {
},
ReferencedIdentifier(node) {
if (node.name === "arguments" && !node._shadowedFunctionLiteral) {
if (node.name === "arguments") {
return remap(this, "arguments", () => t.identifier("arguments"));
}
}

View File

@ -126,6 +126,8 @@ export function merge(visitors) {
var rootVisitor = {};
for (var visitor of (visitors: Array)) {
explode(visitor);
for (var type in visitor) {
var nodeVisitor = rootVisitor[type] = rootVisitor[type] || {};
mergePair(nodeVisitor, visitor[type]);

View File

@ -0,0 +1,6 @@
function broken(x, ...foo) {
if (true) {
class Foo extends Bar { }
return hello(...foo)
}
}

View File

@ -0,0 +1,35 @@
"use strict";
var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }
function broken(x) {
for (var _len = arguments.length, foo = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
foo[_key - 1] = arguments[_key];
}
if (true) {
var _ret = (function () {
var Foo = (function (_Bar) {
function Foo() {
_classCallCheck(this, Foo);
_get(Object.getPrototypeOf(Foo.prototype), "constructor", this).apply(this, arguments);
}
_inherits(Foo, _Bar);
return Foo;
})(Bar);
return {
v: hello.apply(undefined, foo)
};
})();
if (typeof _ret === "object") return _ret.v;
}
}