Commits

Anonymous committed 7715545

added stopAt and continue to the ui prototype

  • Participants
  • Parent commits 65aa912

Comments (0)

Files changed (9)

File src/ecma-debugger/ecma-debugger.html

 <script src="ecma-debugger.js"></script>
 </head>
 <body>
-<div id='debug-container'>
+<div id='debug-container' class='frame-vertical'>
   <input type='button' value='clear output' onclick="document.getElementById('debug').innerHTML=''">
   <h2>Debug</h2>
   <pre id="debug"></pre>
 </div>
-<h2>Enviroment</h2>
-<div id="hello"></div>
-<h2>Configuration</h2>
-<div id="configuration"></div>
-<h2>Runtimes</h2>
-<ul id="runtime-ids"></ul>
-<h2>Scripts</h2>
-<ul id="scripts"></ul>
-<h2>Script</h2>
-<div id="source-view"></div>
+<div id='slider-for-debug-container' class='frame-slider-vertical'></div>
+<div id='control-container' class='frame-vertical'>
+  <div class='block'>
+    <h2>Enviroment</h2>
+    <div id="hello"></div>
+  </div>
+  <div class='block'>
+    <h2>Stop At</h2>
+    <div id="configuration"></div>
+  </div>
+  <div class='block'>
+    <h2>Continue</h2>
+    <div id="continues"></div>
+  </div>
+  <div class='block'>
+    <h2>Runtimes</h2>
+    <ul id="runtime-ids"></ul>
+  </div>
+  <div class='block'>
+    <h2>Scripts</h2>
+    <ul id="scripts"></ul>
+  </div>
+</div>
+<div id='slider-for-control-container' class='frame-slider-vertical'></div>
+
+<div id='inspection-container' class='frame-vertical'>
+  <h2>Backtrace</h2>
+  <div id="backtrace"></div>
+  <h2>Script</h2>
+  <div id="source-view"></div>
+</div>
 </body>
 </html>

File src/ecma-debugger/ecma-debugger.js

       {
         debug.output('not implemented: '+new XMLSerializer().serializeToString(xml));
         //alert("message not implemented: " +(new XMLSerializer().serializeToString(xml));
+        self.getData();
       }
       debug.formatXML(new XMLSerializer().serializeToString(xml));
     }
-    self.getData();
+    //self.getData();
   }
 
   var runtimes = {};
       }
     }
   }
+
+  var parseBacktrace = function(xml)
+  {
+
+  }
   
   var environment = {}
 
     }
     self.setConfiguration.apply(self, config_arr);
     document.getElementById('configuration').render(templates.configStopAt(config));
+    document.getElementById('continues').render(templates.continues());
+    helpers.setUpListeners();
+    helpers.setUpVerticalFrames()
+    self.getData();
   }
 
   this['new-script'] = function(xml)
       script[child.nodeName] = child.firstChild.nodeValue;
     }
     scripts[scripts.length] = script;
-    addRuntime(script['runtime-id'])
+    addRuntime(script['runtime-id']);
+    self.getData();
   }
 
-  this['timeout'] = function() {}
+  this['timeout'] = function() 
+  {
+    self.getData();
+  }
 
   this['runtimes-reply'] = function(xml)
   {
     {
       throw "runtimes-reply, missing tag";
     }
+    self.getData();
   }
 
+  /*
+
+  <thread-stopped-at>
+  <runtime-id>2</runtime-id>
+  <thread-id>8</thread-id>
+  <script-id>10</script-id>
+  <line-number>2</line-number>
+  <stopped-reason>unknown</stopped-reason>
+</thread-stopped-at>
+
+<runtimes-reply>
+
+CONTINUE ::= "<continue>" 
+                 RUNTIME-ID 
+                 THREAD-ID 
+                 MODE 
+               "</continue>" ;
+RUNTIME-ID ::= "<runtime-id>" UNSIGNED "</runtime-id>" ;
+THREAD-ID ::= "<thread-id>" UNSIGNED "</thread-id>" ;
+MODE ::= "<mode>" 
+             ( "run" | "step-into-call" | "step-over-call" | "finish-call" )
+           "</mode>" ;
+*/
+
+  var __stopAt = {}; // there can be only one stop at at the time
+
+  var __stopAtId = 1;
+
+  var getStopAtId = function()
+  {
+    return __stopAtId++;
+  }
+
+  this['thread-stopped-at'] = function(xml)
+  {
+    var stopAt = {};
+    var id = getStopAtId();
+    var children = xml.documentElement.childNodes, child=null, i=0;
+    for ( ; child = children[i]; i++)
+    {
+      stopAt[child.nodeName] = child.firstChild.nodeValue;
+    }
+    __stopAt[id] = stopAt;
+    var line = parseInt( stopAt['line-number'] );
+    if( typeof line == 'number' )
+    {
+      //self.backtrace(stopAt);
+      helpers.showLine( stopAt['script-id'], line );
+      helpers.disableContinues(id, false);
+    }
+    else
+    {
+      throw 'not a line number: '+stopAt['line-number'];
+    }
+  }
+/*
+
+  'runtime-id'
+  'script-id'
+  'script-type'
+  'script-data'
+  'uri'
+
+*/
   var scripts = [];
 
   this.getScripts=function(runtime_id)
     return ret;
   }
 
+  this.getScript=function(script_id)
+  {
+    var script = null, i=0;
+    for( ; script = scripts[i]; i++)
+    {
+      if(script['script-id'] == script_id)
+      {
+        return script;
+      }
+    }
+    return null;
+  }
+
 
 
   this.setup = function()
 
   /**** commands ****/
 
-  this.setConfiguration = function() 
+  this.setConfiguration = function() // stopAt
   {
     var msg = "<set-configuration>", type='', bol='', i=0; 
     for ( ; (type = arguments[i++]) && (bol=arguments[i]); i++ )
     proxy.POST("/" + service, msg);
   }
 
+  this.backtrace = function(stopAt)
+  {
+    var tag = getTagId();
+    var msg = "<backtrace>";
+    msg += "<tag>" + tag + "</tag>";
+    msg += "<runtime-id>" + stopAt['runtime-id'] + "</runtime-id>";
+    msg += "<thread-id>" + stopAt['thread-id'] + "</thread-id>";
+    msg += "<maxframes>" + 10 + "</maxframes>";  // not sure what is correct here;
+    msg += "</backtrace>";
+    setTagCB(tag, parseBacktrace);
+    proxy.POST("/" + service, msg);
+  }
+
+/*
+
+  <thread-stopped-at>
+  <runtime-id>2</runtime-id>
+  <thread-id>8</thread-id>
+  <script-id>10</script-id>
+  <line-number>2</line-number>
+  <stopped-reason>unknown</stopped-reason>
+</thread-stopped-at>
+
+
+CONTINUE ::= "<continue>" 
+                 RUNTIME-ID 
+                 THREAD-ID 
+                 MODE 
+               "</continue>" ;
+RUNTIME-ID ::= "<runtime-id>" UNSIGNED "</runtime-id>" ;
+THREAD-ID ::= "<thread-id>" UNSIGNED "</thread-id>" ;
+MODE ::= "<mode>" 
+             ( "run" | "step-into-call" | "step-over-call" | "finish-call" )
+           "</mode>" ;
+
+*/
+
+  this.__continue = function (stopAtId, mode)
+  {
+    var msg = "<continue>";
+    msg += "<runtime-id>" + __stopAt[stopAtId]['runtime-id'] + "</runtime-id>";
+    msg += "<thread-id>" + __stopAt[stopAtId]['thread-id'] + "</thread-id>";
+    msg += "<mode>" + mode + "</mode>";
+    msg += "</continue>";
+    proxy.POST("/" + service, msg);
+    self.getData();
+  }
+
   /**** tags handling ****/
 
   var tags = {};

