diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index 70e9b45515c..8bfe786a6b2 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -1010,6 +1010,10 @@ EmitAtomOp(ExclusiveContext *cx, JSAtom *atom, JSOp op, BytecodeEmitter *bce) { MOZ_ASSERT(JOF_OPTYPE(op) == JOF_ATOM); + // .generator lookups should be emitted as JSOP_GETALIASEDVAR instead of + // JSOP_NAME etc, to bypass |with| objects on the scope chain. + MOZ_ASSERT_IF(op == JSOP_NAME || op == JSOP_GETGNAME, atom != cx->names().dotGenerator); + if (op == JSOP_GETPROP && atom == cx->names().length) { /* Specialize length accesses for the interpreter. */ op = JSOP_LENGTH; diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index c77ed18c8a8..fb64994cd4b 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -2995,7 +2995,7 @@ LexicalLookup(ContextT *ct, HandleAtom atom, int *slotp, typename ContextT::Stmt * can potentially override any static bindings introduced by statements * further up the stack, we have to abort the search. */ - if (stmt->type == STMT_WITH) + if (stmt->type == STMT_WITH && atom != ct->sc->context->names().dotGenerator) break; // Skip statements that do not introduce a new scope @@ -5206,7 +5206,8 @@ Parser::withStatement() for (AtomDefnRange r = pc->lexdeps->all(); !r.empty(); r.popFront()) { DefinitionNode defn = r.front().value().get(); DefinitionNode lexdep = handler.resolve(defn); - handler.deoptimizeUsesWithin(lexdep, TokenPos(begin, pos().begin)); + if (lexdep->name() != context->names().dotGenerator) + handler.deoptimizeUsesWithin(lexdep, TokenPos(begin, pos().begin)); } ObjectBox *staticWithBox = newObjectBox(staticWith); diff --git a/js/src/jit-test/tests/basic/bug1085464.js b/js/src/jit-test/tests/basic/bug1085464.js new file mode 100644 index 00000000000..8e06c2c08fb --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1085464.js @@ -0,0 +1,20 @@ +function *f() { + var o = Proxy.createFunction({ + get: function() { assertEq(0, 1); }, + has: function() { assertEq(0, 2); } + }, function() {}); + + with (o) { + yield 1; + with ({}) { + yield 2; + } + } + with ({".generator": 100}) { + yield eval("3"); + } +} +var s = ""; +for (var i of f()) + s += i; +assertEq(s, "123");