Merge fx-team to m-c to please philor.
authorKyle Huey <khuey@kylehuey.com>
Mon, 09 Apr 2012 14:51:54 -0700
changeset 94546 434f50e708151ef17748bdba3600b617f828c8cb
parent 94540 52ee2124247dc70a1384ab371256945da994f395 (current diff)
parent 94545 c0946061c57f8b46123880df73afd7e82602f473 (diff)
child 94547 7702bca6b64d7e71e9eede8c139ef51929468688
child 94585 9095ac6a0f0196eac8dc877f977797e6ae36b73a
child 98065 276c1d451f64a597de3ed6bca54de4a28c6cf70d
child 112403 46bdb70a63b945d1afdf228b33816da0b2946db7
push id886
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 19:57:52 +0000
treeherdermozilla-beta@bbd8d5efd6d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone14.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge fx-team to m-c to please philor.
--- a/browser/base/content/newtab/sites.js
+++ b/browser/base/content/newtab/sites.js
@@ -78,20 +78,17 @@ Site.prototype = {
     return gPinnedLinks.isPinned(this._link);
   },
 
   /**
    * Blocks the site (removes it from the grid) and calls the given callback
    * when done.
    */
   block: function Site_block() {
-    if (gBlockedLinks.isBlocked(this._link)) {
-      if (aCallback)
-        aCallback();
-    } else {
+    if (!gBlockedLinks.isBlocked(this._link)) {
       gBlockedLinks.block(this._link);
       gUpdater.updateGrid();
     }
   },
 
   /**
    * Gets the DOM node specified by the given query selector.
    * @param aSelector The query selector.
--- a/browser/devtools/debugger/test/browser_dbg_script-switching.js
+++ b/browser/devtools/debugger/test/browser_dbg_script-switching.js
@@ -15,94 +15,114 @@ let SourceEditor = tempScope.SourceEdito
 var gPane = null;
 var gTab = null;
 var gDebuggee = null;
 var gDebugger = null;
 var gScripts = null;
 
 function test()
 {
+  let scriptShown = false;
+  let framesAdded = false;
+
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
     gDebugger = gPane.debuggerWindow;
 
-    testScriptsDisplay();
+    gPane.activeThread.addOneTimeListener("framesadded", function() {
+      framesAdded = true;
+      runTest();
+    });
+
+    gDebuggee.firstCall();
   });
+
+  window.addEventListener("Debugger:ScriptShown", function _onEvent(aEvent) {
+    let url = aEvent.detail.url;
+    if (url.indexOf("-02.js") != -1) {
+      scriptShown = true;
+      window.removeEventListener(aEvent.type, _onEvent);
+      runTest();
+    }
+  });
+
+  function runTest()
+  {
+    if (scriptShown && framesAdded) {
+      Services.tm.currentThread.dispatch({ run: testScriptsDisplay }, 0);
+    }
+  }
 }
 
 function testScriptsDisplay() {
-  gPane.activeThread.addOneTimeListener("framesadded", function() {
-    Services.tm.currentThread.dispatch({ run: function() {
-      gScripts = gDebugger.DebuggerView.Scripts._scripts;
+  gScripts = gDebugger.DebuggerView.Scripts._scripts;
 
-      is(gDebugger.StackFrames.activeThread.state, "paused",
-        "Should only be getting stack frames while paused.");
+  is(gDebugger.StackFrames.activeThread.state, "paused",
+    "Should only be getting stack frames while paused.");
 
-      is(gScripts.itemCount, 2, "Found the expected number of scripts.");
+  is(gScripts.itemCount, 2, "Found the expected number of scripts.");
 
-      for (let i = 0; i < gScripts.itemCount; i++) {
-        info("label: " + i + " " + gScripts.getItemAtIndex(i).getAttribute("label"));
-      }
+  for (let i = 0; i < gScripts.itemCount; i++) {
+    info("label: " + i + " " + gScripts.getItemAtIndex(i).getAttribute("label"));
+  }
 
-      let label1 = "test-script-switching-01.js";
-      let label2 = "test-script-switching-02.js";
-
-      ok(gDebugger.DebuggerView.Scripts.contains(EXAMPLE_URL +
-        label1), "First script url is incorrect.");
-      ok(gDebugger.DebuggerView.Scripts.contains(EXAMPLE_URL +
-        label2), "Second script url is incorrect.");
+  let label1 = "test-script-switching-01.js";
+  let label2 = "test-script-switching-02.js";
 
-      ok(gDebugger.DebuggerView.Scripts.containsLabel(
-        label1), "First script label is incorrect.");
-      ok(gDebugger.DebuggerView.Scripts.containsLabel(
-        label2), "Second script label is incorrect.");
+  ok(gDebugger.DebuggerView.Scripts.contains(EXAMPLE_URL +
+    label1), "First script url is incorrect.");
+  ok(gDebugger.DebuggerView.Scripts.contains(EXAMPLE_URL +
+    label2), "Second script url is incorrect.");
 
-
-      ok(gDebugger.editor.getText().search(/debugger/) != -1,
-        "The correct script was loaded initially.");
+  ok(gDebugger.DebuggerView.Scripts.containsLabel(
+    label1), "First script label is incorrect.");
+  ok(gDebugger.DebuggerView.Scripts.containsLabel(
+    label2), "Second script label is incorrect.");
 
-      is(gDebugger.editor.getDebugLocation(), 5,
-         "editor debugger location is correct.");
+  ok(gDebugger.editor.getText().search(/debugger/) != -1,
+    "The correct script was loaded initially.");
+
+  is(gDebugger.editor.getDebugLocation(), 5,
+     "editor debugger location is correct.");
 
-      gDebugger.editor.addEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
-                                        function onChange() {
-        gDebugger.editor.removeEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
-                                             onChange);
-        testSwitchPaused();
-      });
-      gScripts.selectedIndex = 0;
-      gDebugger.SourceScripts.onChange({ target: gScripts });
-    }}, 0);
+  window.addEventListener("Debugger:ScriptShown", function _onEvent(aEvent) {
+    let url = aEvent.detail.url;
+    if (url.indexOf("-01.js") != -1) {
+      window.removeEventListener(aEvent.type, _onEvent);
+      testSwitchPaused();
+    }
   });
 
-  gDebuggee.firstCall();
+  gDebugger.DebuggerView.Scripts.selectScript(EXAMPLE_URL + label1);
 }
 
 function testSwitchPaused()
 {
   ok(gDebugger.editor.getText().search(/debugger/) == -1,
     "The second script is no longer displayed.");
 
   ok(gDebugger.editor.getText().search(/firstCall/) != -1,
     "The first script is displayed.");
 
   is(gDebugger.editor.getDebugLocation(), -1,
      "editor debugger location has been cleared.");
 
   gDebugger.StackFrames.activeThread.resume(function() {
-    gDebugger.editor.addEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
-                                      function onSecondChange() {
-      gDebugger.editor.removeEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
-                                           onSecondChange);
-      testSwitchRunning();
+    window.addEventListener("Debugger:ScriptShown", function _onEvent(aEvent) {
+      let url = aEvent.detail.url;
+      if (url.indexOf("-02.js") != -1) {
+        window.removeEventListener(aEvent.type, _onEvent);
+        testSwitchRunning();
+      }
     });
-    gScripts.selectedIndex = 1;
-    gDebugger.SourceScripts.onChange({ target: gScripts });
+
+    gDebugger.DebuggerView.Scripts.selectScript(EXAMPLE_URL +
+                                                "test-script-switching-02.js");
   });
 }
 
 function testSwitchRunning()
 {
   ok(gDebugger.editor.getText().search(/debugger/) != -1,
     "The second script is displayed again.");
 
--- a/browser/devtools/debugger/test/browser_dbg_update-editor-mode.js
+++ b/browser/devtools/debugger/test/browser_dbg_update-editor-mode.js
@@ -15,54 +15,73 @@ let SourceEditor = tempScope.SourceEdito
 var gPane = null;
 var gTab = null;
 var gDebuggee = null;
 var gDebugger = null;
 var gScripts = null;
 
 function test()
 {
+  let scriptShown = false;
+  let framesAdded = false;
+
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
     gDebugger = gPane.debuggerWindow;
 
-    testScriptsDisplay();
+    gPane.activeThread.addOneTimeListener("framesadded", function() {
+      framesAdded = true;
+      runTest();
+    });
+    gDebuggee.firstCall();
   });
+
+  window.addEventListener("Debugger:ScriptShown", function _onEvent(aEvent) {
+    let url = aEvent.detail.url;
+    if (url.indexOf("editor-mode") != -1) {
+      scriptShown = true;
+      window.removeEventListener(aEvent.type, _onEvent);
+      runTest();
+    }
+  });
+
+  function runTest()
+  {
+    if (scriptShown && framesAdded) {
+      Services.tm.currentThread.dispatch({ run: testScriptsDisplay }, 0);
+    }
+  }
 }
 
 function testScriptsDisplay() {
-  gPane.activeThread.addOneTimeListener("framesadded", function() {
-    Services.tm.currentThread.dispatch({ run: function() {
-      gScripts = gDebugger.DebuggerView.Scripts._scripts;
+  gScripts = gDebugger.DebuggerView.Scripts._scripts;
+
+  is(gDebugger.StackFrames.activeThread.state, "paused",
+    "Should only be getting stack frames while paused.");
 
-      is(gDebugger.StackFrames.activeThread.state, "paused",
-        "Should only be getting stack frames while paused.");
+  is(gScripts.itemCount, 2, "Found the expected number of scripts.");
 
-      is(gScripts.itemCount, 2, "Found the expected number of scripts.");
-
-      is(gDebugger.editor.getMode(), SourceEditor.MODES.HTML,
-         "Found the expected editor mode.");
+  is(gDebugger.editor.getMode(), SourceEditor.MODES.HTML,
+     "Found the expected editor mode.");
 
-      ok(gDebugger.editor.getText().search(/debugger/) != -1,
-        "The correct script was loaded initially.");
+  ok(gDebugger.editor.getText().search(/debugger/) != -1,
+    "The correct script was loaded initially.");
 
-      gDebugger.editor.addEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
-                                        function onChange() {
-        gDebugger.editor.removeEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
-                                             onChange);
-        testSwitchPaused();
-      });
-      gScripts.selectedIndex = 0;
-      gDebugger.SourceScripts.onChange({ target: gScripts });
-    }}, 0);
+  window.addEventListener("Debugger:ScriptShown", function _onEvent(aEvent) {
+    let url = aEvent.detail.url;
+    if (url.indexOf("switching-01.js") != -1) {
+      window.removeEventListener(aEvent.type, _onEvent);
+      testSwitchPaused();
+    }
   });
 
-  gDebuggee.firstCall();
+  let url = gDebuggee.document.querySelector("script").src;
+  gDebugger.DebuggerView.Scripts.selectScript(url);
 }
 
 function testSwitchPaused()
 {
   ok(gDebugger.editor.getText().search(/debugger/) == -1,
     "The second script is no longer displayed.");
 
   ok(gDebugger.editor.getText().search(/firstCall/) != -1,
--- a/browser/devtools/sourceeditor/source-editor-orion.jsm
+++ b/browser/devtools/sourceeditor/source-editor-orion.jsm
@@ -148,25 +148,29 @@ const DEFAULT_KEYBINDINGS = [
   },
   {
     action: "Move Lines Down",
     code: Ci.nsIDOMKeyEvent.DOM_VK_DOWN,
     ctrl: Services.appinfo.OS == "Darwin",
     alt: true,
   },
   {
-    action: "Comment",
+    action: "Comment/Uncomment",
     code: Ci.nsIDOMKeyEvent.DOM_VK_SLASH,
     accel: true,
   },
   {
-    action: "Uncomment",
-    code: Ci.nsIDOMKeyEvent.DOM_VK_SLASH,
+    action: "Move to Bracket Opening",
+    code: Ci.nsIDOMKeyEvent.DOM_VK_OPEN_BRACKET,
     accel: true,
-    shift: true,
+  },
+  {
+    action: "Move to Bracket Closing",
+    code: Ci.nsIDOMKeyEvent.DOM_VK_CLOSE_BRACKET,
+    accel: true,
   },
 ];
 
 var EXPORTED_SYMBOLS = ["SourceEditor"];
 
 /**
  * The SourceEditor object constructor. The SourceEditor component allows you to
  * provide users with an editor tailored to the specific needs of editing source
@@ -398,18 +402,19 @@ SourceEditor.prototype = {
       "tab": [this._doTab, this],
       "Unindent Lines": [this._doUnindentLines, this],
       "enter": [this._doEnter, this],
       "Find...": [this.ui.find, this.ui],
       "Find Next Occurrence": [this.ui.findNext, this.ui],
       "Find Previous Occurrence": [this.ui.findPrevious, this.ui],
       "Goto Line...": [this.ui.gotoLine, this.ui],
       "Move Lines Down": [this._moveLines, this],
-      "Comment": [this._doComment, this],
-      "Uncomment": [this._doUncomment, this],
+      "Comment/Uncomment": [this._doCommentUncomment, this],
+      "Move to Bracket Opening": [this._moveToBracketOpening, this],
+      "Move to Bracket Closing": [this._moveToBracketClosing, this],
     };
 
     for (let name in actions) {
       let action = actions[name];
       this._view.setAction(name, action[0].bind(action[1]));
     }
 
     this._view.setAction("Move Lines Up", this._moveLines.bind(this, true));
@@ -1046,16 +1051,73 @@ SourceEditor.prototype = {
         break;
       default:
         return null;
     }
     return {line: line, blockStart: blockCommentStart, blockEnd: blockCommentEnd};
   },
 
   /**
+   * Decide whether to comment the selection/current line or to uncomment it.
+   *
+   * @private
+   */
+  _doCommentUncomment: function SE__doCommentUncomment()
+  {
+    if (this.readOnly) {
+      return false;
+    }
+
+    let commentObject = this._getCommentStrings();
+    if (!commentObject) {
+      return false;
+    }
+
+    let selection = this.getSelection();
+    let model = this._model;
+    let firstLine = model.getLineAtOffset(selection.start);
+    let lastLine = model.getLineAtOffset(selection.end);
+
+    // Checks for block comment.
+    let firstLineText = model.getLine(firstLine);
+    let lastLineText = model.getLine(lastLine);
+    let openIndex = firstLineText.indexOf(commentObject.blockStart);
+    let closeIndex = lastLineText.lastIndexOf(commentObject.blockEnd);
+    if (openIndex != -1 && closeIndex != -1 &&
+        (firstLine != lastLine ||
+        (closeIndex - openIndex) >= commentObject.blockStart.length)) {
+      return this._doUncomment();
+    }
+
+    if (!commentObject.line) {
+      return this._doComment();
+    }
+
+    // If the selection is not a block comment, check for the first and the last
+    // lines to be line commented.
+    let firstLastCommented = [firstLineText,
+                              lastLineText].every(function(aLineText) {
+      let openIndex = aLineText.indexOf(commentObject.line);
+      if (openIndex != -1) {
+        let textUntilComment = aLineText.slice(0, openIndex);
+        if (!textUntilComment || /^\s+$/.test(textUntilComment)) {
+          return true;
+        }
+      }
+      return false;
+    });
+    if (firstLastCommented) {
+      return this._doUncomment();
+    }
+
+    // If we reach here, then we have to comment the selection/line.
+    return this._doComment();
+  },
+
+  /**
    * Wrap the selected text in comments. If nothing is selected the current
    * caret line is commented out. Single line and block comments depend on the
    * current editor mode.
    *
    * @private
    */
   _doComment: function SE__doComment()
   {
@@ -1118,17 +1180,19 @@ SourceEditor.prototype = {
     let firstLine = this._model.getLineAtOffset(selection.start);
     let lastLine = this._model.getLineAtOffset(selection.end);
 
     // Uncomment a block of text.
     let firstLineText = this._model.getLine(firstLine);
     let lastLineText = this._model.getLine(lastLine);
     let openIndex = firstLineText.indexOf(commentObject.blockStart);
     let closeIndex = lastLineText.lastIndexOf(commentObject.blockEnd);
-    if (openIndex != -1 && closeIndex != -1) {
+    if (openIndex != -1 && closeIndex != -1 &&
+        (firstLine != lastLine ||
+        (closeIndex - openIndex) >= commentObject.blockStart.length)) {
       let firstLineStartOffset = this.getLineStart(firstLine);
       let lastLineStartOffset = this.getLineStart(lastLine);
       let openOffset = firstLineStartOffset + openIndex;
       let closeOffset = lastLineStartOffset + closeIndex;
 
       this.startCompoundChange();
       this.setText("", closeOffset, closeOffset + commentObject.blockEnd.length);
       this.setText("", openOffset, openOffset + commentObject.blockStart.length);
@@ -1157,16 +1221,109 @@ SourceEditor.prototype = {
       lineCaret++;
     }
     this.endCompoundChange();
 
     return true;
   },
 
   /**
+   * Helper function for _moveToBracket{Opening/Closing} to find the offset of
+   * matching bracket.
+   *
+   * @param number aOffset
+   *        The offset of the bracket for which you want to find the bracket.
+   * @private
+   */
+  _getMatchingBracketIndex: function SE__getMatchingBracketIndex(aOffset)
+  {
+    return this._styler._findMatchingBracket(this._model, aOffset);
+  },
+
+  /**
+   * Move the cursor to the matching opening bracket if at corresponding closing
+   * bracket, otherwise move to the opening bracket for the current block of code.
+   *
+   * @private
+   */
+  _moveToBracketOpening: function SE__moveToBracketOpening()
+  {
+    let mode = this.getMode();
+    // Returning early if not in JavaScipt or CSS mode.
+    if (mode != SourceEditor.MODES.JAVASCRIPT &&
+        mode != SourceEditor.MODES.CSS) {
+      return false;
+    }
+
+    let caretOffset = this.getCaretOffset() - 1;
+    let matchingIndex = this._getMatchingBracketIndex(caretOffset);
+
+    // If the caret is not at the closing bracket "}", find the index of the
+    // opening bracket "{" for the current code block.
+    if (matchingIndex == -1 || matchingIndex > caretOffset) {
+      let text = this.getText();
+      let closingOffset = text.indexOf("}", caretOffset);
+      while (closingOffset > -1) {
+        let closingMatchingIndex = this._getMatchingBracketIndex(closingOffset);
+        if (closingMatchingIndex < caretOffset && closingMatchingIndex != -1) {
+          matchingIndex = closingMatchingIndex;
+          break;
+        }
+        closingOffset = text.indexOf("}", closingOffset + 1);
+      }
+    }
+
+    if (matchingIndex > -1) {
+      this.setCaretOffset(matchingIndex);
+    }
+
+    return true;
+  },
+
+  /**
+   * Moves the cursor to the matching closing bracket if at corresponding opening
+   * bracket, otherwise move to the closing bracket for the current block of code.
+   *
+   * @private
+   */
+  _moveToBracketClosing: function SE__moveToBracketClosing()
+  {
+    let mode = this.getMode();
+    // Returning early if not in JavaScipt or CSS mode.
+    if (mode != SourceEditor.MODES.JAVASCRIPT &&
+        mode != SourceEditor.MODES.CSS) {
+      return false;
+    }
+
+    let caretOffset = this.getCaretOffset();
+    let matchingIndex = this._getMatchingBracketIndex(caretOffset - 1);
+
+    // If the caret is not at the opening bracket "{", find the index of the
+    // closing bracket "}" for the current code block.
+    if (matchingIndex == -1 || matchingIndex < caretOffset) {
+      let text = this.getText();
+      let openingOffset = text.lastIndexOf("{", caretOffset);
+      while (openingOffset > -1) {
+        let openingMatchingIndex = this._getMatchingBracketIndex(openingOffset);
+        if (openingMatchingIndex > caretOffset) {
+          matchingIndex = openingMatchingIndex;
+          break;
+        }
+        openingOffset = text.lastIndexOf("{", openingOffset - 1);
+      }
+    }
+
+    if (matchingIndex > -1) {
+      this.setCaretOffset(matchingIndex);
+    }
+
+    return true;
+  },
+
+  /**
    * Add an event listener to the editor. You can use one of the known events.
    *
    * @see SourceEditor.EVENTS
    *
    * @param string aEventType
    *        The event type you want to listen for.
    * @param function aCallback
    *        The function you want executed when the event is triggered.
--- a/browser/devtools/sourceeditor/test/Makefile.in
+++ b/browser/devtools/sourceeditor/test/Makefile.in
@@ -58,12 +58,13 @@ include $(topsrcdir)/config/rules.mk
 		browser_bug725388_mouse_events.js \
 		browser_bug707987_debugger_breakpoints.js \
 		browser_bug712982_line_ruler_click.js \
 		browser_bug725618_moveLines_shortcut.js \
 		browser_bug700893_dirty_state.js \
 		browser_bug729480_line_vertical_align.js \
 		browser_bug725430_comment_uncomment.js \
 		browser_bug731721_debugger_stepping.js \
+		browser_bug729960_block_bracket_jump.js \
 		head.js \
 
 libs:: $(_BROWSER_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
--- a/browser/devtools/sourceeditor/test/browser_bug725430_comment_uncomment.js
+++ b/browser/devtools/sourceeditor/test/browser_bug725430_comment_uncomment.js
@@ -43,108 +43,108 @@ function test() {
     editor.setCaretPosition(0);
     EventUtils.synthesizeKey("/", {accelKey: true}, testWin);
     is(editor.getText(), "//" + text, "JS Single line Commenting Works");
     editor.undo();
     is(editor.getText(), text, "Undo Single Line Commenting action works");
     editor.redo();
     is(editor.getText(), "//" + text, "Redo works");
     editor.setCaretPosition(0);
-    EventUtils.synthesizeKey("/", {accelKey: true, shiftKey: true}, testWin);
+    EventUtils.synthesizeKey("/", {accelKey: true}, testWin);
     is(editor.getText(), text, "JS Single Line Uncommenting works");
 
     editor.setText(text);
 
     EventUtils.synthesizeKey("VK_A", {accelKey: true}, testWin);
     EventUtils.synthesizeKey("/", {accelKey: true}, testWin);
     is(editor.getText(), "/*" + text + "*/", "JS Block Commenting works");
     editor.undo();
     is(editor.getText(), text, "Undo Block Commenting action works");
     editor.redo();
     is(editor.getText(), "/*" + text + "*/", "Redo works");
     EventUtils.synthesizeKey("VK_A", {accelKey: true}, testWin);
-    EventUtils.synthesizeKey("/", {accelKey: true, shiftKey: true}, testWin);
+    EventUtils.synthesizeKey("/", {accelKey: true}, testWin);
     is(editor.getText(), text, "JS Block Uncommenting works");
     editor.undo();
     is(editor.getText(), "/*" + text + "*/", "Undo Block Uncommenting works");
     editor.redo();
     is(editor.getText(), text, "Redo works");
 
-    let regText = "//firstline\n    //    secondline\nthird//line\nfourthline//";
-    let expText = "firstline\n        secondline\nthird//line\nfourthline//";
+    let regText = "//firstline\n    //    secondline\nthird//line\n//fourthline";
+    let expText = "firstline\n        secondline\nthird//line\nfourthline";
     editor.setText(regText);
     EventUtils.synthesizeKey("VK_A", {accelKey: true}, testWin);
-    EventUtils.synthesizeKey("/", {accelKey: true, shiftKey: true}, testWin);
+    EventUtils.synthesizeKey("/", {accelKey: true}, testWin);
     is(editor.getText(), expText, "JS Multiple Line Uncommenting works");
     editor.undo();
     is(editor.getText(), regText, "Undo Multiple Line Uncommenting works");
     editor.redo();
     is(editor.getText(), expText, "Redo works");
 
     editor.setMode(SourceEditor.MODES.CSS);
     editor.setText(text);
 
     expText = "/*firstline*/\nsecondline\nthirdline\nfourthline";
     editor.setCaretPosition(0);
     EventUtils.synthesizeKey("/", {accelKey: true}, testWin);
     is(editor.getText(), expText, "CSS Commenting without selection works");
     editor.setCaretPosition(0);
-    EventUtils.synthesizeKey("/", {accelKey: true, shiftKey: true}, testWin);
+    EventUtils.synthesizeKey("/", {accelKey: true}, testWin);
     is(editor.getText(), text, "CSS Uncommenting without selection works");
 
     editor.setText(text);
 
     EventUtils.synthesizeKey("VK_A", {accelKey: true}, testWin);
     EventUtils.synthesizeKey("/", {accelKey: true}, testWin);
     is(editor.getText(), "/*" + text + "*/", "CSS Multiple Line Commenting works");
     EventUtils.synthesizeKey("VK_A", {accelKey: true}, testWin);
-    EventUtils.synthesizeKey("/", {accelKey: true, shiftKey: true}, testWin);
+    EventUtils.synthesizeKey("/", {accelKey: true}, testWin);
     is(editor.getText(), text, "CSS Multiple Line Uncommenting works");
 
     editor.setMode(SourceEditor.MODES.HTML);
     editor.setText(text);
 
     expText = "<!--firstline-->\nsecondline\nthirdline\nfourthline";
     editor.setCaretPosition(0);
     EventUtils.synthesizeKey("/", {accelKey: true}, testWin);
     is(editor.getText(), expText, "HTML Commenting without selection works");
     editor.setCaretPosition(0);
-    EventUtils.synthesizeKey("/", {accelKey: true, shiftKey: true}, testWin);
+    EventUtils.synthesizeKey("/", {accelKey: true}, testWin);
     is(editor.getText(), text, "HTML Uncommenting without selection works");
 
     editor.setText(text);
 
     EventUtils.synthesizeKey("VK_A", {accelKey: true}, testWin);
     EventUtils.synthesizeKey("/", {accelKey: true}, testWin);
     is(editor.getText(), "<!--" + text + "-->", "HTML Multiple Line Commenting works");
     EventUtils.synthesizeKey("VK_A", {accelKey: true}, testWin);
-    EventUtils.synthesizeKey("/", {accelKey: true, shiftKey: true}, testWin);
+    EventUtils.synthesizeKey("/", {accelKey: true}, testWin);
     is(editor.getText(), text, "HTML Multiple Line Uncommenting works");
 
     editor.setMode(SourceEditor.MODES.TEXT);
     editor.setText(text);
 
     editor.setCaretPosition(0);
     EventUtils.synthesizeKey("/", {accelKey: true}, testWin);
     is(editor.getText(), text, "Commenting disabled in Text mode");
-    editor.setText("//" + text);
+    editor.setText(regText);
     EventUtils.synthesizeKey("VK_A", {accelKey: true}, testWin);
-    EventUtils.synthesizeKey("/", {accelKey: true, shiftKey: true}, testWin);
-    is(editor.getText(), "//" + text, "Uncommenting disabled in Text mode");
+    EventUtils.synthesizeKey("/", {accelKey: true}, testWin);
+    is(editor.getText(), regText, "Uncommenting disabled in Text mode");
 
     editor.setText(text);
     editor.readOnly = true;
 
     editor.setCaretPosition(0);
     EventUtils.synthesizeKey("/", {accelKey: true}, testWin);
     is(editor.getText(), text, "Commenting disabled in ReadOnly mode");
-    editor.setText("//" + text);
+    editor.setText(regText);
     EventUtils.synthesizeKey("VK_A", {accelKey: true}, testWin);
-    EventUtils.synthesizeKey("/", {accelKey: true, shiftKey: true}, testWin);
-    is(editor.getText(), "//" + text, "Uncommenting disabled in ReadOnly mode");
+    EventUtils.synthesizeKey("/", {accelKey: true}, testWin);
+    is(editor.getText(), regText, "Uncommenting disabled in ReadOnly mode");
 
     editor.destroy();
 
     testWin.close();
     testWin = editor = null;
 
     waitForFocus(finish, window);
   }
new file mode 100644
--- /dev/null
+++ b/browser/devtools/sourceeditor/test/browser_bug729960_block_bracket_jump.js
@@ -0,0 +1,164 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+function test() {
+
+  let temp = {};
+  Cu.import("resource:///modules/source-editor.jsm", temp);
+  let SourceEditor = temp.SourceEditor;
+
+  waitForExplicitFinish();
+
+  let editor;
+
+  const windowUrl = "data:text/xml,<?xml version='1.0'?>" +
+    "<window xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'" +
+    " title='test for bug 729960' width='600' height='500'><hbox flex='1'/></window>";
+  const windowFeatures = "chrome,titlebar,toolbar,centerscreen,resizable,dialog=no";
+
+  let testWin = Services.ww.openWindow(null, windowUrl, "_blank", windowFeatures, null);
+  testWin.addEventListener("load", function onWindowLoad() {
+    testWin.removeEventListener("load", onWindowLoad, false);
+    waitForFocus(initEditor, testWin);
+  }, false);
+
+  function initEditor()
+  {
+    let hbox = testWin.document.querySelector("hbox");
+    editor = new SourceEditor();
+    editor.init(hbox, {showLineNumbers: true}, editorLoaded);
+  }
+
+  function editorLoaded()
+  {
+    editor.focus();
+    let JSText = "function foo(aVar) {\n" +
+                 "  // Block Level 1\n\n" +
+                 "  function level2() {\n" +
+                 "    let baz = aVar;\n" +
+                 "    // Block Level 2\n" +
+                 "    function level3() {\n" +
+                 "      // Block Level 3\n" +
+                 "    }\n" +
+                 "  }\n" +
+                 "  // Block Level 1" +
+                 "  function bar() { /* Block Level 2 */ }\n" +
+                 "}";
+
+    editor.setMode(SourceEditor.MODES.JAVASCRIPT);
+    editor.setText(JSText);
+
+    // Setting caret at Line 1 bracket start.
+    editor.setCaretOffset(19);
+    EventUtils.synthesizeKey("]", {accelKey: true}, testWin);
+    is(editor.getCaretOffset(), 220,
+       "JS : Jump to closing bracket of the code block when caret at block start");
+
+    EventUtils.synthesizeKey("[", {accelKey: true}, testWin);
+    is(editor.getCaretOffset(), 19,
+       "JS : Jump to opening bracket of the code block when caret at block end");
+
+    // Setting caret at Line 10 start.
+    editor.setCaretOffset(161);
+    EventUtils.synthesizeKey("[", {accelKey: true}, testWin);
+    is(editor.getCaretOffset(), 19,
+       "JS : Jump to opening bracket of code block when inside the function");
+
+    editor.setCaretOffset(161);
+    EventUtils.synthesizeKey("]", {accelKey: true}, testWin);
+    is(editor.getCaretOffset(), 220,
+       "JS : Jump to closing bracket of code block when inside the function");
+
+    // Setting caret at Line 6 start.
+    editor.setCaretOffset(67);
+    EventUtils.synthesizeKey("]", {accelKey: true}, testWin);
+    is(editor.getCaretOffset(), 159,
+       "JS : Jump to closing bracket in a nested function with caret inside");
+
+    editor.setCaretOffset(67);
+    EventUtils.synthesizeKey("[", {accelKey: true}, testWin);
+    is(editor.getCaretOffset(), 61,
+       "JS : Jump to opening bracket in a nested function with caret inside");
+
+    let CSSText = "#object {\n" +
+                  "  property: value;\n" +
+                  "  /* comment */\n" +
+                  "}";
+
+    editor.setMode(SourceEditor.MODES.CSS);
+    editor.setText(CSSText);
+
+    // Setting caret at Line 1 bracket start.
+    editor.setCaretOffset(8);
+    EventUtils.synthesizeKey("]", {accelKey: true}, testWin);
+    is(editor.getCaretOffset(), 45,
+       "CSS : Jump to closing bracket of the code block when caret at block start");
+
+    EventUtils.synthesizeKey("[", {accelKey: true}, testWin);
+    is(editor.getCaretOffset(), 8,
+       "CSS : Jump to opening bracket of the code block when caret at block end");
+
+    // Setting caret at Line 3 start.
+    editor.setCaretOffset(28);
+    EventUtils.synthesizeKey("[", {accelKey: true}, testWin);
+    is(editor.getCaretOffset(), 8,
+       "CSS : Jump to opening bracket of code block when inside the function");
+
+    editor.setCaretOffset(28);
+    EventUtils.synthesizeKey("]", {accelKey: true}, testWin);
+    is(editor.getCaretOffset(), 45,
+       "CSS : Jump to closing bracket of code block when inside the function");
+
+    let HTMLText = "<html>\n" +
+                   "  <head>\n" +
+                   "    <title>Testing Block Jump</title>\n" +
+                   "  </head>\n" +
+                   "  <body></body>\n" +
+                   "</html>";
+
+    editor.setMode(SourceEditor.MODES.HTML);
+    editor.setText(HTMLText);
+
+    // Setting caret at Line 1 end.
+    editor.setCaretOffset(6);
+    EventUtils.synthesizeKey("]", {accelKey: true}, testWin);
+    is(editor.getCaretOffset(), 6,
+       "HTML : Jump to block end : Nothing happens in html mode");
+
+    // Setting caret at Line 4 end.
+    editor.setCaretOffset(64);
+    EventUtils.synthesizeKey("[", {accelKey: true}, testWin);
+    is(editor.getCaretOffset(), 64,
+       "HTML : Jump to block start : Nothing happens in html mode");
+
+    let text = "line 1\n" +
+               "line 2\n" +
+               "line 3\n" +
+               "line 4\n";
+
+    editor.setMode(SourceEditor.MODES.TEXT);
+    editor.setText(text);
+
+    // Setting caret at Line 1 start.
+    editor.setCaretOffset(0);
+    EventUtils.synthesizeKey("]", {accelKey: true}, testWin);
+    is(editor.getCaretOffset(), 0,
+       "Text : Jump to block end : Nothing happens in text mode");
+
+    // Setting caret at Line 4 end.
+    editor.setCaretOffset(28);
+    EventUtils.synthesizeKey("[", {accelKey: true}, testWin);
+    is(editor.getCaretOffset(), 28,
+       "Text : Jump to block start : Nothing happens in text mode");
+
+    editor.destroy();
+
+    testWin.close();
+    testWin = editor = null;
+
+    waitForFocus(finish, window);
+  }
+}
--- a/browser/devtools/styleeditor/StyleEditor.jsm
+++ b/browser/devtools/styleeditor/StyleEditor.jsm
@@ -1172,17 +1172,18 @@ function setupBracketCompletion(aSourceE
     91: { // [
       closeString: "]",
       closeKeyCode: Ci.nsIDOMKeyEvent.DOM_VK_CLOSE_BRACKET
     },
   };
 
   editorElement.addEventListener("keypress", function onKeyPress(aEvent) {
     let pair = pairs[aEvent.charCode];
-    if (!pair) {
+    if (!pair || aEvent.ctrlKey || aEvent.metaKey ||
+        aEvent.accelKey || aEvent.altKey) {
       return true;
     }
 
     // We detected an open bracket, sending closing character
     let keyCode = pair.closeKeyCode;
     let charCode = pair.closeString.charCodeAt(0);
     let modifiers = 0;
     let utils = editorElement.ownerDocument.defaultView.
--- a/browser/devtools/styleeditor/test/browser_styleeditor_new.js
+++ b/browser/devtools/styleeditor/test/browser_styleeditor_new.js
@@ -85,16 +85,24 @@ function testEditorAdded(aChrome, aEdito
         let ruleCount = summary.querySelector(".stylesheet-rule-count").textContent;
         is(parseInt(ruleCount), 0,
            "new editor initially shows 0 rules");
 
         let computedStyle = content.getComputedStyle(content.document.body, null);
         is(computedStyle.backgroundColor, "rgb(255, 255, 255)",
            "content's background color is initially white");
 
+        EventUtils.synthesizeKey("[", {accelKey: true}, gChromeWindow);
+        is(aEditor.sourceEditor.getText(), "",
+           "Nothing happened as it is a known shortcut in source editor");
+
+        EventUtils.synthesizeKey("]", {accelKey: true}, gChromeWindow);
+        is(aEditor.sourceEditor.getText(), "",
+           "Nothing happened as it is a known shortcut in source editor");
+
         for each (let c in TESTCASE_CSS_SOURCE) {
           EventUtils.synthesizeKey(c, {}, gChromeWindow);
         }
 
         is(aEditor.sourceEditor.getText(), TESTCASE_CSS_SOURCE + "}",
            "rule bracket has been auto-closed");
 
         // we know that the testcase above will start a CSS transition