src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ListAdapter.java
author hannesw
Wed, 21 Mar 2018 16:55:34 +0100
changeset 49275 c639a6b33c5c
parent 47216 71c04702a3d5
permissions -rw-r--r--
8199869: Missing copyright headers in nashorn source code Reviewed-by: sundar
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
18845
6bfb1bcec75e 8019814: Add regression test for passing cases
sundar
parents: 17982
diff changeset
     1
/*
6bfb1bcec75e 8019814: Add regression test for passing cases
sundar
parents: 17982
diff changeset
     2
 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
6bfb1bcec75e 8019814: Add regression test for passing cases
sundar
parents: 17982
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6bfb1bcec75e 8019814: Add regression test for passing cases
sundar
parents: 17982
diff changeset
     4
 *
6bfb1bcec75e 8019814: Add regression test for passing cases
sundar
parents: 17982
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
6bfb1bcec75e 8019814: Add regression test for passing cases
sundar
parents: 17982
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
6bfb1bcec75e 8019814: Add regression test for passing cases
sundar
parents: 17982
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
6bfb1bcec75e 8019814: Add regression test for passing cases
sundar
parents: 17982
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
6bfb1bcec75e 8019814: Add regression test for passing cases
sundar
parents: 17982
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
6bfb1bcec75e 8019814: Add regression test for passing cases
sundar
parents: 17982
diff changeset
    10
 *
6bfb1bcec75e 8019814: Add regression test for passing cases
sundar
parents: 17982
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
6bfb1bcec75e 8019814: Add regression test for passing cases
sundar
parents: 17982
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
6bfb1bcec75e 8019814: Add regression test for passing cases
sundar
parents: 17982
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
6bfb1bcec75e 8019814: Add regression test for passing cases
sundar
parents: 17982
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
6bfb1bcec75e 8019814: Add regression test for passing cases
sundar
parents: 17982
diff changeset
    15
 * accompanied this code).
6bfb1bcec75e 8019814: Add regression test for passing cases
sundar
parents: 17982
diff changeset
    16
 *
6bfb1bcec75e 8019814: Add regression test for passing cases
sundar
parents: 17982
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
6bfb1bcec75e 8019814: Add regression test for passing cases
sundar
parents: 17982
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
6bfb1bcec75e 8019814: Add regression test for passing cases
sundar
parents: 17982
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
6bfb1bcec75e 8019814: Add regression test for passing cases
sundar
parents: 17982
diff changeset
    20
 *
6bfb1bcec75e 8019814: Add regression test for passing cases
sundar
parents: 17982
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
6bfb1bcec75e 8019814: Add regression test for passing cases
sundar
parents: 17982
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
6bfb1bcec75e 8019814: Add regression test for passing cases
sundar
parents: 17982
diff changeset
    23
 * questions.
6bfb1bcec75e 8019814: Add regression test for passing cases
sundar
parents: 17982
diff changeset
    24
 */
6bfb1bcec75e 8019814: Add regression test for passing cases
sundar
parents: 17982
diff changeset
    25
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
    26
package jdk.nashorn.internal.runtime;
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
    27
30832
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
    28
import java.lang.invoke.MethodHandle;
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
    29
import java.util.AbstractList;
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
    30
import java.util.Deque;
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
    31
import java.util.Iterator;
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
    32
import java.util.ListIterator;
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
    33
import java.util.NoSuchElementException;
30832
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
    34
import java.util.Objects;
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
    35
import java.util.RandomAccess;
19456
8cc345d620c8 8022524: Memory leaks in nashorn sources and tests found by jhat analysis
sundar
parents: 19105
diff changeset
    36
import java.util.concurrent.Callable;
19897
4235a28bb5e8 8024847: Java.to should accept mirror and external JSObjects as array-like objects as well
sundar
parents: 19456
diff changeset
    37
import jdk.nashorn.api.scripting.JSObject;
21454
f165bf93bb48 8027150: ScriptObjectListAdapter won't work as expected
sundar
parents: 20933
diff changeset
    38
