Skip to content

Commit dd03262

Browse files
authored
Merge pull request webpack#6968 from webpack/fix/harmony_this
Fix 'this' replacement for harmony modules
2 parents a60480e + a8b32ac commit dd03262

File tree

3 files changed

+53
-15
lines changed

3 files changed

+53
-15
lines changed

lib/Parser.js

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1060,9 +1060,10 @@ class Parser extends Tapable {
10601060
}
10611061

10621062
walkFunctionDeclaration(statement) {
1063+
const wasTopLevel = this.scope.topLevelScope;
1064+
this.scope.topLevelScope = false;
10631065
for (const param of statement.params) this.walkPattern(param);
10641066
this.inScope(statement.params, () => {
1065-
this.scope.topLevelScope = false;
10661067
if (statement.body.type === "BlockStatement") {
10671068
this.detectStrictMode(statement.body.body);
10681069
this.prewalkStatement(statement.body);
@@ -1071,6 +1072,7 @@ class Parser extends Tapable {
10711072
this.walkExpression(statement.body);
10721073
}
10731074
});
1075+
this.scope.topLevelScope = wasTopLevel;
10741076
}
10751077

10761078
prewalkImportDeclaration(statement) {
@@ -1465,9 +1467,10 @@ class Parser extends Tapable {
14651467
}
14661468

14671469
walkFunctionExpression(expression) {
1470+
const wasTopLevel = this.scope.topLevelScope;
1471+
this.scope.topLevelScope = false;
14681472
for (const param of expression.params) this.walkPattern(param);
14691473
this.inScope(expression.params, () => {
1470-
this.scope.topLevelScope = false;
14711474
if (expression.body.type === "BlockStatement") {
14721475
this.detectStrictMode(expression.body.body);
14731476
this.prewalkStatement(expression.body);
@@ -1476,6 +1479,7 @@ class Parser extends Tapable {
14761479
this.walkExpression(expression.body);
14771480
}
14781481
});
1482+
this.scope.topLevelScope = wasTopLevel;
14791483
}
14801484

14811485
walkArrowFunctionExpression(expression) {
@@ -1621,10 +1625,10 @@ class Parser extends Tapable {
16211625
}
16221626
this.walkExpression(argOrThis);
16231627
};
1628+
const wasTopLevel = this.scope.topLevelScope;
1629+
this.scope.topLevelScope = false;
16241630
const params = functionExpression.params;
1625-
const renameThis = currentThis
1626-
? renameArgOrThis.call(this, currentThis)
1627-
: null;
1631+
const renameThis = currentThis ? renameArgOrThis(currentThis) : null;
16281632
const args = options.map(renameArgOrThis);
16291633
this.inScope(params.filter((identifier, idx) => !args[idx]), () => {
16301634
if (renameThis) {
@@ -1641,6 +1645,7 @@ class Parser extends Tapable {
16411645
this.walkStatement(functionExpression.body);
16421646
} else this.walkExpression(functionExpression.body);
16431647
});
1648+
this.scope.topLevelScope = wasTopLevel;
16441649
};
16451650
if (
16461651
expression.callee.type === "MemberExpression" &&
@@ -1652,8 +1657,7 @@ class Parser extends Tapable {
16521657
expression.arguments.length > 0
16531658
) {
16541659
// (function(…) { }.call/bind(?, …))
1655-
walkIIFE.call(
1656-
this,
1660+
walkIIFE(
16571661
expression.callee.object,
16581662
expression.arguments.slice(1),
16591663
expression.arguments[0]
@@ -1663,7 +1667,7 @@ class Parser extends Tapable {
16631667
expression.arguments
16641668
) {
16651669
// (function(…) { }(…))
1666-
walkIIFE.call(this, expression.callee, expression.arguments);
1670+
walkIIFE(expression.callee, expression.arguments, null);
16671671
} else if (expression.callee.type === "Import") {
16681672
result = this.hooks.importCall.call(expression);
16691673
if (result === true) return;

test/configCases/parsing/harmony-this/abc.js

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
function returnThis() {
2-
if(typeof this === "undefined") return "undefined";
2+
if (typeof this === "undefined") return "undefined";
33
return this;
44
}
55

66
var a = returnThis;
77
var b = returnThis;
88

9-
export {
10-
a,
11-
b
12-
}
9+
export { a, b };
1310

1411
export const that = this;
1512
export const returnThisArrow = () => this;
@@ -29,10 +26,38 @@ export class C {
2926

3027
export const extendThisClass = () => {
3128
return class extends this.Buffer {};
32-
}
29+
};
3330

3431
export function D() {
3532
this.prop = () => "ok";
3633
}
3734

35+
// See https://github.com/webpack/webpack/issues/6379
36+
export const E = {
37+
x: "bar",
38+
foo(x = this.x) {
39+
return x;
40+
}
41+
};
42+
43+
// See https://github.com/webpack/webpack/issues/6967
44+
export const F = function() {
45+
return this;
46+
}.call("ok");
47+
48+
export function f1(x = this.x) {
49+
return x;
50+
}
51+
52+
export const f2 = function(x = this.x) {
53+
return x;
54+
};
55+
56+
export const f3 = (x = this) => x;
57+
58+
export function G(x) {
59+
this.x = x;
60+
this.getX = (y = this.x) => y;
61+
}
62+
3863
export default returnThis;

test/configCases/parsing/harmony-this/index.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
"use strict";
22

3-
import d, {a, b as B, C as _C, D as _D, extendThisClass, returnThisArrow, returnThisMember, that} from "./abc";
3+
import should from "should";
4+
import {extendThisClass, returnThisArrow, returnThisMember, that} from "./abc";
5+
import d, {a, b as B, C as _C, D as _D, E, F, f1, f2, f3, G} from "./abc";
46

57
import * as abc from "./abc";
68

@@ -24,6 +26,13 @@ it("should not break classes and functions", function() {
2426
(new _C).foo().should.be.eql("bar");
2527
(new _C).bar().should.be.eql("bar");
2628
(new _D).prop().should.be.eql("ok");
29+
E.foo().should.be.eql("bar");
30+
F.should.be.eql("ok");
31+
f1.call({x: "f1"}).should.be.eql("f1");
32+
f2.call({x: "f2"}).should.be.eql("f2");
33+
should(f3.call("f3")).be.eql(undefined);
34+
should(f3()).be.eql(undefined);
35+
(new G("ok")).getX().should.be.eql("ok");
2736
});
2837

2938
function x() { throw new Error("should not be executed"); }

0 commit comments

Comments
 (0)