deps: update v8 to 4.3.61.21
[platform/upstream/nodejs.git] / deps / v8 / test / mjsunit / debug-set-variable-value.js
1 // Copyright 2012 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
28 // Flags: --expose-debug-as debug
29
30 // Get the Debug object exposed from the debug context global object.
31 var Debug = debug.Debug;
32 var DebugCommandProcessor = debug.DebugCommandProcessor;
33
34 // Accepts a function/closure 'fun' that must have a debugger statement inside.
35 // A variable 'variable_name' must be initialized before debugger statement
36 // and returned after the statement. The test will alter variable value when
37 // on debugger statement and check that returned value reflects the change.
38 function RunPauseTest(scope_number, expected_old_result, variable_name,
39     new_value, expected_new_result, fun) {
40   var actual_old_result = fun();
41   assertEquals(expected_old_result, actual_old_result);
42
43   var listener_delegate;
44   var listener_called = false;
45   var exception = null;
46
47   function listener_delegate(exec_state) {
48     var scope = exec_state.frame(0).scope(scope_number);
49     scope.setVariableValue(variable_name, new_value);
50   }
51
52   function listener(event, exec_state, event_data, data) {
53     try {
54       if (event == Debug.DebugEvent.Break) {
55         listener_called = true;
56         listener_delegate(exec_state);
57       }
58     } catch (e) {
59       exception = e;
60     }
61   }
62
63   // Add the debug event listener.
64   Debug.setListener(listener);
65
66   var actual_new_value;
67   try {
68     actual_new_result = fun();
69   } finally {
70     Debug.setListener(null);
71   }
72
73   if (exception != null) {
74    assertUnreachable("Exception in listener\n" + exception.stack);
75   }
76   assertTrue(listener_called);
77
78   assertEquals(expected_new_result, actual_new_result);
79 }
80
81 // Accepts a closure 'fun' that returns a variable from it's outer scope.
82 // The test changes the value of variable via the handle to function and checks
83 // that the return value changed accordingly.
84 function RunClosureTest(scope_number, expected_old_result, variable_name,
85     new_value, expected_new_result, fun) {
86   var actual_old_result = fun();
87   assertEquals(expected_old_result, actual_old_result);
88
89   var fun_mirror = Debug.MakeMirror(fun);
90
91   var scope = fun_mirror.scope(scope_number);
92   scope.setVariableValue(variable_name, new_value);
93
94   var actual_new_result = fun();
95
96   assertEquals(expected_new_result, actual_new_result);
97 }
98
99
100 function ClosureTestCase(scope_index, old_result, variable_name, new_value,
101     new_result, success_expected, factory) {
102   this.scope_index_ = scope_index;
103   this.old_result_ = old_result;
104   this.variable_name_ = variable_name;
105   this.new_value_ = new_value;
106   this.new_result_ = new_result;
107   this.success_expected_ = success_expected;
108   this.factory_ = factory;
109 }
110
111 ClosureTestCase.prototype.run_pause_test = function() {
112   var th = this;
113   var fun = this.factory_(true);
114   this.run_and_catch_(function() {
115     RunPauseTest(th.scope_index_ + 1, th.old_result_, th.variable_name_,
116         th.new_value_, th.new_result_, fun);
117   });
118 }
119
120 ClosureTestCase.prototype.run_closure_test = function() {
121   var th = this;
122   var fun = this.factory_(false);
123   this.run_and_catch_(function() {
124     RunClosureTest(th.scope_index_, th.old_result_, th.variable_name_,
125         th.new_value_, th.new_result_, fun);
126   });
127 }
128
129 ClosureTestCase.prototype.run_and_catch_ = function(runnable) {
130   if (this.success_expected_) {
131     runnable();
132   } else {
133     assertThrows(runnable);
134   }
135 }
136
137
138 // Test scopes visible from closures.
139
140 var closure_test_cases = [
141   new ClosureTestCase(0, 'cat', 'v1', 5, 5, true,
142       function Factory(debug_stop) {
143     var v1 = 'cat';
144     return function() {
145       if (debug_stop) debugger;
146       return v1;
147     }
148   }),
149
150   new ClosureTestCase(0, 4, 't', 7, 9, true, function Factory(debug_stop) {
151     var t = 2;
152     var r = eval("t");
153     return function() {
154       if (debug_stop) debugger;
155       return r + t;
156     }
157   }),
158
159   new ClosureTestCase(0, 6, 't', 10, 13, true, function Factory(debug_stop) {
160     var t = 2;
161     var r = eval("t = 3");
162     return function() {
163       if (debug_stop) debugger;
164       return r + t;
165     }
166   }),
167
168   new ClosureTestCase(0, 17, 's', 'Bird', 'Bird', true,
169       function Factory(debug_stop) {
170     eval("var s = 17");
171     return function() {
172       if (debug_stop) debugger;
173       return s;
174     }
175   }),
176
177   new ClosureTestCase(2, 'capybara', 'foo', 77, 77, true,
178       function Factory(debug_stop) {
179     var foo = "capybara";
180     return (function() {
181       var bar = "fish";
182       try {
183         throw {name: "test exception"};
184       } catch (e) {
185         return function() {
186           if (debug_stop) debugger;
187           bar = "beast";
188           return foo;
189         }
190       }
191     })();
192   }),
193
194   new ClosureTestCase(0, 'AlphaBeta', 'eee', 5, '5Beta', true,
195       function Factory(debug_stop) {
196     var foo = "Beta";
197     return (function() {
198       var bar = "fish";
199       try {
200         throw "Alpha";
201       } catch (eee) {
202         return function() {
203           if (debug_stop) debugger;
204           return eee + foo;
205         }
206       }
207     })();
208   })
209 ];
210
211 for (var i = 0; i < closure_test_cases.length; i++) {
212   closure_test_cases[i].run_pause_test();
213 }
214
215 for (var i = 0; i < closure_test_cases.length; i++) {
216   closure_test_cases[i].run_closure_test();
217 }
218
219
220 // Test local scope.
221
222 RunPauseTest(0, 'HelloYou', 'u', 'We', 'HelloWe', (function Factory() {
223   return function() {
224     var u = "You";
225     var v = "Hello";
226     debugger;
227     return v + u;
228   }
229 })());
230
231 RunPauseTest(0, 'Helloworld', 'p', 'GoodBye', 'HelloGoodBye',
232     (function Factory() {
233   function H(p) {
234     var v = "Hello";
235     debugger;
236     return v + p;
237   }
238   return function() {
239     return H("world");
240   }
241 })());
242
243 RunPauseTest(0, 'mouse', 'v1', 'dog', 'dog', (function Factory() {
244   return function() {
245     var v1 = 'cat';
246     eval("v1 = 'mouse'");
247     debugger;
248     return v1;
249   }
250 })());
251
252 RunPauseTest(0, 'mouse', 'v1', 'dog', 'dog', (function Factory() {
253   return function() {
254     eval("var v1 = 'mouse'");
255     debugger;
256     return v1;
257   }
258 })());
259
260
261 // Check that we correctly update local variable that
262 // is referenced from an inner closure.
263 RunPauseTest(0, 'Blue', 'v', 'Green', 'Green', (function Factory() {
264   return function() {
265     function A() {
266       var v = "Blue";
267       function Inner() {
268         return void v;
269       }
270       debugger;
271       return v;
272     }
273     return A();
274   }
275 })());
276
277 // Check that we correctly update parameter, that is known to be stored
278 // both on stack and in heap.
279 RunPauseTest(0, 5, 'p', 2012, 2012, (function Factory() {
280   return function() {
281     function A(p) {
282       function Inner() {
283         return void p;
284       }
285       debugger;
286       return p;
287     }
288     return A(5);
289   }
290 })());
291
292
293 // Test value description protocol JSON
294
295 assertEquals(true, DebugCommandProcessor.resolveValue_({value: true}));
296
297 assertSame(null, DebugCommandProcessor.resolveValue_({type: "null"}));
298 assertSame(undefined,
299     DebugCommandProcessor.resolveValue_({type: "undefined"}));
300
301 assertSame("123", DebugCommandProcessor.resolveValue_(
302     {type: "string", stringDescription: "123"}));
303 assertSame(123, DebugCommandProcessor.resolveValue_(
304     {type: "number", stringDescription: "123"}));
305
306 assertSame(Number, DebugCommandProcessor.resolveValue_(
307     {handle: Debug.MakeMirror(Number).handle()}));
308 assertSame(RunClosureTest, DebugCommandProcessor.resolveValue_(
309     {handle: Debug.MakeMirror(RunClosureTest).handle()}));