File src/ecma-debugger/formatter.js

 var simple_js_parser=new function()
 {
+  /* adjusted to return fotmatted HTML */
+
   var parser=null;
   var __source=null;
   var __buffer='';
   var __previous_type='';
   var __previous_value='';
   var __string_delimiter=0;
-  var __cbo_onread=null;
-  var __cbo_online=null;
-  var __cbo_onfinish=null;
-
+  var __ret='<ol>';
+  var __line='';
   var WHITESPACE=
   {
     '\u0009': 1, //  Tab <TAB>
     '\u0020': 1, //  Space <SP>
     '\u00A0': 1  //  No-break space <NBSP>
   }
-
   var LINETERMINATOR=
   {
     '\u000A': 1, //  Line Feed <LF>
     '\u2028': 1, //  Line separator <LS>
     '\u2029': 1 //  Paragraph separator <PS>
   }
-
   var NUMBER=
   {
     '0': 1,
     '8': 1,
     '9': 1
   }
-
   var PUNCTUATOR=
   {
     '{': '{',
     ':': ':',
     '.': '.'
   }
-
-  var __not_before_slash=
-  {
-    ')': 1
-  }
-
   var PUNCTUATOR_2=
   {
     '=': '=',
     '&': '&',
     '|': '|'
   }
-
   var STRING_DELIMITER=
   {
     '"': 1,
     '\'': 1
   }
-
   var HEX_NUMBER=
   {
     '0': 1,
     'E': 1,
     'F': 1
   }
-
-
-
   var REG_EXP_FLAG=
   {
     'g': 1,
     'i': 1,
     'm': 1
   }
-
+  var PUNCTUATOR_DIV_PREDECESSOR=
+  {
+    ')': 1
+  }
+  var ESCAPE =
+  {
+    '<': '&lt;',
+    '&': '&amp;'
+  }
   var default_parser=function(c)
   {
     var CRLF='';
         {
           c=__source.charAt(++__pointer);
         }
-        if(__cbo_online)
+        if(__online)
         {
-          __cbo_online();
+          __online();
         }
         continue;
       }
           continue;
         }
         if( __previous_type=='IDENTIFIER' || __previous_type=='NUMBER' || 
-          (__previous_type=='PUNCTUATOR' && __previous_value in __not_before_slash))
+          (__previous_type=='PUNCTUATOR' && __previous_value in PUNCTUATOR_DIV_PREDECESSOR))
         {
           __type='DIV_PUNCTUIATOR';
           if(c=='=') 
       }
       do
       {
-        __buffer+=c=='<'?'&lt;':c;
+        __buffer+=c in ESCAPE ? ESCAPE[c] : c;
         c=__source.charAt(++__pointer);
       }
       while (c && !(c in PUNCTUATOR  || c=='/' || c in LINETERMINATOR  || c in WHITESPACE));
     return c;
   }
 
-
-
   var string_parser=function(c)
   {
     while(c)
       {
         __buffer+=c;
         c=__source.charAt(++__pointer);
-        __buffer+=c=='<'?'&lt;':c;
+        __buffer+=c in ESCAPE ? ESCAPE[c] : c;
         c=__source.charAt(++__pointer);
+        continue;
       }
       if(c==__string_delimiter)
       {
         __type='IDENTIFIER';
         break;
       }
-      __buffer+=c=='<'?'&lt;':c;
+      __buffer+=c in ESCAPE ? ESCAPE[c] : c;
       c=__source.charAt(++__pointer);
     }
   }
 
-
   var multiline_comment_parser=function(c)
   {
     var CRLF='';
         {
           c=__source.charAt(++__pointer);
         }
-        if(__cbo_online)
+        if(__online)
         {
-          __cbo_online();
+          __online();
         }
         continue;
       }
         }
         continue;
       }
-      __buffer+=c=='<'?'&lt;':c;;
+      __buffer+=c in ESCAPE ? ESCAPE[c] : c;
       c=__source.charAt(++__pointer);
     }
   }
 
-
   var singleline_comment_parser=function(c)
   {
     var CRLF='';
         {
           c=__source.charAt(++__pointer);
         }
-        if(__cbo_online)
+        if(__online)
         {
-          __cbo_online();
+          __online();
         }
         return c;
       }
-      __buffer+=c=='<'?'&lt;':c;;
+      __buffer+=c in ESCAPE ? ESCAPE[c] : c;
       c=__source.charAt(++__pointer);
     }
   }
       {
         __buffer+=c;
         c=__source.charAt(++__pointer);
-        __buffer+=c=='<'?'&lt;':c;;
+        __buffer+=c in ESCAPE ? ESCAPE[c] : c;
         c=__source.charAt(++__pointer);
         continue;
       }
         __type='IDENTIFIER';
         return c;
       }
-      __buffer+=c=='<'?'&lt;':c;;
+      __buffer+=c in ESCAPE ? ESCAPE[c] : c;
       c=__source.charAt(++__pointer);
     }
   }
   {
     if(__buffer)
     {
-      if(__cbo_onread)
+      switch (__type)
       {
-        __cbo_onread(__type, __buffer);
+        case 'STRING':
+        {
+          __line += "<span class='string'>" +  __buffer + "</span>";
+          break;
+        }
+        case 'IDENTIFIER':
+        {
+          if(__buffer in js_keywords)
+          {
+            __line += "<span class='js_keywords'>" +  __buffer + "</span>";
+          }
+          else if(__buffer in js_builtins)
+          {
+            __line += "<span class='js_builtins'>" +  __buffer + "</span>";
+          }
+          else
+          {
+            __line += __buffer;
+          }
+          break;
+        }
+        case 'NUMBER':
+        {
+          __line += "<span class='number'>" +  __buffer + "</span>";
+          break;
+        }
+        case 'COMMENT':
+        {
+          __line += "<span class='comment'>" +  __buffer + "</span>";
+          break;
+        }
+        case 'REG_EXP':
+        {
+          __line += "<span class='reg_exp'>" +  __buffer + "</span>";
+          break;
+        }
+        default:
+        {
+          __line += __buffer;
+        }
       }
       if(__type=='IDENTIFIER')
       {
     __buffer='';
   }
 
-  this.parse=function(source, cbo)
+  var __online=function(c)
+  {
+    if( !__line ) 
+    {
+      __line += '\u00A0';
+    }
+    __ret += "<li><span>" + __line + "</span></li>";
+    __line='';
+
+  }
+
+  var __onfinish=function()
+  {
+    __online();
+    return __ret + "</ol>";
+  }
+
+  var __reset = function()
+  {
+    __ret='<ol>';
+    __line='';
+  }
+
+  this.parse=function(source)
   {
     ret='';
-    if(cbo)
-    {
-      __cbo_onread=cbo.onread;
-      __cbo_online=cbo.onlineterminator;
-      __cbo_onfinish=cbo.onfinish;
-    }
+    __reset();
     parser=default_parser;
     __previous_type='';
     __type='IDENTIFIER';
     var length=__source.length;
     __pointer=0;
     parser(__source.charAt(__pointer));
-    if(__cbo_onfinish)
+    if(__onfinish)
     {
-      return __cbo_onfinish();
+      return __onfinish();
     }
   }
 }
-
-/* end file */

File src/ecma-debugger/handlers.js

   {
     debugger.setConfiguration(event.target.value, event.target.checked ? 'yes' : 'no');
   }
+
+  this.__continue = function(event)
+  {
+    var id = event.target.__stop_at_id;
+    helpers.disableContinues(0, true);
+    debugger.__continue(id, event.target.getAttribute('mode'));
+  }
 }

