Skip to content

Commit

Permalink
fix(es/minifier): Make sequential inliner respect resolution order (#…
Browse files Browse the repository at this point in the history
…6509)

**Related issue:**

 - Closes #6491.
  • Loading branch information
kdy1 committed Nov 29, 2022
1 parent c14acc1 commit 27ae59e
Show file tree
Hide file tree
Showing 21 changed files with 242 additions and 35 deletions.
5 changes: 3 additions & 2 deletions crates/swc/tests/tsc-references/enumBasics.2.minified.js
@@ -1,8 +1,9 @@
//// [enumBasics.ts]
var E1, E2, E3, E4, E5, E6, E7, E8, E9;
!function(E1) {
E1[E1.A = 0] = "A", E1[E1.B = 1] = "B", E1[E1.C = 2] = "C";
}(E1 || (E1 = {})), E1.A, E1[E1.A], function(E2) {
}(E1 || (E1 = {})), E1.A;
var E1, E2, E3, E4, E5, E6, E7, E8, E9, e = E1;
E1[e.A], function(E2) {
E2[E2.A = 1] = "A", E2[E2.B = 2] = "B", E2[E2.C = 3] = "C";
}(E2 || (E2 = {})), function(E3) {
E3[E3.X = 3] = "X", E3[E3.Y = 7] = "Y", E3[E3.Z = NaN] = "Z";
Expand Down
15 changes: 15 additions & 0 deletions crates/swc_ecma_minifier/src/compress/optimize/sequences.rs
Expand Up @@ -1597,6 +1597,21 @@ where
return Ok(false);
}

// We can't merge into `[]` in some cases because `obj` is **resolved** before
// evaluating `[]`.
//
// See https://github.com/swc-project/swc/pull/6509

let obj_ids = idents_used_by_ignoring_nested(obj);
let a_ids = match a {
Mergable::Var(a) => idents_used_by_ignoring_nested(&a.init),
Mergable::Expr(a) => idents_used_by_ignoring_nested(&**a),
Mergable::FnDecl(a) => idents_used_by_ignoring_nested(&**a),
};
if obj_ids.intersection(&a_ids).next().is_some() {
return Ok(false);
}

