1 /* 2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.nashorn.internal.runtime.arrays; 27 28 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 29 30 import jdk.nashorn.internal.runtime.Context; 31 import jdk.nashorn.internal.runtime.ScriptFunction; 32 import jdk.nashorn.internal.runtime.ScriptRuntime; 33 34 /** 35 * Helper class for the various map/apply functions in {@link jdk.nashorn.internal.objects.NativeArray}. 36 * @param <T> element type of results from application callback 37 */ 38 public abstract class IteratorAction<T> { 39 /** Self object */ 40 protected final Object self; 41 42 /** This for the callback invocation */ 43 protected Object thisArg; 44 45 /** Callback function to be applied to elements */ 46 protected final Object callbackfn; 47 48 /** Result of array iteration */ 49 protected T result; 50 51 /** Current array index of iterator */ 52 protected long index; 53 54 /** Iterator object */ 55 private final ArrayLikeIterator<Object> iter; 56 57 /** 58 * Constructor 59 * 60 * @param self self reference to array object 61 * @param callbackfn callback function for each element 62 * @param thisArg the reference 63 * @param initialResult result accumulator initialization 64 */ 65 public IteratorAction(final Object self, final Object callbackfn, final Object thisArg, final T initialResult) { 66 this(self, callbackfn, thisArg, initialResult, ArrayLikeIterator.arrayLikeIterator(self)); 67 } 68 69 /** 70 * Constructor 71 * 72 * @param self self reference to array object 73 * @param callbackfn callback function for each element 74 * @param thisArg the reference 75 * @param initialResult result accumulator initialization 76 * @param iter custom element iterator 77 */ 78 public IteratorAction(final Object self, final Object callbackfn, final Object thisArg, final T initialResult, final ArrayLikeIterator<Object> iter) { 79 this.self = self; 80 this.callbackfn = callbackfn; 81 this.result = initialResult; 82 this.iter = iter; 83 this.thisArg = thisArg; 84 } 85 86 /** 87 * An action to be performed once at the start of the apply loop 88 * @param iterator array element iterator 89 */ 90 protected void applyLoopBegin(final ArrayLikeIterator<Object> iterator) { 91 //empty 92 } 93 94 /** 95 * Apply action main loop. 96 * @return result of apply 97 */ 98 public final T apply() { 99 if (!(callbackfn instanceof ScriptFunction)) { 100 throw typeError("not.a.function", ScriptRuntime.safeToString(callbackfn)); 101 } 102 final ScriptFunction func = ((ScriptFunction)callbackfn); 103 // for non-strict callback, need to translate undefined thisArg to be global object 104 thisArg = (thisArg == ScriptRuntime.UNDEFINED && !func.isStrict()) ? Context.getGlobal() : thisArg; 105 106 applyLoopBegin(iter); 107 final boolean reverse = iter.isReverse(); 108 while (iter.hasNext()) { 109 110 final Object val = iter.next(); 111 index = iter.nextIndex() + (reverse ? 1 : -1); 112 113 try { 114 if (!forEach(val, index)) { 115 return result; 116 } 117 } catch (final RuntimeException | Error e) { 118 throw e; 119 } catch (final Throwable t) { 120 throw new RuntimeException(t); 121 } 122 } 123 124 return result; 125 } 126 127 /** 128 * For each callback 129 * 130 * @param val value 131 * @param i position of value 132 * 133 * @return true if callback invocation return true 134 * 135 * @throws Throwable if invocation throws an exception/error 136 */ 137 protected abstract boolean forEach(final Object val, final long i) throws Throwable; 138 139 } --- EOF ---