Fix load of potentially eval-shadowed let bindings.
BUG= TEST=test/mjsunit/harmony/block-let-semantics.js Review URL: http://codereview.chromium.org/8118032 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9541 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
fa425b54b7
commit
80048c14b1
@ -1225,9 +1225,17 @@ void FullCodeGenerator::EmitDynamicLookupFastCase(Variable* var,
|
||||
} else if (var->mode() == Variable::DYNAMIC_LOCAL) {
|
||||
Variable* local = var->local_if_not_shadowed();
|
||||
__ ldr(r0, ContextSlotOperandCheckExtensions(local, slow));
|
||||
if (local->mode() == Variable::CONST) {
|
||||
if (local->mode() == Variable::CONST ||
|
||||
local->mode() == Variable::LET) {
|
||||
__ CompareRoot(r0, Heap::kTheHoleValueRootIndex);
|
||||
if (local->mode() == Variable::CONST) {
|
||||
__ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq);
|
||||
} else { // Variable::LET
|
||||
__ b(ne, done);
|
||||
__ mov(r0, Operand(var->name()));
|
||||
__ push(r0);
|
||||
__ CallRuntime(Runtime::kThrowReferenceError, 1);
|
||||
}
|
||||
}
|
||||
__ jmp(done);
|
||||
}
|
||||
|
@ -1207,10 +1207,16 @@ void FullCodeGenerator::EmitDynamicLookupFastCase(Variable* var,
|
||||
} else if (var->mode() == Variable::DYNAMIC_LOCAL) {
|
||||
Variable* local = var->local_if_not_shadowed();
|
||||
__ mov(eax, ContextSlotOperandCheckExtensions(local, slow));
|
||||
if (local->mode() == Variable::CONST) {
|
||||
if (local->mode() == Variable::CONST ||
|
||||
local->mode() == Variable::LET) {
|
||||
__ cmp(eax, isolate()->factory()->the_hole_value());
|
||||
__ j(not_equal, done);
|
||||
if (local->mode() == Variable::CONST) {
|
||||
__ mov(eax, isolate()->factory()->undefined_value());
|
||||
} else { // Variable::LET
|
||||
__ push(Immediate(var->name()));
|
||||
__ CallRuntime(Runtime::kThrowReferenceError, 1);
|
||||
}
|
||||
}
|
||||
__ jmp(done);
|
||||
}
|
||||
|
@ -1184,10 +1184,16 @@ void FullCodeGenerator::EmitDynamicLookupFastCase(Variable* var,
|
||||
} else if (var->mode() == Variable::DYNAMIC_LOCAL) {
|
||||
Variable* local = var->local_if_not_shadowed();
|
||||
__ movq(rax, ContextSlotOperandCheckExtensions(local, slow));
|
||||
if (local->mode() == Variable::CONST) {
|
||||
if (local->mode() == Variable::CONST ||
|
||||
local->mode() == Variable::LET) {
|
||||
__ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
|
||||
__ j(not_equal, done);
|
||||
if (local->mode() == Variable::CONST) {
|
||||
__ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
|
||||
} else { // Variable::LET
|
||||
__ Push(var->name());
|
||||
__ CallRuntime(Runtime::kThrowReferenceError, 1);
|
||||
}
|
||||
}
|
||||
__ jmp(done);
|
||||
}
|
||||
|
@ -81,13 +81,20 @@ TestAll('f()(); let x; function f() { return function() { x += 1; } }');
|
||||
TestAll('f()(); let x; function f() { return function() { ++x; } }');
|
||||
TestAll('f()(); let x; function f() { return function() { x++; } }');
|
||||
|
||||
// Use in before initialization with a dynamic lookup.
|
||||
// Use before initialization with a dynamic lookup.
|
||||
TestAll('eval("x + 1;"); let x;');
|
||||
TestAll('eval("x = 1;"); let x;');
|
||||
TestAll('eval("x += 1;"); let x;');
|
||||
TestAll('eval("++x;"); let x;');
|
||||
TestAll('eval("x++;"); let x;');
|
||||
|
||||
// Use before initialization with check for eval-shadowed bindings.
|
||||
TestAll('function f() { eval("var y = 2;"); x + 1; }; f(); let x;');
|
||||
TestAll('function f() { eval("var y = 2;"); x = 1; }; f(); let x;');
|
||||
TestAll('function f() { eval("var y = 2;"); x += 1; }; f(); let x;');
|
||||
TestAll('function f() { eval("var y = 2;"); ++x; }; f(); let x;');
|
||||
TestAll('function f() { eval("var y = 2;"); x++; }; f(); let x;');
|
||||
|
||||
// Test that variables introduced by function declarations are created and
|
||||
// initialized upon entering a function / block scope.
|
||||
function f() {
|
||||
@ -136,3 +143,19 @@ function f2() {
|
||||
}
|
||||
assertEquals(5, n());
|
||||
}
|
||||
|
||||
// Test that resolution of let bound variables works with scopes that call eval.
|
||||
function outer() {
|
||||
function middle() {
|
||||
function inner() {
|
||||
return x;
|
||||
}
|
||||
eval("1 + 1");
|
||||
return x + inner();
|
||||
}
|
||||
|
||||
let x = 1;
|
||||
return middle();
|
||||
}
|
||||
|
||||
assertEquals(2, outer());
|
||||
|
Loading…
Reference in New Issue
Block a user