make let scoping collision detection much more reliable

This commit is contained in:
Sebastian McKenzie 2015-01-18 12:15:50 +11:00
parent ddd59b94b0
commit 320c78b815
6 changed files with 69 additions and 34 deletions

View File

@ -162,21 +162,32 @@ LetScoping.prototype.noClosure = function () {
*/
LetScoping.prototype.remap = function () {
var replacements = this.info.duplicates;
var block = this.block;
var duplicates = this.info.duplicates;
var block = this.block;
var scope = this.scope;
if (!this.info.hasDuplicates) return;
var replace = function (node, parent, scope, context, replacements) {
var replace = function (node, parent, scope, context, duplicates) {
if (!t.isIdentifier(node)) return;
if (!t.isReferenced(node, parent)) return;
if (scope && scope.hasOwn(node.name)) return;
node.name = replacements[node.name] || node.name;
var duplicate = duplicates[node.name];
if (!duplicate) return;
var own = scope.get(node.name, true);
if (own === duplicate.node) {
node.name = duplicate.uid;
} else {
// scope already has it's own declaration that doesn't
// match the one we have a stored replacement for
context.skip();
}
};
var traverseReplace = function (node, parent) {
replace(node, parent);
traverse(node, { enter: replace }, null, replacements);
traverse(node, { enter: replace }, scope, duplicates);
};
var loopParent = this.loopParent;
@ -186,7 +197,7 @@ LetScoping.prototype.remap = function () {
traverseReplace(loopParent.update, loopParent);
}
traverse(block, { enter: replace }, null, replacements);
traverse(block, { enter: replace }, scope, duplicates);
};
/**
@ -221,12 +232,14 @@ LetScoping.prototype.getInfo = function () {
};
var duplicates = function (id, key) {
var has = scope.parentGet(key);
if (has && has !== id) {
// there's a variable with this exact name in an upper scope so we need
// to generate a new name
opts.duplicates[key] = id.name = file.generateUidIdentifier(key, scope).name;
// there's a variable with this exact name in an upper scope so we need
// to generate a new name
if (scope.parentHas(key, true)) {
var duplicate = opts.duplicates[key] = {
uid: file.generateUidIdentifier(key, scope).name,
node: id
};
id.name = duplicate.uid;
opts.hasDuplicates = true;
}
};
@ -305,7 +318,7 @@ LetScoping.prototype.checkLoop = function () {
if (replace) return t.inherits(replace, node);
}
}, null, has);
}, this.scope, has);
return has;
};
@ -332,7 +345,7 @@ LetScoping.prototype.hoistVarDeclarations = function () {
return context.skip();
}
}
}, null, this);
}, this.scope, this);
};
/**
@ -347,7 +360,8 @@ LetScoping.prototype.getParams = function (params) {
var info = this.info;
params = _.cloneDeep(params);
_.each(params, function (param) {
param.name = info.duplicates[param.name] || param.name;
var duplicate = info.duplicates[param.name];
if (duplicate) param.name = duplicate.uid;
});
return params;
};
@ -388,12 +402,12 @@ LetScoping.prototype.getLetReferences = function () {
// push this badboy
state.self.letReferences[node.name] = node;
}
}, null, state);
}, scope, state);
return context.skip();
}
}
}, null, state);
}, this.scope, state);
return state.closurify;
};

View File

@ -4,19 +4,19 @@ var A = new WeakMap();
var B = new WeakMap(),
C = new WeakMap();
var D = (function () {
var F = new WeakMap(),
G = new WeakMap();
var E = new WeakMap();
var _F = new WeakMap(),
_G = new WeakMap();
var _E = new WeakMap();
function D() {}
return D;
})();
var H = (function () {
var J = new WeakMap(),
K = new WeakMap();
var I = new WeakMap();
var _J = new WeakMap(),
_K = new WeakMap();
var _I = new WeakMap();
function H() {}
return H;
})();
})();

View File

@ -4,9 +4,9 @@ var arr = (function () {
var _arr = [];
for (var _iterator = [1, 2, 3][Symbol.iterator](), _step; !(_step = _iterator.next()).done;) {
var _i = _step.value;
if (_i > 1) {
_arr.push(_i * _i);
var i = _step.value;
if (i > 1) {
_arr.push(i * i);
}
}

View File

@ -6,9 +6,9 @@ var seattlers = (function () {
for (var _iterator = countries[Symbol.iterator](), _step; !(_step = _iterator.next()).done;) {
var customers = _step.value;
for (var _iterator2 = customers[Symbol.iterator](), _step2; !(_step2 = _iterator2.next()).done;) {
var _c = _step2.value;
if (_c.city == "Seattle") {
_seattlers.push({ name: _c.name, age: _c.age });
var c = _step2.value;
if (c.city == "Seattle") {
_seattlers.push({ name: c.name, age: c.age });
}
}
}

View File

@ -4,9 +4,9 @@ var arr = (function () {
var _arr = [];
for (var _iterator = nums[Symbol.iterator](), _step; !(_step = _iterator.next()).done;) {
var _i = _step.value;
if (_i > 1) {
_arr.push(_i * _i);
var i = _step.value;
if (i > 1) {
_arr.push(i * i);
}
}

View File

@ -0,0 +1,21 @@
assert.equal(8, 2 ** 3);
assert.equal(24, 3 * 2 ** 3);
var x = 2;
assert.equal(8, 2 ** ++x);
assert.equal(1, (2 ** -1) * 2);
var calls = 0;
var q = {q: 3};
var o = {
get p() {
calls++;
return q;
}
};
o.p.q **= 2;
assert.equal(1, calls);
assert.equal(9, o.p.q);
assert.equal(512, 2 ** (3 ** 2));
assert.equal(512, 2 ** 3 ** 2);