aboutsummaryrefslogtreecommitdiffstats
path: root/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ScriptRuntime.java
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ScriptRuntime.java')
-rw-r--r--trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ScriptRuntime.java3830
1 files changed, 0 insertions, 3830 deletions
diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ScriptRuntime.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ScriptRuntime.java
deleted file mode 100644
index f879581..0000000
--- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ScriptRuntime.java
+++ /dev/null
@@ -1,3830 +0,0 @@
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- *
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Rhino code, released
- * May 6, 1999.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1997-2000
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Patrick Beard
- * Norris Boyd
- * Igor Bukanov
- * Ethan Hugg
- * Bob Jervis
- * Roger Lawrence
- * Terry Lucas
- * Frank Mitchell
- * Milen Nankov
- * Hannes Wallnoefer
- * Andrew Wason
- *
- * Alternatively, the contents of this file may be used under the terms of
- * the GNU General Public License Version 2 or later (the "GPL"), in which
- * case the provisions of the GPL are applicable instead of those above. If
- * you wish to allow use of your version of this file only under the terms of
- * the GPL and not to allow others to use your version of this file under the
- * MPL, indicate your decision by deleting the provisions above and replacing
- * them with the notice and other provisions required by the GPL. If you do
- * not delete the provisions above, a recipient may use your version of this
- * file under either the MPL or the GPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-package org.mozilla.javascript;
-
-import java.io.Serializable;
-import java.lang.reflect.*;
-import java.text.MessageFormat;
-import java.util.Locale;
-import java.util.ResourceBundle;
-
-import org.mozilla.javascript.xml.XMLObject;
-import org.mozilla.javascript.xml.XMLLib;
-
-/**
- * This is the class that implements the runtime.
- *
- * @author Norris Boyd
- */
-
-public class ScriptRuntime {
-
- /**
- * No instances should be created.
- */
- protected ScriptRuntime() {
- }
-
- private static class NoSuchMethodShim implements Callable {
- String methodName;
- Callable noSuchMethodMethod;
-
- NoSuchMethodShim(Callable noSuchMethodMethod, String methodName)
- {
- this.noSuchMethodMethod = noSuchMethodMethod;
- this.methodName = methodName;
- }
- /**
- * Perform the call.
- *
- * @param cx the current Context for this thread
- * @param scope the scope to use to resolve properties.
- * @param thisObj the JavaScript <code>this</code> object
- * @param args the array of arguments
- * @return the result of the call
- */
- public Object call(Context cx, Scriptable scope, Scriptable thisObj,
- Object[] args)
- {
- Object[] nestedArgs = new Object[2];
-
- nestedArgs[0] = methodName;
- nestedArgs[1] = newArrayLiteral(args, null, cx, scope);
- return noSuchMethodMethod.call(cx, scope, thisObj, nestedArgs);
- }
-
- }
- /*
- * There's such a huge space (and some time) waste for the Foo.class
- * syntax: the compiler sticks in a test of a static field in the
- * enclosing class for null and the code for creating the class value.
- * It has to do this since the reference has to get pushed off until
- * execution time (i.e. can't force an early load), but for the
- * 'standard' classes - especially those in java.lang, we can trust
- * that they won't cause problems by being loaded early.
- */
-
- public final static Class
- BooleanClass = Kit.classOrNull("java.lang.Boolean"),
- ByteClass = Kit.classOrNull("java.lang.Byte"),
- CharacterClass = Kit.classOrNull("java.lang.Character"),
- ClassClass = Kit.classOrNull("java.lang.Class"),
- DoubleClass = Kit.classOrNull("java.lang.Double"),
- FloatClass = Kit.classOrNull("java.lang.Float"),
- IntegerClass = Kit.classOrNull("java.lang.Integer"),
- LongClass = Kit.classOrNull("java.lang.Long"),
- NumberClass = Kit.classOrNull("java.lang.Number"),
- ObjectClass = Kit.classOrNull("java.lang.Object"),
- ShortClass = Kit.classOrNull("java.lang.Short"),
- StringClass = Kit.classOrNull("java.lang.String"),
- DateClass = Kit.classOrNull("java.util.Date");
-
- public final static Class
- ContextClass
- = Kit.classOrNull("org.mozilla.javascript.Context"),
- ContextFactoryClass
- = Kit.classOrNull("org.mozilla.javascript.ContextFactory"),
- FunctionClass
- = Kit.classOrNull("org.mozilla.javascript.Function"),
- ScriptableClass
- = Kit.classOrNull("org.mozilla.javascript.Scriptable"),
- ScriptableObjectClass
- = Kit.classOrNull("org.mozilla.javascript.ScriptableObject");
-
- private static final String[] lazilyNames = {
- "RegExp", "org.mozilla.javascript.regexp.NativeRegExp",
- "Packages", "org.mozilla.javascript.NativeJavaTopPackage",
- "java", "org.mozilla.javascript.NativeJavaTopPackage",
- "javax", "org.mozilla.javascript.NativeJavaTopPackage",
- "org", "org.mozilla.javascript.NativeJavaTopPackage",
- "com", "org.mozilla.javascript.NativeJavaTopPackage",
- "edu", "org.mozilla.javascript.NativeJavaTopPackage",
- "net", "org.mozilla.javascript.NativeJavaTopPackage",
- "getClass", "org.mozilla.javascript.NativeJavaTopPackage",
- "JavaAdapter", "org.mozilla.javascript.JavaAdapter",
- "JavaImporter", "org.mozilla.javascript.ImporterTopLevel",
- "Continuation", "org.mozilla.javascript.continuations.Continuation",
- // TODO Grotesque hack using literal string (xml) just to minimize
- // changes for now
- "XML", "(xml)",
- "XMLList", "(xml)",
- "Namespace", "(xml)",
- "QName", "(xml)",
- };
-
- private static final Object LIBRARY_SCOPE_KEY = new Object();
-
- public static boolean isRhinoRuntimeType(Class cl)
- {
- if (cl.isPrimitive()) {
- return (cl != Character.TYPE);
- } else {
- return (cl == StringClass || cl == BooleanClass
- || NumberClass.isAssignableFrom(cl)
- || ScriptableClass.isAssignableFrom(cl));
- }
- }
-
- public static ScriptableObject initStandardObjects(Context cx,
- ScriptableObject scope,
- boolean sealed)
- {
- if (scope == null) {
- scope = new NativeObject();
- }
- scope.associateValue(LIBRARY_SCOPE_KEY, scope);
- (new ClassCache()).associate(scope);
-
- BaseFunction.init(scope, sealed);
- NativeObject.init(scope, sealed);
-
- Scriptable objectProto = ScriptableObject.getObjectPrototype(scope);
-
- // Function.prototype.__proto__ should be Object.prototype
- Scriptable functionProto = ScriptableObject.getFunctionPrototype(scope);
- functionProto.setPrototype(objectProto);
-
- // Set the prototype of the object passed in if need be
- if (scope.getPrototype() == null)
- scope.setPrototype(objectProto);
-
- // must precede NativeGlobal since it's needed therein
- NativeError.init(scope, sealed);
- NativeGlobal.init(cx, scope, sealed);
-
- NativeArray.init(scope, sealed);
- if (cx.getOptimizationLevel() > 0) {
- // When optimizing, attempt to fulfill all requests for new Array(N)
- // with a higher threshold before switching to a sparse
- // representation
- NativeArray.setMaximumInitialCapacity(200000);
- }
- NativeString.init(scope, sealed);
- NativeBoolean.init(scope, sealed);
- NativeNumber.init(scope, sealed);
- NativeDate.init(scope, sealed);
- NativeMath.init(scope, sealed);
-
- NativeWith.init(scope, sealed);
- NativeCall.init(scope, sealed);
- NativeScript.init(scope, sealed);
-
- NativeIterator.init(scope, sealed); // Also initializes NativeGenerator
-
- boolean withXml = cx.hasFeature(Context.FEATURE_E4X) &&
- cx.getE4xImplementationFactory() != null;
-
- for (int i = 0; i != lazilyNames.length; i += 2) {
- String topProperty = lazilyNames[i];
- String className = lazilyNames[i + 1];
- if (!withXml && className.equals("(xml)")) {
- continue;
- } else if (withXml && className.equals("(xml)")) {
- className = cx.getE4xImplementationFactory().
- getImplementationClassName();
- }
- new LazilyLoadedCtor(scope, topProperty, className, sealed);
- }
-
- return scope;
- }
-
- public static ScriptableObject getLibraryScopeOrNull(Scriptable scope)
- {
- ScriptableObject libScope;
- libScope = (ScriptableObject)ScriptableObject.
- getTopScopeValue(scope, LIBRARY_SCOPE_KEY);
- return libScope;
- }
-
- // It is public so NativeRegExp can access it.
- public static boolean isJSLineTerminator(int c)
- {
- // Optimization for faster check for eol character:
- // they do not have 0xDFD0 bits set
- if ((c & 0xDFD0) != 0) {
- return false;
- }
- return c == '\n' || c == '\r' || c == 0x2028 || c == 0x2029;
- }
-
- public static Boolean wrapBoolean(boolean b)
- {
- return b ? Boolean.TRUE : Boolean.FALSE;
- }
-
- public static Integer wrapInt(int i)
- {
- return new Integer(i);
- }
-
- public static Number wrapNumber(double x)
- {
- if (x != x) {
- return ScriptRuntime.NaNobj;
- }
- return new Double(x);
- }
-
- /**
- * Convert the value to a boolean.
- *
- * See ECMA 9.2.
- */
- public static boolean toBoolean(Object val)
- {
- for (;;) {
- if (val instanceof Boolean)
- return ((Boolean) val).booleanValue();
- if (val == null || val == Undefined.instance)
- return false;
- if (val instanceof String)
- return ((String) val).length() != 0;
- if (val instanceof Number) {
- double d = ((Number) val).doubleValue();
- return (d == d && d != 0.0);
- }
- if (val instanceof Scriptable) {
- if (val instanceof ScriptableObject &&
- ((ScriptableObject) val).avoidObjectDetection())
- {
- return false;
- }
- if (Context.getContext().isVersionECMA1()) {
- // pure ECMA
- return true;
- }
- // ECMA extension
- val = ((Scriptable) val).getDefaultValue(BooleanClass);
- if (val instanceof Scriptable)
- throw errorWithClassName("msg.primitive.expected", val);
- continue;
- }
- warnAboutNonJSObject(val);
- return true;
- }
- }
-
- /**
- * Convert the value to a number.
- *
- * See ECMA 9.3.
- */
- public static double toNumber(Object val)
- {
- for (;;) {
- if (val instanceof Number)
- return ((Number) val).doubleValue();
- if (val == null)
- return +0.0;
- if (val == Undefined.instance)
- return NaN;
- if (val instanceof String)
- return toNumber((String) val);
- if (val instanceof Boolean)
- return ((Boolean) val).booleanValue() ? 1 : +0.0;
- if (val instanceof Scriptable) {
- val = ((Scriptable) val).getDefaultValue(NumberClass);
- if (val instanceof Scriptable)
- throw errorWithClassName("msg.primitive.expected", val);
- continue;
- }
- warnAboutNonJSObject(val);
- return NaN;
- }
- }
-
- public static double toNumber(Object[] args, int index) {
- return (index < args.length) ? toNumber(args[index]) : NaN;
- }
-
- // Can not use Double.NaN defined as 0.0d / 0.0 as under the Microsoft VM,
- // versions 2.01 and 3.0P1, that causes some uses (returns at least) of
- // Double.NaN to be converted to 1.0.
- // So we use ScriptRuntime.NaN instead of Double.NaN.
- public static final double
- NaN = Double.longBitsToDouble(0x7ff8000000000000L);
-
- // A similar problem exists for negative zero.
- public static final double
- negativeZero = Double.longBitsToDouble(0x8000000000000000L);
-
- public static final Double NaNobj = new Double(NaN);
-
- /*
- * Helper function for toNumber, parseInt, and TokenStream.getToken.
- */
- static double stringToNumber(String s, int start, int radix) {
- char digitMax = '9';
- char lowerCaseBound = 'a';
- char upperCaseBound = 'A';
- int len = s.length();
- if (radix < 10) {
- digitMax = (char) ('0' + radix - 1);
- }
- if (radix > 10) {
- lowerCaseBound = (char) ('a' + radix - 10);
- upperCaseBound = (char) ('A' + radix - 10);
- }
- int end;
- double sum = 0.0;
- for (end=start; end < len; end++) {
- char c = s.charAt(end);
- int newDigit;
- if ('0' <= c && c <= digitMax)
- newDigit = c - '0';
- else if ('a' <= c && c < lowerCaseBound)
- newDigit = c - 'a' + 10;
- else if ('A' <= c && c < upperCaseBound)
- newDigit = c - 'A' + 10;
- else
- break;
- sum = sum*radix + newDigit;
- }
- if (start == end) {
- return NaN;
- }
- if (sum >= 9007199254740992.0) {
- if (radix == 10) {
- /* If we're accumulating a decimal number and the number
- * is >= 2^53, then the result from the repeated multiply-add
- * above may be inaccurate. Call Java to get the correct
- * answer.
- */
- try {
- return Double.valueOf(s.substring(start, end)).doubleValue();
- } catch (NumberFormatException nfe) {
- return NaN;
- }
- } else if (radix == 2 || radix == 4 || radix == 8 ||
- radix == 16 || radix == 32)
- {
- /* The number may also be inaccurate for one of these bases.
- * This happens if the addition in value*radix + digit causes
- * a round-down to an even least significant mantissa bit
- * when the first dropped bit is a one. If any of the
- * following digits in the number (which haven't been added
- * in yet) are nonzero then the correct action would have
- * been to round up instead of down. An example of this
- * occurs when reading the number 0x1000000000000081, which
- * rounds to 0x1000000000000000 instead of 0x1000000000000100.
- */
- int bitShiftInChar = 1;
- int digit = 0;
-
- final int SKIP_LEADING_ZEROS = 0;
- final int FIRST_EXACT_53_BITS = 1;
- final int AFTER_BIT_53 = 2;
- final int ZEROS_AFTER_54 = 3;
- final int MIXED_AFTER_54 = 4;
-
- int state = SKIP_LEADING_ZEROS;
- int exactBitsLimit = 53;
- double factor = 0.0;
- boolean bit53 = false;
- // bit54 is the 54th bit (the first dropped from the mantissa)
- boolean bit54 = false;
-
- for (;;) {
- if (bitShiftInChar == 1) {
- if (start == end)
- break;
- digit = s.charAt(start++);
- if ('0' <= digit && digit <= '9')
- digit -= '0';
- else if ('a' <= digit && digit <= 'z')
- digit -= 'a' - 10;
- else
- digit -= 'A' - 10;
- bitShiftInChar = radix;
- }
- bitShiftInChar >>= 1;
- boolean bit = (digit & bitShiftInChar) != 0;
-
- switch (state) {
- case SKIP_LEADING_ZEROS:
- if (bit) {
- --exactBitsLimit;
- sum = 1.0;
- state = FIRST_EXACT_53_BITS;
- }
- break;
- case FIRST_EXACT_53_BITS:
- sum *= 2.0;
- if (bit)
- sum += 1.0;
- --exactBitsLimit;
- if (exactBitsLimit == 0) {
- bit53 = bit;
- state = AFTER_BIT_53;
- }
- break;
- case AFTER_BIT_53:
- bit54 = bit;
- factor = 2.0;
- state = ZEROS_AFTER_54;
- break;
- case ZEROS_AFTER_54:
- if (bit) {
- state = MIXED_AFTER_54;
- }
- // fallthrough
- case MIXED_AFTER_54:
- factor *= 2;
- break;
- }
- }
- switch (state) {
- case SKIP_LEADING_ZEROS:
- sum = 0.0;
- break;
- case FIRST_EXACT_53_BITS:
- case AFTER_BIT_53:
- // do nothing
- break;
- case ZEROS_AFTER_54:
- // x1.1 -> x1 + 1 (round up)
- // x0.1 -> x0 (round down)
- if (bit54 & bit53)
- sum += 1.0;
- sum *= factor;
- break;
- case MIXED_AFTER_54:
- // x.100...1.. -> x + 1 (round up)
- // x.0anything -> x (round down)
- if (bit54)
- sum += 1.0;
- sum *= factor;
- break;
- }
- }
- /* We don't worry about inaccurate numbers for any other base. */
- }
- return sum;
- }
-
-
- /**
- * ToNumber applied to the String type
- *
- * See ECMA 9.3.1
- */
- public static double toNumber(String s) {
- int len = s.length();
- int start = 0;
- char startChar;
- for (;;) {
- if (start == len) {
- // Empty or contains only whitespace
- return +0.0;
- }
- startChar = s.charAt(start);
- if (!Character.isWhitespace(startChar))
- break;
- start++;
- }
-
- if (startChar == '0') {
- if (start + 2 < len) {
- int c1 = s.charAt(start + 1);
- if (c1 == 'x' || c1 == 'X') {
- // A hexadecimal number
- return stringToNumber(s, start + 2, 16);
- }
- }
- } else if (startChar == '+' || startChar == '-') {
- if (start + 3 < len && s.charAt(start + 1) == '0') {
- int c2 = s.charAt(start + 2);
- if (c2 == 'x' || c2 == 'X') {
- // A hexadecimal number with sign
- double val = stringToNumber(s, start + 3, 16);
- return startChar == '-' ? -val : val;
- }
- }
- }
-
- int end = len - 1;
- char endChar;
- while (Character.isWhitespace(endChar = s.charAt(end)))
- end--;
- if (endChar == 'y') {
- // check for "Infinity"
- if (startChar == '+' || startChar == '-')
- start++;
- if (start + 7 == end && s.regionMatches(start, "Infinity", 0, 8))
- return startChar == '-'
- ? Double.NEGATIVE_INFINITY
- : Double.POSITIVE_INFINITY;
- return NaN;
- }
- // A non-hexadecimal, non-infinity number:
- // just try a normal floating point conversion
- String sub = s.substring(start, end+1);
- if (MSJVM_BUG_WORKAROUNDS) {
- // The MS JVM will accept non-conformant strings
- // rather than throwing a NumberFormatException
- // as it should.
- for (int i=sub.length()-1; i >= 0; i--) {
- char c = sub.charAt(i);
- if (('0' <= c && c <= '9') || c == '.' ||
- c == 'e' || c == 'E' ||
- c == '+' || c == '-')
- continue;
- return NaN;
- }
- }
- try {
- return Double.valueOf(sub).doubleValue();
- } catch (NumberFormatException ex) {
- return NaN;
- }
- }
-
- /**
- * Helper function for builtin objects that use the varargs form.
- * ECMA function formal arguments are undefined if not supplied;
- * this function pads the argument array out to the expected
- * length, if necessary.
- */
- public static Object[] padArguments(Object[] args, int count) {
- if (count < args.length)
- return args;
-
- int i;
- Object[] result = new Object[count];
- for (i = 0; i < args.length; i++) {
- result[i] = args[i];
- }
-
- for (; i < count; i++) {
- result[i] = Undefined.instance;
- }
-
- return result;
- }
-
- /* Work around Microsoft Java VM bugs. */
- private final static boolean MSJVM_BUG_WORKAROUNDS = true;
-
- public static String escapeString(String s)
- {
- return escapeString(s, '"');
- }
-
- /**
- * For escaping strings printed by object and array literals; not quite
- * the same as 'escape.'
- */
- public static String escapeString(String s, char escapeQuote)
- {
- if (!(escapeQuote == '"' || escapeQuote == '\'')) Kit.codeBug();
- StringBuffer sb = null;
-
- for(int i = 0, L = s.length(); i != L; ++i) {
- int c = s.charAt(i);
-
- if (' ' <= c && c <= '~' && c != escapeQuote && c != '\\') {
- // an ordinary print character (like C isprint()) and not "
- // or \ .
- if (sb != null) {
- sb.append((char)c);
- }
- continue;
- }
- if (sb == null) {
- sb = new StringBuffer(L + 3);
- sb.append(s);
- sb.setLength(i);
- }
-
- int escape = -1;
- switch (c) {
- case '\b': escape = 'b'; break;
- case '\f': escape = 'f'; break;
- case '\n': escape = 'n'; break;
- case '\r': escape = 'r'; break;
- case '\t': escape = 't'; break;
- case 0xb: escape = 'v'; break; // Java lacks \v.
- case ' ': escape = ' '; break;
- case '\\': escape = '\\'; break;
- }
- if (escape >= 0) {
- // an \escaped sort of character
- sb.append('\\');
- sb.append((char)escape);
- } else if (c == escapeQuote) {
- sb.append('\\');
- sb.append(escapeQuote);
- } else {
- int hexSize;
- if (c < 256) {
- // 2-digit hex
- sb.append("\\x");
- hexSize = 2;
- } else {
- // Unicode.
- sb.append("\\u");
- hexSize = 4;
- }
- // append hexadecimal form of c left-padded with 0
- for (int shift = (hexSize - 1) * 4; shift >= 0; shift -= 4) {
- int digit = 0xf & (c >> shift);
- int hc = (digit < 10) ? '0' + digit : 'a' - 10 + digit;
- sb.append((char)hc);
- }
- }
- }
- return (sb == null) ? s : sb.toString();
- }
-
- static boolean isValidIdentifierName(String s)
- {
- int L = s.length();
- if (L == 0)
- return false;
- if (!Character.isJavaIdentifierStart(s.charAt(0)))
- return false;
- for (int i = 1; i != L; ++i) {
- if (!Character.isJavaIdentifierPart(s.charAt(i)))
- return false;
- }
- return !TokenStream.isKeyword(s);
- }
-
- /**
- * Convert the value to a string.
- *
- * See ECMA 9.8.
- */
- public static String toString(Object val) {
- for (;;) {
- if (val == null) {
- return "null";
- }
- if (val == Undefined.instance) {
- return "undefined";
- }
- if (val instanceof String) {
- return (String)val;
- }
- if (val instanceof Number) {
- // XXX should we just teach NativeNumber.stringValue()
- // about Numbers?
- return numberToString(((Number)val).doubleValue(), 10);
- }
- if (val instanceof Scriptable) {
- val = ((Scriptable) val).getDefaultValue(StringClass);
- if (val instanceof Scriptable) {
- throw errorWithClassName("msg.primitive.expected", val);
- }
- continue;
- }
- return val.toString();
- }
- }
-
- static String defaultObjectToString(Scriptable obj)
- {
- return "[object " + obj.getClassName() + ']';
- }
-
- public static String toString(Object[] args, int index)
- {
- return (index < args.length) ? toString(args[index]) : "undefined";
- }
-
- /**
- * Optimized version of toString(Object) for numbers.
- */
- public static String toString(double val) {
- return numberToString(val, 10);
- }
-
- public static String numberToString(double d, int base) {
- if (d != d)
- return "NaN";
- if (d == Double.POSITIVE_INFINITY)
- return "Infinity";
- if (d == Double.NEGATIVE_INFINITY)
- return "-Infinity";
- if (d == 0.0)
- return "0";
-
- if ((base < 2) || (base > 36)) {
- throw Context.reportRuntimeError1(
- "msg.bad.radix", Integer.toString(base));
- }
-
- if (base != 10) {
- return DToA.JS_dtobasestr(base, d);
- } else {
- StringBuffer result = new StringBuffer();
- DToA.JS_dtostr(result, DToA.DTOSTR_STANDARD, 0, d);
- return result.toString();
- }
-
- }
-
- static String uneval(Context cx, Scriptable scope, Object value)
- {
- if (value == null) {
- return "null";
- }
- if (value == Undefined.instance) {
- return "undefined";
- }
- if (value instanceof String) {
- String escaped = escapeString((String)value);
- StringBuffer sb = new StringBuffer(escaped.length() + 2);
- sb.append('\"');
- sb.append(escaped);
- sb.append('\"');
- return sb.toString();
- }
- if (value instanceof Number) {
- double d = ((Number)value).doubleValue();
- if (d == 0 && 1 / d < 0) {
- return "-0";
- }
- return toString(d);
- }
- if (value instanceof Boolean) {
- return toString(value);
- }
- if (value instanceof Scriptable) {
- Scriptable obj = (Scriptable)value;
- // Wrapped Java objects won't have "toSource" and will report
- // errors for get()s of nonexistent name, so use has() first
- if (ScriptableObject.hasProperty(obj, "toSource")) {
- Object v = ScriptableObject.getProperty(obj, "toSource");
- if (v instanceof Function) {
- Function f = (Function)v;
- return toString(f.call(cx, scope, obj, emptyArgs));
- }
- }
- return toString(value);
- }
- warnAboutNonJSObject(value);
- return value.toString();
- }
-
- static String defaultObjectToSource(Context cx, Scriptable scope,
- Scriptable thisObj, Object[] args)
- {
- boolean toplevel, iterating;
- if (cx.iterating == null) {
- toplevel = true;
- iterating = false;
- cx.iterating = new ObjToIntMap(31);
- } else {
- toplevel = false;
- iterating = cx.iterating.has(thisObj);
- }
-
- StringBuffer result = new StringBuffer(128);
- if (toplevel) {
- result.append("(");
- }
- result.append('{');
-
- // Make sure cx.iterating is set to null when done
- // so we don't leak memory
- try {
- if (!iterating) {
- cx.iterating.intern(thisObj); // stop recursion.
- Object[] ids = thisObj.getIds();
- for (int i=0; i < ids.length; i++) {
- Object id = ids[i];
- Object value;
- if (id instanceof Integer) {
- int intId = ((Integer)id).intValue();
- value = thisObj.get(intId, thisObj);
- if (value == Scriptable.NOT_FOUND)
- continue; // a property has been removed
- if (i > 0)
- result.append(", ");
- result.append(intId);
- } else {
- String strId = (String)id;
- value = thisObj.get(strId, thisObj);
- if (value == Scriptable.NOT_FOUND)
- continue; // a property has been removed
- if (i > 0)
- result.append(", ");
- if (ScriptRuntime.isValidIdentifierName(strId)) {
- result.append(strId);
- } else {
- result.append('\'');
- result.append(
- ScriptRuntime.escapeString(strId, '\''));
- result.append('\'');
- }
- }
- result.append(':');
- result.append(ScriptRuntime.uneval(cx, scope, value));
- }
- }
- } finally {
- if (toplevel) {
- cx.iterating = null;
- }
- }
-
- result.append('}');
- if (toplevel) {
- result.append(')');
- }
- return result.toString();
- }
-
- public static Scriptable toObject(Scriptable scope, Object val)
- {
- if (val instanceof Scriptable) {
- return (Scriptable)val;
- }
- return toObject(Context.getContext(), scope, val);
- }
-
- public static Scriptable toObjectOrNull(Context cx, Object obj)
- {
- if (obj instanceof Scriptable) {
- return (Scriptable)obj;
- } else if (obj != null && obj != Undefined.instance) {
- return toObject(cx, getTopCallScope(cx), obj);
- }
- return null;
- }
-
- /**
- * @deprecated Use {@link #toObject(Scriptable, Object)} instead.
- */
- public static Scriptable toObject(Scriptable scope, Object val,
- Class staticClass)
- {
- if (val instanceof Scriptable) {
- return (Scriptable)val;
- }
- return toObject(Context.getContext(), scope, val);
- }
-
- /**
- * Convert the value to an object.
- *
- * See ECMA 9.9.
- */
- public static Scriptable toObject(Context cx, Scriptable scope, Object val)
- {
- if (val instanceof Scriptable) {
- return (Scriptable) val;
- }
- if (val == null) {
- throw typeError0("msg.null.to.object");
- }
- if (val == Undefined.instance) {
- throw typeError0("msg.undef.to.object");
- }
- String className = val instanceof String ? "String" :
- val instanceof Number ? "Number" :
- val instanceof Boolean ? "Boolean" :
- null;
- if (className != null) {
- Object[] args = { val };
- scope = ScriptableObject.getTopLevelScope(scope);
- return newObject(cx, scope, className, args);
- }
-
- // Extension: Wrap as a LiveConnect object.
- Object wrapped = cx.getWrapFactory().wrap(cx, scope, val, null);
- if (wrapped instanceof Scriptable)
- return (Scriptable) wrapped;
- throw errorWithClassName("msg.invalid.type", val);
- }
-
- /**
- * @deprecated Use {@link #toObject(Context, Scriptable, Object)} instead.
- */
- public static Scriptable toObject(Context cx, Scriptable scope, Object val,
- Class staticClass)
- {
- return toObject(cx, scope, val);
- }
-
- /**
- * @deprecated The method is only present for compatibility.
- */
- public static Object call(Context cx, Object fun, Object thisArg,
- Object[] args, Scriptable scope)
- {
- if (!(fun instanceof Function)) {
- throw notFunctionError(toString(fun));
- }
- Function function = (Function)fun;
- Scriptable thisObj = toObjectOrNull(cx, thisArg);
- if (thisObj == null) {
- throw undefCallError(thisObj, "function");
- }
- return function.call(cx, scope, thisObj, args);
- }
-
- public static Scriptable newObject(Context cx, Scriptable scope,
- String constructorName, Object[] args)
- {
- scope = ScriptableObject.getVeryTopLevelScope(scope); // APPJET
- Function ctor = getExistingCtor(cx, scope, constructorName);
- if (args == null) { args = ScriptRuntime.emptyArgs; }
- return ctor.construct(cx, scope, args);
- }
-
- /**
- *
- * See ECMA 9.4.
- */
- public static double toInteger(Object val) {
- return toInteger(toNumber(val));
- }
-
- // convenience method
- public static double toInteger(double d) {
- // if it's NaN
- if (d != d)
- return +0.0;
-
- if (d == 0.0 ||
- d == Double.POSITIVE_INFINITY ||
- d == Double.NEGATIVE_INFINITY)
- return d;
-
- if (d > 0.0)
- return Math.floor(d);
- else
- return Math.ceil(d);
- }
-
- public static double toInteger(Object[] args, int index) {
- return (index < args.length) ? toInteger(args[index]) : +0.0;
- }
-
- /**
- *
- * See ECMA 9.5.
- */
- public static int toInt32(Object val)
- {
- // short circuit for common integer values
- if (val instanceof Integer)
- return ((Integer)val).intValue();
-
- return toInt32(toNumber(val));
- }
-
- public static int toInt32(Object[] args, int index) {
- return (index < args.length) ? toInt32(args[index]) : 0;
- }
-
- public static int toInt32(double d) {
- int id = (int)d;
- if (id == d) {
- // This covers -0.0 as well
- return id;
- }
-
- if (d != d
- || d == Double.POSITIVE_INFINITY
- || d == Double.NEGATIVE_INFINITY)
- {
- return 0;
- }
-
- d = (d >= 0) ? Math.floor(d) : Math.ceil(d);
-
- double two32 = 4294967296.0;
- d = Math.IEEEremainder(d, two32);
- // (double)(long)d == d should hold here
-
- long l = (long)d;
- // returning (int)d does not work as d can be outside int range
- // but the result must always be 32 lower bits of l
- return (int)l;
- }
-
- /**
- * See ECMA 9.6.
- * @return long value representing 32 bits unsigned integer
- */
- public static long toUint32(double d) {
- long l = (long)d;
- if (l == d) {
- // This covers -0.0 as well
- return l & 0xffffffffL;
- }
-
- if (d != d
- || d == Double.POSITIVE_INFINITY
- || d == Double.NEGATIVE_INFINITY)
- {
- return 0;
- }
-
- d = (d >= 0) ? Math.floor(d) : Math.ceil(d);
-
- // 0x100000000 gives me a numeric overflow...
- double two32 = 4294967296.0;
- l = (long)Math.IEEEremainder(d, two32);
-
- return l & 0xffffffffL;
- }
-
- public static long toUint32(Object val) {
- return toUint32(toNumber(val));
- }
-
- /**
- *
- * See ECMA 9.7.
- */
- public static char toUint16(Object val) {
- double d = toNumber(val);
-
- int i = (int)d;
- if (i == d) {
- return (char)i;
- }
-
- if (d != d
- || d == Double.POSITIVE_INFINITY
- || d == Double.NEGATIVE_INFINITY)
- {
- return 0;
- }
-
- d = (d >= 0) ? Math.floor(d) : Math.ceil(d);
-
- int int16 = 0x10000;
- i = (int)Math.IEEEremainder(d, int16);
-
- return (char)i;
- }
-
- // XXX: this is until setDefaultNamespace will learn how to store NS
- // properly and separates namespace form Scriptable.get etc.
- private static final String DEFAULT_NS_TAG = "__default_namespace__";
-
- public static Object setDefaultNamespace(Object namespace, Context cx)
- {
- Scriptable scope = cx.currentActivationCall;
- if (scope == null) {
- scope = getTopCallScope(cx);
- }
-
- XMLLib xmlLib = currentXMLLib(cx);
- Object ns = xmlLib.toDefaultXmlNamespace(cx, namespace);
-
- // XXX : this should be in separated namesapce from Scriptable.get/put
- if (!scope.has(DEFAULT_NS_TAG, scope)) {
- // XXX: this is racy of cause
- ScriptableObject.defineProperty(scope, DEFAULT_NS_TAG, ns,
- ScriptableObject.PERMANENT
- | ScriptableObject.DONTENUM);
- } else {
- scope.put(DEFAULT_NS_TAG, scope, ns);
- }
-
- return Undefined.instance;
- }
-
- public static Object searchDefaultNamespace(Context cx)
- {
- Scriptable scope = cx.currentActivationCall;
- if (scope == null) {
- scope = getTopCallScope(cx);
- }
- Object nsObject;
- for (;;) {
- Scriptable parent = scope.getParentScope();
- if (parent == null) {
- nsObject = ScriptableObject.getProperty(scope, DEFAULT_NS_TAG);
- if (nsObject == Scriptable.NOT_FOUND) {
- return null;
- }
- break;
- }
- nsObject = scope.get(DEFAULT_NS_TAG, scope);
- if (nsObject != Scriptable.NOT_FOUND) {
- break;
- }
- scope = parent;
- }
- return nsObject;
- }
-
- public static Object getTopLevelProp(Scriptable scope, String id) {
- scope = ScriptableObject.getTopLevelScope(scope);
- return ScriptableObject.getProperty(scope, id);
- }
-
- static Function getExistingCtor(Context cx, Scriptable scope,
- String constructorName)
- {
- Object ctorVal = ScriptableObject.getProperty(scope, constructorName);
- if (ctorVal instanceof Function) {
- return (Function)ctorVal;
- }
- if (ctorVal == Scriptable.NOT_FOUND) {
- throw Context.reportRuntimeError1(
- "msg.ctor.not.found", constructorName);
- } else {
- throw Context.reportRuntimeError1(
- "msg.not.ctor", constructorName);
- }
- }
-
- /**
- * Return -1L if str is not an index or the index value as lower 32
- * bits of the result.
- */
- private static long indexFromString(String str)
- {
- // The length of the decimal string representation of
- // Integer.MAX_VALUE, 2147483647
- final int MAX_VALUE_LENGTH = 10;
-
- int len = str.length();
- if (len > 0) {
- int i = 0;
- boolean negate = false;
- int c = str.charAt(0);
- if (c == '-') {
- if (len > 1) {
- c = str.charAt(1);
- i = 1;
- negate = true;
- }
- }
- c -= '0';
- if (0 <= c && c <= 9
- && len <= (negate ? MAX_VALUE_LENGTH + 1 : MAX_VALUE_LENGTH))
- {
- // Use negative numbers to accumulate index to handle
- // Integer.MIN_VALUE that is greater by 1 in absolute value
- // then Integer.MAX_VALUE
- int index = -c;
- int oldIndex = 0;
- i++;
- if (index != 0) {
- // Note that 00, 01, 000 etc. are not indexes
- while (i != len && 0 <= (c = str.charAt(i) - '0') && c <= 9)
- {
- oldIndex = index;
- index = 10 * index - c;
- i++;
- }
- }
- // Make sure all characters were consumed and that it couldn't
- // have overflowed.
- if (i == len &&
- (oldIndex > (Integer.MIN_VALUE / 10) ||
- (oldIndex == (Integer.MIN_VALUE / 10) &&
- c <= (negate ? -(Integer.MIN_VALUE % 10)
- : (Integer.MAX_VALUE % 10)))))
- {
- return 0xFFFFFFFFL & (negate ? index : -index);
- }
- }
- }
- return -1L;
- }
-
- /**
- * If str is a decimal presentation of Uint32 value, return it as long.
- * Othewise return -1L;
- */
- public static long testUint32String(String str)
- {
- // The length of the decimal string representation of
- // UINT32_MAX_VALUE, 4294967296
- final int MAX_VALUE_LENGTH = 10;
-
- int len = str.length();
- if (1 <= len && len <= MAX_VALUE_LENGTH) {
- int c = str.charAt(0);
- c -= '0';
- if (c == 0) {
- // Note that 00,01 etc. are not valid Uint32 presentations
- return (len == 1) ? 0L : -1L;
- }
- if (1 <= c && c <= 9) {
- long v = c;
- for (int i = 1; i != len; ++i) {
- c = str.charAt(i) - '0';
- if (!(0 <= c && c <= 9)) {
- return -1;
- }
- v = 10 * v + c;
- }
- // Check for overflow
- if ((v >>> 32) == 0) {
- return v;
- }
- }
- }
- return -1;
- }
-
- /**
- * If s represents index, then return index value wrapped as Integer
- * and othewise return s.
- */
- static Object getIndexObject(String s)
- {
- long indexTest = indexFromString(s);
- if (indexTest >= 0) {
- return new Integer((int)indexTest);
- }
- return s;
- }
-
- /**
- * If d is exact int value, return its value wrapped as Integer
- * and othewise return d converted to String.
- */
- static Object getIndexObject(double d)
- {
- int i = (int)d;
- if (i == d) {
- return new Integer(i);
- }
- return toString(d);
- }
-
- /**
- * If toString(id) is a decimal presentation of int32 value, then id
- * is index. In this case return null and make the index available
- * as ScriptRuntime.lastIndexResult(cx). Otherwise return toString(id).
- */
- static String toStringIdOrIndex(Context cx, Object id)
- {
- if (id instanceof Number) {
- double d = ((Number)id).doubleValue();
- int index = (int)d;
- if (index == d) {
- storeIndexResult(cx, index);
- return null;
- }
- return toString(id);
- } else {
- String s;
- if (id instanceof String) {
- s = (String)id;
- } else {
- s = toString(id);
- }
- long indexTest = indexFromString(s);
- if (indexTest >= 0) {
- storeIndexResult(cx, (int)indexTest);
- return null;
- }
- return s;
- }
- }
-
- /**
- * Call obj.[[Get]](id)
- */
- public static Object getObjectElem(Object obj, Object elem, Context cx)
- {
- Scriptable sobj = toObjectOrNull(cx, obj);
- if (sobj == null) {
- throw undefReadError(obj, elem);
- }
- return getObjectElem(sobj, elem, cx);
- }
-
- public static Object getObjectElem(Scriptable obj, Object elem,
- Context cx)
- {
- if (obj instanceof XMLObject) {
- XMLObject xmlObject = (XMLObject)obj;
- return xmlObject.ecmaGet(cx, elem);
- }
-
- Object result;
-
- String s = toStringIdOrIndex(cx, elem);
- if (s == null) {
- int index = lastIndexResult(cx);
- result = ScriptableObject.getProperty(obj, index);
- } else {
- result = ScriptableObject.getProperty(obj, s);
- }
-
- if (result == Scriptable.NOT_FOUND) {
- result = Undefined.instance;
- }
-
- return result;
- }
-
- /**
- * Version of getObjectElem when elem is a valid JS identifier name.
- */
- public static Object getObjectProp(Object obj, String property,
- Context cx)
- {
- Scriptable sobj = toObjectOrNull(cx, obj);
- if (sobj == null) {
- throw undefReadError(obj, property);
- }
- return getObjectProp(sobj, property, cx);
- }
-
- public static Object getObjectProp(Scriptable obj, String property,
- Context cx)
- {
- if (obj instanceof XMLObject) {
- // TODO: Change XMLObject to just use Scriptable interface
- // to avoid paying cost of instanceof check on *every property
- // lookup* !
- XMLObject xmlObject = (XMLObject)obj;
- return xmlObject.ecmaGet(cx, property);
- }
-
- Object result = ScriptableObject.getProperty(obj, property);
- if (result == Scriptable.NOT_FOUND) {
- if (cx.hasFeature(Context.FEATURE_STRICT_MODE)) {
- Context.reportWarning(ScriptRuntime.getMessage1(
- "msg.ref.undefined.prop", property));
- }
- result = Undefined.instance;
- }
-
- return result;
- }
-
- public static Object getObjectPropNoWarn(Object obj, String property,
- Context cx)
- {
- Scriptable sobj = toObjectOrNull(cx, obj);
- if (sobj == null) {
- throw undefReadError(obj, property);
- }
- if (obj instanceof XMLObject) {
- // TODO: fix as mentioned in note in method above
- getObjectProp(sobj, property, cx);
- }
- Object result = ScriptableObject.getProperty(sobj, property);
- if (result == Scriptable.NOT_FOUND) {
- return Undefined.instance;
- }
- return result;
- }
-
- /*
- * A cheaper and less general version of the above for well-known argument
- * types.
- */
- public static Object getObjectIndex(Object obj, double dblIndex,
- Context cx)
- {
- Scriptable sobj = toObjectOrNull(cx, obj);
- if (sobj == null) {
- throw undefReadError(obj, toString(dblIndex));
- }
-
- int index = (int)dblIndex;
- if (index == dblIndex) {
- return getObjectIndex(sobj, index, cx);
- } else {
- String s = toString(dblIndex);
- return getObjectProp(sobj, s, cx);
- }
- }
-
- public static Object getObjectIndex(Scriptable obj, int index,
- Context cx)
- {
- if (obj instanceof XMLObject) {
- XMLObject xmlObject = (XMLObject)obj;
- return xmlObject.ecmaGet(cx, new Integer(index));
- }
-
- Object result = ScriptableObject.getProperty(obj, index);
- if (result == Scriptable.NOT_FOUND) {
- result = Undefined.instance;
- }
-
- return result;
- }
-
- /*
- * Call obj.[[Put]](id, value)
- */
- public static Object setObjectElem(Object obj, Object elem, Object value,
- Context cx)
- {
- Scriptable sobj = toObjectOrNull(cx, obj);
- if (sobj == null) {
- throw undefWriteError(obj, elem, value);
- }
- return setObjectElem(sobj, elem, value, cx);
- }
-
- public static Object setObjectElem(Scriptable obj, Object elem,
- Object value, Context cx)
- {
- if (obj instanceof XMLObject) {
- XMLObject xmlObject = (XMLObject)obj;
- xmlObject.ecmaPut(cx, elem, value);
- return value;
- }
-
- String s = toStringIdOrIndex(cx, elem);
- if (s == null) {
- int index = lastIndexResult(cx);
- ScriptableObject.putProperty(obj, index, value);
- } else {
- ScriptableObject.putProperty(obj, s, value);
- }
-
- return value;
- }
-
- /**
- * Version of setObjectElem when elem is a valid JS identifier name.
- */
- public static Object setObjectProp(Object obj, String property,
- Object value, Context cx)
- {
- Scriptable sobj = toObjectOrNull(cx, obj);
- if (sobj == null) {
- throw undefWriteError(obj, property, value);
- }
- return setObjectProp(sobj, property, value, cx);
- }
-
- public static Object setObjectProp(Scriptable obj, String property,
- Object value, Context cx)
- {
- if (obj instanceof XMLObject) {
- XMLObject xmlObject = (XMLObject)obj;
- xmlObject.ecmaPut(cx, property, value);
- } else {
- ScriptableObject.putProperty(obj, property, value);
- }
- return value;
- }
-
- /*
- * A cheaper and less general version of the above for well-known argument
- * types.
- */
- public static Object setObjectIndex(Object obj, double dblIndex,
- Object value, Context cx)
- {
- Scriptable sobj = toObjectOrNull(cx, obj);
- if (sobj == null) {
- throw undefWriteError(obj, String.valueOf(dblIndex), value);
- }
-
- int index = (int)dblIndex;
- if (index == dblIndex) {
- return setObjectIndex(sobj, index, value, cx);
- } else {
- String s = toString(dblIndex);
- return setObjectProp(sobj, s, value, cx);
- }
- }
-
- public static Object setObjectIndex(Scriptable obj, int index, Object value,
- Context cx)
- {
- if (obj instanceof XMLObject) {
- XMLObject xmlObject = (XMLObject)obj;
- xmlObject.ecmaPut(cx, new Integer(index), value);
- } else {
- ScriptableObject.putProperty(obj, index, value);
- }
- return value;
- }
-
- public static boolean deleteObjectElem(Scriptable target, Object elem,
- Context cx)
- {
- boolean result;
- if (target instanceof XMLObject) {
- XMLObject xmlObject = (XMLObject)target;
- result = xmlObject.ecmaDelete(cx, elem);
- } else {
- String s = toStringIdOrIndex(cx, elem);
- if (s == null) {
- int index = lastIndexResult(cx);
- result = ScriptableObject.deleteProperty(target, index);
- } else {
- result = ScriptableObject.deleteProperty(target, s);
- }
- }
- return result;
- }
-
- public static boolean hasObjectElem(Scriptable target, Object elem,
- Context cx)
- {
- boolean result;
-
- if (target instanceof XMLObject) {
- XMLObject xmlObject = (XMLObject)target;
- result = xmlObject.ecmaHas(cx, elem);
- } else {
- String s = toStringIdOrIndex(cx, elem);
- if (s == null) {
- int index = lastIndexResult(cx);
- result = ScriptableObject.hasProperty(target, index);
- } else {
- result = ScriptableObject.hasProperty(target, s);
- }
- }
-
- return result;
- }
-
- public static Object refGet(Ref ref, Context cx)
- {
- return ref.get(cx);
- }
-
- public static Object refSet(Ref ref, Object value, Context cx)
- {
- return ref.set(cx, value);
- }
-
- public static Object refDel(Ref ref, Context cx)
- {
- return wrapBoolean(ref.delete(cx));
- }
-
- static boolean isSpecialProperty(String s)
- {
- return s.equals("__proto__") || s.equals("__parent__");
- }
-
- public static Ref specialRef(Object obj, String specialProperty,
- Context cx)
- {
- return SpecialRef.createSpecial(cx, obj, specialProperty);
- }
-
- /**
- * The delete operator
- *
- * See ECMA 11.4.1
- *
- * In ECMA 0.19, the description of the delete operator (11.4.1)
- * assumes that the [[Delete]] method returns a value. However,
- * the definition of the [[Delete]] operator (8.6.2.5) does not
- * define a return value. Here we assume that the [[Delete]]
- * method doesn't return a value.
- */
- public static Object delete(Object obj, Object id, Context cx)
- {
- Scriptable sobj = toObjectOrNull(cx, obj);
- if (sobj == null) {
- String idStr = (id == null) ? "null" : id.toString();
- throw typeError2("msg.undef.prop.delete", toString(obj), idStr);
- }
- boolean result = deleteObjectElem(sobj, id, cx);
- return wrapBoolean(result);
- }
-
- /**
- * Looks up a name in the scope chain and returns its value.
- */
- public static Object name(Context cx, Scriptable scope, String name)
- {
- Scriptable parent = scope.getParentScope();
- if (parent == null) {
- Object result = topScopeName(cx, scope, name);
- if (result == Scriptable.NOT_FOUND) {
- throw notFoundError(scope, name);
- }
- return result;
- }
-
- return nameOrFunction(cx, scope, parent, name, false);
- }
-
- private static Object nameOrFunction(Context cx, Scriptable scope,
- Scriptable parentScope, String name,
- boolean asFunctionCall)
- {
- Object result;
- Scriptable thisObj = scope; // It is used only if asFunctionCall==true.
-
- XMLObject firstXMLObject = null;
- for (;;) {
- if (scope instanceof NativeWith) {
- Scriptable withObj = scope.getPrototype();
- if (withObj instanceof XMLObject) {
- XMLObject xmlObj = (XMLObject)withObj;
- if (xmlObj.ecmaHas(cx, name)) {
- // function this should be the target object of with
- thisObj = xmlObj;
- result = xmlObj.ecmaGet(cx, name);
- break;
- }
- if (firstXMLObject == null) {
- firstXMLObject = xmlObj;
- }
- } else {
- result = ScriptableObject.getProperty(withObj, name);
- if (result != Scriptable.NOT_FOUND) {
- // function this should be the target object of with
- thisObj = withObj;
- break;
- }
- }
- } else if (scope instanceof NativeCall) {
- // NativeCall does not prototype chain and Scriptable.get
- // can be called directly.
- result = scope.get(name, scope);
- if (result != Scriptable.NOT_FOUND) {
- if (asFunctionCall) {
- // ECMA 262 requires that this for nested funtions
- // should be top scope
- thisObj = ScriptableObject.
- getTopLevelScope(parentScope);
- }
- break;
- }
- } else {
- // Can happen if Rhino embedding decided that nested
- // scopes are useful for what ever reasons.
- result = ScriptableObject.getProperty(scope, name);
- if (result != Scriptable.NOT_FOUND) {
- thisObj = scope;
- break;
- }
- }
- scope = parentScope;
- parentScope = parentScope.getParentScope();
- if (parentScope == null) {
- result = topScopeName(cx, scope, name);
- if (result == Scriptable.NOT_FOUND) {
- if (firstXMLObject == null || asFunctionCall) {
- throw notFoundError(scope, name);
- }
- // The name was not found, but we did find an XML
- // object in the scope chain and we are looking for name,
- // not function. The result should be an empty XMLList
- // in name context.
- result = firstXMLObject.ecmaGet(cx, name);
- }
- // For top scope thisObj for functions is always scope itself.
- thisObj = scope;
- break;
- }
- }
-
- if (asFunctionCall) {
- if (!(result instanceof Callable)) {
- throw notFunctionError(result, name);
- }
- storeScriptable(cx, thisObj);
- }
-
- return result;
- }
-
- private static Object topScopeName(Context cx, Scriptable scope,
- String name)
- {
- if (cx.useDynamicScope) {
- scope = checkDynamicScope(cx.topCallScope, scope);
- }
- return ScriptableObject.getProperty(scope, name);
- }
-
-
- /**
- * Returns the object in the scope chain that has a given property.
- *
- * The order of evaluation of an assignment expression involves
- * evaluating the lhs to a reference, evaluating the rhs, and then
- * modifying the reference with the rhs value. This method is used
- * to 'bind' the given name to an object containing that property
- * so that the side effects of evaluating the rhs do not affect
- * which property is modified.
- * Typically used in conjunction with setName.
- *
- * See ECMA 10.1.4
- */
- public static Scriptable bind(Context cx, Scriptable scope, String id)
- {
- Scriptable firstXMLObject = null;
- Scriptable parent = scope.getParentScope();
- childScopesChecks: if (parent != null) {
- // Check for possibly nested "with" scopes first
- while (scope instanceof NativeWith) {
- Scriptable withObj = scope.getPrototype();
- if (withObj instanceof XMLObject) {
- XMLObject xmlObject = (XMLObject)withObj;
- if (xmlObject.ecmaHas(cx, id)) {
- return xmlObject;
- }
- if (firstXMLObject == null) {
- firstXMLObject = xmlObject;
- }
- } else {
- if (ScriptableObject.hasProperty(withObj, id)) {
- return withObj;
- }
- }
- scope = parent;
- parent = parent.getParentScope();
- if (parent == null) {
- break childScopesChecks;
- }
- }
- for (;;) {
- if (ScriptableObject.hasProperty(scope, id)) {
- return scope;
- }
- scope = parent;
- parent = parent.getParentScope();
- if (parent == null) {
- break childScopesChecks;
- }
- }
- }
- // scope here is top scope
- if (cx.useDynamicScope) {
- scope = checkDynamicScope(cx.topCallScope, scope);
- }
- if (ScriptableObject.hasProperty(scope, id)) {
- return scope;
- }
- // Nothing was found, but since XML objects always bind
- // return one if found
- return firstXMLObject;
- }
-
- public static Object setName(Scriptable bound, Object value,
- Context cx, Scriptable scope, String id)
- {
- if (bound != null) {
- if (bound instanceof XMLObject) {
- XMLObject xmlObject = (XMLObject)bound;
- xmlObject.ecmaPut(cx, id, value);
- } else {
- ScriptableObject.putProperty(bound, id, value);
- }
- } else {
- // "newname = 7;", where 'newname' has not yet
- // been defined, creates a new property in the
- // top scope unless strict mode is specified.
- if (cx.hasFeature(Context.FEATURE_STRICT_MODE) ||
- cx.hasFeature(Context.FEATURE_STRICT_VARS))
- {
- Context.reportWarning(
- ScriptRuntime.getMessage1("msg.assn.create.strict", id));
- }
- // Find the top scope by walking up the scope chain.
- bound = ScriptableObject.getTopLevelScope(scope);
- if (cx.useDynamicScope) {
- bound = checkDynamicScope(cx.topCallScope, bound);
- }
- bound.put(id, bound, value);
- }
- return value;
- }
-
- public static Object setConst(Scriptable bound, Object value,
- Context cx, String id)
- {
- if (bound instanceof XMLObject) {
- XMLObject xmlObject = (XMLObject)bound;
- xmlObject.ecmaPut(cx, id, value);
- } else {
- ScriptableObject.putConstProperty(bound, id, value);
- }
- return value;
- }
-
- /**
- * This is the enumeration needed by the for..in statement.
- *
- * See ECMA 12.6.3.
- *
- * IdEnumeration maintains a ObjToIntMap to make sure a given
- * id is enumerated only once across multiple objects in a
- * prototype chain.
- *
- * XXX - ECMA delete doesn't hide properties in the prototype,
- * but js/ref does. This means that the js/ref for..in can
- * avoid maintaining a hash table and instead perform lookups
- * to see if a given property has already been enumerated.
- *
- */
- private static class IdEnumeration implements Serializable
- {
- private static final long serialVersionUID = 1L;
- Scriptable obj;
- Object[] ids;
- int index;
- ObjToIntMap used;
- Object currentId;
- int enumType; /* one of ENUM_INIT_KEYS, ENUM_INIT_VALUES,
- ENUM_INIT_ARRAY */
-
- // if true, integer ids will be returned as numbers rather than strings
- boolean enumNumbers;
-
- Scriptable iterator;
- }
-
- public static Scriptable toIterator(Context cx, Scriptable scope,
- Scriptable obj, boolean keyOnly)
- {
- /*APPJET 1.6*//*
- if (ScriptableObject.hasProperty(obj,
- NativeIterator.ITERATOR_PROPERTY_NAME))
- {
- Object v = ScriptableObject.getProperty(obj,
- NativeIterator.ITERATOR_PROPERTY_NAME);
- if (!(v instanceof Callable)) {
- throw typeError0("msg.invalid.iterator");
- }
- Callable f = (Callable) v;
- Object[] args = new Object[] { keyOnly ? Boolean.TRUE
- : Boolean.FALSE };
- v = f.call(cx, scope, obj, args);
- if (!(v instanceof Scriptable)) {
- throw typeError0("msg.iterator.primitive");
- }
- return (Scriptable) v;
- }*/
- return null;
- }
-
- // for backwards compatibility with generated class files
- public static Object enumInit(Object value, Context cx, boolean enumValues)
- {
- return enumInit(value, cx, enumValues ? ENUMERATE_VALUES
- : ENUMERATE_KEYS);
- }
-
- public static final int ENUMERATE_KEYS = 0;
- public static final int ENUMERATE_VALUES = 1;
- public static final int ENUMERATE_ARRAY = 2;
- public static final int ENUMERATE_KEYS_NO_ITERATOR = 3;
- public static final int ENUMERATE_VALUES_NO_ITERATOR = 4;
- public static final int ENUMERATE_ARRAY_NO_ITERATOR = 5;
-
- public static Object enumInit(Object value, Context cx, int enumType)
- {
- IdEnumeration x = new IdEnumeration();
- x.obj = toObjectOrNull(cx, value);
- if (x.obj == null) {
- // null or undefined do not cause errors but rather lead to empty
- // "for in" loop
- return x;
- }
- x.enumType = enumType;
- x.iterator = null;
- if (enumType != ENUMERATE_KEYS_NO_ITERATOR &&
- enumType != ENUMERATE_VALUES_NO_ITERATOR &&
- enumType != ENUMERATE_ARRAY_NO_ITERATOR)
- {
- x.iterator = toIterator(cx, x.obj.getParentScope(), x.obj, true);
- }
- if (x.iterator == null) {
- // enumInit should read all initial ids before returning
- // or "for (a.i in a)" would wrongly enumerate i in a as well
- enumChangeObject(x);
- }
-
- return x;
- }
-
- public static void setEnumNumbers(Object enumObj, boolean enumNumbers) {
- ((IdEnumeration)enumObj).enumNumbers = enumNumbers;
- }
-
- public static Boolean enumNext(Object enumObj)
- {
- IdEnumeration x = (IdEnumeration)enumObj;
- if (x.iterator != null) {
- Object v = ScriptableObject.getProperty(x.iterator, "next");
- if (!(v instanceof Callable))
- return Boolean.FALSE;
- Callable f = (Callable) v;
- Context cx = Context.enter();
- try {
- x.currentId = f.call(cx, x.iterator.getParentScope(),
- x.iterator, emptyArgs);
- return Boolean.TRUE;
- } catch (JavaScriptException e) {
- if (e.getValue() instanceof NativeIterator.StopIteration) {
- return Boolean.FALSE;
- }
- throw e;
- } finally {
- Context.exit();
- }
- }
- for (;;) {
- if (x.obj == null) {
- return Boolean.FALSE;
- }
- if (x.index == x.ids.length) {
- x.obj = x.obj.getPrototype();
- enumChangeObject(x);
- continue;
- }
- Object id = x.ids[x.index++];
- if (x.used != null && x.used.has(id)) {
- continue;
- }
- if (id instanceof String) {
- String strId = (String)id;
- if (!x.obj.has(strId, x.obj))
- continue; // must have been deleted
- x.currentId = strId;
- } else {
- int intId = ((Number)id).intValue();
- if (!x.obj.has(intId, x.obj))
- continue; // must have been deleted
- x.currentId = x.enumNumbers ? (Object) (new Integer(intId))
- : String.valueOf(intId);
- }
- return Boolean.TRUE;
- }
- }
-
- public static Object enumId(Object enumObj, Context cx)
- {
- IdEnumeration x = (IdEnumeration)enumObj;
- if (x.iterator != null) {
- return x.currentId;
- }
- switch (x.enumType) {
- case ENUMERATE_KEYS:
- case ENUMERATE_KEYS_NO_ITERATOR:
- return x.currentId;
- case ENUMERATE_VALUES:
- case ENUMERATE_VALUES_NO_ITERATOR:
- return enumValue(enumObj, cx);
- case ENUMERATE_ARRAY:
- case ENUMERATE_ARRAY_NO_ITERATOR:
- Object[] elements = { x.currentId, enumValue(enumObj, cx) };
- return cx.newArray(x.obj.getParentScope(), elements);
- default:
- throw Kit.codeBug();
- }
- }
-
- public static Object enumValue(Object enumObj, Context cx) {
- IdEnumeration x = (IdEnumeration)enumObj;
-
- Object result;
-
- String s = toStringIdOrIndex(cx, x.currentId);
- if (s == null) {
- int index = lastIndexResult(cx);
- result = x.obj.get(index, x.obj);
- } else {
- result = x.obj.get(s, x.obj);
- }
-
- return result;
- }
-
- private static void enumChangeObject(IdEnumeration x)
- {
- Object[] ids = null;
- while (x.obj != null) {
- ids = x.obj.getIds();
- if (ids.length != 0) {
- break;
- }
- x.obj = x.obj.getPrototype();
- }
- if (x.obj != null && x.ids != null) {
- Object[] previous = x.ids;
- int L = previous.length;
- if (x.used == null) {
- x.used = new ObjToIntMap(L);
- }
- for (int i = 0; i != L; ++i) {
- x.used.intern(previous[i]);
- }
- }
- x.ids = ids;
- x.index = 0;
- }
-
- /**
- * Prepare for calling name(...): return function corresponding to
- * name and make current top scope available
- * as ScriptRuntime.lastStoredScriptable() for consumption as thisObj.
- * The caller must call ScriptRuntime.lastStoredScriptable() immediately
- * after calling this method.
- */
- public static Callable getNameFunctionAndThis(String name,
- Context cx,
- Scriptable scope)
- {
- Scriptable parent = scope.getParentScope();
- if (parent == null) {
- Object result = topScopeName(cx, scope, name);
- if (!(result instanceof Callable)) {
- if (result == Scriptable.NOT_FOUND) {
- throw notFoundError(scope, name);
- } else {
- throw notFunctionError(result, name);
- }
- }
- // Top scope is not NativeWith or NativeCall => thisObj == scope
- Scriptable thisObj = scope;
- storeScriptable(cx, thisObj);
- return (Callable)result;
- }
-
- // name will call storeScriptable(cx, thisObj);
- return (Callable)nameOrFunction(cx, scope, parent, name, true);
- }
-
- /**
- * Prepare for calling obj[id](...): return function corresponding to
- * obj[id] and make obj properly converted to Scriptable available
- * as ScriptRuntime.lastStoredScriptable() for consumption as thisObj.
- * The caller must call ScriptRuntime.lastStoredScriptable() immediately
- * after calling this method.
- */
- public static Callable getElemFunctionAndThis(Object obj,
- Object elem,
- Context cx)
- {
- String s = toStringIdOrIndex(cx, elem);
- if (s != null) {
- return getPropFunctionAndThis(obj, s, cx);
- }
- int index = lastIndexResult(cx);
-
- Scriptable thisObj = toObjectOrNull(cx, obj);
- if (thisObj == null) {
- throw undefCallError(obj, String.valueOf(index));
- }
-
- Object value;
- for (;;) {
- // Ignore XML lookup as requred by ECMA 357, 11.2.2.1
- value = ScriptableObject.getProperty(thisObj, index);
- if (value != Scriptable.NOT_FOUND) {
- break;
- }
- if (!(thisObj instanceof XMLObject)) {
- break;
- }
- XMLObject xmlObject = (XMLObject)thisObj;
- Scriptable extra = xmlObject.getExtraMethodSource(cx);
- if (extra == null) {
- break;
- }
- thisObj = extra;
- }
- if (!(value instanceof Callable)) {
- throw notFunctionError(value, elem);
- }
-
- storeScriptable(cx, thisObj);
- return (Callable)value;
- }
-
- /**
- * Prepare for calling obj.property(...): return function corresponding to
- * obj.property and make obj properly converted to Scriptable available
- * as ScriptRuntime.lastStoredScriptable() for consumption as thisObj.
- * The caller must call ScriptRuntime.lastStoredScriptable() immediately
- * after calling this method.
- */
- public static Callable getPropFunctionAndThis(Object obj,
- String property,
- Context cx)
- {
- Scriptable thisObj = toObjectOrNull(cx, obj);
- if (thisObj == null) {
- throw undefCallError(obj, property);
- }
-
- Object value;
- for (;;) {
- // Ignore XML lookup as required by ECMA 357, 11.2.2.1
- value = ScriptableObject.getProperty(thisObj, property);
- if (value != Scriptable.NOT_FOUND) {
- break;
- }
- if (!(thisObj instanceof XMLObject)) {
- break;
- }
- XMLObject xmlObject = (XMLObject)thisObj;
- Scriptable extra = xmlObject.getExtraMethodSource(cx);
- if (extra == null) {
- break;
- }
- thisObj = extra;
- }
-
- if (!(value instanceof Callable)) {
- Object noSuchMethod = ScriptableObject.getProperty(thisObj, "__noSuchMethod__");
- if (noSuchMethod instanceof Callable)
- value = new NoSuchMethodShim((Callable)noSuchMethod, property);
- else
- throw notFunctionError(thisObj, value, property);
- }
-
- storeScriptable(cx, thisObj);
- return (Callable)value;
- }
-
- /**
- * Prepare for calling <expression>(...): return function corresponding to
- * <expression> and make parent scope of the function available
- * as ScriptRuntime.lastStoredScriptable() for consumption as thisObj.
- * The caller must call ScriptRuntime.lastStoredScriptable() immediately
- * after calling this method.
- */
- public static Callable getValueFunctionAndThis(Object value, Context cx)
- {
- if (!(value instanceof Callable)) {
- throw notFunctionError(value);
- }
-
- Callable f = (Callable)value;
- Scriptable thisObj = null;
- if (f instanceof Scriptable) {
- thisObj = ((Scriptable)f).getParentScope();
- }
- if (thisObj == null) {
- if (cx.topCallScope == null) throw new IllegalStateException();
- thisObj = cx.topCallScope;
- }
- if (thisObj.getParentScope() != null) {
- if (thisObj instanceof NativeWith) {
- // functions defined inside with should have with target
- // as their thisObj
- } else if (thisObj instanceof NativeCall) {
- // nested functions should have top scope as their thisObj
- thisObj = ScriptableObject.getTopLevelScope(thisObj);
- }
- }
- storeScriptable(cx, thisObj);
- return f;
- }
-
- /**
- * Perform function call in reference context. Should always
- * return value that can be passed to
- * {@link #refGet(Ref, Context)} or {@link #refSet(Ref, Object, Context)}
- * arbitrary number of times.
- * The args array reference should not be stored in any object that is
- * can be GC-reachable after this method returns. If this is necessary,
- * store args.clone(), not args array itself.
- */
- public static Ref callRef(Callable function, Scriptable thisObj,
- Object[] args, Context cx)
- {
- if (function instanceof RefCallable) {
- RefCallable rfunction = (RefCallable)function;
- Ref ref = rfunction.refCall(cx, thisObj, args);
- if (ref == null) {
- throw new IllegalStateException(rfunction.getClass().getName()+".refCall() returned null");
- }
- return ref;
- }
- // No runtime support for now
- String msg = getMessage1("msg.no.ref.from.function",
- toString(function));
- throw constructError("ReferenceError", msg);
- }
-
- /**
- * Operator new.
- *
- * See ECMA 11.2.2
- */
- public static Scriptable newObject(Object fun, Context cx,
- Scriptable scope, Object[] args)
- {
- if (!(fun instanceof Function)) {
- throw notFunctionError(fun);
- }
- Function function = (Function)fun;
- return function.construct(cx, scope, args);
- }
-
- public static Object callSpecial(Context cx, Callable fun,
- Scriptable thisObj,
- Object[] args, Scriptable scope,
- Scriptable callerThis, int callType,
- String filename, int lineNumber)
- {
- if (callType == Node.SPECIALCALL_EVAL) {
- if (NativeGlobal.isEvalFunction(fun)) {
- return evalSpecial(cx, scope, callerThis, args,
- filename, lineNumber);
- }
- } else if (callType == Node.SPECIALCALL_WITH) {
- if (NativeWith.isWithFunction(fun)) {
- throw Context.reportRuntimeError1("msg.only.from.new",
- "With");
- }
- } else {
- throw Kit.codeBug();
- }
-
- return fun.call(cx, scope, thisObj, args);
- }
-
- public static Object newSpecial(Context cx, Object fun,
- Object[] args, Scriptable scope,
- int callType)
- {
- if (callType == Node.SPECIALCALL_EVAL) {
- if (NativeGlobal.isEvalFunction(fun)) {
- throw typeError1("msg.not.ctor", "eval");
- }
- } else if (callType == Node.SPECIALCALL_WITH) {
- if (NativeWith.isWithFunction(fun)) {
- return NativeWith.newWithSpecial(cx, scope, args);
- }
- } else {
- throw Kit.codeBug();
- }
-
- return newObject(fun, cx, scope, args);
- }
-
- /**
- * Function.prototype.apply and Function.prototype.call
- *
- * See Ecma 15.3.4.[34]
- */
- public static Object applyOrCall(boolean isApply,
- Context cx, Scriptable scope,
- Scriptable thisObj, Object[] args)
- {
- int L = args.length;
- Callable function = getCallable(thisObj);
-
- Scriptable callThis = null;
- if (L != 0) {
- callThis = toObjectOrNull(cx, args[0]);
- }
- if (callThis == null) {
- // This covers the case of args[0] == (null|undefined) as well.
- callThis = getTopCallScope(cx);
- }
-
- Object[] callArgs;
- if (isApply) {
- // Follow Ecma 15.3.4.3
- callArgs = L <= 1 ? ScriptRuntime.emptyArgs :
- getApplyArguments(cx, args[1]);
- } else {
- // Follow Ecma 15.3.4.4
- if (L <= 1) {
- callArgs = ScriptRuntime.emptyArgs;
- } else {
- callArgs = new Object[L - 1];
- System.arraycopy(args, 1, callArgs, 0, L - 1);
- }
- }
-
- return function.call(cx, scope, callThis, callArgs);
- }
-
- static Object[] getApplyArguments(Context cx, Object arg1)
- {
- if (arg1 == null || arg1 == Undefined.instance) {
- return ScriptRuntime.emptyArgs;
- } else if (arg1 instanceof NativeArray || arg1 instanceof Arguments) {
- return cx.getElements((Scriptable) arg1);
- } else {
- throw ScriptRuntime.typeError0("msg.arg.isnt.array");
- }
- }
-
- static Callable getCallable(Scriptable thisObj)
- {
- Callable function;
- if (thisObj instanceof Callable) {
- function = (Callable)thisObj;
- } else {
- Object value = thisObj.getDefaultValue(ScriptRuntime.FunctionClass);
- if (!(value instanceof Callable)) {
- throw ScriptRuntime.notFunctionError(value, thisObj);
- }
- function = (Callable)value;
- }
- return function;
- }
-
- /**
- * The eval function property of the global object.
- *
- * See ECMA 15.1.2.1
- */
- public static Object evalSpecial(Context cx, Scriptable scope,
- Object thisArg, Object[] args,
- String filename, int lineNumber)
- {
- if (args.length < 1)
- return Undefined.instance;
- Object x = args[0];
- if (!(x instanceof String)) {
- if (cx.hasFeature(Context.FEATURE_STRICT_MODE) ||
- cx.hasFeature(Context.FEATURE_STRICT_EVAL))
- {
- throw Context.reportRuntimeError0("msg.eval.nonstring.strict");
- }
- String message = ScriptRuntime.getMessage0("msg.eval.nonstring");
- Context.reportWarning(message);
- return x;
- }
- if (filename == null) {
- int[] linep = new int[1];
- filename = Context.getSourcePositionFromStack(linep);
- if (filename != null) {
- lineNumber = linep[0];
- } else {
- filename = "";
- }
- }
- String sourceName = ScriptRuntime.
- makeUrlForGeneratedScript(true, filename, lineNumber);
-
- ErrorReporter reporter;
- reporter = DefaultErrorReporter.forEval(cx.getErrorReporter());
-
- Evaluator evaluator = Context.createInterpreter();
- if (evaluator == null) {
- throw new JavaScriptException("Interpreter not present",
- filename, lineNumber);
- }
-
- // Compile with explicit interpreter instance to force interpreter
- // mode.
- Script script = cx.compileString((String)x, evaluator,
- reporter, sourceName, 1, null);
- evaluator.setEvalScriptFlag(script);
- Callable c = (Callable)script;
- return c.call(cx, scope, (Scriptable)thisArg, ScriptRuntime.emptyArgs);
- }
-
- /**
- * The typeof operator
- */
- public static String typeof(Object value)
- {
- if (value == null)
- return "object";
- if (value == Undefined.instance)
- return "undefined";
- if (value instanceof Scriptable)
- {
- if (value instanceof ScriptableObject &&
- ((ScriptableObject)value).avoidObjectDetection())
- {
- return "undefined";
- }
- if (value instanceof XMLObject)
- return "xml";
- return (value instanceof Callable) ? "function" : "object";
- }
- if (value instanceof String)
- return "string";
- if (value instanceof Number)
- return "number";
- if (value instanceof Boolean)
- return "boolean";
- throw errorWithClassName("msg.invalid.type", value);
- }
-
- /**
- * The typeof operator that correctly handles the undefined case
- */
- public static String typeofName(Scriptable scope, String id)
- {
- Context cx = Context.getContext();
- Scriptable val = bind(cx, scope, id);
- if (val == null)
- return "undefined";
- return typeof(getObjectProp(val, id, cx));
- }
-
- // neg:
- // implement the '-' operator inline in the caller
- // as "-toNumber(val)"
-
- // not:
- // implement the '!' operator inline in the caller
- // as "!toBoolean(val)"
-
- // bitnot:
- // implement the '~' operator inline in the caller
- // as "~toInt32(val)"
-
- public static Object add(Object val1, Object val2, Context cx)
- {
- if(val1 instanceof Number && val2 instanceof Number) {
- return wrapNumber(((Number)val1).doubleValue() +
- ((Number)val2).doubleValue());
- }
- if (val1 instanceof XMLObject) {
- Object test = ((XMLObject)val1).addValues(cx, true, val2);
- if (test != Scriptable.NOT_FOUND) {
- return test;
- }
- }
- if (val2 instanceof XMLObject) {
- Object test = ((XMLObject)val2).addValues(cx, false, val1);
- if (test != Scriptable.NOT_FOUND) {
- return test;
- }
- }
- if (val1 instanceof Scriptable)
- val1 = ((Scriptable) val1).getDefaultValue(null);
- if (val2 instanceof Scriptable)
- val2 = ((Scriptable) val2).getDefaultValue(null);
- if (!(val1 instanceof String) && !(val2 instanceof String))
- if ((val1 instanceof Number) && (val2 instanceof Number))
- return wrapNumber(((Number)val1).doubleValue() +
- ((Number)val2).doubleValue());
- else
- return wrapNumber(toNumber(val1) + toNumber(val2));
- return toString(val1).concat(toString(val2));
- }
-
- public static String add(String val1, Object val2) {
- return val1.concat(toString(val2));
- }
-
- public static String add(Object val1, String val2) {
- return toString(val1).concat(val2);
- }
-
- /**
- * @deprecated The method is only present for compatibility.
- */
- public static Object nameIncrDecr(Scriptable scopeChain, String id,
- int incrDecrMask)
- {
- return nameIncrDecr(scopeChain, id, Context.getContext(), incrDecrMask);
- }
-
- public static Object nameIncrDecr(Scriptable scopeChain, String id,
- Context cx, int incrDecrMask)
- {
- Scriptable target;
- Object value;
- search: {
- do {
- if (cx.useDynamicScope && scopeChain.getParentScope() == null) {
- scopeChain = checkDynamicScope(cx.topCallScope, scopeChain);
- }
- target = scopeChain;
- do {
- value = target.get(id, scopeChain);
- if (value != Scriptable.NOT_FOUND) {
- break search;
- }
- target = target.getPrototype();
- } while (target != null);
- scopeChain = scopeChain.getParentScope();
- } while (scopeChain != null);
- throw notFoundError(scopeChain, id);
- }
- return doScriptableIncrDecr(target, id, scopeChain, value,
- incrDecrMask);
- }
-
- public static Object propIncrDecr(Object obj, String id,
- Context cx, int incrDecrMask)
- {
- Scriptable start = toObjectOrNull(cx, obj);
- if (start == null) {
- throw undefReadError(obj, id);
- }
-
- Scriptable target = start;
- Object value;
- search: {
- do {
- value = target.get(id, start);
- if (value != Scriptable.NOT_FOUND) {
- break search;
- }
- target = target.getPrototype();
- } while (target != null);
- start.put(id, start, NaNobj);
- return NaNobj;
- }
- return doScriptableIncrDecr(target, id, start, value,
- incrDecrMask);
- }
-
- private static Object doScriptableIncrDecr(Scriptable target,
- String id,
- Scriptable protoChainStart,
- Object value,
- int incrDecrMask)
- {
- boolean post = ((incrDecrMask & Node.POST_FLAG) != 0);
- double number;
- if (value instanceof Number) {
- number = ((Number)value).doubleValue();
- } else {
- number = toNumber(value);
- if (post) {
- // convert result to number
- value = wrapNumber(number);
- }
- }
- if ((incrDecrMask & Node.DECR_FLAG) == 0) {
- ++number;
- } else {
- --number;
- }
- Number result = wrapNumber(number);
- target.put(id, protoChainStart, result);
- if (post) {
- return value;
- } else {
- return result;
- }
- }
-
- public static Object elemIncrDecr(Object obj, Object index,
- Context cx, int incrDecrMask)
- {
- Object value = getObjectElem(obj, index, cx);
- boolean post = ((incrDecrMask & Node.POST_FLAG) != 0);
- double number;
- if (value instanceof Number) {
- number = ((Number)value).doubleValue();
- } else {
- number = toNumber(value);
- if (post) {
- // convert result to number
- value = wrapNumber(number);
- }
- }
- if ((incrDecrMask & Node.DECR_FLAG) == 0) {
- ++number;
- } else {
- --number;
- }
- Number result = wrapNumber(number);
- setObjectElem(obj, index, result, cx);
- if (post) {
- return value;
- } else {
- return result;
- }
- }
-
- public static Object refIncrDecr(Ref ref, Context cx, int incrDecrMask)
- {
- Object value = ref.get(cx);
- boolean post = ((incrDecrMask & Node.POST_FLAG) != 0);
- double number;
- if (value instanceof Number) {
- number = ((Number)value).doubleValue();
- } else {
- number = toNumber(value);
- if (post) {
- // convert result to number
- value = wrapNumber(number);
- }
- }
- if ((incrDecrMask & Node.DECR_FLAG) == 0) {
- ++number;
- } else {
- --number;
- }
- Number result = wrapNumber(number);
- ref.set(cx, result);
- if (post) {
- return value;
- } else {
- return result;
- }
- }
-
- private static Object toPrimitive(Object val)
- {
- if (!(val instanceof Scriptable)) {
- return val;
- }
- Scriptable s = (Scriptable)val;
- Object result = s.getDefaultValue(null);
- if (result instanceof Scriptable)
- throw typeError0("msg.bad.default.value");
- return result;
- }
-
- /**
- * Equality
- *
- * See ECMA 11.9
- */
- public static boolean eq(Object x, Object y)
- {
- if (x == null || x == Undefined.instance) {
- if (y == null || y == Undefined.instance) {
- return true;
- }
- if (y instanceof ScriptableObject) {
- Object test = ((ScriptableObject)y).equivalentValues(x);
- if (test != Scriptable.NOT_FOUND) {
- return ((Boolean)test).booleanValue();
- }
- }
- return false;
- } else if (x instanceof Number) {
- return eqNumber(((Number)x).doubleValue(), y);
- } else if (x instanceof String) {
- return eqString((String)x, y);
- } else if (x instanceof Boolean) {
- boolean b = ((Boolean)x).booleanValue();
- if (y instanceof Boolean) {
- return b == ((Boolean)y).booleanValue();
- }
- if (y instanceof ScriptableObject) {
- Object test = ((ScriptableObject)y).equivalentValues(x);
- if (test != Scriptable.NOT_FOUND) {
- return ((Boolean)test).booleanValue();
- }
- }
- return eqNumber(b ? 1.0 : 0.0, y);
- } else if (x instanceof Scriptable) {
- if (y instanceof Scriptable) {
- if (x == y) {
- return true;
- }
- if (x instanceof ScriptableObject) {
- Object test = ((ScriptableObject)x).equivalentValues(y);
- if (test != Scriptable.NOT_FOUND) {
- return ((Boolean)test).booleanValue();
- }
- }
- if (y instanceof ScriptableObject) {
- Object test = ((ScriptableObject)y).equivalentValues(x);
- if (test != Scriptable.NOT_FOUND) {
- return ((Boolean)test).booleanValue();
- }
- }
- if (x instanceof Wrapper && y instanceof Wrapper) {
- // See bug 413838. Effectively an extension to ECMA for
- // the LiveConnect case.
- Object unwrappedX = ((Wrapper)x).unwrap();
- Object unwrappedY = ((Wrapper)y).unwrap();
- return unwrappedX == unwrappedY ||
- (isPrimitive(unwrappedX) &&
- isPrimitive(unwrappedY) &&
- eq(unwrappedX, unwrappedY));
- }
- return false;
- } else if (y instanceof Boolean) {
- if (x instanceof ScriptableObject) {
- Object test = ((ScriptableObject)x).equivalentValues(y);
- if (test != Scriptable.NOT_FOUND) {
- return ((Boolean)test).booleanValue();
- }
- }
- double d = ((Boolean)y).booleanValue() ? 1.0 : 0.0;
- return eqNumber(d, x);
- } else if (y instanceof Number) {
- return eqNumber(((Number)y).doubleValue(), x);
- } else if (y instanceof String) {
- return eqString((String)y, x);
- }
- // covers the case when y == Undefined.instance as well
- return false;
- } else {
- warnAboutNonJSObject(x);
- return x == y;
- }
- }
-
- private static boolean isPrimitive(Object obj) {
- return (obj instanceof Number) || (obj instanceof String) ||
- (obj instanceof Boolean);
- }
-
- static boolean eqNumber(double x, Object y)
- {
- for (;;) {
- if (y == null || y == Undefined.instance) {
- return false;
- } else if (y instanceof Number) {
- return x == ((Number)y).doubleValue();
- } else if (y instanceof String) {
- return x == toNumber(y);
- } else if (y instanceof Boolean) {
- return x == (((Boolean)y).booleanValue() ? 1.0 : +0.0);
- } else if (y instanceof Scriptable) {
- if (y instanceof ScriptableObject) {
- Object xval = wrapNumber(x);
- Object test = ((ScriptableObject)y).equivalentValues(xval);
- if (test != Scriptable.NOT_FOUND) {
- return ((Boolean)test).booleanValue();
- }
- }
- y = toPrimitive(y);
- } else {
- warnAboutNonJSObject(y);
- return false;
- }
- }
- }
-
- private static boolean eqString(String x, Object y)
- {
- for (;;) {
- if (y == null || y == Undefined.instance) {
- return false;
- } else if (y instanceof String) {
- return x.equals(y);
- } else if (y instanceof Number) {
- return toNumber(x) == ((Number)y).doubleValue();
- } else if (y instanceof Boolean) {
- return toNumber(x) == (((Boolean)y).booleanValue() ? 1.0 : 0.0);
- } else if (y instanceof Scriptable) {
- if (y instanceof ScriptableObject) {
- Object test = ((ScriptableObject)y).equivalentValues(x);
- if (test != Scriptable.NOT_FOUND) {
- return ((Boolean)test).booleanValue();
- }
- }
- y = toPrimitive(y);
- continue;
- } else {
- warnAboutNonJSObject(y);
- return false;
- }
- }
- }
- public static boolean shallowEq(Object x, Object y)
- {
- if (x == y) {
- if (!(x instanceof Number)) {
- return true;
- }
- // NaN check
- double d = ((Number)x).doubleValue();
- return d == d;
- }
- if (x == null || x == Undefined.instance) {
- return false;
- } else if (x instanceof Number) {
- if (y instanceof Number) {
- return ((Number)x).doubleValue() == ((Number)y).doubleValue();
- }
- } else if (x instanceof String) {
- if (y instanceof String) {
- return x.equals(y);
- }
- } else if (x instanceof Boolean) {
- if (y instanceof Boolean) {
- return x.equals(y);
- }
- } else if (x instanceof Scriptable) {
- if (x instanceof Wrapper && y instanceof Wrapper) {
- return ((Wrapper)x).unwrap() == ((Wrapper)y).unwrap();
- }
- } else {
- warnAboutNonJSObject(x);
- return x == y;
- }
- return false;
- }
-
- /**
- * The instanceof operator.
- *
- * @return a instanceof b
- */
- public static boolean instanceOf(Object a, Object b, Context cx)
- {
- // Check RHS is an object
- if (! (b instanceof Scriptable)) {
- throw typeError0("msg.instanceof.not.object");
- }
-
- // for primitive values on LHS, return false
- // XXX we may want to change this so that
- // 5 instanceof Number == true
- if (! (a instanceof Scriptable))
- return false;
-
- return ((Scriptable)b).hasInstance((Scriptable)a);
- }
-
- /**
- * Delegates to
- *
- * @return true iff rhs appears in lhs' proto chain
- */
- public static boolean jsDelegatesTo(Scriptable lhs, Scriptable rhs) {
- Scriptable proto = lhs.getPrototype();
-
- while (proto != null) {
- if (proto.equals(rhs)) return true;
- proto = proto.getPrototype();
- }
-
- return false;
- }
-
- /**
- * The in operator.
- *
- * This is a new JS 1.3 language feature. The in operator mirrors
- * the operation of the for .. in construct, and tests whether the
- * rhs has the property given by the lhs. It is different from the
- * for .. in construct in that:
- * <BR> - it doesn't perform ToObject on the right hand side
- * <BR> - it returns true for DontEnum properties.
- * @param a the left hand operand
- * @param b the right hand operand
- *
- * @return true if property name or element number a is a property of b
- */
- public static boolean in(Object a, Object b, Context cx)
- {
- if (!(b instanceof Scriptable)) {
- throw typeError0("msg.instanceof.not.object");
- }
-
- return hasObjectElem((Scriptable)b, a, cx);
- }
-
- public static boolean cmp_LT(Object val1, Object val2)
- {
- double d1, d2;
- if (val1 instanceof Number && val2 instanceof Number) {
- d1 = ((Number)val1).doubleValue();
- d2 = ((Number)val2).doubleValue();
- } else {
- if (val1 instanceof Scriptable)
- val1 = ((Scriptable) val1).getDefaultValue(NumberClass);
- if (val2 instanceof Scriptable)
- val2 = ((Scriptable) val2).getDefaultValue(NumberClass);
- if (val1 instanceof String && val2 instanceof String) {
- return ((String)val1).compareTo((String)val2) < 0;
- }
- d1 = toNumber(val1);
- d2 = toNumber(val2);
- }
- return d1 < d2;
- }
-
- public static boolean cmp_LE(Object val1, Object val2)
- {
- double d1, d2;
- if (val1 instanceof Number && val2 instanceof Number) {
- d1 = ((Number)val1).doubleValue();
- d2 = ((Number)val2).doubleValue();
- } else {
- if (val1 instanceof Scriptable)
- val1 = ((Scriptable) val1).getDefaultValue(NumberClass);
- if (val2 instanceof Scriptable)
- val2 = ((Scriptable) val2).getDefaultValue(NumberClass);
- if (val1 instanceof String && val2 instanceof String) {
- return ((String)val1).compareTo((String)val2) <= 0;
- }
- d1 = toNumber(val1);
- d2 = toNumber(val2);
- }
- return d1 <= d2;
- }
-
- // ------------------
- // Statements
- // ------------------
-
- public static ScriptableObject getGlobal(Context cx) {
- final String GLOBAL_CLASS = "org.mozilla.javascript.tools.shell.Global";
- Class globalClass = Kit.classOrNull(GLOBAL_CLASS);
- if (globalClass != null) {
- try {
- Class[] parm = { ScriptRuntime.ContextClass };
- Constructor globalClassCtor = globalClass.getConstructor(parm);
- Object[] arg = { cx };
- return (ScriptableObject) globalClassCtor.newInstance(arg);
- } catch (Exception e) {
- // fall through...
- }
- }
- return new ImporterTopLevel(cx);
- }
-
- public static boolean hasTopCall(Context cx)
- {
- return (cx.topCallScope != null);
- }
-
- public static Scriptable getTopCallScope(Context cx)
- {
- Scriptable scope = cx.topCallScope;
- if (scope == null) {
- throw new IllegalStateException();
- }
- return scope;
- }
-
- public static Object doTopCall(Callable callable,
- Context cx, Scriptable scope,
- Scriptable thisObj, Object[] args)
- {
- if (scope == null) throw new IllegalArgumentException();
- if (cx.topCallScope != null) throw new IllegalStateException();
-
- Object result;
- cx.topCallScope = ScriptableObject.getTopLevelScope(scope);
- cx.useDynamicScope = cx.hasFeature(Context.FEATURE_DYNAMIC_SCOPE);
- ContextFactory f = cx.getFactory();
- try {
- result = f.doTopCall(callable, cx, scope, thisObj, args);
- } finally {
- cx.topCallScope = null;
- // Cleanup cached references
- cx.cachedXMLLib = null;
-
- if (cx.currentActivationCall != null) {
- // Function should always call exitActivationFunction
- // if it creates activation record
- throw new IllegalStateException();
- }
- }
- return result;
- }
-
- /**
- * Return <tt>possibleDynamicScope</tt> if <tt>staticTopScope</tt>
- * is present on its prototype chain and return <tt>staticTopScope</tt>
- * otherwise.
- * Should only be called when <tt>staticTopScope</tt> is top scope.
- */
- static Scriptable checkDynamicScope(Scriptable possibleDynamicScope,
- Scriptable staticTopScope)
- {
- // Return cx.topCallScope if scope
- if (possibleDynamicScope == staticTopScope) {
- return possibleDynamicScope;
- }
- Scriptable proto = possibleDynamicScope;
- for (;;) {
- proto = proto.getPrototype();
- if (proto == staticTopScope) {
- return possibleDynamicScope;
- }
- if (proto == null) {
- return staticTopScope;
- }
- }
- }
-
- public static void addInstructionCount(Context cx, int instructionsToAdd)
- {
- cx.instructionCount += instructionsToAdd;
- if (cx.instructionCount > cx.instructionThreshold)
- {
- cx.observeInstructionCount(cx.instructionCount);
- cx.instructionCount = 0;
- }
- }
-
- public static void initScript(NativeFunction funObj, Scriptable thisObj,
- Context cx, Scriptable scope,
- boolean evalScript)
- {
- if (cx.topCallScope == null)
- throw new IllegalStateException();
-
- int varCount = funObj.getParamAndVarCount();
- if (varCount != 0) {
-
- Scriptable varScope = scope;
- // Never define any variables from var statements inside with
- // object. See bug 38590.
- while (varScope instanceof NativeWith) {
- varScope = varScope.getParentScope();
- }
-
- for (int i = varCount; i-- != 0;) {
- String name = funObj.getParamOrVarName(i);
- boolean isConst = funObj.getParamOrVarConst(i);
- // Don't overwrite existing def if already defined in object
- // or prototypes of object.
- if (!ScriptableObject.hasProperty(scope, name)) {
- if (!evalScript) {
- // Global var definitions are supposed to be DONTDELETE
- if (isConst)
- ScriptableObject.defineConstProperty(varScope, name);
- else
- ScriptableObject.defineProperty(
- varScope, name, Undefined.instance,
- ScriptableObject.PERMANENT);
- } else {
- varScope.put(name, varScope, Undefined.instance);
- }
- } else {
- ScriptableObject.redefineProperty(scope, name, isConst);
- }
- }
- }
- }
-
- public static Scriptable createFunctionActivation(NativeFunction funObj,
- Scriptable scope,
- Object[] args)
- {
- return new NativeCall(funObj, scope, args);
- }
-
-
- public static void enterActivationFunction(Context cx,
- Scriptable scope)
- {
- if (cx.topCallScope == null)
- throw new IllegalStateException();
- NativeCall call = (NativeCall)scope;
- call.parentActivationCall = cx.currentActivationCall;
- cx.currentActivationCall = call;
- }
-
- public static void exitActivationFunction(Context cx)
- {
- NativeCall call = cx.currentActivationCall;
- cx.currentActivationCall = call.parentActivationCall;
- call.parentActivationCall = null;
- }
-
- static NativeCall findFunctionActivation(Context cx, Function f)
- {
- NativeCall call = cx.currentActivationCall;
- while (call != null) {
- if (call.function == f)
- return call;
- call = call.parentActivationCall;
- }
- return null;
- }
-
- public static Scriptable newCatchScope(Throwable t,
- Scriptable lastCatchScope,
- String exceptionName,
- Context cx, Scriptable scope)
- {
- Object obj;
- boolean cacheObj;
-
- getObj:
- if (t instanceof JavaScriptException) {
- cacheObj = false;
- obj = ((JavaScriptException)t).getValue();
- } else {
- cacheObj = true;
-
- // Create wrapper object unless it was associated with
- // the previous scope object
-
- if (lastCatchScope != null) {
- NativeObject last = (NativeObject)lastCatchScope;
- obj = last.getAssociatedValue(t);
- if (obj == null) Kit.codeBug();
- break getObj;
- }
-
- RhinoException re;
- String errorName;
- String errorMsg;
- Throwable javaException = null;
-
- if (t instanceof EcmaError) {
- EcmaError ee = (EcmaError)t;
- re = ee;
- errorName = ee.getName();
- errorMsg = ee.getErrorMessage();
- } else if (t instanceof WrappedException) {
- WrappedException we = (WrappedException)t;
- re = we;
- javaException = we.getWrappedException();
- errorName = "JavaException";
- errorMsg = javaException.getClass().getName()
- +": "+javaException.getMessage();
- } else if (t instanceof EvaluatorException) {
- // Pure evaluator exception, nor WrappedException instance
- EvaluatorException ee = (EvaluatorException)t;
- re = ee;
- errorName = "InternalError";
- errorMsg = ee.getMessage();
- } else if (cx.hasFeature(Context.FEATURE_ENHANCED_JAVA_ACCESS)) {
- // With FEATURE_ENHANCED_JAVA_ACCESS, scripts can catch
- // all exception types
- re = new WrappedException(t);
- errorName = "JavaException";
- errorMsg = t.toString();
- } else {
- // Script can catch only instances of JavaScriptException,
- // EcmaError and EvaluatorException
- throw Kit.codeBug();
- }
-
- String sourceUri = re.sourceName();
- if (sourceUri == null) {
- sourceUri = "";
- }
- int line = re.lineNumber();
- Object args[];
- if (line > 0) {
- args = new Object[] { errorMsg, sourceUri, new Integer(line) };
- } else {
- args = new Object[] { errorMsg, sourceUri };
- }
-
- Scriptable errorObject = cx.newObject(scope, errorName, args);
- ScriptableObject.putProperty(errorObject, "name", errorName);
-
- if (javaException != null) {
- Object wrap = cx.getWrapFactory().wrap(cx, scope, javaException,
- null);
- ScriptableObject.defineProperty(
- errorObject, "javaException", wrap,
- ScriptableObject.PERMANENT | ScriptableObject.READONLY);
- }
- Object wrap = cx.getWrapFactory().wrap(cx, scope, re, null);
- ScriptableObject.defineProperty(
- errorObject, "rhinoException", wrap,
- ScriptableObject.PERMANENT | ScriptableObject.READONLY);
-
- obj = errorObject;
- }
-
- NativeObject catchScopeObject = new NativeObject();
- // See ECMA 12.4
- catchScopeObject.defineProperty(
- exceptionName, obj, ScriptableObject.PERMANENT);
-
- // Add special Rhino object __exception__ defined in the catch
- // scope that can be used to retrieve the Java exception associated
- // with the JavaScript exception (to get stack trace info, etc.)
- /*APPJET NOJAVA*/
- /*catchScopeObject.defineProperty(
- "__exception__", Context.javaToJS(t, scope),
- ScriptableObject.PERMANENT|ScriptableObject.DONTENUM);*/
-
- if (cacheObj) {
- catchScopeObject.associateValue(t, obj);
- }
- return catchScopeObject;
- }
-
- public static Scriptable enterWith(Object obj, Context cx,
- Scriptable scope)
- {
- Scriptable sobj = toObjectOrNull(cx, obj);
- if (sobj == null) {
- throw typeError1("msg.undef.with", toString(obj));
- }
- if (sobj instanceof XMLObject) {
- XMLObject xmlObject = (XMLObject)sobj;
- return xmlObject.enterWith(scope);
- }
- return new NativeWith(scope, sobj);
- }
-
- public static Scriptable leaveWith(Scriptable scope)
- {
- NativeWith nw = (NativeWith)scope;
- return nw.getParentScope();
- }
-
- public static Scriptable enterDotQuery(Object value, Scriptable scope)
- {
- if (!(value instanceof XMLObject)) {
- throw notXmlError(value);
- }
- XMLObject object = (XMLObject)value;
- return object.enterDotQuery(scope);
- }
-
- public static Object updateDotQuery(boolean value, Scriptable scope)
- {
- // Return null to continue looping
- NativeWith nw = (NativeWith)scope;
- return nw.updateDotQuery(value);
- }
-
- public static Scriptable leaveDotQuery(Scriptable scope)
- {
- NativeWith nw = (NativeWith)scope;
- return nw.getParentScope();
- }
-
- public static void setFunctionProtoAndParent(BaseFunction fn,
- Scriptable scope)
- {
- fn.setParentScope(scope);
- fn.setPrototype(ScriptableObject.getFunctionPrototype(scope));
- }
-
- public static void setObjectProtoAndParent(ScriptableObject object,
- Scriptable scope)
- {
- // Compared with function it always sets the scope to top scope
- scope = ScriptableObject.getVeryTopLevelScope(scope); // APPJET
- object.setParentScope(scope);
- Scriptable proto
- = ScriptableObject.getClassPrototype(scope, object.getClassName());
- object.setPrototype(proto);
- }
-
- public static void initFunction(Context cx, Scriptable scope,
- NativeFunction function, int type,
- boolean fromEvalCode)
- {
- if (type == FunctionNode.FUNCTION_STATEMENT) {
- String name = function.getFunctionName();
- if (name != null && name.length() != 0) {
- if (!fromEvalCode) {
- // ECMA specifies that functions defined in global and
- // function scope outside eval should have DONTDELETE set.
- ScriptableObject.defineProperty
- (scope, name, function, ScriptableObject.PERMANENT);
- } else {
- scope.put(name, scope, function);
- }
- }
- } else if (type == FunctionNode.FUNCTION_EXPRESSION_STATEMENT) {
- String name = function.getFunctionName();
- if (name != null && name.length() != 0) {
- // Always put function expression statements into initial
- // activation object ignoring the with statement to follow
- // SpiderMonkey
- while (scope instanceof NativeWith) {
- scope = scope.getParentScope();
- }
- scope.put(name, scope, function);
- }
- } else {
- throw Kit.codeBug();
- }
- }
-
- public static Scriptable newArrayLiteral(Object[] objects,
- int[] skipIndices,
- Context cx, Scriptable scope)
- {
- final int SKIP_DENSITY = 2;
- int count = objects.length;
- int skipCount = 0;
- if (skipIndices != null) {
- skipCount = skipIndices.length;
- }
- int length = count + skipCount;
- if (length > 1 && skipCount * SKIP_DENSITY < length) {
- // If not too sparse, create whole array for constructor
- Object[] sparse;
- if (skipCount == 0) {
- sparse = objects;
- } else {
- sparse = new Object[length];
- int skip = 0;
- for (int i = 0, j = 0; i != length; ++i) {
- if (skip != skipCount && skipIndices[skip] == i) {
- sparse[i] = Scriptable.NOT_FOUND;
- ++skip;
- continue;
- }
- sparse[i] = objects[j];
- ++j;
- }
- }
- return cx.newObject(scope, "Array", sparse);
- }
-
- Scriptable arrayObj = cx.newObject(scope, "Array",
- ScriptRuntime.emptyArgs);
- int skip = 0;
- for (int i = 0, j = 0; i != length; ++i) {
- if (skip != skipCount && skipIndices[skip] == i) {
- ++skip;
- continue;
- }
- ScriptableObject.putProperty(arrayObj, i, objects[j]);
- ++j;
- }
- return arrayObj;
- }
-
- /**
- * This method is here for backward compat with existing compiled code. It
- * is called when an object literal is compiled. The next instance will be
- * the version called from new code.
- * @deprecated This method only present for compatibility.
- */
- public static Scriptable newObjectLiteral(Object[] propertyIds,
- Object[] propertyValues,
- Context cx, Scriptable scope)
- {
- // This will initialize to all zeros, exactly what we need for old-style
- // getterSetters values (no getters or setters in the list)
- int [] getterSetters = new int[propertyIds.length];
- return newObjectLiteral(propertyIds, propertyValues, getterSetters,
- cx, scope);
- }
-
- public static Scriptable newObjectLiteral(Object[] propertyIds,
- Object[] propertyValues,
- int [] getterSetters,
- Context cx, Scriptable scope)
- {
- Scriptable object = cx.newObject(scope);
- for (int i = 0, end = propertyIds.length; i != end; ++i) {
- Object id = propertyIds[i];
- int getterSetter = getterSetters[i];
- Object value = propertyValues[i];
- if (id instanceof String) {
- if (getterSetter == 0)
- ScriptableObject.putProperty(object, (String)id, value);
- else {
- Callable fun;
- String definer;
- if (getterSetter < 0) // < 0 means get foo() ...
- definer = "__defineGetter__";
- else
- definer = "__defineSetter__";
- fun = getPropFunctionAndThis(object, definer, cx);
- // Must consume the last scriptable object in cx
- lastStoredScriptable(cx);
- Object[] outArgs = new Object[2];
- outArgs[0] = id;
- outArgs[1] = value;
- fun.call(cx, scope, object, outArgs);
- }
- } else {
- int index = ((Integer)id).intValue();
- ScriptableObject.putProperty(object, index, value);
- }
- }
- return object;
- }
-
- public static boolean isArrayObject(Object obj)
- {
- return obj instanceof NativeArray || obj instanceof Arguments;
- }
-
- public static Object[] getArrayElements(Scriptable object)
- {
- Context cx = Context.getContext();
- long longLen = NativeArray.getLengthProperty(cx, object);
- if (longLen > Integer.MAX_VALUE) {
- // arrays beyond MAX_INT is not in Java in any case
- throw new IllegalArgumentException();
- }
- int len = (int) longLen;
- if (len == 0) {
- return ScriptRuntime.emptyArgs;
- } else {
- Object[] result = new Object[len];
- for (int i=0; i < len; i++) {
- Object elem = ScriptableObject.getProperty(object, i);
- result[i] = (elem == Scriptable.NOT_FOUND) ? Undefined.instance
- : elem;
- }
- return result;
- }
- }
-
- static void checkDeprecated(Context cx, String name) {
- int version = cx.getLanguageVersion();
- if (version >= Context.VERSION_1_4 || version == Context.VERSION_DEFAULT) {
- String msg = getMessage1("msg.deprec.ctor", name);
- if (version == Context.VERSION_DEFAULT)
- Context.reportWarning(msg);
- else
- throw Context.reportRuntimeError(msg);
- }
- }
-
- public static String getMessage0(String messageId)
- {
- return getMessage(messageId, null);
- }
-
- public static String getMessage1(String messageId, Object arg1)
- {
- Object[] arguments = {arg1};
- return getMessage(messageId, arguments);
- }
-
- public static String getMessage2(
- String messageId, Object arg1, Object arg2)
- {
- Object[] arguments = {arg1, arg2};
- return getMessage(messageId, arguments);
- }
-
- public static String getMessage3(
- String messageId, Object arg1, Object arg2, Object arg3)
- {
- Object[] arguments = {arg1, arg2, arg3};
- return getMessage(messageId, arguments);
- }
-
- public static String getMessage4(
- String messageId, Object arg1, Object arg2, Object arg3, Object arg4)
- {
- Object[] arguments = {arg1, arg2, arg3, arg4};
- return getMessage(messageId, arguments);
- }
-
- /* OPT there's a noticable delay for the first error! Maybe it'd
- * make sense to use a ListResourceBundle instead of a properties
- * file to avoid (synchronized) text parsing.
- */
- public static String getMessage(String messageId, Object[] arguments)
- {
- final String defaultResource
- = "org.mozilla.javascript.resources.Messages";
-
- Context cx = Context.getCurrentContext();
- Locale locale = cx != null ? cx.getLocale() : Locale.getDefault();
-
- // ResourceBundle does cacheing.
- ResourceBundle rb = ResourceBundle.getBundle(defaultResource, locale);
-
- String formatString;
- try {
- formatString = rb.getString(messageId);
- } catch (java.util.MissingResourceException mre) {
- throw new RuntimeException
- ("no message resource found for message property "+ messageId);
- }
-
- /*
- * It's OK to format the string, even if 'arguments' is null;
- * we need to format it anyway, to make double ''s collapse to
- * single 's.
- */
- MessageFormat formatter = new MessageFormat(formatString);
- return formatter.format(arguments);
- }
-
- public static EcmaError constructError(String error, String message)
- {
- int[] linep = new int[1];
- String filename = Context.getSourcePositionFromStack(linep);
- return constructError(error, message, filename, linep[0], null, 0);
- }
-
- public static EcmaError constructError(String error,
- String message,
- int lineNumberDelta)
- {
- int[] linep = new int[1];
- String filename = Context.getSourcePositionFromStack(linep);
- if (linep[0] != 0) {
- linep[0] += lineNumberDelta;
- }
- return constructError(error, message, filename, linep[0], null, 0);
- }
-
- public static EcmaError constructError(String error,
- String message,
- String sourceName,
- int lineNumber,
- String lineSource,
- int columnNumber)
- {
- return new EcmaError(error, message, sourceName,
- lineNumber, lineSource, columnNumber);
- }
-
- public static EcmaError typeError(String message)
- {
- return constructError("TypeError", message);
- }
-
- public static EcmaError typeError0(String messageId)
- {
- String msg = getMessage0(messageId);
- return typeError(msg);
- }
-
- public static EcmaError typeError1(String messageId, String arg1)
- {
- String msg = getMessage1(messageId, arg1);
- return typeError(msg);
- }
-
- public static EcmaError typeError2(String messageId, String arg1,
- String arg2)
- {
- String msg = getMessage2(messageId, arg1, arg2);
- return typeError(msg);
- }
-
- public static EcmaError typeError3(String messageId, String arg1,
- String arg2, String arg3)
- {
- String msg = getMessage3(messageId, arg1, arg2, arg3);
- return typeError(msg);
- }
-
- public static RuntimeException undefReadError(Object object, Object id)
- {
- String idStr = (id == null) ? "null" : id.toString();
- return typeError2("msg.undef.prop.read", toString(object), idStr);
- }
-
- public static RuntimeException undefCallError(Object object, Object id)
- {
- String idStr = (id == null) ? "null" : id.toString();
- return typeError2("msg.undef.method.call", toString(object), idStr);
- }
-
- public static RuntimeException undefWriteError(Object object,
- Object id,
- Object value)
- {
- String idStr = (id == null) ? "null" : id.toString();
- String valueStr = (value instanceof Scriptable)
- ? value.toString() : toString(value);
- return typeError3("msg.undef.prop.write", toString(object), idStr,
- valueStr);
- }
-
- public static RuntimeException notFoundError(Scriptable object,
- String property)
- {
- // XXX: use object to improve the error message
- String msg = getMessage1("msg.is.not.defined", property);
- throw constructError("ReferenceError", msg);
- }
-
- public static RuntimeException notFunctionError(Object value)
- {
- return notFunctionError(value, value);
- }
-
- public static RuntimeException notFunctionError(Object value,
- Object messageHelper)
- {
- // Use value for better error reporting
- String msg = (messageHelper == null)
- ? "null" : messageHelper.toString();
- if (value == Scriptable.NOT_FOUND) {
- return typeError1("msg.function.not.found", msg);
- }
- return typeError2("msg.isnt.function", msg, typeof(value));
- }
-
- public static RuntimeException notFunctionError(Object obj, Object value,
- String propertyName)
- {
- // Use obj and value for better error reporting
- String objString = toString(obj);
- if (value == Scriptable.NOT_FOUND) {
- return typeError2("msg.function.not.found.in", propertyName,
- objString);
- }
- return typeError3("msg.isnt.function.in", propertyName, objString,
- typeof(value));
- }
-
- private static RuntimeException notXmlError(Object value)
- {
- throw typeError1("msg.isnt.xml.object", toString(value));
- }
-
- private static void warnAboutNonJSObject(Object nonJSObject)
- {
- String message =
-"RHINO USAGE WARNING: Missed Context.javaToJS() conversion:\n"
-+"Rhino runtime detected object "+nonJSObject+" of class "+nonJSObject.getClass().getName()+" where it expected String, Number, Boolean or Scriptable instance. Please check your code for missing Context.javaToJS() call.";
- Context.reportWarning(message);
- // Just to be sure that it would be noticed
- System.err.println(message);
- }
-
- public static RegExpProxy getRegExpProxy(Context cx)
- {
- return cx.getRegExpProxy();
- }
-
- public static void setRegExpProxy(Context cx, RegExpProxy proxy)
- {
- if (proxy == null) throw new IllegalArgumentException();
- cx.regExpProxy = proxy;
- }
-
- public static RegExpProxy checkRegExpProxy(Context cx)
- {
- RegExpProxy result = getRegExpProxy(cx);
- if (result == null) {
- throw Context.reportRuntimeError0("msg.no.regexp");
- }
- return result;
- }
-
- private static XMLLib currentXMLLib(Context cx)
- {
- // Scripts should be running to access this
- if (cx.topCallScope == null)
- throw new IllegalStateException();
-
- XMLLib xmlLib = cx.cachedXMLLib;
- if (xmlLib == null) {
- xmlLib = XMLLib.extractFromScope(cx.topCallScope);
- if (xmlLib == null)
- throw new IllegalStateException();
- cx.cachedXMLLib = xmlLib;
- }
-
- return xmlLib;
- }
-
- /**
- * Escapes the reserved characters in a value of an attribute
- *
- * @param value Unescaped text
- * @return The escaped text
- */
- public static String escapeAttributeValue(Object value, Context cx)
- {
- XMLLib xmlLib = currentXMLLib(cx);
- return xmlLib.escapeAttributeValue(value);
- }
-
- /**
- * Escapes the reserved characters in a value of a text node
- *
- * @param value Unescaped text
- * @return The escaped text
- */
- public static String escapeTextValue(Object value, Context cx)
- {
- XMLLib xmlLib = currentXMLLib(cx);
- return xmlLib.escapeTextValue(value);
- }
-
- public static Ref memberRef(Object obj, Object elem,
- Context cx, int memberTypeFlags)
- {
- if (!(obj instanceof XMLObject)) {
- throw notXmlError(obj);
- }
- XMLObject xmlObject = (XMLObject)obj;
- return xmlObject.memberRef(cx, elem, memberTypeFlags);
- }
-
- public static Ref memberRef(Object obj, Object namespace, Object elem,
- Context cx, int memberTypeFlags)
- {
- if (!(obj instanceof XMLObject)) {
- throw notXmlError(obj);
- }
- XMLObject xmlObject = (XMLObject)obj;
- return xmlObject.memberRef(cx, namespace, elem, memberTypeFlags);
- }
-
- public static Ref nameRef(Object name, Context cx,
- Scriptable scope, int memberTypeFlags)
- {
- XMLLib xmlLib = currentXMLLib(cx);
- return xmlLib.nameRef(cx, name, scope, memberTypeFlags);
- }
-
- public static Ref nameRef(Object namespace, Object name, Context cx,
- Scriptable scope, int memberTypeFlags)
- {
- XMLLib xmlLib = currentXMLLib(cx);
- return xmlLib.nameRef(cx, namespace, name, scope, memberTypeFlags);
- }
-
- private static void storeIndexResult(Context cx, int index)
- {
- cx.scratchIndex = index;
- }
-
- static int lastIndexResult(Context cx)
- {
- return cx.scratchIndex;
- }
-
- public static void storeUint32Result(Context cx, long value)
- {
- if ((value >>> 32) != 0)
- throw new IllegalArgumentException();
- cx.scratchUint32 = value;
- }
-
- public static long lastUint32Result(Context cx)
- {
- long value = cx.scratchUint32;
- if ((value >>> 32) != 0)
- throw new IllegalStateException();
- return value;
- }
-
- private static void storeScriptable(Context cx, Scriptable value)
- {
- // The previosly stored scratchScriptable should be consumed
- if (cx.scratchScriptable != null)
- throw new IllegalStateException();
- cx.scratchScriptable = value;
- }
-
- public static Scriptable lastStoredScriptable(Context cx)
- {
- Scriptable result = cx.scratchScriptable;
- cx.scratchScriptable = null;
- return result;
- }
-
- static String makeUrlForGeneratedScript
- (boolean isEval, String masterScriptUrl, int masterScriptLine)
- {
- if (isEval) {
- return masterScriptUrl+'#'+masterScriptLine+"(eval)";
- } else {
- return masterScriptUrl+'#'+masterScriptLine+"(Function)";
- }
- }
-
- static boolean isGeneratedScript(String sourceUrl) {
- // ALERT: this may clash with a valid URL containing (eval) or
- // (Function)
- return sourceUrl.indexOf("(eval)") >= 0
- || sourceUrl.indexOf("(Function)") >= 0;
- }
-
- private static RuntimeException errorWithClassName(String msg, Object val)
- {
- return Context.reportRuntimeError1(msg, val.getClass().getName());
- }
-
- public static final Object[] emptyArgs = new Object[0];
- public static final String[] emptyStrings = new String[0];
-
-}