1// Copyright 2011 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6//     * Redistributions of source code must retain the above copyright
7//       notice, this list of conditions and the following disclaimer.
8//     * Redistributions in binary form must reproduce the above
9//       copyright notice, this list of conditions and the following
10//       disclaimer in the documentation and/or other materials provided
11//       with the distribution.
12//     * Neither the name of Google Inc. nor the names of its
13//       contributors may be used to endorse or promote products derived
14//       from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28L: with ({x:12}) {
29  assertEquals(12, x);
30  break L;
31  assertTrue(false);
32}
33
34do {
35  with ({x:15}) {
36    assertEquals(15, x);
37    continue;
38    assertTrue(false);
39  }
40} while (false);
41
42var caught = false;
43try {
44  with ({x:18}) { throw 25; assertTrue(false); }
45} catch (e) {
46  caught = true;
47  assertEquals(25, e);
48  with ({y:19}) {
49    assertEquals(19, y);
50    try {
51      // NOTE: This checks that the object containing x has been
52      // removed from the context chain.
53      x;
54      assertTrue(false);  // should not reach here
55    } catch (e2) {
56      assertTrue(e2 instanceof ReferenceError);
57    }
58  }
59}
60assertTrue(caught);
61
62
63// We want to test the context chain shape.  In each of the tests cases
64// below, the outer with is to force a runtime lookup of the identifier 'x'
65// to actually verify that the inner context has been discarded.  A static
66// lookup of 'x' might accidentally succeed.
67with ({x: 'outer'}) {
68  label: {
69    with ({x: 'inner'}) {
70      break label;
71    }
72  }
73  assertEquals('outer', x);
74}
75
76
77with ({x: 'outer'}) {
78  label: {
79    with ({x: 'middle'}) {
80      with ({x: 'inner'}) {
81        break label;
82      }
83    }
84  }
85  assertEquals('outer', x);
86}
87
88
89with ({x: 'outer'}) {
90  for (var i = 0; i < 10; ++i) {
91    with ({x: 'inner' + i}) {
92      continue;
93    }
94  }
95  assertEquals('outer', x);
96}
97
98
99with ({x: 'outer'}) {
100  label: for (var i = 0; i < 10; ++i) {
101    with ({x: 'middle' + i}) {
102      for (var j = 0; j < 10; ++j) {
103        with ({x: 'inner' + j}) {
104          continue label;
105        }
106      }
107    }
108  }
109  assertEquals('outer', x);
110}
111
112
113with ({x: 'outer'}) {
114  try {
115    with ({x: 'inner'}) {
116      throw 0;
117    }
118  } catch (e) {
119    assertEquals('outer', x);
120  }
121}
122
123
124with ({x: 'outer'}) {
125  try {
126    with ({x: 'middle'}) {
127      with ({x: 'inner'}) {
128        throw 0;
129      }
130    }
131  } catch (e) {
132    assertEquals('outer', x);
133  }
134}
135
136
137try {
138  with ({x: 'outer'}) {
139    try {
140      with ({x: 'inner'}) {
141        throw 0;
142      }
143    } finally {
144      assertEquals('outer', x);
145    }
146  }
147} catch (e) {
148  if (e instanceof MjsUnitAssertionError) throw e;
149}
150
151
152try {
153  with ({x: 'outer'}) {
154    try {
155      with ({x: 'middle'}) {
156        with ({x: 'inner'}) {
157          throw 0;
158        }
159      }
160    } finally {
161      assertEquals('outer', x);
162    }
163  }
164} catch (e) {
165  if (e instanceof MjsUnitAssertionError) throw e;
166}
167
168
169// Verify that the context is correctly set in the stack frame after exiting
170// from with.
171function f() {}
172
173with ({x: 'outer'}) {
174  label: {
175    with ({x: 'inner'}) {
176      break label;
177    }
178  }
179  f();  // The context could be restored from the stack after the call.
180  assertEquals('outer', x);
181}
182
183
184with ({x: 'outer'}) {
185  for (var i = 0; i < 10; ++i) {
186    with ({x: 'inner' + i}) {
187      continue;
188    }
189  }
190  f();
191  assertEquals('outer', x);
192}
193
194
195with ({x: 'outer'}) {
196  try {
197    with ({x: 'inner'}) {
198      throw 0;
199    }
200  } catch (e) {
201    f();
202    assertEquals('outer', x);
203  }
204}
205
206
207try {
208  with ({x: 'outer'}) {
209    try {
210      with ({x: 'inner'}) {
211        throw 0;
212      }
213    } finally {
214      f();
215      assertEquals('outer', x);
216    }
217  }
218} catch (e) {
219  if (e instanceof MjsUnitAssertionError) throw e;
220}
221