Home | History | Annotate | Download | only in mjsunit
      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 // Get the Debug object exposed from the debug context global object.
     30 
     31 Debug = debug.Debug
     32 
     33 function FindCallFrame(exec_state, frame_code) {
     34   var number = Number(frame_code);
     35   if (number >= 0) {
     36     return exec_state.frame(number);
     37   } else {
     38     for (var i = 0; i < exec_state.frameCount(); i++) {
     39       var frame = exec_state.frame(i);
     40       var func_mirror = frame.func();
     41       if (frame_code == func_mirror.name()) {
     42         return frame;
     43       }
     44     }
     45   }
     46   throw new Error("Failed to find function name " + function_name);
     47 }
     48 
     49 function TestCase(test_scenario, expected_output) {
     50   // Global variable, accessed from eval'd script.
     51   test_output = "";
     52 
     53   function TestCode() {
     54     function A() {
     55       // Extra stack variable. To make function not slim.
     56       // Restarter doesn't work on slim function when stopped on 'debugger'
     57       // statement. (There is no padding for 'debugger' statement).
     58       var o = {};
     59       test_output += 'A';
     60       test_output += '=';
     61       debugger;
     62       return 'Capybara';
     63     }
     64     function B(p1, p2) {
     65       test_output += 'B';
     66       return A();
     67     }
     68     function C() {
     69       test_output += 'C';
     70       // Function call with argument adaptor is intentional.
     71       return B();
     72     }
     73     function D() {
     74       test_output += 'D';
     75       // Function call with argument adaptor is intentional.
     76       return C(1, 2);
     77     }
     78     function E() {
     79       test_output += 'E';
     80       return D();
     81     }
     82     function F() {
     83       test_output += 'F';
     84       return E();
     85     }
     86     return F();
     87   }
     88 
     89   var scenario_pos = 0;
     90 
     91   function DebuggerStatementHandler(exec_state) {
     92     while (true) {
     93       assertTrue(scenario_pos < test_scenario.length);
     94       var change_code = test_scenario[scenario_pos++];
     95       if (change_code == '=') {
     96         // Continue.
     97         return;
     98       }
     99       var frame = FindCallFrame(exec_state, change_code);
    100       // Throws if fails.
    101       Debug.LiveEdit.RestartFrame(frame);
    102     }
    103   }
    104 
    105   var saved_exception = null;
    106 
    107   function listener(event, exec_state, event_data, data) {
    108     if (saved_exception != null) {
    109       return;
    110     }
    111     if (event == Debug.DebugEvent.Break) {
    112       try {
    113         DebuggerStatementHandler(exec_state);
    114       } catch (e) {
    115         saved_exception = e;
    116       }
    117     } else {
    118       print("Other: " + event);
    119     }
    120   }
    121 
    122   Debug.setListener(listener);
    123   assertEquals("Capybara", TestCode());
    124   Debug.setListener(null);
    125 
    126   if (saved_exception) {
    127     print("Exception: " + saved_exception);
    128     print("Stack: " + saved_exception.stack);
    129     assertUnreachable();
    130   }
    131 
    132   print(test_output);
    133 
    134   assertEquals(expected_output, test_output);
    135 }
    136 
    137 TestCase('0==', "FEDCBA=A=");
    138 TestCase('1==', "FEDCBA=BA=");
    139 TestCase('2==', "FEDCBA=CBA=");
    140 TestCase('3==', "FEDCBA=DCBA=");
    141 TestCase('4==', "FEDCBA=EDCBA=");
    142 TestCase('5==', "FEDCBA=FEDCBA=");
    143 
    144 TestCase('=', "FEDCBA=");
    145 
    146 TestCase('C==', "FEDCBA=CBA=");
    147 
    148 TestCase('B=C=A=D==', "FEDCBA=BA=CBA=A=DCBA=");
    149 
    150 // Successive restarts don't work now and require additional fix.
    151 //TestCase('BCDE==', "FEDCBA=EDCBA=");
    152 //TestCase('BC=BCDE==', "FEDCBA=CBA=EDCBA=");
    153 //TestCase('EF==', "FEDCBA=FEDCBA=");
    154