/* * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package jdk.nashorn.internal.runtime.arrays; import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.ScriptRuntime; import jdk.nashorn.internal.runtime.linker.Bootstrap; /** * Helper class for the various map/apply functions in {@link jdk.nashorn.internal.objects.NativeArray}. * @param element type of results from application callback */ public abstract class IteratorAction { /** Self object */ protected final Object self; /** This for the callback invocation */ protected Object thisArg; /** Callback function to be applied to elements */ protected final Object callbackfn; /** Result of array iteration */ protected T result; /** Current array index of iterator */ protected long index; /** Iterator object */ private final ArrayLikeIterator iter; /** * Constructor * * @param self self reference to array object * @param callbackfn callback function for each element * @param thisArg the reference * @param initialResult result accumulator initialization */ public IteratorAction(final Object self, final Object callbackfn, final Object thisArg, final T initialResult) { this(self, callbackfn, thisArg, initialResult, ArrayLikeIterator.arrayLikeIterator(self)); } /** * Constructor * * @param self self reference to array object * @param callbackfn callback function for each element * @param thisArg the reference * @param initialResult result accumulator initialization * @param iter custom element iterator */ public IteratorAction(final Object self, final Object callbackfn, final Object thisArg, final T initialResult, final ArrayLikeIterator iter) { this.self = self; this.callbackfn = callbackfn; this.result = initialResult; this.iter = iter; this.thisArg = thisArg; } /** * An action to be performed once at the start of the apply loop * @param iterator array element iterator */ protected void applyLoopBegin(final ArrayLikeIterator iterator) { //empty } /** * Apply action main loop. * @return result of apply */ public final T apply() { final boolean strict = Bootstrap.isStrictCallable(callbackfn); // for non-strict callback, need to translate undefined thisArg to be global object thisArg = (thisArg == ScriptRuntime.UNDEFINED && !strict)? Context.getGlobal() : thisArg; applyLoopBegin(iter); final boolean reverse = iter.isReverse(); while (iter.hasNext()) { final Object val = iter.next(); index = iter.nextIndex() + (reverse ? 1 : -1); try { if (!forEach(val, index)) { return result; } } catch (final RuntimeException | Error e) { throw e; } catch (final Throwable t) { throw new RuntimeException(t); } } return result; } /** * For each callback * * @param val value * @param i position of value * * @return true if callback invocation return true * * @throws Throwable if invocation throws an exception/error */ protected abstract boolean forEach(final Object val, final double i) throws Throwable; }