docs: static Object coerceTypeImpl(Class<?> type, Object value)
      {
          if (value != null && value.getClass() == type) {
              return value;
          }
  
          switch (getJSTypeCode(value)) {
  
          case JSTYPE_NULL:
              // raise error if type.isPrimitive()
              if (type.isPrimitive()) {
                  reportConversionError(value, type);
              }
              return null;
  
          case JSTYPE_UNDEFINED:
              if (type == ScriptRuntime.StringClass ||
                  type == ScriptRuntime.ObjectClass) {
                  return "undefined";
              }
              reportConversionError("undefined", type);
              break;
  
          case JSTYPE_BOOLEAN:
              // Under LC3, only JS Booleans can be coerced into a Boolean value
              if (type == Boolean.TYPE ||
                  type == ScriptRuntime.BooleanClass ||
                  type == ScriptRuntime.ObjectClass) {
                  return value;
              }
              else if (type == ScriptRuntime.StringClass) {
                  return value.toString();
              }
              else {
                  reportConversionError(value, type);
              }
              break;
  
          case JSTYPE_NUMBER:
              if (type == ScriptRuntime.StringClass) {
                  return ScriptRuntime.toString(value);
              }
              else if (type == ScriptRuntime.ObjectClass) {
                  Context context = Context.getCurrentContext();
                  if(context.hasFeature(Context.FEATURE_INTEGER_WITHOUT_DECIMAL_PLACE)) {
                      //to process numbers like 2.0 as 2 without decimal place
                      long roundedValue = Math.round(toDouble(value));
                      if(roundedValue == toDouble(value)) {
                          return coerceToNumber(Long.TYPE, value);
                      }
                  }
                  return coerceToNumber(Double.TYPE, value);
              }
              else if ((type.isPrimitive() && type != Boolean.TYPE) ||
                       ScriptRuntime.NumberClass.isAssignableFrom(type)) {
                  return coerceToNumber(type, value);
              }
              else {
                  reportConversionError(value, type);
              }
              break;
  
          case JSTYPE_STRING:
              if (type == ScriptRuntime.StringClass || type.isInstance(value)) {
                  return value.toString();
              }
              else if (type == Character.TYPE
                       || type == ScriptRuntime.CharacterClass)
              {
                  // Special case for converting a single char string to a
                  // character
                  // Placed here because it applies *only* to JS strings,
                  // not other JS objects converted to strings
                  if (((CharSequence)value).length() == 1) {
                      return Character.valueOf(((CharSequence)value).charAt(0));
                  }
                  return coerceToNumber(type, value);
              }
              else if ((type.isPrimitive() && type != Boolean.TYPE)
                       || ScriptRuntime.NumberClass.isAssignableFrom(type))
              {
                  return coerceToNumber(type, value);
              }
              else {
                  reportConversionError(value, type);
              }
              break;
  
          case JSTYPE_JAVA_CLASS:
              if (value instanceof Wrapper) {
                  value = ((Wrapper)value).unwrap();
              }
  
              if (type == ScriptRuntime.ClassClass ||
                  type == ScriptRuntime.ObjectClass) {
                  return value;
              }
              else if (type == ScriptRuntime.StringClass) {
                  return value.toString();
              }
              else {
                  reportConversionError(value, type);
              }
              break;
  
          case JSTYPE_JAVA_OBJECT:
          case JSTYPE_JAVA_ARRAY:
              if (value instanceof Wrapper) {
                value = ((Wrapper)value).unwrap();
              }
              if (type.isPrimitive()) {
                  if (type == Boolean.TYPE) {
                      reportConversionError(value, type);
                  }
                  return coerceToNumber(type, value);
              }
            if (type == ScriptRuntime.StringClass) {
                  return value.toString();
              }
              if (type.isInstance(value)) {
                  return value;
              }
              reportConversionError(value, type);
              break;
  
          case JSTYPE_OBJECT:
              if (type == ScriptRuntime.StringClass) {
                  return ScriptRuntime.toString(value);
              }
              else if (type.isPrimitive()) {
                  if (type == Boolean.TYPE) {
                      reportConversionError(value, type);
                  }
                  return coerceToNumber(type, value);
              }
              else if (type.isInstance(value)) {
                  return value;
              }
              else if (type == ScriptRuntime.DateClass
                       && value instanceof NativeDate)
              {
                  double time = ((NativeDate)value).getJSTimeValue();
                  // XXX: This will replace NaN by 0
                  return new Date((long)time);
              }
              else if (type.isArray() && value instanceof NativeArray) {
                  // Make a new java array, and coerce the JS array components
                  // to the target (component) type.
                  NativeArray array = (NativeArray) value;
                  long length = array.getLength();
                  Class<?> arrayType = type.getComponentType();
                  Object Result = Array.newInstance(arrayType, (int)length);
                  for (int i = 0 ; i < length ; ++i) {
                      try  {
                          Array.set(Result, i, coerceTypeImpl(
                                  arrayType, array.get(i, array)));
                      }
                      catch (EvaluatorException ee) {
                          reportConversionError(value, type);
                      }
                  }
  
                  return Result;
              }
              else if (value instanceof Wrapper) {
                  value = ((Wrapper)value).unwrap();
                  if (type.isInstance(value))
                      return value;
                  reportConversionError(value, type);
              }
              else if (type.isInterface() && (value instanceof NativeObject
                      || value instanceof NativeFunction)) {
                  // Try to use function/object as implementation of Java interface.
                  return createInterfaceAdapter(type, (ScriptableObject) value);
              } else {
                  reportConversionError(value, type);
              }
              break;
          }
  
          return value;
      }