docs: @Override
      public Object call(Context cx, Scriptable scope, Scriptable thisObj,
                         Object[] args)
      {
          Object result;
          boolean checkMethodResult = false;
          int argsLength = args.length;
  
          for (int i = 0; i < argsLength; i++) {
              // flatten cons-strings before passing them as arguments
              if (args[i] instanceof ConsString) {
                  args[i] = args[i].toString();
              }
          }
  
          if (parmsLength < 0) {
              if (parmsLength == VARARGS_METHOD) {
                  Object[] invokeArgs = { cx, thisObj, args, this };
                  result = member.invoke(null, invokeArgs);
                  checkMethodResult = true;
              } else {
                  boolean inNewExpr = (thisObj == null);
                  Boolean b = inNewExpr ? Boolean.TRUE : Boolean.FALSE;
                  Object[] invokeArgs = { cx, args, this, b };
                  result = (member.isCtor())
                           ? member.newInstance(invokeArgs)
                           : member.invoke(null, invokeArgs);
              }
  
          } else {
              if (!isStatic) {
                  Class<?> clazz = member.getDeclaringClass();
                  if (!clazz.isInstance(thisObj)) {
                      boolean compatible = false;
                      if (thisObj == scope) {
                          Scriptable parentScope = getParentScope();
                          if (scope != parentScope) {
                              // Call with dynamic scope for standalone function,
                              // use parentScope as thisObj
                              compatible = clazz.isInstance(parentScope);
                              if (compatible) {
                                  thisObj = parentScope;
                              }
                          }
                      }
                      if (!compatible) {
                          // Couldn't find an object to call this on.
                          throw ScriptRuntime.typeError1("msg.incompat.call",
                                                         functionName);
                      }
                  }
              }
  
              Object[] invokeArgs;
              if (parmsLength == argsLength) {
                  // Do not allocate new argument array if java arguments are
                  // the same as the original js ones.
                  invokeArgs = args;
                  for (int i = 0; i != parmsLength; ++i) {
                      Object arg = args[i];
                      Object converted = convertArg(cx, scope, arg, typeTags[i]);
                      if (arg != converted) {
                          if (invokeArgs == args) {
                              invokeArgs = args.clone();
                          }
                          invokeArgs[i] = converted;
                      }
                  }
              } else if (parmsLength == 0) {
                  invokeArgs = ScriptRuntime.emptyArgs;
              } else {
                  invokeArgs = new Object[parmsLength];
                  for (int i = 0; i != parmsLength; ++i) {
                      Object arg = (i < argsLength)
                                   ? args[i]
                                   : Undefined.instance;
                      invokeArgs[i] = convertArg(cx, scope, arg, typeTags[i]);
                  }
              }
  
              if (member.isMethod()) {
                  result = member.invoke(thisObj, invokeArgs);
                  checkMethodResult = true;
              } else {
                  result = member.newInstance(invokeArgs);
              }
  
          }
  
          if (checkMethodResult) {
              if (hasVoidReturn) {
                  result = Undefined.instance;
              } else if (returnTypeTag == JAVA_UNSUPPORTED_TYPE) {
                  result = cx.getWrapFactory().wrap(cx, scope, result, null);
              }
              // XXX: the code assumes that if returnTypeTag == JAVA_OBJECT_TYPE
              // then the Java method did a proper job of converting the
              // result to JS primitive or Scriptable to avoid
              // potentially costly Context.javaToJS call.
          }
  
          return result;
      }