2003/05/12 05:31:48
[org.ibex.core.git] / src / org / mozilla / javascript / NativeArray.java
diff --git a/src/org/mozilla/javascript/NativeArray.java b/src/org/mozilla/javascript/NativeArray.java
deleted file mode 100644 (file)
index 37d81f8..0000000
+++ /dev/null
@@ -1,1147 +0,0 @@
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation.  Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- * Mike McCabe\r
- * Igor Bukanov\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL.  If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-import java.util.Hashtable;\r
-\r
-/**\r
- * This class implements the Array native object.\r
- * @author Norris Boyd\r
- * @author Mike McCabe\r
- */\r
-public class NativeArray extends IdScriptable {\r
-\r
-    /*\r
-     * Optimization possibilities and open issues:\r
-     * - Long vs. double schizophrenia.  I suspect it might be better\r
-     * to use double throughout.\r
-\r
-     * - Most array operations go through getElem or setElem (defined\r
-     * in this file) to handle the full 2^32 range; it might be faster\r
-     * to have versions of most of the loops in this file for the\r
-     * (infinitely more common) case of indices < 2^31.\r
-\r
-     * - Functions that need a new Array call "new Array" in the\r
-     * current scope rather than using a hardwired constructor;\r
-     * "Array" could be redefined.  It turns out that js calls the\r
-     * equivalent of "new Array" in the current scope, except that it\r
-     * always gets at least an object back, even when Array == null.\r
-     */\r
-\r
-    public static void init(Context cx, Scriptable scope, boolean sealed) {\r
-        NativeArray obj = new NativeArray();\r
-        obj.prototypeFlag = true;\r
-        obj.addAsPrototype(MAX_PROTOTYPE_ID, cx, scope, sealed);\r
-    }\r
-\r
-    /**\r
-     * Zero-parameter constructor: just used to create Array.prototype\r
-     */\r
-    public NativeArray() {\r
-        dense = null;\r
-        this.length = 0;\r
-    }\r
-\r
-    public NativeArray(long length) {\r
-        int intLength = (int) length;\r
-        if (intLength == length && intLength > 0) {\r
-            if (intLength > maximumDenseLength)\r
-                intLength = maximumDenseLength;\r
-            dense = new Object[intLength];\r
-            for (int i=0; i < intLength; i++)\r
-                dense[i] = NOT_FOUND;\r
-        }\r
-        this.length = length;\r
-    }\r
-\r
-    public NativeArray(Object[] array) {\r
-        dense = array;\r
-        this.length = array.length;\r
-    }\r
-\r
-    public String getClassName() {\r
-        return "Array";\r
-    }\r
-\r
-    protected int getIdDefaultAttributes(int id) {\r
-        if (id == Id_length) {\r
-            return DONTENUM | PERMANENT;\r
-        }\r
-        return super.getIdDefaultAttributes(id);\r
-    }\r
-\r
-    protected Object getIdValue(int id) {\r
-        if (id == Id_length) {\r
-            return wrap_double(length);\r
-        }\r
-        return super.getIdValue(id);\r
-    }\r
-    \r
-    protected void setIdValue(int id, Object value) {\r
-        if (id == Id_length) {\r
-            jsSet_length(value); return;\r
-        }\r
-        super.setIdValue(id, value);\r
-    }\r
-    \r
-    public int methodArity(int methodId) {\r
-        if (prototypeFlag) {\r
-            switch (methodId) {\r
-                case Id_constructor:     return 1;\r
-                case Id_toString:        return 0;\r
-                case Id_toLocaleString:  return 1;\r
-                case Id_join:            return 1;\r
-                case Id_reverse:         return 0;\r
-                case Id_sort:            return 1;\r
-                case Id_push:            return 1;\r
-                case Id_pop:             return 1;\r
-                case Id_shift:           return 1;\r
-                case Id_unshift:         return 1;\r
-                case Id_splice:          return 1;\r
-                case Id_concat:          return 1;\r
-                case Id_slice:           return 1;\r
-            }\r
-        }\r
-        return super.methodArity(methodId);\r
-    }\r
-\r
-    public Object execMethod\r
-        (int methodId, IdFunction f,\r
-         Context cx, Scriptable scope, Scriptable thisObj, Object[] args)\r
-        throws JavaScriptException\r
-    {\r
-        if (prototypeFlag) {\r
-            switch (methodId) {\r
-                case Id_constructor:\r
-                    return jsConstructor(cx, scope, args, f, thisObj == null);\r
-\r
-                case Id_toString:\r
-                    return jsFunction_toString(cx, thisObj, args);\r
-\r
-                case Id_toLocaleString:\r
-                    return jsFunction_toLocaleString(cx, thisObj, args);\r
-\r
-                case Id_join:\r
-                    return jsFunction_join(cx, thisObj, args);\r
-\r
-                case Id_reverse:\r
-                    return jsFunction_reverse(cx, thisObj, args);\r
-\r
-                case Id_sort:\r
-                    return jsFunction_sort(cx, scope, thisObj, args);\r
-\r
-                case Id_push:\r
-                    return jsFunction_push(cx, thisObj, args);\r
-\r
-                case Id_pop:\r
-                    return jsFunction_pop(cx, thisObj, args);\r
-\r
-                case Id_shift:\r
-                    return jsFunction_shift(cx, thisObj, args);\r
-\r
-                case Id_unshift:\r
-                    return jsFunction_unshift(cx, thisObj, args);\r
-\r
-                case Id_splice:\r
-                    return jsFunction_splice(cx, scope, thisObj, args);\r
-\r
-                case Id_concat:\r
-                    return jsFunction_concat(cx, scope, thisObj, args);\r
-\r
-                case Id_slice:\r
-                    return jsFunction_slice(cx, thisObj, args);\r
-            }\r
-        }\r
-        return super.execMethod(methodId, f, cx, scope, thisObj, args);\r
-    }\r
-\r
-    public Object get(int index, Scriptable start) {\r
-        if (dense != null && 0 <= index && index < dense.length)\r
-            return dense[index];\r
-        return super.get(index, start);\r
-    }\r
-\r
-    public boolean has(int index, Scriptable start) {\r
-        if (dense != null && 0 <= index && index < dense.length)\r
-            return dense[index] != NOT_FOUND;\r
-        return super.has(index, start);\r
-    }\r
-\r
-    public void put(String id, Scriptable start, Object value) {\r
-        if (start == this) {\r
-            // only set the array length if given an array index (ECMA 15.4.0)\r
-\r
-            // try to get an array index from id\r
-            double d = ScriptRuntime.toNumber(id);\r
-\r
-            if (ScriptRuntime.toUint32(d) == d &&\r
-                ScriptRuntime.numberToString(d, 10).equals(id) &&\r
-                this.length <= d && d != 4294967295.0)\r
-            {\r
-                this.length = (long)d + 1;\r
-            }\r
-        }\r
-        super.put(id, start, value);\r
-    }\r
-\r
-    public void put(int index, Scriptable start, Object value) {\r
-        if (start == this) {\r
-            // only set the array length if given an array index (ECMA 15.4.0)\r
-            if (this.length <= index) {\r
-                // avoid overflowing index!\r
-                this.length = (long)index + 1;\r
-            }\r
-\r
-            if (dense != null && 0 <= index && index < dense.length) {\r
-                dense[index] = value;\r
-                return;\r
-            }\r
-        }\r
-        super.put(index, start, value);\r
-    }\r
-\r
-    public void delete(int index) {\r
-        if (!isSealed()) {\r
-            if (dense != null && 0 <= index && index < dense.length) {\r
-                dense[index] = NOT_FOUND;\r
-                return;\r
-            }\r
-        }\r
-        super.delete(index);\r
-    }\r
-\r
-    public Object[] getIds() {\r
-        Object[] superIds = super.getIds();\r
-        if (dense == null)\r
-            return superIds;\r
-        int count = 0;\r
-        int last = dense.length;\r
-        if (last > length)\r
-            last = (int) length;\r
-        for (int i=last-1; i >= 0; i--) {\r
-            if (dense[i] != NOT_FOUND)\r
-                count++;\r
-        }\r
-        count += superIds.length;\r
-        Object[] result = new Object[count];\r
-        System.arraycopy(superIds, 0, result, 0, superIds.length);\r
-        for (int i=last-1; i >= 0; i--) {\r
-            if (dense[i] != NOT_FOUND)\r
-                result[--count] = new Integer(i);\r
-        }\r
-        return result;\r
-    }\r
-    \r
-    public Object getDefaultValue(Class hint) {\r
-        if (hint == ScriptRuntime.NumberClass) {\r
-            Context cx = Context.getContext();\r
-            if (cx.getLanguageVersion() == Context.VERSION_1_2)\r
-                return new Long(length);\r
-        }\r
-        return super.getDefaultValue(hint);\r
-    }\r
-\r
-    /**\r
-     * See ECMA 15.4.1,2\r
-     */\r
-    private static Object jsConstructor(Context cx, Scriptable scope, \r
-                                        Object[] args, IdFunction ctorObj,\r
-                                        boolean inNewExpr)\r
-        throws JavaScriptException\r
-    {\r
-        if (!inNewExpr) {\r
-            // FunctionObject.construct will set up parent, proto\r
-            return ctorObj.construct(cx, scope, args);\r
-        }\r
-        if (args.length == 0)\r
-            return new NativeArray();\r
-\r
-        // Only use 1 arg as first element for version 1.2; for\r
-        // any other version (including 1.3) follow ECMA and use it as\r
-        // a length.\r
-        if (cx.getLanguageVersion() == cx.VERSION_1_2) {\r
-            return new NativeArray(args);\r
-        }\r
-        else {\r
-            if ((args.length > 1) || (!(args[0] instanceof Number)))\r
-                return new NativeArray(args);\r
-            else {\r
-                long len = ScriptRuntime.toUint32(args[0]);\r
-                if (len != (((Number)(args[0])).doubleValue()))\r
-                    throw Context.reportRuntimeError0("msg.arraylength.bad");\r
-                return new NativeArray(len);\r
-            }\r
-        }\r
-    }\r
-\r
-    public long jsGet_length() {\r
-        return length;\r
-    }\r
-\r
-    private void jsSet_length(Object val) {\r
-        /* XXX do we satisfy this?\r
-         * 15.4.5.1 [[Put]](P, V):\r
-         * 1. Call the [[CanPut]] method of A with name P.\r
-         * 2. If Result(1) is false, return.\r
-         * ?\r
-         */\r
-\r
-        if (!(val instanceof Number))\r
-            throw Context.reportRuntimeError0("msg.arraylength.bad");\r
-        \r
-        long longVal = ScriptRuntime.toUint32(val);\r
-        if (longVal != (((Number)val).doubleValue()))\r
-            throw Context.reportRuntimeError0("msg.arraylength.bad");\r
-\r
-        if (longVal < length) {\r
-            // remove all properties between longVal and length\r
-            if (length - longVal > 0x1000) {\r
-                // assume that the representation is sparse\r
-                Object[] e = getIds(); // will only find in object itself\r
-                for (int i=0; i < e.length; i++) {\r
-                    if (e[i] instanceof String) {\r
-                        // > MAXINT will appear as string\r
-                        String id = (String) e[i];\r
-                        double d = ScriptRuntime.toNumber(id);\r
-                        if (d == d && d < length)\r
-                            delete(id);\r
-                        continue;\r
-                    }\r
-                    int index = ((Number) e[i]).intValue();\r
-                    if (index >= longVal)\r
-                        delete(index);\r
-                }\r
-            } else {\r
-                // assume a dense representation\r
-                for (long i=longVal; i < length; i++) {\r
-                    // only delete if defined in the object itself\r
-                    if (hasElem(this, i))\r
-                        ScriptRuntime.delete(this, new Long(i));\r
-                }\r
-            }\r
-        }\r
-        length = longVal;\r
-    }\r
-\r
-    /* Support for generic Array-ish objects.  Most of the Array\r
-     * functions try to be generic; anything that has a length\r
-     * property is assumed to be an array.  hasLengthProperty is\r
-     * needed in addition to getLengthProperty, because\r
-     * getLengthProperty always succeeds - tries to convert strings, etc.\r
-     */\r
-    static double getLengthProperty(Scriptable obj) {\r
-        // These will both give numeric lengths within Uint32 range.\r
-        if (obj instanceof NativeString)\r
-            return (double)((NativeString)obj).jsGet_length();\r
-        if (obj instanceof NativeArray)\r
-            return (double)((NativeArray)obj).jsGet_length();\r
-        return ScriptRuntime.toUint32(ScriptRuntime\r
-                                      .getProp(obj, "length", obj));\r
-    }\r
-\r
-    static boolean hasLengthProperty(Object obj) {\r
-        if (!(obj instanceof Scriptable) || obj == Context.getUndefinedValue())\r
-            return false;\r
-        if (obj instanceof NativeString || obj instanceof NativeArray)\r
-            return true;\r
-        Scriptable sobj = (Scriptable)obj;\r
-\r
-        // XXX some confusion as to whether or not to walk to get the length\r
-        // property.  Pending review of js/[new ecma submission] treatment\r
-        // of 'arrayness'.\r
-\r
-        Object property = ScriptRuntime.getProp(sobj, "length", sobj);\r
-        return property instanceof Number;\r
-    }\r
-\r
-    /* Utility functions to encapsulate index > Integer.MAX_VALUE\r
-     * handling.  Also avoids unnecessary object creation that would\r
-     * be necessary to use the general ScriptRuntime.get/setElem\r
-     * functions... though this is probably premature optimization.\r
-     */\r
-    private static boolean hasElem(Scriptable target, long index) {\r
-        return index > Integer.MAX_VALUE\r
-               ? target.has(Long.toString(index), target)\r
-               : target.has((int)index, target);\r
-    }\r
-\r
-    private static Object getElem(Scriptable target, long index) {\r
-        if (index > Integer.MAX_VALUE) {\r
-            String id = Long.toString(index);\r
-            return ScriptRuntime.getElem(target, id, target);\r
-        } else {\r
-            return ScriptRuntime.getElem(target, (int)index);\r
-        }\r
-    }\r
-\r
-    private static void setElem(Scriptable target, long index, Object value) {\r
-        if (index > Integer.MAX_VALUE) {\r
-            String id = Long.toString(index);\r
-            ScriptRuntime.setElem(target, id, value, target);\r
-        } else {\r
-            ScriptRuntime.setElem(target, (int)index, value);\r
-        }\r
-    }\r
-\r
-    private static String jsFunction_toString(Context cx, Scriptable thisObj,\r
-                                              Object[] args)\r
-        throws JavaScriptException\r
-    {\r
-        return toStringHelper(cx, thisObj, \r
-                              cx.getLanguageVersion() == cx.VERSION_1_2,\r
-                              false);\r
-    }\r
-    \r
-    private static String jsFunction_toLocaleString(Context cx, \r
-                                                    Scriptable thisObj,\r
-                                                    Object[] args)\r
-        throws JavaScriptException\r
-    {\r
-        return toStringHelper(cx, thisObj, false, true);\r
-    }\r
-    \r
-    private static String toStringHelper(Context cx, Scriptable thisObj,\r
-                                         boolean toSource, boolean toLocale)\r
-        throws JavaScriptException\r
-    {\r
-        /* It's probably redundant to handle long lengths in this\r
-         * function; StringBuffers are limited to 2^31 in java.\r
-         */\r
-\r
-        long length = (long)getLengthProperty(thisObj);\r
-\r
-        StringBuffer result = new StringBuffer();\r
-\r
-        if (cx.iterating == null)\r
-            cx.iterating = new Hashtable(31);\r
-        boolean iterating = cx.iterating.get(thisObj) == Boolean.TRUE;\r
-\r
-        // whether to return '4,unquoted,5' or '[4, "quoted", 5]'\r
-        String separator;\r
-\r
-        if (toSource) {\r
-            result.append('[');\r
-            separator = ", ";\r
-        } else {\r
-            separator = ",";\r
-        }\r
-\r
-        boolean haslast = false;\r
-        long i = 0;\r
-\r
-        if (!iterating) {\r
-            for (i = 0; i < length; i++) {\r
-                if (i > 0)\r
-                    result.append(separator);\r
-                Object elem = getElem(thisObj, i);\r
-                if (elem == null || elem == Undefined.instance) {\r
-                    haslast = false;\r
-                    continue;\r
-                }\r
-                haslast = true;\r
-\r
-                if (elem instanceof String) {\r
-                    if (toSource) {\r
-                        result.append('\"');\r
-                        result.append(ScriptRuntime.escapeString\r
-                                      (ScriptRuntime.toString(elem)));\r
-                        result.append('\"');\r
-                    } else {\r
-                        result.append(ScriptRuntime.toString(elem));\r
-                    }\r
-                } else {\r
-                    /* wrap changes to cx.iterating in a try/finally\r
-                     * so that the reference always gets removed, and\r
-                     * we don't leak memory.  Good place for weak\r
-                     * references, if we had them.  */\r
-                    try {\r
-                        // stop recursion.\r
-                        cx.iterating.put(thisObj, Boolean.TRUE);\r
-                        if (toLocale && elem != Undefined.instance && \r
-                            elem != null) \r
-                        {\r
-                            Scriptable obj = cx.toObject(elem, thisObj);\r
-                            Object tls = ScriptRuntime.getProp(obj, \r
-                                             "toLocaleString", thisObj);\r
-                            elem = ScriptRuntime.call(cx, tls, elem, \r
-                                                      ScriptRuntime.emptyArgs);\r
-                        }\r
-                        result.append(ScriptRuntime.toString(elem));\r
-                    } finally {\r
-                        cx.iterating.remove(thisObj);\r
-                    }\r
-                }\r
-            }\r
-        }\r
-\r
-        if (toSource) {\r
-            //for [,,].length behavior; we want toString to be symmetric.\r
-            if (!haslast && i > 0)\r
-                result.append(", ]");\r
-            else\r
-                result.append(']');\r
-        }\r
-        return result.toString();\r
-    }\r
-\r
-    /**\r
-     * See ECMA 15.4.4.3\r
-     */\r
-    private static String jsFunction_join(Context cx, Scriptable thisObj,\r
-                                          Object[] args) \r
-    {\r
-        StringBuffer result = new StringBuffer();\r
-        String separator;\r
-\r
-        double length = getLengthProperty(thisObj);\r
-\r
-        // if no args, use "," as separator\r
-        if (args.length < 1) {\r
-            separator = ",";\r
-        } else {\r
-            separator = ScriptRuntime.toString(args[0]);\r
-        }\r
-        for (long i=0; i < length; i++) {\r
-            if (i > 0)\r
-                result.append(separator);\r
-            Object temp = getElem(thisObj, i);\r
-            if (temp == null || temp == Undefined.instance)\r
-                continue;\r
-            result.append(ScriptRuntime.toString(temp));\r
-        }\r
-        return result.toString();\r
-    }\r
-\r
-    /**\r
-     * See ECMA 15.4.4.4\r
-     */\r
-    private static Scriptable jsFunction_reverse(Context cx, \r
-                                                 Scriptable thisObj, \r
-                                                 Object[] args) \r
-    {\r
-        long len = (long)getLengthProperty(thisObj);\r
-\r
-        long half = len / 2;\r
-        for(long i=0; i < half; i++) {\r
-            long j = len - i - 1;\r
-            Object temp1 = getElem(thisObj, i);\r
-            Object temp2 = getElem(thisObj, j);\r
-            setElem(thisObj, i, temp2);\r
-            setElem(thisObj, j, temp1);\r
-        }\r
-        return thisObj;\r
-    }\r
-\r
-    /**\r
-     * See ECMA 15.4.4.5\r
-     */\r
-    private static Scriptable jsFunction_sort(Context cx, Scriptable scope,\r
-                                              Scriptable thisObj, \r
-                                              Object[] args)\r
-        throws JavaScriptException\r
-    {\r
-        long length = (long)getLengthProperty(thisObj);\r
-\r
-        Object compare;\r
-        if (args.length > 0 && Undefined.instance != args[0])\r
-            // sort with given compare function\r
-            compare = args[0];\r
-        else\r
-            // sort with default compare\r
-            compare = null;\r
-\r
-\r
-        // OPT: Would it make sense to use the extended sort for very small\r
-        // arrays?\r
-\r
-        // Should we use the extended sort function, or the faster one?\r
-        if (length >= Integer.MAX_VALUE) {\r
-            qsort_extended(cx, compare, thisObj, 0, length - 1);\r
-        } else {\r
-            // copy the JS array into a working array, so it can be\r
-            // sorted cheaply.\r
-            Object[] working = new Object[(int)length];\r
-            for (int i=0; i<length; i++) {\r
-                working[i] = getElem(thisObj, i);\r
-            }\r
-\r
-            qsort(cx, compare, working, 0, (int)length - 1, scope);\r
-\r
-            // copy the working array back into thisObj\r
-            for (int i=0; i<length; i++) {\r
-                setElem(thisObj, i, working[i]);\r
-            }\r
-        }\r
-        return thisObj;\r
-    }\r
-\r
-    private static double qsortCompare(Context cx, Object jsCompare, Object x,\r
-                                       Object y, Scriptable scope)\r
-        throws JavaScriptException\r
-    {\r
-        Object undef = Undefined.instance;\r
-\r
-        // sort undefined to end\r
-        if (undef == x || undef == y) {\r
-            if (undef != x)\r
-                return -1;\r
-            if (undef != y)\r
-                return 1;\r
-            return 0;\r
-        }\r
-\r
-        if (jsCompare == null) {\r
-            // if no compare function supplied, sort lexicographically\r
-            String a = ScriptRuntime.toString(x);\r
-            String b = ScriptRuntime.toString(y);\r
-\r
-            return a.compareTo(b);\r
-        } else {\r
-            // assemble args and call supplied JS compare function\r
-            // OPT: put this argument creation in the caller and reuse it.\r
-            // XXX what to do when compare function returns NaN?  ECMA states\r
-            // that it's then not a 'consistent compararison function'... but\r
-            // then what do we do?  Back out and start over with the generic\r
-            // compare function when we see a NaN?  Throw an error?\r
-            Object[] args = {x, y};\r
-//             return ScriptRuntime.toNumber(ScriptRuntime.call(jsCompare, null,\r
-//                                                              args));\r
-            // for now, just ignore it:\r
-            double d = ScriptRuntime.\r
-                toNumber(ScriptRuntime.call(cx, jsCompare, null, args, scope));\r
-\r
-            return (d == d) ? d : 0;\r
-        }\r
-    }\r
-\r
-    private static void qsort(Context cx, Object jsCompare, Object[] working,\r
-                              int lo, int hi, Scriptable scope)\r
-        throws JavaScriptException\r
-    {\r
-        Object pivot;\r
-        int i, j;\r
-        int a, b;\r
-\r
-        while (lo < hi) {\r
-            i = lo;\r
-            j = hi;\r
-            a = i;\r
-            pivot = working[a];\r
-            while (i < j) {\r
-                for(;;) {\r
-                    b = j;\r
-                    if (qsortCompare(cx, jsCompare, working[j], pivot, \r
-                                     scope) <= 0)\r
-                        break;\r
-                    j--;\r
-                }\r
-                working[a] = working[b];\r
-                while (i < j && qsortCompare(cx, jsCompare, working[a],\r
-                                             pivot, scope) <= 0)\r
-                {\r
-                    i++;\r
-                    a = i;\r
-                }\r
-                working[b] = working[a];\r
-            }\r
-            working[a] = pivot;\r
-            if (i - lo < hi - i) {\r
-                qsort(cx, jsCompare, working, lo, i - 1, scope);\r
-                lo = i + 1;\r
-            } else {\r
-                qsort(cx, jsCompare, working, i + 1, hi, scope);\r
-                hi = i - 1;\r
-            }\r
-        }\r
-    }\r
-\r
-    // A version that knows about long indices and doesn't use\r
-    // a working array.  Probably will never be used.\r
-    private static void qsort_extended(Context cx, Object jsCompare,\r
-                                       Scriptable target, long lo, long hi)\r
-        throws JavaScriptException\r
-    {\r
-        Object pivot;\r
-        long i, j;\r
-        long a, b;\r
-\r
-        while (lo < hi) {\r
-            i = lo;\r
-            j = hi;\r
-            a = i;\r
-            pivot = getElem(target, a);\r
-            while (i < j) {\r
-                for(;;) {\r
-                    b = j;\r
-                    if (qsortCompare(cx, jsCompare, getElem(target, j),\r
-                                     pivot, target) <= 0)\r
-                        break;\r
-                    j--;\r
-                }\r
-                setElem(target, a, getElem(target, b));\r
-                while (i < j && qsortCompare(cx, jsCompare,\r
-                                             getElem(target, a), \r
-                                             pivot, target) <= 0)\r
-                {\r
-                    i++;\r
-                    a = i;\r
-                }\r
-                setElem(target, b, getElem(target, a));\r
-            }\r
-            setElem(target, a, pivot);\r
-            if (i - lo < hi - i) {\r
-                qsort_extended(cx, jsCompare, target, lo, i - 1);\r
-                lo = i + 1;\r
-            } else {\r
-                qsort_extended(cx, jsCompare, target, i + 1, hi);\r
-                hi = i - 1;\r
-            }\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Non-ECMA methods.\r
-     */\r
-\r
-    private static Object jsFunction_push(Context cx, Scriptable thisObj,\r
-                                          Object[] args)\r
-    {\r
-        double length = getLengthProperty(thisObj);\r
-        for (int i = 0; i < args.length; i++) {\r
-            setElem(thisObj, (long)length + i, args[i]);\r
-        }\r
-\r
-        length += args.length;\r
-        ScriptRuntime.setProp(thisObj, "length", new Double(length), thisObj);\r
-\r
-        /*\r
-         * If JS1.2, follow Perl4 by returning the last thing pushed.\r
-         * Otherwise, return the new array length.\r
-         */\r
-        if (cx.getLanguageVersion() == Context.VERSION_1_2)\r
-            // if JS1.2 && no arguments, return undefined.\r
-            return args.length == 0\r
-                ? Context.getUndefinedValue()\r
-                : args[args.length - 1];\r
-\r
-        else\r
-            return new Long((long)length);\r
-    }\r
-\r
-    private static Object jsFunction_pop(Context cx, Scriptable thisObj,\r
-                                         Object[] args) {\r
-        Object result;\r
-        double length = getLengthProperty(thisObj);\r
-        if (length > 0) {\r
-            length--;\r
-\r
-            // Get the to-be-deleted property's value.\r
-            result = getElem(thisObj, (long)length);\r
-\r
-            // We don't need to delete the last property, because\r
-            // setLength does that for us.\r
-        } else {\r
-            result = Context.getUndefinedValue();\r
-        }\r
-        // necessary to match js even when length < 0; js pop will give a\r
-        // length property to any target it is called on.\r
-        ScriptRuntime.setProp(thisObj, "length", new Double(length), thisObj);\r
-\r
-        return result;\r
-    }\r
-\r
-    private static Object jsFunction_shift(Context cx, Scriptable thisObj,\r
-                                           Object[] args)\r
-    {\r
-        Object result;\r
-        double length = getLengthProperty(thisObj);\r
-        if (length > 0) {\r
-            long i = 0;\r
-            length--;\r
-\r
-            // Get the to-be-deleted property's value.\r
-            result = getElem(thisObj, i);\r
-\r
-            /*\r
-             * Slide down the array above the first element.  Leave i\r
-             * set to point to the last element.\r
-             */\r
-            if (length > 0) {\r
-                for (i = 1; i <= length; i++) {\r
-                    Object temp = getElem(thisObj, i);\r
-                    setElem(thisObj, i - 1, temp);\r
-                }\r
-            }\r
-            // We don't need to delete the last property, because\r
-            // setLength does that for us.\r
-        } else {\r
-            result = Context.getUndefinedValue();\r
-        }\r
-        ScriptRuntime.setProp(thisObj, "length", new Double(length), thisObj);\r
-        return result;\r
-    }\r
-\r
-    private static Object jsFunction_unshift(Context cx, Scriptable thisObj,\r
-                                             Object[] args)\r
-    {\r
-        Object result;\r
-        double length = (double)getLengthProperty(thisObj);\r
-        int argc = args.length;\r
-\r
-        if (args.length > 0) {\r
-            /*  Slide up the array to make room for args at the bottom */\r
-            if (length > 0) {\r
-                for (long last = (long)length - 1; last >= 0; last--) {\r
-                    Object temp = getElem(thisObj, last);\r
-                    setElem(thisObj, last + argc, temp);\r
-                }\r
-            }\r
-\r
-            /* Copy from argv to the bottom of the array. */\r
-            for (int i = 0; i < args.length; i++) {\r
-                setElem(thisObj, i, args[i]);\r
-            }\r
-\r
-            /* Follow Perl by returning the new array length. */\r
-            length += args.length;\r
-            ScriptRuntime.setProp(thisObj, "length",\r
-                                  new Double(length), thisObj);\r
-        }\r
-        return new Long((long)length);\r
-    }\r
-\r
-    private static Object jsFunction_splice(Context cx, Scriptable scope,\r
-                                            Scriptable thisObj, Object[] args)\r
-    {\r
-        /* create an empty Array to return. */\r
-        scope = getTopLevelScope(scope);\r
-        Object result = ScriptRuntime.newObject(cx, scope, "Array", null);\r
-        int argc = args.length;\r
-        if (argc == 0)\r
-            return result;\r
-        double length = getLengthProperty(thisObj);\r
-\r
-        /* Convert the first argument into a starting index. */\r
-        double begin = ScriptRuntime.toInteger(args[0]);\r
-        double end;\r
-        double delta;\r
-        double count;\r
-\r
-        if (begin < 0) {\r
-            begin += length;\r
-            if (begin < 0)\r
-                begin = 0;\r
-        } else if (begin > length) {\r
-            begin = length;\r
-        }\r
-        argc--;\r
-\r
-        /* Convert the second argument from a count into a fencepost index. */\r
-        delta = length - begin;\r
-\r
-        if (args.length == 1) {\r
-            count = delta;\r
-            end = length;\r
-        } else {\r
-            count = ScriptRuntime.toInteger(args[1]);\r
-            if (count < 0)\r
-                count = 0;\r
-            else if (count > delta)\r
-                count = delta;\r
-            end = begin + count;\r
-\r
-            argc--;\r
-        }\r
-\r
-        long lbegin = (long)begin;\r
-        long lend = (long)end;\r
-\r
-        /* If there are elements to remove, put them into the return value. */\r
-        if (count > 0) {\r
-            if (count == 1\r
-                && (cx.getLanguageVersion() == Context.VERSION_1_2))\r
-            {\r
-                /*\r
-                 * JS lacks "list context", whereby in Perl one turns the\r
-                 * single scalar that's spliced out into an array just by\r
-                 * assigning it to @single instead of $single, or by using it\r
-                 * as Perl push's first argument, for instance.\r
-                 *\r
-                 * JS1.2 emulated Perl too closely and returned a non-Array for\r
-                 * the single-splice-out case, requiring callers to test and\r
-                 * wrap in [] if necessary.  So JS1.3, default, and other\r
-                 * versions all return an array of length 1 for uniformity.\r
-                 */\r
-                result = getElem(thisObj, lbegin);\r
-            } else {\r
-                for (long last = lbegin; last < lend; last++) {\r
-                    Scriptable resultArray = (Scriptable)result;\r
-                    Object temp = getElem(thisObj, last);\r
-                    setElem(resultArray, last - lbegin, temp);\r
-                }\r
-            }\r
-        } else if (count == 0\r
-                   && cx.getLanguageVersion() == Context.VERSION_1_2)\r
-        {\r
-            /* Emulate C JS1.2; if no elements are removed, return undefined. */\r
-            result = Context.getUndefinedValue();\r
-        }\r
-\r
-        /* Find the direction (up or down) to copy and make way for argv. */\r
-        delta = argc - count;\r
-\r
-        if (delta > 0) {\r
-            for (long last = (long)length - 1; last >= lend; last--) {\r
-                Object temp = getElem(thisObj, last);\r
-                setElem(thisObj, last + (long)delta, temp);\r
-            }\r
-        } else if (delta < 0) {\r
-            for (long last = lend; last < length; last++) {\r
-                Object temp = getElem(thisObj, last);\r
-                setElem(thisObj, last + (long)delta, temp);\r
-            }\r
-        }\r
-\r
-        /* Copy from argv into the hole to complete the splice. */\r
-        int argoffset = args.length - argc;\r
-        for (int i = 0; i < argc; i++) {\r
-            setElem(thisObj, lbegin + i, args[i + argoffset]);\r
-        }\r
-\r
-        /* Update length in case we deleted elements from the end. */\r
-        ScriptRuntime.setProp(thisObj, "length",\r
-                              new Double(length + delta), thisObj);\r
-        return result;\r
-    }\r
-\r
-    /*\r
-     * Python-esque sequence operations.\r
-     */\r
-    private static Scriptable jsFunction_concat(Context cx, Scriptable scope, \r
-                                                Scriptable thisObj,\r
-                                                Object[] args)\r
-    {\r
-        /* Concat tries to keep the definition of an array as general\r
-         * as possible; if it finds that an object has a numeric\r
-         * 'length' property, then it treats that object as an array.\r
-         * This treats string atoms and string objects differently; as\r
-         * string objects have a length property and are accessible by\r
-         * index, they get exploded into arrays when added, while\r
-         * atomic strings are just added as strings.\r
-         */\r
-\r
-        // create an empty Array to return.\r
-        scope = getTopLevelScope(scope);\r
-        Scriptable result = ScriptRuntime.newObject(cx, scope, "Array", null);\r
-        double length;\r
-        long slot = 0;\r
-\r
-        /* Put the target in the result array; only add it as an array\r
-         * if it looks like one.\r
-         */\r
-        if (hasLengthProperty(thisObj)) {\r
-            length = getLengthProperty(thisObj);\r
-\r
-            // Copy from the target object into the result\r
-            for (slot = 0; slot < length; slot++) {\r
-                Object temp = getElem(thisObj, slot);\r
-                setElem(result, slot, temp);\r
-            }\r
-        } else {\r
-            setElem(result, slot++, thisObj);\r
-        }\r
-\r
-        /* Copy from the arguments into the result.  If any argument\r
-         * has a numeric length property, treat it as an array and add\r
-         * elements separately; otherwise, just copy the argument.\r
-         */\r
-        for (int i = 0; i < args.length; i++) {\r
-            if (hasLengthProperty(args[i])) {\r
-                // hasLengthProperty => instanceOf Scriptable.\r
-                Scriptable arg = (Scriptable)args[i];\r
-                length = getLengthProperty(arg);\r
-                for (long j = 0; j < length; j++, slot++) {\r
-                    Object temp = getElem(arg, j);\r
-                    setElem(result, slot, temp);\r
-                }\r
-            } else {\r
-                setElem(result, slot++, args[i]);\r
-            }\r
-        }\r
-        return result;\r
-    }\r
-\r
-    private Scriptable jsFunction_slice(Context cx, Scriptable thisObj,\r
-                                        Object[] args)\r
-    {\r
-        Scriptable scope = getTopLevelScope(this);\r
-        Scriptable result = ScriptRuntime.newObject(cx, scope, "Array", null);\r
-        double length = getLengthProperty(thisObj);\r
-\r
-        double begin = 0;\r
-        double end = length;\r
-\r
-        if (args.length > 0) {\r
-            begin = ScriptRuntime.toInteger(args[0]);\r
-            if (begin < 0) {\r
-                begin += length;\r
-                if (begin < 0)\r
-                    begin = 0;\r
-            } else if (begin > length) {\r
-                begin = length;\r
-            }\r
-\r
-            if (args.length > 1) {\r
-                end = ScriptRuntime.toInteger(args[1]);\r
-                if (end < 0) {\r
-                    end += length;\r
-                    if (end < 0)\r
-                        end = 0;\r
-                } else if (end > length) {\r
-                    end = length;\r
-                }\r
-            }\r
-        }\r
-\r
-        long lbegin = (long)begin;\r
-        long lend = (long)end;\r
-        for (long slot = lbegin; slot < lend; slot++) {\r
-            Object temp = getElem(thisObj, slot);\r
-            setElem(result, slot - lbegin, temp);\r
-        }\r
-\r
-        return result;\r
-    }\r
-\r
-    protected int maxInstanceId() { return MAX_INSTANCE_ID; }\r
-\r
-    protected String getIdName(int id) {\r
-        if (id == Id_length) { return "length"; }\r
-\r
-        if (prototypeFlag) {\r
-            switch (id) {\r
-                case Id_constructor:     return "constructor";\r
-                case Id_toString:        return "toString";\r
-                case Id_toLocaleString:  return "toLocaleString";\r
-                case Id_join:            return "join";\r
-                case Id_reverse:         return "reverse";\r
-                case Id_sort:            return "sort";\r
-                case Id_push:            return "push";\r
-                case Id_pop:             return "pop";\r
-                case Id_shift:           return "shift";\r
-                case Id_unshift:         return "unshift";\r
-                case Id_splice:          return "splice";\r
-                case Id_concat:          return "concat";\r
-                case Id_slice:           return "slice";\r
-            }\r
-        }\r
-        return null;\r
-    }\r
-\r
-    private static final int\r
-        Id_length        =  1,\r
-        MAX_INSTANCE_ID  =  1;\r
-\r
-    protected int mapNameToId(String s) {\r
-        if (s.equals("length")) { return Id_length; }\r
-        else if (prototypeFlag) { \r
-            return toPrototypeId(s); \r
-        }\r
-        return 0;\r
-    }\r
-\r
-// #string_id_map#\r
-\r
-    private static int toPrototypeId(String s) {\r
-        int id;\r
-// #generated# Last update: 2001-04-23 11:46:01 GMT+02:00\r
-        L0: { id = 0; String X = null; int c;\r
-            L: switch (s.length()) {\r
-            case 3: X="pop";id=Id_pop; break L;\r
-            case 4: c=s.charAt(0);\r
-                if (c=='j') { X="join";id=Id_join; }\r
-                else if (c=='p') { X="push";id=Id_push; }\r
-                else if (c=='s') { X="sort";id=Id_sort; }\r
-                break L;\r
-            case 5: c=s.charAt(1);\r
-                if (c=='h') { X="shift";id=Id_shift; }\r
-                else if (c=='l') { X="slice";id=Id_slice; }\r
-                break L;\r
-            case 6: c=s.charAt(0);\r
-                if (c=='c') { X="concat";id=Id_concat; }\r
-                else if (c=='l') { X="length";id=Id_length; }\r
-                else if (c=='s') { X="splice";id=Id_splice; }\r
-                break L;\r
-            case 7: c=s.charAt(0);\r
-                if (c=='r') { X="reverse";id=Id_reverse; }\r
-                else if (c=='u') { X="unshift";id=Id_unshift; }\r
-                break L;\r
-            case 8: X="toString";id=Id_toString; break L;\r
-            case 11: X="constructor";id=Id_constructor; break L;\r
-            case 14: X="toLocaleString";id=Id_toLocaleString; break L;\r
-            }\r
-            if (X!=null && X!=s && !X.equals(s)) id = 0;\r
-        }\r
-// #/generated#\r
-        return id;\r
-    }\r
-\r
-    private static final int\r
-        Id_constructor          = MAX_INSTANCE_ID + 1,\r
-        Id_toString             = MAX_INSTANCE_ID + 2,\r
-        Id_toLocaleString       = MAX_INSTANCE_ID + 3,\r
-        Id_join                 = MAX_INSTANCE_ID + 4,\r
-        Id_reverse              = MAX_INSTANCE_ID + 5,\r
-        Id_sort                 = MAX_INSTANCE_ID + 6,\r
-        Id_push                 = MAX_INSTANCE_ID + 7,\r
-        Id_pop                  = MAX_INSTANCE_ID + 8,\r
-        Id_shift                = MAX_INSTANCE_ID + 9,\r
-        Id_unshift              = MAX_INSTANCE_ID + 10,\r
-        Id_splice               = MAX_INSTANCE_ID + 11,\r
-        Id_concat               = MAX_INSTANCE_ID + 12,\r
-        Id_slice                = MAX_INSTANCE_ID + 13,\r
-\r
-        MAX_PROTOTYPE_ID        = MAX_INSTANCE_ID + 13;\r
-\r
-// #/string_id_map#\r
-\r
-    private long length;\r
-    private Object[] dense;\r
-    private static final int maximumDenseLength = 10000;\r
-    \r
-    private boolean prototypeFlag;\r
-}\r