Skip to content

Commit c47dab5

Browse files
authored
feat(es/minifier): Evaluate Number.XXX constants (#10756)
1 parent c3d5ad1 commit c47dab5

File tree

9 files changed

+74
-12
lines changed

9 files changed

+74
-12
lines changed

.changeset/late-games-pretend.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
swc_core: patch
3+
swc_ecma_minifier: patch
4+
---
5+
6+
feat(es/minifier): Implement more evaluation rules

crates/swc_ecma_minifier/src/compress/optimize/evaluate.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,62 @@ impl Optimizer<'_> {
139139
.into();
140140
}
141141

142+
Expr::Member(MemberExpr {
143+
obj,
144+
prop: MemberProp::Ident(prop),
145+
span,
146+
..
147+
}) if matches!(obj.as_ref(), Expr::Ident(ident) if &*ident.sym == "Number") => {
148+
match &*prop.sym {
149+
"MIN_VALUE" => {
150+
report_change!("evaluate: `Number.MIN_VALUE` -> `5e-324`");
151+
self.changed = true;
152+
*e = Lit::Num(Number {
153+
span: *span,
154+
value: 5e-324,
155+
raw: None,
156+
})
157+
.into();
158+
}
159+
"NaN" => {
160+
report_change!("evaluate: `Number.NaN` -> `NaN`");
161+
self.changed = true;
162+
*e = Ident::new(
163+
atom!("NaN"),
164+
*span,
165+
SyntaxContext::empty().apply_mark(self.marks.unresolved_mark),
166+
)
167+
.into();
168+
}
169+
"POSITIVE_INFINITY" => {
170+
report_change!("evaluate: `Number.POSITIVE_INFINITY` -> `Infinity`");
171+
self.changed = true;
172+
*e = Ident::new(
173+
atom!("Infinity"),
174+
*span,
175+
SyntaxContext::empty().apply_mark(self.marks.unresolved_mark),
176+
)
177+
.into();
178+
}
179+
"NEGATIVE_INFINITY" => {
180+
report_change!("evaluate: `Number.NEGATIVE_INFINITY` -> `-Infinity`");
181+
self.changed = true;
182+
*e = UnaryExpr {
183+
span: *span,
184+
op: op!(unary, "-"),
185+
arg: Ident::new(
186+
atom!("Infinity"),
187+
*span,
188+
SyntaxContext::empty().apply_mark(self.marks.unresolved_mark),
189+
)
190+
.into(),
191+
}
192+
.into();
193+
}
194+
_ => {}
195+
}
196+
}
197+
142198
_ => {}
143199
}
144200
}

crates/swc_ecma_minifier/tests/benches-full/echarts.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4044,7 +4044,7 @@
40444044
}, 0), remainder = map(votesPerQuota, function(votes, idx) {
40454045
return votes - seats[idx];
40464046
}); currentSum < targetSeats;){
4047-
for(var max = Number.NEGATIVE_INFINITY, maxId = null, i = 0, len = remainder.length; i < len; ++i)remainder[i] > max && (max = remainder[i], maxId = i);
4047+
for(var max = -1 / 0, maxId = null, i = 0, len = remainder.length; i < len; ++i)remainder[i] > max && (max = remainder[i], maxId = i);
40484048
// Add a vote to max remainder.
40494049
++seats[maxId], remainder[maxId] = 0, ++currentSum;
40504050
}
@@ -21793,7 +21793,7 @@
2179321793
}, BarView.prototype._isOrderChangedWithinSameData = function(data, orderMapping, baseAxis) {
2179421794
for(var scale = baseAxis.scale, ordinalDataDim = data.mapDimension(baseAxis.dim), lastValue = Number.MAX_VALUE, tickNum = 0, len = scale.getOrdinalMeta().categories.length; tickNum < len; ++tickNum){
2179521795
var rawIdx = data.rawIndexOf(ordinalDataDim, scale.getRawOrdinalNumber(tickNum)), value = rawIdx < 0 // If some tick have no bar, the tick will be treated as min.
21796-
? Number.MIN_VALUE // PENDING: if dataZoom on baseAxis exits, is it a performance issue?
21796+
? 5e-324 // PENDING: if dataZoom on baseAxis exits, is it a performance issue?
2179721797
: orderMapping(data.indexOfRawIndex(rawIdx));
2179821798
if (value > lastValue) return !0;
2179921799
lastValue = value;

crates/swc_ecma_minifier/tests/benches-full/victory.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16990,7 +16990,7 @@
1699016990
case "number":
1699116991
// The standard `isNaN` is fine in this case since we already know the
1699216992
// type is number.
16993-
return !isNaN(obj) && obj !== Number.POSITIVE_INFINITY && obj !== Number.NEGATIVE_INFINITY;
16993+
return !isNaN(obj) && obj !== 1 / 0 && obj !== -1 / 0;
1699416994
case "string":
1699516995
case "function":
1699616996
// d3 might not *actually* be able to interpolate the string, but it

crates/swc_ecma_minifier/tests/fixture/issues/firebase-firestore/1/output.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4977,7 +4977,7 @@
49774977
return js.resolve(this.In.slice());
49784978
}
49794979
getAllMutationBatchesAffectingDocumentKey(t, e) {
4980-
const n = new Pr(e, 0), s = new Pr(e, Number.POSITIVE_INFINITY), i = [];
4980+
const n = new Pr(e, 0), s = new Pr(e, 1 / 0), i = [];
49814981
return this.ds.forEachInRange([
49824982
n,
49834983
s
@@ -4989,7 +4989,7 @@
49894989
getAllMutationBatchesAffectingDocumentKeys(t, e) {
49904990
let n = new gn(et);
49914991
return e.forEach((t)=>{
4992-
const e = new Pr(t, 0), s = new Pr(t, Number.POSITIVE_INFINITY);
4992+
const e = new Pr(t, 0), s = new Pr(t, 1 / 0);
49934993
this.ds.forEachInRange([
49944994
e,
49954995
s

crates/swc_ecma_minifier/tests/libs-size.snapshot.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22
| --- | --- | --- | --- |
33
| antd.js | 6.38 MiB | 2.06 MiB | 445.41 KiB |
44
| d3.js | 542.74 KiB | 261.44 KiB | 85.33 KiB |
5-
| echarts.js | 3.41 MiB | 977.53 KiB | 314.18 KiB |
5+
| echarts.js | 3.41 MiB | 977.50 KiB | 314.17 KiB |
66
| jquery.js | 280.89 KiB | 87.80 KiB | 30.21 KiB |
77
| lodash.js | 531.35 KiB | 68.91 KiB | 24.60 KiB |
88
| moment.js | 169.83 KiB | 57.39 KiB | 18.26 KiB |
99
| react.js | 70.45 KiB | 22.44 KiB | 8.04 KiB |
1010
| terser.js | 1.08 MiB | 446.68 KiB | 120.49 KiB |
1111
| three.js | 1.19 MiB | 630.83 KiB | 154.80 KiB |
12-
| typescript.js | 10.45 MiB | 3.17 MiB | 840.66 KiB |
13-
| victory.js | 2.30 MiB | 694.16 KiB | 154.24 KiB |
12+
| typescript.js | 10.45 MiB | 3.17 MiB | 840.64 KiB |
13+
| victory.js | 2.30 MiB | 694.12 KiB | 154.21 KiB |
1414
| vue.js | 334.13 KiB | 113.72 KiB | 41.82 KiB |
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
| File | Original Size | Compressed Size | Gzipped Size |
22
| --- | --- | --- | --- |
3-
| angular-1.2.5.js | 757.44 KiB | 101.92 KiB | 37.18 KiB |
3+
| angular-1.2.5.js | 757.44 KiB | 101.91 KiB | 37.18 KiB |
44
| backbone-1.1.0.js | 59.77 KiB | 18.33 KiB | 6.29 KiB |
55
| jquery-1.9.1.js | 309.61 KiB | 90.76 KiB | 32.09 KiB |
66
| jquery.mobile-1.4.2.js | 534.38 KiB | 191.29 KiB | 52.61 KiB |
77
| mootools-1.4.5.js | 181.36 KiB | 88.54 KiB | 27.48 KiB |
88
| react-17.0.1.js | 82.58 KiB | 22.44 KiB | 8.04 KiB |
9-
| react-dom-17.0.2.js | 959.53 KiB | 236.53 KiB | 72.88 KiB |
9+
| react-dom-17.0.2.js | 959.53 KiB | 236.50 KiB | 72.87 KiB |
1010
| underscore-1.5.2.js | 43.49 KiB | 13.85 KiB | 4.69 KiB |
1111
| yui-3.12.0.js | 321.32 KiB | 86.04 KiB | 24.95 KiB |

crates/swc_ecma_minifier/tests/projects/output/angular-1.2.5.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10391,7 +10391,7 @@
1039110391
"$element",
1039210392
"$parse",
1039310393
function($scope, $exceptionHandler, $attr, $element, $parse) {
10394-
this.$viewValue = Number.NaN, this.$modelValue = Number.NaN, this.$parsers = [], this.$formatters = [], this.$viewChangeListeners = [], this.$pristine = !0, this.$dirty = !1, this.$valid = !0, this.$invalid = !1, this.$name = $attr.name;
10394+
this.$viewValue = NaN, this.$modelValue = NaN, this.$parsers = [], this.$formatters = [], this.$viewChangeListeners = [], this.$pristine = !0, this.$dirty = !1, this.$valid = !0, this.$invalid = !1, this.$name = $attr.name;
1039510395
var ngModelGet = $parse($attr.ngModel), ngModelSet = ngModelGet.assign;
1039610396
if (!ngModelSet) throw minErr("ngModel")("nonassign", "Expression '{0}' is non-assignable. Element: {1}", $attr.ngModel, startingTag($element));
1039710397
/**

crates/swc_ecma_minifier/tests/projects/output/react-dom-17.0.2.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11132,7 +11132,7 @@
1113211132
// Learn more about this here:
1113311133
// https://github.com/facebook/react/issues/14365
1113411134
// https://bugs.chromium.org/p/v8/issues/detail?id=8538
11135-
this.actualDuration = Number.NaN, this.actualStartTime = Number.NaN, this.selfBaseDuration = Number.NaN, this.treeBaseDuration = Number.NaN, // This won't trigger the performance cliff mentioned above,
11135+
this.actualDuration = NaN, this.actualStartTime = NaN, this.selfBaseDuration = NaN, this.treeBaseDuration = NaN, // This won't trigger the performance cliff mentioned above,
1113611136
// and it simplifies other profiler code (including DevTools).
1113711137
this.actualDuration = 0, this.actualStartTime = -1, this.selfBaseDuration = 0, this.treeBaseDuration = 0, // This isn't directly used but is handy for debugging internals:
1113811138
this._debugID = debugCounter++, this._debugSource = null, this._debugOwner = null, this._debugNeedsRemount = !1, this._debugHookTypes = null, hasBadMapPolyfill || "function" != typeof Object.preventExtensions || Object.preventExtensions(this);

0 commit comments

Comments
 (0)