?? nativearray.java
字號:
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(); } else if (!(obj instanceof Scriptable)) { return 0; } 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); } } else { if (toLocale && elem != Undefined.instance && elem != null) { Callable fun; Scriptable funThis; fun = ScriptRuntime.getPropFunctionAndThis( elem, "toLocaleString", cx); funThis = ScriptRuntime.lastStoredScriptable(cx); elem = fun.call(cx, scope, funThis, ScriptRuntime.emptyArgs); } result.append(ScriptRuntime.toString(elem)); } } } } finally { if (toplevel) { cx.iterating = null; } } if (toSource) { //for [,,].length behavior; we want toString to be symmetric. if (!haslast && i > 0) result.append(", ]"); else result.append(']'); } return result.toString(); } /** * See ECMA 15.4.4.3 */ private static String js_join(Context cx, Scriptable thisObj, Object[] args) { String separator; long llength = getLengthProperty(cx, thisObj); int length = (int)llength; if (llength != length) { throw Context.reportRuntimeError1( "msg.arraylength.too.big", String.valueOf(llength)); } // if no args, use "," as separator if (args.length < 1 || args[0] == Undefined.instance) { separator = ","; } else { separator = ScriptRuntime.toString(args[0]); } if (length == 0) { return ""; } String[] buf = new String[length]; int total_size = 0; for (int i = 0; i != length; i++) { Object temp = getElem(cx, thisObj, i); if (temp != null && temp != Undefined.instance) { String str = ScriptRuntime.toString(temp); total_size += str.length(); buf[i] = str; } } total_size += (length - 1) * separator.length(); StringBuffer sb = new StringBuffer(total_size); for (int i = 0; i != length; i++) { if (i != 0) { sb.append(separator); } String str = buf[i]; if (str != null) { // str == null for undefined or null sb.append(str); } } return sb.toString(); } /** * See ECMA 15.4.4.4 */ private static Scriptable js_reverse(Context cx, Scriptable thisObj, Object[] args) { long len = getLengthProperty(cx, thisObj); long half = len / 2; for(long i=0; i < half; i++) { long j = len - i - 1; Object temp1 = getElem(cx, thisObj, i); Object temp2 = getElem(cx, thisObj, j); setElem(cx, thisObj, i, temp2); setElem(cx, thisObj, j, temp1); } return thisObj; } /** * See ECMA 15.4.4.5 */ private static Scriptable js_sort(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { long length = getLengthProperty(cx, thisObj); if (length <= 1) { return thisObj; } Object compare; Object[] cmpBuf; if (args.length > 0 && Undefined.instance != args[0]) { // sort with given compare function compare = args[0]; cmpBuf = new Object[2]; // Buffer for cmp arguments } else { // sort with default compare compare = null; cmpBuf = null; } // Should we use the extended sort function, or the faster one? if (length >= Integer.MAX_VALUE) { heapsort_extended(cx, scope, thisObj, length, compare, cmpBuf); } else { int ilength = (int)length; // copy the JS array into a working array, so it can be // sorted cheaply. Object[] working = new Object[ilength]; for (int i = 0; i != ilength; ++i) { working[i] = getElem(cx, thisObj, i); } heapsort(cx, scope, working, ilength, compare, cmpBuf); // copy the working array back into thisObj for (int i = 0; i != ilength; ++i) { setElem(cx, thisObj, i, working[i]); } } return thisObj; } // Return true only if x > y private static boolean isBigger(Context cx, Scriptable scope, Object x, Object y, Object cmp, Object[] cmpBuf) { if (cmp == null) { if (cmpBuf != null) Kit.codeBug(); } else { if (cmpBuf == null || cmpBuf.length != 2) Kit.codeBug(); } Object undef = Undefined.instance; // sort undefined to end if (undef == y) { return false; // x can not be bigger then undef } else if (undef == x) { return true; // y != undef here, so x > y } if (cmp == null) { // if no cmp function supplied, sort lexicographically String a = ScriptRuntime.toString(x); String b = ScriptRuntime.toString(y); return a.compareTo(b) > 0; } else { // assemble args and call supplied JS cmp function cmpBuf[0] = x; cmpBuf[1] = y; Callable fun = ScriptRuntime.getValueFunctionAndThis(cmp, cx); Scriptable funThis = ScriptRuntime.lastStoredScriptable(cx); Object ret = fun.call(cx, scope, funThis, cmpBuf); double d = ScriptRuntime.toNumber(ret); // XXX what to do when cmp function returns NaN? ECMA states // that it's then not a 'consistent compararison function'... but // then what do we do? Back out and start over with the generic // cmp function when we see a NaN? Throw an error? // for now, just ignore it: return d > 0; } }/** Heapsort implementation. * See "Introduction to Algorithms" by Cormen, Leiserson, Rivest for details. * Adjusted for zero based indexes. */ private static void heapsort(Context cx, Scriptable scope, Object[] array, int length, Object cmp, Object[] cmpBuf) { if (length <= 1) Kit.codeBug(); // Build heap for (int i = length / 2; i != 0;) { --i; Object pivot = array[i]; heapify(cx, scope, pivot, array, i, length, cmp, cmpBuf); } // Sort heap for (int i = length; i != 1;) { --i; Object pivot = array[i]; array[i] = array[0]; heapify(cx, scope, pivot, array, 0, i, cmp, cmpBuf); } }/** pivot and child heaps of i should be made into heap starting at i, * original array[i] is never used to have less array access during sorting. */ private static void heapify(Context cx, Scriptable scope, Object pivot, Object[] array, int i, int end, Object cmp, Object[] cmpBuf) { for (;;) { int child = i * 2 + 1; if (child >= end) { break; } Object childVal = array[child]; if (child + 1 < end) { Object nextVal = array[child + 1]; if (isBigger(cx, scope, nextVal, childVal, cmp, cmpBuf)) { ++child; childVal = nextVal; } } if (!isBigger(cx, scope, childVal, pivot, cmp, cmpBuf)) { break; } array[i] = childVal; i = child; } array[i] = pivot; }/** Version of heapsort that call getElem/setElem on target to query/assign * array elements instead of Java array access */ private static void heapsort_extended(Context cx, Scriptable scope, Scriptable target, long length, Object cmp, Object[] cmpBuf) { if (length <= 1) Kit.codeBug();
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -