-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
/
IfStatement.ts
107 lines (99 loc) · 3.24 KB
/
IfStatement.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import MagicString from 'magic-string';
import { RenderOptions } from '../../utils/renderHelpers';
import { DeoptimizableEntity } from '../DeoptimizableEntity';
import { ExecutionPathOptions } from '../ExecutionPathOptions';
import { EMPTY_IMMUTABLE_TRACKER } from '../utils/ImmutableEntityPathTracker';
import { EMPTY_PATH, LiteralValueOrUnknown, UNKNOWN_VALUE } from '../values';
import * as NodeType from './NodeType';
import { ExpressionNode, StatementBase, StatementNode } from './shared/Node';
export default class IfStatement extends StatementBase implements DeoptimizableEntity {
type: NodeType.tIfStatement;
test: ExpressionNode;
consequent: StatementNode;
alternate: StatementNode | null;
private testValue: LiteralValueOrUnknown;
private isTestValueAnalysed: boolean;
bind() {
super.bind();
if (!this.isTestValueAnalysed) {
this.testValue = UNKNOWN_VALUE;
this.isTestValueAnalysed = true;
this.testValue = this.test.getLiteralValueAtPath(EMPTY_PATH, EMPTY_IMMUTABLE_TRACKER, this);
}
}
deoptimizeCache() {
this.testValue = UNKNOWN_VALUE;
}
hasEffects(options: ExecutionPathOptions): boolean {
if (this.test.hasEffects(options)) return true;
if (this.testValue === UNKNOWN_VALUE) {
return (
this.consequent.hasEffects(options) ||
(this.alternate !== null && this.alternate.hasEffects(options))
);
}
return this.testValue
? this.consequent.hasEffects(options)
: this.alternate !== null && this.alternate.hasEffects(options);
}
include(includeAllChildrenRecursively: boolean) {
this.included = true;
if (includeAllChildrenRecursively) {
this.test.include(true);
this.consequent.include(true);
if (this.alternate !== null) {
this.alternate.include(true);
}
return;
}
const hasUnknownTest = this.testValue === UNKNOWN_VALUE;
if (hasUnknownTest || this.test.shouldBeIncluded()) {
this.test.include(false);
}
if ((hasUnknownTest || this.testValue) && this.consequent.shouldBeIncluded()) {
this.consequent.include(false);
}
if (
this.alternate !== null &&
((hasUnknownTest || !this.testValue) && this.alternate.shouldBeIncluded())
) {
this.alternate.include(false);
}
}
initialise() {
this.included = false;
this.isTestValueAnalysed = false;
}
render(code: MagicString, options: RenderOptions) {
// Note that unknown test values are always included
if (
!this.test.included &&
(this.testValue
? this.alternate === null || !this.alternate.included
: !this.consequent.included)
) {
const singleRetainedBranch = this.testValue ? this.consequent : this.alternate;
code.remove(this.start, singleRetainedBranch.start);
code.remove(singleRetainedBranch.end, this.end);
singleRetainedBranch.render(code, options);
} else {
if (this.test.included) {
this.test.render(code, options);
} else {
code.overwrite(this.test.start, this.test.end, this.testValue ? 'true' : 'false');
}
if (this.consequent.included) {
this.consequent.render(code, options);
} else {
code.overwrite(this.consequent.start, this.consequent.end, ';');
}
if (this.alternate !== null) {
if (this.alternate.included) {
this.alternate.render(code, options);
} else {
code.remove(this.consequent.end, this.alternate.end);
}
}
}
}
}