Skip to content

Commit

Permalink
Merge pull request #5076 from ljqx/parser-support-rename-this-for-iife
Browse files Browse the repository at this point in the history
[Parser] Support rename this's property for IIFE
  • Loading branch information
sokra committed Jul 1, 2017
2 parents 42cdfed + cc2df2f commit 9ff3c7a
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 15 deletions.
37 changes: 24 additions & 13 deletions lib/Parser.js
Expand Up @@ -1063,19 +1063,24 @@ class Parser extends Tapable {
walkCallExpression(expression) {
let result;

function walkIIFE(functionExpression, options) {
const params = functionExpression.params;
const args = options.map(function(arg) {
const renameIdentifier = this.getRenameIdentifier(arg);
if(renameIdentifier && this.applyPluginsBailResult1("can-rename " + renameIdentifier, arg)) {
if(!this.applyPluginsBailResult1("rename " + renameIdentifier, arg))
function walkIIFE(functionExpression, options, currentThis) {
function renameArgOrThis(argOrThis) {
const renameIdentifier = this.getRenameIdentifier(argOrThis);
if(renameIdentifier && this.applyPluginsBailResult1("can-rename " + renameIdentifier, argOrThis)) {
if(!this.applyPluginsBailResult1("rename " + renameIdentifier, argOrThis))
return renameIdentifier;
}
this.walkExpression(arg);
}, this);
this.walkExpression(argOrThis);
}
const params = functionExpression.params;
const renameThis = currentThis ? renameArgOrThis.call(this, currentThis) : null;
const args = options.map(renameArgOrThis, this);
this.inScope(params.filter(function(identifier, idx) {
return !args[idx];
}), function() {
if(renameThis) {
this.scope.renames.$this = renameThis;
}
for(let i = 0; i < args.length; i++) {
const param = args[i];
if(!param) continue;
Expand All @@ -1094,11 +1099,10 @@ class Parser extends Tapable {
!expression.callee.computed &&
(["call", "bind"]).indexOf(expression.callee.property.name) >= 0 &&
expression.arguments &&
expression.arguments.length > 1
expression.arguments.length > 0
) {
// (function(...) { }.call/bind(?, ...))
walkIIFE.call(this, expression.callee.object, expression.arguments.slice(1));
this.walkExpression(expression.arguments[0]);
walkIIFE.call(this, expression.callee.object, expression.arguments.slice(1), expression.arguments[0]);
} else if(expression.callee.type === "FunctionExpression" && expression.arguments) {
// (function(...) { }(...))
walkIIFE.call(this, expression.callee, expression.arguments);
Expand Down Expand Up @@ -1138,8 +1142,13 @@ class Parser extends Tapable {
exprName.unshift(expr.property.name || expr.property.value);
expr = expr.object;
}
if(expr.type === "Identifier" && this.scope.definitions.indexOf(expr.name) === -1) {
exprName.unshift(this.scope.renames["$" + expr.name] || expr.name);
if((expr.type === "Identifier" && this.scope.definitions.indexOf(expr.name) === -1) ||
(expr.type === "ThisExpression" && this.scope.renames.$this)) {
if(expr.type === "ThisExpression") {
exprName.unshift(this.scope.renames.$this);
} else {
exprName.unshift(this.scope.renames["$" + expr.name] || expr.name);
}
let result = this.applyPluginsBailResult1("expression " + exprName.join("."), expression);
if(result === true)
return;
Expand Down Expand Up @@ -1170,6 +1179,8 @@ class Parser extends Tapable {
renames: Object.create(oldScope.renames)
};

this.scope.renames.$this = undefined;

for(let paramIndex = 0, len = params.length; paramIndex < len; paramIndex++) {
const param = params[paramIndex];

Expand Down
17 changes: 16 additions & 1 deletion test/Parser.test.js
Expand Up @@ -161,7 +161,7 @@ describe("Parser", () => {
abc: ["test"]
}
],
"renaming with IIFE (called)": [
"renaming arguments with IIFE (called)": [
function() {
! function(xyz) {
xyz("test");
Expand All @@ -171,6 +171,15 @@ describe("Parser", () => {
fgh: [""]
}
],
"renaming this's properties with IIFE (called)": [
function() {
! function() {
this.sub;
}.call(ijk);
}, {
ijksub: ["test"]
}
],
};

Object.keys(testCases).forEach((name) => {
Expand All @@ -181,6 +190,7 @@ describe("Parser", () => {

const testParser = new Parser({});
testParser.plugin("can-rename abc", (expr) => true);
testParser.plugin("can-rename ijk", (expr) => true);
testParser.plugin("call abc", (expr) => {
if(!testParser.state.abc) testParser.state.abc = [];
testParser.state.abc.push(testParser.parseString(expr.arguments[0]));
Expand All @@ -206,6 +216,11 @@ describe("Parser", () => {
testParser.state.fghsub.push(testParser.scope.inTry ? "try" : "notry");
return true;
});
testParser.plugin("expression ijk.sub", (expr) => {
if(!testParser.state.ijksub) testParser.state.ijksub = [];
testParser.state.ijksub.push("test");
return true;
});
testParser.plugin("expression memberExpr", (expr) => {
if(!testParser.state.expressions) testParser.state.expressions = [];
testParser.state.expressions.push(expr.name);
Expand Down
10 changes: 9 additions & 1 deletion test/configCases/plugins/provide-plugin/index.js
Expand Up @@ -8,14 +8,22 @@ it("should provide a module for a nested var", function() {
x.should.be.eql("bbbccc");
});

it("should provide a module for a nested var within a IIFE", function() {
it("should provide a module for a nested var within a IIFE's argument", function() {
(function(process) {
(process.env.NODE_ENV).should.be.eql("development");
var x = process.env.NODE_ENV;
x.should.be.eql("development");
}(process));
});

it("should provide a module for a nested var within a IIFE's this", function() {
(function() {
(this.env.NODE_ENV).should.be.eql("development");
var x = this.env.NODE_ENV;
x.should.be.eql("development");
}.call(process));
});

it("should not provide a module for a part of a var", function() {
(typeof bbb).should.be.eql("undefined");
});
Expand Down

0 comments on commit 9ff3c7a

Please sign in to comment.