Program: 7475
Project: 7475
Buggy source:
/** 
 * Removes all JavaScript classes and replaces them with the corresponding Java objects. This method will use instances of Dict and Array to replace native JavaScript objects and arrays. Also, it will replace both JavaScript "null" and "undefined" with null. Any Dict or Array object encountered will be traversed and copied recursively. Other objects will be returned as-is.
 * @param obj            the object to unwrap
 * @return the unwrapped object
 * @see org.rapidcontext.core.data.Array
 * @see org.rapidcontext.core.data.Dict
 */
public static Object unwrap(Object obj){
  if (obj instanceof DataWrapper) {
    return ((DataWrapper)obj).getData();
  }
 else   if (obj instanceof NativeArray) {
    NativeArray nativeArr=(NativeArray)obj;
    int length=(int)nativeArr.getLength();
    Array arr=new Array(length);
    for (int i=0; i < length; i++) {
      arr.set(i,unwrap(nativeArr.get(i,nativeArr)));
    }
    return arr;
  }
 else   if (obj instanceof Scriptable) {
    Scriptable scr=(Scriptable)obj;
    Object[] keys=scr.getIds();
    Dict dict=new Dict(keys.length);
    for (int i=0; i < keys.length; i++) {
      String str=keys[i].toString();
      Object value=null;
      if (keys[i] instanceof Integer) {
        value=scr.get(((Integer)keys[i]).intValue(),scr);
      }
 else {
        value=scr.get(str,scr);
      }
      dict.set(str,unwrap(value));
    }
    return dict;
  }
 else   if (obj instanceof Undefined || obj == Scriptable.NOT_FOUND) {
    return null;
  }
 else   if (obj instanceof Array) {
    Array oldArr=(Array)obj;
    Array newArr=new Array(oldArr.size());
    for (int i=0; i < oldArr.size(); i++) {
      newArr.set(i,unwrap(oldArr.get(i)));
    }
    return newArr;
  }
 else   if (obj instanceof Dict) {
    Dict oldDict=(Dict)obj;
    Dict newDict=new Dict(oldDict.size());
    String[] keys=oldDict.keys();
    for (int i=0; i < keys.length; i++) {
      String key=keys[i].toString();
      newDict.set(key,unwrap(oldDict.get(key)));
    }
    return newDict;
  }
 else {
    return obj;
  }
}

Fixed version (ground truth):
/** 
 * Removes all JavaScript classes and replaces them with the corresponding Java objects. This method will use instances of Dict and Array to replace native JavaScript objects and arrays. Also, it will replace both JavaScript "null" and "undefined" with null. Any Dict or Array object encountered will be traversed and copied recursively. Other objects will be returned as-is.
 * @param obj            the object to unwrap
 * @return the unwrapped object
 * @see org.rapidcontext.core.data.Array
 * @see org.rapidcontext.core.data.Dict
 */
public static Object unwrap(Object obj){
  if (obj instanceof Undefined || obj == Scriptable.NOT_FOUND) {
    return null;
  }
 else   if (obj instanceof DataWrapper) {
    return unwrap(((DataWrapper)obj).getData());
  }
 else   if (obj instanceof NativeArray) {
    NativeArray nativeArr=(NativeArray)obj;
    int length=(int)nativeArr.getLength();
    Array arr=new Array(length);
    for (int i=0; i < length; i++) {
      arr.set(i,unwrap(nativeArr.get(i,nativeArr)));
    }
    return arr;
  }
 else   if (obj instanceof Scriptable) {
    Scriptable scr=(Scriptable)obj;
    Object[] keys=scr.getIds();
    Dict dict=new Dict(keys.length);
    for (int i=0; i < keys.length; i++) {
      String str=keys[i].toString();
      Object value=null;
      if (keys[i] instanceof Integer) {
        value=scr.get(((Integer)keys[i]).intValue(),scr);
      }
 else {
        value=scr.get(str,scr);
      }
      dict.set(str,unwrap(value));
    }
    return dict;
  }
 else   if (obj instanceof Array) {
    Array oldArr=(Array)obj;
    Array newArr=new Array(oldArr.size());
    for (int i=0; i < oldArr.size(); i++) {
      newArr.set(i,unwrap(oldArr.get(i)));
    }
    return newArr;
  }
 else   if (obj instanceof Dict) {
    Dict oldDict=(Dict)obj;
    Dict newDict=new Dict(oldDict.size());
    String[] keys=oldDict.keys();
    for (int i=0; i < keys.length; i++) {
      String key=keys[i].toString();
      newDict.set(key,unwrap(oldDict.get(key)));
    }
    return newDict;
  }
 else {
    return obj;
  }
}