babel-plugin-loop-optimizer icon indicating copy to clipboard operation
babel-plugin-loop-optimizer copied to clipboard

Breaks when declaring variables with comma operator that depend on previous results

Open JobLeonard opened this issue 7 years ago • 1 comments

So this is a bit of an exotic use-case, but it's valid JS:

/**
 * Returns the first key in `keyList` that matches a key
 * in `obj`, case insensitive, i.e. if `keyList` contains
 * `'a'`, and the matching key in `obj` is `'A'`, then
 * the returned key is `'A'`.
 *
 * Returns empty string if no matches are found.
 * @param {object} obj
 * @param {string[]} keyList
 */
function firstMatchingKeyCaseInsensitive(obj, keyList) {
	let keys = Object.keys(obj),
		keysLowerCase = keys.map(toLowerCase),
		keyListLowerCase = keyList.map(toLowerCase);
	for (let i = 0; i < keyList.length; i++) {
		let j = keysLowerCase.indexOf(keyListLowerCase[i]);
		if (j !== -1) {
			return keys[j];
		}
	}
	return '';
}

function toLowerCase(key){
	return key.toLowerCase();
}

keysLowerCase depends on the returned value of Object.keys(obj) being assigned to keys, but because of this construction, that does not happen until later.

The result is an undefined keys being assigned to _a in the code below:

function firstMatchingKeyCaseInsensitive(obj, keyList) {
	var _a = keys;
	var _f = toLowerCase;
	var _r = [];

	for (var _i = 0; _i < _a.length; _i++) {
		_r.push(_f(_a[_i], _i, _a));
	}

	var _a2 = keyList;
	var _f2 = toLowerCase;
	var _r2 = [];

	for (var _i2 = 0; _i2 < _a2.length; _i2++) {
		_r2.push(_f2(_a2[_i2], _i2, _a2));
	}

	var keys = Object.keys(obj),
	    keysLowerCase = _r,
	    keyListLowerCase = _r2;
	for (var i = 0; i < keyList.length; i++) {
		var j = keysLowerCase.indexOf(keyListLowerCase[i]);
		if (j !== -1) {
			return keys[j];
		}
	}
	return '';
}

Separating variables with ; fixes this:

function firstMatchingKeyCaseInsensitive(obj, keyList) {
	let keys = Object.keys(obj);
	let keysLowerCase = keys.map(toLowerCase),
		keyListLowerCase = keyList.map(toLowerCase);
	for (let i = 0; i < keyList.length; i++) {
		let j = keysLowerCase.indexOf(keyListLowerCase[i]);
		if (j !== -1) {
			return keys[j];
		}
	}
	return '';
}
function firstMatchingKeyCaseInsensitive(obj, keyList) {
	var keys = Object.keys(obj);
	var _a = keys;
	var _f = toLowerCase;
	var _r = [];

	for (var _i = 0; _i < _a.length; _i++) {
		_r.push(_f(_a[_i], _i, _a));
	}

	var _a2 = keyList;
	var _f2 = toLowerCase;
	var _r2 = [];

	for (var _i2 = 0; _i2 < _a2.length; _i2++) {
		_r2.push(_f2(_a2[_i2], _i2, _a2));
	}

	var keysLowerCase = _r,
	    keyListLowerCase = _r2;
	for (var i = 0; i < keyList.length; i++) {
		var j = keysLowerCase.indexOf(keyListLowerCase[i]);
		if (j !== -1) {
			return keys[j];
		}
	}
	return '';
}

JobLeonard avatar Nov 21 '17 15:11 JobLeonard

Hm... that’s a tough one. I’ll try transforming to do expressions perhaps

vihanb avatar Nov 21 '17 16:11 vihanb