Home | History | Annotate | Download | only in mjsunit
      1 // Copyright 2008 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 --nocrankshaft
     29 // Get the Debug object exposed from the debug context global object.
     30 Debug = debug.Debug
     31 
     32 function DebuggerStatement() {
     33   debugger;  /*pause*/
     34 }
     35 
     36 function TestCase(fun, frame_number, line_number) {
     37   var exception = false;
     38   var codeSnippet = undefined;
     39   var resultPositions = undefined;
     40   var step = 0;
     41 
     42   function listener(event, exec_state, event_data, data) {
     43     try {
     44       if (event == Debug.DebugEvent.Break ||
     45           event == Debug.DebugEvent.Exception) {
     46         if (step++ > 0) return;
     47         assertHasLineMark(/pause/, exec_state.frame(0));
     48         assertHasLineMark(/positions/, exec_state.frame(frame_number));
     49         var frame = exec_state.frame(frame_number);
     50         codeSnippet = frame.sourceLineText();
     51         resultPositions = frame.stepInPositions();
     52       }
     53     } catch (e) {
     54       exception = e
     55     }
     56 
     57     function assertHasLineMark(mark, frame) {
     58         var line = frame.sourceLineText();
     59         if (!mark.exec(frame.sourceLineText())) {
     60             throw new Error("Line " + line + " should contain mark " + mark);
     61         }
     62     }
     63   }
     64 
     65   Debug.setListener(listener);
     66 
     67   var breakpointId;
     68   if (line_number) breakpointId = Debug.setBreakPoint(fun, line_number);
     69 
     70   fun();
     71 
     72   if (line_number) Debug.clearBreakPoint(breakpointId);
     73 
     74   Debug.setListener(null);
     75 
     76   assertTrue(!exception, exception);
     77 
     78   var expectedPositions = {};
     79   var markPattern = new RegExp("/\\*#\\*/", "g");
     80 
     81   var matchResult;
     82   while ( (matchResult = markPattern.exec(codeSnippet)) ) {
     83     expectedPositions[matchResult.index] = true;
     84   }
     85 
     86   print(codeSnippet);
     87 
     88   var decoratedResult = codeSnippet;
     89 
     90   function replaceStringRange(s, pos, substitute) {
     91    return s.substring(0, pos) + substitute +
     92        s.substring(pos + substitute.length);
     93   }
     94 
     95   var markLength = 5;
     96   var unexpectedPositionFound = false;
     97 
     98   for (var i = 0; i < resultPositions.length; i++) {
     99     var col = resultPositions[i].position.column - markLength;
    100     if (expectedPositions[col]) {
    101       delete expectedPositions[col];
    102       decoratedResult = replaceStringRange(decoratedResult, col, "*YES*");
    103     } else {
    104       decoratedResult = replaceStringRange(decoratedResult, col, "!BAD!");
    105       unexpectedPositionFound = true;
    106     }
    107   }
    108 
    109   print(decoratedResult);
    110 
    111   for (var n in expectedPositions) {
    112     assertTrue(false, "Some positions are not reported: " + decoratedResult);
    113     break;
    114   }
    115   assertFalse(unexpectedPositionFound, "Found unexpected position: " +
    116       decoratedResult);
    117 }
    118 
    119 function TestCaseWithDebugger(fun) {
    120   TestCase(fun, 1);
    121 }
    122 
    123 function TestCaseWithBreakpoint(fun, line_number, frame_number) {
    124   TestCase(fun, frame_number, line_number);
    125 }
    126 
    127 function TestCaseWithException(fun, frame_number) {
    128   Debug.setBreakOnException();
    129   TestCase(fun, frame_number);
    130   Debug.clearBreakOnException();
    131 }
    132 
    133 
    134 // Test cases.
    135 
    136 // Step in position, when the function call that we are standing at is already
    137 // being executed.
    138 var fun = function() {
    139   function g(p) {
    140     throw String(p); /*pause*/
    141   }
    142   try {
    143     var res = [ g(1), /*#*/g(2) ]; /*positions*/
    144   } catch (e) {
    145   }
    146 };
    147 TestCaseWithBreakpoint(fun, 2, 1);
    148 TestCaseWithException(fun, 1);
    149 
    150 
    151 // Step in position, when the function call that we are standing at is raising
    152 // an exception.
    153 var fun = function() {
    154   var o = {
    155     g: function(p) {
    156       throw p;
    157     }
    158   };
    159   try {
    160     var res = [ /*#*/f(1), /*#*/g(2) ]; /*pause, positions*/
    161   } catch (e) {
    162   }
    163 };
    164 TestCaseWithException(fun, 0);
    165 
    166 
    167 // Step-in position, when already paused almost on the first call site.
    168 var fun = function() {
    169   function g(p) {
    170     throw p;
    171   }
    172   try {
    173     var res = [ /*#*/g(Math.rand), /*#*/g(2) ]; /*pause, positions*/
    174   } catch (e) {
    175   }
    176 };
    177 TestCaseWithBreakpoint(fun, 5, 0);
    178 
    179 // Step-in position, when already paused on the first call site.
    180 var fun = function() {
    181   function g() {
    182     throw "Debug";
    183   }
    184   try {
    185     var res = [ /*#*/g(), /*#*/g() ]; /*pause, positions*/
    186   } catch (e) {
    187   }
    188 };
    189 TestCaseWithBreakpoint(fun, 5, 0);
    190 
    191 
    192 // Method calls.
    193 var fun = function() {
    194   var data = {
    195     a: function() {}
    196   };
    197   var res = [ DebuggerStatement(), data./*#*/a(), data[/*#*/String("a")]/*#*/(), data["a"]/*#*/(), data.a, data["a"] ]; /*positions*/
    198 };
    199 TestCaseWithDebugger(fun);
    200 
    201 // Function call on a value.
    202 var fun = function() {
    203   function g(p) {
    204       return g;
    205   }
    206   var res = [ DebuggerStatement(), /*#*/g(2), /*#*/g(2)/*#*/(3), /*#*/g(0)/*#*/(0)/*#*/(g) ]; /*positions*/
    207 };
    208 TestCaseWithDebugger(fun);
    209 
    210 // Local function call, closure function call,
    211 // local function construction call.
    212 var fun = (function(p) {
    213   return function() {
    214     function f(a, b) {
    215     }
    216     var res = /*#*/f(DebuggerStatement(), /*#*/p(/*#*/new f())); /*positions*/
    217   };
    218 })(Object);
    219 TestCaseWithDebugger(fun);
    220 
    221 // Global function, global object construction, calls before pause point.
    222 var fun = (function(p) {
    223   return function() {
    224     var res = [ Math.abs(new Object()), DebuggerStatement(), Math./*#*/abs(4), /*#*/new Object()./*#*/toString() ]; /*positions*/
    225   };
    226 })(Object);
    227 TestCaseWithDebugger(fun);
    228