docs: private static Object reduceMethod(Context cx, int id, Scriptable scope,
                                         Scriptable thisObj, Object[] args)
      {
          Scriptable o = ScriptRuntime.toObject(cx, scope, thisObj);
  
          long length = getLengthProperty(cx, o, false);
          Object callbackArg = args.length > 0 ? args[0] : Undefined.instance;
          if (callbackArg == null || !(callbackArg instanceof Function)) {
              throw ScriptRuntime.notFunctionError(callbackArg);
          }
          Function f = (Function) callbackArg;
          Scriptable parent = ScriptableObject.getTopLevelScope(f);
          // hack to serve both reduce and reduceRight with the same loop
          boolean movingLeft = id == Id_reduce;
          Object value = args.length > 1 ? args[1] : Scriptable.NOT_FOUND;
          for (long i = 0; i < length; i++) {
              long index = movingLeft ? i : (length - 1 - i);
              Object elem = getRawElem(o, index);
              if (elem == Scriptable.NOT_FOUND) {
                  continue;
              }
              if (value == Scriptable.NOT_FOUND) {
                  // no initial value passed, use first element found as inital value
                  value = elem;
              } else {
                  Object[] innerArgs = { value, elem, index, o };
                  value = f.call(cx, parent, parent, innerArgs);
              }
          }
          if (value == Scriptable.NOT_FOUND) {
              // reproduce spidermonkey error message
              throw ScriptRuntime.typeError0("msg.empty.array.reduce");
          }
          return value;
      }