Commit b4b5e3ca authored by ager@chromium.org's avatar ager@chromium.org

Not sure what happened, but my revert did not get everything out. Fixing the...

Not sure what happened, but my revert did not get everything out.  Fixing the problem instead.  The issue was using tmp instead of context in two places.

TBR=kasperl

Review URL: http://codereview.chromium.org/20459

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1303 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 19f04d16
...@@ -256,6 +256,11 @@ class CodeGenerator: public AstVisitor { ...@@ -256,6 +256,11 @@ class CodeGenerator: public AstVisitor {
MemOperand SlotOperand(Slot* slot, Register tmp); MemOperand SlotOperand(Slot* slot, Register tmp);
MemOperand ContextSlotOperandCheckExtensions(Slot* slot,
Register tmp,
Register tmp2,
Label* slow);
// Expressions // Expressions
MemOperand GlobalObject() const { MemOperand GlobalObject() const {
return ContextOperand(cp, Context::GLOBAL_INDEX); return ContextOperand(cp, Context::GLOBAL_INDEX);
...@@ -272,6 +277,11 @@ class CodeGenerator: public AstVisitor { ...@@ -272,6 +277,11 @@ class CodeGenerator: public AstVisitor {
// Read a value from a slot and leave it on top of the expression stack. // Read a value from a slot and leave it on top of the expression stack.
void LoadFromSlot(Slot* slot, TypeofState typeof_state); void LoadFromSlot(Slot* slot, TypeofState typeof_state);
void LoadFromGlobalSlotCheckExtensions(Slot* slot,
TypeofState typeof_state,
Register tmp,
Register tmp2,
Label* slow);
// Special code for typeof expressions: Unfortunately, we must // Special code for typeof expressions: Unfortunately, we must
// be careful when loading the expression in 'typeof' // be careful when loading the expression in 'typeof'
......
...@@ -267,6 +267,9 @@ class CodeGenerator: public AstVisitor { ...@@ -267,6 +267,9 @@ class CodeGenerator: public AstVisitor {
Operand SlotOperand(Slot* slot, Register tmp); Operand SlotOperand(Slot* slot, Register tmp);
Operand ContextSlotOperandCheckExtensions(Slot* slot,
Register tmp,
Label* slow);
// Expressions // Expressions
Operand GlobalObject() const { Operand GlobalObject() const {
...@@ -284,6 +287,10 @@ class CodeGenerator: public AstVisitor { ...@@ -284,6 +287,10 @@ class CodeGenerator: public AstVisitor {
// Read a value from a slot and leave it on top of the expression stack. // Read a value from a slot and leave it on top of the expression stack.
void LoadFromSlot(Slot* slot, TypeofState typeof_state); void LoadFromSlot(Slot* slot, TypeofState typeof_state);
void LoadFromGlobalSlotCheckExtensions(Slot* slot,
TypeofState typeof_state,
Register tmp,
Label* slow);
// Special code for typeof expressions: Unfortunately, we must // Special code for typeof expressions: Unfortunately, we must
// be careful when loading the expression in 'typeof' // be careful when loading the expression in 'typeof'
......
...@@ -134,10 +134,12 @@ Handle<Object> Context::Lookup(Handle<String> name, ContextLookupFlags flags, ...@@ -134,10 +134,12 @@ Handle<Object> Context::Lookup(Handle<String> name, ContextLookupFlags flags,
// declared variables that were introduced through declaration nodes) // declared variables that were introduced through declaration nodes)
// must not appear here. // must not appear here.
switch (mode) { switch (mode) {
case Variable::INTERNAL : // fall through case Variable::INTERNAL: // fall through
case Variable::VAR : *attributes = NONE; break; case Variable::VAR: *attributes = NONE; break;
case Variable::CONST : *attributes = READ_ONLY; break; case Variable::CONST: *attributes = READ_ONLY; break;
case Variable::DYNAMIC : UNREACHABLE(); break; case Variable::DYNAMIC: UNREACHABLE(); break;
case Variable::DYNAMIC_GLOBAL: UNREACHABLE(); break;
case Variable::DYNAMIC_LOCAL: UNREACHABLE(); break;
case Variable::TEMPORARY: UNREACHABLE(); break; case Variable::TEMPORARY: UNREACHABLE(); break;
} }
return context; return context;
......
...@@ -139,6 +139,7 @@ Scope::Scope(Scope* outer_scope, Type type) ...@@ -139,6 +139,7 @@ Scope::Scope(Scope* outer_scope, Type type)
scope_calls_eval_(false), scope_calls_eval_(false),
outer_scope_calls_eval_(false), outer_scope_calls_eval_(false),
inner_scope_calls_eval_(false), inner_scope_calls_eval_(false),
outer_scope_is_eval_scope_(false),
force_eager_compilation_(false), force_eager_compilation_(false),
num_stack_slots_(0), num_stack_slots_(0),
num_heap_slots_(0) { num_heap_slots_(0) {
...@@ -312,7 +313,8 @@ void Scope::AllocateVariables() { ...@@ -312,7 +313,8 @@ void Scope::AllocateVariables() {
// and assume they may invoke eval themselves. Eventually we could capture // and assume they may invoke eval themselves. Eventually we could capture
// this information in the ScopeInfo and then use it here (by traversing // this information in the ScopeInfo and then use it here (by traversing
// the call chain stack, at compile time). // the call chain stack, at compile time).
PropagateScopeInfo(is_eval_scope()); bool eval_scope = is_eval_scope();
PropagateScopeInfo(eval_scope, eval_scope);
// 2) Resolve variables. // 2) Resolve variables.
Scope* global_scope = NULL; Scope* global_scope = NULL;
...@@ -442,6 +444,9 @@ void Scope::Print(int n) { ...@@ -442,6 +444,9 @@ void Scope::Print(int n) {
if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n"); if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n");
if (outer_scope_calls_eval_) Indent(n1, "// outer scope calls 'eval'\n"); if (outer_scope_calls_eval_) Indent(n1, "// outer scope calls 'eval'\n");
if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n"); if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n");
if (outer_scope_is_eval_scope_) {
Indent(n1, "// outer scope is 'eval' scope\n");
}
if (num_stack_slots_ > 0) { Indent(n1, "// "); if (num_stack_slots_ > 0) { Indent(n1, "// ");
PrintF("%d stack slots\n", num_stack_slots_); } PrintF("%d stack slots\n", num_stack_slots_); }
if (num_heap_slots_ > 0) { Indent(n1, "// "); if (num_heap_slots_ > 0) { Indent(n1, "// ");
...@@ -482,20 +487,18 @@ void Scope::Print(int n) { ...@@ -482,20 +487,18 @@ void Scope::Print(int n) {
#endif // DEBUG #endif // DEBUG
Variable* Scope::NonLocal(Handle<String> name) { Variable* Scope::NonLocal(Handle<String> name, Variable::Mode mode) {
// Space optimization: reuse existing non-local with the same name. // Space optimization: reuse existing non-local with the same name
// and mode.
for (int i = 0; i < nonlocals_.length(); i++) { for (int i = 0; i < nonlocals_.length(); i++) {
Variable* var = nonlocals_[i]; Variable* var = nonlocals_[i];
if (var->name().is_identical_to(name)) { if (var->name().is_identical_to(name) && var->mode() == mode) {
ASSERT(var->mode() == Variable::DYNAMIC);
return var; return var;
} }
} }
// Otherwise create a new new-local and add it to the list. // Otherwise create a new non-local and add it to the list.
Variable* var = new Variable( Variable* var = new Variable(NULL, name, mode, true, false);
NULL /* we don't know the scope */,
name, Variable::DYNAMIC, true, false);
nonlocals_.Add(var); nonlocals_.Add(var);
// Allocate it by giving it a dynamic lookup. // Allocate it by giving it a dynamic lookup.
...@@ -511,7 +514,9 @@ Variable* Scope::NonLocal(Handle<String> name) { ...@@ -511,7 +514,9 @@ Variable* Scope::NonLocal(Handle<String> name) {
// because the variable is just a guess (and may be shadowed by another // because the variable is just a guess (and may be shadowed by another
// variable that is introduced dynamically via an 'eval' call or a 'with' // variable that is introduced dynamically via an 'eval' call or a 'with'
// statement). // statement).
Variable* Scope::LookupRecursive(Handle<String> name, bool inner_lookup) { Variable* Scope::LookupRecursive(Handle<String> name,
bool inner_lookup,
Variable** invalidated_local) {
// If we find a variable, but the current scope calls 'eval', the found // If we find a variable, but the current scope calls 'eval', the found
// variable may not be the correct one (the 'eval' may introduce a // variable may not be the correct one (the 'eval' may introduce a
// property with the same name). In that case, remember that the variable // property with the same name). In that case, remember that the variable
...@@ -542,7 +547,7 @@ Variable* Scope::LookupRecursive(Handle<String> name, bool inner_lookup) { ...@@ -542,7 +547,7 @@ Variable* Scope::LookupRecursive(Handle<String> name, bool inner_lookup) {
var = function_; var = function_;
} else if (outer_scope_ != NULL) { } else if (outer_scope_ != NULL) {
var = outer_scope_->LookupRecursive(name, true /* inner lookup */); var = outer_scope_->LookupRecursive(name, true, invalidated_local);
// We may have found a variable in an outer scope. However, if // We may have found a variable in an outer scope. However, if
// the current scope is inside a 'with', the actual variable may // the current scope is inside a 'with', the actual variable may
// be a property introduced via the 'with' statement. Then, the // be a property introduced via the 'with' statement. Then, the
...@@ -563,8 +568,10 @@ Variable* Scope::LookupRecursive(Handle<String> name, bool inner_lookup) { ...@@ -563,8 +568,10 @@ Variable* Scope::LookupRecursive(Handle<String> name, bool inner_lookup) {
var->is_accessed_from_inner_scope_ = true; var->is_accessed_from_inner_scope_ = true;
// If the variable we have found is just a guess, invalidate the result. // If the variable we have found is just a guess, invalidate the result.
if (guess) if (guess) {
*invalidated_local = var;
var = NULL; var = NULL;
}
return var; return var;
} }
...@@ -578,7 +585,8 @@ void Scope::ResolveVariable(Scope* global_scope, VariableProxy* proxy) { ...@@ -578,7 +585,8 @@ void Scope::ResolveVariable(Scope* global_scope, VariableProxy* proxy) {
if (proxy->var() != NULL) return; if (proxy->var() != NULL) return;
// Otherwise, try to resolve the variable. // Otherwise, try to resolve the variable.
Variable* var = LookupRecursive(proxy->name(), false); Variable* invalidated_local = NULL;
Variable* var = LookupRecursive(proxy->name(), false, &invalidated_local);
if (proxy->inside_with()) { if (proxy->inside_with()) {
// If we are inside a local 'with' statement, all bets are off // If we are inside a local 'with' statement, all bets are off
...@@ -587,7 +595,7 @@ void Scope::ResolveVariable(Scope* global_scope, VariableProxy* proxy) { ...@@ -587,7 +595,7 @@ void Scope::ResolveVariable(Scope* global_scope, VariableProxy* proxy) {
// Note that we must do a lookup anyway, because if we find one, // Note that we must do a lookup anyway, because if we find one,
// we must mark that variable as potentially accessed from this // we must mark that variable as potentially accessed from this
// inner scope (the property may not be in the 'with' object). // inner scope (the property may not be in the 'with' object).
var = NonLocal(proxy->name()); var = NonLocal(proxy->name(), Variable::DYNAMIC);
} else { } else {
// We are not inside a local 'with' statement. // We are not inside a local 'with' statement.
...@@ -601,11 +609,22 @@ void Scope::ResolveVariable(Scope* global_scope, VariableProxy* proxy) { ...@@ -601,11 +609,22 @@ void Scope::ResolveVariable(Scope* global_scope, VariableProxy* proxy) {
// or we don't know about the outer scope (because we are // or we don't know about the outer scope (because we are
// in an eval scope). // in an eval scope).
if (!is_global_scope() && if (!is_global_scope() &&
(is_eval_scope() || outer_scope_calls_eval_ || (scope_inside_with_ || outer_scope_is_eval_scope_)) {
scope_calls_eval_ || scope_inside_with_)) { // If we are inside a with statement or the code is executed
// We must look up the variable at runtime, and we don't // using eval, we give up and look up the variable at runtime.
// know anything else. var = NonLocal(proxy->name(), Variable::DYNAMIC);
var = NonLocal(proxy->name());
} else if (!is_global_scope() &&
(scope_calls_eval_ || outer_scope_calls_eval_)) {
// If the code is not executed using eval and there are no
// with scopes, either we have a local or a global variable
// that might be shadowed by an eval-introduced variable.
if (invalidated_local != NULL) {
var = NonLocal(proxy->name(), Variable::DYNAMIC_LOCAL);
var->set_local_if_not_shadowed(invalidated_local);
} else {
var = NonLocal(proxy->name(), Variable::DYNAMIC_GLOBAL);
}
} else { } else {
// We must have a global variable. // We must have a global variable.
...@@ -643,15 +662,21 @@ void Scope::ResolveVariablesRecursively(Scope* global_scope) { ...@@ -643,15 +662,21 @@ void Scope::ResolveVariablesRecursively(Scope* global_scope) {
} }
bool Scope::PropagateScopeInfo(bool outer_scope_calls_eval) { bool Scope::PropagateScopeInfo(bool outer_scope_calls_eval,
bool outer_scope_is_eval_scope) {
if (outer_scope_calls_eval) { if (outer_scope_calls_eval) {
outer_scope_calls_eval_ = true; outer_scope_calls_eval_ = true;
} }
bool b = scope_calls_eval_ || outer_scope_calls_eval_; if (outer_scope_is_eval_scope) {
outer_scope_is_eval_scope_ = true;
}
bool calls_eval = scope_calls_eval_ || outer_scope_calls_eval_;
bool is_eval = is_eval_scope() || outer_scope_is_eval_scope_;
for (int i = 0; i < inner_scopes_.length(); i++) { for (int i = 0; i < inner_scopes_.length(); i++) {
Scope* inner_scope = inner_scopes_[i]; Scope* inner_scope = inner_scopes_[i];
if (inner_scope->PropagateScopeInfo(b)) { if (inner_scope->PropagateScopeInfo(calls_eval, is_eval)) {
inner_scope_calls_eval_ = true; inner_scope_calls_eval_ = true;
} }
if (inner_scope->force_eager_compilation_) { if (inner_scope->force_eager_compilation_) {
......
...@@ -166,10 +166,13 @@ class Scope: public ZoneObject { ...@@ -166,10 +166,13 @@ class Scope: public ZoneObject {
bool is_function_scope() const { return type_ == FUNCTION_SCOPE; } bool is_function_scope() const { return type_ == FUNCTION_SCOPE; }
bool is_global_scope() const { return type_ == GLOBAL_SCOPE; } bool is_global_scope() const { return type_ == GLOBAL_SCOPE; }
// Information about which scopes calls eval.
bool calls_eval() const { return scope_calls_eval_; }
bool outer_scope_calls_eval() const { return outer_scope_calls_eval_; }
// The scope immediately surrounding this scope, or NULL. // The scope immediately surrounding this scope, or NULL.
Scope* outer_scope() const { return outer_scope_; } Scope* outer_scope() const { return outer_scope_; }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Accessors. // Accessors.
...@@ -290,6 +293,7 @@ class Scope: public ZoneObject { ...@@ -290,6 +293,7 @@ class Scope: public ZoneObject {
// Computed via PropagateScopeInfo. // Computed via PropagateScopeInfo.
bool outer_scope_calls_eval_; bool outer_scope_calls_eval_;
bool inner_scope_calls_eval_; bool inner_scope_calls_eval_;
bool outer_scope_is_eval_scope_;
bool force_eager_compilation_; bool force_eager_compilation_;
// Computed via AllocateVariables; function scopes only. // Computed via AllocateVariables; function scopes only.
...@@ -298,15 +302,18 @@ class Scope: public ZoneObject { ...@@ -298,15 +302,18 @@ class Scope: public ZoneObject {
// Create a non-local variable with a given name. // Create a non-local variable with a given name.
// These variables are looked up dynamically at runtime. // These variables are looked up dynamically at runtime.
Variable* NonLocal(Handle<String> name); Variable* NonLocal(Handle<String> name, Variable::Mode mode);
// Variable resolution. // Variable resolution.
Variable* LookupRecursive(Handle<String> name, bool inner_lookup); Variable* LookupRecursive(Handle<String> name,
bool inner_lookup,
Variable** invalidated_local);
void ResolveVariable(Scope* global_scope, VariableProxy* proxy); void ResolveVariable(Scope* global_scope, VariableProxy* proxy);
void ResolveVariablesRecursively(Scope* global_scope); void ResolveVariablesRecursively(Scope* global_scope);
// Scope analysis. // Scope analysis.
bool PropagateScopeInfo(bool outer_scope_calls_eval); bool PropagateScopeInfo(bool outer_scope_calls_eval,
bool outer_scope_is_eval_scope);
bool HasTrivialContext() const; bool HasTrivialContext() const;
// Predicates. // Predicates.
......
...@@ -110,6 +110,8 @@ const char* Variable::Mode2String(Mode mode) { ...@@ -110,6 +110,8 @@ const char* Variable::Mode2String(Mode mode) {
case VAR: return "VAR"; case VAR: return "VAR";
case CONST: return "CONST"; case CONST: return "CONST";
case DYNAMIC: return "DYNAMIC"; case DYNAMIC: return "DYNAMIC";
case DYNAMIC_GLOBAL: return "DYNAMIC_GLOBAL";
case DYNAMIC_LOCAL: return "DYNAMIC_LOCAL";
case INTERNAL: return "INTERNAL"; case INTERNAL: return "INTERNAL";
case TEMPORARY: return "TEMPORARY"; case TEMPORARY: return "TEMPORARY";
} }
...@@ -143,6 +145,7 @@ Variable::Variable(Scope* scope, ...@@ -143,6 +145,7 @@ Variable::Variable(Scope* scope,
mode_(mode), mode_(mode),
is_valid_LHS_(is_valid_LHS), is_valid_LHS_(is_valid_LHS),
is_this_(is_this), is_this_(is_this),
local_if_not_shadowed_(NULL),
is_accessed_from_inner_scope_(false), is_accessed_from_inner_scope_(false),
rewrite_(NULL) { rewrite_(NULL) {
// names must be canonicalized for fast equality checks // names must be canonicalized for fast equality checks
...@@ -156,5 +159,4 @@ bool Variable::is_global() const { ...@@ -156,5 +159,4 @@ bool Variable::is_global() const {
return mode_ != TEMPORARY && scope_ != NULL && scope_->is_global_scope(); return mode_ != TEMPORARY && scope_ != NULL && scope_->is_global_scope();
} }
} } // namespace v8::internal } } // namespace v8::internal
...@@ -113,13 +113,27 @@ class Variable: public ZoneObject { ...@@ -113,13 +113,27 @@ class Variable: public ZoneObject {
enum Mode { enum Mode {
// User declared variables: // User declared variables:
VAR, // declared via 'var', and 'function' declarations VAR, // declared via 'var', and 'function' declarations
CONST, // declared via 'const' declarations CONST, // declared via 'const' declarations
// Variables introduced by the compiler: // Variables introduced by the compiler:
DYNAMIC, // always require dynamic lookup (we don't know the declaration) DYNAMIC, // always require dynamic lookup (we don't know
INTERNAL, // like VAR, but not user-visible (may or may not be in a // the declaration)
// context)
TEMPORARY // temporary variables (not user-visible), never in a context DYNAMIC_GLOBAL, // requires dynamic lookup, but we know that the
// variable is global unless it has been shadowed
// by an eval-introduced variable
DYNAMIC_LOCAL, // requires dynamic lookup, but we know that the
// variable is local and where it is unless it
// has been shadowed by an eval-introduced
// variable
INTERNAL, // like VAR, but not user-visible (may or may not
// be in a context)
TEMPORARY // temporary variables (not user-visible), never
// in a context
}; };
// Printing support // Printing support
...@@ -150,9 +164,24 @@ class Variable: public ZoneObject { ...@@ -150,9 +164,24 @@ class Variable: public ZoneObject {
return !is_this() && name().is_identical_to(n); return !is_this() && name().is_identical_to(n);
} }
bool is_dynamic() const {
return (mode_ == DYNAMIC ||
mode_ == DYNAMIC_GLOBAL ||
mode_ == DYNAMIC_LOCAL);
}
bool is_global() const; bool is_global() const;
bool is_this() const { return is_this_; } bool is_this() const { return is_this_; }
Variable* local_if_not_shadowed() const {
ASSERT(mode_ == DYNAMIC_LOCAL && local_if_not_shadowed_ != NULL);
return local_if_not_shadowed_;
}
void set_local_if_not_shadowed(Variable* local) {
local_if_not_shadowed_ = local;
}
Expression* rewrite() const { return rewrite_; } Expression* rewrite() const { return rewrite_; }
Slot* slot() const; Slot* slot() const;
...@@ -168,6 +197,8 @@ class Variable: public ZoneObject { ...@@ -168,6 +197,8 @@ class Variable: public ZoneObject {
bool is_valid_LHS_; bool is_valid_LHS_;
bool is_this_; bool is_this_;
Variable* local_if_not_shadowed_;
// Usage info. // Usage info.
bool is_accessed_from_inner_scope_; // set by variable resolver bool is_accessed_from_inner_scope_; // set by variable resolver
UseCount var_uses_; // uses of the variable value UseCount var_uses_; // uses of the variable value
......
// Copyright 2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Tests global loads from eval inside of a with statement.
var x = 27;
function test(obj, source) {
with (obj) {
eval(source);
}
}
// Test shadowing in eval scope.
test({ x: 42 }, "assertEquals(42, x)");
test({ y: 42 }, "assertEquals(27, x)");
// Test shadowing in local scope inside an eval scope.
test({ x: 42 }, "function f() { assertEquals(42, x) }; f();");
test({ y: 42 }, "function f() { assertEquals(27, x) }; f();");
// Test shadowing in local scope inside an eval scope. Deeper nesting
// this time.
test({ x: 42 }, "function f() { function g() { assertEquals(42, x) }; g() }; f();");
test({ y: 42 }, "function f() { function g() { assertEquals(27, x) }; g() }; f();");
// Test shadowing in local scope inside an eval scope with eval calls in the eval scopes.
test({ x: 42 }, "function f() { eval('1'); assertEquals(42, x) }; f();");
test({ y: 42 }, "function f() { eval('1'); assertEquals(27, x) }; f();");
// Test shadowing in local scope inside an eval scope with eval calls
// in the eval scopes. Deeper nesting this time.
test({ x: 42 }, "function f() { function g() { eval('1'); assertEquals(42, x) }; g() }; f();");
test({ y: 42 }, "function f() { function g() { eval('1'); assertEquals(27, x) }; g() }; f();");
// Copyright 2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Tests loads of local properties from eval.
function test(source) {
var x = 27;
eval(source);
}
test("assertEquals(27, x);");
test("(function() { assertEquals(27, x) })();");
// Copyright 2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Tests loading of properties across eval calls.
var x = 1;
// Test loading across an eval call that does not shadow variables.
function testNoShadowing() {
var y = 2;
function f() {
eval('1');
assertEquals(1, x);
assertEquals(2, y);
function g() {
assertEquals(1, x);
assertEquals(2, y);
}
g();
}
f();
}
testNoShadowing();
// Test loading across eval calls that do not shadow variables.
function testNoShadowing2() {
var y = 2;
eval('1');
function f() {
eval('1');
assertEquals(1, x);
assertEquals(2, y);
function g() {
assertEquals(1, x);
assertEquals(2, y);
}
g();
}
f();
}
testNoShadowing2();
// Test loading across an eval call that shadows variables.
function testShadowing() {
var y = 2;
function f() {
eval('var x = 3; var y = 4;');
assertEquals(3, x);
assertEquals(4, y);
function g() {
assertEquals(3, x);
assertEquals(4, y);
}
g();
}
f();
}
testShadowing();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment