docs: private static Scriptable js_sort(final Context cx, final Scriptable scope,
              final Scriptable thisObj, final Object[] args)
      {
          final Comparator<Object> comparator;
          if (args.length > 0 && Undefined.instance != args[0]) {
              final Callable jsCompareFunction = ScriptRuntime
                      .getValueFunctionAndThis(args[0], cx);
              final Scriptable funThis = ScriptRuntime.lastStoredScriptable(cx);
              final Object[] cmpBuf = new Object[2]; // Buffer for cmp arguments
              comparator = new ElementComparator(
                  new Comparator<Object>() {
                    @Override
                    public int compare(final Object x, final Object y) {
                      // This comparator is invoked only for non-undefined objects
                      cmpBuf[0] = x;
                      cmpBuf[1] = y;
                      Object ret = jsCompareFunction.call(cx, scope, funThis,
                          cmpBuf);
                      final double d = ScriptRuntime.toNumber(ret);
                      if (d < 0) {
                        return -1;
                      } else if (d > 0) {
                        return +1;
                      }
                      return 0; // ??? double and 0???
                    }
                  });
          } else {
              comparator = DEFAULT_COMPARATOR;
          }
  
          long llength = getLengthProperty(cx, thisObj, false);
          final int length = (int) llength;
          if (llength != length) {
              throw Context.reportRuntimeError1(
                  "msg.arraylength.too.big", String.valueOf(llength));
          }
          // copy the JS array into a working array, so it can be
          // sorted cheaply.
          final Object[] working = new Object[length];
          for (int i = 0; i != length; ++i) {
              working[i] = getRawElem(thisObj, i);
          }
  
          Sorting.hybridSort(working, comparator);
  
          // copy the working array back into thisObj
          for (int i = 0; i < length; ++i) {
              setRawElem(cx, thisObj, i, working[i]);
          }
  
          return thisObj;
      }