@Override public Iterator<String> propertyIterator() { // Try __getIds__ first, if not found then try __getKeys__ // In jdk6, we had added "__getIds__" so this is just for compatibility. Object func = adaptee.get(__getIds__); if (!(func instanceof ScriptFunction)) { func = adaptee.get(__getKeys__); } Object obj; if (func instanceof ScriptFunction) { obj = ScriptRuntime.apply((ScriptFunction)func, adaptee); } else { obj = new NativeArray(0); } final List<String> array = new ArrayList<>(); for (final Iterator<Object> iter = ArrayLikeIterator.arrayLikeIterator(obj); iter.hasNext(); ) { array.add((String)iter.next()); } return array.iterator(); }
/** * ECMA 15.4.4.19 Array.prototype.map ( callbackfn [ , thisArg ] ) * * @param self self reference * @param callbackfn callback function per element * @param thisArg this argument * @return array with elements transformed by map function */ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1) public static NativeArray map(final Object self, final Object callbackfn, final Object thisArg) { return new IteratorAction<NativeArray>(Global.toObject(self), callbackfn, thisArg, null) { private final MethodHandle mapInvoker = getMAP_CALLBACK_INVOKER(); @Override protected boolean forEach(final Object val, final long i) throws Throwable { final Object r = mapInvoker.invokeExact(callbackfn, thisArg, val, i, self); result.defineOwnProperty(ArrayIndex.getArrayIndex(index), r); return true; } @Override public void applyLoopBegin(final ArrayLikeIterator<Object> iter0) { // map return array should be of same length as source array // even if callback reduces source array length result = new NativeArray(iter0.getLength()); } }.apply(); }
@Override public Iterator<String> propertyIterator() { // Try __getIds__ first, if not found then try __getKeys__ // In jdk6, we had added "__getIds__" so this is just for compatibility. Object func = adaptee.get(__getIds__); if (!(func instanceof ScriptFunction)) { func = adaptee.get(__getKeys__); } Object obj; if (func instanceof ScriptFunction) { obj = ScriptRuntime.apply((ScriptFunction)func, this); } else { obj = new NativeArray(0); } final List<String> array = new ArrayList<>(); for (final Iterator<Object> iter = ArrayLikeIterator.arrayLikeIterator(obj); iter.hasNext(); ) { array.add((String)iter.next()); } return array.iterator(); }
/** * ECMA 15.4.4.19 Array.prototype.map ( callbackfn [ , thisArg ] ) * * @param self self reference * @param callbackfn callback function per element * @param thisArg this argument * @return array with elements transformed by map function */ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1) public static NativeArray map(final Object self, final Object callbackfn, final Object thisArg) { return new IteratorAction<NativeArray>(Global.toObject(self), callbackfn, thisArg, null) { private final MethodHandle mapInvoker = getMAP_CALLBACK_INVOKER(); @Override protected boolean forEach(final Object val, final double i) throws Throwable { final Object r = mapInvoker.invokeExact(callbackfn, thisArg, val, i, self); result.defineOwnProperty(ArrayIndex.getArrayIndex(index), r); return true; } @Override public void applyLoopBegin(final ArrayLikeIterator<Object> iter0) { // map return array should be of same length as source array // even if callback reduces source array length result = new NativeArray(iter0.getLength()); } }.apply(); }
/** * ECMA 15.4.4.19 Array.prototype.map ( callbackfn [ , thisArg ] ) * * @param self self reference * @param callbackfn callback function per element * @param thisArg this argument * @return array with elements transformed by map function */ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1) public static Object map(final Object self, final Object callbackfn, final Object thisArg) { return new IteratorAction<NativeArray>(Global.toObject(self), callbackfn, thisArg, null) { private final MethodHandle mapInvoker = getMAP_CALLBACK_INVOKER(); @Override protected boolean forEach(final Object val, final long i) throws Throwable { final Object r = mapInvoker.invokeExact(callbackfn, thisArg, val, i, self); result.defineOwnProperty(ArrayIndex.getArrayIndex(index), r); return true; } @Override public void applyLoopBegin(final ArrayLikeIterator<Object> iter0) { // map return array should be of same length as source array // even if callback reduces source array length result = new NativeArray(iter0.getLength()); } }.apply(); }
private static Object reduceInner(final ArrayLikeIterator<Object> iter, final Object self, final Object... args) { final Object callbackfn = args.length > 0 ? args[0] : ScriptRuntime.UNDEFINED; final boolean initialValuePresent = args.length > 1; Object initialValue = initialValuePresent ? args[1] : ScriptRuntime.UNDEFINED; if (callbackfn == ScriptRuntime.UNDEFINED) { throw typeError("not.a.function", "undefined"); } if (!initialValuePresent) { if (iter.hasNext()) { initialValue = iter.next(); } else { throw typeError("array.reduce.invalid.init"); } } //if initial value is ScriptRuntime.UNDEFINED - step forward once. return new IteratorAction<Object>(Global.toObject(self), callbackfn, ScriptRuntime.UNDEFINED, initialValue, iter) { private final MethodHandle reduceInvoker = getREDUCE_CALLBACK_INVOKER(); @Override protected boolean forEach(final Object val, final long i) throws Throwable { // TODO: why can't I declare the second arg as Undefined.class? result = reduceInvoker.invokeExact(callbackfn, ScriptRuntime.UNDEFINED, result, val, i, self); return true; } }.apply(); }
private static Object reduceInner(final ArrayLikeIterator<Object> iter, final Object self, final Object... args) { final Object callbackfn = args.length > 0 ? args[0] : ScriptRuntime.UNDEFINED; final boolean initialValuePresent = args.length > 1; Object initialValue = initialValuePresent ? args[1] : ScriptRuntime.UNDEFINED; if (callbackfn == ScriptRuntime.UNDEFINED) { throw typeError("not.a.function", "undefined"); } if (!initialValuePresent) { if (iter.hasNext()) { initialValue = iter.next(); } else { throw typeError("array.reduce.invalid.init"); } } //if initial value is ScriptRuntime.UNDEFINED - step forward once. return new IteratorAction<Object>(Global.toObject(self), callbackfn, ScriptRuntime.UNDEFINED, initialValue, iter) { private final MethodHandle reduceInvoker = getREDUCE_CALLBACK_INVOKER(); @Override protected boolean forEach(final Object val, final double i) throws Throwable { // TODO: why can't I declare the second arg as Undefined.class? result = reduceInvoker.invokeExact(callbackfn, ScriptRuntime.UNDEFINED, result, val, i, self); return true; } }.apply(); }
/** * Converts {@code result} to a printable string. The reason we don't use {@link JSType#toString(Object)} * or {@link ScriptRuntime#safeToString(Object)} is that we want to be able to render Symbol values * even if they occur within an Array, and therefore have to implement our own Array to String * conversion. * * @param result the result * @param global the global object * @return the string representation */ protected static String toString(final Object result, final Global global) { if (result instanceof Symbol) { // Normal implicit conversion of symbol to string would throw TypeError return result.toString(); } if (result instanceof NativeSymbol) { return JSType.toPrimitive(result).toString(); } if (isArrayWithDefaultToString(result, global)) { // This should yield the same string as Array.prototype.toString but // will not throw if the array contents include symbols. final StringBuilder sb = new StringBuilder(); final Iterator<Object> iter = ArrayLikeIterator.arrayLikeIterator(result, true); while (iter.hasNext()) { final Object obj = iter.next(); if (obj != null && obj != ScriptRuntime.UNDEFINED) { sb.append(toString(obj, global)); } if (iter.hasNext()) { sb.append(','); } } return sb.toString(); } return JSType.toString(result); }
@Override public Iterator<Object> valueIterator() { final Object obj = callAdaptee(new NativeArray(0), __getValues__); return ArrayLikeIterator.arrayLikeIterator(obj); }