code: function negate(ranges /*:[Range rg]*/) {
    var MIN_CHAR="\u0000",
        // work around UglifyJS's bug
        // it will convert unicode escape to raw char
        // that will cause error in IE
        // because IE recognize "\uFFFF" in source code as "\uFFFD"
        MAX_CHAR=String.fromCharCode(0xFFFF);
  
    ranges=classify(ranges).ranges;
    var negated=[];
    if (!ranges.length) return negated;
    if (ranges[0][0]!==MIN_CHAR) ranges.unshift(MAX_CHAR);
    var hi=ranges.length-1;
    if ((ranges[hi][1] || ranges[hi][0])!==MAX_CHAR) ranges.push(MIN_CHAR);
    ranges.reduce(function (acc,r) {
      var start=succ(acc[1] || acc[0]),end=pred(r[0]);
      if (start<end) negated.push(start+end);
      if (start===end) negated.push(start);
      return r;
    });
    return negated;
  }
docs: Convert exclude ranges to include ranges
  Example: ^b-y, ['by'] to ["\0a","z\uffff"]
  @param {[Range]}
  @return Sorted disjoint ranges