Home | History | Annotate | Download | only in mjsunit
      1 // Copyright 2009 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 Debug = debug.Debug
     31 
     32 listenerComplete = false;
     33 exception = false;
     34 
     35 function safeEval(code) {
     36   try {
     37     return eval('(' + code + ')');
     38   } catch (e) {
     39     assertEquals(void 0, e);
     40     return undefined;
     41   }
     42 }
     43 
     44 
     45 // Send an evaluation request and return the handle of the result.
     46 function evaluateRequest(exec_state, arguments) {
     47   // Get the debug command processor.
     48   var dcp = exec_state.debugCommandProcessor("unspecified_running_state");
     49 
     50   // The base part of all evaluate requests.
     51   var base_request = '"seq":0,"type":"request","command":"evaluate"'
     52 
     53   // Generate request with the supplied arguments.
     54   var request;
     55   if (arguments) {
     56     request = '{' + base_request + ',"arguments":' + arguments + '}';
     57   } else {
     58     request = '{' + base_request + '}'
     59   }
     60 
     61   var response = safeEval(dcp.processDebugJSONRequest(request));
     62   assertTrue(response.success, request + ' -> ' + response.message);
     63 
     64   return response.body.handle;
     65 }
     66 
     67 
     68 // Send a lookup request and return the evaluated JSON response.
     69 function lookupRequest(exec_state, arguments, success) {
     70   // Get the debug command processor.
     71   var dcp = exec_state.debugCommandProcessor("unspecified_running_state");
     72 
     73   // The base part of all lookup requests.
     74   var base_request = '"seq":0,"type":"request","command":"lookup"'
     75   
     76   // Generate request with the supplied arguments.
     77   var request;
     78   if (arguments) {
     79     request = '{' + base_request + ',"arguments":' + arguments + '}';
     80   } else {
     81     request = '{' + base_request + '}'
     82   }
     83 
     84   var response = safeEval(dcp.processDebugJSONRequest(request));
     85   if (success) {
     86     assertTrue(response.success, request + ' -> ' + response.message);
     87   } else {
     88     assertFalse(response.success, request + ' -> ' + response.message);
     89   }
     90   assertEquals(response.running, dcp.isRunning(), request + ' -> expected not running');
     91 
     92   return response;
     93 }
     94 
     95 
     96 function listener(event, exec_state, event_data, data) {
     97   try {
     98   if (event == Debug.DebugEvent.Break) {
     99     // Test some illegal lookup requests.
    100     lookupRequest(exec_state, void 0, false);
    101     lookupRequest(exec_state, '{"handles":["a"]}', false);
    102     lookupRequest(exec_state, '{"handles":[-1]}', false);
    103 
    104     // Evaluate and get some handles.
    105     var handle_o = evaluateRequest(exec_state, '{"expression":"o"}');
    106     var handle_p = evaluateRequest(exec_state, '{"expression":"p"}');
    107     var handle_b = evaluateRequest(exec_state, '{"expression":"a"}');
    108     var handle_a = evaluateRequest(exec_state, '{"expression":"b","frame":1}');
    109     assertEquals(handle_o, handle_a);
    110     assertEquals(handle_a, handle_b);
    111     assertFalse(handle_o == handle_p, "o and p have he same handle");
    112 
    113     var response;
    114     var count;
    115     response = lookupRequest(exec_state, '{"handles":[' + handle_o + ']}', true);
    116     var obj = response.body[handle_o];
    117     assertTrue(!!obj, 'Object not found: ' + handle_o);
    118     assertEquals(handle_o, obj.handle);
    119     count = 0;
    120     for (i in obj.properties) {
    121       switch (obj.properties[i].name) {
    122         case 'o':
    123           obj.properties[i].ref = handle_o;
    124           count++;
    125           break;
    126         case 'p':
    127           obj.properties[i].ref = handle_p;
    128           count++;
    129           break;
    130       }
    131     }
    132     assertEquals(2, count, 'Either "o" or "p" not found');
    133     response = lookupRequest(exec_state, '{"handles":[' + handle_p + ']}', true);
    134     obj = response.body[handle_p];
    135     assertTrue(!!obj, 'Object not found: ' + handle_p);
    136     assertEquals(handle_p, obj.handle);
    137 
    138     // Check handles for functions on the stack.
    139     var handle_f = evaluateRequest(exec_state, '{"expression":"f"}');
    140     var handle_g = evaluateRequest(exec_state, '{"expression":"g"}');
    141     var handle_caller = evaluateRequest(exec_state, '{"expression":"f.caller"}');
    142 
    143     assertFalse(handle_f == handle_g, "f and g have he same handle");
    144     assertEquals(handle_g, handle_caller, "caller for f should be g");
    145 
    146     response = lookupRequest(exec_state, '{"handles":[' + handle_f + ']}', true);
    147     obj = response.body[handle_f];
    148     assertEquals(handle_f, obj.handle);
    149 
    150     count = 0;
    151     for (i in obj.properties) {
    152       var ref = obj.properties[i].ref;
    153       var arguments = '{"handles":[' + ref + ']}';
    154       switch (obj.properties[i].name) {
    155         case 'name':
    156           var response_name;
    157           response_name = lookupRequest(exec_state, arguments, true);
    158           assertEquals('string', response_name.body[ref].type);
    159           assertEquals("f", response_name.body[ref].value);
    160           count++;
    161           break;
    162         case 'length':
    163           var response_length;
    164           response_length = lookupRequest(exec_state, arguments, true);
    165           assertEquals('number', response_length.body[ref].type);
    166           assertEquals(1, response_length.body[ref].value);
    167           count++;
    168           break;
    169         case 'caller':
    170           assertEquals(handle_g, obj.properties[i].ref);
    171           count++;
    172           break;
    173       }
    174     }
    175     assertEquals(3, count, 'Either "name", "length" or "caller" not found');
    176 
    177 
    178     // Resolve all at once.
    179     var refs = [];
    180     for (i in obj.properties) {
    181       refs.push(obj.properties[i].ref);
    182     }
    183 
    184     var arguments = '{"handles":[' + refs.join(',') + ']}';
    185     response = lookupRequest(exec_state, arguments, true);
    186     count = 0;
    187     for (i in obj.properties) {
    188       var ref = obj.properties[i].ref;
    189       var val = response.body[ref];
    190       assertTrue(!!val, 'Failed to lookup "' + obj.properties[i].name + '"');
    191       switch (obj.properties[i].name) {
    192         case 'name':
    193           assertEquals('string', val.type);
    194           assertEquals("f", val.value);
    195           count++;
    196           break;
    197         case 'length':
    198           assertEquals('number', val.type);
    199           assertEquals(1, val.value);
    200           count++;
    201           break;
    202         case 'caller':
    203           assertEquals('function', val.type);
    204           assertEquals(handle_g, ref);
    205           count++;
    206           break;
    207       }
    208     }
    209     assertEquals(3, count, 'Either "name", "length" or "caller" not found');
    210 
    211     count = 0;
    212     for (var handle in response.body) {
    213       assertTrue(refs.indexOf(parseInt(handle)) != -1,
    214                  'Handle not in the request: ' + handle);
    215       count++;
    216     }
    217     assertEquals(count, obj.properties.length, 
    218                  'Unexpected number of resolved objects');
    219 
    220 
    221     // Indicate that all was processed.
    222     listenerComplete = true;
    223   }
    224   } catch (e) {
    225     exception = e
    226   };
    227 };
    228 
    229 // Add the debug event listener.
    230 Debug.setListener(listener);
    231 
    232 function f(a) {
    233   debugger;
    234 };
    235 
    236 function g(b) {
    237   f(b);
    238 };
    239 
    240 // Set a break point at return in f and invoke g to hit the breakpoint.
    241 Debug.setBreakPoint(f, 2, 0);
    242 o = {};
    243 p = {}
    244 o.o = o;
    245 o.p = p;
    246 p.o = o;
    247 p.p = p;
    248 g(o);
    249 
    250 assertFalse(exception, "exception in listener")
    251 // Make sure that the debug event listener vas invoked.
    252 assertTrue(listenerComplete, "listener did not run to completion: " + exception);
    253