15a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org// Copyright 2012 the V8 project authors. All rights reserved.
25a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org// Redistribution and use in source and binary forms, with or without
35a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org// modification, are permitted provided that the following conditions are
45a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org// met:
55a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org//
65a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org//     * Redistributions of source code must retain the above copyright
75a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org//       notice, this list of conditions and the following disclaimer.
85a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org//     * Redistributions in binary form must reproduce the above
95a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org//       copyright notice, this list of conditions and the following
105a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org//       disclaimer in the documentation and/or other materials provided
115a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org//       with the distribution.
125a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org//     * Neither the name of Google Inc. nor the names of its
135a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org//       contributors may be used to endorse or promote products derived
145a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org//       from this software without specific prior written permission.
155a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org//
165a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
175a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
185a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
195a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
205a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
215a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
225a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
235a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
245a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
255a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
265a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
275a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org
285a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org// Flags: --expose-debug-as debug
295a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org// Get the Debug object exposed from the debug context global object.
305a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org
315a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.orgDebug = debug.Debug
325a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org
335a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.orgfunction FindCallFrame(exec_state, frame_code) {
345a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  var number = Number(frame_code);
355a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  if (number >= 0) {
365a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    return exec_state.frame(number);
375a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  } else {
385a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    for (var i = 0; i < exec_state.frameCount(); i++) {
395a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      var frame = exec_state.frame(i);
405a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      var func_mirror = frame.func();
415a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      if (frame_code == func_mirror.name()) {
425a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org        return frame;
435a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      }
445a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    }
455a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  }
465a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  throw new Error("Failed to find function name " + function_name);
475a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org}
485a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org
495a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.orgfunction TestCase(test_scenario, expected_output) {
505a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  // Global variable, accessed from eval'd script.
515a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  test_output = "";
525a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org
535a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  function TestCode() {
545a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    function A() {
555a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      // Extra stack variable. To make function not slim.
565a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      // Restarter doesn't work on slim function when stopped on 'debugger'
575a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      // statement. (There is no padding for 'debugger' statement).
585a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      var o = {};
595a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      test_output += 'A';
605a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      test_output += '=';
615a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      debugger;
625a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      return 'Capybara';
635a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    }
645a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    function B(p1, p2) {
655a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      test_output += 'B';
665a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      return A();
675a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    }
685a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    function C() {
695a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      test_output += 'C';
705a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      // Function call with argument adaptor is intentional.
715a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      return B();
725a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    }
735a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    function D() {
745a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      test_output += 'D';
755a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      // Function call with argument adaptor is intentional.
765a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      return C(1, 2);
775a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    }
785a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    function E() {
795a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      test_output += 'E';
805a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      return D();
815a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    }
825a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    function F() {
835a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      test_output += 'F';
845a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      return E();
855a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    }
865a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    return F();
875a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  }
885a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org
895a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  var scenario_pos = 0;
905a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org
915a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  function DebuggerStatementHandler(exec_state) {
925a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    while (true) {
935a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      assertTrue(scenario_pos < test_scenario.length);
945a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      var change_code = test_scenario[scenario_pos++];
955a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      if (change_code == '=') {
965a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org        // Continue.
975a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org        return;
985a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      }
995a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      var frame = FindCallFrame(exec_state, change_code);
1005a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      // Throws if fails.
1015a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      Debug.LiveEdit.RestartFrame(frame);
1025a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    }
1035a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  }
1045a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org
1055a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  var saved_exception = null;
1065a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org
1075a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  function listener(event, exec_state, event_data, data) {
1085a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    if (saved_exception != null) {
1095a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      return;
1105a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    }
1115a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    if (event == Debug.DebugEvent.Break) {
1125a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      try {
1135a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org        DebuggerStatementHandler(exec_state);
1145a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      } catch (e) {
1155a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org        saved_exception = e;
1165a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      }
1175a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    } else {
1185a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      print("Other: " + event);
1195a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    }
1205a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  }
1215a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org
1225a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  Debug.setListener(listener);
1235a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  assertEquals("Capybara", TestCode());
1245a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  Debug.setListener(null);
1255a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org
1265a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  if (saved_exception) {
1275a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    print("Exception: " + saved_exception);
1285a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    print("Stack: " + saved_exception.stack);
1295a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    assertUnreachable();
1305a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  }
1315a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org
1325a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  print(test_output);
1335a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org
1345a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  assertEquals(expected_output, test_output);
1355a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org}
1365a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org
1375a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.orgTestCase('0==', "FEDCBA=A=");
1385a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.orgTestCase('1==', "FEDCBA=BA=");
1395a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.orgTestCase('2==', "FEDCBA=CBA=");
1405a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.orgTestCase('3==', "FEDCBA=DCBA=");
1415a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.orgTestCase('4==', "FEDCBA=EDCBA=");
1425a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.orgTestCase('5==', "FEDCBA=FEDCBA=");
1435a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org
1445a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.orgTestCase('=', "FEDCBA=");
1455a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org
1465a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.orgTestCase('C==', "FEDCBA=CBA=");
1475a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org
1485a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.orgTestCase('B=C=A=D==', "FEDCBA=BA=CBA=A=DCBA=");
1495a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org
1505a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org// Successive restarts don't work now and require additional fix.
1515a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org//TestCase('BCDE==', "FEDCBA=EDCBA=");
1525a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org//TestCase('BC=BCDE==', "FEDCBA=CBA=EDCBA=");
1535a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org//TestCase('EF==', "FEDCBA=FEDCBA=");
154