Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Rhino code, released
* May 6, 1999.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1997-1999
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Norris Boyd
* Mike McCabe
* Igor Bukanov
*
* Alternatively, the contents of this file may be used under the terms of
* the GNU General Public License Version 2 or later (the "GPL"), in which
* case the provisions of the GPL are applicable instead of those above. If
* you wish to allow use of your version of this file only under the terms of
* the GPL and not to allow others to use your version of this file under the
* MPL, indicate your decision by deleting the provisions above and replacing
* them with the notice and other provisions required by the GPL. If you do
* not delete the provisions above, a recipient may use your version of this
* file under either the MPL or the GPL.
*
* ***** END LICENSE BLOCK ***** */
package org.mozilla.javascript;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.ListIterator;
import java.util.NoSuchElementException;
import java.util.Set;
/**
* This class implements the Array native object.
* @author Norris Boyd
* @author Mike McCabe
*/
public class NativeArray extends IdScriptableObject implements List
{
static final long serialVersionUID = 7331366857676127338L;
/*
* Optimization possibilities and open issues:
* - Long vs. double schizophrenia. I suspect it might be better
* to use double throughout.
*
* - Functions that need a new Array call "new Array" in the
* current scope rather than using a hardwired constructor;
* "Array" could be redefined. It turns out that js calls the
* equivalent of "new Array" in the current scope, except that it
* always gets at least an object back, even when Array == null.
*/
private static final Object ARRAY_TAG = "Array";
private static final Integer NEGATIVE_ONE = Integer.valueOf(-1);
static void init(Scriptable scope, boolean sealed)
{
NativeArray obj = new NativeArray(0);
obj.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed);
}
static int getMaximumInitialCapacity() {
return maximumInitialCapacity;
}
static void setMaximumInitialCapacity(int maximumInitialCapacity) {
NativeArray.maximumInitialCapacity = maximumInitialCapacity;
}
public NativeArray(long lengthArg)
{
denseOnly = lengthArg <= maximumInitialCapacity;
if (denseOnly) {
int intLength = (int) lengthArg;
if (intLength < DEFAULT_INITIAL_CAPACITY)
intLength = DEFAULT_INITIAL_CAPACITY;
dense = new Object[intLength];
Arrays.fill(dense, Scriptable.NOT_FOUND);
}
length = lengthArg;
}
public NativeArray(Object[] array)
{
denseOnly = true;
dense = array;
length = array.length;
}
@Override
public String getClassName()
{
return "Array";
}
private static final int
Id_length = 1,
MAX_INSTANCE_ID = 1;
@Override
protected int getMaxInstanceId()
{
return MAX_INSTANCE_ID;
}
@Override
protected int findInstanceIdInfo(String s)
{
if (s.equals("length")) {
return instanceIdInfo(DONTENUM | PERMANENT, Id_length);
}
return super.findInstanceIdInfo(s);
}
@Override
protected String getInstanceIdName(int id)
{
if (id == Id_length) { return "length"; }
return super.getInstanceIdName(id);
}
@Override
protected Object getInstanceIdValue(int id)
{
if (id == Id_length) {
return ScriptRuntime.wrapNumber(length);
}
return super.getInstanceIdValue(id);
}
@Override
protected void setInstanceIdValue(int id, Object value)
{
if (id == Id_length) {
setLength(value); return;
}
super.setInstanceIdValue(id, value);
}
@Override
protected void fillConstructorProperties(IdFunctionObject ctor)
{
addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_join,
"join", 1);
addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_reverse,
"reverse", 0);
addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_sort,
"sort", 1);
addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_push,
"push", 1);
addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_pop,
"pop", 0);
addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_shift,
"shift", 0);
addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_unshift,
"unshift", 1);
addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_splice,
"splice", 2);
addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_concat,
"concat", 1);
addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_slice,
"slice", 2);
addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_indexOf,
"indexOf", 1);
addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_lastIndexOf,
"lastIndexOf", 1);
addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_every,
"every", 1);
addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_filter,
"filter", 1);
addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_forEach,
"forEach", 1);
addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_map,
"map", 1);
addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_some,
"some", 1);
addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_reduce,
"reduce", 1);
addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_reduceRight,
"reduceRight", 1);
addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_isArray,
"isArray", 1);
super.fillConstructorProperties(ctor);
}
@Override
protected void initPrototypeId(int id)
{
String s;
int arity;
switch (id) {
case Id_constructor: arity=1; s="constructor"; break;
case Id_toString: arity=0; s="toString"; break;
case Id_toLocaleString: arity=0; s="toLocaleString"; break;
case Id_toSource: arity=0; s="toSource"; break;
case Id_join: arity=1; s="join"; break;
case Id_reverse: arity=0; s="reverse"; break;
case Id_sort: arity=1; s="sort"; break;
case Id_push: arity=1; s="push"; break;
case Id_pop: arity=0; s="pop"; break;
case Id_shift: arity=0; s="shift"; break;
case Id_unshift: arity=1; s="unshift"; break;
case Id_splice: arity=2; s="splice"; break;
case Id_concat: arity=1; s="concat"; break;
case Id_slice: arity=2; s="slice"; break;
case Id_indexOf: arity=1; s="indexOf"; break;
case Id_lastIndexOf: arity=1; s="lastIndexOf"; break;
case Id_every: arity=1; s="every"; break;
case Id_filter: arity=1; s="filter"; break;
case Id_forEach: arity=1; s="forEach"; break;
case Id_map: arity=1; s="map"; break;
case Id_some: arity=1; s="some"; break;
case Id_reduce: arity=1; s="reduce"; break;
case Id_reduceRight: arity=1; s="reduceRight"; break;
default: throw new IllegalArgumentException(String.valueOf(id));
}
initPrototypeMethod(ARRAY_TAG, id, s, arity);
}
@Override
public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope,
Scriptable thisObj, Object[] args)
{
if (!f.hasTag(ARRAY_TAG)) {
return super.execIdCall(f, cx, scope, thisObj, args);
}
int id = f.methodId();
again:
for (;;) {
switch (id) {
case ConstructorId_join:
case ConstructorId_reverse:
case ConstructorId_sort:
case ConstructorId_push:
case ConstructorId_pop:
case ConstructorId_shift:
case ConstructorId_unshift:
case ConstructorId_splice:
case ConstructorId_concat:
case ConstructorId_slice:
case ConstructorId_indexOf:
case ConstructorId_lastIndexOf:
case ConstructorId_every:
case ConstructorId_filter:
case ConstructorId_forEach:
case ConstructorId_map:
case ConstructorId_some:
case ConstructorId_reduce:
case ConstructorId_reduceRight: {
if (args.length > 0) {
thisObj = ScriptRuntime.toObject(scope, args[0]);
Object[] newArgs = new Object[args.length-1];
for (int i=0; i < newArgs.length; i++)
newArgs[i] = args[i+1];
args = newArgs;
}
id = -id;
continue again;
}
case ConstructorId_isArray:
return args.length > 0 && (args[0] instanceof NativeArray);
case Id_constructor: {
boolean inNewExpr = (thisObj == null);
if (!inNewExpr) {
// IdFunctionObject.construct will set up parent, proto
return f.construct(cx, scope, args);
}
return jsConstructor(cx, scope, args);
}
case Id_toString:
return toStringHelper(cx, scope, thisObj,
cx.hasFeature(Context.FEATURE_TO_STRING_AS_SOURCE), false);
case Id_toLocaleString:
return toStringHelper(cx, scope, thisObj, false, true);
case Id_toSource:
return toStringHelper(cx, scope, thisObj, true, false);
case Id_join:
return js_join(cx, thisObj, args);
case Id_reverse:
return js_reverse(cx, thisObj, args);
case Id_sort:
return js_sort(cx, scope, thisObj, args);
case Id_push:
return js_push(cx, thisObj, args);
case Id_pop:
return js_pop(cx, thisObj, args);
case Id_shift:
return js_shift(cx, thisObj, args);
case Id_unshift:
return js_unshift(cx, thisObj, args);
case Id_splice:
return js_splice(cx, scope, thisObj, args);
case Id_concat:
return js_concat(cx, scope, thisObj, args);
case Id_slice:
return js_slice(cx, thisObj, args);
case Id_indexOf:
return indexOfHelper(cx, thisObj, args, false);
case Id_lastIndexOf:
return indexOfHelper(cx, thisObj, args, true);
case Id_every:
case Id_filter:
case Id_forEach:
case Id_map:
case Id_some:
return iterativeMethod(cx, id, scope, thisObj, args);
case Id_reduce:
case Id_reduceRight:
return reduceMethod(cx, id, scope, thisObj, args);
}
throw new IllegalArgumentException(String.valueOf(id));
}
}
@Override
public Object get(int index, Scriptable start)
{
if (!denseOnly && isGetterOrSetter(null, index, false))
return super.get(index, start);
if (dense != null && 0 <= index && index < dense.length)
return dense[index];
return super.get(index, start);
}
@Override
public boolean has(int index, Scriptable start)
{
if (!denseOnly && isGetterOrSetter(null, index, false))
return super.has(index, start);
if (dense != null && 0 <= index && index < dense.length)
return dense[index] != NOT_FOUND;
return super.has(index, start);
}
// if id is an array index (ECMA 15.4.0), return the number,
// otherwise return -1L
private static long toArrayIndex(String id)
{
double d = ScriptRuntime.toNumber(id);
if (d == d) {
long index = ScriptRuntime.toUint32(d);
if (index == d && index != 4294967295L) {
// Assume that ScriptRuntime.toString(index) is the same
// as java.lang.Long.toString(index) for long
if (Long.toString(index).equals(id)) {
return index;
}
}
}
return -1;
}
@Override
public void put(String id, Scriptable start, Object value)
{
super.put(id, start, value);
if (start == this) {
// If the object is sealed, super will throw exception
long index = toArrayIndex(id);
if (index >= length) {
length = index + 1;
denseOnly = false;
}
}
}
private boolean ensureCapacity(int capacity)
{
if (capacity > dense.length) {
if (capacity > MAX_PRE_GROW_SIZE) {
denseOnly = false;
return false;
}
capacity = Math.max(capacity, (int)(dense.length * GROW_FACTOR));
Object[] newDense = new Object[capacity];
System.arraycopy(dense, 0, newDense, 0, dense.length);
Arrays.fill(newDense, dense.length, newDense.length,
Scriptable.NOT_FOUND);
dense = newDense;
}
return true;
}
@Override
public void put(int index, Scriptable start, Object value)
{
if (start == this && !isSealed() && dense != null && 0 <= index &&
(denseOnly || !isGetterOrSetter(null, index, true)))
{
if (index < dense.length) {
dense[index] = value;
if (this.length <= index)
this.length = (long)index + 1;
return;
} else if (denseOnly && index < dense.length * GROW_FACTOR &&
ensureCapacity(index+1))
{
dense[index] = value;
this.length = (long)index + 1;
return;
} else {
denseOnly = false;
}
}
super.put(index, start, value);
if (start == this) {
// only set the array length if given an array index (ECMA 15.4.0)
if (this.length <= index) {
// avoid overflowing index!
this.length = (long)index + 1;
}
}
}
@Override
public void delete(int index)
{
if (dense != null && 0 <= index && index < dense.length &&
!isSealed() && (denseOnly || !isGetterOrSetter(null, index, true)))
{
dense[index] = NOT_FOUND;
} else {
super.delete(index);
}
}
@Override
public Object[] getIds()
{
Object[] superIds = super.getIds();
if (dense == null) { return superIds; }
int N = dense.length;
long currentLength = length;
if (N > currentLength) {
N = (int)currentLength;
}
if (N == 0) { return superIds; }
int superLength = superIds.length;
Object[] ids = new Object[N + superLength];
int presentCount = 0;
for (int i = 0; i != N; ++i) {
// Replace existing elements by their indexes
if (dense[i] != NOT_FOUND) {
ids[presentCount] = Integer.valueOf(i);
++presentCount;
}
}
if (presentCount != N) {
// dense contains deleted elems, need to shrink the result
Object[] tmp = new Object[presentCount + superLength];
System.arraycopy(ids, 0, tmp, 0, presentCount);
ids = tmp;
}
System.arraycopy(superIds, 0, ids, presentCount, superLength);
return ids;
}
@Override
public Object[] getAllIds()
{
Set