File src/ecma-debugger/helpers.js

 helpers = new function()
 {
+  var self = this;
+
+  var __current_script_id = 0;
+
+  var __stop_at_id = 0;
+
   this.formatScript = function(data)
   {
     /* *
     var lines = data.split('\n'), length = lines.length, line='', i=0;
     for( ; i<length; i++)
     {
-      line = lines[i];
+      line = lines[i].replace(/</g, '&lt');
       if (!line.length) line ='\u00A0';
-      ret += "<li line='" + i + "'><span><![CDATA["+line+"]]></span></li>";
+      ret += "<li line='" + i + "'><span>"+line+"</span></li>";
     }
     ret +="</ol>";
     return ret;
     /* */
 
-    return simple_js_parser.parse(data, new helpers.GetJS());
+    return simple_js_parser.parse(data);
 
   }
 
-  this.GetJS = function()
+  this.showLine = function(scriptId, line)
   {
-    var ret='<ol>';
-    var line='';
-    var cursor=1;
-    var __puffer = '';
-    var reset_line=function()
+    opera.postError(scriptId+' '+line);
+    var s_c = document.getElementById('source-view'), script = null;
+    if( scriptId == __current_script_id )
     {
-      line += __puffer;
-      if( !line ) 
-      {
-        line += '\u00A0';
-      }
-
-        ret += "<li><span>" + line + "</span></li>";
-        __puffer='';
-        line='';
 
     }
-    var highlight=function(value, _class)
+    else
     {
-      line += __puffer +
-        "<span class='" + _class + "'>" +  value + "</span>";
-      __puffer = '';
-    }
-    this.onread=function(type, puffer)
-    {
-      /* 
-      WHITESPACE, 
-      LINE_TERMINATOR, 
-      NUMBER, 
-      STRING, 
-      PUNCTUATOR, 
-      DIV_PUNCTUIATOR, 
-      IDENTIFIER, 
-      REG_EXP
-      */
-      //opera.postError(type+' : '+puffer)
-      switch (type)
+      script = debugger.getScript(scriptId);
+      if(script)
       {
-        
-        case 'STRING':
-        {
-          highlight(puffer, 'string');
-          break;
-        }
-        case 'IDENTIFIER':
-        {
-          if(puffer in js_keywords)
-          {
-            highlight(puffer, 'js_keywords');
-          }
-          else if(puffer in js_builtins)
-          {
-            highlight(puffer, 'js_builtins');
-          }
-          else
-          {
-            __puffer += puffer;
-          }
-          break;
-        }
-        case 'NUMBER':
-        {
-          highlight(puffer, 'number');
-          break;
-        }
-        case 'COMMENT':
-        {
-          highlight(puffer, 'comment');
-          break;
-        }
-        case 'REG_EXP':
-        {
-          highlight(puffer, 'reg_exp');
-          break;
-        }
-        default:
-        {
-          __puffer += puffer;
-        }
+        __current_script_id = scriptId;
+        s_c.innerHTML = self.formatScript(script['script-data']);
+      }
+      else
+      {
+        throw "Script id not registered";
       }
     }
-    this.onlineterminator=function(c)
+    var __line = s_c.getElementsByTagName('li')[line-1];
+    var line_pointer = document.getElementById('line-pointer');
+    if(__line)
     {
-      reset_line();
+      if(line_pointer)
+      {
+        line_pointer.parentElement.removeChild(line_pointer);
+      }
+      line_pointer = s_c.firstChild.render
+      (
+        ['li', 
+          'id', 'line-pointer', 
+          'style', 'top:'+ __line.offsetTop +'px'
+        ]
+      );
+      //line_pointer.style.top = __line.offsetTop +'px';
+      document.getElementById('inspection-container').scrollTop = __line.offsetTop;
+
     }
-    this.onfinish=function()
+    else
     {
-      reset_line();
-      return ret + "</ol>";
+      throw "the script has no according line "+line;
+    }
+  }
+
+  this.disableContinues = function(stopAtId, bol)
+  {
+    __stop_at_id = stopAtId;
+    var inputs = document.getElementById('continues').getElementsByTagName('input'),
+        input = null, i=0;
+    for( ; input = inputs[i]; i++)
+    {
+      input.disabled = bol;
+      input.__stop_at_id = stopAtId;
+    }
+  }
+
+  var handleKeypress = function(event, id)
+  {
+    event.preventDefault();
+    event.stopPropagation();
+    var button = document.getElementById(id);
+    if(button && !button.disabled)
+    {
+      button.click();
+    }
+  }
+
+  var keypressListener = function(event)
+  {
+    switch(event.keyCode)
+    {
+      case 116: // F5
+      {
+        handleKeypress(event, 'continue-run');
+        break;
+      }
+      case 121: // F10
+      {
+        handleKeypress(event, 'continue-step-over-call');
+        break;
+      }
+      case 122: // F11
+      {
+        if(event.shiftKey)
+        {
+          handleKeypress(event, 'continue-finish-call');
+        }
+        else
+        {
+          handleKeypress(event, 'continue-step-into-call');
+        }
+        break;
+      }
+    }
+  }
+
+  this.setUpListeners = function()
+  {
+    document.addEventListener('keypress', keypressListener, true);
+  }
+
+  var min_height_vertical_frame = 150;
+
+  this.setUpVerticalFrames = function()
+  {
+    var children = document.body.childNodes, child = null, i = 0;
+    var __frames = [];
+    for( ; child = children[i]; i++)
+    {
+      
+      if( child.nodeType == 1 && child.hasClass('frame-vertical'))
+      {
+        __frames[__frames.length] = child;
+      }
+    }
+    var length = __frames.length;
+    var win_height = window.innerHeight;
+    var height = 0, styleHeight = 0;
+    for(i=0; child = __frames[i]; i++)
+    {
+      if( i == length-1 )
+      {
+        child.style.height = (win_height-6)+'px';
+      }
+      else
+      {
+        height = child.offsetHeight;
+        if (height<min_height_vertical_frame)
+        {
+          child.style.height = (min_height_vertical_frame-6)+'px';
+          height = child.offsetHeight;
+        }
+        win_height -= height;
+      }
     }
   }
 }

File src/ecma-debugger/style.css

+
+html, body {
+  overflow: hidden;
+  height:100%;
+  }
 
 body {
   padding:0;
   margin:0;
   font-family: 'Lucida Sans Unicode', Arial, sans-serif;
   font-size:.8em;
+  overflow: hidden;
   }
 
 body>div {
-  padding:1px .7em;
+  padding:0px .7em;
   }
 
 h2, h3 {
 
 #source-view {
   white-space: pre-wrap;
+  border:1px solid transparent; /* prevent any margin collapse */
+  position: relative;
   }
 
 #source-view li {
   color:#999;
+  line-height: 16px;
   }
 
 #source-view li span {
 .selected {
   background-color:#f00;
   color:#fff;
-  }
+  }
+
+.block {
+  float:left;
+  }
+
+#source-view #line-pointer {
+  position:absolute;
+  content: '\25B6';
+  color:#f00;
+  font-size: 20px;
+  list-style:none;
+  line-height:24px;
+  height:24px;
+  padding:0;
+  margin:0;
+  margin-top:-4px;
+  margin-left:-40px;
+  }
+
+.frame-vertical {
+  border: 1px solid #666;
+  border-bottom-width:5px;
+  overflow: auto;
+  position:relative;
+  }
+

File src/ecma-debugger/templates.js

     {
       ret[ret.length] = this.checkbox(n, config[n]); 
     }
-    return ['div', ['h3', 'Stop At']].concat([ret]);
+    return ['div'].concat([ret]);
+  }
+/*
+
+MODE ::= "<mode>" 
+             ( "run" | "step-into-call" | "step-over-call" | "finish-call" )
+           "</mode>" ;
+
+           */
+  this.continues = function()
+  {
+    var ret = ['ul'];
+    ret[ret.length] = self.continueWithMode('run', 'run');
+    ret[ret.length] = self.continueWithMode('step into call', 'step-into-call');
+    ret[ret.length] = self.continueWithMode('step over call', 'step-over-call');
+    ret[ret.length] = self.continueWithMode('finish call', 'finish-call');
+    return ret;
+  }
+
+  this.continueWithMode = function(name, mode)
+  {
+    return ['li',
+        ['input',
+          'type', 'button',
+          'value', name,
+          'mode', mode,
+          'id', 'continue-' + mode,
+          'onclick', handlers.__continue,
+          'disabled', true
+        ]
+      ]
   }
 }

File src/scripts/clientlib_async.js

     {
       return false;
     }
-    proxy.GET( "/enable/" + service_name );  // ignore the response
+    proxy.GET( "/enable/" + service_name, function(){} );  // ignore the response
     return true;
   }
 
           throw "Message failed, POST, empty document: " + this.responseText;
         }
         if(cb) cb(xml);
+        opera.postError('POST: '+this.responseText);
       }
       x.open("POST", "http://" + __host + ":" + __port + msg );
       x.send("postdata=" + data);

File src/scripts/dom.js

   return this;
 }
 
+Element.prototype.hasClass=function(name)
+{
+  return (new RegExp('\\b'+name+'\\b')).test(this.className)
+}
+
 Element.prototype.releaseEvent=function(name)
 {
   var event=document.createEvent('Events');