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