Skip to content

Commit 04016e9

Browse files
authoredSep 20, 2024··
fix(es/minifier): Check variable type while optimizing += (#9575)
**Related issue:** - Closes #9504
1 parent 6d15d9c commit 04016e9

File tree

21 files changed

+97
-32
lines changed

21 files changed

+97
-32
lines changed
 

‎crates/swc/tests/fixture/issues-6xxx/6407/output/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ export default class Demo {
33
let ranges = [], range = [], retrString = A.encode(value), bitField = '';
44
return value.forEach((curValue, i)=>{
55
bitField += B.encode(curValue), range.push(i), ranges.push(range);
6-
}), retrString += '.' + C.encode(ranges);
6+
}), retrString += '.', retrString += C.encode(ranges);
77
}
88
}
99
console.log(Deno.encode());
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
//// [compoundAdditionAssignmentLHSCanBeAssigned.ts]
2-
var E, E1;
3-
(E1 = E || (E = {}))[E1.a = 0] = "a", E1[E1.b = 1] = "b";
2+
var E, a, b, x1, x2, x3, x4, x6, E1;
3+
(E1 = E || (E = {}))[E1.a = 0] = "a", E1[E1.b = 1] = "b", x1 += a, x1 += b, x1 += !0, x1 += 0, x1 += '', x1 += 0, x1 += {}, x1 += null, x1 += void 0, x2 += a, x2 += b, x2 += !0, x2 += 0, x2 += '', x2 += 0, x2 += {}, x2 += null, x2 += void 0, x3 += a, x3 += 0, x3 += null, x3 += void 0, x4 += a, x4 += 0, x4 += null, x4 += void 0, x6 += a, x6 += '';
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
//// [compoundAdditionAssignmentWithInvalidOperands.ts]
2-
var E, E1;
3-
(E1 = E || (E = {}))[E1.a = 0] = "a", E1[E1.b = 1] = "b";
2+
var E, a, x1, x2, x3, x4, x5, E1;
3+
(E1 = E || (E = {}))[E1.a = 0] = "a", E1[E1.b = 1] = "b", x1 += a, x1 += !0, x1 += 0, x1 += {}, x1 += null, x1 += void 0, x2 += a, x2 += !0, x2 += 0, x2 += {}, x2 += null, x2 += void 0, x3 += a, x3 += !0, x3 += 0, x3 += {}, x3 += null, x3 += void 0, x4 += a, x4 += !0, x4 += {}, x5 += a, x5 += !0;
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
//// [symbolType12.ts]
22
var s = Symbol.for("assign"), str = "";
3-
s *= 0 * s, s /= s, s /= 0, s %= s, s %= 0, s += s + 0 + "", str += s, s -= s, s -= 0, s <<= s, s <<= 0, s >>= s, s >>= 0, s >>>= s, s >>>= 0, s &= s, s &= 0, s ^= s, s ^= 0, s |= s, s |= 0, str += s || str;
3+
s *= 0 * s, s /= s, s /= 0, s %= s, s %= 0, s += s, s += 0, s += "", str += s, s -= s, s -= 0, s <<= s, s <<= 0, s >>= s, s >>= 0, s >>>= s, s >>>= 0, s &= s, s &= 0, s ^= s, s ^= 0, s |= s, s |= 0, str += s || str;

‎crates/swc_ecma_minifier/src/compress/optimize/sequences.rs

+15-3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use swc_ecma_usage_analyzer::{
88
};
99
use swc_ecma_utils::{
1010
contains_arguments, contains_this_expr, prepend_stmts, ExprExt, IdentUsageFinder, StmtLike,
11+
Type, Value,
1112
};
1213
use swc_ecma_visit::{noop_visit_type, Visit, VisitWith};
1314
#[cfg(feature = "debug")]
@@ -2379,6 +2380,8 @@ impl Optimizer<'_> {
23792380
Mergable::Drop => return Ok(false),
23802381
};
23812382

2383+
let a_type = a_right.as_deref().map(|a| a.get_type());
2384+
23822385
if let Some(a_right) = a_right {
23832386
if a_right.is_this() || a_right.is_ident_ref_to("arguments") {
23842387
return Ok(false);
@@ -2482,8 +2485,13 @@ impl Optimizer<'_> {
24822485
_ => None,
24832486
};
24842487

2488+
let Some(a_type) = a_type else {
2489+
return Ok(false);
2490+
};
2491+
let b_type = b.right.get_type();
2492+
24852493
if let Some(a_op) = a_op {
2486-
if can_drop_op_for(a_op, b.op) {
2494+
if can_drop_op_for(a_op, b.op, a_type, b_type) {
24872495
if b_left.to_id() == left_id.to_id() {
24882496
if let Some(bin_op) = b.op.to_update() {
24892497
report_change!(
@@ -2715,13 +2723,17 @@ pub(crate) fn is_trivial_lit(e: &Expr) -> bool {
27152723
}
27162724

27172725
/// This assumes `a.left.to_id() == b.left.to_id()`
2718-
fn can_drop_op_for(a: AssignOp, b: AssignOp) -> bool {
2726+
fn can_drop_op_for(a: AssignOp, b: AssignOp, a_type: Value<Type>, b_type: Value<Type>) -> bool {
27192727
if a == op!("=") {
27202728
return true;
27212729
}
27222730

27232731
if a == b {
2724-
return matches!(a, op!("+=") | op!("*="));
2732+
if a == op!("+=") && a_type.is_known() && a_type == b_type {
2733+
return true;
2734+
}
2735+
2736+
return matches!(a, op!("*="));
27252737
}
27262738

27272739
false

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -5716,7 +5716,7 @@
57165716
var width = data[i++], height = data[i++];
57175717
if (x1 = x0 + width, y1 = y0 + height, isStroke) {
57185718
if (containStroke(x0, y0, x1, y0, lineWidth, x, y) || containStroke(x1, y0, x1, y1, lineWidth, x, y) || containStroke(x1, y1, x0, y1, lineWidth, x, y) || containStroke(x0, y1, x0, y0, lineWidth, x, y)) return !0;
5719-
} else w += windingLine(x1, y0, x1, y1, x, y) + windingLine(x0, y1, x0, y0, x, y);
5719+
} else w += windingLine(x1, y0, x1, y1, x, y), w += windingLine(x0, y1, x0, y0, x, y);
57205720
break;
57215721
case CMD$1.Z:
57225722
if (isStroke) {

‎crates/swc_ecma_minifier/tests/benches-full/moment.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -913,8 +913,9 @@
913913
getParsingFlags(config).invalidFormat = !0, config._d = new Date(NaN);
914914
return;
915915
}
916-
for(i = 0; i < config._f.length; i++)currentScore = 0, validFormatFound = !1, tempConfig = copyConfig({}, config), null != config._useUTC && (tempConfig._useUTC = config._useUTC), tempConfig._f = config._f[i], configFromStringAndFormat(tempConfig), isValid(tempConfig) && (validFormatFound = !0), //or tokens
917-
currentScore += getParsingFlags(tempConfig).charsLeftOver + 10 * getParsingFlags(tempConfig).unusedTokens.length, getParsingFlags(tempConfig).score = currentScore, bestFormatIsValid ? currentScore < scoreToBeat && (scoreToBeat = currentScore, bestMoment = tempConfig) : (null == scoreToBeat || currentScore < scoreToBeat || validFormatFound) && (scoreToBeat = currentScore, bestMoment = tempConfig, validFormatFound && (bestFormatIsValid = !0));
916+
for(i = 0; i < config._f.length; i++)currentScore = 0, validFormatFound = !1, tempConfig = copyConfig({}, config), null != config._useUTC && (tempConfig._useUTC = config._useUTC), tempConfig._f = config._f[i], configFromStringAndFormat(tempConfig), isValid(tempConfig) && (validFormatFound = !0), // if there is any input that was not parsed add a penalty for that format
917+
currentScore += getParsingFlags(tempConfig).charsLeftOver, //or tokens
918+
currentScore += 10 * getParsingFlags(tempConfig).unusedTokens.length, getParsingFlags(tempConfig).score = currentScore, bestFormatIsValid ? currentScore < scoreToBeat && (scoreToBeat = currentScore, bestMoment = tempConfig) : (null == scoreToBeat || currentScore < scoreToBeat || validFormatFound) && (scoreToBeat = currentScore, bestMoment = tempConfig, validFormatFound && (bestFormatIsValid = !0));
918919
extend(config, bestMoment || tempConfig);
919920
}(config) : format ? configFromStringAndFormat(config) : isUndefined(input = config._i) ? config._d = new Date(hooks.now()) : isDate(input) ? config._d = new Date(input.valueOf()) : 'string' == typeof input ? // date from 1) ASP.NET, 2) ISO, 3) RFC 2822 formats, or 4) optional fallback if parsing isn't strict
920921
function(config) {

‎crates/swc_ecma_minifier/tests/fixture/issues/6407/1/output.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export default class Demo {
66
bitField += B.encode(curValue);
77
range.push(i);
88
ranges.push(range);
9-
}), retrString += '.' + C.encode(ranges);
9+
}), retrString += '.', retrString += C.encode(ranges);
1010
}
1111
}
1212
console.log(Deno.encode());
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
export function panUpdate(e) {
2+
if (!moveDirectionExpected) {
3+
panStart = false;
4+
return;
5+
}
6+
caf(rafIndex);
7+
if (panStart) { rafIndex = raf(function () { panUpdate(e); }); }
8+
9+
if (moveDirectionExpected === '?') { moveDirectionExpected = getMoveDirectionExpected(); }
10+
if (moveDirectionExpected) {
11+
if (!preventScroll && isTouchEvent(e)) { preventScroll = true; }
12+
13+
try {
14+
if (e.type) { events.emit(isTouchEvent(e) ? 'touchMove' : 'dragMove', info(e)); }
15+
} catch (err) { }
16+
17+
var x = translateInit,
18+
dist = getDist(lastPosition, initPosition);
19+
if (!horizontal || fixedWidth || autoWidth) {
20+
// Relevant lines below
21+
x += dist;
22+
x += 'px';
23+
} else {
24+
var percentageX = TRANSFORM ? dist * items * 100 / ((viewport + gutter) * slideCountNew) : dist * 100 / (viewport + gutter);
25+
x += percentageX;
26+
x += '%';
27+
}
28+
29+
container.style[transformAttr] = transformPrefix + x + transformPostfix;
30+
}
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
export function panUpdate(e) {
2+
if (!moveDirectionExpected) {
3+
panStart = !1;
4+
return;
5+
}
6+
if (caf(rafIndex), panStart && (rafIndex = raf(function() {
7+
panUpdate(e);
8+
})), '?' === moveDirectionExpected && (moveDirectionExpected = getMoveDirectionExpected()), moveDirectionExpected) {
9+
!preventScroll && isTouchEvent(e) && (preventScroll = !0);
10+
try {
11+
e.type && events.emit(isTouchEvent(e) ? 'touchMove' : 'dragMove', info(e));
12+
} catch (err) {}
13+
var x = translateInit, dist = getDist(lastPosition, initPosition);
14+
!horizontal || fixedWidth || autoWidth ? (// Relevant lines below
15+
x += dist, x += 'px') : (x += TRANSFORM ? dist * items * 100 / ((viewport + gutter) * slideCountNew) : 100 * dist / (viewport + gutter), x += '%'), container.style[transformAttr] = transformPrefix + x + transformPostfix;
16+
}
17+
}

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -1336,7 +1336,7 @@
13361336
d = !0;
13371337
}
13381338
d || (b1 = "", xa(c, function(c, d) {
1339-
b1 += d + ":" + c + "\r\n";
1339+
b1 += d, b1 += ":", b1 += c, b1 += "\r\n";
13401340
}), c = b1, "string" == typeof a ? null != c && encodeURIComponent(String(c)) : R(a, b, c));
13411341
}
13421342
function Hd(a, b, c) {

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -1586,7 +1586,7 @@
15861586
function Wt(t) {
15871587
if (null === t.A) {
15881588
let t1 = t.path.canonicalString();
1589-
null !== t.collectionGroup && (t1 += "|cg:" + t.collectionGroup), t1 += "|f:" + t.filters.map((t)=>t.field.canonicalString() + t.op.toString() + xt(t.value)).join(",") + "|ob:" + t.orderBy.map((t)=>t.field.canonicalString() + t.dir).join(","), At(t.limit) || (t1 += "|l:" + t.limit), t.startAt && (t1 += "|lb:" + ce(t.startAt)), t.endAt && (t1 += "|ub:" + ce(t.endAt)), t.A = t1;
1589+
null !== t.collectionGroup && (t1 += "|cg:" + t.collectionGroup), t1 += "|f:", t1 += t.filters.map((t)=>t.field.canonicalString() + t.op.toString() + xt(t.value)).join(","), t1 += "|ob:", t1 += t.orderBy.map((t)=>t.field.canonicalString() + t.dir).join(","), At(t.limit) || (t1 += "|l:", t1 += t.limit), t.startAt && (t1 += "|lb:", t1 += ce(t.startAt)), t.endAt && (t1 += "|ub:", t1 += ce(t.endAt)), t.A = t1;
15901590
}
15911591
return t.A;
15921592
}

‎crates/swc_ecma_minifier/tests/fixture/issues/moment/1/output.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -913,8 +913,9 @@ function(global, factory) {
913913
getParsingFlags(config).invalidFormat = !0, config._d = new Date(NaN);
914914
return;
915915
}
916-
for(i = 0; i < config._f.length; i++)currentScore = 0, validFormatFound = !1, tempConfig = copyConfig({}, config), null != config._useUTC && (tempConfig._useUTC = config._useUTC), tempConfig._f = config._f[i], configFromStringAndFormat(tempConfig), isValid(tempConfig) && (validFormatFound = !0), //or tokens
917-
currentScore += getParsingFlags(tempConfig).charsLeftOver + 10 * getParsingFlags(tempConfig).unusedTokens.length, getParsingFlags(tempConfig).score = currentScore, bestFormatIsValid ? currentScore < scoreToBeat && (scoreToBeat = currentScore, bestMoment = tempConfig) : (null == scoreToBeat || currentScore < scoreToBeat || validFormatFound) && (scoreToBeat = currentScore, bestMoment = tempConfig, validFormatFound && (bestFormatIsValid = !0));
916+
for(i = 0; i < config._f.length; i++)currentScore = 0, validFormatFound = !1, tempConfig = copyConfig({}, config), null != config._useUTC && (tempConfig._useUTC = config._useUTC), tempConfig._f = config._f[i], configFromStringAndFormat(tempConfig), isValid(tempConfig) && (validFormatFound = !0), // if there is any input that was not parsed add a penalty for that format
917+
currentScore += getParsingFlags(tempConfig).charsLeftOver, //or tokens
918+
currentScore += 10 * getParsingFlags(tempConfig).unusedTokens.length, getParsingFlags(tempConfig).score = currentScore, bestFormatIsValid ? currentScore < scoreToBeat && (scoreToBeat = currentScore, bestMoment = tempConfig) : (null == scoreToBeat || currentScore < scoreToBeat || validFormatFound) && (scoreToBeat = currentScore, bestMoment = tempConfig, validFormatFound && (bestFormatIsValid = !0));
918919
extend(config, bestMoment || tempConfig);
919920
}(config) : format ? configFromStringAndFormat(config) : isUndefined(input = config._i) ? config._d = new Date(hooks.now()) : isDate(input) ? config._d = new Date(input.valueOf()) : "string" == typeof input ? // date from 1) ASP.NET, 2) ISO, 3) RFC 2822 formats, or 4) optional fallback if parsing isn't strict
920921
function(config) {

‎crates/swc_ecma_minifier/tests/fixture/next/33265/static/chunks/d6e1aeb5-38a8d7ae57119c23/output.js

+8-5
Original file line numberDiff line numberDiff line change
@@ -19377,7 +19377,8 @@
1937719377
dts: buffer[0].dts
1937819378
}; i < tagSize;)tag.data.set(buffer[0].data.subarray(0, tagSize - i), i), i += buffer[0].data.byteLength, bufferSize -= buffer[0].data.byteLength, buffer.shift();
1937919379
// find the start of the first frame and the end of the tag
19380-
frameStart = 10, 0x40 & tag.data[5] && (frameStart += 4 + parseSyncSafeInteger$1(tag.data.subarray(10, 14)), tagSize -= parseSyncSafeInteger$1(tag.data.subarray(16, 20)));
19380+
frameStart = 10, 0x40 & tag.data[5] && (// advance the frame start past the extended header
19381+
frameStart += 4, frameStart += parseSyncSafeInteger$1(tag.data.subarray(10, 14)), tagSize -= parseSyncSafeInteger$1(tag.data.subarray(16, 20)));
1938119382
// http://id3.org/id3v2.3.0#ID3v2_frame_overview
1938219383
do {
1938319384
if (// determine the number of bytes in this frame
@@ -19395,7 +19396,7 @@
1939519396
var d = frame.data, size = (0x01 & d[3]) << 30 | d[4] << 22 | d[5] << 14 | d[6] << 6 | d[7] >>> 2;
1939619397
size *= 4, size += 0x03 & d[7], frame.timeStamp = size, void 0 === tag.pts && void 0 === tag.dts && (tag.pts = frame.timeStamp, tag.dts = frame.timeStamp), this.trigger("timestamp", frame);
1939719398
}
19398-
tag.frames.push(frame), frameStart += 10 + frameSize;
19399+
tag.frames.push(frame), frameStart += 10, frameStart += frameSize;
1939919400
}while (frameStart < tagSize)
1940019401
this.trigger("data", tag);
1940119402
} // collect the entire frame so it can be parsed
@@ -20125,7 +20126,8 @@
2012520126
},
2012620127
parseAacTimestamp: function(packet) {
2012720128
var frameStart, frameSize, frame; // find the start of the first frame and the end of the tag
20128-
frameStart = 10, 0x40 & packet[5] && (frameStart += 4 + parseSyncSafeInteger(packet.subarray(10, 14)));
20129+
frameStart = 10, 0x40 & packet[5] && (// advance the frame start past the extended header
20130+
frameStart += 4, frameStart += parseSyncSafeInteger(packet.subarray(10, 14)));
2012920131
// http://id3.org/id3v2.3.0#ID3v2_frame_overview
2013020132
do {
2013120133
if (// determine the number of bytes in this frame
@@ -20140,7 +20142,7 @@
2014020142
break;
2014120143
}
2014220144
}
20143-
frameStart += 10 + frameSize; // advance past the frame body
20145+
frameStart += 10, frameStart += frameSize;
2014420146
}while (frameStart < packet.byteLength)
2014520147
return null;
2014620148
}
@@ -20567,7 +20569,8 @@
2056720569
var transmuxer_Transmuxer = _Transmuxer, bin_toUnsigned = function(value) {
2056820570
return value >>> 0;
2056920571
}, parseType_1 = function(buffer) {
20570-
return "" + (String.fromCharCode(buffer[0]) + String.fromCharCode(buffer[1]) + String.fromCharCode(buffer[2]) + String.fromCharCode(buffer[3]));
20572+
var result = "";
20573+
return result += String.fromCharCode(buffer[0]), result += String.fromCharCode(buffer[1]), result += String.fromCharCode(buffer[2]), result += String.fromCharCode(buffer[3]);
2057120574
}, findBox_1 = function findBox(data, path) {
2057220575
var i, size, type, end, subresults, results = [];
2057320576
if (!path.length) // short-circuit the search for empty paths

‎crates/swc_ecma_minifier/tests/fixture/next/react-pdf-renderer/output.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -16540,7 +16540,7 @@
1654016540
i += "".concat(t[0], " and ").concat(t[1], " arguments");
1654116541
break;
1654216542
default:
16543-
i += t.slice(0, o - 1).join(", ") + ", and ".concat(t[o - 1], " arguments");
16543+
i += t.slice(0, o - 1).join(", "), i += ", and ".concat(t[o - 1], " arguments");
1654416544
}
1654516545
return "".concat(i, " must be specified");
1654616546
}, TypeError), e.exports.codes = l;

