Don't build cross-eval upvars for heavyweight functions (bug 616762, r=brendan).

This commit is contained in:
David Anderson 2010-12-14 11:50:20 -08:00
parent 11d86e7398
commit dd81dd3385
2 changed files with 47 additions and 0 deletions

View File

@ -2234,6 +2234,27 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
if (op != JSOP_NAME)
return JS_TRUE;
/*
* It is illegal to add upvars to heavyweight functions (and
* unnecessary, since the optimization avoids creating call
* objects). Take the following code as an eval string:
*
* (function () {
* $(init);
* function init() {
* $();
* }
* })();
*
* The first instance of "$" cannot be an upvar, because the
* outermost lambda is on "init"'s scope chain, which escapes.
*
* A similar restriction exists for upvars which do not cross
* eval (see the end of BindNameToSlot and bug 616762).
*/
if (cg->flags & TCF_FUN_HEAVYWEIGHT)
return JS_TRUE;
/*
* Generator functions may be resumed from any call stack, which
* defeats the display optimization to static link searching used

View File

@ -0,0 +1,26 @@
// vim: set ts=4 sw=4 tw=99 et:
document = {
ready: function (x) {
this.exec = x;
}
};
var $ = function (x) {
return document;
};
(function ($) {
eval("(function(){\n" +
" var Private={};\n" +
" $(document).ready(function(){\n" +
" init()\n" +
" });\n" +
" function init(){\n" +
" $(Private)\n" +
" };\n" +
"})();");
})($);
document.exec();
// Don't crash or assert.