Bug 1447659 - Update Codemirror to 5.36.0. r=bgrins draft
authorGabriel Luong <gabriel.luong@gmail.com>
Thu, 22 Mar 2018 15:05:17 -0400
changeset 771220 5e0efd7a2a795db0b9edcc55a9cf67d5eb1e011d
parent 771219 bdf1b3096b346d457ddea59c1ff7ff2babaefc99
push id103613
push userbmo:gl@mozilla.com
push dateThu, 22 Mar 2018 19:05:50 +0000
reviewersbgrins
bugs1447659
milestone61.0a1
Bug 1447659 - Update Codemirror to 5.36.0. r=bgrins MozReview-Commit-ID: EGYvA4maUjv
devtools/client/sourceeditor/README
devtools/client/sourceeditor/codemirror/addon/edit/continuelist.js
devtools/client/sourceeditor/codemirror/addon/hint/show-hint.js
devtools/client/sourceeditor/codemirror/codemirror.bundle.js
devtools/client/sourceeditor/codemirror/lib/codemirror.js
devtools/client/sourceeditor/codemirror/mode/javascript/javascript.js
--- a/devtools/client/sourceeditor/README
+++ b/devtools/client/sourceeditor/README
@@ -1,16 +1,16 @@
 This is the CodeMirror editor packaged for the Mozilla Project. CodeMirror
 is a JavaScript component that provides a code editor in the browser. When
 a mode is available for the language you are coding in, it will color your
 code, and optionally help with indentation.
 
 # Upgrade
 
-Currently used version is 5.35.0. To upgrade: download a new version of
+Currently used version is 5.36.0. To upgrade: download a new version of
 CodeMirror from the project's page [1] and replace all JavaScript and
 CSS files inside the codemirror directory [2].
 
 Then to recreate codemirror.bundle.js:
  > cd devtools/client/sourceeditor
  > npm install
  > webpack
 
@@ -107,33 +107,33 @@ diff --git a/devtools/client/sourceedito
 @@ -181,56 +196,110 @@
      var state = getSearchState(cm);
      state.lastQuery = state.query;
      if (!state.query) return;
      state.query = state.queryText = null;
      cm.removeOverlay(state.overlay);
      if (state.annotate) { state.annotate.clear(); state.annotate = null; }
    });}
- 
+
 -  var replaceQueryDialog =
 -    ' <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">(Use /re/ syntax for regexp search)</span>';
 -  var replacementQueryDialog = '<span class="CodeMirror-search-label">With:</span> <input type="text" style="width: 10em" class="CodeMirror-search-field"/>';
 -  var doReplaceConfirm = '<span class="CodeMirror-search-label">Replace?</span> <button>Yes</button> <button>No</button> <button>All</button> <button>Stop</button>';
 -
    function replaceAll(cm, query, text) {
      cm.operation(function() {
        for (var cursor = getSearchCursor(cm, query); cursor.findNext();) {
          if (typeof query != "string") {
            var match = cm.getRange(cursor.from(), cursor.to()).match(query);
            cursor.replace(text.replace(/\$(\d)/g, function(_, i) {return match[i];}));
          } else cursor.replace(text);
        }
      });
    }
