Skip to content
This repository was archived by the owner on Dec 5, 2019. It is now read-only.
This repository was archived by the owner on Dec 5, 2019. It is now read-only.

Bug report: Minification causes runtime error for a special variable name #311

@Goues

Description

@Goues

Bug report

Setup

Package versions
webpack: 4.8.3
uglify-es: 3.3.9
uglifyjs-webpack-plugin: 1.2.5
babel: 6.23.0

Babel setup

{
	"presets": [
		"react",
		["env", {
			"modules": false,
			"useBuiltIns": true,
			"targets": {
				"browsers": [
					"last 2 Chrome versions", "not Chrome < 60",
					"last 2 Safari versions", "not Safari < 10.1",
					"last 2 iOS versions", "not iOS < 10.3",
					"last 2 Firefox versions", "not Firefox < 54",
					"last 2 Edge versions", "not Edge < 15"
				]
			}
		}]
	],
	"plugins": [
		["transform-object-rest-spread", {
			"useBuiltins": true
		}],
		"transform-class-properties"
	]
}

Webpack setup

{
	entry: '...',
	output: '...',
	module: {
		rules: [{
			test: /\.js$/,
			exclude: /node_modules/,
			use: babel
		}]
	},
	optimization: {
		minimizer: [
			new UglifyJsPlugin({
				sourceMap: true,
				uglifyOptions: {
					ecma: 6
				}
			})
		]
	}
};

Code samples

Working example

Source code:

const TYPES = {
	type: {
		subtype: ['field']
	}
}

const FIELDS = {
	field: ['property']
}

function getHashTable(type, subtype) {
	return TYPES[type][subtype].map(field => {
		return FIELDS[field].includes('property');
	})
}

function doStuff(data, table) {
	// some heavy operation not necessary for showcase
	return data || table;
}

const minificationError = props => data => {
	const { type, x } = props;
	console.log(type, x);
	const temp = getHashTable(type, x);
	return doStuff(data, temp);
}

console.log(minificationError({
	type: 'type',
	x: 'subtype'
})())

Minified code:

!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:r})},n.r=function(e){Object.defineProperty(e,"__esModule",{value:!0})},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=1)}([function(e,t){const n={type:{subtype:["field"]}},r={field:["property"]};var o;console.log((e=>t=>{const u=e.type,c=e.x;console.log(u,c);const p=(o=c,n[u][o].map(e=>r[e].includes("property")));return t||p})({type:"type",x:"subtype"})())},function(e,t,n){e.exports=n(0)}]);

It first logs type subtype then [true].

Non-working example

Source code:

const TYPES = {
	type: {
		subtype: ['field']
	}
}

const FIELDS = {
	field: ['property']
}

function getHashTable(type, subtype) {
	return TYPES[type][subtype].map(field => {
		return FIELDS[field].includes('property');
	})
}

function doStuff(data, table) {
	// some heavy operation not necessary for showcase
	return data || table;
}

const minificationError = props => data => {
	const { type, subtype } = props;
	console.log(type, subtype);
	const temp = getHashTable(type, subtype);
	return doStuff(data, temp);
}

console.log(minificationError({
	type: 'type',
	subtype: 'subtype'
})())

Minified code:

!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:r})},n.r=function(e){Object.defineProperty(e,"__esModule",{value:!0})},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=1)}([function(e,t){const n={type:{subtype:["field"]}},r={field:["property"]};var o;console.log((e=>t=>{const o=e.type,u=e.subtype;console.log(o,u);const p=(u=u,n[o][u].map(e=>r[e].includes("property")));return t||p})({type:"type",subtype:"subtype"})())},function(e,t,n){e.exports=n(0)}]);

This throws Uncaught TypeError: Assignment to constant variable.

Description of the problem

Hello everyone, we're trying to switch from using webpack + babel to transpiling source code to es5 to only transpiling to es6 and using <script type="module"> because we don't need support for old browsers.

We found out there is an issue with how our webpack + babel + uglify-es handles one of our files. Above is the source code reduced down as much as possible. What happens is that there is a destructuring assignment and then two funnction calls that handle data. When upon minification, the result of first function gets directly inserted into the second function:

const a = fn1();
return fn2(a);

becomes

return fn2(fn1(a))

but there is an issue with function arguments.

When the argument is called subtype minification somehow screws up with variables and tries to assing to a const. Different name of variable, such as x does not cause a problem (see source code above).

The problem occurs even with the default minimizer, which is why we've tried to override it with ecma option.

In my opinion, variable name should not cause such a difference, which is why I've decided to submit this bug report.

Thank you!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions