<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[160500] trunk/Source/WebInspectorUI</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/160500">160500</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2013-12-12 11:52:46 -0800 (Thu, 12 Dec 2013)</dd>
</dl>

<h3>Log Message</h3>
<pre>Web Inspector: ES6: JavaScript syntax highlighting and recognition of for..of
https://bugs.webkit.org/show_bug.cgi?id=122868

Patch by Laszlo Vidacs &lt;lac@inf.u-szeged.hu&gt; on 2013-12-12
Reviewed by Timothy Hatcher.

Update to CodeMirror 3.20 including javascript ES6 updates.

* Tools/PrettyPrinting/codemirror.css:
* Tools/PrettyPrinting/codemirror.js: Minor local change due to error from jsmin.py
* Tools/PrettyPrinting/css.js:
* Tools/PrettyPrinting/javascript.js:
* UserInterface/External/CodeMirror/codemirror.css:
* UserInterface/External/CodeMirror/codemirror.js: Minor local change due to error from jsmin.py
* UserInterface/External/CodeMirror/coffeescript.js:
* UserInterface/External/CodeMirror/css.js:
* UserInterface/External/CodeMirror/htmlmixed.js:
* UserInterface/External/CodeMirror/javascript.js:
* UserInterface/External/CodeMirror/less.js:
* UserInterface/External/CodeMirror/matchbrackets.js:
* UserInterface/External/CodeMirror/placeholder.js:
* UserInterface/External/CodeMirror/runmode.js:
* UserInterface/External/CodeMirror/searchcursor.js:
* UserInterface/External/CodeMirror/sql.js:
* UserInterface/External/CodeMirror/xml.js:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebInspectorUIChangeLog">trunk/Source/WebInspectorUI/ChangeLog</a></li>
<li><a href="#trunkSourceWebInspectorUIToolsPrettyPrintingcodemirrorcss">trunk/Source/WebInspectorUI/Tools/PrettyPrinting/codemirror.css</a></li>
<li><a href="#trunkSourceWebInspectorUIToolsPrettyPrintingcodemirrorjs">trunk/Source/WebInspectorUI/Tools/PrettyPrinting/codemirror.js</a></li>
<li><a href="#trunkSourceWebInspectorUIToolsPrettyPrintingcssjs">trunk/Source/WebInspectorUI/Tools/PrettyPrinting/css.js</a></li>
<li><a href="#trunkSourceWebInspectorUIToolsPrettyPrintingjavascriptjs">trunk/Source/WebInspectorUI/Tools/PrettyPrinting/javascript.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceExternalCodeMirrorcodemirrorcss">trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/codemirror.css</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceExternalCodeMirrorcodemirrorjs">trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/codemirror.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceExternalCodeMirrorcoffeescriptjs">trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/coffeescript.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceExternalCodeMirrorcssjs">trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/css.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceExternalCodeMirrorhtmlmixedjs">trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/htmlmixed.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceExternalCodeMirrorjavascriptjs">trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/javascript.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceExternalCodeMirrorlessjs">trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/less.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceExternalCodeMirrormatchbracketsjs">trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/matchbrackets.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceExternalCodeMirrorplaceholderjs">trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/placeholder.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceExternalCodeMirrorrunmodejs">trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/runmode.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceExternalCodeMirrorsearchcursorjs">trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/searchcursor.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceExternalCodeMirrorsqljs">trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/sql.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceExternalCodeMirrorxmljs">trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/xml.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebInspectorUIChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/ChangeLog (160499 => 160500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/ChangeLog        2013-12-12 19:37:21 UTC (rev 160499)
+++ trunk/Source/WebInspectorUI/ChangeLog        2013-12-12 19:52:46 UTC (rev 160500)
</span><span class="lines">@@ -1,3 +1,30 @@
</span><ins>+2013-12-12  Laszlo Vidacs  &lt;lac@inf.u-szeged.hu&gt;
+
+        Web Inspector: ES6: JavaScript syntax highlighting and recognition of for..of
+        https://bugs.webkit.org/show_bug.cgi?id=122868
+
+        Reviewed by Timothy Hatcher.
+
+        Update to CodeMirror 3.20 including javascript ES6 updates.
+
+        * Tools/PrettyPrinting/codemirror.css:
+        * Tools/PrettyPrinting/codemirror.js: Minor local change due to error from jsmin.py
+        * Tools/PrettyPrinting/css.js:
+        * Tools/PrettyPrinting/javascript.js:
+        * UserInterface/External/CodeMirror/codemirror.css:
+        * UserInterface/External/CodeMirror/codemirror.js: Minor local change due to error from jsmin.py
+        * UserInterface/External/CodeMirror/coffeescript.js:
+        * UserInterface/External/CodeMirror/css.js:
+        * UserInterface/External/CodeMirror/htmlmixed.js:
+        * UserInterface/External/CodeMirror/javascript.js:
+        * UserInterface/External/CodeMirror/less.js:
+        * UserInterface/External/CodeMirror/matchbrackets.js:
+        * UserInterface/External/CodeMirror/placeholder.js:
+        * UserInterface/External/CodeMirror/runmode.js:
+        * UserInterface/External/CodeMirror/searchcursor.js:
+        * UserInterface/External/CodeMirror/sql.js:
+        * UserInterface/External/CodeMirror/xml.js:
+
</ins><span class="cx"> 2013-12-12  Antoine Quint  &lt;graouts@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Web Inspector: allow editing of colors in CSS resources
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIToolsPrettyPrintingcodemirrorcss"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/Tools/PrettyPrinting/codemirror.css (160499 => 160500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/Tools/PrettyPrinting/codemirror.css        2013-12-12 19:37:21 UTC (rev 160499)
+++ trunk/Source/WebInspectorUI/Tools/PrettyPrinting/codemirror.css        2013-12-12 19:52:46 UTC (rev 160500)
</span><span class="lines">@@ -74,7 +74,6 @@
</span><span class="cx"> .cm-s-default .cm-string {color: #a11;}
</span><span class="cx"> .cm-s-default .cm-string-2 {color: #f50;}
</span><span class="cx"> .cm-s-default .cm-meta {color: #555;}
</span><del>-.cm-s-default .cm-error {color: #f00;}
</del><span class="cx"> .cm-s-default .cm-qualifier {color: #555;}
</span><span class="cx"> .cm-s-default .cm-builtin {color: #30a;}
</span><span class="cx"> .cm-s-default .cm-bracket {color: #997;}
</span><span class="lines">@@ -91,6 +90,7 @@
</span><span class="cx"> .cm-em {font-style: italic;}
</span><span class="cx"> .cm-link {text-decoration: underline;}
</span><span class="cx"> 
</span><ins>+.cm-s-default .cm-error {color: #f00;}
</ins><span class="cx"> .cm-invalidchar {color: #f00;}
</span><span class="cx"> 
</span><span class="cx"> div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIToolsPrettyPrintingcodemirrorjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/Tools/PrettyPrinting/codemirror.js (160499 => 160500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/Tools/PrettyPrinting/codemirror.js        2013-12-12 19:37:21 UTC (rev 160499)
+++ trunk/Source/WebInspectorUI/Tools/PrettyPrinting/codemirror.js        2013-12-12 19:52:46 UTC (rev 160500)
</span><span class="lines">@@ -7,9 +7,13 @@
</span><span class="cx">   // Crude, but necessary to handle a number of hard-to-feature-detect
</span><span class="cx">   // bugs and behavior differences.
</span><span class="cx">   var gecko = /gecko\/\d/i.test(navigator.userAgent);
</span><ins>+  // IE11 currently doesn't count as 'ie', since it has almost none of
+  // the same bugs as earlier versions. Use ie_gt10 to handle
+  // incompatibilities in that version.
</ins><span class="cx">   var ie = /MSIE \d/.test(navigator.userAgent);
</span><span class="cx">   var ie_lt8 = ie &amp;&amp; (document.documentMode == null || document.documentMode &lt; 8);
</span><span class="cx">   var ie_lt9 = ie &amp;&amp; (document.documentMode == null || document.documentMode &lt; 9);
</span><ins>+  var ie_gt10 = /Trident\/([7-9]|\d{2,})\./.test(navigator.userAgent);
</ins><span class="cx">   var webkit = /WebKit\//.test(navigator.userAgent);
</span><span class="cx">   var qtwebkit = webkit &amp;&amp; /Qt\/\d+\.\d+/.test(navigator.userAgent);
</span><span class="cx">   var chrome = /Chrome\//.test(navigator.userAgent);
</span><span class="lines">@@ -309,7 +313,7 @@
</span><span class="cx">       options.gutters = options.gutters.concat([&quot;CodeMirror-linenumbers&quot;]);
</span><span class="cx">     } else if (found &gt; -1 &amp;&amp; !options.lineNumbers) {
</span><span class="cx">       options.gutters = options.gutters.slice(0);
</span><del>-      options.gutters.splice(i, 1);
</del><ins>+      options.gutters.splice(found, 1);
</ins><span class="cx">     }
</span><span class="cx">   }
</span><span class="cx"> 
</span><span class="lines">@@ -353,8 +357,10 @@
</span><span class="cx">       d.gutterFiller.style.width = d.gutters.offsetWidth + &quot;px&quot;;
</span><span class="cx">     } else d.gutterFiller.style.display = &quot;&quot;;
</span><span class="cx"> 
</span><del>-    if (mac_geLion &amp;&amp; scrollbarWidth(d.measure) === 0)
</del><ins>+    if (mac_geLion &amp;&amp; scrollbarWidth(d.measure) === 0) {
</ins><span class="cx">       d.scrollbarV.style.minWidth = d.scrollbarH.style.minHeight = mac_geMountainLion ? &quot;18px&quot; : &quot;12px&quot;;
</span><ins>+      d.scrollbarV.style.pointerEvents = d.scrollbarH.style.pointerEvents = &quot;none&quot;;
+    }
</ins><span class="cx">   }
</span><span class="cx"> 
</span><span class="cx">   function visibleLines(display, doc, viewPort) {
</span><span class="lines">@@ -409,14 +415,14 @@
</span><span class="cx">   function updateDisplay(cm, changes, viewPort, forced) {
</span><span class="cx">     var oldFrom = cm.display.showingFrom, oldTo = cm.display.showingTo, updated;
</span><span class="cx">     var visible = visibleLines(cm.display, cm.doc, viewPort);
</span><del>-    for (;;) {
</del><ins>+    for (var first = true;; first = false) {
</ins><span class="cx">       var oldWidth = cm.display.scroller.clientWidth;
</span><span class="cx">       if (!updateDisplayInner(cm, changes, visible, forced)) break;
</span><span class="cx">       updated = true;
</span><span class="cx">       changes = [];
</span><span class="cx">       updateSelection(cm);
</span><span class="cx">       updateScrollbars(cm);
</span><del>-      if (cm.options.lineWrapping &amp;&amp; oldWidth != cm.display.scroller.clientWidth) {
</del><ins>+      if (first &amp;&amp; cm.options.lineWrapping &amp;&amp; oldWidth != cm.display.scroller.clientWidth) {
</ins><span class="cx">         forced = true;
</span><span class="cx">         continue;
</span><span class="cx">       }
</span><span class="lines">@@ -904,7 +910,7 @@
</span><span class="cx">     doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.showingTo + 500), function(line) {
</span><span class="cx">       if (doc.frontier &gt;= cm.display.showingFrom) { // Visible
</span><span class="cx">         var oldStyles = line.styles;
</span><del>-        line.styles = highlightLine(cm, line, state);
</del><ins>+        line.styles = highlightLine(cm, line, state, true);
</ins><span class="cx">         var ischange = !oldStyles || oldStyles.length != line.styles.length;
</span><span class="cx">         for (var i = 0; !ischange &amp;&amp; i &lt; oldStyles.length; ++i) ischange = oldStyles[i] != line.styles[i];
</span><span class="cx">         if (ischange) {
</span><span class="lines">@@ -913,7 +919,7 @@
</span><span class="cx">         }
</span><span class="cx">         line.stateAfter = copyState(doc.mode, state);
</span><span class="cx">       } else {
</span><del>-        processLine(cm, line, state);
</del><ins>+        processLine(cm, line.text, state);
</ins><span class="cx">         line.stateAfter = doc.frontier % 5 == 0 ? copyState(doc.mode, state) : null;
</span><span class="cx">       }
</span><span class="cx">       ++doc.frontier;
</span><span class="lines">@@ -935,8 +941,9 @@
</span><span class="cx">   // smallest indentation, which tends to need the least context to
</span><span class="cx">   // parse correctly.
</span><span class="cx">   function findStartLine(cm, n, precise) {
</span><del>-    var minindent, minline, doc = cm.doc, maxScan = cm.doc.mode.innerMode ? 1000 : 100;
-    for (var search = n, lim = n - maxScan; search &gt; lim; --search) {
</del><ins>+    var minindent, minline, doc = cm.doc;
+    var lim = precise ? -1 : n - (cm.doc.mode.innerMode ? 1000 : 100);
+    for (var search = n; search &gt; lim; --search) {
</ins><span class="cx">       if (search &lt;= doc.first) return doc.first;
</span><span class="cx">       var line = getLine(doc, search - 1);
</span><span class="cx">       if (line.stateAfter &amp;&amp; (!precise || search &lt;= doc.frontier)) return search;
</span><span class="lines">@@ -956,11 +963,12 @@
</span><span class="cx">     if (!state) state = startState(doc.mode);
</span><span class="cx">     else state = copyState(doc.mode, state);
</span><span class="cx">     doc.iter(pos, n, function(line) {
</span><del>-      processLine(cm, line, state);
</del><ins>+      processLine(cm, line.text, state);
</ins><span class="cx">       var save = pos == n - 1 || pos % 5 == 0 || pos &gt;= display.showingFrom &amp;&amp; pos &lt; display.showingTo;
</span><span class="cx">       line.stateAfter = save ? copyState(doc.mode, state) : null;
</span><span class="cx">       ++pos;
</span><span class="cx">     });
</span><ins>+    if (precise) doc.frontier = pos;
</ins><span class="cx">     return state;
</span><span class="cx">   }
</span><span class="cx"> 
</span><span class="lines">@@ -1001,7 +1009,7 @@
</span><span class="cx">       var memo = cache[i];
</span><span class="cx">       if (memo.text == line.text &amp;&amp; memo.markedSpans == line.markedSpans &amp;&amp;
</span><span class="cx">           cm.display.scroller.clientWidth == memo.width &amp;&amp;
</span><del>-          memo.classes == line.textClass + &quot;|&quot; + line.bgClass + &quot;|&quot; + line.wrapClass)
</del><ins>+          memo.classes == line.textClass + &quot;|&quot; + line.wrapClass)
</ins><span class="cx">         return memo;
</span><span class="cx">     }
</span><span class="cx">   }
</span><span class="lines">@@ -1021,7 +1029,7 @@
</span><span class="cx">     var cache = cm.display.measureLineCache;
</span><span class="cx">     var memo = {text: line.text, width: cm.display.scroller.clientWidth,
</span><span class="cx">                 markedSpans: line.markedSpans, measure: measure,
</span><del>-                classes: line.textClass + &quot;|&quot; + line.bgClass + &quot;|&quot; + line.wrapClass};
</del><ins>+                classes: line.textClass + &quot;|&quot; + line.wrapClass};
</ins><span class="cx">     if (cache.length == 16) cache[++cm.display.measureLineCachePos % 16] = memo;
</span><span class="cx">     else cache.push(memo);
</span><span class="cx">     return measure;
</span><span class="lines">@@ -1379,11 +1387,14 @@
</span><span class="cx">     }
</span><span class="cx">     if (!updated &amp;&amp; op.selectionChanged) updateSelection(cm);
</span><span class="cx">     if (op.updateScrollPos) {
</span><del>-      display.scroller.scrollTop = display.scrollbarV.scrollTop = doc.scrollTop = newScrollPos.scrollTop;
-      display.scroller.scrollLeft = display.scrollbarH.scrollLeft = doc.scrollLeft = newScrollPos.scrollLeft;
</del><ins>+      var top = Math.max(0, Math.min(display.scroller.scrollHeight - display.scroller.clientHeight, newScrollPos.scrollTop));
+      var left = Math.max(0, Math.min(display.scroller.scrollWidth - display.scroller.clientWidth, newScrollPos.scrollLeft));
+      display.scroller.scrollTop = display.scrollbarV.scrollTop = doc.scrollTop = top;
+      display.scroller.scrollLeft = display.scrollbarH.scrollLeft = doc.scrollLeft = left;
</ins><span class="cx">       alignHorizontally(cm);
</span><span class="cx">       if (op.scrollToPos)
</span><del>-        scrollPosIntoView(cm, clipPos(cm.doc, op.scrollToPos), op.scrollToPosMargin);
</del><ins>+        scrollPosIntoView(cm, clipPos(cm.doc, op.scrollToPos.from),
+                          clipPos(cm.doc, op.scrollToPos.to), op.scrollToPos.margin);
</ins><span class="cx">     } else if (newScrollPos) {
</span><span class="cx">       scrollCursorIntoView(cm);
</span><span class="cx">     }
</span><span class="lines">@@ -1605,7 +1616,10 @@
</span><span class="cx">       if (signalDOMEvent(cm, e) || cm.options.onKeyEvent &amp;&amp; cm.options.onKeyEvent(cm, addStop(e))) return;
</span><span class="cx">       if (e.keyCode == 16) cm.doc.sel.shift = false;
</span><span class="cx">     }));
</span><del>-    on(d.input, &quot;input&quot;, bind(fastPoll, cm));
</del><ins>+    on(d.input, &quot;input&quot;, function() {
+      if (ie &amp;&amp; !ie_lt9 &amp;&amp; cm.display.inputHasSelection) cm.display.inputHasSelection = null;
+      fastPoll(cm);
+    });
</ins><span class="cx">     on(d.input, &quot;keydown&quot;, operation(cm, onKeyDown));
</span><span class="cx">     on(d.input, &quot;keypress&quot;, operation(cm, onKeyPress));
</span><span class="cx">     on(d.input, &quot;focus&quot;, bind(onFocus, cm));
</span><span class="lines">@@ -1895,7 +1909,6 @@
</span><span class="cx">           if (cm.state.draggingText) replaceRange(cm.doc, &quot;&quot;, curFrom, curTo, &quot;paste&quot;);
</span><span class="cx">           cm.replaceSelection(text, null, &quot;paste&quot;);
</span><span class="cx">           focusInput(cm);
</span><del>-          onFocus(cm);
</del><span class="cx">         }
</span><span class="cx">       }
</span><span class="cx">       catch(e){}
</span><span class="lines">@@ -2176,7 +2189,11 @@
</span><span class="cx"> 
</span><span class="cx">     var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop;
</span><span class="cx">     if (!pos || opera) return; // Opera is difficult.
</span><del>-    if (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to))
</del><ins>+
+    // Reset the current text selection only if the click is done outside of the selection
+    // and 'resetSelectionOnContextMenu' option is true.
+    var reset = cm.options.resetSelectionOnContextMenu;
+    if (reset &amp;&amp; (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to)))
</ins><span class="cx">       operation(cm, setSelection)(cm.doc, pos, pos);
</span><span class="cx"> 
</span><span class="cx">     var oldCSS = display.input.style.cssText;
</span><span class="lines">@@ -2326,6 +2343,7 @@
</span><span class="cx">   }
</span><span class="cx"> 
</span><span class="cx">   function makeChangeNoReadonly(doc, change, selUpdate) {
</span><ins>+    if (change.text.length == 1 &amp;&amp; change.text[0] == &quot;&quot; &amp;&amp; posEq(change.from, change.to)) return;
</ins><span class="cx">     var selAfter = computeSelAfterChange(doc, change, selUpdate);
</span><span class="cx">     addToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN);
</span><span class="cx"> 
</span><span class="lines">@@ -2626,7 +2644,7 @@
</span><span class="cx">   // SCROLLING
</span><span class="cx"> 
</span><span class="cx">   function scrollCursorIntoView(cm) {
</span><del>-    var coords = scrollPosIntoView(cm, cm.doc.sel.head, cm.options.cursorScrollMargin);
</del><ins>+    var coords = scrollPosIntoView(cm, cm.doc.sel.head, null, cm.options.cursorScrollMargin);
</ins><span class="cx">     if (!cm.state.focused) return;
</span><span class="cx">     var display = cm.display, box = getRect(display.sizer), doScroll = null;
</span><span class="cx">     if (coords.top + box.top &lt; 0) doScroll = true;
</span><span class="lines">@@ -2643,11 +2661,15 @@
</span><span class="cx">     }
</span><span class="cx">   }
</span><span class="cx"> 
</span><del>-  function scrollPosIntoView(cm, pos, margin) {
</del><ins>+  function scrollPosIntoView(cm, pos, end, margin) {
</ins><span class="cx">     if (margin == null) margin = 0;
</span><span class="cx">     for (;;) {
</span><span class="cx">       var changed = false, coords = cursorCoords(cm, pos);
</span><del>-      var scrollPos = calculateScrollPos(cm, coords.left, coords.top - margin, coords.left, coords.bottom + margin);
</del><ins>+      var endCoords = !end || end == pos ? coords : cursorCoords(cm, end);
+      var scrollPos = calculateScrollPos(cm, Math.min(coords.left, endCoords.left),
+                                         Math.min(coords.top, endCoords.top) - margin,
+                                         Math.max(coords.left, endCoords.left),
+                                         Math.max(coords.bottom, endCoords.bottom) + margin);
</ins><span class="cx">       var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft;
</span><span class="cx">       if (scrollPos.scrollTop != null) {
</span><span class="cx">         setScrollTop(cm, scrollPos.scrollTop);
</span><span class="lines">@@ -2744,6 +2766,8 @@
</span><span class="cx"> 
</span><span class="cx">     if (indentString != curSpaceString)
</span><span class="cx">       replaceRange(cm.doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), &quot;+input&quot;);
</span><ins>+    else if (doc.sel.head.line == n &amp;&amp; doc.sel.head.ch &lt; curSpaceString.length)
+      setSelection(doc, Pos(n, curSpaceString.length), Pos(n, curSpaceString.length), 1);
</ins><span class="cx">     line.stateAfter = null;
</span><span class="cx">   }
</span><span class="cx"> 
</span><span class="lines">@@ -2844,7 +2868,7 @@
</span><span class="cx"> 
</span><span class="cx">   CodeMirror.prototype = {
</span><span class="cx">     constructor: CodeMirror,
</span><del>-    focus: function(){window.focus(); focusInput(this); onFocus(this); fastPoll(this);},
</del><ins>+    focus: function(){window.focus(); focusInput(this); fastPoll(this);},
</ins><span class="cx"> 
</span><span class="cx">     setOption: function(option, value) {
</span><span class="cx">       var options = this.options, old = options[option];
</span><span class="lines">@@ -3165,17 +3189,23 @@
</span><span class="cx">               clientHeight: scroller.clientHeight - co, clientWidth: scroller.clientWidth - co};
</span><span class="cx">     },
</span><span class="cx"> 
</span><del>-    scrollIntoView: operation(null, function(pos, margin) {
-      if (typeof pos == &quot;number&quot;) pos = Pos(pos, 0);
</del><ins>+    scrollIntoView: operation(null, function(range, margin) {
+      if (range == null) range = {from: this.doc.sel.head, to: null};
+      else if (typeof range == &quot;number&quot;) range = {from: Pos(range, 0), to: null};
+      else if (range.from == null) range = {from: range, to: null};
+      if (!range.to) range.to = range.from;
</ins><span class="cx">       if (!margin) margin = 0;
</span><del>-      var coords = pos;
</del><span class="cx"> 
</span><del>-      if (!pos || pos.line != null) {
-        this.curOp.scrollToPos = pos ? clipPos(this.doc, pos) : this.doc.sel.head;
-        this.curOp.scrollToPosMargin = margin;
-        coords = cursorCoords(this, this.curOp.scrollToPos);
</del><ins>+      var coords = range;
+      if (range.from.line != null) {
+        this.curOp.scrollToPos = {from: range.from, to: range.to, margin: margin};
+        coords = {from: cursorCoords(this, range.from),
+                  to: cursorCoords(this, range.to)};
</ins><span class="cx">       }
</span><del>-      var sPos = calculateScrollPos(this, coords.left, coords.top - margin, coords.right, coords.bottom + margin);
</del><ins>+      var sPos = calculateScrollPos(this, Math.min(coords.from.left, coords.to.left),
+                                    Math.min(coords.from.top, coords.to.top) - margin,
+                                    Math.max(coords.from.right, coords.to.right),
+                                    Math.max(coords.from.bottom, coords.to.bottom) + margin);
</ins><span class="cx">       updateScrollPos(this, sPos.scrollLeft, sPos.scrollTop);
</span><span class="cx">     }),
</span><span class="cx"> 
</span><span class="lines">@@ -3207,6 +3237,7 @@
</span><span class="cx">       clearCaches(this);
</span><span class="cx">       resetInput(this, true);
</span><span class="cx">       updateScrollPos(this, doc.scrollLeft, doc.scrollTop);
</span><ins>+      signalLater(this, &quot;swapDoc&quot;, this, old);
</ins><span class="cx">       return old;
</span><span class="cx">     }),
</span><span class="cx"> 
</span><span class="lines">@@ -3250,8 +3281,14 @@
</span><span class="cx">     clearCaches(cm);
</span><span class="cx">     regChange(cm);
</span><span class="cx">   }, true);
</span><ins>+  option(&quot;specialChars&quot;, /[\t\u0000-\u0019\u00ad\u200b\u2028\u2029\ufeff]/g, function(cm, val) {
+    cm.options.specialChars = new RegExp(val.source + (val.test(&quot;\t&quot;) ? &quot;&quot; : &quot;|\t&quot;), &quot;g&quot;);
+    cm.refresh();
+  }, true);
+  option(&quot;specialCharPlaceholder&quot;, defaultSpecialCharPlaceholder, function(cm) {cm.refresh();}, true);
</ins><span class="cx">   option(&quot;electricChars&quot;, true);
</span><span class="cx">   option(&quot;rtlMoveVisually&quot;, !windows);
</span><ins>+  option(&quot;wholeLineUpdateBefore&quot;, true);
</ins><span class="cx"> 
</span><span class="cx">   option(&quot;theme&quot;, &quot;default&quot;, function(cm) {
</span><span class="cx">     themeChanged(cm);
</span><span class="lines">@@ -3281,9 +3318,17 @@
</span><span class="cx">   option(&quot;lineNumberFormatter&quot;, function(integer) {return integer;}, guttersChanged, true);
</span><span class="cx">   option(&quot;showCursorWhenSelecting&quot;, false, updateSelection, true);
</span><span class="cx"> 
</span><ins>+  option(&quot;resetSelectionOnContextMenu&quot;, true);
+
</ins><span class="cx">   option(&quot;readOnly&quot;, false, function(cm, val) {
</span><del>-    if (val == &quot;nocursor&quot;) {onBlur(cm); cm.display.input.blur();}
-    else if (!val) resetInput(cm, true);
</del><ins>+    if (val == &quot;nocursor&quot;) {
+      onBlur(cm);
+      cm.display.input.blur();
+      cm.display.disabled = true;
+    } else {
+      cm.display.disabled = false;
+      if (!val) resetInput(cm, true);
+    }
</ins><span class="cx">   });
</span><span class="cx">   option(&quot;dragDrop&quot;, true);
</span><span class="cx"> 
</span><span class="lines">@@ -3517,7 +3562,8 @@
</span><span class="cx">   keyMap.basic = {
</span><span class="cx">     &quot;Left&quot;: &quot;goCharLeft&quot;, &quot;Right&quot;: &quot;goCharRight&quot;, &quot;Up&quot;: &quot;goLineUp&quot;, &quot;Down&quot;: &quot;goLineDown&quot;,
</span><span class="cx">     &quot;End&quot;: &quot;goLineEnd&quot;, &quot;Home&quot;: &quot;goLineStartSmart&quot;, &quot;PageUp&quot;: &quot;goPageUp&quot;, &quot;PageDown&quot;: &quot;goPageDown&quot;,
</span><del>-    &quot;Delete&quot;: &quot;delCharAfter&quot;, &quot;Backspace&quot;: &quot;delCharBefore&quot;, &quot;Tab&quot;: &quot;defaultTab&quot;, &quot;Shift-Tab&quot;: &quot;indentAuto&quot;,
</del><ins>+    &quot;Delete&quot;: &quot;delCharAfter&quot;, &quot;Backspace&quot;: &quot;delCharBefore&quot;, &quot;Shift-Backspace&quot;: &quot;delCharBefore&quot;,
+    &quot;Tab&quot;: &quot;defaultTab&quot;, &quot;Shift-Tab&quot;: &quot;indentAuto&quot;,
</ins><span class="cx">     &quot;Enter&quot;: &quot;newlineAndIndent&quot;, &quot;Insert&quot;: &quot;toggleOverwrite&quot;
</span><span class="cx">   };
</span><span class="cx">   // Note that the save and find-related commands aren't defined by
</span><span class="lines">@@ -3823,7 +3869,9 @@
</span><span class="cx">     if (doc.cm &amp;&amp; !doc.cm.curOp) return operation(doc.cm, markText)(doc, from, to, options, type);
</span><span class="cx"> 
</span><span class="cx">     var marker = new TextMarker(doc, type);
</span><del>-    if (type == &quot;range&quot; &amp;&amp; !posLess(from, to)) return marker;
</del><ins>+    if (posLess(to, from) || posEq(from, to) &amp;&amp; type == &quot;range&quot; &amp;&amp;
+        !(options.inclusiveLeft &amp;&amp; options.inclusiveRight))
+      return marker;
</ins><span class="cx">     if (options) copyObj(options, marker);
</span><span class="cx">     if (marker.replacedWith) {
</span><span class="cx">       marker.collapsed = true;
</span><span class="lines">@@ -3939,7 +3987,9 @@
</span><span class="cx">     if (old) for (var i = 0, nw; i &lt; old.length; ++i) {
</span><span class="cx">       var span = old[i], marker = span.marker;
</span><span class="cx">       var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from &lt;= startCh : span.from &lt; startCh);
</span><del>-      if (startsBefore || marker.type == &quot;bookmark&quot; &amp;&amp; span.from == startCh &amp;&amp; (!isInsert || !span.marker.insertLeft)) {
</del><ins>+      if (startsBefore ||
+          (marker.inclusiveLeft &amp;&amp; marker.inclusiveRight || marker.type == &quot;bookmark&quot;) &amp;&amp;
+          span.from == startCh &amp;&amp; (!isInsert || !span.marker.insertLeft)) {
</ins><span class="cx">         var endsAfter = span.to == null || (marker.inclusiveRight ? span.to &gt;= startCh : span.to &gt; startCh);
</span><span class="cx">         (nw || (nw = [])).push({from: span.from,
</span><span class="cx">                                 to: endsAfter ? null : span.to,
</span><span class="lines">@@ -4212,6 +4262,7 @@
</span><span class="cx">     this.height = estimateHeight ? estimateHeight(this) : 1;
</span><span class="cx">   };
</span><span class="cx">   eventMixin(Line);
</span><ins>+  Line.prototype.lineNo = function() { return lineNo(this); };
</ins><span class="cx"> 
</span><span class="cx">   function updateLine(line, text, markedSpans, estimateHeight) {
</span><span class="cx">     line.text = text;
</span><span class="lines">@@ -4232,7 +4283,7 @@
</span><span class="cx">   // Run the given mode's parser over a line, update the styles
</span><span class="cx">   // array, which contains alternating fragments of text and CSS
</span><span class="cx">   // classes.
</span><del>-  function runMode(cm, text, mode, state, f) {
</del><ins>+  function runMode(cm, text, mode, state, f, forceToEnd) {
</ins><span class="cx">     var flattenSpans = mode.flattenSpans;
</span><span class="cx">     if (flattenSpans == null) flattenSpans = cm.options.flattenSpans;
</span><span class="cx">     var curStart = 0, curStyle = null;
</span><span class="lines">@@ -4241,6 +4292,7 @@
</span><span class="cx">     while (!stream.eol()) {
</span><span class="cx">       if (stream.pos &gt; cm.options.maxHighlightLength) {
</span><span class="cx">         flattenSpans = false;
</span><ins>+        if (forceToEnd) processLine(cm, text, state, stream.pos);
</ins><span class="cx">         stream.pos = text.length;
</span><span class="cx">         style = null;
</span><span class="cx">       } else {
</span><span class="lines">@@ -4260,12 +4312,14 @@
</span><span class="cx">     }
</span><span class="cx">   }
</span><span class="cx"> 
</span><del>-  function highlightLine(cm, line, state) {
</del><ins>+  function highlightLine(cm, line, state, forceToEnd) {
</ins><span class="cx">     // A styles array always starts with a number identifying the
</span><span class="cx">     // mode/overlays that it is based on (for easy invalidation).
</span><span class="cx">     var st = [cm.state.modeGen];
</span><span class="cx">     // Compute the base array of styles
</span><del>-    runMode(cm, line.text, cm.doc.mode, state, function(end, style) {st.push(end, style);});
</del><ins>+    runMode(cm, line.text, cm.doc.mode, state, function(end, style) {
+      st.push(end, style);
+    }, forceToEnd);
</ins><span class="cx"> 
</span><span class="cx">     // Run overlays, adjust style array.
</span><span class="cx">     for (var o = 0; o &lt; cm.state.overlays.length; ++o) {
</span><span class="lines">@@ -4304,10 +4358,11 @@
</span><span class="cx"> 
</span><span class="cx">   // Lightweight form of highlight -- proceed over this line and
</span><span class="cx">   // update state, but don't save a style array.
</span><del>-  function processLine(cm, line, state) {
</del><ins>+  function processLine(cm, text, state, startAt) {
</ins><span class="cx">     var mode = cm.doc.mode;
</span><del>-    var stream = new StringStream(line.text, cm.options.tabSize);
-    if (line.text == &quot;&quot; &amp;&amp; mode.blankLine) mode.blankLine(state);
</del><ins>+    var stream = new StringStream(text, cm.options.tabSize);
+    stream.start = stream.pos = startAt || 0;
+    if (text == &quot;&quot; &amp;&amp; mode.blankLine) mode.blankLine(state);
</ins><span class="cx">     while (!stream.eol() &amp;&amp; stream.pos &lt;= cm.options.maxHighlightLength) {
</span><span class="cx">       mode.token(stream, state);
</span><span class="cx">       stream.start = stream.pos;
</span><span class="lines">@@ -4364,7 +4419,7 @@
</span><span class="cx">     // Work around problem with the reported dimensions of single-char
</span><span class="cx">     // direction spans on IE (issue #1129). See also the comment in
</span><span class="cx">     // cursorCoords.
</span><del>-    if (measure &amp;&amp; ie &amp;&amp; (order = getOrder(line))) {
</del><ins>+    if (measure &amp;&amp; (ie || ie_gt10) &amp;&amp; (order = getOrder(line))) {
</ins><span class="cx">       var l = order.length - 1;
</span><span class="cx">       if (order[l].from == order[l].to) --l;
</span><span class="cx">       var last = order[l], prev = order[l - 1];
</span><span class="lines">@@ -4382,17 +4437,23 @@
</span><span class="cx">     return builder;
</span><span class="cx">   }
</span><span class="cx"> 
</span><del>-  var tokenSpecialChars = /[\t\u0000-\u0019\u00ad\u200b\u2028\u2029\uFEFF]/g;
</del><ins>+  function defaultSpecialCharPlaceholder(ch) {
+    var token = elt(&quot;span&quot;, &quot;\u2022&quot;, &quot;cm-invalidchar&quot;);
+    token.title = &quot;\\u&quot; + ch.charCodeAt(0).toString(16);
+    return token;
+  }
+
</ins><span class="cx">   function buildToken(builder, text, style, startStyle, endStyle, title) {
</span><span class="cx">     if (!text) return;
</span><del>-    if (!tokenSpecialChars.test(text)) {
</del><ins>+    var special = builder.cm.options.specialChars;
+    if (!special.test(text)) {
</ins><span class="cx">       builder.col += text.length;
</span><span class="cx">       var content = document.createTextNode(text);
</span><span class="cx">     } else {
</span><span class="cx">       var content = document.createDocumentFragment(), pos = 0;
</span><span class="cx">       while (true) {
</span><del>-        tokenSpecialChars.lastIndex = pos;
-        var m = tokenSpecialChars.exec(text);
</del><ins>+        special.lastIndex = pos;
+        var m = special.exec(text);
</ins><span class="cx">         var skipped = m ? m.index - pos : text.length - pos;
</span><span class="cx">         if (skipped) {
</span><span class="cx">           content.appendChild(document.createTextNode(text.slice(pos, pos + skipped)));
</span><span class="lines">@@ -4405,8 +4466,7 @@
</span><span class="cx">           content.appendChild(elt(&quot;span&quot;, spaceStr(tabWidth), &quot;cm-tab&quot;));
</span><span class="cx">           builder.col += tabWidth;
</span><span class="cx">         } else {
</span><del>-          var token = elt(&quot;span&quot;, &quot;\u2022&quot;, &quot;cm-invalidchar&quot;);
-          token.title = &quot;\\u&quot; + m[0].charCodeAt(0).toString(16);
</del><ins>+          var token = builder.cm.options.specialCharPlaceholder(m[0]);
</ins><span class="cx">           content.appendChild(token);
</span><span class="cx">           builder.col += 1;
</span><span class="cx">         }
</span><span class="lines">@@ -4457,7 +4517,7 @@
</span><span class="cx">       return out;
</span><span class="cx">     }
</span><span class="cx">     return function(builder, text, style, startStyle, endStyle, title) {
</span><del>-      return inner(builder, text.replace(/ {3,}/, split), style, startStyle, endStyle, title);
</del><ins>+      return inner(builder, text.replace(/ {3,}/g, split), style, startStyle, endStyle, title);
</ins><span class="cx">     };
</span><span class="cx">   }
</span><span class="cx"> 
</span><span class="lines">@@ -4559,7 +4619,8 @@
</span><span class="cx">     var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line;
</span><span class="cx"> 
</span><span class="cx">     // First adjust the line structure
</span><del>-    if (from.ch == 0 &amp;&amp; to.ch == 0 &amp;&amp; lastText == &quot;&quot;) {
</del><ins>+    if (from.ch == 0 &amp;&amp; to.ch == 0 &amp;&amp; lastText == &quot;&quot; &amp;&amp;
+        (!doc.cm || doc.cm.options.wholeLineUpdateBefore)) {
</ins><span class="cx">       // This is a whole-line replace. Treated specially to make
</span><span class="cx">       // sure line objects move the way they are supposed to.
</span><span class="cx">       for (var i = 0, e = text.length - 1, added = []; i &lt; e; ++i)
</span><span class="lines">@@ -5446,7 +5507,7 @@
</span><span class="cx">     return true;
</span><span class="cx">   }
</span><span class="cx"> 
</span><del>-  var isExtendingChar = /[\u0300-\u036F\u0483-\u0487\u0488-\u0489\u0591-\u05BD\u05BF\u05C1-\u05C2\u05C4-\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7-\u06E8\u06EA-\u06ED\uA66F\uA670-\uA672\uA674-\uA67D\uA69F\udc00-\udfff]/;
</del><ins>+  var isExtendingChar = /[\u0300-\u036F\u0483-\u0487\u0488-\u0489\u0591-\u05BD\u05BF\u05C1-\u05C2\u05C4-\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7-\u06E8\u06EA-\u06ED\uA66F\u1DC0–\u1DFF\u20D0–\u20FF\uA670-\uA672\uA674-\uA67D\uA69F\udc00-\udfff\uFE20–\uFE2F]/;
</ins><span class="cx"> 
</span><span class="cx">   // DOM UTILITIES
</span><span class="cx"> 
</span><span class="lines">@@ -5520,7 +5581,7 @@
</span><span class="cx">         if (/\w/.test(str.charAt(i - 2)) &amp;&amp; /[^\-?\.]/.test(str.charAt(i))) return true;
</span><span class="cx">         if (i &gt; 2 &amp;&amp; /[\d\.,]/.test(str.charAt(i - 2)) &amp;&amp; /[\d\.,]/.test(str.charAt(i))) return false;
</span><span class="cx">       }
</span><del>-      var result = /[~!#%&amp;*)=+}\]|\&quot;\.&gt;,:;][({[&lt;]|-[^\-?\.\u2010-\u201f\u2026]|\?[\w~`@#$%\^&amp;*(_=+{[|&gt;&lt;]|…[\w~`@#$%\^&amp;*(_=+{[&gt;&lt;]/.test(str.slice(i - 1, i + 1));
</del><ins>+      var result = /[~!#%&amp;*)=+}\]\\|\&quot;\.&gt;,:;][({[&lt;]|-[^\-?\.\u2010-\u201f\u2026]|\?[\w~`@#$%\^&amp;*(_=+{[|&gt;&lt;]|…[\w~`@#$%\^&amp;*(_=+{[&gt;&lt;]/.test(str.slice(i - 1, i + 1));
</ins><span class="cx">       return result;
</span><span class="cx">     };
</span><span class="cx"> 
</span><span class="lines">@@ -5877,7 +5938,7 @@
</span><span class="cx"> 
</span><span class="cx">   // THE END
</span><span class="cx"> 
</span><del>-  CodeMirror.version = &quot;3.16.1&quot;;
</del><ins>+  CodeMirror.version = &quot;3.20.0&quot;;
</ins><span class="cx"> 
</span><span class="cx">   return CodeMirror;
</span><span class="cx"> })();
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIToolsPrettyPrintingcssjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/Tools/PrettyPrinting/css.js (160499 => 160500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/Tools/PrettyPrinting/css.js        2013-12-12 19:37:21 UTC (rev 160499)
+++ trunk/Source/WebInspectorUI/Tools/PrettyPrinting/css.js        2013-12-12 19:52:46 UTC (rev 160500)
</span><span class="lines">@@ -3,7 +3,7 @@
</span><span class="cx"> 
</span><span class="cx">   if (!parserConfig.propertyKeywords) parserConfig = CodeMirror.resolveMode(&quot;text/css&quot;);
</span><span class="cx"> 
</span><del>-  var indentUnit = config.indentUnit,
</del><ins>+  var indentUnit = config.indentUnit || config.tabSize || 2,
</ins><span class="cx">       hooks = parserConfig.hooks || {},
</span><span class="cx">       atMediaTypes = parserConfig.atMediaTypes || {},
</span><span class="cx">       atMediaFeatures = parserConfig.atMediaFeatures || {},
</span><span class="lines">@@ -37,7 +37,7 @@
</span><span class="cx">       stream.match(/^\s*\w*/);
</span><span class="cx">       return ret(&quot;keyword&quot;, &quot;important&quot;);
</span><span class="cx">     }
</span><del>-    else if (/\d/.test(ch)) {
</del><ins>+    else if (/\d/.test(ch) || ch == &quot;.&quot; &amp;&amp; stream.eat(/\d/)) {
</ins><span class="cx">       stream.eatWhile(/[\w.%]/);
</span><span class="cx">       return ret(&quot;number&quot;, &quot;unit&quot;);
</span><span class="cx">     }
</span><span class="lines">@@ -259,8 +259,13 @@
</span><span class="cx">       }
</span><span class="cx">       else if (type == &quot;}&quot;) {
</span><span class="cx">         if (context == &quot;interpolation&quot;) style = &quot;operator&quot;;
</span><del>-        state.stack.pop();
-        if (context == &quot;propertyValue&quot;) state.stack.pop();
</del><ins>+        // Pop off end of array until { is reached
+        while(state.stack.length){
+          var removed = state.stack.pop();
+          if(removed.indexOf(&quot;{&quot;) &gt; -1 || removed == &quot;block&quot; || removed == &quot;rule&quot;){
+            break;
+          }
+        }
</ins><span class="cx">       }
</span><span class="cx">       else if (type == &quot;interpolation&quot;) state.stack.push(&quot;interpolation&quot;);
</span><span class="cx">       else if (type == &quot;@media&quot;) state.stack.push(&quot;@media&quot;);
</span><span class="lines">@@ -278,11 +283,13 @@
</span><span class="cx">         else state.stack.push(&quot;(&quot;);
</span><span class="cx">       }
</span><span class="cx">       else if (type == &quot;)&quot;) {
</span><del>-        if (context == &quot;propertyValue&quot;) {
-          // In @mediaType( without closing ; after propertyValue
-          state.stack.pop();
</del><ins>+        // Pop off end of array until ( is reached
+        while(state.stack.length){
+          var removed = state.stack.pop();
+          if(removed.indexOf(&quot;(&quot;) &gt; -1){
+            break;
+          }
</ins><span class="cx">         }
</span><del>-        state.stack.pop();
</del><span class="cx">       }
</span><span class="cx">       else if (type == &quot;:&quot; &amp;&amp; state.lastToken == &quot;property&quot;) state.stack.push(&quot;propertyValue&quot;);
</span><span class="cx">       else if (context == &quot;propertyValue&quot; &amp;&amp; type == &quot;;&quot;) state.stack.pop();
</span><span class="lines">@@ -602,6 +609,11 @@
</span><span class="cx">         }
</span><span class="cx">         return [&quot;variable&quot;, &quot;variable&quot;];
</span><span class="cx">       },
</span><ins>+      &quot;,&quot;: function(stream, state) {
+        if (state.stack[state.stack.length - 1] == &quot;propertyValue&quot; &amp;&amp; stream.match(/^ *\$/, false)) {
+          return [&quot;operator&quot;, &quot;;&quot;];
+        }
+      },
</ins><span class="cx">       &quot;/&quot;: function(stream, state) {
</span><span class="cx">         if (stream.eat(&quot;/&quot;)) {
</span><span class="cx">           stream.skipToEnd();
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIToolsPrettyPrintingjavascriptjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/Tools/PrettyPrinting/javascript.js (160499 => 160500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/Tools/PrettyPrinting/javascript.js        2013-12-12 19:37:21 UTC (rev 160499)
+++ trunk/Source/WebInspectorUI/Tools/PrettyPrinting/javascript.js        2013-12-12 19:52:46 UTC (rev 160500)
</span><span class="lines">@@ -21,7 +21,8 @@
</span><span class="cx">       &quot;for&quot;: kw(&quot;for&quot;), &quot;switch&quot;: kw(&quot;switch&quot;), &quot;case&quot;: kw(&quot;case&quot;), &quot;default&quot;: kw(&quot;default&quot;),
</span><span class="cx">       &quot;in&quot;: operator, &quot;typeof&quot;: operator, &quot;instanceof&quot;: operator,
</span><span class="cx">       &quot;true&quot;: atom, &quot;false&quot;: atom, &quot;null&quot;: atom, &quot;undefined&quot;: atom, &quot;NaN&quot;: atom, &quot;Infinity&quot;: atom,
</span><del>-      &quot;this&quot;: kw(&quot;this&quot;)
</del><ins>+      &quot;this&quot;: kw(&quot;this&quot;), &quot;module&quot;: kw(&quot;module&quot;), &quot;class&quot;: kw(&quot;class&quot;), &quot;super&quot;: kw(&quot;atom&quot;),
+      &quot;yield&quot;: C, &quot;export&quot;: kw(&quot;export&quot;), &quot;import&quot;: kw(&quot;import&quot;), &quot;extends&quot;: C
</ins><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx">     // Extend the 'normal' keywords with the TypeScript language extensions
</span><span class="lines">@@ -30,7 +31,6 @@
</span><span class="cx">       var tsKeywords = {
</span><span class="cx">         // object-like things
</span><span class="cx">         &quot;interface&quot;: kw(&quot;interface&quot;),
</span><del>-        &quot;class&quot;: kw(&quot;class&quot;),
</del><span class="cx">         &quot;extends&quot;: kw(&quot;extends&quot;),
</span><span class="cx">         &quot;constructor&quot;: kw(&quot;constructor&quot;),
</span><span class="cx"> 
</span><span class="lines">@@ -40,8 +40,6 @@
</span><span class="cx">         &quot;protected&quot;: kw(&quot;protected&quot;),
</span><span class="cx">         &quot;static&quot;: kw(&quot;static&quot;),
</span><span class="cx"> 
</span><del>-        &quot;super&quot;: kw(&quot;super&quot;),
-
</del><span class="cx">         // types
</span><span class="cx">         &quot;string&quot;: type, &quot;number&quot;: type, &quot;bool&quot;: type, &quot;any&quot;: type
</span><span class="cx">       };
</span><span class="lines">@@ -56,11 +54,6 @@
</span><span class="cx"> 
</span><span class="cx">   var isOperatorChar = /[+\-*&amp;%=&lt;&gt;!?|~^]/;
</span><span class="cx"> 
</span><del>-  function chain(stream, state, f) {
-    state.tokenize = f;
-    return f(stream, state);
-  }
-
</del><span class="cx">   function nextUntilUnescaped(stream, end) {
</span><span class="cx">     var escaped = false, next;
</span><span class="cx">     while ((next = stream.next()) != null) {
</span><span class="lines">@@ -78,50 +71,51 @@
</span><span class="cx">     type = tp; content = cont;
</span><span class="cx">     return style;
</span><span class="cx">   }
</span><del>-  function jsTokenBase(stream, state) {
</del><ins>+  function tokenBase(stream, state) {
</ins><span class="cx">     var ch = stream.next();
</span><del>-    if (ch == '&quot;' || ch == &quot;'&quot;)
-      return chain(stream, state, jsTokenString(ch));
-    else if (ch == &quot;.&quot; &amp;&amp; stream.match(/^\d+(?:[eE][+\-]?\d+)?/))
</del><ins>+    if (ch == '&quot;' || ch == &quot;'&quot;) {
+      state.tokenize = tokenString(ch);
+      return state.tokenize(stream, state);
+    } else if (ch == &quot;.&quot; &amp;&amp; stream.match(/^\d+(?:[eE][+\-]?\d+)?/)) {
</ins><span class="cx">       return ret(&quot;number&quot;, &quot;number&quot;);
</span><del>-    else if (/[\[\]{}\(\),;\:\.]/.test(ch))
</del><ins>+    } else if (ch == &quot;.&quot; &amp;&amp; stream.match(&quot;..&quot;)) {
+      return ret(&quot;spread&quot;, &quot;meta&quot;);
+    } else if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
</ins><span class="cx">       return ret(ch);
</span><del>-    else if (ch == &quot;0&quot; &amp;&amp; stream.eat(/x/i)) {
</del><ins>+    } else if (ch == &quot;=&quot; &amp;&amp; stream.eat(&quot;&gt;&quot;)) {
+      return ret(&quot;=&gt;&quot;);
+    } else if (ch == &quot;0&quot; &amp;&amp; stream.eat(/x/i)) {
</ins><span class="cx">       stream.eatWhile(/[\da-f]/i);
</span><span class="cx">       return ret(&quot;number&quot;, &quot;number&quot;);
</span><del>-    }
-    else if (/\d/.test(ch)) {
</del><ins>+    } else if (/\d/.test(ch)) {
</ins><span class="cx">       stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
</span><span class="cx">       return ret(&quot;number&quot;, &quot;number&quot;);
</span><del>-    }
-    else if (ch == &quot;/&quot;) {
</del><ins>+    } else if (ch == &quot;/&quot;) {
</ins><span class="cx">       if (stream.eat(&quot;*&quot;)) {
</span><del>-        return chain(stream, state, jsTokenComment);
-      }
-      else if (stream.eat(&quot;/&quot;)) {
</del><ins>+        state.tokenize = tokenComment;
+        return tokenComment(stream, state);
+      } else if (stream.eat(&quot;/&quot;)) {
</ins><span class="cx">         stream.skipToEnd();
</span><span class="cx">         return ret(&quot;comment&quot;, &quot;comment&quot;);
</span><del>-      }
-      else if (state.lastType == &quot;operator&quot; || state.lastType == &quot;keyword c&quot; ||
-               /^[\[{}\(,;:]$/.test(state.lastType)) {
</del><ins>+      } else if (state.lastType == &quot;operator&quot; || state.lastType == &quot;keyword c&quot; ||
+               state.lastType == &quot;sof&quot; || /^[\[{}\(,;:]$/.test(state.lastType)) {
</ins><span class="cx">         nextUntilUnescaped(stream, &quot;/&quot;);
</span><span class="cx">         stream.eatWhile(/[gimy]/); // 'y' is &quot;sticky&quot; option in Mozilla
</span><span class="cx">         return ret(&quot;regexp&quot;, &quot;string-2&quot;);
</span><del>-      }
-      else {
</del><ins>+      } else {
</ins><span class="cx">         stream.eatWhile(isOperatorChar);
</span><span class="cx">         return ret(&quot;operator&quot;, null, stream.current());
</span><span class="cx">       }
</span><del>-    }
-    else if (ch == &quot;#&quot;) {
</del><ins>+    } else if (ch == &quot;`&quot;) {
+      state.tokenize = tokenQuasi;
+      return tokenQuasi(stream, state);
+    } else if (ch == &quot;#&quot;) {
</ins><span class="cx">       stream.skipToEnd();
</span><span class="cx">       return ret(&quot;error&quot;, &quot;error&quot;);
</span><del>-    }
-    else if (isOperatorChar.test(ch)) {
</del><ins>+    } else if (isOperatorChar.test(ch)) {
</ins><span class="cx">       stream.eatWhile(isOperatorChar);
</span><span class="cx">       return ret(&quot;operator&quot;, null, stream.current());
</span><del>-    }
-    else {
</del><ins>+    } else {
</ins><span class="cx">       stream.eatWhile(/[\w\$_]/);
</span><span class="cx">       var word = stream.current(), known = keywords.propertyIsEnumerable(word) &amp;&amp; keywords[word];
</span><span class="cx">       return (known &amp;&amp; state.lastType != &quot;.&quot;) ? ret(known.type, known.style, word) :
</span><span class="lines">@@ -129,19 +123,19 @@
</span><span class="cx">     }
</span><span class="cx">   }
</span><span class="cx"> 
</span><del>-  function jsTokenString(quote) {
</del><ins>+  function tokenString(quote) {
</ins><span class="cx">     return function(stream, state) {
</span><span class="cx">       if (!nextUntilUnescaped(stream, quote))
</span><del>-        state.tokenize = jsTokenBase;
</del><ins>+        state.tokenize = tokenBase;
</ins><span class="cx">       return ret(&quot;string&quot;, &quot;string&quot;);
</span><span class="cx">     };
</span><span class="cx">   }
</span><span class="cx"> 
</span><del>-  function jsTokenComment(stream, state) {
</del><ins>+  function tokenComment(stream, state) {
</ins><span class="cx">     var maybeEnd = false, ch;
</span><span class="cx">     while (ch = stream.next()) {
</span><span class="cx">       if (ch == &quot;/&quot; &amp;&amp; maybeEnd) {
</span><del>-        state.tokenize = jsTokenBase;
</del><ins>+        state.tokenize = tokenBase;
</ins><span class="cx">         break;
</span><span class="cx">       }
</span><span class="cx">       maybeEnd = (ch == &quot;*&quot;);
</span><span class="lines">@@ -149,6 +143,50 @@
</span><span class="cx">     return ret(&quot;comment&quot;, &quot;comment&quot;);
</span><span class="cx">   }
</span><span class="cx"> 
</span><ins>+  function tokenQuasi(stream, state) {
+    var escaped = false, next;
+    while ((next = stream.next()) != null) {
+      if (!escaped &amp;&amp; (next == &quot;`&quot; || next == &quot;$&quot; &amp;&amp; stream.eat(&quot;{&quot;))) {
+        state.tokenize = tokenBase;
+        break;
+      }
+      escaped = !escaped &amp;&amp; next == &quot;\\&quot;;
+    }
+    return ret(&quot;quasi&quot;, &quot;string-2&quot;, stream.current());
+  }
+
+  var brackets = &quot;([{}])&quot;;
+  // This is a crude lookahead trick to try and notice that we're
+  // parsing the argument patterns for a fat-arrow function before we
+  // actually hit the arrow token. It only works if the arrow is on
+  // the same line as the arguments and there's no strange noise
+  // (comments) in between. Fallback is to only notice when we hit the
+  // arrow, and not declare the arguments as locals for the arrow
+  // body.
+  function findFatArrow(stream, state) {
+    if (state.fatArrowAt) state.fatArrowAt = null;
+    var arrow = stream.string.indexOf(&quot;=&gt;&quot;, stream.start);
+    if (arrow &lt; 0) return;
+
+    var depth = 0, sawSomething = false;
+    for (var pos = arrow - 1; pos &gt;= 0; --pos) {
+      var ch = stream.string.charAt(pos);
+      var bracket = brackets.indexOf(ch);
+      if (bracket &gt;= 0 &amp;&amp; bracket &lt; 3) {
+        if (!depth) { ++pos; break; }
+        if (--depth == 0) break;
+      } else if (bracket &gt;= 3 &amp;&amp; bracket &lt; 6) {
+        ++depth;
+      } else if (/[$\w]/.test(ch)) {
+        sawSomething = true;
+      } else if (sawSomething &amp;&amp; !depth) {
+        ++pos;
+        break;
+      }
+    }
+    if (sawSomething &amp;&amp; !depth) state.fatArrowAt = pos;
+  }
+
</ins><span class="cx">   // Parser
</span><span class="cx"> 
</span><span class="cx">   var atomicTypes = {&quot;atom&quot;: true, &quot;number&quot;: true, &quot;variable&quot;: true, &quot;string&quot;: true, &quot;regexp&quot;: true, &quot;this&quot;: true};
</span><span class="lines">@@ -165,6 +203,10 @@
</span><span class="cx">   function inScope(state, varname) {
</span><span class="cx">     for (var v = state.localVars; v; v = v.next)
</span><span class="cx">       if (v.name == varname) return true;
</span><ins>+    for (var cx = state.context; cx; cx = cx.prev) {
+      for (var v = cx.vars; v; v = v.next)
+        if (v.name == varname) return true;
+    }
</ins><span class="cx">   }
</span><span class="cx"> 
</span><span class="cx">   function parseJS(state, style, type, content, stream) {
</span><span class="lines">@@ -211,7 +253,8 @@
</span><span class="cx">       state.localVars = {name: varname, next: state.localVars};
</span><span class="cx">     } else {
</span><span class="cx">       if (inList(state.globalVars)) return;
</span><del>-      state.globalVars = {name: varname, next: state.globalVars};
</del><ins>+      if (parserConfig.globalVars)
+        state.globalVars = {name: varname, next: state.globalVars};
</ins><span class="cx">     }
</span><span class="cx">   }
</span><span class="cx"> 
</span><span class="lines">@@ -253,16 +296,15 @@
</span><span class="cx">     };
</span><span class="cx">   }
</span><span class="cx"> 
</span><del>-  function statement(type) {
-    if (type == &quot;var&quot;) return cont(pushlex(&quot;vardef&quot;), vardef1, expect(&quot;;&quot;), poplex);
</del><ins>+  function statement(type, value) {
+    if (type == &quot;var&quot;) return cont(pushlex(&quot;vardef&quot;, value.length), vardef, expect(&quot;;&quot;), poplex);
</ins><span class="cx">     if (type == &quot;keyword a&quot;) return cont(pushlex(&quot;form&quot;), expression, statement, poplex);
</span><span class="cx">     if (type == &quot;keyword b&quot;) return cont(pushlex(&quot;form&quot;), statement, poplex);
</span><span class="cx">     if (type == &quot;{&quot;) return cont(pushlex(&quot;}&quot;), block, poplex);
</span><span class="cx">     if (type == &quot;;&quot;) return cont();
</span><span class="cx">     if (type == &quot;if&quot;) return cont(pushlex(&quot;form&quot;), expression, statement, poplex, maybeelse);
</span><span class="cx">     if (type == &quot;function&quot;) return cont(functiondef);
</span><del>-    if (type == &quot;for&quot;) return cont(pushlex(&quot;form&quot;), expect(&quot;(&quot;), pushlex(&quot;)&quot;), forspec1, expect(&quot;)&quot;),
-                                   poplex, statement, poplex);
</del><ins>+    if (type == &quot;for&quot;) return cont(pushlex(&quot;form&quot;), forspec, poplex, statement, poplex);
</ins><span class="cx">     if (type == &quot;variable&quot;) return cont(pushlex(&quot;stat&quot;), maybelabel);
</span><span class="cx">     if (type == &quot;switch&quot;) return cont(pushlex(&quot;form&quot;), expression, pushlex(&quot;}&quot;, &quot;switch&quot;), expect(&quot;{&quot;),
</span><span class="cx">                                       block, poplex, poplex);
</span><span class="lines">@@ -270,6 +312,10 @@
</span><span class="cx">     if (type == &quot;default&quot;) return cont(expect(&quot;:&quot;));
</span><span class="cx">     if (type == &quot;catch&quot;) return cont(pushlex(&quot;form&quot;), pushcontext, expect(&quot;(&quot;), funarg, expect(&quot;)&quot;),
</span><span class="cx">                                      statement, poplex, popcontext);
</span><ins>+    if (type == &quot;module&quot;) return cont(pushlex(&quot;form&quot;), pushcontext, afterModule, popcontext, poplex);
+    if (type == &quot;class&quot;) return cont(pushlex(&quot;form&quot;), className, objlit, poplex);
+    if (type == &quot;export&quot;) return cont(pushlex(&quot;form&quot;), afterExport, poplex);
+    if (type == &quot;import&quot;) return cont(pushlex(&quot;form&quot;), afterImport, poplex);
</ins><span class="cx">     return pass(pushlex(&quot;stat&quot;), expression, expect(&quot;;&quot;), poplex);
</span><span class="cx">   }
</span><span class="cx">   function expression(type) {
</span><span class="lines">@@ -279,14 +325,20 @@
</span><span class="cx">     return expressionInner(type, true);
</span><span class="cx">   }
</span><span class="cx">   function expressionInner(type, noComma) {
</span><ins>+    if (cx.state.fatArrowAt == cx.stream.start) {
+      var body = noComma ? arrowBodyNoComma : arrowBody;
+      if (type == &quot;(&quot;) return cont(pushcontext, commasep(pattern, &quot;)&quot;), expect(&quot;=&gt;&quot;), body, popcontext);
+      else if (type == &quot;variable&quot;) return pass(pushcontext, pattern, expect(&quot;=&gt;&quot;), body, popcontext);
+    }
+
</ins><span class="cx">     var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;
</span><span class="cx">     if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);
</span><span class="cx">     if (type == &quot;function&quot;) return cont(functiondef);
</span><span class="cx">     if (type == &quot;keyword c&quot;) return cont(noComma ? maybeexpressionNoComma : maybeexpression);
</span><del>-    if (type == &quot;(&quot;) return cont(pushlex(&quot;)&quot;), maybeexpression, expect(&quot;)&quot;), poplex, maybeop);
-    if (type == &quot;operator&quot;) return cont(noComma ? expressionNoComma : expression);
-    if (type == &quot;[&quot;) return cont(pushlex(&quot;]&quot;), commasep(expressionNoComma, &quot;]&quot;), poplex, maybeop);
-    if (type == &quot;{&quot;) return cont(pushlex(&quot;}&quot;), commasep(objprop, &quot;}&quot;), poplex, maybeop);
</del><ins>+    if (type == &quot;(&quot;) return cont(pushlex(&quot;)&quot;), maybeexpression, comprehension, expect(&quot;)&quot;), poplex, maybeop);
+    if (type == &quot;operator&quot; || type == &quot;spread&quot;) return cont(noComma ? expressionNoComma : expression);
+    if (type == &quot;[&quot;) return cont(pushlex(&quot;]&quot;), expressionNoComma, maybeArrayComprehension, poplex, maybeop);
+    if (type == &quot;{&quot;) return cont(commasep(objprop, &quot;}&quot;), maybeop);
</ins><span class="cx">     return cont();
</span><span class="cx">   }
</span><span class="cx">   function maybeexpression(type) {
</span><span class="lines">@@ -305,16 +357,40 @@
</span><span class="cx">   function maybeoperatorNoComma(type, value, noComma) {
</span><span class="cx">     var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma;
</span><span class="cx">     var expr = noComma == false ? expression : expressionNoComma;
</span><ins>+    if (value == &quot;=&gt;&quot;) return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext);
</ins><span class="cx">     if (type == &quot;operator&quot;) {
</span><span class="cx">       if (/\+\+|--/.test(value)) return cont(me);
</span><span class="cx">       if (value == &quot;?&quot;) return cont(expression, expect(&quot;:&quot;), expr);
</span><span class="cx">       return cont(expr);
</span><span class="cx">     }
</span><ins>+    if (type == &quot;quasi&quot;) { cx.cc.push(me); return quasi(value); }
</ins><span class="cx">     if (type == &quot;;&quot;) return;
</span><del>-    if (type == &quot;(&quot;) return cont(pushlex(&quot;)&quot;, &quot;call&quot;), commasep(expressionNoComma, &quot;)&quot;), poplex, me);
</del><ins>+    if (type == &quot;(&quot;) return cont(commasep(expressionNoComma, &quot;)&quot;, &quot;call&quot;), me);
</ins><span class="cx">     if (type == &quot;.&quot;) return cont(property, me);
</span><span class="cx">     if (type == &quot;[&quot;) return cont(pushlex(&quot;]&quot;), maybeexpression, expect(&quot;]&quot;), poplex, me);
</span><span class="cx">   }
</span><ins>+  function quasi(value) {
+    if (!value) debugger;
+    if (value.slice(value.length - 2) != &quot;${&quot;) return cont();
+    return cont(expression, continueQuasi);
+  }
+  function continueQuasi(type) {
+    if (type == &quot;}&quot;) {
+      cx.marked = &quot;string-2&quot;;
+      cx.state.tokenize = tokenQuasi;
+      return cont();
+    }
+  }
+  function arrowBody(type) {
+    findFatArrow(cx.stream, cx.state);
+    if (type == &quot;{&quot;) return pass(statement);
+    return pass(expression);
+  }
+  function arrowBodyNoComma(type) {
+    findFatArrow(cx.stream, cx.state);
+    if (type == &quot;{&quot;) return pass(statement);
+    return pass(expressionNoComma);
+  }
</ins><span class="cx">   function maybelabel(type) {
</span><span class="cx">     if (type == &quot;:&quot;) return cont(poplex, statement);
</span><span class="cx">     return pass(maybeoperatorComma, expect(&quot;;&quot;), poplex);
</span><span class="lines">@@ -328,16 +404,21 @@
</span><span class="cx">       if (value == &quot;get&quot; || value == &quot;set&quot;) return cont(getterSetter);
</span><span class="cx">     } else if (type == &quot;number&quot; || type == &quot;string&quot;) {
</span><span class="cx">       cx.marked = type + &quot; property&quot;;
</span><ins>+    } else if (type == &quot;[&quot;) {
+      return cont(expression, expect(&quot;]&quot;), afterprop);
</ins><span class="cx">     }
</span><del>-    if (atomicTypes.hasOwnProperty(type)) return cont(expect(&quot;:&quot;), expressionNoComma);
</del><ins>+    if (atomicTypes.hasOwnProperty(type)) return cont(afterprop);
</ins><span class="cx">   }
</span><span class="cx">   function getterSetter(type) {
</span><del>-    if (type == &quot;:&quot;) return cont(expression);
-    if (type != &quot;variable&quot;) return cont(expect(&quot;:&quot;), expression);
</del><ins>+    if (type != &quot;variable&quot;) return pass(afterprop);
</ins><span class="cx">     cx.marked = &quot;property&quot;;
</span><span class="cx">     return cont(functiondef);
</span><span class="cx">   }
</span><del>-  function commasep(what, end) {
</del><ins>+  function afterprop(type) {
+    if (type == &quot;:&quot;) return cont(expressionNoComma);
+    if (type == &quot;(&quot;) return pass(functiondef);
+  }
+  function commasep(what, end, info) {
</ins><span class="cx">     function proceed(type) {
</span><span class="cx">       if (type == &quot;,&quot;) {
</span><span class="cx">         var lex = cx.state.lexical;
</span><span class="lines">@@ -349,7 +430,8 @@
</span><span class="cx">     }
</span><span class="cx">     return function(type) {
</span><span class="cx">       if (type == end) return cont();
</span><del>-      else return pass(what, proceed);
</del><ins>+      if (info === false) return pass(what, proceed);
+      return pass(pushlex(end, info), what, proceed, poplex);
</ins><span class="cx">     };
</span><span class="cx">   }
</span><span class="cx">   function block(type) {
</span><span class="lines">@@ -357,67 +439,121 @@
</span><span class="cx">     return pass(statement, block);
</span><span class="cx">   }
</span><span class="cx">   function maybetype(type) {
</span><del>-    if (type == &quot;:&quot;) return cont(typedef);
-    return pass();
</del><ins>+    if (isTS &amp;&amp; type == &quot;:&quot;) return cont(typedef);
</ins><span class="cx">   }
</span><span class="cx">   function typedef(type) {
</span><span class="cx">     if (type == &quot;variable&quot;){cx.marked = &quot;variable-3&quot;; return cont();}
</span><del>-    return pass();
</del><span class="cx">   }
</span><del>-  function vardef1(type, value) {
-    if (type == &quot;variable&quot;) {
</del><ins>+  function vardef() {
+    return pass(pattern, maybetype, maybeAssign, vardefCont);
+  }
+  function pattern(type, value) {
+    if (type == &quot;variable&quot;) { register(value); return cont(); }
+    if (type == &quot;[&quot;) return cont(commasep(pattern, &quot;]&quot;));
+    if (type == &quot;{&quot;) return cont(commasep(proppattern, &quot;}&quot;));
+  }
+  function proppattern(type, value) {
+    if (type == &quot;variable&quot; &amp;&amp; !cx.stream.match(/^\s*:/, false)) {
</ins><span class="cx">       register(value);
</span><del>-      return isTS ? cont(maybetype, vardef2) : cont(vardef2);
</del><ins>+      return cont(maybeAssign);
</ins><span class="cx">     }
</span><del>-    return pass();
</del><ins>+    if (type == &quot;variable&quot;) cx.marked = &quot;property&quot;;
+    return cont(expect(&quot;:&quot;), pattern, maybeAssign);
</ins><span class="cx">   }
</span><del>-  function vardef2(type, value) {
-    if (value == &quot;=&quot;) return cont(expressionNoComma, vardef2);
-    if (type == &quot;,&quot;) return cont(vardef1);
</del><ins>+  function maybeAssign(_type, value) {
+    if (value == &quot;=&quot;) return cont(expressionNoComma);
</ins><span class="cx">   }
</span><ins>+  function vardefCont(type) {
+    if (type == &quot;,&quot;) return cont(vardef);
+  }
</ins><span class="cx">   function maybeelse(type, value) {
</span><span class="cx">     if (type == &quot;keyword b&quot; &amp;&amp; value == &quot;else&quot;) return cont(pushlex(&quot;form&quot;), statement, poplex);
</span><span class="cx">   }
</span><ins>+  function forspec(type) {
+    if (type == &quot;(&quot;) return cont(pushlex(&quot;)&quot;), forspec1, expect(&quot;)&quot;));
+  }
</ins><span class="cx">   function forspec1(type) {
</span><del>-    if (type == &quot;var&quot;) return cont(vardef1, expect(&quot;;&quot;), forspec2);
</del><ins>+    if (type == &quot;var&quot;) return cont(vardef, expect(&quot;;&quot;), forspec2);
</ins><span class="cx">     if (type == &quot;;&quot;) return cont(forspec2);
</span><del>-    if (type == &quot;variable&quot;) return cont(formaybein);
</del><ins>+    if (type == &quot;variable&quot;) return cont(formaybeinof);
</ins><span class="cx">     return pass(expression, expect(&quot;;&quot;), forspec2);
</span><span class="cx">   }
</span><del>-  function formaybein(_type, value) {
-    if (value == &quot;in&quot;) return cont(expression);
</del><ins>+  function formaybeinof(_type, value) {
+    if (value == &quot;in&quot; || value == &quot;of&quot;) { cx.marked = &quot;keyword&quot;; return cont(expression); }
</ins><span class="cx">     return cont(maybeoperatorComma, forspec2);
</span><span class="cx">   }
</span><span class="cx">   function forspec2(type, value) {
</span><span class="cx">     if (type == &quot;;&quot;) return cont(forspec3);
</span><del>-    if (value == &quot;in&quot;) return cont(expression);
</del><ins>+    if (value == &quot;in&quot; || value == &quot;of&quot;) { cx.marked = &quot;keyword&quot;; return cont(expression); }
</ins><span class="cx">     return pass(expression, expect(&quot;;&quot;), forspec3);
</span><span class="cx">   }
</span><span class="cx">   function forspec3(type) {
</span><span class="cx">     if (type != &quot;)&quot;) cont(expression);
</span><span class="cx">   }
</span><span class="cx">   function functiondef(type, value) {
</span><ins>+    if (value == &quot;*&quot;) {cx.marked = &quot;keyword&quot;; return cont(functiondef);}
</ins><span class="cx">     if (type == &quot;variable&quot;) {register(value); return cont(functiondef);}
</span><del>-    if (type == &quot;(&quot;) return cont(pushlex(&quot;)&quot;), pushcontext, commasep(funarg, &quot;)&quot;), poplex, statement, popcontext);
</del><ins>+    if (type == &quot;(&quot;) return cont(pushcontext, commasep(funarg, &quot;)&quot;), statement, popcontext);
</ins><span class="cx">   }
</span><del>-  function funarg(type, value) {
-    if (type == &quot;variable&quot;) {register(value); return isTS ? cont(maybetype) : cont();}
</del><ins>+  function funarg(type) {
+    if (type == &quot;spread&quot;) return cont(funarg);
+    return pass(pattern, maybetype);
</ins><span class="cx">   }
</span><ins>+  function className(type, value) {
+    if (type == &quot;variable&quot;) {register(value); return cont(classNameAfter);}
+  }
+  function classNameAfter(_type, value) {
+    if (value == &quot;extends&quot;) return cont(expression);
+  }
+  function objlit(type) {
+    if (type == &quot;{&quot;) return cont(commasep(objprop, &quot;}&quot;));
+  }
+  function afterModule(type, value) {
+    if (type == &quot;string&quot;) return cont(statement);
+    if (type == &quot;variable&quot;) { register(value); return cont(maybeFrom); }
+  }
+  function afterExport(_type, value) {
+    if (value == &quot;*&quot;) { cx.marked = &quot;keyword&quot;; return cont(maybeFrom, expect(&quot;;&quot;)); }
+    if (value == &quot;default&quot;) { cx.marked = &quot;keyword&quot;; return cont(expression, expect(&quot;;&quot;)); }
+    return pass(statement);
+  }
+  function afterImport(type) {
+    if (type == &quot;string&quot;) return cont();
+    return pass(importSpec, maybeFrom);
+  }
+  function importSpec(type, value) {
+    if (type == &quot;{&quot;) return cont(commasep(importSpec, &quot;}&quot;));
+    if (type == &quot;variable&quot;) register(value);
+    return cont();
+  }
+  function maybeFrom(_type, value) {
+    if (value == &quot;from&quot;) { cx.marked = &quot;keyword&quot;; return cont(expression); }
+  }
+  function maybeArrayComprehension(type) {
+    if (type == &quot;for&quot;) return pass(comprehension);
+    if (type == &quot;,&quot;) return cont(commasep(expressionNoComma, &quot;]&quot;, false));
+    return pass(commasep(expressionNoComma, &quot;]&quot;, false));
+  }
+  function comprehension(type) {
+    if (type == &quot;for&quot;) return cont(forspec, comprehension);
+    if (type == &quot;if&quot;) return cont(expression, comprehension);
+  }
</ins><span class="cx"> 
</span><span class="cx">   // Interface
</span><span class="cx"> 
</span><span class="cx">   return {
</span><span class="cx">     startState: function(basecolumn) {
</span><del>-      return {
-        tokenize: jsTokenBase,
-        lastType: null,
</del><ins>+      var state = {
+        tokenize: tokenBase,
+        lastType: &quot;sof&quot;,
</ins><span class="cx">         cc: [],
</span><span class="cx">         lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, &quot;block&quot;, false),
</span><span class="cx">         localVars: parserConfig.localVars,
</span><del>-        globalVars: parserConfig.globalVars,
</del><span class="cx">         context: parserConfig.localVars &amp;&amp; {vars: parserConfig.localVars},
</span><span class="cx">         indented: 0
</span><span class="cx">       };
</span><ins>+      if (parserConfig.globalVars) state.globalVars = parserConfig.globalVars;
+      return state;
</ins><span class="cx">     },
</span><span class="cx"> 
</span><span class="cx">     token: function(stream, state) {
</span><span class="lines">@@ -425,8 +561,9 @@
</span><span class="cx">         if (!state.lexical.hasOwnProperty(&quot;align&quot;))
</span><span class="cx">           state.lexical.align = false;
</span><span class="cx">         state.indented = stream.indentation();
</span><ins>+        findFatArrow(stream, state);
</ins><span class="cx">       }
</span><del>-      if (state.tokenize != jsTokenComment &amp;&amp; stream.eatSpace()) return null;
</del><ins>+      if (state.tokenize != tokenComment &amp;&amp; stream.eatSpace()) return null;
</ins><span class="cx">       var style = state.tokenize(stream, state);
</span><span class="cx">       if (type == &quot;comment&quot;) return style;
</span><span class="cx">       state.lastType = type == &quot;operator&quot; &amp;&amp; (content == &quot;++&quot; || content == &quot;--&quot;) ? &quot;incdec&quot; : type;
</span><span class="lines">@@ -434,21 +571,21 @@
</span><span class="cx">     },
</span><span class="cx"> 
</span><span class="cx">     indent: function(state, textAfter) {
</span><del>-      if (state.tokenize == jsTokenComment) return CodeMirror.Pass;
-      if (state.tokenize != jsTokenBase) return 0;
</del><ins>+      if (state.tokenize == tokenComment) return CodeMirror.Pass;
+      if (state.tokenize != tokenBase) return 0;
</ins><span class="cx">       var firstChar = textAfter &amp;&amp; textAfter.charAt(0), lexical = state.lexical;
</span><span class="cx">       // Kludge to prevent 'maybelse' from blocking lexical scope pops
</span><span class="cx">       for (var i = state.cc.length - 1; i &gt;= 0; --i) {
</span><span class="cx">         var c = state.cc[i];
</span><span class="cx">         if (c == poplex) lexical = lexical.prev;
</span><del>-        else if (c != maybeelse || /^else\b/.test(textAfter)) break;
</del><ins>+        else if (c != maybeelse) break;
</ins><span class="cx">       }
</span><span class="cx">       if (lexical.type == &quot;stat&quot; &amp;&amp; firstChar == &quot;}&quot;) lexical = lexical.prev;
</span><span class="cx">       if (statementIndent &amp;&amp; lexical.type == &quot;)&quot; &amp;&amp; lexical.prev.type == &quot;stat&quot;)
</span><span class="cx">         lexical = lexical.prev;
</span><span class="cx">       var type = lexical.type, closing = firstChar == type;
</span><span class="cx"> 
</span><del>-      if (type == &quot;vardef&quot;) return lexical.indented + (state.lastType == &quot;operator&quot; || state.lastType == &quot;,&quot; ? 4 : 0);
</del><ins>+      if (type == &quot;vardef&quot;) return lexical.indented + (state.lastType == &quot;operator&quot; || state.lastType == &quot;,&quot; ? lexical.info + 1 : 0);
</ins><span class="cx">       else if (type == &quot;form&quot; &amp;&amp; firstChar == &quot;{&quot;) return lexical.indented;
</span><span class="cx">       else if (type == &quot;form&quot;) return lexical.indented + indentUnit;
</span><span class="cx">       else if (type == &quot;stat&quot;)
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceExternalCodeMirrorcodemirrorcss"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/codemirror.css (160499 => 160500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/codemirror.css        2013-12-12 19:37:21 UTC (rev 160499)
+++ trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/codemirror.css        2013-12-12 19:52:46 UTC (rev 160500)
</span><span class="lines">@@ -74,7 +74,6 @@
</span><span class="cx"> .cm-s-default .cm-string {color: #a11;}
</span><span class="cx"> .cm-s-default .cm-string-2 {color: #f50;}
</span><span class="cx"> .cm-s-default .cm-meta {color: #555;}
</span><del>-.cm-s-default .cm-error {color: #f00;}
</del><span class="cx"> .cm-s-default .cm-qualifier {color: #555;}
</span><span class="cx"> .cm-s-default .cm-builtin {color: #30a;}
</span><span class="cx"> .cm-s-default .cm-bracket {color: #997;}
</span><span class="lines">@@ -91,6 +90,7 @@
</span><span class="cx"> .cm-em {font-style: italic;}
</span><span class="cx"> .cm-link {text-decoration: underline;}
</span><span class="cx"> 
</span><ins>+.cm-s-default .cm-error {color: #f00;}
</ins><span class="cx"> .cm-invalidchar {color: #f00;}
</span><span class="cx"> 
</span><span class="cx"> div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceExternalCodeMirrorcodemirrorjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/codemirror.js (160499 => 160500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/codemirror.js        2013-12-12 19:37:21 UTC (rev 160499)
+++ trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/codemirror.js        2013-12-12 19:52:46 UTC (rev 160500)
</span><span class="lines">@@ -7,9 +7,13 @@
</span><span class="cx">   // Crude, but necessary to handle a number of hard-to-feature-detect
</span><span class="cx">   // bugs and behavior differences.
</span><span class="cx">   var gecko = /gecko\/\d/i.test(navigator.userAgent);
</span><ins>+  // IE11 currently doesn't count as 'ie', since it has almost none of
+  // the same bugs as earlier versions. Use ie_gt10 to handle
+  // incompatibilities in that version.
</ins><span class="cx">   var ie = /MSIE \d/.test(navigator.userAgent);
</span><span class="cx">   var ie_lt8 = ie &amp;&amp; (document.documentMode == null || document.documentMode &lt; 8);
</span><span class="cx">   var ie_lt9 = ie &amp;&amp; (document.documentMode == null || document.documentMode &lt; 9);
</span><ins>+  var ie_gt10 = /Trident\/([7-9]|\d{2,})\./.test(navigator.userAgent);
</ins><span class="cx">   var webkit = /WebKit\//.test(navigator.userAgent);
</span><span class="cx">   var qtwebkit = webkit &amp;&amp; /Qt\/\d+\.\d+/.test(navigator.userAgent);
</span><span class="cx">   var chrome = /Chrome\//.test(navigator.userAgent);
</span><span class="lines">@@ -309,7 +313,7 @@
</span><span class="cx">       options.gutters = options.gutters.concat([&quot;CodeMirror-linenumbers&quot;]);
</span><span class="cx">     } else if (found &gt; -1 &amp;&amp; !options.lineNumbers) {
</span><span class="cx">       options.gutters = options.gutters.slice(0);
</span><del>-      options.gutters.splice(i, 1);
</del><ins>+      options.gutters.splice(found, 1);
</ins><span class="cx">     }
</span><span class="cx">   }
</span><span class="cx"> 
</span><span class="lines">@@ -353,8 +357,10 @@
</span><span class="cx">       d.gutterFiller.style.width = d.gutters.offsetWidth + &quot;px&quot;;
</span><span class="cx">     } else d.gutterFiller.style.display = &quot;&quot;;
</span><span class="cx"> 
</span><del>-    if (mac_geLion &amp;&amp; scrollbarWidth(d.measure) === 0)
</del><ins>+    if (mac_geLion &amp;&amp; scrollbarWidth(d.measure) === 0) {
</ins><span class="cx">       d.scrollbarV.style.minWidth = d.scrollbarH.style.minHeight = mac_geMountainLion ? &quot;18px&quot; : &quot;12px&quot;;
</span><ins>+      d.scrollbarV.style.pointerEvents = d.scrollbarH.style.pointerEvents = &quot;none&quot;;
+    }
</ins><span class="cx">   }
</span><span class="cx"> 
</span><span class="cx">   function visibleLines(display, doc, viewPort) {
</span><span class="lines">@@ -409,14 +415,14 @@
</span><span class="cx">   function updateDisplay(cm, changes, viewPort, forced) {
</span><span class="cx">     var oldFrom = cm.display.showingFrom, oldTo = cm.display.showingTo, updated;
</span><span class="cx">     var visible = visibleLines(cm.display, cm.doc, viewPort);
</span><del>-    for (;;) {
</del><ins>+    for (var first = true;; first = false) {
</ins><span class="cx">       var oldWidth = cm.display.scroller.clientWidth;
</span><span class="cx">       if (!updateDisplayInner(cm, changes, visible, forced)) break;
</span><span class="cx">       updated = true;
</span><span class="cx">       changes = [];
</span><span class="cx">       updateSelection(cm);
</span><span class="cx">       updateScrollbars(cm);
</span><del>-      if (cm.options.lineWrapping &amp;&amp; oldWidth != cm.display.scroller.clientWidth) {
</del><ins>+      if (first &amp;&amp; cm.options.lineWrapping &amp;&amp; oldWidth != cm.display.scroller.clientWidth) {
</ins><span class="cx">         forced = true;
</span><span class="cx">         continue;
</span><span class="cx">       }
</span><span class="lines">@@ -904,7 +910,7 @@
</span><span class="cx">     doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.showingTo + 500), function(line) {
</span><span class="cx">       if (doc.frontier &gt;= cm.display.showingFrom) { // Visible
</span><span class="cx">         var oldStyles = line.styles;
</span><del>-        line.styles = highlightLine(cm, line, state);
</del><ins>+        line.styles = highlightLine(cm, line, state, true);
</ins><span class="cx">         var ischange = !oldStyles || oldStyles.length != line.styles.length;
</span><span class="cx">         for (var i = 0; !ischange &amp;&amp; i &lt; oldStyles.length; ++i) ischange = oldStyles[i] != line.styles[i];
</span><span class="cx">         if (ischange) {
</span><span class="lines">@@ -913,7 +919,7 @@
</span><span class="cx">         }
</span><span class="cx">         line.stateAfter = copyState(doc.mode, state);
</span><span class="cx">       } else {
</span><del>-        processLine(cm, line, state);
</del><ins>+        processLine(cm, line.text, state);
</ins><span class="cx">         line.stateAfter = doc.frontier % 5 == 0 ? copyState(doc.mode, state) : null;
</span><span class="cx">       }
</span><span class="cx">       ++doc.frontier;
</span><span class="lines">@@ -935,8 +941,9 @@
</span><span class="cx">   // smallest indentation, which tends to need the least context to
</span><span class="cx">   // parse correctly.
</span><span class="cx">   function findStartLine(cm, n, precise) {
</span><del>-    var minindent, minline, doc = cm.doc, maxScan = cm.doc.mode.innerMode ? 1000 : 100;
-    for (var search = n, lim = n - maxScan; search &gt; lim; --search) {
</del><ins>+    var minindent, minline, doc = cm.doc;
+    var lim = precise ? -1 : n - (cm.doc.mode.innerMode ? 1000 : 100);
+    for (var search = n; search &gt; lim; --search) {
</ins><span class="cx">       if (search &lt;= doc.first) return doc.first;
</span><span class="cx">       var line = getLine(doc, search - 1);
</span><span class="cx">       if (line.stateAfter &amp;&amp; (!precise || search &lt;= doc.frontier)) return search;
</span><span class="lines">@@ -956,11 +963,12 @@
</span><span class="cx">     if (!state) state = startState(doc.mode);
</span><span class="cx">     else state = copyState(doc.mode, state);
</span><span class="cx">     doc.iter(pos, n, function(line) {
</span><del>-      processLine(cm, line, state);
</del><ins>+      processLine(cm, line.text, state);
</ins><span class="cx">       var save = pos == n - 1 || pos % 5 == 0 || pos &gt;= display.showingFrom &amp;&amp; pos &lt; display.showingTo;
</span><span class="cx">       line.stateAfter = save ? copyState(doc.mode, state) : null;
</span><span class="cx">       ++pos;
</span><span class="cx">     });
</span><ins>+    if (precise) doc.frontier = pos;
</ins><span class="cx">     return state;
</span><span class="cx">   }
</span><span class="cx"> 
</span><span class="lines">@@ -1001,7 +1009,7 @@
</span><span class="cx">       var memo = cache[i];
</span><span class="cx">       if (memo.text == line.text &amp;&amp; memo.markedSpans == line.markedSpans &amp;&amp;
</span><span class="cx">           cm.display.scroller.clientWidth == memo.width &amp;&amp;
</span><del>-          memo.classes == line.textClass + &quot;|&quot; + line.bgClass + &quot;|&quot; + line.wrapClass)
</del><ins>+          memo.classes == line.textClass + &quot;|&quot; + line.wrapClass)
</ins><span class="cx">         return memo;
</span><span class="cx">     }
</span><span class="cx">   }
</span><span class="lines">@@ -1021,7 +1029,7 @@
</span><span class="cx">     var cache = cm.display.measureLineCache;
</span><span class="cx">     var memo = {text: line.text, width: cm.display.scroller.clientWidth,
</span><span class="cx">                 markedSpans: line.markedSpans, measure: measure,
</span><del>-                classes: line.textClass + &quot;|&quot; + line.bgClass + &quot;|&quot; + line.wrapClass};
</del><ins>+                classes: line.textClass + &quot;|&quot; + line.wrapClass};
</ins><span class="cx">     if (cache.length == 16) cache[++cm.display.measureLineCachePos % 16] = memo;
</span><span class="cx">     else cache.push(memo);
</span><span class="cx">     return measure;
</span><span class="lines">@@ -1379,11 +1387,14 @@
</span><span class="cx">     }
</span><span class="cx">     if (!updated &amp;&amp; op.selectionChanged) updateSelection(cm);
</span><span class="cx">     if (op.updateScrollPos) {
</span><del>-      display.scroller.scrollTop = display.scrollbarV.scrollTop = doc.scrollTop = newScrollPos.scrollTop;
-      display.scroller.scrollLeft = display.scrollbarH.scrollLeft = doc.scrollLeft = newScrollPos.scrollLeft;
</del><ins>+      var top = Math.max(0, Math.min(display.scroller.scrollHeight - display.scroller.clientHeight, newScrollPos.scrollTop));
+      var left = Math.max(0, Math.min(display.scroller.scrollWidth - display.scroller.clientWidth, newScrollPos.scrollLeft));
+      display.scroller.scrollTop = display.scrollbarV.scrollTop = doc.scrollTop = top;
+      display.scroller.scrollLeft = display.scrollbarH.scrollLeft = doc.scrollLeft = left;
</ins><span class="cx">       alignHorizontally(cm);
</span><span class="cx">       if (op.scrollToPos)
</span><del>-        scrollPosIntoView(cm, clipPos(cm.doc, op.scrollToPos), op.scrollToPosMargin);
</del><ins>+        scrollPosIntoView(cm, clipPos(cm.doc, op.scrollToPos.from),
+                          clipPos(cm.doc, op.scrollToPos.to), op.scrollToPos.margin);
</ins><span class="cx">     } else if (newScrollPos) {
</span><span class="cx">       scrollCursorIntoView(cm);
</span><span class="cx">     }
</span><span class="lines">@@ -1605,7 +1616,10 @@
</span><span class="cx">       if (signalDOMEvent(cm, e) || cm.options.onKeyEvent &amp;&amp; cm.options.onKeyEvent(cm, addStop(e))) return;
</span><span class="cx">       if (e.keyCode == 16) cm.doc.sel.shift = false;
</span><span class="cx">     }));
</span><del>-    on(d.input, &quot;input&quot;, bind(fastPoll, cm));
</del><ins>+    on(d.input, &quot;input&quot;, function() {
+      if (ie &amp;&amp; !ie_lt9 &amp;&amp; cm.display.inputHasSelection) cm.display.inputHasSelection = null;
+      fastPoll(cm);
+    });
</ins><span class="cx">     on(d.input, &quot;keydown&quot;, operation(cm, onKeyDown));
</span><span class="cx">     on(d.input, &quot;keypress&quot;, operation(cm, onKeyPress));
</span><span class="cx">     on(d.input, &quot;focus&quot;, bind(onFocus, cm));
</span><span class="lines">@@ -1895,7 +1909,6 @@
</span><span class="cx">           if (cm.state.draggingText) replaceRange(cm.doc, &quot;&quot;, curFrom, curTo, &quot;paste&quot;);
</span><span class="cx">           cm.replaceSelection(text, null, &quot;paste&quot;);
</span><span class="cx">           focusInput(cm);
</span><del>-          onFocus(cm);
</del><span class="cx">         }
</span><span class="cx">       }
</span><span class="cx">       catch(e){}
</span><span class="lines">@@ -2176,7 +2189,11 @@
</span><span class="cx"> 
</span><span class="cx">     var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop;
</span><span class="cx">     if (!pos || opera) return; // Opera is difficult.
</span><del>-    if (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to))
</del><ins>+
+    // Reset the current text selection only if the click is done outside of the selection
+    // and 'resetSelectionOnContextMenu' option is true.
+    var reset = cm.options.resetSelectionOnContextMenu;
+    if (reset &amp;&amp; (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to)))
</ins><span class="cx">       operation(cm, setSelection)(cm.doc, pos, pos);
</span><span class="cx"> 
</span><span class="cx">     var oldCSS = display.input.style.cssText;
</span><span class="lines">@@ -2326,6 +2343,7 @@
</span><span class="cx">   }
</span><span class="cx"> 
</span><span class="cx">   function makeChangeNoReadonly(doc, change, selUpdate) {
</span><ins>+    if (change.text.length == 1 &amp;&amp; change.text[0] == &quot;&quot; &amp;&amp; posEq(change.from, change.to)) return;
</ins><span class="cx">     var selAfter = computeSelAfterChange(doc, change, selUpdate);
</span><span class="cx">     addToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN);
</span><span class="cx"> 
</span><span class="lines">@@ -2626,7 +2644,7 @@
</span><span class="cx">   // SCROLLING
</span><span class="cx"> 
</span><span class="cx">   function scrollCursorIntoView(cm) {
</span><del>-    var coords = scrollPosIntoView(cm, cm.doc.sel.head, cm.options.cursorScrollMargin);
</del><ins>+    var coords = scrollPosIntoView(cm, cm.doc.sel.head, null, cm.options.cursorScrollMargin);
</ins><span class="cx">     if (!cm.state.focused) return;
</span><span class="cx">     var display = cm.display, box = getRect(display.sizer), doScroll = null;
</span><span class="cx">     if (coords.top + box.top &lt; 0) doScroll = true;
</span><span class="lines">@@ -2643,11 +2661,15 @@
</span><span class="cx">     }
</span><span class="cx">   }
</span><span class="cx"> 
</span><del>-  function scrollPosIntoView(cm, pos, margin) {
</del><ins>+  function scrollPosIntoView(cm, pos, end, margin) {
</ins><span class="cx">     if (margin == null) margin = 0;
</span><span class="cx">     for (;;) {
</span><span class="cx">       var changed = false, coords = cursorCoords(cm, pos);
</span><del>-      var scrollPos = calculateScrollPos(cm, coords.left, coords.top - margin, coords.left, coords.bottom + margin);
</del><ins>+      var endCoords = !end || end == pos ? coords : cursorCoords(cm, end);
+      var scrollPos = calculateScrollPos(cm, Math.min(coords.left, endCoords.left),
+                                         Math.min(coords.top, endCoords.top) - margin,
+                                         Math.max(coords.left, endCoords.left),
+                                         Math.max(coords.bottom, endCoords.bottom) + margin);
</ins><span class="cx">       var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft;
</span><span class="cx">       if (scrollPos.scrollTop != null) {
</span><span class="cx">         setScrollTop(cm, scrollPos.scrollTop);
</span><span class="lines">@@ -2744,6 +2766,8 @@
</span><span class="cx"> 
</span><span class="cx">     if (indentString != curSpaceString)
</span><span class="cx">       replaceRange(cm.doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), &quot;+input&quot;);
</span><ins>+    else if (doc.sel.head.line == n &amp;&amp; doc.sel.head.ch &lt; curSpaceString.length)
+      setSelection(doc, Pos(n, curSpaceString.length), Pos(n, curSpaceString.length), 1);
</ins><span class="cx">     line.stateAfter = null;
</span><span class="cx">   }
</span><span class="cx"> 
</span><span class="lines">@@ -2844,7 +2868,7 @@
</span><span class="cx"> 
</span><span class="cx">   CodeMirror.prototype = {
</span><span class="cx">     constructor: CodeMirror,
</span><del>-    focus: function(){window.focus(); focusInput(this); onFocus(this); fastPoll(this);},
</del><ins>+    focus: function(){window.focus(); focusInput(this); fastPoll(this);},
</ins><span class="cx"> 
</span><span class="cx">     setOption: function(option, value) {
</span><span class="cx">       var options = this.options, old = options[option];
</span><span class="lines">@@ -3165,17 +3189,23 @@
</span><span class="cx">               clientHeight: scroller.clientHeight - co, clientWidth: scroller.clientWidth - co};
</span><span class="cx">     },
</span><span class="cx"> 
</span><del>-    scrollIntoView: operation(null, function(pos, margin) {
-      if (typeof pos == &quot;number&quot;) pos = Pos(pos, 0);
</del><ins>+    scrollIntoView: operation(null, function(range, margin) {
+      if (range == null) range = {from: this.doc.sel.head, to: null};
+      else if (typeof range == &quot;number&quot;) range = {from: Pos(range, 0), to: null};
+      else if (range.from == null) range = {from: range, to: null};
+      if (!range.to) range.to = range.from;
</ins><span class="cx">       if (!margin) margin = 0;
</span><del>-      var coords = pos;
</del><span class="cx"> 
</span><del>-      if (!pos || pos.line != null) {
-        this.curOp.scrollToPos = pos ? clipPos(this.doc, pos) : this.doc.sel.head;
-        this.curOp.scrollToPosMargin = margin;
-        coords = cursorCoords(this, this.curOp.scrollToPos);
</del><ins>+      var coords = range;
+      if (range.from.line != null) {
+        this.curOp.scrollToPos = {from: range.from, to: range.to, margin: margin};
+        coords = {from: cursorCoords(this, range.from),
+                  to: cursorCoords(this, range.to)};
</ins><span class="cx">       }
</span><del>-      var sPos = calculateScrollPos(this, coords.left, coords.top - margin, coords.right, coords.bottom + margin);
</del><ins>+      var sPos = calculateScrollPos(this, Math.min(coords.from.left, coords.to.left),
+                                    Math.min(coords.from.top, coords.to.top) - margin,
+                                    Math.max(coords.from.right, coords.to.right),
+                                    Math.max(coords.from.bottom, coords.to.bottom) + margin);
</ins><span class="cx">       updateScrollPos(this, sPos.scrollLeft, sPos.scrollTop);
</span><span class="cx">     }),
</span><span class="cx"> 
</span><span class="lines">@@ -3207,6 +3237,7 @@
</span><span class="cx">       clearCaches(this);
</span><span class="cx">       resetInput(this, true);
</span><span class="cx">       updateScrollPos(this, doc.scrollLeft, doc.scrollTop);
</span><ins>+      signalLater(this, &quot;swapDoc&quot;, this, old);
</ins><span class="cx">       return old;
</span><span class="cx">     }),
</span><span class="cx"> 
</span><span class="lines">@@ -3250,8 +3281,14 @@
</span><span class="cx">     clearCaches(cm);
</span><span class="cx">     regChange(cm);
</span><span class="cx">   }, true);
</span><ins>+  option(&quot;specialChars&quot;, /[\t\u0000-\u0019\u00ad\u200b\u2028\u2029\ufeff]/g, function(cm, val) {
+    cm.options.specialChars = new RegExp(val.source + (val.test(&quot;\t&quot;) ? &quot;&quot; : &quot;|\t&quot;), &quot;g&quot;);
+    cm.refresh();
+  }, true);
+  option(&quot;specialCharPlaceholder&quot;, defaultSpecialCharPlaceholder, function(cm) {cm.refresh();}, true);
</ins><span class="cx">   option(&quot;electricChars&quot;, true);
</span><span class="cx">   option(&quot;rtlMoveVisually&quot;, !windows);
</span><ins>+  option(&quot;wholeLineUpdateBefore&quot;, true);
</ins><span class="cx"> 
</span><span class="cx">   option(&quot;theme&quot;, &quot;default&quot;, function(cm) {
</span><span class="cx">     themeChanged(cm);
</span><span class="lines">@@ -3281,9 +3318,17 @@
</span><span class="cx">   option(&quot;lineNumberFormatter&quot;, function(integer) {return integer;}, guttersChanged, true);
</span><span class="cx">   option(&quot;showCursorWhenSelecting&quot;, false, updateSelection, true);
</span><span class="cx"> 
</span><ins>+  option(&quot;resetSelectionOnContextMenu&quot;, true);
+
</ins><span class="cx">   option(&quot;readOnly&quot;, false, function(cm, val) {
</span><del>-    if (val == &quot;nocursor&quot;) {onBlur(cm); cm.display.input.blur();}
-    else if (!val) resetInput(cm, true);
</del><ins>+    if (val == &quot;nocursor&quot;) {
+      onBlur(cm);
+      cm.display.input.blur();
+      cm.display.disabled = true;
+    } else {
+      cm.display.disabled = false;
+      if (!val) resetInput(cm, true);
+    }
</ins><span class="cx">   });
</span><span class="cx">   option(&quot;dragDrop&quot;, true);
</span><span class="cx"> 
</span><span class="lines">@@ -3517,7 +3562,8 @@
</span><span class="cx">   keyMap.basic = {
</span><span class="cx">     &quot;Left&quot;: &quot;goCharLeft&quot;, &quot;Right&quot;: &quot;goCharRight&quot;, &quot;Up&quot;: &quot;goLineUp&quot;, &quot;Down&quot;: &quot;goLineDown&quot;,
</span><span class="cx">     &quot;End&quot;: &quot;goLineEnd&quot;, &quot;Home&quot;: &quot;goLineStartSmart&quot;, &quot;PageUp&quot;: &quot;goPageUp&quot;, &quot;PageDown&quot;: &quot;goPageDown&quot;,
</span><del>-    &quot;Delete&quot;: &quot;delCharAfter&quot;, &quot;Backspace&quot;: &quot;delCharBefore&quot;, &quot;Tab&quot;: &quot;defaultTab&quot;, &quot;Shift-Tab&quot;: &quot;indentAuto&quot;,
</del><ins>+    &quot;Delete&quot;: &quot;delCharAfter&quot;, &quot;Backspace&quot;: &quot;delCharBefore&quot;, &quot;Shift-Backspace&quot;: &quot;delCharBefore&quot;,
+    &quot;Tab&quot;: &quot;defaultTab&quot;, &quot;Shift-Tab&quot;: &quot;indentAuto&quot;,
</ins><span class="cx">     &quot;Enter&quot;: &quot;newlineAndIndent&quot;, &quot;Insert&quot;: &quot;toggleOverwrite&quot;
</span><span class="cx">   };
</span><span class="cx">   // Note that the save and find-related commands aren't defined by
</span><span class="lines">@@ -3823,7 +3869,9 @@
</span><span class="cx">     if (doc.cm &amp;&amp; !doc.cm.curOp) return operation(doc.cm, markText)(doc, from, to, options, type);
</span><span class="cx"> 
</span><span class="cx">     var marker = new TextMarker(doc, type);
</span><del>-    if (type == &quot;range&quot; &amp;&amp; !posLess(from, to)) return marker;
</del><ins>+    if (posLess(to, from) || posEq(from, to) &amp;&amp; type == &quot;range&quot; &amp;&amp;
+        !(options.inclusiveLeft &amp;&amp; options.inclusiveRight))
+      return marker;
</ins><span class="cx">     if (options) copyObj(options, marker);
</span><span class="cx">     if (marker.replacedWith) {
</span><span class="cx">       marker.collapsed = true;
</span><span class="lines">@@ -3939,7 +3987,9 @@
</span><span class="cx">     if (old) for (var i = 0, nw; i &lt; old.length; ++i) {
</span><span class="cx">       var span = old[i], marker = span.marker;
</span><span class="cx">       var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from &lt;= startCh : span.from &lt; startCh);
</span><del>-      if (startsBefore || marker.type == &quot;bookmark&quot; &amp;&amp; span.from == startCh &amp;&amp; (!isInsert || !span.marker.insertLeft)) {
</del><ins>+      if (startsBefore ||
+          (marker.inclusiveLeft &amp;&amp; marker.inclusiveRight || marker.type == &quot;bookmark&quot;) &amp;&amp;
+          span.from == startCh &amp;&amp; (!isInsert || !span.marker.insertLeft)) {
</ins><span class="cx">         var endsAfter = span.to == null || (marker.inclusiveRight ? span.to &gt;= startCh : span.to &gt; startCh);
</span><span class="cx">         (nw || (nw = [])).push({from: span.from,
</span><span class="cx">                                 to: endsAfter ? null : span.to,
</span><span class="lines">@@ -4212,6 +4262,7 @@
</span><span class="cx">     this.height = estimateHeight ? estimateHeight(this) : 1;
</span><span class="cx">   };
</span><span class="cx">   eventMixin(Line);
</span><ins>+  Line.prototype.lineNo = function() { return lineNo(this); };
</ins><span class="cx"> 
</span><span class="cx">   function updateLine(line, text, markedSpans, estimateHeight) {
</span><span class="cx">     line.text = text;
</span><span class="lines">@@ -4232,7 +4283,7 @@
</span><span class="cx">   // Run the given mode's parser over a line, update the styles
</span><span class="cx">   // array, which contains alternating fragments of text and CSS
</span><span class="cx">   // classes.
</span><del>-  function runMode(cm, text, mode, state, f) {
</del><ins>+  function runMode(cm, text, mode, state, f, forceToEnd) {
</ins><span class="cx">     var flattenSpans = mode.flattenSpans;
</span><span class="cx">     if (flattenSpans == null) flattenSpans = cm.options.flattenSpans;
</span><span class="cx">     var curStart = 0, curStyle = null;
</span><span class="lines">@@ -4241,6 +4292,7 @@
</span><span class="cx">     while (!stream.eol()) {
</span><span class="cx">       if (stream.pos &gt; cm.options.maxHighlightLength) {
</span><span class="cx">         flattenSpans = false;
</span><ins>+        if (forceToEnd) processLine(cm, text, state, stream.pos);
</ins><span class="cx">         stream.pos = text.length;
</span><span class="cx">         style = null;
</span><span class="cx">       } else {
</span><span class="lines">@@ -4260,12 +4312,14 @@
</span><span class="cx">     }
</span><span class="cx">   }
</span><span class="cx"> 
</span><del>-  function highlightLine(cm, line, state) {
</del><ins>+  function highlightLine(cm, line, state, forceToEnd) {
</ins><span class="cx">     // A styles array always starts with a number identifying the
</span><span class="cx">     // mode/overlays that it is based on (for easy invalidation).
</span><span class="cx">     var st = [cm.state.modeGen];
</span><span class="cx">     // Compute the base array of styles
</span><del>-    runMode(cm, line.text, cm.doc.mode, state, function(end, style) {st.push(end, style);});
</del><ins>+    runMode(cm, line.text, cm.doc.mode, state, function(end, style) {
+      st.push(end, style);
+    }, forceToEnd);
</ins><span class="cx"> 
</span><span class="cx">     // Run overlays, adjust style array.
</span><span class="cx">     for (var o = 0; o &lt; cm.state.overlays.length; ++o) {
</span><span class="lines">@@ -4304,10 +4358,11 @@
</span><span class="cx"> 
</span><span class="cx">   // Lightweight form of highlight -- proceed over this line and
</span><span class="cx">   // update state, but don't save a style array.
</span><del>-  function processLine(cm, line, state) {
</del><ins>+  function processLine(cm, text, state, startAt) {
</ins><span class="cx">     var mode = cm.doc.mode;
</span><del>-    var stream = new StringStream(line.text, cm.options.tabSize);
-    if (line.text == &quot;&quot; &amp;&amp; mode.blankLine) mode.blankLine(state);
</del><ins>+    var stream = new StringStream(text, cm.options.tabSize);
+    stream.start = stream.pos = startAt || 0;
+    if (text == &quot;&quot; &amp;&amp; mode.blankLine) mode.blankLine(state);
</ins><span class="cx">     while (!stream.eol() &amp;&amp; stream.pos &lt;= cm.options.maxHighlightLength) {
</span><span class="cx">       mode.token(stream, state);
</span><span class="cx">       stream.start = stream.pos;
</span><span class="lines">@@ -4364,7 +4419,7 @@
</span><span class="cx">     // Work around problem with the reported dimensions of single-char
</span><span class="cx">     // direction spans on IE (issue #1129). See also the comment in
</span><span class="cx">     // cursorCoords.
</span><del>-    if (measure &amp;&amp; ie &amp;&amp; (order = getOrder(line))) {
</del><ins>+    if (measure &amp;&amp; (ie || ie_gt10) &amp;&amp; (order = getOrder(line))) {
</ins><span class="cx">       var l = order.length - 1;
</span><span class="cx">       if (order[l].from == order[l].to) --l;
</span><span class="cx">       var last = order[l], prev = order[l - 1];
</span><span class="lines">@@ -4382,17 +4437,23 @@
</span><span class="cx">     return builder;
</span><span class="cx">   }
</span><span class="cx"> 
</span><del>-  var tokenSpecialChars = /[\t\u0000-\u0019\u00ad\u200b\u2028\u2029\uFEFF]/g;
</del><ins>+  function defaultSpecialCharPlaceholder(ch) {
+    var token = elt(&quot;span&quot;, &quot;\u2022&quot;, &quot;cm-invalidchar&quot;);
+    token.title = &quot;\\u&quot; + ch.charCodeAt(0).toString(16);
+    return token;
+  }
+
</ins><span class="cx">   function buildToken(builder, text, style, startStyle, endStyle, title) {
</span><span class="cx">     if (!text) return;
</span><del>-    if (!tokenSpecialChars.test(text)) {
</del><ins>+    var special = builder.cm.options.specialChars;
+    if (!special.test(text)) {
</ins><span class="cx">       builder.col += text.length;
</span><span class="cx">       var content = document.createTextNode(text);
</span><span class="cx">     } else {
</span><span class="cx">       var content = document.createDocumentFragment(), pos = 0;
</span><span class="cx">       while (true) {
</span><del>-        tokenSpecialChars.lastIndex = pos;
-        var m = tokenSpecialChars.exec(text);
</del><ins>+        special.lastIndex = pos;
+        var m = special.exec(text);
</ins><span class="cx">         var skipped = m ? m.index - pos : text.length - pos;
</span><span class="cx">         if (skipped) {
</span><span class="cx">           content.appendChild(document.createTextNode(text.slice(pos, pos + skipped)));
</span><span class="lines">@@ -4405,8 +4466,7 @@
</span><span class="cx">           content.appendChild(elt(&quot;span&quot;, spaceStr(tabWidth), &quot;cm-tab&quot;));
</span><span class="cx">           builder.col += tabWidth;
</span><span class="cx">         } else {
</span><del>-          var token = elt(&quot;span&quot;, &quot;\u2022&quot;, &quot;cm-invalidchar&quot;);
-          token.title = &quot;\\u&quot; + m[0].charCodeAt(0).toString(16);
</del><ins>+          var token = builder.cm.options.specialCharPlaceholder(m[0]);
</ins><span class="cx">           content.appendChild(token);
</span><span class="cx">           builder.col += 1;
</span><span class="cx">         }
</span><span class="lines">@@ -4457,7 +4517,7 @@
</span><span class="cx">       return out;
</span><span class="cx">     }
</span><span class="cx">     return function(builder, text, style, startStyle, endStyle, title) {
</span><del>-      return inner(builder, text.replace(/ {3,}/, split), style, startStyle, endStyle, title);
</del><ins>+      return inner(builder, text.replace(/ {3,}/g, split), style, startStyle, endStyle, title);
</ins><span class="cx">     };
</span><span class="cx">   }
</span><span class="cx"> 
</span><span class="lines">@@ -4559,7 +4619,8 @@
</span><span class="cx">     var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line;
</span><span class="cx"> 
</span><span class="cx">     // First adjust the line structure
</span><del>-    if (from.ch == 0 &amp;&amp; to.ch == 0 &amp;&amp; lastText == &quot;&quot;) {
</del><ins>+    if (from.ch == 0 &amp;&amp; to.ch == 0 &amp;&amp; lastText == &quot;&quot; &amp;&amp;
+        (!doc.cm || doc.cm.options.wholeLineUpdateBefore)) {
</ins><span class="cx">       // This is a whole-line replace. Treated specially to make
</span><span class="cx">       // sure line objects move the way they are supposed to.
</span><span class="cx">       for (var i = 0, e = text.length - 1, added = []; i &lt; e; ++i)
</span><span class="lines">@@ -5446,7 +5507,7 @@
</span><span class="cx">     return true;
</span><span class="cx">   }
</span><span class="cx"> 
</span><del>-  var isExtendingChar = /[\u0300-\u036F\u0483-\u0487\u0488-\u0489\u0591-\u05BD\u05BF\u05C1-\u05C2\u05C4-\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7-\u06E8\u06EA-\u06ED\uA66F\uA670-\uA672\uA674-\uA67D\uA69F\udc00-\udfff]/;
</del><ins>+  var isExtendingChar = /[\u0300-\u036F\u0483-\u0487\u0488-\u0489\u0591-\u05BD\u05BF\u05C1-\u05C2\u05C4-\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7-\u06E8\u06EA-\u06ED\uA66F\u1DC0–\u1DFF\u20D0–\u20FF\uA670-\uA672\uA674-\uA67D\uA69F\udc00-\udfff\uFE20–\uFE2F]/;
</ins><span class="cx"> 
</span><span class="cx">   // DOM UTILITIES
</span><span class="cx"> 
</span><span class="lines">@@ -5520,7 +5581,7 @@
</span><span class="cx">         if (/\w/.test(str.charAt(i - 2)) &amp;&amp; /[^\-?\.]/.test(str.charAt(i))) return true;
</span><span class="cx">         if (i &gt; 2 &amp;&amp; /[\d\.,]/.test(str.charAt(i - 2)) &amp;&amp; /[\d\.,]/.test(str.charAt(i))) return false;
</span><span class="cx">       }
</span><del>-      var result = /[~!#%&amp;*)=+}\]|\&quot;\.&gt;,:;][({[&lt;]|-[^\-?\.\u2010-\u201f\u2026]|\?[\w~`@#$%\^&amp;*(_=+{[|&gt;&lt;]|…[\w~`@#$%\^&amp;*(_=+{[&gt;&lt;]/.test(str.slice(i - 1, i + 1));
</del><ins>+      var result = /[~!#%&amp;*)=+}\]\\|\&quot;\.&gt;,:;][({[&lt;]|-[^\-?\.\u2010-\u201f\u2026]|\?[\w~`@#$%\^&amp;*(_=+{[|&gt;&lt;]|…[\w~`@#$%\^&amp;*(_=+{[&gt;&lt;]/.test(str.slice(i - 1, i + 1));
</ins><span class="cx">       return result;
</span><span class="cx">     };
</span><span class="cx"> 
</span><span class="lines">@@ -5877,7 +5938,7 @@
</span><span class="cx"> 
</span><span class="cx">   // THE END
</span><span class="cx"> 
</span><del>-  CodeMirror.version = &quot;3.16.1&quot;;
</del><ins>+  CodeMirror.version = &quot;3.20.0&quot;;
</ins><span class="cx"> 
</span><span class="cx">   return CodeMirror;
</span><span class="cx"> })();
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceExternalCodeMirrorcoffeescriptjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/coffeescript.js (160499 => 160500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/coffeescript.js        2013-12-12 19:37:21 UTC (rev 160499)
+++ trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/coffeescript.js        2013-12-12 19:52:46 UTC (rev 160500)
</span><span class="lines">@@ -2,347 +2,353 @@
</span><span class="cx">  * Link to the project's GitHub page:
</span><span class="cx">  * https://github.com/pickhardt/coffeescript-codemirror-mode
</span><span class="cx">  */
</span><del>-CodeMirror.defineMode('coffeescript', function(conf) {
-    var ERRORCLASS = 'error';
</del><ins>+CodeMirror.defineMode(&quot;coffeescript&quot;, function(conf) {
+  var ERRORCLASS = &quot;error&quot;;
</ins><span class="cx"> 
</span><del>-    function wordRegexp(words) {
-        return new RegExp(&quot;^((&quot; + words.join(&quot;)|(&quot;) + &quot;))\\b&quot;);
-    }
</del><ins>+  function wordRegexp(words) {
+    return new RegExp(&quot;^((&quot; + words.join(&quot;)|(&quot;) + &quot;))\\b&quot;);
+  }
</ins><span class="cx"> 
</span><del>-    var singleOperators = new RegExp(&quot;^[\\+\\-\\*/%&amp;|\\^~&lt;&gt;!\?]&quot;);
-    var singleDelimiters = new RegExp('^[\\(\\)\\[\\]\\{\\},:`=;\\.]');
-    var doubleOperators = new RegExp(&quot;^((\-&gt;)|(\=&gt;)|(\\+\\+)|(\\+\\=)|(\\-\\-)|(\\-\\=)|(\\*\\*)|(\\*\\=)|(\\/\\/)|(\\/\\=)|(==)|(!=)|(&lt;=)|(&gt;=)|(&lt;&gt;)|(&lt;&lt;)|(&gt;&gt;)|(//))&quot;);
-    var doubleDelimiters = new RegExp(&quot;^((\\.\\.)|(\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&amp;=)|(\\|=)|(\\^=))&quot;);
-    var tripleDelimiters = new RegExp(&quot;^((\\.\\.\\.)|(//=)|(&gt;&gt;=)|(&lt;&lt;=)|(\\*\\*=))&quot;);
-    var identifiers = new RegExp(&quot;^[_A-Za-z$][_A-Za-z$0-9]*&quot;);
-    var properties = new RegExp(&quot;^(@|this\.)[_A-Za-z$][_A-Za-z$0-9]*&quot;);
</del><ins>+  var operators = /^(?:-&gt;|=&gt;|\+[+=]?|-[\-=]?|\*[\*=]?|\/[\/=]?|[=!]=|&lt;[&gt;&lt;]?=?|&gt;&gt;?=?|%=?|&amp;=?|\|=?|\^=?|\~|!|\?)/;
+  var delimiters = /^(?:[()\[\]{},:`=;]|\.\.?\.?)/;
+  var identifiers = /^[_A-Za-z$][_A-Za-z$0-9]*/;
+  var properties = /^(@|this\.)[_A-Za-z$][_A-Za-z$0-9]*/;
</ins><span class="cx"> 
</span><del>-    var wordOperators = wordRegexp(['and', 'or', 'not',
-                                    'is', 'isnt', 'in',
-                                    'instanceof', 'typeof']);
-    var indentKeywords = ['for', 'while', 'loop', 'if', 'unless', 'else',
-                          'switch', 'try', 'catch', 'finally', 'class'];
-    var commonKeywords = ['break', 'by', 'continue', 'debugger', 'delete',
-                          'do', 'in', 'of', 'new', 'return', 'then',
-                          'this', 'throw', 'when', 'until'];
</del><ins>+  var wordOperators = wordRegexp([&quot;and&quot;, &quot;or&quot;, &quot;not&quot;,
+                                  &quot;is&quot;, &quot;isnt&quot;, &quot;in&quot;,
+                                  &quot;instanceof&quot;, &quot;typeof&quot;]);
+  var indentKeywords = [&quot;for&quot;, &quot;while&quot;, &quot;loop&quot;, &quot;if&quot;, &quot;unless&quot;, &quot;else&quot;,
+                        &quot;switch&quot;, &quot;try&quot;, &quot;catch&quot;, &quot;finally&quot;, &quot;class&quot;];
+  var commonKeywords = [&quot;break&quot;, &quot;by&quot;, &quot;continue&quot;, &quot;debugger&quot;, &quot;delete&quot;,
+                        &quot;do&quot;, &quot;in&quot;, &quot;of&quot;, &quot;new&quot;, &quot;return&quot;, &quot;then&quot;,
+                        &quot;this&quot;, &quot;throw&quot;, &quot;when&quot;, &quot;until&quot;];
</ins><span class="cx"> 
</span><del>-    var keywords = wordRegexp(indentKeywords.concat(commonKeywords));
</del><ins>+  var keywords = wordRegexp(indentKeywords.concat(commonKeywords));
</ins><span class="cx"> 
</span><del>-    indentKeywords = wordRegexp(indentKeywords);
</del><ins>+  indentKeywords = wordRegexp(indentKeywords);
</ins><span class="cx"> 
</span><span class="cx"> 
</span><del>-    var stringPrefixes = new RegExp(&quot;^('{3}|\&quot;{3}|['\&quot;])&quot;);
-    var regexPrefixes = new RegExp(&quot;^(/{3}|/)&quot;);
-    var commonConstants = ['Infinity', 'NaN', 'undefined', 'null', 'true', 'false', 'on', 'off', 'yes', 'no'];
-    var constants = wordRegexp(commonConstants);
</del><ins>+  var stringPrefixes = /^('{3}|\&quot;{3}|['\&quot;])/;
+  var regexPrefixes = /^(\/{3}|\/)/;
+  var commonConstants = [&quot;Infinity&quot;, &quot;NaN&quot;, &quot;undefined&quot;, &quot;null&quot;, &quot;true&quot;, &quot;false&quot;, &quot;on&quot;, &quot;off&quot;, &quot;yes&quot;, &quot;no&quot;];
+  var constants = wordRegexp(commonConstants);
</ins><span class="cx"> 
</span><del>-    // Tokenizers
-    function tokenBase(stream, state) {
-        // Handle scope changes
-        if (stream.sol()) {
-            var scopeOffset = state.scopes[0].offset;
-            if (stream.eatSpace()) {
-                var lineOffset = stream.indentation();
-                if (lineOffset &gt; scopeOffset) {
-                    return 'indent';
-                } else if (lineOffset &lt; scopeOffset) {
-                    return 'dedent';
-                }
-                return null;
-            } else {
-                if (scopeOffset &gt; 0) {
-                    dedent(stream, state);
-                }
-            }
</del><ins>+  // Tokenizers
+  function tokenBase(stream, state) {
+    // Handle scope changes
+    if (stream.sol()) {
+      if (state.scope.align === null) state.scope.align = false;
+      var scopeOffset = state.scope.offset;
+      if (stream.eatSpace()) {
+        var lineOffset = stream.indentation();
+        if (lineOffset &gt; scopeOffset &amp;&amp; state.scope.type == &quot;coffee&quot;) {
+          return &quot;indent&quot;;
+        } else if (lineOffset &lt; scopeOffset) {
+          return &quot;dedent&quot;;
</ins><span class="cx">         }
</span><del>-        if (stream.eatSpace()) {
-            return null;
</del><ins>+        return null;
+      } else {
+        if (scopeOffset &gt; 0) {
+          dedent(stream, state);
</ins><span class="cx">         }
</span><ins>+      }
+    }
+    if (stream.eatSpace()) {
+      return null;
+    }
</ins><span class="cx"> 
</span><del>-        var ch = stream.peek();
</del><ins>+    var ch = stream.peek();
</ins><span class="cx"> 
</span><del>-        // Handle docco title comment (single line)
-        if (stream.match(&quot;####&quot;)) {
-            stream.skipToEnd();
-            return 'comment';
-        }
</del><ins>+    // Handle docco title comment (single line)
+    if (stream.match(&quot;####&quot;)) {
+      stream.skipToEnd();
+      return &quot;comment&quot;;
+    }
</ins><span class="cx"> 
</span><del>-        // Handle multi line comments
-        if (stream.match(&quot;###&quot;)) {
-            state.tokenize = longComment;
-            return state.tokenize(stream, state);
-        }
</del><ins>+    // Handle multi line comments
+    if (stream.match(&quot;###&quot;)) {
+      state.tokenize = longComment;
+      return state.tokenize(stream, state);
+    }
</ins><span class="cx"> 
</span><del>-        // Single line comment
-        if (ch === '#') {
-            stream.skipToEnd();
-            return 'comment';
-        }
</del><ins>+    // Single line comment
+    if (ch === &quot;#&quot;) {
+      stream.skipToEnd();
+      return &quot;comment&quot;;
+    }
</ins><span class="cx"> 
</span><del>-        // Handle number literals
-        if (stream.match(/^-?[0-9\.]/, false)) {
-            var floatLiteral = false;
-            // Floats
-            if (stream.match(/^-?\d*\.\d+(e[\+\-]?\d+)?/i)) {
-              floatLiteral = true;
-            }
-            if (stream.match(/^-?\d+\.\d*/)) {
-              floatLiteral = true;
-            }
-            if (stream.match(/^-?\.\d+/)) {
-              floatLiteral = true;
-            }
</del><ins>+    // Handle number literals
+    if (stream.match(/^-?[0-9\.]/, false)) {
+      var floatLiteral = false;
+      // Floats
+      if (stream.match(/^-?\d*\.\d+(e[\+\-]?\d+)?/i)) {
+        floatLiteral = true;
+      }
+      if (stream.match(/^-?\d+\.\d*/)) {
+        floatLiteral = true;
+      }
+      if (stream.match(/^-?\.\d+/)) {
+        floatLiteral = true;
+      }
</ins><span class="cx"> 
</span><del>-            if (floatLiteral) {
-                // prevent from getting extra . on 1..
-                if (stream.peek() == &quot;.&quot;){
-                    stream.backUp(1);
-                }
-                return 'number';
-            }
-            // Integers
-            var intLiteral = false;
-            // Hex
-            if (stream.match(/^-?0x[0-9a-f]+/i)) {
-              intLiteral = true;
-            }
-            // Decimal
-            if (stream.match(/^-?[1-9]\d*(e[\+\-]?\d+)?/)) {
-                intLiteral = true;
-            }
-            // Zero by itself with no other piece of number.
-            if (stream.match(/^-?0(?![\dx])/i)) {
-              intLiteral = true;
-            }
-            if (intLiteral) {
-                return 'number';
-            }
</del><ins>+      if (floatLiteral) {
+        // prevent from getting extra . on 1..
+        if (stream.peek() == &quot;.&quot;){
+          stream.backUp(1);
</ins><span class="cx">         }
</span><ins>+        return &quot;number&quot;;
+      }
+      // Integers
+      var intLiteral = false;
+      // Hex
+      if (stream.match(/^-?0x[0-9a-f]+/i)) {
+        intLiteral = true;
+      }
+      // Decimal
+      if (stream.match(/^-?[1-9]\d*(e[\+\-]?\d+)?/)) {
+        intLiteral = true;
+      }
+      // Zero by itself with no other piece of number.
+      if (stream.match(/^-?0(?![\dx])/i)) {
+        intLiteral = true;
+      }
+      if (intLiteral) {
+        return &quot;number&quot;;
+      }
+    }
</ins><span class="cx"> 
</span><del>-        // Handle strings
-        if (stream.match(stringPrefixes)) {
-            state.tokenize = tokenFactory(stream.current(), 'string');
-            return state.tokenize(stream, state);
-        }
-        // Handle regex literals
-        if (stream.match(regexPrefixes)) {
-            if (stream.current() != '/' || stream.match(/^.*\//, false)) { // prevent highlight of division
-                state.tokenize = tokenFactory(stream.current(), 'string-2');
-                return state.tokenize(stream, state);
-            } else {
-                stream.backUp(1);
-            }
-        }
</del><ins>+    // Handle strings
+    if (stream.match(stringPrefixes)) {
+      state.tokenize = tokenFactory(stream.current(), &quot;string&quot;);
+      return state.tokenize(stream, state);
+    }
+    // Handle regex literals
+    if (stream.match(regexPrefixes)) {
+      if (stream.current() != &quot;/&quot; || stream.match(/^.*\//, false)) { // prevent highlight of division
+        state.tokenize = tokenFactory(stream.current(), &quot;string-2&quot;);
+        return state.tokenize(stream, state);
+      } else {
+        stream.backUp(1);
+      }
+    }
</ins><span class="cx"> 
</span><del>-        // Handle operators and delimiters
-        if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters)) {
-            return 'punctuation';
-        }
-        if (stream.match(doubleOperators)
-            || stream.match(singleOperators)
-            || stream.match(wordOperators)) {
-            return 'operator';
-        }
-        if (stream.match(singleDelimiters)) {
-            return 'punctuation';
-        }
</del><ins>+    // Handle operators and delimiters
+    if (stream.match(operators) || stream.match(wordOperators)) {
+      return &quot;operator&quot;;
+    }
+    if (stream.match(delimiters)) {
+      return &quot;punctuation&quot;;
+    }
</ins><span class="cx"> 
</span><del>-        if (stream.match(constants)) {
-            return 'atom';
-        }
</del><ins>+    if (stream.match(constants)) {
+      return &quot;atom&quot;;
+    }
</ins><span class="cx"> 
</span><del>-        if (stream.match(keywords)) {
-            return 'keyword';
-        }
-
-        if (stream.match(identifiers)) {
-            return 'variable';
-        }
-
-        if (stream.match(properties)) {
-            return 'property';
-        }
-
-        // Handle non-detected items
-        stream.next();
-        return ERRORCLASS;
</del><ins>+    if (stream.match(keywords)) {
+      return &quot;keyword&quot;;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    function tokenFactory(delimiter, outclass) {
-        var singleline = delimiter.length == 1;
-        return function(stream, state) {
-            while (!stream.eol()) {
-                stream.eatWhile(/[^'&quot;\/\\]/);
-                if (stream.eat('\\')) {
-                    stream.next();
-                    if (singleline &amp;&amp; stream.eol()) {
-                        return outclass;
-                    }
-                } else if (stream.match(delimiter)) {
-                    state.tokenize = tokenBase;
-                    return outclass;
-                } else {
-                    stream.eat(/['&quot;\/]/);
-                }
-            }
-            if (singleline) {
-                if (conf.mode.singleLineStringErrors) {
-                    outclass = ERRORCLASS;
-                } else {
-                    state.tokenize = tokenBase;
-                }
-            }
-            return outclass;
-        };
</del><ins>+    if (stream.match(identifiers)) {
+      return &quot;variable&quot;;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    function longComment(stream, state) {
-        while (!stream.eol()) {
-            stream.eatWhile(/[^#]/);
-            if (stream.match(&quot;###&quot;)) {
-                state.tokenize = tokenBase;
-                break;
-            }
-            stream.eatWhile(&quot;#&quot;);
-        }
-        return &quot;comment&quot;;
</del><ins>+    if (stream.match(properties)) {
+      return &quot;property&quot;;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    function indent(stream, state, type) {
-        type = type || 'coffee';
-        var indentUnit = 0;
-        if (type === 'coffee') {
-            for (var i = 0; i &lt; state.scopes.length; i++) {
-                if (state.scopes[i].type === 'coffee') {
-                    indentUnit = state.scopes[i].offset + conf.indentUnit;
-                    break;
-                }
-            }
</del><ins>+    // Handle non-detected items
+    stream.next();
+    return ERRORCLASS;
+  }
+
+  function tokenFactory(delimiter, outclass) {
+    var singleline = delimiter.length == 1;
+    return function(stream, state) {
+      while (!stream.eol()) {
+        stream.eatWhile(/[^'&quot;\/\\]/);
+        if (stream.eat(&quot;\\&quot;)) {
+          stream.next();
+          if (singleline &amp;&amp; stream.eol()) {
+            return outclass;
+          }
+        } else if (stream.match(delimiter)) {
+          state.tokenize = tokenBase;
+          return outclass;
</ins><span class="cx">         } else {
</span><del>-            indentUnit = stream.column() + stream.current().length;
</del><ins>+          stream.eat(/['&quot;\/]/);
</ins><span class="cx">         }
</span><del>-        state.scopes.unshift({
-            offset: indentUnit,
-            type: type
-        });
-    }
-
-    function dedent(stream, state) {
-        if (state.scopes.length == 1) return;
-        if (state.scopes[0].type === 'coffee') {
-            var _indent = stream.indentation();
-            var _indent_index = -1;
-            for (var i = 0; i &lt; state.scopes.length; ++i) {
-                if (_indent === state.scopes[i].offset) {
-                    _indent_index = i;
-                    break;
-                }
-            }
-            if (_indent_index === -1) {
-                return true;
-            }
-            while (state.scopes[0].offset !== _indent) {
-                state.scopes.shift();
-            }
-            return false;
</del><ins>+      }
+      if (singleline) {
+        if (conf.mode.singleLineStringErrors) {
+          outclass = ERRORCLASS;
</ins><span class="cx">         } else {
</span><del>-            state.scopes.shift();
-            return false;
</del><ins>+          state.tokenize = tokenBase;
</ins><span class="cx">         }
</span><ins>+      }
+      return outclass;
+    };
+  }
+
+  function longComment(stream, state) {
+    while (!stream.eol()) {
+      stream.eatWhile(/[^#]/);
+      if (stream.match(&quot;###&quot;)) {
+        state.tokenize = tokenBase;
+        break;
+      }
+      stream.eatWhile(&quot;#&quot;);
</ins><span class="cx">     }
</span><ins>+    return &quot;comment&quot;;
+  }
</ins><span class="cx"> 
</span><del>-    function tokenLexer(stream, state) {
-        var style = state.tokenize(stream, state);
-        var current = stream.current();
</del><ins>+  function indent(stream, state, type) {
+    type = type || &quot;coffee&quot;;
+    var offset = 0, align = false, alignOffset = null;
+    for (var scope = state.scope; scope; scope = scope.prev) {
+      if (scope.type === &quot;coffee&quot;) {
+        offset = scope.offset + conf.indentUnit;
+        break;
+      }
+    }
+    if (type !== &quot;coffee&quot;) {
+      align = null;
+      alignOffset = stream.column() + stream.current().length;
+    } else if (state.scope.align) {
+      state.scope.align = false;
+    }
+    state.scope = {
+      offset: offset,
+      type: type,
+      prev: state.scope,
+      align: align,
+      alignOffset: alignOffset
+    };
+  }
</ins><span class="cx"> 
</span><del>-        // Handle '.' connected identifiers
-        if (current === '.') {
-            style = state.tokenize(stream, state);
-            current = stream.current();
-            if (/^\.[\w$]+$/.test(current)) {
-                return 'variable';
-            } else {
-                return ERRORCLASS;
-            }
</del><ins>+  function dedent(stream, state) {
+    if (!state.scope.prev) return;
+    if (state.scope.type === &quot;coffee&quot;) {
+      var _indent = stream.indentation();
+      var matched = false;
+      for (var scope = state.scope; scope; scope = scope.prev) {
+        if (_indent === scope.offset) {
+          matched = true;
+          break;
</ins><span class="cx">         }
</span><ins>+      }
+      if (!matched) {
+        return true;
+      }
+      while (state.scope.prev &amp;&amp; state.scope.offset !== _indent) {
+        state.scope = state.scope.prev;
+      }
+      return false;
+    } else {
+      state.scope = state.scope.prev;
+      return false;
+    }
+  }
</ins><span class="cx"> 
</span><del>-        // Handle scope changes.
-        if (current === 'return') {
-            state.dedent += 1;
-        }
-        if (((current === '-&gt;' || current === '=&gt;') &amp;&amp;
-                  !state.lambda &amp;&amp;
-                  state.scopes[0].type == 'coffee' &amp;&amp;
-                  stream.peek() === '')
-               || style === 'indent') {
-            indent(stream, state);
-        }
-        var delimiter_index = '[({'.indexOf(current);
-        if (delimiter_index !== -1) {
-            indent(stream, state, '])}'.slice(delimiter_index, delimiter_index+1));
-        }
-        if (indentKeywords.exec(current)){
-            indent(stream, state);
-        }
-        if (current == 'then'){
-            dedent(stream, state);
-        }
</del><ins>+  function tokenLexer(stream, state) {
+    var style = state.tokenize(stream, state);
+    var current = stream.current();
</ins><span class="cx"> 
</span><ins>+    // Handle &quot;.&quot; connected identifiers
+    if (current === &quot;.&quot;) {
+      style = state.tokenize(stream, state);
+      current = stream.current();
+      if (/^\.[\w$]+$/.test(current)) {
+        return &quot;variable&quot;;
+      } else {
+        return ERRORCLASS;
+      }
+    }
</ins><span class="cx"> 
</span><del>-        if (style === 'dedent') {
-            if (dedent(stream, state)) {
-                return ERRORCLASS;
-            }
-        }
-        delimiter_index = '])}'.indexOf(current);
-        if (delimiter_index !== -1) {
-            if (dedent(stream, state)) {
-                return ERRORCLASS;
-            }
-        }
-        if (state.dedent &gt; 0 &amp;&amp; stream.eol() &amp;&amp; state.scopes[0].type == 'coffee') {
-            if (state.scopes.length &gt; 1) state.scopes.shift();
-            state.dedent -= 1;
-        }
</del><ins>+    // Handle scope changes.
+    if (current === &quot;return&quot;) {
+      state.dedent += 1;
+    }
+    if (((current === &quot;-&gt;&quot; || current === &quot;=&gt;&quot;) &amp;&amp;
+         !state.lambda &amp;&amp;
+         !stream.peek())
+        || style === &quot;indent&quot;) {
+      indent(stream, state);
+    }
+    var delimiter_index = &quot;[({&quot;.indexOf(current);
+    if (delimiter_index !== -1) {
+      indent(stream, state, &quot;])}&quot;.slice(delimiter_index, delimiter_index+1));
+    }
+    if (indentKeywords.exec(current)){
+      indent(stream, state);
+    }
+    if (current == &quot;then&quot;){
+      dedent(stream, state);
+    }
</ins><span class="cx"> 
</span><del>-        return style;
</del><ins>+
+    if (style === &quot;dedent&quot;) {
+      if (dedent(stream, state)) {
+        return ERRORCLASS;
+      }
</ins><span class="cx">     }
</span><ins>+    delimiter_index = &quot;])}&quot;.indexOf(current);
+    if (delimiter_index !== -1) {
+      while (state.scope.type == &quot;coffee&quot; &amp;&amp; state.scope.prev)
+        state.scope = state.scope.prev;
+      if (state.scope.type == current)
+        state.scope = state.scope.prev;
+    }
+    if (state.dedent &gt; 0 &amp;&amp; stream.eol() &amp;&amp; state.scope.type == &quot;coffee&quot;) {
+      if (state.scope.prev) state.scope = state.scope.prev;
+      state.dedent -= 1;
+    }
</ins><span class="cx"> 
</span><del>-    var external = {
-        startState: function(basecolumn) {
-            return {
-              tokenize: tokenBase,
-              scopes: [{offset:basecolumn || 0, type:'coffee'}],
-              lastToken: null,
-              lambda: false,
-              dedent: 0
-          };
-        },
</del><ins>+    return style;
+  }
</ins><span class="cx"> 
</span><del>-        token: function(stream, state) {
-            var style = tokenLexer(stream, state);
</del><ins>+  var external = {
+    startState: function(basecolumn) {
+      return {
+        tokenize: tokenBase,
+        scope: {offset:basecolumn || 0, type:&quot;coffee&quot;, prev: null, align: false},
+        lastToken: null,
+        lambda: false,
+        dedent: 0
+      };
+    },
</ins><span class="cx"> 
</span><del>-            state.lastToken = {style:style, content: stream.current()};
</del><ins>+    token: function(stream, state) {
+      var fillAlign = state.scope.align === null &amp;&amp; state.scope;
+      if (fillAlign &amp;&amp; stream.sol()) fillAlign.align = false;
</ins><span class="cx"> 
</span><del>-            if (stream.eol() &amp;&amp; stream.lambda) {
-                state.lambda = false;
-            }
</del><ins>+      var style = tokenLexer(stream, state);
+      if (fillAlign &amp;&amp; style &amp;&amp; style != &quot;comment&quot;) fillAlign.align = true;
</ins><span class="cx"> 
</span><del>-            return style;
-        },
</del><ins>+      state.lastToken = {style:style, content: stream.current()};
</ins><span class="cx"> 
</span><del>-        indent: function(state) {
-            if (state.tokenize != tokenBase) {
-                return 0;
-            }
</del><ins>+      if (stream.eol() &amp;&amp; stream.lambda) {
+        state.lambda = false;
+      }
</ins><span class="cx"> 
</span><del>-            return state.scopes[0].offset;
-        },
</del><ins>+      return style;
+    },
</ins><span class="cx"> 
</span><del>-        lineComment: &quot;#&quot;,
-        fold: &quot;indent&quot;
-    };
-    return external;
</del><ins>+    indent: function(state, text) {
+      if (state.tokenize != tokenBase) return 0;
+      var scope = state.scope;
+      var closer = text &amp;&amp; &quot;])}&quot;.indexOf(text.charAt(0)) &gt; -1;
+      if (closer) while (scope.type == &quot;coffee&quot; &amp;&amp; scope.prev) scope = scope.prev;
+      var closes = closer &amp;&amp; scope.type === text.charAt(0);
+      if (scope.align)
+        return scope.alignOffset - (closes ? 1 : 0);
+      else
+        return (closes ? scope.prev : scope).offset;
+    },
+
+    lineComment: &quot;#&quot;,
+    fold: &quot;indent&quot;
+  };
+  return external;
</ins><span class="cx"> });
</span><span class="cx"> 
</span><del>-CodeMirror.defineMIME('text/x-coffeescript', 'coffeescript');
</del><ins>+CodeMirror.defineMIME(&quot;text/x-coffeescript&quot;, &quot;coffeescript&quot;);
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceExternalCodeMirrorcssjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/css.js (160499 => 160500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/css.js        2013-12-12 19:37:21 UTC (rev 160499)
+++ trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/css.js        2013-12-12 19:52:46 UTC (rev 160500)
</span><span class="lines">@@ -3,7 +3,7 @@
</span><span class="cx"> 
</span><span class="cx">   if (!parserConfig.propertyKeywords) parserConfig = CodeMirror.resolveMode(&quot;text/css&quot;);
</span><span class="cx"> 
</span><del>-  var indentUnit = config.indentUnit,
</del><ins>+  var indentUnit = config.indentUnit || config.tabSize || 2,
</ins><span class="cx">       hooks = parserConfig.hooks || {},
</span><span class="cx">       atMediaTypes = parserConfig.atMediaTypes || {},
</span><span class="cx">       atMediaFeatures = parserConfig.atMediaFeatures || {},
</span><span class="lines">@@ -37,7 +37,7 @@
</span><span class="cx">       stream.match(/^\s*\w*/);
</span><span class="cx">       return ret(&quot;keyword&quot;, &quot;important&quot;);
</span><span class="cx">     }
</span><del>-    else if (/\d/.test(ch)) {
</del><ins>+    else if (/\d/.test(ch) || ch == &quot;.&quot; &amp;&amp; stream.eat(/\d/)) {
</ins><span class="cx">       stream.eatWhile(/[\w.%]/);
</span><span class="cx">       return ret(&quot;number&quot;, &quot;unit&quot;);
</span><span class="cx">     }
</span><span class="lines">@@ -259,8 +259,13 @@
</span><span class="cx">       }
</span><span class="cx">       else if (type == &quot;}&quot;) {
</span><span class="cx">         if (context == &quot;interpolation&quot;) style = &quot;operator&quot;;
</span><del>-        state.stack.pop();
-        if (context == &quot;propertyValue&quot;) state.stack.pop();
</del><ins>+        // Pop off end of array until { is reached
+        while(state.stack.length){
+          var removed = state.stack.pop();
+          if(removed.indexOf(&quot;{&quot;) &gt; -1 || removed == &quot;block&quot; || removed == &quot;rule&quot;){
+            break;
+          }
+        }
</ins><span class="cx">       }
</span><span class="cx">       else if (type == &quot;interpolation&quot;) state.stack.push(&quot;interpolation&quot;);
</span><span class="cx">       else if (type == &quot;@media&quot;) state.stack.push(&quot;@media&quot;);
</span><span class="lines">@@ -278,11 +283,13 @@
</span><span class="cx">         else state.stack.push(&quot;(&quot;);
</span><span class="cx">       }
</span><span class="cx">       else if (type == &quot;)&quot;) {
</span><del>-        if (context == &quot;propertyValue&quot;) {
-          // In @mediaType( without closing ; after propertyValue
-          state.stack.pop();
</del><ins>+        // Pop off end of array until ( is reached
+        while(state.stack.length){
+          var removed = state.stack.pop();
+          if(removed.indexOf(&quot;(&quot;) &gt; -1){
+            break;
+          }
</ins><span class="cx">         }
</span><del>-        state.stack.pop();
</del><span class="cx">       }
</span><span class="cx">       else if (type == &quot;:&quot; &amp;&amp; state.lastToken == &quot;property&quot;) state.stack.push(&quot;propertyValue&quot;);
</span><span class="cx">       else if (context == &quot;propertyValue&quot; &amp;&amp; type == &quot;;&quot;) state.stack.pop();
</span><span class="lines">@@ -602,6 +609,11 @@
</span><span class="cx">         }
</span><span class="cx">         return [&quot;variable&quot;, &quot;variable&quot;];
</span><span class="cx">       },
</span><ins>+      &quot;,&quot;: function(stream, state) {
+        if (state.stack[state.stack.length - 1] == &quot;propertyValue&quot; &amp;&amp; stream.match(/^ *\$/, false)) {
+          return [&quot;operator&quot;, &quot;;&quot;];
+        }
+      },
</ins><span class="cx">       &quot;/&quot;: function(stream, state) {
</span><span class="cx">         if (stream.eat(&quot;/&quot;)) {
</span><span class="cx">           stream.skipToEnd();
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceExternalCodeMirrorhtmlmixedjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/htmlmixed.js (160499 => 160500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/htmlmixed.js        2013-12-12 19:37:21 UTC (rev 160499)
+++ trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/htmlmixed.js        2013-12-12 19:52:46 UTC (rev 160500)
</span><span class="lines">@@ -44,7 +44,7 @@
</span><span class="cx">     if (close &gt; -1) stream.backUp(cur.length - close);
</span><span class="cx">     else if (m = cur.match(/&lt;\/?$/)) {
</span><span class="cx">       stream.backUp(cur.length);
</span><del>-      if (!stream.match(pat, false)) stream.match(cur[0]);
</del><ins>+      if (!stream.match(pat, false)) stream.match(cur);
</ins><span class="cx">     }
</span><span class="cx">     return style;
</span><span class="cx">   }
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceExternalCodeMirrorjavascriptjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/javascript.js (160499 => 160500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/javascript.js        2013-12-12 19:37:21 UTC (rev 160499)
+++ trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/javascript.js        2013-12-12 19:52:46 UTC (rev 160500)
</span><span class="lines">@@ -21,7 +21,8 @@
</span><span class="cx">       &quot;for&quot;: kw(&quot;for&quot;), &quot;switch&quot;: kw(&quot;switch&quot;), &quot;case&quot;: kw(&quot;case&quot;), &quot;default&quot;: kw(&quot;default&quot;),
</span><span class="cx">       &quot;in&quot;: operator, &quot;typeof&quot;: operator, &quot;instanceof&quot;: operator,
</span><span class="cx">       &quot;true&quot;: atom, &quot;false&quot;: atom, &quot;null&quot;: atom, &quot;undefined&quot;: atom, &quot;NaN&quot;: atom, &quot;Infinity&quot;: atom,
</span><del>-      &quot;this&quot;: kw(&quot;this&quot;)
</del><ins>+      &quot;this&quot;: kw(&quot;this&quot;), &quot;module&quot;: kw(&quot;module&quot;), &quot;class&quot;: kw(&quot;class&quot;), &quot;super&quot;: kw(&quot;atom&quot;),
+      &quot;yield&quot;: C, &quot;export&quot;: kw(&quot;export&quot;), &quot;import&quot;: kw(&quot;import&quot;), &quot;extends&quot;: C
</ins><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx">     // Extend the 'normal' keywords with the TypeScript language extensions
</span><span class="lines">@@ -30,7 +31,6 @@
</span><span class="cx">       var tsKeywords = {
</span><span class="cx">         // object-like things
</span><span class="cx">         &quot;interface&quot;: kw(&quot;interface&quot;),
</span><del>-        &quot;class&quot;: kw(&quot;class&quot;),
</del><span class="cx">         &quot;extends&quot;: kw(&quot;extends&quot;),
</span><span class="cx">         &quot;constructor&quot;: kw(&quot;constructor&quot;),
</span><span class="cx"> 
</span><span class="lines">@@ -40,8 +40,6 @@
</span><span class="cx">         &quot;protected&quot;: kw(&quot;protected&quot;),
</span><span class="cx">         &quot;static&quot;: kw(&quot;static&quot;),
</span><span class="cx"> 
</span><del>-        &quot;super&quot;: kw(&quot;super&quot;),
-
</del><span class="cx">         // types
</span><span class="cx">         &quot;string&quot;: type, &quot;number&quot;: type, &quot;bool&quot;: type, &quot;any&quot;: type
</span><span class="cx">       };
</span><span class="lines">@@ -56,11 +54,6 @@
</span><span class="cx"> 
</span><span class="cx">   var isOperatorChar = /[+\-*&amp;%=&lt;&gt;!?|~^]/;
</span><span class="cx"> 
</span><del>-  function chain(stream, state, f) {
-    state.tokenize = f;
-    return f(stream, state);
-  }
-
</del><span class="cx">   function nextUntilUnescaped(stream, end) {
</span><span class="cx">     var escaped = false, next;
</span><span class="cx">     while ((next = stream.next()) != null) {
</span><span class="lines">@@ -78,50 +71,51 @@
</span><span class="cx">     type = tp; content = cont;
</span><span class="cx">     return style;
</span><span class="cx">   }
</span><del>-  function jsTokenBase(stream, state) {
</del><ins>+  function tokenBase(stream, state) {
</ins><span class="cx">     var ch = stream.next();
</span><del>-    if (ch == '&quot;' || ch == &quot;'&quot;)
-      return chain(stream, state, jsTokenString(ch));
-    else if (ch == &quot;.&quot; &amp;&amp; stream.match(/^\d+(?:[eE][+\-]?\d+)?/))
</del><ins>+    if (ch == '&quot;' || ch == &quot;'&quot;) {
+      state.tokenize = tokenString(ch);
+      return state.tokenize(stream, state);
+    } else if (ch == &quot;.&quot; &amp;&amp; stream.match(/^\d+(?:[eE][+\-]?\d+)?/)) {
</ins><span class="cx">       return ret(&quot;number&quot;, &quot;number&quot;);
</span><del>-    else if (/[\[\]{}\(\),;\:\.]/.test(ch))
</del><ins>+    } else if (ch == &quot;.&quot; &amp;&amp; stream.match(&quot;..&quot;)) {
+      return ret(&quot;spread&quot;, &quot;meta&quot;);
+    } else if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
</ins><span class="cx">       return ret(ch);
</span><del>-    else if (ch == &quot;0&quot; &amp;&amp; stream.eat(/x/i)) {
</del><ins>+    } else if (ch == &quot;=&quot; &amp;&amp; stream.eat(&quot;&gt;&quot;)) {
+      return ret(&quot;=&gt;&quot;);
+    } else if (ch == &quot;0&quot; &amp;&amp; stream.eat(/x/i)) {
</ins><span class="cx">       stream.eatWhile(/[\da-f]/i);
</span><span class="cx">       return ret(&quot;number&quot;, &quot;number&quot;);
</span><del>-    }
-    else if (/\d/.test(ch)) {
</del><ins>+    } else if (/\d/.test(ch)) {
</ins><span class="cx">       stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
</span><span class="cx">       return ret(&quot;number&quot;, &quot;number&quot;);
</span><del>-    }
-    else if (ch == &quot;/&quot;) {
</del><ins>+    } else if (ch == &quot;/&quot;) {
</ins><span class="cx">       if (stream.eat(&quot;*&quot;)) {
</span><del>-        return chain(stream, state, jsTokenComment);
-      }
-      else if (stream.eat(&quot;/&quot;)) {
</del><ins>+        state.tokenize = tokenComment;
+        return tokenComment(stream, state);
+      } else if (stream.eat(&quot;/&quot;)) {
</ins><span class="cx">         stream.skipToEnd();
</span><span class="cx">         return ret(&quot;comment&quot;, &quot;comment&quot;);
</span><del>-      }
-      else if (state.lastType == &quot;operator&quot; || state.lastType == &quot;keyword c&quot; ||
-               /^[\[{}\(,;:]$/.test(state.lastType)) {
</del><ins>+      } else if (state.lastType == &quot;operator&quot; || state.lastType == &quot;keyword c&quot; ||
+               state.lastType == &quot;sof&quot; || /^[\[{}\(,;:]$/.test(state.lastType)) {
</ins><span class="cx">         nextUntilUnescaped(stream, &quot;/&quot;);
</span><span class="cx">         stream.eatWhile(/[gimy]/); // 'y' is &quot;sticky&quot; option in Mozilla
</span><span class="cx">         return ret(&quot;regexp&quot;, &quot;string-2&quot;);
</span><del>-      }
-      else {
</del><ins>+      } else {
</ins><span class="cx">         stream.eatWhile(isOperatorChar);
</span><span class="cx">         return ret(&quot;operator&quot;, null, stream.current());
</span><span class="cx">       }
</span><del>-    }
-    else if (ch == &quot;#&quot;) {
</del><ins>+    } else if (ch == &quot;`&quot;) {
+      state.tokenize = tokenQuasi;
+      return tokenQuasi(stream, state);
+    } else if (ch == &quot;#&quot;) {
</ins><span class="cx">       stream.skipToEnd();
</span><span class="cx">       return ret(&quot;error&quot;, &quot;error&quot;);
</span><del>-    }
-    else if (isOperatorChar.test(ch)) {
</del><ins>+    } else if (isOperatorChar.test(ch)) {
</ins><span class="cx">       stream.eatWhile(isOperatorChar);
</span><span class="cx">       return ret(&quot;operator&quot;, null, stream.current());
</span><del>-    }
-    else {
</del><ins>+    } else {
</ins><span class="cx">       stream.eatWhile(/[\w\$_]/);
</span><span class="cx">       var word = stream.current(), known = keywords.propertyIsEnumerable(word) &amp;&amp; keywords[word];
</span><span class="cx">       return (known &amp;&amp; state.lastType != &quot;.&quot;) ? ret(known.type, known.style, word) :
</span><span class="lines">@@ -129,19 +123,19 @@
</span><span class="cx">     }
</span><span class="cx">   }
</span><span class="cx"> 
</span><del>-  function jsTokenString(quote) {
</del><ins>+  function tokenString(quote) {
</ins><span class="cx">     return function(stream, state) {
</span><span class="cx">       if (!nextUntilUnescaped(stream, quote))
</span><del>-        state.tokenize = jsTokenBase;
</del><ins>+        state.tokenize = tokenBase;
</ins><span class="cx">       return ret(&quot;string&quot;, &quot;string&quot;);
</span><span class="cx">     };
</span><span class="cx">   }
</span><span class="cx"> 
</span><del>-  function jsTokenComment(stream, state) {
</del><ins>+  function tokenComment(stream, state) {
</ins><span class="cx">     var maybeEnd = false, ch;
</span><span class="cx">     while (ch = stream.next()) {
</span><span class="cx">       if (ch == &quot;/&quot; &amp;&amp; maybeEnd) {
</span><del>-        state.tokenize = jsTokenBase;
</del><ins>+        state.tokenize = tokenBase;
</ins><span class="cx">         break;
</span><span class="cx">       }
</span><span class="cx">       maybeEnd = (ch == &quot;*&quot;);
</span><span class="lines">@@ -149,6 +143,50 @@
</span><span class="cx">     return ret(&quot;comment&quot;, &quot;comment&quot;);
</span><span class="cx">   }
</span><span class="cx"> 
</span><ins>+  function tokenQuasi(stream, state) {
+    var escaped = false, next;
+    while ((next = stream.next()) != null) {
+      if (!escaped &amp;&amp; (next == &quot;`&quot; || next == &quot;$&quot; &amp;&amp; stream.eat(&quot;{&quot;))) {
+        state.tokenize = tokenBase;
+        break;
+      }
+      escaped = !escaped &amp;&amp; next == &quot;\\&quot;;
+    }
+    return ret(&quot;quasi&quot;, &quot;string-2&quot;, stream.current());
+  }
+
+  var brackets = &quot;([{}])&quot;;
+  // This is a crude lookahead trick to try and notice that we're
+  // parsing the argument patterns for a fat-arrow function before we
+  // actually hit the arrow token. It only works if the arrow is on
+  // the same line as the arguments and there's no strange noise
+  // (comments) in between. Fallback is to only notice when we hit the
+  // arrow, and not declare the arguments as locals for the arrow
+  // body.
+  function findFatArrow(stream, state) {
+    if (state.fatArrowAt) state.fatArrowAt = null;
+    var arrow = stream.string.indexOf(&quot;=&gt;&quot;, stream.start);
+    if (arrow &lt; 0) return;
+
+    var depth = 0, sawSomething = false;
+    for (var pos = arrow - 1; pos &gt;= 0; --pos) {
+      var ch = stream.string.charAt(pos);
+      var bracket = brackets.indexOf(ch);
+      if (bracket &gt;= 0 &amp;&amp; bracket &lt; 3) {
+        if (!depth) { ++pos; break; }
+        if (--depth == 0) break;
+      } else if (bracket &gt;= 3 &amp;&amp; bracket &lt; 6) {
+        ++depth;
+      } else if (/[$\w]/.test(ch)) {
+        sawSomething = true;
+      } else if (sawSomething &amp;&amp; !depth) {
+        ++pos;
+        break;
+      }
+    }
+    if (sawSomething &amp;&amp; !depth) state.fatArrowAt = pos;
+  }
+
</ins><span class="cx">   // Parser
</span><span class="cx"> 
</span><span class="cx">   var atomicTypes = {&quot;atom&quot;: true, &quot;number&quot;: true, &quot;variable&quot;: true, &quot;string&quot;: true, &quot;regexp&quot;: true, &quot;this&quot;: true};
</span><span class="lines">@@ -165,6 +203,10 @@
</span><span class="cx">   function inScope(state, varname) {
</span><span class="cx">     for (var v = state.localVars; v; v = v.next)
</span><span class="cx">       if (v.name == varname) return true;
</span><ins>+    for (var cx = state.context; cx; cx = cx.prev) {
+      for (var v = cx.vars; v; v = v.next)
+        if (v.name == varname) return true;
+    }
</ins><span class="cx">   }
</span><span class="cx"> 
</span><span class="cx">   function parseJS(state, style, type, content, stream) {
</span><span class="lines">@@ -211,7 +253,8 @@
</span><span class="cx">       state.localVars = {name: varname, next: state.localVars};
</span><span class="cx">     } else {
</span><span class="cx">       if (inList(state.globalVars)) return;
</span><del>-      state.globalVars = {name: varname, next: state.globalVars};
</del><ins>+      if (parserConfig.globalVars)
+        state.globalVars = {name: varname, next: state.globalVars};
</ins><span class="cx">     }
</span><span class="cx">   }
</span><span class="cx"> 
</span><span class="lines">@@ -253,16 +296,15 @@
</span><span class="cx">     };
</span><span class="cx">   }
</span><span class="cx"> 
</span><del>-  function statement(type) {
-    if (type == &quot;var&quot;) return cont(pushlex(&quot;vardef&quot;), vardef1, expect(&quot;;&quot;), poplex);
</del><ins>+  function statement(type, value) {
+    if (type == &quot;var&quot;) return cont(pushlex(&quot;vardef&quot;, value.length), vardef, expect(&quot;;&quot;), poplex);
</ins><span class="cx">     if (type == &quot;keyword a&quot;) return cont(pushlex(&quot;form&quot;), expression, statement, poplex);
</span><span class="cx">     if (type == &quot;keyword b&quot;) return cont(pushlex(&quot;form&quot;), statement, poplex);
</span><span class="cx">     if (type == &quot;{&quot;) return cont(pushlex(&quot;}&quot;), block, poplex);
</span><span class="cx">     if (type == &quot;;&quot;) return cont();
</span><span class="cx">     if (type == &quot;if&quot;) return cont(pushlex(&quot;form&quot;), expression, statement, poplex, maybeelse);
</span><span class="cx">     if (type == &quot;function&quot;) return cont(functiondef);
</span><del>-    if (type == &quot;for&quot;) return cont(pushlex(&quot;form&quot;), expect(&quot;(&quot;), pushlex(&quot;)&quot;), forspec1, expect(&quot;)&quot;),
-                                   poplex, statement, poplex);
</del><ins>+    if (type == &quot;for&quot;) return cont(pushlex(&quot;form&quot;), forspec, poplex, statement, poplex);
</ins><span class="cx">     if (type == &quot;variable&quot;) return cont(pushlex(&quot;stat&quot;), maybelabel);
</span><span class="cx">     if (type == &quot;switch&quot;) return cont(pushlex(&quot;form&quot;), expression, pushlex(&quot;}&quot;, &quot;switch&quot;), expect(&quot;{&quot;),
</span><span class="cx">                                       block, poplex, poplex);
</span><span class="lines">@@ -270,6 +312,10 @@
</span><span class="cx">     if (type == &quot;default&quot;) return cont(expect(&quot;:&quot;));
</span><span class="cx">     if (type == &quot;catch&quot;) return cont(pushlex(&quot;form&quot;), pushcontext, expect(&quot;(&quot;), funarg, expect(&quot;)&quot;),
</span><span class="cx">                                      statement, poplex, popcontext);
</span><ins>+    if (type == &quot;module&quot;) return cont(pushlex(&quot;form&quot;), pushcontext, afterModule, popcontext, poplex);
+    if (type == &quot;class&quot;) return cont(pushlex(&quot;form&quot;), className, objlit, poplex);
+    if (type == &quot;export&quot;) return cont(pushlex(&quot;form&quot;), afterExport, poplex);
+    if (type == &quot;import&quot;) return cont(pushlex(&quot;form&quot;), afterImport, poplex);
</ins><span class="cx">     return pass(pushlex(&quot;stat&quot;), expression, expect(&quot;;&quot;), poplex);
</span><span class="cx">   }
</span><span class="cx">   function expression(type) {
</span><span class="lines">@@ -279,14 +325,20 @@
</span><span class="cx">     return expressionInner(type, true);
</span><span class="cx">   }
</span><span class="cx">   function expressionInner(type, noComma) {
</span><ins>+    if (cx.state.fatArrowAt == cx.stream.start) {
+      var body = noComma ? arrowBodyNoComma : arrowBody;
+      if (type == &quot;(&quot;) return cont(pushcontext, commasep(pattern, &quot;)&quot;), expect(&quot;=&gt;&quot;), body, popcontext);
+      else if (type == &quot;variable&quot;) return pass(pushcontext, pattern, expect(&quot;=&gt;&quot;), body, popcontext);
+    }
+
</ins><span class="cx">     var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;
</span><span class="cx">     if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);
</span><span class="cx">     if (type == &quot;function&quot;) return cont(functiondef);
</span><span class="cx">     if (type == &quot;keyword c&quot;) return cont(noComma ? maybeexpressionNoComma : maybeexpression);
</span><del>-    if (type == &quot;(&quot;) return cont(pushlex(&quot;)&quot;), maybeexpression, expect(&quot;)&quot;), poplex, maybeop);
-    if (type == &quot;operator&quot;) return cont(noComma ? expressionNoComma : expression);
-    if (type == &quot;[&quot;) return cont(pushlex(&quot;]&quot;), commasep(expressionNoComma, &quot;]&quot;), poplex, maybeop);
-    if (type == &quot;{&quot;) return cont(pushlex(&quot;}&quot;), commasep(objprop, &quot;}&quot;), poplex, maybeop);
</del><ins>+    if (type == &quot;(&quot;) return cont(pushlex(&quot;)&quot;), maybeexpression, comprehension, expect(&quot;)&quot;), poplex, maybeop);
+    if (type == &quot;operator&quot; || type == &quot;spread&quot;) return cont(noComma ? expressionNoComma : expression);
+    if (type == &quot;[&quot;) return cont(pushlex(&quot;]&quot;), expressionNoComma, maybeArrayComprehension, poplex, maybeop);
+    if (type == &quot;{&quot;) return cont(commasep(objprop, &quot;}&quot;), maybeop);
</ins><span class="cx">     return cont();
</span><span class="cx">   }
</span><span class="cx">   function maybeexpression(type) {
</span><span class="lines">@@ -305,16 +357,40 @@
</span><span class="cx">   function maybeoperatorNoComma(type, value, noComma) {
</span><span class="cx">     var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma;
</span><span class="cx">     var expr = noComma == false ? expression : expressionNoComma;
</span><ins>+    if (value == &quot;=&gt;&quot;) return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext);
</ins><span class="cx">     if (type == &quot;operator&quot;) {
</span><span class="cx">       if (/\+\+|--/.test(value)) return cont(me);
</span><span class="cx">       if (value == &quot;?&quot;) return cont(expression, expect(&quot;:&quot;), expr);
</span><span class="cx">       return cont(expr);
</span><span class="cx">     }
</span><ins>+    if (type == &quot;quasi&quot;) { cx.cc.push(me); return quasi(value); }
</ins><span class="cx">     if (type == &quot;;&quot;) return;
</span><del>-    if (type == &quot;(&quot;) return cont(pushlex(&quot;)&quot;, &quot;call&quot;), commasep(expressionNoComma, &quot;)&quot;), poplex, me);
</del><ins>+    if (type == &quot;(&quot;) return cont(commasep(expressionNoComma, &quot;)&quot;, &quot;call&quot;), me);
</ins><span class="cx">     if (type == &quot;.&quot;) return cont(property, me);
</span><span class="cx">     if (type == &quot;[&quot;) return cont(pushlex(&quot;]&quot;), maybeexpression, expect(&quot;]&quot;), poplex, me);
</span><span class="cx">   }
</span><ins>+  function quasi(value) {
+    if (!value) debugger;
+    if (value.slice(value.length - 2) != &quot;${&quot;) return cont();
+    return cont(expression, continueQuasi);
+  }
+  function continueQuasi(type) {
+    if (type == &quot;}&quot;) {
+      cx.marked = &quot;string-2&quot;;
+      cx.state.tokenize = tokenQuasi;
+      return cont();
+    }
+  }
+  function arrowBody(type) {
+    findFatArrow(cx.stream, cx.state);
+    if (type == &quot;{&quot;) return pass(statement);
+    return pass(expression);
+  }
+  function arrowBodyNoComma(type) {
+    findFatArrow(cx.stream, cx.state);
+    if (type == &quot;{&quot;) return pass(statement);
+    return pass(expressionNoComma);
+  }
</ins><span class="cx">   function maybelabel(type) {
</span><span class="cx">     if (type == &quot;:&quot;) return cont(poplex, statement);
</span><span class="cx">     return pass(maybeoperatorComma, expect(&quot;;&quot;), poplex);
</span><span class="lines">@@ -328,16 +404,21 @@
</span><span class="cx">       if (value == &quot;get&quot; || value == &quot;set&quot;) return cont(getterSetter);
</span><span class="cx">     } else if (type == &quot;number&quot; || type == &quot;string&quot;) {
</span><span class="cx">       cx.marked = type + &quot; property&quot;;
</span><ins>+    } else if (type == &quot;[&quot;) {
+      return cont(expression, expect(&quot;]&quot;), afterprop);
</ins><span class="cx">     }
</span><del>-    if (atomicTypes.hasOwnProperty(type)) return cont(expect(&quot;:&quot;), expressionNoComma);
</del><ins>+    if (atomicTypes.hasOwnProperty(type)) return cont(afterprop);
</ins><span class="cx">   }
</span><span class="cx">   function getterSetter(type) {
</span><del>-    if (type == &quot;:&quot;) return cont(expression);
-    if (type != &quot;variable&quot;) return cont(expect(&quot;:&quot;), expression);
</del><ins>+    if (type != &quot;variable&quot;) return pass(afterprop);
</ins><span class="cx">     cx.marked = &quot;property&quot;;
</span><span class="cx">     return cont(functiondef);
</span><span class="cx">   }
</span><del>-  function commasep(what, end) {
</del><ins>+  function afterprop(type) {
+    if (type == &quot;:&quot;) return cont(expressionNoComma);
+    if (type == &quot;(&quot;) return pass(functiondef);
+  }
+  function commasep(what, end, info) {
</ins><span class="cx">     function proceed(type) {
</span><span class="cx">       if (type == &quot;,&quot;) {
</span><span class="cx">         var lex = cx.state.lexical;
</span><span class="lines">@@ -349,7 +430,8 @@
</span><span class="cx">     }
</span><span class="cx">     return function(type) {
</span><span class="cx">       if (type == end) return cont();
</span><del>-      else return pass(what, proceed);
</del><ins>+      if (info === false) return pass(what, proceed);
+      return pass(pushlex(end, info), what, proceed, poplex);
</ins><span class="cx">     };
</span><span class="cx">   }
</span><span class="cx">   function block(type) {
</span><span class="lines">@@ -357,67 +439,121 @@
</span><span class="cx">     return pass(statement, block);
</span><span class="cx">   }
</span><span class="cx">   function maybetype(type) {
</span><del>-    if (type == &quot;:&quot;) return cont(typedef);
-    return pass();
</del><ins>+    if (isTS &amp;&amp; type == &quot;:&quot;) return cont(typedef);
</ins><span class="cx">   }
</span><span class="cx">   function typedef(type) {
</span><span class="cx">     if (type == &quot;variable&quot;){cx.marked = &quot;variable-3&quot;; return cont();}
</span><del>-    return pass();
</del><span class="cx">   }
</span><del>-  function vardef1(type, value) {
-    if (type == &quot;variable&quot;) {
</del><ins>+  function vardef() {
+    return pass(pattern, maybetype, maybeAssign, vardefCont);
+  }
+  function pattern(type, value) {
+    if (type == &quot;variable&quot;) { register(value); return cont(); }
+    if (type == &quot;[&quot;) return cont(commasep(pattern, &quot;]&quot;));
+    if (type == &quot;{&quot;) return cont(commasep(proppattern, &quot;}&quot;));
+  }
+  function proppattern(type, value) {
+    if (type == &quot;variable&quot; &amp;&amp; !cx.stream.match(/^\s*:/, false)) {
</ins><span class="cx">       register(value);
</span><del>-      return isTS ? cont(maybetype, vardef2) : cont(vardef2);
</del><ins>+      return cont(maybeAssign);
</ins><span class="cx">     }
</span><del>-    return pass();
</del><ins>+    if (type == &quot;variable&quot;) cx.marked = &quot;property&quot;;
+    return cont(expect(&quot;:&quot;), pattern, maybeAssign);
</ins><span class="cx">   }
</span><del>-  function vardef2(type, value) {
-    if (value == &quot;=&quot;) return cont(expressionNoComma, vardef2);
-    if (type == &quot;,&quot;) return cont(vardef1);
</del><ins>+  function maybeAssign(_type, value) {
+    if (value == &quot;=&quot;) return cont(expressionNoComma);
</ins><span class="cx">   }
</span><ins>+  function vardefCont(type) {
+    if (type == &quot;,&quot;) return cont(vardef);
+  }
</ins><span class="cx">   function maybeelse(type, value) {
</span><span class="cx">     if (type == &quot;keyword b&quot; &amp;&amp; value == &quot;else&quot;) return cont(pushlex(&quot;form&quot;), statement, poplex);
</span><span class="cx">   }
</span><ins>+  function forspec(type) {
+    if (type == &quot;(&quot;) return cont(pushlex(&quot;)&quot;), forspec1, expect(&quot;)&quot;));
+  }
</ins><span class="cx">   function forspec1(type) {
</span><del>-    if (type == &quot;var&quot;) return cont(vardef1, expect(&quot;;&quot;), forspec2);
</del><ins>+    if (type == &quot;var&quot;) return cont(vardef, expect(&quot;;&quot;), forspec2);
</ins><span class="cx">     if (type == &quot;;&quot;) return cont(forspec2);
</span><del>-    if (type == &quot;variable&quot;) return cont(formaybein);
</del><ins>+    if (type == &quot;variable&quot;) return cont(formaybeinof);
</ins><span class="cx">     return pass(expression, expect(&quot;;&quot;), forspec2);
</span><span class="cx">   }
</span><del>-  function formaybein(_type, value) {
-    if (value == &quot;in&quot;) return cont(expression);
</del><ins>+  function formaybeinof(_type, value) {
+    if (value == &quot;in&quot; || value == &quot;of&quot;) { cx.marked = &quot;keyword&quot;; return cont(expression); }
</ins><span class="cx">     return cont(maybeoperatorComma, forspec2);
</span><span class="cx">   }
</span><span class="cx">   function forspec2(type, value) {
</span><span class="cx">     if (type == &quot;;&quot;) return cont(forspec3);
</span><del>-    if (value == &quot;in&quot;) return cont(expression);
</del><ins>+    if (value == &quot;in&quot; || value == &quot;of&quot;) { cx.marked = &quot;keyword&quot;; return cont(expression); }
</ins><span class="cx">     return pass(expression, expect(&quot;;&quot;), forspec3);
</span><span class="cx">   }
</span><span class="cx">   function forspec3(type) {
</span><span class="cx">     if (type != &quot;)&quot;) cont(expression);
</span><span class="cx">   }
</span><span class="cx">   function functiondef(type, value) {
</span><ins>+    if (value == &quot;*&quot;) {cx.marked = &quot;keyword&quot;; return cont(functiondef);}
</ins><span class="cx">     if (type == &quot;variable&quot;) {register(value); return cont(functiondef);}
</span><del>-    if (type == &quot;(&quot;) return cont(pushlex(&quot;)&quot;), pushcontext, commasep(funarg, &quot;)&quot;), poplex, statement, popcontext);
</del><ins>+    if (type == &quot;(&quot;) return cont(pushcontext, commasep(funarg, &quot;)&quot;), statement, popcontext);
</ins><span class="cx">   }
</span><del>-  function funarg(type, value) {
-    if (type == &quot;variable&quot;) {register(value); return isTS ? cont(maybetype) : cont();}
</del><ins>+  function funarg(type) {
+    if (type == &quot;spread&quot;) return cont(funarg);
+    return pass(pattern, maybetype);
</ins><span class="cx">   }
</span><ins>+  function className(type, value) {
+    if (type == &quot;variable&quot;) {register(value); return cont(classNameAfter);}
+  }
+  function classNameAfter(_type, value) {
+    if (value == &quot;extends&quot;) return cont(expression);
+  }
+  function objlit(type) {
+    if (type == &quot;{&quot;) return cont(commasep(objprop, &quot;}&quot;));
+  }
+  function afterModule(type, value) {
+    if (type == &quot;string&quot;) return cont(statement);
+    if (type == &quot;variable&quot;) { register(value); return cont(maybeFrom); }
+  }
+  function afterExport(_type, value) {
+    if (value == &quot;*&quot;) { cx.marked = &quot;keyword&quot;; return cont(maybeFrom, expect(&quot;;&quot;)); }
+    if (value == &quot;default&quot;) { cx.marked = &quot;keyword&quot;; return cont(expression, expect(&quot;;&quot;)); }
+    return pass(statement);
+  }
+  function afterImport(type) {
+    if (type == &quot;string&quot;) return cont();
+    return pass(importSpec, maybeFrom);
+  }
+  function importSpec(type, value) {
+    if (type == &quot;{&quot;) return cont(commasep(importSpec, &quot;}&quot;));
+    if (type == &quot;variable&quot;) register(value);
+    return cont();
+  }
+  function maybeFrom(_type, value) {
+    if (value == &quot;from&quot;) { cx.marked = &quot;keyword&quot;; return cont(expression); }
+  }
+  function maybeArrayComprehension(type) {
+    if (type == &quot;for&quot;) return pass(comprehension);
+    if (type == &quot;,&quot;) return cont(commasep(expressionNoComma, &quot;]&quot;, false));
+    return pass(commasep(expressionNoComma, &quot;]&quot;, false));
+  }
+  function comprehension(type) {
+    if (type == &quot;for&quot;) return cont(forspec, comprehension);
+    if (type == &quot;if&quot;) return cont(expression, comprehension);
+  }
</ins><span class="cx"> 
</span><span class="cx">   // Interface
</span><span class="cx"> 
</span><span class="cx">   return {
</span><span class="cx">     startState: function(basecolumn) {
</span><del>-      return {
-        tokenize: jsTokenBase,
-        lastType: null,
</del><ins>+      var state = {
+        tokenize: tokenBase,
+        lastType: &quot;sof&quot;,
</ins><span class="cx">         cc: [],
</span><span class="cx">         lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, &quot;block&quot;, false),
</span><span class="cx">         localVars: parserConfig.localVars,
</span><del>-        globalVars: parserConfig.globalVars,
</del><span class="cx">         context: parserConfig.localVars &amp;&amp; {vars: parserConfig.localVars},
</span><span class="cx">         indented: 0
</span><span class="cx">       };
</span><ins>+      if (parserConfig.globalVars) state.globalVars = parserConfig.globalVars;
+      return state;
</ins><span class="cx">     },
</span><span class="cx"> 
</span><span class="cx">     token: function(stream, state) {
</span><span class="lines">@@ -425,8 +561,9 @@
</span><span class="cx">         if (!state.lexical.hasOwnProperty(&quot;align&quot;))
</span><span class="cx">           state.lexical.align = false;
</span><span class="cx">         state.indented = stream.indentation();
</span><ins>+        findFatArrow(stream, state);
</ins><span class="cx">       }
</span><del>-      if (state.tokenize != jsTokenComment &amp;&amp; stream.eatSpace()) return null;
</del><ins>+      if (state.tokenize != tokenComment &amp;&amp; stream.eatSpace()) return null;
</ins><span class="cx">       var style = state.tokenize(stream, state);
</span><span class="cx">       if (type == &quot;comment&quot;) return style;
</span><span class="cx">       state.lastType = type == &quot;operator&quot; &amp;&amp; (content == &quot;++&quot; || content == &quot;--&quot;) ? &quot;incdec&quot; : type;
</span><span class="lines">@@ -434,21 +571,21 @@
</span><span class="cx">     },
</span><span class="cx"> 
</span><span class="cx">     indent: function(state, textAfter) {
</span><del>-      if (state.tokenize == jsTokenComment) return CodeMirror.Pass;
-      if (state.tokenize != jsTokenBase) return 0;
</del><ins>+      if (state.tokenize == tokenComment) return CodeMirror.Pass;
+      if (state.tokenize != tokenBase) return 0;
</ins><span class="cx">       var firstChar = textAfter &amp;&amp; textAfter.charAt(0), lexical = state.lexical;
</span><span class="cx">       // Kludge to prevent 'maybelse' from blocking lexical scope pops
</span><span class="cx">       for (var i = state.cc.length - 1; i &gt;= 0; --i) {
</span><span class="cx">         var c = state.cc[i];
</span><span class="cx">         if (c == poplex) lexical = lexical.prev;
</span><del>-        else if (c != maybeelse || /^else\b/.test(textAfter)) break;
</del><ins>+        else if (c != maybeelse) break;
</ins><span class="cx">       }
</span><span class="cx">       if (lexical.type == &quot;stat&quot; &amp;&amp; firstChar == &quot;}&quot;) lexical = lexical.prev;
</span><span class="cx">       if (statementIndent &amp;&amp; lexical.type == &quot;)&quot; &amp;&amp; lexical.prev.type == &quot;stat&quot;)
</span><span class="cx">         lexical = lexical.prev;
</span><span class="cx">       var type = lexical.type, closing = firstChar == type;
</span><span class="cx"> 
</span><del>-      if (type == &quot;vardef&quot;) return lexical.indented + (state.lastType == &quot;operator&quot; || state.lastType == &quot;,&quot; ? 4 : 0);
</del><ins>+      if (type == &quot;vardef&quot;) return lexical.indented + (state.lastType == &quot;operator&quot; || state.lastType == &quot;,&quot; ? lexical.info + 1 : 0);
</ins><span class="cx">       else if (type == &quot;form&quot; &amp;&amp; firstChar == &quot;{&quot;) return lexical.indented;
</span><span class="cx">       else if (type == &quot;form&quot;) return lexical.indented + indentUnit;
</span><span class="cx">       else if (type == &quot;stat&quot;)
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceExternalCodeMirrorlessjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/less.js (160499 => 160500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/less.js        2013-12-12 19:37:21 UTC (rev 160499)
+++ trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/less.js        2013-12-12 19:52:46 UTC (rev 160500)
</span><span class="lines">@@ -32,9 +32,9 @@
</span><span class="cx">         return tokenSComment(stream, state);
</span><span class="cx">       } else {
</span><span class="cx">         if(type == &quot;string&quot; || type == &quot;(&quot;) return ret(&quot;string&quot;, &quot;string&quot;);
</span><del>-        if(state.stack[state.stack.length-1] != undefined) return ret(null, ch);
</del><ins>+        if(state.stack[state.stack.length-1] !== undefined) return ret(null, ch);
</ins><span class="cx">         stream.eatWhile(/[\a-zA-Z0-9\-_.\s]/);
</span><del>-        if( /\/|\)|#/.test(stream.peek() || (stream.eatSpace() &amp;&amp; stream.peek() == &quot;)&quot;))  || stream.eol() )return ret(&quot;string&quot;, &quot;string&quot;); // let url(/images/logo.png) without quotes return as string
</del><ins>+        if( /\/|\)|#/.test(stream.peek() || (stream.eatSpace() &amp;&amp; stream.peek() === &quot;)&quot;))  || stream.eol() )return ret(&quot;string&quot;, &quot;string&quot;); // let url(/images/logo.png) without quotes return as string
</ins><span class="cx">       }
</span><span class="cx">     } else if (ch == &quot;!&quot;) {
</span><span class="cx">       stream.match(/^\s*\w*/);
</span><span class="lines">@@ -66,10 +66,13 @@
</span><span class="cx">         return ret(null, ch);
</span><span class="cx">       }
</span><span class="cx">     } else if (ch == &quot;.&quot;) {
</span><del>-      if(type == &quot;(&quot; || type == &quot;string&quot;)return ret(&quot;string&quot;, &quot;string&quot;); // allow url(../image.png)
</del><ins>+      if(type == &quot;(&quot;)return ret(&quot;string&quot;, &quot;string&quot;); // allow url(../image.png)
</ins><span class="cx">       stream.eatWhile(/[\a-zA-Z0-9\-_]/);
</span><del>-      if(stream.peek() == &quot; &quot;)stream.eatSpace();
-      if(stream.peek() == &quot;)&quot;)return ret(&quot;number&quot;, &quot;unit&quot;);//rgba(0,0,0,.25);
</del><ins>+      if(stream.peek() === &quot; &quot;)stream.eatSpace();
+      if(stream.peek() === &quot;)&quot; || type === &quot;:&quot;)return ret(&quot;number&quot;, &quot;unit&quot;);//rgba(0,0,0,.25);
+      else if(stream.current().length &gt;1){
+        if(state.stack[state.stack.length-1] === &quot;rule&quot; &amp;&amp; stream.peek().match(/{|,|\+|\(/) === null)return ret(&quot;number&quot;, &quot;unit&quot;);
+      }
</ins><span class="cx">       return ret(&quot;tag&quot;, &quot;tag&quot;);
</span><span class="cx">     } else if (ch == &quot;#&quot;) {
</span><span class="cx">       //we don't eat white-space, we want the hex color and or id only
</span><span class="lines">@@ -82,21 +85,24 @@
</span><span class="cx">           //eat white-space
</span><span class="cx">           stream.eatSpace();
</span><span class="cx">           //when hex value declaration doesn't end with [;,] but is does with a slash/cc comment treat it as an id, just like the other hex values that don't end with[;,]
</span><del>-          if( /[\/&lt;&gt;.(){!$%^&amp;*_\-\\?=+\|#'~`]/.test(stream.peek()) )return ret(&quot;atom&quot;, &quot;tag&quot;);
</del><ins>+          if( /[\/&lt;&gt;.(){!$%^&amp;*_\-\\?=+\|#'~`]/.test(stream.peek()) ){
+            if(type === &quot;select-op&quot;)return ret(&quot;number&quot;, &quot;unit&quot;); else return ret(&quot;atom&quot;, &quot;tag&quot;);
+          }
</ins><span class="cx">           //#time { color: #aaa }
</span><span class="cx">           else if(stream.peek() == &quot;}&quot; )return ret(&quot;number&quot;, &quot;unit&quot;);
</span><span class="cx">           //we have a valid hex color value, parse as id whenever an element/class is defined after the hex(id) value e.g. #eee aaa || #eee .aaa
</span><del>-            else if( /[a-zA-Z\\]/.test(stream.peek()) )return ret(&quot;atom&quot;, &quot;tag&quot;);
</del><ins>+          else if( /[a-zA-Z\\]/.test(stream.peek()) )return ret(&quot;atom&quot;, &quot;tag&quot;);
</ins><span class="cx">           //when a hex value is on the end of a line, parse as id
</span><del>-              else if(stream.eol())return ret(&quot;atom&quot;, &quot;tag&quot;);
</del><ins>+          else if(stream.eol())return ret(&quot;atom&quot;, &quot;tag&quot;);
</ins><span class="cx">           //default
</span><del>-                else return ret(&quot;number&quot;, &quot;unit&quot;);
</del><ins>+          else return ret(&quot;number&quot;, &quot;unit&quot;);
</ins><span class="cx">         } else {//when not a valid hexvalue in the current stream e.g. #footer
</span><span class="cx">           stream.eatWhile(/[\w\\\-]/);
</span><del>-          return ret(&quot;atom&quot;, &quot;tag&quot;);
</del><ins>+          return ret(&quot;atom&quot;, stream.current());
</ins><span class="cx">         }
</span><span class="cx">       } else {//when not a valid hexvalue length
</span><span class="cx">         stream.eatWhile(/[\w\\\-]/);
</span><ins>+        if(state.stack[state.stack.length-1] === &quot;rule&quot;)return ret(&quot;atom&quot;, stream.current());return ret(&quot;atom&quot;, stream.current());
</ins><span class="cx">         return ret(&quot;atom&quot;, &quot;tag&quot;);
</span><span class="cx">       }
</span><span class="cx">     } else if (ch == &quot;&amp;&quot;) {
</span><span class="lines">@@ -104,17 +110,33 @@
</span><span class="cx">       return ret(null, ch);
</span><span class="cx">     } else {
</span><span class="cx">       stream.eatWhile(/[\w\\\-_%.{]/);
</span><del>-      if(type == &quot;string&quot;){
-        return ret(&quot;string&quot;, &quot;string&quot;);
</del><ins>+      if(stream.current().match(/\\/) !== null){
+        if(stream.current().charAt(stream.current().length-1) === &quot;\\&quot;){
+          stream.eat(/\'|\&quot;|\)|\(/);
+          while(stream.eatWhile(/[\w\\\-_%.{]/)){
+            stream.eat(/\'|\&quot;|\)|\(/);
+          }
+          return ret(&quot;string&quot;, stream.current());
+        }
+      } //else if(type === &quot;tag&quot;)return ret(&quot;tag&quot;, &quot;tag&quot;);
+        else if(type == &quot;string&quot;){
+        if(state.stack[state.stack.length-1] === &quot;{&quot; &amp;&amp; stream.peek() === &quot;:&quot;)return ret(&quot;variable&quot;, &quot;variable&quot;);
+        if(stream.peek() === &quot;/&quot;)stream.eatWhile(/[\w\\\-_%.{:\/]/);
+        return ret(type, stream.current());
</ins><span class="cx">       } else if(stream.current().match(/(^http$|^https$)/) != null){
</span><span class="cx">         stream.eatWhile(/[\w\\\-_%.{:\/]/);
</span><ins>+        if(stream.peek() === &quot;/&quot;)stream.eatWhile(/[\w\\\-_%.{:\/]/);
</ins><span class="cx">         return ret(&quot;string&quot;, &quot;string&quot;);
</span><span class="cx">       } else if(stream.peek() == &quot;&lt;&quot; || stream.peek() == &quot;&gt;&quot; || stream.peek() == &quot;+&quot;){
</span><ins>+        if(type === &quot;(&quot; &amp;&amp; (stream.current() === &quot;n&quot; || stream.current() === &quot;-n&quot;))return ret(&quot;string&quot;, stream.current());
</ins><span class="cx">         return ret(&quot;tag&quot;, &quot;tag&quot;);
</span><span class="cx">       } else if( /\(/.test(stream.peek()) ){
</span><ins>+        if(stream.current() === &quot;when&quot;)return ret(&quot;variable&quot;,&quot;variable&quot;);
+        else if(state.stack[state.stack.length-1] === &quot;@media&quot; &amp;&amp; stream.current() === &quot;and&quot;)return ret(&quot;variable&quot;,stream.current());
</ins><span class="cx">         return ret(null, ch);
</span><del>-      } else if (stream.peek() == &quot;/&quot; &amp;&amp; state.stack[state.stack.length-1] != undefined){ // url(dir/center/image.png)
-        return ret(&quot;string&quot;, &quot;string&quot;);
</del><ins>+      } else if (stream.peek() == &quot;/&quot; &amp;&amp; state.stack[state.stack.length-1] !== undefined){ // url(dir/center/image.png)
+        if(stream.peek() === &quot;/&quot;)stream.eatWhile(/[\w\\\-_%.{:\/]/);
+        return ret(&quot;string&quot;, stream.current());
</ins><span class="cx">       } else if( stream.current().match(/\-\d|\-.\d/) ){ // match e.g.: -5px -0.4 etc... only colorize the minus sign
</span><span class="cx">         //commment out these 2 comment if you want the minus sign to be parsed as null -500px
</span><span class="cx">         //stream.backUp(stream.current().length-1);
</span><span class="lines">@@ -129,14 +151,33 @@
</span><span class="cx">         if( /[{&lt;&gt;.a-zA-Z\/]/.test(stream.peek())  || stream.eol() )return ret(&quot;tag&quot;, &quot;tag&quot;); // e.g. button.icon-plus
</span><span class="cx">         return ret(&quot;string&quot;, &quot;string&quot;); // let url(/images/logo.png) without quotes return as string
</span><span class="cx">       } else if( stream.eol() || stream.peek() == &quot;[&quot; || stream.peek() == &quot;#&quot; || type == &quot;tag&quot; ){
</span><ins>+
</ins><span class="cx">         if(stream.current().substring(stream.current().length-1,stream.current().length) == &quot;{&quot;)stream.backUp(1);
</span><ins>+        else if(state.stack[state.stack.length-1] === &quot;border-color&quot; || state.stack[state.stack.length-1] === &quot;background-position&quot; || state.stack[state.stack.length-1] === &quot;font-family&quot;)return ret(null, stream.current());
+        else if(type === &quot;tag&quot;)return ret(&quot;tag&quot;, &quot;tag&quot;);
+        else if((type === &quot;:&quot; || type === &quot;unit&quot;) &amp;&amp; state.stack[state.stack.length-1] === &quot;rule&quot;)return ret(null, stream.current());
+        else if(state.stack[state.stack.length-1] === &quot;rule&quot; &amp;&amp; type === &quot;tag&quot;)return ret(&quot;string&quot;, stream.current());
+        else if(state.stack[state.stack.length-1] === &quot;;&quot; &amp;&amp; type === &quot;:&quot;)return ret(null, stream.current());
+        //else if(state.stack[state.stack.length-1] === &quot;;&quot; || type === &quot;&quot;)return ret(&quot;variable&quot;, stream.current());
+        else if(stream.peek() === &quot;#&quot; &amp;&amp; type !== undefined &amp;&amp; type.match(/\+|,|tag|select\-op|}|{|;/g) === null)return ret(&quot;string&quot;, stream.current());
+        else if(type === &quot;variable&quot;)return ret(null, stream.current());
+        else if(state.stack[state.stack.length-1] === &quot;{&quot; &amp;&amp; type === &quot;comment&quot;)return ret(&quot;variable&quot;, stream.current());
+        else if(state.stack.length === 0 &amp;&amp; (type === &quot;;&quot; || type === &quot;comment&quot;))return ret(&quot;tag&quot;, stream.current());
+        else if((state.stack[state.stack.length-1] === &quot;{&quot; || type === &quot;;&quot;) &amp;&amp; state.stack[state.stack.length-1] !== &quot;@media{&quot;)return ret(&quot;variable&quot;, stream.current());
+        else if(state.stack[state.stack.length-2] === &quot;{&quot; &amp;&amp; state.stack[state.stack.length-1] === &quot;;&quot;)return ret(&quot;variable&quot;, stream.current());
+
</ins><span class="cx">         return ret(&quot;tag&quot;, &quot;tag&quot;);
</span><span class="cx">       } else if(type == &quot;compare&quot; || type == &quot;a&quot; || type == &quot;(&quot;){
</span><span class="cx">         return ret(&quot;string&quot;, &quot;string&quot;);
</span><span class="cx">       } else if(type == &quot;|&quot; || stream.current() == &quot;-&quot; || type == &quot;[&quot;){
</span><del>-        if(type == &quot;|&quot; )return ret(&quot;tag&quot;, &quot;tag&quot;);
</del><ins>+        if(type == &quot;|&quot; &amp;&amp; stream.peek().match(/\]|=|\~/) !== null)return ret(&quot;number&quot;, stream.current());
+        else if(type == &quot;|&quot; )return ret(&quot;tag&quot;, &quot;tag&quot;);
+        else if(type == &quot;[&quot;){
+          stream.eatWhile(/\w\-/);
+          return ret(&quot;number&quot;, stream.current());
+        }
</ins><span class="cx">         return ret(null, ch);
</span><del>-      } else if(stream.peek() == &quot;:&quot;) {
</del><ins>+      } else if((stream.peek() == &quot;:&quot;) || ( stream.eatSpace() &amp;&amp; stream.peek() == &quot;:&quot;)) {
</ins><span class="cx">         stream.next();
</span><span class="cx">         var t_v = stream.peek() == &quot;:&quot; ? true : false;
</span><span class="cx">         if(!t_v){
</span><span class="lines">@@ -152,11 +193,50 @@
</span><span class="cx">           stream.backUp(1);
</span><span class="cx">         }
</span><span class="cx">         if(t_v)return ret(&quot;tag&quot;, &quot;tag&quot;); else return ret(&quot;variable&quot;, &quot;variable&quot;);
</span><del>-      } else if(state.stack[state.stack.length-1]  === &quot;font-family&quot;){
</del><ins>+      } else if(state.stack[state.stack.length-1]  === &quot;font-family&quot; || state.stack[state.stack.length-1]  === &quot;background-position&quot; || state.stack[state.stack.length-1]  === &quot;border-color&quot;){
</ins><span class="cx">         return ret(null, null);
</span><span class="cx">       } else {
</span><del>-        if(state.stack[state.stack.length-1] === &quot;{&quot; || type === &quot;select-op&quot;  || (state.stack[state.stack.length-1] === &quot;rule&quot; &amp;&amp; type === &quot;,&quot;) )return ret(&quot;tag&quot;, &quot;tag&quot;);
-        return ret(&quot;variable&quot;, &quot;variable&quot;);
</del><ins>+
+        if(state.stack[state.stack.length-1] === null &amp;&amp; type === &quot;:&quot;)return ret(null, stream.current());
+
+        //else if((type === &quot;)&quot; &amp;&amp; state.stack[state.stack.length-1] === &quot;rule&quot;) || (state.stack[state.stack.length-2] === &quot;{&quot; &amp;&amp; state.stack[state.stack.length-1] === &quot;rule&quot; &amp;&amp; type === &quot;variable&quot;))return ret(null, stream.current());
+
+        else if(/\^|\$/.test(stream.current()) &amp;&amp; stream.peek().match(/\~|=/) !== null)return ret(&quot;string&quot;, &quot;string&quot;);//att^=val
+
+        else if(type === &quot;unit&quot; &amp;&amp; state.stack[state.stack.length-1] === &quot;rule&quot;)return ret(null, &quot;unit&quot;);
+        else if(type === &quot;unit&quot; &amp;&amp; state.stack[state.stack.length-1] === &quot;;&quot;)return ret(null, &quot;unit&quot;);
+        else if(type === &quot;)&quot; &amp;&amp; state.stack[state.stack.length-1] === &quot;rule&quot;)return ret(null, &quot;unit&quot;);
+        else if(type &amp;&amp; type.match(&quot;@&quot;) !== null  &amp;&amp; state.stack[state.stack.length-1] === &quot;rule&quot;)return ret(null, &quot;unit&quot;);
+        //else if(type === &quot;unit&quot; &amp;&amp; state.stack[state.stack.length-1] === &quot;rule&quot;)return ret(null, stream.current());
+
+        else if((type === &quot;;&quot; || type === &quot;}&quot; || type === &quot;,&quot;) &amp;&amp; state.stack[state.stack.length-1] === &quot;;&quot;)return ret(&quot;tag&quot;, stream.current());
+        else if((type === &quot;;&quot; &amp;&amp; stream.peek() !== undefined &amp;&amp; stream.peek().match(/{|./) === null) || (type === &quot;;&quot; &amp;&amp; stream.eatSpace() &amp;&amp; stream.peek().match(/{|./) === null))return ret(&quot;variable&quot;, stream.current());
+        else if((type === &quot;@media&quot; &amp;&amp; state.stack[state.stack.length-1] === &quot;@media&quot;) || type === &quot;@namespace&quot;)return ret(&quot;tag&quot;, stream.current());
+
+        else if(type === &quot;{&quot;  &amp;&amp; state.stack[state.stack.length-1] === &quot;;&quot; &amp;&amp; stream.peek() === &quot;{&quot;)return ret(&quot;tag&quot;, &quot;tag&quot;);
+        else if((type === &quot;{&quot; || type === &quot;:&quot;) &amp;&amp; state.stack[state.stack.length-1] === &quot;;&quot;)return ret(null, stream.current());
+        else if((state.stack[state.stack.length-1] === &quot;{&quot; &amp;&amp; stream.eatSpace() &amp;&amp; stream.peek().match(/.|#/) === null) || type === &quot;select-op&quot;  || (state.stack[state.stack.length-1] === &quot;rule&quot; &amp;&amp; type === &quot;,&quot;) )return ret(&quot;tag&quot;, &quot;tag&quot;);
+        else if(type === &quot;variable&quot; &amp;&amp; state.stack[state.stack.length-1] === &quot;rule&quot;)return ret(&quot;tag&quot;, &quot;tag&quot;);
+        else if((stream.eatSpace() &amp;&amp; stream.peek() === &quot;{&quot;) || stream.eol() || stream.peek() === &quot;{&quot;)return ret(&quot;tag&quot;, &quot;tag&quot;);
+        //this one messes up indentation
+        //else if((type === &quot;}&quot; &amp;&amp; stream.peek() !== &quot;:&quot;) || (type === &quot;}&quot; &amp;&amp; stream.eatSpace() &amp;&amp; stream.peek() !== &quot;:&quot;))return(type, &quot;tag&quot;);
+
+        else if(type === &quot;)&quot; &amp;&amp; (stream.current() == &quot;and&quot; || stream.current() == &quot;and &quot;))return ret(&quot;variable&quot;, &quot;variable&quot;);
+        else if(type === &quot;)&quot; &amp;&amp; (stream.current() == &quot;when&quot; || stream.current() == &quot;when &quot;))return ret(&quot;variable&quot;, &quot;variable&quot;);
+        else if(type === &quot;)&quot; || type === &quot;comment&quot; || type === &quot;{&quot;)return ret(&quot;tag&quot;, &quot;tag&quot;);
+        else if(stream.sol())return ret(&quot;tag&quot;, &quot;tag&quot;);
+        else if((stream.eatSpace() &amp;&amp; stream.peek() === &quot;#&quot;) || stream.peek() === &quot;#&quot;)return ret(&quot;tag&quot;, &quot;tag&quot;);
+        else if(state.stack.length === 0)return ret(&quot;tag&quot;, &quot;tag&quot;);
+        else if(type === &quot;;&quot; &amp;&amp; stream.peek() !== undefined &amp;&amp; stream.peek().match(/^[.|\#]/g) !== null)return ret(&quot;tag&quot;, &quot;tag&quot;);
+
+        else if(type === &quot;:&quot;){stream.eatSpace();return ret(null, stream.current());}
+
+        else if(stream.current() === &quot;and &quot; || stream.current() === &quot;and&quot;)return ret(&quot;variable&quot;, stream.current());
+        else if(type === &quot;;&quot; &amp;&amp; state.stack[state.stack.length-1] === &quot;{&quot;)return ret(&quot;variable&quot;, stream.current());
+
+        else if(state.stack[state.stack.length-1] === &quot;rule&quot;)return ret(null, stream.current());
+
+        return ret(&quot;tag&quot;, stream.current());
</ins><span class="cx">       }
</span><span class="cx">     }
</span><span class="cx">   }
</span><span class="lines">@@ -234,20 +314,30 @@
</span><span class="cx">       else if (type == &quot;}&quot;) state.stack.pop();
</span><span class="cx">       else if (type == &quot;@media&quot;) state.stack.push(&quot;@media&quot;);
</span><span class="cx">       else if (stream.current() === &quot;font-family&quot;) state.stack[state.stack.length-1] = &quot;font-family&quot;;
</span><ins>+      else if (stream.current() === &quot;background-position&quot;) state.stack[state.stack.length-1] = &quot;background-position&quot;;
+      else if (stream.current() === &quot;border-color&quot;) state.stack[state.stack.length-1] = &quot;border-color&quot;;
</ins><span class="cx">       else if (context == &quot;{&quot; &amp;&amp; type != &quot;comment&quot; &amp;&amp; type !== &quot;tag&quot;) state.stack.push(&quot;rule&quot;);
</span><span class="cx">       else if (stream.peek() === &quot;:&quot; &amp;&amp; stream.current().match(/@|#/) === null) style = type;
</span><ins>+      if(type === &quot;;&quot; &amp;&amp; (state.stack[state.stack.length-1] == &quot;font-family&quot; || state.stack[state.stack.length-1] == &quot;background-position&quot; || state.stack[state.stack.length-1] == &quot;border-color&quot;))state.stack[state.stack.length-1] = stream.current();
+      else if(type === &quot;tag&quot; &amp;&amp; stream.peek() === &quot;)&quot; &amp;&amp; stream.current().match(/\:/) === null){type = null; style = null;}
+      // ????
+      else if((type === &quot;variable&quot; &amp;&amp; stream.peek() === &quot;)&quot;) || (type === &quot;variable&quot; &amp;&amp; stream.eatSpace() &amp;&amp; stream.peek() === &quot;)&quot;))return ret(null,stream.current());
</ins><span class="cx">       return style;
</span><span class="cx">     },
</span><span class="cx"> 
</span><span class="cx">     indent: function(state, textAfter) {
</span><span class="cx">       var n = state.stack.length;
</span><del>-
</del><span class="cx">       if (/^\}/.test(textAfter))
</span><del>-        n -= state.stack[state.stack.length-1] == &quot;rule&quot; ? 2 : 1;
</del><ins>+        n -= state.stack[state.stack.length-1] === &quot;rule&quot; ? 2 : 1;
+      else if (state.stack[state.stack.length-2] === &quot;{&quot;)
+        n -= state.stack[state.stack.length-1] === &quot;rule&quot; ? 1 : 0;
</ins><span class="cx">       return state.baseIndent + n * indentUnit;
</span><span class="cx">     },
</span><span class="cx"> 
</span><del>-    electricChars: &quot;}&quot;
</del><ins>+    electricChars: &quot;}&quot;,
+    blockCommentStart: &quot;/*&quot;,
+    blockCommentEnd: &quot;*/&quot;,
+    lineComment: &quot;//&quot;
</ins><span class="cx">   };
</span><span class="cx"> });
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceExternalCodeMirrormatchbracketsjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/matchbrackets.js (160499 => 160500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/matchbrackets.js        2013-12-12 19:37:21 UTC (rev 160499)
+++ trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/matchbrackets.js        2013-12-12 19:52:46 UTC (rev 160500)
</span><span class="lines">@@ -8,6 +8,7 @@
</span><span class="cx">   function findMatchingBracket(cm, where, strict) {
</span><span class="cx">     var state = cm.state.matchBrackets;
</span><span class="cx">     var maxScanLen = (state &amp;&amp; state.maxScanLineLength) || 10000;
</span><ins>+    var maxScanLines = (state &amp;&amp; state.maxScanLines) || 100;
</ins><span class="cx"> 
</span><span class="cx">     var cur = where || cm.getCursor(), line = cm.getLineHandle(cur.line), pos = cur.ch - 1;
</span><span class="cx">     var match = (pos &gt;= 0 &amp;&amp; matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)];
</span><span class="lines">@@ -32,7 +33,7 @@
</span><span class="cx">         }
</span><span class="cx">       }
</span><span class="cx">     }
</span><del>-    for (var i = cur.line, found, e = forward ? Math.min(i + 100, cm.lineCount()) : Math.max(-1, i - 100); i != e; i+=d) {
</del><ins>+    for (var i = cur.line, found, e = forward ? Math.min(i + maxScanLines, cm.lineCount()) : Math.max(-1, i - maxScanLines); i != e; i+=d) {
</ins><span class="cx">       if (i == cur.line) found = scan(line, i, pos);
</span><span class="cx">       else found = scan(cm.getLineHandle(i), i);
</span><span class="cx">       if (found) break;
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceExternalCodeMirrorplaceholderjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/placeholder.js (160499 => 160500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/placeholder.js        2013-12-12 19:37:21 UTC (rev 160499)
+++ trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/placeholder.js        2013-12-12 19:52:46 UTC (rev 160500)
</span><span class="lines">@@ -2,12 +2,10 @@
</span><span class="cx">   CodeMirror.defineOption(&quot;placeholder&quot;, &quot;&quot;, function(cm, val, old) {
</span><span class="cx">     var prev = old &amp;&amp; old != CodeMirror.Init;
</span><span class="cx">     if (val &amp;&amp; !prev) {
</span><del>-      cm.on(&quot;focus&quot;, onFocus);
</del><span class="cx">       cm.on(&quot;blur&quot;, onBlur);
</span><span class="cx">       cm.on(&quot;change&quot;, onChange);
</span><span class="cx">       onChange(cm);
</span><span class="cx">     } else if (!val &amp;&amp; prev) {
</span><del>-      cm.off(&quot;focus&quot;, onFocus);
</del><span class="cx">       cm.off(&quot;blur&quot;, onBlur);
</span><span class="cx">       cm.off(&quot;change&quot;, onChange);
</span><span class="cx">       clearPlaceholder(cm);
</span><span class="lines">@@ -33,9 +31,6 @@
</span><span class="cx">     cm.display.lineSpace.insertBefore(elt, cm.display.lineSpace.firstChild);
</span><span class="cx">   }
</span><span class="cx"> 
</span><del>-  function onFocus(cm) {
-    clearPlaceholder(cm);
-  }
</del><span class="cx">   function onBlur(cm) {
</span><span class="cx">     if (isEmpty(cm)) setPlaceholder(cm);
</span><span class="cx">   }
</span><span class="lines">@@ -43,7 +38,6 @@
</span><span class="cx">     var wrapper = cm.getWrapperElement(), empty = isEmpty(cm);
</span><span class="cx">     wrapper.className = wrapper.className.replace(&quot; CodeMirror-empty&quot;, &quot;&quot;) + (empty ? &quot; CodeMirror-empty&quot; : &quot;&quot;);
</span><span class="cx"> 
</span><del>-    if (cm.hasFocus()) return;
</del><span class="cx">     if (empty) setPlaceholder(cm);
</span><span class="cx">     else clearPlaceholder(cm);
</span><span class="cx">   }
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceExternalCodeMirrorrunmodejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/runmode.js (160499 => 160500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/runmode.js        2013-12-12 19:37:21 UTC (rev 160499)
+++ trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/runmode.js        2013-12-12 19:52:46 UTC (rev 160500)
</span><span class="lines">@@ -49,7 +49,7 @@
</span><span class="cx">     var stream = new CodeMirror.StringStream(lines[i]);
</span><span class="cx">     while (!stream.eol()) {
</span><span class="cx">       var style = mode.token(stream, state);
</span><del>-      callback(stream.current(), style, i, stream.start);
</del><ins>+      callback(stream.current(), style, i, stream.start, state);
</ins><span class="cx">       stream.start = stream.pos;
</span><span class="cx">     }
</span><span class="cx">   }
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceExternalCodeMirrorsearchcursorjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/searchcursor.js (160499 => 160500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/searchcursor.js        2013-12-12 19:37:21 UTC (rev 160499)
+++ trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/searchcursor.js        2013-12-12 19:52:46 UTC (rev 160500)
</span><span class="lines">@@ -69,8 +69,8 @@
</span><span class="cx">         this.matches = function(reverse, pos) {
</span><span class="cx">           var ln = pos.line, idx = (reverse ? target.length - 1 : 0), match = target[idx], line = fold(doc.getLine(ln));
</span><span class="cx">           var offsetA = (reverse ? line.indexOf(match) + match.length : line.lastIndexOf(match));
</span><del>-          if (reverse ? offsetA &gt;= pos.ch || offsetA != match.length
-              : offsetA &lt;= pos.ch || offsetA != line.length - match.length)
</del><ins>+          if (reverse ? offsetA &gt; pos.ch || offsetA != match.length
+              : offsetA &lt; pos.ch || offsetA != line.length - match.length)
</ins><span class="cx">             return;
</span><span class="cx">           for (;;) {
</span><span class="cx">             if (reverse ? !ln : ln == doc.lineCount() - 1) return;
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceExternalCodeMirrorsqljs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/sql.js (160499 => 160500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/sql.js        2013-12-12 19:37:21 UTC (rev 160499)
+++ trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/sql.js        2013-12-12 19:52:46 UTC (rev 160500)
</span><span class="lines">@@ -262,11 +262,24 @@
</span><span class="cx">     support: set(&quot;ODBCdotTable doubleQuote binaryNumber hexNumber&quot;)
</span><span class="cx">   });
</span><span class="cx"> 
</span><ins>+  CodeMirror.defineMIME(&quot;text/x-mssql&quot;, {
+    name: &quot;sql&quot;,
+    client: set(&quot;charset clear connect edit ego exit go help nopager notee nowarning pager print prompt quit rehash source status system tee&quot;),
+    keywords: set(sqlKeywords + &quot;begin trigger proc view index for add constraint key primary foreign collate clustered nonclustered&quot;),
+    builtin: set(&quot;bigint numeric bit smallint decimal smallmoney int tinyint money float real char varchar text nchar nvarchar ntext binary varbinary image cursor timestamp hierarchyid uniqueidentifier sql_variant xml table &quot;),
+    atoms: set(&quot;false true null unknown&quot;),
+    operatorChars: /^[*+\-%&lt;&gt;!=]/,
+    dateSQL: set(&quot;date datetimeoffset datetime2 smalldatetime datetime time&quot;),
+    hooks: {
+      &quot;@&quot;:   hookVar
+    }
+  });
+
</ins><span class="cx">   CodeMirror.defineMIME(&quot;text/x-mysql&quot;, {
</span><span class="cx">     name: &quot;sql&quot;,
</span><span class="cx">     client: set(&quot;charset clear connect edit ego exit go help nopager notee nowarning pager print prompt quit rehash source status system tee&quot;),
</span><del>-    keywords: set(sqlKeywords + &quot;accessible action add after algorithm all analyze asensitive at authors auto_increment autocommit avg avg_row_length before binary binlog both btree cache call cascade cascaded case catalog_name chain change changed character check checkpoint checksum class_origin client_statistics close coalesce code collate collation collations column columns comment commit committed completion concurrent condition connection consistent constraint contains continue contributors convert cross current_date current_time current_timestamp current_user cursor data database databases day_hour day_microsecond day_minute day_second deallocate dec declare default delay_key_write delayed delimiter des_key_file describe deterministic dev_pop dev_samp deviance directory disable discard distinctrow div dual dumpfile each elseif enable enclosed end ends engine engines enum errors escape escaped even event events every execute exists exit explain extended fast fetch field fields first flush for force foreign found_rows full fulltext function general global grant grants group groupby_concat handler hash help high_priority hosts hour_microsecond hour_minute hour_second if ignore ignore_server_ids import index index_statistics infile inner innodb inout insensitive insert_method install interval invoker isolation iterate key keys kill language last leading leave left level limit linear lines list load local localtime localtimestamp lock logs low_priority master master_heartbeat_period master_ssl_verify_server_cert masters match max max_rows maxvalue message_text middleint migrate min min_rows minute_microsecond minute_second mod mode modifies modify mutex mysql_errno natural next no no_write_to_binlog offline offset one online open optimize option optionally out outer outfile pack_keys parser partition partitions password phase plugin plugins prepare preserve prev primary privileges procedure processlist profile profiles purge query quick range read read_write reads real rebuild recover references regexp relaylog release remove rename reorganize repair repeatable replace require resignal restrict resume return returns revoke right rlike rollback rollup row row_format rtree savepoint schedule schema schema_name schemas second_microsecond security sensitive separator serializable server session share show signal slave slow smallint snapshot soname spatial specific sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_no_cache sql_small_result sqlexception sqlstate sqlwarning ssl start starting starts status std stddev stddev_pop stddev_samp storage straight_join subclass_origin sum suspend table_name table_statistics tables tablespace temporary terminated to trailing transaction trigger triggers truncate uncommitted undo uninstall unique unlock upgrade usage use use_frm user user_resources user_statistics using utc_date utc_time utc_timestamp value variables varying view views warnings when while with work write xa xor year_month zerofill begin do then else loop repeat&quot;),
-    builtin: set(&quot;bool boolean bit blob decimal double enum float long longblob longtext medium mediumblob mediumint mediumtext time timestamp tinyblob tinyint tinytext text bigint int int1 int2 int3 int4 int8 integer float float4 float8 double char varbinary varchar varcharacter precision date datetime year unsigned signed numeric&quot;),
</del><ins>+    keywords: set(sqlKeywords + &quot;accessible action add after algorithm all analyze asensitive at authors auto_increment autocommit avg avg_row_length before binary binlog both btree cache call cascade cascaded case catalog_name chain change changed character check checkpoint checksum class_origin client_statistics close coalesce code collate collation collations column columns comment commit committed completion concurrent condition connection consistent constraint contains continue contributors convert cross current current_date current_time current_timestamp current_user cursor data database databases day_hour day_microsecond day_minute day_second deallocate dec declare default delay_key_write delayed delimiter des_key_file describe deterministic dev_pop dev_samp deviance diagnostics directory disable discard distinctrow div dual dumpfile each elseif enable enclosed end ends engine engines enum errors escape escaped even event events every execute exists exit explain extended fast fetch field fields first flush for force foreign found_rows full fulltext function general get global grant grants group groupby_concat handler hash help high_priority hosts hour_microsecond hour_minute hour_second if ignore ignore_server_ids import index index_statistics infile inner innodb inout insensitive insert_method install interval invoker isolation iterate key keys kill language last leading leave left level limit linear lines list load local localtime localtimestamp lock logs low_priority master master_heartbeat_period master_ssl_verify_server_cert masters match max max_rows maxvalue message_text middleint migrate min min_rows minute_microsecond minute_second mod mode modifies modify mutex mysql_errno natural next no no_write_to_binlog offline offset one online open optimize option optionally out outer outfile pack_keys parser partition partitions password phase plugin plugins prepare preserve prev primary privileges procedure processlist profile profiles purge query quick range read read_write reads real rebuild recover references regexp relaylog release remove rename reorganize repair repeatable replace require resignal restrict resume return returns revoke right rlike rollback rollup row row_format rtree savepoint schedule schema schema_name schemas second_microsecond security sensitive separator serializable server session share show signal slave slow smallint snapshot soname spatial specific sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_no_cache sql_small_result sqlexception sqlstate sqlwarning ssl start starting starts status std stddev stddev_pop stddev_samp storage straight_join subclass_origin sum suspend table_name table_statistics tables tablespace temporary terminated to trailing transaction trigger triggers truncate uncommitted undo uninstall unique unlock upgrade usage use use_frm user user_resources user_statistics using utc_date utc_time utc_timestamp value variables varying view views warnings when while with work write xa xor year_month zerofill begin do then else loop repeat&quot;),
+    builtin: set(&quot;bool boolean bit blob decimal double float long longblob longtext medium mediumblob mediumint mediumtext time timestamp tinyblob tinyint tinytext text bigint int int1 int2 int3 int4 int8 integer float float4 float8 double char varbinary varchar varcharacter precision date datetime year unsigned signed numeric&quot;),
</ins><span class="cx">     atoms: set(&quot;false true null unknown&quot;),
</span><span class="cx">     operatorChars: /^[*+\-%&lt;&gt;!=&amp;|^]/,
</span><span class="cx">     dateSQL: set(&quot;date time timestamp&quot;),
</span><span class="lines">@@ -281,8 +294,8 @@
</span><span class="cx">   CodeMirror.defineMIME(&quot;text/x-mariadb&quot;, {
</span><span class="cx">     name: &quot;sql&quot;,
</span><span class="cx">     client: set(&quot;charset clear connect edit ego exit go help nopager notee nowarning pager print prompt quit rehash source status system tee&quot;),
</span><del>-    keywords: set(sqlKeywords + &quot;accessible action add after algorithm all always analyze asensitive at authors auto_increment autocommit avg avg_row_length before binary binlog both btree cache call cascade cascaded case catalog_name chain change changed character check checkpoint checksum class_origin client_statistics close coalesce code collate collation collations column columns comment commit committed completion concurrent condition connection consistent constraint contains continue contributors convert cross current_date current_time current_timestamp current_user cursor data database databases day_hour day_microsecond day_minute day_second deallocate dec declare default delay_key_write delayed delimiter des_key_file describe deterministic dev_pop dev_samp deviance directory disable discard distinctrow div dual dumpfile each elseif enable enclosed end ends engine engines enum errors escape escaped even event events every execute exists exit explain extended fast fetch field fields first flush for force foreign found_rows full fulltext function general generated global grant grants group groupby_concat handler hard hash help high_priority hosts hour_microsecond hour_minute hour_second if ignore ignore_server_ids import index index_statistics infile inner innodb inout insensitive insert_method install interval invoker isolation iterate key keys kill language last leading leave left level limit linear lines list load local localtime localtimestamp lock logs low_priority master master_heartbeat_period master_ssl_verify_server_cert masters match max max_rows maxvalue message_text middleint migrate min min_rows minute_microsecond minute_second mod mode modifies modify mutex mysql_errno natural next no no_write_to_binlog offline offset one online open optimize option optionally out outer outfile pack_keys parser partition partitions password persistent phase plugin plugins prepare preserve prev primary privileges procedure processlist profile profiles purge query quick range read read_write reads real rebuild recover references regexp relaylog release remove rename reorganize repair repeatable replace require resignal restrict resume return returns revoke right rlike rollback rollup row row_format rtree savepoint schedule schema schema_name schemas second_microsecond security sensitive separator serializable server session share show signal slave slow smallint snapshot soft soname spatial specific sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_no_cache sql_small_result sqlexception sqlstate sqlwarning ssl start starting starts status std stddev stddev_pop stddev_samp storage straight_join subclass_origin sum suspend table_name table_statistics tables tablespace temporary terminated to trailing transaction trigger triggers truncate uncommitted undo uninstall unique unlock upgrade usage use use_frm user user_resources user_statistics using utc_date utc_time utc_timestamp value variables varying view views virtual warnings when while with work write xa xor year_month zerofill begin do then else loop repeat&quot;),
-    builtin: set(&quot;bool boolean bit blob decimal double enum float long longblob longtext medium mediumblob mediumint mediumtext time timestamp tinyblob tinyint tinytext text bigint int int1 int2 int3 int4 int8 integer float float4 float8 double char varbinary varchar varcharacter precision date datetime year unsigned signed numeric&quot;),
</del><ins>+    keywords: set(sqlKeywords + &quot;accessible action add after algorithm all always analyze asensitive at authors auto_increment autocommit avg avg_row_length before binary binlog both btree cache call cascade cascaded case catalog_name chain change changed character check checkpoint checksum class_origin client_statistics close coalesce code collate collation collations column columns comment commit committed completion concurrent condition connection consistent constraint contains continue contributors convert cross current current_date current_time current_timestamp current_user cursor data database databases day_hour day_microsecond day_minute day_second deallocate dec declare default delay_key_write delayed delimiter des_key_file describe deterministic dev_pop dev_samp deviance diagnostics directory disable discard distinctrow div dual dumpfile each elseif enable enclosed end ends engine engines enum errors escape escaped even event events every execute exists exit explain extended fast fetch field fields first flush for force foreign found_rows full fulltext function general generated get global grant grants group groupby_concat handler hard hash help high_priority hosts hour_microsecond hour_minute hour_second if ignore ignore_server_ids import index index_statistics infile inner innodb inout insensitive insert_method install interval invoker isolation iterate key keys kill language last leading leave left level limit linear lines list load local localtime localtimestamp lock logs low_priority master master_heartbeat_period master_ssl_verify_server_cert masters match max max_rows maxvalue message_text middleint migrate min min_rows minute_microsecond minute_second mod mode modifies modify mutex mysql_errno natural next no no_write_to_binlog offline offset one online open optimize option optionally out outer outfile pack_keys parser partition partitions password persistent phase plugin plugins prepare preserve prev primary privileges procedure processlist profile profiles purge query quick range read read_write reads real rebuild recover references regexp relaylog release remove rename reorganize repair repeatable replace require resignal restrict resume return returns revoke right rlike rollback rollup row row_format rtree savepoint schedule schema schema_name schemas second_microsecond security sensitive separator serializable server session share show shutdown signal slave slow smallint snapshot soft soname spatial specific sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_no_cache sql_small_result sqlexception sqlstate sqlwarning ssl start starting starts status std stddev stddev_pop stddev_samp storage straight_join subclass_origin sum suspend table_name table_statistics tables tablespace temporary terminated to trailing transaction trigger triggers truncate uncommitted undo uninstall unique unlock upgrade usage use use_frm user user_resources user_statistics using utc_date utc_time utc_timestamp value variables varying view views virtual warnings when while with work write xa xor year_month zerofill begin do then else loop repeat&quot;),
+    builtin: set(&quot;bool boolean bit blob decimal double float long longblob longtext medium mediumblob mediumint mediumtext time timestamp tinyblob tinyint tinytext text bigint int int1 int2 int3 int4 int8 integer float float4 float8 double char varbinary varchar varcharacter precision date datetime year unsigned signed numeric&quot;),
</ins><span class="cx">     atoms: set(&quot;false true null unknown&quot;),
</span><span class="cx">     operatorChars: /^[*+\-%&lt;&gt;!=&amp;|^]/,
</span><span class="cx">     dateSQL: set(&quot;date time timestamp&quot;),
</span><span class="lines">@@ -313,8 +326,7 @@
</span><span class="cx">     name:       &quot;sql&quot;,
</span><span class="cx">     client:     set(&quot;appinfo arraysize autocommit autoprint autorecovery autotrace blockterminator break btitle cmdsep colsep compatibility compute concat copycommit copytypecheck define describe echo editfile embedded escape exec execute feedback flagger flush heading headsep instance linesize lno loboffset logsource long longchunksize markup native newpage numformat numwidth pagesize pause pno recsep recsepchar release repfooter repheader serveroutput shiftinout show showmode size spool sqlblanklines sqlcase sqlcode sqlcontinue sqlnumber sqlpluscompatibility sqlprefix sqlprompt sqlterminator suffix tab term termout time timing trimout trimspool ttitle underline verify version wrap&quot;),
</span><span class="cx">     keywords:   set(&quot;abort accept access add all alter and any array arraylen as asc assert assign at attributes audit authorization avg base_table begin between binary_integer body boolean by case cast char char_base check close cluster clusters colauth column comment commit compress connect connected constant constraint crash create current currval cursor data_base database date dba deallocate debugoff debugon decimal declare default definition delay delete desc digits dispose distinct do drop else elsif enable end entry escape exception exception_init exchange exclusive exists exit external fast fetch file for force form from function generic goto grant group having identified if immediate in increment index indexes indicator initial initrans insert interface intersect into is key level library like limited local lock log logging long loop master maxextents maxtrans member minextents minus mislabel mode modify multiset new next no noaudit nocompress nologging noparallel not nowait number_base object of off offline on online only open option or order out package parallel partition pctfree pctincrease pctused pls_integer positive positiven pragma primary prior private privileges procedure public raise range raw read rebuild record ref references refresh release rename replace resource restrict return returning reverse revoke rollback row rowid rowlabel rownum rows run savepoint schema segment select separate session set share snapshot some space split sql start statement storage subtype successful synonym tabauth table tables tablespace task terminate then to trigger truncate type union unique unlimited unrecoverable unusable update use using validate value values variable view views when whenever where while with work&quot;),
</span><del>-    functions:  set(&quot;abs acos add_months ascii asin atan atan2 average bfilename ceil chartorowid chr concat convert cos cosh count decode deref dual dump dup_val_on_index empty error exp false floor found glb greatest hextoraw initcap instr instrb isopen last_day least lenght lenghtb ln lower lpad ltrim lub make_ref max min mod months_between new_time next_day nextval nls_charset_decl_len nls_charset_id nls_charset_name nls_initcap nls_lower nls_sort nls_upper nlssort no_data_found notfound null nvl others power rawtohex reftohex round rowcount rowidtochar rpad rtrim sign sin sinh soundex sqlcode sqlerrm sqrt stddev substr substrb sum sysdate tan tanh to_char to_date to_label to_multi_byte to_number to_single_byte translate true trunc uid upper user userenv variance vsize&quot;),
-    builtin:    set(&quot;bfile blob character clob dec float int integer mlslabel natural naturaln nchar nclob number numeric nvarchar2 real rowtype signtype smallint string varchar varchar2&quot;),
</del><ins>+    builtin:    set(&quot;bfile blob character clob dec float int integer mlslabel natural naturaln nchar nclob number numeric nvarchar2 real rowtype signtype smallint string varchar varchar2 abs acos add_months ascii asin atan atan2 average bfilename ceil chartorowid chr concat convert cos cosh count decode deref dual dump dup_val_on_index empty error exp false floor found glb greatest hextoraw initcap instr instrb isopen last_day least lenght lenghtb ln lower lpad ltrim lub make_ref max min mod months_between new_time next_day nextval nls_charset_decl_len nls_charset_id nls_charset_name nls_initcap nls_lower nls_sort nls_upper nlssort no_data_found notfound null nvl others power rawtohex reftohex round rowcount rowidtochar rpad rtrim sign sin sinh soundex sqlcode sqlerrm sqrt stddev substr substrb sum sysdate tan tanh to_char to_date to_label to_multi_byte to_number to_single_byte translate true trunc uid upper user userenv variance vsize&quot;),
</ins><span class="cx">     operatorChars: /^[*+\-%&lt;&gt;!=~]/,
</span><span class="cx">     dateSQL:    set(&quot;date time timestamp&quot;),
</span><span class="cx">     support:    set(&quot;doubleQuote nCharCast zerolessFloat binaryNumber hexNumber&quot;)
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceExternalCodeMirrorxmljs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/xml.js (160499 => 160500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/xml.js        2013-12-12 19:37:21 UTC (rev 160499)
+++ trunk/Source/WebInspectorUI/UserInterface/External/CodeMirror/xml.js        2013-12-12 19:52:46 UTC (rev 160500)
</span><span class="lines">@@ -76,7 +76,7 @@
</span><span class="cx">         tagName = &quot;&quot;;
</span><span class="cx">         var c;
</span><span class="cx">         while ((c = stream.eat(/[^\s\u00a0=&lt;&gt;\&quot;\'\/?]/))) tagName += c;
</span><del>-        if (!tagName) return &quot;error&quot;;
</del><ins>+        if (!tagName) return &quot;tag error&quot;;
</ins><span class="cx">         type = isClose ? &quot;closeTag&quot; : &quot;openTag&quot;;
</span><span class="cx">         state.tokenize = inTag;
</span><span class="cx">         return &quot;tag&quot;;
</span><span class="lines">@@ -109,7 +109,9 @@
</span><span class="cx">       type = &quot;equals&quot;;
</span><span class="cx">       return null;
</span><span class="cx">     } else if (ch == &quot;&lt;&quot;) {
</span><del>-      return &quot;error&quot;;
</del><ins>+      state.tokenize = inText;
+      var next = state.tokenize(stream, state);
+      return next ? next + &quot; error&quot; : &quot;error&quot;;
</ins><span class="cx">     } else if (/[\'\&quot;]/.test(ch)) {
</span><span class="cx">       state.tokenize = inAttribute(ch);
</span><span class="cx">       state.stringStartCol = stream.column();
</span><span class="lines">@@ -298,7 +300,9 @@
</span><span class="cx">         }
</span><span class="cx">       }
</span><span class="cx">       state.startOfLine = false;
</span><del>-      return setStyle || style;
</del><ins>+      if (setStyle)
+        style = setStyle == &quot;error&quot; ? style + &quot; error&quot; : setStyle;
+      return style;
</ins><span class="cx">     },
</span><span class="cx"> 
</span><span class="cx">     indent: function(state, textAfter, fullLine) {
</span></span></pre>
</div>
</div>

</body>
</html>