- 
+
    function replace(cm, all) {
      if (cm.getOption("readOnly")) return;
      var query = cm.getSelection() || getSearchState(cm).lastQuery;
 -    var dialogText = '<span class="CodeMirror-search-label">' + (all ? 'Replace all:' : 'Replace:') + '</span>';
 -    dialog(cm, dialogText + replaceQueryDialog, dialogText, query, function(query) {
 +
 +    let doc = cm.getWrapperElement().ownerDocument;
 +
--- a/devtools/client/sourceeditor/codemirror/addon/edit/continuelist.js
+++ b/devtools/client/sourceeditor/codemirror/addon/edit/continuelist.js
@@ -61,17 +61,17 @@
       var nextLineNumber = startLine + lookAhead;
       var nextLine = cm.getLine(nextLineNumber), nextItem = listRE.exec(nextLine);
 
       if (nextItem) {
         var nextIndent = nextItem[1];
         var newNumber = (parseInt(startItem[3], 10) + lookAhead - skipCount);
         var nextNumber = (parseInt(nextItem[3], 10)), itemNumber = nextNumber;
 
-        if (startIndent === nextIndent) {
+        if (startIndent === nextIndent && !isNaN(nextNumber)) {
           if (newNumber === nextNumber) itemNumber = nextNumber + 1;
           if (newNumber > nextNumber) itemNumber = newNumber + 1;
           cm.replaceRange(
             nextLine.replace(listRE, nextIndent + itemNumber + nextItem[4] + nextItem[5]),
           {
             line: nextLineNumber, ch: 0
           }, {
             line: nextLineNumber, ch: nextLine.length
--- a/devtools/client/sourceeditor/codemirror/addon/hint/show-hint.js
+++ b/devtools/client/sourceeditor/codemirror/addon/hint/show-hint.js
@@ -392,22 +392,23 @@
     }
   }
 
   CodeMirror.registerHelper("hint", "auto", {
     resolve: resolveAutoHints
   });
 
   CodeMirror.registerHelper("hint", "fromList", function(cm, options) {
-    var cur = cm.getCursor(), token = cm.getTokenAt(cur);
-    var to = CodeMirror.Pos(cur.line, token.end);
-    if (token.string && /\w/.test(token.string[token.string.length - 1])) {
-      var term = token.string, from = CodeMirror.Pos(cur.line, token.start);
+    var cur = cm.getCursor(), token = cm.getTokenAt(cur)
+    var term, from = CodeMirror.Pos(cur.line, token.start), to = cur
+    if (token.start < cur.ch && /\w/.test(token.string.charAt(cur.ch - token.start - 1))) {
+      term = token.string.substr(0, cur.ch - token.start)
     } else {
-      var term = "", from = to;
+      term = ""
+      from = cur
     }
     var found = [];
     for (var i = 0; i < options.words.length; i++) {
       var word = options.words[i];
       if (word.slice(0, term.length) == term)
         found.push(word);
     }
 
--- a/devtools/client/sourceeditor/codemirror/codemirror.bundle.js
+++ b/devtools/client/sourceeditor/codemirror/codemirror.bundle.js
@@ -5020,17 +5020,17 @@ var CodeMirror =
 	function addChangeToHistory(doc, change, selAfter, opId) {
 	  var hist = doc.history
 	  hist.undone.length = 0
 	  var time = +new Date, cur
 	  var last
 
 	  if ((hist.lastOp == opId ||
 	       hist.lastOrigin == change.origin && change.origin &&
-	       ((change.origin.charAt(0) == "+" && doc.cm && hist.lastModTime > time - doc.cm.options.historyEventDelay) ||
+	       ((change.origin.charAt(0) == "+" && hist.lastModTime > time - (doc.cm ? doc.cm.options.historyEventDelay : 500)) ||
 	        change.origin.charAt(0) == "*")) &&
 	      (cur = lastChangeEvent(hist, hist.lastOp == opId))) {
 	    // Merge this change into the last event
 	    last = lst(cur.changes)
 	    if (cmp(change.from, change.to) == 0 && cmp(change.from, last.to) == 0) {
 	      // Optimized case for simple insertion -- don't want to add
 	      // new changesets for every character typed
 	      last.to = changeEnd(change)
@@ -7549,43 +7549,43 @@ var CodeMirror =
 
 	// Start a text drag. When it ends, see if any dragging actually
 	// happen, and treat as a click if it didn't.
 	function leftButtonStartDrag(cm, event, pos, behavior) {
 	  var display = cm.display, moved = false
 	  var dragEnd = operation(cm, function (e) {
 	    if (webkit) { display.scroller.draggable = false }
 	    cm.state.draggingText = false
-	    off(document, "mouseup", dragEnd)
-	    off(document, "mousemove", mouseMove)
+	    off(display.wrapper.ownerDocument, "mouseup", dragEnd)
+	    off(display.wrapper.ownerDocument, "mousemove", mouseMove)
 	    off(display.scroller, "dragstart", dragStart)
 	    off(display.scroller, "drop", dragEnd)
 	    if (!moved) {
 	      e_preventDefault(e)
 	      if (!behavior.addNew)
 	        { extendSelection(cm.doc, pos, null, null, behavior.extend) }
 	      // Work around unexplainable focus problem in IE9 (#2127) and Chrome (#3081)
 	      if (webkit || ie && ie_version == 9)
-	        { setTimeout(function () {document.body.focus(); display.input.focus()}, 20) }
+	        { setTimeout(function () {display.wrapper.ownerDocument.body.focus(); display.input.focus()}, 20) }
 	      else
 	        { display.input.focus() }
 	    }
 	  })
 	  var mouseMove = function(e2) {
 	    moved = moved || Math.abs(event.clientX - e2.clientX) + Math.abs(event.clientY - e2.clientY) >= 10
 	  }
 	  var dragStart = function () { return moved = true; }
 	  // Let the drag handler handle this.
 	  if (webkit) { display.scroller.draggable = true }
 	  cm.state.draggingText = dragEnd
 	  dragEnd.copy = !behavior.moveOnDrag
 	  // IE's approach to draggable
 	  if (display.scroller.dragDrop) { display.scroller.dragDrop() }
-	  on(document, "mouseup", dragEnd)
-	  on(document, "mousemove", mouseMove)
+	  on(display.wrapper.ownerDocument, "mouseup", dragEnd)
+	  on(display.wrapper.ownerDocument, "mousemove", mouseMove)
 	  on(display.scroller, "dragstart", dragStart)
 	  on(display.scroller, "drop", dragEnd)
 
 	  delayBlurEvent(cm)
 	  setTimeout(function () { return display.input.focus(); }, 20)
 	}
 
 	function rangeForUnit(cm, pos, unit) {
@@ -7707,29 +7707,29 @@ var CodeMirror =
 	    }
 	  }
 
 	  function done(e) {
 	    cm.state.selectingText = false
 	    counter = Infinity
 	    e_preventDefault(e)
 	    display.input.focus()
-	    off(document, "mousemove", move)
-	    off(document, "mouseup", up)
+	    off(display.wrapper.ownerDocument, "mousemove", move)
+	    off(display.wrapper.ownerDocument, "mouseup", up)
 	    doc.history.lastSelOrigin = null
 	  }
 
 	  var move = operation(cm, function (e) {
 	    if (!e_button(e)) { done(e) }
 	    else { extend(e) }
 	  })
 	  var up = operation(cm, done)
 	  cm.state.selectingText = up
-	  on(document, "mousemove", move)
-	  on(document, "mouseup", up)
+	  on(display.wrapper.ownerDocument, "mousemove", move)
+	  on(display.wrapper.ownerDocument, "mouseup", up)
 	}
 
 	// Used when mouse-selecting to adjust the anchor to the proper side
 	// of a bidi jump depending on the visual position of the head.
 	function bidiSimplify(cm, range) {
 	  var anchor = range.anchor;
 	  var head = range.head;
 	  var anchorLine = getLine(cm.doc, anchor.line)
@@ -9424,23 +9424,20 @@ var CodeMirror =
 	  this.hasSelection = false
 	  this.composing = null
 	};
 
 	TextareaInput.prototype.init = function (display) {
 	    var this$1 = this;
 
 	  var input = this, cm = this.cm
-
-	  // Wraps and hides input textarea
-	  var div = this.wrapper = hiddenTextarea()
-	  // The semihidden textarea that is focused when the editor is
-	  // focused, and receives input.
-	  var te = this.textarea = div.firstChild
-	  display.wrapper.insertBefore(div, display.wrapper.firstChild)
+	  this.createField(display)
+	  var te = this.textarea
+
+	  display.wrapper.insertBefore(this.wrapper, display.wrapper.firstChild)
 
 	  // Needed to hide big blue blinking cursor on Mobile Safari (doesn't seem to work in iOS 8 anymore)
 	  if (ios) { te.style.width = "0px" }
 
 	  on(te, "input", function () {
 	    if (ie && ie_version >= 9 && this$1.hasSelection) { this$1.hasSelection = null }
 	    input.poll()
 	  })
@@ -9497,16 +9494,24 @@ var CodeMirror =
 	    if (input.composing) {
 	      input.poll()
 	      input.composing.range.clear()
 	      input.composing = null
 	    }
 	  })
 	};
 
+	TextareaInput.prototype.createField = function (_display) {
+	  // Wraps and hides input textarea
+	  this.wrapper = hiddenTextarea()
+	  // The semihidden textarea that is focused when the editor is
+	  // focused, and receives input.
+	  this.textarea = this.wrapper.firstChild
+	};
+
 	TextareaInput.prototype.prepareSelection = function () {
 	  // Redraw the selection and/or cursor
 	  var cm = this.cm, display = cm.display, doc = cm.doc
 	  var result = prepareSelection(cm)
 
 	  // Move the hidden textarea near the cursor to prevent scrolling artifacts
 	  if (cm.options.moveInputWithCursor) {
 	    var headPos = cursorCoords(cm, doc.sel.primary().head, "div")
@@ -9890,17 +9895,17 @@ var CodeMirror =
 	CodeMirror.defineDocExtension = function (name, func) {
 	  Doc.prototype[name] = func
 	}
 
 	CodeMirror.fromTextArea = fromTextArea
 
 	addLegacyProps(CodeMirror)
 
-	CodeMirror.version = "5.35.0"
+	CodeMirror.version = "5.36.0"
 
 	return CodeMirror;
 
 	})));
 
 /***/ }),
 /* 3 */
 /***/ (function(module, exports, __webpack_require__) {
@@ -11654,24 +11659,23 @@ var CodeMirror =
 	  }
 	  function isKW(_, value) {
 	    if (value == "is") {
 	      cx.marked = "keyword"
 	      return cont()
 	    }
 	  }
 	  function typeexpr(type, value) {
+	    if (value == "keyof" || value == "typeof") {
+	      cx.marked = "keyword"
+	      return cont(value == "keyof" ? typeexpr : expression)
+	    }
 	    if (type == "variable" || value == "void") {
-	      if (value == "keyof") {
-	        cx.marked = "keyword"
-	        return cont(typeexpr)
-	      } else {
-	        cx.marked = "type"
-	        return cont(afterType)
-	      }
+	      cx.marked = "type"
+	      return cont(afterType)
 	    }
 	    if (type == "string" || type == "number" || type == "atom") return cont(afterType);
 	    if (type == "[") return cont(pushlex("]"), commasep(typeexpr, "]", ","), poplex, afterType)
 	    if (type == "{") return cont(pushlex("}"), commasep(typeprop, "}", ",;"), poplex, afterType)
 	    if (type == "(") return cont(commasep(typearg, ")"), maybeReturnType)
 	  }
 	  function maybeReturnType(type) {
 	    if (type == "=>") return cont(typeexpr)
--- a/devtools/client/sourceeditor/codemirror/lib/codemirror.js
+++ b/devtools/client/sourceeditor/codemirror/lib/codemirror.js
@@ -4778,17 +4778,17 @@ function lastChangeEvent(hist, force) {
 function addChangeToHistory(doc, change, selAfter, opId) {
   var hist = doc.history
   hist.undone.length = 0
   var time = +new Date, cur
   var last
 
   if ((hist.lastOp == opId ||
        hist.lastOrigin == change.origin && change.origin &&
-       ((change.origin.charAt(0) == "+" && doc.cm && hist.lastModTime > time - doc.cm.options.historyEventDelay) ||
+       ((change.origin.charAt(0) == "+" && hist.lastModTime > time - (doc.cm ? doc.cm.options.historyEventDelay : 500)) ||
         change.origin.charAt(0) == "*")) &&
       (cur = lastChangeEvent(hist, hist.lastOp == opId))) {
     // Merge this change into the last event
     last = lst(cur.changes)
     if (cmp(change.from, change.to) == 0 && cmp(change.from, last.to) == 0) {
       // Optimized case for simple insertion -- don't want to add
       // new changesets for every character typed
       last.to = changeEnd(change)
@@ -7307,43 +7307,43 @@ function leftButtonDown(cm, pos, repeat,
 
 // Start a text drag. When it ends, see if any dragging actually
 // happen, and treat as a click if it didn't.
 function leftButtonStartDrag(cm, event, pos, behavior) {
   var display = cm.display, moved = false
   var dragEnd = operation(cm, function (e) {
     if (webkit) { display.scroller.draggable = false }
     cm.state.draggingText = false
-    off(document, "mouseup", dragEnd)
-    off(document, "mousemove", mouseMove)
+    off(display.wrapper.ownerDocument, "mouseup", dragEnd)
+    off(display.wrapper.ownerDocument, "mousemove", mouseMove)
     off(display.scroller, "dragstart", dragStart)
     off(display.scroller, "drop", dragEnd)
     if (!moved) {
       e_preventDefault(e)
       if (!behavior.addNew)
         { extendSelection(cm.doc, pos, null, null, behavior.extend) }
       // Work around unexplainable focus problem in IE9 (#2127) and Chrome (#3081)
       if (webkit || ie && ie_version == 9)
-        { setTimeout(function () {document.body.focus(); display.input.focus()}, 20) }
+        { setTimeout(function () {display.wrapper.ownerDocument.body.focus(); display.input.focus()}, 20) }
       else
         { display.input.focus() }
     }
   })
   var mouseMove = function(e2) {
     moved = moved || Math.abs(event.clientX - e2.clientX) + Math.abs(event.clientY - e2.clientY) >= 10
   }
   var dragStart = function () { return moved = true; }
   // Let the drag handler handle this.
   if (webkit) { display.scroller.draggable = true }
   cm.state.draggingText = dragEnd
   dragEnd.copy = !behavior.moveOnDrag
   // IE's approach to draggable
   if (display.scroller.dragDrop) { display.scroller.dragDrop() }
-  on(document, "mouseup", dragEnd)
-  on(document, "mousemove", mouseMove)
+  on(display.wrapper.ownerDocument, "mouseup", dragEnd)
+  on(display.wrapper.ownerDocument, "mousemove", mouseMove)
   on(display.scroller, "dragstart", dragStart)
   on(display.scroller, "drop", dragEnd)
 
   delayBlurEvent(cm)
   setTimeout(function () { return display.input.focus(); }, 20)
 }
 
 function rangeForUnit(cm, pos, unit) {
@@ -7465,29 +7465,29 @@ function leftButtonSelect(cm, event, sta
     }
   }
 
   function done(e) {
     cm.state.selectingText = false
     counter = Infinity
     e_preventDefault(e)
     display.input.focus()
-    off(document, "mousemove", move)
-    off(document, "mouseup", up)
+    off(display.wrapper.ownerDocument, "mousemove", move)
+    off(display.wrapper.ownerDocument, "mouseup", up)
     doc.history.lastSelOrigin = null
   }
 
   var move = operation(cm, function (e) {
     if (!e_button(e)) { done(e) }
     else { extend(e) }
   })
   var up = operation(cm, done)
   cm.state.selectingText = up
-  on(document, "mousemove", move)
-  on(document, "mouseup", up)
+  on(display.wrapper.ownerDocument, "mousemove", move)
+  on(display.wrapper.ownerDocument, "mouseup", up)
 }
 
 // Used when mouse-selecting to adjust the anchor to the proper side
 // of a bidi jump depending on the visual position of the head.
 function bidiSimplify(cm, range) {
   var anchor = range.anchor;
   var head = range.head;
   var anchorLine = getLine(cm.doc, anchor.line)
@@ -9182,23 +9182,20 @@ var TextareaInput = function(cm) {
   this.hasSelection = false
   this.composing = null
 };
 
 TextareaInput.prototype.init = function (display) {
     var this$1 = this;
 
   var input = this, cm = this.cm
-
-  // Wraps and hides input textarea
-  var div = this.wrapper = hiddenTextarea()
-  // The semihidden textarea that is focused when the editor is
-  // focused, and receives input.
-  var te = this.textarea = div.firstChild
-  display.wrapper.insertBefore(div, display.wrapper.firstChild)
+  this.createField(display)
+  var te = this.textarea
+
+  display.wrapper.insertBefore(this.wrapper, display.wrapper.firstChild)
 
   // Needed to hide big blue blinking cursor on Mobile Safari (doesn't seem to work in iOS 8 anymore)
   if (ios) { te.style.width = "0px" }
 
   on(te, "input", function () {
     if (ie && ie_version >= 9 && this$1.hasSelection) { this$1.hasSelection = null }
     input.poll()
   })
@@ -9255,16 +9252,24 @@ TextareaInput.prototype.init = function 
     if (input.composing) {
       input.poll()
       input.composing.range.clear()
       input.composing = null
     }
   })
 };
 
+TextareaInput.prototype.createField = function (_display) {
+  // Wraps and hides input textarea
+  this.wrapper = hiddenTextarea()
+  // The semihidden textarea that is focused when the editor is
+  // focused, and receives input.
+  this.textarea = this.wrapper.firstChild
+};
+
 TextareaInput.prototype.prepareSelection = function () {
   // Redraw the selection and/or cursor
   var cm = this.cm, display = cm.display, doc = cm.doc
   var result = prepareSelection(cm)
 
   // Move the hidden textarea near the cursor to prevent scrolling artifacts
   if (cm.options.moveInputWithCursor) {
     var headPos = cursorCoords(cm, doc.sel.primary().head, "div")
@@ -9648,13 +9653,13 @@ CodeMirror.defineExtension = function (n
 CodeMirror.defineDocExtension = function (name, func) {
   Doc.prototype[name] = func
 }
 
 CodeMirror.fromTextArea = fromTextArea
 
 addLegacyProps(CodeMirror)
 
-CodeMirror.version = "5.35.0"
+CodeMirror.version = "5.36.0"
 
 return CodeMirror;
 
 })));
\ No newline at end of file
--- a/devtools/client/sourceeditor/codemirror/mode/javascript/javascript.js
+++ b/devtools/client/sourceeditor/codemirror/mode/javascript/javascript.js
@@ -555,24 +555,23 @@ CodeMirror.defineMode("javascript", func
   }
   function isKW(_, value) {
     if (value == "is") {
       cx.marked = "keyword"
       return cont()
     }
   }
   function typeexpr(type, value) {
+    if (value == "keyof" || value == "typeof") {
+      cx.marked = "keyword"
+      return cont(value == "keyof" ? typeexpr : expression)
+    }
     if (type == "variable" || value == "void") {
-      if (value == "keyof") {
-        cx.marked = "keyword"
-        return cont(typeexpr)
-      } else {
-        cx.marked = "type"
-        return cont(afterType)
-      }
+      cx.marked = "type"
+      return cont(afterType)
     }
     if (type == "string" || type == "number" || type == "atom") return cont(afterType);
     if (type == "[") return cont(pushlex("]"), commasep(typeexpr, "]", ","), poplex, afterType)
     if (type == "{") return cont(pushlex("}"), commasep(typeprop, "}", ",;"), poplex, afterType)
     if (type == "(") return cont(commasep(typearg, ")"), maybeReturnType)
   }
   function maybeReturnType(type) {
     if (type == "=>") return cont(typeexpr)