Source Code Cross Referenced for NativeArray.java in  » Scripting » rhino » org » mozilla » javascript » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Scripting » rhino » org.mozilla.javascript 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
0002:         *
0003:         * ***** BEGIN LICENSE BLOCK *****
0004:         * Version: MPL 1.1/GPL 2.0
0005:         *
0006:         * The contents of this file are subject to the Mozilla Public License Version
0007:         * 1.1 (the "License"); you may not use this file except in compliance with
0008:         * the License. You may obtain a copy of the License at
0009:         * http://www.mozilla.org/MPL/
0010:         *
0011:         * Software distributed under the License is distributed on an "AS IS" basis,
0012:         * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
0013:         * for the specific language governing rights and limitations under the
0014:         * License.
0015:         *
0016:         * The Original Code is Rhino code, released
0017:         * May 6, 1999.
0018:         *
0019:         * The Initial Developer of the Original Code is
0020:         * Netscape Communications Corporation.
0021:         * Portions created by the Initial Developer are Copyright (C) 1997-1999
0022:         * the Initial Developer. All Rights Reserved.
0023:         *
0024:         * Contributor(s):
0025:         *   Norris Boyd
0026:         *   Mike McCabe
0027:         *   Igor Bukanov
0028:         *
0029:         * Alternatively, the contents of this file may be used under the terms of
0030:         * the GNU General Public License Version 2 or later (the "GPL"), in which
0031:         * case the provisions of the GPL are applicable instead of those above. If
0032:         * you wish to allow use of your version of this file only under the terms of
0033:         * the GPL and not to allow others to use your version of this file under the
0034:         * MPL, indicate your decision by deleting the provisions above and replacing
0035:         * them with the notice and other provisions required by the GPL. If you do
0036:         * not delete the provisions above, a recipient may use your version of this
0037:         * file under either the MPL or the GPL.
0038:         *
0039:         * ***** END LICENSE BLOCK ***** */
0040:
0041:        package org.mozilla.javascript;
0042:
0043:        import java.util.Arrays;
0044:
0045:        /**
0046:         * This class implements the Array native object.
0047:         * @author Norris Boyd
0048:         * @author Mike McCabe
0049:         */
0050:        public class NativeArray extends IdScriptableObject {
0051:            static final long serialVersionUID = 7331366857676127338L;
0052:
0053:            /*
0054:             * Optimization possibilities and open issues:
0055:             * - Long vs. double schizophrenia.  I suspect it might be better
0056:             * to use double throughout.
0057:             *
0058:             * - Functions that need a new Array call "new Array" in the
0059:             * current scope rather than using a hardwired constructor;
0060:             * "Array" could be redefined.  It turns out that js calls the
0061:             * equivalent of "new Array" in the current scope, except that it
0062:             * always gets at least an object back, even when Array == null.
0063:             */
0064:
0065:            private static final Object ARRAY_TAG = new Object();
0066:            private static final Integer NEGATIVE_ONE = new Integer(-1);
0067:
0068:            static void init(Scriptable scope, boolean sealed) {
0069:                NativeArray obj = new NativeArray(0);
0070:                obj.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed);
0071:            }
0072:
0073:            static int getMaximumInitialCapacity() {
0074:                return maximumInitialCapacity;
0075:            }
0076:
0077:            static void setMaximumInitialCapacity(int maximumInitialCapacity) {
0078:                NativeArray.maximumInitialCapacity = maximumInitialCapacity;
0079:            }
0080:
0081:            public NativeArray(long lengthArg) {
0082:                denseOnly = lengthArg <= maximumInitialCapacity;
0083:                if (denseOnly) {
0084:                    int intLength = (int) lengthArg;
0085:                    if (intLength < DEFAULT_INITIAL_CAPACITY)
0086:                        intLength = DEFAULT_INITIAL_CAPACITY;
0087:                    dense = new Object[intLength];
0088:                    Arrays.fill(dense, Scriptable.NOT_FOUND);
0089:                }
0090:                length = lengthArg;
0091:            }
0092:
0093:            public NativeArray(Object[] array) {
0094:                denseOnly = true;
0095:                dense = array;
0096:                length = array.length;
0097:            }
0098:
0099:            public String getClassName() {
0100:                return "Array";
0101:            }
0102:
0103:            private static final int Id_length = 1, MAX_INSTANCE_ID = 1;
0104:
0105:            protected int getMaxInstanceId() {
0106:                return MAX_INSTANCE_ID;
0107:            }
0108:
0109:            protected int findInstanceIdInfo(String s) {
0110:                if (s.equals("length")) {
0111:                    return instanceIdInfo(DONTENUM | PERMANENT, Id_length);
0112:                }
0113:                return super .findInstanceIdInfo(s);
0114:            }
0115:
0116:            protected String getInstanceIdName(int id) {
0117:                if (id == Id_length) {
0118:                    return "length";
0119:                }
0120:                return super .getInstanceIdName(id);
0121:            }
0122:
0123:            protected Object getInstanceIdValue(int id) {
0124:                if (id == Id_length) {
0125:                    return ScriptRuntime.wrapNumber(length);
0126:                }
0127:                return super .getInstanceIdValue(id);
0128:            }
0129:
0130:            protected void setInstanceIdValue(int id, Object value) {
0131:                if (id == Id_length) {
0132:                    setLength(value);
0133:                    return;
0134:                }
0135:                super .setInstanceIdValue(id, value);
0136:            }
0137:
0138:            protected void fillConstructorProperties(IdFunctionObject ctor) {
0139:                addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_join,
0140:                        "join", 2);
0141:                addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_reverse,
0142:                        "reverse", 1);
0143:                addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_sort,
0144:                        "sort", 2);
0145:                addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_push,
0146:                        "push", 2);
0147:                addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_pop,
0148:                        "pop", 2);
0149:                addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_shift,
0150:                        "shift", 2);
0151:                addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_unshift,
0152:                        "unshift", 2);
0153:                addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_splice,
0154:                        "splice", 2);
0155:                addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_concat,
0156:                        "concat", 2);
0157:                addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_slice,
0158:                        "slice", 2);
0159:                addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_indexOf,
0160:                        "indexOf", 2);
0161:                addIdFunctionProperty(ctor, ARRAY_TAG,
0162:                        ConstructorId_lastIndexOf, "lastIndexOf", 2);
0163:                addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_every,
0164:                        "every", 2);
0165:                addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_filter,
0166:                        "filter", 2);
0167:                addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_forEach,
0168:                        "forEach", 2);
0169:                addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_map,
0170:                        "map", 2);
0171:                addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_some,
0172:                        "some", 2);
0173:                super .fillConstructorProperties(ctor);
0174:            }
0175:
0176:            protected void initPrototypeId(int id) {
0177:                String s;
0178:                int arity;
0179:                switch (id) {
0180:                case Id_constructor:
0181:                    arity = 1;
0182:                    s = "constructor";
0183:                    break;
0184:                case Id_toString:
0185:                    arity = 0;
0186:                    s = "toString";
0187:                    break;
0188:                case Id_toLocaleString:
0189:                    arity = 1;
0190:                    s = "toLocaleString";
0191:                    break;
0192:                case Id_toSource:
0193:                    arity = 0;
0194:                    s = "toSource";
0195:                    break;
0196:                case Id_join:
0197:                    arity = 1;
0198:                    s = "join";
0199:                    break;
0200:                case Id_reverse:
0201:                    arity = 0;
0202:                    s = "reverse";
0203:                    break;
0204:                case Id_sort:
0205:                    arity = 1;
0206:                    s = "sort";
0207:                    break;
0208:                case Id_push:
0209:                    arity = 1;
0210:                    s = "push";
0211:                    break;
0212:                case Id_pop:
0213:                    arity = 1;
0214:                    s = "pop";
0215:                    break;
0216:                case Id_shift:
0217:                    arity = 1;
0218:                    s = "shift";
0219:                    break;
0220:                case Id_unshift:
0221:                    arity = 1;
0222:                    s = "unshift";
0223:                    break;
0224:                case Id_splice:
0225:                    arity = 1;
0226:                    s = "splice";
0227:                    break;
0228:                case Id_concat:
0229:                    arity = 1;
0230:                    s = "concat";
0231:                    break;
0232:                case Id_slice:
0233:                    arity = 1;
0234:                    s = "slice";
0235:                    break;
0236:                case Id_indexOf:
0237:                    arity = 1;
0238:                    s = "indexOf";
0239:                    break;
0240:                case Id_lastIndexOf:
0241:                    arity = 1;
0242:                    s = "lastIndexOf";
0243:                    break;
0244:                case Id_every:
0245:                    arity = 1;
0246:                    s = "every";
0247:                    break;
0248:                case Id_filter:
0249:                    arity = 1;
0250:                    s = "filter";
0251:                    break;
0252:                case Id_forEach:
0253:                    arity = 1;
0254:                    s = "forEach";
0255:                    break;
0256:                case Id_map:
0257:                    arity = 1;
0258:                    s = "map";
0259:                    break;
0260:                case Id_some:
0261:                    arity = 1;
0262:                    s = "some";
0263:                    break;
0264:                default:
0265:                    throw new IllegalArgumentException(String.valueOf(id));
0266:                }
0267:                initPrototypeMethod(ARRAY_TAG, id, s, arity);
0268:            }
0269:
0270:            public Object execIdCall(IdFunctionObject f, Context cx,
0271:                    Scriptable scope, Scriptable this Obj, Object[] args) {
0272:                if (!f.hasTag(ARRAY_TAG)) {
0273:                    return super .execIdCall(f, cx, scope, this Obj, args);
0274:                }
0275:                int id = f.methodId();
0276:                again: for (;;) {
0277:                    switch (id) {
0278:                    case ConstructorId_join:
0279:                    case ConstructorId_reverse:
0280:                    case ConstructorId_sort:
0281:                    case ConstructorId_push:
0282:                    case ConstructorId_pop:
0283:                    case ConstructorId_shift:
0284:                    case ConstructorId_unshift:
0285:                    case ConstructorId_splice:
0286:                    case ConstructorId_concat:
0287:                    case ConstructorId_slice:
0288:                    case ConstructorId_indexOf:
0289:                    case ConstructorId_lastIndexOf:
0290:                    case ConstructorId_every:
0291:                    case ConstructorId_filter:
0292:                    case ConstructorId_forEach:
0293:                    case ConstructorId_map:
0294:                    case ConstructorId_some: {
0295:                        this Obj = ScriptRuntime.toObject(scope, args[0]);
0296:                        Object[] newArgs = new Object[args.length - 1];
0297:                        for (int i = 0; i < newArgs.length; i++)
0298:                            newArgs[i] = args[i + 1];
0299:                        args = newArgs;
0300:                        id = -id;
0301:                        continue again;
0302:                    }
0303:
0304:                    case Id_constructor: {
0305:                        boolean inNewExpr = (this Obj == null);
0306:                        if (!inNewExpr) {
0307:                            // IdFunctionObject.construct will set up parent, proto
0308:                            return f.construct(cx, scope, args);
0309:                        }
0310:                        return jsConstructor(cx, scope, args);
0311:                    }
0312:
0313:                    case Id_toString:
0314:                        return toStringHelper(
0315:                                cx,
0316:                                scope,
0317:                                this Obj,
0318:                                cx
0319:                                        .hasFeature(Context.FEATURE_TO_STRING_AS_SOURCE),
0320:                                false);
0321:
0322:                    case Id_toLocaleString:
0323:                        return toStringHelper(cx, scope, this Obj, false, true);
0324:
0325:                    case Id_toSource:
0326:                        return toStringHelper(cx, scope, this Obj, true, false);
0327:
0328:                    case Id_join:
0329:                        return js_join(cx, this Obj, args);
0330:
0331:                    case Id_reverse:
0332:                        return js_reverse(cx, this Obj, args);
0333:
0334:                    case Id_sort:
0335:                        return js_sort(cx, scope, this Obj, args);
0336:
0337:                    case Id_push:
0338:                        return js_push(cx, this Obj, args);
0339:
0340:                    case Id_pop:
0341:                        return js_pop(cx, this Obj, args);
0342:
0343:                    case Id_shift:
0344:                        return js_shift(cx, this Obj, args);
0345:
0346:                    case Id_unshift:
0347:                        return js_unshift(cx, this Obj, args);
0348:
0349:                    case Id_splice:
0350:                        return js_splice(cx, scope, this Obj, args);
0351:
0352:                    case Id_concat:
0353:                        return js_concat(cx, scope, this Obj, args);
0354:
0355:                    case Id_slice:
0356:                        return js_slice(cx, this Obj, args);
0357:
0358:                    case Id_indexOf:
0359:                        return indexOfHelper(cx, this Obj, args, false);
0360:
0361:                    case Id_lastIndexOf:
0362:                        return indexOfHelper(cx, this Obj, args, true);
0363:
0364:                    case Id_every:
0365:                    case Id_filter:
0366:                    case Id_forEach:
0367:                    case Id_map:
0368:                    case Id_some:
0369:                        return iterativeMethod(cx, id, scope, this Obj, args);
0370:                    }
0371:                    throw new IllegalArgumentException(String.valueOf(id));
0372:                }
0373:            }
0374:
0375:            public Object get(int index, Scriptable start) {
0376:                if (!denseOnly && isGetterOrSetter(null, index, false))
0377:                    return super .get(index, start);
0378:                if (dense != null && 0 <= index && index < dense.length)
0379:                    return dense[index];
0380:                return super .get(index, start);
0381:            }
0382:
0383:            public boolean has(int index, Scriptable start) {
0384:                if (!denseOnly && isGetterOrSetter(null, index, false))
0385:                    return super .has(index, start);
0386:                if (dense != null && 0 <= index && index < dense.length)
0387:                    return dense[index] != NOT_FOUND;
0388:                return super .has(index, start);
0389:            }
0390:
0391:            // if id is an array index (ECMA 15.4.0), return the number,
0392:            // otherwise return -1L
0393:            private static long toArrayIndex(String id) {
0394:                double d = ScriptRuntime.toNumber(id);
0395:                if (d == d) {
0396:                    long index = ScriptRuntime.toUint32(d);
0397:                    if (index == d && index != 4294967295L) {
0398:                        // Assume that ScriptRuntime.toString(index) is the same
0399:                        // as java.lang.Long.toString(index) for long
0400:                        if (Long.toString(index).equals(id)) {
0401:                            return index;
0402:                        }
0403:                    }
0404:                }
0405:                return -1;
0406:            }
0407:
0408:            public void put(String id, Scriptable start, Object value) {
0409:                super .put(id, start, value);
0410:                if (start == this ) {
0411:                    // If the object is sealed, super will throw exception
0412:                    long index = toArrayIndex(id);
0413:                    if (index >= length) {
0414:                        length = index + 1;
0415:                        denseOnly = false;
0416:                    }
0417:                }
0418:            }
0419:
0420:            private boolean ensureCapacity(int capacity) {
0421:                if (capacity > dense.length) {
0422:                    if (capacity > MAX_PRE_GROW_SIZE) {
0423:                        denseOnly = false;
0424:                        return false;
0425:                    }
0426:                    capacity = Math.max(capacity,
0427:                            (int) (dense.length * GROW_FACTOR));
0428:                    Object[] newDense = new Object[capacity];
0429:                    System.arraycopy(dense, 0, newDense, 0, dense.length);
0430:                    Arrays.fill(newDense, dense.length, newDense.length,
0431:                            Scriptable.NOT_FOUND);
0432:                    dense = newDense;
0433:                }
0434:                return true;
0435:            }
0436:
0437:            public void put(int index, Scriptable start, Object value) {
0438:                if (start == this  && !isSealed() && dense != null && 0 <= index
0439:                        && (denseOnly || !isGetterOrSetter(null, index, true))) {
0440:                    if (index < dense.length) {
0441:                        dense[index] = value;
0442:                        if (this .length <= index)
0443:                            this .length = (long) index + 1;
0444:                        return;
0445:                    } else if (denseOnly && index < dense.length * GROW_FACTOR
0446:                            && ensureCapacity(index + 1)) {
0447:                        dense[index] = value;
0448:                        this .length = (long) index + 1;
0449:                        return;
0450:                    } else {
0451:                        denseOnly = false;
0452:                    }
0453:                }
0454:                super .put(index, start, value);
0455:                if (start == this ) {
0456:                    // only set the array length if given an array index (ECMA 15.4.0)
0457:                    if (this .length <= index) {
0458:                        // avoid overflowing index!
0459:                        this .length = (long) index + 1;
0460:                    }
0461:                }
0462:            }
0463:
0464:            public void delete(int index) {
0465:                if (dense != null && 0 <= index && index < dense.length
0466:                        && !isSealed()
0467:                        && (denseOnly || !isGetterOrSetter(null, index, true))) {
0468:                    dense[index] = NOT_FOUND;
0469:                } else {
0470:                    super .delete(index);
0471:                }
0472:            }
0473:
0474:            public Object[] getIds() {
0475:                Object[] super Ids = super .getIds();
0476:                if (dense == null) {
0477:                    return super Ids;
0478:                }
0479:                int N = dense.length;
0480:                long currentLength = length;
0481:                if (N > currentLength) {
0482:                    N = (int) currentLength;
0483:                }
0484:                if (N == 0) {
0485:                    return super Ids;
0486:                }
0487:                int super Length = super Ids.length;
0488:                Object[] ids = new Object[N + super Length];
0489:
0490:                int presentCount = 0;
0491:                for (int i = 0; i != N; ++i) {
0492:                    // Replace existing elements by their indexes
0493:                    if (dense[i] != NOT_FOUND) {
0494:                        ids[presentCount] = new Integer(i);
0495:                        ++presentCount;
0496:                    }
0497:                }
0498:                if (presentCount != N) {
0499:                    // dense contains deleted elems, need to shrink the result
0500:                    Object[] tmp = new Object[presentCount + super Length];
0501:                    System.arraycopy(ids, 0, tmp, 0, presentCount);
0502:                    ids = tmp;
0503:                }
0504:                System.arraycopy(super Ids, 0, ids, presentCount, super Length);
0505:                return ids;
0506:            }
0507:
0508:            public Object getDefaultValue(Class hint) {
0509:                if (hint == ScriptRuntime.NumberClass) {
0510:                    Context cx = Context.getContext();
0511:                    if (cx.getLanguageVersion() == Context.VERSION_1_2)
0512:                        return new Long(length);
0513:                }
0514:                return super .getDefaultValue(hint);
0515:            }
0516:
0517:            /**
0518:             * See ECMA 15.4.1,2
0519:             */
0520:            private static Object jsConstructor(Context cx, Scriptable scope,
0521:                    Object[] args) {
0522:                if (args.length == 0)
0523:                    return new NativeArray(0);
0524:
0525:                // Only use 1 arg as first element for version 1.2; for
0526:                // any other version (including 1.3) follow ECMA and use it as
0527:                // a length.
0528:                if (cx.getLanguageVersion() == Context.VERSION_1_2) {
0529:                    return new NativeArray(args);
0530:                } else {
0531:                    Object arg0 = args[0];
0532:                    if (args.length > 1 || !(arg0 instanceof  Number)) {
0533:                        return new NativeArray(args);
0534:                    } else {
0535:                        long len = ScriptRuntime.toUint32(arg0);
0536:                        if (len != ((Number) arg0).doubleValue())
0537:                            throw Context
0538:                                    .reportRuntimeError0("msg.arraylength.bad");
0539:                        return new NativeArray(len);
0540:                    }
0541:                }
0542:            }
0543:
0544:            public long getLength() {
0545:                return length;
0546:            }
0547:
0548:            /** @deprecated Use {@link #getLength()} instead. */
0549:            public long jsGet_length() {
0550:                return getLength();
0551:            }
0552:
0553:            /**
0554:             * Change the value of the internal flag that determines whether all
0555:             * storage is handed by a dense backing array rather than an associative
0556:             * store.
0557:             * @param denseOnly new value for denseOnly flag
0558:             * @throws IllegalArgumentException if an attempt is made to enable
0559:             *   denseOnly after it was disabled; NativeArray code is not written
0560:             *   to handle switching back to a dense representation
0561:             */
0562:            void setDenseOnly(boolean denseOnly) {
0563:                if (denseOnly && !this .denseOnly)
0564:                    throw new IllegalArgumentException();
0565:                this .denseOnly = denseOnly;
0566:            }
0567:
0568:            private void setLength(Object val) {
0569:                /* XXX do we satisfy this?
0570:                 * 15.4.5.1 [[Put]](P, V):
0571:                 * 1. Call the [[CanPut]] method of A with name P.
0572:                 * 2. If Result(1) is false, return.
0573:                 * ?
0574:                 */
0575:
0576:                double d = ScriptRuntime.toNumber(val);
0577:                long longVal = ScriptRuntime.toUint32(d);
0578:                if (longVal != d)
0579:                    throw Context.reportRuntimeError0("msg.arraylength.bad");
0580:
0581:                if (denseOnly) {
0582:                    if (longVal < length) {
0583:                        // downcast okay because denseOnly
0584:                        Arrays.fill(dense, (int) longVal, dense.length,
0585:                                NOT_FOUND);
0586:                        length = longVal;
0587:                        return;
0588:                    } else if (longVal < MAX_PRE_GROW_SIZE
0589:                            && longVal < (length * GROW_FACTOR)
0590:                            && ensureCapacity((int) longVal)) {
0591:                        length = longVal;
0592:                        return;
0593:                    } else {
0594:                        denseOnly = false;
0595:                    }
0596:                }
0597:                if (longVal < length) {
0598:                    // remove all properties between longVal and length
0599:                    if (length - longVal > 0x1000) {
0600:                        // assume that the representation is sparse
0601:                        Object[] e = getIds(); // will only find in object itself
0602:                        for (int i = 0; i < e.length; i++) {
0603:                            Object id = e[i];
0604:                            if (id instanceof  String) {
0605:                                // > MAXINT will appear as string
0606:                                String strId = (String) id;
0607:                                long index = toArrayIndex(strId);
0608:                                if (index >= longVal)
0609:                                    delete(strId);
0610:                            } else {
0611:                                int index = ((Integer) id).intValue();
0612:                                if (index >= longVal)
0613:                                    delete(index);
0614:                            }
0615:                        }
0616:                    } else {
0617:                        // assume a dense representation
0618:                        for (long i = longVal; i < length; i++) {
0619:                            deleteElem(this , i);
0620:                        }
0621:                    }
0622:                }
0623:                length = longVal;
0624:            }
0625:
0626:            /* Support for generic Array-ish objects.  Most of the Array
0627:             * functions try to be generic; anything that has a length
0628:             * property is assumed to be an array.
0629:             * getLengthProperty returns 0 if obj does not have the length property
0630:             * or its value is not convertible to a number.
0631:             */
0632:            static long getLengthProperty(Context cx, Scriptable obj) {
0633:                // These will both give numeric lengths within Uint32 range.
0634:                if (obj instanceof  NativeString) {
0635:                    return ((NativeString) obj).getLength();
0636:                } else if (obj instanceof  NativeArray) {
0637:                    return ((NativeArray) obj).getLength();
0638:                }
0639:                return ScriptRuntime.toUint32(ScriptRuntime.getObjectProp(obj,
0640:                        "length", cx));
0641:            }
0642:
0643:            private static Object setLengthProperty(Context cx,
0644:                    Scriptable target, long length) {
0645:                return ScriptRuntime.setObjectProp(target, "length",
0646:                        ScriptRuntime.wrapNumber(length), cx);
0647:            }
0648:
0649:            /* Utility functions to encapsulate index > Integer.MAX_VALUE
0650:             * handling.  Also avoids unnecessary object creation that would
0651:             * be necessary to use the general ScriptRuntime.get/setElem
0652:             * functions... though this is probably premature optimization.
0653:             */
0654:            private static void deleteElem(Scriptable target, long index) {
0655:                int i = (int) index;
0656:                if (i == index) {
0657:                    target.delete(i);
0658:                } else {
0659:                    target.delete(Long.toString(index));
0660:                }
0661:            }
0662:
0663:            private static Object getElem(Context cx, Scriptable target,
0664:                    long index) {
0665:                if (index > Integer.MAX_VALUE) {
0666:                    String id = Long.toString(index);
0667:                    return ScriptRuntime.getObjectProp(target, id, cx);
0668:                } else {
0669:                    return ScriptRuntime
0670:                            .getObjectIndex(target, (int) index, cx);
0671:                }
0672:            }
0673:
0674:            private static void setElem(Context cx, Scriptable target,
0675:                    long index, Object value) {
0676:                if (index > Integer.MAX_VALUE) {
0677:                    String id = Long.toString(index);
0678:                    ScriptRuntime.setObjectProp(target, id, value, cx);
0679:                } else {
0680:                    ScriptRuntime
0681:                            .setObjectIndex(target, (int) index, value, cx);
0682:                }
0683:            }
0684:
0685:            private static String toStringHelper(Context cx, Scriptable scope,
0686:                    Scriptable this Obj, boolean toSource, boolean toLocale) {
0687:                /* It's probably redundant to handle long lengths in this
0688:                 * function; StringBuffers are limited to 2^31 in java.
0689:                 */
0690:
0691:                long length = getLengthProperty(cx, this Obj);
0692:
0693:                StringBuffer result = new StringBuffer(256);
0694:
0695:                // whether to return '4,unquoted,5' or '[4, "quoted", 5]'
0696:                String separator;
0697:
0698:                if (toSource) {
0699:                    result.append('[');
0700:                    separator = ", ";
0701:                } else {
0702:                    separator = ",";
0703:                }
0704:
0705:                boolean haslast = false;
0706:                long i = 0;
0707:
0708:                boolean toplevel, iterating;
0709:                if (cx.iterating == null) {
0710:                    toplevel = true;
0711:                    iterating = false;
0712:                    cx.iterating = new ObjToIntMap(31);
0713:                } else {
0714:                    toplevel = false;
0715:                    iterating = cx.iterating.has(this Obj);
0716:                }
0717:
0718:                // Make sure cx.iterating is set to null when done
0719:                // so we don't leak memory
0720:                try {
0721:                    if (!iterating) {
0722:                        cx.iterating.put(this Obj, 0); // stop recursion.
0723:                        for (i = 0; i < length; i++) {
0724:                            if (i > 0)
0725:                                result.append(separator);
0726:                            Object elem = getElem(cx, this Obj, i);
0727:                            if (elem == null || elem == Undefined.instance) {
0728:                                haslast = false;
0729:                                continue;
0730:                            }
0731:                            haslast = true;
0732:
0733:                            if (toSource) {
0734:                                result.append(ScriptRuntime.uneval(cx, scope,
0735:                                        elem));
0736:
0737:                            } else if (elem instanceof  String) {
0738:                                String s = (String) elem;
0739:                                if (toSource) {
0740:                                    result.append('\"');
0741:                                    result
0742:                                            .append(ScriptRuntime
0743:                                                    .escapeString(s));
0744:                                    result.append('\"');
0745:                                } else {
0746:                                    result.append(s);
0747:                                }
0748:
0749:                            } else {
0750:                                if (toLocale) {
0751:                                    Callable fun;
0752:                                    Scriptable funThis;
0753:                                    fun = ScriptRuntime.getPropFunctionAndThis(
0754:                                            elem, "toLocaleString", cx);
0755:                                    funThis = ScriptRuntime
0756:                                            .lastStoredScriptable(cx);
0757:                                    elem = fun.call(cx, scope, funThis,
0758:                                            ScriptRuntime.emptyArgs);
0759:                                }
0760:                                result.append(ScriptRuntime.toString(elem));
0761:                            }
0762:                        }
0763:                    }
0764:                } finally {
0765:                    if (toplevel) {
0766:                        cx.iterating = null;
0767:                    }
0768:                }
0769:
0770:                if (toSource) {
0771:                    //for [,,].length behavior; we want toString to be symmetric.
0772:                    if (!haslast && i > 0)
0773:                        result.append(", ]");
0774:                    else
0775:                        result.append(']');
0776:                }
0777:                return result.toString();
0778:            }
0779:
0780:            /**
0781:             * See ECMA 15.4.4.3
0782:             */
0783:            private static String js_join(Context cx, Scriptable this Obj,
0784:                    Object[] args) {
0785:                long llength = getLengthProperty(cx, this Obj);
0786:                int length = (int) llength;
0787:                if (llength != length) {
0788:                    throw Context.reportRuntimeError1(
0789:                            "msg.arraylength.too.big", String.valueOf(llength));
0790:                }
0791:                // if no args, use "," as separator
0792:                String separator = (args.length < 1 || args[0] == Undefined.instance) ? ","
0793:                        : ScriptRuntime.toString(args[0]);
0794:                if (this Obj instanceof  NativeArray) {
0795:                    NativeArray na = (NativeArray) this Obj;
0796:                    if (na.denseOnly) {
0797:                        StringBuffer sb = new StringBuffer();
0798:                        for (int i = 0; i < length; i++) {
0799:                            if (i != 0) {
0800:                                sb.append(separator);
0801:                            }
0802:                            if (i < na.dense.length) {
0803:                                Object temp = na.dense[i];
0804:                                if (temp != null && temp != Undefined.instance
0805:                                        && temp != Scriptable.NOT_FOUND) {
0806:                                    sb.append(ScriptRuntime.toString(temp));
0807:                                }
0808:                            }
0809:                        }
0810:                        return sb.toString();
0811:                    }
0812:                }
0813:                if (length == 0) {
0814:                    return "";
0815:                }
0816:                String[] buf = new String[length];
0817:                int total_size = 0;
0818:                for (int i = 0; i != length; i++) {
0819:                    Object temp = getElem(cx, this Obj, i);
0820:                    if (temp != null && temp != Undefined.instance) {
0821:                        String str = ScriptRuntime.toString(temp);
0822:                        total_size += str.length();
0823:                        buf[i] = str;
0824:                    }
0825:                }
0826:                total_size += (length - 1) * separator.length();
0827:                StringBuffer sb = new StringBuffer(total_size);
0828:                for (int i = 0; i != length; i++) {
0829:                    if (i != 0) {
0830:                        sb.append(separator);
0831:                    }
0832:                    String str = buf[i];
0833:                    if (str != null) {
0834:                        // str == null for undefined or null
0835:                        sb.append(str);
0836:                    }
0837:                }
0838:                return sb.toString();
0839:            }
0840:
0841:            /**
0842:             * See ECMA 15.4.4.4
0843:             */
0844:            private static Scriptable js_reverse(Context cx,
0845:                    Scriptable this Obj, Object[] args) {
0846:                if (this Obj instanceof  NativeArray) {
0847:                    NativeArray na = (NativeArray) this Obj;
0848:                    if (na.denseOnly) {
0849:                        for (int i = 0, j = ((int) na.length) - 1; i < j; i++, j--) {
0850:                            Object temp = na.dense[i];
0851:                            na.dense[i] = na.dense[j];
0852:                            na.dense[j] = temp;
0853:                        }
0854:                        return this Obj;
0855:                    }
0856:                }
0857:                long len = getLengthProperty(cx, this Obj);
0858:
0859:                long half = len / 2;
0860:                for (long i = 0; i < half; i++) {
0861:                    long j = len - i - 1;
0862:                    Object temp1 = getElem(cx, this Obj, i);
0863:                    Object temp2 = getElem(cx, this Obj, j);
0864:                    setElem(cx, this Obj, i, temp2);
0865:                    setElem(cx, this Obj, j, temp1);
0866:                }
0867:                return this Obj;
0868:            }
0869:
0870:            /**
0871:             * See ECMA 15.4.4.5
0872:             */
0873:            private static Scriptable js_sort(Context cx, Scriptable scope,
0874:                    Scriptable this Obj, Object[] args) {
0875:                long length = getLengthProperty(cx, this Obj);
0876:
0877:                if (length <= 1) {
0878:                    return this Obj;
0879:                }
0880:
0881:                Object compare;
0882:                Object[] cmpBuf;
0883:
0884:                if (args.length > 0 && Undefined.instance != args[0]) {
0885:                    // sort with given compare function
0886:                    compare = args[0];
0887:                    cmpBuf = new Object[2]; // Buffer for cmp arguments
0888:                } else {
0889:                    // sort with default compare
0890:                    compare = null;
0891:                    cmpBuf = null;
0892:                }
0893:                if (this Obj instanceof  NativeArray) {
0894:                    NativeArray na = (NativeArray) this Obj;
0895:                    if (na.denseOnly) {
0896:                        int ilength = (int) length;
0897:                        heapsort(cx, scope, na.dense, ilength, compare, cmpBuf);
0898:                        return this Obj;
0899:                    }
0900:                }
0901:
0902:                // Should we use the extended sort function, or the faster one?
0903:                if (length >= Integer.MAX_VALUE) {
0904:                    heapsort_extended(cx, scope, this Obj, length, compare,
0905:                            cmpBuf);
0906:                } else {
0907:                    int ilength = (int) length;
0908:                    // copy the JS array into a working array, so it can be
0909:                    // sorted cheaply.
0910:                    Object[] working = new Object[ilength];
0911:                    for (int i = 0; i != ilength; ++i) {
0912:                        working[i] = getElem(cx, this Obj, i);
0913:                    }
0914:
0915:                    heapsort(cx, scope, working, ilength, compare, cmpBuf);
0916:
0917:                    // copy the working array back into thisObj
0918:                    for (int i = 0; i != ilength; ++i) {
0919:                        setElem(cx, this Obj, i, working[i]);
0920:                    }
0921:                }
0922:                return this Obj;
0923:            }
0924:
0925:            // Return true only if x > y
0926:            private static boolean isBigger(Context cx, Scriptable scope,
0927:                    Object x, Object y, Object cmp, Object[] cmpBuf) {
0928:                if (cmp == null) {
0929:                    if (cmpBuf != null)
0930:                        Kit.codeBug();
0931:                } else {
0932:                    if (cmpBuf == null || cmpBuf.length != 2)
0933:                        Kit.codeBug();
0934:                }
0935:
0936:                Object undef = Undefined.instance;
0937:                Object notfound = Scriptable.NOT_FOUND;
0938:
0939:                // sort undefined to end
0940:                if (y == undef || y == notfound) {
0941:                    return false; // x can not be bigger then undef
0942:                } else if (x == undef || x == notfound) {
0943:                    return true; // y != undef here, so x > y
0944:                }
0945:
0946:                if (cmp == null) {
0947:                    // if no cmp function supplied, sort lexicographically
0948:                    String a = ScriptRuntime.toString(x);
0949:                    String b = ScriptRuntime.toString(y);
0950:                    return a.compareTo(b) > 0;
0951:                } else {
0952:                    // assemble args and call supplied JS cmp function
0953:                    cmpBuf[0] = x;
0954:                    cmpBuf[1] = y;
0955:                    Callable fun = ScriptRuntime.getValueFunctionAndThis(cmp,
0956:                            cx);
0957:                    Scriptable funThis = ScriptRuntime.lastStoredScriptable(cx);
0958:
0959:                    Object ret = fun.call(cx, scope, funThis, cmpBuf);
0960:                    double d = ScriptRuntime.toNumber(ret);
0961:
0962:                    // XXX what to do when cmp function returns NaN?  ECMA states
0963:                    // that it's then not a 'consistent comparison function'... but
0964:                    // then what do we do?  Back out and start over with the generic
0965:                    // cmp function when we see a NaN?  Throw an error?
0966:
0967:                    // for now, just ignore it:
0968:
0969:                    return d > 0;
0970:                }
0971:            }
0972:
0973:            /** Heapsort implementation.
0974:             * See "Introduction to Algorithms" by Cormen, Leiserson, Rivest for details.
0975:             * Adjusted for zero based indexes.
0976:             */
0977:            private static void heapsort(Context cx, Scriptable scope,
0978:                    Object[] array, int length, Object cmp, Object[] cmpBuf) {
0979:                if (length <= 1)
0980:                    Kit.codeBug();
0981:
0982:                // Build heap
0983:                for (int i = length / 2; i != 0;) {
0984:                    --i;
0985:                    Object pivot = array[i];
0986:                    heapify(cx, scope, pivot, array, i, length, cmp, cmpBuf);
0987:                }
0988:
0989:                // Sort heap
0990:                for (int i = length; i != 1;) {
0991:                    --i;
0992:                    Object pivot = array[i];
0993:                    array[i] = array[0];
0994:                    heapify(cx, scope, pivot, array, 0, i, cmp, cmpBuf);
0995:                }
0996:            }
0997:
0998:            /** pivot and child heaps of i should be made into heap starting at i,
0999:             * original array[i] is never used to have less array access during sorting.
1000:             */
1001:            private static void heapify(Context cx, Scriptable scope,
1002:                    Object pivot, Object[] array, int i, int end, Object cmp,
1003:                    Object[] cmpBuf) {
1004:                for (;;) {
1005:                    int child = i * 2 + 1;
1006:                    if (child >= end) {
1007:                        break;
1008:                    }
1009:                    Object childVal = array[child];
1010:                    if (child + 1 < end) {
1011:                        Object nextVal = array[child + 1];
1012:                        if (isBigger(cx, scope, nextVal, childVal, cmp, cmpBuf)) {
1013:                            ++child;
1014:                            childVal = nextVal;
1015:                        }
1016:                    }
1017:                    if (!isBigger(cx, scope, childVal, pivot, cmp, cmpBuf)) {
1018:                        break;
1019:                    }
1020:                    array[i] = childVal;
1021:                    i = child;
1022:                }
1023:                array[i] = pivot;
1024:            }
1025:
1026:            /** Version of heapsort that call getElem/setElem on target to query/assign
1027:             * array elements instead of Java array access
1028:             */
1029:            private static void heapsort_extended(Context cx, Scriptable scope,
1030:                    Scriptable target, long length, Object cmp, Object[] cmpBuf) {
1031:                if (length <= 1)
1032:                    Kit.codeBug();
1033:
1034:                // Build heap
1035:                for (long i = length / 2; i != 0;) {
1036:                    --i;
1037:                    Object pivot = getElem(cx, target, i);
1038:                    heapify_extended(cx, scope, pivot, target, i, length, cmp,
1039:                            cmpBuf);
1040:                }
1041:
1042:                // Sort heap
1043:                for (long i = length; i != 1;) {
1044:                    --i;
1045:                    Object pivot = getElem(cx, target, i);
1046:                    setElem(cx, target, i, getElem(cx, target, 0));
1047:                    heapify_extended(cx, scope, pivot, target, 0, i, cmp,
1048:                            cmpBuf);
1049:                }
1050:            }
1051:
1052:            private static void heapify_extended(Context cx, Scriptable scope,
1053:                    Object pivot, Scriptable target, long i, long end,
1054:                    Object cmp, Object[] cmpBuf) {
1055:                for (;;) {
1056:                    long child = i * 2 + 1;
1057:                    if (child >= end) {
1058:                        break;
1059:                    }
1060:                    Object childVal = getElem(cx, target, child);
1061:                    if (child + 1 < end) {
1062:                        Object nextVal = getElem(cx, target, child + 1);
1063:                        if (isBigger(cx, scope, nextVal, childVal, cmp, cmpBuf)) {
1064:                            ++child;
1065:                            childVal = nextVal;
1066:                        }
1067:                    }
1068:                    if (!isBigger(cx, scope, childVal, pivot, cmp, cmpBuf)) {
1069:                        break;
1070:                    }
1071:                    setElem(cx, target, i, childVal);
1072:                    i = child;
1073:                }
1074:                setElem(cx, target, i, pivot);
1075:            }
1076:
1077:            /**
1078:             * Non-ECMA methods.
1079:             */
1080:
1081:            private static Object js_push(Context cx, Scriptable this Obj,
1082:                    Object[] args) {
1083:                if (this Obj instanceof  NativeArray) {
1084:                    NativeArray na = (NativeArray) this Obj;
1085:                    if (na.denseOnly
1086:                            && na.ensureCapacity((int) na.length + args.length)) {
1087:                        for (int i = 0; i < args.length; i++) {
1088:                            na.dense[(int) na.length++] = args[i];
1089:                        }
1090:                        return ScriptRuntime.wrapNumber(na.length);
1091:                    }
1092:                }
1093:                long length = getLengthProperty(cx, this Obj);
1094:                for (int i = 0; i < args.length; i++) {
1095:                    setElem(cx, this Obj, length + i, args[i]);
1096:                }
1097:
1098:                length += args.length;
1099:                Object lengthObj = setLengthProperty(cx, this Obj, length);
1100:
1101:                /*
1102:                 * If JS1.2, follow Perl4 by returning the last thing pushed.
1103:                 * Otherwise, return the new array length.
1104:                 */
1105:                if (cx.getLanguageVersion() == Context.VERSION_1_2)
1106:                    // if JS1.2 && no arguments, return undefined.
1107:                    return args.length == 0 ? Undefined.instance
1108:                            : args[args.length - 1];
1109:
1110:                else
1111:                    return lengthObj;
1112:            }
1113:
1114:            private static Object js_pop(Context cx, Scriptable this Obj,
1115:                    Object[] args) {
1116:                Object result;
1117:                if (this Obj instanceof  NativeArray) {
1118:                    NativeArray na = (NativeArray) this Obj;
1119:                    if (na.denseOnly && na.length > 0) {
1120:                        na.length--;
1121:                        result = na.dense[(int) na.length];
1122:                        na.dense[(int) na.length] = NOT_FOUND;
1123:                        return result;
1124:                    }
1125:                }
1126:                long length = getLengthProperty(cx, this Obj);
1127:                if (length > 0) {
1128:                    length--;
1129:
1130:                    // Get the to-be-deleted property's value.
1131:                    result = getElem(cx, this Obj, length);
1132:
1133:                    // We don't need to delete the last property, because
1134:                    // setLength does that for us.
1135:                } else {
1136:                    result = Undefined.instance;
1137:                }
1138:                // necessary to match js even when length < 0; js pop will give a
1139:                // length property to any target it is called on.
1140:                setLengthProperty(cx, this Obj, length);
1141:
1142:                return result;
1143:            }
1144:
1145:            private static Object js_shift(Context cx, Scriptable this Obj,
1146:                    Object[] args) {
1147:                if (this Obj instanceof  NativeArray) {
1148:                    NativeArray na = (NativeArray) this Obj;
1149:                    if (na.denseOnly && na.length > 0) {
1150:                        na.length--;
1151:                        Object result = na.dense[0];
1152:                        System.arraycopy(na.dense, 1, na.dense, 0,
1153:                                (int) na.length);
1154:                        na.dense[(int) na.length] = NOT_FOUND;
1155:                        return result;
1156:                    }
1157:                }
1158:                Object result;
1159:                long length = getLengthProperty(cx, this Obj);
1160:                if (length > 0) {
1161:                    long i = 0;
1162:                    length--;
1163:
1164:                    // Get the to-be-deleted property's value.
1165:                    result = getElem(cx, this Obj, i);
1166:
1167:                    /*
1168:                     * Slide down the array above the first element.  Leave i
1169:                     * set to point to the last element.
1170:                     */
1171:                    if (length > 0) {
1172:                        for (i = 1; i <= length; i++) {
1173:                            Object temp = getElem(cx, this Obj, i);
1174:                            setElem(cx, this Obj, i - 1, temp);
1175:                        }
1176:                    }
1177:                    // We don't need to delete the last property, because
1178:                    // setLength does that for us.
1179:                } else {
1180:                    result = Undefined.instance;
1181:                }
1182:                setLengthProperty(cx, this Obj, length);
1183:                return result;
1184:            }
1185:
1186:            private static Object js_unshift(Context cx, Scriptable this Obj,
1187:                    Object[] args) {
1188:                if (this Obj instanceof  NativeArray) {
1189:                    NativeArray na = (NativeArray) this Obj;
1190:                    if (na.denseOnly
1191:                            && na.ensureCapacity((int) na.length + args.length)) {
1192:                        System.arraycopy(na.dense, 0, na.dense, args.length,
1193:                                (int) na.length);
1194:                        for (int i = 0; i < args.length; i++) {
1195:                            na.dense[i] = args[i];
1196:                        }
1197:                        na.length += args.length;
1198:                        return ScriptRuntime.wrapNumber(na.length);
1199:                    }
1200:                }
1201:                long length = getLengthProperty(cx, this Obj);
1202:                int argc = args.length;
1203:
1204:                if (args.length > 0) {
1205:                    /*  Slide up the array to make room for args at the bottom */
1206:                    if (length > 0) {
1207:                        for (long last = length - 1; last >= 0; last--) {
1208:                            Object temp = getElem(cx, this Obj, last);
1209:                            setElem(cx, this Obj, last + argc, temp);
1210:                        }
1211:                    }
1212:
1213:                    /* Copy from argv to the bottom of the array. */
1214:                    for (int i = 0; i < args.length; i++) {
1215:                        setElem(cx, this Obj, i, args[i]);
1216:                    }
1217:
1218:                    /* Follow Perl by returning the new array length. */
1219:                    length += args.length;
1220:                    return setLengthProperty(cx, this Obj, length);
1221:                }
1222:                return ScriptRuntime.wrapNumber(length);
1223:            }
1224:
1225:            private static Object js_splice(Context cx, Scriptable scope,
1226:                    Scriptable this Obj, Object[] args) {
1227:                NativeArray na = null;
1228:                boolean denseMode = false;
1229:                if (this Obj instanceof  NativeArray) {
1230:                    na = (NativeArray) this Obj;
1231:                    denseMode = na.denseOnly;
1232:                }
1233:
1234:                /* create an empty Array to return. */
1235:                scope = getTopLevelScope(scope);
1236:                int argc = args.length;
1237:                if (argc == 0)
1238:                    return ScriptRuntime.newObject(cx, scope, "Array", null);
1239:                long length = getLengthProperty(cx, this Obj);
1240:
1241:                /* Convert the first argument into a starting index. */
1242:                long begin = toSliceIndex(ScriptRuntime.toInteger(args[0]),
1243:                        length);
1244:                argc--;
1245:
1246:                /* Convert the second argument into count */
1247:                long count;
1248:                if (args.length == 1) {
1249:                    count = length - begin;
1250:                } else {
1251:                    double dcount = ScriptRuntime.toInteger(args[1]);
1252:                    if (dcount < 0) {
1253:                        count = 0;
1254:                    } else if (dcount > (length - begin)) {
1255:                        count = length - begin;
1256:                    } else {
1257:                        count = (long) dcount;
1258:                    }
1259:                    argc--;
1260:                }
1261:
1262:                long end = begin + count;
1263:
1264:                /* If there are elements to remove, put them into the return value. */
1265:                Object result;
1266:                if (count != 0) {
1267:                    if (count == 1
1268:                            && (cx.getLanguageVersion() == Context.VERSION_1_2)) {
1269:                        /*
1270:                         * JS lacks "list context", whereby in Perl one turns the
1271:                         * single scalar that's spliced out into an array just by
1272:                         * assigning it to @single instead of $single, or by using it
1273:                         * as Perl push's first argument, for instance.
1274:                         *
1275:                         * JS1.2 emulated Perl too closely and returned a non-Array for
1276:                         * the single-splice-out case, requiring callers to test and
1277:                         * wrap in [] if necessary.  So JS1.3, default, and other
1278:                         * versions all return an array of length 1 for uniformity.
1279:                         */
1280:                        result = getElem(cx, this Obj, begin);
1281:                    } else {
1282:                        if (denseMode) {
1283:                            int intLen = (int) (end - begin);
1284:                            Object[] copy = new Object[intLen];
1285:                            System.arraycopy(na.dense, (int) begin, copy, 0,
1286:                                    intLen);
1287:                            result = cx.newArray(scope, copy);
1288:                        } else {
1289:                            Scriptable resultArray = ScriptRuntime.newObject(
1290:                                    cx, scope, "Array", null);
1291:                            for (long last = begin; last != end; last++) {
1292:                                Object temp = getElem(cx, this Obj, last);
1293:                                setElem(cx, resultArray, last - begin, temp);
1294:                            }
1295:                            result = resultArray;
1296:                        }
1297:                    }
1298:                } else { // (count == 0)
1299:                    if (cx.getLanguageVersion() == Context.VERSION_1_2) {
1300:                        /* Emulate C JS1.2; if no elements are removed, return undefined. */
1301:                        result = Undefined.instance;
1302:                    } else {
1303:                        result = ScriptRuntime.newObject(cx, scope, "Array",
1304:                                null);
1305:                    }
1306:                }
1307:
1308:                /* Find the direction (up or down) to copy and make way for argv. */
1309:                long delta = argc - count;
1310:                if (denseMode && length + delta < Integer.MAX_VALUE
1311:                        && na.ensureCapacity((int) (length + delta))) {
1312:                    System.arraycopy(na.dense, (int) end, na.dense,
1313:                            (int) (begin + argc), (int) (length - end));
1314:                    if (argc > 0) {
1315:                        System.arraycopy(args, 2, na.dense, (int) begin, argc);
1316:                    }
1317:                    if (delta < 0) {
1318:                        Arrays.fill(na.dense, (int) (length + delta),
1319:                                (int) length, NOT_FOUND);
1320:                    }
1321:                    na.length = length + delta;
1322:                    return result;
1323:                }
1324:
1325:                if (delta > 0) {
1326:                    for (long last = length - 1; last >= end; last--) {
1327:                        Object temp = getElem(cx, this Obj, last);
1328:                        setElem(cx, this Obj, last + delta, temp);
1329:                    }
1330:                } else if (delta < 0) {
1331:                    for (long last = end; last < length; last++) {
1332:                        Object temp = getElem(cx, this Obj, last);
1333:                        setElem(cx, this Obj, last + delta, temp);
1334:                    }
1335:                }
1336:
1337:                /* Copy from argv into the hole to complete the splice. */
1338:                int argoffset = args.length - argc;
1339:                for (int i = 0; i < argc; i++) {
1340:                    setElem(cx, this Obj, begin + i, args[i + argoffset]);
1341:                }
1342:
1343:                /* Update length in case we deleted elements from the end. */
1344:                setLengthProperty(cx, this Obj, length + delta);
1345:                return result;
1346:            }
1347:
1348:            /*
1349:             * See Ecma 262v3 15.4.4.4
1350:             */
1351:            private static Scriptable js_concat(Context cx, Scriptable scope,
1352:                    Scriptable this Obj, Object[] args) {
1353:                // create an empty Array to return.
1354:                scope = getTopLevelScope(scope);
1355:                Function ctor = ScriptRuntime.getExistingCtor(cx, scope,
1356:                        "Array");
1357:                Scriptable result = ctor.construct(cx, scope,
1358:                        ScriptRuntime.emptyArgs);
1359:                if (this Obj instanceof  NativeArray
1360:                        && result instanceof  NativeArray) {
1361:                    NativeArray denseThis = (NativeArray) this Obj;
1362:                    NativeArray denseResult = (NativeArray) result;
1363:                    if (denseThis.denseOnly && denseResult.denseOnly) {
1364:                        // First calculate length of resulting array
1365:                        boolean canUseDense = true;
1366:                        int length = (int) denseThis.length;
1367:                        for (int i = 0; i < args.length && canUseDense; i++) {
1368:                            if (ScriptRuntime.instanceOf(args[i], ctor, cx)) {
1369:                                // only try to use dense approach for Array-like
1370:                                // objects that are actually NativeArrays
1371:                                canUseDense = args[i] instanceof  NativeArray;
1372:                                length += ((NativeArray) args[i]).length;
1373:                            } else {
1374:                                length++;
1375:                            }
1376:                        }
1377:                        if (canUseDense && denseResult.ensureCapacity(length)) {
1378:                            System.arraycopy(denseThis.dense, 0,
1379:                                    denseResult.dense, 0,
1380:                                    (int) denseThis.length);
1381:                            int cursor = (int) denseThis.length;
1382:                            for (int i = 0; i < args.length && canUseDense; i++) {
1383:                                if (args[i] instanceof  NativeArray) {
1384:                                    NativeArray arg = (NativeArray) args[i];
1385:                                    System.arraycopy(arg.dense, 0,
1386:                                            denseResult.dense, cursor,
1387:                                            (int) arg.length);
1388:                                    cursor += (int) arg.length;
1389:                                } else {
1390:                                    denseResult.dense[cursor++] = args[i];
1391:                                }
1392:                            }
1393:                            denseResult.length = length;
1394:                            return result;
1395:                        }
1396:                    }
1397:                }
1398:
1399:                long length;
1400:                long slot = 0;
1401:
1402:                /* Put the target in the result array; only add it as an array
1403:                 * if it looks like one.
1404:                 */
1405:                if (ScriptRuntime.instanceOf(this Obj, ctor, cx)) {
1406:                    length = getLengthProperty(cx, this Obj);
1407:
1408:                    // Copy from the target object into the result
1409:                    for (slot = 0; slot < length; slot++) {
1410:                        Object temp = getElem(cx, this Obj, slot);
1411:                        setElem(cx, result, slot, temp);
1412:                    }
1413:                } else {
1414:                    setElem(cx, result, slot++, this Obj);
1415:                }
1416:
1417:                /* Copy from the arguments into the result.  If any argument
1418:                 * has a numeric length property, treat it as an array and add
1419:                 * elements separately; otherwise, just copy the argument.
1420:                 */
1421:                for (int i = 0; i < args.length; i++) {
1422:                    if (ScriptRuntime.instanceOf(args[i], ctor, cx)) {
1423:                        // ScriptRuntime.instanceOf => instanceof Scriptable
1424:                        Scriptable arg = (Scriptable) args[i];
1425:                        length = getLengthProperty(cx, arg);
1426:                        for (long j = 0; j < length; j++, slot++) {
1427:                            Object temp = getElem(cx, arg, j);
1428:                            setElem(cx, result, slot, temp);
1429:                        }
1430:                    } else {
1431:                        setElem(cx, result, slot++, args[i]);
1432:                    }
1433:                }
1434:                return result;
1435:            }
1436:
1437:            private Scriptable js_slice(Context cx, Scriptable this Obj,
1438:                    Object[] args) {
1439:                Scriptable scope = getTopLevelScope(this );
1440:                Scriptable result = ScriptRuntime.newObject(cx, scope, "Array",
1441:                        null);
1442:                long length = getLengthProperty(cx, this Obj);
1443:
1444:                long begin, end;
1445:                if (args.length == 0) {
1446:                    begin = 0;
1447:                    end = length;
1448:                } else {
1449:                    begin = toSliceIndex(ScriptRuntime.toInteger(args[0]),
1450:                            length);
1451:                    if (args.length == 1) {
1452:                        end = length;
1453:                    } else {
1454:                        end = toSliceIndex(ScriptRuntime.toInteger(args[1]),
1455:                                length);
1456:                    }
1457:                }
1458:
1459:                for (long slot = begin; slot < end; slot++) {
1460:                    Object temp = getElem(cx, this Obj, slot);
1461:                    setElem(cx, result, slot - begin, temp);
1462:                }
1463:
1464:                return result;
1465:            }
1466:
1467:            private static long toSliceIndex(double value, long length) {
1468:                long result;
1469:                if (value < 0.0) {
1470:                    if (value + length < 0.0) {
1471:                        result = 0;
1472:                    } else {
1473:                        result = (long) (value + length);
1474:                    }
1475:                } else if (value > length) {
1476:                    result = length;
1477:                } else {
1478:                    result = (long) value;
1479:                }
1480:                return result;
1481:            }
1482:
1483:            /**
1484:             * Implements the methods "indexOf" and "lastIndexOf".
1485:             */
1486:            private Object indexOfHelper(Context cx, Scriptable this Obj,
1487:                    Object[] args, boolean isLast) {
1488:                Object compareTo = args.length > 0 ? args[0]
1489:                        : Undefined.instance;
1490:                long length = getLengthProperty(cx, this Obj);
1491:                long start;
1492:                if (isLast) {
1493:                    // lastIndexOf
1494:                    /*
1495:                     * From http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:lastIndexOf
1496:                     * The index at which to start searching backwards. Defaults to the
1497:                     * array's length, i.e. the whole array will be searched. If the
1498:                     * index is greater than or equal to the length of the array, the
1499:                     * whole array will be searched. If negative, it is taken as the
1500:                     * offset from the end of the array. Note that even when the index
1501:                     * is negative, the array is still searched from back to front. If
1502:                     * the calculated index is less than 0, -1 is returned, i.e. the
1503:                     * array will not be searched.
1504:                     */
1505:                    if (args.length < 2) {
1506:                        // default
1507:                        start = length - 1;
1508:                    } else {
1509:                        start = ScriptRuntime.toInt32(ScriptRuntime
1510:                                .toNumber(args[1]));
1511:                        if (start >= length)
1512:                            start = length - 1;
1513:                        else if (start < 0)
1514:                            start += length;
1515:                        // Note that start may be negative, but that's okay
1516:                        // as the result of -1 will fall out from the code below
1517:                    }
1518:                } else {
1519:                    // indexOf
1520:                    /*
1521:                     * From http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:indexOf
1522:                     * The index at which to begin the search. Defaults to 0, i.e. the
1523:                     * whole array will be searched. If the index is greater than or
1524:                     * equal to the length of the array, -1 is returned, i.e. the array
1525:                     * will not be searched. If negative, it is taken as the offset from
1526:                     * the end of the array. Note that even when the index is negative,
1527:                     * the array is still searched from front to back. If the calculated
1528:                     * index is less than 0, the whole array will be searched.
1529:                     */
1530:                    if (args.length < 2) {
1531:                        // default
1532:                        start = 0;
1533:                    } else {
1534:                        start = ScriptRuntime.toInt32(ScriptRuntime
1535:                                .toNumber(args[1]));
1536:                        if (start < 0) {
1537:                            start += length;
1538:                            if (start < 0)
1539:                                start = 0;
1540:                        }
1541:                        // Note that start may be > length-1, but that's okay
1542:                        // as the result of -1 will fall out from the code below
1543:                    }
1544:                }
1545:                if (this Obj instanceof  NativeArray) {
1546:                    NativeArray na = (NativeArray) this Obj;
1547:                    if (na.denseOnly) {
1548:                        if (isLast) {
1549:                            for (int i = (int) start; i >= 0; i--) {
1550:                                if (na.dense[i] != Scriptable.NOT_FOUND
1551:                                        && ScriptRuntime.shallowEq(na.dense[i],
1552:                                                compareTo)) {
1553:                                    return new Long(i);
1554:                                }
1555:                            }
1556:                        } else {
1557:                            for (int i = (int) start; i < length; i++) {
1558:                                if (na.dense[i] != Scriptable.NOT_FOUND
1559:                                        && ScriptRuntime.shallowEq(na.dense[i],
1560:                                                compareTo)) {
1561:                                    return new Long(i);
1562:                                }
1563:                            }
1564:                        }
1565:                        return NEGATIVE_ONE;
1566:                    }
1567:                }
1568:                if (isLast) {
1569:                    for (long i = start; i >= 0; i--) {
1570:                        if (ScriptRuntime.shallowEq(getElem(cx, this Obj, i),
1571:                                compareTo)) {
1572:                            return new Long(i);
1573:                        }
1574:                    }
1575:                } else {
1576:                    for (long i = start; i < length; i++) {
1577:                        if (ScriptRuntime.shallowEq(getElem(cx, this Obj, i),
1578:                                compareTo)) {
1579:                            return new Long(i);
1580:                        }
1581:                    }
1582:                }
1583:                return NEGATIVE_ONE;
1584:            }
1585:
1586:            /**
1587:             * Implements the methods "every", "filter", "forEach", "map", and "some".
1588:             */
1589:            private Object iterativeMethod(Context cx, int id,
1590:                    Scriptable scope, Scriptable this Obj, Object[] args) {
1591:                Object callbackArg = args.length > 0 ? args[0]
1592:                        : Undefined.instance;
1593:                if (callbackArg == null || !(callbackArg instanceof  Function)) {
1594:                    throw ScriptRuntime.notFunctionError(ScriptRuntime
1595:                            .toString(callbackArg));
1596:                }
1597:                Function f = (Function) callbackArg;
1598:                Scriptable parent = ScriptableObject.getTopLevelScope(f);
1599:                Scriptable this Arg;
1600:                if (args.length < 2 || args[1] == null
1601:                        || args[1] == Undefined.instance) {
1602:                    this Arg = parent;
1603:                } else {
1604:                    this Arg = ScriptRuntime.toObject(cx, scope, args[1]);
1605:                }
1606:                long length = getLengthProperty(cx, this Obj);
1607:                Scriptable array = ScriptRuntime.newObject(cx, scope, "Array",
1608:                        null);
1609:                long j = 0;
1610:                for (long i = 0; i < length; i++) {
1611:                    Object[] innerArgs = new Object[3];
1612:                    Object elem = (i > Integer.MAX_VALUE) ? ScriptableObject
1613:                            .getProperty(this Obj, Long.toString(i))
1614:                            : ScriptableObject.getProperty(this Obj, (int) i);
1615:                    if (elem == Scriptable.NOT_FOUND) {
1616:                        continue;
1617:                    }
1618:                    innerArgs[0] = elem;
1619:                    innerArgs[1] = new Long(i);
1620:                    innerArgs[2] = this Obj;
1621:                    Object result = f.call(cx, parent, this Arg, innerArgs);
1622:                    switch (id) {
1623:                    case Id_every:
1624:                        if (!ScriptRuntime.toBoolean(result))
1625:                            return Boolean.FALSE;
1626:                        break;
1627:                    case Id_filter:
1628:                        if (ScriptRuntime.toBoolean(result))
1629:                            setElem(cx, array, j++, innerArgs[0]);
1630:                        break;
1631:                    case Id_forEach:
1632:                        break;
1633:                    case Id_map:
1634:                        setElem(cx, array, i, result);
1635:                        break;
1636:                    case Id_some:
1637:                        if (ScriptRuntime.toBoolean(result))
1638:                            return Boolean.TRUE;
1639:                        break;
1640:                    }
1641:                }
1642:                switch (id) {
1643:                case Id_every:
1644:                    return Boolean.TRUE;
1645:                case Id_filter:
1646:                case Id_map:
1647:                    return array;
1648:                case Id_some:
1649:                    return Boolean.FALSE;
1650:                case Id_forEach:
1651:                default:
1652:                    return Undefined.instance;
1653:                }
1654:            }
1655:
1656:            // #string_id_map#
1657:
1658:            protected int findPrototypeId(String s) {
1659:                int id;
1660:                // #generated# Last update: 2005-09-26 15:47:42 EDT
1661:                L0: {
1662:                    id = 0;
1663:                    String X = null;
1664:                    int c;
1665:                    L: switch (s.length()) {
1666:                    case 3:
1667:                        c = s.charAt(0);
1668:                        if (c == 'm') {
1669:                            if (s.charAt(2) == 'p' && s.charAt(1) == 'a') {
1670:                                id = Id_map;
1671:                                break L0;
1672:                            }
1673:                        } else if (c == 'p') {
1674:                            if (s.charAt(2) == 'p' && s.charAt(1) == 'o') {
1675:                                id = Id_pop;
1676:                                break L0;
1677:                            }
1678:                        }
1679:                        break L;
1680:                    case 4:
1681:                        switch (s.charAt(2)) {
1682:                        case 'i':
1683:                            X = "join";
1684:                            id = Id_join;
1685:                            break L;
1686:                        case 'm':
1687:                            X = "some";
1688:                            id = Id_some;
1689:                            break L;
1690:                        case 'r':
1691:                            X = "sort";
1692:                            id = Id_sort;
1693:                            break L;
1694:                        case 's':
1695:                            X = "push";
1696:                            id = Id_push;
1697:                            break L;
1698:                        }
1699:                        break L;
1700:                    case 5:
1701:                        c = s.charAt(1);
1702:                        if (c == 'h') {
1703:                            X = "shift";
1704:                            id = Id_shift;
1705:                        } else if (c == 'l') {
1706:                            X = "slice";
1707:                            id = Id_slice;
1708:                        } else if (c == 'v') {
1709:                            X = "every";
1710:                            id = Id_every;
1711:                        }
1712:                        break L;
1713:                    case 6:
1714:                        c = s.charAt(0);
1715:                        if (c == 'c') {
1716:                            X = "concat";
1717:                            id = Id_concat;
1718:                        } else if (c == 'f') {
1719:                            X = "filter";
1720:                            id = Id_filter;
1721:                        } else if (c == 's') {
1722:                            X = "splice";
1723:                            id = Id_splice;
1724:                        }
1725:                        break L;
1726:                    case 7:
1727:                        switch (s.charAt(0)) {
1728:                        case 'f':
1729:                            X = "forEach";
1730:                            id = Id_forEach;
1731:                            break L;
1732:                        case 'i':
1733:                            X = "indexOf";
1734:                            id = Id_indexOf;
1735:                            break L;
1736:                        case 'r':
1737:                            X = "reverse";
1738:                            id = Id_reverse;
1739:                            break L;
1740:                        case 'u':
1741:                            X = "unshift";
1742:                            id = Id_unshift;
1743:                            break L;
1744:                        }
1745:                        break L;
1746:                    case 8:
1747:                        c = s.charAt(3);
1748:                        if (c == 'o') {
1749:                            X = "toSource";
1750:                            id = Id_toSource;
1751:                        } else if (c == 't') {
1752:                            X = "toString";
1753:                            id = Id_toString;
1754:                        }
1755:                        break L;
1756:                    case 11:
1757:                        c = s.charAt(0);
1758:                        if (c == 'c') {
1759:                            X = "constructor";
1760:                            id = Id_constructor;
1761:                        } else if (c == 'l') {
1762:                            X = "lastIndexOf";
1763:                            id = Id_lastIndexOf;
1764:                        }
1765:                        break L;
1766:                    case 14:
1767:                        X = "toLocaleString";
1768:                        id = Id_toLocaleString;
1769:                        break L;
1770:                    }
1771:                    if (X != null && X != s && !X.equals(s))
1772:                        id = 0;
1773:                }
1774:                // #/generated#
1775:                return id;
1776:            }
1777:
1778:            private static final int Id_constructor = 1, Id_toString = 2,
1779:                    Id_toLocaleString = 3, Id_toSource = 4, Id_join = 5,
1780:                    Id_reverse = 6, Id_sort = 7, Id_push = 8, Id_pop = 9,
1781:                    Id_shift = 10, Id_unshift = 11, Id_splice = 12,
1782:                    Id_concat = 13, Id_slice = 14, Id_indexOf = 15,
1783:                    Id_lastIndexOf = 16, Id_every = 17, Id_filter = 18,
1784:                    Id_forEach = 19, Id_map = 20, Id_some = 21,
1785:
1786:                    MAX_PROTOTYPE_ID = 21;
1787:
1788:            // #/string_id_map#
1789:
1790:            private static final int ConstructorId_join = -Id_join,
1791:                    ConstructorId_reverse = -Id_reverse,
1792:                    ConstructorId_sort = -Id_sort,
1793:                    ConstructorId_push = -Id_push, ConstructorId_pop = -Id_pop,
1794:                    ConstructorId_shift = -Id_shift,
1795:                    ConstructorId_unshift = -Id_unshift,
1796:                    ConstructorId_splice = -Id_splice,
1797:                    ConstructorId_concat = -Id_concat,
1798:                    ConstructorId_slice = -Id_slice,
1799:                    ConstructorId_indexOf = -Id_indexOf,
1800:                    ConstructorId_lastIndexOf = -Id_lastIndexOf,
1801:                    ConstructorId_every = -Id_every,
1802:                    ConstructorId_filter = -Id_filter,
1803:                    ConstructorId_forEach = -Id_forEach,
1804:                    ConstructorId_map = -Id_map, ConstructorId_some = -Id_some;
1805:
1806:            /**
1807:             * Internal representation of the JavaScript array's length property.
1808:             */
1809:            private long length;
1810:
1811:            /**
1812:             * Fast storage for dense arrays. Sparse arrays will use the superclass's
1813:             * hashtable storage scheme.
1814:             */
1815:            private Object[] dense;
1816:
1817:            /**
1818:             * True if all numeric properties are stored in <code>dense</code>.
1819:             */
1820:            private boolean denseOnly;
1821:
1822:            /**
1823:             * The maximum size of <code>dense</code> that will be allocated initially.
1824:             */
1825:            private static int maximumInitialCapacity = 10000;
1826:
1827:            /**
1828:             * The default capacity for <code>dense</code>.
1829:             */
1830:            private static final int DEFAULT_INITIAL_CAPACITY = 10;
1831:
1832:            /**
1833:             * The factor to grow <code>dense</code> by.
1834:             */
1835:            private static final double GROW_FACTOR = 1.5;
1836:            private static final int MAX_PRE_GROW_SIZE = (int) (Integer.MAX_VALUE / GROW_FACTOR);
1837:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.