Skip to content

Commit b892223

Browse files
committed
fix: handle more expression for isPure detection
1 parent 7039d0a commit b892223

9 files changed

Lines changed: 144 additions & 6 deletions

File tree

lib/javascript/JavascriptParser.js

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4815,8 +4815,40 @@ class JavascriptParser extends Parser {
48154815
.for(expr.type)
48164816
.call(expr, commentsStartPos);
48174817
if (typeof result === "boolean") return result;
4818+
// TODO handle more cases
48184819
switch (expr.type) {
4819-
// TODO handle more cases
4820+
case "ArrayExpression": {
4821+
return expr.elements.every((element) => {
4822+
if (element === null) return true;
4823+
if (element.type === "SpreadElement") return false;
4824+
const pureFlag = this.isPure(element, commentsStartPos);
4825+
commentsStartPos = /** @type {Range} */ (element.range)[1];
4826+
return pureFlag;
4827+
});
4828+
}
4829+
4830+
case "ObjectExpression": {
4831+
return expr.properties.every((property) => {
4832+
if (property.type === "SpreadElement") return false;
4833+
const end = /** @type {Range} */ (property.key.range)[1];
4834+
4835+
if (
4836+
property.computed &&
4837+
!this.isPure(property.key, commentsStartPos)
4838+
) {
4839+
return false;
4840+
}
4841+
4842+
const pureFlag = this.isPure(
4843+
/** @type {Exclude<Property["value"], AssignmentPattern | ObjectPattern | ArrayPattern | RestElement>} */
4844+
(property.value),
4845+
end
4846+
);
4847+
commentsStartPos = end;
4848+
return pureFlag;
4849+
});
4850+
}
4851+
48204852
case "ClassDeclaration":
48214853
case "ClassExpression": {
48224854
if (expr.body.type !== "ClassBody") return false;
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { o2, o3 } from "./module";
2+
3+
import {
4+
exportUsed,
5+
export2Used,
6+
export3Used,
7+
export4Used,
8+
export5Used,
9+
export6Used
10+
} from "./inner";
11+
12+
it("some exports should be unused when no array expression use it", () => {
13+
expect(o2[0]).toBe(42);
14+
expect(o3[0].EXPORT5()).toBe(42);
15+
expect(o3[0].EXPORT6()).toBe(42);
16+
if (process.env.NODE_ENV === "production") {
17+
expect(exportUsed).toBe(false);
18+
expect(export2Used).toBe(false);
19+
expect(export3Used).toBe(false);
20+
expect(export4Used).toBe(true);
21+
expect(export5Used).toBe(true);
22+
expect(export6Used).toBe(true);
23+
}
24+
});
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
export const EXPORT = 42;
2+
export const EXPORT2 = 42;
3+
export const EXPORT3 = 42;
4+
export const EXPORT4 = 42;
5+
export const EXPORT5 = () => 42;
6+
export const EXPORT6 = () => 42;
7+
8+
export const exportUsed = __webpack_exports_info__.EXPORT.used;
9+
export const export2Used = __webpack_exports_info__.EXPORT2.used;
10+
export const export3Used = __webpack_exports_info__.EXPORT3.used;
11+
export const export4Used = __webpack_exports_info__.EXPORT4.used;
12+
export const export5Used = __webpack_exports_info__.EXPORT5.used;
13+
export const export6Used = __webpack_exports_info__.EXPORT6.used;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { EXPORT, EXPORT2, EXPORT3, EXPORT4, EXPORT5, EXPORT6 } from "./inner";
2+
3+
const o1 = [EXPORT2, EXPORT3];
4+
5+
const o2 = [EXPORT4];
6+
7+
const o3 = [{ EXPORT5, EXPORT6 }];
8+
9+
export { o1, o2, o3 };
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { o2, o3 } from "./module";
2+
3+
import {
4+
exportUsed,
5+
export2Used,
6+
export3Used,
7+
export4Used,
8+
export5Used,
9+
export6Used
10+
} from "./inner";
11+
12+
it("some exports should be unused when no object expression use it", () => {
13+
expect(o2.EXPORT4).toBe(42);
14+
expect(o3.EXPORT5()).toBe(42);
15+
expect(o3.EXPORT6()).toBe(42);
16+
if (process.env.NODE_ENV === "production") {
17+
expect(exportUsed).toBe(false);
18+
expect(export2Used).toBe(false);
19+
expect(export3Used).toBe(false);
20+
expect(export4Used).toBe(true);
21+
expect(export5Used).toBe(true);
22+
expect(export6Used).toBe(true);
23+
}
24+
});
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
export const EXPORT = 42;
2+
export const EXPORT2 = 42;
3+
export const EXPORT3 = 42;
4+
export const EXPORT4 = 42;
5+
export const EXPORT5 = () => 42;
6+
export const EXPORT6 = () => 42;
7+
8+
export const exportUsed = __webpack_exports_info__.EXPORT.used;
9+
export const export2Used = __webpack_exports_info__.EXPORT2.used;
10+
export const export3Used = __webpack_exports_info__.EXPORT3.used;
11+
export const export4Used = __webpack_exports_info__.EXPORT4.used;
12+
export const export5Used = __webpack_exports_info__.EXPORT5.used;
13+
export const export6Used = __webpack_exports_info__.EXPORT6.used;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { EXPORT, EXPORT2, EXPORT3, EXPORT4, EXPORT5, EXPORT6 } from "./inner";
2+
3+
const o1 = {
4+
EXPORT2: EXPORT2,
5+
EXPORT3: EXPORT3
6+
};
7+
8+
const o2 = {
9+
EXPORT4: EXPORT4
10+
};
11+
12+
const o3 = {
13+
EXPORT5: EXPORT5,
14+
EXPORT6: EXPORT6
15+
};
16+
17+
export { o1, o2, o3 };

test/configCases/side-effects/asset-module/index.js

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
import asset from "./unused.png?asset";
2-
import bytes from "./unused.png?bytes";
3-
import inlined from "./unused.png?inline";
4-
import source from "./unused.png?source";
5-
import resource from "./used.png";
1+
import { resource } from "./module";
62

73
it("should not include unused assets", () => {
84
expect(resource).toMatch(/\.png/);
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import asset from "./unused.png?asset";
2+
import bytes from "./unused.png?bytes";
3+
import inlined from "./unused.png?inline";
4+
import source from "./unused.png?source";
5+
import resource from "./used.png";
6+
7+
let arr = [asset, bytes, inlined, source];
8+
let obj = { asset, bytes, inlined, source };
9+
10+
export { arr, obj, resource };

0 commit comments

Comments
 (0)