title: Why does this Javascript match() function Crash My Browser?
body: <h3>WHAT I DO:</h3>
  
  <ul>
  <li>Make sure Firebug is working.</li>
  <li>Put a break point in the isWrappedInParens() function.</li>
  <li>Navigate to my webapp.</li>
  <li>Trigger a call to isWrappedInParens().</li>
  <li>Step through isWrappedInParens(). Everything goes fine, but it does not proceed past the line of code indicated as the "CRASH POINT".</li>
  <li>I also tried it without Firebug running or having a break point, but it still freezes.</li>
  </ul>
  
  <h3>WHAT I NOTICE:</h3>
  
  <ul>
  <li>In most cases, isWrappedInParens() works fine.</li>
  <li>When it does not work, Firefox freezes. I can still minimize/expand/close the window, though.</li>
  <li>I also noticed that when the test string is a bit shorter (less parentheses), firefox hangs but eventually finishes (~30 seconds) correctly.</li>
  </ul>
  
  <h3>EXAMPLE STRING THAT CRASHES FIREFOX</h3>
  
  <pre><code>// Note that this is not wrapped in parentheses,
  // since it is two separate sets of nested parentheses
  var test = "(the OR (and) OR (and) OR (and)) AND ((to) OR (to) OR (to))";
  </code></pre>
  
  <h3>BACKGROUND</h3>
  
  <ul>
  <li>Browser: Firefox 3.6.18</li>
  <li>The webapp is a jetty application.</li>
  </ul>
  
  <h3>CODE</h3>
  
  <pre><code>isWrappedInParens = function(str){
      if(_.isNull(str)) {
          return false;
      }
      str = str.trim();
  
      var pattern = /^[(](([(][^()]+[)]|[^()]+)|[(]([(][^()]+[)]|[^()]+)+[)])+[)]$/;
  
      var matchesPattern;
      try{
          matchesPattern = str.match(pattern) || null; //CRASH POINT!!!!!!!!!!!
      }catch(err){
          return false; //Note that no error is ever caught from freezing
      }
  
      var isWrapped = !_.isUndefined(matchesPattern) &amp;&amp; !_.isNull(matchesPattern);
      return isWrapped;
  }
  </code></pre>
  
  <h3>WHERE THE REGEX CAME FROM:</h3>
  
  <pre><code>// Atoms, building blocks for the expressions
  var parenAtom = "[(][^()]+[)]";
  var nonParenAtom = "[^()]+";
  
  // Expressions, building blocks for the final regular expression
  var baseCase = "(" + parenAtom + "|" + nonParenAtom + ")";
  var nestedCase = "[(]_base_[)]"
      .replace("_base_", baseCase);
  
  // Regular Expression
  var wholeCase = "^[(](_base_|_nested_)+[)]$"
      .replace("_base_", baseCase)
      .replace("_nested_", nestedCase);
  var pattern = new RegExp(wholeCase, "");
  </code></pre>