/** * Wrap a Java object as corresponding script object * * @param obj object to wrap * @return wrapped object */ public Object wrapAsObject(final Object obj) { if (obj instanceof Boolean) { return new NativeBoolean((Boolean)obj, this); } else if (obj instanceof Number) { return new NativeNumber(((Number)obj).doubleValue(), this); } else if (obj instanceof String || obj instanceof ConsString) { return new NativeString((CharSequence)obj, this); } else if (obj instanceof Object[]) { // extension return new NativeArray((Object[])obj); } else if (obj instanceof double[]) { // extension return new NativeArray((double[])obj); } else if (obj instanceof long[]) { return new NativeArray((long[])obj); } else if (obj instanceof int[]) { return new NativeArray((int[])obj); } else { // FIXME: more special cases? Map? List? return obj; } }
@SuppressWarnings("unused") private static Double toDouble(final Object obj0) { // TODO - Order tests for performance. for (Object obj = obj0; ;) { if (obj == null) { return null; } else if (obj instanceof Double) { return (Double) obj; } else if (obj instanceof Number) { return ((Number)obj).doubleValue(); } else if (obj instanceof String) { return JSType.toNumber((String) obj); } else if (obj instanceof ConsString) { return JSType.toNumber(obj.toString()); } else if (obj instanceof Boolean) { return (Boolean) obj ? 1 : +0.0; } else if (obj instanceof ScriptObject) { obj = JSType.toPrimitive(obj, Number.class); continue; } else if (obj == UNDEFINED) { return Double.NaN; } throw assertUnexpectedType(obj); } }
@SuppressWarnings("unused") private static Number toNumber(final Object obj0) { // TODO - Order tests for performance. for (Object obj = obj0; ;) { if (obj == null) { return null; } else if (obj instanceof Number) { return (Number) obj; } else if (obj instanceof String) { return JSType.toNumber((String) obj); } else if (obj instanceof ConsString) { return JSType.toNumber(obj.toString()); } else if (obj instanceof Boolean) { return (Boolean) obj ? 1 : +0.0; } else if (obj instanceof ScriptObject) { obj = JSType.toPrimitive(obj, Number.class); continue; } else if (obj == UNDEFINED) { return Double.NaN; } throw assertUnexpectedType(obj); } }
/** * Make a script object mirror on given object if needed. * * @param obj object to be wrapped/converted * @param homeGlobal global to which this object belongs. * @param jsonCompatible if true, the created wrapper will implement the Java {@code List} interface if * {@code obj} is a JavaScript {@code Array} object. Arrays retrieved through its properties (transitively) * will also implement the list interface. * @return wrapped/converted object */ private static Object wrap(final Object obj, final Object homeGlobal, final boolean jsonCompatible) { if(obj instanceof ScriptObject) { if (!(homeGlobal instanceof Global)) { return obj; } final ScriptObject sobj = (ScriptObject)obj; final Global global = (Global)homeGlobal; final ScriptObjectMirror mirror = new ScriptObjectMirror(sobj, global, jsonCompatible); if (jsonCompatible && sobj.isArray()) { return new JSONListAdapter(mirror, global); } return mirror; } else if(obj instanceof ConsString) { return obj.toString(); } else if (jsonCompatible && obj instanceof ScriptObjectMirror) { // Since choosing JSON compatible representation is an explicit decision on user's part, if we're asked to // wrap a mirror that was not JSON compatible, explicitly create its compatible counterpart following the // principle of least surprise. return ((ScriptObjectMirror)obj).asJSONCompatible(); } return obj; }
/** * Test toString conversion */ @Test public void testConsStringToString() { final ConsString cs1 = new ConsString("b", "c"); final ConsString cs2 = new ConsString("d", "e"); final ConsString cs3 = new ConsString(cs1, cs2); final ConsString cs4 = new ConsString(cs3, "f"); final ConsString cs5 = new ConsString("a", cs4); assertEquals(cs5.toString(), "abcdef"); assertEquals(cs4.toString(), "bcdef"); assertEquals(cs3.toString(), "bcde"); assertEquals(cs2.toString(), "de"); assertEquals(cs1.toString(), "bc"); // ConsStrings should be flattened now assertEquals(cs1.getComponents()[0], "bc"); assertEquals(cs1.getComponents()[1], ""); assertEquals(cs2.getComponents()[0], "de"); assertEquals(cs2.getComponents()[1], ""); assertEquals(cs3.getComponents()[0], "bcde"); assertEquals(cs3.getComponents()[1], ""); assertEquals(cs4.getComponents()[0], "bcdef"); assertEquals(cs4.getComponents()[1], ""); assertEquals(cs5.getComponents()[0], "abcdef"); assertEquals(cs5.getComponents()[1], ""); }
/** * Test charAt */ @Test public void testConsStringCharAt() { final ConsString cs1 = new ConsString("b", "c"); final ConsString cs2 = new ConsString("d", "e"); final ConsString cs3 = new ConsString(cs1, cs2); final ConsString cs4 = new ConsString(cs3, "f"); final ConsString cs5 = new ConsString("a", cs4); assertEquals(cs1.charAt(1), 'c'); assertEquals(cs2.charAt(0), 'd'); assertEquals(cs3.charAt(3), 'e'); assertEquals(cs4.charAt(1), 'c'); assertEquals(cs5.charAt(2), 'c'); // ConsStrings should be flattened now assertEquals(cs1.getComponents()[0], "bc"); assertEquals(cs1.getComponents()[1], ""); assertEquals(cs2.getComponents()[0], "de"); assertEquals(cs2.getComponents()[1], ""); assertEquals(cs3.getComponents()[0], "bcde"); assertEquals(cs3.getComponents()[1], ""); assertEquals(cs4.getComponents()[0], "bcdef"); assertEquals(cs4.getComponents()[1], ""); assertEquals(cs5.getComponents()[0], "abcdef"); assertEquals(cs5.getComponents()[1], ""); }
/** * Make a script object mirror on given object if needed. Also converts ConsString instances to Strings. * * @param obj object to be wrapped/converted * @param homeGlobal global to which this object belongs. Not used for ConsStrings. * @param jsonCompatible if true, the created wrapper will implement the Java {@code List} interface if * {@code obj} is a JavaScript {@code Array} object. Arrays retrieved through its properties (transitively) * will also implement the list interface. * @return wrapped/converted object */ private static Object wrap(final Object obj, final Object homeGlobal, final boolean jsonCompatible) { if(obj instanceof ScriptObject) { if (!(homeGlobal instanceof Global)) { return obj; } final ScriptObject sobj = (ScriptObject)obj; final Global global = (Global)homeGlobal; final ScriptObjectMirror mirror = new ScriptObjectMirror(sobj, global, jsonCompatible); if (jsonCompatible && sobj.isArray()) { return new JSONListAdapter(mirror, global); } return mirror; } else if(obj instanceof ConsString) { return obj.toString(); } else if (jsonCompatible && obj instanceof ScriptObjectMirror) { // Since choosing JSON compatible representation is an explicit decision on user's part, if we're asked to // wrap a mirror that was not JSON compatible, explicitly create its compatible counterpart following the // principle of least surprise. return ((ScriptObjectMirror)obj).asJSONCompatible(); } return obj; }
@Override public Object wrapAsObject(final Object obj) { if (obj instanceof Boolean) { return new NativeBoolean((Boolean)obj, this); } else if (obj instanceof Number) { return new NativeNumber(((Number)obj).doubleValue(), this); } else if (obj instanceof String || obj instanceof ConsString) { return new NativeString((CharSequence)obj, this); } else if (obj instanceof Object[]) { // extension return new NativeArray((Object[])obj); } else if (obj instanceof double[]) { // extension return new NativeArray((double[])obj); } else if (obj instanceof long[]) { return new NativeArray((long[])obj); } else if (obj instanceof int[]) { return new NativeArray((int[])obj); } else { // FIXME: more special cases? Map? List? return obj; } }
private static String toString(final Object obj0) { for (Object obj = obj0; ;) { if (obj == null) { return null; } else if (obj instanceof String) { return (String) obj; } else if (obj instanceof ConsString) { return obj.toString(); } else if (obj instanceof Number) { return JSType.toString(((Number)obj).doubleValue()); } else if (obj instanceof Boolean) { return ((Boolean) obj).toString(); } else if (obj == UNDEFINED) { return "undefined"; } else if (obj instanceof ScriptObject) { obj = JSType.toPrimitive(obj, String.class); continue; } throw assertUnexpectedType(obj); } }
private static Long toLong(final Object obj0) { // TODO - Order tests for performance. for (Object obj = obj0; ;) { if (obj == null) { return null; } else if (obj instanceof Long) { return (Long) obj; } else if (obj instanceof Number) { return ((Number)obj).longValue(); } else if (obj instanceof String || obj instanceof ConsString) { return JSType.toLong(obj); } else if (obj instanceof Boolean) { return (Boolean)obj ? 1L : 0L; } else if (obj instanceof ScriptObject) { obj = JSType.toPrimitive(obj, Number.class); continue; } else if (obj == UNDEFINED) { return null; // null or 0L? } throw assertUnexpectedType(obj); } }