import jdk.nashorn.api.scripting.ScriptObjectMirror;
30834
ecffc563dfcf 8081204: ListAdapter throws NPE when adding/removing elements outside of JS context
attila
parents: 30832
diff changeset
    39
import jdk.nashorn.internal.objects.Global;
19088
153f268bfa72 8021122: Not all callables are handled for toString and other function valued properties
sundar
parents: 18845
diff changeset
    40
import jdk.nashorn.internal.runtime.linker.Bootstrap;
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
    41
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
    42
/**
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
    43
 * An adapter that can wrap any ECMAScript Array-like object (that adheres to the array rules for the property
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
    44
 * {@code length} and having conforming {@code push}, {@code pop}, {@code shift}, {@code unshift}, and {@code splice}
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
    45
 * methods) and expose it as both a Java list and double-ended queue. While script arrays aren't necessarily efficient
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
    46
 * as dequeues, it's still slightly more efficient to be able to translate dequeue operations into pushes, pops, shifts,
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
    47
 * and unshifts, than to blindly translate all list's add/remove operations into splices. Also, it is conceivable that a
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
    48
 * custom script object that implements an Array-like API can have a background data representation that is optimized
17982
03696682b6e5 8015961: Several small code-gardening fixes
attila
parents: 17765
diff changeset
    49
 * for dequeue-like access. Note that with ECMAScript arrays, {@code push} and {@code pop} operate at the end of the
03696682b6e5 8015961: Several small code-gardening fixes
attila
parents: 17765
diff changeset
    50
 * array, while in Java {@code Deque} they operate on the front of the queue and as such the Java dequeue
03696682b6e5 8015961: Several small code-gardening fixes
attila
parents: 17765
diff changeset
    51
 * {@link #push(Object)} and {@link #pop()} operations will translate to {@code unshift} and {@code shift} script
03696682b6e5 8015961: Several small code-gardening fixes
attila
parents: 17765
diff changeset
    52
 * operations respectively, while {@link #addLast(Object)} and {@link #removeLast()} will translate to {@code push} and
03696682b6e5 8015961: Several small code-gardening fixes
attila
parents: 17765
diff changeset
    53
 * {@code pop}.
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
    54
 */
30977
4a7a2f339176 8066773: JSON-friendly wrapper for objects
attila
parents: 30834
diff changeset
    55
public class ListAdapter extends AbstractList<Object> implements RandomAccess, Deque<Object> {
30832
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
    56
    // Invoker creator for methods that add to the start or end of the list: PUSH and UNSHIFT. Takes fn, this, and value, returns void.
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
    57
    private static final Callable<MethodHandle> ADD_INVOKER_CREATOR = invokerCreator(void.class, Object.class, JSObject.class, Object.class);
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
    58
30834
ecffc563dfcf 8081204: ListAdapter throws NPE when adding/removing elements outside of JS context
attila
parents: 30832
diff changeset
    59
    // PUSH adds to the start of the list
30832
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
    60
    private static final Object PUSH = new Object();
30834
ecffc563dfcf 8081204: ListAdapter throws NPE when adding/removing elements outside of JS context
attila
parents: 30832
diff changeset
    61
    // UNSHIFT adds to the end of the list
19456
8cc345d620c8 8022524: Memory leaks in nashorn sources and tests found by jhat analysis
sundar
parents: 19105
diff changeset
    62
    private static final Object UNSHIFT = new Object();
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
    63
30832
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
    64
    // Invoker creator for methods that remove from the tail or head of the list: POP and SHIFT. Takes fn, this, returns Object.
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
    65
    private static final Callable<MethodHandle> REMOVE_INVOKER_CREATOR = invokerCreator(Object.class, Object.class, JSObject.class);
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
    66
30834
ecffc563dfcf 8081204: ListAdapter throws NPE when adding/removing elements outside of JS context
attila
parents: 30832
diff changeset
    67
    // POP removes from the start of the list
19456
8cc345d620c8 8022524: Memory leaks in nashorn sources and tests found by jhat analysis
sundar
parents: 19105
diff changeset
    68
    private static final Object POP = new Object();
30834
ecffc563dfcf 8081204: ListAdapter throws NPE when adding/removing elements outside of JS context
attila
parents: 30832
diff changeset
    69
    // SHIFT removes from the end of the list
19456
8cc345d620c8 8022524: Memory leaks in nashorn sources and tests found by jhat analysis
sundar
parents: 19105
diff changeset
    70
    private static final Object SHIFT = new Object();
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
    71
30832
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
    72
    // SPLICE can be used to add a value in the middle of the list.
19456
8cc345d620c8 8022524: Memory leaks in nashorn sources and tests found by jhat analysis
sundar
parents: 19105
diff changeset
    73
    private static final Object SPLICE_ADD = new Object();
30832
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
    74
    private static final Callable<MethodHandle> SPLICE_ADD_INVOKER_CREATOR = invokerCreator(void.class, Object.class, JSObject.class, int.class, int.class, Object.class);
19456
8cc345d620c8 8022524: Memory leaks in nashorn sources and tests found by jhat analysis
sundar
parents: 19105
diff changeset
    75
30832
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
    76
    // SPLICE can also be used to remove values from the middle of the list.
19456
8cc345d620c8 8022524: Memory leaks in nashorn sources and tests found by jhat analysis
sundar
parents: 19105
diff changeset
    77
    private static final Object SPLICE_REMOVE = new Object();
30832
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
    78
    private static final Callable<MethodHandle> SPLICE_REMOVE_INVOKER_CREATOR = invokerCreator(void.class, Object.class, JSObject.class, int.class, int.class);
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
    79
20933
89748612fd1d 8026250: Logging nullpointer bugfix and javadoc warnings
lagergren
parents: 19897
diff changeset
    80
    /** wrapped object */
30977
4a7a2f339176 8066773: JSON-friendly wrapper for objects
attila
parents: 30834
diff changeset
    81
    final JSObject obj;
30834
ecffc563dfcf 8081204: ListAdapter throws NPE when adding/removing elements outside of JS context
attila
parents: 30832
diff changeset
    82
    private final Global global;
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
    83
19897
4235a28bb5e8 8024847: Java.to should accept mirror and external JSObjects as array-like objects as well
sundar
parents: 19456
diff changeset
    84
    // allow subclasses only in this package
30977
4a7a2f339176 8066773: JSON-friendly wrapper for objects
attila
parents: 30834
diff changeset
    85
    ListAdapter(final JSObject obj, final Global global) {
4a7a2f339176 8066773: JSON-friendly wrapper for objects
attila
parents: 30834
diff changeset
    86
        if (global == null) {
4a7a2f339176 8066773: JSON-friendly wrapper for objects
attila
parents: 30834
diff changeset
    87
            throw new IllegalStateException(ECMAErrors.getMessage("list.adapter.null.global"));
4a7a2f339176 8066773: JSON-friendly wrapper for objects
attila
parents: 30834
diff changeset
    88
        }
30834
ecffc563dfcf 8081204: ListAdapter throws NPE when adding/removing elements outside of JS context
attila
parents: 30832
diff changeset
    89
30977
4a7a2f339176 8066773: JSON-friendly wrapper for objects
attila
parents: 30834
diff changeset
    90
        this.obj = obj;
4a7a2f339176 8066773: JSON-friendly wrapper for objects
attila
parents: 30834
diff changeset
    91
        this.global = global;
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
    92
    }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
    93
19897
4235a28bb5e8 8024847: Java.to should accept mirror and external JSObjects as array-like objects as well
sundar
parents: 19456
diff changeset
    94
    /**
4235a28bb5e8 8024847: Java.to should accept mirror and external JSObjects as array-like objects as well
sundar
parents: 19456
diff changeset
    95
     * Factory to create a ListAdapter for a given script object.
4235a28bb5e8 8024847: Java.to should accept mirror and external JSObjects as array-like objects as well
sundar
parents: 19456
diff changeset
    96
     *
4235a28bb5e8 8024847: Java.to should accept mirror and external JSObjects as array-like objects as well
sundar
parents: 19456
diff changeset
    97
     * @param obj script object to wrap as a ListAdapter
4235a28bb5e8 8024847: Java.to should accept mirror and external JSObjects as array-like objects as well
sundar
parents: 19456
diff changeset
    98
     * @return A ListAdapter wrapper object
4235a28bb5e8 8024847: Java.to should accept mirror and external JSObjects as array-like objects as well
sundar
parents: 19456
diff changeset
    99
     */
4235a28bb5e8 8024847: Java.to should accept mirror and external JSObjects as array-like objects as well
sundar
parents: 19456
diff changeset
   100
    public static ListAdapter create(final Object obj) {
30977
4a7a2f339176 8066773: JSON-friendly wrapper for objects
attila
parents: 30834
diff changeset
   101
        final Global global = Context.getGlobal();
4a7a2f339176 8066773: JSON-friendly wrapper for objects
attila
parents: 30834
diff changeset
   102
        return new ListAdapter(getJSObject(obj, global), global);
30832
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
   103
    }
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
   104
30977
4a7a2f339176 8066773: JSON-friendly wrapper for objects
attila
parents: 30834
diff changeset
   105
    private static JSObject getJSObject(final Object obj, final Global global) {
19897
4235a28bb5e8 8024847: Java.to should accept mirror and external JSObjects as array-like objects as well
sundar
parents: 19456
diff changeset
   106
        if (obj instanceof ScriptObject) {
30977
4a7a2f339176 8066773: JSON-friendly wrapper for objects
attila
parents: 30834
diff changeset
   107
            return (JSObject)ScriptObjectMirror.wrap(obj, global);
19897
4235a28bb5e8 8024847: Java.to should accept mirror and external JSObjects as array-like objects as well
sundar
parents: 19456
diff changeset
   108
        } else if (obj instanceof JSObject) {
30832
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
   109
            return (JSObject)obj;
19897
4235a28bb5e8 8024847: Java.to should accept mirror and external JSObjects as array-like objects as well
sundar
parents: 19456
diff changeset
   110
        }
30832
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
   111
        throw new IllegalArgumentException("ScriptObject or JSObject expected");
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   112
    }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   113
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   114
    @Override
20933
89748612fd1d 8026250: Logging nullpointer bugfix and javadoc warnings
lagergren
parents: 19897
diff changeset
   115
    public final Object get(final int index) {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   116
        checkRange(index);
19897
4235a28bb5e8 8024847: Java.to should accept mirror and external JSObjects as array-like objects as well
sundar
parents: 19456
diff changeset
   117
        return getAt(index);
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   118
    }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   119
30832
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
   120
    private Object getAt(final int index) {
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
   121
        return obj.getSlot(index);
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
   122
    }
19897
4235a28bb5e8 8024847: Java.to should accept mirror and external JSObjects as array-like objects as well
sundar
parents: 19456
diff changeset
   123
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   124
    @Override
20933
89748612fd1d 8026250: Logging nullpointer bugfix and javadoc warnings
lagergren
parents: 19897
diff changeset
   125
    public Object set(final int index, final Object element) {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   126
        checkRange(index);
19897
4235a28bb5e8 8024847: Java.to should accept mirror and external JSObjects as array-like objects as well
sundar
parents: 19456
diff changeset
   127
        final Object prevValue = getAt(index);
30832
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
   128
        obj.setSlot(index, element);
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   129
        return prevValue;
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   130
    }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   131
24731
ab0c8fc915ae 8038406: Testability: as a first step of moving loggers away from the process global space, the Debug object now supports logging POJOs from log entries as an event queue, which can be introspected from test scripts. This is way better than screen scraping brittle and subject-to-change log output.
lagergren
parents: 23375
diff changeset
   132
    private void checkRange(final int index) {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   133
        if(index < 0 || index >= size()) {
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   134
            throw invalidIndex(index);
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   135
        }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   136
    }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   137
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   138
    @Override
30832
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
   139
    public int size() {
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
   140
        return JSType.toInt32(obj.getMember("length"));
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
   141
    }
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
   142
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
   143
    @Override
20933
89748612fd1d 8026250: Logging nullpointer bugfix and javadoc warnings
lagergren
parents: 19897
diff changeset
   144
    public final void push(final Object e) {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   145
        addFirst(e);
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   146
    }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   147
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   148
    @Override
20933
89748612fd1d 8026250: Logging nullpointer bugfix and javadoc warnings
lagergren
parents: 19897
diff changeset
   149
    public final boolean add(final Object e) {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   150
        addLast(e);
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   151
        return true;
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   152
    }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   153
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   154
    @Override
20933
89748612fd1d 8026250: Logging nullpointer bugfix and javadoc warnings
lagergren
parents: 19897
diff changeset
   155
    public final void addFirst(final Object e) {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   156
        try {
30834
ecffc563dfcf 8081204: ListAdapter throws NPE when adding/removing elements outside of JS context
attila
parents: 30832
diff changeset
   157
            getDynamicInvoker(UNSHIFT, ADD_INVOKER_CREATOR).invokeExact(getFunction("unshift"), obj, e);
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   158
        } catch(RuntimeException | Error ex) {
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   159
            throw ex;
24731
ab0c8fc915ae 8038406: Testability: as a first step of moving loggers away from the process global space, the Debug object now supports logging POJOs from log entries as an event queue, which can be introspected from test scripts. This is way better than screen scraping brittle and subject-to-change log output.
lagergren
parents: 23375
diff changeset
   160
        } catch(final Throwable t) {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   161
            throw new RuntimeException(t);
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   162
        }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   163
    }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   164
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   165
    @Override
20933
89748612fd1d 8026250: Logging nullpointer bugfix and javadoc warnings
lagergren
parents: 19897
diff changeset
   166
    public final void addLast(final Object e) {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   167
        try {
30834
ecffc563dfcf 8081204: ListAdapter throws NPE when adding/removing elements outside of JS context
attila
parents: 30832
diff changeset
   168
            getDynamicInvoker(PUSH, ADD_INVOKER_CREATOR).invokeExact(getFunction("push"), obj, e);
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   169
        } catch(RuntimeException | Error ex) {
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   170
            throw ex;
24731
ab0c8fc915ae 8038406: Testability: as a first step of moving loggers away from the process global space, the Debug object now supports logging POJOs from log entries as an event queue, which can be introspected from test scripts. This is way better than screen scraping brittle and subject-to-change log output.
lagergren
parents: 23375
diff changeset
   171
        } catch(final Throwable t) {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   172
            throw new RuntimeException(t);
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   173
        }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   174
    }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   175
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   176
    @Override
20933
89748612fd1d 8026250: Logging nullpointer bugfix and javadoc warnings
lagergren
parents: 19897
diff changeset
   177
    public final void add(final int index, final Object e) {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   178
        try {
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   179
            if(index < 0) {
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   180
                throw invalidIndex(index);
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   181
            } else if(index == 0) {
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   182
                addFirst(e);
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   183
            } else {
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   184
                final int size = size();
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   185
                if(index < size) {
30834
ecffc563dfcf 8081204: ListAdapter throws NPE when adding/removing elements outside of JS context
attila
parents: 30832
diff changeset
   186
                    getDynamicInvoker(SPLICE_ADD, SPLICE_ADD_INVOKER_CREATOR).invokeExact(obj.getMember("splice"), obj, index, 0, e);
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   187
                } else if(index == size) {
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   188
                    addLast(e);
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   189
                } else {
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   190
                    throw invalidIndex(index);
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   191
                }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   192
            }
20933
89748612fd1d 8026250: Logging nullpointer bugfix and javadoc warnings
lagergren
parents: 19897
diff changeset
   193
        } catch(final RuntimeException | Error ex) {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   194
            throw ex;
20933
89748612fd1d 8026250: Logging nullpointer bugfix and javadoc warnings
lagergren
parents: 19897
diff changeset
   195
        } catch(final Throwable t) {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   196
            throw new RuntimeException(t);
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   197
        }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   198
    }
30832
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
   199
    private Object getFunction(final String name) {
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
   200
        final Object fn = obj.getMember(name);
19088
153f268bfa72 8021122: Not all callables are handled for toString and other function valued properties
sundar
parents: 18845
diff changeset
   201
        if(!(Bootstrap.isCallable(fn))) {
30832
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
   202
            throw new UnsupportedOperationException("The script object doesn't have a function named " + name);
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   203
        }
30832
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
   204
        return fn;
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   205
    }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   206
20933
89748612fd1d 8026250: Logging nullpointer bugfix and javadoc warnings
lagergren
parents: 19897
diff changeset
   207
    private static IndexOutOfBoundsException invalidIndex(final int index) {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   208
        return new IndexOutOfBoundsException(String.valueOf(index));
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   209
    }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   210
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   211
    @Override
20933
89748612fd1d 8026250: Logging nullpointer bugfix and javadoc warnings
lagergren
parents: 19897
diff changeset
   212
    public final boolean offer(final Object e) {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   213
        return offerLast(e);
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   214
    }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   215
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   216
    @Override
20933
89748612fd1d 8026250: Logging nullpointer bugfix and javadoc warnings
lagergren
parents: 19897
diff changeset
   217
    public final boolean offerFirst(final Object e) {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   218
        addFirst(e);
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   219
        return true;
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   220
    }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   221
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   222
    @Override
20933
89748612fd1d 8026250: Logging nullpointer bugfix and javadoc warnings
lagergren
parents: 19897
diff changeset
   223
    public final boolean offerLast(final Object e) {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   224
        addLast(e);
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   225
        return true;
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   226
    }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   227
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   228
    @Override
19897
4235a28bb5e8 8024847: Java.to should accept mirror and external JSObjects as array-like objects as well
sundar
parents: 19456
diff changeset
   229
    public final Object pop() {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   230
        return removeFirst();
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   231
    }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   232
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   233
    @Override
19897
4235a28bb5e8 8024847: Java.to should accept mirror and external JSObjects as array-like objects as well
sundar
parents: 19456
diff changeset
   234
    public final Object remove() {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   235
        return removeFirst();
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   236
    }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   237
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   238
    @Override
19897
4235a28bb5e8 8024847: Java.to should accept mirror and external JSObjects as array-like objects as well
sundar
parents: 19456
diff changeset
   239
    public final Object removeFirst() {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   240
        checkNonEmpty();
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   241
        return invokeShift();
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   242
    }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   243
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   244
    @Override
19897
4235a28bb5e8 8024847: Java.to should accept mirror and external JSObjects as array-like objects as well
sundar
parents: 19456
diff changeset
   245
    public final Object removeLast() {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   246
        checkNonEmpty();
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   247
        return invokePop();
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   248
    }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   249
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   250
    private void checkNonEmpty() {
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   251
        if(isEmpty()) {
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   252
            throw new NoSuchElementException();
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   253
        }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   254
    }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   255
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   256
    @Override
20933
89748612fd1d 8026250: Logging nullpointer bugfix and javadoc warnings
lagergren
parents: 19897
diff changeset
   257
    public final Object remove(final int index) {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   258
        if(index < 0) {
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   259
            throw invalidIndex(index);
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   260
        } else if (index == 0) {
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   261
            return invokeShift();
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   262
        } else {
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   263
            final int maxIndex = size() - 1;
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   264
            if(index < maxIndex) {
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   265
                final Object prevValue = get(index);
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   266
                invokeSpliceRemove(index, 1);
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   267
                return prevValue;
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   268
            } else if(index == maxIndex) {
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   269
                return invokePop();
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   270
            } else {
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   271
                throw invalidIndex(index);
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   272
            }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   273
        }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   274
    }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   275
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   276
    private Object invokeShift() {
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   277
        try {
30834
ecffc563dfcf 8081204: ListAdapter throws NPE when adding/removing elements outside of JS context
attila
parents: 30832
diff changeset
   278
            return getDynamicInvoker(SHIFT, REMOVE_INVOKER_CREATOR).invokeExact(getFunction("shift"), obj);
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   279
        } catch(RuntimeException | Error ex) {
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   280
            throw ex;
24731
ab0c8fc915ae 8038406: Testability: as a first step of moving loggers away from the process global space, the Debug object now supports logging POJOs from log entries as an event queue, which can be introspected from test scripts. This is way better than screen scraping brittle and subject-to-change log output.
lagergren
parents: 23375
diff changeset
   281
        } catch(final Throwable t) {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   282
            throw new RuntimeException(t);
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   283
        }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   284
    }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   285
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   286
    private Object invokePop() {
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   287
        try {
30834
ecffc563dfcf 8081204: ListAdapter throws NPE when adding/removing elements outside of JS context
attila
parents: 30832
diff changeset
   288
            return getDynamicInvoker(POP, REMOVE_INVOKER_CREATOR).invokeExact(getFunction("pop"), obj);
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   289
        } catch(RuntimeException | Error ex) {
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   290
            throw ex;
24731
ab0c8fc915ae 8038406: Testability: as a first step of moving loggers away from the process global space, the Debug object now supports logging POJOs from log entries as an event queue, which can be introspected from test scripts. This is way better than screen scraping brittle and subject-to-change log output.
lagergren
parents: 23375
diff changeset
   291
        } catch(final Throwable t) {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   292
            throw new RuntimeException(t);
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   293
        }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   294
    }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   295
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   296
    @Override
20933
89748612fd1d 8026250: Logging nullpointer bugfix and javadoc warnings
lagergren
parents: 19897
diff changeset
   297
    protected final void removeRange(final int fromIndex, final int toIndex) {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   298
        invokeSpliceRemove(fromIndex, toIndex - fromIndex);
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   299
    }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   300
20933
89748612fd1d 8026250: Logging nullpointer bugfix and javadoc warnings
lagergren
parents: 19897
diff changeset
   301
    private void invokeSpliceRemove(final int fromIndex, final int count) {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   302
        try {
30834
ecffc563dfcf 8081204: ListAdapter throws NPE when adding/removing elements outside of JS context
attila
parents: 30832
diff changeset
   303
            getDynamicInvoker(SPLICE_REMOVE, SPLICE_REMOVE_INVOKER_CREATOR).invokeExact(getFunction("splice"), obj, fromIndex, count);
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   304
        } catch(RuntimeException | Error ex) {
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   305
            throw ex;
24731
ab0c8fc915ae 8038406: Testability: as a first step of moving loggers away from the process global space, the Debug object now supports logging POJOs from log entries as an event queue, which can be introspected from test scripts. This is way better than screen scraping brittle and subject-to-change log output.
lagergren
parents: 23375
diff changeset
   306
        } catch(final Throwable t) {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   307
            throw new RuntimeException(t);
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   308
        }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   309
    }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   310
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   311
    @Override
19897
4235a28bb5e8 8024847: Java.to should accept mirror and external JSObjects as array-like objects as well
sundar
parents: 19456
diff changeset
   312
    public final Object poll() {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   313
        return pollFirst();
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   314
    }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   315
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   316
    @Override
19897
4235a28bb5e8 8024847: Java.to should accept mirror and external JSObjects as array-like objects as well
sundar
parents: 19456
diff changeset
   317
    public final Object pollFirst() {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   318
        return isEmpty() ? null : invokeShift();
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   319
    }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   320
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   321
    @Override
19897
4235a28bb5e8 8024847: Java.to should accept mirror and external JSObjects as array-like objects as well
sundar
parents: 19456
diff changeset
   322
    public final Object pollLast() {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   323
        return isEmpty() ? null : invokePop();
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   324
    }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   325
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   326
    @Override
19897
4235a28bb5e8 8024847: Java.to should accept mirror and external JSObjects as array-like objects as well
sundar
parents: 19456
diff changeset
   327
    public final Object peek() {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   328
        return peekFirst();
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   329
    }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   330
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   331
    @Override
19897
4235a28bb5e8 8024847: Java.to should accept mirror and external JSObjects as array-like objects as well
sundar
parents: 19456
diff changeset
   332
    public final Object peekFirst() {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   333
        return isEmpty() ? null : get(0);
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   334
    }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   335
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   336
    @Override
19897
4235a28bb5e8 8024847: Java.to should accept mirror and external JSObjects as array-like objects as well
sundar
parents: 19456
diff changeset
   337
    public final Object peekLast() {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   338
        return isEmpty() ? null : get(size() - 1);
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   339
    }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   340
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   341
    @Override
19897
4235a28bb5e8 8024847: Java.to should accept mirror and external JSObjects as array-like objects as well
sundar
parents: 19456
diff changeset
   342
    public final Object element() {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   343
        return getFirst();
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   344
    }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   345
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   346
    @Override
19897
4235a28bb5e8 8024847: Java.to should accept mirror and external JSObjects as array-like objects as well
sundar
parents: 19456
diff changeset
   347
    public final Object getFirst() {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   348
        checkNonEmpty();
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   349
        return get(0);
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   350
    }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   351
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   352
    @Override
19897
4235a28bb5e8 8024847: Java.to should accept mirror and external JSObjects as array-like objects as well
sundar
parents: 19456
diff changeset
   353
    public final Object getLast() {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   354
        checkNonEmpty();
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   355
        return get(size() - 1);
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   356
    }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   357
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   358
    @Override
19897
4235a28bb5e8 8024847: Java.to should accept mirror and external JSObjects as array-like objects as well
sundar
parents: 19456
diff changeset
   359
    public final Iterator<Object> descendingIterator() {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   360
        final ListIterator<Object> it = listIterator(size());
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   361
        return new Iterator<Object>() {
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   362
            @Override
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   363
            public boolean hasNext() {
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   364
                return it.hasPrevious();
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   365
            }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   366
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   367
            @Override
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   368
            public Object next() {
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   369
                return it.previous();
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   370
            }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   371
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   372
            @Override
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   373
            public void remove() {
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   374
                it.remove();
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   375
            }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   376
        };
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   377
    }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   378
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   379
    @Override
20933
89748612fd1d 8026250: Logging nullpointer bugfix and javadoc warnings
lagergren
parents: 19897
diff changeset
   380
    public final boolean removeFirstOccurrence(final Object o) {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   381
        return removeOccurrence(o, iterator());
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   382
    }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   383
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   384
    @Override
20933
89748612fd1d 8026250: Logging nullpointer bugfix and javadoc warnings
lagergren
parents: 19897
diff changeset
   385
    public final boolean removeLastOccurrence(final Object o) {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   386
        return removeOccurrence(o, descendingIterator());
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   387
    }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   388
20933
89748612fd1d 8026250: Logging nullpointer bugfix and javadoc warnings
lagergren
parents: 19897
diff changeset
   389
    private static boolean removeOccurrence(final Object o, final Iterator<Object> it) {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   390
        while(it.hasNext()) {
30832
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
   391
            if(Objects.equals(o, it.next())) {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   392
                it.remove();
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   393
                return true;
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   394
            }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   395
        }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   396
        return false;
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   397
    }
30832
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
   398
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
   399
    private static Callable<MethodHandle> invokerCreator(final Class<?> rtype, final Class<?>... ptypes) {
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
   400
        return new Callable<MethodHandle>() {
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
   401
            @Override
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
   402
            public MethodHandle call() {
33343
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents: 30977
diff changeset
   403
                return Bootstrap.createDynamicCallInvoker(rtype, ptypes);
30832
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
   404
            }
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
   405
        };
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
   406
    }
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
   407
30834
ecffc563dfcf 8081204: ListAdapter throws NPE when adding/removing elements outside of JS context
attila
parents: 30832
diff changeset
   408
    private MethodHandle getDynamicInvoker(final Object key, final Callable<MethodHandle> creator) {
ecffc563dfcf 8081204: ListAdapter throws NPE when adding/removing elements outside of JS context
attila
parents: 30832
diff changeset
   409
        return global.getDynamicInvoker(key, creator);
30832
9553298028ef 8081062: ListAdapter should take advantage of JSObject
attila
parents: 25865
diff changeset
   410
    }
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents:
diff changeset
   411
}