Source Code Cross Referenced for ScriptRuntime.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-2000
0022:         * the Initial Developer. All Rights Reserved.
0023:         *
0024:         * Contributor(s):
0025:         *   Patrick Beard
0026:         *   Norris Boyd
0027:         *   Igor Bukanov
0028:         *   Ethan Hugg
0029:         *   Bob Jervis
0030:         *   Roger Lawrence
0031:         *   Terry Lucas
0032:         *   Frank Mitchell
0033:         *   Milen Nankov
0034:         *   Hannes Wallnoefer
0035:         *   Andrew Wason
0036:         *
0037:         * Alternatively, the contents of this file may be used under the terms of
0038:         * the GNU General Public License Version 2 or later (the "GPL"), in which
0039:         * case the provisions of the GPL are applicable instead of those above. If
0040:         * you wish to allow use of your version of this file only under the terms of
0041:         * the GPL and not to allow others to use your version of this file under the
0042:         * MPL, indicate your decision by deleting the provisions above and replacing
0043:         * them with the notice and other provisions required by the GPL. If you do
0044:         * not delete the provisions above, a recipient may use your version of this
0045:         * file under either the MPL or the GPL.
0046:         *
0047:         * ***** END LICENSE BLOCK ***** */
0048:
0049:        package org.mozilla.javascript;
0050:
0051:        import java.io.Serializable;
0052:        import java.lang.reflect.*;
0053:        import java.text.MessageFormat;
0054:        import java.util.Locale;
0055:        import java.util.ResourceBundle;
0056:
0057:        import org.mozilla.javascript.xml.XMLObject;
0058:        import org.mozilla.javascript.xml.XMLLib;
0059:
0060:        /**
0061:         * This is the class that implements the runtime.
0062:         *
0063:         * @author Norris Boyd
0064:         */
0065:
0066:        public class ScriptRuntime {
0067:
0068:            /**
0069:             * No instances should be created.
0070:             */
0071:            protected ScriptRuntime() {
0072:            }
0073:
0074:            private static class NoSuchMethodShim implements  Callable {
0075:                String methodName;
0076:                Callable noSuchMethodMethod;
0077:
0078:                NoSuchMethodShim(Callable noSuchMethodMethod, String methodName) {
0079:                    this .noSuchMethodMethod = noSuchMethodMethod;
0080:                    this .methodName = methodName;
0081:                }
0082:
0083:                /**
0084:                 * Perform the call.
0085:                 *
0086:                 * @param cx the current Context for this thread
0087:                 * @param scope the scope to use to resolve properties.
0088:                 * @param thisObj the JavaScript <code>this</code> object
0089:                 * @param args the array of arguments
0090:                 * @return the result of the call
0091:                 */
0092:                public Object call(Context cx, Scriptable scope,
0093:                        Scriptable this Obj, Object[] args) {
0094:                    Object[] nestedArgs = new Object[2];
0095:
0096:                    nestedArgs[0] = methodName;
0097:                    nestedArgs[1] = newArrayLiteral(args, null, cx, scope);
0098:                    return noSuchMethodMethod.call(cx, scope, this Obj,
0099:                            nestedArgs);
0100:                }
0101:
0102:            }
0103:
0104:            /*
0105:             * There's such a huge space (and some time) waste for the Foo.class
0106:             * syntax: the compiler sticks in a test of a static field in the
0107:             * enclosing class for null and the code for creating the class value.
0108:             * It has to do this since the reference has to get pushed off until
0109:             * execution time (i.e. can't force an early load), but for the
0110:             * 'standard' classes - especially those in java.lang, we can trust
0111:             * that they won't cause problems by being loaded early.
0112:             */
0113:
0114:            public final static Class BooleanClass = Kit
0115:                    .classOrNull("java.lang.Boolean"), ByteClass = Kit
0116:                    .classOrNull("java.lang.Byte"), CharacterClass = Kit
0117:                    .classOrNull("java.lang.Character"), ClassClass = Kit
0118:                    .classOrNull("java.lang.Class"), DoubleClass = Kit
0119:                    .classOrNull("java.lang.Double"), FloatClass = Kit
0120:                    .classOrNull("java.lang.Float"), IntegerClass = Kit
0121:                    .classOrNull("java.lang.Integer"), LongClass = Kit
0122:                    .classOrNull("java.lang.Long"), NumberClass = Kit
0123:                    .classOrNull("java.lang.Number"), ObjectClass = Kit
0124:                    .classOrNull("java.lang.Object"), ShortClass = Kit
0125:                    .classOrNull("java.lang.Short"), StringClass = Kit
0126:                    .classOrNull("java.lang.String"), DateClass = Kit
0127:                    .classOrNull("java.util.Date");
0128:
0129:            public final static Class ContextClass = Kit
0130:                    .classOrNull("org.mozilla.javascript.Context"),
0131:                    ContextFactoryClass = Kit
0132:                            .classOrNull("org.mozilla.javascript.ContextFactory"),
0133:                    FunctionClass = Kit
0134:                            .classOrNull("org.mozilla.javascript.Function"),
0135:                    ScriptableClass = Kit
0136:                            .classOrNull("org.mozilla.javascript.Scriptable"),
0137:                    ScriptableObjectClass = Kit
0138:                            .classOrNull("org.mozilla.javascript.ScriptableObject");
0139:
0140:            private static final String[] lazilyNames = { "RegExp",
0141:                    "org.mozilla.javascript.regexp.NativeRegExp", "Packages",
0142:                    "org.mozilla.javascript.NativeJavaTopPackage", "java",
0143:                    "org.mozilla.javascript.NativeJavaTopPackage", "javax",
0144:                    "org.mozilla.javascript.NativeJavaTopPackage", "org",
0145:                    "org.mozilla.javascript.NativeJavaTopPackage", "com",
0146:                    "org.mozilla.javascript.NativeJavaTopPackage", "edu",
0147:                    "org.mozilla.javascript.NativeJavaTopPackage", "net",
0148:                    "org.mozilla.javascript.NativeJavaTopPackage", "getClass",
0149:                    "org.mozilla.javascript.NativeJavaTopPackage",
0150:                    "JavaAdapter", "org.mozilla.javascript.JavaAdapter",
0151:                    "JavaImporter",
0152:                    "org.mozilla.javascript.ImporterTopLevel",
0153:                    "Continuation",
0154:                    "org.mozilla.javascript.continuations.Continuation",
0155:                    //	TODO	Grotesque hack using literal string (xml) just to minimize
0156:                    //			changes for now
0157:                    "XML", "(xml)", "XMLList", "(xml)", "Namespace", "(xml)",
0158:                    "QName", "(xml)", };
0159:
0160:            private static final Object LIBRARY_SCOPE_KEY = new Object();
0161:
0162:            public static boolean isRhinoRuntimeType(Class cl) {
0163:                if (cl.isPrimitive()) {
0164:                    return (cl != Character.TYPE);
0165:                } else {
0166:                    return (cl == StringClass || cl == BooleanClass
0167:                            || NumberClass.isAssignableFrom(cl) || ScriptableClass
0168:                            .isAssignableFrom(cl));
0169:                }
0170:            }
0171:
0172:            public static ScriptableObject initStandardObjects(Context cx,
0173:                    ScriptableObject scope, boolean sealed) {
0174:                if (scope == null) {
0175:                    scope = new NativeObject();
0176:                }
0177:                scope.associateValue(LIBRARY_SCOPE_KEY, scope);
0178:                (new ClassCache()).associate(scope);
0179:
0180:                BaseFunction.init(scope, sealed);
0181:                NativeObject.init(scope, sealed);
0182:
0183:                Scriptable objectProto = ScriptableObject
0184:                        .getObjectPrototype(scope);
0185:
0186:                // Function.prototype.__proto__ should be Object.prototype
0187:                Scriptable functionProto = ScriptableObject
0188:                        .getFunctionPrototype(scope);
0189:                functionProto.setPrototype(objectProto);
0190:
0191:                // Set the prototype of the object passed in if need be
0192:                if (scope.getPrototype() == null)
0193:                    scope.setPrototype(objectProto);
0194:
0195:                // must precede NativeGlobal since it's needed therein
0196:                NativeError.init(scope, sealed);
0197:                NativeGlobal.init(cx, scope, sealed);
0198:
0199:                NativeArray.init(scope, sealed);
0200:                if (cx.getOptimizationLevel() > 0) {
0201:                    // When optimizing, attempt to fulfill all requests for new Array(N)
0202:                    // with a higher threshold before switching to a sparse 
0203:                    // representation
0204:                    NativeArray.setMaximumInitialCapacity(200000);
0205:                }
0206:                NativeString.init(scope, sealed);
0207:                NativeBoolean.init(scope, sealed);
0208:                NativeNumber.init(scope, sealed);
0209:                NativeDate.init(scope, sealed);
0210:                NativeMath.init(scope, sealed);
0211:
0212:                NativeWith.init(scope, sealed);
0213:                NativeCall.init(scope, sealed);
0214:                NativeScript.init(scope, sealed);
0215:
0216:                NativeIterator.init(scope, sealed); // Also initializes NativeGenerator
0217:
0218:                boolean withXml = cx.hasFeature(Context.FEATURE_E4X)
0219:                        && cx.getE4xImplementationFactory() != null;
0220:
0221:                for (int i = 0; i != lazilyNames.length; i += 2) {
0222:                    String topProperty = lazilyNames[i];
0223:                    String className = lazilyNames[i + 1];
0224:                    if (!withXml && className.equals("(xml)")) {
0225:                        continue;
0226:                    } else if (withXml && className.equals("(xml)")) {
0227:                        className = cx.getE4xImplementationFactory()
0228:                                .getImplementationClassName();
0229:                    }
0230:                    new LazilyLoadedCtor(scope, topProperty, className, sealed);
0231:                }
0232:
0233:                return scope;
0234:            }
0235:
0236:            public static ScriptableObject getLibraryScopeOrNull(
0237:                    Scriptable scope) {
0238:                ScriptableObject libScope;
0239:                libScope = (ScriptableObject) ScriptableObject
0240:                        .getTopScopeValue(scope, LIBRARY_SCOPE_KEY);
0241:                return libScope;
0242:            }
0243:
0244:            // It is public so NativeRegExp can access it.
0245:            public static boolean isJSLineTerminator(int c) {
0246:                // Optimization for faster check for eol character:
0247:                // they do not have 0xDFD0 bits set
0248:                if ((c & 0xDFD0) != 0) {
0249:                    return false;
0250:                }
0251:                return c == '\n' || c == '\r' || c == 0x2028 || c == 0x2029;
0252:            }
0253:
0254:            public static Boolean wrapBoolean(boolean b) {
0255:                return b ? Boolean.TRUE : Boolean.FALSE;
0256:            }
0257:
0258:            public static Integer wrapInt(int i) {
0259:                return new Integer(i);
0260:            }
0261:
0262:            public static Number wrapNumber(double x) {
0263:                if (x != x) {
0264:                    return ScriptRuntime.NaNobj;
0265:                }
0266:                return new Double(x);
0267:            }
0268:
0269:            /**
0270:             * Convert the value to a boolean.
0271:             *
0272:             * See ECMA 9.2.
0273:             */
0274:            public static boolean toBoolean(Object val) {
0275:                for (;;) {
0276:                    if (val instanceof  Boolean)
0277:                        return ((Boolean) val).booleanValue();
0278:                    if (val == null || val == Undefined.instance)
0279:                        return false;
0280:                    if (val instanceof  String)
0281:                        return ((String) val).length() != 0;
0282:                    if (val instanceof  Number) {
0283:                        double d = ((Number) val).doubleValue();
0284:                        return (d == d && d != 0.0);
0285:                    }
0286:                    if (val instanceof  Scriptable) {
0287:                        if (val instanceof  ScriptableObject
0288:                                && ((ScriptableObject) val)
0289:                                        .avoidObjectDetection()) {
0290:                            return false;
0291:                        }
0292:                        if (Context.getContext().isVersionECMA1()) {
0293:                            // pure ECMA
0294:                            return true;
0295:                        }
0296:                        // ECMA extension
0297:                        val = ((Scriptable) val).getDefaultValue(BooleanClass);
0298:                        if (val instanceof  Scriptable)
0299:                            throw errorWithClassName("msg.primitive.expected",
0300:                                    val);
0301:                        continue;
0302:                    }
0303:                    warnAboutNonJSObject(val);
0304:                    return true;
0305:                }
0306:            }
0307:
0308:            /**
0309:             * Convert the value to a number.
0310:             *
0311:             * See ECMA 9.3.
0312:             */
0313:            public static double toNumber(Object val) {
0314:                for (;;) {
0315:                    if (val instanceof  Number)
0316:                        return ((Number) val).doubleValue();
0317:                    if (val == null)
0318:                        return +0.0;
0319:                    if (val == Undefined.instance)
0320:                        return NaN;
0321:                    if (val instanceof  String)
0322:                        return toNumber((String) val);
0323:                    if (val instanceof  Boolean)
0324:                        return ((Boolean) val).booleanValue() ? 1 : +0.0;
0325:                    if (val instanceof  Scriptable) {
0326:                        val = ((Scriptable) val).getDefaultValue(NumberClass);
0327:                        if (val instanceof  Scriptable)
0328:                            throw errorWithClassName("msg.primitive.expected",
0329:                                    val);
0330:                        continue;
0331:                    }
0332:                    warnAboutNonJSObject(val);
0333:                    return NaN;
0334:                }
0335:            }
0336:
0337:            public static double toNumber(Object[] args, int index) {
0338:                return (index < args.length) ? toNumber(args[index]) : NaN;
0339:            }
0340:
0341:            // Can not use Double.NaN defined as 0.0d / 0.0 as under the Microsoft VM,
0342:            // versions 2.01 and 3.0P1, that causes some uses (returns at least) of
0343:            // Double.NaN to be converted to 1.0.
0344:            // So we use ScriptRuntime.NaN instead of Double.NaN.
0345:            public static final double NaN = Double
0346:                    .longBitsToDouble(0x7ff8000000000000L);
0347:
0348:            // A similar problem exists for negative zero.
0349:            public static final double negativeZero = Double
0350:                    .longBitsToDouble(0x8000000000000000L);
0351:
0352:            public static final Double NaNobj = new Double(NaN);
0353:
0354:            /*
0355:             * Helper function for toNumber, parseInt, and TokenStream.getToken.
0356:             */
0357:            static double stringToNumber(String s, int start, int radix) {
0358:                char digitMax = '9';
0359:                char lowerCaseBound = 'a';
0360:                char upperCaseBound = 'A';
0361:                int len = s.length();
0362:                if (radix < 10) {
0363:                    digitMax = (char) ('0' + radix - 1);
0364:                }
0365:                if (radix > 10) {
0366:                    lowerCaseBound = (char) ('a' + radix - 10);
0367:                    upperCaseBound = (char) ('A' + radix - 10);
0368:                }
0369:                int end;
0370:                double sum = 0.0;
0371:                for (end = start; end < len; end++) {
0372:                    char c = s.charAt(end);
0373:                    int newDigit;
0374:                    if ('0' <= c && c <= digitMax)
0375:                        newDigit = c - '0';
0376:                    else if ('a' <= c && c < lowerCaseBound)
0377:                        newDigit = c - 'a' + 10;
0378:                    else if ('A' <= c && c < upperCaseBound)
0379:                        newDigit = c - 'A' + 10;
0380:                    else
0381:                        break;
0382:                    sum = sum * radix + newDigit;
0383:                }
0384:                if (start == end) {
0385:                    return NaN;
0386:                }
0387:                if (sum >= 9007199254740992.0) {
0388:                    if (radix == 10) {
0389:                        /* If we're accumulating a decimal number and the number
0390:                         * is >= 2^53, then the result from the repeated multiply-add
0391:                         * above may be inaccurate.  Call Java to get the correct
0392:                         * answer.
0393:                         */
0394:                        try {
0395:                            return Double.valueOf(s.substring(start, end))
0396:                                    .doubleValue();
0397:                        } catch (NumberFormatException nfe) {
0398:                            return NaN;
0399:                        }
0400:                    } else if (radix == 2 || radix == 4 || radix == 8
0401:                            || radix == 16 || radix == 32) {
0402:                        /* The number may also be inaccurate for one of these bases.
0403:                         * This happens if the addition in value*radix + digit causes
0404:                         * a round-down to an even least significant mantissa bit
0405:                         * when the first dropped bit is a one.  If any of the
0406:                         * following digits in the number (which haven't been added
0407:                         * in yet) are nonzero then the correct action would have
0408:                         * been to round up instead of down.  An example of this
0409:                         * occurs when reading the number 0x1000000000000081, which
0410:                         * rounds to 0x1000000000000000 instead of 0x1000000000000100.
0411:                         */
0412:                        int bitShiftInChar = 1;
0413:                        int digit = 0;
0414:
0415:                        final int SKIP_LEADING_ZEROS = 0;
0416:                        final int FIRST_EXACT_53_BITS = 1;
0417:                        final int AFTER_BIT_53 = 2;
0418:                        final int ZEROS_AFTER_54 = 3;
0419:                        final int MIXED_AFTER_54 = 4;
0420:
0421:                        int state = SKIP_LEADING_ZEROS;
0422:                        int exactBitsLimit = 53;
0423:                        double factor = 0.0;
0424:                        boolean bit53 = false;
0425:                        // bit54 is the 54th bit (the first dropped from the mantissa)
0426:                        boolean bit54 = false;
0427:
0428:                        for (;;) {
0429:                            if (bitShiftInChar == 1) {
0430:                                if (start == end)
0431:                                    break;
0432:                                digit = s.charAt(start++);
0433:                                if ('0' <= digit && digit <= '9')
0434:                                    digit -= '0';
0435:                                else if ('a' <= digit && digit <= 'z')
0436:                                    digit -= 'a' - 10;
0437:                                else
0438:                                    digit -= 'A' - 10;
0439:                                bitShiftInChar = radix;
0440:                            }
0441:                            bitShiftInChar >>= 1;
0442:                            boolean bit = (digit & bitShiftInChar) != 0;
0443:
0444:                            switch (state) {
0445:                            case SKIP_LEADING_ZEROS:
0446:                                if (bit) {
0447:                                    --exactBitsLimit;
0448:                                    sum = 1.0;
0449:                                    state = FIRST_EXACT_53_BITS;
0450:                                }
0451:                                break;
0452:                            case FIRST_EXACT_53_BITS:
0453:                                sum *= 2.0;
0454:                                if (bit)
0455:                                    sum += 1.0;
0456:                                --exactBitsLimit;
0457:                                if (exactBitsLimit == 0) {
0458:                                    bit53 = bit;
0459:                                    state = AFTER_BIT_53;
0460:                                }
0461:                                break;
0462:                            case AFTER_BIT_53:
0463:                                bit54 = bit;
0464:                                factor = 2.0;
0465:                                state = ZEROS_AFTER_54;
0466:                                break;
0467:                            case ZEROS_AFTER_54:
0468:                                if (bit) {
0469:                                    state = MIXED_AFTER_54;
0470:                                }
0471:                                // fallthrough
0472:                            case MIXED_AFTER_54:
0473:                                factor *= 2;
0474:                                break;
0475:                            }
0476:                        }
0477:                        switch (state) {
0478:                        case SKIP_LEADING_ZEROS:
0479:                            sum = 0.0;
0480:                            break;
0481:                        case FIRST_EXACT_53_BITS:
0482:                        case AFTER_BIT_53:
0483:                            // do nothing
0484:                            break;
0485:                        case ZEROS_AFTER_54:
0486:                            // x1.1 -> x1 + 1 (round up)
0487:                            // x0.1 -> x0 (round down)
0488:                            if (bit54 & bit53)
0489:                                sum += 1.0;
0490:                            sum *= factor;
0491:                            break;
0492:                        case MIXED_AFTER_54:
0493:                            // x.100...1.. -> x + 1 (round up)
0494:                            // x.0anything -> x (round down)
0495:                            if (bit54)
0496:                                sum += 1.0;
0497:                            sum *= factor;
0498:                            break;
0499:                        }
0500:                    }
0501:                    /* We don't worry about inaccurate numbers for any other base. */
0502:                }
0503:                return sum;
0504:            }
0505:
0506:            /**
0507:             * ToNumber applied to the String type
0508:             *
0509:             * See ECMA 9.3.1
0510:             */
0511:            public static double toNumber(String s) {
0512:                int len = s.length();
0513:                int start = 0;
0514:                char startChar;
0515:                for (;;) {
0516:                    if (start == len) {
0517:                        // Empty or contains only whitespace
0518:                        return +0.0;
0519:                    }
0520:                    startChar = s.charAt(start);
0521:                    if (!Character.isWhitespace(startChar))
0522:                        break;
0523:                    start++;
0524:                }
0525:
0526:                if (startChar == '0') {
0527:                    if (start + 2 < len) {
0528:                        int c1 = s.charAt(start + 1);
0529:                        if (c1 == 'x' || c1 == 'X') {
0530:                            // A hexadecimal number
0531:                            return stringToNumber(s, start + 2, 16);
0532:                        }
0533:                    }
0534:                } else if (startChar == '+' || startChar == '-') {
0535:                    if (start + 3 < len && s.charAt(start + 1) == '0') {
0536:                        int c2 = s.charAt(start + 2);
0537:                        if (c2 == 'x' || c2 == 'X') {
0538:                            // A hexadecimal number with sign
0539:                            double val = stringToNumber(s, start + 3, 16);
0540:                            return startChar == '-' ? -val : val;
0541:                        }
0542:                    }
0543:                }
0544:
0545:                int end = len - 1;
0546:                char endChar;
0547:                while (Character.isWhitespace(endChar = s.charAt(end)))
0548:                    end--;
0549:                if (endChar == 'y') {
0550:                    // check for "Infinity"
0551:                    if (startChar == '+' || startChar == '-')
0552:                        start++;
0553:                    if (start + 7 == end
0554:                            && s.regionMatches(start, "Infinity", 0, 8))
0555:                        return startChar == '-' ? Double.NEGATIVE_INFINITY
0556:                                : Double.POSITIVE_INFINITY;
0557:                    return NaN;
0558:                }
0559:                // A non-hexadecimal, non-infinity number:
0560:                // just try a normal floating point conversion
0561:                String sub = s.substring(start, end + 1);
0562:                if (MSJVM_BUG_WORKAROUNDS) {
0563:                    // The MS JVM will accept non-conformant strings
0564:                    // rather than throwing a NumberFormatException
0565:                    // as it should.
0566:                    for (int i = sub.length() - 1; i >= 0; i--) {
0567:                        char c = sub.charAt(i);
0568:                        if (('0' <= c && c <= '9') || c == '.' || c == 'e'
0569:                                || c == 'E' || c == '+' || c == '-')
0570:                            continue;
0571:                        return NaN;
0572:                    }
0573:                }
0574:                try {
0575:                    return Double.valueOf(sub).doubleValue();
0576:                } catch (NumberFormatException ex) {
0577:                    return NaN;
0578:                }
0579:            }
0580:
0581:            /**
0582:             * Helper function for builtin objects that use the varargs form.
0583:             * ECMA function formal arguments are undefined if not supplied;
0584:             * this function pads the argument array out to the expected
0585:             * length, if necessary.
0586:             */
0587:            public static Object[] padArguments(Object[] args, int count) {
0588:                if (count < args.length)
0589:                    return args;
0590:
0591:                int i;
0592:                Object[] result = new Object[count];
0593:                for (i = 0; i < args.length; i++) {
0594:                    result[i] = args[i];
0595:                }
0596:
0597:                for (; i < count; i++) {
0598:                    result[i] = Undefined.instance;
0599:                }
0600:
0601:                return result;
0602:            }
0603:
0604:            /* Work around Microsoft Java VM bugs. */
0605:            private final static boolean MSJVM_BUG_WORKAROUNDS = true;
0606:
0607:            public static String escapeString(String s) {
0608:                return escapeString(s, '"');
0609:            }
0610:
0611:            /**
0612:             * For escaping strings printed by object and array literals; not quite
0613:             * the same as 'escape.'
0614:             */
0615:            public static String escapeString(String s, char escapeQuote) {
0616:                if (!(escapeQuote == '"' || escapeQuote == '\''))
0617:                    Kit.codeBug();
0618:                StringBuffer sb = null;
0619:
0620:                for (int i = 0, L = s.length(); i != L; ++i) {
0621:                    int c = s.charAt(i);
0622:
0623:                    if (' ' <= c && c <= '~' && c != escapeQuote && c != '\\') {
0624:                        // an ordinary print character (like C isprint()) and not "
0625:                        // or \ .
0626:                        if (sb != null) {
0627:                            sb.append((char) c);
0628:                        }
0629:                        continue;
0630:                    }
0631:                    if (sb == null) {
0632:                        sb = new StringBuffer(L + 3);
0633:                        sb.append(s);
0634:                        sb.setLength(i);
0635:                    }
0636:
0637:                    int escape = -1;
0638:                    switch (c) {
0639:                    case '\b':
0640:                        escape = 'b';
0641:                        break;
0642:                    case '\f':
0643:                        escape = 'f';
0644:                        break;
0645:                    case '\n':
0646:                        escape = 'n';
0647:                        break;
0648:                    case '\r':
0649:                        escape = 'r';
0650:                        break;
0651:                    case '\t':
0652:                        escape = 't';
0653:                        break;
0654:                    case 0xb:
0655:                        escape = 'v';
0656:                        break; // Java lacks \v.
0657:                    case ' ':
0658:                        escape = ' ';
0659:                        break;
0660:                    case '\\':
0661:                        escape = '\\';
0662:                        break;
0663:                    }
0664:                    if (escape >= 0) {
0665:                        // an \escaped sort of character
0666:                        sb.append('\\');
0667:                        sb.append((char) escape);
0668:                    } else if (c == escapeQuote) {
0669:                        sb.append('\\');
0670:                        sb.append(escapeQuote);
0671:                    } else {
0672:                        int hexSize;
0673:                        if (c < 256) {
0674:                            // 2-digit hex
0675:                            sb.append("\\x");
0676:                            hexSize = 2;
0677:                        } else {
0678:                            // Unicode.
0679:                            sb.append("\\u");
0680:                            hexSize = 4;
0681:                        }
0682:                        // append hexadecimal form of c left-padded with 0
0683:                        for (int shift = (hexSize - 1) * 4; shift >= 0; shift -= 4) {
0684:                            int digit = 0xf & (c >> shift);
0685:                            int hc = (digit < 10) ? '0' + digit
0686:                                    : 'a' - 10 + digit;
0687:                            sb.append((char) hc);
0688:                        }
0689:                    }
0690:                }
0691:                return (sb == null) ? s : sb.toString();
0692:            }
0693:
0694:            static boolean isValidIdentifierName(String s) {
0695:                int L = s.length();
0696:                if (L == 0)
0697:                    return false;
0698:                if (!Character.isJavaIdentifierStart(s.charAt(0)))
0699:                    return false;
0700:                for (int i = 1; i != L; ++i) {
0701:                    if (!Character.isJavaIdentifierPart(s.charAt(i)))
0702:                        return false;
0703:                }
0704:                return !TokenStream.isKeyword(s);
0705:            }
0706:
0707:            /**
0708:             * Convert the value to a string.
0709:             *
0710:             * See ECMA 9.8.
0711:             */
0712:            public static String toString(Object val) {
0713:                for (;;) {
0714:                    if (val == null) {
0715:                        return "null";
0716:                    }
0717:                    if (val == Undefined.instance) {
0718:                        return "undefined";
0719:                    }
0720:                    if (val instanceof  String) {
0721:                        return (String) val;
0722:                    }
0723:                    if (val instanceof  Number) {
0724:                        // XXX should we just teach NativeNumber.stringValue()
0725:                        // about Numbers?
0726:                        return numberToString(((Number) val).doubleValue(), 10);
0727:                    }
0728:                    if (val instanceof  Scriptable) {
0729:                        val = ((Scriptable) val).getDefaultValue(StringClass);
0730:                        if (val instanceof  Scriptable) {
0731:                            throw errorWithClassName("msg.primitive.expected",
0732:                                    val);
0733:                        }
0734:                        continue;
0735:                    }
0736:                    return val.toString();
0737:                }
0738:            }
0739:
0740:            static String defaultObjectToString(Scriptable obj) {
0741:                return "[object " + obj.getClassName() + ']';
0742:            }
0743:
0744:            public static String toString(Object[] args, int index) {
0745:                return (index < args.length) ? toString(args[index])
0746:                        : "undefined";
0747:            }
0748:
0749:            /**
0750:             * Optimized version of toString(Object) for numbers.
0751:             */
0752:            public static String toString(double val) {
0753:                return numberToString(val, 10);
0754:            }
0755:
0756:            public static String numberToString(double d, int base) {
0757:                if (d != d)
0758:                    return "NaN";
0759:                if (d == Double.POSITIVE_INFINITY)
0760:                    return "Infinity";
0761:                if (d == Double.NEGATIVE_INFINITY)
0762:                    return "-Infinity";
0763:                if (d == 0.0)
0764:                    return "0";
0765:
0766:                if ((base < 2) || (base > 36)) {
0767:                    throw Context.reportRuntimeError1("msg.bad.radix", Integer
0768:                            .toString(base));
0769:                }
0770:
0771:                if (base != 10) {
0772:                    return DToA.JS_dtobasestr(base, d);
0773:                } else {
0774:                    StringBuffer result = new StringBuffer();
0775:                    DToA.JS_dtostr(result, DToA.DTOSTR_STANDARD, 0, d);
0776:                    return result.toString();
0777:                }
0778:
0779:            }
0780:
0781:            static String uneval(Context cx, Scriptable scope, Object value) {
0782:                if (value == null) {
0783:                    return "null";
0784:                }
0785:                if (value == Undefined.instance) {
0786:                    return "undefined";
0787:                }
0788:                if (value instanceof  String) {
0789:                    String escaped = escapeString((String) value);
0790:                    StringBuffer sb = new StringBuffer(escaped.length() + 2);
0791:                    sb.append('\"');
0792:                    sb.append(escaped);
0793:                    sb.append('\"');
0794:                    return sb.toString();
0795:                }
0796:                if (value instanceof  Number) {
0797:                    double d = ((Number) value).doubleValue();
0798:                    if (d == 0 && 1 / d < 0) {
0799:                        return "-0";
0800:                    }
0801:                    return toString(d);
0802:                }
0803:                if (value instanceof  Boolean) {
0804:                    return toString(value);
0805:                }
0806:                if (value instanceof  Scriptable) {
0807:                    Scriptable obj = (Scriptable) value;
0808:                    // Wrapped Java objects won't have "toSource" and will report
0809:                    // errors for get()s of nonexistent name, so use has() first
0810:                    if (ScriptableObject.hasProperty(obj, "toSource")) {
0811:                        Object v = ScriptableObject
0812:                                .getProperty(obj, "toSource");
0813:                        if (v instanceof  Function) {
0814:                            Function f = (Function) v;
0815:                            return toString(f.call(cx, scope, obj, emptyArgs));
0816:                        }
0817:                    }
0818:                    return toString(value);
0819:                }
0820:                warnAboutNonJSObject(value);
0821:                return value.toString();
0822:            }
0823:
0824:            static String defaultObjectToSource(Context cx, Scriptable scope,
0825:                    Scriptable this Obj, Object[] args) {
0826:                boolean toplevel, iterating;
0827:                if (cx.iterating == null) {
0828:                    toplevel = true;
0829:                    iterating = false;
0830:                    cx.iterating = new ObjToIntMap(31);
0831:                } else {
0832:                    toplevel = false;
0833:                    iterating = cx.iterating.has(this Obj);
0834:                }
0835:
0836:                StringBuffer result = new StringBuffer(128);
0837:                if (toplevel) {
0838:                    result.append("(");
0839:                }
0840:                result.append('{');
0841:
0842:                // Make sure cx.iterating is set to null when done
0843:                // so we don't leak memory
0844:                try {
0845:                    if (!iterating) {
0846:                        cx.iterating.intern(this Obj); // stop recursion.
0847:                        Object[] ids = this Obj.getIds();
0848:                        for (int i = 0; i < ids.length; i++) {
0849:                            Object id = ids[i];
0850:                            Object value;
0851:                            if (id instanceof  Integer) {
0852:                                int intId = ((Integer) id).intValue();
0853:                                value = this Obj.get(intId, this Obj);
0854:                                if (value == Scriptable.NOT_FOUND)
0855:                                    continue; // a property has been removed
0856:                                if (i > 0)
0857:                                    result.append(", ");
0858:                                result.append(intId);
0859:                            } else {
0860:                                String strId = (String) id;
0861:                                value = this Obj.get(strId, this Obj);
0862:                                if (value == Scriptable.NOT_FOUND)
0863:                                    continue; // a property has been removed
0864:                                if (i > 0)
0865:                                    result.append(", ");
0866:                                if (ScriptRuntime.isValidIdentifierName(strId)) {
0867:                                    result.append(strId);
0868:                                } else {
0869:                                    result.append('\'');
0870:                                    result.append(ScriptRuntime.escapeString(
0871:                                            strId, '\''));
0872:                                    result.append('\'');
0873:                                }
0874:                            }
0875:                            result.append(':');
0876:                            result.append(ScriptRuntime
0877:                                    .uneval(cx, scope, value));
0878:                        }
0879:                    }
0880:                } finally {
0881:                    if (toplevel) {
0882:                        cx.iterating = null;
0883:                    }
0884:                }
0885:
0886:                result.append('}');
0887:                if (toplevel) {
0888:                    result.append(')');
0889:                }
0890:                return result.toString();
0891:            }
0892:
0893:            public static Scriptable toObject(Scriptable scope, Object val) {
0894:                if (val instanceof  Scriptable) {
0895:                    return (Scriptable) val;
0896:                }
0897:                return toObject(Context.getContext(), scope, val);
0898:            }
0899:
0900:            public static Scriptable toObjectOrNull(Context cx, Object obj) {
0901:                if (obj instanceof  Scriptable) {
0902:                    return (Scriptable) obj;
0903:                } else if (obj != null && obj != Undefined.instance) {
0904:                    return toObject(cx, getTopCallScope(cx), obj);
0905:                }
0906:                return null;
0907:            }
0908:
0909:            /**
0910:             * @deprecated Use {@link #toObject(Scriptable, Object)} instead.
0911:             */
0912:            public static Scriptable toObject(Scriptable scope, Object val,
0913:                    Class staticClass) {
0914:                if (val instanceof  Scriptable) {
0915:                    return (Scriptable) val;
0916:                }
0917:                return toObject(Context.getContext(), scope, val);
0918:            }
0919:
0920:            /**
0921:             * Convert the value to an object.
0922:             *
0923:             * See ECMA 9.9.
0924:             */
0925:            public static Scriptable toObject(Context cx, Scriptable scope,
0926:                    Object val) {
0927:                if (val instanceof  Scriptable) {
0928:                    return (Scriptable) val;
0929:                }
0930:                if (val == null) {
0931:                    throw typeError0("msg.null.to.object");
0932:                }
0933:                if (val == Undefined.instance) {
0934:                    throw typeError0("msg.undef.to.object");
0935:                }
0936:                String className = val instanceof  String ? "String"
0937:                        : val instanceof  Number ? "Number"
0938:                                : val instanceof  Boolean ? "Boolean" : null;
0939:                if (className != null) {
0940:                    Object[] args = { val };
0941:                    scope = ScriptableObject.getTopLevelScope(scope);
0942:                    return newObject(cx, scope, className, args);
0943:                }
0944:
0945:                // Extension: Wrap as a LiveConnect object.
0946:                Object wrapped = cx.getWrapFactory().wrap(cx, scope, val, null);
0947:                if (wrapped instanceof  Scriptable)
0948:                    return (Scriptable) wrapped;
0949:                throw errorWithClassName("msg.invalid.type", val);
0950:            }
0951:
0952:            /**
0953:             * @deprecated Use {@link #toObject(Context, Scriptable, Object)} instead.
0954:             */
0955:            public static Scriptable toObject(Context cx, Scriptable scope,
0956:                    Object val, Class staticClass) {
0957:                return toObject(cx, scope, val);
0958:            }
0959:
0960:            /**
0961:             * @deprecated The method is only present for compatibility.
0962:             */
0963:            public static Object call(Context cx, Object fun, Object this Arg,
0964:                    Object[] args, Scriptable scope) {
0965:                if (!(fun instanceof  Function)) {
0966:                    throw notFunctionError(toString(fun));
0967:                }
0968:                Function function = (Function) fun;
0969:                Scriptable this Obj = toObjectOrNull(cx, this Arg);
0970:                if (this Obj == null) {
0971:                    throw undefCallError(this Obj, "function");
0972:                }
0973:                return function.call(cx, scope, this Obj, args);
0974:            }
0975:
0976:            public static Scriptable newObject(Context cx, Scriptable scope,
0977:                    String constructorName, Object[] args) {
0978:                scope = ScriptableObject.getTopLevelScope(scope);
0979:                Function ctor = getExistingCtor(cx, scope, constructorName);
0980:                if (args == null) {
0981:                    args = ScriptRuntime.emptyArgs;
0982:                }
0983:                return ctor.construct(cx, scope, args);
0984:            }
0985:
0986:            /**
0987:             *
0988:             * See ECMA 9.4.
0989:             */
0990:            public static double toInteger(Object val) {
0991:                return toInteger(toNumber(val));
0992:            }
0993:
0994:            // convenience method
0995:            public static double toInteger(double d) {
0996:                // if it's NaN
0997:                if (d != d)
0998:                    return +0.0;
0999:
1000:                if (d == 0.0 || d == Double.POSITIVE_INFINITY
1001:                        || d == Double.NEGATIVE_INFINITY)
1002:                    return d;
1003:
1004:                if (d > 0.0)
1005:                    return Math.floor(d);
1006:                else
1007:                    return Math.ceil(d);
1008:            }
1009:
1010:            public static double toInteger(Object[] args, int index) {
1011:                return (index < args.length) ? toInteger(args[index]) : +0.0;
1012:            }
1013:
1014:            /**
1015:             *
1016:             * See ECMA 9.5.
1017:             */
1018:            public static int toInt32(Object val) {
1019:                // short circuit for common integer values
1020:                if (val instanceof  Integer)
1021:                    return ((Integer) val).intValue();
1022:
1023:                return toInt32(toNumber(val));
1024:            }
1025:
1026:            public static int toInt32(Object[] args, int index) {
1027:                return (index < args.length) ? toInt32(args[index]) : 0;
1028:            }
1029:
1030:            public static int toInt32(double d) {
1031:                int id = (int) d;
1032:                if (id == d) {
1033:                    // This covers -0.0 as well
1034:                    return id;
1035:                }
1036:
1037:                if (d != d || d == Double.POSITIVE_INFINITY
1038:                        || d == Double.NEGATIVE_INFINITY) {
1039:                    return 0;
1040:                }
1041:
1042:                d = (d >= 0) ? Math.floor(d) : Math.ceil(d);
1043:
1044:                double two32 = 4294967296.0;
1045:                d = Math.IEEEremainder(d, two32);
1046:                // (double)(long)d == d should hold here
1047:
1048:                long l = (long) d;
1049:                // returning (int)d does not work as d can be outside int range
1050:                // but the result must always be 32 lower bits of l
1051:                return (int) l;
1052:            }
1053:
1054:            /**
1055:             * See ECMA 9.6.
1056:             * @return long value representing 32 bits unsigned integer
1057:             */
1058:            public static long toUint32(double d) {
1059:                long l = (long) d;
1060:                if (l == d) {
1061:                    // This covers -0.0 as well
1062:                    return l & 0xffffffffL;
1063:                }
1064:
1065:                if (d != d || d == Double.POSITIVE_INFINITY
1066:                        || d == Double.NEGATIVE_INFINITY) {
1067:                    return 0;
1068:                }
1069:
1070:                d = (d >= 0) ? Math.floor(d) : Math.ceil(d);
1071:
1072:                // 0x100000000 gives me a numeric overflow...
1073:                double two32 = 4294967296.0;
1074:                l = (long) Math.IEEEremainder(d, two32);
1075:
1076:                return l & 0xffffffffL;
1077:            }
1078:
1079:            public static long toUint32(Object val) {
1080:                return toUint32(toNumber(val));
1081:            }
1082:
1083:            /**
1084:             *
1085:             * See ECMA 9.7.
1086:             */
1087:            public static char toUint16(Object val) {
1088:                double d = toNumber(val);
1089:
1090:                int i = (int) d;
1091:                if (i == d) {
1092:                    return (char) i;
1093:                }
1094:
1095:                if (d != d || d == Double.POSITIVE_INFINITY
1096:                        || d == Double.NEGATIVE_INFINITY) {
1097:                    return 0;
1098:                }
1099:
1100:                d = (d >= 0) ? Math.floor(d) : Math.ceil(d);
1101:
1102:                int int16 = 0x10000;
1103:                i = (int) Math.IEEEremainder(d, int16);
1104:
1105:                return (char) i;
1106:            }
1107:
1108:            // XXX: this is until setDefaultNamespace will learn how to store NS
1109:            // properly and separates namespace form Scriptable.get etc.
1110:            private static final String DEFAULT_NS_TAG = "__default_namespace__";
1111:
1112:            public static Object setDefaultNamespace(Object namespace,
1113:                    Context cx) {
1114:                Scriptable scope = cx.currentActivationCall;
1115:                if (scope == null) {
1116:                    scope = getTopCallScope(cx);
1117:                }
1118:
1119:                XMLLib xmlLib = currentXMLLib(cx);
1120:                Object ns = xmlLib.toDefaultXmlNamespace(cx, namespace);
1121:
1122:                // XXX : this should be in separated namesapce from Scriptable.get/put
1123:                if (!scope.has(DEFAULT_NS_TAG, scope)) {
1124:                    // XXX: this is racy of cause
1125:                    ScriptableObject.defineProperty(scope, DEFAULT_NS_TAG, ns,
1126:                            ScriptableObject.PERMANENT
1127:                                    | ScriptableObject.DONTENUM);
1128:                } else {
1129:                    scope.put(DEFAULT_NS_TAG, scope, ns);
1130:                }
1131:
1132:                return Undefined.instance;
1133:            }
1134:
1135:            public static Object searchDefaultNamespace(Context cx) {
1136:                Scriptable scope = cx.currentActivationCall;
1137:                if (scope == null) {
1138:                    scope = getTopCallScope(cx);
1139:                }
1140:                Object nsObject;
1141:                for (;;) {
1142:                    Scriptable parent = scope.getParentScope();
1143:                    if (parent == null) {
1144:                        nsObject = ScriptableObject.getProperty(scope,
1145:                                DEFAULT_NS_TAG);
1146:                        if (nsObject == Scriptable.NOT_FOUND) {
1147:                            return null;
1148:                        }
1149:                        break;
1150:                    }
1151:                    nsObject = scope.get(DEFAULT_NS_TAG, scope);
1152:                    if (nsObject != Scriptable.NOT_FOUND) {
1153:                        break;
1154:                    }
1155:                    scope = parent;
1156:                }
1157:                return nsObject;
1158:            }
1159:
1160:            public static Object getTopLevelProp(Scriptable scope, String id) {
1161:                scope = ScriptableObject.getTopLevelScope(scope);
1162:                return ScriptableObject.getProperty(scope, id);
1163:            }
1164:
1165:            static Function getExistingCtor(Context cx, Scriptable scope,
1166:                    String constructorName) {
1167:                Object ctorVal = ScriptableObject.getProperty(scope,
1168:                        constructorName);
1169:                if (ctorVal instanceof  Function) {
1170:                    return (Function) ctorVal;
1171:                }
1172:                if (ctorVal == Scriptable.NOT_FOUND) {
1173:                    throw Context.reportRuntimeError1("msg.ctor.not.found",
1174:                            constructorName);
1175:                } else {
1176:                    throw Context.reportRuntimeError1("msg.not.ctor",
1177:                            constructorName);
1178:                }
1179:            }
1180:
1181:            /**
1182:             * Return -1L if str is not an index or the index value as lower 32
1183:             * bits of the result.
1184:             */
1185:            private static long indexFromString(String str) {
1186:                // The length of the decimal string representation of
1187:                //  Integer.MAX_VALUE, 2147483647
1188:                final int MAX_VALUE_LENGTH = 10;
1189:
1190:                int len = str.length();
1191:                if (len > 0) {
1192:                    int i = 0;
1193:                    boolean negate = false;
1194:                    int c = str.charAt(0);
1195:                    if (c == '-') {
1196:                        if (len > 1) {
1197:                            c = str.charAt(1);
1198:                            i = 1;
1199:                            negate = true;
1200:                        }
1201:                    }
1202:                    c -= '0';
1203:                    if (0 <= c
1204:                            && c <= 9
1205:                            && len <= (negate ? MAX_VALUE_LENGTH + 1
1206:                                    : MAX_VALUE_LENGTH)) {
1207:                        // Use negative numbers to accumulate index to handle
1208:                        // Integer.MIN_VALUE that is greater by 1 in absolute value
1209:                        // then Integer.MAX_VALUE
1210:                        int index = -c;
1211:                        int oldIndex = 0;
1212:                        i++;
1213:                        if (index != 0) {
1214:                            // Note that 00, 01, 000 etc. are not indexes
1215:                            while (i != len && 0 <= (c = str.charAt(i) - '0')
1216:                                    && c <= 9) {
1217:                                oldIndex = index;
1218:                                index = 10 * index - c;
1219:                                i++;
1220:                            }
1221:                        }
1222:                        // Make sure all characters were consumed and that it couldn't
1223:                        // have overflowed.
1224:                        if (i == len
1225:                                && (oldIndex > (Integer.MIN_VALUE / 10) || (oldIndex == (Integer.MIN_VALUE / 10) && c <= (negate ? -(Integer.MIN_VALUE % 10)
1226:                                        : (Integer.MAX_VALUE % 10))))) {
1227:                            return 0xFFFFFFFFL & (negate ? index : -index);
1228:                        }
1229:                    }
1230:                }
1231:                return -1L;
1232:            }
1233:
1234:            /**
1235:             * If str is a decimal presentation of Uint32 value, return it as long.
1236:             * Othewise return -1L;
1237:             */
1238:            public static long testUint32String(String str) {
1239:                // The length of the decimal string representation of
1240:                //  UINT32_MAX_VALUE, 4294967296
1241:                final int MAX_VALUE_LENGTH = 10;
1242:
1243:                int len = str.length();
1244:                if (1 <= len && len <= MAX_VALUE_LENGTH) {
1245:                    int c = str.charAt(0);
1246:                    c -= '0';
1247:                    if (c == 0) {
1248:                        // Note that 00,01 etc. are not valid Uint32 presentations
1249:                        return (len == 1) ? 0L : -1L;
1250:                    }
1251:                    if (1 <= c && c <= 9) {
1252:                        long v = c;
1253:                        for (int i = 1; i != len; ++i) {
1254:                            c = str.charAt(i) - '0';
1255:                            if (!(0 <= c && c <= 9)) {
1256:                                return -1;
1257:                            }
1258:                            v = 10 * v + c;
1259:                        }
1260:                        // Check for overflow
1261:                        if ((v >>> 32) == 0) {
1262:                            return v;
1263:                        }
1264:                    }
1265:                }
1266:                return -1;
1267:            }
1268:
1269:            /**
1270:             * If s represents index, then return index value wrapped as Integer
1271:             * and othewise return s.
1272:             */
1273:            static Object getIndexObject(String s) {
1274:                long indexTest = indexFromString(s);
1275:                if (indexTest >= 0) {
1276:                    return new Integer((int) indexTest);
1277:                }
1278:                return s;
1279:            }
1280:
1281:            /**
1282:             * If d is exact int value, return its value wrapped as Integer
1283:             * and othewise return d converted to String.
1284:             */
1285:            static Object getIndexObject(double d) {
1286:                int i = (int) d;
1287:                if (i == d) {
1288:                    return new Integer(i);
1289:                }
1290:                return toString(d);
1291:            }
1292:
1293:            /**
1294:             * If toString(id) is a decimal presentation of int32 value, then id
1295:             * is index. In this case return null and make the index available
1296:             * as ScriptRuntime.lastIndexResult(cx). Otherwise return toString(id).
1297:             */
1298:            static String toStringIdOrIndex(Context cx, Object id) {
1299:                if (id instanceof  Number) {
1300:                    double d = ((Number) id).doubleValue();
1301:                    int index = (int) d;
1302:                    if (index == d) {
1303:                        storeIndexResult(cx, index);
1304:                        return null;
1305:                    }
1306:                    return toString(id);
1307:                } else {
1308:                    String s;
1309:                    if (id instanceof  String) {
1310:                        s = (String) id;
1311:                    } else {
1312:                        s = toString(id);
1313:                    }
1314:                    long indexTest = indexFromString(s);
1315:                    if (indexTest >= 0) {
1316:                        storeIndexResult(cx, (int) indexTest);
1317:                        return null;
1318:                    }
1319:                    return s;
1320:                }
1321:            }
1322:
1323:            /**
1324:             * Call obj.[[Get]](id)
1325:             */
1326:            public static Object getObjectElem(Object obj, Object elem,
1327:                    Context cx) {
1328:                Scriptable sobj = toObjectOrNull(cx, obj);
1329:                if (sobj == null) {
1330:                    throw undefReadError(obj, elem);
1331:                }
1332:                return getObjectElem(sobj, elem, cx);
1333:            }
1334:
1335:            public static Object getObjectElem(Scriptable obj, Object elem,
1336:                    Context cx) {
1337:                if (obj instanceof  XMLObject) {
1338:                    XMLObject xmlObject = (XMLObject) obj;
1339:                    return xmlObject.ecmaGet(cx, elem);
1340:                }
1341:
1342:                Object result;
1343:
1344:                String s = toStringIdOrIndex(cx, elem);
1345:                if (s == null) {
1346:                    int index = lastIndexResult(cx);
1347:                    result = ScriptableObject.getProperty(obj, index);
1348:                } else {
1349:                    result = ScriptableObject.getProperty(obj, s);
1350:                }
1351:
1352:                if (result == Scriptable.NOT_FOUND) {
1353:                    result = Undefined.instance;
1354:                }
1355:
1356:                return result;
1357:            }
1358:
1359:            /**
1360:             * Version of getObjectElem when elem is a valid JS identifier name.
1361:             */
1362:            public static Object getObjectProp(Object obj, String property,
1363:                    Context cx) {
1364:                Scriptable sobj = toObjectOrNull(cx, obj);
1365:                if (sobj == null) {
1366:                    throw undefReadError(obj, property);
1367:                }
1368:                return getObjectProp(sobj, property, cx);
1369:            }
1370:
1371:            public static Object getObjectProp(Scriptable obj, String property,
1372:                    Context cx) {
1373:                if (obj instanceof  XMLObject) {
1374:                    // TODO: Change XMLObject to just use Scriptable interface
1375:                    // to avoid paying cost of instanceof check on *every property
1376:                    // lookup* !
1377:                    XMLObject xmlObject = (XMLObject) obj;
1378:                    return xmlObject.ecmaGet(cx, property);
1379:                }
1380:
1381:                Object result = ScriptableObject.getProperty(obj, property);
1382:                if (result == Scriptable.NOT_FOUND) {
1383:                    if (cx.hasFeature(Context.FEATURE_STRICT_MODE)) {
1384:                        Context.reportWarning(ScriptRuntime.getMessage1(
1385:                                "msg.ref.undefined.prop", property));
1386:                    }
1387:                    result = Undefined.instance;
1388:                }
1389:
1390:                return result;
1391:            }
1392:
1393:            public static Object getObjectPropNoWarn(Object obj,
1394:                    String property, Context cx) {
1395:                Scriptable sobj = toObjectOrNull(cx, obj);
1396:                if (sobj == null) {
1397:                    throw undefReadError(obj, property);
1398:                }
1399:                if (obj instanceof  XMLObject) {
1400:                    // TODO: fix as mentioned in note in method above
1401:                    getObjectProp(sobj, property, cx);
1402:                }
1403:                Object result = ScriptableObject.getProperty(sobj, property);
1404:                if (result == Scriptable.NOT_FOUND) {
1405:                    return Undefined.instance;
1406:                }
1407:                return result;
1408:            }
1409:
1410:            /*
1411:             * A cheaper and less general version of the above for well-known argument
1412:             * types.
1413:             */
1414:            public static Object getObjectIndex(Object obj, double dblIndex,
1415:                    Context cx) {
1416:                Scriptable sobj = toObjectOrNull(cx, obj);
1417:                if (sobj == null) {
1418:                    throw undefReadError(obj, toString(dblIndex));
1419:                }
1420:
1421:                int index = (int) dblIndex;
1422:                if (index == dblIndex) {
1423:                    return getObjectIndex(sobj, index, cx);
1424:                } else {
1425:                    String s = toString(dblIndex);
1426:                    return getObjectProp(sobj, s, cx);
1427:                }
1428:            }
1429:
1430:            public static Object getObjectIndex(Scriptable obj, int index,
1431:                    Context cx) {
1432:                if (obj instanceof  XMLObject) {
1433:                    XMLObject xmlObject = (XMLObject) obj;
1434:                    return xmlObject.ecmaGet(cx, new Integer(index));
1435:                }
1436:
1437:                Object result = ScriptableObject.getProperty(obj, index);
1438:                if (result == Scriptable.NOT_FOUND) {
1439:                    result = Undefined.instance;
1440:                }
1441:
1442:                return result;
1443:            }
1444:
1445:            /*
1446:             * Call obj.[[Put]](id, value)
1447:             */
1448:            public static Object setObjectElem(Object obj, Object elem,
1449:                    Object value, Context cx) {
1450:                Scriptable sobj = toObjectOrNull(cx, obj);
1451:                if (sobj == null) {
1452:                    throw undefWriteError(obj, elem, value);
1453:                }
1454:                return setObjectElem(sobj, elem, value, cx);
1455:            }
1456:
1457:            public static Object setObjectElem(Scriptable obj, Object elem,
1458:                    Object value, Context cx) {
1459:                if (obj instanceof  XMLObject) {
1460:                    XMLObject xmlObject = (XMLObject) obj;
1461:                    xmlObject.ecmaPut(cx, elem, value);
1462:                    return value;
1463:                }
1464:
1465:                String s = toStringIdOrIndex(cx, elem);
1466:                if (s == null) {
1467:                    int index = lastIndexResult(cx);
1468:                    ScriptableObject.putProperty(obj, index, value);
1469:                } else {
1470:                    ScriptableObject.putProperty(obj, s, value);
1471:                }
1472:
1473:                return value;
1474:            }
1475:
1476:            /**
1477:             * Version of setObjectElem when elem is a valid JS identifier name.
1478:             */
1479:            public static Object setObjectProp(Object obj, String property,
1480:                    Object value, Context cx) {
1481:                Scriptable sobj = toObjectOrNull(cx, obj);
1482:                if (sobj == null) {
1483:                    throw undefWriteError(obj, property, value);
1484:                }
1485:                return setObjectProp(sobj, property, value, cx);
1486:            }
1487:
1488:            public static Object setObjectProp(Scriptable obj, String property,
1489:                    Object value, Context cx) {
1490:                if (obj instanceof  XMLObject) {
1491:                    XMLObject xmlObject = (XMLObject) obj;
1492:                    xmlObject.ecmaPut(cx, property, value);
1493:                } else {
1494:                    ScriptableObject.putProperty(obj, property, value);
1495:                }
1496:                return value;
1497:            }
1498:
1499:            /*
1500:             * A cheaper and less general version of the above for well-known argument
1501:             * types.
1502:             */
1503:            public static Object setObjectIndex(Object obj, double dblIndex,
1504:                    Object value, Context cx) {
1505:                Scriptable sobj = toObjectOrNull(cx, obj);
1506:                if (sobj == null) {
1507:                    throw undefWriteError(obj, String.valueOf(dblIndex), value);
1508:                }
1509:
1510:                int index = (int) dblIndex;
1511:                if (index == dblIndex) {
1512:                    return setObjectIndex(sobj, index, value, cx);
1513:                } else {
1514:                    String s = toString(dblIndex);
1515:                    return setObjectProp(sobj, s, value, cx);
1516:                }
1517:            }
1518:
1519:            public static Object setObjectIndex(Scriptable obj, int index,
1520:                    Object value, Context cx) {
1521:                if (obj instanceof  XMLObject) {
1522:                    XMLObject xmlObject = (XMLObject) obj;
1523:                    xmlObject.ecmaPut(cx, new Integer(index), value);
1524:                } else {
1525:                    ScriptableObject.putProperty(obj, index, value);
1526:                }
1527:                return value;
1528:            }
1529:
1530:            public static boolean deleteObjectElem(Scriptable target,
1531:                    Object elem, Context cx) {
1532:                boolean result;
1533:                if (target instanceof  XMLObject) {
1534:                    XMLObject xmlObject = (XMLObject) target;
1535:                    result = xmlObject.ecmaDelete(cx, elem);
1536:                } else {
1537:                    String s = toStringIdOrIndex(cx, elem);
1538:                    if (s == null) {
1539:                        int index = lastIndexResult(cx);
1540:                        result = ScriptableObject.deleteProperty(target, index);
1541:                    } else {
1542:                        result = ScriptableObject.deleteProperty(target, s);
1543:                    }
1544:                }
1545:                return result;
1546:            }
1547:
1548:            public static boolean hasObjectElem(Scriptable target, Object elem,
1549:                    Context cx) {
1550:                boolean result;
1551:
1552:                if (target instanceof  XMLObject) {
1553:                    XMLObject xmlObject = (XMLObject) target;
1554:                    result = xmlObject.ecmaHas(cx, elem);
1555:                } else {
1556:                    String s = toStringIdOrIndex(cx, elem);
1557:                    if (s == null) {
1558:                        int index = lastIndexResult(cx);
1559:                        result = ScriptableObject.hasProperty(target, index);
1560:                    } else {
1561:                        result = ScriptableObject.hasProperty(target, s);
1562:                    }
1563:                }
1564:
1565:                return result;
1566:            }
1567:
1568:            public static Object refGet(Ref ref, Context cx) {
1569:                return ref.get(cx);
1570:            }
1571:
1572:            public static Object refSet(Ref ref, Object value, Context cx) {
1573:                return ref.set(cx, value);
1574:            }
1575:
1576:            public static Object refDel(Ref ref, Context cx) {
1577:                return wrapBoolean(ref.delete(cx));
1578:            }
1579:
1580:            static boolean isSpecialProperty(String s) {
1581:                return s.equals("__proto__") || s.equals("__parent__");
1582:            }
1583:
1584:            public static Ref specialRef(Object obj, String specialProperty,
1585:                    Context cx) {
1586:                return SpecialRef.createSpecial(cx, obj, specialProperty);
1587:            }
1588:
1589:            /**
1590:             * The delete operator
1591:             *
1592:             * See ECMA 11.4.1
1593:             *
1594:             * In ECMA 0.19, the description of the delete operator (11.4.1)
1595:             * assumes that the [[Delete]] method returns a value. However,
1596:             * the definition of the [[Delete]] operator (8.6.2.5) does not
1597:             * define a return value. Here we assume that the [[Delete]]
1598:             * method doesn't return a value.
1599:             */
1600:            public static Object delete(Object obj, Object id, Context cx) {
1601:                Scriptable sobj = toObjectOrNull(cx, obj);
1602:                if (sobj == null) {
1603:                    String idStr = (id == null) ? "null" : id.toString();
1604:                    throw typeError2("msg.undef.prop.delete", toString(obj),
1605:                            idStr);
1606:                }
1607:                boolean result = deleteObjectElem(sobj, id, cx);
1608:                return wrapBoolean(result);
1609:            }
1610:
1611:            /**
1612:             * Looks up a name in the scope chain and returns its value.
1613:             */
1614:            public static Object name(Context cx, Scriptable scope, String name) {
1615:                Scriptable parent = scope.getParentScope();
1616:                if (parent == null) {
1617:                    Object result = topScopeName(cx, scope, name);
1618:                    if (result == Scriptable.NOT_FOUND) {
1619:                        throw notFoundError(scope, name);
1620:                    }
1621:                    return result;
1622:                }
1623:
1624:                return nameOrFunction(cx, scope, parent, name, false);
1625:            }
1626:
1627:            private static Object nameOrFunction(Context cx, Scriptable scope,
1628:                    Scriptable parentScope, String name, boolean asFunctionCall) {
1629:                Object result;
1630:                Scriptable this Obj = scope; // It is used only if asFunctionCall==true.
1631:
1632:                XMLObject firstXMLObject = null;
1633:                for (;;) {
1634:                    if (scope instanceof  NativeWith) {
1635:                        Scriptable withObj = scope.getPrototype();
1636:                        if (withObj instanceof  XMLObject) {
1637:                            XMLObject xmlObj = (XMLObject) withObj;
1638:                            if (xmlObj.ecmaHas(cx, name)) {
1639:                                // function this should be the target object of with
1640:                                this Obj = xmlObj;
1641:                                result = xmlObj.ecmaGet(cx, name);
1642:                                break;
1643:                            }
1644:                            if (firstXMLObject == null) {
1645:                                firstXMLObject = xmlObj;
1646:                            }
1647:                        } else {
1648:                            result = ScriptableObject
1649:                                    .getProperty(withObj, name);
1650:                            if (result != Scriptable.NOT_FOUND) {
1651:                                // function this should be the target object of with
1652:                                this Obj = withObj;
1653:                                break;
1654:                            }
1655:                        }
1656:                    } else if (scope instanceof  NativeCall) {
1657:                        // NativeCall does not prototype chain and Scriptable.get
1658:                        // can be called directly.
1659:                        result = scope.get(name, scope);
1660:                        if (result != Scriptable.NOT_FOUND) {
1661:                            if (asFunctionCall) {
1662:                                // ECMA 262 requires that this for nested funtions
1663:                                // should be top scope
1664:                                this Obj = ScriptableObject
1665:                                        .getTopLevelScope(parentScope);
1666:                            }
1667:                            break;
1668:                        }
1669:                    } else {
1670:                        // Can happen if Rhino embedding decided that nested
1671:                        // scopes are useful for what ever reasons.
1672:                        result = ScriptableObject.getProperty(scope, name);
1673:                        if (result != Scriptable.NOT_FOUND) {
1674:                            this Obj = scope;
1675:                            break;
1676:                        }
1677:                    }
1678:                    scope = parentScope;
1679:                    parentScope = parentScope.getParentScope();
1680:                    if (parentScope == null) {
1681:                        result = topScopeName(cx, scope, name);
1682:                        if (result == Scriptable.NOT_FOUND) {
1683:                            if (firstXMLObject == null || asFunctionCall) {
1684:                                throw notFoundError(scope, name);
1685:                            }
1686:                            // The name was not found, but we did find an XML
1687:                            // object in the scope chain and we are looking for name,
1688:                            // not function. The result should be an empty XMLList
1689:                            // in name context.
1690:                            result = firstXMLObject.ecmaGet(cx, name);
1691:                        }
1692:                        // For top scope thisObj for functions is always scope itself.
1693:                        this Obj = scope;
1694:                        break;
1695:                    }
1696:                }
1697:
1698:                if (asFunctionCall) {
1699:                    if (!(result instanceof  Callable)) {
1700:                        throw notFunctionError(result, name);
1701:                    }
1702:                    storeScriptable(cx, this Obj);
1703:                }
1704:
1705:                return result;
1706:            }
1707:
1708:            private static Object topScopeName(Context cx, Scriptable scope,
1709:                    String name) {
1710:                if (cx.useDynamicScope) {
1711:                    scope = checkDynamicScope(cx.topCallScope, scope);
1712:                }
1713:                return ScriptableObject.getProperty(scope, name);
1714:            }
1715:
1716:            /**
1717:             * Returns the object in the scope chain that has a given property.
1718:             *
1719:             * The order of evaluation of an assignment expression involves
1720:             * evaluating the lhs to a reference, evaluating the rhs, and then
1721:             * modifying the reference with the rhs value. This method is used
1722:             * to 'bind' the given name to an object containing that property
1723:             * so that the side effects of evaluating the rhs do not affect
1724:             * which property is modified.
1725:             * Typically used in conjunction with setName.
1726:             *
1727:             * See ECMA 10.1.4
1728:             */
1729:            public static Scriptable bind(Context cx, Scriptable scope,
1730:                    String id) {
1731:                Scriptable firstXMLObject = null;
1732:                Scriptable parent = scope.getParentScope();
1733:                childScopesChecks: if (parent != null) {
1734:                    // Check for possibly nested "with" scopes first
1735:                    while (scope instanceof  NativeWith) {
1736:                        Scriptable withObj = scope.getPrototype();
1737:                        if (withObj instanceof  XMLObject) {
1738:                            XMLObject xmlObject = (XMLObject) withObj;
1739:                            if (xmlObject.ecmaHas(cx, id)) {
1740:                                return xmlObject;
1741:                            }
1742:                            if (firstXMLObject == null) {
1743:                                firstXMLObject = xmlObject;
1744:                            }
1745:                        } else {
1746:                            if (ScriptableObject.hasProperty(withObj, id)) {
1747:                                return withObj;
1748:                            }
1749:                        }
1750:                        scope = parent;
1751:                        parent = parent.getParentScope();
1752:                        if (parent == null) {
1753:                            break childScopesChecks;
1754:                        }
1755:                    }
1756:                    for (;;) {
1757:                        if (ScriptableObject.hasProperty(scope, id)) {
1758:                            return scope;
1759:                        }
1760:                        scope = parent;
1761:                        parent = parent.getParentScope();
1762:                        if (parent == null) {
1763:                            break childScopesChecks;
1764:                        }
1765:                    }
1766:                }
1767:                // scope here is top scope
1768:                if (cx.useDynamicScope) {
1769:                    scope = checkDynamicScope(cx.topCallScope, scope);
1770:                }
1771:                if (ScriptableObject.hasProperty(scope, id)) {
1772:                    return scope;
1773:                }
1774:                // Nothing was found, but since XML objects always bind
1775:                // return one if found
1776:                return firstXMLObject;
1777:            }
1778:
1779:            public static Object setName(Scriptable bound, Object value,
1780:                    Context cx, Scriptable scope, String id) {
1781:                if (bound != null) {
1782:                    if (bound instanceof  XMLObject) {
1783:                        XMLObject xmlObject = (XMLObject) bound;
1784:                        xmlObject.ecmaPut(cx, id, value);
1785:                    } else {
1786:                        ScriptableObject.putProperty(bound, id, value);
1787:                    }
1788:                } else {
1789:                    // "newname = 7;", where 'newname' has not yet
1790:                    // been defined, creates a new property in the
1791:                    // top scope unless strict mode is specified.
1792:                    if (cx.hasFeature(Context.FEATURE_STRICT_MODE)
1793:                            || cx.hasFeature(Context.FEATURE_STRICT_VARS)) {
1794:                        Context.reportWarning(ScriptRuntime.getMessage1(
1795:                                "msg.assn.create.strict", id));
1796:                    }
1797:                    // Find the top scope by walking up the scope chain.
1798:                    bound = ScriptableObject.getTopLevelScope(scope);
1799:                    if (cx.useDynamicScope) {
1800:                        bound = checkDynamicScope(cx.topCallScope, bound);
1801:                    }
1802:                    bound.put(id, bound, value);
1803:                }
1804:                return value;
1805:            }
1806:
1807:            public static Object setConst(Scriptable bound, Object value,
1808:                    Context cx, String id) {
1809:                if (bound instanceof  XMLObject) {
1810:                    XMLObject xmlObject = (XMLObject) bound;
1811:                    xmlObject.ecmaPut(cx, id, value);
1812:                } else {
1813:                    ScriptableObject.putConstProperty(bound, id, value);
1814:                }
1815:                return value;
1816:            }
1817:
1818:            /**
1819:             * This is the enumeration needed by the for..in statement.
1820:             *
1821:             * See ECMA 12.6.3.
1822:             *
1823:             * IdEnumeration maintains a ObjToIntMap to make sure a given
1824:             * id is enumerated only once across multiple objects in a
1825:             * prototype chain.
1826:             *
1827:             * XXX - ECMA delete doesn't hide properties in the prototype,
1828:             * but js/ref does. This means that the js/ref for..in can
1829:             * avoid maintaining a hash table and instead perform lookups
1830:             * to see if a given property has already been enumerated.
1831:             *
1832:             */
1833:            private static class IdEnumeration implements  Serializable {
1834:                private static final long serialVersionUID = 1L;
1835:                Scriptable obj;
1836:                Object[] ids;
1837:                int index;
1838:                ObjToIntMap used;
1839:                Object currentId;
1840:                int enumType; /* one of ENUM_INIT_KEYS, ENUM_INIT_VALUES, 
1841:                                        ENUM_INIT_ARRAY */
1842:
1843:                // if true, integer ids will be returned as numbers rather than strings
1844:                boolean enumNumbers;
1845:
1846:                Scriptable iterator;
1847:            }
1848:
1849:            public static Scriptable toIterator(Context cx, Scriptable scope,
1850:                    Scriptable obj, boolean keyOnly) {
1851:                if (ScriptableObject.hasProperty(obj,
1852:                        NativeIterator.ITERATOR_PROPERTY_NAME)) {
1853:                    Object v = ScriptableObject.getProperty(obj,
1854:                            NativeIterator.ITERATOR_PROPERTY_NAME);
1855:                    if (!(v instanceof  Callable)) {
1856:                        throw typeError0("msg.invalid.iterator");
1857:                    }
1858:                    Callable f = (Callable) v;
1859:                    Object[] args = new Object[] { keyOnly ? Boolean.TRUE
1860:                            : Boolean.FALSE };
1861:                    v = f.call(cx, scope, obj, args);
1862:                    if (!(v instanceof  Scriptable)) {
1863:                        throw typeError0("msg.iterator.primitive");
1864:                    }
1865:                    return (Scriptable) v;
1866:                }
1867:                return null;
1868:            }
1869:
1870:            // for backwards compatibility with generated class files
1871:            public static Object enumInit(Object value, Context cx,
1872:                    boolean enumValues) {
1873:                return enumInit(value, cx, enumValues ? ENUMERATE_VALUES
1874:                        : ENUMERATE_KEYS);
1875:            }
1876:
1877:            public static final int ENUMERATE_KEYS = 0;
1878:            public static final int ENUMERATE_VALUES = 1;
1879:            public static final int ENUMERATE_ARRAY = 2;
1880:            public static final int ENUMERATE_KEYS_NO_ITERATOR = 3;
1881:            public static final int ENUMERATE_VALUES_NO_ITERATOR = 4;
1882:            public static final int ENUMERATE_ARRAY_NO_ITERATOR = 5;
1883:
1884:            public static Object enumInit(Object value, Context cx, int enumType) {
1885:                IdEnumeration x = new IdEnumeration();
1886:                x.obj = toObjectOrNull(cx, value);
1887:                if (x.obj == null) {
1888:                    // null or undefined do not cause errors but rather lead to empty
1889:                    // "for in" loop
1890:                    return x;
1891:                }
1892:                x.enumType = enumType;
1893:                x.iterator = null;
1894:                if (enumType != ENUMERATE_KEYS_NO_ITERATOR
1895:                        && enumType != ENUMERATE_VALUES_NO_ITERATOR
1896:                        && enumType != ENUMERATE_ARRAY_NO_ITERATOR) {
1897:                    x.iterator = toIterator(cx, x.obj.getParentScope(), x.obj,
1898:                            true);
1899:                }
1900:                if (x.iterator == null) {
1901:                    // enumInit should read all initial ids before returning
1902:                    // or "for (a.i in a)" would wrongly enumerate i in a as well
1903:                    enumChangeObject(x);
1904:                }
1905:
1906:                return x;
1907:            }
1908:
1909:            public static void setEnumNumbers(Object enumObj,
1910:                    boolean enumNumbers) {
1911:                ((IdEnumeration) enumObj).enumNumbers = enumNumbers;
1912:            }
1913:
1914:            public static Boolean enumNext(Object enumObj) {
1915:                IdEnumeration x = (IdEnumeration) enumObj;
1916:                if (x.iterator != null) {
1917:                    Object v = ScriptableObject.getProperty(x.iterator, "next");
1918:                    if (!(v instanceof  Callable))
1919:                        return Boolean.FALSE;
1920:                    Callable f = (Callable) v;
1921:                    Context cx = Context.enter();
1922:                    try {
1923:                        x.currentId = f.call(cx, x.iterator.getParentScope(),
1924:                                x.iterator, emptyArgs);
1925:                        return Boolean.TRUE;
1926:                    } catch (JavaScriptException e) {
1927:                        if (e.getValue() instanceof  NativeIterator.StopIteration) {
1928:                            return Boolean.FALSE;
1929:                        }
1930:                        throw e;
1931:                    } finally {
1932:                        Context.exit();
1933:                    }
1934:                }
1935:                for (;;) {
1936:                    if (x.obj == null) {
1937:                        return Boolean.FALSE;
1938:                    }
1939:                    if (x.index == x.ids.length) {
1940:                        x.obj = x.obj.getPrototype();
1941:                        enumChangeObject(x);
1942:                        continue;
1943:                    }
1944:                    Object id = x.ids[x.index++];
1945:                    if (x.used != null && x.used.has(id)) {
1946:                        continue;
1947:                    }
1948:                    if (id instanceof  String) {
1949:                        String strId = (String) id;
1950:                        if (!x.obj.has(strId, x.obj))
1951:                            continue; // must have been deleted
1952:                        x.currentId = strId;
1953:                    } else {
1954:                        int intId = ((Number) id).intValue();
1955:                        if (!x.obj.has(intId, x.obj))
1956:                            continue; // must have been deleted
1957:                        x.currentId = x.enumNumbers ? (Object) (new Integer(
1958:                                intId)) : String.valueOf(intId);
1959:                    }
1960:                    return Boolean.TRUE;
1961:                }
1962:            }
1963:
1964:            public static Object enumId(Object enumObj, Context cx) {
1965:                IdEnumeration x = (IdEnumeration) enumObj;
1966:                if (x.iterator != null) {
1967:                    return x.currentId;
1968:                }
1969:                switch (x.enumType) {
1970:                case ENUMERATE_KEYS:
1971:                case ENUMERATE_KEYS_NO_ITERATOR:
1972:                    return x.currentId;
1973:                case ENUMERATE_VALUES:
1974:                case ENUMERATE_VALUES_NO_ITERATOR:
1975:                    return enumValue(enumObj, cx);
1976:                case ENUMERATE_ARRAY:
1977:                case ENUMERATE_ARRAY_NO_ITERATOR:
1978:                    Object[] elements = { x.currentId, enumValue(enumObj, cx) };
1979:                    return cx.newArray(x.obj.getParentScope(), elements);
1980:                default:
1981:                    throw Kit.codeBug();
1982:                }
1983:            }
1984:
1985:            public static Object enumValue(Object enumObj, Context cx) {
1986:                IdEnumeration x = (IdEnumeration) enumObj;
1987:
1988:                Object result;
1989:
1990:                String s = toStringIdOrIndex(cx, x.currentId);
1991:                if (s == null) {
1992:                    int index = lastIndexResult(cx);
1993:                    result = x.obj.get(index, x.obj);
1994:                } else {
1995:                    result = x.obj.get(s, x.obj);
1996:                }
1997:
1998:                return result;
1999:            }
2000:
2001:            private static void enumChangeObject(IdEnumeration x) {
2002:                Object[] ids = null;
2003:                while (x.obj != null) {
2004:                    ids = x.obj.getIds();
2005:                    if (ids.length != 0) {
2006:                        break;
2007:                    }
2008:                    x.obj = x.obj.getPrototype();
2009:                }
2010:                if (x.obj != null && x.ids != null) {
2011:                    Object[] previous = x.ids;
2012:                    int L = previous.length;
2013:                    if (x.used == null) {
2014:                        x.used = new ObjToIntMap(L);
2015:                    }
2016:                    for (int i = 0; i != L; ++i) {
2017:                        x.used.intern(previous[i]);
2018:                    }
2019:                }
2020:                x.ids = ids;
2021:                x.index = 0;
2022:            }
2023:
2024:            /**
2025:             * Prepare for calling name(...): return function corresponding to
2026:             * name and make current top scope available
2027:             * as ScriptRuntime.lastStoredScriptable() for consumption as thisObj.
2028:             * The caller must call ScriptRuntime.lastStoredScriptable() immediately
2029:             * after calling this method.
2030:             */
2031:            public static Callable getNameFunctionAndThis(String name,
2032:                    Context cx, Scriptable scope) {
2033:                Scriptable parent = scope.getParentScope();
2034:                if (parent == null) {
2035:                    Object result = topScopeName(cx, scope, name);
2036:                    if (!(result instanceof  Callable)) {
2037:                        if (result == Scriptable.NOT_FOUND) {
2038:                            throw notFoundError(scope, name);
2039:                        } else {
2040:                            throw notFunctionError(result, name);
2041:                        }
2042:                    }
2043:                    // Top scope is not NativeWith or NativeCall => thisObj == scope
2044:                    Scriptable this Obj = scope;
2045:                    storeScriptable(cx, this Obj);
2046:                    return (Callable) result;
2047:                }
2048:
2049:                // name will call storeScriptable(cx, thisObj);
2050:                return (Callable) nameOrFunction(cx, scope, parent, name, true);
2051:            }
2052:
2053:            /**
2054:             * Prepare for calling obj[id](...): return function corresponding to
2055:             * obj[id] and make obj properly converted to Scriptable available
2056:             * as ScriptRuntime.lastStoredScriptable() for consumption as thisObj.
2057:             * The caller must call ScriptRuntime.lastStoredScriptable() immediately
2058:             * after calling this method.
2059:             */
2060:            public static Callable getElemFunctionAndThis(Object obj,
2061:                    Object elem, Context cx) {
2062:                String s = toStringIdOrIndex(cx, elem);
2063:                if (s != null) {
2064:                    return getPropFunctionAndThis(obj, s, cx);
2065:                }
2066:                int index = lastIndexResult(cx);
2067:
2068:                Scriptable this Obj = toObjectOrNull(cx, obj);
2069:                if (this Obj == null) {
2070:                    throw undefCallError(obj, String.valueOf(index));
2071:                }
2072:
2073:                Object value;
2074:                for (;;) {
2075:                    // Ignore XML lookup as requred by ECMA 357, 11.2.2.1
2076:                    value = ScriptableObject.getProperty(this Obj, index);
2077:                    if (value != Scriptable.NOT_FOUND) {
2078:                        break;
2079:                    }
2080:                    if (!(this Obj instanceof  XMLObject)) {
2081:                        break;
2082:                    }
2083:                    XMLObject xmlObject = (XMLObject) this Obj;
2084:                    Scriptable extra = xmlObject.getExtraMethodSource(cx);
2085:                    if (extra == null) {
2086:                        break;
2087:                    }
2088:                    this Obj = extra;
2089:                }
2090:                if (!(value instanceof  Callable)) {
2091:                    throw notFunctionError(value, elem);
2092:                }
2093:
2094:                storeScriptable(cx, this Obj);
2095:                return (Callable) value;
2096:            }
2097:
2098:            /**
2099:             * Prepare for calling obj.property(...): return function corresponding to
2100:             * obj.property and make obj properly converted to Scriptable available
2101:             * as ScriptRuntime.lastStoredScriptable() for consumption as thisObj.
2102:             * The caller must call ScriptRuntime.lastStoredScriptable() immediately
2103:             * after calling this method.
2104:             */
2105:            public static Callable getPropFunctionAndThis(Object obj,
2106:                    String property, Context cx) {
2107:                Scriptable this Obj = toObjectOrNull(cx, obj);
2108:                if (this Obj == null) {
2109:                    throw undefCallError(obj, property);
2110:                }
2111:
2112:                Object value;
2113:                for (;;) {
2114:                    // Ignore XML lookup as required by ECMA 357, 11.2.2.1
2115:                    value = ScriptableObject.getProperty(this Obj, property);
2116:                    if (value != Scriptable.NOT_FOUND) {
2117:                        break;
2118:                    }
2119:                    if (!(this Obj instanceof  XMLObject)) {
2120:                        break;
2121:                    }
2122:                    XMLObject xmlObject = (XMLObject) this Obj;
2123:                    Scriptable extra = xmlObject.getExtraMethodSource(cx);
2124:                    if (extra == null) {
2125:                        break;
2126:                    }
2127:                    this Obj = extra;
2128:                }
2129:
2130:                if (!(value instanceof  Callable)) {
2131:                    Object noSuchMethod = ScriptableObject.getProperty(this Obj,
2132:                            "__noSuchMethod__");
2133:                    if (noSuchMethod instanceof  Callable)
2134:                        value = new NoSuchMethodShim((Callable) noSuchMethod,
2135:                                property);
2136:                    else
2137:                        throw notFunctionError(this Obj, value, property);
2138:                }
2139:
2140:                storeScriptable(cx, this Obj);
2141:                return (Callable) value;
2142:            }
2143:
2144:            /**
2145:             * Prepare for calling <expression>(...): return function corresponding to
2146:             * <expression> and make parent scope of the function available
2147:             * as ScriptRuntime.lastStoredScriptable() for consumption as thisObj.
2148:             * The caller must call ScriptRuntime.lastStoredScriptable() immediately
2149:             * after calling this method.
2150:             */
2151:            public static Callable getValueFunctionAndThis(Object value,
2152:                    Context cx) {
2153:                if (!(value instanceof  Callable)) {
2154:                    throw notFunctionError(value);
2155:                }
2156:
2157:                Callable f = (Callable) value;
2158:                Scriptable this Obj = null;
2159:                if (f instanceof  Scriptable) {
2160:                    this Obj = ((Scriptable) f).getParentScope();
2161:                }
2162:                if (this Obj == null) {
2163:                    if (cx.topCallScope == null)
2164:                        throw new IllegalStateException();
2165:                    this Obj = cx.topCallScope;
2166:                }
2167:                if (this Obj.getParentScope() != null) {
2168:                    if (this Obj instanceof  NativeWith) {
2169:                        // functions defined inside with should have with target
2170:                        // as their thisObj
2171:                    } else if (this Obj instanceof  NativeCall) {
2172:                        // nested functions should have top scope as their thisObj
2173:                        this Obj = ScriptableObject.getTopLevelScope(this Obj);
2174:                    }
2175:                }
2176:                storeScriptable(cx, this Obj);
2177:                return f;
2178:            }
2179:
2180:            /**
2181:             * Perform function call in reference context. Should always
2182:             * return value that can be passed to
2183:             * {@link #refGet(Ref, Context)} or {@link #refSet(Ref, Object, Context)}
2184:             * arbitrary number of times.
2185:             * The args array reference should not be stored in any object that is
2186:             * can be GC-reachable after this method returns. If this is necessary,
2187:             * store args.clone(), not args array itself.
2188:             */
2189:            public static Ref callRef(Callable function, Scriptable this Obj,
2190:                    Object[] args, Context cx) {
2191:                if (function instanceof  RefCallable) {
2192:                    RefCallable rfunction = (RefCallable) function;
2193:                    Ref ref = rfunction.refCall(cx, this Obj, args);
2194:                    if (ref == null) {
2195:                        throw new IllegalStateException(rfunction.getClass()
2196:                                .getName()
2197:                                + ".refCall() returned null");
2198:                    }
2199:                    return ref;
2200:                }
2201:                // No runtime support for now
2202:                String msg = getMessage1("msg.no.ref.from.function",
2203:                        toString(function));
2204:                throw constructError("ReferenceError", msg);
2205:            }
2206:
2207:            /**
2208:             * Operator new.
2209:             *
2210:             * See ECMA 11.2.2
2211:             */
2212:            public static Scriptable newObject(Object fun, Context cx,
2213:                    Scriptable scope, Object[] args) {
2214:                if (!(fun instanceof  Function)) {
2215:                    throw notFunctionError(fun);
2216:                }
2217:                Function function = (Function) fun;
2218:                return function.construct(cx, scope, args);
2219:            }
2220:
2221:            public static Object callSpecial(Context cx, Callable fun,
2222:                    Scriptable this Obj, Object[] args, Scriptable scope,
2223:                    Scriptable callerThis, int callType, String filename,
2224:                    int lineNumber) {
2225:                if (callType == Node.SPECIALCALL_EVAL) {
2226:                    if (NativeGlobal.isEvalFunction(fun)) {
2227:                        return evalSpecial(cx, scope, callerThis, args,
2228:                                filename, lineNumber);
2229:                    }
2230:                } else if (callType == Node.SPECIALCALL_WITH) {
2231:                    if (NativeWith.isWithFunction(fun)) {
2232:                        throw Context.reportRuntimeError1("msg.only.from.new",
2233:                                "With");
2234:                    }
2235:                } else {
2236:                    throw Kit.codeBug();
2237:                }
2238:
2239:                return fun.call(cx, scope, this Obj, args);
2240:            }
2241:
2242:            public static Object newSpecial(Context cx, Object fun,
2243:                    Object[] args, Scriptable scope, int callType) {
2244:                if (callType == Node.SPECIALCALL_EVAL) {
2245:                    if (NativeGlobal.isEvalFunction(fun)) {
2246:                        throw typeError1("msg.not.ctor", "eval");
2247:                    }
2248:                } else if (callType == Node.SPECIALCALL_WITH) {
2249:                    if (NativeWith.isWithFunction(fun)) {
2250:                        return NativeWith.newWithSpecial(cx, scope, args);
2251:                    }
2252:                } else {
2253:                    throw Kit.codeBug();
2254:                }
2255:
2256:                return newObject(fun, cx, scope, args);
2257:            }
2258:
2259:            /**
2260:             * Function.prototype.apply and Function.prototype.call
2261:             *
2262:             * See Ecma 15.3.4.[34]
2263:             */
2264:            public static Object applyOrCall(boolean isApply, Context cx,
2265:                    Scriptable scope, Scriptable this Obj, Object[] args) {
2266:                int L = args.length;
2267:                Callable function = getCallable(this Obj);
2268:
2269:                Scriptable callThis = null;
2270:                if (L != 0) {
2271:                    callThis = toObjectOrNull(cx, args[0]);
2272:                }
2273:                if (callThis == null) {
2274:                    // This covers the case of args[0] == (null|undefined) as well.
2275:                    callThis = getTopCallScope(cx);
2276:                }
2277:
2278:                Object[] callArgs;
2279:                if (isApply) {
2280:                    // Follow Ecma 15.3.4.3
2281:                    callArgs = L <= 1 ? ScriptRuntime.emptyArgs
2282:                            : getApplyArguments(cx, args[1]);
2283:                } else {
2284:                    // Follow Ecma 15.3.4.4
2285:                    if (L <= 1) {
2286:                        callArgs = ScriptRuntime.emptyArgs;
2287:                    } else {
2288:                        callArgs = new Object[L - 1];
2289:                        System.arraycopy(args, 1, callArgs, 0, L - 1);
2290:                    }
2291:                }
2292:
2293:                return function.call(cx, scope, callThis, callArgs);
2294:            }
2295:
2296:            static Object[] getApplyArguments(Context cx, Object arg1) {
2297:                if (arg1 == null || arg1 == Undefined.instance) {
2298:                    return ScriptRuntime.emptyArgs;
2299:                } else if (arg1 instanceof  NativeArray
2300:                        || arg1 instanceof  Arguments) {
2301:                    return cx.getElements((Scriptable) arg1);
2302:                } else {
2303:                    throw ScriptRuntime.typeError0("msg.arg.isnt.array");
2304:                }
2305:            }
2306:
2307:            static Callable getCallable(Scriptable this Obj) {
2308:                Callable function;
2309:                if (this Obj instanceof  Callable) {
2310:                    function = (Callable) this Obj;
2311:                } else {
2312:                    Object value = this Obj
2313:                            .getDefaultValue(ScriptRuntime.FunctionClass);
2314:                    if (!(value instanceof  Callable)) {
2315:                        throw ScriptRuntime.notFunctionError(value, this Obj);
2316:                    }
2317:                    function = (Callable) value;
2318:                }
2319:                return function;
2320:            }
2321:
2322:            /**
2323:             * The eval function property of the global object.
2324:             *
2325:             * See ECMA 15.1.2.1
2326:             */
2327:            public static Object evalSpecial(Context cx, Scriptable scope,
2328:                    Object this Arg, Object[] args, String filename,
2329:                    int lineNumber) {
2330:                if (args.length < 1)
2331:                    return Undefined.instance;
2332:                Object x = args[0];
2333:                if (!(x instanceof  String)) {
2334:                    if (cx.hasFeature(Context.FEATURE_STRICT_MODE)
2335:                            || cx.hasFeature(Context.FEATURE_STRICT_EVAL)) {
2336:                        throw Context
2337:                                .reportRuntimeError0("msg.eval.nonstring.strict");
2338:                    }
2339:                    String message = ScriptRuntime
2340:                            .getMessage0("msg.eval.nonstring");
2341:                    Context.reportWarning(message);
2342:                    return x;
2343:                }
2344:                if (filename == null) {
2345:                    int[] linep = new int[1];
2346:                    filename = Context.getSourcePositionFromStack(linep);
2347:                    if (filename != null) {
2348:                        lineNumber = linep[0];
2349:                    } else {
2350:                        filename = "";
2351:                    }
2352:                }
2353:                String sourceName = ScriptRuntime.makeUrlForGeneratedScript(
2354:                        true, filename, lineNumber);
2355:
2356:                ErrorReporter reporter;
2357:                reporter = DefaultErrorReporter.forEval(cx.getErrorReporter());
2358:
2359:                Evaluator evaluator = Context.createInterpreter();
2360:                if (evaluator == null) {
2361:                    throw new JavaScriptException("Interpreter not present",
2362:                            filename, lineNumber);
2363:                }
2364:
2365:                // Compile with explicit interpreter instance to force interpreter
2366:                // mode.
2367:                Script script = cx.compileString((String) x, evaluator,
2368:                        reporter, sourceName, 1, null);
2369:                evaluator.setEvalScriptFlag(script);
2370:                Callable c = (Callable) script;
2371:                return c.call(cx, scope, (Scriptable) this Arg,
2372:                        ScriptRuntime.emptyArgs);
2373:            }
2374:
2375:            /**
2376:             * The typeof operator
2377:             */
2378:            public static String typeof(Object value) {
2379:                if (value == null)
2380:                    return "object";
2381:                if (value == Undefined.instance)
2382:                    return "undefined";
2383:                if (value instanceof  Scriptable) {
2384:                    if (value instanceof  ScriptableObject
2385:                            && ((ScriptableObject) value)
2386:                                    .avoidObjectDetection()) {
2387:                        return "undefined";
2388:                    }
2389:                    if (value instanceof  XMLObject)
2390:                        return "xml";
2391:                    return (value instanceof  Callable) ? "function" : "object";
2392:                }
2393:                if (value instanceof  String)
2394:                    return "string";
2395:                if (value instanceof  Number)
2396:                    return "number";
2397:                if (value instanceof  Boolean)
2398:                    return "boolean";
2399:                throw errorWithClassName("msg.invalid.type", value);
2400:            }
2401:
2402:            /**
2403:             * The typeof operator that correctly handles the undefined case
2404:             */
2405:            public static String typeofName(Scriptable scope, String id) {
2406:                Context cx = Context.getContext();
2407:                Scriptable val = bind(cx, scope, id);
2408:                if (val == null)
2409:                    return "undefined";
2410:                return typeof(getObjectProp(val, id, cx));
2411:            }
2412:
2413:            // neg:
2414:            // implement the '-' operator inline in the caller
2415:            // as "-toNumber(val)"
2416:
2417:            // not:
2418:            // implement the '!' operator inline in the caller
2419:            // as "!toBoolean(val)"
2420:
2421:            // bitnot:
2422:            // implement the '~' operator inline in the caller
2423:            // as "~toInt32(val)"
2424:
2425:            public static Object add(Object val1, Object val2, Context cx) {
2426:                if (val1 instanceof  Number && val2 instanceof  Number) {
2427:                    return wrapNumber(((Number) val1).doubleValue()
2428:                            + ((Number) val2).doubleValue());
2429:                }
2430:                if (val1 instanceof  XMLObject) {
2431:                    Object test = ((XMLObject) val1).addValues(cx, true, val2);
2432:                    if (test != Scriptable.NOT_FOUND) {
2433:                        return test;
2434:                    }
2435:                }
2436:                if (val2 instanceof  XMLObject) {
2437:                    Object test = ((XMLObject) val2).addValues(cx, false, val1);
2438:                    if (test != Scriptable.NOT_FOUND) {
2439:                        return test;
2440:                    }
2441:                }
2442:                if (val1 instanceof  Scriptable)
2443:                    val1 = ((Scriptable) val1).getDefaultValue(null);
2444:                if (val2 instanceof  Scriptable)
2445:                    val2 = ((Scriptable) val2).getDefaultValue(null);
2446:                if (!(val1 instanceof  String) && !(val2 instanceof  String))
2447:                    if ((val1 instanceof  Number) && (val2 instanceof  Number))
2448:                        return wrapNumber(((Number) val1).doubleValue()
2449:                                + ((Number) val2).doubleValue());
2450:                    else
2451:                        return wrapNumber(toNumber(val1) + toNumber(val2));
2452:                return toString(val1).concat(toString(val2));
2453:            }
2454:
2455:            public static String add(String val1, Object val2) {
2456:                return val1.concat(toString(val2));
2457:            }
2458:
2459:            public static String add(Object val1, String val2) {
2460:                return toString(val1).concat(val2);
2461:            }
2462:
2463:            /**
2464:             * @deprecated The method is only present for compatibility.
2465:             */
2466:            public static Object nameIncrDecr(Scriptable scopeChain, String id,
2467:                    int incrDecrMask) {
2468:                return nameIncrDecr(scopeChain, id, Context.getContext(),
2469:                        incrDecrMask);
2470:            }
2471:
2472:            public static Object nameIncrDecr(Scriptable scopeChain, String id,
2473:                    Context cx, int incrDecrMask) {
2474:                Scriptable target;
2475:                Object value;
2476:                search: {
2477:                    do {
2478:                        if (cx.useDynamicScope
2479:                                && scopeChain.getParentScope() == null) {
2480:                            scopeChain = checkDynamicScope(cx.topCallScope,
2481:                                    scopeChain);
2482:                        }
2483:                        target = scopeChain;
2484:                        do {
2485:                            value = target.get(id, scopeChain);
2486:                            if (value != Scriptable.NOT_FOUND) {
2487:                                break search;
2488:                            }
2489:                            target = target.getPrototype();
2490:                        } while (target != null);
2491:                        scopeChain = scopeChain.getParentScope();
2492:                    } while (scopeChain != null);
2493:                    throw notFoundError(scopeChain, id);
2494:                }
2495:                return doScriptableIncrDecr(target, id, scopeChain, value,
2496:                        incrDecrMask);
2497:            }
2498:
2499:            public static Object propIncrDecr(Object obj, String id,
2500:                    Context cx, int incrDecrMask) {
2501:                Scriptable start = toObjectOrNull(cx, obj);
2502:                if (start == null) {
2503:                    throw undefReadError(obj, id);
2504:                }
2505:
2506:                Scriptable target = start;
2507:                Object value;
2508:                search: {
2509:                    do {
2510:                        value = target.get(id, start);
2511:                        if (value != Scriptable.NOT_FOUND) {
2512:                            break search;
2513:                        }
2514:                        target = target.getPrototype();
2515:                    } while (target != null);
2516:                    start.put(id, start, NaNobj);
2517:                    return NaNobj;
2518:                }
2519:                return doScriptableIncrDecr(target, id, start, value,
2520:                        incrDecrMask);
2521:            }
2522:
2523:            private static Object doScriptableIncrDecr(Scriptable target,
2524:                    String id, Scriptable protoChainStart, Object value,
2525:                    int incrDecrMask) {
2526:                boolean post = ((incrDecrMask & Node.POST_FLAG) != 0);
2527:                double number;
2528:                if (value instanceof  Number) {
2529:                    number = ((Number) value).doubleValue();
2530:                } else {
2531:                    number = toNumber(value);
2532:                    if (post) {
2533:                        // convert result to number
2534:                        value = wrapNumber(number);
2535:                    }
2536:                }
2537:                if ((incrDecrMask & Node.DECR_FLAG) == 0) {
2538:                    ++number;
2539:                } else {
2540:                    --number;
2541:                }
2542:                Number result = wrapNumber(number);
2543:                target.put(id, protoChainStart, result);
2544:                if (post) {
2545:                    return value;
2546:                } else {
2547:                    return result;
2548:                }
2549:            }
2550:
2551:            public static Object elemIncrDecr(Object obj, Object index,
2552:                    Context cx, int incrDecrMask) {
2553:                Object value = getObjectElem(obj, index, cx);
2554:                boolean post = ((incrDecrMask & Node.POST_FLAG) != 0);
2555:                double number;
2556:                if (value instanceof  Number) {
2557:                    number = ((Number) value).doubleValue();
2558:                } else {
2559:                    number = toNumber(value);
2560:                    if (post) {
2561:                        // convert result to number
2562:                        value = wrapNumber(number);
2563:                    }
2564:                }
2565:                if ((incrDecrMask & Node.DECR_FLAG) == 0) {
2566:                    ++number;
2567:                } else {
2568:                    --number;
2569:                }
2570:                Number result = wrapNumber(number);
2571:                setObjectElem(obj, index, result, cx);
2572:                if (post) {
2573:                    return value;
2574:                } else {
2575:                    return result;
2576:                }
2577:            }
2578:
2579:            public static Object refIncrDecr(Ref ref, Context cx,
2580:                    int incrDecrMask) {
2581:                Object value = ref.get(cx);
2582:                boolean post = ((incrDecrMask & Node.POST_FLAG) != 0);
2583:                double number;
2584:                if (value instanceof  Number) {
2585:                    number = ((Number) value).doubleValue();
2586:                } else {
2587:                    number = toNumber(value);
2588:                    if (post) {
2589:                        // convert result to number
2590:                        value = wrapNumber(number);
2591:                    }
2592:                }
2593:                if ((incrDecrMask & Node.DECR_FLAG) == 0) {
2594:                    ++number;
2595:                } else {
2596:                    --number;
2597:                }
2598:                Number result = wrapNumber(number);
2599:                ref.set(cx, result);
2600:                if (post) {
2601:                    return value;
2602:                } else {
2603:                    return result;
2604:                }
2605:            }
2606:
2607:            private static Object toPrimitive(Object val) {
2608:                if (!(val instanceof  Scriptable)) {
2609:                    return val;
2610:                }
2611:                Scriptable s = (Scriptable) val;
2612:                Object result = s.getDefaultValue(null);
2613:                if (result instanceof  Scriptable)
2614:                    throw typeError0("msg.bad.default.value");
2615:                return result;
2616:            }
2617:
2618:            /**
2619:             * Equality
2620:             *
2621:             * See ECMA 11.9
2622:             */
2623:            public static boolean eq(Object x, Object y) {
2624:                if (x == null || x == Undefined.instance) {
2625:                    if (y == null || y == Undefined.instance) {
2626:                        return true;
2627:                    }
2628:                    if (y instanceof  ScriptableObject) {
2629:                        Object test = ((ScriptableObject) y)
2630:                                .equivalentValues(x);
2631:                        if (test != Scriptable.NOT_FOUND) {
2632:                            return ((Boolean) test).booleanValue();
2633:                        }
2634:                    }
2635:                    return false;
2636:                } else if (x instanceof  Number) {
2637:                    return eqNumber(((Number) x).doubleValue(), y);
2638:                } else if (x instanceof  String) {
2639:                    return eqString((String) x, y);
2640:                } else if (x instanceof  Boolean) {
2641:                    boolean b = ((Boolean) x).booleanValue();
2642:                    if (y instanceof  Boolean) {
2643:                        return b == ((Boolean) y).booleanValue();
2644:                    }
2645:                    if (y instanceof  ScriptableObject) {
2646:                        Object test = ((ScriptableObject) y)
2647:                                .equivalentValues(x);
2648:                        if (test != Scriptable.NOT_FOUND) {
2649:                            return ((Boolean) test).booleanValue();
2650:                        }
2651:                    }
2652:                    return eqNumber(b ? 1.0 : 0.0, y);
2653:                } else if (x instanceof  Scriptable) {
2654:                    if (y instanceof  Scriptable) {
2655:                        if (x == y) {
2656:                            return true;
2657:                        }
2658:                        if (x instanceof  ScriptableObject) {
2659:                            Object test = ((ScriptableObject) x)
2660:                                    .equivalentValues(y);
2661:                            if (test != Scriptable.NOT_FOUND) {
2662:                                return ((Boolean) test).booleanValue();
2663:                            }
2664:                        }
2665:                        if (y instanceof  ScriptableObject) {
2666:                            Object test = ((ScriptableObject) y)
2667:                                    .equivalentValues(x);
2668:                            if (test != Scriptable.NOT_FOUND) {
2669:                                return ((Boolean) test).booleanValue();
2670:                            }
2671:                        }
2672:                        if (x instanceof  Wrapper && y instanceof  Wrapper) {
2673:                            // See bug 413838. Effectively an extension to ECMA for
2674:                            // the LiveConnect case.
2675:                            Object unwrappedX = ((Wrapper) x).unwrap();
2676:                            Object unwrappedY = ((Wrapper) y).unwrap();
2677:                            return unwrappedX == unwrappedY
2678:                                    || (isPrimitive(unwrappedX)
2679:                                            && isPrimitive(unwrappedY) && eq(
2680:                                            unwrappedX, unwrappedY));
2681:                        }
2682:                        return false;
2683:                    } else if (y instanceof  Boolean) {
2684:                        if (x instanceof  ScriptableObject) {
2685:                            Object test = ((ScriptableObject) x)
2686:                                    .equivalentValues(y);
2687:                            if (test != Scriptable.NOT_FOUND) {
2688:                                return ((Boolean) test).booleanValue();
2689:                            }
2690:                        }
2691:                        double d = ((Boolean) y).booleanValue() ? 1.0 : 0.0;
2692:                        return eqNumber(d, x);
2693:                    } else if (y instanceof  Number) {
2694:                        return eqNumber(((Number) y).doubleValue(), x);
2695:                    } else if (y instanceof  String) {
2696:                        return eqString((String) y, x);
2697:                    }
2698:                    // covers the case when y == Undefined.instance as well
2699:                    return false;
2700:                } else {
2701:                    warnAboutNonJSObject(x);
2702:                    return x == y;
2703:                }
2704:            }
2705:
2706:            private static boolean isPrimitive(Object obj) {
2707:                return (obj instanceof  Number) || (obj instanceof  String)
2708:                        || (obj instanceof  Boolean);
2709:            }
2710:
2711:            static boolean eqNumber(double x, Object y) {
2712:                for (;;) {
2713:                    if (y == null || y == Undefined.instance) {
2714:                        return false;
2715:                    } else if (y instanceof  Number) {
2716:                        return x == ((Number) y).doubleValue();
2717:                    } else if (y instanceof  String) {
2718:                        return x == toNumber(y);
2719:                    } else if (y instanceof  Boolean) {
2720:                        return x == (((Boolean) y).booleanValue() ? 1.0 : +0.0);
2721:                    } else if (y instanceof  Scriptable) {
2722:                        if (y instanceof  ScriptableObject) {
2723:                            Object xval = wrapNumber(x);
2724:                            Object test = ((ScriptableObject) y)
2725:                                    .equivalentValues(xval);
2726:                            if (test != Scriptable.NOT_FOUND) {
2727:                                return ((Boolean) test).booleanValue();
2728:                            }
2729:                        }
2730:                        y = toPrimitive(y);
2731:                    } else {
2732:                        warnAboutNonJSObject(y);
2733:                        return false;
2734:                    }
2735:                }
2736:            }
2737:
2738:            private static boolean eqString(String x, Object y) {
2739:                for (;;) {
2740:                    if (y == null || y == Undefined.instance) {
2741:                        return false;
2742:                    } else if (y instanceof  String) {
2743:                        return x.equals(y);
2744:                    } else if (y instanceof  Number) {
2745:                        return toNumber(x) == ((Number) y).doubleValue();
2746:                    } else if (y instanceof  Boolean) {
2747:                        return toNumber(x) == (((Boolean) y).booleanValue() ? 1.0
2748:                                : 0.0);
2749:                    } else if (y instanceof  Scriptable) {
2750:                        if (y instanceof  ScriptableObject) {
2751:                            Object test = ((ScriptableObject) y)
2752:                                    .equivalentValues(x);
2753:                            if (test != Scriptable.NOT_FOUND) {
2754:                                return ((Boolean) test).booleanValue();
2755:                            }
2756:                        }
2757:                        y = toPrimitive(y);
2758:                        continue;
2759:                    } else {
2760:                        warnAboutNonJSObject(y);
2761:                        return false;
2762:                    }
2763:                }
2764:            }
2765:
2766:            public static boolean shallowEq(Object x, Object y) {
2767:                if (x == y) {
2768:                    if (!(x instanceof  Number)) {
2769:                        return true;
2770:                    }
2771:                    // NaN check
2772:                    double d = ((Number) x).doubleValue();
2773:                    return d == d;
2774:                }
2775:                if (x == null || x == Undefined.instance) {
2776:                    return false;
2777:                } else if (x instanceof  Number) {
2778:                    if (y instanceof  Number) {
2779:                        return ((Number) x).doubleValue() == ((Number) y)
2780:                                .doubleValue();
2781:                    }
2782:                } else if (x instanceof  String) {
2783:                    if (y instanceof  String) {
2784:                        return x.equals(y);
2785:                    }
2786:                } else if (x instanceof  Boolean) {
2787:                    if (y instanceof  Boolean) {
2788:                        return x.equals(y);
2789:                    }
2790:                } else if (x instanceof  Scriptable) {
2791:                    if (x instanceof  Wrapper && y instanceof  Wrapper) {
2792:                        return ((Wrapper) x).unwrap() == ((Wrapper) y).unwrap();
2793:                    }
2794:                } else {
2795:                    warnAboutNonJSObject(x);
2796:                    return x == y;
2797:                }
2798:                return false;
2799:            }
2800:
2801:            /**
2802:             * The instanceof operator.
2803:             *
2804:             * @return a instanceof b
2805:             */
2806:            public static boolean instanceOf(Object a, Object b, Context cx) {
2807:                // Check RHS is an object
2808:                if (!(b instanceof  Scriptable)) {
2809:                    throw typeError0("msg.instanceof.not.object");
2810:                }
2811:
2812:                // for primitive values on LHS, return false
2813:                // XXX we may want to change this so that
2814:                // 5 instanceof Number == true
2815:                if (!(a instanceof  Scriptable))
2816:                    return false;
2817:
2818:                return ((Scriptable) b).hasInstance((Scriptable) a);
2819:            }
2820:
2821:            /**
2822:             * Delegates to
2823:             *
2824:             * @return true iff rhs appears in lhs' proto chain
2825:             */
2826:            public static boolean jsDelegatesTo(Scriptable lhs, Scriptable rhs) {
2827:                Scriptable proto = lhs.getPrototype();
2828:
2829:                while (proto != null) {
2830:                    if (proto.equals(rhs))
2831:                        return true;
2832:                    proto = proto.getPrototype();
2833:                }
2834:
2835:                return false;
2836:            }
2837:
2838:            /**
2839:             * The in operator.
2840:             *
2841:             * This is a new JS 1.3 language feature.  The in operator mirrors
2842:             * the operation of the for .. in construct, and tests whether the
2843:             * rhs has the property given by the lhs.  It is different from the
2844:             * for .. in construct in that:
2845:             * <BR> - it doesn't perform ToObject on the right hand side
2846:             * <BR> - it returns true for DontEnum properties.
2847:             * @param a the left hand operand
2848:             * @param b the right hand operand
2849:             *
2850:             * @return true if property name or element number a is a property of b
2851:             */
2852:            public static boolean in(Object a, Object b, Context cx) {
2853:                if (!(b instanceof  Scriptable)) {
2854:                    throw typeError0("msg.instanceof.not.object");
2855:                }
2856:
2857:                return hasObjectElem((Scriptable) b, a, cx);
2858:            }
2859:
2860:            public static boolean cmp_LT(Object val1, Object val2) {
2861:                double d1, d2;
2862:                if (val1 instanceof  Number && val2 instanceof  Number) {
2863:                    d1 = ((Number) val1).doubleValue();
2864:                    d2 = ((Number) val2).doubleValue();
2865:                } else {
2866:                    if (val1 instanceof  Scriptable)
2867:                        val1 = ((Scriptable) val1).getDefaultValue(NumberClass);
2868:                    if (val2 instanceof  Scriptable)
2869:                        val2 = ((Scriptable) val2).getDefaultValue(NumberClass);
2870:                    if (val1 instanceof  String && val2 instanceof  String) {
2871:                        return ((String) val1).compareTo((String) val2) < 0;
2872:                    }
2873:                    d1 = toNumber(val1);
2874:                    d2 = toNumber(val2);
2875:                }
2876:                return d1 < d2;
2877:            }
2878:
2879:            public static boolean cmp_LE(Object val1, Object val2) {
2880:                double d1, d2;
2881:                if (val1 instanceof  Number && val2 instanceof  Number) {
2882:                    d1 = ((Number) val1).doubleValue();
2883:                    d2 = ((Number) val2).doubleValue();
2884:                } else {
2885:                    if (val1 instanceof  Scriptable)
2886:                        val1 = ((Scriptable) val1).getDefaultValue(NumberClass);
2887:                    if (val2 instanceof  Scriptable)
2888:                        val2 = ((Scriptable) val2).getDefaultValue(NumberClass);
2889:                    if (val1 instanceof  String && val2 instanceof  String) {
2890:                        return ((String) val1).compareTo((String) val2) <= 0;
2891:                    }
2892:                    d1 = toNumber(val1);
2893:                    d2 = toNumber(val2);
2894:                }
2895:                return d1 <= d2;
2896:            }
2897:
2898:            // ------------------
2899:            // Statements
2900:            // ------------------
2901:
2902:            public static ScriptableObject getGlobal(Context cx) {
2903:                final String GLOBAL_CLASS = "org.mozilla.javascript.tools.shell.Global";
2904:                Class globalClass = Kit.classOrNull(GLOBAL_CLASS);
2905:                if (globalClass != null) {
2906:                    try {
2907:                        Class[] parm = { ScriptRuntime.ContextClass };
2908:                        Constructor globalClassCtor = globalClass
2909:                                .getConstructor(parm);
2910:                        Object[] arg = { cx };
2911:                        return (ScriptableObject) globalClassCtor
2912:                                .newInstance(arg);
2913:                    } catch (Exception e) {
2914:                        // fall through...
2915:                    }
2916:                }
2917:                return new ImporterTopLevel(cx);
2918:            }
2919:
2920:            public static boolean hasTopCall(Context cx) {
2921:                return (cx.topCallScope != null);
2922:            }
2923:
2924:            public static Scriptable getTopCallScope(Context cx) {
2925:                Scriptable scope = cx.topCallScope;
2926:                if (scope == null) {
2927:                    throw new IllegalStateException();
2928:                }
2929:                return scope;
2930:            }
2931:
2932:            public static Object doTopCall(Callable callable, Context cx,
2933:                    Scriptable scope, Scriptable this Obj, Object[] args) {
2934:                if (scope == null)
2935:                    throw new IllegalArgumentException();
2936:                if (cx.topCallScope != null)
2937:                    throw new IllegalStateException();
2938:
2939:                Object result;
2940:                cx.topCallScope = ScriptableObject.getTopLevelScope(scope);
2941:                cx.useDynamicScope = cx
2942:                        .hasFeature(Context.FEATURE_DYNAMIC_SCOPE);
2943:                ContextFactory f = cx.getFactory();
2944:                try {
2945:                    result = f.doTopCall(callable, cx, scope, this Obj, args);
2946:                } finally {
2947:                    cx.topCallScope = null;
2948:                    // Cleanup cached references
2949:                    cx.cachedXMLLib = null;
2950:
2951:                    if (cx.currentActivationCall != null) {
2952:                        // Function should always call exitActivationFunction
2953:                        // if it creates activation record
2954:                        throw new IllegalStateException();
2955:                    }
2956:                }
2957:                return result;
2958:            }
2959:
2960:            /**
2961:             * Return <tt>possibleDynamicScope</tt> if <tt>staticTopScope</tt>
2962:             * is present on its prototype chain and return <tt>staticTopScope</tt>
2963:             * otherwise.
2964:             * Should only be called when <tt>staticTopScope</tt> is top scope.
2965:             */
2966:            static Scriptable checkDynamicScope(
2967:                    Scriptable possibleDynamicScope, Scriptable staticTopScope) {
2968:                // Return cx.topCallScope if scope
2969:                if (possibleDynamicScope == staticTopScope) {
2970:                    return possibleDynamicScope;
2971:                }
2972:                Scriptable proto = possibleDynamicScope;
2973:                for (;;) {
2974:                    proto = proto.getPrototype();
2975:                    if (proto == staticTopScope) {
2976:                        return possibleDynamicScope;
2977:                    }
2978:                    if (proto == null) {
2979:                        return staticTopScope;
2980:                    }
2981:                }
2982:            }
2983:
2984:            public static void addInstructionCount(Context cx,
2985:                    int instructionsToAdd) {
2986:                cx.instructionCount += instructionsToAdd;
2987:                if (cx.instructionCount > cx.instructionThreshold) {
2988:                    cx.observeInstructionCount(cx.instructionCount);
2989:                    cx.instructionCount = 0;
2990:                }
2991:            }
2992:
2993:            public static void initScript(NativeFunction funObj,
2994:                    Scriptable this Obj, Context cx, Scriptable scope,
2995:                    boolean evalScript) {
2996:                if (cx.topCallScope == null)
2997:                    throw new IllegalStateException();
2998:
2999:                int varCount = funObj.getParamAndVarCount();
3000:                if (varCount != 0) {
3001:
3002:                    Scriptable varScope = scope;
3003:                    // Never define any variables from var statements inside with
3004:                    // object. See bug 38590.
3005:                    while (varScope instanceof  NativeWith) {
3006:                        varScope = varScope.getParentScope();
3007:                    }
3008:
3009:                    for (int i = varCount; i-- != 0;) {
3010:                        String name = funObj.getParamOrVarName(i);
3011:                        boolean isConst = funObj.getParamOrVarConst(i);
3012:                        // Don't overwrite existing def if already defined in object
3013:                        // or prototypes of object.
3014:                        if (!ScriptableObject.hasProperty(scope, name)) {
3015:                            if (!evalScript) {
3016:                                // Global var definitions are supposed to be DONTDELETE
3017:                                if (isConst)
3018:                                    ScriptableObject.defineConstProperty(
3019:                                            varScope, name);
3020:                                else
3021:                                    ScriptableObject.defineProperty(varScope,
3022:                                            name, Undefined.instance,
3023:                                            ScriptableObject.PERMANENT);
3024:                            } else {
3025:                                varScope
3026:                                        .put(name, varScope, Undefined.instance);
3027:                            }
3028:                        } else {
3029:                            ScriptableObject.redefineProperty(scope, name,
3030:                                    isConst);
3031:                        }
3032:                    }
3033:                }
3034:            }
3035:
3036:            public static Scriptable createFunctionActivation(
3037:                    NativeFunction funObj, Scriptable scope, Object[] args) {
3038:                return new NativeCall(funObj, scope, args);
3039:            }
3040:
3041:            public static void enterActivationFunction(Context cx,
3042:                    Scriptable scope) {
3043:                if (cx.topCallScope == null)
3044:                    throw new IllegalStateException();
3045:                NativeCall call = (NativeCall) scope;
3046:                call.parentActivationCall = cx.currentActivationCall;
3047:                cx.currentActivationCall = call;
3048:            }
3049:
3050:            public static void exitActivationFunction(Context cx) {
3051:                NativeCall call = cx.currentActivationCall;
3052:                cx.currentActivationCall = call.parentActivationCall;
3053:                call.parentActivationCall = null;
3054:            }
3055:
3056:            static NativeCall findFunctionActivation(Context cx, Function f) {
3057:                NativeCall call = cx.currentActivationCall;
3058:                while (call != null) {
3059:                    if (call.function == f)
3060:                        return call;
3061:                    call = call.parentActivationCall;
3062:                }
3063:                return null;
3064:            }
3065:
3066:            public static Scriptable newCatchScope(Throwable t,
3067:                    Scriptable lastCatchScope, String exceptionName,
3068:                    Context cx, Scriptable scope) {
3069:                Object obj;
3070:                boolean cacheObj;
3071:
3072:                getObj: if (t instanceof  JavaScriptException) {
3073:                    cacheObj = false;
3074:                    obj = ((JavaScriptException) t).getValue();
3075:                } else {
3076:                    cacheObj = true;
3077:
3078:                    // Create wrapper object unless it was associated with
3079:                    // the previous scope object
3080:
3081:                    if (lastCatchScope != null) {
3082:                        NativeObject last = (NativeObject) lastCatchScope;
3083:                        obj = last.getAssociatedValue(t);
3084:                        if (obj == null)
3085:                            Kit.codeBug();
3086:                        break getObj;
3087:                    }
3088:
3089:                    RhinoException re;
3090:                    String errorName;
3091:                    String errorMsg;
3092:                    Throwable javaException = null;
3093:
3094:                    if (t instanceof  EcmaError) {
3095:                        EcmaError ee = (EcmaError) t;
3096:                        re = ee;
3097:                        errorName = ee.getName();
3098:                        errorMsg = ee.getErrorMessage();
3099:                    } else if (t instanceof  WrappedException) {
3100:                        WrappedException we = (WrappedException) t;
3101:                        re = we;
3102:                        javaException = we.getWrappedException();
3103:                        errorName = "JavaException";
3104:                        errorMsg = javaException.getClass().getName() + ": "
3105:                                + javaException.getMessage();
3106:                    } else if (t instanceof  EvaluatorException) {
3107:                        // Pure evaluator exception, nor WrappedException instance
3108:                        EvaluatorException ee = (EvaluatorException) t;
3109:                        re = ee;
3110:                        errorName = "InternalError";
3111:                        errorMsg = ee.getMessage();
3112:                    } else if (cx
3113:                            .hasFeature(Context.FEATURE_ENHANCED_JAVA_ACCESS)) {
3114:                        // With FEATURE_ENHANCED_JAVA_ACCESS, scripts can catch
3115:                        // all exception types
3116:                        re = new WrappedException(t);
3117:                        errorName = "JavaException";
3118:                        errorMsg = t.toString();
3119:                    } else {
3120:                        // Script can catch only instances of JavaScriptException,
3121:                        // EcmaError and EvaluatorException
3122:                        throw Kit.codeBug();
3123:                    }
3124:
3125:                    String sourceUri = re.sourceName();
3126:                    if (sourceUri == null) {
3127:                        sourceUri = "";
3128:                    }
3129:                    int line = re.lineNumber();
3130:                    Object args[];
3131:                    if (line > 0) {
3132:                        args = new Object[] { errorMsg, sourceUri,
3133:                                new Integer(line) };
3134:                    } else {
3135:                        args = new Object[] { errorMsg, sourceUri };
3136:                    }
3137:
3138:                    Scriptable errorObject = cx.newObject(scope, errorName,
3139:                            args);
3140:                    ScriptableObject
3141:                            .putProperty(errorObject, "name", errorName);
3142:
3143:                    if (javaException != null) {
3144:                        Object wrap = cx.getWrapFactory().wrap(cx, scope,
3145:                                javaException, null);
3146:                        ScriptableObject.defineProperty(errorObject,
3147:                                "javaException", wrap,
3148:                                ScriptableObject.PERMANENT
3149:                                        | ScriptableObject.READONLY);
3150:                    }
3151:                    Object wrap = cx.getWrapFactory().wrap(cx, scope, re, null);
3152:                    ScriptableObject.defineProperty(errorObject,
3153:                            "rhinoException", wrap, ScriptableObject.PERMANENT
3154:                                    | ScriptableObject.READONLY);
3155:
3156:                    obj = errorObject;
3157:                }
3158:
3159:                NativeObject catchScopeObject = new NativeObject();
3160:                // See ECMA 12.4
3161:                catchScopeObject.defineProperty(exceptionName, obj,
3162:                        ScriptableObject.PERMANENT);
3163:
3164:                // Add special Rhino object __exception__ defined in the catch
3165:                // scope that can be used to retrieve the Java exception associated
3166:                // with the JavaScript exception (to get stack trace info, etc.)
3167:                catchScopeObject.defineProperty("__exception__", Context
3168:                        .javaToJS(t, scope), ScriptableObject.PERMANENT
3169:                        | ScriptableObject.DONTENUM);
3170:
3171:                if (cacheObj) {
3172:                    catchScopeObject.associateValue(t, obj);
3173:                }
3174:                return catchScopeObject;
3175:            }
3176:
3177:            public static Scriptable enterWith(Object obj, Context cx,
3178:                    Scriptable scope) {
3179:                Scriptable sobj = toObjectOrNull(cx, obj);
3180:                if (sobj == null) {
3181:                    throw typeError1("msg.undef.with", toString(obj));
3182:                }
3183:                if (sobj instanceof  XMLObject) {
3184:                    XMLObject xmlObject = (XMLObject) sobj;
3185:                    return xmlObject.enterWith(scope);
3186:                }
3187:                return new NativeWith(scope, sobj);
3188:            }
3189:
3190:            public static Scriptable leaveWith(Scriptable scope) {
3191:                NativeWith nw = (NativeWith) scope;
3192:                return nw.getParentScope();
3193:            }
3194:
3195:            public static Scriptable enterDotQuery(Object value,
3196:                    Scriptable scope) {
3197:                if (!(value instanceof  XMLObject)) {
3198:                    throw notXmlError(value);
3199:                }
3200:                XMLObject object = (XMLObject) value;
3201:                return object.enterDotQuery(scope);
3202:            }
3203:
3204:            public static Object updateDotQuery(boolean value, Scriptable scope) {
3205:                // Return null to continue looping
3206:                NativeWith nw = (NativeWith) scope;
3207:                return nw.updateDotQuery(value);
3208:            }
3209:
3210:            public static Scriptable leaveDotQuery(Scriptable scope) {
3211:                NativeWith nw = (NativeWith) scope;
3212:                return nw.getParentScope();
3213:            }
3214:
3215:            public static void setFunctionProtoAndParent(BaseFunction fn,
3216:                    Scriptable scope) {
3217:                fn.setParentScope(scope);
3218:                fn.setPrototype(ScriptableObject.getFunctionPrototype(scope));
3219:            }
3220:
3221:            public static void setObjectProtoAndParent(ScriptableObject object,
3222:                    Scriptable scope) {
3223:                // Compared with function it always sets the scope to top scope
3224:                scope = ScriptableObject.getTopLevelScope(scope);
3225:                object.setParentScope(scope);
3226:                Scriptable proto = ScriptableObject.getClassPrototype(scope,
3227:                        object.getClassName());
3228:                object.setPrototype(proto);
3229:            }
3230:
3231:            public static void initFunction(Context cx, Scriptable scope,
3232:                    NativeFunction function, int type, boolean fromEvalCode) {
3233:                if (type == FunctionNode.FUNCTION_STATEMENT) {
3234:                    String name = function.getFunctionName();
3235:                    if (name != null && name.length() != 0) {
3236:                        if (!fromEvalCode) {
3237:                            // ECMA specifies that functions defined in global and
3238:                            // function scope outside eval should have DONTDELETE set.
3239:                            ScriptableObject.defineProperty(scope, name,
3240:                                    function, ScriptableObject.PERMANENT);
3241:                        } else {
3242:                            scope.put(name, scope, function);
3243:                        }
3244:                    }
3245:                } else if (type == FunctionNode.FUNCTION_EXPRESSION_STATEMENT) {
3246:                    String name = function.getFunctionName();
3247:                    if (name != null && name.length() != 0) {
3248:                        // Always put function expression statements into initial
3249:                        // activation object ignoring the with statement to follow
3250:                        // SpiderMonkey
3251:                        while (scope instanceof  NativeWith) {
3252:                            scope = scope.getParentScope();
3253:                        }
3254:                        scope.put(name, scope, function);
3255:                    }
3256:                } else {
3257:                    throw Kit.codeBug();
3258:                }
3259:            }
3260:
3261:            public static Scriptable newArrayLiteral(Object[] objects,
3262:                    int[] skipIndices, Context cx, Scriptable scope) {
3263:                final int SKIP_DENSITY = 2;
3264:                int count = objects.length;
3265:                int skipCount = 0;
3266:                if (skipIndices != null) {
3267:                    skipCount = skipIndices.length;
3268:                }
3269:                int length = count + skipCount;
3270:                if (length > 1 && skipCount * SKIP_DENSITY < length) {
3271:                    // If not too sparse, create whole array for constructor
3272:                    Object[] sparse;
3273:                    if (skipCount == 0) {
3274:                        sparse = objects;
3275:                    } else {
3276:                        sparse = new Object[length];
3277:                        int skip = 0;
3278:                        for (int i = 0, j = 0; i != length; ++i) {
3279:                            if (skip != skipCount && skipIndices[skip] == i) {
3280:                                sparse[i] = Scriptable.NOT_FOUND;
3281:                                ++skip;
3282:                                continue;
3283:                            }
3284:                            sparse[i] = objects[j];
3285:                            ++j;
3286:                        }
3287:                    }
3288:                    return cx.newObject(scope, "Array", sparse);
3289:                }
3290:
3291:                Scriptable arrayObj = cx.newObject(scope, "Array",
3292:                        ScriptRuntime.emptyArgs);
3293:                int skip = 0;
3294:                for (int i = 0, j = 0; i != length; ++i) {
3295:                    if (skip != skipCount && skipIndices[skip] == i) {
3296:                        ++skip;
3297:                        continue;
3298:                    }
3299:                    ScriptableObject.putProperty(arrayObj, i, objects[j]);
3300:                    ++j;
3301:                }
3302:                return arrayObj;
3303:            }
3304:
3305:            /**
3306:             * This method is here for backward compat with existing compiled code.  It
3307:             * is called when an object literal is compiled.  The next instance will be
3308:             * the version called from new code.
3309:             * @deprecated This method only present for compatibility.
3310:             */
3311:            public static Scriptable newObjectLiteral(Object[] propertyIds,
3312:                    Object[] propertyValues, Context cx, Scriptable scope) {
3313:                // This will initialize to all zeros, exactly what we need for old-style
3314:                // getterSetters values (no getters or setters in the list)
3315:                int[] getterSetters = new int[propertyIds.length];
3316:                return newObjectLiteral(propertyIds, propertyValues,
3317:                        getterSetters, cx, scope);
3318:            }
3319:
3320:            public static Scriptable newObjectLiteral(Object[] propertyIds,
3321:                    Object[] propertyValues, int[] getterSetters, Context cx,
3322:                    Scriptable scope) {
3323:                Scriptable object = cx.newObject(scope);
3324:                for (int i = 0, end = propertyIds.length; i != end; ++i) {
3325:                    Object id = propertyIds[i];
3326:                    int getterSetter = getterSetters[i];
3327:                    Object value = propertyValues[i];
3328:                    if (id instanceof  String) {
3329:                        if (getterSetter == 0)
3330:                            ScriptableObject.putProperty(object, (String) id,
3331:                                    value);
3332:                        else {
3333:                            Callable fun;
3334:                            String definer;
3335:                            if (getterSetter < 0) // < 0 means get foo() ...
3336:                                definer = "__defineGetter__";
3337:                            else
3338:                                definer = "__defineSetter__";
3339:                            fun = getPropFunctionAndThis(object, definer, cx);
3340:                            // Must consume the last scriptable object in cx
3341:                            lastStoredScriptable(cx);
3342:                            Object[] outArgs = new Object[2];
3343:                            outArgs[0] = id;
3344:                            outArgs[1] = value;
3345:                            fun.call(cx, scope, object, outArgs);
3346:                        }
3347:                    } else {
3348:                        int index = ((Integer) id).intValue();
3349:                        ScriptableObject.putProperty(object, index, value);
3350:                    }
3351:                }
3352:                return object;
3353:            }
3354:
3355:            public static boolean isArrayObject(Object obj) {
3356:                return obj instanceof  NativeArray || obj instanceof  Arguments;
3357:            }
3358:
3359:            public static Object[] getArrayElements(Scriptable object) {
3360:                Context cx = Context.getContext();
3361:                long longLen = NativeArray.getLengthProperty(cx, object);
3362:                if (longLen > Integer.MAX_VALUE) {
3363:                    // arrays beyond  MAX_INT is not in Java in any case
3364:                    throw new IllegalArgumentException();
3365:                }
3366:                int len = (int) longLen;
3367:                if (len == 0) {
3368:                    return ScriptRuntime.emptyArgs;
3369:                } else {
3370:                    Object[] result = new Object[len];
3371:                    for (int i = 0; i < len; i++) {
3372:                        Object elem = ScriptableObject.getProperty(object, i);
3373:                        result[i] = (elem == Scriptable.NOT_FOUND) ? Undefined.instance
3374:                                : elem;
3375:                    }
3376:                    return result;
3377:                }
3378:            }
3379:
3380:            static void checkDeprecated(Context cx, String name) {
3381:                int version = cx.getLanguageVersion();
3382:                if (version >= Context.VERSION_1_4
3383:                        || version == Context.VERSION_DEFAULT) {
3384:                    String msg = getMessage1("msg.deprec.ctor", name);
3385:                    if (version == Context.VERSION_DEFAULT)
3386:                        Context.reportWarning(msg);
3387:                    else
3388:                        throw Context.reportRuntimeError(msg);
3389:                }
3390:            }
3391:
3392:            public static String getMessage0(String messageId) {
3393:                return getMessage(messageId, null);
3394:            }
3395:
3396:            public static String getMessage1(String messageId, Object arg1) {
3397:                Object[] arguments = { arg1 };
3398:                return getMessage(messageId, arguments);
3399:            }
3400:
3401:            public static String getMessage2(String messageId, Object arg1,
3402:                    Object arg2) {
3403:                Object[] arguments = { arg1, arg2 };
3404:                return getMessage(messageId, arguments);
3405:            }
3406:
3407:            public static String getMessage3(String messageId, Object arg1,
3408:                    Object arg2, Object arg3) {
3409:                Object[] arguments = { arg1, arg2, arg3 };
3410:                return getMessage(messageId, arguments);
3411:            }
3412:
3413:            public static String getMessage4(String messageId, Object arg1,
3414:                    Object arg2, Object arg3, Object arg4) {
3415:                Object[] arguments = { arg1, arg2, arg3, arg4 };
3416:                return getMessage(messageId, arguments);
3417:            }
3418:
3419:            /* OPT there's a noticable delay for the first error!  Maybe it'd
3420:             * make sense to use a ListResourceBundle instead of a properties
3421:             * file to avoid (synchronized) text parsing.
3422:             */
3423:            public static String getMessage(String messageId, Object[] arguments) {
3424:                final String defaultResource = "org.mozilla.javascript.resources.Messages";
3425:
3426:                Context cx = Context.getCurrentContext();
3427:                Locale locale = cx != null ? cx.getLocale() : Locale
3428:                        .getDefault();
3429:
3430:                // ResourceBundle does cacheing.
3431:                ResourceBundle rb = ResourceBundle.getBundle(defaultResource,
3432:                        locale);
3433:
3434:                String formatString;
3435:                try {
3436:                    formatString = rb.getString(messageId);
3437:                } catch (java.util.MissingResourceException mre) {
3438:                    throw new RuntimeException(
3439:                            "no message resource found for message property "
3440:                                    + messageId);
3441:                }
3442:
3443:                /*
3444:                 * It's OK to format the string, even if 'arguments' is null;
3445:                 * we need to format it anyway, to make double ''s collapse to
3446:                 * single 's.
3447:                 */
3448:                MessageFormat formatter = new MessageFormat(formatString);
3449:                return formatter.format(arguments);
3450:            }
3451:
3452:            public static EcmaError constructError(String error, String message) {
3453:                int[] linep = new int[1];
3454:                String filename = Context.getSourcePositionFromStack(linep);
3455:                return constructError(error, message, filename, linep[0], null,
3456:                        0);
3457:            }
3458:
3459:            public static EcmaError constructError(String error,
3460:                    String message, int lineNumberDelta) {
3461:                int[] linep = new int[1];
3462:                String filename = Context.getSourcePositionFromStack(linep);
3463:                if (linep[0] != 0) {
3464:                    linep[0] += lineNumberDelta;
3465:                }
3466:                return constructError(error, message, filename, linep[0], null,
3467:                        0);
3468:            }
3469:
3470:            public static EcmaError constructError(String error,
3471:                    String message, String sourceName, int lineNumber,
3472:                    String lineSource, int columnNumber) {
3473:                return new EcmaError(error, message, sourceName, lineNumber,
3474:                        lineSource, columnNumber);
3475:            }
3476:
3477:            public static EcmaError typeError(String message) {
3478:                return constructError("TypeError", message);
3479:            }
3480:
3481:            public static EcmaError typeError0(String messageId) {
3482:                String msg = getMessage0(messageId);
3483:                return typeError(msg);
3484:            }
3485:
3486:            public static EcmaError typeError1(String messageId, String arg1) {
3487:                String msg = getMessage1(messageId, arg1);
3488:                return typeError(msg);
3489:            }
3490:
3491:            public static EcmaError typeError2(String messageId, String arg1,
3492:                    String arg2) {
3493:                String msg = getMessage2(messageId, arg1, arg2);
3494:                return typeError(msg);
3495:            }
3496:
3497:            public static EcmaError typeError3(String messageId, String arg1,
3498:                    String arg2, String arg3) {
3499:                String msg = getMessage3(messageId, arg1, arg2, arg3);
3500:                return typeError(msg);
3501:            }
3502:
3503:            public static RuntimeException undefReadError(Object object,
3504:                    Object id) {
3505:                String idStr = (id == null) ? "null" : id.toString();
3506:                return typeError2("msg.undef.prop.read", toString(object),
3507:                        idStr);
3508:            }
3509:
3510:            public static RuntimeException undefCallError(Object object,
3511:                    Object id) {
3512:                String idStr = (id == null) ? "null" : id.toString();
3513:                return typeError2("msg.undef.method.call", toString(object),
3514:                        idStr);
3515:            }
3516:
3517:            public static RuntimeException undefWriteError(Object object,
3518:                    Object id, Object value) {
3519:                String idStr = (id == null) ? "null" : id.toString();
3520:                String valueStr = (value instanceof  Scriptable) ? value
3521:                        .toString() : toString(value);
3522:                return typeError3("msg.undef.prop.write", toString(object),
3523:                        idStr, valueStr);
3524:            }
3525:
3526:            public static RuntimeException notFoundError(Scriptable object,
3527:                    String property) {
3528:                // XXX: use object to improve the error message
3529:                String msg = getMessage1("msg.is.not.defined", property);
3530:                throw constructError("ReferenceError", msg);
3531:            }
3532:
3533:            public static RuntimeException notFunctionError(Object value) {
3534:                return notFunctionError(value, value);
3535:            }
3536:
3537:            public static RuntimeException notFunctionError(Object value,
3538:                    Object messageHelper) {
3539:                // Use value for better error reporting
3540:                String msg = (messageHelper == null) ? "null" : messageHelper
3541:                        .toString();
3542:                if (value == Scriptable.NOT_FOUND) {
3543:                    return typeError1("msg.function.not.found", msg);
3544:                }
3545:                return typeError2("msg.isnt.function", msg, typeof(value));
3546:            }
3547:
3548:            public static RuntimeException notFunctionError(Object obj,
3549:                    Object value, String propertyName) {
3550:                // Use obj and value for better error reporting
3551:                String objString = toString(obj);
3552:                if (value == Scriptable.NOT_FOUND) {
3553:                    return typeError2("msg.function.not.found.in",
3554:                            propertyName, objString);
3555:                }
3556:                return typeError3("msg.isnt.function.in", propertyName,
3557:                        objString, typeof(value));
3558:            }
3559:
3560:            private static RuntimeException notXmlError(Object value) {
3561:                throw typeError1("msg.isnt.xml.object", toString(value));
3562:            }
3563:
3564:            private static void warnAboutNonJSObject(Object nonJSObject) {
3565:                String message = "RHINO USAGE WARNING: Missed Context.javaToJS() conversion:\n"
3566:                        + "Rhino runtime detected object "
3567:                        + nonJSObject
3568:                        + " of class "
3569:                        + nonJSObject.getClass().getName()
3570:                        + " where it expected String, Number, Boolean or Scriptable instance. Please check your code for missing Context.javaToJS() call.";
3571:                Context.reportWarning(message);
3572:                // Just to be sure that it would be noticed
3573:                System.err.println(message);
3574:            }
3575:
3576:            public static RegExpProxy getRegExpProxy(Context cx) {
3577:                return cx.getRegExpProxy();
3578:            }
3579:
3580:            public static void setRegExpProxy(Context cx, RegExpProxy proxy) {
3581:                if (proxy == null)
3582:                    throw new IllegalArgumentException();
3583:                cx.regExpProxy = proxy;
3584:            }
3585:
3586:            public static RegExpProxy checkRegExpProxy(Context cx) {
3587:                RegExpProxy result = getRegExpProxy(cx);
3588:                if (result == null) {
3589:                    throw Context.reportRuntimeError0("msg.no.regexp");
3590:                }
3591:                return result;
3592:            }
3593:
3594:            private static XMLLib currentXMLLib(Context cx) {
3595:                // Scripts should be running to access this
3596:                if (cx.topCallScope == null)
3597:                    throw new IllegalStateException();
3598:
3599:                XMLLib xmlLib = cx.cachedXMLLib;
3600:                if (xmlLib == null) {
3601:                    xmlLib = XMLLib.extractFromScope(cx.topCallScope);
3602:                    if (xmlLib == null)
3603:                        throw new IllegalStateException();
3604:                    cx.cachedXMLLib = xmlLib;
3605:                }
3606:
3607:                return xmlLib;
3608:            }
3609:
3610:            /**
3611:             * Escapes the reserved characters in a value of an attribute
3612:             *
3613:             * @param value Unescaped text
3614:             * @return The escaped text
3615:             */
3616:            public static String escapeAttributeValue(Object value, Context cx) {
3617:                XMLLib xmlLib = currentXMLLib(cx);
3618:                return xmlLib.escapeAttributeValue(value);
3619:            }
3620:
3621:            /**
3622:             * Escapes the reserved characters in a value of a text node
3623:             *
3624:             * @param value Unescaped text
3625:             * @return The escaped text
3626:             */
3627:            public static String escapeTextValue(Object value, Context cx) {
3628:                XMLLib xmlLib = currentXMLLib(cx);
3629:                return xmlLib.escapeTextValue(value);
3630:            }
3631:
3632:            public static Ref memberRef(Object obj, Object elem, Context cx,
3633:                    int memberTypeFlags) {
3634:                if (!(obj instanceof  XMLObject)) {
3635:                    throw notXmlError(obj);
3636:                }
3637:                XMLObject xmlObject = (XMLObject) obj;
3638:                return xmlObject.memberRef(cx, elem, memberTypeFlags);
3639:            }
3640:
3641:            public static Ref memberRef(Object obj, Object namespace,
3642:                    Object elem, Context cx, int memberTypeFlags) {
3643:                if (!(obj instanceof  XMLObject)) {
3644:                    throw notXmlError(obj);
3645:                }
3646:                XMLObject xmlObject = (XMLObject) obj;
3647:                return xmlObject
3648:                        .memberRef(cx, namespace, elem, memberTypeFlags);
3649:            }
3650:
3651:            public static Ref nameRef(Object name, Context cx,
3652:                    Scriptable scope, int memberTypeFlags) {
3653:                XMLLib xmlLib = currentXMLLib(cx);
3654:                return xmlLib.nameRef(cx, name, scope, memberTypeFlags);
3655:            }
3656:
3657:            public static Ref nameRef(Object namespace, Object name,
3658:                    Context cx, Scriptable scope, int memberTypeFlags) {
3659:                XMLLib xmlLib = currentXMLLib(cx);
3660:                return xmlLib.nameRef(cx, namespace, name, scope,
3661:                        memberTypeFlags);
3662:            }
3663:
3664:            private static void storeIndexResult(Context cx, int index) {
3665:                cx.scratchIndex = index;
3666:            }
3667:
3668:            static int lastIndexResult(Context cx) {
3669:                return cx.scratchIndex;
3670:            }
3671:
3672:            public static void storeUint32Result(Context cx, long value) {
3673:                if ((value >>> 32) != 0)
3674:                    throw new IllegalArgumentException();
3675:                cx.scratchUint32 = value;
3676:            }
3677:
3678:            public static long lastUint32Result(Context cx) {
3679:                long value = cx.scratchUint32;
3680:                if ((value >>> 32) != 0)
3681:                    throw new IllegalStateException();
3682:                return value;
3683:            }
3684:
3685:            private static void storeScriptable(Context cx, Scriptable value) {
3686:                // The previosly stored scratchScriptable should be consumed
3687:                if (cx.scratchScriptable != null)
3688:                    throw new IllegalStateException();
3689:                cx.scratchScriptable = value;
3690:            }
3691:
3692:            public static Scriptable lastStoredScriptable(Context cx) {
3693:                Scriptable result = cx.scratchScriptable;
3694:                cx.scratchScriptable = null;
3695:                return result;
3696:            }
3697:
3698:            static String makeUrlForGeneratedScript(boolean isEval,
3699:                    String masterScriptUrl, int masterScriptLine) {
3700:                if (isEval) {
3701:                    return masterScriptUrl + '#' + masterScriptLine + "(eval)";
3702:                } else {
3703:                    return masterScriptUrl + '#' + masterScriptLine
3704:                            + "(Function)";
3705:                }
3706:            }
3707:
3708:            static boolean isGeneratedScript(String sourceUrl) {
3709:                // ALERT: this may clash with a valid URL containing (eval) or
3710:                // (Function)
3711:                return sourceUrl.indexOf("(eval)") >= 0
3712:                        || sourceUrl.indexOf("(Function)") >= 0;
3713:            }
3714:
3715:            private static RuntimeException errorWithClassName(String msg,
3716:                    Object val) {
3717:                return Context.reportRuntimeError1(msg, val.getClass()
3718:                        .getName());
3719:            }
3720:
3721:            public static final Object[] emptyArgs = new Object[0];
3722:            public static final String[] emptyStrings = new String[0];
3723:
3724:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.