Skip to content

Commit

Permalink
fix(es/minifier): Abort inliner on fn declarations used multiple time (
Browse files Browse the repository at this point in the history
…#6473)

**Related issue:**

 - Closes #6463.
  • Loading branch information
kdy1 committed Nov 18, 2022
1 parent e45c665 commit 15ad2c2
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 21 deletions.
8 changes: 8 additions & 0 deletions crates/swc/tests/exec/issues-6xxx/6464/exec.js
@@ -0,0 +1,8 @@
var foo_1 = foo;

function foo() {
console.log("foo");
}

foo_1();
foo_1();
14 changes: 13 additions & 1 deletion crates/swc_ecma_minifier/src/compress/optimize/inline.rs
Expand Up @@ -184,7 +184,19 @@ where
.data
.vars
.get(&id.to_id())
.filter(|a| !a.reassigned() && a.declared)
.filter(|a| {
!a.reassigned() && a.declared && {
// Function declarations are hoisted
//
// As we copy expressions, this can cause a problem.
// See https://github.com/swc-project/swc/issues/6463
//
// We check callee_count of `usage` because we copy simple functions
!a.used_above_decl
|| !a.declared_as_fn_decl
|| usage.callee_count == 0
}
})
.is_some(),

Expr::Lit(lit) => match lit {
Expand Down
41 changes: 21 additions & 20 deletions crates/swc_ecma_minifier/tests/benches-full/echarts.js
Expand Up @@ -6790,6 +6790,7 @@
path.applyTransform(m);
}
}
var subPixelOptimize$1 = subPixelOptimize;
function animateOrSetProps(animationType, el, props, animatableModel, dataIndex, cb, during) {
var removeOpt, animationPayload, isFrom = !1;
'function' == typeof dataIndex ? (during = cb, cb = dataIndex, dataIndex = null) : isObject(dataIndex) && (cb = dataIndex.cb, during = dataIndex.during, isFrom = dataIndex.isFrom, removeOpt = dataIndex.removeOpt, dataIndex = dataIndex.dataIndex);
Expand Down Expand Up @@ -6977,7 +6978,7 @@
subPixelOptimizeRect: function(param) {
return subPixelOptimizeRect(param.shape, param.shape, param.style), param;
},
subPixelOptimize: subPixelOptimize,
subPixelOptimize: subPixelOptimize$1,
updateProps: updateProps,
initProps: initProps,
removeElement: removeElement,
Expand Down Expand Up @@ -8853,7 +8854,7 @@
return clone(-1 === index ? mediaDefault.option : mediaList[index].option);
})), this._currentMediaIndices = indices, result;
}, OptionManager;
}(), POSSIBLE_STYLES = [
}(), isObject$1 = isObject, POSSIBLE_STYLES = [
'areaStyle',
'lineStyle',
'nodeStyle',
Expand All @@ -8879,7 +8880,7 @@
convertNormalEmphasis(opt, 'itemStyle'), convertNormalEmphasis(opt, 'lineStyle'), convertNormalEmphasis(opt, 'areaStyle'), convertNormalEmphasis(opt, 'label'), convertNormalEmphasis(opt, 'labelLine'), convertNormalEmphasis(opt, 'upperLabel'), convertNormalEmphasis(opt, 'edgeLabel');
}
function compatTextStyle(opt, propName) {
var labelOptSingle = isObject(opt) && opt[propName], textStyle = isObject(labelOptSingle) && labelOptSingle.textStyle;
var labelOptSingle = isObject$1(opt) && opt[propName], textStyle = isObject$1(labelOptSingle) && labelOptSingle.textStyle;
if (textStyle) {
deprecateLog("textStyle hierarchy in " + propName + " has been removed since 4.0. All textStyle properties are configured in " + propName + " directly now.");
for(var i = 0, len = TEXT_STYLE_OPTIONS.length; i < len; i++){
Expand Down Expand Up @@ -8961,8 +8962,8 @@
function globalBackwardCompat(option, isTheme) {
var axes;
each(toArr(option.series), function(seriesOpt) {
isObject(seriesOpt) && function(seriesOpt) {
if (isObject(seriesOpt)) {
isObject$1(seriesOpt) && function(seriesOpt) {
if (isObject$1(seriesOpt)) {
compatEC2ItemStyle(seriesOpt), removeEC3NormalStatus(seriesOpt), compatTextStyle(seriesOpt, 'label'), compatTextStyle(seriesOpt, 'upperLabel'), compatTextStyle(seriesOpt, 'edgeLabel'), seriesOpt.emphasis && (compatTextStyle(seriesOpt.emphasis, 'label'), compatTextStyle(seriesOpt.emphasis, 'upperLabel'), compatTextStyle(seriesOpt.emphasis, 'edgeLabel'));
var markPoint = seriesOpt.markPoint;
markPoint && (compatEC2ItemStyle(markPoint), compatEC3CommonStyles(markPoint));
Expand Down Expand Up @@ -9007,7 +9008,7 @@
}), each(toArr(option.radar), function(radarOpt) {
compatTextStyle(radarOpt, 'name'), radarOpt.name && null == radarOpt.axisName && (radarOpt.axisName = radarOpt.name, delete radarOpt.name, deprecateLog('name property in radar component has been changed to axisName')), null != radarOpt.nameGap && null == radarOpt.axisNameGap && (radarOpt.axisNameGap = radarOpt.nameGap, delete radarOpt.nameGap, deprecateLog('nameGap property in radar component has been changed to axisNameGap'));
}), each(toArr(option.geo), function(geoOpt) {
isObject(geoOpt) && (compatEC3CommonStyles(geoOpt), each(toArr(geoOpt.regions), function(regionObj) {
isObject$1(geoOpt) && (compatEC3CommonStyles(geoOpt), each(toArr(geoOpt.regions), function(regionObj) {
compatEC3CommonStyles(regionObj);
}));
}), each(toArr(option.timeline), function(timelineOpt) {
Expand Down Expand Up @@ -12866,7 +12867,7 @@
}
return resource.load(nameMap, nameProperty);
}
}, hasWindow = 'undefined' != typeof window, PRIORITY = {
}, isObject$2 = isObject, hasWindow = 'undefined' != typeof window, PRIORITY = {
PROCESSOR: {
FILTER: 1000,
SERIES_FILTER: 800,
Expand Down Expand Up @@ -12965,7 +12966,7 @@
disposedWarning(this.id);
return;
}
if (isObject(notMerge) && (lazyUpdate = notMerge.lazyUpdate, silent = notMerge.silent, replaceMerge = notMerge.replaceMerge, transitionOpt = notMerge.transition, notMerge = notMerge.notMerge), this[IN_MAIN_PROCESS_KEY] = !0, !this._model || notMerge) {
if (isObject$2(notMerge) && (lazyUpdate = notMerge.lazyUpdate, silent = notMerge.silent, replaceMerge = notMerge.replaceMerge, transitionOpt = notMerge.transition, notMerge = notMerge.notMerge), this[IN_MAIN_PROCESS_KEY] = !0, !this._model || notMerge) {
var silent, replaceMerge, transitionOpt, optionManager = new OptionManager(this._api), theme = this._theme, ecModel = this._model = new GlobalModel();
ecModel.scheduler = this._scheduler, ecModel.init(null, null, null, theme, this._locale, optionManager);
}
Expand Down Expand Up @@ -13178,7 +13179,7 @@
disposedWarning(this.id);
return;
}
if (isObject(name) && (cfg = name, name = ''), name = name || 'default', this.hideLoading(), !loadingEffects[name]) {
if (isObject$2(name) && (cfg = name, name = ''), name = name || 'default', this.hideLoading(), !loadingEffects[name]) {
console.warn('Loading effects ' + name + ' not exists.');
return;
}
Expand All @@ -13198,7 +13199,7 @@
disposedWarning(this.id);
return;
}
if (isObject(opt) || (opt = {
if (isObject$2(opt) || (opt = {
silent: !!opt
}), actions[payload.type] && this._model) {
if (this[IN_MAIN_PROCESS_KEY]) {
Expand Down Expand Up @@ -13688,7 +13689,7 @@
}
function registerAction(actionInfo, eventName, action) {
'function' == typeof eventName && (action = eventName, eventName = '');
var actionType = isObject(actionInfo) ? actionInfo.type : [
var actionType = isObject$2(actionInfo) ? actionInfo.type : [
actionInfo,
actionInfo = {
event: eventName
Expand All @@ -13710,7 +13711,7 @@
}
var registeredTasks = [];
function normalizeRegister(targetList, priority, fn, defaultPriority, visualType) {
if ((isFunction(priority) || isObject(priority)) && (fn = priority, priority = defaultPriority), isNaN(priority) || null == priority) throw Error('Illegal priority');
if ((isFunction(priority) || isObject$2(priority)) && (fn = priority, priority = defaultPriority), isNaN(priority) || null == priority) throw Error('Illegal priority');
if (each(targetList, function(wrap) {
assert(wrap.__raw !== fn);
}), !(indexOf(registeredTasks, fn) >= 0)) {
Expand Down Expand Up @@ -14106,7 +14107,7 @@
}
var DataDimensionInfo = function(opt) {
this.otherDims = {}, null != opt && extend(this, opt);
}, mathFloor = Math.floor, UNDEFINED = 'undefined', dataCtors = {
}, mathFloor = Math.floor, isObject$3 = isObject, UNDEFINED = 'undefined', dataCtors = {
float: typeof Float64Array === UNDEFINED ? Array : Float64Array,
int: typeof Int32Array === UNDEFINED ? Array : Int32Array,
ordinal: Array,
Expand Down Expand Up @@ -14305,7 +14306,7 @@
}, List.prototype.getCalculationInfo = function(key) {
return this._calculationInfo[key];
}, List.prototype.setCalculationInfo = function(key, value) {
isObject(key) ? extend(this._calculationInfo, key) : this._calculationInfo[key] = value;
isObject$3(key) ? extend(this._calculationInfo, key) : this._calculationInfo[key] = value;
}, List.prototype.getSum = function(dim) {
var dimData = this._storage[dim], sum = 0;
if (dimData) for(var i = 0, len = this.count(); i < len; i++){
Expand Down Expand Up @@ -14525,7 +14526,7 @@
var visual = this._visual;
return visual && visual[key];
}, List.prototype.setVisual = function(kvObj, val) {
this._visual = this._visual || {}, isObject(kvObj) ? extend(this._visual, kvObj) : this._visual[kvObj] = val;
this._visual = this._visual || {}, isObject$3(kvObj) ? extend(this._visual, kvObj) : this._visual[kvObj] = val;
}, List.prototype.getItemVisual = function(idx, key) {
var itemVisual = this._itemVisuals[idx], val = itemVisual && itemVisual[key];
return null == val ? this.getVisual(key) : val;
Expand All @@ -14535,14 +14536,14 @@
var itemVisuals = this._itemVisuals, itemVisual = itemVisuals[idx];
itemVisual || (itemVisual = itemVisuals[idx] = {});
var val = itemVisual[key];
return null == val && (isArray(val = this.getVisual(key)) ? val = val.slice() : isObject(val) && (val = extend({}, val)), itemVisual[key] = val), val;
return null == val && (isArray(val = this.getVisual(key)) ? val = val.slice() : isObject$3(val) && (val = extend({}, val)), itemVisual[key] = val), val;
}, List.prototype.setItemVisual = function(idx, key, value) {
var itemVisual = this._itemVisuals[idx] || {};
this._itemVisuals[idx] = itemVisual, isObject(key) ? extend(itemVisual, key) : itemVisual[key] = value;
this._itemVisuals[idx] = itemVisual, isObject$3(key) ? extend(itemVisual, key) : itemVisual[key] = value;
}, List.prototype.clearAllVisual = function() {
this._visual = {}, this._itemVisuals = [];
}, List.prototype.setLayout = function(key, val) {
if (isObject(key)) {
if (isObject$3(key)) {
for(var name_1 in key)key.hasOwnProperty(name_1) && this.setLayout(name_1, key[name_1]);
return;
}
Expand Down Expand Up @@ -28198,10 +28199,10 @@
}
function addBodyEnd(ends, point, start) {
var point1 = point.slice(), point2 = point.slice();
point1[0] = subPixelOptimize(point1[0] + candleWidth / 2, 1, !1), point2[0] = subPixelOptimize(point2[0] - candleWidth / 2, 1, !0), start ? ends.push(point1, point2) : ends.push(point2, point1);
point1[0] = subPixelOptimize$1(point1[0] + candleWidth / 2, 1, !1), point2[0] = subPixelOptimize$1(point2[0] - candleWidth / 2, 1, !0), start ? ends.push(point1, point2) : ends.push(point2, point1);
}
function subPixelOptimizePoint(point) {
return point[0] = subPixelOptimize(point[0], 1), point;
return point[0] = subPixelOptimize$1(point[0], 1), point;
}
}
};
Expand Down
16 changes: 16 additions & 0 deletions crates/swc_ecma_minifier/tests/exec.rs
Expand Up @@ -10358,3 +10358,19 @@ fn issue_6279_2() {
"###,
);
}

#[test]
fn issue_6463_1() {
run_default_exec_test(
r###"
var foo_1 = foo;
function foo() {
console.log("foo");
}
foo_1();
foo_1();
"###,
);
}
8 changes: 8 additions & 0 deletions crates/swc_ecma_minifier/tests/fixture/issues/6463/input.js
@@ -0,0 +1,8 @@
var foo_1 = foo;

function foo() {
console.log("foo");
}

foo_1();
foo_1();
4 changes: 4 additions & 0 deletions crates/swc_ecma_minifier/tests/fixture/issues/6463/output.js
@@ -0,0 +1,4 @@
var foo_1 = function() {
console.log("foo");
};
foo_1(), foo_1();

1 comment on commit 15ad2c2

@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: 15ad2c2 Previous: 3e702b9 Ratio
es/full/bugs-1 346117 ns/iter (± 22474) 354348 ns/iter (± 21258) 0.98
es/full/minify/libraries/antd 1957955351 ns/iter (± 56659346) 1874993974 ns/iter (± 38128542) 1.04
es/full/minify/libraries/d3 444712150 ns/iter (± 38663654) 418175522 ns/iter (± 23574855) 1.06
es/full/minify/libraries/echarts 1615751824 ns/iter (± 115715877) 1609079337 ns/iter (± 34145013) 1.00
es/full/minify/libraries/jquery 110708257 ns/iter (± 5102303) 104126257 ns/iter (± 7991135) 1.06
es/full/minify/libraries/lodash 133833754 ns/iter (± 14042922) 133579282 ns/iter (± 5373792) 1.00
es/full/minify/libraries/moment 65244200 ns/iter (± 7197779) 64179040 ns/iter (± 1799088) 1.02
es/full/minify/libraries/react 25592873 ns/iter (± 2133927) 22172744 ns/iter (± 610282) 1.15
es/full/minify/libraries/terser 368397583 ns/iter (± 23963737) 307930356 ns/iter (± 7505502) 1.20
es/full/minify/libraries/three 635544587 ns/iter (± 23540994) 571502761 ns/iter (± 11258727) 1.11
es/full/minify/libraries/typescript 3664030287 ns/iter (± 95819033) 3377745729 ns/iter (± 21289701) 1.08
es/full/minify/libraries/victory 863451822 ns/iter (± 31194415) 826574577 ns/iter (± 10985643) 1.04
es/full/minify/libraries/vue 165269128 ns/iter (± 11804335) 154079012 ns/iter (± 2955872) 1.07
es/full/codegen/es3 34763 ns/iter (± 1305) 33318 ns/iter (± 1333) 1.04
es/full/codegen/es5 34587 ns/iter (± 1230) 33387 ns/iter (± 2257) 1.04
es/full/codegen/es2015 34433 ns/iter (± 1937) 33359 ns/iter (± 1085) 1.03
es/full/codegen/es2016 34382 ns/iter (± 2122) 33319 ns/iter (± 537) 1.03
es/full/codegen/es2017 34724 ns/iter (± 1535) 33230 ns/iter (± 488) 1.04
es/full/codegen/es2018 34589 ns/iter (± 2727) 33224 ns/iter (± 797) 1.04
es/full/codegen/es2019 34779 ns/iter (± 956) 33353 ns/iter (± 871) 1.04
es/full/codegen/es2020 34435 ns/iter (± 1021) 33354 ns/iter (± 1243) 1.03
es/full/all/es3 208946945 ns/iter (± 17927599) 190515266 ns/iter (± 4057535) 1.10
es/full/all/es5 196987775 ns/iter (± 14151792) 181250320 ns/iter (± 3842697) 1.09
es/full/all/es2015 155192235 ns/iter (± 10338814) 145989342 ns/iter (± 2792108) 1.06
es/full/all/es2016 156039736 ns/iter (± 14142708) 144170725 ns/iter (± 4023659) 1.08
es/full/all/es2017 152429291 ns/iter (± 9867532) 143825266 ns/iter (± 3088115) 1.06
es/full/all/es2018 151556223 ns/iter (± 12155126) 145854294 ns/iter (± 5875440) 1.04
es/full/all/es2019 149367814 ns/iter (± 13828712) 143259939 ns/iter (± 6590229) 1.04
es/full/all/es2020 141622508 ns/iter (± 8817046) 137798688 ns/iter (± 14307266) 1.03
es/full/parser 735960 ns/iter (± 41686) 729658 ns/iter (± 23042) 1.01
es/full/base/fixer 26506 ns/iter (± 1048) 26561 ns/iter (± 1053) 1.00
es/full/base/resolver_and_hygiene 95434 ns/iter (± 18794) 91726 ns/iter (± 3084) 1.04
serialization of ast node 220 ns/iter (± 11) 219 ns/iter (± 18) 1.00
serialization of serde 221 ns/iter (± 3) 218 ns/iter (± 6) 1.01

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

Please sign in to comment.