make let scoping collision detection much more reliable
This commit is contained in:
@@ -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;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user