trace_op!("seq: Try prop of member (computed)");
return self.merge_sequential_expr(a, &mut c.expr);
}
Expand Down
6 changes: 3 additions & 3 deletions crates/swc_ecma_minifier/tests/benches-full/echarts.js
Expand Up @@ -15339,7 +15339,7 @@
}
if (isArray(template)) {
var levelId = null == tick.level ? 0 : tick.level >= 0 ? tick.level : template.length + tick.level;
template = template[levelId = Math.min(levelId, template.length - 1)];
levelId = Math.min(levelId, template.length - 1), template = template[levelId];
}
}
return format(new Date(tick.value), template, isUTC, lang);
Expand Down Expand Up @@ -23629,7 +23629,7 @@
function getSpecifiedVisual(value) {
var thisOption = this.option, pieceList = thisOption.pieceList;
if (thisOption.hasSpecialVisual) {
var piece = pieceList[VisualMapping.findPieceIndex(value, pieceList)];
var pieceIndex = VisualMapping.findPieceIndex(value, pieceList), piece = pieceList[pieceIndex];
if (piece && piece.visual) return piece.visual[this.type];
}
}
Expand Down Expand Up @@ -27805,7 +27805,7 @@
var result, axisList;
each((result = [], axisList = [], ecModel.eachSeriesByType('boxplot', function(seriesModel) {
var baseAxis = seriesModel.getBaseAxis(), idx = indexOf(axisList, baseAxis);
idx < 0 && (axisList[idx = axisList.length] = baseAxis, result[idx] = {
idx < 0 && (idx = axisList.length, axisList[idx] = baseAxis, result[idx] = {
axis: baseAxis,
seriesModels: []
}), result[idx].seriesModels.push(seriesModel);
Expand Down
2 changes: 1 addition & 1 deletion crates/swc_ecma_minifier/tests/benches-full/jquery.js
Expand Up @@ -487,7 +487,7 @@
"",
argument
], Expr.setFilters.hasOwnProperty(pseudo.toLowerCase()) ? markFunction(function(seed, matches) {
for(var idx, matched = fn(seed, argument), i = matched.length; i--;)seed[idx = indexOf(seed, matched[i])] = !(matches[idx] = matched[i]);
for(var idx, matched = fn(seed, argument), i = matched.length; i--;)idx = indexOf(seed, matched[i]), seed[idx] = !(matches[idx] = matched[i]);
}) : function(elem) {
return fn(elem, 0, args);
}) : fn;
Expand Down
7 changes: 5 additions & 2 deletions crates/swc_ecma_minifier/tests/benches-full/three.js
Expand Up @@ -5561,7 +5561,10 @@
return void 0 === program && (program = new WebGLProgram(renderer, cacheKey, parameters, bindingStates), programs.push(program)), program;
},
releaseProgram: function(program) {
0 == --program.usedTimes && (programs[programs.indexOf(program)] = programs[programs.length - 1], programs.pop(), program.destroy());
if (0 == --program.usedTimes) {
var i = programs.indexOf(program);
programs[i] = programs[programs.length - 1], programs.pop(), program.destroy();
}
},
programs: programs
};
Expand Down Expand Up @@ -10006,7 +10009,7 @@
iPrev = i1, tPrev = 2 * t0 - t1;
break;
case 2402:
tPrev = t0 + pp[iPrev = pp.length - 2] - pp[iPrev + 1];
iPrev = pp.length - 2, tPrev = t0 + pp[iPrev] - pp[iPrev + 1];
break;
default:
iPrev = i1, tPrev = t1;
Expand Down
2 changes: 1 addition & 1 deletion crates/swc_ecma_minifier/tests/benches-full/vue.js
Expand Up @@ -761,7 +761,7 @@
createTextVNode(children)
] : Array.isArray(children) ? function normalizeArrayChildren(children, nestedIndex) {
var i, c, lastIndex, last, res = [];
for(i = 0; i < children.length; i++)!isUndef(c = children[i]) && 'boolean' != typeof c && (last = res[lastIndex = res.length - 1], Array.isArray(c) ? c.length > 0 && (isTextNode((c = normalizeArrayChildren(c, (nestedIndex || '') + "_" + i))[0]) && isTextNode(last) && (res[lastIndex] = createTextVNode(last.text + c[0].text), c.shift()), res.push.apply(res, c)) : isPrimitive(c) ? isTextNode(last) ? res[lastIndex] = createTextVNode(last.text + c) : '' !== c && res.push(createTextVNode(c)) : isTextNode(c) && isTextNode(last) ? res[lastIndex] = createTextVNode(last.text + c.text) : (isTrue(children._isVList) && isDef(c.tag) && isUndef(c.key) && isDef(nestedIndex) && (c.key = "__vlist" + nestedIndex + "_" + i + "__"), res.push(c)));
for(i = 0; i < children.length; i++)!isUndef(c = children[i]) && 'boolean' != typeof c && (lastIndex = res.length - 1, last = res[lastIndex], Array.isArray(c) ? c.length > 0 && (isTextNode((c = normalizeArrayChildren(c, (nestedIndex || '') + "_" + i))[0]) && isTextNode(last) && (res[lastIndex] = createTextVNode(last.text + c[0].text), c.shift()), res.push.apply(res, c)) : isPrimitive(c) ? isTextNode(last) ? res[lastIndex] = createTextVNode(last.text + c) : '' !== c && res.push(createTextVNode(c)) : isTextNode(c) && isTextNode(last) ? res[lastIndex] = createTextVNode(last.text + c.text) : (isTrue(children._isVList) && isDef(c.tag) && isUndef(c.key) && isDef(nestedIndex) && (c.key = "__vlist" + nestedIndex + "_" + i + "__"), res.push(c)));
return res;
}(children) : void 0;
}
Expand Down
@@ -0,0 +1,7 @@
{
"toplevel": true,
"defaults": false,
"inline": true,
"sequences": true,
"conditionals": true
}
113 changes: 113 additions & 0 deletions crates/swc_ecma_minifier/tests/fixture/issues/6509/input.js
@@ -0,0 +1,113 @@


function parseOffset(offset, popperOffsets, referenceOffsets, basePlacement) {
var offsets = [0, 0];

// Use height if placement is left or right and index is 0 otherwise use width
// in this way the first offset will use an axis and the second one
// will use the other one
var useHeight = ['right', 'left'].indexOf(basePlacement) !== -1;

// Split the offset string to obtain a list of values and operands
// The regex addresses values with the plus or minus sign in front (+10, -20, etc)
var fragments = offset.split(/(\+|\-)/).map(function (frag) {
return frag.trim();
});

// Detect if the offset string contains a pair of values or a single one
// they could be separated by comma or space
var divider = fragments.indexOf(find(fragments, function (frag) {
return frag.search(/,|\s/) !== -1;
}));

if (fragments[divider] && fragments[divider].indexOf(',') === -1) {
console.warn('Offsets separated by white space(s) are deprecated, use a comma (,) instead.');
}

// If divider is found, we divide the list of values and operands to divide
// them by ofset X and Y.
var splitRegex = /\s*,\s*|\s+/;
var ops = divider !== -1 ? [fragments.slice(0, divider).concat([fragments[divider].split(splitRegex)[0]]), [fragments[divider].split(splitRegex)[1]].concat(fragments.slice(divider + 1))] : [fragments];

// Convert the values with units to absolute pixels to allow our computations
ops = ops.map(function (op, index) {
// Most of the units rely on the orientation of the popper
var measurement = (index === 1 ? !useHeight : useHeight) ? 'height' : 'width';
var mergeWithPrevious = false;
return op
// This aggregates any `+` or `-` sign that aren't considered operators
// e.g.: 10 + +5 => [10, +, +5]
.reduce(function (a, b) {
if (a[a.length - 1] === '' && ['+', '-'].indexOf(b) !== -1) {
a[a.length - 1] = b;
mergeWithPrevious = true;
return a;
} else if (mergeWithPrevious) {
a[a.length - 1] += b;
mergeWithPrevious = false;
return a;
} else {
return a.concat(b);
}
}, [])
// Here we convert the string values into number values (in px)
.map(function (str) {
return toValue(str, measurement, popperOffsets, referenceOffsets);
});
});

// Loop trough the offsets arrays and execute the operations
ops.forEach(function (op, index) {
op.forEach(function (frag, index2) {
if (isNumeric(frag)) {
offsets[index] += frag * (op[index2 - 1] === '-' ? -1 : 1);
}
});
});
return offsets;
}

function offset(data, _ref) {
var offset = _ref.offset;
var placement = data.placement,
_data$offsets = data.offsets,
popper = _data$offsets.popper,
reference = _data$offsets.reference;

var basePlacement = placement.split('-')[0];

var offsets = void 0;
if (isNumeric(+offset)) {
offsets = [+offset, 0];
} else {
offsets = parseOffset(offset, popper, reference, basePlacement);
}

if (basePlacement === 'left') {
popper.top += offsets[0];
popper.left -= offsets[1];
} else if (basePlacement === 'right') {
popper.top += offsets[0];
popper.left += offsets[1];
} else if (basePlacement === 'top') {
popper.left += offsets[0];
popper.top -= offsets[1];
} else if (basePlacement === 'bottom') {
popper.left += offsets[0];
popper.top += offsets[1];
}

data.popper = popper;
return data;
}


export var modifiers = {
offset: {
order: 200,
enabled: true,
fn: offset,
offset: 0
},
};

63 changes: 63 additions & 0 deletions crates/swc_ecma_minifier/tests/fixture/issues/6509/output.js
@@ -0,0 +1,63 @@
export var modifiers = {
offset: {
order: 200,
enabled: true,
fn: function(data, _ref) {
var offset = _ref.offset;
var placement = data.placement, _data$offsets = data.offsets, popper = _data$offsets.popper, reference = _data$offsets.reference;
var basePlacement = placement.split('-')[0];
var offsets = void 0;
if (isNumeric(+offset)) offsets = [
+offset,
0
];
else {
var offsets1;
var useHeight;
var fragments;
var divider;
var splitRegex;
var ops;
offsets1 = [
0,
0
], useHeight = -1 !== [
'right',
'left'
].indexOf(basePlacement), divider = (fragments = offset.split(/(\+|\-)/).map(function(frag) {
return frag.trim();
})).indexOf(find(fragments, function(frag) {
return -1 !== frag.search(/,|\s/);
})), fragments[divider] && -1 === fragments[divider].indexOf(',') && console.warn('Offsets separated by white space(s) are deprecated, use a comma (,) instead.'), splitRegex = /\s*,\s*|\s+/, (ops = (-1 !== divider ? [
fragments.slice(0, divider).concat([
fragments[divider].split(splitRegex)[0]
]),
[
fragments[divider].split(splitRegex)[1]
].concat(fragments.slice(divider + 1))
] : [
fragments
]).map(function(op, index) {
var measurement = (1 === index ? !useHeight : useHeight) ? 'height' : 'width';
var mergeWithPrevious = false;
return op.reduce(function(a, b) {
if ('' === a[a.length - 1] && -1 !== [
'+',
'-'
].indexOf(b)) return a[a.length - 1] = b, mergeWithPrevious = true, a;
if (mergeWithPrevious) return a[a.length - 1] += b, mergeWithPrevious = false, a;
return a.concat(b);
}, []).map(function(str) {
return toValue(str, measurement, popper, reference);
});
})).forEach(function(op, index) {
op.forEach(function(frag, index2) {
isNumeric(frag) && (offsets1[index] += frag * ('-' === op[index2 - 1] ? -1 : 1));
});
}), offsets = offsets1;
}
return 'left' === basePlacement ? (popper.top += offsets[0], popper.left -= offsets[1]) : 'right' === basePlacement ? (popper.top += offsets[0], popper.left += offsets[1]) : 'top' === basePlacement ? (popper.left += offsets[0], popper.top -= offsets[1]) : 'bottom' === basePlacement && (popper.left += offsets[0], popper.top += offsets[1]), data.popper = popper, data;
},
offset: 0
}
};
Expand Up @@ -10418,7 +10418,7 @@
var tkhd, index, id, mdhd;
return (tkhd = findBox_1(trak, [
"tkhd"
])[0]) && (id = toUnsigned(tkhd[index = 0 === tkhd[0] ? 12 : 20] << 24 | tkhd[index + 1] << 16 | tkhd[index + 2] << 8 | tkhd[index + 3]), mdhd = findBox_1(trak, [
])[0]) && (index = 0 === tkhd[0] ? 12 : 20, id = toUnsigned(tkhd[index] << 24 | tkhd[index + 1] << 16 | tkhd[index + 2] << 8 | tkhd[index + 3]), mdhd = findBox_1(trak, [
"mdia",
"mdhd"
])[0]) ? (index = 0 === mdhd[0] ? 12 : 20, result[id] = toUnsigned(mdhd[index] << 24 | mdhd[index + 1] << 16 | mdhd[index + 2] << 8 | mdhd[index + 3]), result) : null;
Expand Down Expand Up @@ -13053,7 +13053,7 @@
var syncPoint = null, lastDistance = null, partsAndSegments = getPartsAndSegments(playlist);
currentTime = currentTime || 0;
for(var i = 0; i < partsAndSegments.length; i++){
var partAndSegment = partsAndSegments[playlist.endList || 0 === currentTime ? i : partsAndSegments.length - (i + 1)], segment = partAndSegment.segment, datetimeMapping = syncController.timelineToDatetimeMappings[segment.timeline];
var index = playlist.endList || 0 === currentTime ? i : partsAndSegments.length - (i + 1), partAndSegment = partsAndSegments[index], segment = partAndSegment.segment, datetimeMapping = syncController.timelineToDatetimeMappings[segment.timeline];
if (datetimeMapping && segment.dateTimeObject) {
var start = segment.dateTimeObject.getTime() / 1000 + datetimeMapping;
if (segment.parts && "number" == typeof partAndSegment.partIndex) for(var z = 0; z < partAndSegment.partIndex; z++)start += segment.parts[z].duration;
Expand All @@ -13075,7 +13075,7 @@
var syncPoint = null, lastDistance = null;
currentTime = currentTime || 0;
for(var partsAndSegments = getPartsAndSegments(playlist), i = 0; i < partsAndSegments.length; i++){
var partAndSegment = partsAndSegments[playlist.endList || 0 === currentTime ? i : partsAndSegments.length - (i + 1)], segment = partAndSegment.segment, start = partAndSegment.part && partAndSegment.part.start || segment && segment.start;
var index = playlist.endList || 0 === currentTime ? i : partsAndSegments.length - (i + 1), partAndSegment = partsAndSegments[index], segment = partAndSegment.segment, start = partAndSegment.part && partAndSegment.part.start || segment && segment.start;
if (segment.timeline === currentTimeline && void 0 !== start) {
var distance = Math.abs(currentTime - start);
if (null !== lastDistance && lastDistance < distance) break;
Expand Down
Expand Up @@ -3175,7 +3175,11 @@
var formatted = addSidxSegmentsToPlaylist$1(formatAudioPlaylist(playlist, isAudioOnly), sidxMapping);
return a[label].playlists.push(formatted), void 0 === mainPlaylist && "main" === role && ((mainPlaylist = playlist).default = !0), a;
}, {});
return mainPlaylist || (formattedPlaylists[Object.keys(formattedPlaylists)[0]].default = !0), formattedPlaylists;
if (!mainPlaylist) {
var firstLabel = Object.keys(formattedPlaylists)[0];
formattedPlaylists[firstLabel].default = !0;
}
return formattedPlaylists;
}, formatVideoPlaylist = function(_ref3) {
var _attributes2, attributes = _ref3.attributes, segments = _ref3.segments, sidx = _ref3.sidx, playlist = {
attributes: ((_attributes2 = {
Expand Down
Expand Up @@ -1675,7 +1675,7 @@
var index = 0;
if (0 === str.length) return list[0];
for(var i = 0; i < str.length; i += 1)index = str.charCodeAt(i) + ((index << 5) - index), index &= index;
return list[index = (index % list.length + list.length) % list.length];
return index = (index % list.length + list.length) % list.length, list[index];
}(opts.string, opts.colors) : opts.string && !opts.colors ? function(str) {
var hash = 0;
if (0 === str.length) return hash.toString();
Expand Down

1 comment on commit 27ae59e

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark

Benchmark suite Current: 27ae59e Previous: b394f9f Ratio
es/full/bugs-1 341625 ns/iter (± 25478) 350508 ns/iter (± 29305) 0.97
es/full/minify/libraries/antd 1966387121 ns/iter (± 78100252) 2111879218 ns/iter (± 98075579) 0.93
es/full/minify/libraries/d3 425075683 ns/iter (± 10580068) 477253912 ns/iter (± 23150529) 0.89
es/full/minify/libraries/echarts 1713521769 ns/iter (± 41812674) 1768784942 ns/iter (± 44996832) 0.97
es/full/minify/libraries/jquery 111480275 ns/iter (± 4014781) 120848711 ns/iter (± 1356858) 0.92
es/full/minify/libraries/lodash 128800553 ns/iter (± 3316350) 139617902 ns/iter (± 9597166) 0.92
es/full/minify/libraries/moment 64739075 ns/iter (± 1349941) 69739935 ns/iter (± 3553422) 0.93
es/full/minify/libraries/react 21808633 ns/iter (± 731131) 22974476 ns/iter (± 143473) 0.95
es/full/minify/libraries/terser 331808118 ns/iter (± 10949519) 397168315 ns/iter (± 43026278) 0.84
es/full/minify/libraries/three 600709409 ns/iter (± 8130627) 659201334 ns/iter (± 35529274) 0.91
es/full/minify/libraries/typescript 3687546872 ns/iter (± 61290690) 3985253857 ns/iter (± 60110808) 0.93
es/full/minify/libraries/victory 897428408 ns/iter (± 19344686) 956683828 ns/iter (± 30089334) 0.94
es/full/minify/libraries/vue 163375698 ns/iter (± 11900145) 185152232 ns/iter (± 4541908) 0.88
es/full/codegen/es3 34336 ns/iter (± 4348) 33985 ns/iter (± 1272) 1.01
es/full/codegen/es5 34350 ns/iter (± 497) 34084 ns/iter (± 656) 1.01
es/full/codegen/es2015 34403 ns/iter (± 969) 34032 ns/iter (± 631) 1.01
es/full/codegen/es2016 34328 ns/iter (± 672) 33974 ns/iter (± 802) 1.01
es/full/codegen/es2017 34364 ns/iter (± 3109) 34080 ns/iter (± 1291) 1.01
es/full/codegen/es2018 34309 ns/iter (± 1607) 34071 ns/iter (± 648) 1.01
es/full/codegen/es2019 34695 ns/iter (± 1505) 34126 ns/iter (± 374) 1.02
es/full/codegen/es2020 34282 ns/iter (± 409) 34227 ns/iter (± 1533) 1.00
es/full/all/es3 190879705 ns/iter (± 7592810) 205468621 ns/iter (± 11777873) 0.93
es/full/all/es5 176483638 ns/iter (± 6194266) 187566358 ns/iter (± 14030526) 0.94
es/full/all/es2015 140163774 ns/iter (± 3081952) 148442741 ns/iter (± 11936301) 0.94
es/full/all/es2016 139584940 ns/iter (± 2700492) 146573299 ns/iter (± 9311702) 0.95
es/full/all/es2017 138687736 ns/iter (± 2575811) 145423013 ns/iter (± 8809769) 0.95
es/full/all/es2018 136956861 ns/iter (± 3000282) 145189265 ns/iter (± 8078586) 0.94
es/full/all/es2019 136426344 ns/iter (± 5033853) 144159830 ns/iter (± 8356838) 0.95
es/full/all/es2020 131369065 ns/iter (± 3631371) 138094151 ns/iter (± 7190825) 0.95
es/full/parser 693589 ns/iter (± 20979) 730601 ns/iter (± 47270) 0.95
es/full/base/fixer 25421 ns/iter (± 1346) 26442 ns/iter (± 734) 0.96
es/full/base/resolver_and_hygiene 88031 ns/iter (± 2547) 91909 ns/iter (± 3392) 0.96
serialization of ast node 211 ns/iter (± 4) 217 ns/iter (± 7) 0.97
serialization of serde 216 ns/iter (± 12) 221 ns/iter (± 2) 0.98

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.