Permalink
Browse files

Don't build cross-eval upvars for heavyweight functions (bug 616762, …

…r=brendan, a=CLOSED TREE).
  • Loading branch information...
1 parent 1c1a26c commit fecd69b7fb36a149a6133983112f20ecfc14f72b @dvander dvander committed Dec 14, 2010
Showing with 47 additions and 0 deletions.
  1. +21 −0 js/src/jsemit.cpp
  2. +26 −0 js/src/trace-test/tests/basic/bug616762.js
View
@@ -2241,6 +2241,27 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
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
* by JSOP_{GET,CALL}UPVAR.
@@ -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.
+

0 comments on commit fecd69b

Please sign in to comment.