📄 nativeglobal.java
字号:
/* -*- 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-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Norris Boyd * Igor Bukanov * Mike McCabe * * 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 org.mozilla.javascript.xml.XMLLib;/** * This class implements the global native object (function and value * properties only). * * See ECMA 15.1.[12]. * * @author Mike Shaver */public class NativeGlobal implements Serializable, IdFunctionCall{ static final long serialVersionUID = 6080442165748707530L; public static void init(Context cx, Scriptable scope, boolean sealed) { NativeGlobal obj = new NativeGlobal(); for (int id = 1; id <= LAST_SCOPE_FUNCTION_ID; ++id) { String name; int arity = 1; switch (id) { case Id_decodeURI: name = "decodeURI"; break; case Id_decodeURIComponent: name = "decodeURIComponent"; break; case Id_encodeURI: name = "encodeURI"; break; case Id_encodeURIComponent: name = "encodeURIComponent"; break; case Id_escape: name = "escape"; break; case Id_eval: name = "eval"; break; case Id_isFinite: name = "isFinite"; break; case Id_isNaN: name = "isNaN"; break; case Id_isXMLName: name = "isXMLName"; break; case Id_parseFloat: name = "parseFloat"; break; case Id_parseInt: name = "parseInt"; arity = 2; break; case Id_unescape: name = "unescape"; break; case Id_uneval: name = "uneval"; break; default: throw Kit.codeBug(); } IdFunctionObject f = new IdFunctionObject(obj, FTAG, id, name, arity, scope); if (sealed) { f.sealObject(); } f.exportAsScopeProperty(); } ScriptableObject.defineProperty( scope, "NaN", ScriptRuntime.NaNobj, ScriptableObject.DONTENUM); ScriptableObject.defineProperty( scope, "Infinity", ScriptRuntime.wrapNumber(Double.POSITIVE_INFINITY), ScriptableObject.DONTENUM); ScriptableObject.defineProperty( scope, "undefined", Undefined.instance, ScriptableObject.DONTENUM); String[] errorMethods = Kit.semicolonSplit("" +"ConversionError;" +"EvalError;" +"RangeError;" +"ReferenceError;" +"SyntaxError;" +"TypeError;" +"URIError;" +"InternalError;" +"JavaException;" ); /* Each error constructor gets its own Error object as a prototype, with the 'name' property set to the name of the error. */ for (int i = 0; i < errorMethods.length; i++) { String name = errorMethods[i]; Scriptable errorProto = ScriptRuntime. newObject(cx, scope, "Error", ScriptRuntime.emptyArgs); errorProto.put("name", errorProto, name); if (sealed) { if (errorProto instanceof ScriptableObject) { ((ScriptableObject)errorProto).sealObject(); } } IdFunctionObject ctor = new IdFunctionObject(obj, FTAG, Id_new_CommonError, name, 1, scope); ctor.markAsConstructor(errorProto); if (sealed) { ctor.sealObject(); } ctor.exportAsScopeProperty(); } } public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { if (f.hasTag(FTAG)) { int methodId = f.methodId(); switch (methodId) { case Id_decodeURI: case Id_decodeURIComponent: { String str = ScriptRuntime.toString(args, 0); return decode(str, methodId == Id_decodeURI); } case Id_encodeURI: case Id_encodeURIComponent: { String str = ScriptRuntime.toString(args, 0); return encode(str, methodId == Id_encodeURI); } case Id_escape: return js_escape(args); case Id_eval: return js_eval(cx, scope, args); case Id_isFinite: { boolean result; if (args.length < 1) { result = false; } else { double d = ScriptRuntime.toNumber(args[0]); result = (d == d && d != Double.POSITIVE_INFINITY && d != Double.NEGATIVE_INFINITY); } return ScriptRuntime.wrapBoolean(result); } case Id_isNaN: { // The global method isNaN, as per ECMA-262 15.1.2.6. boolean result; if (args.length < 1) { result = true; } else { double d = ScriptRuntime.toNumber(args[0]); result = (d != d); } return ScriptRuntime.wrapBoolean(result); } case Id_isXMLName: { Object name = (args.length == 0) ? Undefined.instance : args[0]; XMLLib xmlLib = XMLLib.extractFromScope(scope); return ScriptRuntime.wrapBoolean( xmlLib.isXMLName(cx, name)); } case Id_parseFloat: return js_parseFloat(args); case Id_parseInt: return js_parseInt(args); case Id_unescape: return js_unescape(args); case Id_uneval: { Object value = (args.length != 0) ? args[0] : Undefined.instance; return ScriptRuntime.uneval(cx, scope, value); } case Id_new_CommonError: // The implementation of all the ECMA error constructors // (SyntaxError, TypeError, etc.) return NativeError.make(cx, scope, f, args); } } throw f.unknown(); } /** * The global method parseInt, as per ECMA-262 15.1.2.2. */ private Object js_parseInt(Object[] args) { String s = ScriptRuntime.toString(args, 0); int radix = ScriptRuntime.toInt32(args, 1); int len = s.length(); if (len == 0) return ScriptRuntime.NaNobj; boolean negative = false; int start = 0; char c; do { c = s.charAt(start); if (!Character.isWhitespace(c)) break; start++; } while (start < len); if (c == '+' || (negative = (c == '-'))) start++; final int NO_RADIX = -1; if (radix == 0) { radix = NO_RADIX; } else if (radix < 2 || radix > 36) { return ScriptRuntime.NaNobj; } else if (radix == 16 && len - start > 1 && s.charAt(start) == '0') { c = s.charAt(start+1); if (c == 'x' || c == 'X') start += 2; } if (radix == NO_RADIX) { radix = 10; if (len - start > 1 && s.charAt(start) == '0') { c = s.charAt(start+1); if (c == 'x' || c == 'X') { radix = 16; start += 2; } else if ('0' <= c && c <= '9') { radix = 8; start++; } } } double d = ScriptRuntime.stringToNumber(s, start, radix); return ScriptRuntime.wrapNumber(negative ? -d : d); } /** * The global method parseFloat, as per ECMA-262 15.1.2.3. * * @param cx unused * @param thisObj unused * @param args the arguments to parseFloat, ignoring args[>=1] * @param funObj unused */ private Object js_parseFloat(Object[] args) { if (args.length < 1) return ScriptRuntime.NaNobj; String s = ScriptRuntime.toString(args[0]); int len = s.length(); int start = 0; // Scan forward to skip whitespace char c; for (;;) { if (start == len) { return ScriptRuntime.NaNobj; } c = s.charAt(start); if (!TokenStream.isJSSpace(c)) { break; } ++start; } int i = start; if (c == '+' || c == '-') { ++i; if (i == len) { return ScriptRuntime.NaNobj; } c = s.charAt(i); } if (c == 'I') { // check for "Infinity" if (i+8 <= len && s.regionMatches(i, "Infinity", 0, 8)) { double d; if (s.charAt(start) == '-') { d = Double.NEGATIVE_INFINITY; } else { d = Double.POSITIVE_INFINITY; } return ScriptRuntime.wrapNumber(d); } return ScriptRuntime.NaNobj; } // Find the end of the legal bit int decimal = -1; int exponent = -1; for (; i < len; i++) { switch (s.charAt(i)) { case '.': if (decimal != -1) // Only allow a single decimal point. break; decimal = i; continue; case 'e': case 'E': if (exponent != -1) break; exponent = i; continue; case '+': case '-': // Only allow '+' or '-' after 'e' or 'E' if (exponent != i-1) break; continue; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': continue; default: break; } break; } s = s.substring(start, i); try { return Double.valueOf(s); } catch (NumberFormatException ex) { return ScriptRuntime.NaNobj; } } /** * The global method escape, as per ECMA-262 15.1.2.4.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -