IteratorAction.java revision 1116:ad912b034639
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
26package jdk.nashorn.internal.runtime.arrays;
27
28import jdk.nashorn.internal.runtime.Context;
29import jdk.nashorn.internal.runtime.ScriptRuntime;
30import 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 */
36public 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 long i) throws Throwable;
134
135}
136