‎crates/swc_ecma_minifier/tests/fixture/next/syncfusion/933-e9f9a6bf671b96fc/output.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -23267,7 +23267,7 @@
2326723267
}, Toolbar.prototype.itemWidthCal = function(items) {
2326823268
var style, _this = this, width = 0;
2326923269
return [].slice.call((0, ej2_base /* selectAll */ .td)('.' + CLS_ITEM, items)).forEach(function(el) {
23270-
(0, ej2_base /* isVisible */ .pn)(el) && (style = window.getComputedStyle(el), width += (_this.isVertical ? el.offsetHeight : el.offsetWidth) + parseFloat(_this.isVertical ? style.marginTop : style.marginRight) + parseFloat(_this.isVertical ? style.marginBottom : style.marginLeft));
23270+
(0, ej2_base /* isVisible */ .pn)(el) && (style = window.getComputedStyle(el), width += _this.isVertical ? el.offsetHeight : el.offsetWidth, width += parseFloat(_this.isVertical ? style.marginTop : style.marginRight), width += parseFloat(_this.isVertical ? style.marginBottom : style.marginLeft));
2327123271
}), width;
2327223272
}, Toolbar.prototype.getScrollCntEle = function(innerItem) {
2327323273
var trgClass = this.isVertical ? '.e-vscroll-content' : '.e-hscroll-content';

0 commit comments

Comments
 (0)
Please sign in to comment.