📄 nativearray.java
字号:
if (Long.toString(index).equals(id)) { return index; } } } return -1; } 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; } 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; } } } 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); } } 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] = new Integer(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; } public Object getDefaultValue(Class hint) { if (hint == ScriptRuntime.NumberClass) { Context cx = Context.getContext(); if (cx.getLanguageVersion() == Context.VERSION_1_2) return new Long(length); } return super.getDefaultValue(hint); } /** * See ECMA 15.4.1,2 */ private static Object jsConstructor(Context cx, Scriptable scope, Object[] args) { if (args.length == 0) return new NativeArray(0); // Only use 1 arg as first element for version 1.2; for // any other version (including 1.3) follow ECMA and use it as // a length. if (cx.getLanguageVersion() == Context.VERSION_1_2) { return new NativeArray(args); } else { Object arg0 = args[0]; if (args.length > 1 || !(arg0 instanceof Number)) { return new NativeArray(args); } else { long len = ScriptRuntime.toUint32(arg0); if (len != ((Number)arg0).doubleValue()) throw Context.reportRuntimeError0("msg.arraylength.bad"); return new NativeArray(len); } } } public long getLength() { return length; } /** @deprecated Use {@link #getLength()} instead. */ public long jsGet_length() { return getLength(); } /** * Change the value of the internal flag that determines whether all * storage is handed by a dense backing array rather than an associative * store. * @param denseOnly new value for denseOnly flag * @throws IllegalArgumentException if an attempt is made to enable * denseOnly after it was disabled; NativeArray code is not written * to handle switching back to a dense representation */ void setDenseOnly(boolean denseOnly) { if (denseOnly && !this.denseOnly) throw new IllegalArgumentException(); this.denseOnly = denseOnly; } private void setLength(Object val) { /* XXX do we satisfy this? * 15.4.5.1 [[Put]](P, V): * 1. Call the [[CanPut]] method of A with name P. * 2. If Result(1) is false, return. * ? */ double d = ScriptRuntime.toNumber(val); long longVal = ScriptRuntime.toUint32(d); if (longVal != d) throw Context.reportRuntimeError0("msg.arraylength.bad"); if (denseOnly) { if (longVal < length) { // downcast okay because denseOnly Arrays.fill(dense, (int) longVal, dense.length, NOT_FOUND); length = longVal; return; } else if (longVal < MAX_PRE_GROW_SIZE && longVal < (length * GROW_FACTOR) && ensureCapacity((int)longVal)) { length = longVal; return; } else { denseOnly = false; } } if (longVal < length) { // remove all properties between longVal and length if (length - longVal > 0x1000) { // assume that the representation is sparse Object[] e = getIds(); // will only find in object itself for (int i=0; i < e.length; i++) { Object id = e[i]; if (id instanceof String) { // > MAXINT will appear as string String strId = (String)id; long index = toArrayIndex(strId); if (index >= longVal) delete(strId); } else { int index = ((Integer)id).intValue(); if (index >= longVal) delete(index); } } } else { // assume a dense representation for (long i = longVal; i < length; i++) { deleteElem(this, i); } } } length = longVal; } /* Support for generic Array-ish objects. Most of the Array * functions try to be generic; anything that has a length * property is assumed to be an array. * getLengthProperty returns 0 if obj does not have the length property * or its value is not convertible to a number. */ static long getLengthProperty(Context cx, Scriptable obj) { // These will both give numeric lengths within Uint32 range. if (obj instanceof NativeString) { return ((NativeString)obj).getLength(); } else if (obj instanceof NativeArray) { return ((NativeArray)obj).getLength(); } return ScriptRuntime.toUint32( ScriptRuntime.getObjectProp(obj, "length", cx)); } private static Object setLengthProperty(Context cx, Scriptable target, long length) { return ScriptRuntime.setObjectProp( target, "length", ScriptRuntime.wrapNumber(length), cx); } /* Utility functions to encapsulate index > Integer.MAX_VALUE * handling. Also avoids unnecessary object creation that would * be necessary to use the general ScriptRuntime.get/setElem * functions... though this is probably premature optimization. */ private static void deleteElem(Scriptable target, long index) { int i = (int)index; if (i == index) { target.delete(i); } else { target.delete(Long.toString(index)); } } private static Object getElem(Context cx, Scriptable target, long index) { if (index > Integer.MAX_VALUE) { String id = Long.toString(index); return ScriptRuntime.getObjectProp(target, id, cx); } else { return ScriptRuntime.getObjectIndex(target, (int)index, cx); } } private static void setElem(Context cx, Scriptable target, long index, Object value) { if (index > Integer.MAX_VALUE) { String id = Long.toString(index); ScriptRuntime.setObjectProp(target, id, value, cx); } else { ScriptRuntime.setObjectIndex(target, (int)index, value, cx); } } private static String toStringHelper(Context cx, Scriptable scope, Scriptable thisObj, boolean toSource, boolean toLocale) { /* It's probably redundant to handle long lengths in this * function; StringBuffers are limited to 2^31 in java. */ long length = getLengthProperty(cx, thisObj); StringBuffer result = new StringBuffer(256); // whether to return '4,unquoted,5' or '[4, "quoted", 5]' String separator; if (toSource) { result.append('['); separator = ", "; } else { separator = ","; } boolean haslast = false; long i = 0; boolean toplevel, iterating; if (cx.iterating == null) { toplevel = true; iterating = false; cx.iterating = new ObjToIntMap(31); } else { toplevel = false; iterating = cx.iterating.has(thisObj); } // Make sure cx.iterating is set to null when done // so we don't leak memory try { if (!iterating) { cx.iterating.put(thisObj, 0); // stop recursion. for (i = 0; i < length; i++) { if (i > 0) result.append(separator); Object elem = getElem(cx, thisObj, i); if (elem == null || elem == Undefined.instance) { haslast = false; continue; } haslast = true; if (toSource) { result.append(ScriptRuntime.uneval(cx, scope, elem)); } else if (elem instanceof String) { String s = (String)elem; if (toSource) { result.append('\"'); result.append(ScriptRuntime.escapeString(s)); result.append('\"'); } else { result.append(s); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -