Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move more traversers outside closures #534

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
20 changes: 11 additions & 9 deletions lib/6to5/transformation/helpers/remap-async-to-generator.js
Expand Up @@ -3,19 +3,21 @@
var traverse = require("../../traverse");
var t = require("../../types");

var traverser = {
enter: function (node, parent, scope, context) {
if (t.isFunction(node)) context.skip();

if (t.isAwaitExpression(node)) {
node.type = "YieldExpression";
}
}
};

module.exports = function (node, callId) {
node.async = false;
node.generator = true;

traverse(node, {
enter: function (node, parent, scope, context) {
if (t.isFunction(node)) context.skip();

if (t.isAwaitExpression(node)) {
node.type = "YieldExpression";
}
}
});
traverse(node, traverser);

var call = t.callExpression(callId, [node]);

Expand Down
64 changes: 34 additions & 30 deletions lib/6to5/transformation/helpers/replace-supers.js
Expand Up @@ -5,6 +5,38 @@ module.exports = ReplaceSupers;
var traverse = require("../../traverse");
var t = require("../../types");

var traverser = {
enter: function (node, parent, scope, context, state) {
var topLevel = state.topLevel;
var self = state.self;

if (t.isFunction(node) && !t.isArrowFunctionExpression(node)) {
// we need to call traverseLevel again so we're context aware
self.traverseLevel(node, false);
return context.skip();
}

if (t.isProperty(node, { method: true }) || t.isMethodDefinition(node)) {
// break on object methods
return context.skip();
}

var getThisReference = function () {
if (topLevel) {
// top level so `this` is the instance
return t.thisExpression();
} else {
// not in the top level so we need to create a reference
return self.getThisReference();
}
};

var callback = self.specHandle;
if (self.isLoose) callback = self.looseHandle;
return callback.call(self, getThisReference, node, parent);
}
};

/**
* Description
*
Expand Down Expand Up @@ -111,36 +143,8 @@ ReplaceSupers.prototype.replace = function () {
*/

ReplaceSupers.prototype.traverseLevel = function (node, topLevel) {
var self = this;

traverse(node, {
enter: function (node, parent, scope, context) {
if (t.isFunction(node) && !t.isArrowFunctionExpression(node)) {
// we need to call traverseLevel again so we're context aware
self.traverseLevel(node, false);
return context.skip();
}

if (t.isProperty(node, { method: true }) || t.isMethodDefinition(node)) {
// break on object methods
return context.skip();
}

var getThisReference = function () {
if (topLevel) {
// top level so `this` is the instance
return t.thisExpression();
} else {
// not in the top level so we need to create a reference
return self.getThisReference();
}
};

var callback = self.specHandle;
if (self.isLoose) callback = self.looseHandle;
return callback.call(self, getThisReference, node, parent);
}
});
var state = { self: this, topLevel: topLevel };
traverse(node, traverser, null, state);
};

/**
Expand Down
162 changes: 82 additions & 80 deletions lib/6to5/transformation/modules/_default.js
Expand Up @@ -7,17 +7,6 @@ var util = require("../../util");
var t = require("../../types");
var _ = require("lodash");

function DefaultFormatter(file) {
this.file = file;

this.localExports = this.getLocalExports();
this.localImports = this.getLocalImports();

this.remapAssignments();

//this.checkCollisions();
}

var exportsTraverser = {
enter: function (node, parent, scope, context, localExports) {
var declar = node && node.declaration;
Expand All @@ -27,12 +16,6 @@ var exportsTraverser = {
}
};

DefaultFormatter.prototype.getLocalExports = function () {
var localExports = {};
traverse(this.file.ast, exportsTraverser, null, localExports);
return localExports;
};

var importsTraverser = {
enter: function (node, parent, scope, context, localImports) {
if (t.isImportDeclaration(node)) {
Expand All @@ -41,45 +24,100 @@ var importsTraverser = {
}
};

DefaultFormatter.prototype.getLocalImports = function () {
var localImports = {};
traverse(this.file.ast, importsTraverser, null, localImports);
return localImports;
var remapTraverser = {
enter: function (node, parent, scope, context, state) {
var self = state.self;
if (t.isUpdateExpression(node) && self.isLocalReference(node.argument, scope)) {
context.skip();

// expand to long file assignment expression
var assign = t.assignmentExpression(node.operator[0] + "=", node.argument, t.literal(1));

// remap this assignment expression
var remapped = self.remapExportAssignment(assign);

// we don't need to change the result
if (t.isExpressionStatement(parent) || node.prefix) {
return remapped;
}

var nodes = [];
nodes.push(remapped);

var operator;
if (node.operator === "--") {
operator = "+";
} else { // "++"
operator = "-";
}
nodes.push(t.binaryExpression(operator, node.argument, t.literal(1)));

return t.sequenceExpression(nodes);
}

if (t.isAssignmentExpression(node) && self.isLocalReference(node.left, scope)) {
context.skip();
return self.remapExportAssignment(node);
}
}
};

var collissionsTraverser = {
enter: function (node, parent, scope, context, check) {
enter: function (node, parent, scope, context, state) {
var self = state.self;
if (t.isAssignmentExpression(node)) {

var left = node.left;
if (t.isMemberExpression(left)) {
while (left.object) left = left.object;
}

check(left);
self.checkLocalReference(left);
} else if (t.isDeclaration(node)) {
_.each(t.getIds(node, true), check);
_.each(t.getIds(node, true), self.checkLocalReference);
}
}
};

DefaultFormatter.prototype.checkCollisions = function () {
// todo: all check export collissions
function DefaultFormatter(file) {
this.file = file;

var localImports = this.localImports;
var file = this.file;
this.localExports = this.getLocalExports();
this.localImports = this.getLocalImports();

var isLocalReference = function (node) {
return t.isIdentifier(node) && _.has(localImports, node.name) && localImports[node.name] !== node;
};
this.remapAssignments();

var check = function (node) {
if (isLocalReference(node)) {
throw file.errorWithNode(node, "Illegal assignment of module import");
}
};
//this.checkCollisions();
}

DefaultFormatter.prototype.getLocalExports = function () {
var localExports = {};
traverse(this.file.ast, exportsTraverser, null, localExports);
return localExports;
};

DefaultFormatter.prototype.getLocalImports = function () {
var localImports = {};
traverse(this.file.ast, importsTraverser, null, localImports);
return localImports;
};

DefaultFormatter.prototype.isLocalReference = function (node) {
var localImports = this.localImports;
return t.isIdentifier(node) && _.has(localImports, node.name) && localImports[node.name] !== node;
};

traverse(file.ast, collissionsTraverser, null, check);
DefaultFormatter.prototype.checkLocalReference = function (node) {
var file = this.file;
if (this.isLocalReference(node)) {
throw file.errorWithNode(node, "Illegal assignment of module import");
}
};

DefaultFormatter.prototype.checkCollisions = function () {
// todo: all check export collissions
var state = { self: this };
traverse(this.file.ast, collissionsTraverser, null, state);
};

DefaultFormatter.prototype.remapExportAssignment = function (node) {
Expand All @@ -94,51 +132,15 @@ DefaultFormatter.prototype.remapExportAssignment = function (node) {
);
};

DefaultFormatter.prototype.remapAssignments = function () {
DefaultFormatter.prototype.isLocalReference = function (node, scope) {
var localExports = this.localExports;
var self = this;

var isLocalReference = function (node, scope) {
var name = node.name;
return t.isIdentifier(node) && localExports[name] && localExports[name] === scope.get(name, true);
};

traverse(this.file.ast, {
enter: function (node, parent, scope, context, isLocalReference) {
if (t.isUpdateExpression(node) && isLocalReference(node.argument, scope)) {
context.skip();

// expand to long file assignment expression
var assign = t.assignmentExpression(node.operator[0] + "=", node.argument, t.literal(1));

// remap this assignment expression
var remapped = self.remapExportAssignment(assign);

// we don't need to change the result
if (t.isExpressionStatement(parent) || node.prefix) {
return remapped;
}

var nodes = [];
nodes.push(remapped);

var operator;
if (node.operator === "--") {
operator = "+";
} else { // "++"
operator = "-";
}
nodes.push(t.binaryExpression(operator, node.argument, t.literal(1)));

return t.sequenceExpression(nodes);
}
var name = node.name;
return t.isIdentifier(node) && localExports[name] && localExports[name] === scope.get(name, true);
};

if (t.isAssignmentExpression(node) && isLocalReference(node.left, scope)) {
context.skip();
return self.remapExportAssignment(node);
}
}
}, null, isLocalReference);
DefaultFormatter.prototype.remapAssignments = function () {
var state = { self: this };
traverse(this.file.ast, remapTraverser, null, state);
};

DefaultFormatter.prototype.getModuleName = function () {
Expand Down
17 changes: 10 additions & 7 deletions lib/6to5/transformation/modules/common.js
Expand Up @@ -7,16 +7,19 @@ var traverse = require("../../traverse");
var util = require("../../util");
var t = require("../../types");

var traverser = {
enter: function (node, parent, scope, context, state) {
if (t.isExportDeclaration(node) && !node.default) state.hasNonDefaultExports = true;
}
};

function CommonJSFormatter(file) {
DefaultFormatter.apply(this, arguments);

var hasNonDefaultExports = false;
traverse(file.ast, {
enter: function (node) {
if (t.isExportDeclaration(node) && !node.default) hasNonDefaultExports = true;
}
});
this.hasNonDefaultExports = hasNonDefaultExports;
var state = { hasNonDefaultExports: false };
traverse(file.ast, traverser, null, state);

this.hasNonDefaultExports = state.hasNonDefaultExports;
}

util.inherits(CommonJSFormatter, DefaultFormatter);
Expand Down