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