🌐 AI搜索 & 代理 主页
Skip to content

Commit 65068c0

Browse files
authored
Tree-shakes side effect free string methods on template literals (#4511)
1 parent 46a193b commit 65068c0

File tree

6 files changed

+64
-6
lines changed

6 files changed

+64
-6
lines changed

src/ast/nodes/Literal.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,6 @@ export default class Literal<T extends LiteralValue = LiteralValue> extends Node
5757
return path.length > 1;
5858
}
5959

60-
hasEffectsWhenAssignedAtPath(path: ObjectPath): boolean {
61-
return path.length > 0;
62-
}
63-
6460
hasEffectsWhenCalledAtPath(
6561
path: ObjectPath,
6662
callOptions: CallOptions,

src/ast/nodes/TemplateLiteral.ts

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,59 @@
11
import type MagicString from 'magic-string';
22
import type { RenderOptions } from '../../utils/renderHelpers';
3+
import { CallOptions } from '../CallOptions';
4+
import { HasEffectsContext } from '../ExecutionContext';
35
import type { ObjectPath } from '../utils/PathTracker';
6+
import {
7+
getMemberReturnExpressionWhenCalled,
8+
hasMemberEffectWhenCalled,
9+
literalStringMembers
10+
} from '../values';
411
import type * as NodeType from './NodeType';
512
import type TemplateElement from './TemplateElement';
6-
import { type LiteralValueOrUnknown, UnknownValue } from './shared/Expression';
13+
import {
14+
ExpressionEntity,
15+
type LiteralValueOrUnknown,
16+
UNKNOWN_EXPRESSION,
17+
UnknownValue
18+
} from './shared/Expression';
719
import { type ExpressionNode, NodeBase } from './shared/Node';
820

921
export default class TemplateLiteral extends NodeBase {
1022
declare expressions: ExpressionNode[];
1123
declare quasis: TemplateElement[];
1224
declare type: NodeType.tTemplateLiteral;
1325

26+
deoptimizeThisOnEventAtPath(): void {}
27+
1428
getLiteralValueAtPath(path: ObjectPath): LiteralValueOrUnknown {
1529
if (path.length > 0 || this.quasis.length !== 1) {
1630
return UnknownValue;
1731
}
1832
return this.quasis[0].value.cooked;
1933
}
2034

35+
getReturnExpressionWhenCalledAtPath(path: ObjectPath): ExpressionEntity {
36+
if (path.length !== 1) {
37+
return UNKNOWN_EXPRESSION;
38+
}
39+
return getMemberReturnExpressionWhenCalled(literalStringMembers, path[0]);
40+
}
41+
42+
hasEffectsWhenAccessedAtPath(path: ObjectPath): boolean {
43+
return path.length > 1;
44+
}
45+
46+
hasEffectsWhenCalledAtPath(
47+
path: ObjectPath,
48+
callOptions: CallOptions,
49+
context: HasEffectsContext
50+
): boolean {
51+
if (path.length === 1) {
52+
return hasMemberEffectWhenCalled(literalStringMembers, path[0], callOptions, context);
53+
}
54+
return true;
55+
}
56+
2157
render(code: MagicString, options: RenderOptions): void {
2258
(code.indentExclusionRanges as [number, number][]).push([this.start, this.end]);
2359
super.render(code, options);

src/ast/values.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ const literalNumberMembers: MemberDescriptions = assembleMemberDescriptions(
190190
objectMembers
191191
);
192192

193-
const literalStringMembers: MemberDescriptions = assembleMemberDescriptions(
193+
export const literalStringMembers: MemberDescriptions = assembleMemberDescriptions(
194194
{
195195
anchor: returnsString,
196196

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = {
2+
description: 'Tree-shake known string template literal prototype functions'
3+
};
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// deep property access is forbidden
2+
`ab`.x.y;
3+
4+
// due to strict mode, extension is forbidden
5+
`ab`.x = 1;
6+
7+
// throws when called
8+
`ab`();
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
`ab`.trim();
2+
`ab`.trim().trim();
3+
`ab`.toString().trim();
4+
5+
// property access is allowed
6+
const accessString = `ab`.x;
7+
8+
// deep property access is forbidden
9+
const deepString = `ab`.x.y;
10+
11+
// due to strict mode, extension is forbidden
12+
`ab`.x = 1;
13+
14+
// throws when called
15+
`ab`();

0 commit comments

Comments
 (0)