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 jdk.nashorn.internal.runtime.Context;
29 import jdk.nashorn.internal.runtime.ScriptRuntime;
30 import jdk.nashorn.internal.runtime.linker.Bootstrap;
31
32 /**
33 * Helper class for the various map/apply functions in {@link jdk.nashorn.internal.objects.NativeArray}.
34 * @param <T> element type of results from application callback
35 */
36 public abstract class IteratorAction<T> {
37 /** Self object */
38 protected final Object self;
39
40 /** This for the callback invocation */
41 protected Object thisArg;
42
43 /** Callback function to be applied to elements */
44 protected final Object callbackfn;
45
46 /** Result of array iteration */
47 protected T result;
48
49 /** Current array index of iterator */
50 protected long index;
51
52 /** Iterator object */
53 private final ArrayLikeIterator<Object> iter;
54
55 /**
56 * Constructor
57 *
58 * @param self self reference to array object
59 * @param callbackfn callback function for each element
60 * @param thisArg the reference
61 * @param initialResult result accumulator initialization
62 */
63 public IteratorAction(final Object self, final Object callbackfn, final Object thisArg, final T initialResult) {
64 this(self, callbackfn, thisArg, initialResult, ArrayLikeIterator.arrayLikeIterator(self));
65 }
66
67 /**
68 * Constructor
69 *
70 * @param self self reference to array object
71 * @param callbackfn callback function for each element
72 * @param thisArg the reference
73 * @param initialResult result accumulator initialization
74 * @param iter custom element iterator
75 */
76 public IteratorAction(final Object self, final Object callbackfn, final Object thisArg, final T initialResult, final ArrayLikeIterator<Object> iter) {
77 this.self = self;
78 this.callbackfn = callbackfn;
79 this.result = initialResult;
80 this.iter = iter;
81 this.thisArg = thisArg;
82 }
83
84 /**
85 * An action to be performed once at the start of the apply loop
86 * @param iterator array element iterator
87 */
88 protected void applyLoopBegin(final ArrayLikeIterator<Object> iterator) {
89 //empty
90 }
91
92 /**
93 * Apply action main loop.
94 * @return result of apply
95 */
96 public final T apply() {
97 final boolean strict = Bootstrap.isStrictCallable(callbackfn);
98
99 // for non-strict callback, need to translate undefined thisArg to be global object
100 thisArg = (thisArg == ScriptRuntime.UNDEFINED && !strict)? Context.getGlobal() : thisArg;
101
102 applyLoopBegin(iter);
103 final boolean reverse = iter.isReverse();
104 while (iter.hasNext()) {
105
106 final Object val = iter.next();
107 index = iter.nextIndex() + (reverse ? 1 : -1);
108
109 try {
110 if (!forEach(val, index)) {
111 return result;
112 }
113 } catch (final RuntimeException | Error e) {
114 throw e;
115 } catch (final Throwable t) {
116 throw new RuntimeException(t);
117 }
118 }
119
120 return result;
121 }
122
123 /**
124 * For each callback
125 *
126 * @param val value
127 * @param i position of value
128 *
129 * @return true if callback invocation return true
130 *
131 * @throws Throwable if invocation throws an exception/error
132 */
133 protected abstract boolean forEach(final Object val, final double i) throws Throwable;
134
135 }
--- EOF ---