?? scriptruntime.java
字號:
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * The contents of this file are subject to the Netscape 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/NPL/ * * 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 Netscape are * Copyright (C) 1997-2000 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): * Patrick Beard * Norris Boyd * Igor Bukanov * Ethan Hugg * Roger Lawrence * Terry Lucas * Frank Mitchell * Milen Nankov * Andrew Wason * * Alternatively, the contents of this file may be used under the * terms of the GNU Public License (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 NPL, indicate your decision by * deleting the provisions above and replace 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 NPL or the GPL. */package org.mozilla.javascript;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;import org.mozilla.javascript.continuations.Continuation;/** * This is the class that implements the runtime. * * @author Norris Boyd */public class ScriptRuntime { /** * No instances should be created. */ protected ScriptRuntime() { } /* * 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 til * executiontime (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 XML_INIT_CLASS = "org.mozilla.javascript.xmlimpl.XMLLibImpl"; private static final String[] lazilyNames = { "RegExp", "org.mozilla.javascript.regexp.NativeRegExp", "Packages", "org.mozilla.javascript.NativeJavaTopPackage", "java", "org.mozilla.javascript.NativeJavaTopPackage", "getClass", "org.mozilla.javascript.NativeJavaTopPackage", "JavaAdapter", "org.mozilla.javascript.JavaAdapter", "JavaImporter", "org.mozilla.javascript.ImporterTopLevel", "XML", XML_INIT_CLASS, "XMLList", XML_INIT_CLASS, "Namespace", XML_INIT_CLASS, "QName", XML_INIT_CLASS, }; 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); 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); boolean withXml = cx.hasFeature(Context.FEATURE_E4X); for (int i = 0; i != lazilyNames.length; i += 2) { String topProperty = lazilyNames[i]; String className = lazilyNames[i + 1]; if (!withXml && className == XML_INIT_CLASS) { continue; } new LazilyLoadedCtor(scope, topProperty, className, sealed); } Continuation.init(scope, 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 (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; } } public static boolean toBoolean(Object[] args, int index) { return (index < args.length) ? toBoolean(args[index]) : false; } /** * 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')
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -