Index: test/mjsunit/with-leave.js |
=================================================================== |
--- test/mjsunit/with-leave.js (revision 8931) |
+++ test/mjsunit/with-leave.js (working copy) |
@@ -1,4 +1,4 @@ |
-// Copyright 2008 the V8 project authors. All rights reserved. |
+// Copyright 2011 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: |
@@ -59,3 +59,162 @@ |
} |
assertTrue(caught); |
+ |
+// We want to test the context chain shape. In each of the tests cases |
+// below, the outer with is to force a runtime lookup of the identifier 'x' |
+// to actually verify that the inner context has been discarded. A static |
+// lookup of 'x' might accidentally succeed. |
+with ({x: 'outer'}) { |
+ label: { |
+ with ({x: 'inner'}) { |
+ break label; |
+ } |
+ } |
+ assertEquals('outer', x); |
+} |
+ |
+ |
+with ({x: 'outer'}) { |
+ label: { |
+ with ({x: 'middle'}) { |
+ with ({x: 'inner'}) { |
+ break label; |
+ } |
+ } |
+ } |
+ assertEquals('outer', x); |
+} |
+ |
+ |
+with ({x: 'outer'}) { |
+ for (var i = 0; i < 10; ++i) { |
+ with ({x: 'inner' + i}) { |
+ continue; |
+ } |
+ } |
+ assertEquals('outer', x); |
+} |
+ |
+ |
+with ({x: 'outer'}) { |
+ label: for (var i = 0; i < 10; ++i) { |
+ with ({x: 'middle' + i}) { |
+ for (var j = 0; j < 10; ++j) { |
+ with ({x: 'inner' + j}) { |
+ continue label; |
+ } |
+ } |
+ } |
+ } |
+ assertEquals('outer', x); |
+} |
+ |
+ |
+with ({x: 'outer'}) { |
+ try { |
+ with ({x: 'inner'}) { |
+ throw 0; |
+ } |
+ } catch (e) { |
+ assertEquals('outer', x); |
+ } |
+} |
+ |
+ |
+with ({x: 'outer'}) { |
+ try { |
+ with ({x: 'middle'}) { |
+ with ({x: 'inner'}) { |
+ throw 0; |
+ } |
+ } |
+ } catch (e) { |
+ assertEquals('outer', x); |
+ } |
+} |
+ |
+ |
+try { |
+ with ({x: 'outer'}) { |
+ try { |
+ with ({x: 'inner'}) { |
+ throw 0; |
+ } |
+ } finally { |
+ assertEquals('outer', x); |
+ } |
+ } |
+} catch (e) { |
+ if (e instanceof MjsUnitAssertionError) throw e; |
+} |
+ |
+ |
+try { |
+ with ({x: 'outer'}) { |
+ try { |
+ with ({x: 'middle'}) { |
+ with ({x: 'inner'}) { |
+ throw 0; |
+ } |
+ } |
+ } finally { |
+ assertEquals('outer', x); |
+ } |
+ } |
+} catch (e) { |
+ if (e instanceof MjsUnitAssertionError) throw e; |
+} |
+ |
+ |
+// Verify that the context is correctly set in the stack frame after exiting |
+// from with. |
+function f() {} |
+ |
+with ({x: 'outer'}) { |
+ label: { |
+ with ({x: 'inner'}) { |
+ break label; |
+ } |
+ } |
+ f(); // The context could be restored from the stack after the call. |
+ assertEquals('outer', x); |
+} |
+ |
+ |
+with ({x: 'outer'}) { |
+ for (var i = 0; i < 10; ++i) { |
+ with ({x: 'inner' + i}) { |
+ continue; |
+ } |
+ } |
+ f(); |
+ assertEquals('outer', x); |
+} |
+ |
+ |
+with ({x: 'outer'}) { |
+ try { |
+ with ({x: 'inner'}) { |
+ throw 0; |
+ } |
+ } catch (e) { |
+ f(); |
+ assertEquals('outer', x); |
+ } |
+} |
+ |
+ |
+try { |
+ with ({x: 'outer'}) { |
+ try { |
+ with ({x: 'inner'}) { |
+ throw 0; |
+ } |
+ } finally { |
+ f(); |
+ assertEquals('outer', x); |
+ } |
+ } |
+} catch (e) { |
+ if (e instanceof MjsUnitAssertionError) throw e; |
+} |