+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-/**\r
- * This class implements the "arguments" object.\r
- *\r
- * See ECMA 10.1.8\r
- *\r
- * @see org.mozilla.javascript.NativeCall\r
- * @author Norris Boyd\r
- */\r
-class Arguments extends ScriptableObject {\r
-\r
- public Arguments(NativeCall activation) {\r
- this.activation = activation;\r
-\r
- Scriptable parent = activation.getParentScope();\r
- setParentScope(parent);\r
- setPrototype(ScriptableObject.getObjectPrototype(parent));\r
-\r
- args = activation.getOriginalArguments();\r
- int length = args.length;\r
- Object callee = activation.funObj;\r
-\r
- defineProperty("length", new Integer(length),\r
- ScriptableObject.DONTENUM);\r
- defineProperty("callee", callee, ScriptableObject.DONTENUM);\r
-\r
- hasCaller = (activation.funObj.version <= Context.VERSION_1_3 &&\r
- activation.funObj.version != Context.VERSION_DEFAULT);\r
- }\r
-\r
- public String getClassName() {\r
- return "Arguments";\r
- }\r
-\r
- public boolean has(String name, Scriptable start) {\r
- return (hasCaller && name.equals("caller")) || super.has(name, start);\r
- }\r
-\r
- public boolean has(int index, Scriptable start) {\r
- Object[] args = activation.getOriginalArguments();\r
- return (0 <= index && index < args.length) || super.has(index, start);\r
- }\r
-\r
- public Object get(String name, Scriptable start) {\r
- if (hasCaller && name.equals("caller")) {\r
- NativeCall caller = activation.caller;\r
- if (caller == null || caller.originalArgs == null) return null;\r
- return caller.get("arguments", caller);\r
-\r
- } else if (name.equals("cascade")) {\r
- return org.xwt.Trap.cascadeFunction;\r
-\r
- } else if (name.equals("trapee")) {\r
- return org.xwt.Trap.currentTrapee();\r
-\r
- } else if (name.equals("trapname")) {\r
- return org.xwt.Trap.currentTrapname();\r
-\r
- }\r
-\r
- return super.get(name, start);\r
- }\r
-\r
- public Object get(int index, Scriptable start) {\r
- if (0 <= index && index < args.length) {\r
- NativeFunction f = activation.funObj;\r
- if (index < f.argCount)\r
- return activation.get(f.argNames[index], activation);\r
- return args[index];\r
- }\r
- return super.get(index, start);\r
- }\r
-\r
- public void put(String name, Scriptable start, Object value) {\r
- if (name.equals("caller")) {\r
- // Set "hasCaller" to false so that we won't look up a \r
- // computed value.\r
- hasCaller = false;\r
- }\r
- super.put(name, start, value);\r
- }\r
-\r
- public void put(int index, Scriptable start, Object value) {\r
- if (0 <= index && index < args.length) {\r
- NativeFunction f = activation.funObj;\r
- if (index < f.argCount)\r
- activation.put(f.argNames[index], activation, value);\r
- else\r
- args[index] = value;\r
- return;\r
- }\r
- super.put(index, start, value);\r
- }\r
-\r
- public void delete(String name) {\r
- if (name.equals("caller"))\r
- hasCaller = false;\r
- super.delete(name);\r
- }\r
-\r
- public void delete(int index) {\r
- if (0 <= index && index < args.length) {\r
- NativeFunction f = activation.funObj;\r
- if (index < f.argCount)\r
- activation.delete(f.argNames[index]);\r
- else\r
- args[index] = Undefined.instance;\r
- }\r
- }\r
-\r
- private NativeCall activation;\r
- private Object[] args;\r
- private boolean hasCaller;\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- * Igor Bukanov\r
- * Roger Lawrence\r
- * Mike McCabe\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-/**\r
- * The base class for Function objects\r
- * See ECMA 15.3.\r
- * @author Norris Boyd\r
- */\r
-public class BaseFunction extends IdScriptable implements Function {\r
-\r
- static void init(Context cx, Scriptable scope, boolean sealed) {\r
- BaseFunction obj = new BaseFunction();\r
- obj.prototypeFlag = true;\r
- obj.functionName = "";\r
- obj.prototypePropertyAttrs = DONTENUM | READONLY | PERMANENT;\r
- obj.addAsPrototype(MAX_PROTOTYPE_ID, cx, scope, sealed);\r
- }\r
- \r
- protected void fillConstructorProperties\r
- (Context cx, IdFunction ctor, boolean sealed)\r
- {\r
- // Fix up bootstrapping problem: getPrototype of the IdFunction \r
- // can not return Function.prototype because Function object is not\r
- // yet defined.\r
- ctor.setPrototype(this);\r
- }\r
-\r
- public String getClassName() {\r
- return "Function";\r
- }\r
-\r
- /**\r
- * Implements the instanceof operator for JavaScript Function objects.\r
- * <p>\r
- * <code>\r
- * foo = new Foo();<br>\r
- * foo instanceof Foo; // true<br>\r
- * </code>\r
- *\r
- * @param instance The value that appeared on the LHS of the instanceof\r
- * operator\r
- * @return true if the "prototype" property of "this" appears in\r
- * value's prototype chain\r
- *\r
- */\r
- public boolean hasInstance(Scriptable instance) {\r
- Object protoProp = ScriptableObject.getProperty(this, "prototype");\r
- if (protoProp instanceof Scriptable && protoProp != Undefined.instance)\r
- {\r
- return ScriptRuntime.jsDelegatesTo(instance, (Scriptable)protoProp);\r
- }\r
- throw NativeGlobal.typeError1\r
- ("msg.instanceof.bad.prototype", functionName, instance);\r
- }\r
-\r
- protected int getIdDefaultAttributes(int id) {\r
- switch (id) {\r
- case Id_length:\r
- case Id_arity:\r
- case Id_name:\r
- return DONTENUM | READONLY | PERMANENT;\r
- case Id_prototype:\r
- return prototypePropertyAttrs;\r
- case Id_arguments:\r
- return EMPTY;\r
- }\r
- return super.getIdDefaultAttributes(id);\r
- }\r
- \r
- protected boolean hasIdValue(int id) {\r
- if (id == Id_prototype) {\r
- return prototypeProperty != NOT_FOUND;\r
- }\r
- else if (id == Id_arguments) {\r
- // Should after delete Function.arguments its activation still\r
- // be available during Function call? \r
- // This code assumes it should not: after default set/deleteIdValue\r
- // hasIdValue/getIdValue would not be called again\r
- // To handle the opposite case, set/deleteIdValue should be \r
- // overwritten as well\r
- return null != getActivation(Context.getContext());\r
- }\r
- return super.hasIdValue(id);\r
- }\r
- \r
- protected Object getIdValue(int id) {\r
- switch (id) {\r
- case Id_length: return wrap_int(getLength());\r
- case Id_arity: return wrap_int(getArity());\r
- case Id_name: return getFunctionName();\r
- case Id_prototype: return getPrototypeProperty();\r
- case Id_arguments: return getArguments();\r
- }\r
- return super.getIdValue(id);\r
- }\r
- \r
- protected void setIdValue(int id, Object value) {\r
- if (id == Id_prototype) {\r
- prototypeProperty = (value != null) ? value : NULL_TAG;\r
- return;\r
- }\r
- super.setIdValue(id, value);\r
- }\r
-\r
- protected void deleteIdValue(int id) {\r
- if (id == Id_prototype) {\r
- prototypeProperty = NOT_FOUND;\r
- return;\r
- }\r
- super.deleteIdValue(id);\r
- }\r
-\r
- public int methodArity(int methodId) {\r
- if (prototypeFlag) {\r
- switch (methodId) {\r
- case Id_constructor:\r
- case Id_toString:\r
- case Id_apply:\r
- case Id_call:\r
- return 1;\r
- }\r
- }\r
- return super.methodArity(methodId);\r
- }\r
-\r
- public Object execMethod(int methodId, IdFunction f, Context cx,\r
- Scriptable scope, Scriptable thisObj, \r
- Object[] args)\r
- throws JavaScriptException\r
- {\r
- if (prototypeFlag) {\r
- switch (methodId) {\r
- case Id_constructor:\r
- return jsConstructor(cx, scope, args);\r
-\r
- case Id_toString:\r
- return jsFunction_toString(cx, thisObj, args);\r
-\r
- case Id_apply:\r
- return jsFunction_apply(cx, scope, thisObj, args);\r
-\r
- case Id_call:\r
- return jsFunction_call(cx, scope, thisObj, args);\r
- }\r
- }\r
- return super.execMethod(methodId, f, cx, scope, thisObj, args);\r
- }\r
-\r
- /**\r
- * Make value as DontEnum, DontDelete, ReadOnly\r
- * prototype property of this Function object \r
- */\r
- public void setImmunePrototypeProperty(Object value) {\r
- prototypeProperty = (value != null) ? value : NULL_TAG;\r
- prototypePropertyAttrs = DONTENUM | READONLY | PERMANENT;\r
- }\r
-\r
- protected Scriptable getClassPrototype() {\r
- Object protoVal = getPrototypeProperty();\r
- if (protoVal == null \r
- || !(protoVal instanceof Scriptable)\r
- || (protoVal == Undefined.instance))\r
- protoVal = getClassPrototype(this, "Object");\r
- return (Scriptable) protoVal;\r
- }\r
-\r
- /**\r
- * Should be overridden.\r
- */\r
- public Object call(Context cx, Scriptable scope, Scriptable thisObj,\r
- Object[] args)\r
- throws JavaScriptException\r
- {\r
- return Undefined.instance;\r
- }\r
-\r
- public Scriptable construct(Context cx, Scriptable scope, Object[] args)\r
- throws JavaScriptException\r
- {\r
- Scriptable newInstance = new NativeObject();\r
-\r
- newInstance.setPrototype(getClassPrototype());\r
- newInstance.setParentScope(getParentScope());\r
-\r
- Object val = call(cx, scope, newInstance, args);\r
- if (val instanceof Scriptable && val != Undefined.instance) {\r
- return (Scriptable) val;\r
- }\r
- return newInstance;\r
- }\r
-\r
- /**\r
- * Decompile the source information associated with this js\r
- * function/script back into a string.\r
- *\r
- * @param cx Current context\r
- *\r
- * @param indent How much to indent the decompiled result\r
- *\r
- * @param justbody Whether the decompilation should omit the\r
- * function header and trailing brace.\r
- */\r
-\r
- public String decompile(Context cx, int indent, boolean justbody) {\r
- StringBuffer sb = new StringBuffer();\r
- if (!justbody) {\r
- sb.append("function ");\r
- sb.append(getFunctionName());\r
- sb.append("() {\n\t");\r
- }\r
- sb.append("[native code, arity=");\r
- sb.append(getArity());\r
- sb.append("]\n");\r
- if (!justbody) {\r
- sb.append("}\n");\r
- }\r
- return sb.toString();\r
- }\r
-\r
- public int getArity() { return 0; }\r
-\r
- public int getLength() { return 0; }\r
-\r
- public String getFunctionName() {\r
- if (functionName == null)\r
- return "";\r
- if (functionName.equals("anonymous")) {\r
- Context cx = Context.getCurrentContext();\r
- if (cx != null && cx.getLanguageVersion() == Context.VERSION_1_2)\r
- return "";\r
- }\r
- return functionName;\r
- }\r
-\r
- private Object getPrototypeProperty() {\r
- Object result = prototypeProperty;\r
- if (result == null) { \r
- synchronized (this) {\r
- result = prototypeProperty;\r
- if (result == null) {\r
- setupDefaultPrototype();\r
- result = prototypeProperty;\r
- }\r
- }\r
- }\r
- else if (result == NULL_TAG) { result = null; }\r
- return result;\r
- }\r
-\r
- private void setupDefaultPrototype() {\r
- NativeObject obj = new NativeObject();\r
- final int attr = ScriptableObject.DONTENUM |\r
- ScriptableObject.READONLY |\r
- ScriptableObject.PERMANENT;\r
- obj.defineProperty("constructor", this, attr);\r
- // put the prototype property into the object now, then in the\r
- // wacky case of a user defining a function Object(), we don't\r
- // get an infinite loop trying to find the prototype.\r
- prototypeProperty = obj;\r
- Scriptable proto = getObjectPrototype(this); \r
- if (proto != obj) {\r
- // not the one we just made, it must remain grounded\r
- obj.setPrototype(proto);\r
- }\r
- }\r
-\r
- private Object getArguments() {\r
- // <Function name>.arguments is deprecated, so we use a slow\r
- // way of getting it that doesn't add to the invocation cost.\r
- // TODO: add warning, error based on version\r
- NativeCall activation = getActivation(Context.getContext());\r
- return activation == null \r
- ? null \r
- : activation.get("arguments", activation);\r
- }\r
- \r
- NativeCall getActivation(Context cx) {\r
- NativeCall activation = cx.currentActivation;\r
- while (activation != null) {\r
- if (activation.getFunctionObject() == this) \r
- return activation;\r
- activation = activation.caller;\r
- }\r
- return null;\r
- }\r
- \r
- private static Object jsConstructor(Context cx, Scriptable scope, \r
- Object[] args)\r
- {\r
- int arglen = args.length;\r
- StringBuffer funArgs = new StringBuffer();\r
-\r
- /* Collect the arguments into a string. */\r
-\r
- int i;\r
- for (i = 0; i < arglen - 1; i++) {\r
- if (i > 0)\r
- funArgs.append(',');\r
- funArgs.append(ScriptRuntime.toString(args[i]));\r
- }\r
- String funBody = arglen == 0 ? "" : ScriptRuntime.toString(args[i]);\r
-\r
- String source = "function (" + funArgs.toString() + ") {" +\r
- funBody + "}";\r
- int[] linep = { 0 };\r
- String filename = Context.getSourcePositionFromStack(linep);\r
- if (filename == null) {\r
- filename = "<eval'ed string>";\r
- linep[0] = 1;\r
- }\r
- Object securityDomain = cx.getSecurityDomainForStackDepth(4);\r
- Scriptable global = ScriptableObject.getTopLevelScope(scope);\r
- \r
- // Compile the function with opt level of -1 to force interpreter\r
- // mode.\r
- int oldOptLevel = cx.getOptimizationLevel();\r
- cx.setOptimizationLevel(-1);\r
- NativeFunction fn;\r
- try {\r
- fn = (NativeFunction) cx.compileFunction(global, source,\r
- filename, linep[0], \r
- securityDomain);\r
- }\r
- finally { cx.setOptimizationLevel(oldOptLevel); }\r
-\r
- fn.functionName = "anonymous";\r
- fn.setPrototype(getFunctionPrototype(global));\r
- fn.setParentScope(global);\r
-\r
- return fn;\r
- }\r
-\r
- private static Object jsFunction_toString(Context cx, Scriptable thisObj,\r
- Object[] args)\r
- {\r
- int indent = ScriptRuntime.toInt32(args, 0);\r
- Object val = thisObj.getDefaultValue(ScriptRuntime.FunctionClass);\r
- if (val instanceof BaseFunction) {\r
- return ((BaseFunction)val).decompile(cx, indent, false);\r
- }\r
- throw NativeGlobal.typeError1("msg.incompat.call", "toString", thisObj);\r
- }\r
-\r
- /**\r
- * Function.prototype.apply\r
- *\r
- * A proposed ECMA extension for round 2.\r
- */\r
- private static Object jsFunction_apply(Context cx, Scriptable scope,\r
- Scriptable thisObj, Object[] args)\r
- throws JavaScriptException\r
- {\r
- if (args.length != 2)\r
- return jsFunction_call(cx, scope, thisObj, args);\r
- Object val = thisObj.getDefaultValue(ScriptRuntime.FunctionClass);\r
- Scriptable newThis = args[0] == null\r
- ? ScriptableObject.getTopLevelScope(thisObj)\r
- : ScriptRuntime.toObject(scope, args[0]);\r
- Object[] newArgs;\r
- if (args.length > 1) {\r
- if ((args[1] instanceof NativeArray) \r
- || (args[1] instanceof Arguments))\r
- newArgs = cx.getElements((Scriptable) args[1]);\r
- else\r
- throw NativeGlobal.typeError0("msg.arg.isnt.array", thisObj); \r
- }\r
- else\r
- newArgs = ScriptRuntime.emptyArgs;\r
- return ScriptRuntime.call(cx, val, newThis, newArgs, newThis);\r
- }\r
-\r
- /**\r
- * Function.prototype.call\r
- *\r
- * A proposed ECMA extension for round 2.\r
- */\r
- private static Object jsFunction_call(Context cx, Scriptable scope,\r
- Scriptable thisObj, Object[] args)\r
- throws JavaScriptException\r
- {\r
- Object val = thisObj.getDefaultValue(ScriptRuntime.FunctionClass);\r
- if (args.length == 0) {\r
- Scriptable s = ScriptRuntime.toObject(scope, val);\r
- Scriptable topScope = s.getParentScope();\r
- return ScriptRuntime.call(cx, val, \r
- topScope, ScriptRuntime.emptyArgs, \r
- topScope);\r
- } else {\r
- Scriptable newThis = args[0] == null\r
- ? ScriptableObject.getTopLevelScope(thisObj)\r
- : ScriptRuntime.toObject(scope, args[0]);\r
-\r
- Object[] newArgs = new Object[args.length - 1];\r
- System.arraycopy(args, 1, newArgs, 0, newArgs.length);\r
- return ScriptRuntime.call(cx, val, newThis, newArgs, newThis);\r
- }\r
- }\r
-\r
- protected int maxInstanceId() { return MAX_INSTANCE_ID; }\r
-\r
- protected String getIdName(int id) {\r
- switch (id) {\r
- case Id_length: return "length";\r
- case Id_arity: return "arity";\r
- case Id_name: return "name";\r
- case Id_prototype: return "prototype";\r
- case Id_arguments: return "arguments";\r
- }\r
- \r
- if (prototypeFlag) {\r
- switch (id) {\r
- case Id_constructor: return "constructor";\r
- case Id_toString: return "toString";\r
- case Id_apply: return "apply";\r
- case Id_call: return "call";\r
- }\r
- }\r
- return null;\r
- }\r
-\r
-// #string_id_map#\r
-\r
- private static final int\r
- Id_length = 1,\r
- Id_arity = 2,\r
- Id_name = 3,\r
- Id_prototype = 4,\r
- Id_arguments = 5,\r
- \r
- MAX_INSTANCE_ID = 5;\r
-\r
- protected int mapNameToId(String s) {\r
- int id;\r
-// #generated# Last update: 2001-05-20 00:12:12 GMT+02:00\r
- L0: { id = 0; String X = null; int c;\r
- L: switch (s.length()) {\r
- case 4: X="name";id=Id_name; break L;\r
- case 5: X="arity";id=Id_arity; break L;\r
- case 6: X="length";id=Id_length; break L;\r
- case 9: c=s.charAt(0);\r
- if (c=='a') { X="arguments";id=Id_arguments; }\r
- else if (c=='p') { X="prototype";id=Id_prototype; }\r
- break L;\r
- }\r
- if (X!=null && X!=s && !X.equals(s)) id = 0;\r
- }\r
-// #/generated#\r
-// #/string_id_map#\r
-\r
- if (id != 0 || !prototypeFlag) { return id; }\r
-\r
-// #string_id_map#\r
-// #generated# Last update: 2001-05-20 00:12:12 GMT+02:00\r
- L0: { id = 0; String X = null;\r
- L: switch (s.length()) {\r
- case 4: X="call";id=Id_call; break L;\r
- case 5: X="apply";id=Id_apply; break L;\r
- case 8: X="toString";id=Id_toString; break L;\r
- case 11: X="constructor";id=Id_constructor; break L;\r
- }\r
- if (X!=null && X!=s && !X.equals(s)) id = 0;\r
- }\r
-// #/generated#\r
- return id;\r
- }\r
-\r
- private static final int\r
- Id_constructor = MAX_INSTANCE_ID + 1,\r
- Id_toString = MAX_INSTANCE_ID + 2,\r
- Id_apply = MAX_INSTANCE_ID + 3,\r
- Id_call = MAX_INSTANCE_ID + 4,\r
- \r
- MAX_PROTOTYPE_ID = MAX_INSTANCE_ID + 4;\r
-\r
-// #/string_id_map#\r
- \r
- protected String functionName;\r
-\r
- private Object prototypeProperty; \r
- private int prototypePropertyAttrs = DONTENUM;\r
-\r
- private boolean prototypeFlag;\r
-}\r
-\r
+++ /dev/null
-\r
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Waldemar Horwat\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-package org.mozilla.javascript;\r
-\r
-final class BinaryDigitReader {\r
- int lgBase; // Logarithm of base of number\r
- int digit; // Current digit value in radix given by base\r
- int digitPos; // Bit position of last bit extracted from digit\r
- String digits; // String containing the digits\r
- int start; // Index of the first remaining digit\r
- int end; // Index past the last remaining digit\r
-\r
- BinaryDigitReader(int base, String digits, int start, int end) {\r
- lgBase = 0;\r
- while (base != 1) {\r
- lgBase++;\r
- base >>= 1;\r
- }\r
- digitPos = 0;\r
- this.digits = digits;\r
- this.start = start;\r
- this.end = end;\r
- }\r
-\r
- /* Return the next binary digit from the number or -1 if done */\r
- int getNextBinaryDigit()\r
- {\r
- if (digitPos == 0) {\r
- if (start == end)\r
- return -1;\r
- \r
- char c = digits.charAt(start++);\r
- if ('0' <= c && c <= '9')\r
- digit = c - '0';\r
- else if ('a' <= c && c <= 'z')\r
- digit = c - 'a' + 10;\r
- else digit = c - 'A' + 10;\r
- digitPos = lgBase;\r
- }\r
- return digit >> --digitPos & 1;\r
- }\r
-}\r
+++ /dev/null
-\r
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-// API class\r
-\r
-package org.mozilla.javascript;\r
-\r
-/**\r
- * Thrown if errors are detected while attempting to define a host object\r
- * from a Java class.\r
- */\r
-public class ClassDefinitionException extends Exception {\r
-\r
- public ClassDefinitionException(String detail) {\r
- super(detail);\r
- }\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s):\r
- * Norris Boyd\r
- * Roger Lawrence\r
- * Andi Vajda\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-public interface ClassNameHelper {\r
-\r
- public String getTargetClassFileName();\r
-\r
- public void setTargetClassFileName(String classFileName);\r
-\r
- public String getTargetPackage();\r
-\r
- public void setTargetPackage(String targetPackage);\r
-\r
- public String getTargetClassFileName(String className);\r
- \r
- public String getGeneratingDirectory();\r
- \r
- public void setTargetExtends(Class extendsClass);\r
- \r
- public void setTargetImplements(Class[] implementsClasses);\r
-\r
- public ClassOutput getClassOutput();\r
-\r
- public void setClassOutput(ClassOutput classOutput);\r
- \r
- public void reset();\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-2000 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Andi Vajda\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-package org.mozilla.javascript;\r
-\r
-// API class\r
-\r
-import java.io.*;\r
-\r
-/**\r
- * This interface is implemented by classes interested in the bytecode\r
- * generated by the rhino compiler for script objects.\r
- *\r
- * @see Context\r
- * @author Andi Vajda\r
- */\r
-public interface ClassOutput {\r \r
- /**\r
- * @param className the name of the class for which bytecode is ready.\r
- * @param isTopLevel if true, represents the top-level script being compiled\r
- * @return a stream into which to write bytecode.\r
- * @since 1.5 Release 2\r
- */\r
- public OutputStream getOutputStream(String className, boolean isTopLevel)\r
- throws IOException;\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-2000 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s):\r
- *\r
- * Patrick Beard\r
- * Norris Boyd\r
- * Igor Bukanov\r
- * Brendan Eich\r
- * Roger Lawrence\r
- * Mike McCabe\r
- * Ian D. Stewart\r
- * Andi Vajda\r
- * Andrew Wason\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-// API class\r
-\r
-package org.mozilla.javascript;\r
-\r
-import java.beans.*;\r
-import java.io.*;\r
-import java.util.Vector;\r
-import java.util.Enumeration;\r
-import java.util.Hashtable;\r
-import java.util.Locale;\r
-import java.util.ResourceBundle;\r
-import java.util.ListResourceBundle;\r
-import java.text.MessageFormat;\r
-import java.lang.reflect.*;\r
-import org.mozilla.javascript.debug.*;\r
-\r
-/**\r
- * This class represents the runtime context of an executing script.\r
- *\r
- * Before executing a script, an instance of Context must be created\r
- * and associated with the thread that will be executing the script.\r
- * The Context will be used to store information about the executing\r
- * of the script such as the call stack. Contexts are associated with\r
- * the current thread using the <a href="#enter()">enter()</a> method.<p>\r
- *\r
- * The behavior of the execution engine may be altered through methods\r
- * such as <a href="#setLanguageVersion>setLanguageVersion</a> and\r
- * <a href="#setErrorReporter>setErrorReporter</a>.<p>\r
- *\r
- * Different forms of script execution are supported. Scripts may be\r
- * evaluated from the source directly, or first compiled and then later\r
- * executed. Interactive execution is also supported.<p>\r
- *\r
- * Some aspects of script execution, such as type conversions and\r
- * object creation, may be accessed directly through methods of\r
- * Context.\r
- *\r
- * @see Scriptable\r
- * @author Norris Boyd\r
- * @author Brendan Eich\r
- */\r
-\r
-public class Context {\r
- public static final String languageVersionProperty = "language version";\r
- public static final String errorReporterProperty = "error reporter";\r
- \r
- /**\r
- * Create a new Context.\r
- *\r
- * Note that the Context must be associated with a thread before\r
- * it can be used to execute a script.\r
- *\r
- * @see org.mozilla.javascript.Context#enter\r
- */\r
- public Context() {\r
- init();\r
- }\r
- \r
- /**\r
- * Create a new context with the associated security support.\r
- * \r
- * @param securitySupport an encapsulation of the functionality \r
- * needed to support security for scripts.\r
- * @see org.mozilla.javascript.SecuritySupport\r
- */\r
- public Context(SecuritySupport securitySupport) {\r
- this.securitySupport = securitySupport;\r
- init();\r
- }\r
- \r
- private void init() {\r
- setLanguageVersion(VERSION_DEFAULT);\r
- optimizationLevel = codegenClass != null ? 0 : -1;\r
- Object[] array = contextListeners;\r
- if (array != null) {\r
- for (int i = array.length; i-- != 0;) {\r
- ((ContextListener)array[i]).contextCreated(this);\r
- }\r
- }\r
- }\r
- \r
- /**\r
- * Get a context associated with the current thread, creating\r
- * one if need be.\r
- *\r
- * The Context stores the execution state of the JavaScript\r
- * engine, so it is required that the context be entered\r
- * before execution may begin. Once a thread has entered\r
- * a Context, then getCurrentContext() may be called to find\r
- * the context that is associated with the current thread.\r
- * <p>\r
- * Calling <code>enter()</code> will\r
- * return either the Context currently associated with the\r
- * thread, or will create a new context and associate it \r
- * with the current thread. Each call to <code>enter()</code>\r
- * must have a matching call to <code>exit()</code>. For example,\r
- * <pre>\r
- * Context cx = Context.enter();\r
- * ...\r
- * cx.evaluateString(...);\r
- * Context.exit();\r
- * </pre>\r
- * @return a Context associated with the current thread\r
- * @see org.mozilla.javascript.Context#getCurrentContext\r
- * @see org.mozilla.javascript.Context#exit\r
- */\r
- public static Context enter() {\r
- return enter(null);\r
- }\r
- \r
- /**\r
- * Get a Context associated with the current thread, using\r
- * the given Context if need be.\r
- * <p>\r
- * The same as <code>enter()</code> except that <code>cx</code>\r
- * is associated with the current thread and returned if \r
- * the current thread has no associated context and <code>cx</code>\r
- * is not associated with any other thread.\r
- * @param cx a Context to associate with the thread if possible\r
- * @return a Context associated with the current thread\r
- */\r
- public static Context enter(Context cx) {\r
- // There's some duplication of code in this method to avoid\r
- // unnecessary synchronizations.\r
- Thread t = Thread.currentThread();\r
- Context current = (Context) threadContexts.get(t);\r
- if (current != null) {\r
- synchronized (current) {\r
- current.enterCount++;\r
- }\r
- }\r
- else if (cx != null) {\r
- synchronized (cx) {\r
- if (cx.currentThread == null) {\r
- cx.currentThread = t;\r
- threadContexts.put(t, cx);\r
- cx.enterCount++;\r
- }\r
- }\r
- current = cx;\r
- }\r
- else {\r
- current = new Context();\r
- current.currentThread = t;\r
- threadContexts.put(t, current);\r
- current.enterCount = 1;\r
- }\r
- Object[] array = contextListeners;\r
- if (array != null) {\r
- for (int i = array.length; i-- != 0;) {\r
- ((ContextListener)array[i]).contextEntered(current);\r
- }\r
- }\r
- return current;\r
- }\r
- \r
- /**\r
- * Exit a block of code requiring a Context.\r
- *\r
- * Calling <code>exit()</code> will remove the association between\r
- * the current thread and a Context if the prior call to \r
- * <code>enter()</code> on this thread newly associated a Context \r
- * with this thread.\r
- * Once the current thread no longer has an associated Context,\r
- * it cannot be used to execute JavaScript until it is again associated\r
- * with a Context.\r
- *\r
- * @see org.mozilla.javascript.Context#enter\r
- */\r
- public static void exit() {\r
- Context cx = getCurrentContext();\r
- boolean released = false;\r
- if (cx != null) {\r
- synchronized (cx) {\r
- if (--cx.enterCount == 0) {\r
- threadContexts.remove(cx.currentThread);\r
- cx.currentThread = null;\r
- released = true;\r
- }\r
- }\r
- Object[] array = contextListeners;\r
- if (array != null) {\r
- for (int i = array.length; i-- != 0;) {\r
- ContextListener l = (ContextListener)array[i];\r
- l.contextExited(cx);\r
- if (released) { l.contextReleased(cx); }\r
- }\r
- }\r
- }\r
- }\r
-\r
- /**\r
- * Get the current Context.\r
- *\r
- * The current Context is per-thread; this method looks up\r
- * the Context associated with the current thread. <p>\r
- *\r
- * @return the Context associated with the current thread, or\r
- * null if no context is associated with the current \r
- * thread.\r
- * @see org.mozilla.javascript.Context#enter\r
- * @see org.mozilla.javascript.Context#exit\r
- */\r
- public static Context getCurrentContext() {\r
- Thread t = Thread.currentThread();\r
- return (Context) threadContexts.get(t);\r
- }\r
- \r
- public static Context getContextForThread(Thread t) {\r
- Context ret = (Context) threadContexts.get(t);\r
- return ret == null ? Context.enter() : ret;\r
- }\r
- \r
- /**\r
- * Language versions\r
- *\r
- * All integral values are reserved for future version numbers.\r
- */\r
-\r
- /**\r
- * The unknown version.\r
- */\r
- public static final int VERSION_UNKNOWN = -1;\r
-\r
- /**\r
- * The default version.\r
- */\r
- public static final int VERSION_DEFAULT = 0;\r
-\r
- /**\r
- * JavaScript 1.0\r
- */\r
- public static final int VERSION_1_0 = 100;\r
-\r
- /**\r
- * JavaScript 1.1\r
- */\r
- public static final int VERSION_1_1 = 110;\r
-\r
- /**\r
- * JavaScript 1.2\r
- */\r
- public static final int VERSION_1_2 = 120;\r
-\r
- /**\r
- * JavaScript 1.3\r
- */\r
- public static final int VERSION_1_3 = 130;\r
-\r
- /**\r
- * JavaScript 1.4\r
- */\r
- public static final int VERSION_1_4 = 140;\r
-\r
- /**\r
- * JavaScript 1.5\r
- */\r
- public static final int VERSION_1_5 = 150;\r
-\r
- /**\r
- * Get the current language version.\r
- * <p>\r
- * The language version number affects JavaScript semantics as detailed\r
- * in the overview documentation.\r
- *\r
- * @return an integer that is one of VERSION_1_0, VERSION_1_1, etc.\r
- */\r
- public int getLanguageVersion() {\r
- return version;\r
- }\r
-\r
- /**\r
- * Set the language version.\r
- *\r
- * <p>\r
- * Setting the language version will affect functions and scripts compiled\r
- * subsequently. See the overview documentation for version-specific\r
- * behavior.\r
- *\r
- * @param version the version as specified by VERSION_1_0, VERSION_1_1, etc.\r
- */\r
- public void setLanguageVersion(int version) {\r
- Object[] array = listeners;\r
- if (array != null && version != this.version) {\r
- firePropertyChangeImpl(array, languageVersionProperty,\r
- new Integer(this.version), \r
- new Integer(version));\r
- }\r
- this.version = version;\r
- }\r
-\r
- /**\r
- * Get the implementation version.\r
- *\r
- * <p>\r
- * The implementation version is of the form \r
- * <pre>\r
- * "<i>name langVer</i> <code>release</code> <i>relNum date</i>"\r
- * </pre>\r
- * where <i>name</i> is the name of the product, <i>langVer</i> is \r
- * the language version, <i>relNum</i> is the release number, and \r
- * <i>date</i> is the release date for that specific \r
- * release in the form "yyyy mm dd". \r
- *\r
- * @return a string that encodes the product, language version, release \r
- * number, and date.\r
- */\r
- public String getImplementationVersion() {\r
- return "Rhino 1.5 release 2 2001 07 27";\r
- }\r
-\r
- /**\r
- * Get the current error reporter.\r
- *\r
- * @see org.mozilla.javascript.ErrorReporter\r
- */\r
- public ErrorReporter getErrorReporter() {\r
- if (errorReporter == null) {\r
- errorReporter = new DefaultErrorReporter();\r
- }\r
- return errorReporter;\r
- }\r
-\r
- /**\r
- * Change the current error reporter.\r
- *\r
- * @return the previous error reporter\r
- * @see org.mozilla.javascript.ErrorReporter\r
- */\r
- public ErrorReporter setErrorReporter(ErrorReporter reporter) {\r
- ErrorReporter result = errorReporter;\r
- Object[] array = listeners;\r
- if (array != null && errorReporter != reporter) {\r
- firePropertyChangeImpl(array, errorReporterProperty,\r
- errorReporter, reporter);\r
- }\r
- errorReporter = reporter;\r
- return result;\r
- }\r
-\r
- /**\r
- * Get the current locale. Returns the default locale if none has\r
- * been set.\r
- *\r
- * @see java.util.Locale\r
- */\r
-\r
- public Locale getLocale() {\r
- if (locale == null)\r
- locale = Locale.getDefault();\r
- return locale;\r
- }\r
-\r
- /**\r
- * Set the current locale.\r
- *\r
- * @see java.util.Locale\r
- */\r
- public Locale setLocale(Locale loc) {\r
- Locale result = locale;\r
- locale = loc;\r
- return result;\r
- }\r
- \r
- /**\r
- * Register an object to receive notifications when a bound property\r
- * has changed\r
- * @see java.beans.PropertyChangeEvent\r
- * @see #removePropertyChangeListener(java.beans.PropertyChangeListener)\r
- * @param listener the listener\r
- */\r
- public void addPropertyChangeListener(PropertyChangeListener listener) {\r
- synchronized (this) {\r
- listeners = ListenerArray.add(listeners, listener);\r
- } \r
- }\r
- \r
- /**\r
- * Remove an object from the list of objects registered to receive \r
- * notification of changes to a bounded property\r
- * @see java.beans.PropertyChangeEvent\r
- * @see #addPropertyChangeListener(java.beans.PropertyChangeListener)\r
- * @param listener the listener\r
- */\r
- public void removePropertyChangeListener(PropertyChangeListener listener) {\r
- synchronized (this) {\r
- listeners = ListenerArray.remove(listeners, listener);\r
- }\r
- }\r
- \r
- /**\r
- * Notify any registered listeners that a bounded property has changed\r
- * @see #addPropertyChangeListener(java.beans.PropertyChangeListener)\r
- * @see #removePropertyChangeListener(java.beans.PropertyChangeListener)\r
- * @see java.beans.PropertyChangeListener\r
- * @see java.beans.PropertyChangeEvent\r
- * @param property the bound property\r
- * @param oldValue the old value\r
- * @param newVale the new value\r
- */\r
- void firePropertyChange(String property, Object oldValue,\r
- Object newValue)\r
- {\r
- Object[] array = listeners;\r
- if (array != null) {\r
- firePropertyChangeImpl(array, property, oldValue, newValue);\r
- }\r
- }\r
-\r
- private void firePropertyChangeImpl(Object[] array, String property,\r
- Object oldValue, Object newValue)\r
- {\r
- for (int i = array.length; i-- != 0;) {\r
- Object obj = array[i];\r
- if (obj instanceof PropertyChangeListener) {\r
- PropertyChangeListener l = (PropertyChangeListener)obj;\r
- l.propertyChange(new PropertyChangeEvent(\r
- this, property, oldValue, newValue));\r
- }\r
- }\r
- }\r
- \r
- /**\r
- * Report a warning using the error reporter for the current thread.\r
- *\r
- * @param message the warning message to report\r
- * @param sourceName a string describing the source, such as a filename\r
- * @param lineno the starting line number\r
- * @param lineSource the text of the line (may be null)\r
- * @param lineOffset the offset into lineSource where problem was detected\r
- * @see org.mozilla.javascript.ErrorReporter\r
- */\r
- public static void reportWarning(String message, String sourceName,\r
- int lineno, String lineSource,\r
- int lineOffset)\r
- {\r
- Context cx = Context.getContext();\r
- cx.getErrorReporter().warning(message, sourceName, lineno,\r
- lineSource, lineOffset);\r
- }\r
-\r
- /**\r
- * Report a warning using the error reporter for the current thread.\r
- *\r
- * @param message the warning message to report\r
- * @see org.mozilla.javascript.ErrorReporter\r
- */\r
- public static void reportWarning(String message) {\r
- int[] linep = { 0 };\r
- String filename = getSourcePositionFromStack(linep);\r
- Context.reportWarning(message, filename, linep[0], null, 0);\r
- }\r
-\r
- /**\r
- * Report an error using the error reporter for the current thread.\r
- *\r
- * @param message the error message to report\r
- * @param sourceName a string describing the source, such as a filename\r
- * @param lineno the starting line number\r
- * @param lineSource the text of the line (may be null)\r
- * @param lineOffset the offset into lineSource where problem was detected\r
- * @see org.mozilla.javascript.ErrorReporter\r
- */\r
- public static void reportError(String message, String sourceName,\r
- int lineno, String lineSource,\r
- int lineOffset)\r
- {\r
- Context cx = getCurrentContext();\r
- if (cx != null) {\r
- cx.errorCount++;\r
- cx.getErrorReporter().error(message, sourceName, lineno,\r
- lineSource, lineOffset);\r
- } else {\r
- throw new EvaluatorException(message);\r
- }\r
- }\r
-\r
- /**\r
- * Report an error using the error reporter for the current thread.\r
- *\r
- * @param message the error message to report\r
- * @see org.mozilla.javascript.ErrorReporter\r
- */\r
- public static void reportError(String message) {\r
- int[] linep = { 0 };\r
- String filename = getSourcePositionFromStack(linep);\r
- Context.reportError(message, filename, linep[0], null, 0);\r
- }\r
-\r
- /**\r
- * Report a runtime error using the error reporter for the current thread.\r
- *\r
- * @param message the error message to report\r
- * @param sourceName a string describing the source, such as a filename\r
- * @param lineno the starting line number\r
- * @param lineSource the text of the line (may be null)\r
- * @param lineOffset the offset into lineSource where problem was detected\r
- * @return a runtime exception that will be thrown to terminate the\r
- * execution of the script\r
- * @see org.mozilla.javascript.ErrorReporter\r
- */\r
- public static EvaluatorException reportRuntimeError(String message,\r
- String sourceName,\r
- int lineno,\r
- String lineSource,\r
- int lineOffset)\r
- {\r
- Context cx = getCurrentContext();\r
- if (cx != null) {\r
- cx.errorCount++;\r
- return cx.getErrorReporter().\r
- runtimeError(message, sourceName, lineno,\r
- lineSource, lineOffset);\r
- } else {\r
- throw new EvaluatorException(message);\r
- }\r
- }\r
-\r
- static EvaluatorException reportRuntimeError0(String messageId) {\r
- return reportRuntimeError(getMessage0(messageId));\r
- }\r
-\r
- static EvaluatorException reportRuntimeError1\r
- (String messageId, Object arg1) \r
- {\r
- return reportRuntimeError(getMessage1(messageId, arg1));\r
- }\r
-\r
- static EvaluatorException reportRuntimeError2\r
- (String messageId, Object arg1, Object arg2) \r
- {\r
- return reportRuntimeError(getMessage2(messageId, arg1, arg2));\r
- }\r
-\r
- static EvaluatorException reportRuntimeError3\r
- (String messageId, Object arg1, Object arg2, Object arg3) \r
- {\r
- return reportRuntimeError(getMessage3(messageId, arg1, arg2, arg3));\r
- }\r
-\r
- /**\r
- * Report a runtime error using the error reporter for the current thread.\r
- *\r
- * @param message the error message to report\r
- * @see org.mozilla.javascript.ErrorReporter\r
- */\r
- public static EvaluatorException reportRuntimeError(String message) {\r
- int[] linep = { 0 };\r
- String filename = getSourcePositionFromStack(linep);\r
- return Context.reportRuntimeError(message, filename, linep[0], null, 0);\r
- }\r
-\r
- /**\r
- * Initialize the standard objects.\r
- *\r
- * Creates instances of the standard objects and their constructors\r
- * (Object, String, Number, Date, etc.), setting up 'scope' to act\r
- * as a global object as in ECMA 15.1.<p>\r
- *\r
- * This method must be called to initialize a scope before scripts\r
- * can be evaluated in that scope.\r
- *\r
- * @param scope the scope to initialize, or null, in which case a new\r
- * object will be created to serve as the scope\r
- * @return the initialized scope\r
- */\r
- public Scriptable initStandardObjects(ScriptableObject scope) {\r
- return initStandardObjects(scope, false);\r
- }\r
- \r
- /**\r
- * Initialize the standard objects.\r
- *\r
- * Creates instances of the standard objects and their constructors\r
- * (Object, String, Number, Date, etc.), setting up 'scope' to act\r
- * as a global object as in ECMA 15.1.<p>\r
- *\r
- * This method must be called to initialize a scope before scripts\r
- * can be evaluated in that scope.<p>\r
- * \r
- * This form of the method also allows for creating "sealed" standard\r
- * objects. An object that is sealed cannot have properties added or\r
- * removed. This is useful to create a "superglobal" that can be shared \r
- * among several top-level objects. Note that sealing is not allowed in\r
- * the current ECMA/ISO language specification, but is likely for\r
- * the next version.\r
- *\r
- * @param scope the scope to initialize, or null, in which case a new\r
- * object will be created to serve as the scope\r
- * @param sealed whether or not to create sealed standard objects that\r
- * cannot be modified. \r
- * @return the initialized scope\r
- * @since 1.4R3\r
- */\r
- public ScriptableObject initStandardObjects(ScriptableObject scope,\r
- boolean sealed)\r
- {\r
- if (scope == null)\r
- scope = new NativeObject();\r
-\r
- BaseFunction.init(this, scope, sealed);\r
- NativeObject.init(this, scope, sealed);\r
-\r
- Scriptable objectProto = ScriptableObject.getObjectPrototype(scope);\r
-\r
- // Function.prototype.__proto__ should be Object.prototype\r
- Scriptable functionProto = ScriptableObject.getFunctionPrototype(scope);\r
- functionProto.setPrototype(objectProto);\r
-\r
- // Set the prototype of the object passed in if need be\r
- if (scope.getPrototype() == null)\r
- scope.setPrototype(objectProto);\r
-\r
- // must precede NativeGlobal since it's needed therein\r
- NativeError.init(this, scope, sealed);\r
- NativeGlobal.init(this, scope, sealed);\r
-\r
- NativeArray.init(this, scope, sealed);\r
- NativeString.init(this, scope, sealed);\r
- NativeBoolean.init(this, scope, sealed);\r
- NativeNumber.init(this, scope, sealed);\r
- NativeDate.init(this, scope, sealed);\r
- NativeMath.init(this, scope, sealed);\r
-\r
- NativeWith.init(this, scope, sealed);\r
- NativeCall.init(this, scope, sealed);\r
- NativeScript.init(this, scope, sealed);\r
-\r
- new LazilyLoadedCtor(scope, \r
- "RegExp",\r
- "org.mozilla.javascript.regexp.NativeRegExp",\r
- sealed);\r
-\r
- // This creates the Packages and java package roots.\r
- new LazilyLoadedCtor(scope, \r
- "Packages",\r
- "org.mozilla.javascript.NativeJavaPackage",\r
- sealed);\r
- new LazilyLoadedCtor(scope, \r
- "java", \r
- "org.mozilla.javascript.NativeJavaPackage",\r
- sealed);\r
- new LazilyLoadedCtor(scope, \r
- "getClass",\r
- "org.mozilla.javascript.NativeJavaPackage",\r
- sealed);\r
- \r
- // Define the JavaAdapter class, allowing it to be overridden.\r
- String adapterClass = "org.mozilla.javascript.JavaAdapter";\r
- String adapterProperty = "JavaAdapter";\r
- try {\r
- adapterClass = System.getProperty(adapterClass, adapterClass);\r
- adapterProperty = System.getProperty\r
- ("org.mozilla.javascript.JavaAdapterClassName",\r
- adapterProperty);\r
- }\r
- catch (SecurityException e) {\r
- // We may not be allowed to get system properties. Just\r
- // use the default adapter in that case.\r
- }\r
-\r
- new LazilyLoadedCtor(scope, adapterProperty, adapterClass, sealed);\r
-\r
- return scope;\r
- }\r
- \r
- /**\r
- * Get the singleton object that represents the JavaScript Undefined value.\r
- */\r
- public static Object getUndefinedValue() {\r
- return Undefined.instance;\r
- }\r
- \r
- /**\r
- * Evaluate a JavaScript source string.\r
- *\r
- * The provided source name and line number are used for error messages\r
- * and for producing debug information.\r
- *\r
- * @param scope the scope to execute in\r
- * @param source the JavaScript source\r
- * @param sourceName a string describing the source, such as a filename\r
- * @param lineno the starting line number\r
- * @param securityDomain an arbitrary object that specifies security \r
- * information about the origin or owner of the script. For \r
- * implementations that don't care about security, this value \r
- * may be null.\r
- * @return the result of evaluating the string\r
- * @exception JavaScriptException if an uncaught JavaScript exception\r
- * occurred while evaluating the source string\r
- * @see org.mozilla.javascript.SecuritySupport\r
- */\r
- public Object evaluateString(Scriptable scope, String source,\r
- String sourceName, int lineno,\r
- Object securityDomain)\r
- throws JavaScriptException\r
- {\r
- try {\r
- Reader in = new StringReader(source);\r
- return evaluateReader(scope, in, sourceName, lineno, \r
- securityDomain);\r
- }\r
- catch (IOException ioe) {\r
- // Should never occur because we just made the reader from a String\r
- throw new RuntimeException();\r
- }\r
- }\r
-\r
- /**\r
- * Evaluate a reader as JavaScript source.\r
- *\r
- * All characters of the reader are consumed.\r
- *\r
- * @param scope the scope to execute in\r
- * @param in the Reader to get JavaScript source from\r
- * @param sourceName a string describing the source, such as a filename\r
- * @param lineno the starting line number\r
- * @param securityDomain an arbitrary object that specifies security \r
- * information about the origin or owner of the script. For \r
- * implementations that don't care about security, this value \r
- * may be null.\r
- * @return the result of evaluating the source\r
- *\r
- * @exception IOException if an IOException was generated by the Reader\r
- * @exception JavaScriptException if an uncaught JavaScript exception\r
- * occurred while evaluating the Reader\r
- */\r
- public Object evaluateReader(Scriptable scope, Reader in,\r
- String sourceName, int lineno,\r
- Object securityDomain)\r
- throws IOException, JavaScriptException\r
- {\r
- Script script = compileReader(scope, in, sourceName, lineno, \r
- securityDomain);\r
- if (script != null)\r
- return script.exec(this, scope);\r
- else\r
- return null;\r
- }\r
-\r
- /**\r
- * Check whether a string is ready to be compiled.\r
- * <p>\r
- * stringIsCompilableUnit is intended to support interactive compilation of\r
- * javascript. If compiling the string would result in an error\r
- * that might be fixed by appending more source, this method\r
- * returns false. In every other case, it returns true.\r
- * <p>\r
- * Interactive shells may accumulate source lines, using this\r
- * method after each new line is appended to check whether the\r
- * statement being entered is complete.\r
- *\r
- * @param source the source buffer to check\r
- * @return whether the source is ready for compilation\r
- * @since 1.4 Release 2\r
- */\r
- synchronized public boolean stringIsCompilableUnit(String source)\r
- {\r
- Reader in = new StringReader(source);\r
- // no source name or source text manager, because we're just\r
- // going to throw away the result.\r
- TokenStream ts = new TokenStream(in, null, null, 1);\r
-\r
- // Temporarily set error reporter to always be the exception-throwing\r
- // DefaultErrorReporter. (This is why the method is synchronized...)\r
- ErrorReporter currentReporter = \r
- setErrorReporter(new DefaultErrorReporter());\r
-\r
- boolean errorseen = false;\r
- try {\r
- IRFactory irf = new IRFactory(ts, null);\r
- Parser p = new Parser(irf);\r
- p.parse(ts);\r
- } catch (IOException ioe) {\r
- errorseen = true;\r
- } catch (EvaluatorException ee) {\r
- errorseen = true;\r
- } finally {\r
- // Restore the old error reporter.\r
- setErrorReporter(currentReporter);\r
- }\r
- // Return false only if an error occurred as a result of reading past\r
- // the end of the file, i.e. if the source could be fixed by\r
- // appending more source.\r
- if (errorseen && ts.eof())\r
- return false;\r
- else \r
- return true;\r
- }\r
-\r
- /**\r
- * Compiles the source in the given reader.\r
- * <p>\r
- * Returns a script that may later be executed.\r
- * Will consume all the source in the reader.\r
- *\r
- * @param scope if nonnull, will be the scope in which the script object\r
- * is created. The script object will be a valid JavaScript object\r
- * as if it were created using the JavaScript1.3 Script constructor\r
- * @param in the input reader\r
- * @param sourceName a string describing the source, such as a filename\r
- * @param lineno the starting line number for reporting errors\r
- * @param securityDomain an arbitrary object that specifies security \r
- * information about the origin or owner of the script. For \r
- * implementations that don't care about security, this value \r
- * may be null.\r
- * @return a script that may later be executed\r
- * @see org.mozilla.javascript.Script#exec\r
- * @exception IOException if an IOException was generated by the Reader\r
- */\r
- public Script compileReader(Scriptable scope, Reader in, String sourceName,\r
- int lineno, Object securityDomain)\r
- throws IOException\r
- {\r
- return (Script) compile(scope, in, sourceName, lineno, securityDomain, \r
- false);\r
- }\r
-\r
-\r
- /**\r
- * Compile a JavaScript function.\r
- * <p>\r
- * The function source must be a function definition as defined by\r
- * ECMA (e.g., "function f(a) { return a; }"). \r
- *\r
- * @param scope the scope to compile relative to\r
- * @param source the function definition source\r
- * @param sourceName a string describing the source, such as a filename\r
- * @param lineno the starting line number\r
- * @param securityDomain an arbitrary object that specifies security \r
- * information about the origin or owner of the script. For \r
- * implementations that don't care about security, this value \r
- * may be null.\r
- * @return a Function that may later be called\r
- * @see org.mozilla.javascript.Function\r
- */\r
- public Function compileFunction(Scriptable scope, String source,\r
- String sourceName, int lineno,\r
- Object securityDomain)\r
- {\r
- Reader in = new StringReader(source);\r
- try {\r
- return (Function) compile(scope, in, sourceName, lineno, \r
- securityDomain, true);\r
- }\r
- catch (IOException ioe) {\r
- // Should never happen because we just made the reader\r
- // from a String\r
- throw new RuntimeException();\r
- }\r
- }\r
-\r
- /**\r
- * Decompile the script.\r
- * <p>\r
- * The canonical source of the script is returned.\r
- *\r
- * @param script the script to decompile\r
- * @param scope the scope under which to decompile\r
- * @param indent the number of spaces to indent the result\r
- * @return a string representing the script source\r
- */\r
- public String decompileScript(Script script, Scriptable scope,\r
- int indent)\r
- {\r
- NativeScript ns = (NativeScript) script;\r
- ns.initScript(scope);\r
- return ns.decompile(this, indent, false);\r
- }\r
-\r
- /**\r
- * Decompile a JavaScript Function.\r
- * <p>\r
- * Decompiles a previously compiled JavaScript function object to\r
- * canonical source.\r
- * <p>\r
- * Returns function body of '[native code]' if no decompilation\r
- * information is available.\r
- *\r
- * @param fun the JavaScript function to decompile\r
- * @param indent the number of spaces to indent the result\r
- * @return a string representing the function source\r
- */\r
- public String decompileFunction(Function fun, int indent) {\r
- if (fun instanceof BaseFunction)\r
- return ((BaseFunction)fun).decompile(this, indent, false);\r
- else\r
- return "function " + fun.getClassName() +\r
- "() {\n\t[native code]\n}\n";\r
- }\r
-\r
- /**\r
- * Decompile the body of a JavaScript Function.\r
- * <p>\r
- * Decompiles the body a previously compiled JavaScript Function\r
- * object to canonical source, omitting the function header and\r
- * trailing brace.\r
- *\r
- * Returns '[native code]' if no decompilation information is available.\r
- *\r
- * @param fun the JavaScript function to decompile\r
- * @param indent the number of spaces to indent the result\r
- * @return a string representing the function body source.\r
- */\r
- public String decompileFunctionBody(Function fun, int indent) {\r
- if (fun instanceof BaseFunction)\r
- return ((BaseFunction)fun).decompile(this, indent, true);\r
- else\r
- // not sure what the right response here is. JSRef currently\r
- // dumps core.\r
- return "[native code]\n";\r
- }\r
-\r
- /**\r
- * Create a new JavaScript object.\r
- *\r
- * Equivalent to evaluating "new Object()".\r
- * @param scope the scope to search for the constructor and to evaluate\r
- * against\r
- * @return the new object\r
- * @exception PropertyException if "Object" cannot be found in\r
- * the scope\r
- * @exception NotAFunctionException if the "Object" found in the scope\r
- * is not a function\r
- * @exception JavaScriptException if an uncaught JavaScript exception\r
- * occurred while creating the object\r
- */\r
- public Scriptable newObject(Scriptable scope)\r
- throws PropertyException,\r
- NotAFunctionException,\r
- JavaScriptException\r
- {\r
- return newObject(scope, "Object", null);\r
- }\r
-\r
- /**\r
- * Create a new JavaScript object by executing the named constructor.\r
- *\r
- * The call <code>newObject(scope, "Foo")</code> is equivalent to\r
- * evaluating "new Foo()".\r
- *\r
- * @param scope the scope to search for the constructor and to evaluate against\r
- * @param constructorName the name of the constructor to call\r
- * @return the new object\r
- * @exception PropertyException if a property with the constructor\r
- * name cannot be found in the scope\r
- * @exception NotAFunctionException if the property found in the scope\r
- * is not a function\r
- * @exception JavaScriptException if an uncaught JavaScript exception\r
- * occurred while creating the object\r
- */\r
- public Scriptable newObject(Scriptable scope, String constructorName)\r
- throws PropertyException,\r
- NotAFunctionException,\r
- JavaScriptException\r
- {\r
- return newObject(scope, constructorName, null);\r
- }\r
-\r
- /**\r
- * Creates a new JavaScript object by executing the named constructor.\r
- *\r
- * Searches <code>scope</code> for the named constructor, calls it with\r
- * the given arguments, and returns the result.<p>\r
- *\r
- * The code\r
- * <pre>\r
- * Object[] args = { "a", "b" };\r
- * newObject(scope, "Foo", args)</pre>\r
- * is equivalent to evaluating "new Foo('a', 'b')", assuming that the Foo\r
- * constructor has been defined in <code>scope</code>.\r
- *\r
- * @param scope The scope to search for the constructor and to evaluate\r
- * against\r
- * @param constructorName the name of the constructor to call\r
- * @param args the array of arguments for the constructor\r
- * @return the new object\r
- * @exception PropertyException if a property with the constructor\r
- * name cannot be found in the scope\r
- * @exception NotAFunctionException if the property found in the scope\r
- * is not a function\r
- * @exception JavaScriptException if an uncaught JavaScript exception\r
- * occurs while creating the object\r
- */\r
- public Scriptable newObject(Scriptable scope, String constructorName,\r
- Object[] args)\r
- throws PropertyException,\r
- NotAFunctionException,\r
- JavaScriptException\r
- {\r
- Object ctorVal = ScriptRuntime.getTopLevelProp(scope, constructorName);\r
- if (ctorVal == Scriptable.NOT_FOUND) {\r
- String message = getMessage1("msg.ctor.not.found", constructorName);\r
- throw new PropertyException(message);\r
- }\r
- if (!(ctorVal instanceof Function)) {\r
- String message = getMessage1("msg.not.ctor", constructorName);\r
- throw new NotAFunctionException(message);\r
- }\r
- Function ctor = (Function) ctorVal;\r
- return ctor.construct(this, ctor.getParentScope(),\r
- (args == null) ? ScriptRuntime.emptyArgs : args);\r
- }\r
-\r
- /**\r
- * Create an array with a specified initial length.\r
- * <p>\r
- * @param scope the scope to create the object in\r
- * @param length the initial length (JavaScript arrays may have\r
- * additional properties added dynamically).\r
- * @return the new array object\r
- */\r
- public Scriptable newArray(Scriptable scope, int length) {\r
- Scriptable result = new NativeArray(length);\r
- newArrayHelper(scope, result);\r
- return result;\r
- }\r
-\r
- /**\r
- * Create an array with a set of initial elements.\r
- * <p>\r
- * @param scope the scope to create the object in\r
- * @param elements the initial elements. Each object in this array\r
- * must be an acceptable JavaScript type.\r
- * @return the new array object\r
- */\r
- public Scriptable newArray(Scriptable scope, Object[] elements) {\r
- Scriptable result = new NativeArray(elements);\r
- newArrayHelper(scope, result);\r
- return result;\r
- }\r
- \r
- /**\r
- * Get the elements of a JavaScript array.\r
- * <p>\r
- * If the object defines a length property, a Java array with that\r
- * length is created and initialized with the values obtained by\r
- * calling get() on object for each value of i in [0,length-1]. If\r
- * there is not a defined value for a property the Undefined value\r
- * is used to initialize the corresponding element in the array. The\r
- * Java array is then returned.\r
- * If the object doesn't define a length property, null is returned.\r
- * @param object the JavaScript array or array-like object\r
- * @return a Java array of objects\r
- * @since 1.4 release 2\r
- */\r
- public Object[] getElements(Scriptable object) {\r
- double doubleLen = NativeArray.getLengthProperty(object);\r
- if (doubleLen != doubleLen)\r
- return null;\r
- int len = (int) doubleLen;\r
- Object[] result = new Object[len];\r
- for (int i=0; i < len; i++) {\r
- Object elem = object.get(i, object);\r
- result[i] = elem == Scriptable.NOT_FOUND ? Undefined.instance \r
- : elem;\r
- }\r
- return result;\r
- }\r
-\r
- /**\r
- * Convert the value to a JavaScript boolean value.\r
- * <p>\r
- * See ECMA 9.2.\r
- *\r
- * @param value a JavaScript value\r
- * @return the corresponding boolean value converted using\r
- * the ECMA rules\r
- */\r
- public static boolean toBoolean(Object value) {\r
- return ScriptRuntime.toBoolean(value);\r
- }\r
-\r
- /**\r
- * Convert the value to a JavaScript Number value.\r
- * <p>\r
- * Returns a Java double for the JavaScript Number.\r
- * <p>\r
- * See ECMA 9.3.\r
- *\r
- * @param value a JavaScript value\r
- * @return the corresponding double value converted using\r
- * the ECMA rules\r
- */\r
- public static double toNumber(Object value) {\r
- return ScriptRuntime.toNumber(value);\r
- }\r
-\r
- /**\r
- * Convert the value to a JavaScript String value.\r
- * <p>\r
- * See ECMA 9.8.\r
- * <p>\r
- * @param value a JavaScript value\r
- * @return the corresponding String value converted using\r
- * the ECMA rules\r
- */\r
- public static String toString(Object value) {\r
- return ScriptRuntime.toString(value);\r
- }\r
-\r
- /**\r
- * Convert the value to an JavaScript object value.\r
- * <p>\r
- * Note that a scope must be provided to look up the constructors\r
- * for Number, Boolean, and String.\r
- * <p>\r
- * See ECMA 9.9.\r
- * <p>\r
- * Additionally, arbitrary Java objects and classes will be\r
- * wrapped in a Scriptable object with its Java fields and methods\r
- * reflected as JavaScript properties of the object.\r
- *\r
- * @param value any Java object\r
- * @param scope global scope containing constructors for Number,\r
- * Boolean, and String\r
- * @return new JavaScript object\r
- */\r
- public static Scriptable toObject(Object value, Scriptable scope) {\r
- return ScriptRuntime.toObject(scope, value, null);\r
- }\r
- \r
- /**\r
- * Convert the value to an JavaScript object value.\r
- * <p>\r
- * Note that a scope must be provided to look up the constructors\r
- * for Number, Boolean, and String.\r
- * <p>\r
- * See ECMA 9.9.\r
- * <p>\r
- * Additionally, arbitrary Java objects and classes will be\r
- * wrapped in a Scriptable object with its Java fields and methods\r
- * reflected as JavaScript properties of the object. If the \r
- * "staticType" parameter is provided, it will be used as the static\r
- * type of the Java value to create.\r
- *\r
- * @param value any Java object\r
- * @param scope global scope containing constructors for Number,\r
- * Boolean, and String\r
- * @param staticType the static type of the Java value to create\r
- * @return new JavaScript object\r
- */\r
- public static Scriptable toObject(Object value, Scriptable scope, \r
- Class staticType) {\r
- if (value == null && staticType != null)\r
- return null;\r
- return ScriptRuntime.toObject(scope, value, staticType);\r
- }\r
-\r
- /**\r
- * Tell whether debug information is being generated.\r
- * @since 1.3\r
- */\r
- public boolean isGeneratingDebug() {\r
- return generatingDebug;\r
- }\r
-\r
- /**\r
- * Specify whether or not debug information should be generated.\r
- * <p>\r
- * Setting the generation of debug information on will set the\r
- * optimization level to zero.\r
- * @since 1.3\r
- */\r
- public void setGeneratingDebug(boolean generatingDebug) {\r
- generatingDebugChanged = true;\r
- if (generatingDebug)\r
- setOptimizationLevel(0);\r
- this.generatingDebug = generatingDebug;\r
- }\r
-\r
- /**\r
- * Tell whether source information is being generated.\r
- * @since 1.3\r
- */\r
- public boolean isGeneratingSource() {\r
- return generatingSource;\r
- }\r
-\r
- /**\r
- * Specify whether or not source information should be generated.\r
- * <p>\r
- * Without source information, evaluating the "toString" method\r
- * on JavaScript functions produces only "[native code]" for\r
- * the body of the function.\r
- * Note that code generated without source is not fully ECMA\r
- * conformant.\r
- * @since 1.3\r
- */\r
- public void setGeneratingSource(boolean generatingSource) {\r
- this.generatingSource = generatingSource;\r
- }\r
-\r
- /**\r
- * Get the current optimization level.\r
- * <p>\r
- * The optimization level is expressed as an integer between -1 and\r
- * 9.\r
- * @since 1.3\r
- *\r
- */\r
- public int getOptimizationLevel() {\r
- return optimizationLevel;\r
- }\r
-\r
- /**\r
- * Set the current optimization level.\r
- * <p>\r
- * The optimization level is expected to be an integer between -1 and\r
- * 9. Any negative values will be interpreted as -1, and any values\r
- * greater than 9 will be interpreted as 9.\r
- * An optimization level of -1 indicates that interpretive mode will\r
- * always be used. Levels 0 through 9 indicate that class files may \r
- * be generated. Higher optimization levels trade off compile time\r
- * performance for runtime performance.\r
- * The optimizer level can't be set greater than -1 if the optimizer\r
- * package doesn't exist at run time.\r
- * @param optimizationLevel an integer indicating the level of\r
- * optimization to perform\r
- * @since 1.3\r
- *\r
- */\r
- public void setOptimizationLevel(int optimizationLevel) {\r
- if (optimizationLevel < 0) {\r
- optimizationLevel = -1;\r
- } else if (optimizationLevel > 9) {\r
- optimizationLevel = 9;\r
- }\r
- if (codegenClass == null)\r
- optimizationLevel = -1;\r
- this.optimizationLevel = optimizationLevel;\r
- }\r
-\r
- /**\r
- * Get the current target class file name.\r
- * <p>\r
- * If nonnull, requests to compile source will result in one or\r
- * more class files being generated.\r
- * @since 1.3\r
- */\r
- public String getTargetClassFileName() {\r
- return nameHelper == null\r
- ? null \r
- : nameHelper.getTargetClassFileName();\r
- }\r
-\r
- /**\r
- * Set the current target class file name.\r
- * <p>\r
- * If nonnull, requests to compile source will result in one or\r
- * more class files being generated. If null, classes will only\r
- * be generated in memory.\r
- *\r
- * @since 1.3\r
- */\r
- public void setTargetClassFileName(String classFileName) {\r
- if (nameHelper != null)\r
- nameHelper.setTargetClassFileName(classFileName);\r
- }\r
-\r
- /**\r
- * Get the current package to generate classes into.\r
- *\r
- * @since 1.3\r
- */\r
- public String getTargetPackage() {\r
- return (nameHelper == null) ? null : nameHelper.getTargetPackage();\r
- }\r
-\r
- /**\r
- * Set the package to generate classes into.\r
- *\r
- * @since 1.3\r
- */\r
- public void setTargetPackage(String targetPackage) {\r
- if (nameHelper != null)\r
- nameHelper.setTargetPackage(targetPackage);\r
- }\r
-\r
- /**\r
- * Get the current interface to write class bytes into.\r
- *\r
- * @see ClassOutput\r
- * @since 1.5 Release 2\r
- */\r
- public ClassOutput getClassOutput() {\r
- return nameHelper == null ? null : nameHelper.getClassOutput();\r
- }\r
-\r
- /**\r
- * Set the interface to write class bytes into.\r
- * Unless setTargetClassFileName() has been called classOutput will be\r
- * used each time the javascript compiler has generated the bytecode for a\r
- * script class.\r
- *\r
- * @see ClassOutput\r
- * @since 1.5 Release 2\r
- */\r
- public void setClassOutput(ClassOutput classOutput) {\r
- if (nameHelper != null)\r
- nameHelper.setClassOutput(classOutput);\r
- }\r
- \r
- /**\r
- * Add a Context listener.\r
- */\r
- public static void addContextListener(ContextListener listener) {\r
- synchronized (staticDataLock) {\r
- contextListeners = ListenerArray.add(contextListeners, listener);\r
- }\r
- }\r
- \r
- /**\r
- * Remove a Context listener.\r
- * @param listener the listener to remove.\r
- */\r
- public static void removeContextListener(ContextListener listener) {\r
- synchronized (staticDataLock) {\r
- contextListeners = ListenerArray.remove(contextListeners, listener);\r
- }\r
- }\r
-\r
- /**\r
- * Set the security support for this context. \r
- * <p> SecuritySupport may only be set if it is currently null.\r
- * Otherwise a SecurityException is thrown.\r
- * @param supportObj a SecuritySupport object\r
- * @throws SecurityException if there is already a SecuritySupport\r
- * object for this Context\r
- */\r
- public synchronized void setSecuritySupport(SecuritySupport supportObj) {\r
- if (securitySupport != null) {\r
- throw new SecurityException("Cannot overwrite existing " +\r
- "SecuritySupport object");\r
- }\r
- securitySupport = supportObj;\r
- }\r
- \r
- /**\r
- * Return true if a security domain is required on calls to\r
- * compile and evaluate scripts.\r
- *\r
- * @since 1.4 Release 2\r
- */\r
- public static boolean isSecurityDomainRequired() { \r
- return requireSecurityDomain;\r
- }\r
- \r
- /**\r
- * Returns the security context associated with the innermost\r
- * script or function being executed by the interpreter.\r
- * @since 1.4 release 2\r
- */\r
- public Object getInterpreterSecurityDomain() {\r
- return interpreterSecurityDomain;\r
- }\r
- \r
- /**\r
- * Returns true if the class parameter is a class in the \r
- * interpreter. Typically used by embeddings that get a class\r
- * context to check security. These embeddings must know \r
- * whether to get the security context associated with the\r
- * interpreter or not.\r
- * \r
- * @param cl a class to test whether or not it is an interpreter\r
- * class\r
- * @return true if cl is an interpreter class\r
- * @since 1.4 release 2\r
- */\r
- public boolean isInterpreterClass(Class cl) {\r
- return cl == Interpreter.class;\r
- }\r
- \r
- /**\r
- * Set the class that the generated target will extend.\r
- * \r
- * @param extendsClass the class it extends\r
- */\r
- public void setTargetExtends(Class extendsClass) {\r
- if (nameHelper != null) {\r
- nameHelper.setTargetExtends(extendsClass);\r
- }\r
- }\r
- \r
- /**\r
- * Set the interfaces that the generated target will implement.\r
- * \r
- * @param implementsClasses an array of Class objects, one for each\r
- * interface the target will extend\r
- */\r
- public void setTargetImplements(Class[] implementsClasses) {\r
- if (nameHelper != null) {\r
- nameHelper.setTargetImplements(implementsClasses);\r
- }\r
- }\r
- \r
- /**\r
- * Get a value corresponding to a key.\r
- * <p>\r
- * Since the Context is associated with a thread it can be \r
- * used to maintain values that can be later retrieved using \r
- * the current thread. \r
- * <p>\r
- * Note that the values are maintained with the Context, so\r
- * if the Context is disassociated from the thread the values\r
- * cannot be retreived. Also, if private data is to be maintained\r
- * in this manner the key should be a java.lang.Object \r
- * whose reference is not divulged to untrusted code.\r
- * @param key the key used to lookup the value\r
- * @return a value previously stored using putThreadLocal.\r
- */\r
- public Object getThreadLocal(Object key) {\r
- if (hashtable == null)\r
- return null;\r
- return hashtable.get(key);\r
- }\r
-\r
- /**\r
- * Put a value that can later be retrieved using a given key.\r
- * <p>\r
- * @param key the key used to index the value\r
- * @param value the value to save\r
- */\r
- public void putThreadLocal(Object key, Object value) {\r
- if (hashtable == null)\r
- hashtable = new Hashtable();\r
- hashtable.put(key, value);\r
- }\r
- \r
- /**\r
- * Remove values from thread-local storage.\r
- * @param key the key for the entry to remove.\r
- * @since 1.5 release 2\r
- */\r
- public void removeThreadLocal(Object key) {\r
- if (hashtable == null)\r
- return;\r
- hashtable.remove(key);\r
- } \r
- \r
- /**\r
- * Return whether functions are compiled by this context using\r
- * dynamic scope.\r
- * <p>\r
- * If functions are compiled with dynamic scope, then they execute\r
- * in the scope of their caller, rather than in their parent scope.\r
- * This is useful for sharing functions across multiple scopes.\r
- * @since 1.5 Release 1\r
- */\r
- public boolean hasCompileFunctionsWithDynamicScope() {\r
- return compileFunctionsWithDynamicScopeFlag;\r
- }\r
- \r
- /**\r
- * Set whether functions compiled by this context should use\r
- * dynamic scope.\r
- * <p>\r
- * @param flag if true, compile functions with dynamic scope\r
- * @since 1.5 Release 1\r
- */\r
- public void setCompileFunctionsWithDynamicScope(boolean flag) {\r
- compileFunctionsWithDynamicScopeFlag = flag;\r
- }\r
- \r
- /**\r
- * Set whether to cache some values statically.\r
- * <p>\r
- * By default, the engine will cache some values statically \r
- * (reflected Java classes, for instance). This can speed\r
- * execution dramatically, but increases the memory footprint.\r
- * Also, with caching enabled, references may be held to \r
- * objects past the lifetime of any real usage. \r
- * <p>\r
- * If caching is enabled and this method is called with a \r
- * <code>false</code> argument, the caches will be emptied.\r
- * So one strategy could be to clear the caches at times\r
- * appropriate to the application.\r
- * <p>\r
- * Caching is enabled by default.\r
- * \r
- * @param cachingEnabled if true, caching is enabled\r
- * @since 1.5 Release 1 \r
- */\r
- public static void setCachingEnabled(boolean cachingEnabled) {\r
- if (isCachingEnabled && !cachingEnabled) {\r
- // Caching is being turned off. Empty caches.\r
- JavaMembers.classTable = new Hashtable();\r
- nameHelper.reset();\r
- }\r
- isCachingEnabled = cachingEnabled;\r
- FunctionObject.setCachingEnabled(cachingEnabled);\r
- }\r
- \r
- /**\r
- * Set a WrapHandler for this Context.\r
- * <p>\r
- * The WrapHandler allows custom object wrapping behavior for \r
- * Java object manipulated with JavaScript.\r
- * @see org.mozilla.javascript.WrapHandler\r
- * @since 1.5 Release 2 \r
- */\r
- public void setWrapHandler(WrapHandler wrapHandler) {\r
- this.wrapHandler = wrapHandler;\r
- }\r
- \r
- /**\r
- * Return the current WrapHandler, or null if none is defined.\r
- * @see org.mozilla.javascript.WrapHandler\r
- * @since 1.5 Release 2 \r
- */\r
- public WrapHandler getWrapHandler() {\r
- return wrapHandler;\r
- }\r
- \r
- public DebuggableEngine getDebuggableEngine() {\r
- if (debuggableEngine == null)\r
- debuggableEngine = new DebuggableEngineImpl(this);\r
- return debuggableEngine;\r
- }\r
- \r
- \r
- /**\r
- * if hasFeature(FEATURE_NON_ECMA_GET_YEAR) returns true,\r
- * Date.prototype.getYear subtructs 1900 only if 1900 <= date < 2000\r
- * in deviation with Ecma B.2.4\r
- */\r
- public static final int FEATURE_NON_ECMA_GET_YEAR = 1;\r
- \r
- /**\r
- * Controls certain aspects of script semantics. \r
- * Should be overwritten to alter default behavior.\r
- * @param featureIndex feature index to check\r
- * @return true if the <code>featureIndex</code> feature is turned on\r
- * @see #FEATURE_NON_ECMA_GET_YEAR\r
- */\r
- public boolean hasFeature(int featureIndex) {\r
- if (featureIndex == FEATURE_NON_ECMA_GET_YEAR) {\r
- /*\r
- * During the great date rewrite of 1.3, we tried to track the\r
- * evolving ECMA standard, which then had a definition of\r
- * getYear which always subtracted 1900. Which we\r
- * implemented, not realizing that it was incompatible with\r
- * the old behavior... now, rather than thrash the behavior\r
- * yet again, we've decided to leave it with the - 1900\r
- * behavior and point people to the getFullYear method. But\r
- * we try to protect existing scripts that have specified a\r
- * version...\r
- */\r
- return (version == Context.VERSION_1_0 \r
- || version == Context.VERSION_1_1\r
- || version == Context.VERSION_1_2);\r
- }\r
- throw new RuntimeException("Bad feature index: " + featureIndex);\r
- }\r
-\r
- /**\r
- * Get/Set threshold of executed instructions counter that triggers call to\r
- * <code>observeInstructionCount()</code>.\r
- * When the threshold is zero, instruction counting is disabled, \r
- * otherwise each time the run-time executes at least the threshold value\r
- * of script instructions, <code>observeInstructionCount()</code> will \r
- * be called.\r
- */\r
- public int getInstructionObserverThreshold() {\r
- return instructionThreshold;\r
- }\r
- \r
- public void setInstructionObserverThreshold(int threshold) {\r
- instructionThreshold = threshold;\r
- }\r
- \r
- /** \r
- * Allow application to monitor counter of executed script instructions\r
- * in Context subclasses.\r
- * Run-time calls this when instruction counting is enabled and the counter\r
- * reaches limit set by <code>setInstructionObserverThreshold()</code>.\r
- * The method is useful to observe long running scripts and if necessary\r
- * to terminate them.\r
- * @param instructionCount amount of script instruction executed since \r
- * last call to <code>observeInstructionCount</code> \r
- * @throws Error to terminate the script\r
- */\r
- protected void observeInstructionCount(int instructionCount) {}\r
- \r
- /********** end of API **********/\r
- \r
- void pushFrame(DebugFrame frame) {\r
- if (frameStack == null)\r
- frameStack = new java.util.Stack();\r
- frameStack.push(frame);\r
- }\r
- \r
- void popFrame() {\r
- frameStack.pop();\r
- }\r
- \r
-\r
-\r
- static String getMessage0(String messageId) {\r
- return getMessage(messageId, null);\r
- }\r
-\r
- static String getMessage1(String messageId, Object arg1) {\r
- Object[] arguments = {arg1};\r
- return getMessage(messageId, arguments);\r
- }\r
-\r
- static String getMessage2(String messageId, Object arg1, Object arg2) {\r
- Object[] arguments = {arg1, arg2};\r
- return getMessage(messageId, arguments);\r
- }\r
-\r
- static String getMessage3\r
- (String messageId, Object arg1, Object arg2, Object arg3) {\r
- Object[] arguments = {arg1, arg2, arg3};\r
- return getMessage(messageId, arguments);\r
- }\r
- /**\r
- * Internal method that reports an error for missing calls to\r
- * enter().\r
- */\r
- static Context getContext() {\r
- Thread t = Thread.currentThread();\r
- Context cx = (Context) threadContexts.get(t);\r
- if (cx == null) {\r
- throw new RuntimeException(\r
- "No Context associated with current Thread");\r
- }\r
- return cx;\r
- }\r
-\r
- /** GCJ doesn't have an easy way to bundle up .properties files, so we do this */\r
- static class HardCodedResourceBundle extends ListResourceBundle {\r
- public Object[][] getContents() { return contents; }\r
- static final Object[][] contents = {\r
- { "msg.dup.parms", "Duplicate parameter name \"{0}\"." },\r
- { "msg.ctor.not.found", "Constructor for \"{0}\" not found." },\r
- { "msg.not.ctor", "\"{0}\" is not a constructor." },\r
- { "msg.varargs.ctor", "Method or constructor \"{0}\" must be static with the signature \"(Context cx, Object[] args, Function ctorObj, boolean inNewExpr)\" to define a variable arguments constructor." },\r
- { "msg.varargs.fun", "Method \"{0}\" must be static with the signature \"(Context cx, Scriptable thisObj, Object[] args, Function funObj)\" to define a variable arguments function." },\r
- { "msg.incompat.call", "Method \"{0}\" called on incompatible object." },\r
- { "msg.bad.parms", "Bad method parameters for \"{0}\"." },\r
- { "msg.no.overload", "Method \"{0}\" occurs multiple times in class \"{1}\"." },\r
- { "msg.method.not.found", "Method \"{0}\" not found in \"{1}\"." },\r
- { "msg.bad.for.in.lhs", "Invalid left-hand side of for..in loop." },\r
- { "msg.bad.lhs.assign", "Invalid assignment left-hand side." },\r
- { "msg.mult.index", "Only one variable allowed in for..in loop." },\r
- { "msg.cant.convert", "Can''t convert to type \"{0}\"." },\r
- { "msg.cant.call.indirect", "Function \"{0}\" must be called directly, and not by way of a function of another name." },\r
- { "msg.eval.nonstring", "Calling eval() with anything other than a primitive string value will simply return the value. Is this what you intended?" },\r
- { "msg.only.from.new", "\"{0}\" may only be invoked from a \"new\" expression." },\r
- { "msg.deprec.ctor", "The \"{0}\" constructor is deprecated." },\r
- { "msg.no.function.ref.found.in", "no source found in {1} to decompile function reference {0}" },\r
- { "msg.no.function.ref.found", "no source found to decompile function reference {0}" },\r
- { "msg.arg.isnt.array", "second argument to Function.prototype.apply must be an array" },\r
- { "msg.bad.esc.mask", "invalid string escape mask" },\r
- { "msg.cant.instantiate", "error instantiating ({0}): class {1} is interface or abstract" },\r
- { "msg.bad.ctor.sig", "Found constructor with wrong signature: {0} calling {1} with signature {2}" },\r
- { "msg.not.java.obj", "Expected argument to getClass() to be a Java object." },\r
- { "msg.no.java.ctor", "Java constructor for \"{0}\" with arguments \"{1}\" not found." },\r
- { "msg.method.ambiguous", "The choice of Java method {0}.{1} matching JavaScript argument types ({2}) is ambiguous; candidate methods are: {3}" },\r
- { "msg.constructor.ambiguous", "The choice of Java constructor {0} matching JavaScript argument types ({1}) is ambiguous; candidate constructors are: {2}" },\r
- { "msg.conversion.not.allowed", "Cannot convert {0} to {1}" },\r
- { "msg.bad.quant", "Invalid quantifier {0}" },\r
- { "msg.overlarge.max", "Overly large maximum {0}" },\r
- { "msg.zero.quant", "Zero quantifier {0}" },\r
- { "msg.max.lt.min", "Maximum {0} less than minimum" },\r
- { "msg.unterm.quant", "Unterminated quantifier {0}" },\r
- { "msg.unterm.paren", "Unterminated parenthetical {0}" },\r
- { "msg.unterm.class", "Unterminated character class {0}" },\r
- { "msg.bad.range", "Invalid range in character class." },\r
- { "msg.trail.backslash", "Trailing \\ in regular expression." },\r
- { "msg.no.regexp", "Regular expressions are not available." },\r
- { "msg.bad.backref", "back-reference exceeds number of capturing parentheses." },\r
- { "msg.dup.label", "Duplicate label {0}." },\r
- { "msg.undef.label", "Undefined label {0}." },\r
- { "msg.bad.break", "Unlabelled break must be inside loop or switch." },\r
- { "msg.continue.outside", "continue must be inside loop." },\r
- { "msg.continue.nonloop", "Can only continue to labeled iteration statement." },\r
- { "msg.fn.redecl", "Function \"{0}\" redeclared; prior definition will be ignored." },\r
- { "msg.no.paren.parms", "missing ( before function parameters" },\r
- { "msg.no.parm", "missing formal parameter" },\r
- { "msg.no.paren.after.parms", "missing ) after formal parameters" },\r
- { "msg.no.brace.body", "missing open brace before function body" },\r
- { "msg.no.brace.after.body", "missing close brace after function body" },\r
- { "msg.no.paren.cond", "missing ( before condition" },\r
- { "msg.no.paren.after.cond", "missing ) after condition" },\r
- { "msg.no.semi.stmt", "missing ; before statement" },\r
- { "msg.no.name.after.dot", "missing name after . operator" },\r
- { "msg.no.bracket.index", "missing ] in index expression" },\r
- { "msg.no.paren.switch", "missing ( before switch expression" },\r
- { "msg.no.paren.after.switch", "missing ) after switch expression" },\r
- { "msg.no.brace.switch", "missing open brace before switch body" },\r
- { "msg.bad.switch", "invalid switch statement" },\r
- { "msg.no.colon.case", "missing : after case expression" },\r
- { "msg.no.while.do", "missing while after do-loop body" },\r
- { "msg.no.paren.for", "missing ( after for" },\r
- { "msg.no.semi.for", "missing ; after for-loop initializer" },\r
- { "msg.no.semi.for.cond", "missing ; after for-loop condition" },\r
- { "msg.no.paren.for.ctrl", "missing ) after for-loop control" },\r
- { "msg.no.paren.with", "missing ( before with-statement object" },\r
- { "msg.no.paren.after.with", "missing ) after with-statement object" },\r
- { "msg.bad.return", "invalid return" },\r
- { "msg.no.brace.block", "missing close brace in compound statement" },\r
- { "msg.bad.label", "invalid label" },\r
- { "msg.bad.var", "missing variable name" },\r
- { "msg.bad.var.init", "invalid variable initialization" },\r
- { "msg.no.colon.cond", "missing : in conditional expression" },\r
- { "msg.no.paren.arg", "missing ) after argument list" },\r
- { "msg.no.bracket.arg", "missing ] after element list" },\r
- { "msg.bad.prop", "invalid property id" },\r
- { "msg.no.colon.prop", "missing : after property id" },\r
- { "msg.no.brace.prop", "missing close brace after property list" },\r
- { "msg.no.paren", "missing ) in parenthetical" },\r
- { "msg.reserved.id", "identifier is a reserved word" },\r
- { "msg.no.paren.catch", "missing ( before catch-block condition" },\r
- { "msg.bad.catchcond", "invalid catch block condition" },\r
- { "msg.catch.unreachable", "any catch clauses following an unqualified catch are unreachable" },\r
- { "msg.no.brace.catchblock", "missing open brace before catch-block body" },\r
- { "msg.try.no.catchfinally", "''try'' without ''catch'' or ''finally''" },\r
- { "msg.syntax", "syntax error" },\r
- { "msg.assn.create", "Assignment to undefined \"{0}\" will create a new variable. Add a variable statement at the top level scope to remove this warning." },\r
- { "msg.prop.not.found", "Property not found." },\r
- { "msg.invalid.type", "Invalid JavaScript value of type {0}" },\r
- { "msg.primitive.expected", "Primitive type expected (had {0} instead)" },\r
- { "msg.null.to.object", "Cannot convert null to an object." },\r
- { "msg.undef.to.object", "Cannot convert undefined to an object." },\r
- { "msg.cyclic.value", "Cyclic {0} value not allowed." },\r
- { "msg.is.not.defined", "\"{0}\" is not defined." },\r
- { "msg.isnt.function", "{0} is not a function." },\r
- { "msg.bad.default.value", "Object''s getDefaultValue() method returned an object." },\r
- { "msg.instanceof.not.object", " Can''t use instanceof on a non-object." },\r
- { "msg.instanceof.bad.prototype", " ''prototype'' property of {0} is not an object." },\r
- { "msg.bad.radix", " illegal radix {0}." },\r
- { "msg.default.value", "Cannot find default value for object." },\r
- { "msg.zero.arg.ctor", "Cannot load class \"{0}\" which has no zero-parameter constructor." },\r
- { "msg.multiple.ctors", "Cannot have more than one constructor method, but found both {0} and {1}." },\r
- { "msg.ctor.multiple.parms", "Can''t define constructor or class {0} since more than one constructor has multiple parameters." },\r
- { "msg.extend.scriptable", "{0} must extend ScriptableObject in order to define property {1}." },\r
- { "msg.bad.getter.parms", "In order to define a property, getter {0} must have zero parameters or a single ScriptableObject parameter." },\r
- { "msg.obj.getter.parms", "Expected static or delegated getter {0} to take a ScriptableObject parameter." },\r
- { "msg.getter.static", "Getter and setter must both be static or neither be static." },\r
- { "msg.setter2.parms", "Two-parameter setter must take a ScriptableObject as its first parameter." },\r
- { "msg.setter1.parms", "Expected single parameter setter for {0}" },\r
- { "msg.setter2.expected", "Expected static or delegated setter {0} to take two parameters." },\r
- { "msg.setter.parms", "Expected either one or two parameters for setter." },\r
- { "msg.add.sealed", "Cannot add a property to a sealed object." },\r
- { "msg.remove.sealed", "Cannot remove a property from a sealed object." },\r
- { "msg.token.replaces.pushback", "ungot token {0} replaces pushback token {1}" },\r
- { "msg.missing.exponent", "missing exponent" },\r
- { "msg.caught.nfe", "number format error: {0}" },\r
- { "msg.unterminated.string.lit", "unterminated string literal" },\r
- { "msg.oct.esc.too.large", "octal escape too large" },\r
- { "msg.nested.comment", "nested comment" },\r
- { "msg.unterminated.comment", "unterminated comment" },\r
- { "msg.unterminated.re.lit", "unterminated regular expression literal" },\r
- { "msg.invalid.re.flag", "invalid flag after regular expression" },\r
- { "msg.no.re.input.for", "no input for {0}" },\r
- { "msg.illegal.character", "illegal character" },\r
- { "msg.invalid.escape", "invalid Unicode escape sequence" },\r
- { "msg.bad.octal.literal", "illegal octal literal digit {0}; interpreting it as a decimal digit" },\r
- { "msg.undefined", "The undefined value has no properties." },\r
- { "msg.java.internal.field.type", "Internal error: type conversion of {0} to assign to {1} on {2} failed." },\r
- { "msg.java.conversion.implicit_method", "Can''t find converter method \"{0}\" on class {1}." },\r
- { "msg.java.method.assign", "Java method \"{0}\" cannot be assigned to." },\r
- { "msg.java.internal.private", "Internal error: attempt to access private/protected field \"{0}\"." },\r
- { "msg.java.no_such_method", "Can''t find method {0}." },\r
- { "msg.script.is.not.constructor", "Script objects are not constructors." },\r
- { "msg.nonjava.method", "Java method \"{0}\" was invoked with a ''this'' value that was not a Java object." },\r
- { "msg.java.member.not.found", "Java class \"{0}\" has no public instance field or method named \"{1}\"." },\r
- { "msg.pkg.int", "Java package names may not be numbers." },\r
- { "msg.ambig.import", "Ambiguous import: \"{0}\" and and \"{1}\"." },\r
- { "msg.not.pkg", "Function importPackage must be called with a package; had \"{0}\" instead." },\r
- { "msg.not.class", "Function importClass must be called with a class; had \"{0}\" instead." },\r
- { "msg.prop.defined", "Cannot import \"{0}\" since a property by that name is already defined." },\r
- { "msg.arraylength.bad", "Inappropriate array length." },\r
- { "msg.bad.uri", "Malformed URI sequence." },\r
- { "msg.bad.precision", "Precision {0} out of range." }\r
- };\r
- }\r
-\r
- static final ResourceBundle myresources = new HardCodedResourceBundle();\r
-\r
- /* OPT there's a noticable delay for the first error! Maybe it'd\r
- * make sense to use a ListResourceBundle instead of a properties\r
- * file to avoid (synchronized) text parsing.\r
- */\r
- static String getMessage(String messageId, Object[] arguments) {\r
- Context cx = getCurrentContext();\r
- Locale locale = cx != null ? cx.getLocale() : Locale.getDefault();\r
-\r
- // ResourceBundle does cacheing.\r
- ResourceBundle rb = myresources;\r
-\r
- String formatString;\r
- try {\r
- formatString = rb.getString(messageId);\r
- } catch (java.util.MissingResourceException mre) {\r
- throw new RuntimeException\r
- ("no message resource found for message property "+ messageId);\r
- }\r
-\r
- /*\r
- * It's OK to format the string, even if 'arguments' is null;\r
- * we need to format it anyway, to make double ''s collapse to\r
- * single 's.\r
- */\r
- // TODO: MessageFormat is not available on pJava\r
- MessageFormat formatter = new MessageFormat(formatString);\r
- return formatter.format(arguments);\r
- }\r
-\r
- // debug flags\r
- static final boolean printTrees = false;\r
- \r
- /**\r
- * Compile a script.\r
- *\r
- * Reads script source from the reader and compiles it, returning\r
- * a class for either the script or the function depending on the\r
- * value of <code>returnFunction</code>.\r
- *\r
- * @param scope the scope to compile relative to\r
- * @param in the Reader to read source from\r
- * @param sourceName the name of the origin of the source (usually\r
- * a file or URL)\r
- * @param lineno the line number of the start of the source\r
- * @param securityDomain an arbitrary object that specifies security \r
- * information about the origin or owner of the script. For \r
- * implementations that don't care about security, this value \r
- * may be null.\r
- * @param returnFunction if true, will expect the source to contain\r
- * a function; return value is assumed to\r
- * then be a org.mozilla.javascript.Function\r
- * @return a class for the script or function\r
- * @see org.mozilla.javascript.Context#compileReader\r
- */\r
- private Object compile(Scriptable scope, Reader in, String sourceName, \r
- int lineno, Object securityDomain, \r
- boolean returnFunction)\r
- throws IOException\r
- {\r
- if (debugger != null && in != null) {\r
- in = new DebugReader(in);\r
- }\r
- TokenStream ts = new TokenStream(in, scope, sourceName, lineno);\r
- return compile(scope, ts, securityDomain, in, returnFunction);\r
- }\r
-\r
- private static Class codegenClass = null;\r
- private static ClassNameHelper nameHelper = null;\r
- static {\r
- /*\r
- try {\r
- codegenClass = Class.forName(\r
- "org.mozilla.javascript.optimizer.Codegen");\r
- Class nameHelperClass = Class.forName(\r
- "org.mozilla.javascript.optimizer.OptClassNameHelper");\r
- nameHelper = (ClassNameHelper)nameHelperClass.newInstance();\r
- } catch (ClassNotFoundException x) {\r
- // ...must be running lite, that's ok\r
- codegenClass = null;\r
- } catch (IllegalAccessException x) {\r
- codegenClass = null;\r
- } catch (InstantiationException x) {\r
- codegenClass = null;\r
- }\r
- */\r
- }\r
- \r
- private Interpreter getCompiler() {\r
- if (codegenClass != null) {\r
- try {\r
- return (Interpreter) codegenClass.newInstance();\r
- }\r
- catch (SecurityException x) { \r
- }\r
- catch (IllegalArgumentException x) {\r
- }\r
- catch (InstantiationException x) {\r
- }\r
- catch (IllegalAccessException x) {\r
- }\r
- // fall through\r
- }\r
- return new Interpreter();\r
- }\r
- \r
- private Object compile(Scriptable scope, TokenStream ts, \r
- Object securityDomain, Reader in,\r
- boolean returnFunction)\r
- throws IOException\r
- {\r
- Interpreter compiler = optimizationLevel == -1 \r
- ? new Interpreter()\r
- : getCompiler();\r
- \r
- errorCount = 0;\r
- IRFactory irf = compiler.createIRFactory(ts, nameHelper, scope);\r
- Parser p = new Parser(irf);\r
- Node tree = (Node) p.parse(ts);\r
- if (tree == null) \r
- return null;\r
-\r
- tree = compiler.transform(tree, ts, scope);\r
-\r
- if (printTrees)\r
- System.out.println(tree.toStringTree());\r
- \r
- if (returnFunction) {\r
- Node first = tree.getFirstChild();\r
- if (first == null)\r
- return null;\r
- tree = (Node) first.getProp(Node.FUNCTION_PROP);\r
- if (tree == null)\r
- return null;\r
- }\r
- \r
- if (in instanceof DebugReader) {\r
- DebugReader dr = (DebugReader) in;\r
- tree.putProp(Node.DEBUGSOURCE_PROP, dr.getSaved());\r
- }\r
-\r
- Object result = compiler.compile(this, scope, tree, securityDomain,\r
- securitySupport, nameHelper);\r
-\r
- return errorCount == 0 ? result : null;\r
- }\r
-\r
- static String getSourcePositionFromStack(int[] linep) {\r
- Context cx = getCurrentContext();\r
- if (cx == null)\r
- return null;\r
- if (cx.interpreterLine > 0 && cx.interpreterSourceFile != null) {\r
- linep[0] = cx.interpreterLine;\r
- return cx.interpreterSourceFile;\r
- }\r
- /**\r
- * A bit of a hack, but the only way to get filename and line\r
- * number from an enclosing frame.\r
- */\r
- CharArrayWriter writer = new CharArrayWriter();\r
- RuntimeException re = new RuntimeException();\r
- re.printStackTrace(new PrintWriter(writer));\r
- String s = writer.toString();\r
- int open = -1;\r
- int close = -1;\r
- int colon = -1;\r
- for (int i=0; i < s.length(); i++) {\r
- char c = s.charAt(i);\r
- if (c == ':')\r
- colon = i;\r
- else if (c == '(')\r
- open = i;\r
- else if (c == ')')\r
- close = i;\r
- else if (c == '\n' && open != -1 && close != -1 && colon != -1 && \r
- open < colon && colon < close) \r
- {\r
- String fileStr = s.substring(open + 1, colon);\r
- if (fileStr.endsWith(".js")) {\r
- String lineStr = s.substring(colon + 1, close);\r
- try {\r
- linep[0] = Integer.parseInt(lineStr);\r
- return fileStr;\r
- }\r
- catch (NumberFormatException e) {\r
- // fall through\r
- }\r
- }\r
- open = close = colon = -1;\r
- }\r
- }\r
-\r
- return null;\r
- }\r
-\r
- RegExpProxy getRegExpProxy() {\r
- if (regExpProxy == null) {\r
- try {\r
- Class c = Class.forName(\r
- "org.mozilla.javascript.regexp.RegExpImpl");\r
- regExpProxy = (RegExpProxy) c.newInstance();\r
- return regExpProxy;\r
- } catch (ClassNotFoundException e) {\r
- } catch (InstantiationException e) {\r
- } catch (IllegalAccessException e) {\r
- }\r
- }\r
- return regExpProxy;\r
- }\r
-\r
- private void newArrayHelper(Scriptable scope, Scriptable array) {\r
- array.setParentScope(scope);\r
- Object ctor = ScriptRuntime.getTopLevelProp(scope, "Array");\r
- if (ctor != null && ctor instanceof Scriptable) {\r
- Scriptable s = (Scriptable) ctor;\r
- array.setPrototype((Scriptable) s.get("prototype", s));\r
- }\r
- }\r
- \r
- final boolean isVersionECMA1() {\r
- return version == VERSION_DEFAULT || version >= VERSION_1_3;\r
- }\r
-\r
- /**\r
- * Get the security context from the given class.\r
- * <p>\r
- * When some form of security check needs to be done, the class context\r
- * must retrieved from the security manager to determine what class is\r
- * requesting some form of privileged access. \r
- * @since 1.4 release 2\r
- */\r
- Object getSecurityDomainFromClass(Class cl) {\r
- if (cl == Interpreter.class)\r
- return interpreterSecurityDomain;\r
- return securitySupport.getSecurityDomain(cl);\r
- }\r
- \r
- SecuritySupport getSecuritySupport() {\r
- return securitySupport;\r
- }\r
- \r
- Object getSecurityDomainForStackDepth(int depth) {\r
- Object result = null;\r
- if (securitySupport != null) {\r
- Class[] classes = securitySupport.getClassContext();\r
- if (classes != null) {\r
- if (depth != -1) {\r
- int depth1 = depth + 1;\r
- result = getSecurityDomainFromClass(classes[depth1]);\r
- } else {\r
- for (int i=1; i < classes.length; i++) {\r
- result = getSecurityDomainFromClass(classes[i]);\r
- if (result != null)\r
- break;\r
- }\r
- }\r
- }\r
- }\r
- if (result != null)\r
- return result;\r
- if (requireSecurityDomain) \r
- checkSecurityDomainRequired();\r
- return null;\r
- }\r
-\r
- private static boolean requireSecurityDomain = false;\r
- private static boolean resourceMissing = false;\r
-\r
- final static String securityResourceName = "org.mozilla.javascript.resources.Security";\r
- \r
- final public static void checkSecurityDomainRequired() { }\r
-\r
- public boolean isGeneratingDebugChanged() {\r
- return generatingDebugChanged;\r
- }\r
- \r
-\r
- /**\r
- * Add a name to the list of names forcing the creation of real\r
- * activation objects for functions.\r
- *\r
- * @param name the name of the object to add to the list\r
- */\r
- public void addActivationName(String name) {\r
- if (activationNames == null) \r
- activationNames = new Hashtable(5);\r
- activationNames.put(name, name);\r
- }\r
-\r
- /**\r
- * Check whether the name is in the list of names of objects\r
- * forcing the creation of activation objects.\r
- *\r
- * @param name the name of the object to test\r
- *\r
- * @return true if an function activation object is needed.\r
- */\r
- public boolean isActivationNeeded(String name) {\r
- if ("arguments".equals(name))\r
- return true;\r
- return activationNames != null && activationNames.containsKey(name);\r
- }\r
-\r
- /**\r
- * Remove a name from the list of names forcing the creation of real\r
- * activation objects for functions.\r
- *\r
- * @param name the name of the object to remove from the list\r
- */\r
- public void removeActivationName(String name) {\r
- if (activationNames != null)\r
- activationNames.remove(name);\r
- }\r
-\r
-\r
- static final boolean useJSObject = false;\r
-\r
- /** \r
- * The activation of the currently executing function or script. \r
- */\r
- NativeCall currentActivation;\r
-\r
- // for Objects, Arrays to tag themselves as being printed out,\r
- // so they don't print themselves out recursively.\r
- Hashtable iterating;\r
- \r
- Object interpreterSecurityDomain;\r
-\r
- int version;\r
- int errorCount;\r
- static boolean isCachingEnabled = true;\r
- \r
- private SecuritySupport securitySupport;\r
- private ErrorReporter errorReporter;\r
- private Thread currentThread;\r
- private static Hashtable threadContexts = new Hashtable(11);\r
- private RegExpProxy regExpProxy;\r
- private Locale locale;\r
- private boolean generatingDebug;\r
- private boolean generatingDebugChanged;\r
- private boolean generatingSource=true;\r
- private boolean compileFunctionsWithDynamicScopeFlag;\r
- private int optimizationLevel;\r
- WrapHandler wrapHandler;\r
- Debugger debugger;\r
- DebuggableEngine debuggableEngine;\r
- boolean inLineStepMode;\r
- java.util.Stack frameStack; \r
- private int enterCount;\r
- private Object[] listeners;\r
- private Hashtable hashtable;\r
-\r
- /**\r
- * This is the list of names of objects forcing the creation of\r
- * function activation records.\r
- */\r
- private Hashtable activationNames;\r
-\r
- // Private lock for static fields to avoid a possibility of denial\r
- // of service via synchronized (Context.class) { while (true) {} }\r
- private static final Object staticDataLock = new Object();\r
- private static Object[] contextListeners;\r
- public Function currentFunction;\r
- Vector arrayCache = new Vector(10);\r
-\r
- // For the interpreter to indicate line/source for error reports.\r
- public int interpreterLine;\r
- public String interpreterSourceFile;\r
-\r
- public int stackDepth = 0;\r
-\r
- // For instruction counting (interpreter only)\r
- int instructionCount;\r
- int instructionThreshold;\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-2000 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-// API class\r
-\r
-package org.mozilla.javascript;\r
-\r
-/**\r
- * Embeddings that wish to \r
- * @see org.mozilla.javascript.Context#addContextListener\r
- */\r
-public interface ContextListener {\r
-\r
- public void contextCreated(Context cx);\r
- \r
- public void contextEntered(Context cx);\r
- \r
- public void contextExited(Context cx);\r
- \r
- public void contextReleased(Context cx);\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s):\r
- * Waldemar Horwat\r
- * Roger Lawrence\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-import java.math.BigInteger;\r
-\r
-class DToA {\r
-\r
-\r
-/* "-0.0000...(1073 zeros after decimal point)...0001\0" is the longest string that we could produce,\r
- * which occurs when printing -5e-324 in binary. We could compute a better estimate of the size of\r
- * the output string and malloc fewer bytes depending on d and base, but why bother? */\r
-\r
- static final int DTOBASESTR_BUFFER_SIZE = 1078;\r
-\r
- static char BASEDIGIT(int digit) {\r
- return (char)((digit >= 10) ? 'a' - 10 + digit : '0' + digit);\r
- }\r
- \r
- static final int\r
- DTOSTR_STANDARD = 0, /* Either fixed or exponential format; round-trip */\r
- DTOSTR_STANDARD_EXPONENTIAL = 1, /* Always exponential format; round-trip */\r
- DTOSTR_FIXED = 2, /* Round to <precision> digits after the decimal point; exponential if number is large */\r
- DTOSTR_EXPONENTIAL = 3, /* Always exponential format; <precision> significant digits */\r
- DTOSTR_PRECISION = 4; /* Either fixed or exponential format; <precision> significant digits */\r
- \r
-\r
- static final int Frac_mask = 0xfffff;\r
- static final int Exp_shift = 20;\r
- static final int Exp_msk1 = 0x100000;\r
- static final int Bias = 1023;\r
- static final int P = 53;\r
-\r
- static final int Exp_shift1 = 20;\r
- static final int Exp_mask = 0x7ff00000;\r
- static final int Bndry_mask = 0xfffff;\r
- static final int Log2P = 1;\r
-\r
- static final int Sign_bit = 0x80000000;\r
- static final int Exp_11 = 0x3ff00000;\r
- static final int Ten_pmax = 22;\r
- static final int Quick_max = 14;\r
- static final int Bletch = 0x10;\r
- static final int Frac_mask1 = 0xfffff;\r
- static final int Int_max = 14;\r
- static final int n_bigtens = 5;\r
-\r
- \r
- static final double tens[] = {\r
- 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,\r
- 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,\r
- 1e20, 1e21, 1e22\r
- };\r
- \r
- static final double bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };\r
-\r
- static int lo0bits(int y)\r
- {\r
- int k;\r
- int x = y;\r
-\r
- if ((x & 7) != 0) {\r
- if ((x & 1) != 0)\r
- return 0;\r
- if ((x & 2) != 0) {\r
- return 1;\r
- }\r
- return 2;\r
- }\r
- k = 0;\r
- if ((x & 0xffff) == 0) {\r
- k = 16;\r
- x >>>= 16;\r
- }\r
- if ((x & 0xff) == 0) {\r
- k += 8;\r
- x >>>= 8;\r
- }\r
- if ((x & 0xf) == 0) {\r
- k += 4;\r
- x >>>= 4;\r
- }\r
- if ((x & 0x3) == 0) {\r
- k += 2;\r
- x >>>= 2;\r
- }\r
- if ((x & 1) == 0) {\r
- k++;\r
- x >>>= 1;\r
- if ((x & 1) == 0)\r
- return 32;\r
- }\r
- return k;\r
- }\r
-\r
- /* Return the number (0 through 32) of most significant zero bits in x. */\r
- static int hi0bits(int x)\r
- {\r
- int k = 0;\r
-\r
- if ((x & 0xffff0000) == 0) {\r
- k = 16;\r
- x <<= 16;\r
- }\r
- if ((x & 0xff000000) == 0) {\r
- k += 8;\r
- x <<= 8;\r
- }\r
- if ((x & 0xf0000000) == 0) {\r
- k += 4;\r
- x <<= 4;\r
- }\r
- if ((x & 0xc0000000) == 0) {\r
- k += 2;\r
- x <<= 2;\r
- }\r
- if ((x & 0x80000000) == 0) {\r
- k++;\r
- if ((x & 0x40000000) == 0)\r
- return 32;\r
- }\r
- return k;\r
- }\r
-\r
- static void stuffBits(byte bits[], int offset, int val)\r
- {\r
- bits[offset] = (byte)(val >> 24);\r
- bits[offset + 1] = (byte)(val >> 16);\r
- bits[offset + 2] = (byte)(val >> 8);\r
- bits[offset + 3] = (byte)(val);\r
- }\r
-\r
- /* Convert d into the form b*2^e, where b is an odd integer. b is the returned\r
- * Bigint and e is the returned binary exponent. Return the number of significant\r
- * bits in b in bits. d must be finite and nonzero. */\r
- static BigInteger d2b(double d, int[] e, int[] bits)\r
- {\r
- byte dbl_bits[];\r
- int i, k, y, z, de;\r
- long dBits = Double.doubleToLongBits(d);\r
- int d0 = (int)(dBits >>> 32);\r
- int d1 = (int)(dBits);\r
-\r
- z = d0 & Frac_mask;\r
- d0 &= 0x7fffffff; /* clear sign bit, which we ignore */\r
-\r
- if ((de = (int)(d0 >>> Exp_shift)) != 0)\r
- z |= Exp_msk1;\r
-\r
- if ((y = d1) != 0) {\r
- dbl_bits = new byte[8];\r
- k = lo0bits(y);\r
- y >>>= k;\r
- if (k != 0) {\r
- stuffBits(dbl_bits, 4, y | z << (32 - k));\r
- z >>= k;\r
- }\r
- else\r
- stuffBits(dbl_bits, 4, y);\r
- stuffBits(dbl_bits, 0, z);\r
- i = (z != 0) ? 2 : 1;\r
- }\r
- else {\r
- // JS_ASSERT(z);\r
- dbl_bits = new byte[4];\r
- k = lo0bits(z);\r
- z >>>= k;\r
- stuffBits(dbl_bits, 0, z);\r
- k += 32;\r
- i = 1;\r
- }\r
- if (de != 0) {\r
- e[0] = de - Bias - (P-1) + k;\r
- bits[0] = P - k;\r
- }\r
- else {\r
- e[0] = de - Bias - (P-1) + 1 + k;\r
- bits[0] = 32*i - hi0bits(z);\r
- }\r
- return new BigInteger(dbl_bits);\r
- }\r
-\r
- public static String JS_dtobasestr(int base, double d)\r
- {\r
- char[] buffer; /* The output string */\r
- int p; /* index to current position in the buffer */\r
- int pInt; /* index to the beginning of the integer part of the string */\r
-\r
- int q;\r
- int digit;\r
- double di; /* d truncated to an integer */\r
- double df; /* The fractional part of d */\r
-\r
-// JS_ASSERT(base >= 2 && base <= 36);\r
-\r
- buffer = new char[DTOBASESTR_BUFFER_SIZE];\r
-\r
- p = 0;\r
- if (d < 0.0) {\r
- buffer[p++] = '-';\r
- d = -d;\r
- }\r
-\r
- /* Check for Infinity and NaN */\r
- if (Double.isNaN(d))\r
- return "NaN";\r
- else\r
- if (Double.isInfinite(d))\r
- return "Infinity";\r
-\r
- /* Output the integer part of d with the digits in reverse order. */\r
- pInt = p;\r
- di = (int)d;\r
- BigInteger b = BigInteger.valueOf((int)di);\r
- String intDigits = b.toString(base);\r
- intDigits.getChars(0, intDigits.length(), buffer, p);\r
- p += intDigits.length();\r
-\r
- df = d - di;\r
- if (df != 0.0) {\r
- /* We have a fraction. */\r
- buffer[p++] = '.';\r
-\r
- long dBits = Double.doubleToLongBits(d);\r
- int word0 = (int)(dBits >> 32);\r
- int word1 = (int)(dBits);\r
-\r
- int[] e = new int[1];\r
- int[] bbits = new int[1];\r
- \r
- b = d2b(df, e, bbits);\r
-// JS_ASSERT(e < 0);\r
- /* At this point df = b * 2^e. e must be less than zero because 0 < df < 1. */\r
-\r
- int s2 = -(word0 >>> Exp_shift1 & Exp_mask >> Exp_shift1);\r
- if (s2 == 0)\r
- s2 = -1;\r
- s2 += Bias + P;\r
- /* 1/2^s2 = (nextDouble(d) - d)/2 */\r
-// JS_ASSERT(-s2 < e);\r
- BigInteger mlo = BigInteger.valueOf(1);\r
- BigInteger mhi = mlo;\r
- if ((word1 == 0) && ((word0 & Bndry_mask) == 0)\r
- && ((word0 & (Exp_mask & Exp_mask << 1)) != 0)) {\r
- /* The special case. Here we want to be within a quarter of the last input\r
- significant digit instead of one half of it when the output string's value is less than d. */\r
- s2 += Log2P;\r
- mhi = BigInteger.valueOf(1<<Log2P);\r
- }\r
-\r
- b = b.shiftLeft(e[0] + s2);\r
- BigInteger s = BigInteger.valueOf(1);\r
- s = s.shiftLeft(s2);\r
- /* At this point we have the following:\r
- * s = 2^s2;\r
- * 1 > df = b/2^s2 > 0;\r
- * (d - prevDouble(d))/2 = mlo/2^s2;\r
- * (nextDouble(d) - d)/2 = mhi/2^s2. */\r
- BigInteger bigBase = BigInteger.valueOf(base);\r
-\r
- boolean done = false;\r
- do {\r
- b = b.multiply(bigBase);\r
- BigInteger[] divResult = b.divideAndRemainder(s);\r
- b = divResult[1];\r
- digit = (char)(divResult[0].intValue());\r
- if (mlo == mhi)\r
- mlo = mhi = mlo.multiply(bigBase);\r
- else {\r
- mlo = mlo.multiply(bigBase);\r
- mhi = mhi.multiply(bigBase);\r
- }\r
-\r
- /* Do we yet have the shortest string that will round to d? */\r
- int j = b.compareTo(mlo);\r
- /* j is b/2^s2 compared with mlo/2^s2. */\r
- BigInteger delta = s.subtract(mhi);\r
- int j1 = (delta.signum() <= 0) ? 1 : b.compareTo(delta);\r
- /* j1 is b/2^s2 compared with 1 - mhi/2^s2. */\r
- if (j1 == 0 && ((word1 & 1) == 0)) {\r
- if (j > 0)\r
- digit++;\r
- done = true;\r
- } else\r
- if (j < 0 || (j == 0 && ((word1 & 1) == 0))) {\r
- if (j1 > 0) {\r
- /* Either dig or dig+1 would work here as the least significant digit.\r
- Use whichever would produce an output value closer to d. */\r
- b = b.shiftLeft(1);\r
- j1 = b.compareTo(s);\r
- if (j1 > 0) /* The even test (|| (j1 == 0 && (digit & 1))) is not here because it messes up odd base output\r
- * such as 3.5 in base 3. */\r
- digit++;\r
- }\r
- done = true;\r
- } else if (j1 > 0) {\r
- digit++;\r
- done = true;\r
- }\r
-// JS_ASSERT(digit < (uint32)base);\r
- buffer[p++] = BASEDIGIT(digit);\r
- } while (!done);\r
- }\r
-\r
- return new String(buffer, 0, p);\r
- }\r
-\r
- /* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.\r
- *\r
- * Inspired by "How to Print Floating-Point Numbers Accurately" by\r
- * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 92-101].\r
- *\r
- * Modifications:\r
- * 1. Rather than iterating, we use a simple numeric overestimate\r
- * to determine k = floor(log10(d)). We scale relevant\r
- * quantities using O(log2(k)) rather than O(k) multiplications.\r
- * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't\r
- * try to generate digits strictly left to right. Instead, we\r
- * compute with fewer bits and propagate the carry if necessary\r
- * when rounding the final digit up. This is often faster.\r
- * 3. Under the assumption that input will be rounded nearest,\r
- * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22.\r
- * That is, we allow equality in stopping tests when the\r
- * round-nearest rule will give the same floating-point value\r
- * as would satisfaction of the stopping test with strict\r
- * inequality.\r
- * 4. We remove common factors of powers of 2 from relevant\r
- * quantities.\r
- * 5. When converting floating-point integers less than 1e16,\r
- * we use floating-point arithmetic rather than resorting\r
- * to multiple-precision integers.\r
- * 6. When asked to produce fewer than 15 digits, we first try\r
- * to get by with floating-point arithmetic; we resort to\r
- * multiple-precision integer arithmetic only if we cannot\r
- * guarantee that the floating-point calculation has given\r
- * the correctly rounded result. For k requested digits and\r
- * "uniformly" distributed input, the probability is\r
- * something like 10^(k-15) that we must resort to the Long\r
- * calculation.\r
- */\r
-\r
- static int word0(double d)\r
- {\r
- long dBits = Double.doubleToLongBits(d);\r
- return (int)(dBits >> 32);\r
- }\r
- \r
- static double setWord0(double d, int i)\r
- {\r
- long dBits = Double.doubleToLongBits(d);\r
- dBits = ((long)i << 32) | (dBits & 0x0FFFFFFFFL);\r
- return Double.longBitsToDouble(dBits);\r
- }\r
- \r
- static int word1(double d)\r
- {\r
- long dBits = Double.doubleToLongBits(d);\r
- return (int)(dBits);\r
- }\r
- \r
- /* Return b * 5^k. k must be nonnegative. */\r
- // XXXX the C version built a cache of these\r
- static BigInteger pow5mult(BigInteger b, int k)\r
- {\r
- return b.multiply(BigInteger.valueOf(5).pow(k));\r
- }\r
- \r
- static boolean roundOff(StringBuffer buf)\r
- {\r
- char lastCh;\r
- while ((lastCh = buf.charAt(buf.length() - 1)) == '9') {\r
- buf.setLength(buf.length() - 1);\r
- if (buf.length() == 0) {\r
- return true;\r
- }\r
- }\r
- buf.append((char)(lastCh + 1));\r
- return false;\r
- }\r
- \r
- /* Always emits at least one digit. */\r
- /* If biasUp is set, then rounding in modes 2 and 3 will round away from zero\r
- * when the number is exactly halfway between two representable values. For example, \r
- * rounding 2.5 to zero digits after the decimal point will return 3 and not 2.\r
- * 2.49 will still round to 2, and 2.51 will still round to 3. */\r
- /* bufsize should be at least 20 for modes 0 and 1. For the other modes,\r
- * bufsize should be two greater than the maximum number of output characters expected. */\r
- static int\r
- JS_dtoa(double d, int mode, boolean biasUp, int ndigits,\r
- boolean[] sign, StringBuffer buf)\r
- {\r
- /* Arguments ndigits, decpt, sign are similar to those\r
- of ecvt and fcvt; trailing zeros are suppressed from\r
- the returned string. If not null, *rve is set to point\r
- to the end of the return value. If d is +-Infinity or NaN,\r
- then *decpt is set to 9999.\r
-\r
- mode:\r
- 0 ==> shortest string that yields d when read in\r
- and rounded to nearest.\r
- 1 ==> like 0, but with Steele & White stopping rule;\r
- e.g. with IEEE P754 arithmetic , mode 0 gives\r
- 1e23 whereas mode 1 gives 9.999999999999999e22.\r
- 2 ==> max(1,ndigits) significant digits. This gives a\r
- return value similar to that of ecvt, except\r
- that trailing zeros are suppressed.\r
- 3 ==> through ndigits past the decimal point. This\r
- gives a return value similar to that from fcvt,\r
- except that trailing zeros are suppressed, and\r
- ndigits can be negative.\r
- 4-9 should give the same return values as 2-3, i.e.,\r
- 4 <= mode <= 9 ==> same return as mode\r
- 2 + (mode & 1). These modes are mainly for\r
- debugging; often they run slower but sometimes\r
- faster than modes 2-3.\r
- 4,5,8,9 ==> left-to-right digit generation.\r
- 6-9 ==> don't try fast floating-point estimate\r
- (if applicable).\r
-\r
- Values of mode other than 0-9 are treated as mode 0.\r
-\r
- Sufficient space is allocated to the return value\r
- to hold the suppressed trailing zeros.\r
- */\r
-\r
- int b2, b5, i, ieps, ilim, ilim0, ilim1,\r
- j, j1, k, k0, m2, m5, s2, s5;\r
- char dig;\r
- long L;\r
- long x;\r
- BigInteger b, b1, delta, mlo, mhi, S;\r
- int[] be = new int[1];\r
- int[] bbits = new int[1];\r
- double d2, ds, eps;\r
- boolean spec_case, denorm, k_check, try_quick, leftright;\r
-\r
- if ((word0(d) & Sign_bit) != 0) {\r
- /* set sign for everything, including 0's and NaNs */\r
- sign[0] = true;\r
- // word0(d) &= ~Sign_bit; /* clear sign bit */\r
- d = setWord0(d, word0(d) & ~Sign_bit);\r
- }\r
- else\r
- sign[0] = false;\r
-\r
- if ((word0(d) & Exp_mask) == Exp_mask) {\r
- /* Infinity or NaN */\r
- buf.append(((word1(d) == 0) && ((word0(d) & Frac_mask) == 0)) ? "Infinity" : "NaN");\r
- return 9999;\r
- }\r
- if (d == 0) {\r
-// no_digits:\r
- buf.setLength(0);\r
- buf.append('0'); /* copy "0" to buffer */\r
- return 1;\r
- }\r
- \r
- b = d2b(d, be, bbits);\r
- if ((i = (int)(word0(d) >>> Exp_shift1 & (Exp_mask>>Exp_shift1))) != 0) {\r
- d2 = setWord0(d, (word0(d) & Frac_mask1) | Exp_11);\r
- /* log(x) ~=~ log(1.5) + (x-1.5)/1.5\r
- * log10(x) = log(x) / log(10)\r
- * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))\r
- * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2)\r
- *\r
- * This suggests computing an approximation k to log10(d) by\r
- *\r
- * k = (i - Bias)*0.301029995663981\r
- * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );\r
- *\r
- * We want k to be too large rather than too small.\r
- * The error in the first-order Taylor series approximation\r
- * is in our favor, so we just round up the constant enough\r
- * to compensate for any error in the multiplication of\r
- * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,\r
- * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,\r
- * adding 1e-13 to the constant term more than suffices.\r
- * Hence we adjust the constant term to 0.1760912590558.\r
- * (We could get a more accurate k by invoking log10,\r
- * but this is probably not worthwhile.)\r
- */\r
- i -= Bias;\r
- denorm = false;\r
- }\r
- else {\r
- /* d is denormalized */\r
- i = bbits[0] + be[0] + (Bias + (P-1) - 1);\r
- x = (i > 32) ? word0(d) << (64 - i) | word1(d) >>> (i - 32) : word1(d) << (32 - i);\r
-// d2 = x;\r
-// word0(d2) -= 31*Exp_msk1; /* adjust exponent */\r
- d2 = setWord0(x, word0(x) - 31*Exp_msk1);\r
- i -= (Bias + (P-1) - 1) + 1;\r
- denorm = true;\r
- }\r
- /* At this point d = f*2^i, where 1 <= f < 2. d2 is an approximation of f. */\r
- ds = (d2-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;\r
- k = (int)ds;\r
- if (ds < 0.0 && ds != k)\r
- k--; /* want k = floor(ds) */\r
- k_check = true;\r
- if (k >= 0 && k <= Ten_pmax) {\r
- if (d < tens[k])\r
- k--;\r
- k_check = false;\r
- }\r
- /* At this point floor(log10(d)) <= k <= floor(log10(d))+1.\r
- If k_check is zero, we're guaranteed that k = floor(log10(d)). */\r
- j = bbits[0] - i - 1;\r
- /* At this point d = b/2^j, where b is an odd integer. */\r
- if (j >= 0) {\r
- b2 = 0;\r
- s2 = j;\r
- }\r
- else {\r
- b2 = -j;\r
- s2 = 0;\r
- }\r
- if (k >= 0) {\r
- b5 = 0;\r
- s5 = k;\r
- s2 += k;\r
- }\r
- else {\r
- b2 -= k;\r
- b5 = -k;\r
- s5 = 0;\r
- }\r
- /* At this point d/10^k = (b * 2^b2 * 5^b5) / (2^s2 * 5^s5), where b is an odd integer,\r
- b2 >= 0, b5 >= 0, s2 >= 0, and s5 >= 0. */\r
- if (mode < 0 || mode > 9)\r
- mode = 0;\r
- try_quick = true;\r
- if (mode > 5) {\r
- mode -= 4;\r
- try_quick = false;\r
- }\r
- leftright = true;\r
- ilim = ilim1 = 0;\r
- switch(mode) {\r
- case 0:\r
- case 1:\r
- ilim = ilim1 = -1;\r
- i = 18;\r
- ndigits = 0;\r
- break;\r
- case 2:\r
- leftright = false;\r
- /* no break */\r
- case 4:\r
- if (ndigits <= 0)\r
- ndigits = 1;\r
- ilim = ilim1 = i = ndigits;\r
- break;\r
- case 3:\r
- leftright = false;\r
- /* no break */\r
- case 5:\r
- i = ndigits + k + 1;\r
- ilim = i;\r
- ilim1 = i - 1;\r
- if (i <= 0)\r
- i = 1;\r
- }\r
- /* ilim is the maximum number of significant digits we want, based on k and ndigits. */\r
- /* ilim1 is the maximum number of significant digits we want, based on k and ndigits,\r
- when it turns out that k was computed too high by one. */\r
-\r
- boolean fast_failed = false;\r
- if (ilim >= 0 && ilim <= Quick_max && try_quick) {\r
-\r
- /* Try to get by with floating-point arithmetic. */\r
-\r
- i = 0;\r
- d2 = d;\r
- k0 = k;\r
- ilim0 = ilim;\r
- ieps = 2; /* conservative */\r
- /* Divide d by 10^k, keeping track of the roundoff error and avoiding overflows. */\r
- if (k > 0) {\r
- ds = tens[k&0xf];\r
- j = k >> 4;\r
- if ((j & Bletch) != 0) {\r
- /* prevent overflows */\r
- j &= Bletch - 1;\r
- d /= bigtens[n_bigtens-1];\r
- ieps++;\r
- }\r
- for(; (j != 0); j >>= 1, i++)\r
- if ((j & 1) != 0) {\r
- ieps++;\r
- ds *= bigtens[i];\r
- }\r
- d /= ds;\r
- }\r
- else if ((j1 = -k) != 0) {\r
- d *= tens[j1 & 0xf];\r
- for(j = j1 >> 4; (j != 0); j >>= 1, i++)\r
- if ((j & 1) != 0) {\r
- ieps++;\r
- d *= bigtens[i];\r
- }\r
- }\r
- /* Check that k was computed correctly. */\r
- if (k_check && d < 1.0 && ilim > 0) {\r
- if (ilim1 <= 0)\r
- fast_failed = true;\r
- else {\r
- ilim = ilim1;\r
- k--;\r
- d *= 10.;\r
- ieps++;\r
- }\r
- }\r
- /* eps bounds the cumulative error. */\r
-// eps = ieps*d + 7.0;\r
-// word0(eps) -= (P-1)*Exp_msk1;\r
- eps = ieps*d + 7.0;\r
- eps = setWord0(eps, word0(eps) - (P-1)*Exp_msk1);\r
- if (ilim == 0) {\r
- S = mhi = null;\r
- d -= 5.0;\r
- if (d > eps) {\r
- buf.append('1');\r
- k++;\r
- return k + 1;\r
- }\r
- if (d < -eps) {\r
- buf.setLength(0);\r
- buf.append('0'); /* copy "0" to buffer */\r
- return 1;\r
- }\r
- fast_failed = true;\r
- }\r
- if (!fast_failed) {\r
- fast_failed = true;\r
- if (leftright) {\r
- /* Use Steele & White method of only\r
- * generating digits needed.\r
- */\r
- eps = 0.5/tens[ilim-1] - eps;\r
- for(i = 0;;) {\r
- L = (long)d;\r
- d -= L;\r
- buf.append((char)('0' + L));\r
- if (d < eps) {\r
- return k + 1;\r
- }\r
- if (1.0 - d < eps) {\r
-// goto bump_up;\r
- char lastCh;\r
- while (true) {\r
- lastCh = buf.charAt(buf.length() - 1);\r
- buf.setLength(buf.length() - 1);\r
- if (lastCh != '9') break;\r
- if (buf.length() == 0) {\r
- k++;\r
- lastCh = '0';\r
- break;\r
- }\r
- } \r
- buf.append((char)(lastCh + 1));\r
- return k + 1;\r
- }\r
- if (++i >= ilim)\r
- break;\r
- eps *= 10.0;\r
- d *= 10.0;\r
- }\r
- }\r
- else {\r
- /* Generate ilim digits, then fix them up. */\r
- eps *= tens[ilim-1];\r
- for(i = 1;; i++, d *= 10.0) {\r
- L = (long)d;\r
- d -= L;\r
- buf.append((char)('0' + L));\r
- if (i == ilim) {\r
- if (d > 0.5 + eps) {\r
-// goto bump_up;\r
- char lastCh;\r
- while (true) {\r
- lastCh = buf.charAt(buf.length() - 1);\r
- buf.setLength(buf.length() - 1);\r
- if (lastCh != '9') break;\r
- if (buf.length() == 0) {\r
- k++;\r
- lastCh = '0';\r
- break;\r
- }\r
- } \r
- buf.append((char)(lastCh + 1));\r
- return k + 1;\r
- }\r
- else\r
- if (d < 0.5 - eps) {\r
- while (buf.charAt(buf.length() - 1) == '0')\r
- buf.setLength(buf.length() - 1);\r
-// while(*--s == '0') ;\r
-// s++;\r
- return k + 1;\r
- }\r
- break;\r
- }\r
- }\r
- }\r
- }\r
- if (fast_failed) {\r
- buf.setLength(0);\r
- d = d2;\r
- k = k0;\r
- ilim = ilim0;\r
- }\r
- }\r
-\r
- /* Do we have a "small" integer? */\r
-\r
- if (be[0] >= 0 && k <= Int_max) {\r
- /* Yes. */\r
- ds = tens[k];\r
- if (ndigits < 0 && ilim <= 0) {\r
- S = mhi = null;\r
- if (ilim < 0 || d < 5*ds || (!biasUp && d == 5*ds)) {\r
- buf.setLength(0);\r
- buf.append('0'); /* copy "0" to buffer */\r
- return 1;\r
- }\r
- buf.append('1');\r
- k++;\r
- return k + 1;\r
- }\r
- for(i = 1;; i++) {\r
- L = (long) (d / ds);\r
- d -= L*ds;\r
- buf.append((char)('0' + L));\r
- if (i == ilim) {\r
- d += d;\r
- if ((d > ds) || (d == ds && (((L & 1) != 0) || biasUp))) {\r
-// bump_up:\r
-// while(*--s == '9')\r
-// if (s == buf) {\r
-// k++;\r
-// *s = '0';\r
-// break;\r
-// }\r
-// ++*s++;\r
- char lastCh;\r
- while (true) {\r
- lastCh = buf.charAt(buf.length() - 1);\r
- buf.setLength(buf.length() - 1);\r
- if (lastCh != '9') break;\r
- if (buf.length() == 0) {\r
- k++;\r
- lastCh = '0';\r
- break;\r
- }\r
- } \r
- buf.append((char)(lastCh + 1));\r
- }\r
- break;\r
- }\r
- d *= 10.0;\r
- if (d == 0)\r
- break;\r
- }\r
- return k + 1;\r
- }\r
-\r
- m2 = b2;\r
- m5 = b5;\r
- mhi = mlo = null;\r
- if (leftright) {\r
- if (mode < 2) {\r
- i = (denorm) ? be[0] + (Bias + (P-1) - 1 + 1) : 1 + P - bbits[0];\r
- /* i is 1 plus the number of trailing zero bits in d's significand. Thus,\r
- (2^m2 * 5^m5) / (2^(s2+i) * 5^s5) = (1/2 lsb of d)/10^k. */\r
- }\r
- else {\r
- j = ilim - 1;\r
- if (m5 >= j)\r
- m5 -= j;\r
- else {\r
- s5 += j -= m5;\r
- b5 += j;\r
- m5 = 0;\r
- }\r
- if ((i = ilim) < 0) {\r
- m2 -= i;\r
- i = 0;\r
- }\r
- /* (2^m2 * 5^m5) / (2^(s2+i) * 5^s5) = (1/2 * 10^(1-ilim))/10^k. */\r
- }\r
- b2 += i;\r
- s2 += i;\r
- mhi = BigInteger.valueOf(1);\r
- /* (mhi * 2^m2 * 5^m5) / (2^s2 * 5^s5) = one-half of last printed (when mode >= 2) or\r
- input (when mode < 2) significant digit, divided by 10^k. */\r
- }\r
- /* We still have d/10^k = (b * 2^b2 * 5^b5) / (2^s2 * 5^s5). Reduce common factors in\r
- b2, m2, and s2 without changing the equalities. */\r
- if (m2 > 0 && s2 > 0) {\r
- i = (m2 < s2) ? m2 : s2;\r
- b2 -= i;\r
- m2 -= i;\r
- s2 -= i;\r
- }\r
-\r
- /* Fold b5 into b and m5 into mhi. */\r
- if (b5 > 0) {\r
- if (leftright) {\r
- if (m5 > 0) {\r
- mhi = pow5mult(mhi, m5);\r
- b1 = mhi.multiply(b);\r
- b = b1;\r
- }\r
- if ((j = b5 - m5) != 0)\r
- b = pow5mult(b, j);\r
- }\r
- else\r
- b = pow5mult(b, b5);\r
- }\r
- /* Now we have d/10^k = (b * 2^b2) / (2^s2 * 5^s5) and\r
- (mhi * 2^m2) / (2^s2 * 5^s5) = one-half of last printed or input significant digit, divided by 10^k. */\r
-\r
- S = BigInteger.valueOf(1);\r
- if (s5 > 0)\r
- S = pow5mult(S, s5);\r
- /* Now we have d/10^k = (b * 2^b2) / (S * 2^s2) and\r
- (mhi * 2^m2) / (S * 2^s2) = one-half of last printed or input significant digit, divided by 10^k. */\r
-\r
- /* Check for special case that d is a normalized power of 2. */\r
- spec_case = false;\r
- if (mode < 2) {\r
- if ( (word1(d) == 0) && ((word0(d) & Bndry_mask) == 0)\r
- && ((word0(d) & (Exp_mask & Exp_mask << 1)) != 0)\r
- ) {\r
- /* The special case. Here we want to be within a quarter of the last input\r
- significant digit instead of one half of it when the decimal output string's value is less than d. */\r
- b2 += Log2P;\r
- s2 += Log2P;\r
- spec_case = true;\r
- }\r
- }\r
-\r
- /* Arrange for convenient computation of quotients:\r
- * shift left if necessary so divisor has 4 leading 0 bits.\r
- *\r
- * Perhaps we should just compute leading 28 bits of S once\r
- * and for all and pass them and a shift to quorem, so it\r
- * can do shifts and ors to compute the numerator for q.\r
- */\r
- byte [] S_bytes = S.toByteArray();\r
- int S_hiWord = 0;\r
- for (int idx = 0; idx < 4; idx++) {\r
- S_hiWord = (S_hiWord << 8);\r
- if (idx < S_bytes.length)\r
- S_hiWord |= (S_bytes[idx] & 0xFF);\r
- } \r
- if ((i = (((s5 != 0) ? 32 - hi0bits(S_hiWord) : 1) + s2) & 0x1f) != 0)\r
- i = 32 - i;\r
- /* i is the number of leading zero bits in the most significant word of S*2^s2. */\r
- if (i > 4) {\r
- i -= 4;\r
- b2 += i;\r
- m2 += i;\r
- s2 += i;\r
- }\r
- else if (i < 4) {\r
- i += 28;\r
- b2 += i;\r
- m2 += i;\r
- s2 += i;\r
- }\r
- /* Now S*2^s2 has exactly four leading zero bits in its most significant word. */\r
- if (b2 > 0)\r
- b = b.shiftLeft(b2);\r
- if (s2 > 0)\r
- S = S.shiftLeft(s2);\r
- /* Now we have d/10^k = b/S and\r
- (mhi * 2^m2) / S = maximum acceptable error, divided by 10^k. */\r
- if (k_check) {\r
- if (b.compareTo(S) < 0) {\r
- k--;\r
- b = b.multiply(BigInteger.valueOf(10)); /* we botched the k estimate */\r
- if (leftright)\r
- mhi = mhi.multiply(BigInteger.valueOf(10));\r
- ilim = ilim1;\r
- }\r
- }\r
- /* At this point 1 <= d/10^k = b/S < 10. */\r
-\r
- if (ilim <= 0 && mode > 2) {\r
- /* We're doing fixed-mode output and d is less than the minimum nonzero output in this mode.\r
- Output either zero or the minimum nonzero output depending on which is closer to d. */\r
- if ((ilim < 0 )\r
- || ((i = b.compareTo(S = S.multiply(BigInteger.valueOf(5)))) < 0)\r
- || ((i == 0 && !biasUp))) {\r
- /* Always emit at least one digit. If the number appears to be zero\r
- using the current mode, then emit one '0' digit and set decpt to 1. */\r
- /*no_digits:\r
- k = -1 - ndigits;\r
- goto ret; */\r
- buf.setLength(0);\r
- buf.append('0'); /* copy "0" to buffer */\r
- return 1;\r
-// goto no_digits;\r
- }\r
-// one_digit:\r
- buf.append('1');\r
- k++;\r
- return k + 1;\r
- }\r
- if (leftright) {\r
- if (m2 > 0)\r
- mhi = mhi.shiftLeft(m2);\r
-\r
- /* Compute mlo -- check for special case\r
- * that d is a normalized power of 2.\r
- */\r
-\r
- mlo = mhi;\r
- if (spec_case) {\r
- mhi = mlo;\r
- mhi = mhi.shiftLeft(Log2P);\r
- }\r
- /* mlo/S = maximum acceptable error, divided by 10^k, if the output is less than d. */\r
- /* mhi/S = maximum acceptable error, divided by 10^k, if the output is greater than d. */\r
-\r
- for(i = 1;;i++) { \r
- BigInteger[] divResult = b.divideAndRemainder(S);\r
- b = divResult[1]; \r
- dig = (char)(divResult[0].intValue() + '0');\r
- /* Do we yet have the shortest decimal string\r
- * that will round to d?\r
- */\r
- j = b.compareTo(mlo);\r
- /* j is b/S compared with mlo/S. */\r
- delta = S.subtract(mhi);\r
- j1 = (delta.signum() <= 0) ? 1 : b.compareTo(delta);\r
- /* j1 is b/S compared with 1 - mhi/S. */\r
- if ((j1 == 0) && (mode == 0) && ((word1(d) & 1) == 0)) {\r
- if (dig == '9') {\r
- buf.append('9');\r
- if (roundOff(buf)) {\r
- k++;\r
- buf.append('1');\r
- }\r
- return k + 1;\r
-// goto round_9_up;\r
- }\r
- if (j > 0)\r
- dig++;\r
- buf.append(dig);\r
- return k + 1;\r
- }\r
- if ((j < 0) \r
- || ((j == 0) \r
- && (mode == 0)\r
- && ((word1(d) & 1) == 0)\r
- )) {\r
- if (j1 > 0) {\r
- /* Either dig or dig+1 would work here as the least significant decimal digit.\r
- Use whichever would produce a decimal value closer to d. */\r
- b = b.shiftLeft(1);\r
- j1 = b.compareTo(S);\r
- if (((j1 > 0) || (j1 == 0 && (((dig & 1) == 1) || biasUp)))\r
- && (dig++ == '9')) {\r
- buf.append('9');\r
- if (roundOff(buf)) {\r
- k++;\r
- buf.append('1');\r
- }\r
- return k + 1;\r
-// goto round_9_up;\r
- }\r
- }\r
- buf.append(dig);\r
- return k + 1;\r
- }\r
- if (j1 > 0) {\r
- if (dig == '9') { /* possible if i == 1 */\r
-// round_9_up:\r
-// *s++ = '9';\r
-// goto roundoff;\r
- buf.append('9');\r
- if (roundOff(buf)) {\r
- k++;\r
- buf.append('1');\r
- } \r
- return k + 1;\r
- }\r
- buf.append((char)(dig + 1));\r
- return k + 1;\r
- }\r
- buf.append(dig);\r
- if (i == ilim)\r
- break;\r
- b = b.multiply(BigInteger.valueOf(10));\r
- if (mlo == mhi)\r
- mlo = mhi = mhi.multiply(BigInteger.valueOf(10));\r
- else {\r
- mlo = mlo.multiply(BigInteger.valueOf(10));\r
- mhi = mhi.multiply(BigInteger.valueOf(10));\r
- }\r
- }\r
- }\r
- else\r
- for(i = 1;; i++) {\r
-// (char)(dig = quorem(b,S) + '0');\r
- BigInteger[] divResult = b.divideAndRemainder(S);\r
- b = divResult[1]; \r
- dig = (char)(divResult[0].intValue() + '0');\r
- buf.append(dig);\r
- if (i >= ilim)\r
- break;\r
- b = b.multiply(BigInteger.valueOf(10));\r
- }\r
-\r
- /* Round off last digit */\r
-\r
- b = b.shiftLeft(1);\r
- j = b.compareTo(S);\r
- if ((j > 0) || (j == 0 && (((dig & 1) == 1) || biasUp))) {\r
-// roundoff:\r
-// while(*--s == '9')\r
-// if (s == buf) {\r
-// k++;\r
-// *s++ = '1';\r
-// goto ret;\r
-// }\r
-// ++*s++;\r
- if (roundOff(buf)) {\r
- k++;\r
- buf.append('1');\r
- return k + 1;\r
- } \r
- }\r
- else {\r
- /* Strip trailing zeros */\r
- while (buf.charAt(buf.length() - 1) == '0')\r
- buf.setLength(buf.length() - 1);\r
-// while(*--s == '0') ;\r
-// s++;\r
- }\r
-// ret:\r
-// Bfree(S);\r
-// if (mhi) {\r
-// if (mlo && mlo != mhi)\r
-// Bfree(mlo);\r
-// Bfree(mhi);\r
-// }\r
-// ret1:\r
-// Bfree(b);\r
-// JS_ASSERT(s < buf + bufsize);\r
- return k + 1;\r
- }\r
-\r
- /* Mapping of JSDToStrMode -> JS_dtoa mode */\r
- private static final int dtoaModes[] = {\r
- 0, /* DTOSTR_STANDARD */\r
- 0, /* DTOSTR_STANDARD_EXPONENTIAL, */\r
- 3, /* DTOSTR_FIXED, */\r
- 2, /* DTOSTR_EXPONENTIAL, */\r
- 2}; /* DTOSTR_PRECISION */\r
-\r
- static void\r
- JS_dtostr(StringBuffer buffer, int mode, int precision, double d)\r
- {\r
- int decPt; /* Position of decimal point relative to first digit returned by JS_dtoa */\r
- boolean[] sign = new boolean[1]; /* true if the sign bit was set in d */\r
- int nDigits; /* Number of significand digits returned by JS_dtoa */\r
-\r
-// JS_ASSERT(bufferSize >= (size_t)(mode <= DTOSTR_STANDARD_EXPONENTIAL ? DTOSTR_STANDARD_BUFFER_SIZE :\r
-// DTOSTR_VARIABLE_BUFFER_SIZE(precision)));\r
-\r
- if (mode == DTOSTR_FIXED && (d >= 1e21 || d <= -1e21))\r
- mode = DTOSTR_STANDARD; /* Change mode here rather than below because the buffer may not be large enough to hold a large integer. */\r
-\r
- decPt = JS_dtoa(d, dtoaModes[mode], mode >= DTOSTR_FIXED, precision, sign, buffer);\r
- nDigits = buffer.length();\r
-\r
- /* If Infinity, -Infinity, or NaN, return the string regardless of the mode. */\r
- if (decPt != 9999) {\r
- boolean exponentialNotation = false;\r
- int minNDigits = 0; /* Minimum number of significand digits required by mode and precision */\r
- int p;\r
- int q;\r
-\r
- switch (mode) {\r
- case DTOSTR_STANDARD:\r
- if (decPt < -5 || decPt > 21)\r
- exponentialNotation = true;\r
- else\r
- minNDigits = decPt;\r
- break;\r
-\r
- case DTOSTR_FIXED:\r
- if (precision >= 0)\r
- minNDigits = decPt + precision;\r
- else\r
- minNDigits = decPt;\r
- break;\r
-\r
- case DTOSTR_EXPONENTIAL:\r
-// JS_ASSERT(precision > 0);\r
- minNDigits = precision;\r
- /* Fall through */\r
- case DTOSTR_STANDARD_EXPONENTIAL:\r
- exponentialNotation = true;\r
- break;\r
-\r
- case DTOSTR_PRECISION:\r
-// JS_ASSERT(precision > 0);\r
- minNDigits = precision;\r
- if (decPt < -5 || decPt > precision)\r
- exponentialNotation = true;\r
- break;\r
- }\r
-\r
- /* If the number has fewer than minNDigits, pad it with zeros at the end */\r
- if (nDigits < minNDigits) {\r
- p = minNDigits;\r
- nDigits = minNDigits;\r
- do {\r
- buffer.append('0');\r
- } while (buffer.length() != p);\r
- }\r
- \r
- if (exponentialNotation) {\r
- /* Insert a decimal point if more than one significand digit */\r
- if (nDigits != 1) {\r
- buffer.insert(1, '.');\r
- }\r
- buffer.append('e');\r
- if ((decPt - 1) >= 0)\r
- buffer.append('+');\r
- buffer.append(decPt - 1);\r
-// JS_snprintf(numEnd, bufferSize - (numEnd - buffer), "e%+d", decPt-1);\r
- } else if (decPt != nDigits) {\r
- /* Some kind of a fraction in fixed notation */\r
-// JS_ASSERT(decPt <= nDigits);\r
- if (decPt > 0) {\r
- /* dd...dd . dd...dd */\r
- buffer.insert(decPt, '.');\r
- } else {\r
- /* 0 . 00...00dd...dd */\r
- for (int i = 0; i < 1 - decPt; i++)\r
- buffer.insert(0, '0');\r
- buffer.insert(1, '.');\r
- }\r
- }\r
- }\r
-\r
- /* If negative and neither -0.0 nor NaN, output a leading '-'. */\r
- if (sign[0] &&\r
- !(word0(d) == Sign_bit && word1(d) == 0) &&\r
- !((word0(d) & Exp_mask) == Exp_mask &&\r
- ((word1(d) != 0) || ((word0(d) & Frac_mask) != 0)))) {\r
- buffer.insert(0, '-');\r
- }\r
- }\r
-\r
-}\r
-\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-2000 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-// API class\r
-\r
-package org.mozilla.javascript;\r
-\r
-import org.mozilla.javascript.debug.*;\r
-\r
-public class DebuggableEngineImpl implements DebuggableEngine {\r
- \r
- public DebuggableEngineImpl(Context cx) {\r
- this.cx = cx;\r
- }\r
-\r
- /**\r
- * Set whether the engine should break when it encounters\r
- * the next line.\r
- * <p>\r
- * The engine will call the attached debugger's handleBreakpointHit\r
- * method on the next line it executes if isLineStep is true.\r
- * May be used from another thread to interrupt execution.\r
- * \r
- * @param isLineStep if true, break next line\r
- */\r
- public void setBreakNextLine(boolean isLineStep) {\r
- cx.inLineStepMode = isLineStep;\r
- }\r
- \r
- /**\r
- * Return the value of the breakNextLine flag.\r
- * @return true if the engine will break on execution of the \r
- * next line.\r
- */\r
- public boolean getBreakNextLine() {\r
- return cx.inLineStepMode;\r
- }\r
-\r
- /**\r
- * Set the associated debugger.\r
- * @param debugger the debugger to be used on callbacks from\r
- * the engine.\r
- */\r
- public void setDebugger(Debugger debugger) {\r
- cx.debugger = debugger;\r
- }\r
- \r
- /**\r
- * Return the current debugger.\r
- * @return the debugger, or null if none is attached.\r
- */\r
- public Debugger getDebugger() {\r
- return cx.debugger;\r
- }\r
- \r
- /**\r
- * Return the number of frames in current execution.\r
- * @return the count of current frames\r
- */\r
- public int getFrameCount() {\r
- return cx.frameStack == null ? 0 : cx.frameStack.size();\r
- }\r
- \r
- /**\r
- * Return a frame from the current execution.\r
- * Frames are numbered starting from 0 for the innermost\r
- * frame.\r
- * @param frameNumber the number of the frame in the range\r
- * [0,frameCount-1]\r
- * @return the relevant DebugFrame, or null if frameNumber is out\r
- * of range or the engine isn't currently saving \r
- * frames\r
- */\r
- public DebugFrame getFrame(int frameNumber) {\r
- return (DebugFrame) cx.frameStack.elementAt(cx.frameStack.size() - frameNumber - 1);\r
- }\r
- \r
- private Context cx;\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-/**\r
- * This is the default error reporter for JavaScript.\r
- *\r
- * @author Norris Boyd\r
- */\r
-class DefaultErrorReporter implements ErrorReporter {\r
-\r
- public void warning(String message, String sourceName, int line,\r
- String lineSource, int lineOffset)\r
- {\r
- // do nothing\r
- }\r
-\r
- public void error(String message, String sourceName, int line,\r
- String lineSource, int lineOffset)\r
- {\r
- //System.out.println("error at " + sourceName + ":" + line + " -- " + message);\r
- throw new EvaluatorException(message + " at " + sourceName + ":" + line);\r
- }\r
-\r
- public EvaluatorException runtimeError(String message, String sourceName,\r
- int line, String lineSource, \r
- int lineOffset)\r
- {\r
- //System.out.println("error at " + sourceName + ":" + line + " -- " + message);\r
- return new EvaluatorException(message + " at " + sourceName + ":" + line);\r
- }\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- * The contents of this file are subject to the Mozilla Public License\r
- * Version 1.1 (the "License"); you may not use this file except in\r
- * compliance with the License. You may obtain a copy of the License at\r
- * http://www.mozilla.org/MPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS IS"\r
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
- * License for the specific language governing rights and limitations\r
- * under the License.\r
- *\r
- * The Original Code is Delegator.java, released Sep 27, 2000.\r
- *\r
- * The Initial Developer of the Original Code is Matthias Radestock.\r
- * <matthias@sorted.org>. Portions created by Matthias Radestock are\r
- * Copyright (C) 2000 Matthias Radestock. All Rights Reserved.\r
- *\r
- * Contributor(s):\r
- * Redfig Ltd (http://www.redfig.com)\r
- * LShift Ltd (http://www.lshift.net)\r
- *\r
- * Alternatively, the contents of this file may be used under the terms\r
- * of the GNU Public License (the "GPL License"), in which case the\r
- * provisions of the GPL License are applicable instead of those\r
- * above. If you wish to allow use of your version of this file only\r
- * under the terms of the GPL License and not to allow others to use\r
- * your version of this file under the MPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice and\r
- * other provisions required by the GPL License. If you do not delete\r
- * the provisions above, a recipient may use your version of this file\r
- * under either the MPL or the GPL License.\r
- */\r
-\r
-// API class\r
-\r
-package org.mozilla.javascript;\r
-\r
-/**\r
- * This is a helper class for implementing wrappers around Scriptable\r
- * objects. It implements the Function interface and delegates all\r
- * invocations to a delegee Scriptable object. The normal use of this\r
- * class involves creating a sub-class and overriding one or more of\r
- * the methods.\r
- *\r
- * A useful application is the implementation of interceptors,\r
- * pre/post conditions, debugging.\r
- *\r
- * @see Function\r
- * @see Scriptable\r
- * @author Matthias Radestock\r
- */\r
-\r
-public class Delegator implements Function {\r
-\r
- protected Scriptable obj = null;\r
-\r
- /**\r
- * Create a Delegator prototype.\r
- *\r
- * This constructor should only be used for creating prototype\r
- * objects of Delegator.\r
- *\r
- * @see org.mozilla.javascript.Delegator#construct\r
- */\r
- public Delegator() {\r
- }\r
-\r
- /**\r
- * Create a new Delegator that forwards requests to a delegee\r
- * Scriptable object.\r
- *\r
- * @param obj the delegee\r
- * @see org.mozilla.javascript.Scriptable\r
- */\r
- public Delegator(Scriptable obj) {\r
- this.obj = obj;\r
- }\r
-\r
- /**\r
- * Retrieve the delegee.\r
- *\r
- * @return the delegee\r
- */\r
- public Scriptable getDelegee() {\r
- return obj;\r
- }\r
- /**\r
- * Set the delegee.\r
- *\r
- * @param obj the delegee\r
- * @see org.mozilla.javascript.Scriptable\r
- */\r
- public void setDelegee(Scriptable obj) {\r
- this.obj = obj;\r
- }\r
- /**\r
- * @see org.mozilla.javascript.Scriptable#getClassName\r
- */\r
- public String getClassName() {\r
- return obj.getClassName();\r
- }\r
- /**\r
- * @see org.mozilla.javascript.Scriptable#get\r
- */\r
- public Object get(String name, Scriptable start) {\r
- return obj.get(name,start);\r
- }\r
- /**\r
- * @see org.mozilla.javascript.Scriptable#get\r
- */\r
- public Object get(int index, Scriptable start) {\r
- return obj.get(index,start);\r
- }\r
- /**\r
- * @see org.mozilla.javascript.Scriptable#has\r
- */\r
- public boolean has(String name, Scriptable start) {\r
- return obj.has(name,start);\r
- }\r
- /**\r
- * @see org.mozilla.javascript.Scriptable#has\r
- */\r
- public boolean has(int index, Scriptable start) {\r
- return obj.has(index,start);\r
- }\r
- /**\r
- * @see org.mozilla.javascript.Scriptable#put\r
- */\r
- public void put(String name, Scriptable start, Object value) {\r
- obj.put(name,start,value);\r
- }\r
- /**\r
- * @see org.mozilla.javascript.Scriptable#put\r
- */\r
- public void put(int index, Scriptable start, Object value) {\r
- obj.put(index,start,value);\r
- }\r
- /**\r
- * @see org.mozilla.javascript.Scriptable#delete\r
- */\r
- public void delete(String name) {\r
- obj.delete(name);\r
- }\r
- /**\r
- * @see org.mozilla.javascript.Scriptable#delete\r
- */\r
- public void delete(int index) {\r
- obj.delete(index);\r
- }\r
- /**\r
- * @see org.mozilla.javascript.Scriptable#getPrototype\r
- */\r
- public Scriptable getPrototype() {\r
- return obj.getPrototype();\r
- }\r
- /**\r
- * @see org.mozilla.javascript.Scriptable#setPrototype\r
- */\r
- public void setPrototype(Scriptable prototype) {\r
- obj.setPrototype(prototype);\r
- }\r
- /**\r
- * @see org.mozilla.javascript.Scriptable#getParentScope\r
- */\r
- public Scriptable getParentScope() {\r
- return obj.getParentScope();\r
- }\r
- /**\r
- * @see org.mozilla.javascript.Scriptable#setParentScope\r
- */\r
- public void setParentScope(Scriptable parent) {\r
- obj.setParentScope(parent);\r
- }\r
- /**\r
- * @see org.mozilla.javascript.Scriptable#getIds\r
- */\r
- public Object[] getIds() {\r
- return obj.getIds();\r
- }\r
- /**\r
- * Note that this method does not get forwarded to the delegee if\r
- * the <code>hint</code> parameter is null,\r
- * <code>ScriptRuntime.ScriptableClass</code> or\r
- * <code>ScriptRuntime.FunctionClass</code>. Instead the object\r
- * itself is returned.\r
- *\r
- * @param hint the type hint\r
- * @return the default value\r
- *\r
- * @see org.mozilla.javascript.Scriptable#getDefaultValue\r
- */\r
- public Object getDefaultValue(Class hint) {\r
- return (hint == null ||\r
- hint == ScriptRuntime.ScriptableClass ||\r
- hint == ScriptRuntime.FunctionClass) ?\r
- this : obj.getDefaultValue(hint);\r
- }\r
- /**\r
- * @see org.mozilla.javascript.Scriptable#hasInstance\r
- */\r
- public boolean hasInstance(Scriptable instance) {\r
- return obj.hasInstance(instance);\r
- }\r
- /**\r
- * @see org.mozilla.javascript.Function#call\r
- */\r
- public Object call(Context cx, Scriptable scope, Scriptable thisObj,\r
- Object[] args)\r
- throws JavaScriptException {\r
- return ((Function)obj).call(cx,scope,thisObj,args);\r
- }\r
-\r
- /**\r
- * Note that if the <code>delegee</code> is <code>null</code>,\r
- * this method creates a new instance of the Delegator itself\r
- * rathert than forwarding the call to the\r
- * <code>delegee</code>. This permits the use of Delegator\r
- * prototypes.\r
- *\r
- * @param cx the current Context for this thread\r
- * @param scope an enclosing scope of the caller except\r
- * when the function is called from a closure.\r
- * @param args the array of arguments\r
- * @return the allocated object\r
- * @exception JavaScriptException if an uncaught exception\r
- * occurred while executing the constructor\r
- *\r
- * @see org.mozilla.javascript.Function#construct\r
- */\r
- public Scriptable construct(Context cx, Scriptable scope, Object[] args)\r
- throws JavaScriptException {\r
- if (obj == null) {\r
- //this little trick allows us to declare prototype objects for\r
- //Delegators\r
- try {\r
- Delegator n = (Delegator)this.getClass().newInstance();\r
- n.setDelegee((Scriptable)args[0]);\r
- return n;\r
- }\r
- catch (Exception e) {\r
- e.printStackTrace();\r
- throw new Error("exception in org.mozilla.javascript.Delegator.construct()");\r
- //System.exit(0);\r
- }\r
- }\r
- else {\r
- return ((Function)obj).construct(cx,scope,args);\r
- }\r
- }\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Roger Lawrence\r
- * \r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-// API class\r
-\r
-package org.mozilla.javascript;\r
-\r
-/**\r
- * The class of exceptions raised by the engine as described in \r
- * ECMA edition 3. See section 15.11.6 in particular.\r
- */\r
-public class EcmaError extends RuntimeException {\r
-\r
- /**\r
- * Create an exception with the specified detail message.\r
- *\r
- * Errors internal to the JavaScript engine will simply throw a\r
- * RuntimeException.\r
- *\r
- * @param nativeError the NativeError object constructed for this error\r
- * @param sourceName the name of the source reponsible for the error\r
- * @param lineNumber the line number of the source\r
- * @param columnNumber the columnNumber of the source (may be zero if\r
- * unknown)\r
- * @param lineSource the source of the line containing the error (may be \r
- * null if unknown)\r
- */\r
- public EcmaError(NativeError nativeError, String sourceName, \r
- int lineNumber, int columnNumber, String lineSource) \r
- {\r
- super("EcmaError");\r
- errorObject = nativeError;\r
- this.sourceName = sourceName;\r
- this.lineNumber = lineNumber;\r
- this.columnNumber = columnNumber;\r
- this.lineSource = lineSource;\r
- }\r
- \r
- /**\r
- * Return a string representation of the error, which currently consists \r
- * of the name of the error together with the message.\r
- */\r
- public String toString() {\r
- if (sourceName != null && lineNumber > 0)\r
- return errorObject.toString() + " (" + sourceName + \r
- "; line " + lineNumber + ")";\r
- else\r
- return errorObject.toString();\r
- }\r
- \r
- /**\r
- * Gets the name of the error.\r
- * \r
- * ECMA edition 3 defines the following\r
- * errors: EvalError, RangeError, ReferenceError, \r
- * SyntaxError, TypeError, and URIError. Additional error names\r
- * may be added in the future.\r
- * \r
- * See ECMA edition 3, 15.11.7.9.\r
- * \r
- * @return the name of the error. \r
- */\r
- public String getName() {\r
- return errorObject.getName();\r
- }\r
- \r
- /**\r
- * Gets the message corresponding to the error.\r
- * \r
- * See ECMA edition 3, 15.11.7.10.\r
- * \r
- * @return an implemenation-defined string describing the error.\r
- */\r
- public String getMessage() {\r
- return errorObject.getMessage();\r
- }\r
- \r
- /**\r
- * Get the name of the source containing the error, or null\r
- * if that information is not available.\r
- */\r
- public String getSourceName() {\r
- return sourceName;\r
- }\r
- \r
- /**\r
- * Returns the line number of the statement causing the error,\r
- * or zero if not available.\r
- */\r
- public int getLineNumber() {\r
- return lineNumber;\r
- }\r
- \r
- /**\r
- * Get the error object corresponding to this exception.\r
- */\r
- public Scriptable getErrorObject() {\r
- return errorObject;\r
- }\r
- \r
- /**\r
- * The column number of the location of the error, or zero if unknown.\r
- */\r
- public int getColumnNumber() {\r
- return columnNumber;\r
- }\r
- \r
- /**\r
- * The source of the line causing the error, or zero if unknown.\r
- */\r
- public String getLineSource() {\r
- return lineSource;\r
- }\r
- \r
- private NativeError errorObject;\r
- private String sourceName;\r
- private int lineNumber;\r
- private int columnNumber;\r
- private String lineSource;\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-// API class\r
-\r
-package org.mozilla.javascript;\r
-\r
-/**\r
- * This is interface defines a protocol for the reporting of\r
- * errors during JavaScript translation or execution.\r
- *\r
- * @author Norris Boyd\r
- */\r
-\r
-public interface ErrorReporter {\r
-\r
- /**\r
- * Report a warning.\r
- *\r
- * The implementing class may choose to ignore the warning\r
- * if it desires.\r
- *\r
- * @param message a String describing the warning\r
- * @param sourceName a String describing the JavaScript source\r
- * where the warning occured; typically a filename or URL\r
- * @param line the line number associated with the warning\r
- * @param lineSource the text of the line (may be null)\r
- * @param lineOffset the offset into lineSource where problem was detected\r
- */\r
- void warning(String message, String sourceName, int line,\r
- String lineSource, int lineOffset);\r
-\r
- /**\r
- * Report an error.\r
- *\r
- * The implementing class is free to throw an exception if\r
- * it desires.\r
- *\r
- * If execution has not yet begun, the JavaScript engine is\r
- * free to find additional errors rather than terminating\r
- * the translation. It will not execute a script that had\r
- * errors, however.\r
- *\r
- * @param message a String describing the error\r
- * @param sourceName a String describing the JavaScript source\r
- * where the error occured; typically a filename or URL\r
- * @param line the line number associated with the error\r
- * @param lineSource the text of the line (may be null)\r
- * @param lineOffset the offset into lineSource where problem was detected\r
- */\r
- void error(String message, String sourceName, int line,\r
- String lineSource, int lineOffset);\r
-\r
- /**\r
- * Creates an EvaluatorException that may be thrown.\r
- *\r
- * runtimeErrors, unlike errors, will always terminate the\r
- * current script.\r
- *\r
- * @param message a String describing the error\r
- * @param sourceName a String describing the JavaScript source\r
- * where the error occured; typically a filename or URL\r
- * @param line the line number associated with the error\r
- * @param lineSource the text of the line (may be null)\r
- * @param lineOffset the offset into lineSource where problem was detected\r
- * @return an EvaluatorException that will be thrown.\r
- */\r
- EvaluatorException runtimeError(String message, String sourceName, \r
- int line, String lineSource, \r
- int lineOffset);\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-\r
-package org.mozilla.javascript;\r
-\r
-/**\r
- * The class of exceptions thrown by the JavaScript engine.\r
- */\r
-public class EvaluatorException extends RuntimeException {\r
-\r
- /**\r
- * Create an exception with the specified detail message.\r
- *\r
- * Errors internal to the JavaScript engine will simply throw a\r
- * RuntimeException.\r
- *\r
- * @param detail a message with detail about the exception\r
- */\r
- public EvaluatorException(String detail) {\r
- super(detail);\r
- }\r
-\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- * Roger Lawrence\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-import java.util.Hashtable;\r
-import java.util.Enumeration;\r
-\r
-/**\r
- * Manipulate a Scriptable object as if its prototype chain were flattened.\r
- * <p>\r
- * This class has been deprecated in favor of the static methods \r
- * <code>getProperty</code>, <code>putProperty</code>, and \r
- * <code>deleteProperty</code> of ScripableObject. Those methods provide the\r
- * same functionality without the confusing and inefficient need to construct\r
- * a new object instance.\r
- *\r
- * @see org.mozilla.javascript.ScriptableObject\r
- * @deprecated\r
- * @author Norris Boyd\r
- */\r
-\r
-public class FlattenedObject {\r
-\r
- /**\r
- * Construct a new FlattenedObject.\r
- *\r
- * @param object the object to be viewed with flattened properties\r
- * @deprecated\r
- */\r
- public FlattenedObject(Scriptable object) {\r
- this.obj = object;\r
- }\r
-\r
- /**\r
- * Get the associated Scriptable object.\r
- * @deprecated\r
- */\r
- public Scriptable getObject() {\r
- return obj;\r
- }\r
-\r
- /**\r
- * Determine if a property exists in an object.\r
- *\r
- * This is a more convenient (and less efficient) form than\r
- * <code>Scriptable.has()</code>.\r
- * It returns true if and only if the property\r
- * exists in this object or any of the objects in its prototype\r
- * chain.\r
- *\r
- * @param id the property index, which may be either a String or a\r
- * Number\r
- * @return true if and only if the property exists in the prototype\r
- * chain\r
- * @see org.mozilla.javascript.Scriptable#has\r
- * @deprecated As of 1.5R2, replaced by ScriptableObject.getProperty\r
- */\r
- public boolean hasProperty(Object id) {\r
- String stringId = ScriptRuntime.toString(id);\r
- String s = ScriptRuntime.getStringId(stringId);\r
- if (s == null)\r
- return getBase(obj, ScriptRuntime.getIntId(stringId)) != null;\r
- return getBase(obj, s) != null;\r
- }\r
-\r
- /**\r
- * Get a property of an object.\r
- * <p>\r
- * This is a more convenient (and less efficient) form than\r
- * <code>Scriptable.get()</code>. It corresponds exactly to the\r
- * expression <code>obj[id]</code> in JavaScript. This method\r
- * will traverse the prototype chain of an object to find the\r
- * property.<p>\r
- *\r
- * If the property does not exist in the object or its prototype\r
- * chain, the undefined value will be returned.\r
- *\r
- * @param id the property index; can be a String or a Number; the\r
- * String may contain characters representing a number\r
- * @return the value of the property or the undefined value\r
- * @see org.mozilla.javascript.Scriptable#get\r
- * @see org.mozilla.javascript.Context#getUndefinedValue\r
- * @deprecated As of 1.5R2, replaced by ScriptableObject.getProperty\r
- */\r
- public Object getProperty(Object id) {\r
- String s = ScriptRuntime.getStringId(id);\r
- int index = s == null ? ScriptRuntime.getIntId(id) : 0;\r
- Scriptable m = obj;\r
- Object result;\r
- for(;;) {\r
- result = s == null ? m.get(index, obj) : m.get(s, obj);\r
- if (result != Scriptable.NOT_FOUND)\r
- break;\r
- m = m.getPrototype();\r
- if (m == null)\r
- return Undefined.instance;\r
- }\r
- if (result instanceof Scriptable)\r
- return new FlattenedObject((Scriptable) result);\r
- return result;\r
- }\r
-\r
- /**\r
- * Set a property of an object.\r
- *\r
- * This is a more convenient (and less efficient) form than that\r
- * provided in Scriptable. It corresponds exactly to the\r
- * expression <code>obj[id] = val</code> in JavaScript.<p>\r
- *\r
- * @param id the property index, which may be either a String or\r
- * a Number\r
- * @param value the value of the property\r
- * @see org.mozilla.javascript.Scriptable#put\r
- * @deprecated As of 1.5R2, replaced by ScriptableObject.putProperty\r
- */\r
- public void putProperty(Object id, Object value) {\r
- String s = ScriptRuntime.getStringId(id);\r
- if (value instanceof FlattenedObject)\r
- value = ((FlattenedObject) value).getObject();\r
- Scriptable x;\r
- if (s == null) {\r
- int index = ScriptRuntime.getIntId(id);\r
- x = getBase(obj, index);\r
- if (x == null)\r
- x = obj;\r
- x.put(index, obj, value);\r
- return;\r
- }\r
- x = getBase(obj, s);\r
- if (x == null)\r
- x = obj;\r
- x.put(s, obj, value);\r
- }\r
-\r
- /**\r
- * Remove a property.\r
- *\r
- * This method provides the functionality of the <code>delete</code>\r
- * operator in JavaScript.\r
- *\r
- * @param id the property index, which may be either a String or\r
- * a Number\r
- * @return true if the property didn't exist, or existed and was removed\r
- * @see org.mozilla.javascript.Scriptable#delete\r
- * @deprecated as of 1.5R2, replaced by ScriptableObject.deleteProperty\r
- */\r
- public boolean deleteProperty(Object id) {\r
- String s = ScriptRuntime.getStringId(id);\r
- if (s == null) {\r
- int index = ScriptRuntime.getIntId(id);\r
- Scriptable base = getBase(obj, index);\r
- if (base == null)\r
- return true;\r
- base.delete(index);\r
- return !base.has(index, base);\r
- }\r
- Scriptable base = getBase(obj, s);\r
- if (base == null)\r
- return true;\r
- base.delete(s);\r
- return !base.has(s, base);\r
- }\r
-\r
- /**\r
- * Return an array that contains the ids of the properties.\r
- *\r
- * <p>This method will walk the prototype chain and collect the\r
- * ids of all objects in the prototype chain.<p>\r
- *\r
- * If an id appears in more than one object in the prototype chain,\r
- * it will only be in the array once. (So all the entries in the\r
- * array will be unique respective to equals().)\r
- *\r
- * @see org.mozilla.javascript.Scriptable#getIds\r
- * @deprecated\r
- */\r
- public Object[] getIds() {\r
- Hashtable h = new Hashtable(11);\r
- Scriptable m = obj;\r
- while (m != null) {\r
- Object[] e = m.getIds();\r
- for (int i=0; i < e.length; i++) {\r
- h.put(e[i], Boolean.TRUE);\r
- }\r
- m = m.getPrototype();\r
- }\r
- Enumeration keys = h.keys();\r
- Object elem;\r
- Object[] result = new Object[h.size()];\r
- int index = 0;\r
- while (keys.hasMoreElements()) {\r
- elem = keys.nextElement();\r
- result[index++] = elem;\r
- }\r
- return result;\r
- }\r
-\r
- /**\r
- * Consider this object to be a function, and call it.\r
- *\r
- * @param cx the current Context for this thread\r
- * @param thisObj the JavaScript 'this' for the call\r
- * @param args the arguments for the call\r
- * @return the result of the JavaScript function call\r
- * @exception NotAFunctionException if this object is not a function\r
- * @exception JavaScriptException if an uncaught JavaScript exception\r
- * occurred while executing the function\r
- * @see org.mozilla.javascript.Function#call\r
- * @deprecated\r
- */\r
- public Object call(Context cx, Scriptable thisObj, Object[] args)\r
- throws NotAFunctionException,\r
- JavaScriptException\r
- {\r
- if (!(obj instanceof Function)) {\r
- throw new NotAFunctionException();\r
- }\r
- return ScriptRuntime.call(cx, obj, thisObj, args, (Function) obj);\r
- }\r
-\r
- /**\r
- * Consider this object to be a function, and invoke it as a\r
- * constructor call.\r
- *\r
- * @param cx the current Context for this thread\r
- * @param args the arguments for the constructor call\r
- * @return the allocated object\r
- * @exception NotAFunctionException if this object is not a function\r
- * @exception JavaScriptException if an uncaught JavaScript exception\r
- * occurred while executing the constructor\r
- * @see org.mozilla.javascript.Function#construct\r
- * @deprecated\r
- */\r
- public Scriptable construct(Context cx, Object[] args)\r
- throws NotAFunctionException,\r
- JavaScriptException\r
- {\r
- if (!(obj instanceof Function)) {\r
- throw new NotAFunctionException();\r
- }\r
- return ScriptRuntime.newObject(cx, obj, args, null);\r
- }\r
-\r
- /**\r
- * Get the property indicated by the id, and invoke it with the\r
- * specified arguments.\r
- * <p>\r
- * For example, for a FlattenedObject <code>obj</code>,\r
- * and a Java array <code>a</code> consisting of a single string\r
- * <code>"hi"</code>, the call <pre>\r
- * obj.callMethod("m", a)</pre>\r
- * is equivalent to the JavaScript code <code>obj.m("hi")</code>.<p>\r
- *\r
- * If the property is not found or is not a function, an\r
- * exception will be thrown.\r
- *\r
- * @param id the Number or String to use to find the function property\r
- * to call\r
- * @param args the arguments for the constructor call\r
- * @return the result of the call\r
- * @exception PropertyException if the designated property\r
- * was not found\r
- * @exception NotAFunctionException if this object is not a function\r
- * @exception JavaScriptException if an uncaught JavaScript exception\r
- * occurred while executing the method\r
- * @see org.mozilla.javascript.Function#call\r
- * @deprecated\r
- */\r
- public Object callMethod(Object id, Object[] args)\r
- throws PropertyException,\r
- NotAFunctionException,\r
- JavaScriptException\r
- {\r
- if (!hasProperty(id)) {\r
- throw PropertyException.withMessage0("msg.prop.not.found");\r
- }\r
- Object o = getProperty(id);\r
- if (o instanceof FlattenedObject)\r
- return ((FlattenedObject) o).call(Context.getContext(), obj, args);\r
- throw new NotAFunctionException();\r
- }\r
-\r
- /****** End of API *******/\r
-\r
- private static Scriptable getBase(Scriptable obj, String s) {\r
- Scriptable m = obj;\r
- while (m != null) {\r
- if (m.has(s, obj))\r
- return m;\r
- m = m.getPrototype();\r
- }\r
- return null;\r
- }\r
-\r
- private static Scriptable getBase(Scriptable obj, int index) {\r
- Scriptable m = obj;\r
- while (m != null) {\r
- if (m.has(index, obj))\r
- return m;\r
- m = m.getPrototype();\r
- }\r
- return null;\r
- }\r
-\r
- private Scriptable obj;\r
-}\r
-\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-// API class\r
-\r
-package org.mozilla.javascript;\r
-\r
-/**\r
- * This is interface that all functions in JavaScript must implement.\r
- * The interface provides for calling functions and constructors.\r
- *\r
- * @see org.mozilla.javascript.Scriptable\r
- * @author Norris Boyd\r
- */\r
-\r
-public interface Function extends Scriptable {\r
- /**\r
- * Call the function.\r
- *\r
- * Note that the array of arguments is not guaranteed to have\r
- * length greater than 0.\r
- *\r
- * @param cx the current Context for this thread\r
- * @param scope the scope to execute the function relative to. This is\r
- * set to the value returned by getParentScope() except\r
- * when the function is called from a closure.\r
- * @param thisObj the JavaScript <code>this</code> object\r
- * @param args the array of arguments\r
- * @return the result of the call\r
- * @exception JavaScriptException if an uncaught exception\r
- * occurred while executing the function\r
- */\r
- public Object call(Context cx, Scriptable scope, Scriptable thisObj,\r
- Object[] args)\r
- throws JavaScriptException;\r
-\r
- /**\r
- * Call the function as a constructor.\r
- *\r
- * This method is invoked by the runtime in order to satisfy a use\r
- * of the JavaScript <code>new</code> operator. This method is\r
- * expected to create a new object and return it.\r
- *\r
- * @param cx the current Context for this thread\r
- * @param scope an enclosing scope of the caller except\r
- * when the function is called from a closure.\r
- * @param args the array of arguments\r
- * @return the allocated object\r
- * @exception JavaScriptException if an uncaught exception\r
- * occurred while executing the constructor\r
- */\r
- public Scriptable construct(Context cx, Scriptable scope, Object[] args)\r
- throws JavaScriptException;\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- * Roger Lawrence\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-import java.util.*;\r
-\r
-public class FunctionNode extends Node {\r
-\r
- public FunctionNode(String name, Node left, Node right) {\r
- super(TokenStream.FUNCTION, left, right, name);\r
- itsVariableTable = new VariableTable();\r
- }\r
-\r
- public String getFunctionName() {\r
- return getString();\r
- }\r
-\r
- public VariableTable getVariableTable() {\r
- return itsVariableTable;\r
- }\r
-\r
- public boolean requiresActivation() {\r
- return itsNeedsActivation;\r
- }\r
-\r
- public boolean setRequiresActivation(boolean b) {\r
- return itsNeedsActivation = b;\r
- }\r
- \r
- public boolean getCheckThis() {\r
- return itsCheckThis;\r
- }\r
-\r
- public void setCheckThis(boolean b) {\r
- itsCheckThis = b;\r
- }\r
- \r
- /**\r
- * There are three types of functions that can be defined. The first\r
- * is a function statement. This is a function appearing as a top-level\r
- * statement (i.e., not nested inside some other statement) in either a\r
- * script or a function.\r
- * \r
- * The second is a function expression, which is a function appearing in\r
- * an expression except for the third type, which is...\r
- * \r
- * The third type is a function expression where the expression is the \r
- * top-level expression in an expression statement.\r
- * \r
- * The three types of functions have different treatment and must be \r
- * distinquished.\r
- */\r
- public static final byte FUNCTION_STATEMENT = 1;\r
- public static final byte FUNCTION_EXPRESSION = 2;\r
- public static final byte FUNCTION_EXPRESSION_STATEMENT = 3;\r
- \r
- public byte getFunctionType() {\r
- return itsFunctionType;\r
- }\r
-\r
- public void setFunctionType(byte functionType) {\r
- itsFunctionType = functionType;\r
- }\r
-\r
- protected VariableTable itsVariableTable;\r
- protected boolean itsNeedsActivation;\r
- protected boolean itsCheckThis;\r
- protected byte itsFunctionType;\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-2000 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- * Igor Bukanov\r
- * David C. Navas\r
- * Ted Neward\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-// API class\r
-\r
-package org.mozilla.javascript;\r
-\r
-import java.util.Vector;\r
-import java.lang.reflect.Constructor;\r
-import java.lang.reflect.Member;\r
-import java.lang.reflect.Method;\r
-import java.lang.reflect.Modifier;\r
-import java.lang.reflect.InvocationTargetException;\r
-\r
-public class FunctionObject extends NativeFunction {\r
-\r
- /**\r
- * Create a JavaScript function object from a Java method.\r
- *\r
- * <p>The <code>member</code> argument must be either a java.lang.reflect.Method\r
- * or a java.lang.reflect.Constructor and must match one of two forms.<p>\r
- *\r
- * The first form is a member with zero or more parameters\r
- * of the following types: Object, String, boolean, Scriptable,\r
- * byte, short, int, float, or double. The Long type is not supported\r
- * because the double representation of a long (which is the \r
- * EMCA-mandated storage type for Numbers) may lose precision.\r
- * If the member is a Method, the return value must be void or one \r
- * of the types allowed for parameters.<p>\r
- *\r
- * The runtime will perform appropriate conversions based\r
- * upon the type of the parameter. A parameter type of\r
- * Object specifies that no conversions are to be done. A parameter\r
- * of type String will use Context.toString to convert arguments.\r
- * Similarly, parameters of type double, boolean, and Scriptable\r
- * will cause Context.toNumber, Context.toBoolean, and\r
- * Context.toObject, respectively, to be called.<p>\r
- *\r
- * If the method is not static, the Java 'this' value will\r
- * correspond to the JavaScript 'this' value. Any attempt\r
- * to call the function with a 'this' value that is not\r
- * of the right Java type will result in an error.<p>\r
- *\r
- * The second form is the variable arguments (or "varargs")\r
- * form. If the FunctionObject will be used as a constructor,\r
- * the member must have the following parameters\r
- * <pre>\r
- * (Context cx, Object[] args, Function ctorObj,\r
- * boolean inNewExpr)</pre>\r
- * and if it is a Method, be static and return an Object result.<p>\r
- *\r
- * Otherwise, if the FunctionObject will <i>not</i> be used to define a\r
- * constructor, the member must be a static Method with parameters\r
- * (Context cx, Scriptable thisObj, Object[] args,\r
- * Function funObj) </pre>\r
- * <pre>\r
- * and an Object result.<p>\r
- *\r
- * When the function varargs form is called as part of a function call,\r
- * the <code>args</code> parameter contains the\r
- * arguments, with <code>thisObj</code>\r
- * set to the JavaScript 'this' value. <code>funObj</code>\r
- * is the function object for the invoked function.<p>\r
- *\r
- * When the constructor varargs form is called or invoked while evaluating\r
- * a <code>new</code> expression, <code>args</code> contains the\r
- * arguments, <code>ctorObj</code> refers to this FunctionObject, and\r
- * <code>inNewExpr</code> is true if and only if a <code>new</code>\r
- * expression caused the call. This supports defining a function that\r
- * has different behavior when called as a constructor than when\r
- * invoked as a normal function call. (For example, the Boolean\r
- * constructor, when called as a function,\r
- * will convert to boolean rather than creating a new object.)<p>\r
- *\r
- * @param name the name of the function\r
- * @param methodOrConstructor a java.lang.reflect.Method or a java.lang.reflect.Constructor\r
- * that defines the object\r
- * @param scope enclosing scope of function\r
- * @see org.mozilla.javascript.Scriptable\r
- */\r
- public FunctionObject(String name, Member methodOrConstructor,\r
- Scriptable scope)\r
- {\r
- String methodName;\r
- if (methodOrConstructor instanceof Constructor) {\r
- ctor = (Constructor) methodOrConstructor;\r
- isStatic = true; // well, doesn't take a 'this'\r
- types = ctor.getParameterTypes();\r
- methodName = ctor.getName();\r
- } else {\r
- method = (Method) methodOrConstructor;\r
- isStatic = Modifier.isStatic(method.getModifiers());\r
- types = method.getParameterTypes();\r
- methodName = method.getName();\r
- }\r
- this.functionName = name;\r
- int length;\r
- if (types.length == 4 && (types[1].isArray() || types[2].isArray())) {\r
- // Either variable args or an error.\r
- if (types[1].isArray()) {\r
- if (!isStatic ||\r
- types[0] != Context.class ||\r
- types[1].getComponentType() != ScriptRuntime.ObjectClass ||\r
- types[2] != ScriptRuntime.FunctionClass ||\r
- types[3] != Boolean.TYPE)\r
- {\r
- throw Context.reportRuntimeError1(\r
- "msg.varargs.ctor", methodName);\r
- }\r
- parmsLength = VARARGS_CTOR;\r
- } else {\r
- if (!isStatic ||\r
- types[0] != Context.class ||\r
- types[1] != ScriptRuntime.ScriptableClass ||\r
- types[2].getComponentType() != ScriptRuntime.ObjectClass ||\r
- types[3] != ScriptRuntime.FunctionClass)\r
- {\r
- throw Context.reportRuntimeError1(\r
- "msg.varargs.fun", methodName);\r
- }\r
- parmsLength = VARARGS_METHOD;\r
- }\r
- // XXX check return type\r
- length = 1;\r
- } else {\r
- parmsLength = (short) types.length;\r
- for (int i=0; i < parmsLength; i++) {\r
- Class type = types[i];\r
- if (type != ScriptRuntime.ObjectClass &&\r
- type != ScriptRuntime.StringClass &&\r
- type != ScriptRuntime.BooleanClass &&\r
- !ScriptRuntime.NumberClass.isAssignableFrom(type) &&\r
- !Scriptable.class.isAssignableFrom(type) &&\r
- type != Boolean.TYPE &&\r
- type != Byte.TYPE &&\r
- type != Short.TYPE &&\r
- type != Integer.TYPE &&\r
- type != Float.TYPE && \r
- type != Double.TYPE)\r
- {\r
- // Note that long is not supported.\r
- throw Context.reportRuntimeError1("msg.bad.parms", \r
- methodName);\r
- }\r
- }\r
- length = parmsLength;\r
- }\r
-\r
- // Initialize length property\r
- lengthPropertyValue = (short) length;\r
-\r
- hasVoidReturn = method != null && method.getReturnType() == Void.TYPE;\r
- this.argCount = (short) length;\r
-\r
- setParentScope(scope);\r
- setPrototype(getFunctionPrototype(scope));\r
- Context cx = Context.getCurrentContext();\r
- useDynamicScope = cx != null && \r
- cx.hasCompileFunctionsWithDynamicScope();\r
- }\r
-\r
- /**\r
- * Return the value defined by the method used to construct the object\r
- * (number of parameters of the method, or 1 if the method is a "varargs"\r
- * form), unless setLength has been called with a new value.\r
- * Overrides getLength in BaseFunction.\r
- *\r
- * @see org.mozilla.javascript.FunctionObject#setLength\r
- * @see org.mozilla.javascript.BaseFunction#getLength\r
- */\r
- public int getLength() {\r
- return lengthPropertyValue;\r
- }\r
-\r
- /**\r
- * Set the value of the "length" property.\r
- *\r
- * <p>Changing the value of the "length" property of a FunctionObject only\r
- * affects the value retrieved from get() and does not affect the way\r
- * the method itself is called. <p>\r
- *\r
- * The "length" property will be defined by default as the number\r
- * of parameters of the method used to construct the FunctionObject,\r
- * unless the method is a "varargs" form, in which case the "length"\r
- * property will be defined to 1.\r
- *\r
- * @param length the new length\r
- */\r
- public void setLength(short length) {\r
- lengthPropertyValue = length;\r
- }\r
-\r
- // TODO: Make not public\r
- /**\r
- * Finds methods of a given name in a given class.\r
- *\r
- * <p>Searches <code>clazz</code> for methods with name\r
- * <code>name</code>. Maintains a cache so that multiple\r
- * lookups on the same class are cheap.\r
- *\r
- * @param clazz the class to search\r
- * @param name the name of the methods to find\r
- * @return an array of the found methods, or null if no methods\r
- * by that name were found.\r
- * @see java.lang.Class#getMethods\r
- */\r
- public static Method[] findMethods(Class clazz, String name) {\r
- return findMethods(getMethodList(clazz), name);\r
- }\r
- \r
- static Method[] findMethods(Method[] methods, String name) {\r
- // Usually we're just looking for a single method, so optimize\r
- // for that case.\r
- Vector v = null;\r
- Method first = null;\r
- for (int i=0; i < methods.length; i++) {\r
- if (methods[i] == null)\r
- continue;\r
- if (methods[i].getName().equals(name)) {\r
- if (first == null) {\r
- first = methods[i];\r
- } else {\r
- if (v == null) {\r
- v = new Vector(5);\r
- v.addElement(first);\r
- }\r
- v.addElement(methods[i]);\r
- }\r
- }\r
- }\r
- if (v == null) {\r
- if (first == null)\r
- return null;\r
- Method[] single = { first };\r
- return single;\r
- }\r
- Method[] result = new Method[v.size()];\r
- v.copyInto(result);\r
- return result;\r
- }\r
-\r
- static Method[] getMethodList(Class clazz) {\r
- Method[] cached = methodsCache; // get once to avoid synchronization\r
- if (cached != null && cached[0].getDeclaringClass() == clazz)\r
- return cached;\r
- Method[] methods = null;\r
- try {\r
- // getDeclaredMethods may be rejected by the security manager\r
- // but getMethods is more expensive\r
- if (!sawSecurityException) \r
- methods = clazz.getDeclaredMethods();\r
- } catch (SecurityException e) {\r
- // If we get an exception once, give up on getDeclaredMethods\r
- sawSecurityException = true;\r
- }\r
- if (methods == null) {\r
- methods = clazz.getMethods();\r
- }\r
- int count = 0;\r
- for (int i=0; i < methods.length; i++) {\r
- if (sawSecurityException \r
- ? methods[i].getDeclaringClass() != clazz\r
- : !Modifier.isPublic(methods[i].getModifiers()))\r
- {\r
- methods[i] = null;\r
- } else {\r
- count++;\r
- }\r
- }\r
- Method[] result = new Method[count];\r
- int j=0;\r
- for (int i=0; i < methods.length; i++) {\r
- if (methods[i] != null)\r
- result[j++] = methods[i];\r
- }\r
- if (result.length > 0 && Context.isCachingEnabled)\r
- methodsCache = result;\r
- return result;\r
- }\r
-\r
- /**\r
- * Define this function as a JavaScript constructor.\r
- * <p>\r
- * Sets up the "prototype" and "constructor" properties. Also\r
- * calls setParent and setPrototype with appropriate values.\r
- * Then adds the function object as a property of the given scope, using\r
- * <code>prototype.getClassName()</code>\r
- * as the name of the property.\r
- *\r
- * @param scope the scope in which to define the constructor (typically\r
- * the global object)\r
- * @param prototype the prototype object\r
- * @see org.mozilla.javascript.Scriptable#setParentScope\r
- * @see org.mozilla.javascript.Scriptable#setPrototype\r
- * @see org.mozilla.javascript.Scriptable#getClassName\r
- */\r
- public void addAsConstructor(Scriptable scope, Scriptable prototype) {\r
- setParentScope(scope);\r
- setPrototype(getFunctionPrototype(scope));\r
- setImmunePrototypeProperty(prototype);\r
-\r
- prototype.setParentScope(this);\r
- \r
- final int attr = ScriptableObject.DONTENUM |\r
- ScriptableObject.PERMANENT |\r
- ScriptableObject.READONLY;\r
- defineProperty(prototype, "constructor", this, attr);\r
-\r
- String name = prototype.getClassName();\r
- defineProperty(scope, name, this, ScriptableObject.DONTENUM);\r
-\r
- setParentScope(scope);\r
- }\r
-\r
- static public Object convertArg(Scriptable scope,\r
- Object arg, Class desired)\r
- {\r
- if (desired == ScriptRuntime.StringClass) \r
- return ScriptRuntime.toString(arg);\r
- if (desired == ScriptRuntime.IntegerClass || \r
- desired == Integer.TYPE)\r
- {\r
- return new Integer(ScriptRuntime.toInt32(arg));\r
- }\r
- if (desired == ScriptRuntime.BooleanClass || \r
- desired == Boolean.TYPE)\r
- {\r
- return ScriptRuntime.toBoolean(arg) ? Boolean.TRUE \r
- : Boolean.FALSE;\r
- }\r
- if (desired == ScriptRuntime.DoubleClass || \r
- desired == Double.TYPE)\r
- {\r
- return new Double(ScriptRuntime.toNumber(arg));\r
- }\r
- if (desired == ScriptRuntime.ScriptableClass)\r
- return ScriptRuntime.toObject(scope, arg);\r
- if (desired == ScriptRuntime.ObjectClass)\r
- return arg;\r
- \r
- // Note that the long type is not supported; see the javadoc for\r
- // the constructor for this class\r
- throw Context.reportRuntimeError1\r
- ("msg.cant.convert", desired.getName());\r
- }\r
-\r
- /**\r
- * Performs conversions on argument types if needed and\r
- * invokes the underlying Java method or constructor.\r
- * <p>\r
- * Implements Function.call.\r
- *\r
- * @see org.mozilla.javascript.Function#call\r
- * @exception JavaScriptException if the underlying Java method or \r
- * constructor threw an exception\r
- */\r
- public Object call(Context cx, Scriptable scope, Scriptable thisObj,\r
- Object[] args)\r
- throws JavaScriptException\r
- {\r
- if (parmsLength < 0) {\r
- return callVarargs(cx, thisObj, args, false);\r
- }\r
- if (!isStatic) {\r
- // OPT: cache "clazz"?\r
- Class clazz = method != null ? method.getDeclaringClass()\r
- : ctor.getDeclaringClass();\r
- while (!clazz.isInstance(thisObj)) {\r
- thisObj = thisObj.getPrototype();\r
- if (thisObj == null || !useDynamicScope) {\r
- // Couldn't find an object to call this on.\r
- throw NativeGlobal.typeError1\r
- ("msg.incompat.call", functionName, scope);\r
- }\r
- }\r
- }\r
- Object[] invokeArgs;\r
- int i;\r
- if (parmsLength == args.length) {\r
- invokeArgs = args;\r
- // avoid copy loop if no conversions needed\r
- i = (types == null) ? parmsLength : 0;\r
- } else {\r
- invokeArgs = new Object[parmsLength];\r
- i = 0;\r
- }\r
- for (; i < parmsLength; i++) {\r
- Object arg = (i < args.length)\r
- ? args[i]\r
- : Undefined.instance;\r
- if (types != null) {\r
- arg = convertArg(this, arg, types[i]);\r
- }\r
- invokeArgs[i] = arg;\r
- }\r
- try {\r
- Object result = method == null ? ctor.newInstance(invokeArgs)\r
- : doInvoke(thisObj, invokeArgs);\r
- return hasVoidReturn ? Undefined.instance : result;\r
- }\r
- catch (InvocationTargetException e) {\r
- throw JavaScriptException.wrapException(scope, e);\r
- }\r
- catch (IllegalAccessException e) {\r
- throw WrappedException.wrapException(e);\r
- }\r
- catch (InstantiationException e) {\r
- throw WrappedException.wrapException(e);\r
- }\r
- }\r
-\r
- /**\r
- * Performs conversions on argument types if needed and\r
- * invokes the underlying Java method or constructor\r
- * to create a new Scriptable object.\r
- * <p>\r
- * Implements Function.construct.\r
- *\r
- * @param cx the current Context for this thread\r
- * @param scope the scope to execute the function relative to. This\r
- * set to the value returned by getParentScope() except\r
- * when the function is called from a closure.\r
- * @param args arguments to the constructor\r
- * @see org.mozilla.javascript.Function#construct\r
- * @exception JavaScriptException if the underlying Java method or constructor\r
- * threw an exception\r
- */\r
- public Scriptable construct(Context cx, Scriptable scope, Object[] args)\r
- throws JavaScriptException\r
- {\r
- if (method == null || parmsLength == VARARGS_CTOR) {\r
- Scriptable result;\r
- if (method != null) {\r
- result = (Scriptable) callVarargs(cx, null, args, true);\r
- } else {\r
- result = (Scriptable) call(cx, scope, null, args);\r
- }\r
-\r
- if (result.getPrototype() == null)\r
- result.setPrototype(getClassPrototype());\r
- if (result.getParentScope() == null) {\r
- Scriptable parent = getParentScope();\r
- if (result != parent)\r
- result.setParentScope(parent);\r
- }\r
-\r
- return result;\r
- } else if (method != null && !isStatic) {\r
- Scriptable result;\r
- try {\r
- result = (Scriptable) method.getDeclaringClass().newInstance();\r
- } catch (IllegalAccessException e) {\r
- throw WrappedException.wrapException(e);\r
- } catch (InstantiationException e) {\r
- throw WrappedException.wrapException(e);\r
- }\r
-\r
- result.setPrototype(getClassPrototype());\r
- result.setParentScope(getParentScope());\r
-\r
- Object val = call(cx, scope, result, args);\r
- if (val != null && val != Undefined.instance &&\r
- val instanceof Scriptable)\r
- {\r
- return (Scriptable) val;\r
- }\r
- return result;\r
- }\r
-\r
- return super.construct(cx, scope, args);\r
- }\r
- \r
- private final Object doInvoke(Object thisObj, Object[] args) \r
- throws IllegalAccessException, InvocationTargetException\r
- {\r
- Invoker master = invokerMaster;\r
- if (master != null) {\r
- if (invoker == null) {\r
- invoker = master.createInvoker(method, types);\r
- }\r
- try {\r
- return invoker.invoke(thisObj, args);\r
- } catch (RuntimeException e) {\r
- throw new InvocationTargetException(e);\r
- }\r
- } \r
- return method.invoke(thisObj, args);\r
- }\r
-\r
- private Object callVarargs(Context cx, Scriptable thisObj, Object[] args,\r
- boolean inNewExpr)\r
- throws JavaScriptException\r
- {\r
- try {\r
- Object[] invokeArgs;\r
- Object ret;\r
- if (cx.arrayCache.size() > 0) invokeArgs = (Object[])cx.arrayCache.lastElement();\r
- else invokeArgs = new Object[4];\r
- \r
- if (parmsLength == VARARGS_METHOD) {\r
- invokeArgs[0] = cx;\r
- invokeArgs[1] = thisObj;\r
- invokeArgs[2] = args;\r
- invokeArgs[3] = this;\r
- Object result = doInvoke(null, invokeArgs);\r
- ret = hasVoidReturn ? Undefined.instance : result;\r
- } else {\r
- Boolean b = inNewExpr ? Boolean.TRUE : Boolean.FALSE;\r
- invokeArgs[0] = cx;\r
- invokeArgs[1] = args;\r
- invokeArgs[2] = this;\r
- invokeArgs[3] = b;\r
- ret = (method == null)\r
- ? ctor.newInstance(invokeArgs)\r
- : doInvoke(null, invokeArgs);\r
- }\r
- \r
- cx.arrayCache.addElement(invokeArgs);\r
- return ret;\r
- }\r
- catch (InvocationTargetException e) {\r
- Throwable target = e.getTargetException();\r
- if (target instanceof EvaluatorException)\r
- throw (EvaluatorException) target;\r
- if (target instanceof EcmaError)\r
- throw (EcmaError) target;\r
- Scriptable scope = thisObj == null ? this : thisObj;\r
- throw JavaScriptException.wrapException(scope, target);\r
- }\r
- catch (IllegalAccessException e) {\r
- throw WrappedException.wrapException(e);\r
- }\r
- catch (InstantiationException e) {\r
- throw WrappedException.wrapException(e);\r
- }\r
- }\r
- \r
- boolean isVarArgsMethod() { \r
- return parmsLength == VARARGS_METHOD;\r
- }\r
-\r
- boolean isVarArgsConstructor() { \r
- return parmsLength == VARARGS_CTOR;\r
- }\r
- \r
- static void setCachingEnabled(boolean enabled) {\r
- if (!enabled) {\r
- methodsCache = null;\r
- invokerMaster = null;\r
- } else if (invokerMaster == null) {\r
- invokerMaster = newInvokerMaster();\r
- }\r
- }\r
-\r
- /** Get default master implementation or null if not available */\r
- private static Invoker newInvokerMaster() {\r
- /*\r
- try {\r
- Class cl = ScriptRuntime.loadClassName(INVOKER_MASTER_CLASS);\r
- return (Invoker)cl.newInstance();\r
- }\r
- catch (ClassNotFoundException ex) {}\r
- catch (IllegalAccessException ex) {}\r
- catch (InstantiationException ex) {}\r
- catch (SecurityException ex) {}\r
- */\r
- return null;\r
- }\r
-\r
- private static final String \r
- INVOKER_MASTER_CLASS = "org.mozilla.javascript.optimizer.InvokerImpl";\r
-\r
- static Invoker invokerMaster = newInvokerMaster();\r
- \r
- private static final short VARARGS_METHOD = -1;\r
- private static final short VARARGS_CTOR = -2;\r
- \r
- private static boolean sawSecurityException;\r
-\r
- static Method[] methodsCache;\r
-\r
- Method method;\r
- Constructor ctor;\r
- private Class[] types;\r
- Invoker invoker;\r
- private short parmsLength;\r
- private short lengthPropertyValue;\r
- private boolean hasVoidReturn;\r
- private boolean isStatic;\r
- private boolean useDynamicScope;\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-/**\r
- * This class allows the creation of nodes, and follows the Factory pattern.\r
- *\r
- * @see Node\r
- * @author Mike McCabe\r
- * @author Norris Boyd\r
- */\r
-public class IRFactory {\r
- \r
- public IRFactory(TokenStream ts, Scriptable scope) {\r
- this.ts = ts;\r
- this.scope = scope;\r
- }\r
-\r
- /**\r
- * Script (for associating file/url names with toplevel scripts.)\r
- */\r
- public Object createScript(Object body, String sourceName, \r
- int baseLineno, int endLineno, Object source)\r
- {\r
- Node result = new Node(TokenStream.SCRIPT, sourceName);\r
- Node children = ((Node) body).getFirstChild();\r
- if (children != null)\r
- result.addChildrenToBack(children);\r
- result.putProp(Node.SOURCENAME_PROP, sourceName);\r
- result.putProp(Node.BASE_LINENO_PROP, new Integer(baseLineno));\r
- result.putProp(Node.END_LINENO_PROP, new Integer(endLineno));\r
- if (source != null)\r
- result.putProp(Node.SOURCE_PROP, source);\r
- return result;\r
- }\r
-\r
- /**\r
- * Leaf\r
- */\r
- public Object createLeaf(int nodeType) {\r
- return new Node(nodeType);\r
- }\r
-\r
- public Object createLeaf(int nodeType, String id) {\r
- return new Node(nodeType, id);\r
- }\r
-\r
- public Object createLeaf(int nodeType, int nodeOp) {\r
- return new Node(nodeType, new Integer(nodeOp));\r
- }\r
-\r
- /**\r
- * Statement leaf nodes.\r
- */\r
-\r
- public Object createSwitch(int lineno) {\r
- return new Node(TokenStream.SWITCH, new Integer(lineno));\r
- }\r
-\r
- public Object createVariables(int lineno) {\r
- return new Node(TokenStream.VAR, new Integer(lineno));\r
- }\r
-\r
- public Object createExprStatement(Object expr, int lineno) {\r
- return new Node(TokenStream.EXPRSTMT, (Node) expr, new Integer(lineno));\r
- }\r
-\r
- /**\r
- * Name\r
- */\r
- public Object createName(String name) {\r
- return new Node(TokenStream.NAME, name);\r
- }\r
-\r
- /**\r
- * String (for literals)\r
- */\r
- public Object createString(String string) {\r
- return new Node(TokenStream.STRING, string);\r
- }\r
-\r
- /**\r
- * Number (for literals)\r
- */\r
- public Object createNumber(Number number) {\r
- return new Node(TokenStream.NUMBER, number);\r
- }\r
-\r
- /**\r
- * Catch clause of try/catch/finally\r
- * @param varName the name of the variable to bind to the exception\r
- * @param catchCond the condition under which to catch the exception.\r
- * May be null if no condition is given.\r
- * @param stmts the statements in the catch clause\r
- * @param lineno the starting line number of the catch clause\r
- */\r
- public Object createCatch(String varName, Object catchCond, Object stmts,\r
- int lineno)\r
- {\r
- if (catchCond == null)\r
- catchCond = new Node(TokenStream.PRIMARY, \r
- new Integer(TokenStream.TRUE));\r
- Node result = new Node(TokenStream.CATCH, (Node)createName(varName), \r
- (Node)catchCond, (Node)stmts);\r
- result.setDatum(new Integer(lineno));\r
- return result;\r
- }\r
- \r
- /**\r
- * Throw\r
- */\r
- public Object createThrow(Object expr, int lineno) {\r
- return new Node(TokenStream.THROW, (Node)expr, new Integer(lineno));\r
- }\r
-\r
- /**\r
- * Return\r
- */\r
- public Object createReturn(Object expr, int lineno) {\r
- return expr == null\r
- ? new Node(TokenStream.RETURN, new Integer(lineno))\r
- : new Node(TokenStream.RETURN, (Node)expr, new Integer(lineno));\r
- }\r
-\r
- /**\r
- * Assert\r
- */\r
- public Object createAssert(Object expr, int lineno) {\r
- return expr == null\r
- ? new Node(TokenStream.ASSERT, new Integer(lineno))\r
- : new Node(TokenStream.ASSERT, (Node)expr, new Integer(lineno));\r
- }\r
-\r
- /**\r
- * Label\r
- */\r
- public Object createLabel(String label, int lineno) {\r
- Node result = new Node(TokenStream.LABEL, new Integer(lineno));\r
- Node name = new Node(TokenStream.NAME, label);\r
- result.addChildToBack(name);\r
- return result;\r
- }\r
-\r
- /**\r
- * Break (possibly labeled)\r
- */\r
- public Object createBreak(String label, int lineno) {\r
- Node result = new Node(TokenStream.BREAK, new Integer(lineno));\r
- if (label == null) {\r
- return result;\r
- } else {\r
- Node name = new Node(TokenStream.NAME, label);\r
- result.addChildToBack(name);\r
- return result;\r
- }\r
- }\r
-\r
- /**\r
- * Continue (possibly labeled)\r
- */\r
- public Object createContinue(String label, int lineno) {\r
- Node result = new Node(TokenStream.CONTINUE, new Integer(lineno));\r
- if (label == null) {\r
- return result;\r
- } else {\r
- Node name = new Node(TokenStream.NAME, label);\r
- result.addChildToBack(name);\r
- return result;\r
- }\r
- }\r
-\r
- /**\r
- * Statement block\r
- * Creates the empty statement block\r
- * Must make subsequent calls to add statements to the node\r
- */\r
- public Object createBlock(int lineno) {\r
- return new Node(TokenStream.BLOCK, new Integer(lineno));\r
- }\r
- \r
- public Object createFunctionNode(String name, Object args, \r
- Object statements) \r
- {\r
- if (name == null)\r
- name = "";\r
- return new FunctionNode(name, (Node) args, (Node) statements);\r
- }\r
-\r
- public Object createFunction(String name, Object args, Object statements,\r
- String sourceName, int baseLineno, \r
- int endLineno, Object source,\r
- boolean isExpr)\r
- {\r
- FunctionNode f = (FunctionNode) createFunctionNode(name, args, \r
- statements);\r
- f.setFunctionType(isExpr ? FunctionNode.FUNCTION_EXPRESSION\r
- : FunctionNode.FUNCTION_STATEMENT);\r
- f.putProp(Node.SOURCENAME_PROP, sourceName);\r
- f.putProp(Node.BASE_LINENO_PROP, new Integer(baseLineno));\r
- f.putProp(Node.END_LINENO_PROP, new Integer(endLineno));\r
- if (source != null)\r
- f.putProp(Node.SOURCE_PROP, source);\r
- Node result = new Node(TokenStream.FUNCTION, name);\r
- result.putProp(Node.FUNCTION_PROP, f);\r
- return result;\r
- }\r
- \r
- public void setFunctionExpressionStatement(Object o) {\r
- Node n = (Node) o;\r
- FunctionNode f = (FunctionNode) n.getProp(Node.FUNCTION_PROP);\r
- f.setFunctionType(FunctionNode.FUNCTION_EXPRESSION_STATEMENT);\r
- }\r
-\r
- /**\r
- * Add a child to the back of the given node. This function\r
- * breaks the Factory abstraction, but it removes a requirement\r
- * from implementors of Node.\r
- */\r
- public void addChildToBack(Object parent, Object child) {\r
- ((Node)parent).addChildToBack((Node)child);\r
- }\r
-\r
- /**\r
- * While\r
- */\r
- public Object createWhile(Object cond, Object body, int lineno) {\r
- // Just add a GOTO to the condition in the do..while\r
- Node result = (Node) createDoWhile(body, cond, lineno);\r
- Node condTarget = (Node) result.getProp(Node.CONTINUE_PROP);\r
- Node GOTO = new Node(TokenStream.GOTO);\r
- GOTO.putProp(Node.TARGET_PROP, condTarget);\r
- result.addChildToFront(GOTO);\r
- return result;\r
- }\r
-\r
- /**\r
- * DoWhile\r
- */\r
- public Object createDoWhile(Object body, Object cond, int lineno) {\r
- Node result = new Node(TokenStream.LOOP, new Integer(lineno));\r
- Node bodyTarget = new Node(TokenStream.TARGET);\r
- Node condTarget = new Node(TokenStream.TARGET);\r
- Node IFEQ = new Node(TokenStream.IFEQ, (Node)cond);\r
- IFEQ.putProp(Node.TARGET_PROP, bodyTarget);\r
- Node breakTarget = new Node(TokenStream.TARGET);\r
-\r
- result.addChildToBack(bodyTarget);\r
- result.addChildrenToBack((Node)body);\r
- result.addChildToBack(condTarget);\r
- result.addChildToBack(IFEQ);\r
- result.addChildToBack(breakTarget);\r
-\r
- result.putProp(Node.BREAK_PROP, breakTarget);\r
- result.putProp(Node.CONTINUE_PROP, condTarget);\r
-\r
- return result;\r
- }\r
-\r
- /**\r
- * For\r
- */\r
- public Object createFor(Object init, Object test, Object incr,\r
- Object body, int lineno)\r
- {\r
- if (((Node) test).getType() == TokenStream.VOID) {\r
- test = new Node(TokenStream.PRIMARY, \r
- new Integer(TokenStream.TRUE));\r
- }\r
- Node result = (Node)createWhile(test, body, lineno);\r
- Node initNode = (Node) init;\r
- if (initNode.getType() != TokenStream.VOID) {\r
- if (initNode.getType() != TokenStream.VAR)\r
- initNode = new Node(TokenStream.POP, initNode);\r
- result.addChildToFront(initNode);\r
- }\r
- Node condTarget = (Node)result.getProp(Node.CONTINUE_PROP);\r
- Node incrTarget = new Node(TokenStream.TARGET);\r
- result.addChildBefore(incrTarget, condTarget);\r
- if (((Node) incr).getType() != TokenStream.VOID) {\r
- incr = createUnary(TokenStream.POP, incr);\r
- result.addChildAfter((Node)incr, incrTarget);\r
- }\r
- result.putProp(Node.CONTINUE_PROP, incrTarget);\r
- return result;\r
- }\r
-\r
- /**\r
- * For .. In\r
- *\r
- */\r
- public Object createForIn(Object lhs, Object obj, Object body, int lineno) {\r
- String name;\r
- Node lhsNode = (Node) lhs;\r
- Node objNode = (Node) obj;\r
- int type = lhsNode.getType();\r
-\r
- Node lvalue = lhsNode;\r
- switch (type) {\r
-\r
- case TokenStream.NAME:\r
- case TokenStream.GETPROP:\r
- case TokenStream.GETELEM:\r
- break;\r
-\r
- case TokenStream.VAR:\r
- /*\r
- * check that there was only one variable given.\r
- * we can't do this in the parser, because then the\r
- * parser would have to know something about the\r
- * 'init' node of the for-in loop.\r
- */\r
- Node lastChild = lhsNode.getLastChild();\r
- if (lhsNode.getFirstChild() != lastChild) {\r
- reportError("msg.mult.index");\r
- }\r
- lvalue = new Node(TokenStream.NAME, lastChild.getString());\r
- break;\r
-\r
- default:\r
- reportError("msg.bad.for.in.lhs");\r
- return objNode;\r
- }\r
-\r
- Node init = new Node(TokenStream.ENUMINIT, objNode);\r
- Node next = new Node(TokenStream.ENUMNEXT);\r
- next.putProp(Node.ENUM_PROP, init);\r
- Node temp = createNewTemp(next);\r
- Node cond = new Node(TokenStream.EQOP, new Integer(TokenStream.NE));\r
- cond.addChildToBack(temp);\r
- cond.addChildToBack(new Node(TokenStream.PRIMARY,\r
- new Integer(TokenStream.NULL)));\r
- Node newBody = new Node(TokenStream.BLOCK);\r
- Node assign = (Node) createAssignment(TokenStream.NOP, lvalue,\r
- createUseTemp(temp), null,\r
- false);\r
- newBody.addChildToBack(new Node(TokenStream.POP, assign));\r
- newBody.addChildToBack((Node) body);\r
- Node result = (Node) createWhile(cond, newBody, lineno);\r
-\r
- result.addChildToFront(init);\r
- if (type == TokenStream.VAR)\r
- result.addChildToFront(lhsNode);\r
-\r
- Node done = new Node(TokenStream.ENUMDONE);\r
- done.putProp(Node.ENUM_PROP, init);\r
- result.addChildToBack(done);\r
-\r
- return result;\r
- }\r
-\r
- /**\r
- * Try/Catch/Finally\r
- *\r
- * The IRFactory tries to express as much as possible in the tree;\r
- * the responsibilities remaining for Codegen are to add the Java\r
- * handlers: (Either (but not both) of TARGET and FINALLY might not\r
- * be defined)\r
-\r
- * - a catch handler for javascript exceptions that unwraps the\r
- * exception onto the stack and GOTOes to the catch target -\r
- * TARGET_PROP in the try node.\r
-\r
- * - a finally handler that catches any exception, stores it to a\r
- * temporary, and JSRs to the finally target - FINALLY_PROP in the\r
- * try node - before re-throwing the exception.\r
-\r
- * ... and a goto to GOTO around these handlers.\r
- */\r
- public Object createTryCatchFinally(Object tryblock, Object catchblocks,\r
- Object finallyblock, int lineno)\r
- {\r
- Node trynode = (Node)tryblock;\r
-\r
- // short circuit\r
- if (trynode.getType() == TokenStream.BLOCK && !trynode.hasChildren())\r
- return trynode;\r
-\r
- Node pn = new Node(TokenStream.TRY, trynode, new Integer(lineno));\r
- Node catchNodes = (Node)catchblocks;\r
- boolean hasCatch = catchNodes.hasChildren();\r
- boolean hasFinally = false;\r
- Node finallyNode = null;\r
- Node finallyTarget = null;\r
- if (finallyblock != null) {\r
- finallyNode = (Node)finallyblock;\r
- hasFinally = (finallyNode.getType() != TokenStream.BLOCK\r
- || finallyNode.hasChildren());\r
- if (hasFinally) {\r
- // make a TARGET for the finally that the tcf node knows about\r
- finallyTarget = new Node(TokenStream.TARGET);\r
- pn.putProp(Node.FINALLY_PROP, finallyTarget);\r
-\r
- // add jsr finally to the try block\r
- Node jsrFinally = new Node(TokenStream.JSR);\r
- jsrFinally.putProp(Node.TARGET_PROP, finallyTarget);\r
- pn.addChildToBack(jsrFinally);\r
- }\r
- }\r
-\r
- // short circuit\r
- if (!hasFinally && !hasCatch) // bc finally might be an empty block...\r
- return trynode;\r
-\r
- Node endTarget = new Node(TokenStream.TARGET);\r
- Node GOTOToEnd = new Node(TokenStream.GOTO);\r
- GOTOToEnd.putProp(Node.TARGET_PROP, endTarget);\r
- pn.addChildToBack(GOTOToEnd);\r
- \r
- if (hasCatch) {\r
- /*\r
- *\r
- Given\r
- \r
- try {\r
- throw 3;\r
- } catch (e: e instanceof Object) {\r
- print("object");\r
- } catch (e2) {\r
- print(e2);\r
- }\r
-\r
- rewrite as\r
-\r
- try {\r
- throw 3;\r
- } catch (x) {\r
- o = newScope();\r
- o.e = x;\r
- with (o) {\r
- if (e instanceof Object) {\r
- print("object");\r
- }\r
- }\r
- o2 = newScope();\r
- o2.e2 = x;\r
- with (o2) {\r
- if (true) {\r
- print(e2);\r
- }\r
- }\r
- }\r
- */\r
- // make a TARGET for the catch that the tcf node knows about\r
- Node catchTarget = new Node(TokenStream.TARGET);\r
- pn.putProp(Node.TARGET_PROP, catchTarget);\r
- // mark it\r
- pn.addChildToBack(catchTarget);\r
- \r
- // get the exception object and store it in a temp\r
- Node exn = createNewLocal(new Node(TokenStream.VOID));\r
- pn.addChildToBack(new Node(TokenStream.POP, exn));\r
- \r
- Node endCatch = new Node(TokenStream.TARGET);\r
-\r
- // add [jsr finally?] goto end to each catch block\r
- // expects catchNode children to be (cond block) pairs.\r
- Node cb = catchNodes.getFirstChild();\r
- while (cb != null) {\r
- Node catchStmt = new Node(TokenStream.BLOCK);\r
- int catchLineNo = ((Integer)cb.getDatum()).intValue();\r
- \r
- Node name = cb.getFirstChild();\r
- Node cond = name.getNextSibling();\r
- Node catchBlock = cond.getNextSibling();\r
- cb.removeChild(name);\r
- cb.removeChild(cond);\r
- cb.removeChild(catchBlock);\r
- \r
- Node newScope = createNewLocal(new Node(TokenStream.NEWSCOPE));\r
- Node initScope = new Node(TokenStream.SETPROP, newScope, \r
- new Node(TokenStream.STRING, \r
- name.getString()), \r
- createUseLocal(exn));\r
- catchStmt.addChildToBack(new Node(TokenStream.POP, initScope));\r
- \r
- catchBlock.addChildToBack(new Node(TokenStream.LEAVEWITH));\r
- Node GOTOToEndCatch = new Node(TokenStream.GOTO);\r
- GOTOToEndCatch.putProp(Node.TARGET_PROP, endCatch);\r
- catchBlock.addChildToBack(GOTOToEndCatch);\r
- \r
- Node ifStmt = (Node) createIf(cond, catchBlock, null, catchLineNo);\r
- // Try..catch produces "with" code in order to limit \r
- // the scope of the exception object.\r
- // OPT: We should be able to figure out the correct\r
- // scoping at compile-time and avoid the\r
- // runtime overhead.\r
- Node withStmt = (Node) createWith(createUseLocal(newScope), \r
- ifStmt, catchLineNo);\r
- catchStmt.addChildToBack(withStmt);\r
- \r
- pn.addChildToBack(catchStmt);\r
- \r
- // move to next cb \r
- cb = cb.getNextSibling();\r
- }\r
- \r
- // Generate code to rethrow if no catch clause was executed\r
- Node rethrow = new Node(TokenStream.THROW, createUseLocal(exn));\r
- pn.addChildToBack(rethrow);\r
-\r
- pn.addChildToBack(endCatch);\r
- // add a JSR finally if needed\r
- if (hasFinally) {\r
- Node jsrFinally = new Node(TokenStream.JSR);\r
- jsrFinally.putProp(Node.TARGET_PROP, finallyTarget);\r
- pn.addChildToBack(jsrFinally);\r
- Node GOTO = new Node(TokenStream.GOTO);\r
- GOTO.putProp(Node.TARGET_PROP, endTarget);\r
- pn.addChildToBack(GOTO);\r
- }\r
- }\r
-\r
- if (hasFinally) {\r
- pn.addChildToBack(finallyTarget);\r
- Node returnTemp = createNewLocal(new Node(TokenStream.VOID));\r
- Node popAndMake = new Node(TokenStream.POP, returnTemp);\r
- pn.addChildToBack(popAndMake);\r
- pn.addChildToBack(finallyNode);\r
- Node ret = createUseLocal(returnTemp);\r
-\r
- // add the magic prop that makes it output a RET\r
- ret.putProp(Node.TARGET_PROP, Boolean.TRUE);\r
- pn.addChildToBack(ret);\r
- }\r
- pn.addChildToBack(endTarget);\r
- return pn;\r
- }\r
-\r
- /**\r
- * Throw, Return, Label, Break and Continue are defined in ASTFactory.\r
- */\r
-\r
- /**\r
- * With\r
- */\r
- public Object createWith(Object obj, Object body, int lineno) {\r
- Node result = new Node(TokenStream.BLOCK, new Integer(lineno));\r
- result.addChildToBack(new Node(TokenStream.ENTERWITH, (Node)obj));\r
- Node bodyNode = new Node(TokenStream.WITH, (Node) body,\r
- new Integer(lineno));\r
- result.addChildrenToBack(bodyNode);\r
- result.addChildToBack(new Node(TokenStream.LEAVEWITH));\r
- return result;\r
- }\r
-\r
- /**\r
- * Array Literal\r
- * <BR>createArrayLiteral rewrites its argument as array creation\r
- * plus a series of array element entries, so later compiler\r
- * stages don't need to know about array literals.\r
- */\r
- public Object createArrayLiteral(Object obj) {\r
- Node array;\r
- Node result;\r
- array = result = new Node(TokenStream.NEW,\r
- new Node(TokenStream.NAME, "Array"));\r
- Node temp = createNewTemp(result);\r
- result = temp;\r
-\r
- java.util.Enumeration children = ((Node) obj).getChildIterator();\r
-\r
- Node elem = null;\r
- int i = 0;\r
- while (children.hasMoreElements()) {\r
- elem = (Node) children.nextElement();\r
- if (elem.getType() == TokenStream.PRIMARY &&\r
- elem.getInt() == TokenStream.UNDEFINED)\r
- {\r
- i++;\r
- continue;\r
- }\r
- Node addelem = new Node(TokenStream.SETELEM, createUseTemp(temp),\r
- new Node(TokenStream.NUMBER,\r
- new Integer(i)),\r
- elem);\r
- i++;\r
- result = new Node(TokenStream.COMMA, result, addelem);\r
- }\r
-\r
- /*\r
- * If the version is 120, then new Array(4) means create a new\r
- * array with 4 as the first element. In this case, we might\r
- * need to explicitly check against trailing undefined\r
- * elements in the array literal, and set the length manually\r
- * if these occur. Otherwise, we can add an argument to the\r
- * node specifying new Array() to provide the array length.\r
- * (Which will make Array optimizations involving allocating a\r
- * Java array to back the javascript array work better.)\r
- */\r
- if (Context.getContext().getLanguageVersion() == Context.VERSION_1_2) {\r
- /* When last array element is empty, we need to set the\r
- * length explicitly, because we can't depend on SETELEM\r
- * to do it for us - because empty [,,] array elements\r
- * never set anything at all. */\r
- if (elem != null &&\r
- elem.getType() == TokenStream.PRIMARY &&\r
- elem.getInt() == TokenStream.UNDEFINED)\r
- {\r
- Node setlength = new Node(TokenStream.SETPROP,\r
- createUseTemp(temp),\r
- new Node(TokenStream.STRING,\r
- "length"),\r
- new Node(TokenStream.NUMBER,\r
- new Integer(i)));\r
- result = new Node(TokenStream.COMMA, result, setlength);\r
- }\r
- } else {\r
- array.addChildToBack(new Node(TokenStream.NUMBER,\r
- new Integer(i)));\r
- }\r
- return new Node(TokenStream.COMMA, result, createUseTemp(temp));\r
- }\r
-\r
- /**\r
- * Object Literals\r
- * <BR> createObjectLiteral rewrites its argument as object\r
- * creation plus object property entries, so later compiler\r
- * stages don't need to know about object literals.\r
- */\r
- public Object createObjectLiteral(Object obj) {\r
- Node result = new Node(TokenStream.NEW, new Node(TokenStream.NAME,\r
- "Object"));\r
- Node temp = createNewTemp(result);\r
- result = temp;\r
-\r
- java.util.Enumeration children = ((Node) obj).getChildIterator();\r
-\r
- while (children.hasMoreElements()) {\r
- Node elem = (Node)children.nextElement();\r
-\r
- int op = (elem.getType() == TokenStream.NAME)\r
- ? TokenStream.SETPROP\r
- : TokenStream.SETELEM;\r
- Node addelem = new Node(op, createUseTemp(temp),\r
- elem, (Node)children.nextElement());\r
- result = new Node(TokenStream.COMMA, result, addelem);\r
- }\r
- return new Node(TokenStream.COMMA, result, createUseTemp(temp));\r
- }\r
-\r
- /**\r
- * Regular expressions\r
- */\r
- public Object createRegExp(String string, String flags) {\r
- return flags.length() == 0\r
- ? new Node(TokenStream.OBJECT,\r
- new Node(TokenStream.STRING, string))\r
- : new Node(TokenStream.OBJECT,\r
- new Node(TokenStream.STRING, string),\r
- new Node(TokenStream.STRING, flags));\r
- }\r
-\r
- /**\r
- * If statement\r
- */\r
- public Object createIf(Object cond, Object ifTrue, Object ifFalse,\r
- int lineno)\r
- {\r
- Node result = new Node(TokenStream.BLOCK, new Integer(lineno));\r
- Node ifNotTarget = new Node(TokenStream.TARGET);\r
- Node IFNE = new Node(TokenStream.IFNE, (Node) cond);\r
- IFNE.putProp(Node.TARGET_PROP, ifNotTarget);\r
-\r
- result.addChildToBack(IFNE);\r
- result.addChildrenToBack((Node)ifTrue);\r
-\r
- if (ifFalse != null) {\r
- Node GOTOToEnd = new Node(TokenStream.GOTO);\r
- Node endTarget = new Node(TokenStream.TARGET);\r
- GOTOToEnd.putProp(Node.TARGET_PROP, endTarget);\r
- result.addChildToBack(GOTOToEnd);\r
- result.addChildToBack(ifNotTarget);\r
- result.addChildrenToBack((Node)ifFalse);\r
- result.addChildToBack(endTarget);\r
- } else {\r
- result.addChildToBack(ifNotTarget);\r
- }\r
-\r
- return result;\r
- }\r
-\r
- public Object createTernary(Object cond, Object ifTrue, Object ifFalse) {\r
- return createIf(cond, ifTrue, ifFalse, -1);\r
- }\r
-\r
- /**\r
- * Unary\r
- */\r
- public Object createUnary(int nodeType, Object child) {\r
- Node childNode = (Node) child;\r
- if (nodeType == TokenStream.DELPROP) {\r
- int childType = childNode.getType();\r
- Node left;\r
- Node right;\r
- if (childType == TokenStream.NAME) {\r
- // Transform Delete(Name "a")\r
- // to Delete(Bind("a"), String("a"))\r
- childNode.setType(TokenStream.BINDNAME);\r
- left = childNode;\r
- right = childNode.cloneNode();\r
- right.setType(TokenStream.STRING);\r
- } else if (childType == TokenStream.GETPROP ||\r
- childType == TokenStream.GETELEM)\r
- {\r
- left = childNode.getFirstChild();\r
- right = childNode.getLastChild();\r
- childNode.removeChild(left);\r
- childNode.removeChild(right);\r
- } else {\r
- return new Node(TokenStream.PRIMARY,\r
- new Integer(TokenStream.TRUE));\r
- }\r
- return new Node(nodeType, left, right);\r
- }\r
- return new Node(nodeType, childNode);\r
- }\r
-\r
- public Object createUnary(int nodeType, int nodeOp, Object child) {\r
- Node childNode = (Node) child;\r
- int childType = childNode.getType();\r
- if (nodeOp == TokenStream.TYPEOF &&\r
- childType == TokenStream.NAME)\r
- {\r
- childNode.setType(TokenStream.TYPEOF);\r
- return childNode;\r
- }\r
-\r
- if (nodeType == TokenStream.INC || nodeType == TokenStream.DEC) {\r
-\r
- if (!hasSideEffects(childNode)\r
- && (nodeOp == TokenStream.POST)\r
- && (childType == TokenStream.NAME \r
- || childType == TokenStream.GETPROP\r
- || childType == TokenStream.GETELEM))\r
- {\r
- // if it's not a LHS type, createAssignment (below) will throw\r
- // an exception.\r
- return new Node(nodeType, childNode);\r
- }\r
-\r
- /*\r
- * Transform INC/DEC ops to +=1, -=1,\r
- * expecting later optimization of all +/-=1 cases to INC, DEC.\r
- */\r
- // we have to use Double for now, because\r
- // 0.0 and 1.0 are stored as dconst_[01],\r
- // and using a Float creates a stack mismatch.\r
- Node rhs = (Node) createNumber(new Double(1.0));\r
-\r
- return createAssignment(nodeType == TokenStream.INC\r
- ? TokenStream.ADD\r
- : TokenStream.SUB,\r
- childNode,\r
- rhs,\r
- ScriptRuntime.NumberClass,\r
- nodeOp == TokenStream.POST);\r
- }\r
-\r
- Node result = new Node(nodeType, new Integer(nodeOp));\r
- result.addChildToBack((Node)child);\r
- return result;\r
- }\r
-\r
- /**\r
- * Binary\r
- */\r
- public Object createBinary(int nodeType, Object left, Object right) {\r
- Node temp;\r
- switch (nodeType) {\r
-\r
- case TokenStream.DOT:\r
- nodeType = TokenStream.GETPROP;\r
- Node idNode = (Node) right;\r
- idNode.setType(TokenStream.STRING);\r
- String id = idNode.getString();\r
- if (id.equals("__proto__") || id.equals("__parent__")) {\r
- Node result = new Node(nodeType, (Node) left);\r
- result.putProp(Node.SPECIAL_PROP_PROP, id);\r
- return result;\r
- }\r
- break;\r
-\r
- case TokenStream.LB:\r
- // OPT: could optimize to GETPROP iff string can't be a number\r
- nodeType = TokenStream.GETELEM;\r
- break;\r
-/*\r
- case TokenStream.AND:\r
- temp = createNewTemp((Node) left);\r
- return createTernary(temp, right, createUseTemp(temp));\r
-\r
- case TokenStream.OR:\r
- temp = createNewTemp((Node) left);\r
- return createTernary(temp, createUseTemp(temp), right);\r
-*/ \r
- }\r
- return new Node(nodeType, (Node)left, (Node)right);\r
- }\r
-\r
- public Object createBinary(int nodeType, int nodeOp, Object left,\r
- Object right)\r
- {\r
- if (nodeType == TokenStream.ASSIGN) {\r
- return createAssignment(nodeOp, (Node) left, (Node) right,\r
- null, false);\r
- }\r
- return new Node(nodeType, (Node) left, (Node) right,\r
- new Integer(nodeOp));\r
- }\r
-\r
- public Object createAssignment(int nodeOp, Node left, Node right,\r
- Class convert, boolean postfix)\r
- {\r
- int nodeType = left.getType();\r
- String idString;\r
- Node id = null;\r
- switch (nodeType) {\r
- case TokenStream.NAME:\r
- return createSetName(nodeOp, left, right, convert, postfix);\r
-\r
- case TokenStream.GETPROP:\r
- idString = (String) left.getProp(Node.SPECIAL_PROP_PROP);\r
- if (idString != null)\r
- id = new Node(TokenStream.STRING, idString);\r
- /* fall through */\r
- case TokenStream.GETELEM:\r
- if (id == null)\r
- id = left.getLastChild();\r
- return createSetProp(nodeType, nodeOp, left.getFirstChild(),\r
- id, right, convert, postfix);\r
- default:\r
- // TODO: This should be a ReferenceError--but that's a runtime \r
- // exception. Should we compile an exception into the code?\r
- reportError("msg.bad.lhs.assign");\r
- return left;\r
- }\r
- }\r
-\r
- private Node createConvert(Class toType, Node expr) {\r
- if (toType == null)\r
- return expr;\r
- Node result = new Node(TokenStream.CONVERT, expr);\r
- result.putProp(Node.TYPE_PROP, ScriptRuntime.NumberClass);\r
- return result;\r
- }\r
-\r
- private Object createSetName(int nodeOp, Node left, Node right,\r
- Class convert, boolean postfix)\r
- {\r
- if (nodeOp == TokenStream.NOP) {\r
- left.setType(TokenStream.BINDNAME);\r
- return new Node(TokenStream.SETNAME, left, right);\r
- }\r
-\r
- String s = left.getString();\r
-\r
- if (s.equals("__proto__") || s.equals("__parent__")) {\r
- Node result = new Node(TokenStream.SETPROP, left, right);\r
- result.putProp(Node.SPECIAL_PROP_PROP, s);\r
- return result;\r
- }\r
-\r
- Node opLeft = new Node(TokenStream.NAME, s);\r
- if (convert != null)\r
- opLeft = createConvert(convert, opLeft);\r
- if (postfix)\r
- opLeft = createNewTemp(opLeft);\r
- Node op = new Node(nodeOp, opLeft, right);\r
-\r
- Node lvalueLeft = new Node(TokenStream.BINDNAME, s);\r
- Node result = new Node(TokenStream.SETNAME, lvalueLeft, op);\r
- if (postfix) {\r
- result = new Node(TokenStream.COMMA, result,\r
- createUseTemp(opLeft));\r
- }\r
- return result;\r
- }\r
-\r
- public Node createNewTemp(Node n) {\r
- int type = n.getType();\r
- if (type == TokenStream.STRING || type == TokenStream.NUMBER) {\r
- // Optimization: clone these values rather than storing\r
- // and loading from a temp\r
- return n;\r
- }\r
- Node result = new Node(TokenStream.NEWTEMP, n);\r
- return result;\r
- }\r
-\r
- public Node createUseTemp(Node newTemp) {\r
- int type = newTemp.getType();\r
- if (type == TokenStream.NEWTEMP) {\r
- Node result = new Node(TokenStream.USETEMP);\r
- result.putProp(Node.TEMP_PROP, newTemp);\r
- Integer n = (Integer) newTemp.getProp(Node.USES_PROP);\r
- if (n == null) {\r
- n = new Integer(1);\r
- } else {\r
- if (n.intValue() < Integer.MAX_VALUE)\r
- n = new Integer(n.intValue() + 1);\r
- }\r
- newTemp.putProp(Node.USES_PROP, n);\r
- return result;\r
- }\r
- return newTemp.cloneNode();\r
- }\r
-\r
- public Node createNewLocal(Node n) {\r
- Node result = new Node(TokenStream.NEWLOCAL, n);\r
- return result;\r
- }\r
-\r
- public Node createUseLocal(Node newLocal) {\r
- int type = newLocal.getType();\r
- if (type == TokenStream.NEWLOCAL) {\r
- Node result = new Node(TokenStream.USELOCAL);\r
- result.putProp(Node.LOCAL_PROP, newLocal);\r
- return result;\r
- }\r
- return newLocal.cloneNode(); // what's this path for ?\r
- }\r
-\r
- public static boolean hasSideEffects(Node exprTree) {\r
- switch (exprTree.getType()) {\r
- case TokenStream.INC:\r
- case TokenStream.DEC:\r
- case TokenStream.SETPROP:\r
- case TokenStream.SETELEM:\r
- case TokenStream.SETNAME:\r
- case TokenStream.CALL:\r
- case TokenStream.NEW:\r
- return true;\r
- default:\r
- Node child = exprTree.getFirstChild();\r
- while (child != null) {\r
- if (hasSideEffects(child))\r
- return true;\r
- else\r
- child = child.getNextSibling();\r
- }\r
- break;\r
- }\r
- return false;\r
- }\r
-\r
- private Node createSetProp(int nodeType, int nodeOp, Node obj, Node id,\r
- Node expr, Class convert, boolean postfix)\r
- {\r
- int type = nodeType == TokenStream.GETPROP\r
- ? TokenStream.SETPROP\r
- : TokenStream.SETELEM;\r
-\r
- Object datum = id.getDatum();\r
- if (type == TokenStream.SETPROP && datum != null &&\r
- datum instanceof String)\r
- {\r
- String s = (String) datum;\r
- if (s.equals("__proto__") || s.equals("__parent__")) {\r
- Node result = new Node(type, obj, expr);\r
- result.putProp(Node.SPECIAL_PROP_PROP, s);\r
- return result;\r
- }\r
- }\r
-\r
- if (nodeOp == TokenStream.NOP)\r
- return new Node(type, obj, id, expr);\r
-/*\r
-* If the RHS expression could modify the LHS we have\r
-* to construct a temporary to hold the LHS context\r
-* prior to running the expression. Ditto, if the id\r
-* expression has side-effects.\r
-*\r
-* XXX If the hasSideEffects tests take too long, we\r
-* could make this an optimizer-only transform\r
-* and always do the temp assignment otherwise.\r
-*\r
-*/\r
- Node tmp1, tmp2, opLeft;\r
- if (hasSideEffects(expr)\r
- || hasSideEffects(id)\r
- || (obj.getType() != TokenStream.NAME)) {\r
- tmp1 = createNewTemp(obj);\r
- Node useTmp1 = createUseTemp(tmp1);\r
-\r
- tmp2 = createNewTemp(id);\r
- Node useTmp2 = createUseTemp(tmp2);\r
-\r
- opLeft = new Node(nodeType, useTmp1, useTmp2);\r
- } else {\r
- tmp1 = obj.cloneNode();\r
- tmp2 = id.cloneNode();\r
- opLeft = new Node(nodeType, obj, id);\r
- }\r
-\r
- if (convert != null)\r
- opLeft = createConvert(convert, opLeft);\r
- if (postfix)\r
- opLeft = createNewTemp(opLeft);\r
- Node op = new Node(nodeOp, opLeft, expr);\r
-\r
- Node result = new Node(type, tmp1, tmp2, op);\r
- if (postfix) {\r
- result = new Node(TokenStream.COMMA, result,\r
- createUseTemp(opLeft));\r
- }\r
-\r
- return result;\r
- }\r
- \r
- private void reportError(String msgResource) {\r
-\r
- if (scope != null)\r
- throw NativeGlobal.constructError(\r
- Context.getContext(), "SyntaxError",\r
- ScriptRuntime.getMessage0(msgResource),\r
- scope);\r
- else {\r
- String message = Context.getMessage0(msgResource);\r
- Context.reportError(message, ts.getSourceName(), ts.getLineno(), \r
- ts.getLine(), ts.getOffset());\r
- }\r
- }\r
- \r
- // Only needed to get file/line information. Could create an interface\r
- // that TokenStream implements if we want to make the connection less\r
- // direct.\r
- private TokenStream ts;\r
- \r
- // Only needed to pass to the Erorr exception constructors\r
- private Scriptable scope;\r
-}\r
-\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Igor Bukanov\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-// API class\r
-\r
-package org.mozilla.javascript;\r
-\r
-public class IdFunction extends BaseFunction\r
-{\r
- public static final int FUNCTION_ONLY = 0;\r
-\r
- public static final int CONSTRUCTOR_ONLY = 1;\r
-\r
- public static final int FUNCTION_AND_CONSTRUCTOR = 2;\r
-\r
- public IdFunction(IdFunctionMaster master, String name, int id) {\r
- this.functionName = name;\r
- this.master = master;\r
- this.methodId = id;\r
- }\r
- \r
- public final int functionType() {\r
- return functionType;\r
- }\r
- \r
- public void setFunctionType(int type) {\r
- functionType = type;\r
- }\r
- \r
- public Scriptable getPrototype() {\r
- // Lazy initialization of prototype: for native functions this\r
- // may not be called at all\r
- Scriptable proto = super.getPrototype(); \r
- if (proto == null) {\r
- proto = getFunctionPrototype(getParentScope());\r
- setPrototype(proto);\r
- }\r
- return proto;\r
- }\r
-\r
- public Object call(Context cx, Scriptable scope, Scriptable thisObj, \r
- Object[] args)\r
- throws JavaScriptException\r
- {\r
- if (functionType != CONSTRUCTOR_ONLY) {\r
- return master.execMethod(methodId, this, cx, scope, thisObj, args);\r
- }\r
- else {\r
- return Undefined.instance;\r
- }\r
- }\r
-\r
- public Scriptable construct(Context cx, Scriptable scope, Object[] args)\r
- throws JavaScriptException\r
- {\r
- if (functionType != FUNCTION_ONLY) {\r
- // It is program error not to return Scriptable from constructor\r
- Scriptable result = (Scriptable)master.execMethod(methodId, this,\r
- cx, scope, \r
- null, args);\r
- postConstruction(result);\r
- return result;\r
- }\r
- else {\r
- return Undefined.instance;\r
- }\r
- }\r
-\r
- public String decompile(Context cx, int indent, boolean justbody) {\r
- StringBuffer sb = new StringBuffer();\r
- if (!justbody) {\r
- sb.append("function ");\r
- sb.append(getFunctionName());\r
- sb.append("() { ");\r
- }\r
- sb.append("[native code for ");\r
- if (master instanceof Scriptable) {\r
- Scriptable smaster = (Scriptable)master;\r
- sb.append(smaster.getClassName());\r
- sb.append('.');\r
- }\r
- sb.append(getFunctionName());\r
- sb.append(", arity=");\r
- sb.append(getArity());\r
- sb.append(justbody ? "]\n" : "] }\n");\r
- return sb.toString();\r
- }\r
- \r
- public int getArity() {\r
- int arity = master.methodArity(methodId);\r
- if (arity < 0) { \r
- throw onBadMethodId(master, methodId);\r
- }\r
- return arity;\r
- }\r
- \r
- public int getLength() { return getArity(); }\r
-\r
- /** Prepare to be used as constructor .\r
- ** @param scope constructor scope\r
- ** @param prototype DontEnum, DontDelete, ReadOnly prototype property \r
- ** of the constructor */\r
- public void initAsConstructor(Scriptable scope, Scriptable prototype) {\r
- setFunctionType(FUNCTION_AND_CONSTRUCTOR);\r
- setParentScope(scope);\r
- setImmunePrototypeProperty(prototype);\r
- }\r
- \r
- static RuntimeException onBadMethodId(IdFunctionMaster master, int id) {\r
- // It is program error to call id-like methods for unknown or \r
- // non-function id\r
- return new RuntimeException("BAD FUNCTION ID="+id+" MASTER="+master);\r
- }\r
-\r
- // Copied from NativeFunction.construct\r
- private void postConstruction(Scriptable newObj) {\r
- if (newObj.getPrototype() == null) {\r
- newObj.setPrototype(getClassPrototype());\r
- }\r
- if (newObj.getParentScope() == null) {\r
- Scriptable parent = getParentScope();\r
- if (newObj != parent) {\r
- newObj.setParentScope(parent);\r
- }\r
- }\r
- }\r
-\r
- protected IdFunctionMaster master;\r
- protected int methodId;\r
-\r
- protected int functionType = FUNCTION_ONLY;\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s):\r
- * Igor Bukanov\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-/** Master for id-based functions that knows their properties and how to\r
- ** execute them\r
- */\r
-public interface IdFunctionMaster {\r
- /** 'thisObj' will be null if invoked as constructor, in which case\r
- ** instance of Scriptable should be returned */\r
- public Object execMethod(int methodId, IdFunction function,\r
- Context cx, Scriptable scope,\r
- Scriptable thisObj, Object[] args)\r
- throws JavaScriptException;\r
-\r
- /** Get arity or defined argument count for method with given id.\r
- ** Should return -1 if methodId is not known or can not be used\r
- ** with execMethod call */\r
- public int methodArity(int methodId);\r
-}\r
-\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 4; indent-tabs-mode: 1; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s):\r
- * Igor Bukanov\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-/**\r
-Base class for native object implementation that uses IdFunction to export its methods to script via <class-name>.prototype object.\r
-\r
-Any descendant should implement at least the following methods:\r
- mapNameToId\r
- getIdName\r
- execMethod\r
- methodArity\r
-\r
-To define non-function properties, the descendant should customize\r
- getIdValue\r
- setIdValue\r
- getIdDefaultAttributes\r
- maxInstanceId\r
-to get/set property value and provide its default attributes.\r
-\r
-To customize initializition of constructor and protype objects, descendant\r
-may override scopeInit or fillConstructorProperties methods.\r
-\r
-*/\r
-public abstract class IdScriptable extends ScriptableObject\r
- implements IdFunctionMaster\r
-{\r
- /** NULL_TAG can be used to distinguish between uninitialized and null\r
- ** values\r
- */\r
- protected static final Object NULL_TAG = new Object();\r
-\r
- public IdScriptable() {\r
- activateIdMap(maxInstanceId());\r
- }\r
- \r
- public boolean has(String name, Scriptable start) {\r
- if (maxId != 0) {\r
- int id = mapNameToId(name);\r
- if (id != 0) {\r
- return hasValue(id);\r
- }\r
- }\r
- return super.has(name, start);\r
- }\r
-\r
- public Object get(String name, Scriptable start) {\r
- if (CACHE_NAMES) {\r
- int maxId = this.maxId;\r
- L:if (maxId != 0) {\r
- Object[] data = idMapData;\r
- if (data == null) { \r
- int id = mapNameToId(name);\r
- if (id != 0) {\r
- return getIdValue(id);\r
- }\r
- }\r
- else {\r
- int id = lastIdCache;\r
- if (data[id - 1 + maxId] != name) {\r
- id = mapNameToId(name);\r
- if (id == 0) { break L; }\r
- data[id - 1 + maxId] = name;\r
- lastIdCache = id;\r
- }\r
- Object value = data[id - 1];\r
- if (value == null) {\r
- value = getIdValue(id);\r
- }\r
- else if (value == NULL_TAG) {\r
- value = null;\r
- }\r
- return value;\r
- }\r
- }\r
- }\r
- else {\r
- if (maxId != 0) {\r
- int id = mapNameToId(name);\r
- if (id != 0) {\r
- Object[] data = idMapData;\r
- if (data == null) { \r
- return getIdValue(id);\r
- }\r
- else {\r
- Object value = data[id - 1];\r
- if (value == null) {\r
- value = getIdValue(id);\r
- }\r
- else if (value == NULL_TAG) {\r
- value = null;\r
- }\r
- return value;\r
- }\r
- }\r
- }\r
- }\r
- return super.get(name, start);\r
- }\r
-\r
- public void put(String name, Scriptable start, Object value) {\r
- if (maxId != 0) {\r
- int id = mapNameToId(name);\r
- if (id != 0) {\r
- int attr = getAttributes(id);\r
- if ((attr & READONLY) == 0) {\r
- if (start == this) {\r
- setIdValue(id, value);\r
- }\r
- else {\r
- start.put(name, start, value);\r
- }\r
- }\r
- return;\r
- }\r
- }\r
- super.put(name, start, value);\r
- }\r
-\r
- public void delete(String name) {\r
- if (maxId != 0) {\r
- int id = mapNameToId(name);\r
- if (id != 0) {\r
- // Let the super class to throw exceptions for sealed objects\r
- if (!isSealed()) {\r
- int attr = getAttributes(id);\r
- if ((attr & PERMANENT) == 0) {\r
- deleteIdValue(id);\r
- }\r
- return;\r
- }\r
- }\r
- }\r
- super.delete(name);\r
- }\r
-\r
- public int getAttributes(String name, Scriptable start)\r
- throws PropertyException\r
- {\r
- if (maxId != 0) {\r
- int id = mapNameToId(name);\r
- if (id != 0) {\r
- if (hasValue(id)) {\r
- return getAttributes(id);\r
- }\r
- // For ids with deleted values super will throw exceptions\r
- }\r
- }\r
- return super.getAttributes(name, start);\r
- }\r
-\r
- public void setAttributes(String name, Scriptable start,\r
- int attributes)\r
- throws PropertyException\r
- {\r
- if (maxId != 0) {\r
- int id = mapNameToId(name);\r
- if (id != 0) {\r
- if (hasValue(id)) {\r
- synchronized (this) {\r
- setAttributes(id, attributes);\r
- }\r
- return;\r
- }\r
- // For ids with deleted values super will throw exceptions\r
- }\r
- }\r
- super.setAttributes(name, start, attributes);\r
- }\r
-\r
- synchronized void addPropertyAttribute(int attribute) {\r
- extraIdAttributes |= (byte)attribute;\r
- super.addPropertyAttribute(attribute);\r
- }\r
-\r
- /**\r
- * Redefine ScriptableObject.defineProperty to allow changing\r
- * values/attributes of id-based properties unless \r
- * getIdDefaultAttributes contains the READONLY attribute.\r
- * @see #getIdDefaultAttributes\r
- * @see org.mozilla.javascript.ScriptableObject#defineProperty\r
- */\r
- public void defineProperty(String propertyName, Object value,\r
- int attributes)\r
- {\r
- if (maxId != 0) {\r
- int id = mapNameToId(propertyName);\r
- if (id != 0) {\r
- int default_attributes = getIdDefaultAttributes(id);\r
- if ((default_attributes & READONLY) != 0) {\r
- // It is a bug to redefine id with readonly attributes\r
- throw new RuntimeException\r
- ("Attempt to redefine read-only id " + propertyName);\r
- }\r
- setAttributes(id, attributes);\r
- setIdValue(id, value);\r
- return;\r
- }\r
- }\r
- super.defineProperty(propertyName, value, attributes);\r
- }\r
-\r
- Object[] getIds(boolean getAll) {\r
- Object[] result = super.getIds(getAll);\r
- \r
- if (maxId != 0) {\r
- Object[] ids = null;\r
- int count = 0;\r
- \r
- for (int id = maxId; id != 0; --id) {\r
- if (hasValue(id)) {\r
- if (getAll || (getAttributes(id) & DONTENUM) == 0) {\r
- if (count == 0) {\r
- // Need extra room for nor more then [1..id] names\r
- ids = new Object[id];\r
- }\r
- ids[count++] = getIdName(id);\r
- }\r
- }\r
- }\r
- if (count != 0) {\r
- if (result.length == 0 && ids.length == count) {\r
- result = ids;\r
- }\r
- else {\r
- Object[] tmp = new Object[result.length + count];\r
- System.arraycopy(result, 0, tmp, 0, result.length);\r
- System.arraycopy(ids, 0, tmp, result.length, count);\r
- result = tmp;\r
- }\r
- }\r
- }\r
- return result;\r
- }\r
-\r
- /** Return maximum id number that should be present in each instance. */\r
- protected int maxInstanceId() { return 0; }\r
-\r
- /**\r
- * Map name to id of prototype or instance property.\r
- * Should return 0 if not found\r
- */\r
- protected abstract int mapNameToId(String name);\r
-\r
- /** Map id back to property name it defines.\r
- */\r
- protected abstract String getIdName(int id);\r
-\r
- /** Get default attributes for id. \r
- ** Default implementation return DONTENUM that is the standard attribute \r
- ** for core EcmaScript function. Typically descendants need to overwrite\r
- ** this for non-function attributes like length to return\r
- ** DONTENUM | READONLY | PERMANENT or DONTENUM | PERMANENT\r
- */\r
- protected int getIdDefaultAttributes(int id) {\r
- return DONTENUM;\r
- }\r
-\r
- /** Check if id value exists.\r
- ** Default implementation always returns true */\r
- protected boolean hasIdValue(int id) {\r
- return true;\r
- }\r
-\r
- /** Get id value. \r
- ** If id value is constant, descendant can call cacheIdValue to store\r
- ** value in the permanent cache.\r
- ** Default implementation creates IdFunction instance for given id\r
- ** and cache its value\r
- */\r
- protected Object getIdValue(int id) {\r
- IdFunction f = newIdFunction(id);\r
- f.setParentScope(getParentScope());\r
- return cacheIdValue(id, f);\r
- }\r
-\r
- /**\r
- * Set id value. \r
- * IdScriptable never calls this method if result of\r
- * <code>getIdDefaultAttributes(id)</code> contains READONLY attribute.\r
- * Descendants can overwrite this method to provide custom handler for\r
- * property assignments.\r
- */\r
- protected void setIdValue(int id, Object value) {\r
- synchronized (this) {\r
- ensureIdData()[id - 1] = (value != null) ? value : NULL_TAG;\r
- }\r
- }\r
- \r
- /**\r
- * Store value in permanent cache unless value was already assigned to id.\r
- * After this call IdScriptable never calls hasIdValue and getIdValue \r
- * for the given id.\r
- */\r
- protected Object cacheIdValue(int id, Object value) {\r
- synchronized (this) {\r
- Object[] data = ensureIdData();\r
- Object curValue = data[id - 1];\r
- if (curValue == null) {\r
- data[id - 1] = (value != null) ? value : NULL_TAG;\r
- }\r
- else {\r
- value = curValue;\r
- }\r
- }\r
- return value;\r
- }\r
- \r
- /**\r
- * Delete value represented by id so hasIdValue return false. \r
- * IdScriptable never calls this method if result of\r
- * <code>getIdDefaultAttributes(id)</code> contains PERMANENT attribute.\r
- * Descendants can overwrite this method to provide custom handler for\r
- * property delete.\r
- */\r
- protected void deleteIdValue(int id) {\r
- synchronized (this) {\r
- ensureIdData()[id - 1] = NOT_FOUND;\r
- }\r
- }\r
- \r
- /** 'thisObj' will be null if invoked as constructor, in which case\r
- ** instance of Scriptable should be returned. */\r
- public Object execMethod(int methodId, IdFunction function,\r
- Context cx, Scriptable scope,\r
- Scriptable thisObj, Object[] args)\r
- throws JavaScriptException\r
- {\r
- throw IdFunction.onBadMethodId(this, methodId);\r
- }\r
-\r
- /** Get arity or defined argument count for method with given id. \r
- ** Should return -1 if methodId is not known or can not be used\r
- ** with execMethod call. */\r
- public int methodArity(int methodId) {\r
- return -1;\r
- }\r
- \r
- /** Activate id support with the given maximum id */\r
- protected void activateIdMap(int maxId) {\r
- this.maxId = maxId;\r
- }\r
- \r
- /** Sets whether newly constructed function objects should be sealed */\r
- protected void setSealFunctionsFlag(boolean sealed) {\r
- setSetupFlag(SEAL_FUNCTIONS_FLAG, sealed);\r
- }\r
- \r
- /** \r
- * Set parameters of function properties. \r
- * Currently only determines whether functions should use dynamic scope.\r
- * @param cx context to read function parameters.\r
- * \r
- * @see org.mozilla.javascript.Context#hasCompileFunctionsWithDynamicScope\r
- */\r
- protected void setFunctionParametrs(Context cx) {\r
- setSetupFlag(USE_DYNAMIC_SCOPE_FLAG,\r
- cx.hasCompileFunctionsWithDynamicScope());\r
- }\r
- \r
- private void setSetupFlag(int flag, boolean value) {\r
- setupFlags = (byte)(value ? setupFlags | flag : setupFlags & ~flag);\r
- }\r
-\r
- /** \r
- * Prepare this object to serve as the prototype property of constructor \r
- * object with name <code>getClassName()<code> defined in\r
- * <code>scope</code>.\r
- * @param maxId maximum id available in prototype object\r
- * @param cx current context\r
- * @param scope object to define constructor in.\r
- * @param sealed indicates whether object and all its properties should \r
- * be sealed \r
- */ \r
- public void addAsPrototype(int maxId, Context cx, Scriptable scope, \r
- boolean sealed) \r
- {\r
- activateIdMap(maxId);\r
-\r
- setSealFunctionsFlag(sealed);\r
- setFunctionParametrs(cx);\r
- \r
- int constructorId = mapNameToId("constructor");\r
- if (constructorId == 0) {\r
- // It is a bug to call this function without id for constructor \r
- throw new RuntimeException("No id for constructor property");\r
- }\r
-\r
- IdFunction ctor = newIdFunction(constructorId);\r
- ctor.initAsConstructor(scope, this);\r
- fillConstructorProperties(cx, ctor, sealed);\r
- if (sealed) {\r
- ctor.sealObject();\r
- ctor.addPropertyAttribute(READONLY);\r
- }\r
-\r
- setParentScope(ctor);\r
- setPrototype(getObjectPrototype(scope));\r
- cacheIdValue(constructorId, ctor);\r
-\r
- if (sealed) {\r
- sealObject();\r
- }\r
-\r
- defineProperty(scope, getClassName(), ctor, ScriptableObject.DONTENUM);\r
- }\r
-\r
- protected void fillConstructorProperties\r
- (Context cx, IdFunction ctor, boolean sealed)\r
- {\r
- }\r
-\r
- protected void addIdFunctionProperty\r
- (Scriptable obj, int id, boolean sealed)\r
- {\r
- IdFunction f = newIdFunction(id);\r
- if (sealed) { f.sealObject(); }\r
- defineProperty(obj, getIdName(id), f, DONTENUM);\r
- }\r
-\r
- /** \r
- * Utility method for converting target object into native this.\r
- * Possible usage would be to have a private function like realThis:\r
- * <pre>\r
- private NativeSomething realThis(Scriptable thisObj,\r
- IdFunction f, boolean readOnly)\r
- {\r
- while (!(thisObj instanceof NativeSomething)) {\r
- thisObj = nextInstanceCheck(thisObj, f, readOnly);\r
- }\r
- return (NativeSomething)thisObj;\r
- }\r
- * </pre>\r
- * Note that although such function can be implemented universally via\r
- * java.lang.Class.isInstance(), it would be much more slower.\r
- * @param readOnly specify if the function f does not change state of object.\r
- * @return Scriptable object suitable for a check by the instanceof operator.\r
- * @throws RuntimeException if no more instanceof target can be found\r
- */\r
- protected Scriptable nextInstanceCheck(Scriptable thisObj,\r
- IdFunction f,\r
- boolean readOnly)\r
- {\r
- if (readOnly && 0 != (setupFlags & USE_DYNAMIC_SCOPE_FLAG)) {\r
- // for read only functions under dynamic scope look prototype chain\r
- thisObj = thisObj.getPrototype();\r
- if (thisObj != null) { return thisObj; }\r
- }\r
- throw NativeGlobal.typeError1("msg.incompat.call", \r
- f.getFunctionName(), f);\r
- }\r
-\r
- protected IdFunction newIdFunction(int id) {\r
- IdFunction f = new IdFunction(this, getIdName(id), id);\r
- if (0 != (setupFlags & SEAL_FUNCTIONS_FLAG)) { f.sealObject(); }\r
- return f;\r
- }\r
-\r
- protected final Object wrap_double(double x) {\r
- return (x == x) ? new Double(x) : ScriptRuntime.NaNobj;\r
- }\r
-\r
- protected final Object wrap_int(int x) {\r
- byte b = (byte)x;\r
- if (b == x) { return new Byte(b); }\r
- return new Integer(x);\r
- }\r
-\r
- protected final Object wrap_long(long x) {\r
- int i = (int)x;\r
- if (i == x) { return wrap_int(i); }\r
- return new Long(x);\r
- }\r
-\r
- protected final Object wrap_boolean(boolean x) {\r
- return x ? Boolean.TRUE : Boolean.FALSE;\r
- }\r
- \r
- private boolean hasValue(int id) {\r
- Object value;\r
- Object[] data = idMapData;\r
- if (data == null || (value = data[id - 1]) == null) {\r
- return hasIdValue(id);\r
- }\r
- else {\r
- return value != NOT_FOUND;\r
- }\r
- }\r
-\r
- // Must be called only from synchronized (this)\r
- private Object[] ensureIdData() {\r
- Object[] data = idMapData;\r
- if (data == null) { \r
- idMapData = data = new Object[CACHE_NAMES ? maxId * 2 : maxId];\r
- }\r
- return data;\r
- }\r
- \r
- private int getAttributes(int id) {\r
- int attributes = getIdDefaultAttributes(id) | extraIdAttributes;\r
- byte[] array = attributesArray;\r
- if (array != null) {\r
- attributes |= 0xFF & array[id - 1];\r
- }\r
- return attributes;\r
- }\r
-\r
- private void setAttributes(int id, int attributes) {\r
- int defaultAttrs = getIdDefaultAttributes(id);\r
- if ((attributes & defaultAttrs) != defaultAttrs) {\r
- // It is a bug to set attributes to less restrictive values \r
- // then given by defaultAttrs\r
- throw new RuntimeException("Attempt to unset default attributes");\r
- }\r
- // Store only additional bits\r
- attributes &= ~defaultAttrs;\r
- byte[] array = attributesArray;\r
- if (array == null && attributes != 0) {\r
- synchronized (this) {\r
- array = attributesArray;\r
- if (array == null) {\r
- attributesArray = array = new byte[maxId];\r
- }\r
- }\r
- }\r
- if (array != null) {\r
- array[id - 1] = (byte)attributes;\r
- }\r
- }\r
-\r
- private int maxId;\r
- private Object[] idMapData;\r
- private byte[] attributesArray;\r
-\r
- private static final boolean CACHE_NAMES = true;\r
- private int lastIdCache;\r
-\r
- private static final int USE_DYNAMIC_SCOPE_FLAG = 1 << 0;\r
- private static final int SEAL_FUNCTIONS_FLAG = 1 << 1;\r
- \r
- private byte setupFlags;\r
- private byte extraIdAttributes;\r
-}\r
-\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- * Matthias Radestock\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-// API class\r
-\r
-package org.mozilla.javascript;\r
-\r
-import java.util.Vector;\r
-\r
-/**\r
- * Class ImporterTopLevel\r
- * \r
- * This class defines a ScriptableObject that can be instantiated \r
- * as a top-level ("global") object to provide functionality similar\r
- * to Java's "import" statement.\r
- * <p>\r
- * This class can be used to create a top-level scope using the following code: \r
- * <pre>\r
- * Scriptable scope = new ImporterTopLevel(cx);\r
- * </pre>\r
- * Then JavaScript code will have access to the following methods:\r
- * <ul>\r
- * <li>importClass - will "import" a class by making its unqualified name \r
- * available as a property of the top-level scope\r
- * <li>importPackage - will "import" all the classes of the package by \r
- * searching for unqualified names as classes qualified\r
- * by the given package.\r
- * </ul>\r
- * The following code from the shell illustrates this use:\r
- * <pre>\r
- * js> importClass(java.io.File)\r
- * js> f = new File('help.txt')\r
- * help.txt\r
- * js> importPackage(java.util)\r
- * js> v = new Vector()\r
- * []\r
- * \r
- * @author Norris Boyd\r
- */\r
-public class ImporterTopLevel extends ScriptableObject {\r
- \r
- /**\r
- * @deprecated\r
- */\r
- public ImporterTopLevel() {\r
- init();\r
- }\r
-\r
- public ImporterTopLevel(Context cx) {\r
- cx.initStandardObjects(this);\r
- init();\r
- }\r
- \r
- private void init() {\r
- String[] names = { "importClass", "importPackage" };\r
-\r
- try {\r
- this.defineFunctionProperties(names, ImporterTopLevel.class,\r
- ScriptableObject.DONTENUM);\r
- } catch (PropertyException e) {\r
- throw new Error(); // should never happen\r
- }\r
- }\r
-\r
- public String getClassName() { \r
- return "global";\r
- }\r
- \r
- public Object get(String name, Scriptable start) {\r
- Object result = super.get(name, start);\r
- if (result != NOT_FOUND) \r
- return result;\r
- if (name.equals("_packages_")) \r
- return result;\r
- Object plist = ScriptableObject.getProperty(start,"_packages_");\r
- if (plist == NOT_FOUND) \r
- return result;\r
- Context cx = Context.enter();\r
- Object[] elements = cx.getElements((Scriptable)plist);\r
- Context.exit();\r
- for (int i=0; i < elements.length; i++) {\r
- NativeJavaPackage p = (NativeJavaPackage) elements[i];\r
- Object v = p.getPkgProperty(name, start, false);\r
- if (v != null && !(v instanceof NativeJavaPackage)) {\r
- if (result == NOT_FOUND) {\r
- result = v;\r
- } else {\r
- throw Context.reportRuntimeError2(\r
- "msg.ambig.import", result.toString(), v.toString());\r
- }\r
- }\r
- }\r
- return result;\r
- }\r
- \r
- public static void importClass(Context cx, Scriptable thisObj,\r
- Object[] args, Function funObj) {\r
- for (int i=0; i<args.length; i++) {\r
- Object cl = args[i];\r
- if (!(cl instanceof NativeJavaClass)) {\r
- throw Context.reportRuntimeError1(\r
- "msg.not.class", Context.toString(cl));\r
- }\r
- String s = ((NativeJavaClass) cl).getClassObject().getName();\r
- String n = s.substring(s.lastIndexOf('.')+1);\r
- Object val = thisObj.get(n, thisObj);\r
- if (val != NOT_FOUND && val != cl) {\r
- throw Context.reportRuntimeError1("msg.prop.defined", n);\r
- }\r
- //thisObj.defineProperty(n, cl, DONTENUM);\r
- thisObj.put(n,thisObj,cl);\r
- }\r
- }\r
- \r
- public static void importPackage(Context cx, Scriptable thisObj,\r
- Object[] args, Function funObj) {\r
- Scriptable importedPackages;\r
- Object plist = thisObj.get("_packages_", thisObj);\r
- if (plist == NOT_FOUND) {\r
- importedPackages = cx.newArray(thisObj,0);\r
- thisObj.put("_packages_", thisObj, importedPackages);\r
- }\r
- else {\r
- importedPackages = (Scriptable)plist;\r
- }\r
- for (int i=0; i<args.length; i++) {\r
- Object pkg = args[i];\r
- if (!(pkg instanceof NativeJavaPackage)) {\r
- throw Context.reportRuntimeError1(\r
- "msg.not.pkg", Context.toString(pkg));\r
- }\r
- Object[] elements = cx.getElements(importedPackages);\r
- for (int j=0; j < elements.length; j++) {\r
- if (pkg == elements[j]) {\r
- pkg = null;\r
- break;\r
- }\r
- }\r
- if (pkg != null)\r
- importedPackages.put(elements.length,importedPackages,pkg);\r
- }\r
- }\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-2000 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Roger Lawrence\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-import java.util.*;\r
-import org.mozilla.javascript.debug.DebuggableScript;\r
-\r
-public class InterpretedFunction extends NativeFunction implements DebuggableScript {\r
- \r
- InterpretedFunction(Context cx,\r
- InterpreterData theData, \r
- String[] argNames, short argCount)\r
- {\r
- itsData = theData;\r
- this.argNames = argNames;\r
- this.argCount = argCount;\r
- init(cx);\r
- }\r
- \r
- void init(Context cx)\r
- {\r
- functionName = itsData.itsName;\r
- source = itsData.itsSource;\r
- nestedFunctions = itsData.itsNestedFunctions;\r
- if (cx != null)\r
- version = (short)cx.getLanguageVersion();\r
- }\r
- \r
- InterpretedFunction(InterpretedFunction theOther,\r
- Scriptable theScope, Context cx)\r
- {\r
- itsData = theOther.itsData;\r
- this.argNames = theOther.argNames;\r
- this.argCount = theOther.argCount;\r
- itsClosure = theScope;\r
- init(cx);\r
- }\r
- \r
- public Object call(Context cx, Scriptable scope, Scriptable thisObj,\r
- Object[] args)\r
- throws JavaScriptException\r
- { \r
- Function temp = cx.currentFunction;\r
- if (cx.stackDepth++ > 200) {\r
- NativeError ne = new NativeError();\r
- ne.put("message", ne, "maximum interpreter stack depth limit exceeded");\r
- cx.stackDepth--;\r
- throw new EcmaError(ne, cx.interpreterSourceFile, cx.interpreterLine, 0, "");\r
- }\r
- cx.currentFunction = this;\r
- cx.interpreterSourceFile = itsData.itsSourceFile;\r
- if (itsClosure != null)\r
- scope = itsClosure;\r
- else if (!itsData.itsUseDynamicScope)\r
- scope = getParentScope();\r
-\r
- if (itsData.itsCheckThis) \r
- thisObj = ScriptRuntime.getThis(thisObj);\r
- \r
- if (itsData.itsNeedsActivation) {\r
- scope = ScriptRuntime.initVarObj(cx, scope, this, thisObj, args);\r
- }\r
- try {\r
- return Interpreter.interpret(cx, scope, thisObj, args, this,\r
- itsData);\r
- } finally {\r
- if (itsData.itsNeedsActivation) {\r
- ScriptRuntime.popActivation(cx);\r
- }\r
- cx.currentFunction = temp;\r
- cx.stackDepth--;\r
- }\r
- }\r
- \r
- public boolean isFunction() {\r
- return true;\r
- }\r
- \r
- public Scriptable getScriptable() {\r
- return this;\r
- }\r
- \r
- public String getSourceName() {\r
- return itsData.itsSourceFile;\r
- }\r
- \r
- public int[] getLineNumbers() { \r
- return itsData.itsLineNumberTable.getKeys();\r
- }\r
- \r
- public boolean placeBreakpoint(int line) { // XXX throw exn?\r
- return itsData.placeBreakpoint(line);\r
- }\r
- \r
- public boolean removeBreakpoint(int line) {\r
- return itsData.removeBreakpoint(line);\r
- }\r
- \r
- InterpreterData itsData;\r
- Scriptable itsClosure;\r
-}\r
- \r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Roger Lawrence\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-import org.mozilla.javascript.debug.*;\r
-\r
-import java.util.*;\r
-\r
-public class InterpretedScript extends NativeScript implements DebuggableScript {\r
-\r
- InterpretedScript(Context cx,\r
- InterpreterData theData, \r
- String[] argNames, short argCount)\r
- {\r
- itsData = theData;\r
- this.argNames = argNames;\r
- this.argCount = argCount;\r
- functionName = "";\r
- nestedFunctions = itsData.itsNestedFunctions;\r
- version = (short)cx.getLanguageVersion(); \r
- }\r
- \r
- public Object exec(Context cx, Scriptable scope)\r
- throws JavaScriptException\r
- {\r
- return call(cx, scope, scope, null); \r
- }\r
-\r
- public Object call(Context cx, Scriptable scope, \r
- Scriptable thisObj, Object[] args)\r
- throws JavaScriptException\r
- {\r
- Function temp = cx.currentFunction;\r
- cx.currentFunction = this;\r
- cx.interpreterSourceFile = itsData.itsSourceFile;\r
- scope = ScriptRuntime.initScript(cx, scope, this, thisObj, \r
- itsData.itsFromEvalCode);\r
- Object ret = Interpreter.interpret(cx, scope, thisObj, args, this, itsData); \r
- cx.currentFunction = temp;\r
- return ret;\r
- }\r
- \r
- public boolean isFunction() {\r
- return false;\r
- }\r
- \r
- public Scriptable getScriptable() {\r
- return this;\r
- }\r
- \r
- public String getSourceName() {\r
- return itsData.itsSourceFile;\r
- }\r
- \r
- public int[] getLineNumbers() {\r
- return itsData.itsLineNumberTable.getKeys();\r
- }\r
- \r
- public boolean placeBreakpoint(int line) { // XXX throw exn?\r
- return itsData.placeBreakpoint(line);\r
- }\r
- \r
- public boolean removeBreakpoint(int line) {\r
- return itsData.removeBreakpoint(line);\r
- }\r
- \r
- InterpreterData itsData;\r
-}\r
-\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-2000 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Patrick Beard\r
- * Norris Boyd\r
- * Igor Bukanov\r
- * Roger Lawrence\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-import java.io.*;\r
-import java.util.Vector;\r
-import java.util.Enumeration;\r
-\r
-import org.mozilla.javascript.debug.*;\r
-\r
-public class Interpreter extends LabelTable {\r
- \r
- public static final boolean printICode = false;\r
- \r
- public IRFactory createIRFactory(TokenStream ts, \r
- ClassNameHelper nameHelper, Scriptable scope) \r
- {\r
- return new IRFactory(ts, scope);\r
- }\r
- \r
- public Node transform(Node tree, TokenStream ts, Scriptable scope) {\r
- return (new NodeTransformer()).transform(tree, null, ts, scope);\r
- }\r
- \r
- public Object compile(Context cx, Scriptable scope, Node tree, \r
- Object securityDomain,\r
- SecuritySupport securitySupport,\r
- ClassNameHelper nameHelper)\r
- throws IOException\r
- {\r
- version = cx.getLanguageVersion();\r
- itsData = new InterpreterData(0, 0, 0, securityDomain, \r
- cx.hasCompileFunctionsWithDynamicScope(), false);\r
- if (tree instanceof FunctionNode) {\r
- FunctionNode f = (FunctionNode) tree;\r
- InterpretedFunction result = \r
- generateFunctionICode(cx, scope, f, securityDomain);\r
- result.itsData.itsFunctionType = f.getFunctionType();\r
- createFunctionObject(result, scope);\r
- return result;\r
- }\r
- return generateScriptICode(cx, scope, tree, securityDomain);\r
- }\r
- \r
- private void generateICodeFromTree(Node tree, \r
- VariableTable varTable, \r
- boolean needsActivation,\r
- Object securityDomain)\r
- {\r
- int theICodeTop = 0;\r
- itsVariableTable = varTable;\r
- itsData.itsNeedsActivation = needsActivation;\r
- theICodeTop = generateICode(tree, theICodeTop);\r
- itsData.itsICodeTop = theICodeTop;\r
- if (itsEpilogLabel != -1)\r
- markLabel(itsEpilogLabel, theICodeTop);\r
- for (int i = 0; i < itsLabelTableTop; i++)\r
- itsLabelTable[i].fixGotos(itsData.itsICode); \r
- }\r
-\r
- private Object[] generateRegExpLiterals(Context cx,\r
- Scriptable scope,\r
- Vector regexps)\r
- {\r
- Object[] result = new Object[regexps.size()];\r
- RegExpProxy rep = cx.getRegExpProxy();\r
- for (int i = 0; i < regexps.size(); i++) {\r
- Node regexp = (Node) regexps.elementAt(i);\r
- Node left = regexp.getFirstChild();\r
- Node right = regexp.getLastChild();\r
- result[i] = rep.newRegExp(cx, scope, left.getString(), \r
- (left != right) ? right.getString() : null, false);\r
- regexp.putProp(Node.REGEXP_PROP, new Integer(i));\r
- }\r
- return result;\r
- }\r
- \r
- private InterpretedScript generateScriptICode(Context cx, \r
- Scriptable scope, \r
- Node tree,\r
- Object securityDomain)\r
- { \r
- itsSourceFile = (String) tree.getProp(Node.SOURCENAME_PROP);\r
- itsData.itsSourceFile = itsSourceFile;\r
- itsFunctionList = (Vector) tree.getProp(Node.FUNCTION_PROP); \r
- debugSource = (StringBuffer) tree.getProp(Node.DEBUGSOURCE_PROP);\r
- if (itsFunctionList != null)\r
- generateNestedFunctions(scope, cx, securityDomain);\r
- Object[] regExpLiterals = null;\r
- Vector regexps = (Vector)tree.getProp(Node.REGEXP_PROP);\r
- if (regexps != null) \r
- regExpLiterals = generateRegExpLiterals(cx, scope, regexps);\r
- \r
- VariableTable varTable = (VariableTable)tree.getProp(Node.VARS_PROP);\r
- // The default is not to generate debug information\r
- boolean activationNeeded = cx.isGeneratingDebugChanged() && \r
- cx.isGeneratingDebug();\r
- generateICodeFromTree(tree, varTable, activationNeeded, securityDomain);\r
- itsData.itsNestedFunctions = itsNestedFunctions;\r
- itsData.itsRegExpLiterals = regExpLiterals;\r
- if (printICode) dumpICode(itsData);\r
- \r
- String[] argNames = itsVariableTable.getAllNames();\r
- short argCount = (short)itsVariableTable.getParameterCount();\r
- InterpretedScript\r
- result = new InterpretedScript(cx, itsData, argNames, argCount);\r
- if (cx.debugger != null) {\r
- cx.debugger.handleCompilationDone(cx, result, debugSource);\r
- }\r
- return result;\r
- }\r
- \r
- private void generateNestedFunctions(Scriptable scope,\r
- Context cx, \r
- Object securityDomain)\r
- {\r
- itsNestedFunctions = new InterpretedFunction[itsFunctionList.size()];\r
- for (short i = 0; i < itsFunctionList.size(); i++) {\r
- FunctionNode def = (FunctionNode)itsFunctionList.elementAt(i);\r
- Interpreter jsi = new Interpreter();\r
- jsi.itsSourceFile = itsSourceFile;\r
- jsi.itsData = new InterpreterData(0, 0, 0, securityDomain,\r
- cx.hasCompileFunctionsWithDynamicScope(),\r
- def.getCheckThis());\r
- jsi.itsData.itsFunctionType = def.getFunctionType();\r
- jsi.itsInFunctionFlag = true;\r
- jsi.debugSource = debugSource;\r
- itsNestedFunctions[i] = jsi.generateFunctionICode(cx, scope, def, \r
- securityDomain);\r
- def.putProp(Node.FUNCTION_PROP, new Short(i));\r
- }\r
- } \r
- \r
- private InterpretedFunction \r
- generateFunctionICode(Context cx, Scriptable scope, \r
- FunctionNode theFunction, Object securityDomain)\r
- {\r
- itsFunctionList = (Vector) theFunction.getProp(Node.FUNCTION_PROP);\r
- if (itsFunctionList != null) \r
- generateNestedFunctions(scope, cx, securityDomain);\r
- Object[] regExpLiterals = null;\r
- Vector regexps = (Vector)theFunction.getProp(Node.REGEXP_PROP);\r
- if (regexps != null) \r
- regExpLiterals = generateRegExpLiterals(cx, scope, regexps);\r
-\r
- VariableTable varTable = theFunction.getVariableTable();\r
- boolean needsActivation = theFunction.requiresActivation() ||\r
- (cx.isGeneratingDebugChanged() && \r
- cx.isGeneratingDebug());\r
- generateICodeFromTree(theFunction.getLastChild(), \r
- varTable, needsActivation,\r
- securityDomain);\r
- \r
- itsData.itsName = theFunction.getFunctionName();\r
- itsData.itsSourceFile = (String) theFunction.getProp(\r
- Node.SOURCENAME_PROP);\r
- itsData.itsSource = (String)theFunction.getProp(Node.SOURCE_PROP);\r
- itsData.itsNestedFunctions = itsNestedFunctions;\r
- itsData.itsRegExpLiterals = regExpLiterals;\r
- if (printICode) dumpICode(itsData); \r
- \r
- String[] argNames = itsVariableTable.getAllNames();\r
- short argCount = (short)itsVariableTable.getParameterCount();\r
- InterpretedFunction \r
- result = new InterpretedFunction(cx, itsData, argNames, argCount); \r
- if (cx.debugger != null) {\r
- cx.debugger.handleCompilationDone(cx, result, debugSource);\r
- }\r
- return result;\r
- }\r
- \r
- boolean itsInFunctionFlag;\r
- Vector itsFunctionList;\r
- \r
- InterpreterData itsData;\r
- VariableTable itsVariableTable;\r
- int itsTryDepth = 0;\r
- int itsStackDepth = 0;\r
- int itsEpilogLabel = -1;\r
- String itsSourceFile;\r
- int itsLineNumber = 0;\r
- InterpretedFunction[] itsNestedFunctions = null;\r
- \r
- private int updateLineNumber(Node node, int iCodeTop)\r
- {\r
- Object datum = node.getDatum();\r
- if (datum == null || !(datum instanceof Number))\r
- return iCodeTop;\r
- short lineNumber = ((Number) datum).shortValue(); \r
- if (lineNumber != itsLineNumber) {\r
- itsLineNumber = lineNumber;\r
- if (itsData.itsLineNumberTable == null && \r
- Context.getCurrentContext().isGeneratingDebug())\r
- {\r
- itsData.itsLineNumberTable = new UintMap();\r
- }\r
- if (itsData.itsLineNumberTable != null) {\r
- itsData.itsLineNumberTable.put(lineNumber, iCodeTop);\r
- }\r
- iCodeTop = addByte((byte) TokenStream.LINE, iCodeTop);\r
- iCodeTop = addByte((byte)(lineNumber >> 8), iCodeTop);\r
- iCodeTop = addByte((byte)(lineNumber & 0xff), iCodeTop);\r
- \r
- }\r
- \r
- return iCodeTop;\r
- }\r
- \r
- private void badTree(Node node)\r
- {\r
- try {\r
- out = new PrintWriter(new FileOutputStream("icode.txt", true));\r
- out.println("Un-handled node : " + node.toString());\r
- out.close();\r
- }\r
- catch (IOException x) {}\r
- throw new RuntimeException("Un-handled node : "\r
- + node.toString());\r
- }\r
- \r
- private int generateICode(Node node, int iCodeTop) {\r
- int type = node.getType();\r
- Node child = node.getFirstChild();\r
- Node firstChild = child;\r
- switch (type) {\r
- \r
- case TokenStream.FUNCTION : { \r
- iCodeTop = addByte((byte) TokenStream.CLOSURE, iCodeTop);\r
- Node fn = (Node) node.getProp(Node.FUNCTION_PROP);\r
- Short index = (Short) fn.getProp(Node.FUNCTION_PROP);\r
- iCodeTop = addByte((byte)(index.shortValue() >> 8), iCodeTop);\r
- iCodeTop = addByte((byte)(index.shortValue() & 0xff), iCodeTop); \r
- itsStackDepth++;\r
- if (itsStackDepth > itsData.itsMaxStack)\r
- itsData.itsMaxStack = itsStackDepth;\r
- }\r
- break;\r
-\r
- case TokenStream.SCRIPT :\r
- iCodeTop = updateLineNumber(node, iCodeTop);\r
- while (child != null) {\r
- if (child.getType() != TokenStream.FUNCTION) \r
- iCodeTop = generateICode(child, iCodeTop);\r
- child = child.getNextSibling();\r
- }\r
- break;\r
-\r
- case TokenStream.CASE :\r
- iCodeTop = updateLineNumber(node, iCodeTop);\r
- child = child.getNextSibling();\r
- while (child != null) {\r
- iCodeTop = generateICode(child, iCodeTop);\r
- child = child.getNextSibling();\r
- }\r
- break;\r
- \r
- case TokenStream.LABEL :\r
- case TokenStream.WITH :\r
- case TokenStream.LOOP :\r
- case TokenStream.DEFAULT :\r
- case TokenStream.BLOCK :\r
- case TokenStream.VOID :\r
- case TokenStream.NOP :\r
- iCodeTop = updateLineNumber(node, iCodeTop);\r
- while (child != null) {\r
- iCodeTop = generateICode(child, iCodeTop);\r
- child = child.getNextSibling();\r
- }\r
- break;\r
-\r
- case TokenStream.COMMA :\r
- iCodeTop = generateICode(child, iCodeTop);\r
- iCodeTop = addByte((byte) TokenStream.POP, iCodeTop);\r
- itsStackDepth--;\r
- child = child.getNextSibling();\r
- iCodeTop = generateICode(child, iCodeTop);\r
- break;\r
- \r
- case TokenStream.SWITCH : {\r
- iCodeTop = updateLineNumber(node, iCodeTop);\r
- iCodeTop = generateICode(child, iCodeTop);\r
- int theLocalSlot = itsData.itsMaxLocals++;\r
- iCodeTop = addByte((byte) TokenStream.NEWTEMP, iCodeTop);\r
- iCodeTop = addByte((byte)theLocalSlot, iCodeTop);\r
- iCodeTop = addByte((byte) TokenStream.POP, iCodeTop);\r
- itsStackDepth--;\r
- /*\r
- reminder - below we construct new GOTO nodes that aren't\r
- linked into the tree just for the purpose of having a node\r
- to pass to the addGoto routine. (Parallels codegen here).\r
- Seems unnecessary. \r
- */\r
- Vector cases = (Vector) node.getProp(Node.CASES_PROP);\r
- for (int i = 0; i < cases.size(); i++) {\r
- Node thisCase = (Node)cases.elementAt(i);\r
- Node first = thisCase.getFirstChild();\r
- // the case expression is the firstmost child\r
- // the rest will be generated when the case\r
- // statements are encountered as siblings of\r
- // the switch statement.\r
- iCodeTop = generateICode(first, iCodeTop); \r
- iCodeTop = addByte((byte) TokenStream.USETEMP, iCodeTop);\r
- itsStackDepth++;\r
- if (itsStackDepth > itsData.itsMaxStack)\r
- itsData.itsMaxStack = itsStackDepth;\r
- iCodeTop = addByte((byte) theLocalSlot, iCodeTop);\r
- iCodeTop = addByte((byte) TokenStream.SHEQ, iCodeTop);\r
- Node target = new Node(TokenStream.TARGET);\r
- thisCase.addChildAfter(target, first);\r
- Node branch = new Node(TokenStream.IFEQ);\r
- branch.putProp(Node.TARGET_PROP, target);\r
- iCodeTop = addGoto(branch, TokenStream.IFEQ, \r
- iCodeTop);\r
- itsStackDepth--;\r
- }\r
-\r
- Node defaultNode = (Node) node.getProp(Node.DEFAULT_PROP);\r
- if (defaultNode != null) {\r
- Node defaultTarget = new Node(TokenStream.TARGET);\r
- defaultNode.getFirstChild().addChildToFront(defaultTarget);\r
- Node branch = new Node(TokenStream.GOTO);\r
- branch.putProp(Node.TARGET_PROP, defaultTarget);\r
- iCodeTop = addGoto(branch, TokenStream.GOTO,\r
- iCodeTop); \r
- }\r
-\r
- Node breakTarget = (Node) node.getProp(Node.BREAK_PROP);\r
- Node branch = new Node(TokenStream.GOTO);\r
- branch.putProp(Node.TARGET_PROP, breakTarget);\r
- iCodeTop = addGoto(branch, TokenStream.GOTO, \r
- iCodeTop); \r
- }\r
- break;\r
- \r
- case TokenStream.TARGET : { \r
- Object lblObect = node.getProp(Node.LABEL_PROP);\r
- if (lblObect == null) {\r
- int label = markLabel(acquireLabel(), iCodeTop);\r
- node.putProp(Node.LABEL_PROP, new Integer(label));\r
- }\r
- else {\r
- int label = ((Integer)lblObect).intValue();\r
- markLabel(label, iCodeTop);\r
- }\r
- // if this target has a FINALLY_PROP, it is a JSR target\r
- // and so has a PC value on the top of the stack\r
- if (node.getProp(Node.FINALLY_PROP) != null) {\r
- itsStackDepth = 1;\r
- if (itsStackDepth > itsData.itsMaxStack)\r
- itsData.itsMaxStack = itsStackDepth;\r
- }\r
- }\r
- break;\r
- \r
- case TokenStream.EQOP :\r
- case TokenStream.RELOP : {\r
- iCodeTop = generateICode(child, iCodeTop);\r
- child = child.getNextSibling();\r
- iCodeTop = generateICode(child, iCodeTop);\r
- int op = node.getInt();\r
- if (version == Context.VERSION_1_2) {\r
- if (op == TokenStream.EQ)\r
- op = TokenStream.SHEQ;\r
- else if (op == TokenStream.NE)\r
- op = TokenStream.SHNE;\r
- }\r
- iCodeTop = addByte((byte) op, iCodeTop);\r
- itsStackDepth--;\r
- }\r
- break;\r
- \r
- case TokenStream.NEW :\r
- case TokenStream.CALL : {\r
- if (itsSourceFile != null && (itsData.itsSourceFile == null || ! itsSourceFile.equals(itsData.itsSourceFile))) \r
- itsData.itsSourceFile = itsSourceFile;\r
- iCodeTop = addByte((byte)TokenStream.SOURCEFILE, iCodeTop);\r
- \r
- int childCount = 0;\r
- short nameIndex = -1;\r
- while (child != null) {\r
- iCodeTop = generateICode(child, iCodeTop);\r
- if (nameIndex == -1) {\r
- if (child.getType() == TokenStream.NAME)\r
- nameIndex = (short)(itsData.itsStringTableIndex - 1);\r
- else if (child.getType() == TokenStream.GETPROP)\r
- nameIndex = (short)(itsData.itsStringTableIndex - 1);\r
- }\r
- child = child.getNextSibling();\r
- childCount++;\r
- }\r
- if (node.getProp(Node.SPECIALCALL_PROP) != null) {\r
- // embed line number and source filename\r
- iCodeTop = addByte((byte) TokenStream.CALLSPECIAL, iCodeTop);\r
- iCodeTop = addByte((byte)(itsLineNumber >> 8), iCodeTop);\r
- iCodeTop = addByte((byte)(itsLineNumber & 0xff), iCodeTop);\r
- iCodeTop = addString(itsSourceFile, iCodeTop);\r
- } else {\r
- iCodeTop = addByte((byte) type, iCodeTop);\r
- iCodeTop = addByte((byte)(nameIndex >> 8), iCodeTop);\r
- iCodeTop = addByte((byte)(nameIndex & 0xFF), iCodeTop);\r
- }\r
- \r
- itsStackDepth -= (childCount - 1); // always a result value\r
- // subtract from child count to account for [thisObj &] fun\r
- if (type == TokenStream.NEW)\r
- childCount -= 1;\r
- else\r
- childCount -= 2;\r
- iCodeTop = addByte((byte)(childCount >> 8), iCodeTop);\r
- iCodeTop = addByte((byte)(childCount & 0xff), iCodeTop);\r
- if (childCount > itsData.itsMaxArgs)\r
- itsData.itsMaxArgs = childCount;\r
- \r
- iCodeTop = addByte((byte)TokenStream.SOURCEFILE, iCodeTop);\r
- }\r
- break;\r
- \r
- case TokenStream.NEWLOCAL :\r
- case TokenStream.NEWTEMP : {\r
- iCodeTop = generateICode(child, iCodeTop);\r
- iCodeTop = addByte((byte) TokenStream.NEWTEMP, iCodeTop);\r
- iCodeTop = addLocalRef(node, iCodeTop);\r
- }\r
- break; \r
- \r
- case TokenStream.USELOCAL : {\r
- if (node.getProp(Node.TARGET_PROP) != null) \r
- iCodeTop = addByte((byte) TokenStream.RETSUB, iCodeTop);\r
- else {\r
- iCodeTop = addByte((byte) TokenStream.USETEMP, iCodeTop);\r
- itsStackDepth++;\r
- if (itsStackDepth > itsData.itsMaxStack)\r
- itsData.itsMaxStack = itsStackDepth;\r
- }\r
- Node temp = (Node) node.getProp(Node.LOCAL_PROP);\r
- iCodeTop = addLocalRef(temp, iCodeTop);\r
- }\r
- break; \r
-\r
- case TokenStream.USETEMP : {\r
- iCodeTop = addByte((byte) TokenStream.USETEMP, iCodeTop);\r
- Node temp = (Node) node.getProp(Node.TEMP_PROP);\r
- iCodeTop = addLocalRef(temp, iCodeTop);\r
- itsStackDepth++;\r
- if (itsStackDepth > itsData.itsMaxStack)\r
- itsData.itsMaxStack = itsStackDepth;\r
- }\r
- break; \r
- \r
- case TokenStream.IFEQ :\r
- case TokenStream.IFNE :\r
- iCodeTop = generateICode(child, iCodeTop);\r
- itsStackDepth--; // after the conditional GOTO, really\r
- // fall thru...\r
- case TokenStream.GOTO :\r
- iCodeTop = addGoto(node, (byte) type, iCodeTop);\r
- break;\r
-\r
- case TokenStream.JSR : {\r
- /*\r
- mark the target with a FINALLY_PROP to indicate\r
- that it will have an incoming PC value on the top\r
- of the stack.\r
- !!! \r
- This only works if the target follows the JSR\r
- in the tree.\r
- !!!\r
- */\r
- Node target = (Node)(node.getProp(Node.TARGET_PROP));\r
- target.putProp(Node.FINALLY_PROP, node);\r
- iCodeTop = addGoto(node, TokenStream.GOSUB, iCodeTop);\r
- }\r
- break;\r
- \r
- case TokenStream.AND : { \r
- iCodeTop = generateICode(child, iCodeTop);\r
- iCodeTop = addByte((byte) TokenStream.DUP, iCodeTop); \r
- itsStackDepth++;\r
- if (itsStackDepth > itsData.itsMaxStack)\r
- itsData.itsMaxStack = itsStackDepth;\r
- int falseTarget = acquireLabel();\r
- iCodeTop = addGoto(falseTarget, TokenStream.IFNE, \r
- iCodeTop);\r
- iCodeTop = addByte((byte) TokenStream.POP, iCodeTop);\r
- itsStackDepth--;\r
- child = child.getNextSibling();\r
- iCodeTop = generateICode(child, iCodeTop);\r
- markLabel(falseTarget, iCodeTop);\r
- }\r
- break;\r
-\r
- case TokenStream.OR : {\r
- iCodeTop = generateICode(child, iCodeTop);\r
- iCodeTop = addByte((byte) TokenStream.DUP, iCodeTop); \r
- itsStackDepth++;\r
- if (itsStackDepth > itsData.itsMaxStack)\r
- itsData.itsMaxStack = itsStackDepth;\r
- int trueTarget = acquireLabel();\r
- iCodeTop = addGoto(trueTarget, TokenStream.IFEQ,\r
- iCodeTop);\r
- iCodeTop = addByte((byte) TokenStream.POP, iCodeTop); \r
- itsStackDepth--;\r
- child = child.getNextSibling();\r
- iCodeTop = generateICode(child, iCodeTop);\r
- markLabel(trueTarget, iCodeTop);\r
- }\r
- break;\r
-\r
- case TokenStream.GETPROP : {\r
- iCodeTop = generateICode(child, iCodeTop);\r
- String s = (String) node.getProp(Node.SPECIAL_PROP_PROP);\r
- if (s != null) {\r
- if (s.equals("__proto__"))\r
- iCodeTop = addByte((byte) TokenStream.GETPROTO, iCodeTop);\r
- else\r
- if (s.equals("__parent__"))\r
- iCodeTop = addByte((byte) TokenStream.GETSCOPEPARENT, iCodeTop);\r
- else\r
- badTree(node);\r
- }\r
- else {\r
- child = child.getNextSibling();\r
- iCodeTop = generateICode(child, iCodeTop);\r
- iCodeTop = addByte((byte) TokenStream.GETPROP, iCodeTop);\r
- itsStackDepth--;\r
- }\r
- }\r
- break;\r
-\r
- case TokenStream.DELPROP : \r
- case TokenStream.BITAND : \r
- case TokenStream.BITOR :\r
- case TokenStream.BITXOR :\r
- case TokenStream.LSH :\r
- case TokenStream.RSH :\r
- case TokenStream.URSH :\r
- case TokenStream.ADD :\r
- case TokenStream.SUB :\r
- case TokenStream.MOD :\r
- case TokenStream.DIV :\r
- case TokenStream.MUL :\r
- case TokenStream.GETELEM :\r
- iCodeTop = generateICode(child, iCodeTop);\r
- child = child.getNextSibling();\r
- iCodeTop = generateICode(child, iCodeTop);\r
- iCodeTop = addByte((byte) type, iCodeTop);\r
- itsStackDepth--;\r
- break;\r
-\r
- case TokenStream.CONVERT : {\r
- iCodeTop = generateICode(child, iCodeTop);\r
- Object toType = node.getProp(Node.TYPE_PROP);\r
- if (toType == ScriptRuntime.NumberClass)\r
- iCodeTop = addByte((byte) TokenStream.POS, iCodeTop);\r
- else\r
- badTree(node);\r
- }\r
- break;\r
-\r
- case TokenStream.UNARYOP :\r
- iCodeTop = generateICode(child, iCodeTop);\r
- switch (node.getInt()) {\r
- case TokenStream.VOID :\r
- iCodeTop = addByte((byte) TokenStream.POP, iCodeTop);\r
- iCodeTop = addByte((byte) TokenStream.UNDEFINED, iCodeTop);\r
- break;\r
- case TokenStream.NOT : {\r
- int trueTarget = acquireLabel();\r
- int beyond = acquireLabel();\r
- iCodeTop = addGoto(trueTarget, TokenStream.IFEQ,\r
- iCodeTop);\r
- iCodeTop = addByte((byte) TokenStream.TRUE, iCodeTop);\r
- iCodeTop = addGoto(beyond, TokenStream.GOTO, \r
- iCodeTop);\r
- markLabel(trueTarget, iCodeTop);\r
- iCodeTop = addByte((byte) TokenStream.FALSE, iCodeTop);\r
- markLabel(beyond, iCodeTop);\r
- }\r
- break;\r
- case TokenStream.BITNOT :\r
- iCodeTop = addByte((byte) TokenStream.BITNOT, iCodeTop);\r
- break;\r
- case TokenStream.TYPEOF :\r
- iCodeTop = addByte((byte) TokenStream.TYPEOF, iCodeTop);\r
- break;\r
- case TokenStream.SUB :\r
- iCodeTop = addByte((byte) TokenStream.NEG, iCodeTop);\r
- break;\r
- case TokenStream.ADD :\r
- iCodeTop = addByte((byte) TokenStream.POS, iCodeTop);\r
- break;\r
- default:\r
- badTree(node);\r
- break;\r
- }\r
- break;\r
-\r
- case TokenStream.SETPROP : {\r
- iCodeTop = generateICode(child, iCodeTop);\r
- child = child.getNextSibling();\r
- iCodeTop = generateICode(child, iCodeTop);\r
- String s = (String) node.getProp(Node.SPECIAL_PROP_PROP);\r
- if (s != null) {\r
- if (s.equals("__proto__"))\r
- iCodeTop = addByte((byte) TokenStream.SETPROTO, iCodeTop);\r
- else\r
- if (s.equals("__parent__"))\r
- iCodeTop = addByte((byte) TokenStream.SETPARENT, iCodeTop);\r
- else\r
- badTree(node);\r
- }\r
- else {\r
- child = child.getNextSibling();\r
- iCodeTop = generateICode(child, iCodeTop);\r
- iCodeTop = addByte((byte) TokenStream.SETPROP, iCodeTop);\r
- itsStackDepth -= 2;\r
- }\r
- }\r
- break; \r
-\r
- case TokenStream.SETELEM :\r
- iCodeTop = generateICode(child, iCodeTop);\r
- child = child.getNextSibling();\r
- iCodeTop = generateICode(child, iCodeTop);\r
- child = child.getNextSibling();\r
- iCodeTop = generateICode(child, iCodeTop);\r
- iCodeTop = addByte((byte) type, iCodeTop);\r
- itsStackDepth -= 2;\r
- break;\r
-\r
- case TokenStream.SETNAME :\r
- iCodeTop = generateICode(child, iCodeTop);\r
- child = child.getNextSibling();\r
- iCodeTop = generateICode(child, iCodeTop);\r
- iCodeTop = addByte((byte) TokenStream.SETNAME, iCodeTop); \r
- iCodeTop = addString(firstChild.getString(), iCodeTop);\r
- itsStackDepth--;\r
- break;\r
- \r
- case TokenStream.TYPEOF : {\r
- String name = node.getString();\r
- int index = -1;\r
- // use typeofname if an activation frame exists\r
- // since the vars all exist there instead of in jregs\r
- if (itsInFunctionFlag && !itsData.itsNeedsActivation)\r
- index = itsVariableTable.getOrdinal(name);\r
- if (index == -1) { \r
- iCodeTop = addByte((byte) TokenStream.TYPEOFNAME, iCodeTop);\r
- iCodeTop = addString(name, iCodeTop);\r
- }\r
- else {\r
- iCodeTop = addByte((byte) TokenStream.GETVAR, iCodeTop);\r
- iCodeTop = addByte((byte) index, iCodeTop);\r
- iCodeTop = addByte((byte) TokenStream.TYPEOF, iCodeTop);\r
- }\r
- itsStackDepth++;\r
- if (itsStackDepth > itsData.itsMaxStack)\r
- itsData.itsMaxStack = itsStackDepth;\r
- }\r
- break;\r
-\r
- case TokenStream.PARENT :\r
- iCodeTop = generateICode(child, iCodeTop);\r
- iCodeTop = addByte((byte) TokenStream.GETPARENT, iCodeTop);\r
- break;\r
-\r
- case TokenStream.GETBASE :\r
- case TokenStream.BINDNAME :\r
- case TokenStream.NAME :\r
- case TokenStream.STRING :\r
- iCodeTop = addByte((byte) type, iCodeTop);\r
- iCodeTop = addString(node.getString(), iCodeTop);\r
- itsStackDepth++;\r
- if (itsStackDepth > itsData.itsMaxStack)\r
- itsData.itsMaxStack = itsStackDepth;\r
- break;\r
-\r
- case TokenStream.INC :\r
- case TokenStream.DEC : {\r
- int childType = child.getType();\r
- switch (childType) {\r
- case TokenStream.GETVAR : {\r
- String name = child.getString();\r
- if (itsData.itsNeedsActivation) {\r
- iCodeTop = addByte((byte) TokenStream.SCOPE, iCodeTop);\r
- iCodeTop = addByte((byte) TokenStream.STRING, iCodeTop);\r
- iCodeTop = addString(name, iCodeTop);\r
- itsStackDepth += 2;\r
- if (itsStackDepth > itsData.itsMaxStack)\r
- itsData.itsMaxStack = itsStackDepth;\r
- iCodeTop = addByte((byte)\r
- (type == TokenStream.INC\r
- ? TokenStream.PROPINC \r
- : TokenStream.PROPDEC),\r
- iCodeTop);\r
- itsStackDepth--; \r
- }\r
- else {\r
- iCodeTop = addByte((byte)\r
- (type == TokenStream.INC\r
- ? TokenStream.VARINC\r
- : TokenStream.VARDEC),\r
- iCodeTop);\r
- int i = itsVariableTable.getOrdinal(name);\r
- iCodeTop = addByte((byte)i, iCodeTop);\r
- itsStackDepth++;\r
- if (itsStackDepth > itsData.itsMaxStack)\r
- itsData.itsMaxStack = itsStackDepth;\r
- }\r
- }\r
- break;\r
- case TokenStream.GETPROP :\r
- case TokenStream.GETELEM : {\r
- Node getPropChild = child.getFirstChild();\r
- iCodeTop = generateICode(getPropChild,\r
- iCodeTop);\r
- getPropChild = getPropChild.getNextSibling();\r
- iCodeTop = generateICode(getPropChild,\r
- iCodeTop);\r
- if (childType == TokenStream.GETPROP)\r
- iCodeTop = addByte((byte)\r
- (type == TokenStream.INC\r
- ? TokenStream.PROPINC \r
- : TokenStream.PROPDEC),\r
- iCodeTop);\r
- else \r
- iCodeTop = addByte((byte)\r
- (type == TokenStream.INC\r
- ? TokenStream.ELEMINC \r
- : TokenStream.ELEMDEC),\r
- iCodeTop);\r
- itsStackDepth--; \r
- }\r
- break;\r
- default : {\r
- iCodeTop = addByte((byte)\r
- (type == TokenStream.INC \r
- ? TokenStream.NAMEINC \r
- : TokenStream.NAMEDEC),\r
- iCodeTop);\r
- iCodeTop = addString(child.getString(), \r
- iCodeTop);\r
- itsStackDepth++;\r
- if (itsStackDepth > itsData.itsMaxStack)\r
- itsData.itsMaxStack = itsStackDepth;\r
- }\r
- break;\r
- }\r
- }\r
- break;\r
-\r
- case TokenStream.NUMBER : {\r
- double num = node.getDouble();\r
- if (num == 0.0) {\r
- iCodeTop = addByte((byte) TokenStream.ZERO, iCodeTop);\r
- }\r
- else if (num == 1.0) {\r
- iCodeTop = addByte((byte) TokenStream.ONE, iCodeTop);\r
- }\r
- else {\r
- iCodeTop = addByte((byte) TokenStream.NUMBER, iCodeTop);\r
- iCodeTop = addNumber(num, iCodeTop);\r
- }\r
- itsStackDepth++;\r
- if (itsStackDepth > itsData.itsMaxStack)\r
- itsData.itsMaxStack = itsStackDepth;\r
- break;\r
- }\r
-\r
- case TokenStream.POP :\r
- case TokenStream.POPV :\r
- iCodeTop = updateLineNumber(node, iCodeTop);\r
- case TokenStream.ENTERWITH :\r
- iCodeTop = generateICode(child, iCodeTop);\r
- iCodeTop = addByte((byte) type, iCodeTop);\r
- itsStackDepth--;\r
- break;\r
-\r
- case TokenStream.GETTHIS :\r
- iCodeTop = generateICode(child, iCodeTop);\r
- iCodeTop = addByte((byte) type, iCodeTop);\r
- break;\r
- \r
- case TokenStream.NEWSCOPE :\r
- iCodeTop = addByte((byte) type, iCodeTop);\r
- itsStackDepth++;\r
- if (itsStackDepth > itsData.itsMaxStack)\r
- itsData.itsMaxStack = itsStackDepth;\r
- break;\r
-\r
- case TokenStream.LEAVEWITH :\r
- iCodeTop = addByte((byte) type, iCodeTop);\r
- break;\r
-\r
- case TokenStream.TRY : {\r
- itsTryDepth++;\r
- if (itsTryDepth > itsData.itsMaxTryDepth)\r
- itsData.itsMaxTryDepth = itsTryDepth;\r
- Node catchTarget = (Node)node.getProp(Node.TARGET_PROP);\r
- Node finallyTarget = (Node)node.getProp(Node.FINALLY_PROP);\r
- if (catchTarget == null) {\r
- iCodeTop = addByte((byte) TokenStream.TRY, iCodeTop);\r
- iCodeTop = addByte((byte)0, iCodeTop);\r
- iCodeTop = addByte((byte)0, iCodeTop);\r
- }\r
- else\r
- iCodeTop = \r
- addGoto(node, TokenStream.TRY, iCodeTop);\r
- int finallyHandler = 0;\r
- if (finallyTarget != null) {\r
- finallyHandler = acquireLabel();\r
- int theLabel = finallyHandler & 0x7FFFFFFF;\r
- itsLabelTable[theLabel].addFixup(iCodeTop);\r
- }\r
- iCodeTop = addByte((byte)0, iCodeTop);\r
- iCodeTop = addByte((byte)0, iCodeTop);\r
- \r
- Node lastChild = null;\r
- /*\r
- when we encounter the child of the catchTarget, we\r
- set the stackDepth to 1 to account for the incoming\r
- exception object.\r
- */\r
- boolean insertedEndTry = false;\r
- while (child != null) {\r
- if (catchTarget != null && lastChild == catchTarget) {\r
- itsStackDepth = 1;\r
- if (itsStackDepth > itsData.itsMaxStack)\r
- itsData.itsMaxStack = itsStackDepth;\r
- }\r
- /*\r
- When the following child is the catchTarget\r
- (or the finallyTarget if there are no catches),\r
- the current child is the goto at the end of\r
- the try statemets, we need to emit the endtry\r
- before that goto.\r
- */\r
- Node nextSibling = child.getNextSibling();\r
- if (!insertedEndTry && nextSibling != null &&\r
- (nextSibling == catchTarget ||\r
- nextSibling == finallyTarget))\r
- {\r
- iCodeTop = addByte((byte) TokenStream.ENDTRY,\r
- iCodeTop);\r
- insertedEndTry = true;\r
- }\r
- iCodeTop = generateICode(child, iCodeTop);\r
- lastChild = child;\r
- child = child.getNextSibling();\r
- }\r
- itsStackDepth = 0;\r
- if (finallyTarget != null) {\r
- // normal flow goes around the finally handler stublet\r
- int skippy = acquireLabel();\r
- iCodeTop = \r
- addGoto(skippy, TokenStream.GOTO, iCodeTop);\r
- // on entry the stack will have the exception object\r
- markLabel(finallyHandler, iCodeTop);\r
- itsStackDepth = 1;\r
- if (itsStackDepth > itsData.itsMaxStack)\r
- itsData.itsMaxStack = itsStackDepth;\r
- int theLocalSlot = itsData.itsMaxLocals++;\r
- iCodeTop = addByte((byte) TokenStream.NEWTEMP, iCodeTop);\r
- iCodeTop = addByte((byte)theLocalSlot, iCodeTop);\r
- iCodeTop = addByte((byte) TokenStream.POP, iCodeTop);\r
- Integer finallyLabel \r
- = (Integer)(finallyTarget.getProp(Node.LABEL_PROP));\r
- iCodeTop = addGoto(finallyLabel.intValue(), \r
- TokenStream.GOSUB, iCodeTop);\r
- iCodeTop = addByte((byte) TokenStream.USETEMP, iCodeTop);\r
- iCodeTop = addByte((byte)theLocalSlot, iCodeTop);\r
- iCodeTop = addByte((byte) TokenStream.JTHROW, iCodeTop);\r
- itsStackDepth = 0;\r
- markLabel(skippy, iCodeTop);\r
- }\r
- itsTryDepth--;\r
- }\r
- break;\r
- \r
- case TokenStream.THROW :\r
- iCodeTop = updateLineNumber(node, iCodeTop);\r
- iCodeTop = generateICode(child, iCodeTop);\r
- iCodeTop = addByte((byte) TokenStream.THROW, iCodeTop);\r
- itsStackDepth--;\r
- break;\r
- \r
- case TokenStream.ASSERT:\r
- iCodeTop = updateLineNumber(node, iCodeTop);\r
- if (child != null) \r
- iCodeTop = generateICode(child, iCodeTop);\r
- else {\r
- iCodeTop = addByte((byte) TokenStream.UNDEFINED, iCodeTop);\r
- itsStackDepth++;\r
- if (itsStackDepth > itsData.itsMaxStack)\r
- itsData.itsMaxStack = itsStackDepth;\r
- }\r
- iCodeTop = addGoto(node, TokenStream.ASSERT, iCodeTop);\r
- itsStackDepth--;\r
- break;\r
- \r
- case TokenStream.RETURN :\r
- iCodeTop = updateLineNumber(node, iCodeTop);\r
- if (child != null) \r
- iCodeTop = generateICode(child, iCodeTop);\r
- else {\r
- iCodeTop = addByte((byte) TokenStream.UNDEFINED, iCodeTop);\r
- itsStackDepth++;\r
- if (itsStackDepth > itsData.itsMaxStack)\r
- itsData.itsMaxStack = itsStackDepth;\r
- }\r
- iCodeTop = addGoto(node, TokenStream.RETURN, iCodeTop);\r
- itsStackDepth--;\r
- break;\r
- \r
- case TokenStream.GETVAR : {\r
- String name = node.getString();\r
- if (itsData.itsNeedsActivation) {\r
- // SETVAR handled this by turning into a SETPROP, but\r
- // we can't do that to a GETVAR without manufacturing\r
- // bogus children. Instead we use a special op to\r
- // push the current scope.\r
- iCodeTop = addByte((byte) TokenStream.SCOPE, iCodeTop);\r
- iCodeTop = addByte((byte) TokenStream.STRING, iCodeTop);\r
- iCodeTop = addString(name, iCodeTop);\r
- itsStackDepth += 2;\r
- if (itsStackDepth > itsData.itsMaxStack)\r
- itsData.itsMaxStack = itsStackDepth;\r
- iCodeTop = addByte((byte) TokenStream.GETPROP, iCodeTop);\r
- itsStackDepth--;\r
- }\r
- else {\r
- int index = itsVariableTable.getOrdinal(name);\r
- iCodeTop = addByte((byte) TokenStream.GETVAR, iCodeTop);\r
- iCodeTop = addByte((byte)index, iCodeTop);\r
- itsStackDepth++;\r
- if (itsStackDepth > itsData.itsMaxStack)\r
- itsData.itsMaxStack = itsStackDepth;\r
- }\r
- }\r
- break;\r
- \r
- case TokenStream.SETVAR : {\r
- if (itsData.itsNeedsActivation) {\r
- child.setType(TokenStream.BINDNAME);\r
- node.setType(TokenStream.SETNAME);\r
- iCodeTop = generateICode(node, iCodeTop);\r
- }\r
- else {\r
- String name = child.getString();\r
- child = child.getNextSibling();\r
- iCodeTop = generateICode(child, iCodeTop);\r
- int index = itsVariableTable.getOrdinal(name);\r
- iCodeTop = addByte((byte) TokenStream.SETVAR, iCodeTop);\r
- iCodeTop = addByte((byte)index, iCodeTop);\r
- }\r
- }\r
- break;\r
- \r
- case TokenStream.PRIMARY:\r
- iCodeTop = addByte((byte) node.getInt(), iCodeTop);\r
- itsStackDepth++;\r
- if (itsStackDepth > itsData.itsMaxStack)\r
- itsData.itsMaxStack = itsStackDepth;\r
- break;\r
-\r
- case TokenStream.ENUMINIT :\r
- iCodeTop = generateICode(child, iCodeTop);\r
- iCodeTop = addByte((byte) TokenStream.ENUMINIT, iCodeTop);\r
- iCodeTop = addLocalRef(node, iCodeTop);\r
- itsStackDepth--;\r
- break;\r
- \r
- case TokenStream.ENUMNEXT : {\r
- iCodeTop = addByte((byte) TokenStream.ENUMNEXT, iCodeTop);\r
- Node init = (Node)node.getProp(Node.ENUM_PROP);\r
- iCodeTop = addLocalRef(init, iCodeTop);\r
- itsStackDepth++;\r
- if (itsStackDepth > itsData.itsMaxStack)\r
- itsData.itsMaxStack = itsStackDepth;\r
- } \r
- break;\r
- \r
- case TokenStream.ENUMDONE :\r
- // could release the local here??\r
- break;\r
- \r
- case TokenStream.OBJECT : {\r
- Node regexp = (Node) node.getProp(Node.REGEXP_PROP);\r
- int index = ((Integer)(regexp.getProp(\r
- Node.REGEXP_PROP))).intValue();\r
- iCodeTop = addByte((byte) TokenStream.OBJECT, iCodeTop);\r
- iCodeTop = addByte((byte)(index >> 8), iCodeTop);\r
- iCodeTop = addByte((byte)(index & 0xff), iCodeTop);\r
- itsStackDepth++;\r
- if (itsStackDepth > itsData.itsMaxStack)\r
- itsData.itsMaxStack = itsStackDepth;\r
- }\r
- break;\r
- \r
- default : \r
- badTree(node);\r
- break;\r
- }\r
- return iCodeTop;\r
- }\r
- \r
- private int addLocalRef(Node node, int iCodeTop)\r
- {\r
- int theLocalSlot;\r
- Integer localProp = (Integer)node.getProp(Node.LOCAL_PROP);\r
- if (localProp == null) {\r
- theLocalSlot = itsData.itsMaxLocals++;\r
- node.putProp(Node.LOCAL_PROP, new Integer(theLocalSlot));\r
- }\r
- else\r
- theLocalSlot = localProp.intValue();\r
- iCodeTop = addByte((byte)theLocalSlot, iCodeTop);\r
- if (theLocalSlot >= itsData.itsMaxLocals)\r
- itsData.itsMaxLocals = theLocalSlot + 1;\r
- return iCodeTop; \r
- }\r
- \r
- private int addGoto(Node node, int gotoOp, int iCodeTop)\r
- {\r
- int targetLabel;\r
- if (node.getType() == TokenStream.RETURN || node.getType() == TokenStream.ASSERT) {\r
- if (itsEpilogLabel == -1)\r
- itsEpilogLabel = acquireLabel();\r
- targetLabel = itsEpilogLabel;\r
- }\r
- else {\r
- Node target = (Node)(node.getProp(Node.TARGET_PROP));\r
- Object lblObect = target.getProp(Node.LABEL_PROP);\r
- if (lblObect == null) {\r
- targetLabel = acquireLabel();\r
- target.putProp(Node.LABEL_PROP, new Integer(targetLabel));\r
- }\r
- else\r
- targetLabel = ((Integer)lblObect).intValue();\r
- }\r
- iCodeTop = addGoto(targetLabel, (byte) gotoOp, iCodeTop);\r
- return iCodeTop;\r
- }\r
- \r
- private int addGoto(int targetLabel, int gotoOp, int iCodeTop)\r
- {\r
- int gotoPC = iCodeTop;\r
- iCodeTop = addByte((byte) gotoOp, iCodeTop);\r
- int theLabel = targetLabel & 0x7FFFFFFF;\r
- int targetPC = itsLabelTable[theLabel].getPC();\r
- if (targetPC != -1) {\r
- short offset = (short)(targetPC - gotoPC);\r
- iCodeTop = addByte((byte)(offset >> 8), iCodeTop);\r
- iCodeTop = addByte((byte)offset, iCodeTop);\r
- }\r
- else {\r
- itsLabelTable[theLabel].addFixup(gotoPC + 1);\r
- iCodeTop = addByte((byte)0, iCodeTop);\r
- iCodeTop = addByte((byte)0, iCodeTop);\r
- }\r
- return iCodeTop;\r
- }\r
- \r
- private final int addByte(byte b, int iCodeTop) {\r
- if (itsData.itsICode.length == iCodeTop) {\r
- byte[] ba = new byte[iCodeTop * 2];\r
- System.arraycopy(itsData.itsICode, 0, ba, 0, iCodeTop);\r
- itsData.itsICode = ba;\r
- }\r
- itsData.itsICode[iCodeTop++] = b;\r
- return iCodeTop;\r
- }\r
- \r
- private final int addString(String str, int iCodeTop)\r
- {\r
- int index = itsData.itsStringTableIndex;\r
- if (itsData.itsStringTable.length == index) {\r
- String[] sa = new String[index * 2];\r
- System.arraycopy(itsData.itsStringTable, 0, sa, 0, index);\r
- itsData.itsStringTable = sa;\r
- }\r
- itsData.itsStringTable[index] = str;\r
- itsData.itsStringTableIndex = index + 1;\r
-\r
- iCodeTop = addByte((byte)(index >> 8), iCodeTop);\r
- iCodeTop = addByte((byte)(index & 0xFF), iCodeTop);\r
- return iCodeTop;\r
- }\r
- \r
- private final int addNumber(double num, int iCodeTop)\r
- {\r
- int index = itsData.itsNumberTableIndex;\r
- if (itsData.itsNumberTable.length == index) {\r
- double[] na = new double[index * 2];\r
- System.arraycopy(itsData.itsNumberTable, 0, na, 0, index);\r
- itsData.itsNumberTable = na;\r
- }\r
- itsData.itsNumberTable[index] = num;\r
- itsData.itsNumberTableIndex = index + 1;\r
-\r
- iCodeTop = addByte((byte)(index >> 8), iCodeTop);\r
- iCodeTop = addByte((byte)(index & 0xFF), iCodeTop);\r
- return iCodeTop;\r
- }\r
- \r
- private static String getString(String[] theStringTable, byte[] iCode, \r
- int pc)\r
- {\r
- int index = (iCode[pc] << 8) + (iCode[pc + 1] & 0xFF);\r
- return theStringTable[index];\r
- }\r
- \r
- private static double getNumber(double[] theNumberTable, byte[] iCode, \r
- int pc)\r
- {\r
- int index = (iCode[pc] << 8) + (iCode[pc + 1] & 0xFF);\r
- return theNumberTable[index];\r
- }\r
- \r
- private static int getTarget(byte[] iCode, int pc)\r
- {\r
- int displacement = (iCode[pc] << 8) + (iCode[pc + 1] & 0xFF);\r
- return pc - 1 + displacement;\r
- }\r
- \r
- static PrintWriter out;\r
- static {\r
- if (printICode) {\r
- try {\r
- out = new PrintWriter(new FileOutputStream("icode.txt"));\r
- out.close();\r
- }\r
- catch (IOException x) {\r
- }\r
- }\r
- } \r
- \r
- private static void dumpICode(InterpreterData theData) {\r
- if (printICode) {\r
- try {\r
- int iCodeLength = theData.itsICodeTop;\r
- byte iCode[] = theData.itsICode;\r
- \r
- out = new PrintWriter(new FileOutputStream("icode.txt", true));\r
- out.println("ICode dump, for " + theData.itsName + ", length = " + iCodeLength);\r
- out.println("MaxStack = " + theData.itsMaxStack);\r
- \r
- for (int pc = 0; pc < iCodeLength; ) {\r
- out.print("[" + pc + "] ");\r
- switch ((int)(iCode[pc] & 0xff)) {\r
- case TokenStream.SCOPE :\r
- case TokenStream.GETPROTO :\r
- case TokenStream.GETPARENT :\r
- case TokenStream.GETSCOPEPARENT :\r
- case TokenStream.SETPROTO :\r
- case TokenStream.SETPARENT :\r
- case TokenStream.DELPROP :\r
- case TokenStream.TYPEOF :\r
- case TokenStream.NEWSCOPE :\r
- case TokenStream.ENTERWITH :\r
- case TokenStream.LEAVEWITH :\r
- case TokenStream.ENDTRY :\r
- case TokenStream.THROW :\r
- case TokenStream.JTHROW :\r
- case TokenStream.GETTHIS :\r
- case TokenStream.SETELEM :\r
- case TokenStream.GETELEM :\r
- case TokenStream.SETPROP :\r
- case TokenStream.GETPROP :\r
- case TokenStream.PROPINC :\r
- case TokenStream.PROPDEC :\r
- case TokenStream.ELEMINC :\r
- case TokenStream.ELEMDEC :\r
- case TokenStream.BITNOT : \r
- case TokenStream.BITAND : \r
- case TokenStream.BITOR :\r
- case TokenStream.BITXOR :\r
- case TokenStream.LSH :\r
- case TokenStream.RSH :\r
- case TokenStream.URSH :\r
- case TokenStream.NEG :\r
- case TokenStream.POS :\r
- case TokenStream.SUB :\r
- case TokenStream.MUL :\r
- case TokenStream.DIV :\r
- case TokenStream.MOD :\r
- case TokenStream.ADD :\r
- case TokenStream.POPV :\r
- case TokenStream.POP :\r
- case TokenStream.DUP :\r
- case TokenStream.LT :\r
- case TokenStream.GT :\r
- case TokenStream.LE :\r
- case TokenStream.GE :\r
- case TokenStream.IN :\r
- case TokenStream.INSTANCEOF :\r
- case TokenStream.EQ :\r
- case TokenStream.NE :\r
- case TokenStream.SHEQ :\r
- case TokenStream.SHNE :\r
- case TokenStream.ZERO :\r
- case TokenStream.ONE :\r
- case TokenStream.NULL :\r
- case TokenStream.THIS :\r
- case TokenStream.THISFN :\r
- case TokenStream.FALSE :\r
- case TokenStream.TRUE :\r
- case TokenStream.UNDEFINED :\r
- case TokenStream.SOURCEFILE : \r
- out.println(TokenStream.tokenToName(iCode[pc] & 0xff));\r
- break;\r
- case TokenStream.GOSUB :\r
- case TokenStream.RETURN :\r
- case TokenStream.GOTO :\r
- case TokenStream.IFEQ :\r
- case TokenStream.IFNE : {\r
- int newPC = getTarget(iCode, pc + 1); \r
- out.println(\r
- TokenStream.tokenToName(iCode[pc] & 0xff) +\r
- " " + newPC);\r
- pc += 2;\r
- }\r
- break;\r
- case TokenStream.TRY : {\r
- int newPC1 = getTarget(iCode, pc + 1); \r
- int newPC2 = getTarget(iCode, pc + 3); \r
- out.println(\r
- TokenStream.tokenToName(iCode[pc] & 0xff) +\r
- " " + newPC1 +\r
- " " + newPC2);\r
- pc += 4;\r
- }\r
- break;\r
- case TokenStream.RETSUB : \r
- case TokenStream.ENUMINIT :\r
- case TokenStream.ENUMNEXT :\r
- case TokenStream.VARINC :\r
- case TokenStream.VARDEC :\r
- case TokenStream.GETVAR :\r
- case TokenStream.SETVAR :\r
- case TokenStream.NEWTEMP :\r
- case TokenStream.USETEMP : {\r
- int slot = (iCode[pc + 1] & 0xFF);\r
- out.println(\r
- TokenStream.tokenToName(iCode[pc] & 0xff) +\r
- " " + slot);\r
- pc++;\r
- }\r
- break;\r
- case TokenStream.CALLSPECIAL : {\r
- int line = (iCode[pc + 1] << 8) \r
- | (iCode[pc + 2] & 0xFF);\r
- String name = getString(theData.itsStringTable,\r
- iCode, pc + 3);\r
- int count = (iCode[pc + 5] << 8) | (iCode[pc + 6] & 0xFF);\r
- out.println(\r
- TokenStream.tokenToName(iCode[pc] & 0xff) +\r
- " " + count + " " + line + " " + name);\r
- pc += 6;\r
- }\r
- break;\r
- case TokenStream.OBJECT :\r
- case TokenStream.CLOSURE :\r
- case TokenStream.NEW :\r
- case TokenStream.CALL : {\r
- int count = (iCode[pc + 3] << 8) | (iCode[pc + 4] & 0xFF);\r
- out.println(\r
- TokenStream.tokenToName(iCode[pc] & 0xff) +\r
- " " + count + " \"" + \r
- getString(theData.itsStringTable, iCode, \r
- pc + 1) + "\"");\r
- pc += 5;\r
- }\r
- break;\r
- case TokenStream.NUMBER :\r
- out.println(\r
- TokenStream.tokenToName(iCode[pc] & 0xff) + \r
- " " + getNumber(theData.itsNumberTable,\r
- iCode, pc + 1));\r
- pc += 2;\r
- break;\r
- case TokenStream.TYPEOFNAME :\r
- case TokenStream.GETBASE :\r
- case TokenStream.BINDNAME :\r
- case TokenStream.SETNAME :\r
- case TokenStream.NAME :\r
- case TokenStream.NAMEINC :\r
- case TokenStream.NAMEDEC :\r
- case TokenStream.STRING :\r
- out.println(\r
- TokenStream.tokenToName(iCode[pc] & 0xff) +\r
- " \"" +\r
- getString(theData.itsStringTable, iCode, pc + 1) +\r
- "\"");\r
- pc += 2;\r
- break;\r
- case TokenStream.LINE : {\r
- int line = (iCode[pc + 1] << 8) | (iCode[pc + 2] & 0xFF);\r
- out.println(\r
- TokenStream.tokenToName(iCode[pc] & 0xff) + " : " + line);\r
- pc += 2;\r
- }\r
- break;\r
- default :\r
- out.close();\r
- throw new RuntimeException("Unknown icode : "\r
- + (iCode[pc] & 0xff) + " @ pc : " + pc);\r
- }\r
- pc++;\r
- }\r
- out.close();\r
- }\r
- catch (IOException x) {}\r
- }\r
- }\r
- \r
- private static void createFunctionObject(InterpretedFunction fn, \r
- Scriptable scope)\r
- {\r
- fn.setPrototype(ScriptableObject.getClassPrototype(scope, "Function"));\r
- fn.setParentScope(scope);\r
- InterpreterData id = fn.itsData;\r
- if (id.itsName.length() == 0)\r
- return;\r
- if ((id.itsFunctionType == FunctionNode.FUNCTION_STATEMENT &&\r
- fn.itsClosure == null) ||\r
- (id.itsFunctionType == FunctionNode.FUNCTION_EXPRESSION_STATEMENT &&\r
- fn.itsClosure != null))\r
- {\r
- ScriptRuntime.setProp(scope, fn.itsData.itsName, fn, scope);\r
- }\r
- }\r
- \r
- public static Object interpret(Context cx, Scriptable scope, \r
- Scriptable thisObj, Object[] args, \r
- NativeFunction fnOrScript,\r
- InterpreterData theData)\r
- throws JavaScriptException\r
- {\r
- int i;\r
- Object lhs;\r
-\r
- final int maxStack = theData.itsMaxStack;\r
- final int maxVars = (fnOrScript.argNames == null) \r
- ? 0 : fnOrScript.argNames.length;\r
- final int maxLocals = theData.itsMaxLocals;\r
- final int maxTryDepth = theData.itsMaxTryDepth;\r
- \r
- final int VAR_SHFT = maxStack; \r
- final int LOCAL_SHFT = VAR_SHFT + maxVars; \r
- final int TRY_SCOPE_SHFT = LOCAL_SHFT + maxLocals;\r
-\r
-// stack[0 <= i < VAR_SHFT]: stack data\r
-// stack[VAR_SHFT <= i < LOCAL_SHFT]: variables\r
-// stack[LOCAL_SHFT <= i < TRY_SCOPE_SHFT]: used for newtemp/usetemp\r
-// stack[TRY_SCOPE_SHFT <= i]: try scopes\r
-// when 0 <= i < LOCAL_SHFT and stack[x] == DBL_MRK, \r
-// sDbl[i] gives the number value\r
-\r
- final Object DBL_MRK = Interpreter.DBL_MRK;\r
- \r
- Object[] stack = new Object[TRY_SCOPE_SHFT + maxTryDepth];\r
- double[] sDbl = new double[TRY_SCOPE_SHFT];\r
- int stackTop = -1;\r
- byte[] iCode = theData.itsICode; \r
- int pc = 0;\r
- int iCodeLength = theData.itsICodeTop;\r
- \r
- final Scriptable undefined = Undefined.instance;\r
- if (maxVars != 0) {\r
- int definedArgs = fnOrScript.argCount;\r
- if (definedArgs != 0) {\r
- if (definedArgs > args.length) { definedArgs = args.length; }\r
- for (i = 0; i != definedArgs; ++i) {\r
- stack[VAR_SHFT + i] = args[i]; \r
- }\r
- }\r
- for (i = definedArgs; i != maxVars; ++i) {\r
- stack[VAR_SHFT + i] = undefined;\r
- }\r
- }\r
- \r
- if (theData.itsNestedFunctions != null) {\r
- for (i = 0; i < theData.itsNestedFunctions.length; i++)\r
- createFunctionObject(theData.itsNestedFunctions[i], scope);\r
- } \r
-\r
- Object id;\r
- Object rhs, val;\r
- double valDbl;\r
- boolean valBln;\r
-\r
- int count;\r
- int slot;\r
- \r
- String name = null;\r
- \r
- Object[] outArgs;\r
-\r
- int lIntValue;\r
- long lLongValue;\r
- double lDbl;\r
- int rIntValue;\r
- double rDbl;\r
- \r
- int[] catchStack = null;\r
- int tryStackTop = 0;\r
- InterpreterFrame frame = null;\r
- \r
- if (cx.debugger != null) {\r
- frame = new InterpreterFrame(scope, theData, fnOrScript);\r
- cx.pushFrame(frame);\r
- }\r
- \r
- if (maxTryDepth != 0) {\r
- // catchStack[2 * i]: starting pc of catch block\r
- // catchStack[2 * i + 1]: starting pc of finally block\r
- catchStack = new int[maxTryDepth * 2];\r
- }\r
- \r
- /* Save the security domain. Must restore upon normal exit. \r
- * If we exit the interpreter loop by throwing an exception,\r
- * set cx.interpreterSecurityDomain to null, and require the\r
- * catching function to restore it.\r
- */\r
- Object savedSecurityDomain = cx.interpreterSecurityDomain;\r
- cx.interpreterSecurityDomain = theData.securityDomain;\r
- Object result = undefined;\r
- \r
- int pcPrevBranch = pc;\r
- final int instructionThreshold = cx.instructionThreshold;\r
- // During function call this will be set to -1 so catch can properly\r
- // adjust it\r
- int instructionCount = cx.instructionCount;\r
- // arbitrary number to add to instructionCount when calling \r
- // other functions\r
- final int INVOCATION_COST = 100;\r
- \r
- while (pc < iCodeLength) {\r
- try {\r
- switch (iCode[pc] & 0xff) {\r
- case TokenStream.ENDTRY :\r
- tryStackTop--;\r
- break;\r
- case TokenStream.TRY :\r
- i = getTarget(iCode, pc + 1);\r
- if (i == pc) i = 0;\r
- catchStack[tryStackTop * 2] = i;\r
- i = getTarget(iCode, pc + 3);\r
- if (i == (pc + 2)) i = 0;\r
- catchStack[tryStackTop * 2 + 1] = i;\r
- stack[TRY_SCOPE_SHFT + tryStackTop] = scope;\r
- ++tryStackTop;\r
- pc += 4;\r
- break;\r
- case TokenStream.GE :\r
- --stackTop;\r
- rhs = stack[stackTop + 1]; \r
- lhs = stack[stackTop];\r
- if (rhs == DBL_MRK || lhs == DBL_MRK) {\r
- rDbl = stack_double(stack, sDbl, stackTop + 1);\r
- lDbl = stack_double(stack, sDbl, stackTop);\r
- valBln = (rDbl == rDbl && lDbl == lDbl \r
- && rDbl <= lDbl);\r
- }\r
- else {\r
- valBln = (1 == ScriptRuntime.cmp_LE(rhs, lhs));\r
- }\r
- stack[stackTop] = valBln ? Boolean.TRUE : Boolean.FALSE;\r
- break;\r
- case TokenStream.LE :\r
- --stackTop;\r
- rhs = stack[stackTop + 1]; \r
- lhs = stack[stackTop];\r
- if (rhs == DBL_MRK || lhs == DBL_MRK) {\r
- rDbl = stack_double(stack, sDbl, stackTop + 1);\r
- lDbl = stack_double(stack, sDbl, stackTop);\r
- valBln = (rDbl == rDbl && lDbl == lDbl \r
- && lDbl <= rDbl);\r
- }\r
- else {\r
- valBln = (1 == ScriptRuntime.cmp_LE(lhs, rhs));\r
- }\r
- stack[stackTop] = valBln ? Boolean.TRUE : Boolean.FALSE;\r
- break;\r
- case TokenStream.GT :\r
- --stackTop;\r
- rhs = stack[stackTop + 1]; \r
- lhs = stack[stackTop];\r
- if (rhs == DBL_MRK || lhs == DBL_MRK) {\r
- rDbl = stack_double(stack, sDbl, stackTop + 1);\r
- lDbl = stack_double(stack, sDbl, stackTop);\r
- valBln = (rDbl == rDbl && lDbl == lDbl \r
- && rDbl < lDbl);\r
- }\r
- else {\r
- valBln = (1 == ScriptRuntime.cmp_LT(rhs, lhs));\r
- }\r
- stack[stackTop] = valBln ? Boolean.TRUE : Boolean.FALSE;\r
- break;\r
- case TokenStream.LT :\r
- --stackTop;\r
- rhs = stack[stackTop + 1]; \r
- lhs = stack[stackTop];\r
- if (rhs == DBL_MRK || lhs == DBL_MRK) {\r
- rDbl = stack_double(stack, sDbl, stackTop + 1);\r
- lDbl = stack_double(stack, sDbl, stackTop);\r
- valBln = (rDbl == rDbl && lDbl == lDbl \r
- && lDbl < rDbl);\r
- }\r
- else {\r
- valBln = (1 == ScriptRuntime.cmp_LT(lhs, rhs));\r
- }\r
- stack[stackTop] = valBln ? Boolean.TRUE : Boolean.FALSE;\r
- break;\r
- case TokenStream.IN :\r
- rhs = stack[stackTop]; \r
- if (rhs == DBL_MRK) rhs = doubleWrap(sDbl[stackTop]);\r
- --stackTop;\r
- lhs = stack[stackTop]; \r
- if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);\r
- valBln = ScriptRuntime.in(lhs, rhs, scope);\r
- stack[stackTop] = valBln ? Boolean.TRUE : Boolean.FALSE;\r
- break;\r
- case TokenStream.INSTANCEOF :\r
- rhs = stack[stackTop]; \r
- if (rhs == DBL_MRK) rhs = doubleWrap(sDbl[stackTop]);\r
- --stackTop;\r
- lhs = stack[stackTop]; \r
- if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);\r
- valBln = ScriptRuntime.instanceOf(scope, lhs, rhs);\r
- stack[stackTop] = valBln ? Boolean.TRUE : Boolean.FALSE;\r
- break;\r
- case TokenStream.EQ :\r
- --stackTop;\r
- valBln = do_eq(stack, sDbl, stackTop);\r
- stack[stackTop] = valBln ? Boolean.TRUE : Boolean.FALSE;\r
- break;\r
- case TokenStream.NE :\r
- --stackTop;\r
- valBln = !do_eq(stack, sDbl, stackTop);\r
- stack[stackTop] = valBln ? Boolean.TRUE : Boolean.FALSE;\r
- break;\r
- case TokenStream.SHEQ :\r
- --stackTop;\r
- valBln = do_sheq(stack, sDbl, stackTop);\r
- stack[stackTop] = valBln ? Boolean.TRUE : Boolean.FALSE;\r
- break;\r
- case TokenStream.SHNE :\r
- --stackTop;\r
- valBln = !do_sheq(stack, sDbl, stackTop);\r
- stack[stackTop] = valBln ? Boolean.TRUE : Boolean.FALSE;\r
- break;\r
- case TokenStream.IFNE :\r
- val = stack[stackTop];\r
- if (val != DBL_MRK) {\r
- valBln = !ScriptRuntime.toBoolean(val);\r
- }\r
- else {\r
- valDbl = sDbl[stackTop];\r
- valBln = !(valDbl == valDbl && valDbl != 0.0);\r
- }\r
- --stackTop;\r
- if (valBln) {\r
- if (instructionThreshold != 0) {\r
- instructionCount += pc + 3 - pcPrevBranch;\r
- if (instructionCount > instructionThreshold) {\r
- cx.observeInstructionCount\r
- (instructionCount);\r
- instructionCount = 0;\r
- }\r
- }\r
- pcPrevBranch = pc = getTarget(iCode, pc + 1);\r
- continue;\r
- }\r
- pc += 2;\r
- break;\r
- case TokenStream.IFEQ :\r
- val = stack[stackTop];\r
- if (val != DBL_MRK) {\r
- valBln = ScriptRuntime.toBoolean(val);\r
- }\r
- else {\r
- valDbl = sDbl[stackTop];\r
- valBln = (valDbl == valDbl && valDbl != 0.0);\r
- }\r
- --stackTop;\r
- if (valBln) {\r
- if (instructionThreshold != 0) {\r
- instructionCount += pc + 3 - pcPrevBranch;\r
- if (instructionCount > instructionThreshold) {\r
- cx.observeInstructionCount\r
- (instructionCount);\r
- instructionCount = 0;\r
- }\r
- }\r
- pcPrevBranch = pc = getTarget(iCode, pc + 1);\r
- continue;\r
- }\r
- pc += 2;\r
- break;\r
- case TokenStream.GOTO :\r
- if (instructionThreshold != 0) {\r
- instructionCount += pc + 3 - pcPrevBranch;\r
- if (instructionCount > instructionThreshold) {\r
- cx.observeInstructionCount(instructionCount);\r
- instructionCount = 0;\r
- }\r
- }\r
- pcPrevBranch = pc = getTarget(iCode, pc + 1);\r
- continue;\r
- case TokenStream.GOSUB :\r
- sDbl[++stackTop] = pc + 3;\r
- if (instructionThreshold != 0) {\r
- instructionCount += pc + 3 - pcPrevBranch;\r
- if (instructionCount > instructionThreshold) {\r
- cx.observeInstructionCount(instructionCount);\r
- instructionCount = 0;\r
- }\r
- }\r
- pcPrevBranch = pc = getTarget(iCode, pc + 1); continue;\r
- case TokenStream.RETSUB :\r
- slot = (iCode[pc + 1] & 0xFF);\r
- if (instructionThreshold != 0) {\r
- instructionCount += pc + 2 - pcPrevBranch;\r
- if (instructionCount > instructionThreshold) {\r
- cx.observeInstructionCount(instructionCount);\r
- instructionCount = 0;\r
- }\r
- }\r
- pcPrevBranch = pc = (int)sDbl[LOCAL_SHFT + slot];\r
- continue;\r
- case TokenStream.POP :\r
- stackTop--;\r
- break;\r
- case TokenStream.DUP :\r
- stack[stackTop + 1] = stack[stackTop];\r
- sDbl[stackTop + 1] = sDbl[stackTop];\r
- stackTop++;\r
- break;\r
- case TokenStream.POPV :\r
- result = stack[stackTop]; \r
- if (result == DBL_MRK) \r
- result = doubleWrap(sDbl[stackTop]);\r
- --stackTop;\r
- break;\r
- case TokenStream.RETURN :\r
- result = stack[stackTop]; \r
- if (result == DBL_MRK) \r
- result = doubleWrap(sDbl[stackTop]);\r
- --stackTop;\r
- pc = getTarget(iCode, pc + 1);\r
- break;\r
- case TokenStream.ASSERT :\r
- val = stack[stackTop];\r
- if (val != DBL_MRK) {\r
- valBln = ScriptRuntime.toBoolean(val);\r
- } else {\r
- valDbl = sDbl[stackTop];\r
- valBln = (valDbl == valDbl && valDbl != 0.0);\r
- }\r
- --stackTop;\r
- if (!valBln) {\r
- throw new Error("assertion failed");\r
- //System.exit(-1);\r
- }\r
- pc += 2;\r
- break;\r
- case TokenStream.BITNOT :\r
- rIntValue = stack_int32(stack, sDbl, stackTop);\r
- stack[stackTop] = DBL_MRK;\r
- sDbl[stackTop] = ~rIntValue;\r
- break;\r
- case TokenStream.BITAND : \r
- rIntValue = stack_int32(stack, sDbl, stackTop);\r
- --stackTop;\r
- lIntValue = stack_int32(stack, sDbl, stackTop);\r
- stack[stackTop] = DBL_MRK;\r
- sDbl[stackTop] = lIntValue & rIntValue;\r
- break;\r
- case TokenStream.BITOR :\r
- rIntValue = stack_int32(stack, sDbl, stackTop);\r
- --stackTop;\r
- lIntValue = stack_int32(stack, sDbl, stackTop);\r
- stack[stackTop] = DBL_MRK;\r
- sDbl[stackTop] = lIntValue | rIntValue;\r
- break;\r
- case TokenStream.BITXOR :\r
- rIntValue = stack_int32(stack, sDbl, stackTop);\r
- --stackTop;\r
- lIntValue = stack_int32(stack, sDbl, stackTop);\r
- stack[stackTop] = DBL_MRK;\r
- sDbl[stackTop] = lIntValue ^ rIntValue;\r
- break;\r
- case TokenStream.LSH :\r
- rIntValue = stack_int32(stack, sDbl, stackTop);\r
- --stackTop;\r
- lIntValue = stack_int32(stack, sDbl, stackTop);\r
- stack[stackTop] = DBL_MRK;\r
- sDbl[stackTop] = lIntValue << rIntValue;\r
- break;\r
- case TokenStream.RSH :\r
- rIntValue = stack_int32(stack, sDbl, stackTop);\r
- --stackTop;\r
- lIntValue = stack_int32(stack, sDbl, stackTop);\r
- stack[stackTop] = DBL_MRK;\r
- sDbl[stackTop] = lIntValue >> rIntValue;\r
- break;\r
- case TokenStream.URSH :\r
- rIntValue = stack_int32(stack, sDbl, stackTop) & 0x1F;\r
- --stackTop;\r
- lLongValue = stack_uint32(stack, sDbl, stackTop);\r
- stack[stackTop] = DBL_MRK;\r
- sDbl[stackTop] = lLongValue >>> rIntValue;\r
- break;\r
- case TokenStream.ADD :\r
- --stackTop;\r
- do_add(stack, sDbl, stackTop);\r
- break;\r
- case TokenStream.SUB :\r
- rDbl = stack_double(stack, sDbl, stackTop);\r
- --stackTop;\r
- lDbl = stack_double(stack, sDbl, stackTop);\r
- stack[stackTop] = DBL_MRK;\r
- sDbl[stackTop] = lDbl - rDbl;\r
- break;\r
- case TokenStream.NEG :\r
- rDbl = stack_double(stack, sDbl, stackTop);\r
- stack[stackTop] = DBL_MRK;\r
- sDbl[stackTop] = -rDbl;\r
- break;\r
- case TokenStream.POS :\r
- rDbl = stack_double(stack, sDbl, stackTop);\r
- stack[stackTop] = DBL_MRK;\r
- sDbl[stackTop] = rDbl;\r
- break;\r
- case TokenStream.MUL :\r
- rDbl = stack_double(stack, sDbl, stackTop);\r
- --stackTop;\r
- lDbl = stack_double(stack, sDbl, stackTop);\r
- stack[stackTop] = DBL_MRK;\r
- sDbl[stackTop] = lDbl * rDbl;\r
- break;\r
- case TokenStream.DIV :\r
- rDbl = stack_double(stack, sDbl, stackTop);\r
- --stackTop;\r
- lDbl = stack_double(stack, sDbl, stackTop);\r
- stack[stackTop] = DBL_MRK;\r
- // Detect the divide by zero or let Java do it ?\r
- sDbl[stackTop] = lDbl / rDbl;\r
- break;\r
- case TokenStream.MOD :\r
- rDbl = stack_double(stack, sDbl, stackTop);\r
- --stackTop;\r
- lDbl = stack_double(stack, sDbl, stackTop);\r
- stack[stackTop] = DBL_MRK;\r
- sDbl[stackTop] = lDbl % rDbl;\r
- break;\r
- case TokenStream.BINDNAME :\r
- stack[++stackTop] = \r
- ScriptRuntime.bind(scope, \r
- getString(theData.itsStringTable, \r
- iCode, pc + 1));\r
- pc += 2;\r
- break;\r
- case TokenStream.GETBASE :\r
- stack[++stackTop] =\r
- ScriptRuntime.getBase(scope, \r
- getString(theData.itsStringTable,\r
- iCode, pc + 1));\r
- pc += 2;\r
- break;\r
- case TokenStream.SETNAME :\r
- rhs = stack[stackTop]; \r
- if (rhs == DBL_MRK) rhs = doubleWrap(sDbl[stackTop]);\r
- --stackTop;\r
- lhs = stack[stackTop]; \r
- if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);\r
- // what about class cast exception here ?\r
- stack[stackTop] = ScriptRuntime.setName\r
- ((Scriptable)lhs, rhs, scope, \r
- getString(theData.itsStringTable, iCode, pc + 1));\r
- pc += 2;\r
- break;\r
- case TokenStream.DELPROP :\r
- rhs = stack[stackTop]; \r
- if (rhs == DBL_MRK) rhs = doubleWrap(sDbl[stackTop]);\r
- --stackTop;\r
- lhs = stack[stackTop]; \r
- if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);\r
- stack[stackTop] = ScriptRuntime.delete(lhs, rhs);\r
- break;\r
- case TokenStream.GETPROP :\r
- name = (String)stack[stackTop];\r
- --stackTop;\r
- lhs = stack[stackTop]; \r
- if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);\r
- stack[stackTop] \r
- = ScriptRuntime.getProp(lhs, name, scope);\r
- break;\r
- case TokenStream.SETPROP :\r
- rhs = stack[stackTop]; \r
- if (rhs == DBL_MRK) rhs = doubleWrap(sDbl[stackTop]);\r
- --stackTop;\r
- name = (String)stack[stackTop];\r
- --stackTop;\r
- lhs = stack[stackTop]; \r
- if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);\r
- stack[stackTop] \r
- = ScriptRuntime.setProp(lhs, name, rhs, scope);\r
- break;\r
- case TokenStream.GETELEM :\r
- id = stack[stackTop]; \r
- if (id == DBL_MRK) id = doubleWrap(sDbl[stackTop]);\r
- --stackTop;\r
- lhs = stack[stackTop]; \r
- if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);\r
- stack[stackTop] \r
- = ScriptRuntime.getElem(lhs, id, scope);\r
- break;\r
- case TokenStream.SETELEM :\r
- rhs = stack[stackTop]; \r
- if (rhs == DBL_MRK) rhs = doubleWrap(sDbl[stackTop]);\r
- --stackTop;\r
- id = stack[stackTop]; \r
- if (id == DBL_MRK) id = doubleWrap(sDbl[stackTop]);\r
- --stackTop;\r
- lhs = stack[stackTop]; \r
- if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);\r
- stack[stackTop] \r
- = ScriptRuntime.setElem(lhs, id, rhs, scope);\r
- break;\r
- case TokenStream.PROPINC :\r
- name = (String)stack[stackTop];\r
- --stackTop;\r
- lhs = stack[stackTop]; \r
- if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);\r
- stack[stackTop] \r
- = ScriptRuntime.postIncrement(lhs, name, scope);\r
- break;\r
- case TokenStream.PROPDEC :\r
- name = (String)stack[stackTop];\r
- --stackTop;\r
- lhs = stack[stackTop]; \r
- if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);\r
- stack[stackTop] \r
- = ScriptRuntime.postDecrement(lhs, name, scope);\r
- break;\r
- case TokenStream.ELEMINC :\r
- rhs = stack[stackTop]; \r
- if (rhs == DBL_MRK) rhs = doubleWrap(sDbl[stackTop]);\r
- --stackTop;\r
- lhs = stack[stackTop]; \r
- if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);\r
- stack[stackTop] \r
- = ScriptRuntime.postIncrementElem(lhs, rhs, scope);\r
- break;\r
- case TokenStream.ELEMDEC :\r
- rhs = stack[stackTop]; \r
- if (rhs == DBL_MRK) rhs = doubleWrap(sDbl[stackTop]);\r
- --stackTop;\r
- lhs = stack[stackTop]; \r
- if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);\r
- stack[stackTop] \r
- = ScriptRuntime.postDecrementElem(lhs, rhs, scope);\r
- break;\r
- case TokenStream.GETTHIS :\r
- lhs = stack[stackTop]; \r
- if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);\r
- stack[stackTop] \r
- = ScriptRuntime.getThis((Scriptable)lhs);\r
- break;\r
- case TokenStream.NEWTEMP :\r
- slot = (iCode[++pc] & 0xFF);\r
- stack[LOCAL_SHFT + slot] = stack[stackTop];\r
- sDbl[LOCAL_SHFT + slot] = sDbl[stackTop];\r
- break;\r
- case TokenStream.USETEMP :\r
- slot = (iCode[++pc] & 0xFF);\r
- ++stackTop;\r
- stack[stackTop] = stack[LOCAL_SHFT + slot];\r
- sDbl[stackTop] = sDbl[LOCAL_SHFT + slot];\r
- break;\r
- case TokenStream.CALLSPECIAL :\r
- if (instructionThreshold != 0) {\r
- instructionCount += INVOCATION_COST;\r
- cx.instructionCount = instructionCount;\r
- instructionCount = -1;\r
- }\r
- int lineNum = (iCode[pc + 1] << 8) \r
- | (iCode[pc + 2] & 0xFF); \r
- name = getString(theData.itsStringTable, iCode, pc + 3);\r
- count = (iCode[pc + 5] << 8) | (iCode[pc + 6] & 0xFF);\r
- outArgs = new Object[count];\r
- for (i = count - 1; i >= 0; i--) {\r
- val = stack[stackTop]; \r
- if (val == DBL_MRK) \r
- val = doubleWrap(sDbl[stackTop]);\r
- outArgs[i] = val;\r
- --stackTop;\r
- }\r
- rhs = stack[stackTop]; \r
- if (rhs == DBL_MRK) rhs = doubleWrap(sDbl[stackTop]);\r
- --stackTop;\r
- lhs = stack[stackTop]; \r
- if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);\r
- stack[stackTop] = ScriptRuntime.callSpecial(\r
- cx, lhs, rhs, outArgs, \r
- thisObj, scope, name, lineNum);\r
- pc += 6;\r
- instructionCount = cx.instructionCount;\r
- break;\r
- case TokenStream.CALL :\r
- if (instructionThreshold != 0) {\r
- instructionCount += INVOCATION_COST;\r
- cx.instructionCount = instructionCount;\r
- instructionCount = -1;\r
- }\r
- cx.instructionCount = instructionCount;\r
- count = (iCode[pc + 3] << 8) | (iCode[pc + 4] & 0xFF);\r
- outArgs = new Object[count];\r
- for (i = count - 1; i >= 0; i--) {\r
- val = stack[stackTop]; \r
- if (val == DBL_MRK) \r
- val = doubleWrap(sDbl[stackTop]);\r
- outArgs[i] = val;\r
- --stackTop;\r
- }\r
- rhs = stack[stackTop]; \r
- if (rhs == DBL_MRK) rhs = doubleWrap(sDbl[stackTop]);\r
- --stackTop;\r
- lhs = stack[stackTop]; \r
- if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);\r
- if (lhs == undefined) {\r
- lhs = getString(theData.itsStringTable, iCode, \r
- pc + 1);\r
- }\r
- Scriptable calleeScope = scope;\r
- if (theData.itsNeedsActivation) {\r
- calleeScope = ScriptableObject.\r
- getTopLevelScope(scope);\r
- }\r
- stack[stackTop] = ScriptRuntime.call(cx, lhs, rhs, \r
- outArgs, \r
- calleeScope);\r
- pc += 4; instructionCount = cx.instructionCount;\r
- break;\r
- case TokenStream.NEW :\r
- if (instructionThreshold != 0) {\r
- instructionCount += INVOCATION_COST;\r
- cx.instructionCount = instructionCount;\r
- instructionCount = -1;\r
- }\r
- count = (iCode[pc + 3] << 8) | (iCode[pc + 4] & 0xFF);\r
- outArgs = new Object[count];\r
- for (i = count - 1; i >= 0; i--) {\r
- val = stack[stackTop]; \r
- if (val == DBL_MRK) \r
- val = doubleWrap(sDbl[stackTop]);\r
- outArgs[i] = val;\r
- --stackTop;\r
- }\r
- lhs = stack[stackTop]; \r
- if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);\r
- if (lhs == undefined && \r
- (iCode[pc+1] << 8) + (iCode[pc+2] & 0xFF) != -1) \r
- {\r
- // special code for better error message for call \r
- // to undefined\r
- lhs = getString(theData.itsStringTable, iCode, \r
- pc + 1);\r
- }\r
- stack[stackTop] = ScriptRuntime.newObject(cx, lhs, \r
- outArgs, \r
- scope);\r
- pc += 4; instructionCount = cx.instructionCount;\r
- break;\r
- case TokenStream.TYPEOF :\r
- lhs = stack[stackTop]; \r
- if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);\r
- stack[stackTop] = ScriptRuntime.typeof(lhs);\r
- break;\r
- case TokenStream.TYPEOFNAME :\r
- name = getString(theData.itsStringTable, iCode, pc + 1);\r
- stack[++stackTop] \r
- = ScriptRuntime.typeofName(scope, name);\r
- pc += 2;\r
- break;\r
- case TokenStream.STRING :\r
- stack[++stackTop] = getString(theData.itsStringTable,\r
- iCode, pc + 1);\r
- pc += 2;\r
- break;\r
- case TokenStream.NUMBER :\r
- ++stackTop;\r
- stack[stackTop] = DBL_MRK;\r
- sDbl[stackTop] = getNumber(theData.itsNumberTable,\r
- iCode, pc + 1);\r
- pc += 2;\r
- break;\r
- case TokenStream.NAME :\r
- stack[++stackTop] = ScriptRuntime.name(scope,\r
- getString(theData.itsStringTable,\r
- iCode, pc + 1));\r
- pc += 2;\r
- break;\r
- case TokenStream.NAMEINC :\r
- stack[++stackTop] = ScriptRuntime.postIncrement(scope,\r
- getString(theData.itsStringTable,\r
- iCode, pc + 1));\r
- pc += 2;\r
- break;\r
- case TokenStream.NAMEDEC :\r
- stack[++stackTop] = ScriptRuntime.postDecrement(scope,\r
- getString(theData.itsStringTable,\r
- iCode, pc + 1));\r
- pc += 2;\r
- break;\r
- case TokenStream.SETVAR :\r
- slot = (iCode[++pc] & 0xFF);\r
- stack[VAR_SHFT + slot] = stack[stackTop];\r
- sDbl[VAR_SHFT + slot] = sDbl[stackTop];\r
- break;\r
- case TokenStream.GETVAR :\r
- slot = (iCode[++pc] & 0xFF);\r
- ++stackTop;\r
- stack[stackTop] = stack[VAR_SHFT + slot];\r
- sDbl[stackTop] = sDbl[VAR_SHFT + slot];\r
- break;\r
- case TokenStream.VARINC :\r
- slot = (iCode[++pc] & 0xFF);\r
- ++stackTop;\r
- stack[stackTop] = stack[VAR_SHFT + slot];\r
- sDbl[stackTop] = sDbl[VAR_SHFT + slot];\r
- stack[VAR_SHFT + slot] = DBL_MRK;\r
- sDbl[VAR_SHFT + slot] \r
- = stack_double(stack, sDbl, stackTop) + 1.0;\r
- break;\r
- case TokenStream.VARDEC :\r
- slot = (iCode[++pc] & 0xFF);\r
- ++stackTop;\r
- stack[stackTop] = stack[VAR_SHFT + slot];\r
- sDbl[stackTop] = sDbl[VAR_SHFT + slot];\r
- stack[VAR_SHFT + slot] = DBL_MRK;\r
- sDbl[VAR_SHFT + slot] \r
- = stack_double(stack, sDbl, stackTop) - 1.0;\r
- break;\r
- case TokenStream.ZERO :\r
- ++stackTop;\r
- stack[stackTop] = DBL_MRK;\r
- sDbl[stackTop] = 0;\r
- break;\r
- case TokenStream.ONE :\r
- ++stackTop;\r
- stack[stackTop] = DBL_MRK;\r
- sDbl[stackTop] = 1;\r
- break;\r
- case TokenStream.NULL :\r
- stack[++stackTop] = null;\r
- break;\r
- case TokenStream.THIS :\r
- stack[++stackTop] = thisObj;\r
- break;\r
- case TokenStream.THISFN :\r
- stack[++stackTop] = fnOrScript;\r
- break;\r
- case TokenStream.FALSE :\r
- stack[++stackTop] = Boolean.FALSE;\r
- break;\r
- case TokenStream.TRUE :\r
- stack[++stackTop] = Boolean.TRUE;\r
- break;\r
- case TokenStream.UNDEFINED :\r
- stack[++stackTop] = Undefined.instance;\r
- break;\r
- case TokenStream.THROW :\r
- result = stack[stackTop];\r
- if (result == DBL_MRK) \r
- result = doubleWrap(sDbl[stackTop]);\r
- --stackTop;\r
- throw new JavaScriptException(result);\r
- case TokenStream.JTHROW :\r
- result = stack[stackTop];\r
- // No need to check for DBL_MRK: result is Exception\r
- --stackTop;\r
- if (result instanceof JavaScriptException)\r
- throw (JavaScriptException)result;\r
- else\r
- throw (RuntimeException)result;\r
- case TokenStream.ENTERWITH :\r
- lhs = stack[stackTop]; \r
- if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);\r
- --stackTop;\r
- scope = ScriptRuntime.enterWith(lhs, scope);\r
- break;\r
- case TokenStream.LEAVEWITH :\r
- scope = ScriptRuntime.leaveWith(scope);\r
- break;\r
- case TokenStream.NEWSCOPE :\r
- stack[++stackTop] = ScriptRuntime.newScope();\r
- break;\r
- case TokenStream.ENUMINIT :\r
- slot = (iCode[++pc] & 0xFF);\r
- lhs = stack[stackTop]; \r
- if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);\r
- --stackTop;\r
- stack[LOCAL_SHFT + slot] \r
- = ScriptRuntime.initEnum(lhs, scope);\r
- break;\r
- case TokenStream.ENUMNEXT :\r
- slot = (iCode[++pc] & 0xFF);\r
- val = stack[LOCAL_SHFT + slot]; \r
- ++stackTop;\r
- stack[stackTop] = ScriptRuntime.\r
- nextEnum((Enumeration)val);\r
- break;\r
- case TokenStream.GETPROTO :\r
- lhs = stack[stackTop]; \r
- if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);\r
- stack[stackTop] = ScriptRuntime.getProto(lhs, scope);\r
- break;\r
- case TokenStream.GETPARENT :\r
- lhs = stack[stackTop]; \r
- if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);\r
- stack[stackTop] = ScriptRuntime.getParent(lhs);\r
- break;\r
- case TokenStream.GETSCOPEPARENT :\r
- lhs = stack[stackTop]; \r
- if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);\r
- stack[stackTop] = ScriptRuntime.getParent(lhs, scope);\r
- break;\r
- case TokenStream.SETPROTO :\r
- rhs = stack[stackTop]; \r
- if (rhs == DBL_MRK) rhs = doubleWrap(sDbl[stackTop]);\r
- --stackTop;\r
- lhs = stack[stackTop]; \r
- if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);\r
- stack[stackTop]\r
- = ScriptRuntime.setProto(lhs, rhs, scope);\r
- break;\r
- case TokenStream.SETPARENT :\r
- rhs = stack[stackTop]; \r
- if (rhs == DBL_MRK) rhs = doubleWrap(sDbl[stackTop]);\r
- --stackTop;\r
- lhs = stack[stackTop]; \r
- if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);\r
- stack[stackTop]\r
- = ScriptRuntime.setParent(lhs, rhs, scope);\r
- break;\r
- case TokenStream.SCOPE :\r
- stack[++stackTop] = scope;\r
- break;\r
- case TokenStream.CLOSURE :\r
- i = (iCode[pc + 1] << 8) | (iCode[pc + 2] & 0xFF);\r
- stack[++stackTop] \r
- = new InterpretedFunction(\r
- theData.itsNestedFunctions[i],\r
- scope, cx);\r
- createFunctionObject(\r
- (InterpretedFunction)stack[stackTop], scope);\r
- pc += 2;\r
- break;\r
- case TokenStream.OBJECT :\r
- i = (iCode[pc + 1] << 8) | (iCode[pc + 2] & 0xFF); \r
- stack[++stackTop] = theData.itsRegExpLiterals[i];\r
- pc += 2;\r
- break;\r
- case TokenStream.SOURCEFILE : \r
- cx.interpreterSourceFile = theData.itsSourceFile;\r
- break;\r
- case TokenStream.LINE : \r
- case TokenStream.BREAKPOINT :\r
- i = (iCode[pc + 1] << 8) | (iCode[pc + 2] & 0xFF); \r
- cx.interpreterLine = i;\r
- if (frame != null)\r
- frame.setLineNumber(i);\r
- if ((iCode[pc] & 0xff) == TokenStream.BREAKPOINT ||\r
- cx.inLineStepMode) \r
- {\r
- cx.getDebuggableEngine().\r
- getDebugger().handleBreakpointHit(cx);\r
- }\r
- pc += 2;\r
- break;\r
- default :\r
- dumpICode(theData);\r
- throw new RuntimeException("Unknown icode : "\r
- + (iCode[pc] & 0xff) + " @ pc : " + pc);\r
- }\r
- pc++;\r
- }\r
- catch (Throwable ex) {\r
- cx.interpreterSecurityDomain = null;\r
- \r
- if (instructionThreshold != 0) {\r
- if (instructionCount < 0) {\r
- // throw during function call\r
- instructionCount = cx.instructionCount;\r
- }\r
- else {\r
- // throw during any other operation\r
- instructionCount += pc - pcPrevBranch;\r
- cx.instructionCount = instructionCount;\r
- }\r
- }\r
-\r
- final int SCRIPT_THROW = 0, ECMA = 1, RUNTIME = 2, OTHER = 3;\r
-\r
- int exType;\r
- Object errObj; // Object seen by catch\r
- if (ex instanceof JavaScriptException) {\r
- errObj = ScriptRuntime.\r
- unwrapJavaScriptException((JavaScriptException)ex);\r
- exType = SCRIPT_THROW;\r
- }\r
- else if (ex instanceof EcmaError) {\r
- // an offical ECMA error object,\r
- errObj = ((EcmaError)ex).getErrorObject();\r
- exType = ECMA;\r
- }\r
- else if (ex instanceof RuntimeException) {\r
- errObj = ex;\r
- exType = RUNTIME;\r
- }\r
- else {\r
- errObj = ex; // Error instance\r
- exType = OTHER;\r
- }\r
-\r
- if (exType != OTHER && cx.debugger != null) {\r
- cx.debugger.handleExceptionThrown(cx, errObj);\r
- }\r
-\r
- boolean rethrow = true;\r
- if (exType != OTHER && tryStackTop > 0) {\r
- --tryStackTop;\r
- if (exType == SCRIPT_THROW || exType == ECMA) {\r
- // Check for catch only for \r
- // JavaScriptException and EcmaError\r
- pc = catchStack[tryStackTop * 2];\r
- if (pc != 0) {\r
- // Has catch block\r
- rethrow = false;\r
- }\r
- }\r
- if (rethrow) {\r
- pc = catchStack[tryStackTop * 2 + 1];\r
- if (pc != 0) {\r
- // has finally block\r
- rethrow = false;\r
- errObj = ex;\r
- }\r
- }\r
- }\r
-\r
- if (rethrow) {\r
- if (frame != null)\r
- cx.popFrame();\r
- \r
- if (exType == SCRIPT_THROW)\r
- throw (JavaScriptException)ex;\r
- if (exType == ECMA || exType == RUNTIME) \r
- throw (RuntimeException)ex;\r
- throw (Error)ex;\r
- }\r
- \r
- // We caught an exception,\r
-\r
- // Notify instruction observer if necessary\r
- // and point pcPrevBranch to start of catch/finally block\r
- if (instructionThreshold != 0) {\r
- if (instructionCount > instructionThreshold) {\r
- // Note: this can throw Error \r
- cx.observeInstructionCount(instructionCount);\r
- instructionCount = 0;\r
- }\r
- }\r
- pcPrevBranch = pc;\r
-\r
- // prepare stack and restore this function's security domain.\r
- scope = (Scriptable)stack[TRY_SCOPE_SHFT + tryStackTop];\r
- stackTop = 0;\r
- stack[0] = errObj;\r
- cx.interpreterSecurityDomain = theData.securityDomain;\r
- }\r
- }\r
- cx.interpreterSecurityDomain = savedSecurityDomain;\r
- if (frame != null)\r
- cx.popFrame();\r
-\r
- if (instructionThreshold != 0) {\r
- if (instructionCount > instructionThreshold) {\r
- cx.observeInstructionCount(instructionCount);\r
- instructionCount = 0;\r
- }\r
- cx.instructionCount = instructionCount;\r
- }\r
-\r
- return result; \r
- }\r
- \r
- private static Object doubleWrap(double x) {\r
- return new Double(x);\r
- }\r
-\r
- private static int stack_int32(Object[] stack, double[] stackDbl, int i) {\r
- Object x = stack[i];\r
- return (x != DBL_MRK)\r
- ? ScriptRuntime.toInt32(x)\r
- : ScriptRuntime.toInt32(stackDbl[i]);\r
- }\r
- \r
- private static long stack_uint32(Object[] stack, double[] stackDbl, int i) {\r
- Object x = stack[i];\r
- return (x != DBL_MRK)\r
- ? ScriptRuntime.toUint32(x)\r
- : ScriptRuntime.toUint32(stackDbl[i]);\r
- }\r
- \r
- private static double stack_double(Object[] stack, double[] stackDbl, \r
- int i) \r
- {\r
- Object x = stack[i];\r
- return (x != DBL_MRK) ? ScriptRuntime.toNumber(x) : stackDbl[i];\r
- }\r
- \r
- private static void do_add(Object[] stack, double[] stackDbl, int stackTop)\r
- {\r
- Object rhs = stack[stackTop + 1]; \r
- Object lhs = stack[stackTop];\r
- if (rhs == DBL_MRK) {\r
- double rDbl = stackDbl[stackTop + 1];\r
- if (lhs == DBL_MRK) {\r
- stackDbl[stackTop] += rDbl;\r
- }\r
- else {\r
- do_add(lhs, rDbl, stack, stackDbl, stackTop, true);\r
- }\r
- }\r
- else if (lhs == DBL_MRK) {\r
- do_add(rhs, stackDbl[stackTop], stack, stackDbl, stackTop, false);\r
- }\r
- else {\r
- if (lhs instanceof Scriptable)\r
- lhs = ((Scriptable) lhs).getDefaultValue(null);\r
- if (rhs instanceof Scriptable)\r
- rhs = ((Scriptable) rhs).getDefaultValue(null);\r
- if (lhs instanceof String || rhs instanceof String) {\r
- stack[stackTop] = ScriptRuntime.toString(lhs)\r
- + ScriptRuntime.toString(rhs);\r
- }\r
- else {\r
- double lDbl = (lhs instanceof Number)\r
- ? ((Number)lhs).doubleValue() : ScriptRuntime.toNumber(lhs);\r
- double rDbl = (rhs instanceof Number)\r
- ? ((Number)rhs).doubleValue() : ScriptRuntime.toNumber(rhs);\r
- stack[stackTop] = DBL_MRK;\r
- stackDbl[stackTop] = lDbl + rDbl;\r
- }\r
- }\r
- }\r
- \r
- // x + y when x is Number, see \r
- private static void do_add\r
- (Object lhs, double rDbl, \r
- Object[] stack, double[] stackDbl, int stackTop, \r
- boolean left_right_order) \r
- {\r
- if (lhs instanceof Scriptable) {\r
- if (lhs == Undefined.instance) { lhs = ScriptRuntime.NaNobj; }\r
- lhs = ((Scriptable)lhs).getDefaultValue(null);\r
- }\r
- if (lhs instanceof String) {\r
- if (left_right_order) {\r
- stack[stackTop] = (String)lhs + ScriptRuntime.toString(rDbl);\r
- }\r
- else {\r
- stack[stackTop] = ScriptRuntime.toString(rDbl) + (String)lhs;\r
- }\r
- }\r
- else {\r
- double lDbl = (lhs instanceof Number) \r
- ? ((Number)lhs).doubleValue() : ScriptRuntime.toNumber(lhs);\r
- stack[stackTop] = DBL_MRK;\r
- stackDbl[stackTop] = lDbl + rDbl;\r
- }\r
- }\r
-\r
-\r
- \r
- private static boolean do_eq(Object[] stack, double[] stackDbl,\r
- int stackTop)\r
- {\r
- boolean result;\r
- Object rhs = stack[stackTop + 1]; \r
- Object lhs = stack[stackTop];\r
- if (rhs == DBL_MRK) {\r
- if (lhs == DBL_MRK) {\r
- result = (stackDbl[stackTop] == stackDbl[stackTop + 1]);\r
- }\r
- else {\r
- result = do_eq(stackDbl[stackTop + 1], lhs);\r
- }\r
- }\r
- else {\r
- if (lhs == DBL_MRK) {\r
- result = do_eq(stackDbl[stackTop], rhs);\r
- }\r
- else {\r
- result = ScriptRuntime.eq(lhs, rhs);\r
- }\r
- }\r
- return result;\r
- }\r
- \r
-// Optimized version of ScriptRuntime.eq if x is a Number \r
- private static boolean do_eq(double x, Object y) {\r
- for (;;) {\r
- if (y instanceof Number) {\r
- return x == ((Number) y).doubleValue();\r
- }\r
- if (y instanceof String) {\r
- return x == ScriptRuntime.toNumber((String)y);\r
- }\r
- if (y instanceof Boolean) {\r
- return x == (((Boolean)y).booleanValue() ? 1 : 0);\r
- }\r
- if (y instanceof Scriptable) {\r
- if (y == Undefined.instance) { return false; }\r
- y = ScriptRuntime.toPrimitive(y);\r
- continue;\r
- }\r
- return false;\r
- }\r
- }\r
-\r
- private static boolean do_sheq(Object[] stack, double[] stackDbl,\r
- int stackTop)\r
- {\r
- boolean result;\r
- Object rhs = stack[stackTop + 1]; \r
- Object lhs = stack[stackTop];\r
- if (rhs == DBL_MRK) {\r
- double rDbl = stackDbl[stackTop + 1];\r
- if (lhs == DBL_MRK) {\r
- result = (stackDbl[stackTop] == rDbl);\r
- }\r
- else {\r
- result = (lhs instanceof Number);\r
- if (result) {\r
- result = (((Number)lhs).doubleValue() == rDbl);\r
- }\r
- }\r
- }\r
- else if (rhs instanceof Number) {\r
- double rDbl = ((Number)rhs).doubleValue();\r
- if (lhs == DBL_MRK) {\r
- result = (stackDbl[stackTop] == rDbl);\r
- }\r
- else {\r
- result = (lhs instanceof Number);\r
- if (result) {\r
- result = (((Number)lhs).doubleValue() == rDbl);\r
- }\r
- }\r
- }\r
- else {\r
- result = ScriptRuntime.shallowEq(lhs, rhs);\r
- }\r
- return result;\r
- }\r
- \r
- private int version;\r
- private boolean inLineStepMode;\r
- private StringBuffer debugSource;\r
-\r
- private static final Object DBL_MRK = new Object();\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-2000 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- * Roger Lawrence\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-import java.util.Vector;\r
-\r
-class InterpreterData {\r
- \r
- static final int INITIAL_MAX_ICODE_LENGTH = 1024;\r
- static final int INITIAL_STRINGTABLE_SIZE = 64;\r
- static final int INITIAL_NUMBERTABLE_SIZE = 64;\r
- \r
- InterpreterData(int lastICodeTop, int lastStringTableIndex, \r
- int lastNumberTableIndex, Object securityDomain,\r
- boolean useDynamicScope, boolean checkThis)\r
- {\r
- itsICodeTop = lastICodeTop == 0 \r
- ? INITIAL_MAX_ICODE_LENGTH\r
- : lastICodeTop * 2;\r
- itsICode = new byte[itsICodeTop];\r
-\r
- itsStringTable = new String[lastStringTableIndex == 0\r
- ? INITIAL_STRINGTABLE_SIZE\r
- : lastStringTableIndex * 2];\r
-\r
- itsNumberTable = new double[lastNumberTableIndex == 0\r
- ? INITIAL_NUMBERTABLE_SIZE\r
- : lastNumberTableIndex * 2];\r
- \r
- itsUseDynamicScope = useDynamicScope;\r
- itsCheckThis = checkThis;\r
- if (securityDomain == null)\r
- Context.checkSecurityDomainRequired();\r
- this.securityDomain = securityDomain;\r
- }\r
- \r
- public boolean placeBreakpoint(int line) { // XXX throw exn?\r
- int offset = getOffset(line);\r
- if (offset != -1 && (itsICode[offset] == (byte)TokenStream.LINE ||\r
- itsICode[offset] == (byte)TokenStream.BREAKPOINT))\r
- {\r
- itsICode[offset] = (byte) TokenStream.BREAKPOINT;\r
- return true;\r
- }\r
- return false;\r
- }\r
- \r
- public boolean removeBreakpoint(int line) {\r
- int offset = getOffset(line);\r
- if (offset != -1 && itsICode[offset] == (byte) TokenStream.BREAKPOINT)\r
- {\r
- itsICode[offset] = (byte) TokenStream.LINE;\r
- return true;\r
- }\r
- return false;\r
- }\r
- \r
- private int getOffset(int line) {\r
- int offset = itsLineNumberTable.getInt(line, -1);\r
- if (0 <= offset && offset <= itsICode.length) {\r
- return offset;\r
- }\r
- return -1;\r
- } \r
- \r
- String itsName;\r
- String itsSource;\r
- String itsSourceFile;\r
- boolean itsNeedsActivation;\r
- boolean itsFromEvalCode;\r
- boolean itsUseDynamicScope;\r
- boolean itsCheckThis;\r
- byte itsFunctionType;\r
-\r
- String[] itsStringTable;\r
- int itsStringTableIndex;\r
-\r
- double[] itsNumberTable;\r
- int itsNumberTableIndex;\r
- \r
- InterpretedFunction[] itsNestedFunctions;\r
- \r
- Object[] itsRegExpLiterals;\r
-\r
- byte[] itsICode;\r
- int itsICodeTop;\r
- \r
- int itsMaxLocals;\r
- int itsMaxArgs;\r
- int itsMaxStack;\r
- int itsMaxTryDepth;\r
- \r
- UintMap itsLineNumberTable;\r
-\r
- Object securityDomain;\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-2000 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-import java.util.Vector;\r
-\r
-import org.mozilla.javascript.debug.*;\r
-\r
-class InterpreterFrame implements DebugFrame {\r
- \r
- InterpreterFrame(Scriptable scope, InterpreterData data, Scriptable obj) {\r
- this.scope = scope;\r
- this.data = data;\r
- this.lineNumber = -1;\r
- this.obj = obj;\r
- }\r
-\r
- public Scriptable getVariableObject() {\r
- return scope;\r
- }\r
- \r
- public String getSourceName() {\r
- return data.itsSourceFile;\r
- }\r
- \r
- public void setLineNumber(int lineNumber) {\r
- this.lineNumber = lineNumber;\r
- }\r
- \r
- public int getLineNumber() {\r
- return lineNumber;\r
- }\r
- \r
- public DebuggableScript getScript() {\r
- if (obj instanceof DebuggableScript)\r
- return (DebuggableScript) obj;\r
- return null;\r
- }\r
- \r
- private Scriptable scope;\r
- private InterpreterData data;\r
- private Scriptable obj;\r
- private int lineNumber;\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-2000 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s):\r
- * Norris Boyd\r
- * David C. Navas\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-import java.lang.reflect.Method;\r
-\r
-/**\r
- * Avoid cost of java.lang.reflect.Method.invoke() by compiling a class to\r
- * perform the method call directly.\r
- */\r
-public abstract class Invoker {\r
-\r
- public abstract Object invoke(Object that, Object [] args);\r
-\r
- /** Factory method to get invoker for given method */\r
- public Invoker createInvoker(Method method, Class[] types) {\r
- return null;\r
- }\r
-\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-2000 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- * Frank Mitchell\r
- * Mike Shaver\r
- * Kurt Westerfeld\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-import java.lang.reflect.*;\r
-import java.util.Hashtable;\r
-import java.util.Enumeration;\r
-\r
-/**\r
- *\r
- * @author Mike Shaver\r
- * @author Norris Boyd\r
- * @see NativeJavaObject\r
- * @see NativeJavaClass\r
- */\r
-class JavaMembers {\r
-\r
- JavaMembers(Scriptable scope, Class cl) {\r
- this.members = new Hashtable(23);\r
- this.staticMembers = new Hashtable(7);\r
- this.cl = cl;\r
- reflect(scope, cl);\r
- }\r
-\r
- boolean has(String name, boolean isStatic) {\r
- Hashtable ht = isStatic ? staticMembers : members;\r
- Object obj = ht.get(name);\r
- if (obj != null) {\r
- return true;\r
- } else {\r
- Member member = this.findExplicitFunction(name, isStatic);\r
- return member != null;\r
- }\r
- }\r
-\r
- Object get(Scriptable scope, String name, Object javaObject,\r
- boolean isStatic)\r
- {\r
- Hashtable ht = isStatic ? staticMembers : members;\r
- Object member = ht.get(name);\r
- if (!isStatic && member == null) {\r
- // Try to get static member from instance (LC3)\r
- member = staticMembers.get(name);\r
- }\r
- if (member == null) {\r
- member = this.getExplicitFunction(scope, name, \r
- javaObject, isStatic);\r
- if (member == null)\r
- return Scriptable.NOT_FOUND;\r
- }\r
- if (member instanceof Scriptable)\r
- return member; // why is this here?\r
- Object rval;\r
- Class type;\r
- try {\r
- if (member instanceof BeanProperty) {\r
- BeanProperty bp = (BeanProperty) member;\r
- rval = bp.getter.invoke(javaObject, ScriptRuntime.emptyArgs);\r
- type = bp.getter.getReturnType();\r
- } else {\r
- Field field = (Field) member;\r
- rval = field.get(isStatic ? null : javaObject);\r
- type = field.getType();\r
- }\r
- } catch (IllegalAccessException accEx) {\r
- throw new RuntimeException("unexpected IllegalAccessException "+\r
- "accessing Java field");\r
- } catch (InvocationTargetException e) {\r
- throw WrappedException.wrapException(\r
- JavaScriptException.wrapException(scope, e));\r
- }\r
- // Need to wrap the object before we return it.\r
- scope = ScriptableObject.getTopLevelScope(scope);\r
- return NativeJavaObject.wrap(scope, rval, type);\r
- }\r
-\r
- Member findExplicitFunction(String name, boolean isStatic) {\r
- Hashtable ht = isStatic ? staticMembers : members;\r
- int sigStart = name.indexOf('(');\r
- Member[] methodsOrCtors = null;\r
- NativeJavaMethod method = null;\r
- boolean isCtor = (isStatic && sigStart == 0);\r
-\r
- if (isCtor) {\r
- // Explicit request for an overloaded constructor\r
- methodsOrCtors = ctors;\r
- }\r
- else if (sigStart > 0) {\r
- // Explicit request for an overloaded method\r
- String trueName = name.substring(0,sigStart);\r
- Object obj = ht.get(trueName);\r
- if (!isStatic && obj == null) {\r
- // Try to get static member from instance (LC3)\r
- obj = staticMembers.get(trueName);\r
- }\r
- if (obj != null && obj instanceof NativeJavaMethod) {\r
- method = (NativeJavaMethod)obj;\r
- methodsOrCtors = method.getMethods();\r
- }\r
- }\r
-\r
- if (methodsOrCtors != null) {\r
- for (int i = 0; i < methodsOrCtors.length; i++) {\r
- String nameWithSig = \r
- NativeJavaMethod.signature(methodsOrCtors[i]);\r
- if (name.equals(nameWithSig)) {\r
- return methodsOrCtors[i];\r
- }\r
- }\r
- }\r
-\r
- return null;\r
- }\r
-\r
- Object getExplicitFunction(Scriptable scope, String name, \r
- Object javaObject, boolean isStatic) \r
- {\r
- Hashtable ht = isStatic ? staticMembers : members;\r
- Object member = null;\r
- Member methodOrCtor = this.findExplicitFunction(name, isStatic);\r
-\r
- if (methodOrCtor != null) {\r
- Scriptable prototype = \r
- ScriptableObject.getFunctionPrototype(scope);\r
-\r
- if (methodOrCtor instanceof Constructor) {\r
- NativeJavaConstructor fun = \r
- new NativeJavaConstructor((Constructor)methodOrCtor);\r
- fun.setPrototype(prototype);\r
- member = fun;\r
- ht.put(name, fun);\r
- } else {\r
- String trueName = methodOrCtor.getName();\r
- member = ht.get(trueName);\r
-\r
- if (member instanceof NativeJavaMethod &&\r
- ((NativeJavaMethod)member).getMethods().length > 1 ) {\r
- NativeJavaMethod fun = \r
- new NativeJavaMethod((Method)methodOrCtor, name);\r
- fun.setPrototype(prototype);\r
- ht.put(name, fun);\r
- member = fun;\r
- }\r
- }\r
- }\r
-\r
- return member;\r
- }\r
-\r
-\r
- public void put(Scriptable scope, String name, Object javaObject, \r
- Object value, boolean isStatic)\r
- {\r
- Hashtable ht = isStatic ? staticMembers : members;\r
- Object member = ht.get(name);\r
- if (!isStatic && member == null) {\r
- // Try to get static member from instance (LC3)\r
- member = staticMembers.get(name);\r
- }\r
- if (member == null)\r
- throw reportMemberNotFound(name);\r
- if (member instanceof FieldAndMethods) {\r
- FieldAndMethods fam = (FieldAndMethods) ht.get(name);\r
- member = fam.getField();\r
- }\r
- \r
- // Is this a bean property "set"?\r
- if (member instanceof BeanProperty) { \r
- try {\r
- Method method = ((BeanProperty) member).setter;\r
- if (method == null)\r
- throw reportMemberNotFound(name);\r
- Class[] types = method.getParameterTypes();\r
- Object[] params = { NativeJavaObject.coerceType(types[0], value) };\r
- method.invoke(javaObject, params);\r
- } catch (IllegalAccessException accessEx) {\r
- throw new RuntimeException("unexpected IllegalAccessException " +\r
- "accessing Java field");\r
- } catch (InvocationTargetException e) {\r
- throw WrappedException.wrapException(\r
- JavaScriptException.wrapException(scope, e));\r
- }\r
- }\r
- else {\r
- Field field = null;\r
- try {\r
- field = (Field) member;\r
- if (field == null) {\r
- throw Context.reportRuntimeError1(\r
- "msg.java.internal.private", name);\r
- }\r
- field.set(javaObject,\r
- NativeJavaObject.coerceType(field.getType(), value));\r
- } catch (ClassCastException e) {\r
- throw Context.reportRuntimeError1(\r
- "msg.java.method.assign", name);\r
- } catch (IllegalAccessException accessEx) {\r
- throw new RuntimeException("unexpected IllegalAccessException "+\r
- "accessing Java field");\r
- } catch (IllegalArgumentException argEx) {\r
- throw Context.reportRuntimeError3(\r
- "msg.java.internal.field.type", \r
- value.getClass().getName(), field,\r
- javaObject.getClass().getName());\r
- }\r
- }\r
- }\r
-\r
- Object[] getIds(boolean isStatic) {\r
- Hashtable ht = isStatic ? staticMembers : members;\r
- int len = ht.size();\r
- Object[] result = new Object[len];\r
- Enumeration keys = ht.keys();\r
- for (int i=0; i < len; i++)\r
- result[i] = keys.nextElement();\r
- return result;\r
- }\r
- \r
- Class getReflectedClass() {\r
- return cl;\r
- }\r
- \r
- void reflectField(Scriptable scope, Field field) {\r
- int mods = field.getModifiers();\r
- if (!Modifier.isPublic(mods))\r
- return;\r
- boolean isStatic = Modifier.isStatic(mods);\r
- Hashtable ht = isStatic ? staticMembers : members;\r
- String name = field.getName();\r
- Object member = ht.get(name);\r
- if (member != null) {\r
- if (member instanceof NativeJavaMethod) {\r
- NativeJavaMethod method = (NativeJavaMethod) member;\r
- FieldAndMethods fam = new FieldAndMethods(method.getMethods(),\r
- field,\r
- null);\r
- fam.setPrototype(ScriptableObject.getFunctionPrototype(scope));\r
- getFieldAndMethodsTable(isStatic).put(name, fam);\r
- ht.put(name, fam);\r
- return;\r
- }\r
- if (member instanceof Field) {\r
- Field oldField = (Field) member;\r
- // If this newly reflected field shadows an inherited field, \r
- // then replace it. Otherwise, since access to the field \r
- // would be ambiguous from Java, no field should be reflected.\r
- // For now, the first field found wins, unless another field \r
- // explicitly shadows it.\r
- if (oldField.getDeclaringClass().isAssignableFrom(field.getDeclaringClass()))\r
- ht.put(name, field);\r
- return;\r
- }\r
- throw new RuntimeException("unknown member type");\r
- }\r
- ht.put(name, field);\r
- }\r
-\r
- void reflectMethod(Scriptable scope, Method method) {\r
- int mods = method.getModifiers();\r
- if (!Modifier.isPublic(mods))\r
- return;\r
- boolean isStatic = Modifier.isStatic(mods);\r
- Hashtable ht = isStatic ? staticMembers : members;\r
- String name = method.getName();\r
- NativeJavaMethod fun = (NativeJavaMethod) ht.get(name);\r
- if (fun == null) {\r
- fun = new NativeJavaMethod();\r
- if (scope != null)\r
- fun.setPrototype(ScriptableObject.getFunctionPrototype(scope));\r
- ht.put(name, fun);\r
- fun.add(method);\r
- } else {\r
- fun.add(method);\r
- }\r
- }\r
-\r
- void reflect(Scriptable scope, Class cl) {\r
- // We reflect methods first, because we want overloaded field/method\r
- // names to be allocated to the NativeJavaMethod before the field\r
- // gets in the way.\r
- Method[] methods = cl.getMethods();\r
- for (int i = 0; i < methods.length; i++)\r
- reflectMethod(scope, methods[i]);\r
- \r
- Field[] fields = cl.getFields();\r
- for (int i = 0; i < fields.length; i++)\r
- reflectField(scope, fields[i]);\r
-\r
- makeBeanProperties(scope, false);\r
- makeBeanProperties(scope, true);\r
- \r
- ctors = cl.getConstructors();\r
- }\r
- \r
- Hashtable getFieldAndMethodsTable(boolean isStatic) {\r
- Hashtable fmht = isStatic ? staticFieldAndMethods\r
- : fieldAndMethods;\r
- if (fmht == null) {\r
- fmht = new Hashtable(11);\r
- if (isStatic)\r
- staticFieldAndMethods = fmht;\r
- else\r
- fieldAndMethods = fmht;\r
- }\r
- \r
- return fmht;\r
- }\r
-\r
- void makeBeanProperties(Scriptable scope, boolean isStatic) {\r
- Hashtable ht = isStatic ? staticMembers : members;\r
- Hashtable toAdd = new Hashtable();\r
- \r
- // Now, For each member, make "bean" properties.\r
- for (Enumeration e = ht.keys(); e.hasMoreElements(); ) {\r
- \r
- // Is this a getter?\r
- String name = (String) e.nextElement();\r
- boolean memberIsGetMethod = name.startsWith("get");\r
- boolean memberIsIsMethod = name.startsWith("is");\r
- if (memberIsGetMethod || memberIsIsMethod) {\r
- // Double check name component.\r
- String nameComponent = name.substring(memberIsGetMethod ? 3 : 2);\r
- if (nameComponent.length() == 0) \r
- continue;\r
- \r
- // Make the bean property name.\r
- String beanPropertyName = nameComponent;\r
- if (Character.isUpperCase(nameComponent.charAt(0))) {\r
- if (nameComponent.length() == 1) {\r
- beanPropertyName = nameComponent.substring(0, 1).toLowerCase();\r
- } else if (!Character.isUpperCase(nameComponent.charAt(1))) {\r
- beanPropertyName = Character.toLowerCase(nameComponent.charAt(0)) + \r
- nameComponent.substring(1);\r
- }\r
- }\r
- \r
- // If we already have a member by this name, don't do this\r
- // property.\r
- if (ht.containsKey(beanPropertyName))\r
- continue;\r
- \r
- // Get the method by this name.\r
- Object method = ht.get(name);\r
- if (!(method instanceof NativeJavaMethod))\r
- continue;\r
- NativeJavaMethod getJavaMethod = (NativeJavaMethod) method;\r
- \r
- // Grab and inspect the getter method; does it have an empty parameter list,\r
- // with a return value (eg. a getSomething() or isSomething())?\r
- Class[] params;\r
- Method[] getMethods = getJavaMethod.getMethods();\r
- Class type;\r
- if (getMethods != null && \r
- getMethods.length == 1 && \r
- (type = getMethods[0].getReturnType()) != null &&\r
- (params = getMethods[0].getParameterTypes()) != null && \r
- params.length == 0) \r
- { \r
- \r
- // Make sure the method static-ness is preserved for this property.\r
- if (isStatic && !Modifier.isStatic(getMethods[0].getModifiers()))\r
- continue;\r
- \r
- // We have a getter. Now, do we have a setter?\r
- Method setMethod = null;\r
- String setter = "set" + nameComponent;\r
- if (ht.containsKey(setter)) { \r
-\r
- // Is this value a method?\r
- method = ht.get(setter);\r
- if (method instanceof NativeJavaMethod) {\r
- \r
- //\r
- // Note: it may be preferable to allow NativeJavaMethod.findFunction()\r
- // to find the appropriate setter; unfortunately, it requires an\r
- // instance of the target arg to determine that.\r
- //\r
-\r
- // Make two passes: one to find a method with direct type assignment, \r
- // and one to find a widening conversion.\r
- NativeJavaMethod setJavaMethod = (NativeJavaMethod) method;\r
- Method[] setMethods = setJavaMethod.getMethods();\r
- for (int pass = 1; pass <= 2 && setMethod == null; ++pass) {\r
- for (int i = 0; i < setMethods.length; ++i) {\r
- if (setMethods[i].getReturnType() == void.class &&\r
- (!isStatic || Modifier.isStatic(setMethods[i].getModifiers())) &&\r
- (params = setMethods[i].getParameterTypes()) != null && \r
- params.length == 1 ) { \r
- \r
- if ((pass == 1 && params[0] == type) ||\r
- (pass == 2 && params[0].isAssignableFrom(type))) { \r
- setMethod = setMethods[i];\r
- break;\r
- }\r
- }\r
- }\r
- }\r
- }\r
- }\r
- \r
- // Make the property.\r
- BeanProperty bp = new BeanProperty(getMethods[0], setMethod);\r
- toAdd.put(beanPropertyName, bp);\r
- }\r
- }\r
- } \r
- \r
- // Add the new bean properties.\r
- for (Enumeration e = toAdd.keys(); e.hasMoreElements();) {\r
- String key = (String) e.nextElement();\r
- Object value = toAdd.get(key);\r
- ht.put(key, value);\r
- }\r
- }\r
-\r
- Hashtable getFieldAndMethodsObjects(Scriptable scope, Object javaObject,\r
- boolean isStatic) \r
- {\r
- Hashtable ht = isStatic ? staticFieldAndMethods : fieldAndMethods;\r
- if (ht == null)\r
- return null;\r
- int len = ht.size();\r
- Hashtable result = new Hashtable(Math.max(len,1));\r
- Enumeration e = ht.elements();\r
- while (len-- > 0) {\r
- FieldAndMethods fam = (FieldAndMethods) e.nextElement();\r
- fam = (FieldAndMethods) fam.clone();\r
- fam.setJavaObject(javaObject);\r
- result.put(fam.getName(), fam);\r
- }\r
- return result;\r
- }\r
-\r
- Constructor[] getConstructors() {\r
- return ctors;\r
- }\r
-\r
- static JavaMembers lookupClass(Scriptable scope, Class dynamicType,\r
- Class staticType)\r
- {\r
- Class cl = dynamicType;\r
- Hashtable ct = classTable; // use local reference to avoid synchronize\r
- JavaMembers members = (JavaMembers) ct.get(cl);\r
- if (members != null)\r
- return members;\r
- if (staticType != null && staticType != dynamicType &&\r
- !Modifier.isPublic(dynamicType.getModifiers()) &&\r
- Modifier.isPublic(staticType.getModifiers()))\r
- {\r
- cl = staticType;\r
- \r
- // We can use the static type, and that is OK, but we'll trace\r
- // back the java class chain here to look for something more suitable.\r
- for (Class parentType = dynamicType; \r
- parentType != null && parentType != ScriptRuntime.ObjectClass;\r
- parentType = parentType.getSuperclass())\r
- {\r
- if (Modifier.isPublic(parentType.getModifiers())) {\r
- cl = parentType;\r
- break;\r
- }\r
- }\r
- }\r
- try {\r
- members = new JavaMembers(scope, cl);\r
- } catch (SecurityException e) {\r
- // Reflection may fail for objects that are in a restricted \r
- // access package (e.g. sun.*). If we get a security\r
- // exception, try again with the static type. Otherwise, \r
- // rethrow the exception.\r
- if (cl != staticType)\r
- members = new JavaMembers(scope, staticType);\r
- else\r
- throw e;\r
- }\r
- if (Context.isCachingEnabled) \r
- ct.put(cl, members);\r
- return members;\r
- }\r
-\r
- RuntimeException reportMemberNotFound(String memberName) {\r
- return Context.reportRuntimeError2(\r
- "msg.java.member.not.found", cl.getName(), memberName);\r
- }\r
-\r
- static Hashtable classTable = new Hashtable();\r
-\r
- private Class cl;\r
- private Hashtable members;\r
- private Hashtable fieldAndMethods;\r
- private Hashtable staticMembers;\r
- private Hashtable staticFieldAndMethods;\r
- private Constructor[] ctors;\r
-}\r
-\r
-class BeanProperty {\r
- BeanProperty(Method getter, Method setter) {\r
- this.getter = getter;\r
- this.setter = setter;\r
- }\r
- Method getter;\r
- Method setter;\r
-}\r
-\r
-class FieldAndMethods extends NativeJavaMethod {\r
-\r
- FieldAndMethods(Method[] methods, Field field, String name) {\r
- super(methods);\r
- this.field = field;\r
- this.name = name;\r
- }\r
-\r
- void setJavaObject(Object javaObject) {\r
- this.javaObject = javaObject;\r
- }\r
-\r
- String getName() {\r
- if (field == null)\r
- return name;\r
- return field.getName();\r
- }\r
-\r
- Field getField() {\r
- return field;\r
- }\r
- \r
- public Object getDefaultValue(Class hint) {\r
- if (hint == ScriptRuntime.FunctionClass)\r
- return this;\r
- Object rval;\r
- Class type;\r
- try {\r
- rval = field.get(javaObject);\r
- type = field.getType();\r
- } catch (IllegalAccessException accEx) {\r
- throw Context.reportRuntimeError1(\r
- "msg.java.internal.private", getName());\r
- }\r
- rval = NativeJavaObject.wrap(this, rval, type);\r
- if (rval instanceof Scriptable) {\r
- rval = ((Scriptable) rval).getDefaultValue(hint);\r
- }\r
- return rval;\r
- }\r
-\r
- public Object clone() {\r
- FieldAndMethods result = new FieldAndMethods(methods, field, name);\r
- result.javaObject = javaObject;\r
- return result;\r
- }\r
- \r
- private Field field;\r
- private Object javaObject;\r
- private String name;\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-// API class\r
-\r
-package org.mozilla.javascript;\r
-\r
-import java.lang.reflect.InvocationTargetException;\r
-\r
-/**\r
- * Java reflection of JavaScript exceptions. (Possibly wrapping a Java exception.)\r
- *\r
- * @author Mike McCabe\r
- */\r
-public class JavaScriptException extends Exception {\r
-\r
- public int line;\r
- public String sourceFile;\r
-\r
- /**\r
- * Create a JavaScript exception wrapping the given JavaScript value.\r
- *\r
- * Instances of this class are thrown by the JavaScript 'throw' keyword.\r
- *\r
- * @param value the JavaScript value thrown.\r
- */\r
- public JavaScriptException(Object value) {\r
- super(ScriptRuntime.toString(value));\r
- line = Context.enter().interpreterLine;\r
- sourceFile = Context.enter().interpreterSourceFile;\r
- this.value = value;\r
- }\r
-\r
- /**\r
- * Get the exception message.\r
- *\r
- * <p>Will just convert the wrapped exception to a string.\r
- */\r
- public String getMessage() {\r
- return ScriptRuntime.toString(value);\r
- }\r
-\r
- static JavaScriptException wrapException(Scriptable scope,\r
- Throwable exn)\r
- {\r
- if (exn instanceof InvocationTargetException)\r
- exn = ((InvocationTargetException)exn).getTargetException();\r
- if (exn instanceof JavaScriptException)\r
- return (JavaScriptException)exn;\r
- Object wrapper = NativeJavaObject.wrap(scope, exn, Throwable.class);\r
- return new JavaScriptException(wrapper);\r
- }\r
-\r
- /**\r
- * Get the exception value originally thrown. This may be a\r
- * JavaScript value (null, undefined, Boolean, Number, String,\r
- * Scriptable or Function) or a Java exception value thrown from a\r
- * host object or from Java called through LiveConnect.\r
- *\r
- * @return the value wrapped by this exception\r
- */\r
- public Object getValue() {\r
- if (value != null && value instanceof Wrapper)\r
- // this will also catch NativeStrings...\r
- return ((Wrapper)value).unwrap();\r
- else\r
- return value;\r
- }\r
-\r
- /**\r
- * The JavaScript exception value. This value is not\r
- * intended for general use; if the JavaScriptException wraps a\r
- * Java exception, getScriptableValue may return a Scriptable\r
- * wrapping the original Java exception object.\r
- *\r
- * We would prefer to go through a getter to encapsulate the value,\r
- * however that causes the bizarre error "nanosecond timeout value \r
- * out of range" on the MS JVM. \r
- * @serial \r
- */\r
- Object value;\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Roger Lawrence\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-public class Label {\r
- \r
- private static final int FIXUPTABLE_SIZE = 8;\r
-\r
- private static final boolean DEBUG = true;\r
-\r
- public Label()\r
- {\r
- itsPC = -1;\r
- }\r
-\r
- public short getPC()\r
- {\r
- return itsPC;\r
- }\r
- \r
- public void fixGotos(byte theCodeBuffer[])\r
- {\r
- if (DEBUG) {\r
- if ((itsPC == -1) && (itsFixupTable != null))\r
- throw new RuntimeException("Unlocated label");\r
- }\r
- if (itsFixupTable != null) {\r
- for (int i = 0; i < itsFixupTableTop; i++) {\r
- int fixupSite = itsFixupTable[i];\r
- // -1 to get delta from instruction start\r
- short offset = (short)(itsPC - (fixupSite - 1));\r
- theCodeBuffer[fixupSite++] = (byte)(offset >> 8);\r
- theCodeBuffer[fixupSite] = (byte)offset;\r
- }\r
- }\r
- itsFixupTable = null;\r
- }\r
-\r
- public void setPC(short thePC)\r
- {\r
- if (DEBUG) {\r
- if ((itsPC != -1) && (itsPC != thePC)) {\r
- throw new RuntimeException("Duplicate label");\r
- }\r
- }\r
-\r
- itsPC = thePC;\r
- }\r
-\r
- public void addFixup(int fixupSite)\r
- {\r
- if (itsFixupTable == null) {\r
- itsFixupTableTop = 1;\r
- itsFixupTable = new int[FIXUPTABLE_SIZE];\r
- itsFixupTable[0] = fixupSite; \r
- }\r
- else {\r
- if (itsFixupTableTop == itsFixupTable.length) {\r
- int oldLength = itsFixupTable.length;\r
- int newTable[] = new int[oldLength + FIXUPTABLE_SIZE];\r
- System.arraycopy(itsFixupTable, 0, newTable, 0, oldLength);\r
- itsFixupTable = newTable;\r
- }\r
- itsFixupTable[itsFixupTableTop++] = fixupSite; \r
- }\r
- }\r
-\r
- private short itsPC = -1;\r
- private int itsFixupTable[];\r
- private int itsFixupTableTop;\r
-\r
-}\r
-\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Roger Lawrence\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-public class LabelTable {\r
-\r
- private static final boolean DEBUGLABELS = false;\r
- \r
- private static final int LabelTableSize = 32;\r
- protected Label itsLabelTable[];\r
- protected int itsLabelTableTop;\r
-\r
- public int acquireLabel()\r
- {\r
- if (itsLabelTable == null) {\r
- itsLabelTable = new Label[LabelTableSize];\r
- itsLabelTable[0] = new Label();\r
- itsLabelTableTop = 1;\r
- return 0x80000000;\r
- }\r
- else {\r
- if (itsLabelTableTop == itsLabelTable.length) {\r
- Label oldTable[] = itsLabelTable;\r
- itsLabelTable = new Label[itsLabelTableTop * 2];\r
- System.arraycopy(oldTable, 0, itsLabelTable, 0, itsLabelTableTop);\r
- }\r
- itsLabelTable[itsLabelTableTop] = new Label();\r
- int result = itsLabelTableTop++;\r
- return result | 0x80000000;\r
- }\r
- }\r
-\r
- public int markLabel(int theLabel, int pc)\r
- {\r
- if (DEBUGLABELS) {\r
- if ((theLabel & 0x80000000) != 0x80000000)\r
- throw new RuntimeException("Bad label, no biscuit");\r
- }\r
- theLabel &= 0x7FFFFFFF;\r
- if (DEBUGLABELS) {\r
- System.out.println("Marking label " + theLabel + " at " + pc);\r
- }\r
- itsLabelTable[theLabel].setPC((short)pc);\r
- return theLabel | 0x80000000;\r
- }\r
-\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-2000 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s):\r
- * Norris Boyd\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-import java.lang.reflect.*;\r
-\r
-/**\r
- * Avoid loading classes unless they are used.\r
- *\r
- * <p> This improves startup time and average memory usage.\r
- */\r
-public final class LazilyLoadedCtor {\r
-\r
- public LazilyLoadedCtor(ScriptableObject scope,\r
- String ctorName, String className, boolean sealed)\r
- {\r
-\r
- this.className = className;\r
- this.ctorName = ctorName;\r
- this.sealed = sealed;\r
-\r
- if (getter == null) {\r
- Method[] all = FunctionObject.getMethodList(getClass());\r
- getter = FunctionObject.findMethods(all, "getProperty")[0];\r
- setter = FunctionObject.findMethods(all, "setProperty")[0];\r
- }\r
-\r
- try {\r
- scope.defineProperty(ctorName, this, getter, setter,\r
- ScriptableObject.DONTENUM);\r
- }\r
- catch (PropertyException e) {\r
- throw WrappedException.wrapException(e);\r
- }\r
- }\r
-\r
- public Object getProperty(ScriptableObject obj) {\r
- synchronized (obj) {\r
- if (!isReplaced) {\r
- boolean removeOnError = false;\r
-\r
- // Treat security exceptions as absence of object.\r
- // They can be due to the following reasons:\r
- // java.lang.RuntimePermission createClassLoader\r
- // java.util.PropertyPermission\r
- // org.mozilla.javascript.JavaAdapter read\r
-\r
- Class cl = null;\r
- try { cl = Class.forName(className); }\r
- catch (ClassNotFoundException ex) { removeOnError = true; }\r
- catch (SecurityException ex) { removeOnError = true; }\r
-\r
- if (cl != null) {\r
- try {\r
- ScriptableObject.defineClass(obj, cl, sealed);\r
- isReplaced = true;\r
- }\r
- catch (InstantiationException e) {\r
- throw WrappedException.wrapException(e);\r
- }\r
- catch (IllegalAccessException e) {\r
- throw WrappedException.wrapException(e);\r
- }\r
- catch (InvocationTargetException e) {\r
- throw WrappedException.wrapException(e);\r
- }\r
- catch (ClassDefinitionException e) {\r
- throw WrappedException.wrapException(e);\r
- }\r
- catch (PropertyException e) {\r
- throw WrappedException.wrapException(e);\r
- }\r
- catch (SecurityException ex) {\r
- removeOnError = true;\r
- }\r
- }\r
- if (removeOnError) {\r
- obj.delete(ctorName);\r
- return Scriptable.NOT_FOUND;\r
- }\r
- }\r
- }\r
- // Get just added object\r
- return obj.get(ctorName, obj);\r
- }\r
-\r
- public Object setProperty(ScriptableObject obj, Object val) {\r
- synchronized (obj) {\r
- isReplaced = true;\r
- return val;\r
- }\r
- }\r
-\r
- private static Method getter, setter;\r
-\r
- private String ctorName;\r
- private String className;\r
- private boolean sealed;\r
- private boolean isReplaced;\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Mike McCabe\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-import java.io.Reader;\r
-import java.io.IOException;\r
-\r
-/**\r
- * An input buffer that combines fast character-based access with\r
- * (slower) support for retrieving the text of the current line. It\r
- * also supports building strings directly out of the internal buffer\r
- * to support fast scanning with minimal object creation.\r
- *\r
- * Note that it is customized in several ways to support the\r
- * TokenStream class, and should not be considered general.\r
- *\r
- * Credits to Kipp Hickman and John Bandhauer.\r
- *\r
- * @author Mike McCabe\r
- */\r
-final class LineBuffer {\r
- /*\r
- * for smooth operation of getLine(), this should be greater than\r
- * the length of any expected line. Currently, 256 is 3% slower\r
- * than 4096 for large compiles, but seems safer given evaluateString.\r
- * Strings for the scanner are are built with StringBuffers\r
- * instead of directly out of the buffer whenever a string crosses\r
- * a buffer boundary, so small buffer sizes will mean that more\r
- * objects are created.\r
- */\r
- static final int BUFLEN = 256;\r
-\r
- LineBuffer(Reader in, int lineno) {\r
- this.in = in;\r
- this.lineno = lineno;\r
- }\r
-\r
- int read() throws IOException {\r
- for(;;) {\r
- if (end == offset && !fill())\r
- return -1;\r
-\r
- // Do only a bitmask + branch per character, at the cost of\r
- // three branches per low-bits-only (or 2028/9) character.\r
- if ((buffer[offset] & '\udfd0') == 0) {\r
- if (buffer[offset] == '\r') {\r
- // if the next character is a newline, skip past it.\r
- if ((offset + 1) < end) {\r
- if (buffer[offset + 1] == '\n')\r
- offset++;\r
- } else {\r
- // set a flag for fill(), in case the first char of the\r
- // next fill is a newline.\r
- lastWasCR = true;\r
- }\r
- }\r
- else \r
- if ((buffer[offset] != '\n') \r
- && (buffer[offset] != '\u2028')\r
- && (buffer[offset] != '\u2029'))\r
- { \r
- if (Character.getType(buffer[offset])\r
- == Character.FORMAT) {\r
- hadCFSinceStringStart = true;\r
- offset++;\r
- continue;\r
- }\r
- return (int) buffer[offset++];\r
- }\r
- offset++;\r
- prevStart = lineStart;\r
- lineStart = offset;\r
- lineno++;\r
- return '\n';\r
- }\r
- if ((buffer[offset] >= 128) \r
- && (Character.getType(buffer[offset]) == Character.FORMAT)) {\r
- hadCFSinceStringStart = true;\r
- offset++;\r
- }\r
- else\r
- break;\r
- }\r
- \r
- return (int) buffer[offset++];\r
- }\r
-\r
- void unread() {\r
- if (offset == 0)\r
- // We can get here when we're asked to unread() an\r
- // implicit EOF_CHAR.\r
- \r
- // This would also be wrong behavior in the general case,\r
- // because a peek() could map a buffer.length offset to 0\r
- // in the process of a fill(), and leave it there. But\r
- // the scanner never calls peek() or a failed match()\r
- // followed by unread()... this would violate 1-character\r
- // lookahead. So we're OK.\r
- return;\r
- offset--;\r
- if ((buffer[offset] & '\ufff0') == 0\r
- && (buffer[offset] == '\r' || buffer[offset] == '\n')) {\r
- // back off from the line start we presumably just registered...\r
- lineStart = prevStart;\r
- lineno--;\r
- }\r
- }\r
-\r
- int peek() throws IOException {\r
- if (end == offset && !fill())\r
- return -1;\r
-\r
- if (buffer[offset] == '\r')\r
- return '\n';\r
-\r
- return buffer[offset];\r
- }\r
-\r
- boolean match(char c) throws IOException {\r
- if (end == offset && !fill())\r
- return false;\r
-\r
- // This'd be a place where we'd need to map '\r' to '\n' and\r
- // do other updates, but TokenStream never looks ahead for\r
- // '\n', so we don't bother.\r
- if (buffer[offset] == c) {\r
- offset++;\r
- return true;\r
- }\r
- return false;\r
- }\r
-\r
- // Reconstruct a source line from the buffers. This can be slow...\r
- String getLine() {\r
- StringBuffer result = new StringBuffer();\r
-\r
- int start = lineStart;\r
- if (start >= offset) {\r
- // the line begins somewhere in the other buffer; get that first.\r
- if (otherStart < otherEnd)\r
- // if a line ending was seen in the other buffer... otherwise\r
- // just ignore this strange case.\r
- result.append(otherBuffer, otherStart,\r
- otherEnd - otherStart);\r
- start = 0;\r
- }\r
-\r
- // get the part of the line in the current buffer.\r
- result.append(buffer, start, offset - start);\r
-\r
- // Get the remainder of the line.\r
- int i = offset;\r
- while(true) {\r
- if (i == buffer.length) {\r
- // we're out of buffer, let's just expand it. We do\r
- // this instead of reading into a StringBuffer to\r
- // preserve the stream for later reads.\r
- char[] newBuffer = new char[buffer.length * 2];\r
- System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);\r
- buffer = newBuffer;\r
- int charsRead = 0;\r
- try {\r
- charsRead = in.read(buffer, end, buffer.length - end);\r
- } catch (IOException ioe) {\r
- // ignore it, we're already displaying an error...\r
- }\r
- if (charsRead < 0)\r
- break;\r
- end += charsRead;\r
- }\r
- if (buffer[i] == '\r' || buffer[i] == '\n')\r
- break;\r
- i++;\r
- }\r
-\r
- result.append(buffer, offset, i - offset);\r
- return result.toString();\r
- }\r
-\r
- // Get the offset of the current character, relative to\r
- // the line that getLine() returns.\r
- int getOffset() {\r
- if (lineStart >= offset)\r
- // The line begins somewhere in the other buffer.\r
- return offset + (otherEnd - otherStart);\r
- else\r
- return offset - lineStart;\r
- }\r
-\r
- // Set a mark to indicate that the reader should begin\r
- // accumulating characters for getString(). The string begins\r
- // with the last character read.\r
- void startString() {\r
- if (offset == 0) {\r
- // We can get here if startString is called after a peek()\r
- // or failed match() with offset past the end of the\r
- // buffer.\r
-\r
- // We're at the beginning of the buffer, and the previous character\r
- // (which we want to include) is at the end of the last one, so\r
- // we just go to StringBuffer mode.\r
- stringSoFar = new StringBuffer();\r
- \r
- stringSoFar.append(otherBuffer, otherEnd - 1, 1);\r
-\r
- stringStart = -1; // Set sentinel value.\r
- hadCFSinceStringStart = ((otherBuffer[otherEnd - 1] >= 128) \r
- && Character.getType(otherBuffer[otherEnd - 1])\r
- == Character.FORMAT);\r
- } else {\r
- // Support restarting strings\r
- stringSoFar = null;\r
- stringStart = offset - 1;\r
- hadCFSinceStringStart = ((buffer[stringStart] >= 128) \r
- && Character.getType(buffer[stringStart]) == Character.FORMAT);\r
- }\r
- \r
- }\r
-\r
- // Get a string consisting of the characters seen since the last\r
- // startString.\r
- String getString() {\r
- String result;\r
-\r
- /*\r
- * There's one strange case here: If the character offset currently\r
- * points to (which we never want to include in the string) is\r
- * a newline, then if the previous character is a carriage return,\r
- * we probably want to exclude that as well. If the offset is 0,\r
- * then we hope that fill() handled excluding it from stringSoFar.\r
- */\r
- int loseCR = (offset > 0 &&\r
- buffer[offset] == '\n' && buffer[offset - 1] == '\r') ?\r
- 1 : 0;\r
-\r
- if (stringStart != -1) {\r
- // String mark is valid, and in this buffer.\r
-\r
- result = new String(buffer, stringStart, \r
- offset - stringStart - loseCR);\r
- } else {\r
- if (stringSoFar == null) \r
- stringSoFar = new StringBuffer();\r
- // Exclude cr as well as nl of newline. If offset is 0, then\r
- // hopefully fill() did the right thing.\r
- result = (stringSoFar.append(buffer, 0, offset - loseCR)).toString();\r
- }\r
- \r
- stringStart = -1;\r
- stringSoFar = null;\r
- \r
- if (hadCFSinceStringStart) {\r
- char c[] = result.toCharArray();\r
- StringBuffer x = null;\r
- for (int i = 0; i < c.length; i++) {\r
- if (Character.getType(c[i]) == Character.FORMAT) {\r
- if (x == null) {\r
- x = new StringBuffer();\r
- x.append(c, 0, i);\r
- }\r
- }\r
- else\r
- if (x != null) x.append(c[i]);\r
- }\r
- if (x != null) result = x.toString(); \r
- }\r
- \r
- return result;\r
- } \r
-\r
- boolean fill() throws IOException {\r
- // not sure I care...\r
- if (end - offset != 0) \r
- throw new IOException("fill of non-empty buffer");\r
-\r
- // If there's a string currently being accumulated, save\r
- // off the progress.\r
-\r
- /*\r
- * Exclude an end-of-buffer carriage return. NOTE this is not\r
- * fully correct in the general case, because we really only\r
- * want to exclude the carriage return if it's followed by a\r
- * linefeed at the beginning of the next buffer. But we fudge\r
- * because the scanner doesn't do this.\r
- */\r
- int loseCR = (offset > 0 && lastWasCR) ? 1 : 0;\r
-\r
- if (stringStart != -1) {\r
- // The mark is in the current buffer, save off from the mark to the\r
- // end.\r
- stringSoFar = new StringBuffer();\r
-\r
- stringSoFar.append(buffer, stringStart, end - stringStart - loseCR);\r
- stringStart = -1;\r
- } else if (stringSoFar != null) {\r
- // the string began prior to the current buffer, so save the\r
- // whole current buffer.\r
- stringSoFar.append(buffer, 0, end - loseCR);\r
- }\r
-\r
- // swap buffers\r
- char[] tempBuffer = buffer;\r
- buffer = otherBuffer;\r
- otherBuffer = tempBuffer;\r
-\r
- // allocate the buffers lazily, in case we're handed a short string.\r
- if (buffer == null) {\r
- buffer = new char[BUFLEN];\r
- }\r
-\r
- // buffers have switched, so move the newline marker.\r
- otherStart = lineStart;\r
- otherEnd = end;\r
-\r
- // set lineStart to a sentinel value, unless this is the first\r
- // time around.\r
- prevStart = lineStart = (otherBuffer == null) ? 0 : buffer.length + 1;\r
- \r
- offset = 0;\r
- end = in.read(buffer, 0, buffer.length);\r
- if (end < 0) {\r
- end = 0;\r
-\r
- // can't null buffers here, because a string might be retrieved\r
- // out of the other buffer, and a 0-length string might be\r
- // retrieved out of this one.\r
-\r
- hitEOF = true;\r
- return false;\r
- }\r
-\r
- // If the last character of the previous fill was a carriage return,\r
- // then ignore a newline.\r
-\r
- // There's another bizzare special case here. If lastWasCR is\r
- // true, and we see a newline, and the buffer length is\r
- // 1... then we probably just read the last character of the\r
- // file, and returning after advancing offset is not the right\r
- // thing to do. Instead, we try to ignore the newline (and\r
- // likely get to EOF for real) by doing yet another fill().\r
- if (lastWasCR) {\r
- if (buffer[0] == '\n') {\r
- offset++;\r
- if (end == 1)\r
- return fill();\r
- }\r
- lineStart = offset;\r
- lastWasCR = false;\r
- }\r
- return true;\r
- }\r
-\r
- int getLineno() { return lineno; }\r
- boolean eof() { return hitEOF; }\r
- \r
- private Reader in;\r
- private char[] otherBuffer = null;\r
- private char[] buffer = null;\r
-\r
- // Yes, there are too too many of these.\r
- private int offset = 0;\r
- private int end = 0;\r
- private int otherEnd;\r
- private int lineno;\r
-\r
- private int lineStart = 0;\r
- private int otherStart = 0;\r
- private int prevStart = 0;\r
- \r
- private boolean lastWasCR = false;\r
- private boolean hitEOF = false;\r
-\r
- private int stringStart = -1;\r
- private StringBuffer stringSoFar = null;\r
- private boolean hadCFSinceStringStart = false;\r
-\r
-}\r
-\r
-\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 4; indent-tabs-mode: 1; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s):\r
- * Igor Bukanov\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-/* Helper class to add/remove listeners from Object array */\r
-\r
-package org.mozilla.javascript;\r
-\r
-/**\r
- * Utility class to manage listeners array.\r
- * A possible usage would be:\r
-<pre>\r
- private Object[] listeners;\r
- ...\r
- void addListener(ListenerType listener) {\r
- synchronized (this) {\r
- listeners = ListenerArray.add(listeners, listener);\r
- }\r
- }\r
-\r
- void removeListener(ListenerType listener) {\r
- synchronized (this) {\r
- listeners = ListenerArray.remove(listeners, listener);\r
- }\r
- }\r
-</pre>\r
- * Here is a thread safe while synchronization free example of event firing\r
-<pre>\r
- void fireEvent(EventType event) {\r
- Object[] array = listeners;\r
- if (array != null) {\r
- for (int i = array.length; i-- != 0;) {\r
- ((ListenerType)array[i]).onEvent(event);\r
- }\r
- }\r
-\r
- }\r
-</pre>\r
-\r
- * or if listeners of different types can present in listeners array:\r
-<pre>\r
- void fireEvent(EventType event) {\r
- Object[] array = listeners;\r
- if (array != null) {\r
- for (int i = array.length; i-- != 0;) {\r
- Object obj = array[i];\r
- if (obj instanceof ListenerType) {\r
- ((ListenerType)obj).onEvent(event);\r
- }\r
- }\r
- }\r
-\r
- }\r
-</pre>\r
- */\r
-public class ListenerArray {\r
-\r
- /** Return newly allocated array that contains listener and all elements\r
- ** from data array.\r
- ** Note: listener is added to resulting array even if it is already\r
- ** present in data */\r
- public static Object[] add(Object[] data, Object listener) {\r
- if (data == null) {\r
- data = new Object[1];\r
- }\r
- else {\r
- int N = data.length;\r
- Object[] tmp = new Object[N + 1];\r
- System.arraycopy(data, 0, tmp, 1, N);\r
- data = tmp;\r
- }\r
- data[0] = listener;\r
- return data;\r
- }\r
-\r
- /** Return a copy of data array with the first occurrence of listener\r
- ** removed.\r
- ** If listener is not present in data, simply return data.\r
- ** Note: return <code>null</code> if listener is the single element\r
- ** of data. */\r
- public static Object[] remove(Object[] data, Object listener) {\r
- if (data != null) {\r
- int N = data.length;\r
- for (int i = 0; i != N; ++i) {\r
- if (data[i] == listener) {\r
- if (N == 1) { data = null; }\r
- else {\r
- Object[] tmp = new Object[N - 1];\r
- System.arraycopy(data, 0, tmp, 0, i);\r
- System.arraycopy(data, i + 1, tmp, i, N - 1 - i);\r
- data = tmp;\r
- }\r
- break;\r
- }\r
- }\r
- }\r
- return data;\r
- }\r
-\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Roger Lawrence\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-public class LocalVariable {\r
- \r
- public LocalVariable(String name, boolean isParameter) {\r
- itsName = name;\r
- itsIsParameter = isParameter; \r
- }\r
- \r
- public void setIndex(int index){ itsIndex = index; }\r
- public int getIndex() { return itsIndex; }\r
- \r
- public void setIsParameter() { itsIsParameter = true; }\r
- public boolean isParameter() { return itsIsParameter; }\r
- \r
- public String getName() { return itsName; }\r
- \r
- /**\r
- * Return the starting PC where this variable is live, or -1\r
- * if it is not a Java register.\r
- */\r
- public int getStartPC() {\r
- return -1;\r
- }\r
-\r
- /**\r
- * Return the Java register number or -1 if it is not a Java register.\r
- */\r
- public short getJRegister() {\r
- return -1;\r
- }\r
-\r
- /**\r
- * Return true if the local variable is a Java register with double type.\r
- */\r
- public boolean isNumber() {\r
- return false;\r
- }\r
-\r
- private String itsName;\r
- private int itsIndex = -1;\r
- \r
- private boolean itsIsParameter;\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- * Mike McCabe\r
- * Igor Bukanov\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-import java.util.Hashtable;\r
-\r
-/**\r
- * This class implements the Array native object.\r
- * @author Norris Boyd\r
- * @author Mike McCabe\r
- */\r
-public class NativeArray extends IdScriptable {\r
-\r
- /*\r
- * Optimization possibilities and open issues:\r
- * - Long vs. double schizophrenia. I suspect it might be better\r
- * to use double throughout.\r
-\r
- * - Most array operations go through getElem or setElem (defined\r
- * in this file) to handle the full 2^32 range; it might be faster\r
- * to have versions of most of the loops in this file for the\r
- * (infinitely more common) case of indices < 2^31.\r
-\r
- * - Functions that need a new Array call "new Array" in the\r
- * current scope rather than using a hardwired constructor;\r
- * "Array" could be redefined. It turns out that js calls the\r
- * equivalent of "new Array" in the current scope, except that it\r
- * always gets at least an object back, even when Array == null.\r
- */\r
-\r
- public static void init(Context cx, Scriptable scope, boolean sealed) {\r
- NativeArray obj = new NativeArray();\r
- obj.prototypeFlag = true;\r
- obj.addAsPrototype(MAX_PROTOTYPE_ID, cx, scope, sealed);\r
- }\r
-\r
- /**\r
- * Zero-parameter constructor: just used to create Array.prototype\r
- */\r
- public NativeArray() {\r
- dense = null;\r
- this.length = 0;\r
- }\r
-\r
- public NativeArray(long length) {\r
- int intLength = (int) length;\r
- if (intLength == length && intLength > 0) {\r
- if (intLength > maximumDenseLength)\r
- intLength = maximumDenseLength;\r
- dense = new Object[intLength];\r
- for (int i=0; i < intLength; i++)\r
- dense[i] = NOT_FOUND;\r
- }\r
- this.length = length;\r
- }\r
-\r
- public NativeArray(Object[] array) {\r
- dense = array;\r
- this.length = array.length;\r
- }\r
-\r
- public String getClassName() {\r
- return "Array";\r
- }\r
-\r
- protected int getIdDefaultAttributes(int id) {\r
- if (id == Id_length) {\r
- return DONTENUM | PERMANENT;\r
- }\r
- return super.getIdDefaultAttributes(id);\r
- }\r
-\r
- protected Object getIdValue(int id) {\r
- if (id == Id_length) {\r
- return wrap_double(length);\r
- }\r
- return super.getIdValue(id);\r
- }\r
- \r
- protected void setIdValue(int id, Object value) {\r
- if (id == Id_length) {\r
- jsSet_length(value); return;\r
- }\r
- super.setIdValue(id, value);\r
- }\r
- \r
- public int methodArity(int methodId) {\r
- if (prototypeFlag) {\r
- switch (methodId) {\r
- case Id_constructor: return 1;\r
- case Id_toString: return 0;\r
- case Id_toLocaleString: return 1;\r
- case Id_join: return 1;\r
- case Id_reverse: return 0;\r
- case Id_sort: return 1;\r
- case Id_push: return 1;\r
- case Id_pop: return 1;\r
- case Id_shift: return 1;\r
- case Id_unshift: return 1;\r
- case Id_splice: return 1;\r
- case Id_concat: return 1;\r
- case Id_slice: return 1;\r
- }\r
- }\r
- return super.methodArity(methodId);\r
- }\r
-\r
- public Object execMethod\r
- (int methodId, IdFunction f,\r
- Context cx, Scriptable scope, Scriptable thisObj, Object[] args)\r
- throws JavaScriptException\r
- {\r
- if (prototypeFlag) {\r
- switch (methodId) {\r
- case Id_constructor:\r
- return jsConstructor(cx, scope, args, f, thisObj == null);\r
-\r
- case Id_toString:\r
- return jsFunction_toString(cx, thisObj, args);\r
-\r
- case Id_toLocaleString:\r
- return jsFunction_toLocaleString(cx, thisObj, args);\r
-\r
- case Id_join:\r
- return jsFunction_join(cx, thisObj, args);\r
-\r
- case Id_reverse:\r
- return jsFunction_reverse(cx, thisObj, args);\r
-\r
- case Id_sort:\r
- return jsFunction_sort(cx, scope, thisObj, args);\r
-\r
- case Id_push:\r
- return jsFunction_push(cx, thisObj, args);\r
-\r
- case Id_pop:\r
- return jsFunction_pop(cx, thisObj, args);\r
-\r
- case Id_shift:\r
- return jsFunction_shift(cx, thisObj, args);\r
-\r
- case Id_unshift:\r
- return jsFunction_unshift(cx, thisObj, args);\r
-\r
- case Id_splice:\r
- return jsFunction_splice(cx, scope, thisObj, args);\r
-\r
- case Id_concat:\r
- return jsFunction_concat(cx, scope, thisObj, args);\r
-\r
- case Id_slice:\r
- return jsFunction_slice(cx, thisObj, args);\r
- }\r
- }\r
- return super.execMethod(methodId, f, cx, scope, thisObj, args);\r
- }\r
-\r
- public Object get(int index, Scriptable start) {\r
- if (dense != null && 0 <= index && index < dense.length)\r
- return dense[index];\r
- return super.get(index, start);\r
- }\r
-\r
- public boolean has(int index, Scriptable start) {\r
- if (dense != null && 0 <= index && index < dense.length)\r
- return dense[index] != NOT_FOUND;\r
- return super.has(index, start);\r
- }\r
-\r
- public void put(String id, Scriptable start, Object value) {\r
- if (start == this) {\r
- // only set the array length if given an array index (ECMA 15.4.0)\r
-\r
- // try to get an array index from id\r
- double d = ScriptRuntime.toNumber(id);\r
-\r
- if (ScriptRuntime.toUint32(d) == d &&\r
- ScriptRuntime.numberToString(d, 10).equals(id) &&\r
- this.length <= d && d != 4294967295.0)\r
- {\r
- this.length = (long)d + 1;\r
- }\r
- }\r
- super.put(id, start, value);\r
- }\r
-\r
- public void put(int index, Scriptable start, Object value) {\r
- if (start == this) {\r
- // only set the array length if given an array index (ECMA 15.4.0)\r
- if (this.length <= index) {\r
- // avoid overflowing index!\r
- this.length = (long)index + 1;\r
- }\r
-\r
- if (dense != null && 0 <= index && index < dense.length) {\r
- dense[index] = value;\r
- return;\r
- }\r
- }\r
- super.put(index, start, value);\r
- }\r
-\r
- public void delete(int index) {\r
- if (!isSealed()) {\r
- if (dense != null && 0 <= index && index < dense.length) {\r
- dense[index] = NOT_FOUND;\r
- return;\r
- }\r
- }\r
- super.delete(index);\r
- }\r
-\r
- public Object[] getIds() {\r
- Object[] superIds = super.getIds();\r
- if (dense == null)\r
- return superIds;\r
- int count = 0;\r
- int last = dense.length;\r
- if (last > length)\r
- last = (int) length;\r
- for (int i=last-1; i >= 0; i--) {\r
- if (dense[i] != NOT_FOUND)\r
- count++;\r
- }\r
- count += superIds.length;\r
- Object[] result = new Object[count];\r
- System.arraycopy(superIds, 0, result, 0, superIds.length);\r
- for (int i=last-1; i >= 0; i--) {\r
- if (dense[i] != NOT_FOUND)\r
- result[--count] = new Integer(i);\r
- }\r
- return result;\r
- }\r
- \r
- public Object getDefaultValue(Class hint) {\r
- if (hint == ScriptRuntime.NumberClass) {\r
- Context cx = Context.getContext();\r
- if (cx.getLanguageVersion() == Context.VERSION_1_2)\r
- return new Long(length);\r
- }\r
- return super.getDefaultValue(hint);\r
- }\r
-\r
- /**\r
- * See ECMA 15.4.1,2\r
- */\r
- private static Object jsConstructor(Context cx, Scriptable scope, \r
- Object[] args, IdFunction ctorObj,\r
- boolean inNewExpr)\r
- throws JavaScriptException\r
- {\r
- if (!inNewExpr) {\r
- // FunctionObject.construct will set up parent, proto\r
- return ctorObj.construct(cx, scope, args);\r
- }\r
- if (args.length == 0)\r
- return new NativeArray();\r
-\r
- // Only use 1 arg as first element for version 1.2; for\r
- // any other version (including 1.3) follow ECMA and use it as\r
- // a length.\r
- if (cx.getLanguageVersion() == cx.VERSION_1_2) {\r
- return new NativeArray(args);\r
- }\r
- else {\r
- if ((args.length > 1) || (!(args[0] instanceof Number)))\r
- return new NativeArray(args);\r
- else {\r
- long len = ScriptRuntime.toUint32(args[0]);\r
- if (len != (((Number)(args[0])).doubleValue()))\r
- throw Context.reportRuntimeError0("msg.arraylength.bad");\r
- return new NativeArray(len);\r
- }\r
- }\r
- }\r
-\r
- public long jsGet_length() {\r
- return length;\r
- }\r
-\r
- private void jsSet_length(Object val) {\r
- /* XXX do we satisfy this?\r
- * 15.4.5.1 [[Put]](P, V):\r
- * 1. Call the [[CanPut]] method of A with name P.\r
- * 2. If Result(1) is false, return.\r
- * ?\r
- */\r
-\r
- if (!(val instanceof Number))\r
- throw Context.reportRuntimeError0("msg.arraylength.bad");\r
- \r
- long longVal = ScriptRuntime.toUint32(val);\r
- if (longVal != (((Number)val).doubleValue()))\r
- throw Context.reportRuntimeError0("msg.arraylength.bad");\r
-\r
- if (longVal < length) {\r
- // remove all properties between longVal and length\r
- if (length - longVal > 0x1000) {\r
- // assume that the representation is sparse\r
- Object[] e = getIds(); // will only find in object itself\r
- for (int i=0; i < e.length; i++) {\r
- if (e[i] instanceof String) {\r
- // > MAXINT will appear as string\r
- String id = (String) e[i];\r
- double d = ScriptRuntime.toNumber(id);\r
- if (d == d && d < length)\r
- delete(id);\r
- continue;\r
- }\r
- int index = ((Number) e[i]).intValue();\r
- if (index >= longVal)\r
- delete(index);\r
- }\r
- } else {\r
- // assume a dense representation\r
- for (long i=longVal; i < length; i++) {\r
- // only delete if defined in the object itself\r
- if (hasElem(this, i))\r
- ScriptRuntime.delete(this, new Long(i));\r
- }\r
- }\r
- }\r
- length = longVal;\r
- }\r
-\r
- /* Support for generic Array-ish objects. Most of the Array\r
- * functions try to be generic; anything that has a length\r
- * property is assumed to be an array. hasLengthProperty is\r
- * needed in addition to getLengthProperty, because\r
- * getLengthProperty always succeeds - tries to convert strings, etc.\r
- */\r
- static double getLengthProperty(Scriptable obj) {\r
- // These will both give numeric lengths within Uint32 range.\r
- if (obj instanceof NativeString)\r
- return (double)((NativeString)obj).jsGet_length();\r
- if (obj instanceof NativeArray)\r
- return (double)((NativeArray)obj).jsGet_length();\r
- return ScriptRuntime.toUint32(ScriptRuntime\r
- .getProp(obj, "length", obj));\r
- }\r
-\r
- static boolean hasLengthProperty(Object obj) {\r
- if (!(obj instanceof Scriptable) || obj == Context.getUndefinedValue())\r
- return false;\r
- if (obj instanceof NativeString || obj instanceof NativeArray)\r
- return true;\r
- Scriptable sobj = (Scriptable)obj;\r
-\r
- // XXX some confusion as to whether or not to walk to get the length\r
- // property. Pending review of js/[new ecma submission] treatment\r
- // of 'arrayness'.\r
-\r
- Object property = ScriptRuntime.getProp(sobj, "length", sobj);\r
- return property instanceof Number;\r
- }\r
-\r
- /* Utility functions to encapsulate index > Integer.MAX_VALUE\r
- * handling. Also avoids unnecessary object creation that would\r
- * be necessary to use the general ScriptRuntime.get/setElem\r
- * functions... though this is probably premature optimization.\r
- */\r
- private static boolean hasElem(Scriptable target, long index) {\r
- return index > Integer.MAX_VALUE\r
- ? target.has(Long.toString(index), target)\r
- : target.has((int)index, target);\r
- }\r
-\r
- private static Object getElem(Scriptable target, long index) {\r
- if (index > Integer.MAX_VALUE) {\r
- String id = Long.toString(index);\r
- return ScriptRuntime.getElem(target, id, target);\r
- } else {\r
- return ScriptRuntime.getElem(target, (int)index);\r
- }\r
- }\r
-\r
- private static void setElem(Scriptable target, long index, Object value) {\r
- if (index > Integer.MAX_VALUE) {\r
- String id = Long.toString(index);\r
- ScriptRuntime.setElem(target, id, value, target);\r
- } else {\r
- ScriptRuntime.setElem(target, (int)index, value);\r
- }\r
- }\r
-\r
- private static String jsFunction_toString(Context cx, Scriptable thisObj,\r
- Object[] args)\r
- throws JavaScriptException\r
- {\r
- return toStringHelper(cx, thisObj, \r
- cx.getLanguageVersion() == cx.VERSION_1_2,\r
- false);\r
- }\r
- \r
- private static String jsFunction_toLocaleString(Context cx, \r
- Scriptable thisObj,\r
- Object[] args)\r
- throws JavaScriptException\r
- {\r
- return toStringHelper(cx, thisObj, false, true);\r
- }\r
- \r
- private static String toStringHelper(Context cx, Scriptable thisObj,\r
- boolean toSource, boolean toLocale)\r
- throws JavaScriptException\r
- {\r
- /* It's probably redundant to handle long lengths in this\r
- * function; StringBuffers are limited to 2^31 in java.\r
- */\r
-\r
- long length = (long)getLengthProperty(thisObj);\r
-\r
- StringBuffer result = new StringBuffer();\r
-\r
- if (cx.iterating == null)\r
- cx.iterating = new Hashtable(31);\r
- boolean iterating = cx.iterating.get(thisObj) == Boolean.TRUE;\r
-\r
- // whether to return '4,unquoted,5' or '[4, "quoted", 5]'\r
- String separator;\r
-\r
- if (toSource) {\r
- result.append('[');\r
- separator = ", ";\r
- } else {\r
- separator = ",";\r
- }\r
-\r
- boolean haslast = false;\r
- long i = 0;\r
-\r
- if (!iterating) {\r
- for (i = 0; i < length; i++) {\r
- if (i > 0)\r
- result.append(separator);\r
- Object elem = getElem(thisObj, i);\r
- if (elem == null || elem == Undefined.instance) {\r
- haslast = false;\r
- continue;\r
- }\r
- haslast = true;\r
-\r
- if (elem instanceof String) {\r
- if (toSource) {\r
- result.append('\"');\r
- result.append(ScriptRuntime.escapeString\r
- (ScriptRuntime.toString(elem)));\r
- result.append('\"');\r
- } else {\r
- result.append(ScriptRuntime.toString(elem));\r
- }\r
- } else {\r
- /* wrap changes to cx.iterating in a try/finally\r
- * so that the reference always gets removed, and\r
- * we don't leak memory. Good place for weak\r
- * references, if we had them. */\r
- try {\r
- // stop recursion.\r
- cx.iterating.put(thisObj, Boolean.TRUE);\r
- if (toLocale && elem != Undefined.instance && \r
- elem != null) \r
- {\r
- Scriptable obj = cx.toObject(elem, thisObj);\r
- Object tls = ScriptRuntime.getProp(obj, \r
- "toLocaleString", thisObj);\r
- elem = ScriptRuntime.call(cx, tls, elem, \r
- ScriptRuntime.emptyArgs);\r
- }\r
- result.append(ScriptRuntime.toString(elem));\r
- } finally {\r
- cx.iterating.remove(thisObj);\r
- }\r
- }\r
- }\r
- }\r
-\r
- if (toSource) {\r
- //for [,,].length behavior; we want toString to be symmetric.\r
- if (!haslast && i > 0)\r
- result.append(", ]");\r
- else\r
- result.append(']');\r
- }\r
- return result.toString();\r
- }\r
-\r
- /**\r
- * See ECMA 15.4.4.3\r
- */\r
- private static String jsFunction_join(Context cx, Scriptable thisObj,\r
- Object[] args) \r
- {\r
- StringBuffer result = new StringBuffer();\r
- String separator;\r
-\r
- double length = getLengthProperty(thisObj);\r
-\r
- // if no args, use "," as separator\r
- if (args.length < 1) {\r
- separator = ",";\r
- } else {\r
- separator = ScriptRuntime.toString(args[0]);\r
- }\r
- for (long i=0; i < length; i++) {\r
- if (i > 0)\r
- result.append(separator);\r
- Object temp = getElem(thisObj, i);\r
- if (temp == null || temp == Undefined.instance)\r
- continue;\r
- result.append(ScriptRuntime.toString(temp));\r
- }\r
- return result.toString();\r
- }\r
-\r
- /**\r
- * See ECMA 15.4.4.4\r
- */\r
- private static Scriptable jsFunction_reverse(Context cx, \r
- Scriptable thisObj, \r
- Object[] args) \r
- {\r
- long len = (long)getLengthProperty(thisObj);\r
-\r
- long half = len / 2;\r
- for(long i=0; i < half; i++) {\r
- long j = len - i - 1;\r
- Object temp1 = getElem(thisObj, i);\r
- Object temp2 = getElem(thisObj, j);\r
- setElem(thisObj, i, temp2);\r
- setElem(thisObj, j, temp1);\r
- }\r
- return thisObj;\r
- }\r
-\r
- /**\r
- * See ECMA 15.4.4.5\r
- */\r
- private static Scriptable jsFunction_sort(Context cx, Scriptable scope,\r
- Scriptable thisObj, \r
- Object[] args)\r
- throws JavaScriptException\r
- {\r
- long length = (long)getLengthProperty(thisObj);\r
-\r
- Object compare;\r
- if (args.length > 0 && Undefined.instance != args[0])\r
- // sort with given compare function\r
- compare = args[0];\r
- else\r
- // sort with default compare\r
- compare = null;\r
-\r
-\r
- // OPT: Would it make sense to use the extended sort for very small\r
- // arrays?\r
-\r
- // Should we use the extended sort function, or the faster one?\r
- if (length >= Integer.MAX_VALUE) {\r
- qsort_extended(cx, compare, thisObj, 0, length - 1);\r
- } else {\r
- // copy the JS array into a working array, so it can be\r
- // sorted cheaply.\r
- Object[] working = new Object[(int)length];\r
- for (int i=0; i<length; i++) {\r
- working[i] = getElem(thisObj, i);\r
- }\r
-\r
- qsort(cx, compare, working, 0, (int)length - 1, scope);\r
-\r
- // copy the working array back into thisObj\r
- for (int i=0; i<length; i++) {\r
- setElem(thisObj, i, working[i]);\r
- }\r
- }\r
- return thisObj;\r
- }\r
-\r
- private static double qsortCompare(Context cx, Object jsCompare, Object x,\r
- Object y, Scriptable scope)\r
- throws JavaScriptException\r
- {\r
- Object undef = Undefined.instance;\r
-\r
- // sort undefined to end\r
- if (undef == x || undef == y) {\r
- if (undef != x)\r
- return -1;\r
- if (undef != y)\r
- return 1;\r
- return 0;\r
- }\r
-\r
- if (jsCompare == null) {\r
- // if no compare function supplied, sort lexicographically\r
- String a = ScriptRuntime.toString(x);\r
- String b = ScriptRuntime.toString(y);\r
-\r
- return a.compareTo(b);\r
- } else {\r
- // assemble args and call supplied JS compare function\r
- // OPT: put this argument creation in the caller and reuse it.\r
- // XXX what to do when compare function returns NaN? ECMA states\r
- // that it's then not a 'consistent compararison function'... but\r
- // then what do we do? Back out and start over with the generic\r
- // compare function when we see a NaN? Throw an error?\r
- Object[] args = {x, y};\r
-// return ScriptRuntime.toNumber(ScriptRuntime.call(jsCompare, null,\r
-// args));\r
- // for now, just ignore it:\r
- double d = ScriptRuntime.\r
- toNumber(ScriptRuntime.call(cx, jsCompare, null, args, scope));\r
-\r
- return (d == d) ? d : 0;\r
- }\r
- }\r
-\r
- private static void qsort(Context cx, Object jsCompare, Object[] working,\r
- int lo, int hi, Scriptable scope)\r
- throws JavaScriptException\r
- {\r
- Object pivot;\r
- int i, j;\r
- int a, b;\r
-\r
- while (lo < hi) {\r
- i = lo;\r
- j = hi;\r
- a = i;\r
- pivot = working[a];\r
- while (i < j) {\r
- for(;;) {\r
- b = j;\r
- if (qsortCompare(cx, jsCompare, working[j], pivot, \r
- scope) <= 0)\r
- break;\r
- j--;\r
- }\r
- working[a] = working[b];\r
- while (i < j && qsortCompare(cx, jsCompare, working[a],\r
- pivot, scope) <= 0)\r
- {\r
- i++;\r
- a = i;\r
- }\r
- working[b] = working[a];\r
- }\r
- working[a] = pivot;\r
- if (i - lo < hi - i) {\r
- qsort(cx, jsCompare, working, lo, i - 1, scope);\r
- lo = i + 1;\r
- } else {\r
- qsort(cx, jsCompare, working, i + 1, hi, scope);\r
- hi = i - 1;\r
- }\r
- }\r
- }\r
-\r
- // A version that knows about long indices and doesn't use\r
- // a working array. Probably will never be used.\r
- private static void qsort_extended(Context cx, Object jsCompare,\r
- Scriptable target, long lo, long hi)\r
- throws JavaScriptException\r
- {\r
- Object pivot;\r
- long i, j;\r
- long a, b;\r
-\r
- while (lo < hi) {\r
- i = lo;\r
- j = hi;\r
- a = i;\r
- pivot = getElem(target, a);\r
- while (i < j) {\r
- for(;;) {\r
- b = j;\r
- if (qsortCompare(cx, jsCompare, getElem(target, j),\r
- pivot, target) <= 0)\r
- break;\r
- j--;\r
- }\r
- setElem(target, a, getElem(target, b));\r
- while (i < j && qsortCompare(cx, jsCompare,\r
- getElem(target, a), \r
- pivot, target) <= 0)\r
- {\r
- i++;\r
- a = i;\r
- }\r
- setElem(target, b, getElem(target, a));\r
- }\r
- setElem(target, a, pivot);\r
- if (i - lo < hi - i) {\r
- qsort_extended(cx, jsCompare, target, lo, i - 1);\r
- lo = i + 1;\r
- } else {\r
- qsort_extended(cx, jsCompare, target, i + 1, hi);\r
- hi = i - 1;\r
- }\r
- }\r
- }\r
-\r
- /**\r
- * Non-ECMA methods.\r
- */\r
-\r
- private static Object jsFunction_push(Context cx, Scriptable thisObj,\r
- Object[] args)\r
- {\r
- double length = getLengthProperty(thisObj);\r
- for (int i = 0; i < args.length; i++) {\r
- setElem(thisObj, (long)length + i, args[i]);\r
- }\r
-\r
- length += args.length;\r
- ScriptRuntime.setProp(thisObj, "length", new Double(length), thisObj);\r
-\r
- /*\r
- * If JS1.2, follow Perl4 by returning the last thing pushed.\r
- * Otherwise, return the new array length.\r
- */\r
- if (cx.getLanguageVersion() == Context.VERSION_1_2)\r
- // if JS1.2 && no arguments, return undefined.\r
- return args.length == 0\r
- ? Context.getUndefinedValue()\r
- : args[args.length - 1];\r
-\r
- else\r
- return new Long((long)length);\r
- }\r
-\r
- private static Object jsFunction_pop(Context cx, Scriptable thisObj,\r
- Object[] args) {\r
- Object result;\r
- double length = getLengthProperty(thisObj);\r
- if (length > 0) {\r
- length--;\r
-\r
- // Get the to-be-deleted property's value.\r
- result = getElem(thisObj, (long)length);\r
-\r
- // We don't need to delete the last property, because\r
- // setLength does that for us.\r
- } else {\r
- result = Context.getUndefinedValue();\r
- }\r
- // necessary to match js even when length < 0; js pop will give a\r
- // length property to any target it is called on.\r
- ScriptRuntime.setProp(thisObj, "length", new Double(length), thisObj);\r
-\r
- return result;\r
- }\r
-\r
- private static Object jsFunction_shift(Context cx, Scriptable thisObj,\r
- Object[] args)\r
- {\r
- Object result;\r
- double length = getLengthProperty(thisObj);\r
- if (length > 0) {\r
- long i = 0;\r
- length--;\r
-\r
- // Get the to-be-deleted property's value.\r
- result = getElem(thisObj, i);\r
-\r
- /*\r
- * Slide down the array above the first element. Leave i\r
- * set to point to the last element.\r
- */\r
- if (length > 0) {\r
- for (i = 1; i <= length; i++) {\r
- Object temp = getElem(thisObj, i);\r
- setElem(thisObj, i - 1, temp);\r
- }\r
- }\r
- // We don't need to delete the last property, because\r
- // setLength does that for us.\r
- } else {\r
- result = Context.getUndefinedValue();\r
- }\r
- ScriptRuntime.setProp(thisObj, "length", new Double(length), thisObj);\r
- return result;\r
- }\r
-\r
- private static Object jsFunction_unshift(Context cx, Scriptable thisObj,\r
- Object[] args)\r
- {\r
- Object result;\r
- double length = (double)getLengthProperty(thisObj);\r
- int argc = args.length;\r
-\r
- if (args.length > 0) {\r
- /* Slide up the array to make room for args at the bottom */\r
- if (length > 0) {\r
- for (long last = (long)length - 1; last >= 0; last--) {\r
- Object temp = getElem(thisObj, last);\r
- setElem(thisObj, last + argc, temp);\r
- }\r
- }\r
-\r
- /* Copy from argv to the bottom of the array. */\r
- for (int i = 0; i < args.length; i++) {\r
- setElem(thisObj, i, args[i]);\r
- }\r
-\r
- /* Follow Perl by returning the new array length. */\r
- length += args.length;\r
- ScriptRuntime.setProp(thisObj, "length",\r
- new Double(length), thisObj);\r
- }\r
- return new Long((long)length);\r
- }\r
-\r
- private static Object jsFunction_splice(Context cx, Scriptable scope,\r
- Scriptable thisObj, Object[] args)\r
- {\r
- /* create an empty Array to return. */\r
- scope = getTopLevelScope(scope);\r
- Object result = ScriptRuntime.newObject(cx, scope, "Array", null);\r
- int argc = args.length;\r
- if (argc == 0)\r
- return result;\r
- double length = getLengthProperty(thisObj);\r
-\r
- /* Convert the first argument into a starting index. */\r
- double begin = ScriptRuntime.toInteger(args[0]);\r
- double end;\r
- double delta;\r
- double count;\r
-\r
- if (begin < 0) {\r
- begin += length;\r
- if (begin < 0)\r
- begin = 0;\r
- } else if (begin > length) {\r
- begin = length;\r
- }\r
- argc--;\r
-\r
- /* Convert the second argument from a count into a fencepost index. */\r
- delta = length - begin;\r
-\r
- if (args.length == 1) {\r
- count = delta;\r
- end = length;\r
- } else {\r
- count = ScriptRuntime.toInteger(args[1]);\r
- if (count < 0)\r
- count = 0;\r
- else if (count > delta)\r
- count = delta;\r
- end = begin + count;\r
-\r
- argc--;\r
- }\r
-\r
- long lbegin = (long)begin;\r
- long lend = (long)end;\r
-\r
- /* If there are elements to remove, put them into the return value. */\r
- if (count > 0) {\r
- if (count == 1\r
- && (cx.getLanguageVersion() == Context.VERSION_1_2))\r
- {\r
- /*\r
- * JS lacks "list context", whereby in Perl one turns the\r
- * single scalar that's spliced out into an array just by\r
- * assigning it to @single instead of $single, or by using it\r
- * as Perl push's first argument, for instance.\r
- *\r
- * JS1.2 emulated Perl too closely and returned a non-Array for\r
- * the single-splice-out case, requiring callers to test and\r
- * wrap in [] if necessary. So JS1.3, default, and other\r
- * versions all return an array of length 1 for uniformity.\r
- */\r
- result = getElem(thisObj, lbegin);\r
- } else {\r
- for (long last = lbegin; last < lend; last++) {\r
- Scriptable resultArray = (Scriptable)result;\r
- Object temp = getElem(thisObj, last);\r
- setElem(resultArray, last - lbegin, temp);\r
- }\r
- }\r
- } else if (count == 0\r
- && cx.getLanguageVersion() == Context.VERSION_1_2)\r
- {\r
- /* Emulate C JS1.2; if no elements are removed, return undefined. */\r
- result = Context.getUndefinedValue();\r
- }\r
-\r
- /* Find the direction (up or down) to copy and make way for argv. */\r
- delta = argc - count;\r
-\r
- if (delta > 0) {\r
- for (long last = (long)length - 1; last >= lend; last--) {\r
- Object temp = getElem(thisObj, last);\r
- setElem(thisObj, last + (long)delta, temp);\r
- }\r
- } else if (delta < 0) {\r
- for (long last = lend; last < length; last++) {\r
- Object temp = getElem(thisObj, last);\r
- setElem(thisObj, last + (long)delta, temp);\r
- }\r
- }\r
-\r
- /* Copy from argv into the hole to complete the splice. */\r
- int argoffset = args.length - argc;\r
- for (int i = 0; i < argc; i++) {\r
- setElem(thisObj, lbegin + i, args[i + argoffset]);\r
- }\r
-\r
- /* Update length in case we deleted elements from the end. */\r
- ScriptRuntime.setProp(thisObj, "length",\r
- new Double(length + delta), thisObj);\r
- return result;\r
- }\r
-\r
- /*\r
- * Python-esque sequence operations.\r
- */\r
- private static Scriptable jsFunction_concat(Context cx, Scriptable scope, \r
- Scriptable thisObj,\r
- Object[] args)\r
- {\r
- /* Concat tries to keep the definition of an array as general\r
- * as possible; if it finds that an object has a numeric\r
- * 'length' property, then it treats that object as an array.\r
- * This treats string atoms and string objects differently; as\r
- * string objects have a length property and are accessible by\r
- * index, they get exploded into arrays when added, while\r
- * atomic strings are just added as strings.\r
- */\r
-\r
- // create an empty Array to return.\r
- scope = getTopLevelScope(scope);\r
- Scriptable result = ScriptRuntime.newObject(cx, scope, "Array", null);\r
- double length;\r
- long slot = 0;\r
-\r
- /* Put the target in the result array; only add it as an array\r
- * if it looks like one.\r
- */\r
- if (hasLengthProperty(thisObj)) {\r
- length = getLengthProperty(thisObj);\r
-\r
- // Copy from the target object into the result\r
- for (slot = 0; slot < length; slot++) {\r
- Object temp = getElem(thisObj, slot);\r
- setElem(result, slot, temp);\r
- }\r
- } else {\r
- setElem(result, slot++, thisObj);\r
- }\r
-\r
- /* Copy from the arguments into the result. If any argument\r
- * has a numeric length property, treat it as an array and add\r
- * elements separately; otherwise, just copy the argument.\r
- */\r
- for (int i = 0; i < args.length; i++) {\r
- if (hasLengthProperty(args[i])) {\r
- // hasLengthProperty => instanceOf Scriptable.\r
- Scriptable arg = (Scriptable)args[i];\r
- length = getLengthProperty(arg);\r
- for (long j = 0; j < length; j++, slot++) {\r
- Object temp = getElem(arg, j);\r
- setElem(result, slot, temp);\r
- }\r
- } else {\r
- setElem(result, slot++, args[i]);\r
- }\r
- }\r
- return result;\r
- }\r
-\r
- private Scriptable jsFunction_slice(Context cx, Scriptable thisObj,\r
- Object[] args)\r
- {\r
- Scriptable scope = getTopLevelScope(this);\r
- Scriptable result = ScriptRuntime.newObject(cx, scope, "Array", null);\r
- double length = getLengthProperty(thisObj);\r
-\r
- double begin = 0;\r
- double end = length;\r
-\r
- if (args.length > 0) {\r
- begin = ScriptRuntime.toInteger(args[0]);\r
- if (begin < 0) {\r
- begin += length;\r
- if (begin < 0)\r
- begin = 0;\r
- } else if (begin > length) {\r
- begin = length;\r
- }\r
-\r
- if (args.length > 1) {\r
- end = ScriptRuntime.toInteger(args[1]);\r
- if (end < 0) {\r
- end += length;\r
- if (end < 0)\r
- end = 0;\r
- } else if (end > length) {\r
- end = length;\r
- }\r
- }\r
- }\r
-\r
- long lbegin = (long)begin;\r
- long lend = (long)end;\r
- for (long slot = lbegin; slot < lend; slot++) {\r
- Object temp = getElem(thisObj, slot);\r
- setElem(result, slot - lbegin, temp);\r
- }\r
-\r
- return result;\r
- }\r
-\r
- protected int maxInstanceId() { return MAX_INSTANCE_ID; }\r
-\r
- protected String getIdName(int id) {\r
- if (id == Id_length) { return "length"; }\r
-\r
- if (prototypeFlag) {\r
- switch (id) {\r
- case Id_constructor: return "constructor";\r
- case Id_toString: return "toString";\r
- case Id_toLocaleString: return "toLocaleString";\r
- case Id_join: return "join";\r
- case Id_reverse: return "reverse";\r
- case Id_sort: return "sort";\r
- case Id_push: return "push";\r
- case Id_pop: return "pop";\r
- case Id_shift: return "shift";\r
- case Id_unshift: return "unshift";\r
- case Id_splice: return "splice";\r
- case Id_concat: return "concat";\r
- case Id_slice: return "slice";\r
- }\r
- }\r
- return null;\r
- }\r
-\r
- private static final int\r
- Id_length = 1,\r
- MAX_INSTANCE_ID = 1;\r
-\r
- protected int mapNameToId(String s) {\r
- if (s.equals("length")) { return Id_length; }\r
- else if (prototypeFlag) { \r
- return toPrototypeId(s); \r
- }\r
- return 0;\r
- }\r
-\r
-// #string_id_map#\r
-\r
- private static int toPrototypeId(String s) {\r
- int id;\r
-// #generated# Last update: 2001-04-23 11:46:01 GMT+02:00\r
- L0: { id = 0; String X = null; int c;\r
- L: switch (s.length()) {\r
- case 3: X="pop";id=Id_pop; break L;\r
- case 4: c=s.charAt(0);\r
- if (c=='j') { X="join";id=Id_join; }\r
- else if (c=='p') { X="push";id=Id_push; }\r
- else if (c=='s') { X="sort";id=Id_sort; }\r
- break L;\r
- case 5: c=s.charAt(1);\r
- if (c=='h') { X="shift";id=Id_shift; }\r
- else if (c=='l') { X="slice";id=Id_slice; }\r
- break L;\r
- case 6: c=s.charAt(0);\r
- if (c=='c') { X="concat";id=Id_concat; }\r
- else if (c=='l') { X="length";id=Id_length; }\r
- else if (c=='s') { X="splice";id=Id_splice; }\r
- break L;\r
- case 7: c=s.charAt(0);\r
- if (c=='r') { X="reverse";id=Id_reverse; }\r
- else if (c=='u') { X="unshift";id=Id_unshift; }\r
- break L;\r
- case 8: X="toString";id=Id_toString; break L;\r
- case 11: X="constructor";id=Id_constructor; break L;\r
- case 14: X="toLocaleString";id=Id_toLocaleString; break L;\r
- }\r
- if (X!=null && X!=s && !X.equals(s)) id = 0;\r
- }\r
-// #/generated#\r
- return id;\r
- }\r
-\r
- private static final int\r
- Id_constructor = MAX_INSTANCE_ID + 1,\r
- Id_toString = MAX_INSTANCE_ID + 2,\r
- Id_toLocaleString = MAX_INSTANCE_ID + 3,\r
- Id_join = MAX_INSTANCE_ID + 4,\r
- Id_reverse = MAX_INSTANCE_ID + 5,\r
- Id_sort = MAX_INSTANCE_ID + 6,\r
- Id_push = MAX_INSTANCE_ID + 7,\r
- Id_pop = MAX_INSTANCE_ID + 8,\r
- Id_shift = MAX_INSTANCE_ID + 9,\r
- Id_unshift = MAX_INSTANCE_ID + 10,\r
- Id_splice = MAX_INSTANCE_ID + 11,\r
- Id_concat = MAX_INSTANCE_ID + 12,\r
- Id_slice = MAX_INSTANCE_ID + 13,\r
-\r
- MAX_PROTOTYPE_ID = MAX_INSTANCE_ID + 13;\r
-\r
-// #/string_id_map#\r
-\r
- private long length;\r
- private Object[] dense;\r
- private static final int maximumDenseLength = 10000;\r
- \r
- private boolean prototypeFlag;\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- * Igor Bukanov\r
- * Mike McCabe\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-/**\r
- * This class implements the Boolean native object.\r
- * See ECMA 15.6.\r
- * @author Norris Boyd\r
- */\r
-public class NativeBoolean extends IdScriptable {\r
-\r
- public static void init(Context cx, Scriptable scope, boolean sealed) {\r
- NativeBoolean obj = new NativeBoolean();\r
- obj.prototypeFlag = true;\r
- obj.addAsPrototype(MAX_PROTOTYPE_ID, cx, scope, sealed);\r
- }\r
-\r
- /**\r
- * Zero-parameter constructor: just used to create Boolean.prototype\r
- */\r
- public NativeBoolean() {\r
- }\r
-\r
- public NativeBoolean(boolean b) {\r
- booleanValue = b;\r
- }\r
-\r
- public String getClassName() {\r
- return "Boolean";\r
- }\r
-\r
- public Object getDefaultValue(Class typeHint) {\r
- // This is actually non-ECMA, but will be proposed\r
- // as a change in round 2.\r
- if (typeHint == ScriptRuntime.BooleanClass)\r
- return wrap_boolean(booleanValue);\r
- return super.getDefaultValue(typeHint);\r
- }\r
-\r
- public int methodArity(int methodId) {\r
- if (prototypeFlag) {\r
- if (methodId == Id_constructor) return 1;\r
- if (methodId == Id_toString) return 0;\r
- if (methodId == Id_valueOf) return 0;\r
- }\r
- return super.methodArity(methodId);\r
- }\r
-\r
- public Object execMethod\r
- (int methodId, IdFunction f,\r
- Context cx, Scriptable scope, Scriptable thisObj, Object[] args)\r
- throws JavaScriptException\r
- {\r
- if (prototypeFlag) {\r
- if (methodId == Id_constructor) {\r
- return jsConstructor(args, thisObj == null);\r
- }\r
- else if (methodId == Id_toString) {\r
- return realThis(thisObj, f).jsFunction_toString();\r
- }\r
- else if (methodId == Id_valueOf) {\r
- return wrap_boolean(realThis(thisObj, f).jsFunction_valueOf());\r
- }\r
- }\r
-\r
- return super.execMethod(methodId, f, cx, scope, thisObj, args);\r
- }\r
-\r
- private NativeBoolean realThis(Scriptable thisObj, IdFunction f) {\r
- while (!(thisObj instanceof NativeBoolean)) {\r
- thisObj = nextInstanceCheck(thisObj, f, true);\r
- }\r
- return (NativeBoolean)thisObj;\r
- }\r
-\r
-\r
- private Object jsConstructor(Object[] args, boolean inNewExpr) {\r
- boolean b = ScriptRuntime.toBoolean(args, 0);\r
- if (inNewExpr) {\r
- // new Boolean(val) creates a new boolean object.\r
- return new NativeBoolean(b);\r
- }\r
-\r
- // Boolean(val) converts val to a boolean.\r
- return wrap_boolean(b);\r
- }\r
-\r
- private String jsFunction_toString() {\r
- return booleanValue ? "true" : "false";\r
- }\r
-\r
- private boolean jsFunction_valueOf() {\r
- return booleanValue;\r
- }\r
-\r
- protected String getIdName(int id) {\r
- if (prototypeFlag) {\r
- if (id == Id_constructor) return "constructor";\r
- if (id == Id_toString) return "toString";\r
- if (id == Id_valueOf) return "valueOf";\r
- }\r
- return null; \r
- }\r
-\r
-// #string_id_map#\r
-\r
- protected int mapNameToId(String s) {\r
- if (!prototypeFlag) { return 0; }\r
- int id;\r
-// #generated# Last update: 2001-04-23 10:38:18 CEST\r
- L0: { id = 0; String X = null;\r
- int s_length = s.length();\r
- if (s_length==7) { X="valueOf";id=Id_valueOf; }\r
- else if (s_length==8) { X="toString";id=Id_toString; }\r
- else if (s_length==11) { X="constructor";id=Id_constructor; }\r
- if (X!=null && X!=s && !X.equals(s)) id = 0;\r
- }\r
-// #/generated#\r
- return id;\r
- }\r
-\r
- private static final int\r
- Id_constructor = 1,\r
- Id_toString = 2,\r
- Id_valueOf = 3,\r
- MAX_PROTOTYPE_ID = 3;\r
-\r
-// #/string_id_map#\r
-\r
- private boolean booleanValue;\r
-\r
- private boolean prototypeFlag;\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-/**\r
- * This class implements the activation object.\r
- *\r
- * See ECMA 10.1.6\r
- *\r
- * @see org.mozilla.javascript.Arguments\r
- * @author Norris Boyd\r
- */\r
-public final class NativeCall extends IdScriptable {\r
-\r
- static void init(Context cx, Scriptable scope, boolean sealed) {\r
- NativeCall obj = new NativeCall();\r
- obj.prototypeFlag = true;\r
- obj.addAsPrototype(MAX_PROTOTYPE_ID, cx, scope, sealed);\r
- }\r
-\r
- NativeCall(Context cx, Scriptable scope, NativeFunction funObj, \r
- Scriptable thisObj, Object[] args)\r
- {\r
- this.funObj = funObj;\r
- this.thisObj = thisObj;\r
- \r
- setParentScope(scope);\r
- // leave prototype null\r
- \r
- // save current activation\r
- this.caller = cx.currentActivation;\r
- cx.currentActivation = this;\r
-\r
- this.originalArgs = (args == null) ? ScriptRuntime.emptyArgs : args;\r
- \r
- // initialize values of arguments\r
- String[] argNames = funObj.argNames;\r
- if (argNames != null) {\r
- for (int i=0; i < funObj.argCount; i++) {\r
- Object val = i < args.length ? args[i] \r
- : Undefined.instance;\r
- super.put(argNames[i], this, val);\r
- }\r
- }\r
- \r
- // initialize "arguments" property\r
- super.put("arguments", this, new Arguments(this));\r
- }\r
- \r
- private NativeCall() {\r
- }\r
-\r
- public String getClassName() {\r
- return "Call";\r
- }\r
- \r
- private static Object jsConstructor(Context cx, Object[] args, \r
- Function ctorObj, boolean inNewExpr)\r
- {\r
- if (!inNewExpr) {\r
- throw Context.reportRuntimeError1("msg.only.from.new", "Call");\r
- }\r
- ScriptRuntime.checkDeprecated(cx, "Call");\r
- NativeCall result = new NativeCall();\r
- result.setPrototype(getObjectPrototype(ctorObj));\r
- return result;\r
- }\r
- \r
- NativeCall getActivation(Function f) {\r
- NativeCall x = this;\r
- do {\r
- if (x.funObj == f)\r
- return x;\r
- x = x.caller;\r
- } while (x != null);\r
- return null;\r
- }\r
- \r
- public Function getFunctionObject() {\r
- return funObj;\r
- }\r
-\r
- public Object[] getOriginalArguments() {\r
- return originalArgs;\r
- }\r
- \r
- public NativeCall getCaller() {\r
- return caller;\r
- }\r
- \r
- public Scriptable getThisObj() {\r
- return thisObj;\r
- }\r
- \r
- public int methodArity(int methodId) {\r
- if (prototypeFlag) {\r
- if (methodId == Id_constructor) return 1;\r
- }\r
- return super.methodArity(methodId);\r
- }\r
-\r
- public Object execMethod\r
- (int methodId, IdFunction f,\r
- Context cx, Scriptable scope, Scriptable thisObj, Object[] args)\r
- throws JavaScriptException\r
- {\r
- if (prototypeFlag) {\r
- if (methodId == Id_constructor) {\r
- return jsConstructor(cx, args, f, thisObj == null);\r
- }\r
- }\r
- return super.execMethod(methodId, f, cx, scope, thisObj, args);\r
- }\r
-\r
- protected String getIdName(int id) {\r
- if (prototypeFlag) {\r
- if (id == Id_constructor) return "constructor";\r
- }\r
- return null; \r
- }\r
- \r
- protected int mapNameToId(String s) {\r
- if (!prototypeFlag) { return 0; }\r
- return s.equals("constructor") ? Id_constructor : 0;\r
- }\r
-\r
- private static final int\r
- Id_constructor = 1,\r
- MAX_PROTOTYPE_ID = 1;\r
-\r
- NativeCall caller;\r
- NativeFunction funObj;\r
- Scriptable thisObj;\r
- Object[] originalArgs;\r
- public int debugPC;\r
-\r
- private boolean prototypeFlag;\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s):\r
- * Norris Boyd\r
- * Mike McCabe\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-import java.util.Date;\r
-import java.util.TimeZone;\r
-import java.util.Locale;\r
-import java.text.NumberFormat;\r
-import java.text.DateFormat;\r
-import java.text.SimpleDateFormat;\r
-\r
-/**\r
- * This class implements the Date native object.\r
- * See ECMA 15.9.\r
- * @author Mike McCabe\r
- */\r
-public class NativeDate extends IdScriptable {\r
-\r
- public static void init(Context cx, Scriptable scope, boolean sealed) {\r
- NativeDate obj = new NativeDate();\r
- obj.prototypeFlag = true;\r
- \r
- // Set the value of the prototype Date to NaN ('invalid date');\r
- obj.date = ScriptRuntime.NaN;\r
-\r
- obj.addAsPrototype(MAX_PROTOTYPE_ID, cx, scope, sealed);\r
- }\r
- \r
- public NativeDate() {\r
- if (thisTimeZone == null) {\r
- // j.u.TimeZone is synchronized, so setting class statics from it\r
- // should be OK.\r
- thisTimeZone = java.util.TimeZone.getDefault();\r
- LocalTZA = thisTimeZone.getRawOffset();\r
- }\r
- }\r
-\r
- public String getClassName() {\r
- return "Date";\r
- }\r
-\r
- public Object getDefaultValue(Class typeHint) {\r
- if (typeHint == null)\r
- typeHint = ScriptRuntime.StringClass;\r
- return super.getDefaultValue(typeHint);\r
- }\r
-\r
- protected void fillConstructorProperties\r
- (Context cx, IdFunction ctor, boolean sealed)\r
- {\r
- addIdFunctionProperty(ctor, ConstructorId_UTC, sealed);\r
- addIdFunctionProperty(ctor, ConstructorId_parse, sealed);\r
- super.fillConstructorProperties(cx, ctor, sealed);\r
- }\r
-\r
- public int methodArity(int methodId) {\r
- if (prototypeFlag) {\r
- switch (methodId) {\r
- case ConstructorId_UTC: return 1;\r
- case ConstructorId_parse: return 1;\r
- case Id_constructor: return 1; \r
- case Id_toString: return 0;\r
- case Id_toTimeString: return 0;\r
- case Id_toDateString: return 0;\r
- case Id_toLocaleString: return 0;\r
- case Id_toLocaleTimeString: return 0;\r
- case Id_toLocaleDateString: return 0;\r
- case Id_toUTCString: return 0;\r
- case Id_valueOf: return 0;\r
- case Id_getTime: return 0;\r
- case Id_getYear: return 0;\r
- case Id_getFullYear: return 0;\r
- case Id_getUTCFullYear: return 0;\r
- case Id_getMonth: return 0;\r
- case Id_getUTCMonth: return 0;\r
- case Id_getDate: return 0;\r
- case Id_getUTCDate: return 0;\r
- case Id_getDay: return 0;\r
- case Id_getUTCDay: return 0;\r
- case Id_getHours: return 0;\r
- case Id_getUTCHours: return 0;\r
- case Id_getMinutes: return 0;\r
- case Id_getUTCMinutes: return 0;\r
- case Id_getSeconds: return 0;\r
- case Id_getUTCSeconds: return 0;\r
- case Id_getMilliseconds: return 0;\r
- case Id_getUTCMilliseconds: return 0;\r
- case Id_getTimezoneOffset: return 0;\r
- case Id_setTime: return 1;\r
- case Id_setMilliseconds: return 1;\r
- case Id_setUTCMilliseconds: return 1;\r
- case Id_setSeconds: return 2;\r
- case Id_setUTCSeconds: return 2;\r
- case Id_setMinutes: return 3;\r
- case Id_setUTCMinutes: return 3;\r
- case Id_setHours: return 4;\r
- case Id_setUTCHours: return 4;\r
- case Id_setDate: return 1;\r
- case Id_setUTCDate: return 1;\r
- case Id_setMonth: return 2;\r
- case Id_setUTCMonth: return 2;\r
- case Id_setFullYear: return 3;\r
- case Id_setUTCFullYear: return 3;\r
- case Id_setYear: return 1;\r
- }\r
- }\r
- return super.methodArity(methodId);\r
- }\r
-\r
- public String toString() {\r
- return date_format(date, FORMATSPEC_FULL);\r
- }\r
-\r
- public Object execMethod\r
- (int methodId, IdFunction f,\r
- Context cx, Scriptable scope, Scriptable thisObj, Object[] args)\r
- throws JavaScriptException\r
- {\r
- if (prototypeFlag) {\r
- switch (methodId) {\r
- case ConstructorId_UTC: \r
- return wrap_double(jsStaticFunction_UTC(args));\r
-\r
- case ConstructorId_parse: \r
- return wrap_double(jsStaticFunction_parse\r
- (ScriptRuntime.toString(args, 0)));\r
-\r
- case Id_constructor:\r
- return jsConstructor(args, thisObj == null);\r
-\r
- case Id_toString: {\r
- double t = realThis(thisObj, f, true).date;\r
- return date_format(t, FORMATSPEC_FULL);\r
- }\r
-\r
- case Id_toTimeString: {\r
- double t = realThis(thisObj, f, true).date;\r
- return date_format(t, FORMATSPEC_TIME);\r
- }\r
-\r
- case Id_toDateString: {\r
- double t = realThis(thisObj, f, true).date;\r
- return date_format(t, FORMATSPEC_DATE);\r
- }\r
-\r
- case Id_toLocaleString: {\r
- double t = realThis(thisObj, f, true).date;\r
- return jsFunction_toLocaleString(t);\r
- }\r
-\r
- case Id_toLocaleTimeString: {\r
- double t = realThis(thisObj, f, true).date;\r
- return jsFunction_toLocaleTimeString(t);\r
- }\r
-\r
- case Id_toLocaleDateString: {\r
- double t = realThis(thisObj, f, true).date;\r
- return jsFunction_toLocaleDateString(t);\r
- }\r
-\r
- case Id_toUTCString: {\r
- double t = realThis(thisObj, f, true).date;\r
- if (t == t) { return jsFunction_toUTCString(t); }\r
- return jsFunction_NaN_date_str;\r
- }\r
-\r
- case Id_valueOf: \r
- return wrap_double(realThis(thisObj, f, true).date);\r
-\r
- case Id_getTime: \r
- return wrap_double(realThis(thisObj, f, true).date);\r
-\r
- case Id_getYear: {\r
- double t = realThis(thisObj, f, true).date;\r
- if (t == t) { t = jsFunction_getYear(cx, t); }\r
- return wrap_double(t);\r
- }\r
-\r
- case Id_getFullYear: {\r
- double t = realThis(thisObj, f, true).date;\r
- if (t == t) { t = YearFromTime(LocalTime(t)); }\r
- return wrap_double(t);\r
- }\r
-\r
- case Id_getUTCFullYear: {\r
- double t = realThis(thisObj, f, true).date;\r
- if (t == t) { t = YearFromTime(t); }\r
- return wrap_double(t);\r
- }\r
-\r
- case Id_getMonth: {\r
- double t = realThis(thisObj, f, true).date;\r
- if (t == t) { t = MonthFromTime(LocalTime(t)); }\r
- return wrap_double(t);\r
- }\r
- \r
- case Id_getUTCMonth: {\r
- double t = realThis(thisObj, f, true).date;\r
- if (t == t) { t = MonthFromTime(t); }\r
- return wrap_double(t);\r
- }\r
-\r
- case Id_getDate: {\r
- double t = realThis(thisObj, f, true).date;\r
- if (t == t) { t = DateFromTime(LocalTime(t)); }\r
- return wrap_double(t);\r
- }\r
-\r
- case Id_getUTCDate: {\r
- double t = realThis(thisObj, f, true).date;\r
- if (t == t) { t = DateFromTime(t); }\r
- return wrap_double(t);\r
- } \r
-\r
- case Id_getDay: {\r
- double t = realThis(thisObj, f, true).date;\r
- if (t == t) { t = WeekDay(LocalTime(t)); }\r
- return wrap_double(t);\r
- }\r
-\r
- case Id_getUTCDay: {\r
- double t = realThis(thisObj, f, true).date;\r
- if (t == t) { t = WeekDay(t); }\r
- return wrap_double(t);\r
- } \r
-\r
- case Id_getHours: {\r
- double t = realThis(thisObj, f, true).date;\r
- if (t == t) { t = HourFromTime(LocalTime(t)); }\r
- return wrap_double(t);\r
- } \r
-\r
- case Id_getUTCHours: {\r
- double t = realThis(thisObj, f, true).date;\r
- if (t == t) { t = HourFromTime(t); }\r
- return wrap_double(t);\r
- }\r
-\r
- case Id_getMinutes: {\r
- double t = realThis(thisObj, f, true).date;\r
- if (t == t) { t = MinFromTime(LocalTime(t)); }\r
- return wrap_double(t);\r
- } \r
-\r
- case Id_getUTCMinutes: {\r
- double t = realThis(thisObj, f, true).date;\r
- if (t == t) { t = MinFromTime(t); }\r
- return wrap_double(t);\r
- } \r
-\r
- case Id_getSeconds: {\r
- double t = realThis(thisObj, f, true).date;\r
- if (t == t) { t = SecFromTime(LocalTime(t)); }\r
- return wrap_double(t);\r
- }\r
-\r
- case Id_getUTCSeconds: {\r
- double t = realThis(thisObj, f, true).date;\r
- if (t == t) { t = SecFromTime(t); }\r
- return wrap_double(t);\r
- }\r
- \r
- case Id_getMilliseconds: {\r
- double t = realThis(thisObj, f, true).date;\r
- if (t == t) { t = msFromTime(LocalTime(t)); }\r
- return wrap_double(t);\r
- }\r
-\r
- case Id_getUTCMilliseconds: {\r
- double t = realThis(thisObj, f, true).date;\r
- if (t == t) { t = msFromTime(t); }\r
- return wrap_double(t);\r
- }\r
- \r
- case Id_getTimezoneOffset: {\r
- double t = realThis(thisObj, f, true).date;\r
- if (t == t) { t = jsFunction_getTimezoneOffset(t); }\r
- return wrap_double(t);\r
- }\r
-\r
- case Id_setTime: \r
- return wrap_double(realThis(thisObj, f, true).\r
- jsFunction_setTime(ScriptRuntime.toNumber(args, 0)));\r
-\r
- case Id_setMilliseconds: \r
- return wrap_double(realThis(thisObj, f, false).\r
- makeTime(args, 1, true));\r
-\r
- case Id_setUTCMilliseconds: \r
- return wrap_double(realThis(thisObj, f, false).\r
- makeTime(args, 1, false));\r
-\r
- case Id_setSeconds: \r
- return wrap_double(realThis(thisObj, f, false).\r
- makeTime(args, 2, true));\r
-\r
- case Id_setUTCSeconds: \r
- return wrap_double(realThis(thisObj, f, false).\r
- makeTime(args, 2, false));\r
-\r
- case Id_setMinutes: \r
- return wrap_double(realThis(thisObj, f, false).\r
- makeTime(args, 3, true));\r
-\r
- case Id_setUTCMinutes: \r
- return wrap_double(realThis(thisObj, f, false).\r
- makeTime(args, 3, false));\r
-\r
- case Id_setHours: \r
- return wrap_double(realThis(thisObj, f, false).\r
- makeTime(args, 4, true));\r
-\r
- case Id_setUTCHours: \r
- return wrap_double(realThis(thisObj, f, false).\r
- makeTime(args, 4, false));\r
-\r
- case Id_setDate: \r
- return wrap_double(realThis(thisObj, f, false).\r
- makeDate(args, 1, true));\r
-\r
- case Id_setUTCDate: \r
- return wrap_double(realThis(thisObj, f, false).\r
- makeDate(args, 1, false));\r
-\r
- case Id_setMonth: \r
- return wrap_double(realThis(thisObj, f, false).\r
- makeDate(args, 2, true));\r
-\r
- case Id_setUTCMonth: \r
- return wrap_double(realThis(thisObj, f, false).\r
- makeDate(args, 2, false));\r
-\r
- case Id_setFullYear: \r
- return wrap_double(realThis(thisObj, f, false).\r
- makeDate(args, 3, true));\r
-\r
- case Id_setUTCFullYear: \r
- return wrap_double(realThis(thisObj, f, false).\r
- makeDate(args, 3, false));\r
-\r
- case Id_setYear: \r
- return wrap_double(realThis(thisObj, f, false).\r
- jsFunction_setYear(ScriptRuntime.toNumber(args, 0)));\r
- }\r
- }\r
-\r
- return super.execMethod(methodId, f, cx, scope, thisObj, args);\r
- }\r
-\r
- private NativeDate realThis(Scriptable thisObj, IdFunction f, \r
- boolean readOnly)\r
- {\r
- while (!(thisObj instanceof NativeDate)) {\r
- thisObj = nextInstanceCheck(thisObj, f, readOnly);\r
- }\r
- return (NativeDate)thisObj;\r
- }\r
-\r
- /* ECMA helper functions */\r
-\r
- private static final double HalfTimeDomain = 8.64e15;\r
- private static final double HoursPerDay = 24.0;\r
- private static final double MinutesPerHour = 60.0;\r
- private static final double SecondsPerMinute = 60.0;\r
- private static final double msPerSecond = 1000.0;\r
- private static final double MinutesPerDay = (HoursPerDay * MinutesPerHour);\r
- private static final double SecondsPerDay = (MinutesPerDay * SecondsPerMinute);\r
- private static final double SecondsPerHour = (MinutesPerHour * SecondsPerMinute);\r
- private static final double msPerDay = (SecondsPerDay * msPerSecond);\r
- private static final double msPerHour = (SecondsPerHour * msPerSecond);\r
- private static final double msPerMinute = (SecondsPerMinute * msPerSecond);\r
-\r
- private static double Day(double t) {\r
- return Math.floor(t / msPerDay);\r
- }\r
-\r
- private static double TimeWithinDay(double t) {\r
- double result;\r
- result = t % msPerDay;\r
- if (result < 0)\r
- result += msPerDay;\r
- return result;\r
- }\r
-\r
- private static int DaysInYear(int y) {\r
- if (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))\r
- return 366;\r
- else\r
- return 365;\r
- }\r
-\r
-\r
- /* math here has to be f.p, because we need\r
- * floor((1968 - 1969) / 4) == -1\r
- */\r
- private static double DayFromYear(double y) {\r
- return ((365 * ((y)-1970) + Math.floor(((y)-1969)/4.0)\r
- - Math.floor(((y)-1901)/100.0) + Math.floor(((y)-1601)/400.0)));\r
- }\r
-\r
- private static double TimeFromYear(double y) {\r
- return DayFromYear(y) * msPerDay;\r
- }\r
-\r
- private static int YearFromTime(double t) {\r
- int lo = (int) Math.floor((t / msPerDay) / 366) + 1970;\r
- int hi = (int) Math.floor((t / msPerDay) / 365) + 1970;\r
- int mid;\r
-\r
- /* above doesn't work for negative dates... */\r
- if (hi < lo) {\r
- int temp = lo;\r
- lo = hi;\r
- hi = temp;\r
- }\r
-\r
- /* Use a simple binary search algorithm to find the right\r
- year. This seems like brute force... but the computation\r
- of hi and lo years above lands within one year of the\r
- correct answer for years within a thousand years of\r
- 1970; the loop below only requires six iterations\r
- for year 270000. */\r
- while (hi > lo) {\r
- mid = (hi + lo) / 2;\r
- if (TimeFromYear(mid) > t) {\r
- hi = mid - 1;\r
- } else {\r
- if (TimeFromYear(mid) <= t) {\r
- int temp = mid + 1;\r
- if (TimeFromYear(temp) > t) {\r
- return mid;\r
- }\r
- lo = mid + 1;\r
- }\r
- }\r
- }\r
- return lo;\r
- }\r
-\r
- private static boolean InLeapYear(double t) {\r
- return DaysInYear(YearFromTime(t)) == 366;\r
- }\r
-\r
- private static int DayWithinYear(double t) {\r
- int year = YearFromTime(t);\r
- return (int) (Day(t) - DayFromYear(year));\r
- }\r
- /*\r
- * The following array contains the day of year for the first day of\r
- * each month, where index 0 is January, and day 0 is January 1.\r
- */\r
-\r
- private static double DayFromMonth(int m, boolean leap) {\r
- int day = m * 30;\r
-\r
- if (m >= 7) { day += m / 2 - 1; }\r
- else if (m >= 2) { day += (m - 1) / 2 - 1; }\r
- else { day += m; }\r
-\r
- if (leap && m >= 2) { ++day; }\r
-\r
- return day;\r
- }\r
-\r
- private static int MonthFromTime(double t) {\r
- int d, step;\r
-\r
- d = DayWithinYear(t);\r
-\r
- if (d < (step = 31))\r
- return 0;\r
-\r
- // Originally coded as step += (InLeapYear(t) ? 29 : 28);\r
- // but some jits always returned 28!\r
- if (InLeapYear(t))\r
- step += 29;\r
- else\r
- step += 28;\r
-\r
- if (d < step)\r
- return 1;\r
- if (d < (step += 31))\r
- return 2;\r
- if (d < (step += 30))\r
- return 3;\r
- if (d < (step += 31))\r
- return 4;\r
- if (d < (step += 30))\r
- return 5;\r
- if (d < (step += 31))\r
- return 6;\r
- if (d < (step += 31))\r
- return 7;\r
- if (d < (step += 30))\r
- return 8;\r
- if (d < (step += 31))\r
- return 9;\r
- if (d < (step += 30))\r
- return 10;\r
- return 11;\r
- }\r
-\r
- private static int DateFromTime(double t) {\r
- int d, step, next;\r
-\r
- d = DayWithinYear(t);\r
- if (d <= (next = 30))\r
- return d + 1;\r
- step = next;\r
-\r
- // Originally coded as next += (InLeapYear(t) ? 29 : 28);\r
- // but some jits always returned 28!\r
- if (InLeapYear(t))\r
- next += 29;\r
- else\r
- next += 28;\r
-\r
- if (d <= next)\r
- return d - step;\r
- step = next;\r
- if (d <= (next += 31))\r
- return d - step;\r
- step = next;\r
- if (d <= (next += 30))\r
- return d - step;\r
- step = next;\r
- if (d <= (next += 31))\r
- return d - step;\r
- step = next;\r
- if (d <= (next += 30))\r
- return d - step;\r
- step = next;\r
- if (d <= (next += 31))\r
- return d - step;\r
- step = next;\r
- if (d <= (next += 31))\r
- return d - step;\r
- step = next;\r
- if (d <= (next += 30))\r
- return d - step;\r
- step = next;\r
- if (d <= (next += 31))\r
- return d - step;\r
- step = next;\r
- if (d <= (next += 30))\r
- return d - step;\r
- step = next;\r
-\r
- return d - step;\r
- }\r
-\r
- private static int WeekDay(double t) {\r
- double result;\r
- result = Day(t) + 4;\r
- result = result % 7;\r
- if (result < 0)\r
- result += 7;\r
- return (int) result;\r
- }\r
-\r
- private static double Now() {\r
- return (double) System.currentTimeMillis();\r
- }\r
-\r
- /* Should be possible to determine the need for this dynamically\r
- * if we go with the workaround... I'm not using it now, because I\r
- * can't think of any clean way to make toLocaleString() and the\r
- * time zone (comment) in toString match the generated string\r
- * values. Currently it's wrong-but-consistent in all but the\r
- * most recent betas of the JRE - seems to work in 1.1.7.\r
- */\r
- private final static boolean TZO_WORKAROUND = false;\r
- private static double DaylightSavingTA(double t) {\r
- if (!TZO_WORKAROUND) {\r
- Date date = new Date((long) t);\r
- if (thisTimeZone.inDaylightTime(date))\r
- return msPerHour;\r
- else\r
- return 0;\r
- } else {\r
- /* Use getOffset if inDaylightTime() is broken, because it\r
- * seems to work acceptably. We don't switch over to it\r
- * entirely, because it requires (expensive) exploded date arguments,\r
- * and the api makes it impossible to handle dst\r
- * changeovers cleanly.\r
- */\r
-\r
- // Hardcode the assumption that the changeover always\r
- // happens at 2:00 AM:\r
- t += LocalTZA + (HourFromTime(t) <= 2 ? msPerHour : 0);\r
-\r
- int year = YearFromTime(t);\r
- double offset = thisTimeZone.getOffset(year > 0 ? 1 : 0,\r
- year,\r
- MonthFromTime(t),\r
- DateFromTime(t),\r
- WeekDay(t),\r
- (int)TimeWithinDay(t));\r
-\r
- if ((offset - LocalTZA) != 0)\r
- return msPerHour;\r
- else\r
- return 0;\r
- // return offset - LocalTZA;\r
- }\r
- }\r
-\r
- private static double LocalTime(double t) {\r
- return t + LocalTZA + DaylightSavingTA(t);\r
- }\r
-\r
- public static double internalUTC(double t) {\r
- return t - LocalTZA - DaylightSavingTA(t - LocalTZA);\r
- }\r
-\r
- private static int HourFromTime(double t) {\r
- double result;\r
- result = Math.floor(t / msPerHour) % HoursPerDay;\r
- if (result < 0)\r
- result += HoursPerDay;\r
- return (int) result;\r
- }\r
-\r
- private static int MinFromTime(double t) {\r
- double result;\r
- result = Math.floor(t / msPerMinute) % MinutesPerHour;\r
- if (result < 0)\r
- result += MinutesPerHour;\r
- return (int) result;\r
- }\r
-\r
- private static int SecFromTime(double t) {\r
- double result;\r
- result = Math.floor(t / msPerSecond) % SecondsPerMinute;\r
- if (result < 0)\r
- result += SecondsPerMinute;\r
- return (int) result;\r
- }\r
-\r
- private static int msFromTime(double t) {\r
- double result;\r
- result = t % msPerSecond;\r
- if (result < 0)\r
- result += msPerSecond;\r
- return (int) result;\r
- }\r
-\r
- private static double MakeTime(double hour, double min,\r
- double sec, double ms)\r
- {\r
- return ((hour * MinutesPerHour + min) * SecondsPerMinute + sec)\r
- * msPerSecond + ms;\r
- }\r
-\r
- private static double MakeDay(double year, double month, double date) {\r
- double result;\r
- boolean leap;\r
- double yearday;\r
- double monthday;\r
-\r
- year += Math.floor(month / 12);\r
-\r
- month = month % 12;\r
- if (month < 0)\r
- month += 12;\r
-\r
- leap = (DaysInYear((int) year) == 366);\r
-\r
- yearday = Math.floor(TimeFromYear(year) / msPerDay);\r
- monthday = DayFromMonth((int) month, leap);\r
-\r
- result = yearday\r
- + monthday\r
- + date - 1;\r
- return result;\r
- }\r
-\r
- private static double MakeDate(double day, double time) {\r
- return day * msPerDay + time;\r
- }\r
-\r
- private static double TimeClip(double d) {\r
- if (d != d ||\r
- d == Double.POSITIVE_INFINITY ||\r
- d == Double.NEGATIVE_INFINITY ||\r
- Math.abs(d) > HalfTimeDomain)\r
- {\r
- return ScriptRuntime.NaN;\r
- }\r
- if (d > 0.0)\r
- return Math.floor(d + 0.);\r
- else\r
- return Math.ceil(d + 0.);\r
- }\r
-\r
- /* end of ECMA helper functions */\r
-\r
- /* find UTC time from given date... no 1900 correction! */\r
- public static double date_msecFromDate(double year, double mon,\r
- double mday, double hour,\r
- double min, double sec,\r
- double msec)\r
- {\r
- double day;\r
- double time;\r
- double result;\r
-\r
- day = MakeDay(year, mon, mday);\r
- time = MakeTime(hour, min, sec, msec);\r
- result = MakeDate(day, time);\r
- return result;\r
- }\r
-\r
-\r
- private static final int MAXARGS = 7;\r
- private static double jsStaticFunction_UTC(Object[] args) {\r
- double array[] = new double[MAXARGS];\r
- int loop;\r
- double d;\r
-\r
- for (loop = 0; loop < MAXARGS; loop++) {\r
- if (loop < args.length) {\r
- d = ScriptRuntime.toNumber(args[loop]);\r
- if (d != d || Double.isInfinite(d)) {\r
- return ScriptRuntime.NaN;\r
- }\r
- array[loop] = ScriptRuntime.toInteger(args[loop]);\r
- } else {\r
- array[loop] = 0;\r
- }\r
- }\r
-\r
- /* adjust 2-digit years into the 20th century */\r
- if (array[0] >= 0 && array[0] <= 99)\r
- array[0] += 1900;\r
-\r
- /* if we got a 0 for 'date' (which is out of range)\r
- * pretend it's a 1. (So Date.UTC(1972, 5) works) */\r
- if (array[2] < 1)\r
- array[2] = 1;\r
-\r
- d = date_msecFromDate(array[0], array[1], array[2],\r
- array[3], array[4], array[5], array[6]);\r
- d = TimeClip(d);\r
- return d;\r
- // return new Double(d);\r
- }\r
-\r
- /*\r
- * Use ported code from jsdate.c rather than the locale-specific\r
- * date-parsing code from Java, to keep js and rhino consistent.\r
- * Is this the right strategy?\r
- */\r
-\r
- /* for use by date_parse */\r
-\r
- /* replace this with byte arrays? Cheaper? */\r
- private static String wtb[] = {\r
- "am", "pm",\r
- "monday", "tuesday", "wednesday", "thursday", "friday",\r
- "saturday", "sunday",\r
- "january", "february", "march", "april", "may", "june",\r
- "july", "august", "september", "october", "november", "december",\r
- "gmt", "ut", "utc", "est", "edt", "cst", "cdt",\r
- "mst", "mdt", "pst", "pdt"\r
- /* time zone table needs to be expanded */\r
- };\r
-\r
- private static int ttb[] = {\r
- -1, -2, 0, 0, 0, 0, 0, 0, 0, /* AM/PM */\r
- 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,\r
- 10000 + 0, 10000 + 0, 10000 + 0, /* UT/UTC */\r
- 10000 + 5 * 60, 10000 + 4 * 60, /* EDT */\r
- 10000 + 6 * 60, 10000 + 5 * 60,\r
- 10000 + 7 * 60, 10000 + 6 * 60,\r
- 10000 + 8 * 60, 10000 + 7 * 60\r
- };\r
-\r
- /* helper for date_parse */\r
- private static boolean date_regionMatches(String s1, int s1off,\r
- String s2, int s2off,\r
- int count)\r
- {\r
- boolean result = false;\r
- /* return true if matches, otherwise, false */\r
- int s1len = s1.length();\r
- int s2len = s2.length();\r
-\r
- while (count > 0 && s1off < s1len && s2off < s2len) {\r
- if (Character.toLowerCase(s1.charAt(s1off)) !=\r
- Character.toLowerCase(s2.charAt(s2off)))\r
- break;\r
- s1off++;\r
- s2off++;\r
- count--;\r
- }\r
-\r
- if (count == 0) {\r
- result = true;\r
- }\r
- return result;\r
- }\r
-\r
- private static double date_parseString(String s) {\r
- double msec;\r
-\r
- int year = -1;\r
- int mon = -1;\r
- int mday = -1;\r
- int hour = -1;\r
- int min = -1;\r
- int sec = -1;\r
- char c = 0;\r
- char si = 0;\r
- int i = 0;\r
- int n = -1;\r
- double tzoffset = -1;\r
- char prevc = 0;\r
- int limit = 0;\r
- boolean seenplusminus = false;\r
-\r
- if (s == null) // ??? Will s be null?\r
- return ScriptRuntime.NaN;\r
- limit = s.length();\r
- while (i < limit) {\r
- c = s.charAt(i);\r
- i++;\r
- if (c <= ' ' || c == ',' || c == '-') {\r
- if (i < limit) {\r
- si = s.charAt(i);\r
- if (c == '-' && '0' <= si && si <= '9') {\r
- prevc = c;\r
- }\r
- }\r
- continue;\r
- }\r
- if (c == '(') { /* comments) */\r
- int depth = 1;\r
- while (i < limit) {\r
- c = s.charAt(i);\r
- i++;\r
- if (c == '(')\r
- depth++;\r
- else if (c == ')')\r
- if (--depth <= 0)\r
- break;\r
- }\r
- continue;\r
- }\r
- if ('0' <= c && c <= '9') {\r
- n = c - '0';\r
- while (i < limit && '0' <= (c = s.charAt(i)) && c <= '9') {\r
- n = n * 10 + c - '0';\r
- i++;\r
- }\r
-\r
- /* allow TZA before the year, so\r
- * 'Wed Nov 05 21:49:11 GMT-0800 1997'\r
- * works */\r
-\r
- /* uses of seenplusminus allow : in TZA, so Java\r
- * no-timezone style of GMT+4:30 works\r
- */\r
- if ((prevc == '+' || prevc == '-')/* && year>=0 */) {\r
- /* make ':' case below change tzoffset */\r
- seenplusminus = true;\r
-\r
- /* offset */\r
- if (n < 24)\r
- n = n * 60; /* EG. "GMT-3" */\r
- else\r
- n = n % 100 + n / 100 * 60; /* eg "GMT-0430" */\r
- if (prevc == '+') /* plus means east of GMT */\r
- n = -n;\r
- if (tzoffset != 0 && tzoffset != -1)\r
- return ScriptRuntime.NaN;\r
- tzoffset = n;\r
- } else if (n >= 70 ||\r
- (prevc == '/' && mon >= 0 && mday >= 0 && year < 0)) {\r
- if (year >= 0)\r
- return ScriptRuntime.NaN;\r
- else if (c <= ' ' || c == ',' || c == '/' || i >= limit)\r
- year = n < 100 ? n + 1900 : n;\r
- else\r
- return ScriptRuntime.NaN;\r
- } else if (c == ':') {\r
- if (hour < 0)\r
- hour = /*byte*/ n;\r
- else if (min < 0)\r
- min = /*byte*/ n;\r
- else\r
- return ScriptRuntime.NaN;\r
- } else if (c == '/') {\r
- if (mon < 0)\r
- mon = /*byte*/ n-1;\r
- else if (mday < 0)\r
- mday = /*byte*/ n;\r
- else\r
- return ScriptRuntime.NaN;\r
- } else if (i < limit && c != ',' && c > ' ' && c != '-') {\r
- return ScriptRuntime.NaN;\r
- } else if (seenplusminus && n < 60) { /* handle GMT-3:30 */\r
- if (tzoffset < 0)\r
- tzoffset -= n;\r
- else\r
- tzoffset += n;\r
- } else if (hour >= 0 && min < 0) {\r
- min = /*byte*/ n;\r
- } else if (min >= 0 && sec < 0) {\r
- sec = /*byte*/ n;\r
- } else if (mday < 0) {\r
- mday = /*byte*/ n;\r
- } else {\r
- return ScriptRuntime.NaN;\r
- }\r
- prevc = 0;\r
- } else if (c == '/' || c == ':' || c == '+' || c == '-') {\r
- prevc = c;\r
- } else {\r
- int st = i - 1;\r
- int k;\r
- while (i < limit) {\r
- c = s.charAt(i);\r
- if (!(('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z')))\r
- break;\r
- i++;\r
- }\r
- if (i <= st + 1)\r
- return ScriptRuntime.NaN;\r
- for (k = wtb.length; --k >= 0;)\r
- if (date_regionMatches(wtb[k], 0, s, st, i-st)) {\r
- int action = ttb[k];\r
- if (action != 0) {\r
- if (action < 0) {\r
- /*\r
- * AM/PM. Count 12:30 AM as 00:30, 12:30 PM as\r
- * 12:30, instead of blindly adding 12 if PM.\r
- */\r
- if (hour > 12 || hour < 0) {\r
- return ScriptRuntime.NaN;\r
- } else {\r
- if (action == -1 && hour == 12) { // am\r
- hour = 0;\r
- } else if (action == -2 && hour != 12) {// pm\r
- hour += 12;\r
- }\r
- }\r
- } else if (action <= 13) { /* month! */\r
- if (mon < 0) {\r
- mon = /*byte*/ (action - 2);\r
- } else {\r
- return ScriptRuntime.NaN;\r
- }\r
- } else {\r
- tzoffset = action - 10000;\r
- }\r
- }\r
- break;\r
- }\r
- if (k < 0)\r
- return ScriptRuntime.NaN;\r
- prevc = 0;\r
- }\r
- }\r
- if (year < 0 || mon < 0 || mday < 0)\r
- return ScriptRuntime.NaN;\r
- if (sec < 0)\r
- sec = 0;\r
- if (min < 0)\r
- min = 0;\r
- if (hour < 0)\r
- hour = 0;\r
- if (tzoffset == -1) { /* no time zone specified, have to use local */\r
- double time;\r
- time = date_msecFromDate(year, mon, mday, hour, min, sec, 0);\r
- return internalUTC(time);\r
- }\r
-\r
- msec = date_msecFromDate(year, mon, mday, hour, min, sec, 0);\r
- msec += tzoffset * msPerMinute;\r
- return msec;\r
- }\r
-\r
- private static double jsStaticFunction_parse(String s) {\r
- return date_parseString(s);\r
- }\r
-\r
- private static final int FORMATSPEC_FULL = 0;\r
- private static final int FORMATSPEC_DATE = 1;\r
- private static final int FORMATSPEC_TIME = 2;\r
-\r
- private static String date_format(double t, int format) {\r
- if (t != t)\r
- return jsFunction_NaN_date_str;\r
-\r
- StringBuffer result = new StringBuffer(60);\r
- double local = LocalTime(t);\r
-\r
- /* offset from GMT in minutes. The offset includes daylight savings,\r
- if it applies. */\r
- int minutes = (int) Math.floor((LocalTZA + DaylightSavingTA(t))\r
- / msPerMinute);\r
- /* map 510 minutes to 0830 hours */\r
- int offset = (minutes / 60) * 100 + minutes % 60;\r
-\r
- String dateStr = Integer.toString(DateFromTime(local));\r
- String hourStr = Integer.toString(HourFromTime(local));\r
- String minStr = Integer.toString(MinFromTime(local));\r
- String secStr = Integer.toString(SecFromTime(local));\r
- String offsetStr = Integer.toString(offset > 0 ? offset : -offset);\r
- int year = YearFromTime(local);\r
- String yearStr = Integer.toString(year > 0 ? year : -year);\r
-\r
- /* Tue Oct 31 09:41:40 GMT-0800 (PST) 2000 */\r
- /* Tue Oct 31 2000 */\r
- /* 09:41:40 GMT-0800 (PST) */\r
-\r
- if (format != FORMATSPEC_TIME) {\r
- result.append(days[WeekDay(local)]);\r
- result.append(' ');\r
- result.append(months[MonthFromTime(local)]);\r
- if (dateStr.length() == 1)\r
- result.append(" 0");\r
- else\r
- result.append(' ');\r
- result.append(dateStr);\r
- result.append(' ');\r
- }\r
-\r
- if (format != FORMATSPEC_DATE) {\r
- if (hourStr.length() == 1)\r
- result.append('0');\r
- result.append(hourStr);\r
- if (minStr.length() == 1)\r
- result.append(":0");\r
- else\r
- result.append(':');\r
- result.append(minStr);\r
- if (secStr.length() == 1)\r
- result.append(":0");\r
- else\r
- result.append(':');\r
- result.append(secStr);\r
- if (offset > 0)\r
- result.append(" GMT+");\r
- else\r
- result.append(" GMT-");\r
- for (int i = offsetStr.length(); i < 4; i++)\r
- result.append('0');\r
- result.append(offsetStr);\r
-\r
- if (timeZoneFormatter == null)\r
- timeZoneFormatter = new java.text.SimpleDateFormat("zzz");\r
-\r
- if (timeZoneFormatter != null) {\r
- result.append(" (");\r
- java.util.Date date = new Date((long) t);\r
- result.append(timeZoneFormatter.format(date));\r
- result.append(')');\r
- }\r
- if (format != FORMATSPEC_TIME)\r
- result.append(' ');\r
- }\r
-\r
- if (format != FORMATSPEC_TIME) {\r
- if (year < 0)\r
- result.append('-');\r
- for (int i = yearStr.length(); i < 4; i++)\r
- result.append('0');\r
- result.append(yearStr);\r
- }\r
-\r
- return result.toString();\r
- }\r
-\r
- /* the javascript constructor */\r
- private static Object jsConstructor(Object[] args, boolean inNewExpr) {\r
- // if called as a function, just return a string\r
- // representing the current time.\r
- if (!inNewExpr)\r
- return date_format(Now(), FORMATSPEC_FULL);\r
-\r
- NativeDate obj = new NativeDate();\r
-\r
- // if called as a constructor with no args,\r
- // return a new Date with the current time.\r
- if (args.length == 0) {\r
- obj.date = Now();\r
- return obj;\r
- }\r
-\r
- // if called with just one arg -\r
- if (args.length == 1) {\r
- double date;\r
- if (args[0] instanceof Scriptable)\r
- args[0] = ((Scriptable) args[0]).getDefaultValue(null);\r
- if (!(args[0] instanceof String)) {\r
- // if it's not a string, use it as a millisecond date\r
- date = ScriptRuntime.toNumber(args[0]);\r
- } else {\r
- // it's a string; parse it.\r
- String str = (String) args[0];\r
- date = date_parseString(str);\r
- }\r
- obj.date = TimeClip(date);\r
- return obj;\r
- }\r
-\r
- // multiple arguments; year, month, day etc.\r
- double array[] = new double[MAXARGS];\r
- int loop;\r
- double d;\r
-\r
- for (loop = 0; loop < MAXARGS; loop++) {\r
- if (loop < args.length) {\r
- d = ScriptRuntime.toNumber(args[loop]);\r
-\r
- if (d != d || Double.isInfinite(d)) {\r
- obj.date = ScriptRuntime.NaN;\r
- return obj;\r
- }\r
- array[loop] = ScriptRuntime.toInteger(args[loop]);\r
- } else {\r
- array[loop] = 0;\r
- }\r
- }\r
-\r
- /* adjust 2-digit years into the 20th century */\r
- if (array[0] >= 0 && array[0] <= 99)\r
- array[0] += 1900;\r
-\r
- /* if we got a 0 for 'date' (which is out of range)\r
- * pretend it's a 1 */\r
- if (array[2] < 1)\r
- array[2] = 1;\r
-\r
- double day = MakeDay(array[0], array[1], array[2]);\r
- double time = MakeTime(array[3], array[4], array[5], array[6]);\r
- time = MakeDate(day, time);\r
- time = internalUTC(time);\r
- obj.date = TimeClip(time);\r
-\r
- return obj;\r
- }\r
-\r
- /* constants for toString, toUTCString */\r
- private static String jsFunction_NaN_date_str = "Invalid Date";\r
-\r
- private static String[] days = {\r
- "Sun","Mon","Tue","Wed","Thu","Fri","Sat"\r
- };\r
-\r
- private static String[] months = {\r
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",\r
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"\r
- };\r
-\r
- private static String toLocale_helper(double t,\r
- java.text.DateFormat formatter)\r
- {\r
- if (t != t)\r
- return jsFunction_NaN_date_str;\r
-\r
- java.util.Date tempdate = new Date((long) t);\r
- return formatter.format(tempdate);\r
- }\r
-\r
- private static String jsFunction_toLocaleString(double date) {\r
- if (localeDateTimeFormatter == null)\r
- localeDateTimeFormatter =\r
- DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG);\r
-\r
- return toLocale_helper(date, localeDateTimeFormatter);\r
- }\r
-\r
- private static String jsFunction_toLocaleTimeString(double date) {\r
- if (localeTimeFormatter == null)\r
- localeTimeFormatter = DateFormat.getTimeInstance(DateFormat.LONG);\r
-\r
- return toLocale_helper(date, localeTimeFormatter);\r
- }\r
-\r
- private static String jsFunction_toLocaleDateString(double date) {\r
- if (localeDateFormatter == null)\r
- localeDateFormatter = DateFormat.getDateInstance(DateFormat.LONG);\r
-\r
- return toLocale_helper(date, localeDateFormatter);\r
- }\r
-\r
- private static String jsFunction_toUTCString(double date) {\r
- StringBuffer result = new StringBuffer(60);\r
-\r
- String dateStr = Integer.toString(DateFromTime(date));\r
- String hourStr = Integer.toString(HourFromTime(date));\r
- String minStr = Integer.toString(MinFromTime(date));\r
- String secStr = Integer.toString(SecFromTime(date));\r
- int year = YearFromTime(date);\r
- String yearStr = Integer.toString(year > 0 ? year : -year);\r
-\r
- result.append(days[WeekDay(date)]);\r
- result.append(", ");\r
- if (dateStr.length() == 1)\r
- result.append('0');\r
- result.append(dateStr);\r
- result.append(' ');\r
- result.append(months[MonthFromTime(date)]);\r
- if (year < 0)\r
- result.append(" -");\r
- else\r
- result.append(' ');\r
- int i;\r
- for (i = yearStr.length(); i < 4; i++)\r
- result.append('0');\r
- result.append(yearStr);\r
-\r
- if (hourStr.length() == 1)\r
- result.append(" 0");\r
- else\r
- result.append(' ');\r
- result.append(hourStr);\r
- if (minStr.length() == 1)\r
- result.append(":0");\r
- else\r
- result.append(':');\r
- result.append(minStr);\r
- if (secStr.length() == 1)\r
- result.append(":0");\r
- else\r
- result.append(':');\r
- result.append(secStr);\r
-\r
- result.append(" GMT");\r
- return result.toString();\r
- }\r
-\r
- private static double jsFunction_getYear(Context cx, double date) {\r
-\r
- int result = YearFromTime(LocalTime(date));\r
-\r
- if (cx.hasFeature(Context.FEATURE_NON_ECMA_GET_YEAR)) {\r
- if (result >= 1900 && result < 2000) {\r
- result -= 1900;\r
- }\r
- } \r
- else {\r
- result -= 1900;\r
- }\r
- return result;\r
- }\r
-\r
- private static double jsFunction_getTimezoneOffset(double date) {\r
- return (date - LocalTime(date)) / msPerMinute;\r
- }\r
-\r
- public double jsFunction_setTime(double time) {\r
- this.date = TimeClip(time);\r
- return this.date;\r
- }\r
-\r
- private double makeTime(Object[] args, int maxargs, boolean local) {\r
- int i;\r
- double conv[] = new double[4];\r
- double hour, min, sec, msec;\r
- double lorutime; /* Local or UTC version of date */\r
-\r
- double time;\r
- double result;\r
-\r
- double date = this.date;\r
-\r
- /* just return NaN if the date is already NaN */\r
- if (date != date)\r
- return date;\r
-\r
- /* Satisfy the ECMA rule that if a function is called with\r
- * fewer arguments than the specified formal arguments, the\r
- * remaining arguments are set to undefined. Seems like all\r
- * the Date.setWhatever functions in ECMA are only varargs\r
- * beyond the first argument; this should be set to undefined\r
- * if it's not given. This means that "d = new Date();\r
- * d.setMilliseconds()" returns NaN. Blech.\r
- */\r
- if (args.length == 0)\r
- args = ScriptRuntime.padArguments(args, 1);\r
-\r
- for (i = 0; i < args.length && i < maxargs; i++) {\r
- conv[i] = ScriptRuntime.toNumber(args[i]);\r
-\r
- // limit checks that happen in MakeTime in ECMA.\r
- if (conv[i] != conv[i] || Double.isInfinite(conv[i])) {\r
- this.date = ScriptRuntime.NaN;\r
- return this.date;\r
- }\r
- conv[i] = ScriptRuntime.toInteger(conv[i]);\r
- }\r
-\r
- if (local)\r
- lorutime = LocalTime(date);\r
- else\r
- lorutime = date;\r
-\r
- i = 0;\r
- int stop = args.length;\r
-\r
- if (maxargs >= 4 && i < stop)\r
- hour = conv[i++];\r
- else\r
- hour = HourFromTime(lorutime);\r
-\r
- if (maxargs >= 3 && i < stop)\r
- min = conv[i++];\r
- else\r
- min = MinFromTime(lorutime);\r
-\r
- if (maxargs >= 2 && i < stop)\r
- sec = conv[i++];\r
- else\r
- sec = SecFromTime(lorutime);\r
-\r
- if (maxargs >= 1 && i < stop)\r
- msec = conv[i++];\r
- else\r
- msec = msFromTime(lorutime);\r
-\r
- time = MakeTime(hour, min, sec, msec);\r
- result = MakeDate(Day(lorutime), time);\r
-\r
- if (local)\r
- result = internalUTC(result);\r
- date = TimeClip(result);\r
-\r
- this.date = date;\r
- return date;\r
- }\r
-\r
- private double jsFunction_setHours(Object[] args) {\r
- return makeTime(args, 4, true);\r
- }\r
-\r
- private double jsFunction_setUTCHours(Object[] args) {\r
- return makeTime(args, 4, false);\r
- }\r
-\r
- private double makeDate(Object[] args, int maxargs, boolean local) {\r
- int i;\r
- double conv[] = new double[3];\r
- double year, month, day;\r
- double lorutime; /* local or UTC version of date */\r
- double result;\r
-\r
- double date = this.date;\r
-\r
- /* See arg padding comment in makeTime.*/\r
- if (args.length == 0)\r
- args = ScriptRuntime.padArguments(args, 1);\r
-\r
- for (i = 0; i < args.length && i < maxargs; i++) {\r
- conv[i] = ScriptRuntime.toNumber(args[i]);\r
-\r
- // limit checks that happen in MakeDate in ECMA.\r
- if (conv[i] != conv[i] || Double.isInfinite(conv[i])) {\r
- this.date = ScriptRuntime.NaN;\r
- return this.date;\r
- }\r
- conv[i] = ScriptRuntime.toInteger(conv[i]);\r
- }\r
-\r
- /* return NaN if date is NaN and we're not setting the year,\r
- * If we are, use 0 as the time. */\r
- if (date != date) {\r
- if (args.length < 3) {\r
- return ScriptRuntime.NaN;\r
- } else {\r
- lorutime = 0;\r
- }\r
- } else {\r
- if (local)\r
- lorutime = LocalTime(date);\r
- else\r
- lorutime = date;\r
- }\r
-\r
- i = 0;\r
- int stop = args.length;\r
-\r
- if (maxargs >= 3 && i < stop)\r
- year = conv[i++];\r
- else\r
- year = YearFromTime(lorutime);\r
-\r
- if (maxargs >= 2 && i < stop)\r
- month = conv[i++];\r
- else\r
- month = MonthFromTime(lorutime);\r
-\r
- if (maxargs >= 1 && i < stop)\r
- day = conv[i++];\r
- else\r
- day = DateFromTime(lorutime);\r
-\r
- day = MakeDay(year, month, day); /* day within year */\r
- result = MakeDate(day, TimeWithinDay(lorutime));\r
-\r
- if (local)\r
- result = internalUTC(result);\r
-\r
- date = TimeClip(result);\r
-\r
- this.date = date;\r
- return date;\r
- }\r
-\r
- private double jsFunction_setYear(double year) {\r
- double day, result;\r
- if (year != year || Double.isInfinite(year)) {\r
- this.date = ScriptRuntime.NaN;\r
- return this.date;\r
- }\r
-\r
- if (this.date != this.date) {\r
- this.date = 0;\r
- } else {\r
- this.date = LocalTime(this.date);\r
- }\r
-\r
- if (year >= 0 && year <= 99)\r
- year += 1900;\r
-\r
- day = MakeDay(year, MonthFromTime(this.date), DateFromTime(this.date));\r
- result = MakeDate(day, TimeWithinDay(this.date));\r
- result = internalUTC(result);\r
-\r
- this.date = TimeClip(result);\r
- return this.date;\r
- }\r
-\r
- protected String getIdName(int id) {\r
- if (prototypeFlag) {\r
- switch (id) {\r
- case ConstructorId_UTC: return "UTC";\r
- case ConstructorId_parse: return "parse";\r
- case Id_constructor: return "constructor"; \r
- case Id_toString: return "toString";\r
- case Id_toTimeString: return "toTimeString";\r
- case Id_toDateString: return "toDateString";\r
- case Id_toLocaleString: return "toLocaleString";\r
- case Id_toLocaleTimeString: return "toLocaleTimeString";\r
- case Id_toLocaleDateString: return "toLocaleDateString";\r
- case Id_toUTCString: return "toUTCString";\r
- case Id_valueOf: return "valueOf";\r
- case Id_getTime: return "getTime";\r
- case Id_getYear: return "getYear";\r
- case Id_getFullYear: return "getFullYear";\r
- case Id_getUTCFullYear: return "getUTCFullYear";\r
- case Id_getMonth: return "getMonth";\r
- case Id_getUTCMonth: return "getUTCMonth";\r
- case Id_getDate: return "getDate";\r
- case Id_getUTCDate: return "getUTCDate";\r
- case Id_getDay: return "getDay";\r
- case Id_getUTCDay: return "getUTCDay";\r
- case Id_getHours: return "getHours";\r
- case Id_getUTCHours: return "getUTCHours";\r
- case Id_getMinutes: return "getMinutes";\r
- case Id_getUTCMinutes: return "getUTCMinutes";\r
- case Id_getSeconds: return "getSeconds";\r
- case Id_getUTCSeconds: return "getUTCSeconds";\r
- case Id_getMilliseconds: return "getMilliseconds";\r
- case Id_getUTCMilliseconds: return "getUTCMilliseconds";\r
- case Id_getTimezoneOffset: return "getTimezoneOffset";\r
- case Id_setTime: return "setTime";\r
- case Id_setMilliseconds: return "setMilliseconds";\r
- case Id_setUTCMilliseconds: return "setUTCMilliseconds";\r
- case Id_setSeconds: return "setSeconds";\r
- case Id_setUTCSeconds: return "setUTCSeconds";\r
- case Id_setMinutes: return "setMinutes";\r
- case Id_setUTCMinutes: return "setUTCMinutes";\r
- case Id_setHours: return "setHours";\r
- case Id_setUTCHours: return "setUTCHours";\r
- case Id_setDate: return "setDate";\r
- case Id_setUTCDate: return "setUTCDate";\r
- case Id_setMonth: return "setMonth";\r
- case Id_setUTCMonth: return "setUTCMonth";\r
- case Id_setFullYear: return "setFullYear";\r
- case Id_setUTCFullYear: return "setUTCFullYear";\r
- case Id_setYear: return "setYear";\r
- }\r
- }\r
- return null; \r
- }\r
-\r
-// #string_id_map#\r
-\r
- protected int mapNameToId(String s) {\r
- if (!prototypeFlag) { return 0; }\r
- int id;\r
-// #generated# Last update: 2001-04-22 23:46:59 CEST\r
- L0: { id = 0; String X = null; int c;\r
- L: switch (s.length()) {\r
- case 6: X="getDay";id=Id_getDay; break L;\r
- case 7: switch (s.charAt(3)) {\r
- case 'D': c=s.charAt(0);\r
- if (c=='g') { X="getDate";id=Id_getDate; }\r
- else if (c=='s') { X="setDate";id=Id_setDate; }\r
- break L;\r
- case 'T': c=s.charAt(0);\r
- if (c=='g') { X="getTime";id=Id_getTime; }\r
- else if (c=='s') { X="setTime";id=Id_setTime; }\r
- break L;\r
- case 'Y': c=s.charAt(0);\r
- if (c=='g') { X="getYear";id=Id_getYear; }\r
- else if (c=='s') { X="setYear";id=Id_setYear; }\r
- break L;\r
- case 'u': X="valueOf";id=Id_valueOf; break L;\r
- } break L;\r
- case 8: c=s.charAt(0);\r
- if (c=='g') {\r
- c=s.charAt(7);\r
- if (c=='h') { X="getMonth";id=Id_getMonth; }\r
- else if (c=='s') { X="getHours";id=Id_getHours; }\r
- }\r
- else if (c=='s') {\r
- c=s.charAt(7);\r
- if (c=='h') { X="setMonth";id=Id_setMonth; }\r
- else if (c=='s') { X="setHours";id=Id_setHours; }\r
- }\r
- else if (c=='t') { X="toString";id=Id_toString; }\r
- break L;\r
- case 9: X="getUTCDay";id=Id_getUTCDay; break L;\r
- case 10: c=s.charAt(3);\r
- if (c=='M') {\r
- c=s.charAt(0);\r
- if (c=='g') { X="getMinutes";id=Id_getMinutes; }\r
- else if (c=='s') { X="setMinutes";id=Id_setMinutes; }\r
- }\r
- else if (c=='S') {\r
- c=s.charAt(0);\r
- if (c=='g') { X="getSeconds";id=Id_getSeconds; }\r
- else if (c=='s') { X="setSeconds";id=Id_setSeconds; }\r
- }\r
- else if (c=='U') {\r
- c=s.charAt(0);\r
- if (c=='g') { X="getUTCDate";id=Id_getUTCDate; }\r
- else if (c=='s') { X="setUTCDate";id=Id_setUTCDate; }\r
- }\r
- break L;\r
- case 11: switch (s.charAt(3)) {\r
- case 'F': c=s.charAt(0);\r
- if (c=='g') { X="getFullYear";id=Id_getFullYear; }\r
- else if (c=='s') { X="setFullYear";id=Id_setFullYear; }\r
- break L;\r
- case 'M': X="toGMTString";id=Id_toGMTString; break L;\r
- case 'T': X="toUTCString";id=Id_toUTCString; break L;\r
- case 'U': c=s.charAt(0);\r
- if (c=='g') {\r
- c=s.charAt(9);\r
- if (c=='r') { X="getUTCHours";id=Id_getUTCHours; }\r
- else if (c=='t') { X="getUTCMonth";id=Id_getUTCMonth; }\r
- }\r
- else if (c=='s') {\r
- c=s.charAt(9);\r
- if (c=='r') { X="setUTCHours";id=Id_setUTCHours; }\r
- else if (c=='t') { X="setUTCMonth";id=Id_setUTCMonth; }\r
- }\r
- break L;\r
- case 's': X="constructor";id=Id_constructor; break L;\r
- } break L;\r
- case 12: c=s.charAt(2);\r
- if (c=='D') { X="toDateString";id=Id_toDateString; }\r
- else if (c=='T') { X="toTimeString";id=Id_toTimeString; }\r
- break L;\r
- case 13: c=s.charAt(0);\r
- if (c=='g') {\r
- c=s.charAt(6);\r
- if (c=='M') { X="getUTCMinutes";id=Id_getUTCMinutes; }\r
- else if (c=='S') { X="getUTCSeconds";id=Id_getUTCSeconds; }\r
- }\r
- else if (c=='s') {\r
- c=s.charAt(6);\r
- if (c=='M') { X="setUTCMinutes";id=Id_setUTCMinutes; }\r
- else if (c=='S') { X="setUTCSeconds";id=Id_setUTCSeconds; }\r
- }\r
- break L;\r
- case 14: c=s.charAt(0);\r
- if (c=='g') { X="getUTCFullYear";id=Id_getUTCFullYear; }\r
- else if (c=='s') { X="setUTCFullYear";id=Id_setUTCFullYear; }\r
- else if (c=='t') { X="toLocaleString";id=Id_toLocaleString; }\r
- break L;\r
- case 15: c=s.charAt(0);\r
- if (c=='g') { X="getMilliseconds";id=Id_getMilliseconds; }\r
- else if (c=='s') { X="setMilliseconds";id=Id_setMilliseconds; }\r
- break L;\r
- case 17: X="getTimezoneOffset";id=Id_getTimezoneOffset; break L;\r
- case 18: c=s.charAt(0);\r
- if (c=='g') { X="getUTCMilliseconds";id=Id_getUTCMilliseconds; }\r
- else if (c=='s') { X="setUTCMilliseconds";id=Id_setUTCMilliseconds; }\r
- else if (c=='t') {\r
- c=s.charAt(8);\r
- if (c=='D') { X="toLocaleDateString";id=Id_toLocaleDateString; }\r
- else if (c=='T') { X="toLocaleTimeString";id=Id_toLocaleTimeString; }\r
- }\r
- break L;\r
- }\r
- if (X!=null && X!=s && !X.equals(s)) id = 0;\r
- }\r
-// #/generated#\r
- return id;\r
- }\r
-\r
- private static final int\r
- ConstructorId_UTC = -2,\r
- ConstructorId_parse = -1,\r
-\r
- Id_constructor = 1,\r
- Id_toString = 2,\r
- Id_toTimeString = 3,\r
- Id_toDateString = 4,\r
- Id_toLocaleString = 5,\r
- Id_toLocaleTimeString = 6,\r
- Id_toLocaleDateString = 7,\r
- Id_toUTCString = 8,\r
- Id_valueOf = 9,\r
- Id_getTime = 10,\r
- Id_getYear = 11,\r
- Id_getFullYear = 12,\r
- Id_getUTCFullYear = 13,\r
- Id_getMonth = 14,\r
- Id_getUTCMonth = 15,\r
- Id_getDate = 16,\r
- Id_getUTCDate = 17,\r
- Id_getDay = 18,\r
- Id_getUTCDay = 19,\r
- Id_getHours = 20,\r
- Id_getUTCHours = 21,\r
- Id_getMinutes = 22,\r
- Id_getUTCMinutes = 23,\r
- Id_getSeconds = 24,\r
- Id_getUTCSeconds = 25,\r
- Id_getMilliseconds = 26,\r
- Id_getUTCMilliseconds = 27,\r
- Id_getTimezoneOffset = 28,\r
- Id_setTime = 29,\r
- Id_setMilliseconds = 30,\r
- Id_setUTCMilliseconds = 31,\r
- Id_setSeconds = 32,\r
- Id_setUTCSeconds = 33,\r
- Id_setMinutes = 34,\r
- Id_setUTCMinutes = 35,\r
- Id_setHours = 36,\r
- Id_setUTCHours = 37,\r
- Id_setDate = 38,\r
- Id_setUTCDate = 39,\r
- Id_setMonth = 40,\r
- Id_setUTCMonth = 41,\r
- Id_setFullYear = 42,\r
- Id_setUTCFullYear = 43,\r
- Id_setYear = 44,\r
-\r
- MAX_PROTOTYPE_ID = 44;\r
-\r
- private static final int\r
- Id_toGMTString = Id_toUTCString; // Alias, see Ecma B.2.6\r
-// #/string_id_map#\r
-\r
- /* cached values */\r
- private static java.util.TimeZone thisTimeZone;\r
- private static double LocalTZA;\r
- private static java.text.DateFormat timeZoneFormatter;\r
- private static java.text.DateFormat localeDateTimeFormatter;\r
- private static java.text.DateFormat localeDateFormatter;\r
- private static java.text.DateFormat localeTimeFormatter;\r
-\r
- private double date;\r
-\r
- private boolean prototypeFlag;\r
-\r
- public long getRawTime() { return (long)this.date; }\r
-}\r
-\r
-\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Igor Bukanov\r
- * Roger Lawrence\r
- * \r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-\r
-package org.mozilla.javascript;\r
-\r
-/**\r
- *\r
- * The class of error objects\r
- *\r
- * ECMA 15.11\r
- */\r
-public class NativeError extends IdScriptable {\r
-\r
- public static void init(Context cx, Scriptable scope, boolean sealed) {\r
- NativeError obj = new NativeError();\r
- obj.prototypeFlag = true;\r
- obj.messageValue = "";\r
- obj.nameValue = "Error";\r
- obj.addAsPrototype(MAX_PROTOTYPE_ID, cx, scope, sealed);\r
- }\r
- \r
- protected int getIdDefaultAttributes(int id) {\r
- if (id == Id_message || id == Id_name) { return EMPTY; }\r
- return super.getIdDefaultAttributes(id);\r
- }\r
-\r
- protected boolean hasIdValue(int id) {\r
- if (id == Id_message) { return messageValue != NOT_FOUND; }\r
- if (id == Id_name) { return nameValue != NOT_FOUND; }\r
- return super.hasIdValue(id);\r
- }\r
-\r
- protected Object getIdValue(int id) {\r
- if (id == Id_message) { return messageValue; }\r
- if (id == Id_name) { return nameValue; }\r
- return super.getIdValue(id);\r
- }\r
-\r
- protected void setIdValue(int id, Object value) {\r
- if (id == Id_message) { messageValue = value; return; }\r
- if (id == Id_name) { nameValue = value; return; }\r
- super.setIdValue(id, value);\r
- }\r
-\r
- protected void deleteIdValue(int id) {\r
- if (id == Id_message) { messageValue = NOT_FOUND; return; }\r
- if (id == Id_name) { nameValue = NOT_FOUND; return; }\r
- super.deleteIdValue(id);\r
- }\r
-\r
- public int methodArity(int methodId) {\r
- if (prototypeFlag) {\r
- if (methodId == Id_constructor) return 1;\r
- if (methodId == Id_toString) return 0;\r
- }\r
- return super.methodArity(methodId);\r
- }\r
-\r
- public Object execMethod\r
- (int methodId, IdFunction f,\r
- Context cx, Scriptable scope, Scriptable thisObj, Object[] args)\r
- throws JavaScriptException\r
- {\r
- if (prototypeFlag) {\r
- if (methodId == Id_constructor) {\r
- return jsConstructor(cx, args, f, thisObj == null);\r
- }\r
- else if (methodId == Id_toString) {\r
- return realThis(thisObj, f).toString();\r
- }\r
- }\r
- return super.execMethod(methodId, f, cx, scope, thisObj, args);\r
- }\r
-\r
- private NativeError realThis(Scriptable thisObj, IdFunction f) {\r
- while (!(thisObj instanceof NativeError)) {\r
- thisObj = nextInstanceCheck(thisObj, f, true);\r
- }\r
- return (NativeError)thisObj;\r
- }\r
-\r
- private static Object jsConstructor(Context cx, Object[] args, \r
- Function funObj, boolean inNewExpr)\r
- {\r
- NativeError result = new NativeError();\r
- if (args.length >= 1) \r
- result.messageValue = ScriptRuntime.toString(args[0]);\r
- result.setPrototype(getClassPrototype(funObj, "Error"));\r
- return result;\r
- }\r
- \r
- public String getClassName() { \r
- return "Error"; \r
- }\r
-\r
- public String toString() {\r
- return getName() + ": " + getMessage();\r
- }\r
- \r
- public String getName() {\r
- Object val = nameValue;\r
- return ScriptRuntime.toString(val != NOT_FOUND ? val \r
- : Undefined.instance);\r
- }\r
- \r
- public String getMessage() {\r
- Object val = messageValue;\r
- return ScriptRuntime.toString(val != NOT_FOUND ? val \r
- : Undefined.instance);\r
- } \r
-\r
- protected int maxInstanceId() { return MAX_INSTANCE_ID; }\r
-\r
- protected String getIdName(int id) {\r
- if (id == Id_message) { return "message"; }\r
- if (id == Id_name) { return "name"; }\r
- if (prototypeFlag) {\r
- if (id == Id_constructor) return "constructor";\r
- if (id == Id_toString) return "toString";\r
- }\r
- return null; \r
- }\r
- \r
-// #string_id_map#\r
-\r
- private static final int\r
- Id_message = 1,\r
- Id_name = 2,\r
- \r
- MAX_INSTANCE_ID = 2;\r
-\r
- protected int mapNameToId(String s) {\r
- int id;\r
-// #generated# Last update: 2001-05-19 21:55:23 CEST\r
- L0: { id = 0; String X = null;\r
- int s_length = s.length();\r
- if (s_length==4) { X="name";id=Id_name; }\r
- else if (s_length==7) { X="message";id=Id_message; }\r
- if (X!=null && X!=s && !X.equals(s)) id = 0;\r
- }\r
-// #/generated#\r
-// #/string_id_map#\r
-\r
- if (id != 0 || !prototypeFlag) { return id; }\r
-\r
-// #string_id_map#\r
-// #generated# Last update: 2001-05-19 21:55:23 CEST\r
- L0: { id = 0; String X = null;\r
- int s_length = s.length();\r
- if (s_length==8) { X="toString";id=Id_toString; }\r
- else if (s_length==11) { X="constructor";id=Id_constructor; }\r
- if (X!=null && X!=s && !X.equals(s)) id = 0;\r
- }\r
-// #/generated#\r
- return id;\r
- }\r
-\r
- private static final int\r
- Id_constructor = MAX_INSTANCE_ID + 1,\r
- Id_toString = MAX_INSTANCE_ID + 2,\r
- \r
- MAX_PROTOTYPE_ID = MAX_INSTANCE_ID + 2;\r
-\r
-// #/string_id_map#\r
- \r
- private Object messageValue = NOT_FOUND;\r
- private Object nameValue = NOT_FOUND;\r
-\r
- private boolean prototypeFlag;\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- * Igor Bukanov\r
- * Roger Lawrence\r
- * Mike McCabe\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-import java.util.Hashtable;\r
-\r
-/**\r
- * This class implements the Function native object.\r
- * See ECMA 15.3.\r
- * @author Norris Boyd\r
- */\r
-public class NativeFunction extends BaseFunction {\r
-\r
- private boolean nextIs(int i, int token) {\r
- if (i + 1 < source.length())\r
- return source.charAt(i + 1) == token;\r
- return false;\r
- }\r
-\r
- // how much to indent\r
- private final static int OFFSET = 4;\r
-\r
- // less how much for case labels\r
- private final static int SETBACK = 2;\r
-\r
- // whether to do a debug print of the source information, when\r
- // decompiling.\r
- private static final boolean printSource = false;\r
-\r
- /**\r
- * Decompile the source information associated with this js\r
- * function/script back into a string. For the most part, this\r
- * just means translating tokens back to their string\r
- * representations; there's a little bit of lookahead logic to\r
- * decide the proper spacing/indentation. Most of the work in\r
- * mapping the original source to the prettyprinted decompiled\r
- * version is done by the parser.\r
- *\r
- * Note that support for Context.decompileFunctionBody is hacked\r
- * on through special cases; I suspect that js makes a distinction\r
- * between function header and function body that rhino\r
- * decompilation does not.\r
- *\r
- * @param cx Current context\r
- *\r
- * @param indent How much to indent the decompiled result\r
- *\r
- * @param justbody Whether the decompilation should omit the\r
- * function header and trailing brace.\r
- */\r
-\r
- public String decompile(Context cx, int indent, boolean justbody) {\r
- StringBuffer result = new StringBuffer();\r
- decompile(indent, true, justbody, result);\r
- return result.toString(); \r
- \r
- }\r
- \r
- private void decompile(int indent, boolean toplevel, boolean justbody,\r
- StringBuffer result) \r
- {\r
- if (source == null) {\r
- if (!justbody) {\r
- result.append("function ");\r
- result.append(getFunctionName());\r
- result.append("() {\n\t");\r
- }\r
- result.append("[native code]\n");\r
- if (!justbody) {\r
- result.append("}\n");\r
- }\r
- return;\r
- }\r
-\r
- // Spew tokens in source, for debugging.\r
- // as TYPE number char\r
- if (printSource) {\r
- System.err.println("length:" + source.length());\r
- for (int i = 0; i < source.length(); i++) {\r
- // Note that tokenToName will fail unless Context.printTrees\r
- // is true.\r
- String tokenname = TokenStream.tokenToName(source.charAt(i));\r
- if (tokenname == null)\r
- tokenname = "---";\r
- String pad = tokenname.length() > 7\r
- ? "\t"\r
- : "\t\t";\r
- System.err.println\r
- (tokenname\r
- + pad + (int)source.charAt(i)\r
- + "\t'" + ScriptRuntime.escapeString\r
- (source.substring(i, i+1))\r
- + "'");\r
- }\r
- System.err.println();\r
- }\r
-\r
- int i = 0;\r
-\r
- if (source.length() > 0) {\r
- /* special-case FUNCTION as the first token; if it is,\r
- * (and it's not followed by a NAME or LP) then we're\r
- * decompiling a function (and not the toplevel script.)\r
-\r
- * FUNCTION appearing elsewhere is an escape that means we'll\r
- * need to call toString of the given function (object).\r
-\r
- * If not at the top level, don't add an initial indent;\r
- * let the caller do it, so functions as expressions look\r
- * reasonable. */\r
-\r
- if (toplevel) {\r
- // add an initial newline to exactly match js.\r
- if (!justbody)\r
- result.append('\n');\r
- for (int j = 0; j < indent; j++)\r
- result.append(' ');\r
- }\r
-\r
- if (source.charAt(0) == TokenStream.FUNCTION\r
- // make sure it's not a script that begins with a\r
- // reference to a function definition.\r
- && source.length() > 1\r
- && (source.charAt(1) == TokenStream.NAME\r
- || source.charAt(1) == TokenStream.LP))\r
- {\r
- if (!justbody) {\r
- result.append("function ");\r
-\r
- /* version != 1.2 Function constructor behavior - if\r
- * there's no function name in the source info, and\r
- * the names[0] entry is the empty string, then it must\r
- * have been created by the Function constructor;\r
- * print 'anonymous' as the function name if the\r
- * version (under which the function was compiled) is\r
- * less than 1.2... or if it's greater than 1.2, because\r
- * we need to be closer to ECMA. (ToSource, please?)\r
- */\r
- if (nextIs(i, TokenStream.LP)\r
- && this.version != Context.VERSION_1_2\r
- && this.functionName != null \r
- && this.functionName.equals("anonymous"))\r
- result.append("anonymous");\r
- i++;\r
- } else {\r
- /* Skip past the entire function header to the next EOL.\r
- * Depends on how NAMEs are encoded.\r
- */\r
- while (i < source.length()\r
- && (source.charAt(i) != TokenStream.EOL\r
- // the length char of a NAME sequence\r
- // can look like an EOL.\r
- || (i > 0\r
- && source.charAt(i-1) == TokenStream.NAME)))\r
- {\r
- i++;\r
- }\r
- // Skip past the EOL, too.\r
- i++;\r
- }\r
- }\r
- }\r
-\r
- while (i < source.length()) {\r
- int stop;\r
- switch(source.charAt(i)) {\r
- case TokenStream.NAME:\r
- case TokenStream.OBJECT: // re-wrapped in '/'s in parser...\r
- /* NAMEs are encoded as NAME, (char) length, string...\r
- * Note that lookahead for detecting labels depends on\r
- * this encoding; change there if this changes.\r
-\r
- * Also change function-header skipping code above,\r
- * used when decompling under decompileFunctionBody.\r
- */\r
- i++;\r
- stop = i + (int)source.charAt(i);\r
- result.append(source.substring(i + 1, stop + 1));\r
- i = stop;\r
- break;\r
-\r
- case TokenStream.NUMBER:\r
- i++;\r
- long lbits = 0;\r
- switch(source.charAt(i)) {\r
- case 'S':\r
- i++;\r
- result.append((int)source.charAt(i));\r
- break;\r
-\r
- case 'J':\r
- i++;\r
- lbits |= (long)source.charAt(i++) << 48;\r
- lbits |= (long)source.charAt(i++) << 32;\r
- lbits |= (long)source.charAt(i++) << 16;\r
- lbits |= (long)source.charAt(i);\r
-\r
- result.append(lbits);\r
- break;\r
- case 'D':\r
- i++;\r
-\r
- lbits |= (long)source.charAt(i++) << 48;\r
- lbits |= (long)source.charAt(i++) << 32;\r
- lbits |= (long)source.charAt(i++) << 16;\r
- lbits |= (long)source.charAt(i);\r
-\r
- double dval = Double.longBitsToDouble(lbits);\r
- result.append(ScriptRuntime.numberToString(dval, 10));\r
- break;\r
- }\r
- break;\r
-\r
- case TokenStream.STRING:\r
- i++;\r
- stop = i + (int)source.charAt(i);\r
- result.append('"');\r
- result.append(ScriptRuntime.escapeString\r
- (source.substring(i + 1, stop + 1)));\r
- result.append('"');\r
- i = stop;\r
- break;\r
-\r
- case TokenStream.PRIMARY:\r
- i++;\r
- switch(source.charAt(i)) {\r
- case TokenStream.TRUE:\r
- result.append("true");\r
- break;\r
-\r
- case TokenStream.FALSE:\r
- result.append("false");\r
- break;\r
-\r
- case TokenStream.NULL:\r
- result.append("null");\r
- break;\r
-\r
- case TokenStream.THIS:\r
- result.append("this");\r
- break;\r
-\r
- case TokenStream.TYPEOF:\r
- result.append("typeof");\r
- break;\r
-\r
- case TokenStream.VOID:\r
- result.append("void");\r
- break;\r
-\r
- case TokenStream.UNDEFINED:\r
- result.append("undefined");\r
- break;\r
- }\r
- break;\r
-\r
- case TokenStream.FUNCTION: {\r
- /* decompile a FUNCTION token as an escape; call\r
- * toString on the nth enclosed nested function,\r
- * where n is given by the byte that follows.\r
- */\r
-\r
- i++;\r
- int functionNumber = source.charAt(i);\r
- if (nestedFunctions == null\r
- || functionNumber > nestedFunctions.length)\r
- {\r
- String message;\r
- if (functionName != null && functionName.length() > 0) {\r
- message = Context.getMessage2\r
- ("msg.no.function.ref.found.in", \r
- new Integer((int)source.charAt(i)), functionName);\r
- } else {\r
- message = Context.getMessage1\r
- ("msg.no.function.ref.found", \r
- new Integer((int)source.charAt(i)));\r
- }\r
- throw Context.reportRuntimeError(message);\r
- }\r
- nestedFunctions[functionNumber].\r
- decompile(indent, false, false, result);\r
- break;\r
- }\r
- case TokenStream.COMMA:\r
- result.append(", ");\r
- break;\r
-\r
- case TokenStream.LC:\r
- if (nextIs(i, TokenStream.EOL))\r
- indent += OFFSET;\r
- result.append('{');\r
- break;\r
-\r
- case TokenStream.RC:\r
- /* don't print the closing RC if it closes the\r
- * toplevel function and we're called from\r
- * decompileFunctionBody.\r
- */\r
- if (justbody && toplevel && i + 1 == source.length())\r
- break;\r
-\r
- if (nextIs(i, TokenStream.EOL))\r
- indent -= OFFSET;\r
- if (nextIs(i, TokenStream.WHILE)\r
- || nextIs(i, TokenStream.ELSE)) {\r
- indent -= OFFSET;\r
- result.append("} ");\r
- }\r
- else\r
- result.append('}');\r
- break;\r
-\r
- case TokenStream.LP:\r
- result.append('(');\r
- break;\r
-\r
- case TokenStream.RP:\r
- if (nextIs(i, TokenStream.LC))\r
- result.append(") ");\r
- else\r
- result.append(')');\r
- break;\r
-\r
- case TokenStream.LB:\r
- result.append('[');\r
- break;\r
-\r
- case TokenStream.RB:\r
- result.append(']');\r
- break;\r
-\r
- case TokenStream.EOL:\r
- result.append('\n');\r
-\r
- /* add indent if any tokens remain,\r
- * less setback if next token is\r
- * a label, case or default.\r
- */\r
- if (i + 1 < source.length()) {\r
- int less = 0;\r
- if (nextIs(i, TokenStream.CASE)\r
- || nextIs(i, TokenStream.DEFAULT))\r
- less = SETBACK;\r
- else if (nextIs(i, TokenStream.RC))\r
- less = OFFSET;\r
-\r
- /* elaborate check against label... skip past a\r
- * following inlined NAME and look for a COLON.\r
- * Depends on how NAME is encoded.\r
- */\r
- else if (nextIs(i, TokenStream.NAME)) {\r
- int skip = source.charAt(i + 2);\r
- if (source.charAt(i + skip + 3) == TokenStream.COLON)\r
- less = OFFSET;\r
- }\r
-\r
- for (; less < indent; less++)\r
- result.append(' ');\r
- }\r
- break;\r
-\r
- case TokenStream.DOT:\r
- result.append('.');\r
- break;\r
-\r
- case TokenStream.NEW:\r
- result.append("new ");\r
- break;\r
-\r
- case TokenStream.DELPROP:\r
- result.append("delete ");\r
- break;\r
-\r
- case TokenStream.IF:\r
- result.append("if ");\r
- break;\r
-\r
- case TokenStream.ELSE:\r
- result.append("else ");\r
- break;\r
-\r
- case TokenStream.FOR:\r
- result.append("for ");\r
- break;\r
-\r
- case TokenStream.IN:\r
- result.append(" in ");\r
- break;\r
-\r
- case TokenStream.WITH:\r
- result.append("with ");\r
- break;\r
-\r
- case TokenStream.WHILE:\r
- result.append("while ");\r
- break;\r
-\r
- case TokenStream.DO:\r
- result.append("do ");\r
- break;\r
-\r
- case TokenStream.TRY:\r
- result.append("try ");\r
- break;\r
-\r
- case TokenStream.CATCH:\r
- result.append("catch ");\r
- break;\r
-\r
- case TokenStream.FINALLY:\r
- result.append("finally ");\r
- break;\r
-\r
- case TokenStream.THROW:\r
- result.append("throw ");\r
- break;\r
-\r
- case TokenStream.SWITCH:\r
- result.append("switch ");\r
- break;\r
-\r
- case TokenStream.BREAK:\r
- if (nextIs(i, TokenStream.NAME))\r
- result.append("break ");\r
- else\r
- result.append("break");\r
- break;\r
-\r
- case TokenStream.CONTINUE:\r
- if (nextIs(i, TokenStream.NAME))\r
- result.append("continue ");\r
- else\r
- result.append("continue");\r
- break;\r
-\r
- case TokenStream.CASE:\r
- result.append("case ");\r
- break;\r
-\r
- case TokenStream.DEFAULT:\r
- result.append("default");\r
- break;\r
-\r
- case TokenStream.RETURN:\r
- if (nextIs(i, TokenStream.SEMI))\r
- result.append("return");\r
- else\r
- result.append("return ");\r
- break;\r
-\r
- case TokenStream.VAR:\r
- result.append("var ");\r
- break;\r
-\r
- case TokenStream.SEMI:\r
- if (nextIs(i, TokenStream.EOL))\r
- // statement termination\r
- result.append(';');\r
- else\r
- // separators in FOR\r
- result.append("; ");\r
- break;\r
-\r
- case TokenStream.ASSIGN:\r
- i++;\r
- switch(source.charAt(i)) {\r
- case TokenStream.NOP:\r
- result.append(" = ");\r
- break;\r
-\r
- case TokenStream.ADD:\r
- result.append(" += ");\r
- break;\r
-\r
- case TokenStream.SUB:\r
- result.append(" -= ");\r
- break;\r
-\r
- case TokenStream.MUL:\r
- result.append(" *= ");\r
- break;\r
-\r
- case TokenStream.DIV:\r
- result.append(" /= ");\r
- break;\r
-\r
- case TokenStream.MOD:\r
- result.append(" %= ");\r
- break;\r
-\r
- case TokenStream.BITOR:\r
- result.append(" |= ");\r
- break;\r
-\r
- case TokenStream.BITXOR:\r
- result.append(" ^= ");\r
- break;\r
-\r
- case TokenStream.BITAND:\r
- result.append(" &= ");\r
- break;\r
-\r
- case TokenStream.LSH:\r
- result.append(" <<= ");\r
- break;\r
-\r
- case TokenStream.RSH:\r
- result.append(" >>= ");\r
- break;\r
-\r
- case TokenStream.URSH:\r
- result.append(" >>>= ");\r
- break;\r
- }\r
- break;\r
-\r
- case TokenStream.HOOK:\r
- result.append(" ? ");\r
- break;\r
-\r
- case TokenStream.OBJLIT:\r
- // pun OBJLIT to mean colon in objlit property initialization.\r
- // this needs to be distinct from COLON in the general case\r
- // to distinguish from the colon in a ternary... which needs\r
- // different spacing.\r
- result.append(':');\r
- break;\r
-\r
- case TokenStream.COLON:\r
- if (nextIs(i, TokenStream.EOL))\r
- // it's the end of a label\r
- result.append(':');\r
- else\r
- // it's the middle part of a ternary\r
- result.append(" : ");\r
- break;\r
-\r
- case TokenStream.OR:\r
- result.append(" || ");\r
- break;\r
-\r
- case TokenStream.AND:\r
- result.append(" && ");\r
- break;\r
-\r
- case TokenStream.BITOR:\r
- result.append(" | ");\r
- break;\r
-\r
- case TokenStream.BITXOR:\r
- result.append(" ^ ");\r
- break;\r
-\r
- case TokenStream.BITAND:\r
- result.append(" & ");\r
- break;\r
-\r
- case TokenStream.EQOP:\r
- i++;\r
- switch(source.charAt(i)) {\r
- case TokenStream.SHEQ:\r
- /*\r
- * Emulate the C engine; if we're under version\r
- * 1.2, then the == operator behaves like the ===\r
- * operator (and the source is generated by\r
- * decompiling a === opcode), so print the ===\r
- * operator as ==.\r
- */\r
- result.append(this.version == Context.VERSION_1_2 ? " == "\r
- : " === ");\r
- break;\r
-\r
- case TokenStream.SHNE:\r
- result.append(this.version == Context.VERSION_1_2 ? " != "\r
- : " !== ");\r
- break;\r
-\r
- case TokenStream.EQ:\r
- result.append(" == ");\r
- break;\r
-\r
- case TokenStream.NE:\r
- result.append(" != ");\r
- break;\r
- }\r
- break;\r
-\r
- case TokenStream.RELOP:\r
- i++;\r
- switch(source.charAt(i)) {\r
- case TokenStream.LE:\r
- result.append(" <= ");\r
- break;\r
-\r
- case TokenStream.LT:\r
- result.append(" < ");\r
- break;\r
-\r
- case TokenStream.GE:\r
- result.append(" >= ");\r
- break;\r
-\r
- case TokenStream.GT:\r
- result.append(" > ");\r
- break;\r
-\r
- case TokenStream.INSTANCEOF:\r
- result.append(" instanceof ");\r
- break;\r
- }\r
- break;\r
-\r
- case TokenStream.SHOP:\r
- i++;\r
- switch(source.charAt(i)) {\r
- case TokenStream.LSH:\r
- result.append(" << ");\r
- break;\r
-\r
- case TokenStream.RSH:\r
- result.append(" >> ");\r
- break;\r
-\r
- case TokenStream.URSH:\r
- result.append(" >>> ");\r
- break;\r
- }\r
- break;\r
-\r
- case TokenStream.UNARYOP:\r
- i++;\r
- switch(source.charAt(i)) {\r
- case TokenStream.TYPEOF:\r
- result.append("typeof ");\r
- break;\r
-\r
- case TokenStream.VOID:\r
- result.append("void ");\r
- break;\r
-\r
- case TokenStream.NOT:\r
- result.append('!');\r
- break;\r
-\r
- case TokenStream.BITNOT:\r
- result.append('~');\r
- break;\r
-\r
- case TokenStream.ADD:\r
- result.append('+');\r
- break;\r
-\r
- case TokenStream.SUB:\r
- result.append('-');\r
- break;\r
- }\r
- break;\r
-\r
- case TokenStream.INC:\r
- result.append("++");\r
- break;\r
-\r
- case TokenStream.DEC:\r
- result.append("--");\r
- break;\r
-\r
- case TokenStream.ADD:\r
- result.append(" + ");\r
- break;\r
-\r
- case TokenStream.SUB:\r
- result.append(" - ");\r
- break;\r
-\r
- case TokenStream.MUL:\r
- result.append(" * ");\r
- break;\r
-\r
- case TokenStream.DIV:\r
- result.append(" / ");\r
- break;\r
-\r
- case TokenStream.MOD:\r
- result.append(" % ");\r
- break;\r
-\r
- default: \r
- // If we don't know how to decompile it, raise an exception.\r
- throw new RuntimeException("Unknown token " + \r
- source.charAt(i));\r
- }\r
- i++;\r
- }\r
-\r
- // add that trailing newline if it's an outermost function.\r
- if (toplevel && !justbody)\r
- result.append('\n');\r
- }\r
-\r
- public int getLength() {\r
- Context cx = Context.getContext();\r
- if (cx != null && cx.getLanguageVersion() != Context.VERSION_1_2)\r
- return argCount;\r
- NativeCall activation = getActivation(cx);\r
- if (activation == null)\r
- return argCount;\r
- return activation.getOriginalArguments().length;\r
- }\r
-\r
- public int getArity() {\r
- return argCount;\r
- }\r
-\r
- public String getFunctionName() {\r
- if (functionName == null)\r
- return "";\r
- if (functionName.equals("anonymous")) {\r
- Context cx = Context.getCurrentContext();\r
- if (cx != null && cx.getLanguageVersion() == Context.VERSION_1_2)\r
- return "";\r
- }\r
- return functionName;\r
- }\r
-\r
- /**\r
- * For backwards compatibility keep an old method name used by\r
- * Batik and possibly others.\r
- */\r
- public String jsGet_name() {\r
- return getFunctionName();\r
- }\r
-\r
- /**\r
- * The "argsNames" array has the following information:\r
- * argNames[0] through argNames[argCount - 1]: the names of the parameters\r
- * argNames[argCount] through argNames[args.length-1]: the names of the\r
- * variables declared in var statements\r
- */\r
- protected String[] argNames;\r
- protected short argCount;\r
- protected short version;\r
-\r
- /**\r
- * An encoded representation of the function source, for\r
- * decompiling. Needs to be visible (only) to generated\r
- * subclasses of NativeFunction.\r
- */\r
- protected String source;\r
-\r
- /**\r
- * An array of NativeFunction values for each nested function.\r
- * Used internally, and also for decompiling nested functions.\r
- */\r
- public NativeFunction[] nestedFunctions;\r
-\r
- // For all generated subclass objects debug_level is set to 0 or higher.\r
- // So, if debug_level remains -1 in some object, then that object is\r
- // known to have not been generated.\r
- public int debug_level = -1;\r
- public String debug_srcName;\r
-}\r
-\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s):\r
- * Norris Boyd\r
- * Igor Bukanov\r
- * Mike McCabe\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-import java.io.StringReader;\r
-import java.io.IOException;\r
-import java.lang.reflect.Method;\r
-\r
-/**\r
- * This class implements the global native object (function and value\r
- * properties only).\r
- *\r
- * See ECMA 15.1.[12].\r
- *\r
- * @author Mike Shaver\r
- */\r
-\r
-public class NativeGlobal implements IdFunctionMaster {\r
-\r
- public static void init(Context cx, Scriptable scope, boolean sealed) {\r
- NativeGlobal obj = new NativeGlobal();\r
- obj.scopeSlaveFlag = true;\r
-\r
- for (int id = 1; id <= LAST_SCOPE_FUNCTION_ID; ++id) {\r
- String name = getMethodName(id);\r
- IdFunction f = new IdFunction(obj, name, id);\r
- f.setParentScope(scope);\r
- if (sealed) { f.sealObject(); }\r
- ScriptableObject.defineProperty(scope, name, f,\r
- ScriptableObject.DONTENUM);\r
- }\r
-\r
- ScriptableObject.defineProperty(scope, "NaN",\r
- ScriptRuntime.NaNobj,\r
- ScriptableObject.DONTENUM);\r
- ScriptableObject.defineProperty(scope, "Infinity",\r
- new Double(Double.POSITIVE_INFINITY),\r
- ScriptableObject.DONTENUM);\r
- /*\r
- ScriptableObject.defineProperty(scope, "undefined",\r
- Undefined.instance,\r
- ScriptableObject.DONTENUM);\r
- */\r
-\r
- String[] errorMethods = { "ConversionError",\r
- "EvalError",\r
- "RangeError",\r
- "ReferenceError",\r
- "SyntaxError",\r
- "TypeError",\r
- "URIError"\r
- };\r
-\r
- /*\r
- Each error constructor gets its own Error object as a prototype,\r
- with the 'name' property set to the name of the error.\r
- */\r
- for (int i = 0; i < errorMethods.length; i++) {\r
- String name = errorMethods[i];\r
- IdFunction ctor = new IdFunction(obj, name, Id_new_CommonError);\r
- ctor.setFunctionType(IdFunction.FUNCTION_AND_CONSTRUCTOR);\r
- ctor.setParentScope(scope);\r
- ScriptableObject.defineProperty(scope, name, ctor,\r
- ScriptableObject.DONTENUM);\r
-\r
- Scriptable errorProto = ScriptRuntime.newObject\r
- (cx, scope, "Error", ScriptRuntime.emptyArgs);\r
-\r
- errorProto.put("name", errorProto, name);\r
- ctor.put("prototype", ctor, errorProto);\r
- if (sealed) {\r
- ctor.sealObject();\r
- if (errorProto instanceof ScriptableObject) {\r
- ((ScriptableObject)errorProto).sealObject();\r
- }\r
- }\r
- }\r
- }\r
-\r
- public Object execMethod(int methodId, IdFunction function, Context cx,\r
- Scriptable scope, Scriptable thisObj,\r
- Object[] args)\r
- throws JavaScriptException\r
- {\r
- if (scopeSlaveFlag) {\r
- switch (methodId) {\r
- case Id_decodeURI:\r
- return js_decodeURI(cx, args);\r
-\r
- case Id_decodeURIComponent:\r
- return js_decodeURIComponent(cx, args);\r
-\r
- case Id_encodeURI:\r
- return js_encodeURI(cx, args);\r
-\r
- case Id_encodeURIComponent:\r
- return js_encodeURIComponent(cx, args);\r
-\r
- case Id_escape:\r
- return js_escape(cx, args);\r
-\r
- case Id_eval:\r
- return js_eval(cx, scope, args);\r
-\r
- case Id_isFinite:\r
- return js_isFinite(cx, args);\r
-\r
- case Id_isNaN:\r
- return js_isNaN(cx, args);\r
-\r
- case Id_parseFloat:\r
- return js_parseFloat(cx, args);\r
-\r
- case Id_parseInt:\r
- return js_parseInt(cx, args);\r
-\r
- case Id_unescape:\r
- return js_unescape(cx, args);\r
-\r
- case Id_new_CommonError:\r
- return new_CommonError(function, cx, scope, args);\r
- }\r
- }\r
- throw IdFunction.onBadMethodId(this, methodId);\r
- }\r
-\r
- public int methodArity(int methodId) {\r
- if (scopeSlaveFlag) {\r
- switch (methodId) {\r
- case Id_decodeURI: return 1;\r
- case Id_decodeURIComponent: return 1;\r
- case Id_encodeURI: return 1;\r
- case Id_encodeURIComponent: return 1;\r
- case Id_escape: return 1;\r
- case Id_eval: return 1;\r
- case Id_isFinite: return 1;\r
- case Id_isNaN: return 1;\r
- case Id_parseFloat: return 1;\r
- case Id_parseInt: return 2;\r
- case Id_unescape: return 1;\r
-\r
- case Id_new_CommonError: return 1;\r
- }\r
- }\r
- return -1;\r
- }\r
-\r
- private static String getMethodName(int methodId) {\r
- switch (methodId) {\r
- case Id_decodeURI: return "decodeURI";\r
- case Id_decodeURIComponent: return "decodeURIComponent";\r
- case Id_encodeURI: return "encodeURI";\r
- case Id_encodeURIComponent: return "encodeURIComponent";\r
- case Id_escape: return "escape";\r
- case Id_eval: return "eval";\r
- case Id_isFinite: return "isFinite";\r
- case Id_isNaN: return "isNaN";\r
- case Id_parseFloat: return "parseFloat";\r
- case Id_parseInt: return "parseInt";\r
- case Id_unescape: return "unescape";\r
- }\r
- return null;\r
- }\r
-\r
- /**\r
- * The global method parseInt, as per ECMA-262 15.1.2.2.\r
- */\r
- private Object js_parseInt(Context cx, Object[] args) {\r
- String s = ScriptRuntime.toString(args, 0);\r
- int radix = ScriptRuntime.toInt32(args, 1);\r
-\r
- int len = s.length();\r
- if (len == 0)\r
- return ScriptRuntime.NaNobj;\r
-\r
- boolean negative = false;\r
- int start = 0;\r
- char c;\r
- do {\r
- c = s.charAt(start);\r
- if (!Character.isWhitespace(c))\r
- break;\r
- start++;\r
- } while (start < len);\r
-\r
- if (c == '+' || (negative = (c == '-')))\r
- start++;\r
-\r
- final int NO_RADIX = -1;\r
- if (radix == 0) {\r
- radix = NO_RADIX;\r
- } else if (radix < 2 || radix > 36) {\r
- return ScriptRuntime.NaNobj;\r
- } else if (radix == 16 && len - start > 1 && s.charAt(start) == '0') {\r
- c = s.charAt(start+1);\r
- if (c == 'x' || c == 'X')\r
- start += 2;\r
- }\r
-\r
- if (radix == NO_RADIX) {\r
- radix = 10;\r
- if (len - start > 1 && s.charAt(start) == '0') {\r
- c = s.charAt(start+1);\r
- if (c == 'x' || c == 'X') {\r
- radix = 16;\r
- start += 2;\r
- } else if (c != '.') {\r
- radix = 8;\r
- start++;\r
- }\r
- }\r
- }\r
-\r
- double d = ScriptRuntime.stringToNumber(s, start, radix);\r
- return new Double(negative ? -d : d);\r
- }\r
-\r
- /**\r
- * The global method parseFloat, as per ECMA-262 15.1.2.3.\r
- *\r
- * @param cx unused\r
- * @param thisObj unused\r
- * @param args the arguments to parseFloat, ignoring args[>=1]\r
- * @param funObj unused\r
- */\r
- private Object js_parseFloat(Context cx, Object[] args) {\r
- if (args.length < 1)\r
- return ScriptRuntime.NaNobj;\r
- String s = ScriptRuntime.toString(args[0]);\r
- int len = s.length();\r
- if (len == 0)\r
- return ScriptRuntime.NaNobj;\r
-\r
- int i;\r
- char c;\r
- // Scan forward to the first digit or .\r
- for (i=0; TokenStream.isJSSpace(c = s.charAt(i)) && i+1 < len; i++)\r
- /* empty */\r
- ;\r
-\r
- int start = i;\r
-\r
- if (c == '+' || c == '-')\r
- c = s.charAt(++i);\r
-\r
- if (c == 'I') {\r
- // check for "Infinity"\r
- double d;\r
- if (i+8 <= len && s.substring(i, i+8).equals("Infinity"))\r
- d = s.charAt(start) == '-' ? Double.NEGATIVE_INFINITY\r
- : Double.POSITIVE_INFINITY;\r
- else\r
- return ScriptRuntime.NaNobj;\r
- return new Double(d);\r
- }\r
-\r
- // Find the end of the legal bit\r
- int decimal = -1;\r
- int exponent = -1;\r
- for (; i < len; i++) {\r
- switch (s.charAt(i)) {\r
- case '.':\r
- if (decimal != -1) // Only allow a single decimal point.\r
- break;\r
- decimal = i;\r
- continue;\r
-\r
- case 'e':\r
- case 'E':\r
- if (exponent != -1)\r
- break;\r
- exponent = i;\r
- continue;\r
-\r
- case '+':\r
- case '-':\r
- // Only allow '+' or '-' after 'e' or 'E'\r
- if (exponent != i-1)\r
- break;\r
- continue;\r
-\r
- case '0': case '1': case '2': case '3': case '4':\r
- case '5': case '6': case '7': case '8': case '9':\r
- continue;\r
-\r
- default:\r
- break;\r
- }\r
- break;\r
- }\r
- s = s.substring(start, i);\r
- try {\r
- return Double.valueOf(s);\r
- }\r
- catch (NumberFormatException ex) {\r
- return ScriptRuntime.NaNobj;\r
- }\r
- }\r
-\r
- /**\r
- * The global method escape, as per ECMA-262 15.1.2.4.\r
-\r
- * Includes code for the 'mask' argument supported by the C escape\r
- * method, which used to be part of the browser imbedding. Blame\r
- * for the strange constant names should be directed there.\r
- */\r
-\r
- private Object js_escape(Context cx, Object[] args) {\r
- final int\r
- URL_XALPHAS = 1,\r
- URL_XPALPHAS = 2,\r
- URL_PATH = 4;\r
-\r
- String s = ScriptRuntime.toString(args, 0);\r
-\r
- int mask = URL_XALPHAS | URL_XPALPHAS | URL_PATH;\r
- if (args.length > 1) { // the 'mask' argument. Non-ECMA.\r
- double d = ScriptRuntime.toNumber(args[1]);\r
- if (d != d || ((mask = (int) d) != d) ||\r
- 0 != (mask & ~(URL_XALPHAS | URL_XPALPHAS | URL_PATH)))\r
- {\r
- String message = Context.getMessage0("msg.bad.esc.mask");\r
- cx.reportError(message);\r
- // do the ecma thing, in case reportError returns.\r
- mask = URL_XALPHAS | URL_XPALPHAS | URL_PATH;\r
- }\r
- }\r
-\r
- StringBuffer R = new StringBuffer();\r
- for (int k = 0; k < s.length(); k++) {\r
- int c = s.charAt(k), d;\r
- if (mask != 0 && ((c >= '0' && c <= '9') ||\r
- (c >= 'A' && c <= 'Z') ||\r
- (c >= 'a' && c <= 'z') ||\r
- c == '@' || c == '*' || c == '_' ||\r
- c == '-' || c == '.' ||\r
- ((c == '/' || c == '+') && mask > 3)))\r
- R.append((char)c);\r
- else if (c < 256) {\r
- if (c == ' ' && mask == URL_XPALPHAS) {\r
- R.append('+');\r
- } else {\r
- R.append('%');\r
- R.append(hex_digit_to_char(c >>> 4));\r
- R.append(hex_digit_to_char(c & 0xF));\r
- }\r
- } else {\r
- R.append('%');\r
- R.append('u');\r
- R.append(hex_digit_to_char(c >>> 12));\r
- R.append(hex_digit_to_char((c & 0xF00) >>> 8));\r
- R.append(hex_digit_to_char((c & 0xF0) >>> 4));\r
- R.append(hex_digit_to_char(c & 0xF));\r
- }\r
- }\r
- return R.toString();\r
- }\r
-\r
- private static char hex_digit_to_char(int x) {\r
- return (char)(x <= 9 ? x + '0' : x + ('A' - 10));\r
- }\r
-\r
- /**\r
- * The global unescape method, as per ECMA-262 15.1.2.5.\r
- */\r
-\r
- private Object js_unescape(Context cx, Object[] args)\r
- {\r
- String s = ScriptRuntime.toString(args, 0);\r
- int firstEscapePos = s.indexOf('%');\r
- if (firstEscapePos >= 0) {\r
- int L = s.length();\r
- char[] buf = s.toCharArray();\r
- int destination = firstEscapePos;\r
- for (int k = firstEscapePos; k != L;) {\r
- char c = buf[k];\r
- ++k;\r
- if (c == '%' && k != L) {\r
- int end, start;\r
- if (buf[k] == 'u') {\r
- start = k + 1;\r
- end = k + 5;\r
- } else {\r
- start = k;\r
- end = k + 2;\r
- }\r
- if (end <= L) {\r
- int x = 0;\r
- for (int i = start; i != end; ++i) {\r
- x = (x << 4) | TokenStream.xDigitToInt(buf[i]);\r
- }\r
- if (x >= 0) {\r
- c = (char)x;\r
- k = end;\r
- }\r
- }\r
- }\r
- buf[destination] = c;\r
- ++destination;\r
- }\r
- s = new String(buf, 0, destination); \r
- }\r
- return s;\r
- }\r
-\r
- /**\r
- * The global method isNaN, as per ECMA-262 15.1.2.6.\r
- */\r
-\r
- private Object js_isNaN(Context cx, Object[] args) {\r
- if (args.length < 1)\r
- return Boolean.TRUE;\r
- double d = ScriptRuntime.toNumber(args[0]);\r
- return (d != d) ? Boolean.TRUE : Boolean.FALSE;\r
- }\r
-\r
- private Object js_isFinite(Context cx, Object[] args) {\r
- if (args.length < 1)\r
- return Boolean.FALSE;\r
- double d = ScriptRuntime.toNumber(args[0]);\r
- return (d != d || d == Double.POSITIVE_INFINITY ||\r
- d == Double.NEGATIVE_INFINITY)\r
- ? Boolean.FALSE\r
- : Boolean.TRUE;\r
- }\r
-\r
- private Object js_eval(Context cx, Scriptable scope, Object[] args)\r
- throws JavaScriptException\r
- {\r
- String m = ScriptRuntime.getMessage1("msg.cant.call.indirect", "eval");\r
- throw NativeGlobal.constructError(cx, "EvalError", m, scope);\r
- }\r
-\r
- /**\r
- * The eval function property of the global object.\r
- *\r
- * See ECMA 15.1.2.1\r
- */\r
- public static Object evalSpecial(Context cx, Scriptable scope,\r
- Object thisArg, Object[] args,\r
- String filename, int lineNumber)\r
- throws JavaScriptException\r
- {\r
- throw NativeGlobal.constructError(cx, "EvalError", "XWT does not allow eval()", scope);\r
- /*\r
- if (args.length < 1)\r
- return Undefined.instance;\r
- Object x = args[0];\r
- if (!(x instanceof String)) {\r
- String message = Context.getMessage0("msg.eval.nonstring");\r
- Context.reportWarning(message);\r
- return x;\r
- }\r
- int[] linep = { lineNumber };\r
- if (filename == null) {\r
- filename = Context.getSourcePositionFromStack(linep);\r
- if (filename == null) {\r
- filename = "";\r
- linep[0] = 1;\r
- } \r
- } \r
- filename += "(eval)";\r
-\r
- try {\r
- StringReader in = new StringReader((String) x);\r
- Object securityDomain = cx.getSecurityDomainForStackDepth(3);\r
-\r
- // Compile the reader with opt level of -1 to force interpreter\r
- // mode.\r
- int oldOptLevel = cx.getOptimizationLevel();\r
- cx.setOptimizationLevel(-1);\r
- Script script = cx.compileReader(scope, in, filename, linep[0],\r
- securityDomain);\r
- cx.setOptimizationLevel(oldOptLevel);\r
-\r
- // if the compile fails, an error has been reported by the\r
- // compiler, but we need to stop execution to avoid\r
- // infinite looping on while(true) { eval('foo bar') } -\r
- // so we throw an EvaluatorException.\r
- if (script == null) {\r
- String message = Context.getMessage0("msg.syntax");\r
- throw new EvaluatorException(message);\r
- }\r
-\r
- InterpretedScript is = (InterpretedScript) script;\r
- is.itsData.itsFromEvalCode = true;\r
- Object result = is.call(cx, scope, (Scriptable) thisArg, null);\r
-\r
- return result;\r
- }\r
- catch (IOException ioe) {\r
- // should never happen since we just made the Reader from a String\r
- throw new RuntimeException("unexpected io exception");\r
- }\r
- */\r
- }\r
-\r
-\r
- /**\r
- * The NativeError functions\r
- *\r
- * See ECMA 15.11.6\r
- */\r
- public static EcmaError constructError(Context cx,\r
- String error,\r
- String message,\r
- Object scope)\r
- {\r
- int[] linep = { 0 };\r
- String filename = cx.getSourcePositionFromStack(linep);\r
- return constructError(cx, error, message, scope,\r
- filename, linep[0], 0, null);\r
- }\r
-\r
- static EcmaError typeError0(String messageId, Object scope) {\r
- return constructError(Context.getContext(), "TypeError",\r
- ScriptRuntime.getMessage0(messageId), scope);\r
- }\r
-\r
- static EcmaError typeError1(String messageId, Object arg1, Object scope) {\r
- return constructError(Context.getContext(), "TypeError",\r
- ScriptRuntime.getMessage1(messageId, arg1), scope);\r
- }\r
-\r
- /**\r
- * The NativeError functions\r
- *\r
- * See ECMA 15.11.6\r
- */\r
- public static EcmaError constructError(Context cx,\r
- String error,\r
- String message,\r
- Object scope,\r
- String sourceName,\r
- int lineNumber,\r
- int columnNumber,\r
- String lineSource)\r
- {\r
- Scriptable scopeObject;\r
- try {\r
- scopeObject = (Scriptable) scope;\r
- }\r
- catch (ClassCastException x) {\r
- throw new RuntimeException(x.toString());\r
- }\r
-\r
- Object args[] = { message };\r
- try {\r
- Object errorObject = cx.newObject(scopeObject, error, args);\r
- return new EcmaError((NativeError)errorObject, sourceName,\r
- lineNumber, columnNumber, lineSource);\r
- }\r
- catch (PropertyException x) {\r
- throw new RuntimeException(x.toString());\r
- }\r
- catch (JavaScriptException x) {\r
- throw new RuntimeException(x.toString());\r
- }\r
- catch (NotAFunctionException x) {\r
- throw new RuntimeException(x.toString());\r
- }\r
- }\r
-\r
- /**\r
- * The implementation of all the ECMA error constructors (SyntaxError,\r
- * TypeError, etc.)\r
- */\r
- private Object new_CommonError(IdFunction ctorObj, Context cx,\r
- Scriptable scope, Object[] args)\r
- {\r
- Scriptable newInstance = new NativeError();\r
- newInstance.setPrototype((Scriptable)(ctorObj.get("prototype", ctorObj)));\r
- newInstance.setParentScope(scope);\r
- if (args.length > 0)\r
- newInstance.put("message", newInstance, args[0]);\r
- return newInstance;\r
- }\r
-\r
- /*\r
- * ECMA 3, 15.1.3 URI Handling Function Properties\r
- *\r
- * The following are implementations of the algorithms\r
- * given in the ECMA specification for the hidden functions\r
- * 'Encode' and 'Decode'.\r
- */\r
- private static String encode(Context cx, String str, String unescapedSet) {\r
- int j, k = 0, L;\r
- char C, C2;\r
- int V;\r
- char utf8buf[] = new char[6];\r
- StringBuffer R;\r
-\r
- R = new StringBuffer();\r
-\r
- while (k < str.length()) {\r
- C = str.charAt(k);\r
- if (unescapedSet.indexOf(C) != -1) {\r
- R.append(C);\r
- } else {\r
- if ((C >= 0xDC00) && (C <= 0xDFFF)) {\r
- throw cx.reportRuntimeError0("msg.bad.uri");\r
- }\r
- if ((C < 0xD800) || (C > 0xDBFF))\r
- V = C;\r
- else {\r
- k++;\r
- if (k == str.length()) {\r
- throw cx.reportRuntimeError0("msg.bad.uri");\r
- }\r
- C2 = str.charAt(k);\r
- if ((C2 < 0xDC00) || (C2 > 0xDFFF)) {\r
- throw cx.reportRuntimeError0("msg.bad.uri");\r
- }\r
- V = ((C - 0xD800) << 10) + (C2 - 0xDC00) + 0x10000;\r
- }\r
- L = oneUcs4ToUtf8Char(utf8buf, V);\r
- for (j = 0; j < L; j++) {\r
- R.append('%');\r
- if (utf8buf[j] < 16)\r
- R.append('0');\r
- R.append(Integer.toHexString(utf8buf[j]));\r
- }\r
- }\r
- k++;\r
- }\r
- return R.toString();\r
- }\r
-\r
- private static boolean isHex(char c) {\r
- return ((c >= '0' && c <= '9')\r
- || (c >= 'a' && c <= 'f')\r
- || (c >= 'A' && c <= 'F'));\r
- }\r
-\r
- private static int unHex(char c) {\r
- if (c >= '0' && c <= '9')\r
- return c - '0';\r
- else\r
- if (c >= 'a' && c <= 'f')\r
- return c - 'a' + 10;\r
- else\r
- return c - 'A' +10;\r
- }\r
-\r
- private static String decode(Context cx, String str, String reservedSet) {\r
- int start, k = 0;\r
- char C, H;\r
- int V;\r
- int B;\r
- char[] octets = new char[6];\r
- StringBuffer R;\r
- int j, n;\r
-\r
- R = new StringBuffer();\r
-\r
- while (k < str.length()) {\r
- C = str.charAt(k);\r
- if (C == '%') {\r
- start = k;\r
- if ((k + 2) >= str.length())\r
- throw cx.reportRuntimeError0("msg.bad.uri");\r
- if (!isHex(str.charAt(k + 1)) || !isHex(str.charAt(k + 2)))\r
- throw cx.reportRuntimeError0("msg.bad.uri");\r
- B = unHex(str.charAt(k + 1)) * 16 + unHex(str.charAt(k + 2));\r
- k += 2;\r
- if ((B & 0x80) == 0)\r
- C = (char)B;\r
- else {\r
- n = 1;\r
- while ((B & (0x80 >>> n)) != 0) n++;\r
- if ((n == 1) || (n > 6))\r
- throw cx.reportRuntimeError0("msg.bad.uri");\r
- octets[0] = (char)B;\r
- if ((k + 3 * (n - 1)) >= str.length())\r
- throw cx.reportRuntimeError0("msg.bad.uri");\r
- for (j = 1; j < n; j++) {\r
- k++;\r
- if (str.charAt(k) != '%')\r
- throw cx.reportRuntimeError0("msg.bad.uri");\r
- if (!isHex(str.charAt(k + 1))\r
- || !isHex(str.charAt(k + 2)))\r
- throw cx.reportRuntimeError0("msg.bad.uri");\r
- B = unHex(str.charAt(k + 1)) * 16\r
- + unHex(str.charAt(k + 2));\r
- if ((B & 0xC0) != 0x80)\r
- throw cx.reportRuntimeError0("msg.bad.uri");\r
- k += 2;\r
- octets[j] = (char)B;\r
- }\r
- V = utf8ToOneUcs4Char(octets, n);\r
- if (V >= 0x10000) {\r
- V -= 0x10000;\r
- if (V > 0xFFFFF)\r
- throw cx.reportRuntimeError0("msg.bad.uri");\r
- C = (char)((V & 0x3FF) + 0xDC00);\r
- H = (char)((V >>> 10) + 0xD800);\r
- R.append(H);\r
- }\r
- else\r
- C = (char)V;\r
- }\r
- if (reservedSet.indexOf(C) != -1) {\r
- for (int x = 0; x < (k - start + 1); x++)\r
- R.append(str.charAt(start + x));\r
- }\r
- else\r
- R.append(C);\r
- }\r
- else\r
- R.append(C);\r
- k++;\r
- }\r
- return R.toString();\r
- }\r
-\r
- private static String uriReservedPlusPound = ";/?:@&=+$,#";\r
- private static String uriUnescaped =\r
- "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_.!~*'()";\r
-\r
- private String js_decodeURI(Context cx, Object[] args) {\r
- String str = ScriptRuntime.toString(args, 0);\r
- return decode(cx, str, uriReservedPlusPound);\r
- }\r
-\r
- private String js_decodeURIComponent(Context cx, Object[] args) {\r
- String str = ScriptRuntime.toString(args, 0);\r
- return decode(cx, str, "");\r
- }\r
-\r
- private Object js_encodeURI(Context cx, Object[] args) {\r
- String str = ScriptRuntime.toString(args, 0);\r
- return encode(cx, str, uriReservedPlusPound + uriUnescaped);\r
- }\r
-\r
- private String js_encodeURIComponent(Context cx, Object[] args) {\r
- String str = ScriptRuntime.toString(args, 0);\r
- return encode(cx, str, uriUnescaped);\r
- }\r
-\r
- /* Convert one UCS-4 char and write it into a UTF-8 buffer, which must be\r
- * at least 6 bytes long. Return the number of UTF-8 bytes of data written.\r
- */\r
- private static int oneUcs4ToUtf8Char(char[] utf8Buffer, int ucs4Char) {\r
- int utf8Length = 1;\r
-\r
- //JS_ASSERT(ucs4Char <= 0x7FFFFFFF);\r
- if ((ucs4Char & ~0x7F) == 0)\r
- utf8Buffer[0] = (char)ucs4Char;\r
- else {\r
- int i;\r
- int a = ucs4Char >>> 11;\r
- utf8Length = 2;\r
- while (a != 0) {\r
- a >>>= 5;\r
- utf8Length++;\r
- }\r
- i = utf8Length;\r
- while (--i > 0) {\r
- utf8Buffer[i] = (char)((ucs4Char & 0x3F) | 0x80);\r
- ucs4Char >>>= 6;\r
- }\r
- utf8Buffer[0] = (char)(0x100 - (1 << (8-utf8Length)) + ucs4Char);\r
- }\r
- return utf8Length;\r
- }\r
-\r
-\r
- /* Convert a utf8 character sequence into a UCS-4 character and return that\r
- * character. It is assumed that the caller already checked that the sequence is valid.\r
- */\r
- private static int utf8ToOneUcs4Char(char[] utf8Buffer, int utf8Length) {\r
- int ucs4Char;\r
- int k = 0;\r
- //JS_ASSERT(utf8Length >= 1 && utf8Length <= 6);\r
- if (utf8Length == 1) {\r
- ucs4Char = utf8Buffer[0];\r
- // JS_ASSERT(!(ucs4Char & 0x80));\r
- } else {\r
- //JS_ASSERT((*utf8Buffer & (0x100 - (1 << (7-utf8Length)))) == (0x100 - (1 << (8-utf8Length))));\r
- ucs4Char = utf8Buffer[k++] & ((1<<(7-utf8Length))-1);\r
- while (--utf8Length > 0) {\r
- //JS_ASSERT((*utf8Buffer & 0xC0) == 0x80);\r
- ucs4Char = ucs4Char<<6 | (utf8Buffer[k++] & 0x3F);\r
- }\r
- }\r
- return ucs4Char;\r
- }\r
-\r
- private static final int\r
- Id_decodeURI = 1,\r
- Id_decodeURIComponent = 2,\r
- Id_encodeURI = 3,\r
- Id_encodeURIComponent = 4,\r
- Id_escape = 5,\r
- Id_eval = 6,\r
- Id_isFinite = 7,\r
- Id_isNaN = 8,\r
- Id_parseFloat = 9,\r
- Id_parseInt = 10,\r
- Id_unescape = 11,\r
-\r
- LAST_SCOPE_FUNCTION_ID = 11,\r
-\r
- Id_new_CommonError = 12;\r
-\r
- private boolean scopeSlaveFlag;\r
-\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- * Frank Mitchell\r
- * Mike Shaver\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-import java.lang.reflect.Array;\r
-\r
-/**\r
- * This class reflects Java arrays into the JavaScript environment.\r
- *\r
- * @author Mike Shaver\r
- * @see NativeJavaClass\r
- * @see NativeJavaObject\r
- * @see NativeJavaPackage\r
- */\r
-\r
-public class NativeJavaArray extends NativeJavaObject {\r
-\r
- public String getClassName() {\r
- return "JavaArray";\r
- }\r
-\r
- public static NativeJavaArray wrap(Scriptable scope, Object array) {\r
- return new NativeJavaArray(scope, array);\r
- }\r
-\r
- public Object unwrap() {\r
- return array;\r
- }\r
-\r
- public NativeJavaArray(Scriptable scope, Object array) {\r
- super(scope, null, ScriptRuntime.ObjectClass);\r
- Class cl = array.getClass();\r
- if (!cl.isArray()) {\r
- throw new RuntimeException("Array expected");\r
- }\r
- this.array = array;\r
- this.length = Array.getLength(array);\r
- this.cls = cl.getComponentType();\r
- }\r
-\r
- public boolean has(String id, Scriptable start) {\r
- return id.equals("length") || super.has(id, start);\r
- }\r
-\r
- public boolean has(int index, Scriptable start) {\r
- return 0 <= index && index < length;\r
- }\r
-\r
- public Object get(String id, Scriptable start) {\r
- if (id.equals("length"))\r
- return new Integer(length);\r
- Object result = super.get(id, start);\r
- if (result == NOT_FOUND && \r
- !ScriptRuntime.hasProp(getPrototype(), id)) \r
- {\r
- throw Context.reportRuntimeError2(\r
- "msg.java.member.not.found", array.getClass().getName(), id);\r
- }\r
- return result; \r
- }\r
-\r
- public Object get(int index, Scriptable start) {\r
- if (0 <= index && index < length)\r
- return NativeJavaObject.wrap(this, Array.get(array, index), cls);\r
- return Undefined.instance;\r
- }\r
-\r
- public void put(String id, Scriptable start, Object value) {\r
- // Ignore assignments to "length"--it's readonly.\r
- if (!id.equals("length"))\r
- super.put(id, start, value);\r
- }\r
- \r
- public void put(int index, Scriptable start, Object value) {\r
- if (0 <= index && index < length) {\r
- Array.set(array, index, NativeJavaObject.coerceType(cls, value));\r
- return;\r
- }\r
- super.put(index, start, value);\r
- }\r
-\r
- public Object getDefaultValue(Class hint) {\r
- if (hint == null || hint == ScriptRuntime.StringClass) \r
- return array.toString();\r
- if (hint == ScriptRuntime.BooleanClass)\r
- return Boolean.TRUE;\r
- if (hint == ScriptRuntime.NumberClass)\r
- return ScriptRuntime.NaNobj;\r
- return this;\r
- }\r
- \r
- public Object[] getIds() {\r
- Object[] result = new Object[length];\r
- int i = length;\r
- while (--i >= 0)\r
- result[i] = new Integer(i);\r
- return result;\r
- }\r
-\r
- public boolean hasInstance(Scriptable value) {\r
- if (!(value instanceof Wrapper))\r
- return false;\r
- Object instance = ((Wrapper)value).unwrap();\r
- return cls.isInstance(instance);\r
- }\r
-\r
- public Scriptable getPrototype() {\r
- if (prototype == null) {\r
- prototype = \r
- ScriptableObject.getClassPrototype(this.getParentScope(),\r
- "Array");\r
- }\r
- return prototype;\r
- }\r
-\r
- Object array;\r
- int length;\r
- Class cls;\r
- Scriptable prototype;\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- * Frank Mitchell\r
- * Mike Shaver\r
- * Kurt Westerfeld\r
- * \r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-import java.lang.reflect.*;\r
-import java.util.Hashtable;\r
-\r
-/**\r
- * This class reflects Java classes into the JavaScript environment, mainly\r
- * for constructors and static members. We lazily reflect properties,\r
- * and currently do not guarantee that a single j.l.Class is only\r
- * reflected once into the JS environment, although we should.\r
- * The only known case where multiple reflections\r
- * are possible occurs when a j.l.Class is wrapped as part of a\r
- * method return or property access, rather than by walking the\r
- * Packages/java tree.\r
- *\r
- * @author Mike Shaver\r
- * @see NativeJavaArray\r
- * @see NativeJavaObject\r
- * @see NativeJavaPackage\r
- */\r
-\r
-public class NativeJavaClass extends NativeJavaObject implements Function {\r
-\r
- public NativeJavaClass(Scriptable scope, Class cl) {\r
- super(scope, cl, JavaMembers.lookupClass(scope, cl, cl));\r
- fieldAndMethods = members.getFieldAndMethodsObjects(this, javaObject, \r
- true);\r
- }\r
-\r
- public String getClassName() {\r
- return "JavaClass";\r
- }\r
- \r
- public boolean has(String name, Scriptable start) {\r
- return members.has(name, true);\r
- }\r
- \r
- public Object get(String name, Scriptable start) {\r
- // When used as a constructor, ScriptRuntime.newObject() asks\r
- // for our prototype to create an object of the correct type.\r
- // We don't really care what the object is, since we're returning\r
- // one constructed out of whole cloth, so we return null.\r
-\r
- if (name.equals("prototype"))\r
- return null;\r
- \r
- Object result = Scriptable.NOT_FOUND;\r
- \r
- if (fieldAndMethods != null) {\r
- result = fieldAndMethods.get(name);\r
- if (result != null)\r
- return result;\r
- }\r
- \r
- if (members.has(name, true)) {\r
- result = members.get(this, name, javaObject, true);\r
- } else {\r
- // experimental: look for nested classes by appending $name to current class' name.\r
- try {\r
- String nestedName = getClassObject().getName() + '$' + name;\r
- Class nestedClass = ScriptRuntime.loadClassName(nestedName);\r
- Scriptable nestedValue = wrap(ScriptableObject.getTopLevelScope(this), nestedClass);\r
- nestedValue.setParentScope(this);\r
- result = nestedValue;\r
- } catch (ClassNotFoundException ex) {\r
- throw members.reportMemberNotFound(name);\r
- } catch (IllegalArgumentException e) {\r
- throw members.reportMemberNotFound(name);\r
- }\r
- }\r
- \r
- return result;\r
- }\r
-\r
- public void put(String name, Scriptable start, Object value) {\r
- members.put(this, name, javaObject, value, true);\r
- }\r
-\r
- public Object[] getIds() {\r
- return members.getIds(true);\r
- }\r
- \r
- public Class getClassObject() { \r
- return (Class) super.unwrap();\r
- }\r
-\r
- // XXX ??\r
- public static NativeJavaClass wrap(Scriptable scope, Class cls) {\r
- return new NativeJavaClass(scope, cls);\r
- }\r
-\r
- public Object getDefaultValue(Class hint) {\r
- if (hint == null || hint == ScriptRuntime.StringClass)\r
- return this.toString();\r
- if (hint == ScriptRuntime.BooleanClass)\r
- return Boolean.TRUE;\r
- if (hint == ScriptRuntime.NumberClass)\r
- return ScriptRuntime.NaNobj;\r
- return this;\r
- }\r
-\r
- public Object call(Context cx, Scriptable scope, Scriptable thisObj,\r
- Object[] args)\r
- throws JavaScriptException\r
- {\r
- // If it looks like a "cast" of an object to this class type,\r
- // walk the prototype chain to see if there's a wrapper of a \r
- // object that's an instanceof this class.\r
- if (args.length == 1 && args[0] instanceof Scriptable) {\r
- Class c = getClassObject();\r
- Scriptable p = (Scriptable) args[0];\r
- do {\r
- if (p instanceof Wrapper) {\r
- Object o = ((Wrapper) p).unwrap();\r
- if (c.isInstance(o))\r
- return p;\r
- }\r
- p = p.getPrototype();\r
- } while (p != null);\r
- }\r
- return construct(cx, scope, args);\r
- }\r
-\r
- public Scriptable construct(Context cx, Scriptable scope, Object[] args)\r
- throws JavaScriptException\r
- {\r
- Class classObject = getClassObject();\r
- int modifiers = classObject.getModifiers();\r
- if (! (Modifier.isInterface(modifiers) || \r
- Modifier.isAbstract(modifiers))) \r
- {\r
- Constructor[] ctors = members.getConstructors();\r
- Member member = NativeJavaMethod.findFunction(ctors, args);\r
- Constructor ctor = (Constructor) member;\r
- if (ctor == null) {\r
- String sig = NativeJavaMethod.scriptSignature(args);\r
- throw Context.reportRuntimeError2(\r
- "msg.no.java.ctor", classObject.getName(), sig);\r
- }\r
-\r
- // Found the constructor, so try invoking it.\r
- return NativeJavaClass.constructSpecific(cx, scope, \r
- this, ctor, args);\r
- } else {\r
- Scriptable topLevel = ScriptableObject.getTopLevelScope(this);\r
- String msg = "";\r
- try {\r
- // trying to construct an interface; use JavaAdapter to \r
- // construct a new class on the fly that implements this \r
- // interface.\r
- Object v = topLevel.get("JavaAdapter", topLevel);\r
- if (v != NOT_FOUND) {\r
- Function f = (Function) v;\r
- Object[] adapterArgs = { this, args[0] };\r
- return (Scriptable) f.construct(cx, topLevel, \r
- adapterArgs);\r
- }\r
- } catch (Exception ex) {\r
- // fall through to error\r
- String m = ex.getMessage();\r
- if (m != null)\r
- msg = m;\r
- }\r
- throw Context.reportRuntimeError2(\r
- "msg.cant.instantiate", msg, classObject.getName());\r
- }\r
- }\r
-\r
- public static Scriptable constructSpecific(Context cx, \r
- Scriptable scope, \r
- Scriptable thisObj, \r
- Constructor ctor,\r
- Object[] args)\r
- throws JavaScriptException\r
- {\r
- Scriptable topLevel = ScriptableObject.getTopLevelScope(thisObj);\r
- Class classObject = ctor.getDeclaringClass();\r
-\r
- Class[] paramTypes = ctor.getParameterTypes();\r
- for (int i = 0; i < args.length; i++) {\r
- args[i] = NativeJavaObject.coerceType(paramTypes[i], args[i]);\r
- }\r
- try {\r
- // we need to force this to be wrapped, because construct _has_\r
- // to return a scriptable \r
- return \r
- (Scriptable) NativeJavaObject.wrap(topLevel, \r
- ctor.newInstance(args),\r
- classObject);\r
-\r
- } catch (InstantiationException instEx) {\r
- throw Context.reportRuntimeError2(\r
- "msg.cant.instantiate", \r
- instEx.getMessage(), classObject.getName());\r
- } catch (IllegalArgumentException argEx) {\r
- String signature = NativeJavaMethod.scriptSignature(args);\r
- String ctorString = ctor.toString();\r
- throw Context.reportRuntimeError3(\r
- "msg.bad.ctor.sig", argEx.getMessage(), ctorString, signature);\r
- } catch (InvocationTargetException e) {\r
- throw JavaScriptException.wrapException(scope, e);\r
- } catch (IllegalAccessException accessEx) {\r
- throw Context.reportRuntimeError1(\r
- "msg.java.internal.private", accessEx.getMessage());\r
- }\r
- }\r
-\r
- public String toString() {\r
- return "[JavaClass " + getClassObject().getName() + "]";\r
- }\r
-\r
- /**\r
- * Determines if prototype is a wrapped Java object and performs\r
- * a Java "instanceof".\r
- * Exception: if value is an instance of NativeJavaClass, it isn't \r
- * considered an instance of the Java class; this forestalls any \r
- * name conflicts between java.lang.Class's methods and the \r
- * static methods exposed by a JavaNativeClass.\r
- */\r
- public boolean hasInstance(Scriptable value) {\r
-\r
- if (value instanceof Wrapper && \r
- !(value instanceof NativeJavaClass)) {\r
- Object instance = ((Wrapper)value).unwrap();\r
-\r
- return getClassObject().isInstance(instance);\r
- }\r
-\r
- // value wasn't something we understand\r
- return false;\r
- }\r
-\r
- private Hashtable fieldAndMethods;\r
-\r
- // beard: need a scope for finding top-level prototypes.\r
- private Scriptable parent;\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- * Frank Mitchell\r
- * Mike Shaver\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-import java.lang.reflect.*;\r
-\r
-/**\r
- * This class reflects a single Java constructor into the JavaScript \r
- * environment. It satisfies a request for an overloaded constructor,\r
- * as introduced in LiveConnect 3.\r
- * All NativeJavaConstructors behave as JSRef `bound' methods, in that they\r
- * always construct the same NativeJavaClass regardless of any reparenting \r
- * that may occur.\r
- *\r
- * @author Frank Mitchell\r
- * @see NativeJavaMethod\r
- * @see NativeJavaPackage\r
- * @see NativeJavaClass\r
- */\r
-\r
-public class NativeJavaConstructor extends NativeFunction implements Function {\r
-\r
- public NativeJavaConstructor(Constructor ctor) {\r
- this.constructor = ctor;\r
- this.functionName = "<init>" + NativeJavaMethod.signature(ctor);\r
- }\r
-\r
- public Object call(Context cx, Scriptable scope, Scriptable thisObj,\r
- Object[] args)\r
- throws JavaScriptException\r
- {\r
- // Find a method that matches the types given.\r
- if (constructor == null) {\r
- throw new RuntimeException("No constructor defined for call");\r
- }\r
-\r
- return NativeJavaClass.constructSpecific(cx, scope, \r
- this, constructor, args);\r
- }\r
-\r
- public String toString() {\r
- return "[JavaConstructor " + constructor.getName() + "]";\r
- }\r
-\r
- Constructor getConstructor() {\r
- return constructor; \r
- }\r
-\r
- Constructor constructor;\r
-}\r
-\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- * Frank Mitchell\r
- * Mike Shaver\r
- * \r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-import java.lang.reflect.*;\r
-\r
-/**\r
- * This class reflects Java methods into the JavaScript environment. It\r
- * handles overloading of methods, and method/field name conflicts.\r
- * All NativeJavaMethods behave as JSRef `bound' methods, in that they\r
- * always operate on the object underlying the original NativeJavaObject\r
- * parent regardless of any reparenting that may occur.\r
- *\r
- * @author Mike Shaver\r
- * @see NativeJavaArray\r
- * @see NativeJavaPackage\r
- * @see NativeJavaClass\r
- */\r
-\r
-public class NativeJavaMethod extends NativeFunction implements Function {\r
-\r
- public NativeJavaMethod() {\r
- this.functionName = null;\r
- }\r
-\r
- public NativeJavaMethod(Method[] methods) {\r
- this.methods = methods;\r
- this.functionName = methods[0].getName();\r
- }\r
-\r
- public NativeJavaMethod(Method method, String name) {\r
- this.methods = new Method[1];\r
- this.methods[0] = method;\r
- this.functionName = name;\r
- }\r
-\r
- public void add(Method method) {\r
- if (functionName == null) {\r
- functionName = method.getName();\r
- } else if (!functionName.equals(method.getName())) {\r
- throw new RuntimeException("internal method name mismatch");\r
- } \r
- // XXX a more intelligent growth algorithm would be nice\r
- int len = methods == null ? 0 : methods.length;\r
- Method[] newMeths = new Method[len + 1];\r
- for (int i = 0; i < len; i++)\r
- newMeths[i] = methods[i];\r
- newMeths[len] = method;\r
- methods = newMeths;\r
- }\r
-\r
- static String scriptSignature(Object value) {\r
- if (value == null) {\r
- return "null";\r
- }\r
- else {\r
- Class type = value.getClass();\r
- if (type == ScriptRuntime.UndefinedClass)\r
- return "undefined";\r
- if (type == ScriptRuntime.BooleanClass)\r
- return "boolean";\r
- if (type == ScriptRuntime.StringClass)\r
- return "string";\r
- if (ScriptRuntime.NumberClass.isAssignableFrom(type))\r
- return "number";\r
- if (value instanceof Wrapper) {\r
- return ((Wrapper)value).unwrap().getClass().getName();\r
- }\r
- if (value instanceof Scriptable) {\r
- if (value instanceof Function)\r
- return "function";\r
- return "object";\r
- }\r
- return javaSignature(type);\r
- }\r
- }\r
-\r
- static String scriptSignature(Object[] values) {\r
- StringBuffer sig = new StringBuffer();\r
- for (int i = 0; i < values.length; i++) {\r
- if (i != 0)\r
- sig.append(',');\r
- sig.append(scriptSignature(values[i]));\r
- }\r
- return sig.toString();\r
- }\r
-\r
- static String javaSignature(Class type) {\r
- if (type == null) {\r
- return "null";\r
- }\r
- else if (type.isArray()) {\r
- return javaSignature(type.getComponentType()) + "[]";\r
- }\r
- return type.getName();\r
- }\r
-\r
- static String javaSignature(Class[] types) {\r
- StringBuffer sig = new StringBuffer();\r
- for (int i = 0; i < types.length; i++) {\r
- if (i != 0)\r
- sig.append(',');\r
- sig.append(javaSignature(types[i]));\r
- }\r
- return sig.toString();\r
- }\r
-\r
- static String signature(Member member) {\r
- Class paramTypes[];\r
-\r
- if (member instanceof Method) {\r
- paramTypes = ((Method) member).getParameterTypes();\r
- return member.getName() + "(" + javaSignature(paramTypes) + ")";\r
- }\r
- else {\r
- paramTypes = ((Constructor) member).getParameterTypes();\r
- return "(" + javaSignature(paramTypes) + ")";\r
- }\r
- }\r
- \r
- public String decompile(Context cx, int indent, boolean justbody) {\r
- StringBuffer sb = new StringBuffer();\r
- if (!justbody) {\r
- sb.append("function ");\r
- sb.append(getFunctionName());\r
- sb.append("() {");\r
- }\r
- sb.append("/*\n");\r
- toString(sb);\r
- sb.append(justbody ? "*/\n" : "*/}\n");\r
- return sb.toString();\r
- }\r
- \r
- public String toString() {\r
- StringBuffer sb = new StringBuffer();\r
- toString(sb);\r
- return sb.toString();\r
- }\r
-\r
- private void toString(StringBuffer sb) {\r
- for (int i=0; i < methods.length; i++) {\r
- sb.append(javaSignature(methods[i].getReturnType()));\r
- sb.append(' ');\r
- sb.append(signature(methods[i]));\r
- sb.append('\n');\r
- }\r
- }\r
-\r
- public Object call(Context cx, Scriptable scope, Scriptable thisObj,\r
- Object[] args)\r
- throws JavaScriptException\r
- {\r
- // Find a method that matches the types given.\r
- if (methods.length == 0) {\r
- throw new RuntimeException("No methods defined for call");\r
- }\r
-\r
- Method meth = (Method) findFunction(methods, args);\r
- if (meth == null) {\r
- Class c = methods[0].getDeclaringClass();\r
- String sig = c.getName() + "." + functionName + "(" +\r
- scriptSignature(args) + ")";\r
- throw Context.reportRuntimeError1("msg.java.no_such_method", sig);\r
- }\r
-\r
- // OPT: already retrieved in findFunction, so we should inline that\r
- // OPT: or pass it back somehow\r
- Class paramTypes[] = meth.getParameterTypes();\r
-\r
- // First, we marshall the args.\r
- for (int i = 0; i < args.length; i++) {\r
- args[i] = NativeJavaObject.coerceType(paramTypes[i], args[i]);\r
- }\r
- Object javaObject;\r
- if (Modifier.isStatic(meth.getModifiers())) {\r
- javaObject = null; // don't need an object\r
- } else {\r
- Scriptable o = thisObj;\r
- while (!(o instanceof Wrapper)) {\r
- o = o.getPrototype();\r
- if (o == null) {\r
- throw Context.reportRuntimeError1(\r
- "msg.nonjava.method", functionName);\r
- }\r
- }\r
- javaObject = ((Wrapper) o).unwrap(); \r
- }\r
- try {\r
- if (debug) {\r
- printDebug("Calling ", meth, args);\r
- }\r
-\r
- Object retval = meth.invoke(javaObject, args);\r
- Class staticType = meth.getReturnType();\r
-\r
- if (debug) {\r
- Class actualType = (retval == null) ? null : retval.getClass();\r
- System.err.println(" ----- Returned " + retval + \r
- " actual = " + actualType +\r
- " expect = " + staticType);\r
- }\r
-\r
- Object wrapped = NativeJavaObject.wrap(scope, retval, staticType);\r
-\r
- if (debug) {\r
- Class actualType = (wrapped == null) ? null : wrapped.getClass();\r
- System.err.println(" ----- Wrapped as " + wrapped + \r
- " class = " + actualType);\r
- }\r
-\r
- if (wrapped == Undefined.instance)\r
- return wrapped;\r
- if (wrapped == null && staticType == Void.TYPE)\r
- return Undefined.instance;\r
- return wrapped;\r
- } catch (IllegalAccessException accessEx) {\r
- throw Context.reportRuntimeError(accessEx.getMessage());\r
- } catch (InvocationTargetException e) {\r
- throw JavaScriptException.wrapException(scope, e);\r
- }\r
- }\r
-\r
- /** \r
- * Find the correct function to call given the set of methods\r
- * or constructors and the arguments.\r
- * If no function can be found to call, return null.\r
- */\r
- static Member findFunction(Member[] methodsOrCtors, Object[] args) {\r
- if (methodsOrCtors.length == 0)\r
- return null;\r
- boolean hasMethods = methodsOrCtors[0] instanceof Method;\r
- if (Context.useJSObject && \r
- NativeJavaObject.jsObjectClass != null) \r
- {\r
- try {\r
- for (int i = 0; i < args.length; i++) {\r
- if (NativeJavaObject.jsObjectClass.isInstance(args[i]))\r
- args[i] = NativeJavaObject.jsObjectGetScriptable.invoke(\r
- args[i], ScriptRuntime.emptyArgs);\r
- }\r
- }\r
- catch (InvocationTargetException e) {\r
- // Just abandon conversion from JSObject\r
- }\r
- catch (IllegalAccessException e) {\r
- // Just abandon conversion from JSObject\r
- }\r
- }\r
-\r
- Member bestFit = null;\r
- Class[] bestFitTypes = null;\r
-\r
- java.util.Vector ambiguousMethods = null;\r
-\r
- for (int i = 0; i < methodsOrCtors.length; i++) {\r
- Member member = methodsOrCtors[i];\r
- Class paramTypes[] = hasMethods\r
- ? ((Method) member).getParameterTypes()\r
- : ((Constructor) member).getParameterTypes();\r
- if (paramTypes.length != args.length) {\r
- continue;\r
- }\r
- if (bestFitTypes == null) {\r
- int j;\r
- for (j = 0; j < paramTypes.length; j++) {\r
- if (!NativeJavaObject.canConvert(args[j], paramTypes[j])) {\r
- if (debug) printDebug("Rejecting (args can't convert) ", \r
- member, args);\r
- break;\r
- }\r
- }\r
- if (j == paramTypes.length) {\r
- if (debug) printDebug("Found ", member, args);\r
- bestFit = member;\r
- bestFitTypes = paramTypes;\r
- }\r
- }\r
- else {\r
- int preference = \r
- NativeJavaMethod.preferSignature(args, \r
- paramTypes, \r
- bestFitTypes);\r
- if (preference == PREFERENCE_AMBIGUOUS) {\r
- if (debug) printDebug("Deferring ", member, args);\r
- // add to "ambiguity list"\r
- if (ambiguousMethods == null)\r
- ambiguousMethods = new java.util.Vector();\r
- ambiguousMethods.addElement(member);\r
- }\r
- else if (preference == PREFERENCE_FIRST_ARG) {\r
- if (debug) printDebug("Substituting ", member, args);\r
- bestFit = member;\r
- bestFitTypes = paramTypes;\r
- }\r
- else {\r
- if (preference == PREFERENCE_EQUAL &&\r
- Modifier.isStatic(bestFit.getModifiers()) &&\r
- bestFit.getDeclaringClass().isAssignableFrom(\r
- member.getDeclaringClass())) \r
- {\r
- // On some JVMs, Class.getMethods will return all\r
- // static methods of the class heirarchy, even if\r
- // a derived class's parameters match exactly.\r
- // We want to call the dervied class's method.\r
- if (debug) printDebug("Rejecting (overridden static)",\r
- member, args);\r
- bestFit = member;\r
- bestFitTypes = paramTypes;\r
- } else {\r
- if (debug) printDebug("Rejecting ", member, args);\r
- }\r
- }\r
- }\r
- }\r
- \r
- if (ambiguousMethods == null)\r
- return bestFit;\r
-\r
- // Compare ambiguous methods with best fit, in case \r
- // the current best fit removes the ambiguities.\r
- for (int i = ambiguousMethods.size() - 1; i >= 0 ; i--) {\r
- Member member = (Member)ambiguousMethods.elementAt(i);\r
- Class paramTypes[] = hasMethods\r
- ? ((Method) member).getParameterTypes()\r
- : ((Constructor) member).getParameterTypes();\r
- int preference = \r
- NativeJavaMethod.preferSignature(args, \r
- paramTypes, \r
- bestFitTypes);\r
-\r
- if (preference == PREFERENCE_FIRST_ARG) {\r
- if (debug) printDebug("Substituting ", member, args);\r
- bestFit = member;\r
- bestFitTypes = paramTypes;\r
- ambiguousMethods.removeElementAt(i);\r
- }\r
- else if (preference == PREFERENCE_SECOND_ARG) {\r
- if (debug) printDebug("Rejecting ", member, args);\r
- ambiguousMethods.removeElementAt(i);\r
- }\r
- else {\r
- if (debug) printDebug("UNRESOLVED: ", member, args);\r
- }\r
- }\r
-\r
- if (ambiguousMethods.size() > 0) {\r
- // PENDING: report remaining ambiguity\r
- StringBuffer buf = new StringBuffer();\r
- boolean isCtor = (bestFit instanceof Constructor);\r
-\r
- ambiguousMethods.addElement(bestFit);\r
-\r
- for (int i = 0; i < ambiguousMethods.size(); i++) {\r
- if (i != 0) {\r
- buf.append(", ");\r
- }\r
- Member member = (Member)ambiguousMethods.elementAt(i);\r
- if (!isCtor) {\r
- Class rtnType = ((Method)member).getReturnType();\r
- buf.append(rtnType);\r
- buf.append(' ');\r
- }\r
- buf.append(NativeJavaMethod.signature(member));\r
- }\r
-\r
- String errMsg;\r
- if (isCtor) {\r
- Object errArgs[] = { \r
- bestFit.getName(), \r
- NativeJavaMethod.scriptSignature(args),\r
- buf.toString()\r
- };\r
- errMsg = \r
- Context.getMessage("msg.constructor.ambiguous", errArgs);\r
- }\r
- else {\r
- Object errArgs[] = { \r
- bestFit.getDeclaringClass().getName(), \r
- bestFit.getName(), \r
- NativeJavaMethod.scriptSignature(args),\r
- buf.toString()\r
- };\r
- errMsg = Context.getMessage("msg.method.ambiguous", errArgs);\r
- }\r
-\r
- throw \r
- Context.reportRuntimeError(errMsg);\r
- }\r
-\r
- return bestFit;\r
- }\r
- \r
- /** Types are equal */\r
- static final int PREFERENCE_EQUAL = 0;\r
- static final int PREFERENCE_FIRST_ARG = 1;\r
- static final int PREFERENCE_SECOND_ARG = 2;\r
- /** No clear "easy" conversion */\r
- static final int PREFERENCE_AMBIGUOUS = 3;\r
-\r
- /**\r
- * Determine which of two signatures is the closer fit.\r
- * Returns one of PREFERENCE_EQUAL, PREFERENCE_FIRST_ARG, \r
- * PREFERENCE_SECOND_ARG, or PREFERENCE_AMBIGUOUS.\r
- */\r
- public static int preferSignature(Object[] args, \r
- Class[] sig1, Class[] sig2) \r
- {\r
- int preference = 0;\r
-\r
- for (int j = 0; j < args.length; j++) {\r
- Class type1 = sig1[j];\r
- Class type2 = sig2[j];\r
-\r
- if (type1 == type2) {\r
- continue;\r
- }\r
-\r
- preference |=\r
- NativeJavaMethod.preferConversion(args[j], \r
- type1,\r
- type2);\r
-\r
- if (preference == PREFERENCE_AMBIGUOUS) {\r
- break;\r
- }\r
- }\r
- return preference;\r
- }\r
-\r
-\r
- /**\r
- * Determine which of two types is the easier conversion.\r
- * Returns one of PREFERENCE_EQUAL, PREFERENCE_FIRST_ARG, \r
- * PREFERENCE_SECOND_ARG, or PREFERENCE_AMBIGUOUS.\r
- */\r
- public static int preferConversion(Object fromObj, \r
- Class toClass1, Class toClass2) {\r
-\r
- int rank1 = \r
- NativeJavaObject.getConversionWeight(fromObj, toClass1);\r
- int rank2 = \r
- NativeJavaObject.getConversionWeight(fromObj, toClass2);\r
-\r
- if (rank1 == NativeJavaObject.CONVERSION_NONTRIVIAL && \r
- rank2 == NativeJavaObject.CONVERSION_NONTRIVIAL) {\r
-\r
- if (toClass1.isAssignableFrom(toClass2)) {\r
- return PREFERENCE_SECOND_ARG;\r
- }\r
- else if (toClass2.isAssignableFrom(toClass1)) {\r
- return PREFERENCE_FIRST_ARG;\r
- }\r
- }\r
- else {\r
- if (rank1 < rank2) {\r
- return PREFERENCE_FIRST_ARG;\r
- }\r
- else if (rank1 > rank2) {\r
- return PREFERENCE_SECOND_ARG;\r
- }\r
- }\r
- return PREFERENCE_AMBIGUOUS;\r
- }\r
-\r
- Method[] getMethods() {\r
- return methods; \r
- }\r
-\r
- private static final boolean debug = false;\r
-\r
- private static void printDebug(String msg, Member member, Object[] args) {\r
- if (debug) {\r
- System.err.println(" ----- " + msg + \r
- member.getDeclaringClass().getName() +\r
- "." + signature(member) +\r
- " for arguments (" + scriptSignature(args) + ")");\r
- }\r
- }\r
-\r
- Method methods[];\r
-}\r
-\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-2000 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- * Igor Bukanov\r
- * Frank Mitchell\r
- * Mike Shaver\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-import java.lang.reflect.*;\r
-import java.util.Hashtable;\r
-import java.util.Enumeration;\r
-\r
-/**\r
- * This class reflects non-Array Java objects into the JavaScript environment. It\r
- * reflect fields directly, and uses NativeJavaMethod objects to reflect (possibly\r
- * overloaded) methods.<p>\r
- *\r
- * @author Mike Shaver\r
- * @see NativeJavaArray\r
- * @see NativeJavaPackage\r
- * @see NativeJavaClass\r
- */\r
-\r
-public class NativeJavaObject implements Scriptable, Wrapper {\r
-\r
- public NativeJavaObject(Scriptable scope, Object javaObject, \r
- JavaMembers members) \r
- {\r
- this.parent = scope;\r
- this.javaObject = javaObject;\r
- this.members = members;\r
- }\r
- \r
- public NativeJavaObject(Scriptable scope, Object javaObject, \r
- Class staticType) \r
- {\r
- this.parent = scope;\r
- this.javaObject = javaObject;\r
- Class dynamicType = javaObject != null ? javaObject.getClass()\r
- : staticType;\r
- members = JavaMembers.lookupClass(scope, dynamicType, staticType);\r
- fieldAndMethods = members.getFieldAndMethodsObjects(this, javaObject, false);\r
- }\r
- \r
- public boolean has(String name, Scriptable start) {\r
- return members.has(name, false);\r
- }\r
- \r
- public boolean has(int index, Scriptable start) {\r
- return false;\r
- }\r
- \r
- public Object get(String name, Scriptable start) {\r
- if (fieldAndMethods != null) {\r
- Object result = fieldAndMethods.get(name);\r
- if (result != null) {\r
- return result;\r
- }\r
- }\r
- // TODO: passing 'this' as the scope is bogus since it has \r
- // no parent scope\r
- return members.get(this, name, javaObject, false);\r
- }\r
-\r
- public Object get(int index, Scriptable start) {\r
- throw members.reportMemberNotFound(Integer.toString(index));\r
- }\r
- \r
- public void put(String name, Scriptable start, Object value) {\r
- // We could be asked to modify the value of a property in the \r
- // prototype. Since we can't add a property to a Java object,\r
- // we modify it in the prototype rather than copy it down.\r
- if (prototype == null || members.has(name, false))\r
- members.put(this, name, javaObject, value, false);\r
- else\r
- prototype.put(name, prototype, value);\r
- }\r
-\r
- public void put(int index, Scriptable start, Object value) {\r
- throw members.reportMemberNotFound(Integer.toString(index));\r
- }\r
-\r
- public boolean hasInstance(Scriptable value) {\r
- // This is an instance of a Java class, so always return false\r
- return false;\r
- }\r
- \r
- public void delete(String name) {\r
- }\r
- \r
- public void delete(int index) {\r
- }\r
- \r
- public Scriptable getPrototype() {\r
- if (prototype == null && javaObject.getClass() == ScriptRuntime.StringClass) {\r
- return ScriptableObject.getClassPrototype(parent, "String");\r
- }\r
- return prototype;\r
- }\r
-\r
- /**\r
- * Sets the prototype of the object.\r
- */\r
- public void setPrototype(Scriptable m) {\r
- prototype = m;\r
- }\r
-\r
- /**\r
- * Returns the parent (enclosing) scope of the object.\r
- */\r
- public Scriptable getParentScope() {\r
- return parent;\r
- }\r
-\r
- /**\r
- * Sets the parent (enclosing) scope of the object.\r
- */\r
- public void setParentScope(Scriptable m) {\r
- parent = m;\r
- }\r
-\r
- public Object[] getIds() {\r
- return members.getIds(false);\r
- }\r
- \r
- public static Object wrap(Scriptable scope, Object obj, Class staticType) \r
- {\r
- if (obj == null)\r
- return obj;\r
- Context cx = Context.getCurrentContext();\r
- if (cx != null && cx.wrapHandler != null) {\r
- Object result = cx.wrapHandler.wrap(scope, obj, staticType);\r
- if (result != null)\r
- return result;\r
- }\r
- Class cls = obj.getClass();\r
- if (staticType != null && staticType.isPrimitive()) {\r
- if (staticType == Void.TYPE)\r
- return Undefined.instance;\r
- if (staticType == Character.TYPE)\r
- return new Integer((int) ((Character) obj).charValue());\r
- return obj;\r
- }\r
- if (cls.isArray())\r
- return NativeJavaArray.wrap(scope, obj);\r
- if (obj instanceof Scriptable)\r
- return obj;\r
- if (Context.useJSObject && jsObjectClass != null && \r
- staticType != jsObjectClass && jsObjectClass.isInstance(obj)) \r
- {\r
- try {\r
- return jsObjectGetScriptable.invoke(obj, ScriptRuntime.emptyArgs);\r
- }\r
- catch (InvocationTargetException e) {\r
- // Just abandon conversion from JSObject\r
- }\r
- catch (IllegalAccessException e) {\r
- // Just abandon conversion from JSObject\r
- }\r
- }\r
- return new NativeJavaObject(scope, obj, staticType);\r
- }\r
-\r
- public Object unwrap() {\r
- return javaObject;\r
- }\r
-\r
- public String getClassName() {\r
- return "JavaObject";\r
- }\r
-\r
- Function getConverter(String converterName) {\r
- Object converterFunction = get(converterName, this);\r
- if (converterFunction instanceof Function) {\r
- return (Function) converterFunction;\r
- }\r
- return null;\r
- }\r
-\r
- Object callConverter(Function converterFunction)\r
- throws JavaScriptException\r
- {\r
- Function f = (Function) converterFunction;\r
- return f.call(Context.getContext(), f.getParentScope(),\r
- this, ScriptRuntime.emptyArgs);\r
- }\r
-\r
- Object callConverter(String converterName)\r
- throws JavaScriptException\r
- {\r
- Function converter = getConverter(converterName);\r
- if (converter == null) {\r
- return javaObject.toString();\r
- }\r
- return callConverter(converter);\r
- }\r
-\r
- public Object getDefaultValue(Class hint) {\r
- if (hint == null || hint == ScriptRuntime.StringClass)\r
- return javaObject.toString();\r
- try {\r
- if (hint == ScriptRuntime.BooleanClass)\r
- return callConverter("booleanValue");\r
- if (hint == ScriptRuntime.NumberClass) {\r
- return callConverter("doubleValue");\r
- }\r
- // fall through to error message\r
- } catch (JavaScriptException jse) {\r
- // fall through to error message\r
- }\r
- throw Context.reportRuntimeError0("msg.default.value");\r
- }\r
-\r
-\r
- /**\r
- * Determine whether we can/should convert between the given type and the\r
- * desired one. This should be superceded by a conversion-cost calculation\r
- * function, but for now I'll hide behind precedent.\r
- */\r
- public static boolean canConvert(Object fromObj, Class to) {\r
- int weight = NativeJavaObject.getConversionWeight(fromObj, to);\r
-\r
- return (weight < CONVERSION_NONE);\r
- }\r
-\r
- static final int JSTYPE_UNDEFINED = 0; // undefined type\r
- static final int JSTYPE_NULL = 1; // null\r
- static final int JSTYPE_BOOLEAN = 2; // boolean\r
- static final int JSTYPE_NUMBER = 3; // number\r
- static final int JSTYPE_STRING = 4; // string\r
- static final int JSTYPE_JAVA_CLASS = 5; // JavaClass\r
- static final int JSTYPE_JAVA_OBJECT = 6; // JavaObject\r
- static final int JSTYPE_JAVA_ARRAY = 7; // JavaArray\r
- static final int JSTYPE_OBJECT = 8; // Scriptable\r
-\r
- public static final byte CONVERSION_TRIVIAL = 1;\r
- public static final byte CONVERSION_NONTRIVIAL = 0;\r
- public static final byte CONVERSION_NONE = 99;\r
-\r
- /**\r
- * Derive a ranking based on how "natural" the conversion is.\r
- * The special value CONVERSION_NONE means no conversion is possible, \r
- * and CONVERSION_NONTRIVIAL signals that more type conformance testing \r
- * is required.\r
- * Based on \r
- * <a href="http://www.mozilla.org/js/liveconnect/lc3_method_overloading.html">\r
- * "preferred method conversions" from Live Connect 3</a>\r
- */\r
- public static int getConversionWeight(Object fromObj, Class to) {\r
- int fromCode = NativeJavaObject.getJSTypeCode(fromObj);\r
-\r
- int result = CONVERSION_NONE;\r
-\r
- switch (fromCode) {\r
-\r
- case JSTYPE_UNDEFINED:\r
- if (to == ScriptRuntime.StringClass || \r
- to == ScriptRuntime.ObjectClass) {\r
- result = 1;\r
- }\r
- break;\r
-\r
- case JSTYPE_NULL:\r
- if (!to.isPrimitive()) {\r
- result = 1;\r
- }\r
- break;\r
-\r
- case JSTYPE_BOOLEAN:\r
- // "boolean" is #1\r
- if (to == Boolean.TYPE) {\r
- result = 1;\r
- }\r
- else if (to == ScriptRuntime.BooleanClass) {\r
- result = 2;\r
- }\r
- else if (to == ScriptRuntime.ObjectClass) {\r
- result = 3;\r
- }\r
- else if (to == ScriptRuntime.StringClass) {\r
- result = 4;\r
- }\r
- break;\r
-\r
- case JSTYPE_NUMBER:\r
- if (to.isPrimitive()) {\r
- if (to == Double.TYPE) {\r
- result = 1;\r
- }\r
- else if (to != Boolean.TYPE) {\r
- result = 1 + NativeJavaObject.getSizeRank(to);\r
- }\r
- }\r
- else {\r
- if (to == ScriptRuntime.StringClass) {\r
- // native numbers are #1-8\r
- result = 9;\r
- }\r
- else if (to == ScriptRuntime.ObjectClass) {\r
- result = 10;\r
- }\r
- else if (ScriptRuntime.NumberClass.isAssignableFrom(to)) {\r
- // "double" is #1\r
- result = 2;\r
- }\r
- }\r
- break;\r
-\r
- case JSTYPE_STRING:\r
- if (to == ScriptRuntime.StringClass) {\r
- result = 1;\r
- }\r
- else if (to == ScriptRuntime.ObjectClass) {\r
- result = 2;\r
- }\r
- else if (to.isPrimitive() && to != Boolean.TYPE) {\r
- if (to == Character.TYPE) {\r
- result = 3;\r
- }\r
- else {\r
- result = 4;\r
- }\r
- }\r
- break;\r
-\r
- case JSTYPE_JAVA_CLASS:\r
- if (to == ScriptRuntime.ClassClass) {\r
- result = 1;\r
- }\r
- else if (Context.useJSObject && jsObjectClass != null && \r
- jsObjectClass.isAssignableFrom(to)) {\r
- result = 2;\r
- }\r
- else if (to == ScriptRuntime.ObjectClass) {\r
- result = 3;\r
- }\r
- else if (to == ScriptRuntime.StringClass) {\r
- result = 4;\r
- }\r
- break;\r
-\r
- case JSTYPE_JAVA_OBJECT:\r
- case JSTYPE_JAVA_ARRAY:\r
- if (to == ScriptRuntime.StringClass) {\r
- result = 2;\r
- }\r
- else if (to.isPrimitive() && to != Boolean.TYPE) {\r
- result = \r
- (fromCode == JSTYPE_JAVA_ARRAY) ?\r
- CONVERSION_NONTRIVIAL :\r
- 2 + NativeJavaObject.getSizeRank(to);\r
- }\r
- else {\r
- Object javaObj = fromObj;\r
- if (javaObj instanceof Wrapper) {\r
- javaObj = ((Wrapper)javaObj).unwrap();\r
- }\r
- if (to.isInstance(javaObj)) {\r
- result = CONVERSION_NONTRIVIAL;\r
- }\r
- }\r
- break;\r
-\r
- case JSTYPE_OBJECT:\r
- // Other objects takes #1-#3 spots\r
- if (Context.useJSObject && jsObjectClass != null && \r
- jsObjectClass.isAssignableFrom(to)) {\r
- result = 1;\r
- }\r
- else if (fromObj instanceof NativeArray && to.isArray()) {\r
- // This is a native array conversion to a java array\r
- // Array conversions are all equal, and preferable to object \r
- // and string conversion, per LC3.\r
- result = 1;\r
- }\r
- else if (to == ScriptRuntime.ObjectClass) {\r
- result = 2;\r
- }\r
- else if (to == ScriptRuntime.StringClass) {\r
- result = 3;\r
- }\r
- else if (to.isPrimitive() || to != Boolean.TYPE) {\r
- result = 3 + NativeJavaObject.getSizeRank(to);\r
- }\r
- break;\r
- }\r
-\r
- return result;\r
- \r
- }\r
-\r
- static int getSizeRank(Class aType) {\r
- if (aType == Double.TYPE) {\r
- return 1;\r
- }\r
- else if (aType == Float.TYPE) {\r
- return 2;\r
- }\r
- else if (aType == Long.TYPE) {\r
- return 3;\r
- }\r
- else if (aType == Integer.TYPE) {\r
- return 4;\r
- }\r
- else if (aType == Short.TYPE) {\r
- return 5;\r
- }\r
- else if (aType == Character.TYPE) {\r
- return 6;\r
- }\r
- else if (aType == Byte.TYPE) {\r
- return 7;\r
- }\r
- else if (aType == Boolean.TYPE) {\r
- return CONVERSION_NONE;\r
- }\r
- else {\r
- return 8;\r
- }\r
- }\r
-\r
- static int getJSTypeCode(Object value) {\r
- if (value == null) {\r
- return JSTYPE_NULL;\r
- }\r
- else if (value == Undefined.instance) {\r
- return JSTYPE_UNDEFINED;\r
- }\r
- else if (value instanceof Scriptable) {\r
- if (value instanceof NativeJavaClass) {\r
- return JSTYPE_JAVA_CLASS;\r
- }\r
- else if (value instanceof NativeJavaArray) {\r
- return JSTYPE_JAVA_ARRAY;\r
- }\r
- else if (value instanceof NativeJavaObject) {\r
- return JSTYPE_JAVA_OBJECT;\r
- }\r
- else {\r
- return JSTYPE_OBJECT;\r
- }\r
- }\r
- else {\r
- Class valueClass = value.getClass();\r
-\r
- if (valueClass == ScriptRuntime.StringClass) {\r
- return JSTYPE_STRING;\r
- }\r
- else if (valueClass == ScriptRuntime.BooleanClass) {\r
- return JSTYPE_BOOLEAN;\r
- }\r
- else if (value instanceof Number) {\r
- return JSTYPE_NUMBER;\r
- }\r
- else if (valueClass == ScriptRuntime.ClassClass) {\r
- return JSTYPE_JAVA_CLASS;\r
- }\r
- else if (valueClass.isArray()) {\r
- return JSTYPE_JAVA_ARRAY;\r
- }\r
- else {\r
- return JSTYPE_JAVA_OBJECT;\r
- }\r
- }\r
- }\r
-\r
- /**\r
- * Type-munging for field setting and method invocation.\r
- * Conforms to LC3 specification\r
- */\r
- public static Object coerceType(Class type, Object value) {\r
- if (value != null && value.getClass() == type) {\r
- return value;\r
- }\r
- \r
- switch (NativeJavaObject.getJSTypeCode(value)) {\r
-\r
- case JSTYPE_NULL:\r
- // raise error if type.isPrimitive()\r
- if (type.isPrimitive()) {\r
- reportConversionError(value, type);\r
- }\r
- return null;\r
-\r
- case JSTYPE_UNDEFINED:\r
- if (type == ScriptRuntime.StringClass || \r
- type == ScriptRuntime.ObjectClass) {\r
- return "undefined";\r
- }\r
- else {\r
- reportConversionError("undefined", type);\r
- }\r
- break;\r
-\r
- case JSTYPE_BOOLEAN:\r
- // Under LC3, only JS Booleans can be coerced into a Boolean value\r
- if (type == Boolean.TYPE || \r
- type == ScriptRuntime.BooleanClass || \r
- type == ScriptRuntime.ObjectClass) {\r
- return value;\r
- }\r
- else if (type == ScriptRuntime.StringClass) {\r
- return value.toString();\r
- }\r
- else {\r
- reportConversionError(value, type);\r
- }\r
- break;\r
-\r
- case JSTYPE_NUMBER:\r
- if (type == ScriptRuntime.StringClass) {\r
- return ScriptRuntime.toString(value);\r
- }\r
- else if (type == ScriptRuntime.ObjectClass) {\r
- return coerceToNumber(Double.TYPE, value);\r
- }\r
- else if ((type.isPrimitive() && type != Boolean.TYPE) || \r
- ScriptRuntime.NumberClass.isAssignableFrom(type)) {\r
- return coerceToNumber(type, value);\r
- }\r
- else {\r
- reportConversionError(value, type);\r
- }\r
- break;\r
-\r
- case JSTYPE_STRING:\r
- if (type == ScriptRuntime.StringClass ||\r
- type == ScriptRuntime.ObjectClass) {\r
- return value;\r
- }\r
- else if (type == Character.TYPE || \r
- type == ScriptRuntime.CharacterClass) {\r
- // Special case for converting a single char string to a \r
- // character\r
- // Placed here because it applies *only* to JS strings, \r
- // not other JS objects converted to strings\r
- if (((String)value).length() == 1) {\r
- return new Character(((String)value).charAt(0));\r
- }\r
- else {\r
- return coerceToNumber(type, value);\r
- }\r
- }\r
- else if ((type.isPrimitive() && type != Boolean.TYPE) || \r
- ScriptRuntime.NumberClass.isAssignableFrom(type)) {\r
- return coerceToNumber(type, value);\r
- }\r
- else {\r
- reportConversionError(value, type);\r
- }\r
- break;\r
-\r
- case JSTYPE_JAVA_CLASS:\r
- if (Context.useJSObject && jsObjectClass != null && \r
- (type == ScriptRuntime.ObjectClass || \r
- jsObjectClass.isAssignableFrom(type))) {\r
- return coerceToJSObject(type, (Scriptable)value);\r
- }\r
- else {\r
- if (value instanceof Wrapper) {\r
- value = ((Wrapper)value).unwrap();\r
- }\r
-\r
- if (type == ScriptRuntime.ClassClass ||\r
- type == ScriptRuntime.ObjectClass) {\r
- return value;\r
- }\r
- else if (type == ScriptRuntime.StringClass) {\r
- return value.toString();\r
- }\r
- else {\r
- reportConversionError(value, type);\r
- }\r
- }\r
- break;\r
-\r
- case JSTYPE_JAVA_OBJECT:\r
- case JSTYPE_JAVA_ARRAY:\r
- if (type.isPrimitive()) {\r
- if (type == Boolean.TYPE) {\r
- reportConversionError(value, type);\r
- }\r
- return coerceToNumber(type, value);\r
- }\r
- else {\r
- if (value instanceof Wrapper) {\r
- value = ((Wrapper)value).unwrap();\r
- }\r
- if (type == ScriptRuntime.StringClass) {\r
- return value.toString();\r
- }\r
- else {\r
- if (type.isInstance(value)) {\r
- return value;\r
- }\r
- else {\r
- reportConversionError(value, type);\r
- }\r
- }\r
- }\r
- break;\r
-\r
- case JSTYPE_OBJECT:\r
- if (Context.useJSObject && jsObjectClass != null && \r
- (type == ScriptRuntime.ObjectClass || \r
- jsObjectClass.isAssignableFrom(type))) {\r
- return coerceToJSObject(type, (Scriptable)value);\r
- }\r
- else if (type == ScriptRuntime.StringClass) {\r
- return ScriptRuntime.toString(value);\r
- }\r
- else if (type.isPrimitive()) {\r
- if (type == Boolean.TYPE) {\r
- reportConversionError(value, type);\r
- }\r
- return coerceToNumber(type, value);\r
- }\r
- else if (type.isInstance(value)) {\r
- return value;\r
- }\r
- else if (type.isArray() && value instanceof NativeArray) {\r
- // Make a new java array, and coerce the JS array components \r
- // to the target (component) type.\r
- NativeArray array = (NativeArray) value;\r
- long length = array.jsGet_length();\r
- Class arrayType = type.getComponentType();\r
- Object Result = Array.newInstance(arrayType, (int)length);\r
- for (int i = 0 ; i < length ; ++i) {\r
- try {\r
- Array.set(Result, i, coerceType(arrayType, \r
- array.get(i, array)));\r
- }\r
- catch (EvaluatorException ee) {\r
- reportConversionError(value, type);\r
- }\r
- }\r
-\r
- return Result;\r
- }\r
- else if (value instanceof Wrapper) {\r
- value = ((Wrapper)value).unwrap();\r
- if (type.isInstance(value))\r
- return value;\r
- reportConversionError(value, type);\r
- }\r
- else {\r
- reportConversionError(value, type);\r
- }\r
- break;\r
- }\r
-\r
- return value;\r
- }\r
-\r
- static Object coerceToJSObject(Class type, Scriptable value) {\r
- // If JSObject compatibility is enabled, and the method wants it,\r
- // wrap the Scriptable value in a JSObject.\r
-\r
- if (ScriptRuntime.ScriptableClass.isAssignableFrom(type))\r
- return value;\r
-\r
- try {\r
- Object ctorArgs[] = { value };\r
- return jsObjectCtor.newInstance(ctorArgs);\r
- } catch (InstantiationException instEx) {\r
- throw new EvaluatorException("error generating JSObject wrapper for " +\r
- value);\r
- } catch (IllegalArgumentException argEx) {\r
- throw new EvaluatorException("JSObject constructor doesn't want [Scriptable]!");\r
- } catch (InvocationTargetException e) {\r
- throw WrappedException.wrapException(e.getTargetException());\r
- } catch (IllegalAccessException accessEx) {\r
- throw new EvaluatorException("JSObject constructor is protected/private!");\r
- }\r
- }\r
-\r
- static Object coerceToNumber(Class type, Object value) {\r
- Class valueClass = value.getClass();\r
-\r
- // Character\r
- if (type == Character.TYPE || type == ScriptRuntime.CharacterClass) {\r
- if (valueClass == ScriptRuntime.CharacterClass) {\r
- return value;\r
- }\r
- return new Character((char)toInteger(value, \r
- ScriptRuntime.CharacterClass,\r
- (double)Character.MIN_VALUE,\r
- (double)Character.MAX_VALUE));\r
- }\r
-\r
- // Double, Float\r
- if (type == ScriptRuntime.ObjectClass || \r
- type == ScriptRuntime.DoubleClass || type == Double.TYPE) {\r
- return valueClass == ScriptRuntime.DoubleClass\r
- ? value\r
- : new Double(toDouble(value));\r
- }\r
-\r
- if (type == ScriptRuntime.FloatClass || type == Float.TYPE) {\r
- if (valueClass == ScriptRuntime.FloatClass) {\r
- return value;\r
- }\r
- else {\r
- double number = toDouble(value);\r
- if (Double.isInfinite(number) || Double.isNaN(number)\r
- || number == 0.0) {\r
- return new Float((float)number);\r
- }\r
- else {\r
- double absNumber = Math.abs(number);\r
- if (absNumber < (double)Float.MIN_VALUE) {\r
- return new Float((number > 0.0) ? +0.0 : -0.0);\r
- }\r
- else if (absNumber > (double)Float.MAX_VALUE) {\r
- return new Float((number > 0.0) ?\r
- Float.POSITIVE_INFINITY : \r
- Float.NEGATIVE_INFINITY);\r
- }\r
- else {\r
- return new Float((float)number);\r
- }\r
- }\r
- }\r
- }\r
-\r
- // Integer, Long, Short, Byte\r
- if (type == ScriptRuntime.IntegerClass || type == Integer.TYPE) {\r
- if (valueClass == ScriptRuntime.IntegerClass) {\r
- return value;\r
- }\r
- else {\r
- return new Integer((int)toInteger(value, \r
- ScriptRuntime.IntegerClass,\r
- (double)Integer.MIN_VALUE,\r
- (double)Integer.MAX_VALUE));\r
- }\r
- }\r
-\r
- if (type == ScriptRuntime.LongClass || type == Long.TYPE) {\r
- if (valueClass == ScriptRuntime.LongClass) {\r
- return value;\r
- }\r
- else {\r
- /* Long values cannot be expressed exactly in doubles.\r
- * We thus use the largest and smallest double value that \r
- * has a value expressible as a long value. We build these \r
- * numerical values from their hexidecimal representations\r
- * to avoid any problems caused by attempting to parse a\r
- * decimal representation.\r
- */\r
- final double max = Double.longBitsToDouble(0x43dfffffffffffffL);\r
- final double min = Double.longBitsToDouble(0xc3e0000000000000L);\r
- return new Long(toInteger(value, \r
- ScriptRuntime.LongClass,\r
- min,\r
- max));\r
- }\r
- }\r
-\r
- if (type == ScriptRuntime.ShortClass || type == Short.TYPE) {\r
- if (valueClass == ScriptRuntime.ShortClass) {\r
- return value;\r
- }\r
- else {\r
- return new Short((short)toInteger(value, \r
- ScriptRuntime.ShortClass,\r
- (double)Short.MIN_VALUE,\r
- (double)Short.MAX_VALUE));\r
- }\r
- }\r
-\r
- if (type == ScriptRuntime.ByteClass || type == Byte.TYPE) {\r
- if (valueClass == ScriptRuntime.ByteClass) {\r
- return value;\r
- }\r
- else {\r
- return new Byte((byte)toInteger(value, \r
- ScriptRuntime.ByteClass,\r
- (double)Byte.MIN_VALUE,\r
- (double)Byte.MAX_VALUE));\r
- }\r
- }\r
-\r
- return new Double(toDouble(value));\r
- }\r
-\r
-\r
- static double toDouble(Object value) {\r
- if (value instanceof Number) {\r
- return ((Number)value).doubleValue();\r
- }\r
- else if (value instanceof String) {\r
- return ScriptRuntime.toNumber((String)value);\r
- }\r
- else if (value instanceof Scriptable) {\r
- if (value instanceof Wrapper) {\r
- // XXX: optimize tail-recursion?\r
- return toDouble(((Wrapper)value).unwrap());\r
- }\r
- else {\r
- return ScriptRuntime.toNumber(value);\r
- }\r
- }\r
- else {\r
- Method meth;\r
- try {\r
- meth = value.getClass().getMethod("doubleValue", null);\r
- }\r
- catch (NoSuchMethodException e) {\r
- meth = null;\r
- }\r
- catch (SecurityException e) {\r
- meth = null;\r
- }\r
- if (meth != null) {\r
- try {\r
- return ((Number)meth.invoke(value, null)).doubleValue();\r
- }\r
- catch (IllegalAccessException e) {\r
- // XXX: ignore, or error message?\r
- reportConversionError(value, Double.TYPE);\r
- }\r
- catch (InvocationTargetException e) {\r
- // XXX: ignore, or error message?\r
- reportConversionError(value, Double.TYPE);\r
- }\r
- }\r
- return ScriptRuntime.toNumber(value.toString());\r
- }\r
- }\r
-\r
- static long toInteger(Object value, Class type, double min, double max) {\r
- double d = toDouble(value);\r
-\r
- if (Double.isInfinite(d) || Double.isNaN(d)) {\r
- // Convert to string first, for more readable message\r
- reportConversionError(ScriptRuntime.toString(value), type);\r
- }\r
-\r
- if (d > 0.0) {\r
- d = Math.floor(d);\r
- }\r
- else {\r
- d = Math.ceil(d);\r
- }\r
-\r
- if (d < min || d > max) {\r
- // Convert to string first, for more readable message\r
- reportConversionError(ScriptRuntime.toString(value), type);\r
- }\r
- return (long)d;\r
- }\r
-\r
- static void reportConversionError(Object value, Class type) {\r
- throw Context.reportRuntimeError2\r
- ("msg.conversion.not.allowed", \r
- value.toString(), NativeJavaMethod.javaSignature(type));\r
- }\r
-\r
- public static void initJSObject() {\r
- // if netscape.javascript.JSObject is in the CLASSPATH, enable JSObject\r
- // compatability wrappers\r
- jsObjectClass = null;\r
- try {\r
- jsObjectClass = Class.forName("netscape.javascript.JSObject");\r
- Class ctorParms[] = { ScriptRuntime.ScriptableClass };\r
- jsObjectCtor = jsObjectClass.getConstructor(ctorParms);\r
- jsObjectGetScriptable = jsObjectClass.getMethod("getScriptable", \r
- new Class[0]);\r
- } catch (ClassNotFoundException classEx) {\r
- // jsObjectClass already null\r
- } catch (NoSuchMethodException methEx) {\r
- // jsObjectClass already null\r
- }\r
- }\r
- \r
- /**\r
- * The prototype of this object.\r
- */\r
- protected Scriptable prototype;\r
-\r
- /**\r
- * The parent scope of this object.\r
- */\r
- protected Scriptable parent;\r
-\r
- protected Object javaObject;\r
- protected JavaMembers members;\r
- private Hashtable fieldAndMethods;\r
- static Class jsObjectClass;\r
- static Constructor jsObjectCtor;\r
- static Method jsObjectGetScriptable;\r
-}\r
-\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- * Frank Mitchell\r
- * Mike Shaver\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-import java.lang.reflect.*;\r
-\r
-/**\r
- * This class reflects Java packages into the JavaScript environment. We \r
- * lazily reflect classes and subpackages, and use a caching/sharing \r
- * system to ensure that members reflected into one JavaPackage appear\r
- * in all other references to the same package (as with Packages.java.lang \r
- * and java.lang).\r
- *\r
- * @author Mike Shaver\r
- * @see NativeJavaArray\r
- * @see NativeJavaObject\r
- * @see NativeJavaClass\r
- */\r
-\r
-public class NativeJavaPackage extends ScriptableObject {\r
-\r
- // we know these are packages so we can skip the class check\r
- // note that this is ok even if the package isn't present.\r
- static final String[] commonPackages = {\r
- "java.lang",\r
- "java.lang.reflect",\r
- "java.io",\r
- "java.math",\r
- "java.util",\r
- "java.util.zip",\r
- "java.text",\r
- "java.text.resources",\r
- "java.applet",\r
- };\r
-\r
- public static Scriptable init(Scriptable scope) \r
- throws PropertyException\r
- {\r
- NativeJavaPackage packages = new NativeJavaPackage("");\r
- packages.setPrototype(getObjectPrototype(scope));\r
- packages.setParentScope(scope);\r
-\r
- // We want to get a real alias, and not a distinct JavaPackage\r
- // with the same packageName, so that we share classes and packages\r
- // that are underneath.\r
- NativeJavaPackage javaAlias = (NativeJavaPackage)packages.get("java",\r
- packages);\r
-\r
- // It's safe to downcast here since initStandardObjects takes\r
- // a ScriptableObject.\r
- ScriptableObject global = (ScriptableObject) scope;\r
-\r
- global.defineProperty("Packages", packages, ScriptableObject.DONTENUM);\r
- global.defineProperty("java", javaAlias, ScriptableObject.DONTENUM);\r
-\r
- for (int i = 0; i < commonPackages.length; i++)\r
- packages.forcePackage(commonPackages[i]);\r
-\r
- if (Context.useJSObject)\r
- NativeJavaObject.initJSObject();\r
- \r
- Method[] m = FunctionObject.findMethods(NativeJavaPackage.class, \r
- "jsFunction_getClass");\r
- FunctionObject f = new FunctionObject("getClass", m[0], global);\r
- global.defineProperty("getClass", f, ScriptableObject.DONTENUM);\r
-\r
- // I think I'm supposed to return the prototype, but I don't have one.\r
- return packages;\r
- }\r
-\r
- // set up a name which is known to be a package so we don't\r
- // need to look for a class by that name\r
- void forcePackage(String name) {\r
- NativeJavaPackage pkg;\r
- int end = name.indexOf('.');\r
- if (end == -1)\r
- end = name.length();\r
-\r
- String id = name.substring(0, end);\r
- Object cached = super.get(id, this);\r
- if (cached != null && cached instanceof NativeJavaPackage) {\r
- pkg = (NativeJavaPackage) cached;\r
- } else {\r
- String newPackage = packageName.length() == 0 \r
- ? id \r
- : packageName + "." + id;\r
- pkg = new NativeJavaPackage(newPackage);\r
- pkg.setParentScope(this);\r
- pkg.setPrototype(this.prototype);\r
- super.put(id, this, pkg);\r
- }\r
- if (end < name.length())\r
- pkg.forcePackage(name.substring(end+1));\r
- }\r
-\r
- public NativeJavaPackage(String packageName) {\r
- this.packageName = packageName;\r
- }\r
-\r
- public String getClassName() {\r
- return "JavaPackage";\r
- }\r
-\r
- public boolean has(String id, int index, Scriptable start) {\r
- return true;\r
- }\r
-\r
- public void put(String id, Scriptable start, Object value) {\r
- // Can't add properties to Java packages. Sorry.\r
- }\r
-\r
- public void put(int index, Scriptable start, Object value) {\r
- throw Context.reportRuntimeError0("msg.pkg.int");\r
- }\r
-\r
- public Object get(String id, Scriptable start) {\r
- return getPkgProperty(id, start, true);\r
- }\r
-\r
- public Object get(int index, Scriptable start) {\r
- return NOT_FOUND;\r
- }\r
-\r
- synchronized Object getPkgProperty(String name, Scriptable start,\r
- boolean createPkg) \r
- {\r
- Object cached = super.get(name, start);\r
- if (cached != NOT_FOUND)\r
- return cached;\r
- \r
- String newPackage = packageName.length() == 0\r
- ? name \r
- : packageName + "." + name;\r
- Context cx = Context.getContext();\r
- SecuritySupport ss = cx.getSecuritySupport();\r
- Scriptable newValue;\r
- try {\r
- /*\r
- if (ss != null && !ss.visibleToScripts(newPackage))\r
- */\r
- throw new ClassNotFoundException();\r
- /*\r
- Class newClass = ScriptRuntime.loadClassName(newPackage);\r
- newValue = NativeJavaClass.wrap(getTopLevelScope(this), newClass);\r
- newValue.setParentScope(this);\r
- newValue.setPrototype(this.prototype);\r
- */\r
- } catch (ClassNotFoundException ex) {\r
- if (createPkg) {\r
- NativeJavaPackage pkg = new NativeJavaPackage(newPackage);\r
- pkg.setParentScope(this);\r
- pkg.setPrototype(this.prototype);\r
- newValue = pkg;\r
- } else {\r
- newValue = null;\r
- }\r
- }\r
- if (newValue != null) {\r
- // Make it available for fast lookup and sharing of \r
- // lazily-reflected constructors and static members.\r
- super.put(name, start, newValue);\r
- }\r
- return newValue;\r
- }\r
-\r
- public Object getDefaultValue(Class ignored) {\r
- return toString();\r
- }\r
-\r
- public String toString() {\r
- return "[JavaPackage " + packageName + "]";\r
- }\r
- \r
- public static Scriptable jsFunction_getClass(Context cx, \r
- Scriptable thisObj,\r
- Object[] args, \r
- Function funObj)\r
- {\r
- if (args.length > 0 && args[0] instanceof Wrapper) {\r
- Scriptable result = getTopLevelScope(thisObj);\r
- Class cl = ((Wrapper) args[0]).unwrap().getClass();\r
- // Evaluate the class name by getting successive properties of \r
- // the string to find the appropriate NativeJavaClass object\r
- String name = "Packages." + cl.getName();\r
- int offset = 0;\r
- for (;;) {\r
- int index = name.indexOf('.', offset);\r
- String propName = index == -1\r
- ? name.substring(offset)\r
- : name.substring(offset, index);\r
- Object prop = result.get(propName, result);\r
- if (!(prop instanceof Scriptable)) \r
- break; // fall through to error\r
- result = (Scriptable) prop;\r
- if (index == -1)\r
- return result;\r
- offset = index+1;\r
- }\r
- }\r
- throw Context.reportRuntimeError(\r
- Context.getMessage0("msg.not.java.obj"));\r
- }\r
-\r
- private String packageName;\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 4; indent-tabs-mode: 1; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s):\r
- * Norris Boyd\r
- * Igor Bukanov\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-/**\r
- * This class implements the Math native object.\r
- * See ECMA 15.8.\r
- * @author Norris Boyd\r
- */\r
-\r
-public class NativeMath extends IdScriptable\r
-{\r
- public static void init(Context cx, Scriptable scope, boolean sealed) {\r
- NativeMath obj = new NativeMath();\r
- obj.setSealFunctionsFlag(sealed);\r
- obj.setFunctionParametrs(cx);\r
- obj.setPrototype(getObjectPrototype(scope));\r
- obj.setParentScope(scope);\r
- if (sealed) { obj.sealObject(); }\r
- ScriptableObject.defineProperty(scope, "Math", obj,\r
- ScriptableObject.DONTENUM);\r
- }\r
-\r
- public String getClassName() { return "Math"; }\r
-\r
- protected int getIdDefaultAttributes(int id) {\r
- if (id > LAST_METHOD_ID) {\r
- return DONTENUM | READONLY | PERMANENT;\r
- }\r
- return super.getIdDefaultAttributes(id);\r
- }\r
-\r
- protected Object getIdValue(int id) {\r
- if (id > LAST_METHOD_ID) {\r
- return cacheIdValue(id, wrap_double(getField(id)));\r
- }\r
- return super.getIdValue(id);\r
- }\r
-\r
- private double getField(int fieldId) {\r
- switch (fieldId) {\r
- case Id_E: return E;\r
- case Id_PI: return PI;\r
- case Id_LN10: return LN10;\r
- case Id_LN2: return LN2;\r
- case Id_LOG2E: return LOG2E;\r
- case Id_LOG10E: return LOG10E;\r
- case Id_SQRT1_2: return SQRT1_2;\r
- case Id_SQRT2: return SQRT2;\r
- }\r
- return 0; // Unreachable\r
- }\r
-\r
- public int methodArity(int methodId) {\r
- switch (methodId) {\r
- case Id_abs: return 1;\r
- case Id_acos: return 1;\r
- case Id_asin: return 1;\r
- case Id_atan: return 1;\r
- case Id_atan2: return 2;\r
- case Id_ceil: return 1;\r
- case Id_cos: return 1;\r
- case Id_exp: return 1;\r
- case Id_floor: return 1;\r
- case Id_log: return 1;\r
- case Id_max: return 2;\r
- case Id_min: return 2;\r
- case Id_pow: return 2;\r
- case Id_random: return 0;\r
- case Id_round: return 1;\r
- case Id_sin: return 1;\r
- case Id_sqrt: return 1;\r
- case Id_tan: return 1;\r
- }\r
- return super.methodArity(methodId);\r
- }\r
-\r
- public Object execMethod\r
- (int methodId, IdFunction f,\r
- Context cx, Scriptable scope, Scriptable thisObj, Object[] args)\r
- throws JavaScriptException\r
- {\r
- switch (methodId) {\r
- case Id_abs: return wrap_double\r
- (js_abs(ScriptRuntime.toNumber(args, 0)));\r
-\r
- case Id_acos: return wrap_double\r
- (js_acos(ScriptRuntime.toNumber(args, 0)));\r
-\r
- case Id_asin: return wrap_double\r
- (js_asin(ScriptRuntime.toNumber(args, 0)));\r
-\r
- case Id_atan: return wrap_double\r
- (js_atan(ScriptRuntime.toNumber(args, 0)));\r
-\r
- case Id_atan2: return wrap_double\r
- (js_atan2(ScriptRuntime.toNumber(args, 0),\r
- ScriptRuntime.toNumber(args, 1)));\r
-\r
- case Id_ceil: return wrap_double\r
- (js_ceil(ScriptRuntime.toNumber(args, 0)));\r
-\r
- case Id_cos: return wrap_double\r
- (js_cos(ScriptRuntime.toNumber(args, 0)));\r
-\r
- case Id_exp: return wrap_double\r
- (js_exp(ScriptRuntime.toNumber(args, 0)));\r
-\r
- case Id_floor: return wrap_double\r
- (js_floor(ScriptRuntime.toNumber(args, 0)));\r
-\r
- case Id_log: return wrap_double\r
- (js_log(ScriptRuntime.toNumber(args, 0)));\r
-\r
- case Id_max: return wrap_double\r
- (js_max(args));\r
-\r
- case Id_min: return wrap_double\r
- (js_min(args));\r
-\r
- case Id_pow: return wrap_double\r
- (js_pow(ScriptRuntime.toNumber(args, 0),\r
- ScriptRuntime.toNumber(args, 1)));\r
-\r
- case Id_random: return wrap_double\r
- (js_random());\r
-\r
- case Id_round: return wrap_double\r
- (js_round(ScriptRuntime.toNumber(args, 0)));\r
-\r
- case Id_sin: return wrap_double\r
- (js_sin(ScriptRuntime.toNumber(args, 0)));\r
-\r
- case Id_sqrt: return wrap_double\r
- (js_sqrt(ScriptRuntime.toNumber(args, 0)));\r
-\r
- case Id_tan: return wrap_double\r
- (js_tan(ScriptRuntime.toNumber(args, 0)));\r
- }\r
- return super.execMethod(methodId, f, cx, scope, thisObj, args);\r
- }\r
-\r
- private double js_abs(double x) {\r
- // abs(-0.0) should be 0.0, but -0.0 < 0.0 == false\r
- return (x == 0.0) ? 0.0 : (x < 0.0) ? -x : x;\r
- }\r
-\r
- private double js_acos(double x) {\r
- return (x == x && -1.0 <= x && x <= 1.0) ? Math.acos(x) : Double.NaN;\r
- }\r
-\r
- private double js_asin(double x) {\r
- return (x == x && -1.0 <= x && x <= 1.0) ? Math.asin(x) : Double.NaN;\r
- }\r
-\r
- private double js_atan(double x) { return Math.atan(x); }\r
-\r
- private double js_atan2(double x, double y) { return Math.atan2(x, y); }\r
-\r
- private double js_ceil(double x) { return Math.ceil(x); }\r
-\r
- private double js_cos(double x) { return Math.cos(x); }\r
-\r
- private double js_exp(double x) {\r
- return (x == Double.POSITIVE_INFINITY) ? x\r
- : (x == Double.NEGATIVE_INFINITY) ? 0.0\r
- : Math.exp(x);\r
- }\r
-\r
- private double js_floor(double x) { return Math.floor(x); }\r
-\r
- private double js_log(double x) {\r
- // Java's log(<0) = -Infinity; we need NaN\r
- return (x < 0) ? Double.NaN : Math.log(x);\r
- }\r
-\r
- private double js_max(Object[] args) {\r
- double result = Double.NEGATIVE_INFINITY;\r
- if (args.length == 0)\r
- return result;\r
- for (int i = 0; i < args.length; i++) {\r
- double d = ScriptRuntime.toNumber(args[i]);\r
- if (d != d) return d;\r
- // if (result < d) result = d; does not work due to -0.0 >= +0.0\r
- result = Math.max(result, d);\r
- }\r
- return result;\r
- }\r
-\r
- private double js_min(Object[] args) {\r
- double result = Double.POSITIVE_INFINITY;\r
- if (args.length == 0)\r
- return result;\r
- for (int i = 0; i < args.length; i++) {\r
- double d = ScriptRuntime.toNumber(args[i]);\r
- if (d != d) return d;\r
- // if (result > d) result = d; does not work due to -0.0 >= +0.0\r
- result = Math.min(result, d);\r
- }\r
- return result;\r
- }\r
-\r
- private double js_pow(double x, double y) {\r
- if (y == 0) return 1.0; // Java's pow(NaN, 0) = NaN; we need 1\r
- if ((x == 0) && (y < 0)) {\r
- if (1 / x > 0) {\r
- // x is +0, Java is -oo, we need +oo\r
- return Double.POSITIVE_INFINITY;\r
- }\r
- /* if x is -0 and y is an odd integer, -oo */\r
- int y_int = (int)y;\r
- if (y_int == y && (y_int & 0x1) != 0)\r
- return Double.NEGATIVE_INFINITY;\r
- return Double.POSITIVE_INFINITY;\r
- }\r
- return Math.pow(x, y);\r
- }\r
-\r
- private double js_random() { return Math.random(); }\r
-\r
- private double js_round(double d) {\r
- if (d != d)\r
- return d; // NaN\r
- if (d == Double.POSITIVE_INFINITY || d == Double.NEGATIVE_INFINITY)\r
- return d;\r
- long l = Math.round(d);\r
- if (l == 0) {\r
- // We must propagate the sign of d into the result\r
- if (d < 0.0)\r
- return ScriptRuntime.negativeZero;\r
- return d == 0.0 ? d : 0.0;\r
- }\r
- return (double) l;\r
- }\r
-\r
- private double js_sin(double x) { return Math.sin(x); }\r
-\r
- private double js_sqrt(double x) { return Math.sqrt(x); }\r
-\r
- private double js_tan(double x) { return Math.tan(x); }\r
-\r
- protected int maxInstanceId() { return MAX_INSTANCE_ID; }\r
-\r
- protected String getIdName(int id) {\r
- switch (id) {\r
- case Id_abs: return "abs";\r
- case Id_acos: return "acos";\r
- case Id_asin: return "asin";\r
- case Id_atan: return "atan";\r
- case Id_atan2: return "atan2";\r
- case Id_ceil: return "ceil";\r
- case Id_cos: return "cos";\r
- case Id_exp: return "exp";\r
- case Id_floor: return "floor";\r
- case Id_log: return "log";\r
- case Id_max: return "max";\r
- case Id_min: return "min";\r
- case Id_pow: return "pow";\r
- case Id_random: return "random";\r
- case Id_round: return "round";\r
- case Id_sin: return "sin";\r
- case Id_sqrt: return "sqrt";\r
- case Id_tan: return "tan";\r
-\r
- case Id_E: return "E";\r
- case Id_PI: return "PI";\r
- case Id_LN10: return "LN10";\r
- case Id_LN2: return "LN2";\r
- case Id_LOG2E: return "LOG2E";\r
- case Id_LOG10E: return "LOG10E";\r
- case Id_SQRT1_2: return "SQRT1_2";\r
- case Id_SQRT2: return "SQRT2";\r
- }\r
- return null;\r
- }\r
-\r
-// #string_id_map#\r
-\r
- protected int mapNameToId(String s) {\r
- int id;\r
-// #generated# Last update: 2001-03-23 13:50:14 GMT+01:00\r
- L0: { id = 0; String X = null; int c;\r
- L: switch (s.length()) {\r
- case 1: if (s.charAt(0)=='E') {id=Id_E; break L0;} break L;\r
- case 2: if (s.charAt(0)=='P' && s.charAt(1)=='I') {id=Id_PI; break L0;} break L;\r
- case 3: switch (s.charAt(0)) {\r
- case 'L': if (s.charAt(2)=='2' && s.charAt(1)=='N') {id=Id_LN2; break L0;} break L;\r
- case 'a': if (s.charAt(2)=='s' && s.charAt(1)=='b') {id=Id_abs; break L0;} break L;\r
- case 'c': if (s.charAt(2)=='s' && s.charAt(1)=='o') {id=Id_cos; break L0;} break L;\r
- case 'e': if (s.charAt(2)=='p' && s.charAt(1)=='x') {id=Id_exp; break L0;} break L;\r
- case 'l': if (s.charAt(2)=='g' && s.charAt(1)=='o') {id=Id_log; break L0;} break L;\r
- case 'm': c=s.charAt(2);\r
- if (c=='n') { if (s.charAt(1)=='i') {id=Id_min; break L0;} }\r
- else if (c=='x') { if (s.charAt(1)=='a') {id=Id_max; break L0;} }\r
- break L;\r
- case 'p': if (s.charAt(2)=='w' && s.charAt(1)=='o') {id=Id_pow; break L0;} break L;\r
- case 's': if (s.charAt(2)=='n' && s.charAt(1)=='i') {id=Id_sin; break L0;} break L;\r
- case 't': if (s.charAt(2)=='n' && s.charAt(1)=='a') {id=Id_tan; break L0;} break L;\r
- } break L;\r
- case 4: switch (s.charAt(1)) {\r
- case 'N': X="LN10";id=Id_LN10; break L;\r
- case 'c': X="acos";id=Id_acos; break L;\r
- case 'e': X="ceil";id=Id_ceil; break L;\r
- case 'q': X="sqrt";id=Id_sqrt; break L;\r
- case 's': X="asin";id=Id_asin; break L;\r
- case 't': X="atan";id=Id_atan; break L;\r
- } break L;\r
- case 5: switch (s.charAt(0)) {\r
- case 'L': X="LOG2E";id=Id_LOG2E; break L;\r
- case 'S': X="SQRT2";id=Id_SQRT2; break L;\r
- case 'a': X="atan2";id=Id_atan2; break L;\r
- case 'f': X="floor";id=Id_floor; break L;\r
- case 'r': X="round";id=Id_round; break L;\r
- } break L;\r
- case 6: c=s.charAt(0);\r
- if (c=='L') { X="LOG10E";id=Id_LOG10E; }\r
- else if (c=='r') { X="random";id=Id_random; }\r
- break L;\r
- case 7: X="SQRT1_2";id=Id_SQRT1_2; break L;\r
- }\r
- if (X!=null && X!=s && !X.equals(s)) id = 0;\r
- }\r
-// #/generated#\r
- return id;\r
- }\r
-\r
- private static final int\r
- Id_abs = 1,\r
- Id_acos = 2,\r
- Id_asin = 3,\r
- Id_atan = 4,\r
- Id_atan2 = 5,\r
- Id_ceil = 6,\r
- Id_cos = 7,\r
- Id_exp = 8,\r
- Id_floor = 9,\r
- Id_log = 10,\r
- Id_max = 11,\r
- Id_min = 12,\r
- Id_pow = 13,\r
- Id_random = 14,\r
- Id_round = 15,\r
- Id_sin = 16,\r
- Id_sqrt = 17,\r
- Id_tan = 18,\r
-\r
- LAST_METHOD_ID = 18,\r
-\r
- Id_E = 19,\r
- Id_PI = 20,\r
- Id_LN10 = 21,\r
- Id_LN2 = 22,\r
- Id_LOG2E = 23,\r
- Id_LOG10E = 24,\r
- Id_SQRT1_2 = 25,\r
- Id_SQRT2 = 26,\r
-\r
- MAX_INSTANCE_ID = 26;\r
-\r
-// #/string_id_map#\r
-\r
- private static final double\r
- E = Math.E,\r
- PI = Math.PI,\r
- LN10 = 2.302585092994046,\r
- LN2 = 0.6931471805599453,\r
- LOG2E = 1.4426950408889634,\r
- LOG10E = 0.4342944819032518,\r
- SQRT1_2 = 0.7071067811865476,\r
- SQRT2 = 1.4142135623730951;\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s):\r
- * Norris Boyd\r
- * Igor Bukanov\r
- * Mike McCabe\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-/**\r
- * This class implements the Number native object.\r
- *\r
- * See ECMA 15.7.\r
- *\r
- * @author Norris Boyd\r
- */\r
-public class NativeNumber extends IdScriptable {\r
-\r
- private static final int MAX_PRECISION = 100;\r
-\r
- public static void init(Context cx, Scriptable scope, boolean sealed) {\r
- NativeNumber obj = new NativeNumber();\r
- obj.prototypeFlag = true;\r
- obj.addAsPrototype(MAX_PROTOTYPE_ID, cx, scope, sealed);\r
- }\r
-\r
- /**\r
- * Zero-parameter constructor: just used to create Number.prototype\r
- */\r
- public NativeNumber() {\r
- doubleValue = defaultValue;\r
- }\r
-\r
- public NativeNumber(double number) {\r
- doubleValue = number;\r
- }\r
-\r
- public String getClassName() {\r
- return "Number";\r
- }\r
-\r
- protected void fillConstructorProperties\r
- (Context cx, IdFunction ctor, boolean sealed)\r
- {\r
- final int attr = ScriptableObject.DONTENUM |\r
- ScriptableObject.PERMANENT |\r
- ScriptableObject.READONLY;\r
-\r
- ctor.defineProperty("NaN", wrap_double(ScriptRuntime.NaN), attr);\r
- ctor.defineProperty("POSITIVE_INFINITY",\r
- wrap_double(Double.POSITIVE_INFINITY), attr);\r
- ctor.defineProperty("NEGATIVE_INFINITY",\r
- wrap_double(Double.NEGATIVE_INFINITY), attr);\r
- ctor.defineProperty("MAX_VALUE", wrap_double(Double.MAX_VALUE), attr);\r
- ctor.defineProperty("MIN_VALUE", wrap_double(Double.MIN_VALUE), attr);\r
-\r
- super.fillConstructorProperties(cx, ctor, sealed);\r
- }\r
- \r
- public int methodArity(int methodId) {\r
- if (prototypeFlag) {\r
- switch (methodId) {\r
- case Id_constructor: return 1; \r
- case Id_toString: return 1; \r
- case Id_valueOf: return 0; \r
- case Id_toLocaleString: return 1; \r
- case Id_toFixed: return 1;\r
- case Id_toExponential: return 1;\r
- case Id_toPrecision: return 1;\r
- }\r
- }\r
- return super.methodArity(methodId);\r
- }\r
-\r
- public Object execMethod\r
- (int methodId, IdFunction f,\r
- Context cx, Scriptable scope, Scriptable thisObj, Object[] args)\r
- throws JavaScriptException\r
- {\r
- if (prototypeFlag) {\r
- switch (methodId) {\r
- case Id_constructor:\r
- return jsConstructor(args, thisObj == null);\r
-\r
- case Id_toString: return realThis(thisObj, f).\r
- jsFunction_toString(toBase(args, 0));\r
-\r
- case Id_valueOf: return wrap_double(realThis(thisObj, f).\r
- jsFunction_valueOf());\r
-\r
- case Id_toLocaleString: return realThis(thisObj, f).\r
- jsFunction_toLocaleString(toBase(args, 0));\r
-\r
- case Id_toFixed: return realThis(thisObj, f).\r
- jsFunction_toFixed(cx, args);\r
-\r
- case Id_toExponential: return realThis(thisObj, f).\r
- jsFunction_toExponential(cx, args);\r
-\r
- case Id_toPrecision:return realThis(thisObj, f).\r
- jsFunction_toPrecision(cx, args);\r
- }\r
- }\r
- return super.execMethod(methodId, f, cx, scope, thisObj, args);\r
- }\r
-\r
- private NativeNumber realThis(Scriptable thisObj, IdFunction f) {\r
- while (!(thisObj instanceof NativeNumber)) {\r
- thisObj = nextInstanceCheck(thisObj, f, true);\r
- }\r
- return (NativeNumber)thisObj;\r
- }\r
-\r
- private static int toBase(Object[] args, int index) {\r
- return (index < args.length) ? ScriptRuntime.toInt32(args[index]) : 10;\r
- }\r
-\r
- private Object jsConstructor(Object[] args, boolean inNewExpr) {\r
- double d = args.length >= 1\r
- ? ScriptRuntime.toNumber(args[0])\r
- : defaultValue;\r
- if (inNewExpr) {\r
- // new Number(val) creates a new Number object.\r
- return new NativeNumber(d);\r
- }\r
- // Number(val) converts val to a number value.\r
- return wrap_double(d);\r
- }\r
-\r
- public String toString() {\r
- return jsFunction_toString(10);\r
- }\r
-\r
- private String jsFunction_toString(int base) {\r
- return ScriptRuntime.numberToString(doubleValue, base);\r
- }\r
-\r
- private double jsFunction_valueOf() {\r
- return doubleValue;\r
- }\r
-\r
- private String jsFunction_toLocaleString(int base) {\r
- return jsFunction_toString(base);\r
- }\r
-\r
- private String jsFunction_toFixed(Context cx, Object[] args) {\r
- /* We allow a larger range of precision than\r
- ECMA requires; this is permitted by ECMA. */\r
- return num_to(cx, args, DToA.DTOSTR_FIXED, DToA.DTOSTR_FIXED,\r
- -20, MAX_PRECISION, 0);\r
- }\r
-\r
- private String jsFunction_toExponential(Context cx, Object[] args) {\r
- /* We allow a larger range of precision than\r
- ECMA requires; this is permitted by ECMA. */\r
- return num_to(cx, args,\r
- DToA.DTOSTR_STANDARD_EXPONENTIAL,\r
- DToA.DTOSTR_EXPONENTIAL,\r
- 0, MAX_PRECISION, 1);\r
- }\r
-\r
- private String jsFunction_toPrecision(Context cx, Object[] args) {\r
- /* We allow a larger range of precision than\r
- ECMA requires; this is permitted by ECMA. */\r
- return num_to(cx, args, DToA.DTOSTR_STANDARD, DToA.DTOSTR_PRECISION,\r
- 1, MAX_PRECISION, 0);\r
- }\r
-\r
- private String num_to(Context cx, Object[] args,\r
- int zeroArgMode, int oneArgMode,\r
- int precisionMin, int precisionMax,\r
- int precisionOffset)\r
- {\r
- int precision;\r
-\r
- if (args.length == 0) {\r
- precision = 0;\r
- oneArgMode = zeroArgMode;\r
- } else {\r
- precision = ScriptRuntime.toInt32(args[0]);\r
- if (precision < precisionMin || precision > precisionMax) {\r
- String msg = ScriptRuntime.getMessage1(\r
- "msg.bad.precision", ScriptRuntime.toString(args[0]));\r
- throw NativeGlobal.constructError(cx, "RangeError", msg, this);\r
- }\r
- }\r
- StringBuffer result = new StringBuffer();\r
- DToA.JS_dtostr(result, oneArgMode, precision + precisionOffset,\r
- doubleValue);\r
- return result.toString();\r
- }\r
-\r
- protected String getIdName(int id) {\r
- if (prototypeFlag) {\r
- switch (id) {\r
- case Id_constructor: return "constructor"; \r
- case Id_toString: return "toString"; \r
- case Id_valueOf: return "valueOf"; \r
- case Id_toLocaleString: return "toLocaleString"; \r
- case Id_toFixed: return "toFixed";\r
- case Id_toExponential: return "toExponential";\r
- case Id_toPrecision: return "toPrecision";\r
- }\r
- }\r
- return null; \r
- }\r
-\r
-// #string_id_map#\r
-\r
- protected int mapNameToId(String s) {\r
- if (!prototypeFlag) { return 0; }\r
- int id;\r
-// #generated# Last update: 2001-04-23 10:40:45 CEST\r
- L0: { id = 0; String X = null; int c;\r
- L: switch (s.length()) {\r
- case 7: c=s.charAt(0);\r
- if (c=='t') { X="toFixed";id=Id_toFixed; }\r
- else if (c=='v') { X="valueOf";id=Id_valueOf; }\r
- break L;\r
- case 8: X="toString";id=Id_toString; break L;\r
- case 11: c=s.charAt(0);\r
- if (c=='c') { X="constructor";id=Id_constructor; }\r
- else if (c=='t') { X="toPrecision";id=Id_toPrecision; }\r
- break L;\r
- case 13: X="toExponential";id=Id_toExponential; break L;\r
- case 14: X="toLocaleString";id=Id_toLocaleString; break L;\r
- }\r
- if (X!=null && X!=s && !X.equals(s)) id = 0;\r
- }\r
-// #/generated#\r
- return id;\r
- }\r
-\r
- private static final int\r
- Id_constructor = 1,\r
- Id_toString = 2,\r
- Id_valueOf = 3,\r
- Id_toLocaleString = 4,\r
- Id_toFixed = 5,\r
- Id_toExponential = 6,\r
- Id_toPrecision = 7,\r
- MAX_PROTOTYPE_ID = 7;\r
-\r
-// #/string_id_map#\r
-\r
- private static final double defaultValue = +0.0;\r
- private double doubleValue;\r
-\r
- private boolean prototypeFlag;\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s):\r
- * Norris Boyd\r
- * Mike McCabe\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-import java.util.Hashtable;\r
-\r
-/**\r
- * This class implements the Object native object.\r
- * See ECMA 15.2.\r
- * @author Norris Boyd\r
- */\r
-public class NativeObject extends IdScriptable {\r
-\r
- public static void init(Context cx, Scriptable scope, boolean sealed) {\r
- NativeObject obj = new NativeObject();\r
- obj.prototypeFlag = true;\r
- obj.addAsPrototype(MAX_PROTOTYPE_ID, cx, scope, sealed);\r
- }\r
-\r
- public String getClassName() {\r
- return "Object";\r
- }\r
-\r
- public int methodArity(int methodId) {\r
- if (prototypeFlag) {\r
- switch (methodId) {\r
- case Id_constructor: return 1;\r
- case Id_toString: return 0;\r
- case Id_toLocaleString: return 0;\r
- case Id_valueOf: return 0;\r
- case Id_hasOwnProperty: return 1;\r
- case Id_propertyIsEnumerable: return 1;\r
- case Id_isPrototypeOf: return 1;\r
- }\r
- }\r
- return super.methodArity(methodId);\r
- }\r
-\r
- public Object execMethod\r
- (int methodId, IdFunction f,\r
- Context cx, Scriptable scope, Scriptable thisObj, Object[] args)\r
- throws JavaScriptException\r
- {\r
- if (prototypeFlag) {\r
- switch (methodId) {\r
- case Id_constructor:\r
- return jsConstructor(cx, args, f, thisObj == null);\r
-\r
- case Id_toString:\r
- return jsFunction_toString(cx, thisObj);\r
-\r
- case Id_toLocaleString:\r
- return jsFunction_toLocaleString(cx, thisObj);\r
-\r
- case Id_valueOf:\r
- return jsFunction_valueOf(thisObj);\r
-\r
- case Id_hasOwnProperty:\r
- return jsFunction_hasOwnProperty(thisObj, args);\r
-\r
- case Id_propertyIsEnumerable:\r
- return jsFunction_propertyIsEnumerable(cx, thisObj, args);\r
-\r
- case Id_isPrototypeOf:\r
- return jsFunction_isPrototypeOf(cx, thisObj, args);\r
- }\r
- }\r
- return super.execMethod(methodId, f, cx, scope, thisObj, args);\r
- }\r
-\r
- private static Object jsConstructor(Context cx, Object[] args,\r
- Function ctorObj, boolean inNewExpr)\r
- throws JavaScriptException\r
- {\r
- if (!inNewExpr) {\r
- // FunctionObject.construct will set up parent, proto\r
- return ctorObj.construct(cx, ctorObj.getParentScope(), args);\r
- }\r
- if (args.length == 0 || args[0] == null ||\r
- args[0] == Undefined.instance)\r
- {\r
- return new NativeObject();\r
- }\r
- return ScriptRuntime.toObject(ctorObj.getParentScope(), args[0]);\r
- }\r
-\r
- public String toString() {\r
- Context cx = Context.getCurrentContext();\r
- if (cx != null)\r
- return jsFunction_toString(cx, this);\r
- else\r
- return "[object " + getClassName() + "]";\r
- }\r
-\r
- private static String jsFunction_toString(Context cx, Scriptable thisObj)\r
- {\r
- if (cx.getLanguageVersion() != cx.VERSION_1_2)\r
- return "[object " + thisObj.getClassName() + "]";\r
-\r
- return toSource(cx, thisObj);\r
- }\r
-\r
- private static String jsFunction_toLocaleString(Context cx,\r
- Scriptable thisObj)\r
- {\r
- return jsFunction_toString(cx, thisObj);\r
- }\r
-\r
- private static String toSource(Context cx, Scriptable thisObj)\r
- {\r
- Scriptable m = thisObj;\r
-\r
- if (cx.iterating == null)\r
- cx.iterating = new Hashtable(31);\r
-\r
- if (cx.iterating.get(m) == Boolean.TRUE) {\r
- return "{}"; // stop recursion\r
- } else {\r
- StringBuffer result = new StringBuffer("{");\r
- Object[] ids = m.getIds();\r
-\r
- for(int i=0; i < ids.length; i++) {\r
- if (i > 0)\r
- result.append(", ");\r
-\r
- Object id = ids[i];\r
- String idString = ScriptRuntime.toString(id);\r
- Object p = (id instanceof String)\r
- ? m.get((String) id, m)\r
- : m.get(((Number) id).intValue(), m);\r
- if (p instanceof String) {\r
- result.append(idString + ":\""\r
- + ScriptRuntime\r
- .escapeString(ScriptRuntime.toString(p))\r
- + "\"");\r
- } else {\r
- /* wrap changes to cx.iterating in a try/finally\r
- * so that the reference always gets removed, and\r
- * we don't leak memory. Good place for weak\r
- * references, if we had them.\r
- */\r
- try {\r
- cx.iterating.put(m, Boolean.TRUE); // stop recursion.\r
- result.append(idString + ":" + ScriptRuntime.toString(p));\r
- } finally {\r
- cx.iterating.remove(m);\r
- }\r
- }\r
- }\r
- result.append('}');\r
- return result.toString();\r
- }\r
- }\r
-\r
- private static Object jsFunction_valueOf(Scriptable thisObj) {\r
- return thisObj;\r
- }\r
-\r
- private static Object jsFunction_hasOwnProperty(Scriptable thisObj,\r
- Object[] args)\r
- {\r
- if (args.length != 0) {\r
- if (thisObj.has(ScriptRuntime.toString(args[0]), thisObj))\r
- return Boolean.TRUE;\r
- }\r
- return Boolean.FALSE;\r
- }\r
-\r
- private static Object jsFunction_propertyIsEnumerable(Context cx,\r
- Scriptable thisObj,\r
- Object[] args)\r
- {\r
- try {\r
- if (args.length != 0) {\r
- String name = ScriptRuntime.toString(args[0]);\r
- if (thisObj.has(name, thisObj)) {\r
- int a = ((ScriptableObject)thisObj).getAttributes(name, thisObj);\r
- if ((a & ScriptableObject.DONTENUM) == 0)\r
- return Boolean.TRUE;\r
- }\r
- }\r
- }\r
- catch (PropertyException x) {\r
- }\r
- catch (ClassCastException x) {\r
- }\r
- return Boolean.FALSE;\r
- }\r
-\r
- private static Object jsFunction_isPrototypeOf(Context cx,\r
- Scriptable thisObj,\r
- Object[] args)\r
- {\r
- if (args.length != 0 && args[0] instanceof Scriptable) {\r
- Scriptable v = (Scriptable) args[0];\r
- do {\r
- v = v.getPrototype();\r
- if (v == thisObj)\r
- return Boolean.TRUE;\r
- } while (v != null);\r
- }\r
- return Boolean.FALSE;\r
- }\r
-\r
- protected String getIdName(int id) {\r
- if (prototypeFlag) {\r
- switch (id) {\r
- case Id_constructor: return "constructor";\r
- case Id_toString: return "toString";\r
- case Id_toLocaleString: return "toLocaleString";\r
- case Id_valueOf: return "valueOf";\r
- case Id_hasOwnProperty: return "hasOwnProperty";\r
- case Id_propertyIsEnumerable: return "propertyIsEnumerable";\r
- case Id_isPrototypeOf: return "isPrototypeOf";\r
- }\r
- }\r
- return null;\r
- }\r
-\r
-// #string_id_map#\r
-\r
- protected int mapNameToId(String s) {\r
- if (!prototypeFlag) { return 0; }\r
- int id;\r
-// #generated# Last update: 2001-04-24 12:37:03 GMT+02:00\r
- L0: { id = 0; String X = null; int c;\r
- L: switch (s.length()) {\r
- case 7: X="valueOf";id=Id_valueOf; break L;\r
- case 8: X="toString";id=Id_toString; break L;\r
- case 11: X="constructor";id=Id_constructor; break L;\r
- case 13: X="isPrototypeOf";id=Id_isPrototypeOf; break L;\r
- case 14: c=s.charAt(0);\r
- if (c=='h') { X="hasOwnProperty";id=Id_hasOwnProperty; }\r
- else if (c=='t') { X="toLocaleString";id=Id_toLocaleString; }\r
- break L;\r
- case 20: X="propertyIsEnumerable";id=Id_propertyIsEnumerable; break L;\r
- }\r
- if (X!=null && X!=s && !X.equals(s)) id = 0;\r
- }\r
-// #/generated#\r
- return id;\r
- }\r
-\r
- private static final int\r
- Id_constructor = 1,\r
- Id_toString = 2,\r
- Id_toLocaleString = 3,\r
- Id_valueOf = 4,\r
- Id_hasOwnProperty = 5,\r
- Id_propertyIsEnumerable = 6,\r
- Id_isPrototypeOf = 7,\r
- MAX_PROTOTYPE_ID = 7;\r
-\r
-// #/string_id_map#\r
-\r
- private boolean prototypeFlag;\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- * Roger Lawrence\r
- * Mike McCabe\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-import java.io.StringReader;\r
-import java.io.IOException;\r
-\r
-/**\r
- * The JavaScript Script object.\r
- *\r
- * Note that the C version of the engine uses XDR as the format used\r
- * by freeze and thaw. Since this depends on the internal format of\r
- * structures in the C runtime, we cannot duplicate it.\r
- *\r
- * Since we cannot replace 'this' as a result of the compile method,\r
- * this class has a dual nature. Generated scripts will have a null\r
- * 'script' field and will override 'exec' and 'call'. Scripts created\r
- * using the JavaScript constructor will forward requests to the\r
- * nonnull 'script' field.\r
- *\r
- * @since 1.3\r
- * @author Norris Boyd\r
- */\r
-\r
-public class NativeScript extends NativeFunction implements Script {\r
-\r
- public static void init(Context cx, Scriptable scope, boolean sealed) {\r
- NativeScript obj = new NativeScript();\r
- obj.scopeInit(cx, scope, sealed);\r
- }\r
-\r
- public NativeScript() {\r
- }\r
-\r
- private void scopeInit(Context cx, Scriptable scope, boolean sealed) {\r
- // prototypeIdShift != 0 serves as indicator of prototype instance\r
- // and as id offset to take into account ids present in each instance\r
- // of the base class NativeFunction. \r
- // Not to depend on the assumption NativeFunction.maxInstanceId() != 0,\r
- // 1 is added super.maxInstanceId() to make sure that \r
- // prototypeIdShift != 0 in the NativeScript prototype.\r
- // In a similar way the following methods use \r
- // methodId - prototypeIdShift + 1, not methodId - prototypeIdShift\r
- // to unshift prototype id to [1 .. MAX_PROTOTYPE_ID] interval\r
- prototypeIdShift = super.maxInstanceId() + 1;\r
- addAsPrototype(MAX_PROTOTYPE_ID + prototypeIdShift - 1, \r
- cx, scope, sealed);\r
- }\r
-\r
- /**\r
- * Returns the name of this JavaScript class, "Script".\r
- */\r
- public String getClassName() {\r
- return "Script";\r
- }\r
-\r
- /**\r
- * Initialize script.\r
- *\r
- * Does nothing here, but scripts will override with code\r
- * to initialize contained functions, regexp literals, etc.\r
- */\r
- public void initScript(Scriptable scope) {\r
- }\r
-\r
- public int methodArity(int methodId) {\r
- if (prototypeIdShift != 0) {\r
- switch (methodId - prototypeIdShift + 1) {\r
- case Id_constructor: return 1;\r
- case Id_toString: return 0;\r
- case Id_exec: return 0;\r
- case Id_compile: return 1;\r
- }\r
- }\r
- return super.methodArity(methodId);\r
- }\r
-\r
- public Object execMethod(int methodId, IdFunction f, Context cx,\r
- Scriptable scope, Scriptable thisObj, \r
- Object[] args)\r
- throws JavaScriptException\r
- {\r
- if (prototypeIdShift != 0) {\r
- switch (methodId - prototypeIdShift + 1) {\r
- case Id_constructor:\r
- return jsConstructor(cx, scope, args);\r
-\r
- case Id_toString:\r
- return realThis(thisObj, f, true).\r
- jsFunction_toString(cx, args);\r
-\r
- case Id_exec:\r
- return realThis(thisObj, f, true).jsFunction_exec();\r
-\r
- case Id_compile:\r
- return realThis(thisObj, f, false).\r
- jsFunction_compile(ScriptRuntime.toString(args, 0));\r
- }\r
- }\r
-\r
- return super.execMethod(methodId, f, cx, scope, thisObj, args);\r
- }\r
-\r
- private NativeScript realThis(Scriptable thisObj, IdFunction f, \r
- boolean readOnly)\r
- {\r
- while (!(thisObj instanceof NativeScript)) {\r
- thisObj = nextInstanceCheck(thisObj, f, readOnly);\r
- }\r
- return (NativeScript)thisObj;\r
- }\r
-\r
- /**\r
- * The Java method defining the JavaScript Script constructor.\r
- *\r
- */\r
- private static Object jsConstructor(Context cx, Scriptable scope, \r
- Object[] args)\r
- {\r
- String source = args.length == 0\r
- ? ""\r
- : ScriptRuntime.toString(args[0]);\r
- return compile(scope, source);\r
- }\r
-\r
- public static Script compile(Scriptable scope, String source) {\r
- Context cx = Context.getContext();\r
- StringReader reader = new StringReader(source);\r
- try {\r
- int[] linep = { 0 };\r
- String filename = Context.getSourcePositionFromStack(linep);\r
- if (filename == null) {\r
- filename = "<Script object>";\r
- linep[0] = 1;\r
- }\r
- Object securityDomain = \r
- cx.getSecurityDomainForStackDepth(5);\r
- return cx.compileReader(scope, reader, filename, linep[0], \r
- securityDomain);\r
- }\r
- catch (IOException e) {\r
- throw new RuntimeException("Unexpected IOException");\r
- }\r
- }\r
-\r
- private Scriptable jsFunction_compile(String source) {\r
- script = compile(null, source);\r
- return this;\r
- }\r
-\r
- private Object jsFunction_exec() throws JavaScriptException {\r
- throw Context.reportRuntimeError1\r
- ("msg.cant.call.indirect", "exec");\r
- }\r
-\r
- private Object jsFunction_toString(Context cx, Object[] args)\r
- {\r
- Script thisScript = script;\r
- if (thisScript == null) { thisScript = this; }\r
- Scriptable scope = getTopLevelScope(this);\r
- return cx.decompileScript(thisScript, scope, 0);\r
- }\r
- \r
- /*\r
- * Override method in NativeFunction to avoid ever returning "anonymous"\r
- */\r
- public String getFunctionName() {\r
- return "";\r
- }\r
-\r
- /**\r
- * Execute the script.\r
- *\r
- * Will be overridden by generated scripts; needed to implement Script.\r
- */\r
- public Object exec(Context cx, Scriptable scope)\r
- throws JavaScriptException\r
- {\r
- return script == null ? Undefined.instance : script.exec(cx, scope);\r
- }\r
-\r
- public Object call(Context cx, Scriptable scope, Scriptable thisObj,\r
- Object[] args)\r
- throws JavaScriptException\r
- {\r
- return exec(cx, scope);\r
- }\r
-\r
- public Scriptable construct(Context cx, Scriptable scope, Object[] args)\r
- throws JavaScriptException\r
- {\r
- throw Context.reportRuntimeError0("msg.script.is.not.constructor");\r
- }\r
-\r
- protected String getIdName(int id) {\r
- if (prototypeIdShift != 0) {\r
- switch (id - prototypeIdShift + 1) {\r
- case Id_constructor: return "constructor";\r
- case Id_toString: return "toString";\r
- case Id_exec: return "exec";\r
- case Id_compile: return "compile";\r
- }\r
- }\r
- return super.getIdName(id);\r
- }\r
-\r
- protected int mapNameToId(String s) {\r
- if (prototypeIdShift != 0) {\r
- int id = toPrototypeId(s);\r
- if (id != 0) { \r
- // Shift [1, MAX_PROTOTYPE_ID] to\r
- // [super.maxInstanceId() + 1,\r
- // super.maxInstanceId() + MAX_PROTOTYPE_ID]\r
- return id + prototypeIdShift - 1; \r
- }\r
- }\r
- return super.mapNameToId(s);\r
- }\r
-\r
-// #string_id_map#\r
-\r
- private static int toPrototypeId(String s) {\r
- int id;\r
-// #generated# Last update: 2001-05-23 13:25:01 GMT+02:00\r
- L0: { id = 0; String X = null;\r
- L: switch (s.length()) {\r
- case 4: X="exec";id=Id_exec; break L;\r
- case 7: X="compile";id=Id_compile; break L;\r
- case 8: X="toString";id=Id_toString; break L;\r
- case 11: X="constructor";id=Id_constructor; break L;\r
- }\r
- if (X!=null && X!=s && !X.equals(s)) id = 0;\r
- }\r
-// #/generated#\r
- return id;\r
- }\r
-\r
- private static final int\r
- Id_constructor = 1,\r
- Id_toString = 2,\r
- Id_compile = 3,\r
- Id_exec = 4,\r
- MAX_PROTOTYPE_ID = 4;\r
-\r
-// #/string_id_map#\r
-\r
- private Script script;\r
-\r
- private int prototypeIdShift;\r
-}\r
-\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s):\r
- * Tom Beauvais\r
- * Norris Boyd\r
- * Mike McCabe\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-import java.lang.reflect.Method;\r
-import java.util.Vector;\r
-\r
-/**\r
- * This class implements the String native object.\r
- *\r
- * See ECMA 15.5.\r
- *\r
- * String methods for dealing with regular expressions are\r
- * ported directly from C. Latest port is from version 1.40.12.19\r
- * in the JSFUN13_BRANCH.\r
- *\r
- * @author Mike McCabe\r
- * @author Norris Boyd\r
- */\r
-public class NativeString extends IdScriptable {\r
-\r
- public static void init(Context cx, Scriptable scope, boolean sealed) {\r
- NativeString obj = new NativeString();\r
- obj.prototypeFlag = true;\r
- obj.addAsPrototype(MAX_PROTOTYPE_ID, cx, scope, sealed);\r
- }\r
-\r
- /**\r
- * Zero-parameter constructor: just used to create String.prototype\r
- */\r
- public NativeString() {\r
- string = defaultValue;\r
- }\r
-\r
- public NativeString(String s) {\r
- string = s;\r
- }\r
-\r
- public String getClassName() {\r
- return "String";\r
- }\r
-\r
- protected void fillConstructorProperties\r
- (Context cx, IdFunction ctor, boolean sealed)\r
- {\r
- addIdFunctionProperty(ctor, ConstructorId_fromCharCode, sealed);\r
- super.fillConstructorProperties(cx, ctor, sealed);\r
- }\r
-\r
- protected int getIdDefaultAttributes(int id) {\r
- if (id == Id_length) {\r
- return DONTENUM | READONLY | PERMANENT;\r
- }\r
- return super.getIdDefaultAttributes(id);\r
- }\r
-\r
- protected Object getIdValue(int id) {\r
- if (id == Id_length) {\r
- return wrap_int(string.length());\r
- }\r
- return super.getIdValue(id);\r
- }\r
-\r
- public int methodArity(int methodId) {\r
- if (prototypeFlag) {\r
- switch (methodId) {\r
- case ConstructorId_fromCharCode: return 1;\r
-\r
- case Id_constructor: return 1;\r
- case Id_toString: return 0;\r
- case Id_valueOf: return 0;\r
- case Id_charAt: return 1;\r
- case Id_charCodeAt: return 1;\r
- case Id_indexOf: return 2;\r
- case Id_lastIndexOf: return 2;\r
- case Id_split: return 1;\r
- case Id_substring: return 2;\r
- case Id_toLowerCase: return 0;\r
- case Id_toUpperCase: return 0;\r
- case Id_substr: return 2;\r
- case Id_concat: return 1;\r
- case Id_slice: return 2;\r
- case Id_bold: return 0;\r
- case Id_italics: return 0;\r
- case Id_fixed: return 0;\r
- case Id_strike: return 0;\r
- case Id_small: return 0;\r
- case Id_big: return 0;\r
- case Id_blink: return 0;\r
- case Id_sup: return 0;\r
- case Id_sub: return 0;\r
- case Id_fontsize: return 0;\r
- case Id_fontcolor: return 0;\r
- case Id_link: return 0;\r
- case Id_anchor: return 0;\r
- case Id_equals: return 1;\r
- case Id_equalsIgnoreCase: return 1;\r
- case Id_match: return 1;\r
- case Id_search: return 1;\r
- case Id_replace: return 1;\r
- }\r
- }\r
- return super.methodArity(methodId);\r
- }\r
-\r
- public Object execMethod\r
- (int methodId, IdFunction f,\r
- Context cx, Scriptable scope, Scriptable thisObj, Object[] args)\r
- throws JavaScriptException\r
- {\r
- if (prototypeFlag) {\r
- switch (methodId) {\r
- case ConstructorId_fromCharCode: \r
- return jsStaticFunction_fromCharCode(args);\r
-\r
- case Id_constructor:\r
- return jsConstructor(args, thisObj == null);\r
-\r
- case Id_toString:\r
- return realThis(thisObj, f).jsFunction_toString();\r
-\r
- case Id_valueOf:\r
- return realThis(thisObj, f).jsFunction_valueOf();\r
-\r
- case Id_charAt: \r
- return jsFunction_charAt\r
- (ScriptRuntime.toString(thisObj), args);\r
-\r
- case Id_charCodeAt: \r
- return wrap_double(jsFunction_charCodeAt\r
- (ScriptRuntime.toString(thisObj), args));\r
-\r
- case Id_indexOf:\r
- return wrap_int(jsFunction_indexOf\r
- (ScriptRuntime.toString(thisObj), args));\r
-\r
- case Id_lastIndexOf: \r
- return wrap_int(jsFunction_lastIndexOf\r
- (ScriptRuntime.toString(thisObj), args));\r
-\r
- case Id_split: \r
- return jsFunction_split\r
- (cx, scope, ScriptRuntime.toString(thisObj), args);\r
-\r
- case Id_substring:\r
- return jsFunction_substring\r
- (cx, ScriptRuntime.toString(thisObj), args);\r
-\r
- case Id_toLowerCase:\r
- return jsFunction_toLowerCase\r
- (ScriptRuntime.toString(thisObj));\r
-\r
- case Id_toUpperCase:\r
- return jsFunction_toUpperCase\r
- (ScriptRuntime.toString(thisObj));\r
-\r
- case Id_substr: \r
- return jsFunction_substr\r
- (ScriptRuntime.toString(thisObj), args);\r
-\r
- case Id_concat:\r
- return jsFunction_concat\r
- (ScriptRuntime.toString(thisObj), args);\r
-\r
- case Id_slice:\r
- return jsFunction_slice\r
- (ScriptRuntime.toString(thisObj), args);\r
-\r
- case Id_bold:\r
- return realThis(thisObj, f).tagify("b", null, null);\r
-\r
- case Id_italics:\r
- return realThis(thisObj, f).tagify("i", null, null);\r
-\r
- case Id_fixed:\r
- return realThis(thisObj, f).tagify("tt", null, null);\r
-\r
- case Id_strike:\r
- return realThis(thisObj, f).tagify("strike", null, null);\r
-\r
- case Id_small:\r
- return realThis(thisObj, f).tagify("small", null, null);\r
-\r
- case Id_big:\r
- return realThis(thisObj, f).tagify("big", null, null);\r
-\r
- case Id_blink:\r
- return realThis(thisObj, f).tagify("blink", null, null);\r
-\r
- case Id_sup:\r
- return realThis(thisObj, f).tagify("sup", null, null);\r
-\r
- case Id_sub:\r
- return realThis(thisObj, f).tagify("sub", null, null);\r
-\r
- case Id_fontsize:\r
- return realThis(thisObj, f).\r
- tagify("font size", "font", \r
- ScriptRuntime.toString(args, 0));\r
-\r
- case Id_fontcolor:\r
- return realThis(thisObj, f).\r
- tagify("font color", "font",\r
- ScriptRuntime.toString(args, 0));\r
-\r
- case Id_link:\r
- return realThis(thisObj, f).\r
- tagify("a href", "a", ScriptRuntime.toString(args, 0));\r
-\r
- case Id_anchor:\r
- return realThis(thisObj, f).\r
- tagify("a name", "a", ScriptRuntime.toString(args, 0));\r
-\r
- case Id_equals:\r
- return wrap_boolean(jsFunction_equals\r
- (ScriptRuntime.toString(thisObj),\r
- ScriptRuntime.toString(args, 0)));\r
-\r
- case Id_equalsIgnoreCase:\r
- return wrap_boolean(jsFunction_equalsIgnoreCase\r
- (ScriptRuntime.toString(thisObj),\r
- ScriptRuntime.toString(args, 0)));\r
-\r
- case Id_match:\r
- return checkReProxy(cx).match(cx, scope, thisObj, args);\r
-\r
- case Id_search:\r
- return checkReProxy(cx).search(cx, scope, thisObj, args);\r
-\r
- case Id_replace:\r
- return checkReProxy(cx).replace(cx, scope, thisObj, args);\r
- }\r
- }\r
- return super.execMethod(methodId, f, cx, scope, thisObj, args);\r
- }\r
-\r
- private NativeString realThis(Scriptable thisObj, IdFunction f) {\r
- while (!(thisObj instanceof NativeString)) {\r
- thisObj = nextInstanceCheck(thisObj, f, true);\r
- }\r
- return (NativeString)thisObj;\r
- }\r
-\r
- private static RegExpProxy checkReProxy(Context cx) {\r
- RegExpProxy result = cx.getRegExpProxy();\r
- if (result == null) {\r
- throw cx.reportRuntimeError0("msg.no.regexp");\r
- }\r
- return result;\r
- }\r
-\r
- /*\r
- * HTML composition aids.\r
- */\r
- private String tagify(String begin, String end, String value) {\r
- StringBuffer result = new StringBuffer();\r
- result.append('<');\r
- result.append(begin);\r
- if (value != null) {\r
- result.append("=\"");\r
- result.append(value);\r
- result.append('"');\r
- }\r
- result.append('>');\r
- result.append(this.string);\r
- result.append("</");\r
- result.append((end == null) ? begin : end);\r
- result.append('>');\r
- return result.toString();\r
- }\r
-\r
- private static String jsStaticFunction_fromCharCode(Object[] args) {\r
- int N = args.length;\r
- if (N < 1)\r
- return "";\r
- StringBuffer s = new java.lang.StringBuffer(N);\r
- for (int i=0; i < N; i++) {\r
- s.append(ScriptRuntime.toUint16(args[i]));\r
- }\r
- return s.toString();\r
- }\r
-\r
- private static Object jsConstructor(Object[] args, boolean inNewExpr) {\r
- String s = args.length >= 1\r
- ? ScriptRuntime.toString(args[0])\r
- : defaultValue;\r
- if (inNewExpr) {\r
- // new String(val) creates a new String object.\r
- return new NativeString(s);\r
- }\r
- // String(val) converts val to a string value.\r
- return s;\r
- }\r
-\r
- public String toString() {\r
- return string;\r
- }\r
-\r
- /* ECMA 15.5.4.2: 'the toString function is not generic.' */\r
- private String jsFunction_toString() {\r
- return string;\r
- }\r
-\r
- private String jsFunction_valueOf() {\r
- return string;\r
- }\r
-\r
- /* Make array-style property lookup work for strings.\r
- * XXX is this ECMA? A version check is probably needed. In js too.\r
- */\r
- public Object get(int index, Scriptable start) {\r
- if (index >= 0 && index < string.length())\r
- return string.substring(index, index + 1);\r
- return super.get(index, start);\r
- }\r
-\r
- public void put(int index, Scriptable start, Object value) {\r
- if (index >= 0 && index < string.length())\r
- return;\r
- super.put(index, start, value);\r
- }\r
-\r
- /*\r
- *\r
- * See ECMA 15.5.4.[4,5]\r
- */\r
- private static String jsFunction_charAt(String target, Object[] args)\r
- {\r
- // this'll return 0 if undefined... seems\r
- // to be ECMA.\r
- double pos = ScriptRuntime.toInteger(args, 0);\r
-\r
- if (pos < 0 || pos >= target.length())\r
- return "";\r
-\r
- return target.substring((int)pos, (int)pos + 1);\r
- }\r
-\r
- private static double jsFunction_charCodeAt(String target, Object[] args)\r
- {\r
- double pos = ScriptRuntime.toInteger(args, 0);\r
-\r
- if (pos < 0 || pos >= target.length()) {\r
- return ScriptRuntime.NaN;\r
- }\r
-\r
- return target.charAt((int)pos);\r
- }\r
-\r
- /*\r
- *\r
- * See ECMA 15.5.4.6. Uses Java String.indexOf()\r
- * OPT to add - BMH searching from jsstr.c.\r
- */\r
- private static int jsFunction_indexOf(String target, Object[] args) {\r
- String search = ScriptRuntime.toString(args, 0);\r
- double begin = ScriptRuntime.toInteger(args, 1);\r
-\r
- if (begin > target.length()) {\r
- return -1;\r
- } else {\r
- if (begin < 0)\r
- begin = 0;\r
- return target.indexOf(search, (int)begin);\r
- }\r
- }\r
-\r
- /*\r
- *\r
- * See ECMA 15.5.4.7\r
- *\r
- */\r
- private static int jsFunction_lastIndexOf(String target, Object[] args) {\r
- String search = ScriptRuntime.toString(args, 0);\r
- double end = ScriptRuntime.toNumber(args, 1);\r
-\r
- if (end != end || end > target.length())\r
- end = target.length();\r
- else if (end < 0)\r
- end = 0;\r
-\r
- return target.lastIndexOf(search, (int)end);\r
- }\r
-\r
- /*\r
- * Used by js_split to find the next split point in target,\r
- * starting at offset ip and looking either for the given\r
- * separator substring, or for the next re match. ip and\r
- * matchlen must be reference variables (assumed to be arrays of\r
- * length 1) so they can be updated in the leading whitespace or\r
- * re case.\r
- *\r
- * Return -1 on end of string, >= 0 for a valid index of the next\r
- * separator occurrence if found, or the string length if no\r
- * separator is found.\r
- */\r
- private static int find_split(Scriptable scope, String target,\r
- String separator, Object re,\r
- int[] ip, int[] matchlen, boolean[] matched,\r
- String[][] parensp)\r
- {\r
- int i = ip[0];\r
- int length = target.length();\r
- Context cx = Context.getContext();\r
- int version = cx.getLanguageVersion();\r
-\r
- /*\r
- * Perl4 special case for str.split(' '), only if the user has selected\r
- * JavaScript1.2 explicitly. Split on whitespace, and skip leading w/s.\r
- * Strange but true, apparently modeled after awk.\r
- */\r
- if (version == Context.VERSION_1_2 &&\r
- re == null && separator.length() == 1 && separator.charAt(0) == ' ')\r
- {\r
- /* Skip leading whitespace if at front of str. */\r
- if (i == 0) {\r
- while (i < length && Character.isWhitespace(target.charAt(i)))\r
- i++;\r
- ip[0] = i;\r
- }\r
-\r
- /* Don't delimit whitespace at end of string. */\r
- if (i == length)\r
- return -1;\r
-\r
- /* Skip over the non-whitespace chars. */\r
- while (i < length\r
- && !Character.isWhitespace(target.charAt(i)))\r
- i++;\r
-\r
- /* Now skip the next run of whitespace. */\r
- int j = i;\r
- while (j < length && Character.isWhitespace(target.charAt(j)))\r
- j++;\r
-\r
- /* Update matchlen to count delimiter chars. */\r
- matchlen[0] = j - i;\r
- return i;\r
- }\r
-\r
- /*\r
- * Stop if past end of string. If at end of string, we will\r
- * return target length, so that\r
- *\r
- * "ab,".split(',') => new Array("ab", "")\r
- *\r
- * and the resulting array converts back to the string "ab,"\r
- * for symmetry. NB: This differs from perl, which drops the\r
- * trailing empty substring if the LIMIT argument is omitted.\r
- */\r
- if (i > length)\r
- return -1;\r
-\r
- /*\r
- * Match a regular expression against the separator at or\r
- * above index i. Return -1 at end of string instead of\r
- * trying for a match, so we don't get stuck in a loop.\r
- */\r
- if (re != null) {\r
- return cx.getRegExpProxy().find_split(scope, target,\r
- separator, re,\r
- ip, matchlen, matched,\r
- parensp);\r
- }\r
-\r
- /*\r
- * Deviate from ECMA by never splitting an empty string by any separator\r
- * string into a non-empty array (an array of length 1 that contains the\r
- * empty string).\r
- */\r
- if (version != Context.VERSION_DEFAULT && version < Context.VERSION_1_3\r
- && length == 0)\r
- return -1;\r
-\r
- /*\r
- * Special case: if sep is the empty string, split str into\r
- * one character substrings. Let our caller worry about\r
- * whether to split once at end of string into an empty\r
- * substring.\r
- *\r
- * For 1.2 compatibility, at the end of the string, we return the length as\r
- * the result, and set the separator length to 1 -- this allows the caller\r
- * to include an additional null string at the end of the substring list.\r
- */\r
- if (separator.length() == 0) {\r
- if (version == Context.VERSION_1_2) {\r
- if (i == length) {\r
- matchlen[0] = 1;\r
- return i;\r
- }\r
- return i + 1;\r
- }\r
- return (i == length) ? -1 : i + 1;\r
- }\r
-\r
- /* Punt to j.l.s.indexOf; return target length if seperator is\r
- * not found.\r
- */\r
- if (ip[0] >= length)\r
- return length;\r
-\r
- i = target.indexOf(separator, ip[0]);\r
-\r
- return (i != -1) ? i : length;\r
- }\r
-\r
- /*\r
- * See ECMA 15.5.4.8. Modified to match JS 1.2 - optionally takes\r
- * a limit argument and accepts a regular expression as the split\r
- * argument.\r
- */\r
- private static Object jsFunction_split(Context cx, Scriptable scope,\r
- String target, Object[] args)\r
- {\r
- // create an empty Array to return;\r
- Scriptable top = getTopLevelScope(scope);\r
- Scriptable result = ScriptRuntime.newObject(cx, top, "Array", null);\r
-\r
- // return an array consisting of the target if no separator given\r
- // don't check against undefined, because we want\r
- // 'fooundefinedbar'.split(void 0) to split to ['foo', 'bar']\r
- if (args.length < 1) {\r
- result.put(0, result, target);\r
- return result;\r
- }\r
-\r
- // Use the second argument as the split limit, if given.\r
- boolean limited = (args.length > 1) && (args[1] != Undefined.instance);\r
- long limit = 0; // Initialize to avoid warning.\r
- if (limited) {\r
- /* Clamp limit between 0 and 1 + string length. */\r
- limit = ScriptRuntime.toUint32(args[1]);\r
- if (limit > target.length())\r
- limit = 1 + target.length();\r
- }\r
-\r
- String separator = null;\r
- int[] matchlen = { 0 };\r
- Object re = null;\r
- RegExpProxy reProxy = cx.getRegExpProxy();\r
- if (reProxy != null && reProxy.isRegExp(args[0])) {\r
- re = args[0];\r
- } else {\r
- separator = ScriptRuntime.toString(args[0]);\r
- matchlen[0] = separator.length();\r
- }\r
-\r
- // split target with separator or re\r
- int[] ip = { 0 };\r
- int match;\r
- int len = 0;\r
- boolean[] matched = { false };\r
- String[][] parens = { null };\r
- while ((match = find_split(scope, target, separator, re, ip,\r
- matchlen, matched, parens)) >= 0)\r
- {\r
- if ((limited && len >= limit) || (match > target.length()))\r
- break;\r
-\r
- String substr;\r
- if (target.length() == 0)\r
- substr = target;\r
- else\r
- substr = target.substring(ip[0], match);\r
-\r
- result.put(len, result, substr);\r
- len++;\r
- /*\r
- * Imitate perl's feature of including parenthesized substrings\r
- * that matched part of the delimiter in the new array, after the\r
- * split substring that was delimited.\r
- */\r
- if (re != null && matched[0] == true) {\r
- int size = parens[0].length;\r
- for (int num = 0; num < size; num++) {\r
- if (limited && len >= limit)\r
- break;\r
- result.put(len, result, parens[0][num]);\r
- len++;\r
- }\r
- matched[0] = false;\r
- }\r
- ip[0] = match + matchlen[0];\r
-\r
- if (cx.getLanguageVersion() < Context.VERSION_1_3\r
- && cx.getLanguageVersion() != Context.VERSION_DEFAULT)\r
- {\r
- /*\r
- * Deviate from ECMA to imitate Perl, which omits a final\r
- * split unless a limit argument is given and big enough.\r
- */\r
- if (!limited && ip[0] == target.length())\r
- break;\r
- }\r
- }\r
- return result;\r
- }\r
-\r
- /*\r
- * See ECMA 15.5.4.15\r
- */\r
- private static String jsFunction_substring(Context cx, String target,\r
- Object[] args)\r
- {\r
- int length = target.length();\r
- double start = ScriptRuntime.toInteger(args, 0);\r
- double end;\r
-\r
- if (start < 0)\r
- start = 0;\r
- else if (start > length)\r
- start = length;\r
-\r
- if (args.length <= 1 || args[1] == Undefined.instance) {\r
- end = length;\r
- } else {\r
- end = ScriptRuntime.toInteger(args[1]);\r
- if (end < 0)\r
- end = 0;\r
- else if (end > length)\r
- end = length;\r
-\r
- // swap if end < start\r
- if (end < start) {\r
- if (cx.getLanguageVersion() != Context.VERSION_1_2) {\r
- double temp = start;\r
- start = end;\r
- end = temp;\r
- } else {\r
- // Emulate old JDK1.0 java.lang.String.substring()\r
- end = start;\r
- }\r
- }\r
- }\r
- return target.substring((int)start, (int)end);\r
- }\r
-\r
- /*\r
- *\r
- * See ECMA 15.5.4.[11,12]\r
- */\r
- private static String jsFunction_toLowerCase(String target) {\r
- return target.toLowerCase();\r
- }\r
-\r
- private static String jsFunction_toUpperCase(String target) {\r
- return target.toUpperCase();\r
- }\r
-\r
- public double jsGet_length() {\r
- return (double) string.length();\r
- }\r
-\r
- /*\r
- * Non-ECMA methods.\r
- */\r
- private static String jsFunction_substr(String target, Object[] args) {\r
- if (args.length < 1)\r
- return target;\r
-\r
- double begin = ScriptRuntime.toInteger(args[0]);\r
- double end;\r
- int length = target.length();\r
-\r
- if (begin < 0) {\r
- begin += length;\r
- if (begin < 0)\r
- begin = 0;\r
- } else if (begin > length) {\r
- begin = length;\r
- }\r
-\r
- if (args.length == 1) {\r
- end = length;\r
- } else {\r
- end = ScriptRuntime.toInteger(args[1]);\r
- if (end < 0)\r
- end = 0;\r
- end += begin;\r
- if (end > length)\r
- end = length;\r
- }\r
-\r
- return target.substring((int)begin, (int)end);\r
- }\r
-\r
- /*\r
- * Python-esque sequence operations.\r
- */\r
- private static String jsFunction_concat(String target, Object[] args) {\r
- int N = args.length;\r
- if (N == 0) { return target; }\r
-\r
- StringBuffer result = new StringBuffer();\r
- result.append(target);\r
-\r
- for (int i = 0; i < N; i++)\r
- result.append(ScriptRuntime.toString(args[i]));\r
-\r
- return result.toString();\r
- }\r
-\r
- private static String jsFunction_slice(String target, Object[] args) {\r
- if (args.length != 0) {\r
- double begin = ScriptRuntime.toInteger(args[0]);\r
- double end;\r
- int length = target.length();\r
- if (begin < 0) {\r
- begin += length;\r
- if (begin < 0)\r
- begin = 0;\r
- } else if (begin > length) {\r
- begin = length;\r
- }\r
-\r
- if (args.length == 1) {\r
- end = length;\r
- } else {\r
- end = ScriptRuntime.toInteger(args[1]);\r
- if (end < 0) {\r
- end += length;\r
- if (end < 0)\r
- end = 0;\r
- } else if (end > length) {\r
- end = length;\r
- }\r
- if (end < begin)\r
- end = begin;\r
- }\r
- return target.substring((int)begin, (int)end);\r
- }\r
- return target;\r
- }\r
-\r
- private static boolean jsFunction_equals(String target, String strOther) {\r
- return target.equals(strOther);\r
- }\r
-\r
-\r
- private static boolean jsFunction_equalsIgnoreCase(String target,\r
- String strOther)\r
- {\r
- return target.equalsIgnoreCase(strOther);\r
- }\r
-\r
- protected int maxInstanceId() { return MAX_INSTANCE_ID; }\r
-\r
- protected String getIdName(int id) {\r
- if (id == Id_length) { return "length"; }\r
- \r
- if (prototypeFlag) {\r
- switch (id) {\r
- case ConstructorId_fromCharCode: return "fromCharCode";\r
-\r
- case Id_constructor: return "constructor";\r
- case Id_toString: return "toString";\r
- case Id_valueOf: return "valueOf";\r
- case Id_charAt: return "charAt";\r
- case Id_charCodeAt: return "charCodeAt";\r
- case Id_indexOf: return "indexOf";\r
- case Id_lastIndexOf: return "lastIndexOf";\r
- case Id_split: return "split";\r
- case Id_substring: return "substring";\r
- case Id_toLowerCase: return "toLowerCase";\r
- case Id_toUpperCase: return "toUpperCase";\r
- case Id_substr: return "substr";\r
- case Id_concat: return "concat";\r
- case Id_slice: return "slice";\r
- case Id_bold: return "bold";\r
- case Id_italics: return "italics";\r
- case Id_fixed: return "fixed";\r
- case Id_strike: return "strike";\r
- case Id_small: return "small";\r
- case Id_big: return "big";\r
- case Id_blink: return "blink";\r
- case Id_sup: return "sup";\r
- case Id_sub: return "sub";\r
- case Id_fontsize: return "fontsize";\r
- case Id_fontcolor: return "fontcolor";\r
- case Id_link: return "link";\r
- case Id_anchor: return "anchor";\r
- case Id_equals: return "equals";\r
- case Id_equalsIgnoreCase: return "equalsIgnoreCase";\r
- case Id_match: return "match";\r
- case Id_search: return "search";\r
- case Id_replace: return "replace";\r
- }\r
- }\r
- return null;\r
- }\r
-\r
- private static final int\r
- ConstructorId_fromCharCode = -1,\r
- Id_length = 1,\r
- MAX_INSTANCE_ID = 1;\r
- \r
-\r
- protected int mapNameToId(String s) {\r
- if (s.equals("length")) { return Id_length; }\r
- else if (prototypeFlag) { \r
- return toPrototypeId(s); \r
- }\r
- return 0;\r
- }\r
-\r
-// #string_id_map#\r
-\r
- private static int toPrototypeId(String s) {\r
- int id;\r
-// #generated# Last update: 2001-04-23 12:50:07 GMT+02:00\r
- L0: { id = 0; String X = null; int c;\r
- L: switch (s.length()) {\r
- case 3: c=s.charAt(2);\r
- if (c=='b') { if (s.charAt(0)=='s' && s.charAt(1)=='u') {id=Id_sub; break L0;} }\r
- else if (c=='g') { if (s.charAt(0)=='b' && s.charAt(1)=='i') {id=Id_big; break L0;} }\r
- else if (c=='p') { if (s.charAt(0)=='s' && s.charAt(1)=='u') {id=Id_sup; break L0;} }\r
- break L;\r
- case 4: c=s.charAt(0);\r
- if (c=='b') { X="bold";id=Id_bold; }\r
- else if (c=='l') { X="link";id=Id_link; }\r
- break L;\r
- case 5: switch (s.charAt(4)) {\r
- case 'd': X="fixed";id=Id_fixed; break L;\r
- case 'e': X="slice";id=Id_slice; break L;\r
- case 'h': X="match";id=Id_match; break L;\r
- case 'k': X="blink";id=Id_blink; break L;\r
- case 'l': X="small";id=Id_small; break L;\r
- case 't': X="split";id=Id_split; break L;\r
- } break L;\r
- case 6: switch (s.charAt(1)) {\r
- case 'e': c=s.charAt(0);\r
- if (c=='l') { X="length";id=Id_length; }\r
- else if (c=='s') { X="search";id=Id_search; }\r
- break L;\r
- case 'h': X="charAt";id=Id_charAt; break L;\r
- case 'n': X="anchor";id=Id_anchor; break L;\r
- case 'o': X="concat";id=Id_concat; break L;\r
- case 'q': X="equals";id=Id_equals; break L;\r
- case 't': X="strike";id=Id_strike; break L;\r
- case 'u': X="substr";id=Id_substr; break L;\r
- } break L;\r
- case 7: switch (s.charAt(1)) {\r
- case 'a': X="valueOf";id=Id_valueOf; break L;\r
- case 'e': X="replace";id=Id_replace; break L;\r
- case 'n': X="indexOf";id=Id_indexOf; break L;\r
- case 't': X="italics";id=Id_italics; break L;\r
- } break L;\r
- case 8: c=s.charAt(0);\r
- if (c=='f') { X="fontsize";id=Id_fontsize; }\r
- else if (c=='t') { X="toString";id=Id_toString; }\r
- break L;\r
- case 9: c=s.charAt(0);\r
- if (c=='f') { X="fontcolor";id=Id_fontcolor; }\r
- else if (c=='s') { X="substring";id=Id_substring; }\r
- break L;\r
- case 10: X="charCodeAt";id=Id_charCodeAt; break L;\r
- case 11: switch (s.charAt(2)) {\r
- case 'L': X="toLowerCase";id=Id_toLowerCase; break L;\r
- case 'U': X="toUpperCase";id=Id_toUpperCase; break L;\r
- case 'n': X="constructor";id=Id_constructor; break L;\r
- case 's': X="lastIndexOf";id=Id_lastIndexOf; break L;\r
- } break L;\r
- case 16: X="equalsIgnoreCase";id=Id_equalsIgnoreCase; break L;\r
- }\r
- if (X!=null && X!=s && !X.equals(s)) id = 0;\r
- }\r
-// #/generated#\r
- return id;\r
- }\r
-\r
- private static final int\r
- Id_constructor = MAX_INSTANCE_ID + 1,\r
- Id_toString = MAX_INSTANCE_ID + 2,\r
- Id_valueOf = MAX_INSTANCE_ID + 3,\r
- Id_charAt = MAX_INSTANCE_ID + 4,\r
- Id_charCodeAt = MAX_INSTANCE_ID + 5,\r
- Id_indexOf = MAX_INSTANCE_ID + 6,\r
- Id_lastIndexOf = MAX_INSTANCE_ID + 7,\r
- Id_split = MAX_INSTANCE_ID + 8,\r
- Id_substring = MAX_INSTANCE_ID + 9,\r
- Id_toLowerCase = MAX_INSTANCE_ID + 10,\r
- Id_toUpperCase = MAX_INSTANCE_ID + 11,\r
- Id_substr = MAX_INSTANCE_ID + 12,\r
- Id_concat = MAX_INSTANCE_ID + 13,\r
- Id_slice = MAX_INSTANCE_ID + 14,\r
- Id_bold = MAX_INSTANCE_ID + 15,\r
- Id_italics = MAX_INSTANCE_ID + 16,\r
- Id_fixed = MAX_INSTANCE_ID + 17,\r
- Id_strike = MAX_INSTANCE_ID + 18,\r
- Id_small = MAX_INSTANCE_ID + 19,\r
- Id_big = MAX_INSTANCE_ID + 20,\r
- Id_blink = MAX_INSTANCE_ID + 21,\r
- Id_sup = MAX_INSTANCE_ID + 22,\r
- Id_sub = MAX_INSTANCE_ID + 23,\r
- Id_fontsize = MAX_INSTANCE_ID + 24,\r
- Id_fontcolor = MAX_INSTANCE_ID + 25,\r
- Id_link = MAX_INSTANCE_ID + 26,\r
- Id_anchor = MAX_INSTANCE_ID + 27,\r
- Id_equals = MAX_INSTANCE_ID + 28,\r
- Id_equalsIgnoreCase = MAX_INSTANCE_ID + 29,\r
- Id_match = MAX_INSTANCE_ID + 30,\r
- Id_search = MAX_INSTANCE_ID + 31,\r
- Id_replace = MAX_INSTANCE_ID + 32,\r
-\r
- MAX_PROTOTYPE_ID = MAX_INSTANCE_ID + 32;\r
-\r
-// #/string_id_map#\r
-\r
- private static final String defaultValue = "";\r
-\r
- private String string;\r
- \r
- private boolean prototypeFlag;\r
-}\r
-\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-import java.lang.reflect.Method;\r
-\r
-/**\r
- * This class implements the object lookup required for the\r
- * <code>with</code> statement.\r
- * It simply delegates every action to its prototype except\r
- * for operations on its parent.\r
- */\r
-public class NativeWith implements Scriptable, IdFunctionMaster { \r
- \r
- public static void init(Context cx, Scriptable scope, boolean sealed) {\r
- NativeWith obj = new NativeWith();\r
- obj.prototypeFlag = true;\r
-\r
- IdFunction ctor = new IdFunction(obj, "constructor", Id_constructor);\r
- ctor.initAsConstructor(scope, obj);\r
- if (sealed) { ctor.sealObject(); }\r
- \r
- obj.setParentScope(ctor);\r
- obj.setPrototype(ScriptableObject.getObjectPrototype(scope));\r
- \r
- ScriptableObject.defineProperty(scope, "With", ctor,\r
- ScriptableObject.DONTENUM);\r
- }\r
-\r
- public NativeWith() {\r
- }\r
-\r
- public NativeWith(Scriptable parent, Scriptable prototype) {\r
- this.parent = parent;\r
- this.prototype = prototype;\r
- }\r
-\r
- public String getClassName() {\r
- return "With";\r
- }\r
-\r
- public boolean has(String id, Scriptable start) {\r
- if (start == this)\r
- start = prototype;\r
- return prototype.has(id, start);\r
- }\r
-\r
- public boolean has(int index, Scriptable start) {\r
- if (start == this)\r
- start = prototype;\r
- return prototype.has(index, start);\r
- }\r
-\r
- public Object get(String id, Scriptable start) {\r
- if (start == this)\r
- start = prototype;\r
- return prototype.get(id, start);\r
- }\r
-\r
- public Object get(int index, Scriptable start) {\r
- if (start == this)\r
- start = prototype;\r
- return prototype.get(index, start);\r
- }\r
-\r
- public void put(String id, Scriptable start, Object value) {\r
- if (start == this)\r
- start = prototype;\r
- prototype.put(id, start, value);\r
- }\r
-\r
- public void put(int index, Scriptable start, Object value) {\r
- if (start == this)\r
- start = prototype;\r
- prototype.put(index, start, value);\r
- }\r
-\r
- public void delete(String id) {\r
- prototype.delete(id);\r
- }\r
-\r
- public void delete(int index) {\r
- prototype.delete(index);\r
- }\r
-\r
- public Scriptable getPrototype() {\r
- return prototype;\r
- }\r
-\r
- public void setPrototype(Scriptable prototype) {\r
- this.prototype = prototype;\r
- }\r
-\r
- public Scriptable getParentScope() {\r
- return parent;\r
- }\r
-\r
- public void setParentScope(Scriptable parent) {\r
- this.parent = parent;\r
- }\r
-\r
- public Object[] getIds() {\r
- return prototype.getIds();\r
- }\r
-\r
- public Object getDefaultValue(Class typeHint) {\r
- return prototype.getDefaultValue(typeHint);\r
- }\r
-\r
- public boolean hasInstance(Scriptable value) {\r
- return prototype.hasInstance(value);\r
- }\r
-\r
- public Object execMethod(int methodId, IdFunction function, Context cx,\r
- Scriptable scope, Scriptable thisObj, \r
- Object[] args)\r
- throws JavaScriptException\r
- {\r
- if (prototypeFlag) {\r
- if (methodId == Id_constructor) {\r
- throw Context.reportRuntimeError1\r
- ("msg.cant.call.indirect", "With");\r
- }\r
- }\r
- throw IdFunction.onBadMethodId(this, methodId);\r
- }\r
- \r
- public int methodArity(int methodId) {\r
- if (prototypeFlag) {\r
- if (methodId == Id_constructor) { return 0; }\r
- }\r
- return -1;\r
- }\r
-\r
- public static Object newWithSpecial(Context cx, Object[] args, \r
- Function ctorObj, boolean inNewExpr)\r
- {\r
- if (!inNewExpr) {\r
- throw Context.reportRuntimeError1("msg.only.from.new", "With");\r
- }\r
- \r
- ScriptRuntime.checkDeprecated(cx, "With");\r
- \r
- Scriptable scope = ScriptableObject.getTopLevelScope(ctorObj);\r
- NativeWith thisObj = new NativeWith();\r
- thisObj.setPrototype(args.length == 0\r
- ? ScriptableObject.getClassPrototype(scope,\r
- "Object")\r
- : ScriptRuntime.toObject(scope, args[0]));\r
- thisObj.setParentScope(scope);\r
- return thisObj;\r
- }\r
- \r
- private static final int \r
- Id_constructor = 1;\r
-\r
- private Scriptable prototype;\r
- private Scriptable parent;\r
- private Scriptable constructor;\r
-\r
- private boolean prototypeFlag;\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- * Roger Lawrence\r
- * Mike McCabe\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-/**\r
- * This class implements the root of the intermediate representation.\r
- *\r
- * @author Norris Boyd\r
- * @author Mike McCabe\r
- */\r
-\r
-public class Node implements Cloneable {\r
-\r
- public Node(int nodeType) {\r
- type = nodeType;\r
- }\r
-\r
- public Node(int nodeType, Node child) {\r
- type = nodeType;\r
- first = last = child;\r
- child.next = null;\r
- }\r
-\r
- public Node(int nodeType, Node left, Node right) {\r
- type = nodeType;\r
- first = left;\r
- last = right;\r
- left.next = right;\r
- right.next = null;\r
- }\r
-\r
- public Node(int nodeType, Node left, Node mid, Node right) {\r
- type = nodeType;\r
- first = left;\r
- last = right;\r
- left.next = mid;\r
- mid.next = right;\r
- right.next = null;\r
- }\r
-\r
- public Node(int nodeType, Object datum) {\r
- type = nodeType;\r
- this.datum = datum;\r
- }\r
-\r
- public Node(int nodeType, Node child, Object datum) {\r
- this(nodeType, child);\r
- this.datum = datum;\r
- }\r
-\r
- public Node(int nodeType, Node left, Node right, Object datum) {\r
- this(nodeType, left, right);\r
- this.datum = datum;\r
- }\r
-\r
- public int getType() {\r
- return type;\r
- }\r
-\r
- public void setType(int type) {\r
- this.type = type;\r
- }\r
-\r
- public boolean hasChildren() {\r
- return first != null;\r
- }\r
-\r
- public Node getFirstChild() {\r
- return first;\r
- }\r
-\r
- public Node getLastChild() {\r
- return last;\r
- }\r
-\r
- public Node getNextSibling() {\r
- return next;\r
- }\r
-\r
- public Node getChildBefore(Node child) {\r
- if (child == first)\r
- return null;\r
- Node n = first;\r
- while (n.next != child) {\r
- n = n.next;\r
- if (n == null)\r
- throw new RuntimeException("node is not a child");\r
- }\r
- return n;\r
- }\r
-\r
- public Node getLastSibling() {\r
- Node n = this;\r
- while (n.next != null) {\r
- n = n.next;\r
- }\r
- return n;\r
- }\r
-\r
- public ShallowNodeIterator getChildIterator() {\r
- return new ShallowNodeIterator(first);\r
- }\r
-\r
- public PreorderNodeIterator getPreorderIterator() {\r
- return new PreorderNodeIterator(this);\r
- }\r
-\r
- public void addChildToFront(Node child) {\r
- child.next = first;\r
- first = child;\r
- if (last == null) {\r
- last = child;\r
- }\r
- }\r
-\r
- public void addChildToBack(Node child) {\r
- child.next = null;\r
- if (last == null) {\r
- first = last = child;\r
- return;\r
- }\r
- last.next = child;\r
- last = child;\r
- }\r
-\r
- public void addChildrenToFront(Node children) {\r
- Node lastSib = children.getLastSibling();\r
- lastSib.next = first;\r
- first = children;\r
- if (last == null) {\r
- last = lastSib;\r
- }\r
- }\r
-\r
- public void addChildrenToBack(Node children) {\r
- if (last != null) {\r
- last.next = children;\r
- }\r
- last = children.getLastSibling();\r
- if (first == null) {\r
- first = children;\r
- }\r
- }\r
-\r
- /**\r
- * Add 'child' before 'node'.\r
- */\r
- public void addChildBefore(Node newChild, Node node) {\r
- if (newChild.next != null)\r
- throw new RuntimeException(\r
- "newChild had siblings in addChildBefore");\r
- if (first == node) {\r
- newChild.next = first;\r
- first = newChild;\r
- return;\r
- }\r
- Node prev = getChildBefore(node);\r
- addChildAfter(newChild, prev);\r
- }\r
-\r
- /**\r
- * Add 'child' after 'node'.\r
- */\r
- public void addChildAfter(Node newChild, Node node) {\r
- if (newChild.next != null)\r
- throw new RuntimeException(\r
- "newChild had siblings in addChildAfter");\r
- newChild.next = node.next;\r
- node.next = newChild;\r
- if (last == node)\r
- last = newChild;\r
- }\r
-\r
- public void removeChild(Node child) {\r
- Node prev = getChildBefore(child);\r
- if (prev == null)\r
- first = first.next;\r
- else\r
- prev.next = child.next;\r
- if (child == last) last = prev;\r
- child.next = null;\r
- }\r
-\r
- public void replaceChild(Node child, Node newChild) {\r
- newChild.next = child.next;\r
- if (child == first) {\r
- first = newChild;\r
- } else {\r
- Node prev = getChildBefore(child);\r
- prev.next = newChild;\r
- }\r
- if (child == last)\r
- last = newChild;\r
- child.next = null;\r
- }\r
-\r
- public static final int\r
- TARGET_PROP = 1,\r
- BREAK_PROP = 2,\r
- CONTINUE_PROP = 3,\r
- ENUM_PROP = 4,\r
- FUNCTION_PROP = 5,\r
- TEMP_PROP = 6,\r
- LOCAL_PROP = 7,\r
- CODEOFFSET_PROP = 8,\r
- FIXUPS_PROP = 9,\r
- VARS_PROP = 10,\r
- USES_PROP = 11,\r
- REGEXP_PROP = 12,\r
- CASES_PROP = 13,\r
- DEFAULT_PROP = 14,\r
- CASEARRAY_PROP = 15,\r
- SOURCENAME_PROP = 16,\r
- SOURCE_PROP = 17,\r
- TYPE_PROP = 18,\r
- SPECIAL_PROP_PROP = 19,\r
- LABEL_PROP = 20,\r
- FINALLY_PROP = 21,\r
- LOCALCOUNT_PROP = 22,\r
- /*\r
- the following properties are defined and manipulated by the\r
- optimizer -\r
- TARGETBLOCK_PROP - the block referenced by a branch node\r
- VARIABLE_PROP - the variable referenced by a BIND or NAME node\r
- LASTUSE_PROP - that variable node is the last reference before\r
- a new def or the end of the block\r
- ISNUMBER_PROP - this node generates code on Number children and\r
- delivers a Number result (as opposed to Objects)\r
- DIRECTCALL_PROP - this call node should emit code to test the function\r
- object against the known class and call diret if it\r
- matches.\r
- */\r
-\r
- TARGETBLOCK_PROP = 23,\r
- VARIABLE_PROP = 24,\r
- LASTUSE_PROP = 25,\r
- ISNUMBER_PROP = 26,\r
- DIRECTCALL_PROP = 27,\r
-\r
- BASE_LINENO_PROP = 28,\r
- END_LINENO_PROP = 29,\r
- SPECIALCALL_PROP = 30,\r
- DEBUGSOURCE_PROP = 31;\r
-\r
- public static final int // this value of the ISNUMBER_PROP specifies\r
- BOTH = 0, // which of the children are Number types\r
- LEFT = 1,\r
- RIGHT = 2;\r
-\r
- private static String propNames[];\r
- \r
- private static final String propToString(int propType) {\r
- if (Context.printTrees && propNames == null) {\r
- // If Context.printTrees is false, the compiler\r
- // can remove all these strings.\r
- String[] a = {\r
- "target",\r
- "break",\r
- "continue",\r
- "enum",\r
- "function",\r
- "temp",\r
- "local",\r
- "codeoffset",\r
- "fixups",\r
- "vars",\r
- "uses",\r
- "regexp",\r
- "cases",\r
- "default",\r
- "casearray",\r
- "sourcename",\r
- "source",\r
- "type",\r
- "special_prop",\r
- "label",\r
- "finally",\r
- "localcount",\r
- "targetblock",\r
- "variable",\r
- "lastuse",\r
- "isnumber",\r
- "directcall",\r
- "base_lineno",\r
- "end_lineno",\r
- "specialcall"\r
- };\r
- propNames = a;\r
- }\r
- return propNames[propType-1];\r
- }\r
-\r
- public Object getProp(int propType) {\r
- if (props == null)\r
- return null;\r
- return props.getObject(propType);\r
- }\r
-\r
- public int getIntProp(int propType, int defaultValue) {\r
- if (props == null)\r
- return defaultValue;\r
- return props.getInt(propType, defaultValue);\r
- }\r
-\r
- public int getExistingIntProp(int propType) {\r
- return props.getExistingInt(propType);\r
- }\r
-\r
- public void putProp(int propType, Object prop) {\r
- if (props == null)\r
- props = new UintMap(2);\r
- if (prop == null)\r
- props.remove(propType);\r
- else\r
- props.put(propType, prop);\r
- }\r
-\r
- public void putIntProp(int propType, int prop) {\r
- if (props == null)\r
- props = new UintMap(2);\r
- props.put(propType, prop);\r
- }\r
-\r
- public Object getDatum() {\r
- return datum;\r
- }\r
-\r
- public void setDatum(Object datum) {\r
- this.datum = datum;\r
- }\r
-\r
- public int getInt() {\r
- return ((Number) datum).intValue();\r
- }\r
-\r
- public double getDouble() {\r
- return ((Number) datum).doubleValue();\r
- }\r
-\r
- public long getLong() {\r
- return ((Number) datum).longValue();\r
- }\r
-\r
- public String getString() {\r
- return (String) datum;\r
- }\r
-\r
- public Node cloneNode() {\r
- Node result;\r
- try {\r
- result = (Node) super.clone();\r
- result.next = null;\r
- result.first = null;\r
- result.last = null;\r
- }\r
- catch (CloneNotSupportedException e) {\r
- throw new RuntimeException(e.getMessage());\r
- }\r
- return result;\r
- }\r
- public String toString() {\r
- return super.toString();\r
- }\r
- /*\r
- public String toString() {\r
- if (Context.printTrees) {\r
- StringBuffer sb = new StringBuffer(TokenStream.tokenToName(type));\r
- if (type == TokenStream.TARGET) {\r
- sb.append(' ');\r
- sb.append(hashCode());\r
- }\r
- if (datum != null) {\r
- sb.append(' ');\r
- sb.append(datum.toString());\r
- }\r
- if (props == null)\r
- return sb.toString();\r
-\r
- int[] keys = props.getKeys();\r
- for (int i = 0; i != keys.length; ++i) {\r
- int key = keys[i];\r
- sb.append(" [");\r
- sb.append(propToString(key));\r
- sb.append(": ");\r
- switch (key) {\r
- case FIXUPS_PROP : // can't add this as it recurses\r
- sb.append("fixups property");\r
- break;\r
- case SOURCE_PROP : // can't add this as it has unprintables\r
- sb.append("source property");\r
- break;\r
- case TARGETBLOCK_PROP : // can't add this as it recurses\r
- sb.append("target block property");\r
- break;\r
- case LASTUSE_PROP : // can't add this as it is dull\r
- sb.append("last use property");\r
- break;\r
- default :\r
- if (props.isObjectType(key)) {\r
- sb.append(props.getObject(key).toString());\r
- }\r
- else {\r
- sb.append(props.getExistingInt(key));\r
- }\r
- break;\r
- }\r
- sb.append(']');\r
- }\r
- return sb.toString();\r
- }\r
- return null;\r
- }\r
- */\r
- public String toStringTree() {\r
- return toStringTreeHelper(0);\r
- }\r
- \r
-\r
- private String toStringTreeHelper(int level) {\r
- if (Context.printTrees) {\r
- StringBuffer s = new StringBuffer();\r
- for (int i=0; i < level; i++) {\r
- s.append(" ");\r
- }\r
- s.append(toString());\r
- s.append('\n');\r
- ShallowNodeIterator iterator = getChildIterator();\r
- if (iterator != null) {\r
- while (iterator.hasMoreElements()) {\r
- Node n = (Node) iterator.nextElement();\r
- if (n.getType() == TokenStream.FUNCTION) {\r
- Node p = (Node) n.getProp(Node.FUNCTION_PROP);\r
- if (p != null)\r
- n = p;\r
- }\r
- s.append(n.toStringTreeHelper(level+1));\r
- }\r
- }\r
- return s.toString();\r
- }\r
- return "";\r
- }\r
-\r
- public Node getFirst() { return first; }\r
- public Node getNext() { return next; }\r
-\r
- protected int type; // type of the node; TokenStream.NAME for example\r
- protected Node next; // next sibling\r
- protected Node first; // first element of a linked list of children\r
- protected Node last; // last element of a linked list of children\r
- protected UintMap props;\r
- protected Object datum; // encapsulated data; depends on type\r
-}\r
-\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- * Roger Lawrence\r
- * Mike McCabe\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-import java.util.Hashtable;\r
-import java.util.Stack;\r
-import java.util.Vector;\r
-\r
-/**\r
- * This class transforms a tree to a lower-level representation for codegen.\r
- *\r
- * @see Node\r
- * @author Norris Boyd\r
- */\r
-\r
-public class NodeTransformer {\r
- \r
- /**\r
- * Return new instance of this class. So that derived classes\r
- * can override methods of the transformer.\r
- */\r
- public NodeTransformer newInstance() {\r
- return new NodeTransformer();\r
- }\r
- \r
- public IRFactory createIRFactory(TokenStream ts, Scriptable scope) {\r
- return new IRFactory(ts, scope);\r
- }\r
-\r
- public Node transform(Node tree, Node enclosing, TokenStream ts,\r
- Scriptable scope) \r
- {\r
- loops = new Stack();\r
- loopEnds = new Stack();\r
- inFunction = tree.getType() == TokenStream.FUNCTION;\r
- if (!inFunction) {\r
- addVariables(tree, getVariableTable(tree));\r
- }\r
- irFactory = createIRFactory(ts, scope);\r
-\r
- // to save against upchecks if no finally blocks are used.\r
- boolean hasFinally = false;\r
-\r
- PreorderNodeIterator iterator = tree.getPreorderIterator();\r
- Node node;\r
- while ((node = iterator.nextNode()) != null) {\r
- int type = node.getType();\r
-\r
- typeswitch:\r
- switch (type) {\r
-\r
- case TokenStream.FUNCTION:\r
- if (node == tree) {\r
- // Add the variables to variable table, the\r
- // parameters were added earlier.\r
- VariableTable vars = getVariableTable(tree);\r
- addVariables(tree, vars);\r
-\r
- // Add return to end if needed.\r
- Node stmts = node.getLastChild();\r
- Node lastStmt = stmts.getLastChild();\r
- if (lastStmt == null ||\r
- lastStmt.getType() != TokenStream.RETURN)\r
- {\r
- stmts.addChildToBack(new Node(TokenStream.RETURN));\r
- }\r
-\r
- } else {\r
- FunctionNode fnNode = (FunctionNode)\r
- node.getProp(Node.FUNCTION_PROP);\r
- if (inFunction) {\r
- // Functions containing other functions require \r
- // activation objects \r
- ((FunctionNode) tree).setRequiresActivation(true);\r
-\r
- // Nested functions must check their 'this' value to\r
- // insure it is not an activation object:\r
- // see 10.1.6 Activation Object\r
- fnNode.setCheckThis(true);\r
- }\r
- addParameters(fnNode);\r
- NodeTransformer inner = newInstance();\r
- fnNode = (FunctionNode) \r
- inner.transform(fnNode, tree, ts, scope);\r
- node.putProp(Node.FUNCTION_PROP, fnNode);\r
- Vector fns = (Vector) tree.getProp(Node.FUNCTION_PROP);\r
- if (fns == null) {\r
- fns = new Vector(7);\r
- tree.putProp(Node.FUNCTION_PROP, fns);\r
- }\r
- fns.addElement(fnNode);\r
- }\r
- break;\r
-\r
- case TokenStream.LABEL:\r
- {\r
- Node child = node.getFirstChild();\r
- node.removeChild(child);\r
- String id = child.getString();\r
-\r
- // check against duplicate labels...\r
- for (int i=loops.size()-1; i >= 0; i--) {\r
- Node n = (Node) loops.elementAt(i);\r
- if (n.getType() == TokenStream.LABEL) {\r
- String otherId = (String)n.getProp(Node.LABEL_PROP);\r
- if (id.equals(otherId)) {\r
- String message = Context.getMessage1(\r
- "msg.dup.label", id);\r
- reportMessage(Context.getContext(), message, node, \r
- tree, true, scope);\r
- break typeswitch;\r
- }\r
- }\r
- }\r
-\r
- node.putProp(Node.LABEL_PROP, id);\r
-\r
- /* Make a target and put it _after_ the following\r
- * node. And in the LABEL node, so breaks get the\r
- * right target.\r
- */\r
- Node breakTarget = new Node(TokenStream.TARGET);\r
- Node parent = iterator.getCurrentParent();\r
- Node next = node.getNextSibling();\r
- while (next != null &&\r
- (next.getType() == TokenStream.LABEL ||\r
- next.getType() == TokenStream.TARGET))\r
- next = next.getNextSibling();\r
- if (next == null)\r
- break;\r
- parent.addChildAfter(breakTarget, next);\r
- node.putProp(Node.BREAK_PROP, breakTarget);\r
- \r
- if (next.getType() == TokenStream.LOOP) {\r
- node.putProp(Node.CONTINUE_PROP, \r
- next.getProp(Node.CONTINUE_PROP));\r
- } \r
-\r
- loops.push(node);\r
- loopEnds.push(breakTarget);\r
-\r
- break;\r
- }\r
-\r
- case TokenStream.SWITCH:\r
- {\r
- Node breakTarget = new Node(TokenStream.TARGET);\r
- Node parent = iterator.getCurrentParent();\r
- parent.addChildAfter(breakTarget, node);\r
-\r
- // make all children siblings except for selector\r
- Node sib = node;\r
- Node child = node.getFirstChild().next;\r
- while (child != null) {\r
- Node next = child.next;\r
- node.removeChild(child);\r
- parent.addChildAfter(child, sib);\r
- sib = child;\r
- child = next;\r
- }\r
-\r
- node.putProp(Node.BREAK_PROP, breakTarget);\r
- loops.push(node);\r
- loopEnds.push(breakTarget);\r
- node.putProp(Node.CASES_PROP, new Vector(13));\r
- break;\r
- }\r
-\r
- case TokenStream.DEFAULT:\r
- case TokenStream.CASE:\r
- {\r
- Node sw = (Node) loops.peek();\r
- if (type == TokenStream.CASE) {\r
- Vector cases = (Vector) sw.getProp(Node.CASES_PROP);\r
- cases.addElement(node);\r
- } else {\r
- sw.putProp(Node.DEFAULT_PROP, node);\r
- }\r
- break;\r
- }\r
-\r
- case TokenStream.NEWLOCAL : {\r
- Integer localCount\r
- = (Integer)(tree.getProp(Node.LOCALCOUNT_PROP));\r
- if (localCount == null) {\r
- tree.putProp(Node.LOCALCOUNT_PROP, new Integer(1));\r
- }\r
- else {\r
- tree.putProp(Node.LOCALCOUNT_PROP,\r
- new Integer(localCount.intValue() + 1));\r
- }\r
- }\r
- break;\r
-\r
- case TokenStream.LOOP:\r
- loops.push(node);\r
- loopEnds.push(node.getProp(Node.BREAK_PROP));\r
- break;\r
-\r
- case TokenStream.WITH:\r
- {\r
- if (inFunction) {\r
- // With statements require an activation object.\r
- ((FunctionNode) tree).setRequiresActivation(true);\r
- }\r
- loops.push(node);\r
- Node leave = node.getNextSibling();\r
- if (leave.getType() != TokenStream.LEAVEWITH) {\r
- throw new RuntimeException("Unexpected tree");\r
- }\r
- loopEnds.push(leave);\r
- break;\r
- }\r
-\r
- case TokenStream.TRY:\r
- {\r
- Node finallytarget = (Node)node.getProp(Node.FINALLY_PROP);\r
- if (finallytarget != null) {\r
- hasFinally = true;\r
- loops.push(node);\r
- loopEnds.push(finallytarget);\r
- }\r
- Integer localCount\r
- = (Integer)(tree.getProp(Node.LOCALCOUNT_PROP));\r
- if (localCount == null) {\r
- tree.putProp(Node.LOCALCOUNT_PROP, new Integer(1));\r
- }\r
- else {\r
- tree.putProp(Node.LOCALCOUNT_PROP,\r
- new Integer(localCount.intValue() + 1));\r
- }\r
- break;\r
- }\r
-\r
- case TokenStream.TARGET:\r
- case TokenStream.LEAVEWITH:\r
- if (!loopEnds.empty() && loopEnds.peek() == node) {\r
- loopEnds.pop();\r
- loops.pop();\r
- }\r
- break;\r
-\r
- case TokenStream.RETURN:\r
- {\r
- /* If we didn't support try/finally, it wouldn't be\r
- * necessary to put LEAVEWITH nodes here... but as\r
- * we do need a series of JSR FINALLY nodes before\r
- * each RETURN, we need to ensure that each finally\r
- * block gets the correct scope... which could mean\r
- * that some LEAVEWITH nodes are necessary.\r
- */\r
- if (!hasFinally)\r
- break; // skip the whole mess.\r
-\r
- Node parent = iterator.getCurrentParent();\r
- for (int i=loops.size()-1; i >= 0; i--) {\r
- Node n = (Node) loops.elementAt(i);\r
- int elemtype = n.getType();\r
- if (elemtype == TokenStream.TRY) {\r
- Node jsrnode = new Node(TokenStream.JSR);\r
- Object jsrtarget = n.getProp(Node.FINALLY_PROP);\r
- jsrnode.putProp(Node.TARGET_PROP, jsrtarget);\r
- parent.addChildBefore(jsrnode, node);\r
- } else if (elemtype == TokenStream.WITH) {\r
- parent.addChildBefore(new Node(TokenStream.LEAVEWITH),\r
- node);\r
- }\r
- }\r
- break;\r
- }\r
-\r
- case TokenStream.BREAK:\r
- case TokenStream.CONTINUE:\r
- {\r
- Node loop = null;\r
- boolean labelled = node.hasChildren();\r
- String id = null;\r
- if (labelled) {\r
- /* get the label */\r
- Node child = node.getFirstChild();\r
- id = child.getString();\r
- node.removeChild(child);\r
- }\r
-\r
- int i;\r
- Node parent = iterator.getCurrentParent();\r
- for (i=loops.size()-1; i >= 0; i--) {\r
- Node n = (Node) loops.elementAt(i);\r
- int elemtype = n.getType();\r
- if (elemtype == TokenStream.WITH) {\r
- parent.addChildBefore(new Node(TokenStream.LEAVEWITH),\r
- node);\r
- } else if (elemtype == TokenStream.TRY) {\r
- Node jsrFinally = new Node(TokenStream.JSR);\r
- Object jsrTarget = n.getProp(Node.FINALLY_PROP);\r
- jsrFinally.putProp(Node.TARGET_PROP, jsrTarget);\r
- parent.addChildBefore(jsrFinally, node);\r
- } else if (!labelled &&\r
- (elemtype == TokenStream.LOOP ||\r
- (elemtype == TokenStream.SWITCH &&\r
- type == TokenStream.BREAK)))\r
- {\r
- /* if it's a simple break/continue, break from the\r
- * nearest enclosing loop or switch\r
- */\r
- loop = n;\r
- break;\r
- } else if (labelled &&\r
- elemtype == TokenStream.LABEL &&\r
- id.equals((String)n.getProp(Node.LABEL_PROP)))\r
- {\r
- loop = n;\r
- break;\r
- }\r
- }\r
- int propType = type == TokenStream.BREAK\r
- ? Node.BREAK_PROP\r
- : Node.CONTINUE_PROP;\r
- Node target = loop == null \r
- ? null\r
- : (Node) loop.getProp(propType);\r
- if (loop == null || target == null) {\r
- String message;\r
- if (!labelled) {\r
- // didn't find an appropriate target\r
- if (type == TokenStream.CONTINUE) {\r
- message = Context.getMessage\r
- ("msg.continue.outside", null);\r
- } else {\r
- message = Context.getMessage\r
- ("msg.bad.break", null);\r
- }\r
- } else if (loop != null) {\r
- message = Context.getMessage0("msg.continue.nonloop");\r
- } else {\r
- Object[] errArgs = { id };\r
- message = Context.getMessage\r
- ("msg.undef.label", errArgs);\r
- }\r
- reportMessage(Context.getContext(), message, node, \r
- tree, true, scope);\r
- node.setType(TokenStream.NOP);\r
- break;\r
- }\r
- node.setType(TokenStream.GOTO);\r
- node.putProp(Node.TARGET_PROP, target);\r
- break;\r
- }\r
-\r
- case TokenStream.CALL:\r
- if (isSpecialCallName(tree, node))\r
- node.putProp(Node.SPECIALCALL_PROP, Boolean.TRUE);\r
- visitCall(node, tree);\r
- break;\r
-\r
- case TokenStream.NEW:\r
- if (isSpecialCallName(tree, node))\r
- node.putProp(Node.SPECIALCALL_PROP, Boolean.TRUE);\r
- visitNew(node, tree);\r
- break;\r
-\r
- case TokenStream.DOT:\r
- {\r
- Node right = node.getLastChild();\r
- right.setType(TokenStream.STRING);\r
- break;\r
- }\r
-\r
- case TokenStream.EXPRSTMT:\r
- node.setType(inFunction ? TokenStream.POP : TokenStream.POPV);\r
- break;\r
-\r
- case TokenStream.OBJECT:\r
- {\r
- Vector regexps = (Vector) tree.getProp(Node.REGEXP_PROP);\r
- if (regexps == null) {\r
- regexps = new Vector(3);\r
- tree.putProp(Node.REGEXP_PROP, regexps);\r
- }\r
- regexps.addElement(node);\r
- Node n = new Node(TokenStream.OBJECT);\r
- iterator.replaceCurrent(n);\r
- n.putProp(Node.REGEXP_PROP, node);\r
- break;\r
- }\r
-\r
- case TokenStream.VAR:\r
- {\r
- ShallowNodeIterator i = node.getChildIterator();\r
- Node result = new Node(TokenStream.BLOCK);\r
- while (i.hasMoreElements()) {\r
- Node n = i.nextNode();\r
- if (!n.hasChildren())\r
- continue;\r
- Node init = n.getFirstChild();\r
- n.removeChild(init);\r
- Node asn = (Node) irFactory.createAssignment(\r
- TokenStream.NOP, n, init, null,\r
- false);\r
- Node pop = new Node(TokenStream.POP, asn, node.getDatum());\r
- result.addChildToBack(pop);\r
- }\r
- iterator.replaceCurrent(result);\r
- break;\r
- }\r
-\r
- case TokenStream.DELPROP:\r
- case TokenStream.SETNAME:\r
- {\r
- if (!inFunction || inWithStatement())\r
- break;\r
- Node bind = node.getFirstChild();\r
- if (bind == null || bind.getType() != TokenStream.BINDNAME)\r
- break;\r
- String name = bind.getString();\r
- Context cx = Context.getCurrentContext();\r
- if (cx != null && cx.isActivationNeeded(name)) {\r
- // use of "arguments" requires an activation object.\r
- ((FunctionNode) tree).setRequiresActivation(true);\r
- }\r
- VariableTable vars = getVariableTable(tree);\r
- if (vars.getVariable(name) != null) {\r
- if (type == TokenStream.SETNAME) {\r
- node.setType(TokenStream.SETVAR);\r
- bind.setType(TokenStream.STRING);\r
- } else {\r
- // Local variables are by definition permanent\r
- Node n = new Node(TokenStream.PRIMARY,\r
- new Integer(TokenStream.FALSE));\r
- iterator.replaceCurrent(n);\r
- }\r
- }\r
- break;\r
- }\r
- \r
- case TokenStream.GETPROP:\r
- if (inFunction) {\r
- Node n = node.getFirstChild().getNextSibling();\r
- String name = n == null ? "" : n.getString();\r
- Context cx = Context.getCurrentContext();\r
- if ((cx != null && cx.isActivationNeeded(name)) ||\r
- (name.equals("length") && \r
- Context.getContext().getLanguageVersion() == \r
- Context.VERSION_1_2))\r
- {\r
- // Use of "arguments" or "length" in 1.2 requires \r
- // an activation object.\r
- ((FunctionNode) tree).setRequiresActivation(true);\r
- }\r
- }\r
- break;\r
-\r
- case TokenStream.NAME:\r
- {\r
- if (!inFunction || inWithStatement())\r
- break;\r
- String name = node.getString();\r
- Context cx = Context.getCurrentContext();\r
- if (cx != null && cx.isActivationNeeded(name)) {\r
- // Use of "arguments" requires an activation object.\r
- ((FunctionNode) tree).setRequiresActivation(true);\r
- }\r
- VariableTable vars = getVariableTable(tree);\r
- if (vars.getVariable(name) != null) {\r
- node.setType(TokenStream.GETVAR);\r
- }\r
- break;\r
- }\r
- }\r
- }\r
-\r
- return tree;\r
- }\r
-\r
- protected void addVariables(Node tree, VariableTable vars) {\r
- // OPT: a whole pass to collect variables seems expensive.\r
- // Could special case to go into statements only.\r
- boolean inFunction = tree.getType() == TokenStream.FUNCTION;\r
- PreorderNodeIterator iterator = tree.getPreorderIterator();\r
- Hashtable ht = null;\r
- Node node;\r
- while ((node = iterator.nextNode()) != null) {\r
- int nodeType = node.getType();\r
- if (inFunction && nodeType == TokenStream.FUNCTION &&\r
- node != tree && \r
- ((FunctionNode) node.getProp(Node.FUNCTION_PROP)).getFunctionType() == \r
- FunctionNode.FUNCTION_EXPRESSION_STATEMENT) \r
- {\r
- // In a function with both "var x" and "function x",\r
- // disregard the var statement, independent of order.\r
- String name = node.getString();\r
- if (name == null)\r
- continue;\r
- vars.removeLocal(name);\r
- if (ht == null)\r
- ht = new Hashtable();\r
- ht.put(name, Boolean.TRUE);\r
- }\r
- if (nodeType != TokenStream.VAR)\r
- continue;\r
- ShallowNodeIterator i = node.getChildIterator();\r
- while (i.hasMoreElements()) {\r
- Node n = i.nextNode();\r
- if (ht == null || ht.get(n.getString()) == null)\r
- vars.addLocal(n.getString());\r
- }\r
- }\r
- String name = (String) tree.getDatum();\r
- if (inFunction && ((FunctionNode) tree).getFunctionType() ==\r
- FunctionNode.FUNCTION_EXPRESSION &&\r
- name != null && name.length() > 0 &&\r
- vars.getVariable(name) == null)\r
- {\r
- // A function expression needs to have its name as a variable\r
- // (if it isn't already allocated as a variable). See \r
- // ECMA Ch. 13. We add code to the beginning of the function\r
- // to initialize a local variable of the function's name\r
- // to the function value.\r
- vars.addLocal(name);\r
- Node block = tree.getLastChild();\r
- Node setFn = new Node(TokenStream.POP,\r
- new Node(TokenStream.SETVAR,\r
- new Node(TokenStream.STRING, name),\r
- new Node(TokenStream.PRIMARY,\r
- new Integer(TokenStream.THISFN))));\r
- block.addChildrenToFront(setFn);\r
- }\r
- }\r
-\r
- protected void addParameters(FunctionNode fnNode) {\r
- VariableTable vars = fnNode.getVariableTable();\r
- Node args = fnNode.getFirstChild();\r
- if (args.getType() == TokenStream.LP && vars.getParameterCount() == 0)\r
- {\r
- // Add parameters\r
- ShallowNodeIterator i = args.getChildIterator();\r
- while (i.hasMoreElements()) {\r
- Node n = i.nextNode();\r
- String arg = n.getString();\r
- vars.addParameter(arg);\r
- }\r
- }\r
- }\r
- \r
- protected void visitNew(Node node, Node tree) {\r
- }\r
-\r
- protected void visitCall(Node node, Node tree) {\r
- /*\r
- * For\r
- * Call(GetProp(a, b), c, d) // or GetElem...\r
- * we wish to evaluate as\r
- * Call(GetProp(tmp=a, b), tmp, c, d)\r
- *\r
- * for\r
- * Call(Name("a"), b, c)\r
- * we wish to evaluate as\r
- * Call(GetProp(tmp=GetBase("a"), "a"), tmp, b, c)\r
- *\r
- * and for\r
- * Call(a, b, c);\r
- * we wish to evaluate as\r
- * Call(tmp=a, Parent(tmp), c, d)\r
- */\r
- Node left = node.getFirstChild();\r
- // count the arguments\r
- int argCount = 0;\r
- Node arg = left.getNextSibling();\r
- while (arg != null) {\r
- arg = arg.getNextSibling();\r
- argCount++;\r
- }\r
- boolean addGetThis = false;\r
- if (left.getType() == TokenStream.NAME) {\r
- VariableTable vars = getVariableTable(tree);\r
- String name = left.getString();\r
- if (inFunction && vars.getVariable(name) != null && \r
- !inWithStatement()) \r
- {\r
- // call to a var. Transform to Call(GetVar("a"), b, c)\r
- left.setType(TokenStream.GETVAR);\r
- // fall through to code to add GetParent\r
- } else {\r
- // transform to Call(GetProp(GetBase("a"), "a"), b, c)\r
-\r
- node.removeChild(left);\r
- left.setType(TokenStream.GETBASE);\r
- Node str = left.cloneNode();\r
- str.setType(TokenStream.STRING);\r
- Node getProp = new Node(TokenStream.GETPROP, left, str);\r
- node.addChildToFront(getProp);\r
- left = getProp;\r
-\r
- // Conditionally set a flag to add a GETTHIS node.\r
- // The getThis entry in the runtime will take a\r
- // Scriptable object intended to be used as a 'this'\r
- // and make sure that it is neither a With object or\r
- // an activation object.\r
- // Executing getThis requires at least two instanceof\r
- // tests, so we only include it if we are currently\r
- // inside a 'with' statement, or if we are executing\r
- // a script (to protect against an eval inside a with).\r
- addGetThis = inWithStatement() || !inFunction;\r
- // fall through to GETPROP code\r
- }\r
- }\r
- if (left.getType() != TokenStream.GETPROP &&\r
- left.getType() != TokenStream.GETELEM)\r
- {\r
- node.removeChild(left);\r
- Node tmp = irFactory.createNewTemp(left);\r
- Node use = irFactory.createUseTemp(tmp);\r
- use.putProp(Node.TEMP_PROP, tmp);\r
- Node parent = new Node(TokenStream.PARENT, use);\r
- node.addChildToFront(parent);\r
- node.addChildToFront(tmp);\r
- return;\r
- }\r
- Node leftLeft = left.getFirstChild();\r
- left.removeChild(leftLeft);\r
- Node tmp = irFactory.createNewTemp(leftLeft);\r
- left.addChildToFront(tmp);\r
- Node use = irFactory.createUseTemp(tmp);\r
- use.putProp(Node.TEMP_PROP, tmp);\r
- if (addGetThis)\r
- use = new Node(TokenStream.GETTHIS, use);\r
- node.addChildAfter(use, left);\r
- }\r
-\r
- protected boolean inWithStatement() {\r
- for (int i=loops.size()-1; i >= 0; i--) {\r
- Node n = (Node) loops.elementAt(i);\r
- if (n.getType() == TokenStream.WITH)\r
- return true;\r
- }\r
- return false;\r
- }\r
-\r
- /**\r
- * Return true if the node is a call to a function that requires \r
- * access to the enclosing activation object.\r
- */\r
- private boolean isSpecialCallName(Node tree, Node node) {\r
- Node left = node.getFirstChild();\r
- boolean isSpecial = false;\r
- if (left.getType() == TokenStream.NAME) {\r
- String name = left.getString();\r
- isSpecial = name.equals("eval") || name.equals("With");\r
- } else {\r
- if (left.getType() == TokenStream.GETPROP) {\r
- String name = left.getLastChild().getString();\r
- isSpecial = name.equals("exec");\r
- }\r
- }\r
- if (isSpecial) {\r
- // Calls to these functions require activation objects.\r
- if (inFunction)\r
- ((FunctionNode) tree).setRequiresActivation(true);\r
- return true;\r
- }\r
- return false;\r
- }\r
-\r
- protected VariableTable createVariableTable() {\r
- return new VariableTable();\r
- }\r
-\r
- protected VariableTable getVariableTable(Node tree) {\r
- if (inFunction) {\r
- return ((FunctionNode)tree).getVariableTable();\r
- }\r
- VariableTable result = (VariableTable)(tree.getProp(Node.VARS_PROP));\r
- if (result == null) {\r
- result = createVariableTable();\r
- tree.putProp(Node.VARS_PROP, result);\r
- }\r
- return result;\r
- }\r
- \r
- protected void reportMessage(Context cx, String msg, Node stmt, \r
- Node tree, boolean isError,\r
- Scriptable scope)\r
- {\r
- Object obj = stmt.getDatum();\r
- int lineno = 0;\r
- if (obj != null && obj instanceof Integer)\r
- lineno = ((Integer) obj).intValue();\r
- Object prop = tree == null \r
- ? null\r
- : tree.getProp(Node.SOURCENAME_PROP);\r
- if (isError) {\r
- if (scope != null)\r
- throw NativeGlobal.constructError(\r
- cx, "SyntaxError", msg, scope, \r
- (String) prop, lineno, 0, null);\r
- else\r
- cx.reportError(msg, (String) prop, lineno, null, 0);\r
- }\r
- else\r
- cx.reportWarning(msg, (String) prop, lineno, null, 0); \r
- }\r
-\r
- protected Stack loops;\r
- protected Stack loopEnds;\r
- protected boolean inFunction;\r
- protected IRFactory irFactory;\r
-}\r
-\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-// API class\r
-\r
-package org.mozilla.javascript;\r
-\r
-/**\r
- * Thrown if call is attempted on an object that is not a function.\r
- */\r
-public class NotAFunctionException extends Exception {\r
-\r
- public NotAFunctionException() {\r
- }\r
-\r
- public NotAFunctionException(String detail) {\r
- super(detail);\r
- }\r
-\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Mike Ang\r
- * Mike McCabe\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-import org.mozilla.javascript.ErrorReporter;\r
-import org.mozilla.javascript.Context;\r
-import java.io.IOException;\r
-\r
-/**\r
- * This class implements the JavaScript parser.\r
- *\r
- * It is based on the C source files jsparse.c and jsparse.h\r
- * in the jsref package.\r
- *\r
- * @see TokenStream\r
- *\r
- * @author Mike McCabe\r
- * @author Brendan Eich\r
- */\r
-\r
-class Parser {\r
-\r
- public Parser(IRFactory nf) {\r
- this.nf = nf;\r
- }\r
-\r
- private void mustMatchToken(TokenStream ts, int toMatch, String messageId)\r
- throws IOException, JavaScriptException\r
- {\r
- int tt;\r
- if ((tt = ts.getToken()) != toMatch) {\r
- reportError(ts, messageId);\r
- ts.ungetToken(tt); // In case the parser decides to continue\r
- }\r
- }\r
- \r
- private void reportError(TokenStream ts, String messageId) \r
- throws JavaScriptException\r
- {\r
- this.ok = false;\r
- ts.reportSyntaxError(messageId, null);\r
- \r
- /* Throw an exception to unwind the recursive descent parse. \r
- * We use JavaScriptException here even though it is really \r
- * a different use of the exception than it is usually used\r
- * for.\r
- */\r
- throw new JavaScriptException(messageId);\r
- }\r
-\r
- /*\r
- * Build a parse tree from the given TokenStream. \r
- *\r
- * @param ts the TokenStream to parse\r
- *\r
- * @return an Object representing the parsed\r
- * program. If the parse fails, null will be returned. (The\r
- * parse failure will result in a call to the current Context's\r
- * ErrorReporter.)\r
- */\r
- public Object parse(TokenStream ts)\r
- throws IOException\r
- {\r
- this.ok = true;\r
- Source source = new Source();\r
-\r
- int tt; // last token from getToken();\r
- int baseLineno = ts.getLineno(); // line number where source starts\r
-\r
- /* so we have something to add nodes to until\r
- * we've collected all the source */\r
- Object tempBlock = nf.createLeaf(TokenStream.BLOCK);\r
-\r
- while (true) {\r
- ts.flags |= ts.TSF_REGEXP;\r
- tt = ts.getToken();\r
- ts.flags &= ~ts.TSF_REGEXP;\r
-\r
- if (tt <= ts.EOF) {\r
- break;\r
- }\r
-\r
- if (tt == ts.FUNCTION) {\r
- try {\r
- nf.addChildToBack(tempBlock, function(ts, source, false));\r
- /* function doesn't add its own final EOL,\r
- * because it gets SEMI + EOL from Statement when it's\r
- * a nested function; so we need to explicitly add an\r
- * EOL here.\r
- */\r
- source.append((char)ts.EOL);\r
- wellTerminated(ts, ts.FUNCTION);\r
- } catch (JavaScriptException e) {\r
- this.ok = false;\r
- break;\r
- }\r
- } else {\r
- ts.ungetToken(tt);\r
- nf.addChildToBack(tempBlock, statement(ts, source));\r
- }\r
- }\r
-\r
- if (!this.ok) {\r
- // XXX ts.clearPushback() call here?\r
- return null;\r
- }\r
-\r
- Object pn = nf.createScript(tempBlock, ts.getSourceName(),\r
- baseLineno, ts.getLineno(),\r
- source.buf.toString());\r
- return pn;\r
- }\r
-\r
- /*\r
- * The C version of this function takes an argument list,\r
- * which doesn't seem to be needed for tree generation...\r
- * it'd only be useful for checking argument hiding, which\r
- * I'm not doing anyway...\r
- */\r
- private Object parseFunctionBody(TokenStream ts, Source source)\r
- throws IOException\r
- {\r
- int oldflags = ts.flags;\r
- ts.flags &= ~(TokenStream.TSF_RETURN_EXPR\r
- | TokenStream.TSF_RETURN_VOID);\r
- ts.flags |= TokenStream.TSF_FUNCTION;\r
-\r
- Object pn = nf.createBlock(ts.getLineno());\r
- try {\r
- int tt;\r
- while((tt = ts.peekToken()) > ts.EOF && tt != ts.RC) {\r
- if (tt == TokenStream.FUNCTION) {\r
- ts.getToken();\r
- nf.addChildToBack(pn, function(ts, source, false));\r
- /* function doesn't add its own final EOL,\r
- * because it gets SEMI + EOL from Statement when it's\r
- * a nested function; so we need to explicitly add an\r
- * EOL here.\r
- */\r
- source.append((char)ts.EOL);\r
- wellTerminated(ts, ts.FUNCTION); \r
- } else {\r
- nf.addChildToBack(pn, statement(ts, source));\r
- }\r
- }\r
- } catch (JavaScriptException e) {\r
- this.ok = false;\r
- } finally {\r
- // also in finally block:\r
- // flushNewLines, clearPushback.\r
-\r
- ts.flags = oldflags;\r
- }\r
-\r
- return pn;\r
- }\r
-\r
- private Object function(TokenStream ts, Source source, boolean isExpr)\r
- throws IOException, JavaScriptException\r
- {\r
- String name = null;\r
- Object args = nf.createLeaf(ts.LP);\r
- Object body;\r
- int baseLineno = ts.getLineno(); // line number where source starts\r
-\r
- // save a reference to the function in the enclosing source.\r
- source.append((char) ts.FUNCTION);\r
- source.append(source.functionNumber);\r
- source.functionNumber++;\r
-\r
- // make a new Source for the enclosed function\r
- source = new Source();\r
-\r
- // FUNCTION as the first token in a Source means it's a function\r
- // definition, and not a reference.\r
- source.append((char) ts.FUNCTION);\r
-\r
- if (ts.matchToken(ts.NAME)) {\r
- // HACK: XWT does not support named functions
- throw new IOException(
- "named functions are not supported, use anonymos "+
- "declaration (myfun = function() {...}"
- );
- }\r
- else\r
- ; // it's an anonymous function\r
-\r
- mustMatchToken(ts, ts.LP, "msg.no.paren.parms");\r
- source.append((char) ts.LP);\r
-\r
- if (!ts.matchToken(ts.RP)) {\r
- boolean first = true;\r
- do {\r
- if (!first)\r
- source.append((char)ts.COMMA);\r
- first = false;\r
- mustMatchToken(ts, ts.NAME, "msg.no.parm");\r
- String s = ts.getString();\r
- nf.addChildToBack(args, nf.createName(s));\r
-\r
- source.addString(ts.NAME, s);\r
- } while (ts.matchToken(ts.COMMA));\r
-\r
- mustMatchToken(ts, ts.RP, "msg.no.paren.after.parms");\r
- }\r
- source.append((char)ts.RP);\r
-\r
- mustMatchToken(ts, ts.LC, "msg.no.brace.body");\r
- source.append((char)ts.LC);\r
- source.append((char)ts.EOL);\r
- body = parseFunctionBody(ts, source);\r
- mustMatchToken(ts, ts.RC, "msg.no.brace.after.body");\r
- source.append((char)ts.RC);\r
- // skip the last EOL so nested functions work...\r
-\r
- // name might be null;\r
- return nf.createFunction(name, args, body,\r
- ts.getSourceName(),\r
- baseLineno, ts.getLineno(),\r
- source.buf.toString(),\r
- isExpr);\r
- }\r
-\r
- private Object statements(TokenStream ts, Source source)\r
- throws IOException\r
- {\r
- Object pn = nf.createBlock(ts.getLineno());\r
-\r
- int tt;\r
- while((tt = ts.peekToken()) > ts.EOF && tt != ts.RC) {\r
- nf.addChildToBack(pn, statement(ts, source));\r
- }\r
-\r
- return pn;\r
- }\r
-\r
- private Object condition(TokenStream ts, Source source)\r
- throws IOException, JavaScriptException\r
- {\r
- Object pn;\r
- mustMatchToken(ts, ts.LP, "msg.no.paren.cond");\r
- source.append((char)ts.LP);\r
- pn = expr(ts, source, false);\r
- mustMatchToken(ts, ts.RP, "msg.no.paren.after.cond");\r
- source.append((char)ts.RP);\r
-\r
- // there's a check here in jsparse.c that corrects = to ==\r
-\r
- return pn;\r
- }\r
-\r
- private boolean wellTerminated(TokenStream ts, int lastExprType)\r
- throws IOException, JavaScriptException\r
- {\r
- int tt = ts.peekTokenSameLine();\r
- if (tt == ts.ERROR) {\r
- return false;\r
- }\r
-\r
- if (tt != ts.EOF && tt != ts.EOL\r
- && tt != ts.SEMI && tt != ts.RC)\r
- {\r
- int version = Context.getContext().getLanguageVersion();\r
- if ((tt == ts.FUNCTION || lastExprType == ts.FUNCTION) &&\r
- (version < Context.VERSION_1_2)) {\r
- /*\r
- * Checking against version < 1.2 and version >= 1.0\r
- * in the above line breaks old javascript, so we keep it\r
- * this way for now... XXX warning needed?\r
- */\r
- return true;\r
- } else {\r
- reportError(ts, "msg.no.semi.stmt");\r
- }\r
- }\r
- return true;\r
- }\r
-\r
- // match a NAME; return null if no match.\r
- private String matchLabel(TokenStream ts)\r
- throws IOException, JavaScriptException\r
- {\r
- int lineno = ts.getLineno();\r
-\r
- String label = null;\r
- int tt;\r
- tt = ts.peekTokenSameLine();\r
- if (tt == ts.NAME) {\r
- ts.getToken();\r
- label = ts.getString();\r
- }\r
-\r
- if (lineno == ts.getLineno())\r
- wellTerminated(ts, ts.ERROR);\r
-\r
- return label;\r
- }\r
-\r
- private Object statement(TokenStream ts, Source source) \r
- throws IOException\r
- {\r
- try {\r
- return statementHelper(ts, source);\r
- } catch (JavaScriptException e) {\r
- // skip to end of statement\r
- int lineno = ts.getLineno();\r
- int t;\r
- do {\r
- t = ts.getToken();\r
- } while (t != TokenStream.SEMI && t != TokenStream.EOL && \r
- t != TokenStream.EOF && t != TokenStream.ERROR);\r
- return nf.createExprStatement(nf.createName("error"), lineno);\r
- }\r
- }\r
- \r
- /**\r
- * Whether the "catch (e: e instanceof Exception) { ... }" syntax\r
- * is implemented.\r
- */\r
- \r
- private Object statementHelper(TokenStream ts, Source source)\r
- throws IOException, JavaScriptException\r
- {\r
- Object pn = null;\r
-\r
- // If skipsemi == true, don't add SEMI + EOL to source at the\r
- // end of this statment. For compound statements, IF/FOR etc.\r
- boolean skipsemi = false;\r
-\r
- int tt;\r
-\r
- int lastExprType = 0; // For wellTerminated. 0 to avoid warning.\r
-\r
- tt = ts.getToken();\r
-\r
- switch(tt) {\r
- case TokenStream.IF: {\r
- skipsemi = true;\r
-\r
- source.append((char)ts.IF);\r
- int lineno = ts.getLineno();\r
- Object cond = condition(ts, source);\r
- source.append((char)ts.LC);\r
- source.append((char)ts.EOL);\r
- Object ifTrue = statement(ts, source);\r
- Object ifFalse = null;\r
- if (ts.matchToken(ts.ELSE)) {\r
- source.append((char)ts.RC);\r
- source.append((char)ts.ELSE);\r
- source.append((char)ts.LC);\r
- source.append((char)ts.EOL);\r
- ifFalse = statement(ts, source);\r
- }\r
- source.append((char)ts.RC);\r
- source.append((char)ts.EOL);\r
- pn = nf.createIf(cond, ifTrue, ifFalse, lineno);\r
- break;\r
- }\r
-\r
- case TokenStream.SWITCH: {\r
- skipsemi = true;\r
-\r
- source.append((char)ts.SWITCH);\r
- pn = nf.createSwitch(ts.getLineno());\r
-\r
- Object cur_case = null; // to kill warning\r
- Object case_statements;\r
-\r
- mustMatchToken(ts, ts.LP, "msg.no.paren.switch");\r
- source.append((char)ts.LP);\r
- nf.addChildToBack(pn, expr(ts, source, false));\r
- mustMatchToken(ts, ts.RP, "msg.no.paren.after.switch");\r
- source.append((char)ts.RP);\r
- mustMatchToken(ts, ts.LC, "msg.no.brace.switch");\r
- source.append((char)ts.LC);\r
- source.append((char)ts.EOL);\r
-\r
- while ((tt = ts.getToken()) != ts.RC && tt != ts.EOF) {\r
- switch(tt) {\r
- case TokenStream.CASE:\r
- source.append((char)ts.CASE);\r
- cur_case = nf.createUnary(ts.CASE, expr(ts, source, false));\r
- source.append((char)ts.COLON);\r
- source.append((char)ts.EOL);\r
- break;\r
-\r
- case TokenStream.DEFAULT:\r
- cur_case = nf.createLeaf(ts.DEFAULT);\r
- source.append((char)ts.DEFAULT);\r
- source.append((char)ts.COLON);\r
- source.append((char)ts.EOL);\r
- // XXX check that there isn't more than one default\r
- break;\r
-\r
- default:\r
- reportError(ts, "msg.bad.switch");\r
- break;\r
- }\r
- mustMatchToken(ts, ts.COLON, "msg.no.colon.case");\r
-\r
- case_statements = nf.createLeaf(TokenStream.BLOCK);\r
-\r
- while ((tt = ts.peekToken()) != ts.RC && tt != ts.CASE &&\r
- tt != ts.DEFAULT && tt != ts.EOF) \r
- {\r
- nf.addChildToBack(case_statements, statement(ts, source));\r
- }\r
- // assert cur_case\r
- nf.addChildToBack(cur_case, case_statements);\r
-\r
- nf.addChildToBack(pn, cur_case);\r
- }\r
- source.append((char)ts.RC);\r
- source.append((char)ts.EOL);\r
- break;\r
- }\r
-\r
- case TokenStream.WHILE: {\r
- skipsemi = true;\r
-\r
- source.append((char)ts.WHILE);\r
- int lineno = ts.getLineno();\r
- Object cond = condition(ts, source);\r
- source.append((char)ts.LC);\r
- source.append((char)ts.EOL);\r
- Object body = statement(ts, source);\r
- source.append((char)ts.RC);\r
- source.append((char)ts.EOL);\r
-\r
- pn = nf.createWhile(cond, body, lineno);\r
- break;\r
-\r
- }\r
-\r
- case TokenStream.DO: {\r
- source.append((char)ts.DO);\r
- source.append((char)ts.LC);\r
- source.append((char)ts.EOL);\r
-\r
- int lineno = ts.getLineno();\r
-\r
- Object body = statement(ts, source);\r
-\r
- source.append((char)ts.RC);\r
- mustMatchToken(ts, ts.WHILE, "msg.no.while.do");\r
- source.append((char)ts.WHILE);\r
- Object cond = condition(ts, source);\r
-\r
- pn = nf.createDoWhile(body, cond, lineno);\r
- break;\r
- }\r
-\r
- case TokenStream.FOR: {\r
- skipsemi = true;\r
-\r
- source.append((char)ts.FOR);\r
- int lineno = ts.getLineno();\r
-\r
- Object init; // Node init is also foo in 'foo in Object'\r
- Object cond; // Node cond is also object in 'foo in Object'\r
- Object incr = null; // to kill warning\r
- Object body;\r
-\r
- mustMatchToken(ts, ts.LP, "msg.no.paren.for");\r
- source.append((char)ts.LP);\r
- tt = ts.peekToken();\r
- if (tt == ts.SEMI) {\r
- init = nf.createLeaf(ts.VOID);\r
- } else {\r
- if (tt == ts.VAR) {\r
- // set init to a var list or initial\r
- ts.getToken(); // throw away the 'var' token\r
- init = variables(ts, source, true);\r
- }\r
- else {\r
- init = expr(ts, source, true);\r
- }\r
- }\r
-\r
- tt = ts.peekToken();\r
- if (tt == ts.RELOP && ts.getOp() == ts.IN) {\r
- ts.matchToken(ts.RELOP);\r
- source.append((char)ts.IN);\r
- // 'cond' is the object over which we're iterating\r
- cond = expr(ts, source, false);\r
- } else { // ordinary for loop\r
- mustMatchToken(ts, ts.SEMI,\r
- "msg.no.semi.for");\r
- source.append((char)ts.SEMI);\r
- if (ts.peekToken() == ts.SEMI) {\r
- // no loop condition\r
- cond = nf.createLeaf(ts.VOID);\r
- } else {\r
- cond = expr(ts, source, false);\r
- }\r
-\r
- mustMatchToken(ts, ts.SEMI,\r
- "msg.no.semi.for.cond");\r
- source.append((char)ts.SEMI);\r
- if (ts.peekToken() == ts.RP) {\r
- incr = nf.createLeaf(ts.VOID);\r
- } else {\r
- incr = expr(ts, source, false);\r
- }\r
- }\r
-\r
- mustMatchToken(ts, ts.RP, "msg.no.paren.for.ctrl");\r
- source.append((char)ts.RP);\r
- source.append((char)ts.LC);\r
- source.append((char)ts.EOL);\r
- body = statement(ts, source);\r
- source.append((char)ts.RC);\r
- source.append((char)ts.EOL);\r
-\r
- if (incr == null) {\r
- // cond could be null if 'in obj' got eaten by the init node.\r
- pn = nf.createForIn(init, cond, body, lineno);\r
- } else {\r
- pn = nf.createFor(init, cond, incr, body, lineno);\r
- }\r
- break;\r
- }\r
-\r
- case TokenStream.TRY: {\r
- int lineno = ts.getLineno();\r
-\r
- Object tryblock;\r
- Object catchblocks = null;\r
- Object finallyblock = null;\r
-\r
- skipsemi = true;\r
- source.append((char)ts.TRY);\r
- source.append((char)ts.LC);\r
- source.append((char)ts.EOL);\r
- tryblock = statement(ts, source);\r
- source.append((char)ts.RC);\r
- source.append((char)ts.EOL);\r
-\r
- catchblocks = nf.createLeaf(TokenStream.BLOCK);\r
-\r
- boolean sawDefaultCatch = false;\r
- int peek = ts.peekToken();\r
- if (peek == ts.CATCH) {\r
- while (ts.matchToken(ts.CATCH)) {\r
- if (sawDefaultCatch) {\r
- reportError(ts, "msg.catch.unreachable");\r
- }\r
- source.append((char)ts.CATCH);\r
- mustMatchToken(ts, ts.LP, "msg.no.paren.catch");\r
- source.append((char)ts.LP);\r
-\r
- mustMatchToken(ts, ts.NAME, "msg.bad.catchcond");\r
- String varName = ts.getString();\r
- source.addString(ts.NAME, varName);\r
- \r
- Object catchCond = null;\r
- if (ts.matchToken(ts.IF)) {\r
- source.append((char)ts.IF);\r
- catchCond = expr(ts, source, false);\r
- } else {\r
- sawDefaultCatch = true;\r
- }\r
-\r
- mustMatchToken(ts, ts.RP, "msg.bad.catchcond");\r
- source.append((char)ts.RP);\r
- mustMatchToken(ts, ts.LC, "msg.no.brace.catchblock");\r
- source.append((char)ts.LC);\r
- source.append((char)ts.EOL);\r
- \r
- nf.addChildToBack(catchblocks, \r
- nf.createCatch(varName, catchCond, \r
- statements(ts, source), \r
- ts.getLineno()));\r
-\r
- mustMatchToken(ts, ts.RC, "msg.no.brace.after.body");\r
- source.append((char)ts.RC);\r
- source.append((char)ts.EOL);\r
- }\r
- } else if (peek != ts.FINALLY) {\r
- mustMatchToken(ts, ts.FINALLY, "msg.try.no.catchfinally");\r
- }\r
-\r
- if (ts.matchToken(ts.FINALLY)) {\r
- source.append((char)ts.FINALLY);\r
-\r
- source.append((char)ts.LC);\r
- source.append((char)ts.EOL);\r
- finallyblock = statement(ts, source);\r
- source.append((char)ts.RC);\r
- source.append((char)ts.EOL);\r
- }\r
-\r
- pn = nf.createTryCatchFinally(tryblock, catchblocks,\r
- finallyblock, lineno);\r
-\r
- break;\r
- }\r
- case TokenStream.THROW: {\r
- int lineno = ts.getLineno();\r
- source.append((char)ts.THROW);\r
- pn = nf.createThrow(expr(ts, source, false), lineno);\r
- if (lineno == ts.getLineno())\r
- wellTerminated(ts, ts.ERROR);\r
- break;\r
- }\r
- case TokenStream.BREAK: {\r
- int lineno = ts.getLineno();\r
-\r
- source.append((char)ts.BREAK);\r
-\r
- // matchLabel only matches if there is one\r
- String label = matchLabel(ts);\r
- if (label != null) {\r
- source.addString(ts.NAME, label);\r
- }\r
- pn = nf.createBreak(label, lineno);\r
- break;\r
- }\r
- case TokenStream.CONTINUE: {\r
- int lineno = ts.getLineno();\r
-\r
- source.append((char)ts.CONTINUE);\r
-\r
- // matchLabel only matches if there is one\r
- String label = matchLabel(ts);\r
- if (label != null) {\r
- source.addString(ts.NAME, label);\r
- }\r
- pn = nf.createContinue(label, lineno);\r
- break;\r
- }\r
- case TokenStream.WITH: {\r
- skipsemi = true;\r
-\r
- source.append((char)ts.WITH);\r
- int lineno = ts.getLineno();\r
- mustMatchToken(ts, ts.LP, "msg.no.paren.with");\r
- source.append((char)ts.LP);\r
- Object obj = expr(ts, source, false);\r
- mustMatchToken(ts, ts.RP, "msg.no.paren.after.with");\r
- source.append((char)ts.RP);\r
- source.append((char)ts.LC);\r
- source.append((char)ts.EOL);\r
-\r
- Object body = statement(ts, source);\r
-\r
- source.append((char)ts.RC);\r
- source.append((char)ts.EOL);\r
-\r
- pn = nf.createWith(obj, body, lineno);\r
- break;\r
- }\r
- case TokenStream.VAR: {\r
- int lineno = ts.getLineno();\r
- pn = variables(ts, source, false);\r
- if (ts.getLineno() == lineno)\r
- wellTerminated(ts, ts.ERROR);\r
- break;\r
- }\r
- case TokenStream.ASSERT: {\r
- Object retExpr = null;\r
- int lineno = 0;\r
- source.append((char)ts.ASSERT);\r
-\r
- // bail if we're not in a (toplevel) function\r
- if ((ts.flags & ts.TSF_FUNCTION) == 0)\r
- reportError(ts, "msg.bad.return");\r
-\r
- /* This is ugly, but we don't want to require a semicolon. */\r
- ts.flags |= ts.TSF_REGEXP;\r
- tt = ts.peekTokenSameLine();\r
- ts.flags &= ~ts.TSF_REGEXP;\r
- /*\r
- if (tt != ts.EOF && tt != ts.EOL && tt != ts.SEMI && tt != ts.RC) {\r
- lineno = ts.getLineno();\r
- retExpr = expr(ts, source, false);\r
- if (ts.getLineno() == lineno)\r
- wellTerminated(ts, ts.ERROR);\r
- ts.flags |= ts.TSF_RETURN_EXPR;\r
- } else {\r
- ts.flags |= ts.TSF_RETURN_VOID;\r
- }\r
- */\r
- // XXX ASSERT pn\r
- pn = nf.createAssert(retExpr, lineno);\r
- break;\r
- }\r
-\r
- case TokenStream.RETURN: {\r
- Object retExpr = null;\r
- int lineno = 0;\r
-\r
- source.append((char)ts.RETURN);\r
-\r
- // bail if we're not in a (toplevel) function\r
- if ((ts.flags & ts.TSF_FUNCTION) == 0)\r
- reportError(ts, "msg.bad.return");\r
-\r
- /* This is ugly, but we don't want to require a semicolon. */\r
- ts.flags |= ts.TSF_REGEXP;\r
- tt = ts.peekTokenSameLine();\r
- ts.flags &= ~ts.TSF_REGEXP;\r
-\r
- if (tt != ts.EOF && tt != ts.EOL && tt != ts.SEMI && tt != ts.RC) {\r
- lineno = ts.getLineno();\r
- retExpr = expr(ts, source, false);\r
- if (ts.getLineno() == lineno)\r
- wellTerminated(ts, ts.ERROR);\r
- ts.flags |= ts.TSF_RETURN_EXPR;\r
- } else {\r
- ts.flags |= ts.TSF_RETURN_VOID;\r
- }\r
-\r
- // XXX ASSERT pn\r
- pn = nf.createReturn(retExpr, lineno);\r
- break;\r
- }\r
- case TokenStream.LC:\r
- skipsemi = true;\r
-\r
- pn = statements(ts, source);\r
- mustMatchToken(ts, ts.RC, "msg.no.brace.block");\r
- break;\r
-\r
- case TokenStream.ERROR:\r
- // Fall thru, to have a node for error recovery to work on\r
- case TokenStream.EOL:\r
- case TokenStream.SEMI:\r
- pn = nf.createLeaf(ts.VOID);\r
- skipsemi = true;\r
- break;\r
-\r
- default: {\r
- lastExprType = tt;\r
- int tokenno = ts.getTokenno();\r
- ts.ungetToken(tt);\r
- int lineno = ts.getLineno();\r
-\r
- pn = expr(ts, source, false);\r
-\r
- if (ts.peekToken() == ts.COLON) {\r
- /* check that the last thing the tokenizer returned was a\r
- * NAME and that only one token was consumed.\r
- */\r
- if (lastExprType != ts.NAME || (ts.getTokenno() != tokenno))\r
- reportError(ts, "msg.bad.label");\r
-\r
- ts.getToken(); // eat the COLON\r
-\r
- /* in the C source, the label is associated with the\r
- * statement that follows:\r
- * nf.addChildToBack(pn, statement(ts));\r
- */\r
- String name = ts.getString();\r
- pn = nf.createLabel(name, lineno);\r
-\r
- // depend on decompiling lookahead to guess that that\r
- // last name was a label.\r
- source.append((char)ts.COLON);\r
- source.append((char)ts.EOL);\r
- return pn;\r
- }\r
-\r
- if (lastExprType == ts.FUNCTION)\r
- nf.setFunctionExpressionStatement(pn);\r
-\r
- pn = nf.createExprStatement(pn, lineno);\r
- \r
- /*\r
- * Check explicitly against (multi-line) function\r
- * statement.\r
-\r
- * lastExprEndLine is a hack to fix an\r
- * automatic semicolon insertion problem with function\r
- * expressions; the ts.getLineno() == lineno check was\r
- * firing after a function definition even though the\r
- * next statement was on a new line, because\r
- * speculative getToken calls advanced the line number\r
- * even when they didn't succeed.\r
- */\r
- if (ts.getLineno() == lineno ||\r
- (lastExprType == ts.FUNCTION &&\r
- ts.getLineno() == lastExprEndLine))\r
- {\r
- wellTerminated(ts, lastExprType);\r
- }\r
- break;\r
- }\r
- }\r
- ts.matchToken(ts.SEMI);\r
- if (!skipsemi) {\r
- source.append((char)ts.SEMI);\r
- source.append((char)ts.EOL);\r
- }\r
-\r
- return pn;\r
- }\r
-\r
- private Object variables(TokenStream ts, Source source, boolean inForInit)\r
- throws IOException, JavaScriptException\r
- {\r
- Object pn = nf.createVariables(ts.getLineno());\r
- boolean first = true;\r
-\r
- source.append((char)ts.VAR);\r
-\r
- for (;;) {\r
- Object name;\r
- Object init;\r
- mustMatchToken(ts, ts.NAME, "msg.bad.var");\r
- String s = ts.getString();\r
-\r
- if (!first)\r
- source.append((char)ts.COMMA);\r
- first = false;\r
-\r
- source.addString(ts.NAME, s);\r
- name = nf.createName(s);\r
-\r
- // omitted check for argument hiding\r
-\r
- if (ts.matchToken(ts.ASSIGN)) {\r
- if (ts.getOp() != ts.NOP)\r
- reportError(ts, "msg.bad.var.init");\r
-\r
- source.append((char)ts.ASSIGN);\r
- source.append((char)ts.NOP);\r
-\r
- init = assignExpr(ts, source, inForInit);\r
- nf.addChildToBack(name, init);\r
- }\r
- nf.addChildToBack(pn, name);\r
- if (!ts.matchToken(ts.COMMA))\r
- break;\r
- }\r
- return pn;\r
- }\r
-\r
- private Object expr(TokenStream ts, Source source, boolean inForInit)\r
- throws IOException, JavaScriptException\r
- {\r
- Object pn = assignExpr(ts, source, inForInit);\r
- while (ts.matchToken(ts.COMMA)) {\r
- source.append((char)ts.COMMA);\r
- pn = nf.createBinary(ts.COMMA, pn, assignExpr(ts, source,\r
- inForInit));\r
- }\r
- return pn;\r
- }\r
-\r
- private Object assignExpr(TokenStream ts, Source source, boolean inForInit)\r
- throws IOException, JavaScriptException\r
- {\r
- Object pn = condExpr(ts, source, inForInit);\r
-\r
- if (ts.matchToken(ts.ASSIGN)) {\r
- // omitted: "invalid assignment left-hand side" check.\r
- source.append((char)ts.ASSIGN);\r
- source.append((char)ts.getOp());\r
- pn = nf.createBinary(ts.ASSIGN, ts.getOp(), pn,\r
- assignExpr(ts, source, inForInit));\r
- }\r
-\r
- return pn;\r
- }\r
-\r
- private Object condExpr(TokenStream ts, Source source, boolean inForInit)\r
- throws IOException, JavaScriptException\r
- {\r
- Object ifTrue;\r
- Object ifFalse;\r
-\r
- Object pn = orExpr(ts, source, inForInit);\r
-\r
- if (ts.matchToken(ts.HOOK)) {\r
- source.append((char)ts.HOOK);\r
- ifTrue = assignExpr(ts, source, false);\r
- mustMatchToken(ts, ts.COLON, "msg.no.colon.cond");\r
- source.append((char)ts.COLON);\r
- ifFalse = assignExpr(ts, source, inForInit);\r
- return nf.createTernary(pn, ifTrue, ifFalse);\r
- }\r
-\r
- return pn;\r
- }\r
-\r
- private Object orExpr(TokenStream ts, Source source, boolean inForInit)\r
- throws IOException, JavaScriptException\r
- {\r
- Object pn = andExpr(ts, source, inForInit);\r
- if (ts.matchToken(ts.OR)) {\r
- source.append((char)ts.OR);\r
- pn = nf.createBinary(ts.OR, pn, orExpr(ts, source, inForInit));\r
- }\r
-\r
- return pn;\r
- }\r
-\r
- private Object andExpr(TokenStream ts, Source source, boolean inForInit)\r
- throws IOException, JavaScriptException\r
- {\r
- Object pn = bitOrExpr(ts, source, inForInit);\r
- if (ts.matchToken(ts.AND)) {\r
- source.append((char)ts.AND);\r
- pn = nf.createBinary(ts.AND, pn, andExpr(ts, source, inForInit));\r
- }\r
-\r
- return pn;\r
- }\r
-\r
- private Object bitOrExpr(TokenStream ts, Source source, boolean inForInit)\r
- throws IOException, JavaScriptException\r
- {\r
- Object pn = bitXorExpr(ts, source, inForInit);\r
- while (ts.matchToken(ts.BITOR)) {\r
- source.append((char)ts.BITOR);\r
- pn = nf.createBinary(ts.BITOR, pn, bitXorExpr(ts, source,\r
- inForInit));\r
- }\r
- return pn;\r
- }\r
-\r
- private Object bitXorExpr(TokenStream ts, Source source, boolean inForInit)\r
- throws IOException, JavaScriptException\r
- {\r
- Object pn = bitAndExpr(ts, source, inForInit);\r
- while (ts.matchToken(ts.BITXOR)) {\r
- source.append((char)ts.BITXOR);\r
- pn = nf.createBinary(ts.BITXOR, pn, bitAndExpr(ts, source,\r
- inForInit));\r
- }\r
- return pn;\r
- }\r
-\r
- private Object bitAndExpr(TokenStream ts, Source source, boolean inForInit)\r
- throws IOException, JavaScriptException\r
- {\r
- Object pn = eqExpr(ts, source, inForInit);\r
- while (ts.matchToken(ts.BITAND)) {\r
- source.append((char)ts.BITAND);\r
- pn = nf.createBinary(ts.BITAND, pn, eqExpr(ts, source, inForInit));\r
- }\r
- return pn;\r
- }\r
-\r
- private Object eqExpr(TokenStream ts, Source source, boolean inForInit)\r
- throws IOException, JavaScriptException\r
- {\r
- Object pn = relExpr(ts, source, inForInit);\r
- while (ts.matchToken(ts.EQOP)) {\r
- source.append((char)ts.EQOP);\r
- source.append((char)ts.getOp());\r
- pn = nf.createBinary(ts.EQOP, ts.getOp(), pn,\r
- relExpr(ts, source, inForInit));\r
- }\r
- return pn;\r
- }\r
-\r
- private Object relExpr(TokenStream ts, Source source, boolean inForInit)\r
- throws IOException, JavaScriptException\r
- {\r
- Object pn = shiftExpr(ts, source);\r
- while (ts.matchToken(ts.RELOP)) {\r
- int op = ts.getOp();\r
- if (inForInit && op == ts.IN) {\r
- ts.ungetToken(ts.RELOP);\r
- break;\r
- }\r
- source.append((char)ts.RELOP);\r
- source.append((char)op);\r
- pn = nf.createBinary(ts.RELOP, op, pn,\r
- shiftExpr(ts, source));\r
- }\r
- return pn;\r
- }\r
-\r
- private Object shiftExpr(TokenStream ts, Source source)\r
- throws IOException, JavaScriptException\r
- {\r
- Object pn = addExpr(ts, source);\r
- while (ts.matchToken(ts.SHOP)) {\r
- source.append((char)ts.SHOP);\r
- source.append((char)ts.getOp());\r
- pn = nf.createBinary(ts.getOp(), pn, addExpr(ts, source));\r
- }\r
- return pn;\r
- }\r
-\r
- private Object addExpr(TokenStream ts, Source source)\r
- throws IOException, JavaScriptException\r
- {\r
- int tt;\r
- Object pn = mulExpr(ts, source);\r
-\r
- while ((tt = ts.getToken()) == ts.ADD || tt == ts.SUB) {\r
- source.append((char)tt);\r
- // flushNewLines\r
- pn = nf.createBinary(tt, pn, mulExpr(ts, source));\r
- }\r
- ts.ungetToken(tt);\r
-\r
- return pn;\r
- }\r
-\r
- private Object mulExpr(TokenStream ts, Source source)\r
- throws IOException, JavaScriptException\r
- {\r
- int tt;\r
-\r
- Object pn = unaryExpr(ts, source);\r
-\r
- while ((tt = ts.peekToken()) == ts.MUL ||\r
- tt == ts.DIV ||\r
- tt == ts.MOD) {\r
- tt = ts.getToken();\r
- source.append((char)tt);\r
- pn = nf.createBinary(tt, pn, unaryExpr(ts, source));\r
- }\r
-\r
-\r
- return pn;\r
- }\r
-\r
- private Object unaryExpr(TokenStream ts, Source source)\r
- throws IOException, JavaScriptException\r
- {\r
- int tt;\r
-\r
- ts.flags |= ts.TSF_REGEXP;\r
- tt = ts.getToken();\r
- ts.flags &= ~ts.TSF_REGEXP;\r
-\r
- switch(tt) {\r
- case TokenStream.UNARYOP:\r
- source.append((char)ts.UNARYOP);\r
- source.append((char)ts.getOp());\r
- return nf.createUnary(ts.UNARYOP, ts.getOp(),\r
- unaryExpr(ts, source));\r
-\r
- case TokenStream.ADD:\r
- case TokenStream.SUB:\r
- source.append((char)ts.UNARYOP);\r
- source.append((char)tt);\r
- return nf.createUnary(ts.UNARYOP, tt, unaryExpr(ts, source));\r
-\r
- case TokenStream.INC:\r
- case TokenStream.DEC:\r
- source.append((char)tt);\r
- return nf.createUnary(tt, ts.PRE, memberExpr(ts, source, true));\r
-\r
- case TokenStream.DELPROP:\r
- source.append((char)ts.DELPROP);\r
- return nf.createUnary(ts.DELPROP, unaryExpr(ts, source));\r
-\r
- case TokenStream.ERROR:\r
- break;\r
-\r
- default:\r
- ts.ungetToken(tt);\r
-\r
- int lineno = ts.getLineno();\r
-\r
- Object pn = memberExpr(ts, source, true);\r
-\r
- /* don't look across a newline boundary for a postfix incop.\r
-\r
- * the rhino scanner seems to work differently than the js\r
- * scanner here; in js, it works to have the line number check\r
- * precede the peekToken calls. It'd be better if they had\r
- * similar behavior...\r
- */\r
- int peeked;\r
- if (((peeked = ts.peekToken()) == ts.INC ||\r
- peeked == ts.DEC) &&\r
- ts.getLineno() == lineno)\r
- {\r
- int pf = ts.getToken();\r
- source.append((char)pf);\r
- return nf.createUnary(pf, ts.POST, pn);\r
- }\r
- return pn;\r
- }\r
- return nf.createName("err"); // Only reached on error. Try to continue.\r
- \r
- }\r
-\r
- private Object argumentList(TokenStream ts, Source source, Object listNode)\r
- throws IOException, JavaScriptException\r
- {\r
- boolean matched;\r
- ts.flags |= ts.TSF_REGEXP;\r
- matched = ts.matchToken(ts.RP);\r
- ts.flags &= ~ts.TSF_REGEXP;\r
- if (!matched) {\r
- boolean first = true;\r
- do {\r
- if (!first)\r
- source.append((char)ts.COMMA);\r
- first = false;\r
- nf.addChildToBack(listNode, assignExpr(ts, source, false));\r
- } while (ts.matchToken(ts.COMMA));\r
- \r
- mustMatchToken(ts, ts.RP, "msg.no.paren.arg");\r
- }\r
- source.append((char)ts.RP);\r
- return listNode;\r
- }\r
-\r
- private Object memberExpr(TokenStream ts, Source source,\r
- boolean allowCallSyntax)\r
- throws IOException, JavaScriptException\r
- {\r
- int tt;\r
-\r
- Object pn;\r
- \r
- /* Check for new expressions. */\r
- ts.flags |= ts.TSF_REGEXP;\r
- tt = ts.peekToken();\r
- ts.flags &= ~ts.TSF_REGEXP;\r
- if (tt == ts.NEW) {\r
- /* Eat the NEW token. */\r
- ts.getToken();\r
- source.append((char)ts.NEW);\r
-\r
- /* Make a NEW node to append to. */\r
- pn = nf.createLeaf(ts.NEW);\r
- nf.addChildToBack(pn, memberExpr(ts, source, false));\r
-\r
- if (ts.matchToken(ts.LP)) {\r
- source.append((char)ts.LP);\r
- /* Add the arguments to pn, if any are supplied. */\r
- pn = argumentList(ts, source, pn);\r
- }\r
-\r
- /* XXX there's a check in the C source against\r
- * "too many constructor arguments" - how many\r
- * do we claim to support?\r
- */\r
- \r
- /* Experimental syntax: allow an object literal to follow a new expression,\r
- * which will mean a kind of anonymous class built with the JavaAdapter.\r
- * the object literal will be passed as an additional argument to the constructor.\r
- */\r
- tt = ts.peekToken();\r
- if (tt == ts.LC) {\r
- nf.addChildToBack(pn, primaryExpr(ts, source));\r
- }\r
- } else {\r
- pn = primaryExpr(ts, source);\r
- }\r
-\r
- lastExprEndLine = ts.getLineno();\r
- while ((tt = ts.getToken()) > ts.EOF) {\r
- if (tt == ts.DOT) {\r
- source.append((char)ts.DOT);\r
- mustMatchToken(ts, ts.NAME, "msg.no.name.after.dot");\r
- String s = ts.getString();\r
- source.addString(ts.NAME, s);\r
- pn = nf.createBinary(ts.DOT, pn,\r
- nf.createName(ts.getString()));\r
- /* pn = nf.createBinary(ts.DOT, pn, memberExpr(ts))\r
- * is the version in Brendan's IR C version. Not in ECMA...\r
- * does it reflect the 'new' operator syntax he mentioned?\r
- */\r
- lastExprEndLine = ts.getLineno();\r
- } else if (tt == ts.LB) {\r
- source.append((char)ts.LB);\r
- pn = nf.createBinary(ts.LB, pn, expr(ts, source, false));\r
-\r
- mustMatchToken(ts, ts.RB, "msg.no.bracket.index");\r
- source.append((char)ts.RB);\r
- lastExprEndLine = ts.getLineno();\r
- } else if (allowCallSyntax && tt == ts.LP) {\r
- /* make a call node */\r
-\r
- pn = nf.createUnary(ts.CALL, pn);\r
- source.append((char)ts.LP);\r
- \r
- /* Add the arguments to pn, if any are supplied. */\r
- pn = argumentList(ts, source, pn);\r
- lastExprEndLine = ts.getLineno();\r
- } else {\r
- ts.ungetToken(tt);\r
-\r
- break;\r
- }\r
- }\r
-\r
- return pn;\r
- }\r
-\r
- private Object primaryExpr(TokenStream ts, Source source)\r
- throws IOException, JavaScriptException\r
- {\r
- int tt;\r
-\r
- Object pn;\r
-\r
- ts.flags |= ts.TSF_REGEXP;\r
- tt = ts.getToken();\r
- ts.flags &= ~ts.TSF_REGEXP;\r
-\r
- switch(tt) {\r
-\r
- case TokenStream.FUNCTION:\r
- return function(ts, source, true);\r
-\r
- case TokenStream.LB:\r
- {\r
- source.append((char)ts.LB);\r
- pn = nf.createLeaf(ts.ARRAYLIT);\r
-\r
- ts.flags |= ts.TSF_REGEXP;\r
- boolean matched = ts.matchToken(ts.RB);\r
- ts.flags &= ~ts.TSF_REGEXP;\r
-\r
- if (!matched) {\r
- boolean first = true;\r
- do {\r
- ts.flags |= ts.TSF_REGEXP;\r
- tt = ts.peekToken();\r
- ts.flags &= ~ts.TSF_REGEXP;\r
-\r
- if (!first)\r
- source.append((char)ts.COMMA);\r
- else\r
- first = false;\r
-\r
- if (tt == ts.RB) { // to fix [,,,].length behavior...\r
- break;\r
- }\r
-\r
- if (tt == ts.COMMA) {\r
- nf.addChildToBack(pn, nf.createLeaf(ts.PRIMARY,\r
- ts.UNDEFINED));\r
- } else {\r
- nf.addChildToBack(pn, assignExpr(ts, source, false));\r
- }\r
-\r
- } while (ts.matchToken(ts.COMMA));\r
- mustMatchToken(ts, ts.RB, "msg.no.bracket.arg");\r
- }\r
- source.append((char)ts.RB);\r
- return nf.createArrayLiteral(pn);\r
- }\r
-\r
- case TokenStream.LC: {\r
- pn = nf.createLeaf(ts.OBJLIT);\r
-\r
- source.append((char)ts.LC);\r
- if (!ts.matchToken(ts.RC)) {\r
-\r
- boolean first = true;\r
- commaloop:\r
- do {\r
- Object property;\r
-\r
- if (!first)\r
- source.append((char)ts.COMMA);\r
- else\r
- first = false;\r
-\r
- tt = ts.getToken();\r
- switch(tt) {\r
- // map NAMEs to STRINGs in object literal context.\r
- case TokenStream.NAME:\r
- case TokenStream.STRING:\r
- String s = ts.getString();\r
- source.addString(ts.NAME, s);\r
- property = nf.createString(ts.getString());\r
- break;\r
- case TokenStream.NUMBER:\r
- Number n = ts.getNumber();\r
- source.addNumber(n);\r
- property = nf.createNumber(n);\r
- break;\r
- case TokenStream.RC:\r
- // trailing comma is OK.\r
- ts.ungetToken(tt);\r
- break commaloop;\r
- default:\r
- reportError(ts, "msg.bad.prop");\r
- break commaloop;\r
- }\r
- mustMatchToken(ts, ts.COLON, "msg.no.colon.prop");\r
-\r
- // OBJLIT is used as ':' in object literal for\r
- // decompilation to solve spacing ambiguity.\r
- source.append((char)ts.OBJLIT);\r
- nf.addChildToBack(pn, property);\r
- nf.addChildToBack(pn, assignExpr(ts, source, false));\r
-\r
- } while (ts.matchToken(ts.COMMA));\r
-\r
- mustMatchToken(ts, ts.RC, "msg.no.brace.prop");\r
- }\r
- source.append((char)ts.RC);\r
- return nf.createObjectLiteral(pn);\r
- }\r
-\r
- case TokenStream.LP:\r
-\r
- /* Brendan's IR-jsparse.c makes a new node tagged with\r
- * TOK_LP here... I'm not sure I understand why. Isn't\r
- * the grouping already implicit in the structure of the\r
- * parse tree? also TOK_LP is already overloaded (I\r
- * think) in the C IR as 'function call.' */\r
- source.append((char)ts.LP);\r
- pn = expr(ts, source, false);\r
- source.append((char)ts.RP);\r
- mustMatchToken(ts, ts.RP, "msg.no.paren");\r
- return pn;\r
-\r
- case TokenStream.NAME:\r
- String name = ts.getString();\r
- source.addString(ts.NAME, name);\r
- return nf.createName(name);\r
-\r
- case TokenStream.NUMBER:\r
- Number n = ts.getNumber();\r
- source.addNumber(n);\r
- return nf.createNumber(n);\r
-\r
- case TokenStream.STRING:\r
- String s = ts.getString();\r
- source.addString(ts.STRING, s);\r
- return nf.createString(s);\r
-\r
- case TokenStream.OBJECT:\r
- {\r
- String flags = ts.regExpFlags;\r
- ts.regExpFlags = null;\r
- String re = ts.getString();\r
- source.addString(ts.OBJECT, '/' + re + '/' + flags);\r
- return nf.createRegExp(re, flags);\r
- }\r
-\r
- case TokenStream.PRIMARY:\r
- source.append((char)ts.PRIMARY);\r
- source.append((char)ts.getOp());\r
- return nf.createLeaf(ts.PRIMARY, ts.getOp());\r
-\r
- case TokenStream.RESERVED:\r
- reportError(ts, "msg.reserved.id");\r
- break;\r
-\r
- case TokenStream.ERROR:\r
- /* the scanner or one of its subroutines reported the error. */\r
- break;\r
-\r
- default:\r
- reportError(ts, "msg.syntax");\r
- break;\r
-\r
- }\r
- return null; // should never reach here\r
- }\r
-\r
- private int lastExprEndLine; // Hack to handle function expr termination.\r
- private IRFactory nf;\r
- private ErrorReporter er;\r
- private boolean ok; // Did the parse encounter an error?\r
-}\r
-\r
-/**\r
- * This class saves decompilation information about the source.\r
- * Source information is returned from the parser as a String\r
- * associated with function nodes and with the toplevel script. When\r
- * saved in the constant pool of a class, this string will be UTF-8\r
- * encoded, and token values will occupy a single byte.\r
-\r
- * Source is saved (mostly) as token numbers. The tokens saved pretty\r
- * much correspond to the token stream of a 'canonical' representation\r
- * of the input program, as directed by the parser. (There were a few\r
- * cases where tokens could have been left out where decompiler could\r
- * easily reconstruct them, but I left them in for clarity). (I also\r
- * looked adding source collection to TokenStream instead, where I\r
- * could have limited the changes to a few lines in getToken... but\r
- * this wouldn't have saved any space in the resulting source\r
- * representation, and would have meant that I'd have to duplicate\r
- * parser logic in the decompiler to disambiguate situations where\r
- * newlines are important.) NativeFunction.decompile expands the\r
- * tokens back into their string representations, using simple\r
- * lookahead to correct spacing and indentation.\r
-\r
- * Token types with associated ops (ASSIGN, SHOP, PRIMARY, etc.) are\r
- * saved as two-token pairs. Number tokens are stored inline, as a\r
- * NUMBER token, a character representing the type, and either 1 or 4\r
- * characters representing the bit-encoding of the number. String\r
- * types NAME, STRING and OBJECT are currently stored as a token type,\r
- * followed by a character giving the length of the string (assumed to\r
- * be less than 2^16), followed by the characters of the string\r
- * inlined into the source string. Changing this to some reference to\r
- * to the string in the compiled class' constant pool would probably\r
- * save a lot of space... but would require some method of deriving\r
- * the final constant pool entry from information available at parse\r
- * time.\r
-\r
- * Nested functions need a similar mechanism... fortunately the nested\r
- * functions for a given function are generated in source order.\r
- * Nested functions are encoded as FUNCTION followed by a function\r
- * number (encoded as a character), which is enough information to\r
- * find the proper generated NativeFunction instance.\r
-\r
- * OPT source info collection is a potential performance bottleneck;\r
- * Source wraps a java.lang.StringBuffer, which is synchronized. It\r
- * might be faster to implement Source with its own char buffer and\r
- * toString method.\r
-\r
- */\r
-\r
-final class Source {\r
- Source() {\r
- // OPT the default 16 is probably too small, but it's not\r
- // clear just what size would work best for most javascript.\r
- // It'd be nice to know what characterizes the javascript\r
- // that's out there.\r
- buf = new StringBuffer(64);\r
- }\r
-\r
- void append(char c) {\r
- buf.append(c);\r
- }\r
-\r
- void addString(int type, String str) {\r
- buf.append((char)type);\r
- // java string length < 2^16?\r
- buf.append((char)str.length());\r
- buf.append(str);\r
- }\r
-\r
- void addNumber(Number n) {\r
- buf.append((char)TokenStream.NUMBER);\r
-\r
- /* encode the number in the source stream.\r
- * Save as NUMBER type (char | char char char char)\r
- * where type is\r
- * 'D' - double, 'S' - short, 'J' - long.\r
-\r
- * We need to retain float vs. integer type info to keep the\r
- * behavior of liveconnect type-guessing the same after\r
- * decompilation. (Liveconnect tries to present 1.0 to Java\r
- * as a float/double)\r
- * OPT: This is no longer true. We could compress the format.\r
-\r
- * This may not be the most space-efficient encoding;\r
- * the chars created below may take up to 3 bytes in\r
- * constant pool UTF-8 encoding, so a Double could take\r
- * up to 12 bytes.\r
- */\r
-\r
- if (n instanceof Double || n instanceof Float) {\r
- // if it's floating point, save as a Double bit pattern.\r
- // (12/15/97 our scanner only returns Double for f.p.)\r
- buf.append('D');\r
- long lbits = Double.doubleToLongBits(n.doubleValue());\r
-\r
- buf.append((char)((lbits >> 48) & 0xFFFF));\r
- buf.append((char)((lbits >> 32) & 0xFFFF));\r
- buf.append((char)((lbits >> 16) & 0xFFFF));\r
- buf.append((char)(lbits & 0xFFFF));\r
- } else {\r
- long lbits = n.longValue();\r
- // will it fit in a char?\r
- // (we can ignore negative values, bc they're already prefixed\r
- // by UNARYOP SUB)\r
- // this gives a short encoding for integer values up to 2^16.\r
- if (lbits <= Character.MAX_VALUE) {\r
- buf.append('S');\r
- buf.append((char)lbits);\r
- } else { // Integral, but won't fit in a char. Store as a long.\r
- buf.append('J');\r
- buf.append((char)((lbits >> 48) & 0xFFFF));\r
- buf.append((char)((lbits >> 32) & 0xFFFF));\r
- buf.append((char)((lbits >> 16) & 0xFFFF));\r
- buf.append((char)(lbits & 0xFFFF));\r
- }\r
- }\r
- }\r
-\r
- char functionNumber;\r
- StringBuffer buf;\r
-}\r
-\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- * Roger Lawrence\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-import java.util.Stack;\r
-\r
-/**\r
- * This class implements a preorder tree iterator for the Node class.\r
- *\r
- * @see Node\r
- * @author Norris Boyd\r
- */\r
-public class PreorderNodeIterator {\r
- public PreorderNodeIterator(Node n) {\r
- start = n;\r
- stack = new Stack();\r
- }\r
-\r
- public Node currentNode() {\r
- return current;\r
- }\r
-\r
- public Node getCurrentParent() {\r
- return currentParent;\r
- }\r
-\r
- public Node nextNode() {\r
- if (current == null)\r
- return current = start;\r
- if (current.first != null) {\r
- stack.push(current);\r
- currentParent = current;\r
- current = current.first;\r
- } else {\r
- current = current.next;\r
- boolean isEmpty;\r
- for (;;) {\r
- isEmpty = stack.isEmpty();\r
- if (isEmpty || current != null)\r
- break;\r
- current = (Node) stack.pop();\r
- current = current.next;\r
- }\r
- currentParent = isEmpty ? null : (Node) stack.peek();\r
- }\r
- return current;\r
- }\r
-\r
- public void replaceCurrent(Node newNode) {\r
- currentParent.replaceChild(current, newNode);\r
- current = newNode;\r
- }\r
-\r
- private Node start;\r
- private Node current;\r
- private Node currentParent;\r
- private Stack stack;\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-// API class\r
-\r
-package org.mozilla.javascript;\r
-\r
-/**\r
- * Thrown if errors are detected while attempting to define a property of\r
- * a host object from a Java class or method, or if a property is not found.\r
- */\r
-public class PropertyException extends Exception {\r
-\r
- public PropertyException(String detail) {\r
- super(detail);\r
- }\r
-\r
- static PropertyException withMessage0(String messageId) {\r
- return new PropertyException(Context.getMessage0(messageId));\r
- }\r
-\r
- static PropertyException withMessage1(String messageId, Object arg1) {\r
- return new PropertyException(Context.getMessage1(messageId, arg1));\r
- }\r
-\r
- static PropertyException withMessage2\r
- (String messageId, Object arg1, Object arg2) \r
- {\r
- return new PropertyException\r
- (Context.getMessage2(messageId, arg1, arg2));\r
- }\r
-\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- * Roger Lawrence\r
- *\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-/**\r
- * A proxy for the regexp package, so that the regexp package can be\r
- * loaded optionally.\r
- * \r
- * @author Norris Boyd\r
- */\r
-public interface RegExpProxy {\r
- \r
- public boolean isRegExp(Object obj);\r
- \r
- public Object newRegExp(Context cx, Scriptable scope, String source, \r
- String global, boolean flat);\r
- \r
- public Object match(Context cx, Scriptable scope,\r
- Scriptable thisObj, Object[] args)\r
- throws JavaScriptException;\r
-\r
- public Object search(Context cx, Scriptable scope, \r
- Scriptable thisObj, Object[] args)\r
- throws JavaScriptException;\r
-\r
- public Object replace(Context cx, Scriptable scope, \r
- Scriptable thisObj, Object[] args)\r
- throws JavaScriptException;\r
- \r
- public int find_split(Scriptable scope, String target, String separator, \r
- Object re, int[] ip, int[] matchlen, \r
- boolean[] matched, String[][] parensp);\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-// API class\r
-\r
-package org.mozilla.javascript;\r
-\r
-/**\r
- * All compiled scripts implement this interface.\r
- * <p>\r
- * This class encapsulates script execution relative to an\r
- * object scope.\r
- * @since 1.3\r
- * @author Norris Boyd\r
- */\r
-\r
-public interface Script {\r
-\r
- /**\r
- * Execute the script.\r
- * <p>\r
- * The script is executed in a particular runtime Context, which\r
- * must be associated with the current thread.\r
- * The script is executed relative to a scope--definitions and\r
- * uses of global top-level variables and functions will access\r
- * properties of the scope object. For compliant ECMA\r
- * programs, the scope must be an object that has been initialized\r
- * as a global object using <code>Context.initStandardObjects</code>.\r
- * <p>\r
- *\r
- * @param cx the Context associated with the current thread\r
- * @param scope the scope to execute relative to\r
- * @return the result of executing the script\r
- * @see org.mozilla.javascript.Context#initStandardObjects\r
- * @exception JavaScriptException if an uncaught JavaScript exception\r
- * occurred while executing the script\r
- */\r
- public Object exec(Context cx, Scriptable scope)\r
- throws JavaScriptException;\r
-\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-2000 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s):\r
- * Patrick Beard\r
- * Norris Boyd\r
- * Igor Bukanov \r
- * Roger Lawrence\r
- * Frank Mitchell\r
- * Andrew Wason\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-import java.util.*;\r
-import java.lang.reflect.*;\r
-//import org.mozilla.classfile.DefiningClassLoader;\r
-\r
-/**\r
- * This is the class that implements the runtime.\r
- *\r
- * @author Norris Boyd\r
- */\r
-\r
-public class ScriptRuntime {\r
-\r
- /**\r
- * No instances should be created.\r
- */\r
- protected ScriptRuntime() {\r
- }\r
-\r
- /*\r
- * There's such a huge space (and some time) waste for the Foo.class\r
- * syntax: the compiler sticks in a test of a static field in the\r
- * enclosing class for null and the code for creating the class value.\r
- * It has to do this since the reference has to get pushed off til\r
- * executiontime (i.e. can't force an early load), but for the\r
- * 'standard' classes - especially those in java.lang, we can trust\r
- * that they won't cause problems by being loaded early.\r
- */\r
-\r
- public final static Class UndefinedClass = Undefined.class;\r
- public final static Class ScriptableClass = Scriptable.class;\r
- public final static Class StringClass = String.class;\r
- public final static Class NumberClass = Number.class;\r
- public final static Class BooleanClass = Boolean.class;\r
- public final static Class ByteClass = Byte.class;\r
- public final static Class ShortClass = Short.class;\r
- public final static Class IntegerClass = Integer.class;\r
- public final static Class LongClass = Long.class;\r
- public final static Class FloatClass = Float.class;\r
- public final static Class DoubleClass = Double.class;\r
- public final static Class CharacterClass = Character.class;\r
- public final static Class ObjectClass = Object.class;\r
- public final static Class FunctionClass = Function.class;\r
- public final static Class ClassClass = Class.class;\r
-\r
- /**\r
- * Convert the value to a boolean.\r
- *\r
- * See ECMA 9.2.\r
- */\r
- public static boolean toBoolean(Object val) {\r
- if (val == null)\r
- return false;\r
- if (val instanceof Scriptable) {\r
- if (Context.getContext().isVersionECMA1()) {\r
- // pure ECMA\r
- return val != Undefined.instance;\r
- }\r
- // ECMA extension\r
- val = ((Scriptable) val).getDefaultValue(BooleanClass);\r
- if (val instanceof Scriptable)\r
- throw errorWithClassName("msg.primitive.expected", val);\r
- // fall through\r
- }\r
- if (val instanceof String)\r
- return ((String) val).length() != 0;\r
- if (val instanceof Number) {\r
- double d = ((Number) val).doubleValue();\r
- return (d == d && d != 0.0);\r
- }\r
- if (val instanceof Boolean)\r
- return ((Boolean) val).booleanValue();\r
- throw errorWithClassName("msg.invalid.type", val);\r
- }\r
-\r
- public static boolean toBoolean(Object[] args, int index) {\r
- return (index < args.length) ? toBoolean(args[index]) : false;\r
- }\r
- /**\r
- * Convert the value to a number.\r
- *\r
- * See ECMA 9.3.\r
- */\r
- public static double toNumber(Object val) {\r
- if (val == null) \r
- return +0.0;\r
- if (val instanceof Scriptable) {\r
- val = ((Scriptable) val).getDefaultValue(NumberClass);\r
- if (val != null && val instanceof Scriptable)\r
- throw errorWithClassName("msg.primitive.expected", val);\r
- // fall through\r
- }\r
- if (val instanceof String)\r
- return toNumber((String) val);\r
- if (val instanceof Number)\r
- return ((Number) val).doubleValue();\r
- if (val instanceof Boolean)\r
- return ((Boolean) val).booleanValue() ? 1 : +0.0;\r
- throw errorWithClassName("msg.invalid.type", val);\r
- }\r
-\r
- public static double toNumber(Object[] args, int index) {\r
- return (index < args.length) ? toNumber(args[index]) : NaN;\r
- }\r
- \r
- // This definition of NaN is identical to that in java.lang.Double\r
- // except that it is not final. This is a workaround for a bug in\r
- // the Microsoft VM, versions 2.01 and 3.0P1, that causes some uses\r
- // (returns at least) of Double.NaN to be converted to 1.0.\r
- // So we use ScriptRuntime.NaN instead of Double.NaN.\r
- public static double NaN = 0.0d / 0.0;\r
- public static Double NaNobj = new Double(0.0d / 0.0);\r
-\r
- // A similar problem exists for negative zero.\r
- public static double negativeZero = -0.0;\r
-\r
- /*\r
- * Helper function for toNumber, parseInt, and TokenStream.getToken.\r
- */\r
- static double stringToNumber(String s, int start, int radix) {\r
- char digitMax = '9';\r
- char lowerCaseBound = 'a';\r
- char upperCaseBound = 'A';\r
- int len = s.length();\r
- if (radix < 10) {\r
- digitMax = (char) ('0' + radix - 1);\r
- }\r
- if (radix > 10) {\r
- lowerCaseBound = (char) ('a' + radix - 10);\r
- upperCaseBound = (char) ('A' + radix - 10);\r
- }\r
- int end;\r
- double sum = 0.0;\r
- for (end=start; end < len; end++) {\r
- char c = s.charAt(end);\r
- int newDigit;\r
- if ('0' <= c && c <= digitMax)\r
- newDigit = c - '0';\r
- else if ('a' <= c && c < lowerCaseBound)\r
- newDigit = c - 'a' + 10;\r
- else if ('A' <= c && c < upperCaseBound)\r
- newDigit = c - 'A' + 10;\r
- else\r
- break;\r
- sum = sum*radix + newDigit;\r
- }\r
- if (start == end) {\r
- return NaN;\r
- }\r
- if (sum >= 9007199254740992.0) {\r
- if (radix == 10) {\r
- /* If we're accumulating a decimal number and the number\r
- * is >= 2^53, then the result from the repeated multiply-add\r
- * above may be inaccurate. Call Java to get the correct\r
- * answer.\r
- */\r
- try {\r
- return Double.valueOf(s.substring(start, end)).doubleValue();\r
- } catch (NumberFormatException nfe) {\r
- return NaN;\r
- }\r
- } else if (radix == 2 || radix == 4 || radix == 8 ||\r
- radix == 16 || radix == 32)\r
- {\r
- /* The number may also be inaccurate for one of these bases.\r
- * This happens if the addition in value*radix + digit causes\r
- * a round-down to an even least significant mantissa bit\r
- * when the first dropped bit is a one. If any of the\r
- * following digits in the number (which haven't been added\r
- * in yet) are nonzero then the correct action would have\r
- * been to round up instead of down. An example of this\r
- * occurs when reading the number 0x1000000000000081, which\r
- * rounds to 0x1000000000000000 instead of 0x1000000000000100.\r
- */\r
- BinaryDigitReader bdr = new BinaryDigitReader(radix, s, start, end);\r
- int bit;\r
- sum = 0.0;\r
-\r
- /* Skip leading zeros. */\r
- do {\r
- bit = bdr.getNextBinaryDigit();\r
- } while (bit == 0);\r
-\r
- if (bit == 1) {\r
- /* Gather the 53 significant bits (including the leading 1) */\r
- sum = 1.0;\r
- for (int j = 52; j != 0; j--) {\r
- bit = bdr.getNextBinaryDigit();\r
- if (bit < 0)\r
- return sum;\r
- sum = sum*2 + bit;\r
- }\r
- /* bit54 is the 54th bit (the first dropped from the mantissa) */\r
- int bit54 = bdr.getNextBinaryDigit();\r
- if (bit54 >= 0) {\r
- double factor = 2.0;\r
- int sticky = 0; /* sticky is 1 if any bit beyond the 54th is 1 */\r
- int bit3;\r
-\r
- while ((bit3 = bdr.getNextBinaryDigit()) >= 0) {\r
- sticky |= bit3;\r
- factor *= 2;\r
- }\r
- sum += bit54 & (bit | sticky);\r
- sum *= factor;\r
- }\r
- }\r
- }\r
- /* We don't worry about inaccurate numbers for any other base. */\r
- }\r
- return sum;\r
- }\r
-\r
-\r
- /**\r
- * ToNumber applied to the String type\r
- *\r
- * See ECMA 9.3.1\r
- */\r
- public static double toNumber(String s) {\r
- int len = s.length();\r
- int start = 0;\r
- char startChar;\r
- for (;;) {\r
- if (start == len) {\r
- // Empty or contains only whitespace\r
- return +0.0;\r
- }\r
- startChar = s.charAt(start);\r
- if (!Character.isWhitespace(startChar))\r
- break;\r
- start++;\r
- }\r
-\r
- if (startChar == '0' && start+2 < len &&\r
- Character.toLowerCase(s.charAt(start+1)) == 'x')\r
- // A hexadecimal number\r
- return stringToNumber(s, start + 2, 16);\r
-\r
- if ((startChar == '+' || startChar == '-') && start+3 < len &&\r
- s.charAt(start+1) == '0' &&\r
- Character.toLowerCase(s.charAt(start+2)) == 'x') {\r
- // A hexadecimal number\r
- double val = stringToNumber(s, start + 3, 16);\r
- return startChar == '-' ? -val : val;\r
- }\r
-\r
- int end = len - 1;\r
- char endChar;\r
- while (Character.isWhitespace(endChar = s.charAt(end)))\r
- end--;\r
- if (endChar == 'y') {\r
- // check for "Infinity"\r
- if (startChar == '+' || startChar == '-')\r
- start++;\r
- if (start + 7 == end && s.regionMatches(start, "Infinity", 0, 8))\r
- return startChar == '-'\r
- ? Double.NEGATIVE_INFINITY\r
- : Double.POSITIVE_INFINITY;\r
- return NaN;\r
- }\r
- // A non-hexadecimal, non-infinity number:\r
- // just try a normal floating point conversion\r
- String sub = s.substring(start, end+1);\r
- if (MSJVM_BUG_WORKAROUNDS) {\r
- // The MS JVM will accept non-conformant strings\r
- // rather than throwing a NumberFormatException\r
- // as it should.\r
- for (int i=sub.length()-1; i >= 0; i--) {\r
- char c = sub.charAt(i);\r
- if (('0' <= c && c <= '9') || c == '.' ||\r
- c == 'e' || c == 'E' ||\r
- c == '+' || c == '-')\r
- continue;\r
- return NaN;\r
- }\r
- }\r
- try {\r
- return Double.valueOf(sub).doubleValue();\r
- } catch (NumberFormatException ex) {\r
- return NaN;\r
- }\r
- }\r
-\r
- /**\r
- * Helper function for builtin objects that use the varargs form.\r
- * ECMA function formal arguments are undefined if not supplied;\r
- * this function pads the argument array out to the expected\r
- * length, if necessary.\r
- */\r
- public static Object[] padArguments(Object[] args, int count) {\r
- if (count < args.length)\r
- return args;\r
-\r
- int i;\r
- Object[] result = new Object[count];\r
- for (i = 0; i < args.length; i++) {\r
- result[i] = args[i];\r
- }\r
-\r
- for (; i < count; i++) {\r
- result[i] = Undefined.instance;\r
- }\r
-\r
- return result;\r
- }\r
-\r
- /* Work around Microsoft Java VM bugs. */\r
- private final static boolean MSJVM_BUG_WORKAROUNDS = true;\r
-\r
- /**\r
- * For escaping strings printed by object and array literals; not quite\r
- * the same as 'escape.'\r
- */\r
- public static String escapeString(String s) {\r
- // ack! Java lacks \v.\r
- String escapeMap = "\bb\ff\nn\rr\tt\u000bv\"\"''";\r
- StringBuffer result = new StringBuffer(s.length());\r
-\r
- for(int i=0; i < s.length(); i++) {\r
- char c = s.charAt(i);\r
-\r
- // an ordinary print character\r
- if (c >= ' ' && c <= '~' // string.h isprint()\r
- && c != '"')\r
- {\r
- result.append(c);\r
- continue;\r
- }\r
-\r
- // an \escaped sort of character\r
- int index;\r
- if ((index = escapeMap.indexOf(c)) >= 0) {\r
- result.append("\\");\r
- result.append(escapeMap.charAt(index + 1));\r
- continue;\r
- }\r
-\r
- // 2-digit hex?\r
- if (c < 256) {\r
- String hex = Integer.toHexString((int) c);\r
- if (hex.length() == 1) {\r
- result.append("\\x0");\r
- result.append(hex);\r
- } else {\r
- result.append("\\x");\r
- result.append(hex);\r
- }\r
- continue;\r
- }\r
-\r
- // nope. Unicode.\r
- String hex = Integer.toHexString((int) c);\r
- // cool idiom courtesy Shaver.\r
- result.append("\\u");\r
- for (int l = hex.length(); l < 4; l++)\r
- result.append('0');\r
- result.append(hex);\r
- }\r
-\r
- return result.toString();\r
- }\r
-\r
-\r
- /**\r
- * Convert the value to a string.\r
- *\r
- * See ECMA 9.8.\r
- */\r
- public static String toString(Object val) {\r
- for (;;) {\r
- if (val == null)\r
- return "null";\r
- if (val instanceof Scriptable) {\r
- val = ((Scriptable) val).getDefaultValue(StringClass);\r
- if (val != Undefined.instance && val instanceof Scriptable) {\r
- throw errorWithClassName("msg.primitive.expected", val);\r
- }\r
- continue;\r
- }\r
- if (val instanceof Number) {\r
- // XXX should we just teach NativeNumber.stringValue()\r
- // about Numbers?\r
- return numberToString(((Number) val).doubleValue(), 10);\r
- }\r
- return val.toString();\r
- }\r
- }\r
-\r
- public static String toString(Object[] args, int index) {\r
- return (index < args.length) ? toString(args[index]) : "undefined";\r
- }\r
-\r
- /**\r
- * Optimized version of toString(Object) for numbers.\r
- */\r
- public static String toString(double val) {\r
- return numberToString(val, 10);\r
- }\r
- \r
- public static String numberToString(double d, int base) {\r
- if (d != d)\r
- return "NaN";\r
- if (d == Double.POSITIVE_INFINITY)\r
- return "Infinity";\r
- if (d == Double.NEGATIVE_INFINITY)\r
- return "-Infinity";\r
- if (d == 0.0)\r
- return "0";\r
-\r
- if ((base < 2) || (base > 36)) {\r
- throw Context.reportRuntimeError1(\r
- "msg.bad.radix", Integer.toString(base));\r
- }\r
-\r
- if (base != 10) {\r
- return DToA.JS_dtobasestr(base, d);\r
- } else {\r
- StringBuffer result = new StringBuffer();\r
- DToA.JS_dtostr(result, DToA.DTOSTR_STANDARD, 0, d);\r
- return result.toString();\r
- }\r
- \r
- }\r
-\r
- /**\r
- * Convert the value to an object.\r
- *\r
- * See ECMA 9.9.\r
- */\r
- public static Scriptable toObject(Scriptable scope, Object val) {\r
- return toObject(scope, val, null);\r
- }\r
-\r
- public static Scriptable toObject(Scriptable scope, Object val,\r
- Class staticClass)\r
- {\r
- if (val == null) {\r
- throw NativeGlobal.typeError0("msg.null.to.object", scope);\r
- }\r
- if (val instanceof Scriptable) {\r
- if (val == Undefined.instance) {\r
- throw NativeGlobal.typeError0("msg.undef.to.object", scope);\r
- }\r
- return (Scriptable) val;\r
- }\r
- String className = val instanceof String ? "String" :\r
- val instanceof Number ? "Number" :\r
- val instanceof Boolean ? "Boolean" :\r
- null;\r
-\r
- if (className == null) {\r
- // Extension: Wrap as a LiveConnect object.\r
- Object wrapped = NativeJavaObject.wrap(scope, val, staticClass);\r
- if (wrapped instanceof Scriptable)\r
- return (Scriptable) wrapped;\r
- throw errorWithClassName("msg.invalid.type", val);\r
- }\r
-\r
- Object[] args = { val };\r
- scope = ScriptableObject.getTopLevelScope(scope);\r
- Scriptable result = newObject(Context.getContext(), org.xwt.util.JSObject.defaultObjects, className, args);\r
- return result;\r
- }\r
-\r
- public static Scriptable newObject(Context cx, Scriptable scope,\r
- String constructorName, Object[] args)\r
- {\r
- Exception re = null;\r
- try {\r
- return cx.newObject(scope, constructorName, args);\r
- }\r
- catch (NotAFunctionException e) {\r
- re = e;\r
- }\r
- catch (PropertyException e) {\r
- re = e;\r
- }\r
- catch (JavaScriptException e) {\r
- re = e;\r
- }\r
- throw cx.reportRuntimeError(re.getMessage());\r
- }\r
-\r
- /**\r
- *\r
- * See ECMA 9.4.\r
- */\r
- public static double toInteger(Object val) {\r
- return toInteger(toNumber(val));\r
- }\r
-\r
- // convenience method\r
- public static double toInteger(double d) {\r
- // if it's NaN\r
- if (d != d)\r
- return +0.0;\r
-\r
- if (d == 0.0 ||\r
- d == Double.POSITIVE_INFINITY ||\r
- d == Double.NEGATIVE_INFINITY)\r
- return d;\r
-\r
- if (d > 0.0)\r
- return Math.floor(d);\r
- else\r
- return Math.ceil(d);\r
- }\r
-\r
- public static double toInteger(Object[] args, int index) {\r
- return (index < args.length) ? toInteger(args[index]) : +0.0;\r
- }\r
-\r
- /**\r
- *\r
- * See ECMA 9.5.\r
- */\r
- public static int toInt32(Object val) {\r
- // 0x100000000 gives me a numeric overflow...\r
- double two32 = 4294967296.0;\r
- double two31 = 2147483648.0;\r
-\r
- // short circuit for common small values; TokenStream\r
- // returns them as Bytes.\r
- if (val instanceof Byte)\r
- return ((Number)val).intValue();\r
-\r
- double d = toNumber(val);\r
- if (d != d || d == 0.0 ||\r
- d == Double.POSITIVE_INFINITY ||\r
- d == Double.NEGATIVE_INFINITY)\r
- return 0;\r
-\r
- d = Math.IEEEremainder(d, two32);\r
-\r
- d = d >= 0\r
- ? d\r
- : d + two32;\r
-\r
- if (d >= two31)\r
- return (int)(d - two32);\r
- else\r
- return (int)d;\r
- }\r
-\r
- public static int toInt32(Object[] args, int index) {\r
- return (index < args.length) ? toInt32(args[index]) : 0;\r
- }\r
-\r
- public static int toInt32(double d) {\r
- // 0x100000000 gives me a numeric overflow...\r
- double two32 = 4294967296.0;\r
- double two31 = 2147483648.0;\r
-\r
- if (d != d || d == 0.0 ||\r
- d == Double.POSITIVE_INFINITY ||\r
- d == Double.NEGATIVE_INFINITY)\r
- return 0;\r
-\r
- d = Math.IEEEremainder(d, two32);\r
-\r
- d = d >= 0\r
- ? d\r
- : d + two32;\r
-\r
- if (d >= two31)\r
- return (int)(d - two32);\r
- else\r
- return (int)d;\r
- }\r
-\r
- /**\r
- *\r
- * See ECMA 9.6.\r
- */\r
-\r
- // must return long to hold an _unsigned_ int\r
- public static long toUint32(double d) {\r
- // 0x100000000 gives me a numeric overflow...\r
- double two32 = 4294967296.0;\r
-\r
- if (d != d || d == 0.0 ||\r
- d == Double.POSITIVE_INFINITY ||\r
- d == Double.NEGATIVE_INFINITY)\r
- return 0;\r
-\r
- if (d > 0.0)\r
- d = Math.floor(d);\r
- else\r
- d = Math.ceil(d);\r
-\r
- d = Math.IEEEremainder(d, two32);\r
-\r
- d = d >= 0\r
- ? d\r
- : d + two32;\r
-\r
- return (long) Math.floor(d);\r
- }\r
-\r
- public static long toUint32(Object val) {\r
- return toUint32(toNumber(val));\r
- }\r
-\r
- /**\r
- *\r
- * See ECMA 9.7.\r
- */\r
- public static char toUint16(Object val) {\r
- long int16 = 0x10000;\r
-\r
- double d = toNumber(val);\r
- if (d != d || d == 0.0 ||\r
- d == Double.POSITIVE_INFINITY ||\r
- d == Double.NEGATIVE_INFINITY)\r
- {\r
- return 0;\r
- }\r
-\r
- d = Math.IEEEremainder(d, int16);\r
-\r
- d = d >= 0\r
- ? d\r
- : d + int16;\r
-\r
- return (char) Math.floor(d);\r
- }\r
-\r
- /**\r
- * Unwrap a JavaScriptException. Sleight of hand so that we don't\r
- * javadoc JavaScriptException.getRuntimeValue().\r
- */\r
- public static Object unwrapJavaScriptException(JavaScriptException jse) {\r
- return jse.value;\r
- }\r
-\r
- /**\r
- * Check a WrappedException. Unwrap a JavaScriptException and return\r
- * the value, otherwise rethrow.\r
- */\r
- public static Object unwrapWrappedException(WrappedException we) {\r
- Throwable t = we.getWrappedException();\r
- if (t instanceof JavaScriptException)\r
- return ((JavaScriptException) t).value;\r
- throw we;\r
- }\r
-\r
- public static Object getProp(Object obj, String id, Scriptable scope) {\r
- Scriptable start;\r
- if (obj instanceof Scriptable) {\r
- start = (Scriptable) obj;\r
- } else {\r
- start = toObject(scope, obj);\r
- }\r
- if (start == null || start == Undefined.instance) {\r
- String msg = start == null ? "msg.null.to.object"\r
- : "msg.undefined";\r
- throw NativeGlobal.constructError(\r
- Context.getContext(), "ConversionError",\r
- ScriptRuntime.getMessage0(msg),\r
- scope);\r
- }\r
- Scriptable m = start;\r
- do {\r
- Object result = m.get(id, start);\r
- if (result != Scriptable.NOT_FOUND)\r
- return result;\r
- m = m.getPrototype();\r
- } while (m != null);\r
- return Undefined.instance;\r
- }\r
-\r
- public static Object getTopLevelProp(Scriptable scope, String id) {\r
- Scriptable s = ScriptableObject.getTopLevelScope(scope);\r
- Object v;\r
- do {\r
- v = s.get(id, s);\r
- if (v != Scriptable.NOT_FOUND)\r
- return v;\r
- s = s.getPrototype();\r
- } while (s != null);\r
- return v;\r
- }\r
-\r
-\r
-\r
-/***********************************************************************/\r
-\r
- public static Scriptable getProto(Object obj, Scriptable scope) {\r
- Scriptable s;\r
- if (obj instanceof Scriptable) {\r
- s = (Scriptable) obj;\r
- } else {\r
- s = toObject(scope, obj);\r
- }\r
- if (s == null) {\r
- throw NativeGlobal.typeError0("msg.null.to.object", scope);\r
- }\r
- return s.getPrototype();\r
- }\r
-\r
- public static Scriptable getParent(Object obj) {\r
- Scriptable s;\r
- try {\r
- s = (Scriptable) obj;\r
- }\r
- catch (ClassCastException e) {\r
- return null;\r
- }\r
- if (s == null) {\r
- return null;\r
- }\r
- return getThis(s.getParentScope());\r
- }\r
-\r
- public static Scriptable getParent(Object obj, Scriptable scope) {\r
- Scriptable s;\r
- if (obj instanceof Scriptable) {\r
- s = (Scriptable) obj;\r
- } else {\r
- s = toObject(scope, obj);\r
- }\r
- if (s == null) {\r
- throw NativeGlobal.typeError0("msg.null.to.object", scope);\r
- }\r
- return s.getParentScope();\r
- }\r
-\r
- public static Object setProto(Object obj, Object value, Scriptable scope) {\r
- Scriptable start;\r
- if (obj instanceof Scriptable) {\r
- start = (Scriptable) obj;\r
- } else {\r
- start = toObject(scope, obj);\r
- }\r
- Scriptable result = value == null ? null : toObject(scope, value);\r
- Scriptable s = result;\r
- while (s != null) {\r
- if (s == start) {\r
- throw Context.reportRuntimeError1(\r
- "msg.cyclic.value", "__proto__");\r
- }\r
- s = s.getPrototype();\r
- }\r
- if (start == null) {\r
- throw NativeGlobal.typeError0("msg.null.to.object", scope);\r
- }\r
- start.setPrototype(result);\r
- return result;\r
- }\r
-\r
- public static Object setParent(Object obj, Object value, Scriptable scope) {\r
- Scriptable start;\r
- if (obj instanceof Scriptable) {\r
- start = (Scriptable) obj;\r
- } else {\r
- start = toObject(scope, obj);\r
- }\r
- Scriptable result = value == null ? null : toObject(scope, value);\r
- Scriptable s = result;\r
- while (s != null) {\r
- if (s == start) {\r
- throw Context.reportRuntimeError1(\r
- "msg.cyclic.value", "__parent__");\r
- }\r
- s = s.getParentScope();\r
- }\r
- if (start == null) {\r
- throw NativeGlobal.typeError0("msg.null.to.object", scope);\r
- }\r
- start.setParentScope(result);\r
- return result;\r
- }\r
-\r
- public static Object setProp(Object obj, String id, Object value,\r
- Scriptable scope)\r
- {\r
- Scriptable start;\r
- if (obj instanceof Scriptable) {\r
- start = (Scriptable) obj;\r
- } else {\r
- start = toObject(scope, obj);\r
- }\r
- if (start == null) {\r
- throw NativeGlobal.typeError0("msg.null.to.object", scope);\r
- }\r
- Scriptable m = start;\r
- do {\r
- if (m.has(id, start)) {\r
- m.put(id, start, value);\r
- return value;\r
- }\r
- m = m.getPrototype();\r
- } while (m != null);\r
-\r
- start.put(id, start, value);\r
- return value;\r
- }\r
-\r
- // Return -1L if str is not an index or the index value as lower 32 \r
- // bits of the result\r
- private static long indexFromString(String str) {\r
- // It must be a string.\r
-\r
- // The length of the decimal string representation of \r
- // Integer.MAX_VALUE, 2147483647\r
- final int MAX_VALUE_LENGTH = 10;\r
- \r
- int len = str.length();\r
- if (len > 0) {\r
- int i = 0;\r
- boolean negate = false;\r
- int c = str.charAt(0);\r
- if (c == '-') {\r
- if (len > 1) {\r
- c = str.charAt(1); \r
- i = 1; \r
- negate = true;\r
- }\r
- }\r
- c -= '0';\r
- if (0 <= c && c <= 9 \r
- && len <= (negate ? MAX_VALUE_LENGTH + 1 : MAX_VALUE_LENGTH))\r
- {\r
- // Use negative numbers to accumulate index to handle\r
- // Integer.MIN_VALUE that is greater by 1 in absolute value\r
- // then Integer.MAX_VALUE\r
- int index = -c;\r
- int oldIndex = 0;\r
- i++;\r
- if (index != 0) {\r
- // Note that 00, 01, 000 etc. are not indexes\r
- while (i != len && 0 <= (c = str.charAt(i) - '0') && c <= 9)\r
- {\r
- oldIndex = index;\r
- index = 10 * index - c;\r
- i++;\r
- }\r
- }\r
- // Make sure all characters were consumed and that it couldn't\r
- // have overflowed.\r
- if (i == len &&\r
- (oldIndex > (Integer.MIN_VALUE / 10) ||\r
- (oldIndex == (Integer.MIN_VALUE / 10) &&\r
- c <= (negate ? -(Integer.MIN_VALUE % 10) \r
- : (Integer.MAX_VALUE % 10)))))\r
- {\r
- return 0xFFFFFFFFL & (negate ? index : -index);\r
- }\r
- }\r
- }\r
- return -1L;\r
- }\r
-\r
- static String getStringId(Object id) {\r
- if (id instanceof Number) {\r
- double d = ((Number) id).doubleValue();\r
- int index = (int) d;\r
- if (((double) index) == d)\r
- return null;\r
- return toString(id);\r
- }\r
- String s = toString(id);\r
- long indexTest = indexFromString(s);\r
- if (indexTest >= 0)\r
- return null;\r
- return s;\r
- }\r
-\r
- static int getIntId(Object id) {\r
- if (id instanceof Number) {\r
- double d = ((Number) id).doubleValue();\r
- int index = (int) d;\r
- if (((double) index) == d)\r
- return index;\r
- return 0;\r
- }\r
- String s = toString(id);\r
- long indexTest = indexFromString(s);\r
- if (indexTest >= 0)\r
- return (int)indexTest;\r
- return 0;\r
- }\r
-\r
- public static Object getElem(Object obj, Object id, Scriptable scope) {\r
- int index;\r
- String s;\r
- if (id instanceof Number) {\r
- double d = ((Number) id).doubleValue();\r
- index = (int) d;\r
- s = ((double) index) == d ? null : toString(id);\r
- } else {\r
- s = toString(id);\r
- long indexTest = indexFromString(s);\r
- if (indexTest >= 0) {\r
- index = (int)indexTest;\r
- s = null;\r
- } else {\r
- index = 0;\r
- } \r
- }\r
- Scriptable start = obj instanceof Scriptable\r
- ? (Scriptable) obj\r
- : toObject(scope, obj);\r
- Scriptable m = start;\r
- if (s != null) {\r
- if (s.equals("__proto__"))\r
- return start.getPrototype();\r
- if (s.equals("__parent__"))\r
- return start.getParentScope();\r
- while (m != null) {\r
- Object result = m.get(s, start);\r
- if (result != Scriptable.NOT_FOUND)\r
- return result;\r
- m = m.getPrototype();\r
- }\r
- return Undefined.instance;\r
- }\r
- while (m != null) {\r
- Object result = m.get(index, start);\r
- if (result != Scriptable.NOT_FOUND)\r
- return result;\r
- m = m.getPrototype();\r
- }\r
- return Undefined.instance;\r
- }\r
-\r
-\r
- /*\r
- * A cheaper and less general version of the above for well-known argument\r
- * types.\r
- */\r
- public static Object getElem(Scriptable obj, int index)\r
- {\r
- Scriptable m = obj;\r
- while (m != null) {\r
- Object result = m.get(index, obj);\r
- if (result != Scriptable.NOT_FOUND)\r
- return result;\r
- m = m.getPrototype();\r
- }\r
- return Undefined.instance;\r
- }\r
-\r
- public static Object setElem(Object obj, Object id, Object value,\r
- Scriptable scope)\r
- {\r
- int index;\r
- String s;\r
- if (id instanceof Number) {\r
- double d = ((Number) id).doubleValue();\r
- index = (int) d;\r
- s = ((double) index) == d ? null : toString(id);\r
- } else {\r
- s = toString(id);\r
- long indexTest = indexFromString(s);\r
- if (indexTest >= 0) {\r
- index = (int)indexTest;\r
- s = null;\r
- } else {\r
- index = 0;\r
- }\r
- }\r
-\r
- Scriptable start = obj instanceof Scriptable\r
- ? (Scriptable) obj\r
- : toObject(scope, obj);\r
- Scriptable m = start;\r
- if (s != null) {\r
- if (s.equals("__proto__"))\r
- return setProto(obj, value, scope);\r
- if (s.equals("__parent__"))\r
- return setParent(obj, value, scope);\r
-\r
- do {\r
- if (m.has(s, start)) {\r
- m.put(s, start, value);\r
- return value;\r
- }\r
- m = m.getPrototype();\r
- } while (m != null);\r
- start.put(s, start, value);\r
- return value;\r
- }\r
-\r
- do {\r
- if (m.has(index, start)) {\r
- m.put(index, start, value);\r
- return value;\r
- }\r
- m = m.getPrototype();\r
- } while (m != null);\r
- start.put(index, start, value);\r
- return value;\r
- }\r
-\r
- /*\r
- * A cheaper and less general version of the above for well-known argument\r
- * types.\r
- */\r
- public static Object setElem(Scriptable obj, int index, Object value)\r
- {\r
- Scriptable m = obj;\r
- do {\r
- if (m.has(index, obj)) {\r
- m.put(index, obj, value);\r
- return value;\r
- }\r
- m = m.getPrototype();\r
- } while (m != null);\r
- obj.put(index, obj, value);\r
- return value;\r
- }\r
-\r
- /**\r
- * The delete operator\r
- *\r
- * See ECMA 11.4.1\r
- *\r
- * In ECMA 0.19, the description of the delete operator (11.4.1)\r
- * assumes that the [[Delete]] method returns a value. However,\r
- * the definition of the [[Delete]] operator (8.6.2.5) does not\r
- * define a return value. Here we assume that the [[Delete]]\r
- * method doesn't return a value.\r
- */\r
- public static Object delete(Object obj, Object id) {\r
- String s = getStringId(id);\r
- boolean result = s != null\r
- ? ScriptableObject.deleteProperty((Scriptable) obj, s)\r
- : ScriptableObject.deleteProperty((Scriptable) obj, getIntId(id));\r
- return result ? Boolean.TRUE : Boolean.FALSE;\r
- }\r
-\r
- /**\r
- * Looks up a name in the scope chain and returns its value.\r
- */\r
- public static Object name(Scriptable scopeChain, String id) {\r
- Scriptable obj = scopeChain;\r
- Object prop;\r
- while (obj != null) {\r
- Scriptable m = obj;\r
- do {\r
- Object result = m.get(id, obj);\r
- if (result != Scriptable.NOT_FOUND)\r
- return result;\r
- m = m.getPrototype();\r
- } while (m != null);\r
- obj = obj.getParentScope();\r
- }\r
- throw NativeGlobal.constructError\r
- (Context.getContext(), "ReferenceError",\r
- ScriptRuntime.getMessage1("msg.is.not.defined", id.toString()),\r
- scopeChain);\r
- }\r
-\r
- /**\r
- * Returns the object in the scope chain that has a given property.\r
- *\r
- * The order of evaluation of an assignment expression involves\r
- * evaluating the lhs to a reference, evaluating the rhs, and then\r
- * modifying the reference with the rhs value. This method is used\r
- * to 'bind' the given name to an object containing that property\r
- * so that the side effects of evaluating the rhs do not affect\r
- * which property is modified.\r
- * Typically used in conjunction with setName.\r
- *\r
- * See ECMA 10.1.4\r
- */\r
- public static Scriptable bind(Scriptable scope, String id) {\r
- Scriptable obj = scope;\r
- Object prop;\r
- while (obj != null) {\r
- Scriptable m = obj;\r
- do {\r
- if (m.has(id, obj))\r
- return obj;\r
- m = m.getPrototype();\r
- } while (m != null);\r
- obj = obj.getParentScope();\r
- }\r
- return null;\r
- }\r
-\r
- public static Scriptable getBase(Scriptable scope, String id) {\r
- Scriptable obj = scope;\r
- Object prop;\r
- while (obj != null) {\r
- Scriptable m = obj;\r
- do {\r
- if (m.get(id, obj) != Scriptable.NOT_FOUND)\r
- return obj;\r
- m = m.getPrototype();\r
- } while (m != null);\r
- obj = obj.getParentScope();\r
- }\r
- throw NativeGlobal.constructError(\r
- Context.getContext(), "ReferenceError",\r
- ScriptRuntime.getMessage1("msg.is.not.defined", id),\r
- scope);\r
- }\r
-\r
- public static Scriptable getThis(Scriptable base) {\r
- while (base instanceof NativeWith)\r
- base = base.getPrototype();\r
- if (base instanceof NativeCall)\r
- base = ScriptableObject.getTopLevelScope(base);\r
- return base;\r
- }\r
-\r
- public static Object setName(Scriptable bound, Object value,\r
- Scriptable scope, String id)\r
- {\r
- if (bound == null) {\r
- // "newname = 7;", where 'newname' has not yet\r
- // been defined, creates a new property in the\r
- // global object. Find the global object by\r
- // walking up the scope chain.\r
- Scriptable next = scope;\r
- do {\r
- bound = next;\r
- next = bound.getParentScope();\r
- } while (next != null);\r
-\r
- bound.put(id, bound, value);\r
- /*\r
- This code is causing immense performance problems in\r
- scripts that assign to the variables as a way of creating them.\r
- XXX need strict mode\r
- String message = getMessage1("msg.assn.create", id);\r
- Context.reportWarning(message);\r
- */\r
- return value;\r
- }\r
- return setProp(bound, id, value, scope);\r
- }\r
-\r
- public static Enumeration initEnum(Object value, Scriptable scope) {\r
- Scriptable m = toObject(scope, value);\r
- return new IdEnumeration(m);\r
- }\r
-\r
- public static Object nextEnum(Enumeration enum) {\r
- // OPT this could be more efficient; should junk the Enumeration\r
- // interface\r
- if (!enum.hasMoreElements())\r
- return null;\r
- return enum.nextElement();\r
- }\r
-\r
- // Form used by class files generated by 1.4R3 and earlier.\r
- public static Object call(Context cx, Object fun, Object thisArg,\r
- Object[] args)\r
- throws JavaScriptException\r
- {\r
- Scriptable scope = null;\r
- if (fun instanceof Scriptable) \r
- scope = ((Scriptable) fun).getParentScope();\r
- return call(cx, fun, thisArg, args, scope);\r
- }\r
- \r
- public static Object call(Context cx, Object fun, Object thisArg,\r
- Object[] args, Scriptable scope)\r
- throws JavaScriptException\r
- {\r
- Function function;\r
- try {\r
- function = (Function) fun;\r
- }\r
- catch (ClassCastException e) {\r
- throw NativeGlobal.typeError1\r
- ("msg.isnt.function", toString(fun), scope);\r
- }\r
-\r
- Scriptable thisObj;\r
- if (thisArg instanceof Scriptable || thisArg == null) {\r
- thisObj = (Scriptable) thisArg;\r
- } else {\r
- thisObj = ScriptRuntime.toObject(scope, thisArg);\r
- }\r
- if (function == null) throw NativeGlobal.typeError0("msg.null.to.object", scope);\r
- return function.call(cx, scope, thisObj, args);\r
- }\r
-\r
- private static Object callOrNewSpecial(Context cx, Scriptable scope,\r
- Object fun, Object jsThis, \r
- Object thisArg,\r
- Object[] args, boolean isCall,\r
- String filename, int lineNumber)\r
- throws JavaScriptException\r
- {\r
- if (fun instanceof IdFunction) {\r
- IdFunction f = (IdFunction)fun;\r
- String name = f.getFunctionName();\r
- if (name.length() == 4) {\r
- if (name.equals("eval")) {\r
- if (f.master.getClass() == NativeGlobal.class) {\r
- return NativeGlobal.evalSpecial(cx, scope, \r
- thisArg, args,\r
- filename, lineNumber);\r
- }\r
- }\r
- else if (name.equals("With")) {\r
- if (f.master.getClass() == NativeWith.class) {\r
- return NativeWith.newWithSpecial(cx, args, f, !isCall);\r
- }\r
- }\r
- else if (name.equals("exec")) {\r
- if (f.master.getClass() == NativeScript.class) {\r
- return ((NativeScript)jsThis).\r
- exec(cx, ScriptableObject.getTopLevelScope(scope));\r
- }\r
- else {\r
- RegExpProxy proxy = cx.getRegExpProxy();\r
- if (proxy != null && proxy.isRegExp(jsThis)) {\r
- return call(cx, fun, jsThis, args, scope);\r
- }\r
- }\r
- }\r
- }\r
- }\r
- else // could've been <java>.XXX.exec() that was re-directed here\r
- if (fun instanceof NativeJavaMethod)\r
- return call(cx, fun, jsThis, args, scope);\r
-\r
- if (isCall)\r
- return call(cx, fun, thisArg, args, scope);\r
- return newObject(cx, fun, args, scope);\r
- }\r
-\r
- public static Object callSpecial(Context cx, Object fun,\r
- Object thisArg, Object[] args,\r
- Scriptable enclosingThisArg,\r
- Scriptable scope, String filename,\r
- int lineNumber)\r
- throws JavaScriptException\r
- {\r
- return callOrNewSpecial(cx, scope, fun, thisArg,\r
- enclosingThisArg, args, true,\r
- filename, lineNumber);\r
- }\r
-\r
- /**\r
- * Operator new.\r
- *\r
- * See ECMA 11.2.2\r
- */\r
- public static Scriptable newObject(Context cx, Object fun,\r
- Object[] args, Scriptable scope)\r
- throws JavaScriptException\r
- {\r
- Function f;\r
- try {\r
- f = (Function) fun;\r
- if (f != null) {\r
- return f.construct(cx, scope, args);\r
- }\r
- // else fall through to error\r
- } catch (ClassCastException e) {\r
- // fall through to error\r
- }\r
- throw NativeGlobal.typeError1\r
- ("msg.isnt.function", toString(fun), scope);\r
- }\r
-\r
- public static Scriptable newObjectSpecial(Context cx, Object fun,\r
- Object[] args, Scriptable scope)\r
- throws JavaScriptException\r
- {\r
- return (Scriptable) callOrNewSpecial(cx, scope, fun, null, null, args,\r
- false, null, -1);\r
- }\r
-\r
- /**\r
- * The typeof operator\r
- */\r
- public static String typeof(Object value) {\r
- if (value == Undefined.instance)\r
- return "undefined";\r
- if (value == null)\r
- return "object";\r
- if (value instanceof Scriptable)\r
- return (value instanceof Function) ? "function" : "object";\r
- if (value instanceof String)\r
- return "string";\r
- if (value instanceof Number)\r
- return "number";\r
- if (value instanceof Boolean)\r
- return "boolean";\r
- throw errorWithClassName("msg.invalid.type", value);\r
- }\r
-\r
- /**\r
- * The typeof operator that correctly handles the undefined case\r
- */\r
- public static String typeofName(Scriptable scope, String id) {\r
- Object val = bind(scope, id);\r
- if (val == null)\r
- return "undefined";\r
- return typeof(getProp(val, id, scope));\r
- }\r
-\r
- // neg:\r
- // implement the '-' operator inline in the caller\r
- // as "-toNumber(val)"\r
-\r
- // not:\r
- // implement the '!' operator inline in the caller\r
- // as "!toBoolean(val)"\r
-\r
- // bitnot:\r
- // implement the '~' operator inline in the caller\r
- // as "~toInt32(val)"\r
-\r
- public static Object add(Object val1, Object val2) {\r
- if (val1 instanceof Scriptable)\r
- val1 = ((Scriptable) val1).getDefaultValue(null);\r
- if (val2 instanceof Scriptable)\r
- val2 = ((Scriptable) val2).getDefaultValue(null);\r
- if (!(val1 instanceof String) && !(val2 instanceof String))\r
- if ((val1 instanceof Number) && (val2 instanceof Number))\r
- return new Double(((Number)val1).doubleValue() +\r
- ((Number)val2).doubleValue());\r
- else\r
- return new Double(toNumber(val1) + toNumber(val2));\r
- return toString(val1) + toString(val2);\r
- }\r
-\r
- public static Object postIncrement(Object value) {\r
- if (value instanceof Number)\r
- value = new Double(((Number)value).doubleValue() + 1.0);\r
- else\r
- value = new Double(toNumber(value) + 1.0);\r
- return value;\r
- }\r
-\r
- public static Object postIncrement(Scriptable scopeChain, String id) {\r
- Scriptable obj = scopeChain;\r
- Object prop;\r
- while (obj != null) {\r
- Scriptable m = obj;\r
- do {\r
- Object result = m.get(id, obj);\r
- if (result != Scriptable.NOT_FOUND) {\r
- Object newValue = result;\r
- if (newValue instanceof Number) {\r
- newValue = new Double(\r
- ((Number)newValue).doubleValue() + 1.0);\r
- m.put(id, obj, newValue);\r
- return result;\r
- }\r
- else {\r
- newValue = new Double(toNumber(newValue) + 1.0);\r
- m.put(id, obj, newValue);\r
- return new Double(toNumber(result));\r
- }\r
- }\r
- m = m.getPrototype();\r
- } while (m != null);\r
- obj = obj.getParentScope();\r
- }\r
- throw NativeGlobal.constructError\r
- (Context.getContext(), "ReferenceError",\r
- ScriptRuntime.getMessage1("msg.is.not.defined", id),\r
- scopeChain);\r
- }\r
-\r
- public static Object postIncrement(Object obj, String id, Scriptable scope) {\r
- Scriptable start;\r
- if (obj instanceof Scriptable) {\r
- start = (Scriptable) obj;\r
- } else {\r
- start = toObject(scope, obj);\r
- }\r
- if (start == null) {\r
- throw NativeGlobal.typeError0("msg.null.to.object", scope);\r
- }\r
- Scriptable m = start;\r
- do {\r
- Object result = m.get(id, start);\r
- if (result != Scriptable.NOT_FOUND) {\r
- Object newValue = result;\r
- if (newValue instanceof Number) {\r
- newValue = new Double(\r
- ((Number)newValue).doubleValue() + 1.0);\r
- m.put(id, start, newValue);\r
- return result;\r
- }\r
- else {\r
- newValue = new Double(toNumber(newValue) + 1.0);\r
- m.put(id, start, newValue);\r
- return new Double(toNumber(result));\r
- }\r
- }\r
- m = m.getPrototype();\r
- } while (m != null);\r
- return Undefined.instance;\r
- }\r
-\r
- public static Object postIncrementElem(Object obj,\r
- Object index, Scriptable scope) {\r
- Object oldValue = getElem(obj, index, scope);\r
- if (oldValue == Undefined.instance)\r
- return Undefined.instance;\r
- double resultValue = toNumber(oldValue);\r
- Double newValue = new Double(resultValue + 1.0);\r
- setElem(obj, index, newValue, scope);\r
- return new Double(resultValue);\r
- }\r
-\r
- public static Object postDecrementElem(Object obj,\r
- Object index, Scriptable scope) {\r
- Object oldValue = getElem(obj, index, scope);\r
- if (oldValue == Undefined.instance)\r
- return Undefined.instance;\r
- double resultValue = toNumber(oldValue);\r
- Double newValue = new Double(resultValue - 1.0);\r
- setElem(obj, index, newValue, scope);\r
- return new Double(resultValue);\r
- }\r
-\r
- public static Object postDecrement(Object value) {\r
- if (value instanceof Number)\r
- value = new Double(((Number)value).doubleValue() - 1.0);\r
- else\r
- value = new Double(toNumber(value) - 1.0);\r
- return value;\r
- }\r
-\r
- public static Object postDecrement(Scriptable scopeChain, String id) {\r
- Scriptable obj = scopeChain;\r
- Object prop;\r
- while (obj != null) {\r
- Scriptable m = obj;\r
- do {\r
- Object result = m.get(id, obj);\r
- if (result != Scriptable.NOT_FOUND) {\r
- Object newValue = result;\r
- if (newValue instanceof Number) {\r
- newValue = new Double(\r
- ((Number)newValue).doubleValue() - 1.0);\r
- m.put(id, obj, newValue);\r
- return result;\r
- }\r
- else {\r
- newValue = new Double(toNumber(newValue) - 1.0);\r
- m.put(id, obj, newValue);\r
- return new Double(toNumber(result));\r
- }\r
- }\r
- m = m.getPrototype();\r
- } while (m != null);\r
- obj = obj.getParentScope();\r
- }\r
- throw NativeGlobal.constructError\r
- (Context.getContext(), "ReferenceError",\r
- ScriptRuntime.getMessage1("msg.is.not.defined", id),\r
- scopeChain);\r
- }\r
-\r
- public static Object postDecrement(Object obj, String id, Scriptable scope) {\r
- Scriptable start;\r
- if (obj instanceof Scriptable) {\r
- start = (Scriptable) obj;\r
- } else {\r
- start = toObject(scope, obj);\r
- }\r
- if (start == null) {\r
- throw NativeGlobal.typeError0("msg.null.to.object", scope);\r
- }\r
- Scriptable m = start;\r
- do {\r
- Object result = m.get(id, start);\r
- if (result != Scriptable.NOT_FOUND) {\r
- Object newValue = result;\r
- if (newValue instanceof Number) {\r
- newValue = new Double(\r
- ((Number)newValue).doubleValue() - 1.0);\r
- m.put(id, start, newValue);\r
- return result;\r
- }\r
- else {\r
- newValue = new Double(toNumber(newValue) - 1.0);\r
- m.put(id, start, newValue);\r
- return new Double(toNumber(result));\r
- }\r
- }\r
- m = m.getPrototype();\r
- } while (m != null);\r
- return Undefined.instance;\r
- }\r
-\r
- public static Object toPrimitive(Object val) {\r
- if (val == null || !(val instanceof Scriptable)) {\r
- return val;\r
- }\r
- Object result = ((Scriptable) val).getDefaultValue(null);\r
- if (result != null && result instanceof Scriptable)\r
- throw NativeGlobal.typeError0("msg.bad.default.value", val);\r
- return result;\r
- }\r
-\r
- private static Class getTypeOfValue(Object obj) {\r
- if (obj == null)\r
- return ScriptableClass;\r
- if (obj == Undefined.instance)\r
- return UndefinedClass;\r
- if (obj instanceof Scriptable)\r
- return ScriptableClass;\r
- if (obj instanceof Number)\r
- return NumberClass;\r
- return obj.getClass();\r
- }\r
-\r
- /**\r
- * Equality\r
- *\r
- * See ECMA 11.9\r
- */\r
- public static boolean eq(Object x, Object y) {\r
- Object xCopy = x; // !!! JIT bug in Cafe 2.1\r
- Object yCopy = y; // need local copies, otherwise their values get blown below\r
- for (;;) {\r
- Class typeX = getTypeOfValue(x);\r
- Class typeY = getTypeOfValue(y);\r
- if (typeX == typeY) {\r
- if (typeX == UndefinedClass)\r
- return true;\r
- if (typeX == NumberClass)\r
- return ((Number) x).doubleValue() ==\r
- ((Number) y).doubleValue();\r
- if (typeX == StringClass || typeX == BooleanClass)\r
- return xCopy.equals(yCopy); // !!! JIT bug in Cafe 2.1\r
- if (typeX == ScriptableClass) {\r
- if (x == y)\r
- return true;\r
- if (x instanceof Wrapper &&\r
- y instanceof Wrapper)\r
- {\r
- return ((Wrapper) x).unwrap() ==\r
- ((Wrapper) y).unwrap();\r
- }\r
- return false;\r
- }\r
- throw new RuntimeException(); // shouldn't get here\r
- }\r
- if (x == null && y == Undefined.instance)\r
- return true;\r
- if (x == Undefined.instance && y == null)\r
- return true;\r
- if (typeX == NumberClass &&\r
- typeY == StringClass)\r
- {\r
- return ((Number) x).doubleValue() == toNumber(y);\r
- }\r
- if (typeX == StringClass &&\r
- typeY == NumberClass)\r
- {\r
- return toNumber(x) == ((Number) y).doubleValue();\r
- }\r
- if (typeX == BooleanClass) {\r
- x = new Double(toNumber(x));\r
- xCopy = x; // !!! JIT bug in Cafe 2.1\r
- continue;\r
- }\r
- if (typeY == BooleanClass) {\r
- y = new Double(toNumber(y));\r
- yCopy = y; // !!! JIT bug in Cafe 2.1\r
- continue;\r
- }\r
- if ((typeX == StringClass ||\r
- typeX == NumberClass) &&\r
- typeY == ScriptableClass && y != null)\r
- {\r
- y = toPrimitive(y);\r
- yCopy = y; // !!! JIT bug in Cafe 2.1\r
- continue;\r
- }\r
- if (typeX == ScriptableClass && x != null &&\r
- (typeY == StringClass ||\r
- typeY == NumberClass))\r
- {\r
- x = toPrimitive(x);\r
- xCopy = x; // !!! JIT bug in Cafe 2.1\r
- continue;\r
- }\r
- return false;\r
- }\r
- }\r
-\r
- public static Boolean eqB(Object x, Object y) {\r
- if (eq(x,y))\r
- return Boolean.TRUE;\r
- else\r
- return Boolean.FALSE;\r
- }\r
-\r
- public static Boolean neB(Object x, Object y) {\r
- if (eq(x,y))\r
- return Boolean.FALSE;\r
- else\r
- return Boolean.TRUE;\r
- }\r
-\r
- public static boolean shallowEq(Object x, Object y) {\r
- Class type = getTypeOfValue(x);\r
- if (type != getTypeOfValue(y))\r
- return false;\r
- if (type == StringClass || type == BooleanClass)\r
- return x.equals(y);\r
- if (type == NumberClass)\r
- return ((Number) x).doubleValue() ==\r
- ((Number) y).doubleValue();\r
- if (type == ScriptableClass) {\r
- if (x == y)\r
- return true;\r
- if (x instanceof Wrapper && y instanceof Wrapper)\r
- return ((Wrapper) x).unwrap() ==\r
- ((Wrapper) y).unwrap();\r
- return false;\r
- }\r
- if (type == UndefinedClass)\r
- return true;\r
- return false;\r
- }\r
-\r
- public static Boolean seqB(Object x, Object y) {\r
- if (shallowEq(x,y))\r
- return Boolean.TRUE;\r
- else\r
- return Boolean.FALSE;\r
- }\r
-\r
- public static Boolean sneB(Object x, Object y) {\r
- if (shallowEq(x,y))\r
- return Boolean.FALSE;\r
- else\r
- return Boolean.TRUE;\r
- }\r
-\r
- /**\r
- * The instanceof operator.\r
- *\r
- * @return a instanceof b\r
- */\r
- public static boolean instanceOf(Scriptable scope, Object a, Object b) {\r
- // Check RHS is an object\r
- if (! (b instanceof Scriptable)) {\r
- throw NativeGlobal.typeError0("msg.instanceof.not.object", scope);\r
- }\r
-\r
- // for primitive values on LHS, return false\r
- // XXX we may want to change this so that\r
- // 5 instanceof Number == true\r
- if (! (a instanceof Scriptable))\r
- return false;\r
-\r
- return ((Scriptable)b).hasInstance((Scriptable)a);\r
- }\r
-\r
- /**\r
- * Delegates to\r
- *\r
- * @return true iff rhs appears in lhs' proto chain\r
- */\r
- protected static boolean jsDelegatesTo(Scriptable lhs, Scriptable rhs) {\r
- Scriptable proto = lhs.getPrototype();\r
-\r
- while (proto != null) {\r
- if (proto.equals(rhs)) return true;\r
- proto = proto.getPrototype();\r
- }\r
-\r
- return false;\r
- }\r
-\r
- /**\r
- * The in operator.\r
- *\r
- * This is a new JS 1.3 language feature. The in operator mirrors\r
- * the operation of the for .. in construct, and tests whether the\r
- * rhs has the property given by the lhs. It is different from the \r
- * for .. in construct in that:\r
- * <BR> - it doesn't perform ToObject on the right hand side\r
- * <BR> - it returns true for DontEnum properties.\r
- * @param a the left hand operand\r
- * @param b the right hand operand\r
- *\r
- * @return true if property name or element number a is a property of b\r
- */\r
- public static boolean in(Object a, Object b, Scriptable scope) {\r
- if (!(b instanceof Scriptable)) {\r
- throw NativeGlobal.typeError0("msg.instanceof.not.object", scope);\r
- }\r
- String s = getStringId(a);\r
- return s != null\r
- ? ScriptableObject.hasProperty((Scriptable) b, s)\r
- : ScriptableObject.hasProperty((Scriptable) b, getIntId(a));\r
- }\r
-\r
- public static Boolean cmp_LTB(Object val1, Object val2) {\r
- if (cmp_LT(val1, val2) == 1)\r
- return Boolean.TRUE;\r
- else\r
- return Boolean.FALSE;\r
- }\r
-\r
- public static int cmp_LT(Object val1, Object val2) {\r
- if (val1 instanceof Scriptable)\r
- val1 = ((Scriptable) val1).getDefaultValue(NumberClass);\r
- if (val2 instanceof Scriptable)\r
- val2 = ((Scriptable) val2).getDefaultValue(NumberClass);\r
- if (!(val1 instanceof String) || !(val2 instanceof String)) {\r
- double d1 = toNumber(val1);\r
- if (d1 != d1)\r
- return 0;\r
- double d2 = toNumber(val2);\r
- if (d2 != d2)\r
- return 0;\r
- return d1 < d2 ? 1 : 0;\r
- }\r
- return toString(val1).compareTo(toString(val2)) < 0 ? 1 : 0;\r
- }\r
-\r
- public static Boolean cmp_LEB(Object val1, Object val2) {\r
- if (cmp_LE(val1, val2) == 1)\r
- return Boolean.TRUE;\r
- else\r
- return Boolean.FALSE;\r
- }\r
-\r
- public static int cmp_LE(Object val1, Object val2) {\r
- if (val1 instanceof Scriptable)\r
- val1 = ((Scriptable) val1).getDefaultValue(NumberClass);\r
- if (val2 instanceof Scriptable)\r
- val2 = ((Scriptable) val2).getDefaultValue(NumberClass);\r
- if (!(val1 instanceof String) || !(val2 instanceof String)) {\r
- double d1 = toNumber(val1);\r
- if (d1 != d1)\r
- return 0;\r
- double d2 = toNumber(val2);\r
- if (d2 != d2)\r
- return 0;\r
- return d1 <= d2 ? 1 : 0;\r
- }\r
- return toString(val1).compareTo(toString(val2)) <= 0 ? 1 : 0;\r
- }\r
-\r
- // lt:\r
- // implement the '<' operator inline in the caller\r
- // as "compare(val1, val2) == 1"\r
-\r
- // le:\r
- // implement the '<=' operator inline in the caller\r
- // as "compare(val2, val1) == 0"\r
-\r
- // gt:\r
- // implement the '>' operator inline in the caller\r
- // as "compare(val2, val1) == 1"\r
-\r
- // ge:\r
- // implement the '>=' operator inline in the caller\r
- // as "compare(val1, val2) == 0"\r
-\r
- // ------------------\r
- // Statements\r
- // ------------------\r
-\r
- private static final String GLOBAL_CLASS = \r
- "org.mozilla.javascript.tools.shell.Global";\r
-\r
- private static ScriptableObject getGlobal(Context cx) {\r
- try {\r
- Class globalClass = loadClassName(GLOBAL_CLASS);\r
- Class[] parm = { Context.class };\r
- Constructor globalClassCtor = globalClass.getConstructor(parm);\r
- Object[] arg = { cx };\r
- return (ScriptableObject) globalClassCtor.newInstance(arg);\r
- } catch (ClassNotFoundException e) {\r
- // fall through...\r
- } catch (NoSuchMethodException e) {\r
- // fall through...\r
- } catch (InvocationTargetException e) {\r
- // fall through...\r
- } catch (IllegalAccessException e) {\r
- // fall through...\r
- } catch (InstantiationException e) {\r
- // fall through...\r
- }\r
- return new ImporterTopLevel(cx);\r
- }\r
-\r
- public static void main(String scriptClassName, String[] args)\r
- throws JavaScriptException\r
- {\r
- Context cx = Context.enter();\r
- ScriptableObject global = getGlobal(cx);\r
-\r
- // get the command line arguments and define "arguments" \r
- // array in the top-level object\r
- Scriptable argsObj = cx.newArray(global, args);\r
- global.defineProperty("arguments", argsObj,\r
- ScriptableObject.DONTENUM);\r
- \r
- try {\r
- Class cl = loadClassName(scriptClassName);\r
- Script script = (Script) cl.newInstance();\r
- script.exec(cx, global);\r
- return;\r
- }\r
- catch (ClassNotFoundException e) {\r
- }\r
- catch (InstantiationException e) {\r
- }\r
- catch (IllegalAccessException e) {\r
- }\r
- finally {\r
- Context.exit();\r
- }\r
- throw new RuntimeException("Error creating script object");\r
- }\r
-\r
- public static Scriptable initScript(Context cx, Scriptable scope,\r
- NativeFunction funObj,\r
- Scriptable thisObj,\r
- boolean fromEvalCode)\r
- {\r
- String[] argNames = funObj.argNames;\r
- if (argNames != null) {\r
- ScriptableObject so;\r
- try {\r
- /* Global var definitions are supposed to be DONTDELETE\r
- * so we try to create them that way by hoping that the\r
- * scope is a ScriptableObject which provides access to\r
- * setting the attributes.\r
- */\r
- so = (ScriptableObject) scope;\r
- } catch (ClassCastException x) {\r
- // oh well, we tried.\r
- so = null;\r
- }\r
-\r
- Scriptable varScope = scope;\r
- if (fromEvalCode) {\r
- // When executing an eval() inside a with statement,\r
- // define any variables resulting from var statements\r
- // in the first non-with scope. See bug 38590.\r
- varScope = scope;\r
- while (varScope instanceof NativeWith)\r
- varScope = varScope.getParentScope();\r
- }\r
- for (int i = argNames.length; i-- != 0;) {\r
- String name = argNames[i];\r
- // Don't overwrite existing def if already defined in object\r
- // or prototypes of object.\r
- if (!hasProp(scope, name)) {\r
- if (so != null && !fromEvalCode)\r
- so.defineProperty(name, Undefined.instance,\r
- ScriptableObject.PERMANENT);\r
- else \r
- varScope.put(name, varScope, Undefined.instance);\r
- }\r
- }\r
- }\r
-\r
- return scope;\r
- }\r
-\r
- public static Scriptable runScript(Script script) {\r
- Context cx = Context.enter();\r
- ScriptableObject global = getGlobal(cx);\r
- try {\r
- script.exec(cx, global);\r
- } catch (JavaScriptException e) {\r
- throw new Error(e.toString());\r
- } finally {\r
- Context.exit();\r
- }\r
- return global;\r
- }\r
-\r
- public static Scriptable initVarObj(Context cx, Scriptable scope,\r
- NativeFunction funObj,\r
- Scriptable thisObj, Object[] args)\r
- {\r
- NativeCall result = new NativeCall(cx, scope, funObj, thisObj, args);\r
- String[] argNames = funObj.argNames;\r
- if (argNames != null) {\r
- for (int i = funObj.argCount; i != argNames.length; i++) {\r
- String name = argNames[i];\r
- result.put(name, result, Undefined.instance);\r
- }\r
- }\r
- return result;\r
- }\r
-\r
- public static void popActivation(Context cx) {\r
- NativeCall current = cx.currentActivation;\r
- if (current != null) {\r
- cx.currentActivation = current.caller;\r
- current.caller = null;\r
- }\r
- }\r
-\r
- public static Scriptable newScope() {\r
- return new NativeObject();\r
- }\r
-\r
- public static Scriptable enterWith(Object value, Scriptable scope) {\r
- return new NativeWith(scope, toObject(scope, value));\r
- }\r
-\r
- public static Scriptable leaveWith(Scriptable scope) {\r
- return scope.getParentScope();\r
- }\r
-\r
- public static NativeFunction initFunction(NativeFunction fn,\r
- Scriptable scope,\r
- String fnName,\r
- Context cx,\r
- boolean doSetName)\r
- {\r
- fn.setPrototype(ScriptableObject.getClassPrototype(scope, "Function"));\r
- fn.setParentScope(scope);\r
- if (doSetName)\r
- setName(scope, fn, scope, fnName);\r
- return fn;\r
- }\r
-\r
- public static NativeFunction createFunctionObject(Scriptable scope,\r
- Class functionClass,\r
- Context cx,\r
- boolean setName)\r
- {\r
- Constructor[] ctors = functionClass.getConstructors();\r
-\r
- NativeFunction result = null;\r
- Object[] initArgs = { scope, cx };\r
- try {\r
- result = (NativeFunction) ctors[0].newInstance(initArgs);\r
- }\r
- catch (InstantiationException e) {\r
- throw WrappedException.wrapException(e);\r
- }\r
- catch (IllegalAccessException e) {\r
- throw WrappedException.wrapException(e);\r
- }\r
- catch (IllegalArgumentException e) {\r
- throw WrappedException.wrapException(e);\r
- }\r
- catch (InvocationTargetException e) {\r
- throw WrappedException.wrapException(e);\r
- }\r
-\r
- result.setPrototype(ScriptableObject.getClassPrototype(scope, "Function"));\r
- result.setParentScope(scope);\r
-\r
- String fnName = result.getFunctionName();\r
- if (setName && fnName != null && fnName.length() != 0 && \r
- !fnName.equals("anonymous"))\r
- {\r
- setProp(scope, fnName, result, scope);\r
- }\r
-\r
- return result;\r
- }\r
-\r
- static void checkDeprecated(Context cx, String name) {\r
- int version = cx.getLanguageVersion();\r
- if (version >= Context.VERSION_1_4 || version == Context.VERSION_DEFAULT) {\r
- String msg = getMessage1("msg.deprec.ctor", name);\r
- if (version == Context.VERSION_DEFAULT)\r
- Context.reportWarning(msg);\r
- else\r
- throw Context.reportRuntimeError(msg);\r
- }\r
- }\r
-\r
- public static String getMessage0(String messageId) {\r
- return Context.getMessage0(messageId);\r
- }\r
-\r
- public static String getMessage1(String messageId, Object arg1) {\r
- return Context.getMessage1(messageId, arg1);\r
- }\r
-\r
- public static String getMessage2\r
- (String messageId, Object arg1, Object arg2) \r
- {\r
- return Context.getMessage2(messageId, arg1, arg2);\r
- }\r
-\r
- public static String getMessage(String messageId, Object[] arguments) {\r
- return Context.getMessage(messageId, arguments);\r
- }\r
-\r
- public static RegExpProxy getRegExpProxy(Context cx) {\r
- return cx.getRegExpProxy();\r
- }\r
-\r
- public static NativeCall getCurrentActivation(Context cx) {\r
- return cx.currentActivation;\r
- }\r
-\r
- public static void setCurrentActivation(Context cx,\r
- NativeCall activation)\r
- {\r
- cx.currentActivation = activation;\r
- }\r
-\r
- public static Class loadClassName(String className) \r
- throws ClassNotFoundException\r
- {\r
- /*\r
- try {\r
- ClassLoader cl = DefiningClassLoader.getContextClassLoader();\r
- if (cl != null)\r
- return cl.loadClass(className);\r
- } catch (SecurityException e) {\r
- // fall through...\r
- } catch (ClassNotFoundException e) {\r
- // Rather than just letting the exception propagate\r
- // we'll try Class.forName as well. The results could be\r
- // different if this class was loaded on a different\r
- // thread than the current thread.\r
- // So fall through...\r
- }\r
- */\r
- return Class.forName(className); \r
- }\r
-\r
- static boolean hasProp(Scriptable start, String name) {\r
- Scriptable m = start;\r
- do {\r
- if (m.has(name, start))\r
- return true;\r
- m = m.getPrototype();\r
- } while (m != null);\r
- return false;\r
- }\r
-\r
- private static RuntimeException errorWithClassName(String msg, Object val)\r
- {\r
- return Context.reportRuntimeError1(msg, val.getClass().getName());\r
- }\r
-\r
- public static final Object[] emptyArgs = new Object[0];\r
-\r
-}\r
-\r
-\r
-/**\r
- * This is the enumeration needed by the for..in statement.\r
- *\r
- * See ECMA 12.6.3.\r
- *\r
- * IdEnumeration maintains a Hashtable to make sure a given\r
- * id is enumerated only once across multiple objects in a\r
- * prototype chain.\r
- *\r
- * XXX - ECMA delete doesn't hide properties in the prototype,\r
- * but js/ref does. This means that the js/ref for..in can\r
- * avoid maintaining a hash table and instead perform lookups\r
- * to see if a given property has already been enumerated.\r
- *\r
- */\r
-class IdEnumeration implements Enumeration {\r
- IdEnumeration(Scriptable m) {\r
- used = new Hashtable(27);\r
- changeObject(m);\r
- next = getNext();\r
- }\r
-\r
- public boolean hasMoreElements() {\r
- return next != null;\r
- }\r
-\r
- public Object nextElement() {\r
- Object result = next;\r
-\r
- // only key used; 'next' as value for convenience\r
- used.put(next, next);\r
-\r
- next = getNext();\r
- return result;\r
- }\r
-\r
- private void changeObject(Scriptable m) {\r
- obj = m;\r
- if (obj != null) {\r
- array = m.getIds();\r
- if (array.length == 0)\r
- changeObject(obj.getPrototype());\r
- }\r
- index = 0;\r
- }\r
-\r
- private Object getNext() {\r
- if (obj == null)\r
- return null;\r
- Object result;\r
- for (;;) {\r
- if (index == array.length) {\r
- changeObject(obj.getPrototype());\r
- if (obj == null)\r
- return null;\r
- }\r
- result = array[index++];\r
- if (result instanceof String) {\r
- if (!obj.has((String) result, obj))\r
- continue; // must have been deleted\r
- } else {\r
- if (!obj.has(((Number) result).intValue(), obj))\r
- continue; // must have been deleted\r
- }\r
- if (!used.containsKey(result)) {\r
- break;\r
- }\r
- }\r
- return ScriptRuntime.toString(result);\r
- }\r
-\r
- private Object next;\r
- private Scriptable obj;\r
- private int index;\r
- private Object[] array;\r
- private Hashtable used;\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-// API class\r
-\r
-package org.mozilla.javascript;\r
-\r
-/**\r
- * This is interface that all objects in JavaScript must implement.\r
- * The interface provides for the management of properties and for\r
- * performing conversions.\r
- * <p>\r
- * Host system implementors may find it easier to extend the ScriptableObject\r
- * class rather than implementing Scriptable when writing host objects.\r
- * <p>\r
- * There are many static methods defined in ScriptableObject that perform\r
- * the multiple calls to the Scriptable interface needed in order to \r
- * manipulate properties in prototype chains.\r
- * <p>\r
- *\r
- * @see org.mozilla.javascript.ScriptableObject\r
- * @author Norris Boyd\r
- * @author Nick Thompson\r
- * @author Brendan Eich\r
- */\r
-\r
-public interface Scriptable {\r
-\r
- /**\r
- * Get the name of the set of objects implemented by this Java class.\r
- * This corresponds to the [[Class]] operation in ECMA and is used\r
- * by Object.prototype.toString() in ECMA.<p>\r
- * See ECMA 8.6.2 and 15.2.4.2.\r
- */\r
- public String getClassName();\r
-\r
- /**\r
- * Value returned from <code>get</code> if the property is not\r
- * found.\r
- */\r
- public static final Object NOT_FOUND = new Object();\r
-\r
- /**\r
- * Get a named property from the object.\r
- *\r
- * Looks property up in this object and returns the associated value\r
- * if found. Returns NOT_FOUND if not found.\r
- * Note that this method is not expected to traverse the prototype\r
- * chain. This is different from the ECMA [[Get]] operation.\r
- *\r
- * Depending on the property selector, the runtime will call\r
- * this method or the form of <code>get</code> that takes an\r
- * integer:\r
- * <table>\r
- * <tr><th>JavaScript code</th><th>Java code</th></tr>\r
- * <tr><td>a.b </td><td>a.get("b", a)</td></tr>\r
- * <tr><td>a["foo"] </td><td>a.get("foo", a)</td></tr>\r
- * <tr><td>a[3] </td><td>a.get(3, a)</td></tr>\r
- * <tr><td>a["3"] </td><td>a.get(3, a)</td></tr>\r
- * <tr><td>a[3.0] </td><td>a.get(3, a)</td></tr>\r
- * <tr><td>a["3.0"] </td><td>a.get("3.0", a)</td></tr>\r
- * <tr><td>a[1.1] </td><td>a.get("1.1", a)</td></tr>\r
- * <tr><td>a[-4] </td><td>a.get(-4, a)</td></tr>\r
- * </table>\r
- * <p>\r
- * The values that may be returned are limited to the following:\r
- * <UL>\r
- * <LI>java.lang.Boolean objects</LI>\r
- * <LI>java.lang.String objects</LI>\r
- * <LI>java.lang.Number objects</LI>\r
- * <LI>org.mozilla.javascript.Scriptable objects</LI>\r
- * <LI>null</LI>\r
- * <LI>The value returned by Context.getUndefinedValue()</LI>\r
- * <LI>NOT_FOUND</LI>\r
- * </UL>\r
- * @param name the name of the property\r
- * @param start the object in which the lookup began\r
- * @return the value of the property (may be null), or NOT_FOUND\r
- * @see org.mozilla.javascript.Context#getUndefinedValue\r
- */\r
- public Object get(String name, Scriptable start);\r
-\r
- /**\r
- * Get a property from the object selected by an integral index.\r
- *\r
- * Identical to <code>get(String, Scriptable)</code> except that\r
- * an integral index is used to select the property.\r
- *\r
- * @param index the numeric index for the property\r
- * @param start the object in which the lookup began\r
- * @return the value of the property (may be null), or NOT_FOUND\r
- * @see org.mozilla.javascript.Scriptable#get(String,Scriptable)\r
- */\r
- public Object get(int index, Scriptable start);\r
-\r
- /**\r
- * Indicates whether or not a named property is defined in an object.\r
- *\r
- * Does not traverse the prototype chain.<p>\r
- *\r
- * The property is specified by a String name\r
- * as defined for the <code>get</code> method.<p>\r
- *\r
- * @param name the name of the property\r
- * @param start the object in which the lookup began\r
- * @return true if and only if the named property is found in the object\r
- * @see org.mozilla.javascript.Scriptable#get\r
- * @see org.mozilla.javascript.ScriptableObject#getProperty\r
- */\r
- public boolean has(String name, Scriptable start);\r
-\r
- /**\r
- * Indicates whether or not an indexed property is defined in an object.\r
- *\r
- * Does not traverse the prototype chain.<p>\r
- *\r
- * The property is specified by an integral index\r
- * as defined for the <code>get</code> method.<p>\r
- *\r
- * @param index the numeric index for the property\r
- * @param start the object in which the lookup began\r
- * @return true if and only if the indexed property is found in the object\r
- * @see org.mozilla.javascript.Scriptable#get\r
- * @see org.mozilla.javascript.ScriptableObject#getProperty\r
- */\r
- public boolean has(int index, Scriptable start);\r
-\r
- /**\r
- * Sets a named property in this object.\r
- * <p>\r
- * The property is specified by a string name \r
- * as defined for <code>get</code>.\r
- * <p>\r
- * The possible values that may be passed in are as defined for\r
- * <code>get</code>. A class that implements this method may choose\r
- * to ignore calls to set certain properties, in which case those\r
- * properties are effectively read-only.<p>\r
- * For properties defined in a prototype chain,\r
- * use <code>putProperty</code> in ScriptableObject. <p>\r
- * Note that if a property <i>a</i> is defined in the prototype <i>p</i>\r
- * of an object <i>o</i>, then evaluating <code>o.a = 23</code> will cause\r
- * <code>set</code> to be called on the prototype <i>p</i> with\r
- * <i>o</i> as the <i>start</i> parameter.\r
- * To preserve JavaScript semantics, it is the Scriptable\r
- * object's responsibility to modify <i>o</i>. <p>\r
- * This design allows properties to be defined in prototypes and implemented\r
- * in terms of getters and setters of Java values without consuming slots\r
- * in each instance.<p>\r
- * <p>\r
- * The values that may be set are limited to the following:\r
- * <UL>\r
- * <LI>java.lang.Boolean objects</LI>\r
- * <LI>java.lang.String objects</LI>\r
- * <LI>java.lang.Number objects</LI>\r
- * <LI>org.mozilla.javascript.Scriptable objects</LI>\r
- * <LI>null</LI>\r
- * <LI>The value returned by Context.getUndefinedValue()</LI> \r
- * </UL><p> \r
- * Arbitrary Java objects may be wrapped in a Scriptable by first calling\r
- * <code>Context.toObject</code>. This allows the property of a JavaScript\r
- * object to contain an arbitrary Java object as a value.<p> \r
- * Note that <code>has</code> will be called by the runtime first before\r
- * <code>set</code> is called to determine in which object the\r
- * property is defined.\r
- * Note that this method is not expected to traverse the prototype chain,\r
- * which is different from the ECMA [[Put]] operation.\r
- * @param name the name of the property\r
- * @param start the object whose property is being set\r
- * @param value value to set the property to\r
- * @see org.mozilla.javascript.Scriptable#has\r
- * @see org.mozilla.javascript.Scriptable#get\r
- * @see org.mozilla.javascript.ScriptableObject#putProperty\r
- * @see org.mozilla.javascript.Context#toObject\r
- */\r
- public void put(String name, Scriptable start, Object value);\r
-\r
- /**\r
- * Sets an indexed property in this object.\r
- * <p>\r
- * The property is specified by an integral index\r
- * as defined for <code>get</code>.<p>\r
- *\r
- * Identical to <code>put(String, Scriptable, Object)</code> except that\r
- * an integral index is used to select the property.\r
- *\r
- * @param index the numeric index for the property\r
- * @param start the object whose property is being set\r
- * @param value value to set the property to\r
- * @see org.mozilla.javascript.Scriptable#has\r
- * @see org.mozilla.javascript.Scriptable#get\r
- * @see org.mozilla.javascript.Scriptable#put(String,Scriptable,Object)\r
- * @see org.mozilla.javascript.ScriptableObject#putProperty\r
- */\r
- public void put(int index, Scriptable start, Object value);\r
-\r
- /**\r
- * Removes a property from this object.\r
- * This operation corresponds to the ECMA [[Delete]] except that\r
- * the no result is returned. The runtime will guarantee that this\r
- * method is called only if the property exists. After this method\r
- * is called, the runtime will call Scriptable.has to see if the\r
- * property has been removed in order to determine the boolean\r
- * result of the delete operator as defined by ECMA 11.4.1.\r
- * <p>\r
- * A property can be made permanent by ignoring calls to remove\r
- * it.<p>\r
- * The property is specified by a String name\r
- * as defined for <code>get</code>.\r
- * <p>\r
- * To delete properties defined in a prototype chain,\r
- * see deleteProperty in ScriptableObject.\r
- * @param name the identifier for the property\r
- * @see org.mozilla.javascript.Scriptable#get\r
- * @see org.mozilla.javascript.ScriptableObject#deleteProperty\r
- */\r
- public void delete(String name);\r
-\r
- /**\r
- * Removes a property from this object.\r
- *\r
- * The property is specified by an integral index\r
- * as defined for <code>get</code>.\r
- * <p>\r
- * To delete properties defined in a prototype chain,\r
- * see deleteProperty in ScriptableObject.\r
- *\r
- * Identical to <code>delete(String)</code> except that\r
- * an integral index is used to select the property.\r
- *\r
- * @param index the numeric index for the property\r
- * @see org.mozilla.javascript.Scriptable#get\r
- * @see org.mozilla.javascript.ScriptableObject#deleteProperty\r
- */\r
- public void delete(int index);\r
-\r
- /**\r
- * Get the prototype of the object.\r
- * @return the prototype\r
- */\r
- public Scriptable getPrototype();\r
-\r
- /**\r
- * Set the prototype of the object.\r
- * @param prototype the prototype to set\r
- */\r
- public void setPrototype(Scriptable prototype);\r
-\r
- /**\r
- * Get the parent scope of the object.\r
- * @return the parent scope\r
- */\r
- public Scriptable getParentScope();\r
-\r
- /**\r
- * Set the parent scope of the object.\r
- * @param parent the parent scope to set\r
- */\r
- public void setParentScope(Scriptable parent);\r
-\r
- /**\r
- * Get an array of property ids.\r
- *\r
- * Not all property ids need be returned. Those properties\r
- * whose ids are not returned are considered non-enumerable.\r
- *\r
- * @return an array of Objects. Each entry in the array is either\r
- * a java.lang.String or a java.lang.Number\r
- */\r
- public Object[] getIds();\r
-\r
- /**\r
- * Get the default value of the object with a given hint.\r
- * The hints are String.class for type String, Number.class for type\r
- * Number, Scriptable.class for type Object, and Boolean.class for\r
- * type Boolean. <p>\r
- *\r
- * A <code>hint</code> of null means "no hint".\r
- *\r
- * See ECMA 8.6.2.6.\r
- *\r
- * @param hint the type hint\r
- * @return the default value\r
- */\r
- public Object getDefaultValue(Class hint);\r
-\r
- /**\r
- * The instanceof operator.\r
- *\r
- * <p>\r
- * The JavaScript code "lhs instanceof rhs" causes rhs.hasInstance(lhs) to\r
- * be called.\r
- *\r
- * <p>\r
- * The return value is implementation dependent so that embedded host objects can\r
- * return an appropriate value. See the JS 1.3 language documentation for more\r
- * detail.\r
- *\r
- * <p>This operator corresponds to the proposed EMCA [[HasInstance]] operator.\r
- *\r
- * @param instance The value that appeared on the LHS of the instanceof\r
- * operator\r
- *\r
- * @return an implementation dependent value\r
- */\r
- public boolean hasInstance(Scriptable instance);\r
-}\r
-\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- * Igor Bukanov\r
- * Roger Lawrence\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-// API class\r
-\r
-package org.mozilla.javascript;\r
-\r
-import java.lang.reflect.*;\r
-import java.util.Hashtable;\r
-\r
-/**\r
- * This is the default implementation of the Scriptable interface. This\r
- * class provides convenient default behavior that makes it easier to\r
- * define host objects.\r
- * <p>\r
- * Various properties and methods of JavaScript objects can be conveniently\r
- * defined using methods of ScriptableObject.\r
- * <p>\r
- * Classes extending ScriptableObject must define the getClassName method.\r
- *\r
- * @see org.mozilla.javascript.Scriptable\r
- * @author Norris Boyd\r
- */\r
-\r
-public abstract class ScriptableObject implements Scriptable {\r
-\r
- /**\r
- * The empty property attribute.\r
- *\r
- * Used by getAttributes() and setAttributes().\r
- *\r
- * @see org.mozilla.javascript.ScriptableObject#getAttributes\r
- * @see org.mozilla.javascript.ScriptableObject#setAttributes\r
- */\r
- public static final int EMPTY = 0x00;\r
-\r
- /**\r
- * Property attribute indicating assignment to this property is ignored.\r
- *\r
- * @see org.mozilla.javascript.ScriptableObject#put\r
- * @see org.mozilla.javascript.ScriptableObject#getAttributes\r
- * @see org.mozilla.javascript.ScriptableObject#setAttributes\r
- */\r
- public static final int READONLY = 0x01;\r
-\r
- /**\r
- * Property attribute indicating property is not enumerated.\r
- *\r
- * Only enumerated properties will be returned by getIds().\r
- *\r
- * @see org.mozilla.javascript.ScriptableObject#getIds\r
- * @see org.mozilla.javascript.ScriptableObject#getAttributes\r
- * @see org.mozilla.javascript.ScriptableObject#setAttributes\r
- */\r
- public static final int DONTENUM = 0x02;\r
-\r
- /**\r
- * Property attribute indicating property cannot be deleted.\r
- *\r
- * @see org.mozilla.javascript.ScriptableObject#delete\r
- * @see org.mozilla.javascript.ScriptableObject#getAttributes\r
- * @see org.mozilla.javascript.ScriptableObject#setAttributes\r
- */\r
- public static final int PERMANENT = 0x04;\r
-\r
- /**\r
- * Return the name of the class.\r
- *\r
- * This is typically the same name as the constructor.\r
- * Classes extending ScriptableObject must implement this abstract\r
- * method.\r
- */\r
- public abstract String getClassName();\r
-\r
- /**\r
- * Returns true if the named property is defined.\r
- *\r
- * @param name the name of the property\r
- * @param start the object in which the lookup began\r
- * @return true if and only if the property was found in the object\r
- */\r
- public boolean has(String name, Scriptable start) {\r
- return getSlot(name, name.hashCode(), false) != null;\r
- }\r
-\r
- /**\r
- * Returns true if the property index is defined.\r
- *\r
- * @param index the numeric index for the property\r
- * @param start the object in which the lookup began\r
- * @return true if and only if the property was found in the object\r
- */\r
- public boolean has(int index, Scriptable start) {\r
- return getSlot(null, index, false) != null;\r
- }\r
-\r
- /**\r
- * Returns the value of the named property or NOT_FOUND.\r
- *\r
- * If the property was created using defineProperty, the\r
- * appropriate getter method is called.\r
- *\r
- * @param name the name of the property\r
- * @param start the object in which the lookup began\r
- * @return the value of the property (may be null), or NOT_FOUND\r
- */\r
- public Object get(String name, Scriptable start) {\r
- Slot slot = lastAccess; // Get local copy\r
- if (name == slot.stringKey) {\r
- if (slot.wasDeleted == 0) { return slot.value; }\r
- } \r
- int hashCode = name.hashCode();\r
- slot = getSlot(name, hashCode, false);\r
- if (slot == null)\r
- return Scriptable.NOT_FOUND;\r
- if ((slot.flags & Slot.HAS_GETTER) != 0) {\r
- GetterSlot getterSlot = (GetterSlot) slot;\r
- try {\r
- if (getterSlot.delegateTo == null) {\r
- // Walk the prototype chain to find an appropriate\r
- // object to invoke the getter on.\r
- Class clazz = getterSlot.getter.getDeclaringClass();\r
- while (!clazz.isInstance(start)) {\r
- start = start.getPrototype();\r
- if (start == null) {\r
- start = this;\r
- break;\r
- }\r
- }\r
- return getterSlot.getter.invoke(start, ScriptRuntime.emptyArgs);\r
- }\r
- Object[] args = { this };\r
- return getterSlot.getter.invoke(getterSlot.delegateTo, args);\r
- }\r
- catch (InvocationTargetException e) {\r
- throw WrappedException.wrapException(e);\r
- }\r
- catch (IllegalAccessException e) {\r
- throw WrappedException.wrapException(e);\r
- }\r
- }\r
- // Here stringKey.equals(name) holds, but it can be that \r
- // slot.stringKey != name. To make last name cache work, need\r
- // to change the key\r
- slot.stringKey = name;\r
-\r
- // Update cache. \r
- lastAccess = slot;\r
- return slot.value;\r
- }\r
-\r
- /**\r
- * Returns the value of the indexed property or NOT_FOUND.\r
- *\r
- * @param index the numeric index for the property\r
- * @param start the object in which the lookup began\r
- * @return the value of the property (may be null), or NOT_FOUND\r
- */\r
- public Object get(int index, Scriptable start) {\r
- Slot slot = getSlot(null, index, false);\r
- if (slot == null)\r
- return Scriptable.NOT_FOUND;\r
- return slot.value;\r
- }\r
- \r
- /**\r
- * Sets the value of the named property, creating it if need be.\r
- *\r
- * If the property was created using defineProperty, the\r
- * appropriate setter method is called. <p>\r
- *\r
- * If the property's attributes include READONLY, no action is\r
- * taken.\r
- * This method will actually set the property in the start\r
- * object.\r
- *\r
- * @param name the name of the property\r
- * @param start the object whose property is being set\r
- * @param value value to set the property to\r
- */\r
- public void put(String name, Scriptable start, Object value) {\r
- int hash = name.hashCode();\r
- Slot slot = getSlot(name, hash, false);\r
- if (slot == null) {\r
- if (start != this) {\r
- start.put(name, start, value);\r
- return;\r
- }\r
- slot = getSlotToSet(name, hash, false);\r
- }\r
- if ((slot.attributes & ScriptableObject.READONLY) != 0)\r
- return;\r
- if ((slot.flags & Slot.HAS_SETTER) != 0) {\r
- GetterSlot getterSlot = (GetterSlot) slot;\r
- try {\r
- Class pTypes[] = getterSlot.setter.getParameterTypes();\r
- Class desired = pTypes[pTypes.length - 1];\r
- Object actualArg\r
- = FunctionObject.convertArg(start, value, desired);\r
- if (getterSlot.delegateTo == null) {\r
- // Walk the prototype chain to find an appropriate\r
- // object to invoke the setter on.\r
- Object[] arg = { actualArg };\r
- Class clazz = getterSlot.setter.getDeclaringClass();\r
- while (!clazz.isInstance(start)) {\r
- start = start.getPrototype();\r
- if (start == null) {\r
- start = this;\r
- break;\r
- }\r
- }\r
- Object v = getterSlot.setter.invoke(start, arg);\r
- if (getterSlot.setterReturnsValue) {\r
- slot.value = v;\r
- if (!(v instanceof Method))\r
- slot.flags = 0;\r
- }\r
- return;\r
- }\r
- Object[] args = { this, actualArg };\r
- Object v = getterSlot.setter.invoke(getterSlot.delegateTo, args);\r
- if (getterSlot.setterReturnsValue) {\r
- slot.value = v;\r
- if (!(v instanceof Method))\r
- slot.flags = 0;\r
- }\r
- return;\r
- }\r
- catch (InvocationTargetException e) {\r
- throw WrappedException.wrapException(e);\r
- }\r
- catch (IllegalAccessException e) {\r
- throw WrappedException.wrapException(e);\r
- }\r
- }\r
- if (this == start) {\r
- slot.value = value;\r
- // Make cache work\r
- slot.stringKey = name;\r
- lastAccess = slot;\r
- } else {\r
- start.put(name, start, value);\r
- }\r
- }\r
-\r
- /**\r
- * Sets the value of the indexed property, creating it if need be.\r
- *\r
- * @param index the numeric index for the property\r
- * @param start the object whose property is being set\r
- * @param value value to set the property to\r
- */\r
- public void put(int index, Scriptable start, Object value) {\r
- Slot slot = getSlot(null, index, false);\r
- if (slot == null) {\r
- if (start != this) {\r
- start.put(index, start, value);\r
- return;\r
- }\r
- slot = getSlotToSet(null, index, false);\r
- }\r
- if ((slot.attributes & ScriptableObject.READONLY) != 0)\r
- return;\r
- if (this == start) {\r
- slot.value = value;\r
- } else {\r
- start.put(index, start, value);\r
- }\r
- }\r
-\r
- /**\r
- * Removes a named property from the object.\r
- *\r
- * If the property is not found, or it has the PERMANENT attribute,\r
- * no action is taken.\r
- *\r
- * @param name the name of the property\r
- */\r
- public void delete(String name) {\r
- removeSlot(name, name.hashCode());\r
- }\r
-\r
- /**\r
- * Removes the indexed property from the object.\r
- *\r
- * If the property is not found, or it has the PERMANENT attribute,\r
- * no action is taken.\r
- *\r
- * @param index the numeric index for the property\r
- */\r
- public void delete(int index) {\r
- removeSlot(null, index);\r
- }\r
-\r
- /**\r
- * Get the attributes of a named property.\r
- *\r
- * The property is specified by <code>name</code>\r
- * as defined for <code>has</code>.<p>\r
- *\r
- * @param name the identifier for the property\r
- * @param start the object in which the lookup began\r
- * @return the bitset of attributes\r
- * @exception PropertyException if the named property\r
- * is not found\r
- * @see org.mozilla.javascript.ScriptableObject#has\r
- * @see org.mozilla.javascript.ScriptableObject#READONLY\r
- * @see org.mozilla.javascript.ScriptableObject#DONTENUM\r
- * @see org.mozilla.javascript.ScriptableObject#PERMANENT\r
- * @see org.mozilla.javascript.ScriptableObject#EMPTY\r
- */\r
- public int getAttributes(String name, Scriptable start)\r
- throws PropertyException\r
- {\r
- Slot slot = getSlot(name, name.hashCode(), false);\r
- if (slot == null) {\r
- throw PropertyException.withMessage0("msg.prop.not.found");\r
- }\r
- return slot.attributes;\r
- }\r
-\r
- /**\r
- * Get the attributes of an indexed property.\r
- *\r
- * @param index the numeric index for the property\r
- * @param start the object in which the lookup began\r
- * @exception PropertyException if the indexed property\r
- * is not found\r
- * @return the bitset of attributes\r
- * @see org.mozilla.javascript.ScriptableObject#has\r
- * @see org.mozilla.javascript.ScriptableObject#READONLY\r
- * @see org.mozilla.javascript.ScriptableObject#DONTENUM\r
- * @see org.mozilla.javascript.ScriptableObject#PERMANENT\r
- * @see org.mozilla.javascript.ScriptableObject#EMPTY\r
- */\r
- public int getAttributes(int index, Scriptable start)\r
- throws PropertyException\r
- {\r
- Slot slot = getSlot(null, index, false);\r
- if (slot == null) {\r
- throw PropertyException.withMessage0("msg.prop.not.found");\r
- }\r
- return slot.attributes;\r
- }\r
-\r
- /**\r
- * Set the attributes of a named property.\r
- *\r
- * The property is specified by <code>name</code>\r
- * as defined for <code>has</code>.<p>\r
- *\r
- * The possible attributes are READONLY, DONTENUM,\r
- * and PERMANENT. Combinations of attributes\r
- * are expressed by the bitwise OR of attributes.\r
- * EMPTY is the state of no attributes set. Any unused\r
- * bits are reserved for future use.\r
- *\r
- * @param name the name of the property\r
- * @param start the object in which the lookup began\r
- * @param attributes the bitset of attributes\r
- * @exception PropertyException if the named property\r
- * is not found\r
- * @see org.mozilla.javascript.Scriptable#has\r
- * @see org.mozilla.javascript.ScriptableObject#READONLY\r
- * @see org.mozilla.javascript.ScriptableObject#DONTENUM\r
- * @see org.mozilla.javascript.ScriptableObject#PERMANENT\r
- * @see org.mozilla.javascript.ScriptableObject#EMPTY\r
- */\r
- public void setAttributes(String name, Scriptable start,\r
- int attributes)\r
- throws PropertyException\r
- {\r
- final int mask = READONLY | DONTENUM | PERMANENT;\r
- attributes &= mask; // mask out unused bits\r
- Slot slot = getSlot(name, name.hashCode(), false);\r
- if (slot == null) {\r
- throw PropertyException.withMessage0("msg.prop.not.found");\r
- }\r
- slot.attributes = (short) attributes;\r
- }\r
-\r
- /**\r
- * Set the attributes of an indexed property.\r
- *\r
- * @param index the numeric index for the property\r
- * @param start the object in which the lookup began\r
- * @param attributes the bitset of attributes\r
- * @exception PropertyException if the indexed property\r
- * is not found\r
- * @see org.mozilla.javascript.Scriptable#has\r
- * @see org.mozilla.javascript.ScriptableObject#READONLY\r
- * @see org.mozilla.javascript.ScriptableObject#DONTENUM\r
- * @see org.mozilla.javascript.ScriptableObject#PERMANENT\r
- * @see org.mozilla.javascript.ScriptableObject#EMPTY\r
- */\r
- public void setAttributes(int index, Scriptable start,\r
- int attributes)\r
- throws PropertyException\r
- {\r
- Slot slot = getSlot(null, index, false);\r
- if (slot == null) {\r
- throw PropertyException.withMessage0("msg.prop.not.found");\r
- }\r
- slot.attributes = (short) attributes;\r
- }\r
-\r
- /**\r
- * Returns the prototype of the object.\r
- */\r
- public Scriptable getPrototype() {\r
- return prototype;\r
- }\r
-\r
- /**\r
- * Sets the prototype of the object.\r
- */\r
- public void setPrototype(Scriptable m) {\r
- prototype = m;\r
- }\r
-\r
- /**\r
- * Returns the parent (enclosing) scope of the object.\r
- */\r
- public Scriptable getParentScope() {\r
- return parent;\r
- }\r
-\r
- /**\r
- * Sets the parent (enclosing) scope of the object.\r
- */\r
- public void setParentScope(Scriptable m) {\r
- parent = m;\r
- }\r
-\r
- /**\r
- * Returns an array of ids for the properties of the object.\r
- *\r
- * <p>Any properties with the attribute DONTENUM are not listed. <p>\r
- *\r
- * @return an array of java.lang.Objects with an entry for every\r
- * listed property. Properties accessed via an integer index will \r
- * have a corresponding\r
- * Integer entry in the returned array. Properties accessed by\r
- * a String will have a String entry in the returned array.\r
- */\r
- public Object[] getIds() {\r
- return getIds(false);\r
- }\r
- \r
- /**\r
- * Returns an array of ids for the properties of the object.\r
- *\r
- * <p>All properties, even those with attribute DONTENUM, are listed. <p>\r
- *\r
- * @return an array of java.lang.Objects with an entry for every\r
- * listed property. Properties accessed via an integer index will \r
- * have a corresponding\r
- * Integer entry in the returned array. Properties accessed by\r
- * a String will have a String entry in the returned array.\r
- */\r
- public Object[] getAllIds() {\r
- return getIds(true);\r
- }\r
- \r
- /**\r
- * Implements the [[DefaultValue]] internal method.\r
- *\r
- * <p>Note that the toPrimitive conversion is a no-op for\r
- * every type other than Object, for which [[DefaultValue]]\r
- * is called. See ECMA 9.1.<p>\r
- *\r
- * A <code>hint</code> of null means "no hint".\r
- *\r
- * @param typeHint the type hint\r
- * @return the default value for the object\r
- *\r
- * See ECMA 8.6.2.6.\r
- */\r
- public Object getDefaultValue(Class typeHint) {\r
- Object val;\r
- Context cx = null;\r
- try {\r
- for (int i=0; i < 2; i++) {\r
- if (typeHint == ScriptRuntime.StringClass ? i == 0 : i == 1) {\r
- Object v = getProperty(this, "toString");\r
- if (!(v instanceof Function))\r
- continue;\r
- Function fun = (Function) v;\r
- if (cx == null)\r
- cx = Context.getContext();\r
- val = fun.call(cx, fun.getParentScope(), this,\r
- ScriptRuntime.emptyArgs);\r
- } else {\r
- String hint;\r
- if (typeHint == null)\r
- hint = "undefined";\r
- else if (typeHint == ScriptRuntime.StringClass)\r
- hint = "string";\r
- else if (typeHint == ScriptRuntime.ScriptableClass)\r
- hint = "object";\r
- else if (typeHint == ScriptRuntime.FunctionClass)\r
- hint = "function";\r
- else if (typeHint == ScriptRuntime.BooleanClass || \r
- typeHint == Boolean.TYPE)\r
- hint = "boolean";\r
- else if (typeHint == ScriptRuntime.NumberClass ||\r
- typeHint == ScriptRuntime.ByteClass || \r
- typeHint == Byte.TYPE ||\r
- typeHint == ScriptRuntime.ShortClass || \r
- typeHint == Short.TYPE ||\r
- typeHint == ScriptRuntime.IntegerClass || \r
- typeHint == Integer.TYPE ||\r
- typeHint == ScriptRuntime.FloatClass || \r
- typeHint == Float.TYPE ||\r
- typeHint == ScriptRuntime.DoubleClass || \r
- typeHint == Double.TYPE)\r
- hint = "number";\r
- else {\r
- throw Context.reportRuntimeError1(\r
- "msg.invalid.type", typeHint.toString());\r
- }\r
- Object v = getProperty(this, "valueOf");\r
- if (!(v instanceof Function))\r
- continue;\r
- Function fun = (Function) v;\r
- Object[] args = { hint };\r
- if (cx == null)\r
- cx = Context.getContext();\r
- val = fun.call(cx, fun.getParentScope(), this, args);\r
- }\r
- if (val != null && (val == Undefined.instance ||\r
- !(val instanceof Scriptable) ||\r
- typeHint == Scriptable.class ||\r
- typeHint == Function.class))\r
- {\r
- return val;\r
- }\r
- if (val instanceof NativeJavaObject) {\r
- // Let a wrapped java.lang.String pass for a primitive \r
- // string.\r
- Object u = ((Wrapper) val).unwrap();\r
- if (u instanceof String)\r
- return u;\r
- }\r
- }\r
- // fall through to error \r
- }\r
- catch (JavaScriptException jse) {\r
- // fall through to error \r
- }\r
- Object arg = (typeHint == null) ? "undefined" : typeHint.toString();\r
- throw NativeGlobal.typeError1("msg.default.value", arg, this);\r
- }\r
-\r
- /**\r
- * Implements the instanceof operator.\r
- *\r
- * <p>This operator has been proposed to ECMA.\r
- *\r
- * @param instance The value that appeared on the LHS of the instanceof\r
- * operator\r
- * @return true if "this" appears in value's prototype chain\r
- *\r
- */\r
- public boolean hasInstance(Scriptable instance) {\r
- // Default for JS objects (other than Function) is to do prototype\r
- // chasing. This will be overridden in NativeFunction and non-JS objects.\r
-\r
- return ScriptRuntime.jsDelegatesTo(instance, this);\r
- }\r
-\r
- /**\r
- * Defines JavaScript objects from a Java class that implements Scriptable.\r
- *\r
- * If the given class has a method\r
- * <pre>\r
- * static void init(Context cx, Scriptable scope, boolean sealed);</pre>\r
- *\r
- * or its compatibility form \r
- * <pre>\r
- * static void init(Scriptable scope);</pre>\r
- *\r
- * then it is invoked and no further initialization is done.<p>\r
- *\r
- * However, if no such a method is found, then the class's constructors and\r
- * methods are used to initialize a class in the following manner.<p>\r
- *\r
- * First, the zero-parameter constructor of the class is called to\r
- * create the prototype. If no such constructor exists,\r
- * a ClassDefinitionException is thrown. <p>\r
- *\r
- * Next, all methods are scanned for special prefixes that indicate that they\r
- * have special meaning for defining JavaScript objects.\r
- * These special prefixes are\r
- * <ul>\r
- * <li><code>jsFunction_</code> for a JavaScript function\r
- * <li><code>jsStaticFunction_</code> for a JavaScript function that \r
- * is a property of the constructor\r
- * <li><code>jsGet_</code> for a getter of a JavaScript property\r
- * <li><code>jsSet_</code> for a setter of a JavaScript property\r
- * <li><code>jsConstructor</code> for a JavaScript function that \r
- * is the constructor\r
- * </ul><p>\r
- *\r
- * If the method's name begins with "jsFunction_", a JavaScript function \r
- * is created with a name formed from the rest of the Java method name \r
- * following "jsFunction_". So a Java method named "jsFunction_foo" will\r
- * define a JavaScript method "foo". Calling this JavaScript function \r
- * will cause the Java method to be called. The parameters of the method\r
- * must be of number and types as defined by the FunctionObject class.\r
- * The JavaScript function is then added as a property\r
- * of the prototype. <p>\r
- * \r
- * If the method's name begins with "jsStaticFunction_", it is handled\r
- * similarly except that the resulting JavaScript function is added as a \r
- * property of the constructor object. The Java method must be static.\r
- * \r
- * If the method's name begins with "jsGet_" or "jsSet_", the method is\r
- * considered to define a property. Accesses to the defined property\r
- * will result in calls to these getter and setter methods. If no\r
- * setter is defined, the property is defined as READONLY.<p>\r
- *\r
- * If the method's name is "jsConstructor", the method is\r
- * considered to define the body of the constructor. Only one \r
- * method of this name may be defined. \r
- * If no method is found that can serve as constructor, a Java\r
- * constructor will be selected to serve as the JavaScript\r
- * constructor in the following manner. If the class has only one\r
- * Java constructor, that constructor is used to define\r
- * the JavaScript constructor. If the the class has two constructors,\r
- * one must be the zero-argument constructor (otherwise an\r
- * ClassDefinitionException would have already been thrown\r
- * when the prototype was to be created). In this case\r
- * the Java constructor with one or more parameters will be used\r
- * to define the JavaScript constructor. If the class has three\r
- * or more constructors, an ClassDefinitionException\r
- * will be thrown.<p>\r
- *\r
- * Finally, if there is a method\r
- * <pre>\r
- * static void finishInit(Scriptable scope, FunctionObject constructor,\r
- * Scriptable prototype)</pre>\r
- *\r
- * it will be called to finish any initialization. The <code>scope</code>\r
- * argument will be passed, along with the newly created constructor and\r
- * the newly created prototype.<p>\r
- *\r
- * @param scope The scope in which to define the constructor\r
- * @param clazz The Java class to use to define the JavaScript objects\r
- * and properties\r
- * @exception IllegalAccessException if access is not available\r
- * to a reflected class member\r
- * @exception InstantiationException if unable to instantiate\r
- * the named class\r
- * @exception InvocationTargetException if an exception is thrown\r
- * during execution of methods of the named class\r
- * @exception ClassDefinitionException if an appropriate\r
- * constructor cannot be found to create the prototype\r
- * @exception PropertyException if getter and setter\r
- * methods do not conform to the requirements of the\r
- * defineProperty method\r
- * @see org.mozilla.javascript.Function\r
- * @see org.mozilla.javascript.FunctionObject\r
- * @see org.mozilla.javascript.ScriptableObject#READONLY\r
- * @see org.mozilla.javascript.ScriptableObject#defineProperty\r
- */\r
- public static void defineClass(Scriptable scope, Class clazz)\r
- throws IllegalAccessException, InstantiationException,\r
- InvocationTargetException, ClassDefinitionException,\r
- PropertyException\r
- {\r
- defineClass(scope, clazz, false);\r
- }\r
- \r
- /**\r
- * Defines JavaScript objects from a Java class, optionally \r
- * allowing sealing.\r
- *\r
- * Similar to <code>defineClass(Scriptable scope, Class clazz)</code>\r
- * except that sealing is allowed. An object that is sealed cannot have \r
- * properties added or removed. Note that sealing is not allowed in\r
- * the current ECMA/ISO language specification, but is likely for\r
- * the next version.\r
- * \r
- * @param scope The scope in which to define the constructor\r
- * @param clazz The Java class to use to define the JavaScript objects\r
- * and properties. The class must implement Scriptable.\r
- * @param sealed whether or not to create sealed standard objects that\r
- * cannot be modified. \r
- * @exception IllegalAccessException if access is not available\r
- * to a reflected class member\r
- * @exception InstantiationException if unable to instantiate\r
- * the named class\r
- * @exception InvocationTargetException if an exception is thrown\r
- * during execution of methods of the named class\r
- * @exception ClassDefinitionException if an appropriate\r
- * constructor cannot be found to create the prototype\r
- * @exception PropertyException if getter and setter\r
- * methods do not conform to the requirements of the\r
- * defineProperty method\r
- * @since 1.4R3\r
- */\r
- public static void defineClass(Scriptable scope, Class clazz, \r
- boolean sealed)\r
- throws IllegalAccessException, InstantiationException,\r
- InvocationTargetException, ClassDefinitionException,\r
- PropertyException\r
- {\r
- Method[] methods = FunctionObject.getMethodList(clazz);\r
- for (int i=0; i < methods.length; i++) {\r
- Method method = methods[i];\r
- if (!method.getName().equals("init"))\r
- continue;\r
- Class[] parmTypes = method.getParameterTypes();\r
- if (parmTypes.length == 3 &&\r
- parmTypes[0] == ContextClass &&\r
- parmTypes[1] == ScriptRuntime.ScriptableClass &&\r
- parmTypes[2] == Boolean.TYPE &&\r
- Modifier.isStatic(method.getModifiers()))\r
- {\r
- Object args[] = { Context.getContext(), scope, \r
- sealed ? Boolean.TRUE : Boolean.FALSE };\r
- method.invoke(null, args);\r
- return;\r
- }\r
- if (parmTypes.length == 1 &&\r
- parmTypes[0] == ScriptRuntime.ScriptableClass &&\r
- Modifier.isStatic(method.getModifiers()))\r
- {\r
- Object args[] = { scope };\r
- method.invoke(null, args);\r
- return;\r
- }\r
- \r
- }\r
-\r
- // If we got here, there isn't an "init" method with the right\r
- // parameter types.\r
- Hashtable exclusionList = getExclusionList();\r
-\r
- Constructor[] ctors = clazz.getConstructors();\r
- Constructor protoCtor = null;\r
- for (int i=0; i < ctors.length; i++) {\r
- if (ctors[i].getParameterTypes().length == 0) {\r
- protoCtor = ctors[i];\r
- break;\r
- }\r
- }\r
- if (protoCtor == null) {\r
- throw new ClassDefinitionException(\r
- Context.getMessage1("msg.zero.arg.ctor", clazz.getName()));\r
- }\r
-\r
- Scriptable proto = (Scriptable) \r
- protoCtor.newInstance(ScriptRuntime.emptyArgs);\r
- proto.setPrototype(getObjectPrototype(scope));\r
- String className = proto.getClassName();\r
-\r
- // Find out whether there are any methods that begin with\r
- // "js". If so, then only methods that begin with special\r
- // prefixes will be defined as JavaScript entities.\r
- // The prefixes "js_" and "jsProperty_" are deprecated.\r
- final String genericPrefix = "js_";\r
- final String functionPrefix = "jsFunction_";\r
- final String staticFunctionPrefix = "jsStaticFunction_";\r
- final String propertyPrefix = "jsProperty_";\r
- final String getterPrefix = "jsGet_";\r
- final String setterPrefix = "jsSet_";\r
- final String ctorName = "jsConstructor";\r
-\r
- boolean hasPrefix = false;\r
- Method[] ctorMeths = FunctionObject.findMethods(clazz, ctorName);\r
- Member ctorMember = null;\r
- if (ctorMeths != null) {\r
- if (ctorMeths.length > 1) {\r
- throw new ClassDefinitionException(\r
- Context.getMessage2("msg.multiple.ctors", \r
- ctorMeths[0], ctorMeths[1]));\r
- }\r
- ctorMember = ctorMeths[0];\r
- hasPrefix = true;\r
- }\r
-\r
- // Deprecated: look for functions with the same name as the class\r
- // and consider them constructors.\r
- for (int i=0; i < methods.length; i++) {\r
- String name = methods[i].getName();\r
- String prefix = null;\r
- if (!name.startsWith("js")) // common start to all prefixes\r
- prefix = null;\r
- else if (name.startsWith(genericPrefix))\r
- prefix = genericPrefix;\r
- else if (name.startsWith(functionPrefix))\r
- prefix = functionPrefix;\r
- else if (name.startsWith(staticFunctionPrefix))\r
- prefix = staticFunctionPrefix;\r
- else if (name.startsWith(propertyPrefix))\r
- prefix = propertyPrefix;\r
- else if (name.startsWith(getterPrefix))\r
- prefix = getterPrefix;\r
- else if (name.startsWith(setterPrefix))\r
- prefix = setterPrefix;\r
- if (prefix != null) {\r
- hasPrefix = true;\r
- name = name.substring(prefix.length());\r
- }\r
- if (name.equals(className)) {\r
- if (ctorMember != null) {\r
- throw new ClassDefinitionException(\r
- Context.getMessage2("msg.multiple.ctors", \r
- ctorMember, methods[i]));\r
- }\r
- ctorMember = methods[i];\r
- }\r
- }\r
-\r
- if (ctorMember == null) {\r
- if (ctors.length == 1) {\r
- ctorMember = ctors[0];\r
- } else if (ctors.length == 2) {\r
- if (ctors[0].getParameterTypes().length == 0)\r
- ctorMember = ctors[1];\r
- else if (ctors[1].getParameterTypes().length == 0)\r
- ctorMember = ctors[0];\r
- }\r
- if (ctorMember == null) {\r
- throw new ClassDefinitionException(\r
- Context.getMessage1("msg.ctor.multiple.parms",\r
- clazz.getName()));\r
- }\r
- }\r
-\r
- FunctionObject ctor = new FunctionObject(className, ctorMember, scope);\r
- if (ctor.isVarArgsMethod()) {\r
- throw Context.reportRuntimeError1\r
- ("msg.varargs.ctor", ctorMember.getName());\r
- }\r
- ctor.addAsConstructor(scope, proto);\r
-\r
- if (!hasPrefix && exclusionList == null)\r
- exclusionList = getExclusionList();\r
- Method finishInit = null;\r
- for (int i=0; i < methods.length; i++) {\r
- if (!hasPrefix && methods[i].getDeclaringClass() != clazz)\r
- continue;\r
- String name = methods[i].getName();\r
- if (name.equals("finishInit")) {\r
- Class[] parmTypes = methods[i].getParameterTypes();\r
- if (parmTypes.length == 3 &&\r
- parmTypes[0] == ScriptRuntime.ScriptableClass &&\r
- parmTypes[1] == FunctionObject.class &&\r
- parmTypes[2] == ScriptRuntime.ScriptableClass &&\r
- Modifier.isStatic(methods[i].getModifiers()))\r
- {\r
- finishInit = methods[i];\r
- continue;\r
- }\r
- }\r
- // ignore any compiler generated methods.\r
- if (name.indexOf('$') != -1)\r
- continue;\r
- if (name.equals(ctorName))\r
- continue;\r
- String prefix = null;\r
- if (hasPrefix) {\r
- if (name.startsWith(genericPrefix)) {\r
- prefix = genericPrefix;\r
- } else if (name.startsWith(functionPrefix)) {\r
- prefix = functionPrefix;\r
- } else if (name.startsWith(staticFunctionPrefix)) {\r
- prefix = staticFunctionPrefix;\r
- if (!Modifier.isStatic(methods[i].getModifiers())) {\r
- throw new ClassDefinitionException(\r
- "jsStaticFunction must be used with static method.");\r
- }\r
- } else if (name.startsWith(propertyPrefix)) {\r
- prefix = propertyPrefix;\r
- } else if (name.startsWith(getterPrefix)) {\r
- prefix = getterPrefix;\r
- } else if (name.startsWith(setterPrefix)) {\r
- prefix = setterPrefix;\r
- } else {\r
- continue;\r
- }\r
- name = name.substring(prefix.length());\r
- } else if (exclusionList.get(name) != null)\r
- continue;\r
- if (methods[i] == ctorMember) {\r
- continue;\r
- }\r
- if (prefix != null && prefix.equals(setterPrefix))\r
- continue; // deal with set when we see get\r
- if (prefix != null && prefix.equals(getterPrefix)) {\r
- if (!(proto instanceof ScriptableObject)) {\r
- throw PropertyException.withMessage2\r
- ("msg.extend.scriptable", proto.getClass().toString(), name);\r
- }\r
- Method[] setter = FunctionObject.findMethods(\r
- clazz,\r
- setterPrefix + name);\r
- if (setter != null && setter.length != 1) {\r
- throw PropertyException.withMessage2\r
- ("msg.no.overload", name, clazz.getName());\r
- }\r
- int attr = ScriptableObject.PERMANENT |\r
- ScriptableObject.DONTENUM |\r
- (setter != null ? 0\r
- : ScriptableObject.READONLY);\r
- Method m = setter == null ? null : setter[0];\r
- ((ScriptableObject) proto).defineProperty(name, null,\r
- methods[i], m,\r
- attr);\r
- continue;\r
- }\r
- if ((name.startsWith("get") || name.startsWith("set")) &&\r
- name.length() > 3 &&\r
- !(hasPrefix && (prefix.equals(functionPrefix) ||\r
- prefix.equals(staticFunctionPrefix))))\r
- {\r
- if (!(proto instanceof ScriptableObject)) {\r
- throw PropertyException.withMessage2\r
- ("msg.extend.scriptable",\r
- proto.getClass().toString(), name);\r
- }\r
- if (name.startsWith("set"))\r
- continue; // deal with set when we see get\r
- StringBuffer buf = new StringBuffer();\r
- char c = name.charAt(3);\r
- buf.append(Character.toLowerCase(c));\r
- if (name.length() > 4)\r
- buf.append(name.substring(4));\r
- String propertyName = buf.toString();\r
- buf.setCharAt(0, c);\r
- buf.insert(0, "set");\r
- String setterName = buf.toString();\r
- Method[] setter = FunctionObject.findMethods(\r
- clazz,\r
- hasPrefix ? genericPrefix + setterName\r
- : setterName);\r
- if (setter != null && setter.length != 1) {\r
- throw PropertyException.withMessage2\r
- ("msg.no.overload", name, clazz.getName());\r
- }\r
- if (setter == null && hasPrefix)\r
- setter = FunctionObject.findMethods(\r
- clazz,\r
- propertyPrefix + setterName);\r
- int attr = ScriptableObject.PERMANENT |\r
- ScriptableObject.DONTENUM |\r
- (setter != null ? 0\r
- : ScriptableObject.READONLY);\r
- Method m = setter == null ? null : setter[0];\r
- ((ScriptableObject) proto).defineProperty(propertyName, null,\r
- methods[i], m,\r
- attr);\r
- continue;\r
- }\r
- FunctionObject f = new FunctionObject(name, methods[i], proto);\r
- if (f.isVarArgsConstructor()) {\r
- throw Context.reportRuntimeError1\r
- ("msg.varargs.fun", ctorMember.getName());\r
- }\r
- Scriptable dest = prefix == staticFunctionPrefix\r
- ? ctor\r
- : proto;\r
- defineProperty(dest, name, f, DONTENUM);\r
- if (sealed) {\r
- f.sealObject();\r
- f.addPropertyAttribute(READONLY);\r
- }\r
- }\r
-\r
- if (finishInit != null) {\r
- // call user code to complete the initialization\r
- Object[] finishArgs = { scope, ctor, proto };\r
- finishInit.invoke(null, finishArgs);\r
- }\r
- \r
- if (sealed) {\r
- ctor.sealObject();\r
- ctor.addPropertyAttribute(READONLY);\r
- if (proto instanceof ScriptableObject) {\r
- ((ScriptableObject) proto).sealObject();\r
- ((ScriptableObject) proto).addPropertyAttribute(READONLY);\r
- }\r
- }\r
- }\r
-\r
- /**\r
- * Define a JavaScript property.\r
- *\r
- * Creates the property with an initial value and sets its attributes.\r
- *\r
- * @param propertyName the name of the property to define.\r
- * @param value the initial value of the property\r
- * @param attributes the attributes of the JavaScript property\r
- * @see org.mozilla.javascript.Scriptable#put\r
- */\r
- public void defineProperty(String propertyName, Object value,\r
- int attributes)\r
- {\r
- put(propertyName, this, value);\r
- try {\r
- setAttributes(propertyName, this, attributes);\r
- }\r
- catch (PropertyException e) {\r
- throw new RuntimeException("Cannot create property");\r
- }\r
- }\r
-\r
- /**\r
- * Utility method to add properties to arbitrary Scriptable object.\r
- * If destination is instance of ScriptableObject, calls \r
- * defineProperty there, otherwise calls put in destination \r
- * ignoring attributes\r
- */\r
- public static void defineProperty(Scriptable destination, \r
- String propertyName, Object value,\r
- int attributes)\r
- {\r
- if (destination instanceof ScriptableObject) {\r
- ScriptableObject obj = (ScriptableObject)destination;\r
- obj.defineProperty(propertyName, value, attributes);\r
- }\r
- else {\r
- destination.put(propertyName, destination, value);\r
- }\r
- }\r
- \r
- /**\r
- * Define a JavaScript property with getter and setter side effects.\r
- *\r
- * If the setter is not found, the attribute READONLY is added to\r
- * the given attributes. <p>\r
- *\r
- * The getter must be a method with zero parameters, and the setter, if\r
- * found, must be a method with one parameter.<p>\r
- *\r
- * @param propertyName the name of the property to define. This name\r
- * also affects the name of the setter and getter\r
- * to search for. If the propertyId is "foo", then\r
- * <code>clazz</code> will be searched for "getFoo"\r
- * and "setFoo" methods.\r
- * @param clazz the Java class to search for the getter and setter\r
- * @param attributes the attributes of the JavaScript property\r
- * @exception PropertyException if multiple methods\r
- * are found for the getter or setter, or if the getter\r
- * or setter do not conform to the forms described in\r
- * <code>defineProperty(String, Object, Method, Method,\r
- * int)</code>\r
- * @see org.mozilla.javascript.Scriptable#put\r
- */\r
- public void defineProperty(String propertyName, Class clazz,\r
- int attributes)\r
- throws PropertyException\r
- {\r
- StringBuffer buf = new StringBuffer(propertyName);\r
- buf.setCharAt(0, Character.toUpperCase(propertyName.charAt(0)));\r
- String s = buf.toString();\r
- Method[] getter = FunctionObject.findMethods(clazz, "get" + s);\r
- Method[] setter = FunctionObject.findMethods(clazz, "set" + s);\r
- if (setter == null)\r
- attributes |= ScriptableObject.READONLY;\r
- if (getter.length != 1 || (setter != null && setter.length != 1)) {\r
- throw PropertyException.withMessage2\r
- ("msg.no.overload", propertyName, clazz.getName());\r
- }\r
- defineProperty(propertyName, null, getter[0],\r
- setter == null ? null : setter[0], attributes);\r
- }\r
-\r
- /**\r
- * Define a JavaScript property.\r
- *\r
- * Use this method only if you wish to define getters and setters for\r
- * a given property in a ScriptableObject. To create a property without\r
- * special getter or setter side effects, use\r
- * <code>defineProperty(String,int)</code>.\r
- *\r
- * If <code>setter</code> is null, the attribute READONLY is added to\r
- * the given attributes.<p>\r
- *\r
- * Several forms of getters or setters are allowed. In all cases the\r
- * type of the value parameter can be any one of the following types: \r
- * Object, String, boolean, Scriptable, byte, short, int, long, float,\r
- * or double. The runtime will perform appropriate conversions based\r
- * upon the type of the parameter (see description in FunctionObject).\r
- * The first forms are nonstatic methods of the class referred to\r
- * by 'this':\r
- * <pre>\r
- * Object getFoo();\r
- * void setFoo(SomeType value);</pre>\r
- * Next are static methods that may be of any class; the object whose\r
- * property is being accessed is passed in as an extra argument:\r
- * <pre>\r
- * static Object getFoo(ScriptableObject obj);\r
- * static void setFoo(ScriptableObject obj, SomeType value);</pre>\r
- * Finally, it is possible to delegate to another object entirely using\r
- * the <code>delegateTo</code> parameter. In this case the methods are\r
- * nonstatic methods of the class delegated to, and the object whose\r
- * property is being accessed is passed in as an extra argument:\r
- * <pre>\r
- * Object getFoo(ScriptableObject obj);\r
- * void setFoo(ScriptableObject obj, SomeType value);</pre>\r
- *\r
- * @param propertyName the name of the property to define.\r
- * @param delegateTo an object to call the getter and setter methods on,\r
- * or null, depending on the form used above.\r
- * @param getter the method to invoke to get the value of the property\r
- * @param setter the method to invoke to set the value of the property\r
- * @param attributes the attributes of the JavaScript property\r
- * @exception PropertyException if the getter or setter\r
- * do not conform to the forms specified above\r
- */\r
- public void defineProperty(String propertyName, Object delegateTo,\r
- Method getter, Method setter, int attributes)\r
- throws PropertyException\r
- {\r
- int flags = Slot.HAS_GETTER;\r
- if (delegateTo == null && (Modifier.isStatic(getter.getModifiers())))\r
- delegateTo = HAS_STATIC_ACCESSORS;\r
- Class[] parmTypes = getter.getParameterTypes();\r
- if (parmTypes.length != 0) {\r
- if (parmTypes.length != 1 ||\r
- parmTypes[0] != ScriptableObject.class)\r
- {\r
- throw PropertyException.withMessage1\r
- ("msg.bad.getter.parms", getter.toString());\r
- }\r
- } else if (delegateTo != null) {\r
- throw PropertyException.withMessage1\r
- ("msg.obj.getter.parms", getter.toString());\r
- }\r
- if (setter != null) {\r
- flags |= Slot.HAS_SETTER;\r
- if ((delegateTo == HAS_STATIC_ACCESSORS) !=\r
- (Modifier.isStatic(setter.getModifiers())))\r
- {\r
- throw PropertyException.withMessage0("msg.getter.static");\r
- }\r
- parmTypes = setter.getParameterTypes();\r
- if (parmTypes.length == 2) {\r
- if (parmTypes[0] != ScriptableObject.class) {\r
- throw PropertyException.withMessage0("msg.setter2.parms");\r
- }\r
- if (delegateTo == null) {\r
- throw PropertyException.withMessage1\r
- ("msg.setter1.parms", setter.toString());\r
- }\r
- } else if (parmTypes.length == 1) {\r
- if (delegateTo != null) {\r
- throw PropertyException.withMessage1\r
- ("msg.setter2.expected", setter.toString());\r
- }\r
- } else {\r
- throw PropertyException.withMessage0("msg.setter.parms");\r
- }\r
- }\r
- GetterSlot slot = (GetterSlot)getSlotToSet(propertyName,\r
- propertyName.hashCode(),\r
- true);\r
- slot.delegateTo = delegateTo;\r
- slot.getter = getter;\r
- slot.setter = setter;\r
- slot.setterReturnsValue = setter != null && setter.getReturnType() != Void.TYPE;\r
- slot.value = null;\r
- slot.attributes = (short) attributes;\r
- slot.flags = (byte)flags;\r
- }\r
-\r
- /**\r
- * Search for names in a class, adding the resulting methods\r
- * as properties.\r
- *\r
- * <p> Uses reflection to find the methods of the given names. Then\r
- * FunctionObjects are constructed from the methods found, and\r
- * are added to this object as properties with the given names.\r
- *\r
- * @param names the names of the Methods to add as function properties\r
- * @param clazz the class to search for the Methods\r
- * @param attributes the attributes of the new properties\r
- * @exception PropertyException if any of the names\r
- * has no corresponding method or more than one corresponding\r
- * method in the class\r
- * @see org.mozilla.javascript.FunctionObject\r
- */\r
- public void defineFunctionProperties(String[] names, Class clazz,\r
- int attributes)\r
- throws PropertyException\r
- {\r
- for (int i=0; i < names.length; i++) {\r
- String name = names[i];\r
- Method[] m = FunctionObject.findMethods(clazz, name);\r
- if (m == null) {\r
- throw PropertyException.withMessage2\r
- ("msg.method.not.found", name, clazz.getName());\r
- }\r
- if (m.length > 1) {\r
- throw PropertyException.withMessage2\r
- ("msg.no.overload", name, clazz.getName());\r
- }\r
- FunctionObject f = new FunctionObject(name, m[0], this);\r
- defineProperty(name, f, attributes);\r
- }\r
- }\r
-\r
- /**\r
- * Get the Object.prototype property.\r
- * See ECMA 15.2.4.\r
- */\r
- public static Scriptable getObjectPrototype(Scriptable scope) {\r
- return getClassPrototype(scope, "Object");\r
- }\r
-\r
- /**\r
- * Get the Function.prototype property.\r
- * See ECMA 15.3.4.\r
- */\r
- public static Scriptable getFunctionPrototype(Scriptable scope) {\r
- return getClassPrototype(scope, "Function");\r
- }\r
-\r
- /**\r
- * Get the prototype for the named class.\r
- *\r
- * For example, <code>getClassPrototype(s, "Date")</code> will first\r
- * walk up the parent chain to find the outermost scope, then will\r
- * search that scope for the Date constructor, and then will\r
- * return Date.prototype. If any of the lookups fail, or\r
- * the prototype is not a JavaScript object, then null will\r
- * be returned.\r
- *\r
- * @param scope an object in the scope chain\r
- * @param className the name of the constructor\r
- * @return the prototype for the named class, or null if it\r
- * cannot be found.\r
- */\r
- public static Scriptable getClassPrototype(Scriptable scope,\r
- String className)\r
- {\r
- scope = getTopLevelScope(scope);\r
- Object ctor = ScriptRuntime.getTopLevelProp(scope, className);\r
- if (ctor == NOT_FOUND || !(ctor instanceof Scriptable))\r
- return null;\r
- Scriptable ctorObj = (Scriptable) ctor;\r
- if (!ctorObj.has("prototype", ctorObj))\r
- return null;\r
- Object proto = ctorObj.get("prototype", ctorObj);\r
- if (!(proto instanceof Scriptable))\r
- return null;\r
- return (Scriptable) proto;\r
- }\r
-\r
- /**\r
- * Get the global scope.\r
- *\r
- * <p>Walks the parent scope chain to find an object with a null\r
- * parent scope (the global object).\r
- *\r
- * @param obj a JavaScript object\r
- * @return the corresponding global scope\r
- */\r
- public static Scriptable getTopLevelScope(Scriptable obj) {\r
- Scriptable next = obj;\r
- do {\r
- obj = next;\r
- next = obj.getParentScope();\r
- } while (next != null);\r
- return obj;\r
- }\r
- \r
- /**\r
- * Seal this object.\r
- * \r
- * A sealed object may not have properties added or removed. Once\r
- * an object is sealed it may not be unsealed.\r
- * \r
- * @since 1.4R3\r
- */\r
- public void sealObject() {\r
- count = -1;\r
- }\r
- \r
- /**\r
- * Return true if this object is sealed.\r
- * \r
- * It is an error to attempt to add or remove properties to \r
- * a sealed object.\r
- * \r
- * @return true if sealed, false otherwise.\r
- * @since 1.4R3\r
- */\r
- public boolean isSealed() {\r
- return count == -1;\r
- }\r
-\r
- /**\r
- * Gets a named property from an object or any object in its prototype chain.\r
- * <p>\r
- * Searches the prototype chain for a property named <code>name</code>.\r
- * <p>\r
- * @param obj a JavaScript object \r
- * @param name a property name \r
- * @return the value of a property with name <code>name</code> found in \r
- * <code>obj</code> or any object in its prototype chain, or \r
- * <code>Scriptable.NOT_FOUND</code> if not found\r
- * @since 1.5R2\r
- */\r
- public static Object getProperty(Scriptable obj, String name) {\r
- Scriptable start = obj;\r
- Object result;\r
- do {\r
- result = obj.get(name, start);\r
- if (result != Scriptable.NOT_FOUND)\r
- break;\r
- obj = obj.getPrototype();\r
- } while (obj != null);\r
- return result;\r
- }\r
- \r
- /**\r
- * Gets an indexed property from an object or any object in its prototype chain.\r
- * <p>\r
- * Searches the prototype chain for a property with integral index \r
- * <code>index</code>. Note that if you wish to look for properties with numerical\r
- * but non-integral indicies, you should use getProperty(Scriptable,String) with\r
- * the string value of the index.\r
- * <p>\r
- * @param obj a JavaScript object \r
- * @param index an integral index \r
- * @return the value of a property with index <code>index</code> found in \r
- * <code>obj</code> or any object in its prototype chain, or \r
- * <code>Scriptable.NOT_FOUND</code> if not found\r
- * @since 1.5R2\r
- */\r
- public static Object getProperty(Scriptable obj, int index) {\r
- Scriptable start = obj;\r
- Object result;\r
- do {\r
- result = obj.get(index, start);\r
- if (result != Scriptable.NOT_FOUND)\r
- break;\r
- obj = obj.getPrototype();\r
- } while (obj != null);\r
- return result;\r
- }\r
- \r
- /**\r
- * Returns whether a named property is defined in an object or any object \r
- * in its prototype chain.\r
- * <p>\r
- * Searches the prototype chain for a property named <code>name</code>.\r
- * <p>\r
- * @param obj a JavaScript object \r
- * @param name a property name \r
- * @return the true if property was found\r
- * @since 1.5R2\r
- */\r
- public static boolean hasProperty(Scriptable obj, String name) {\r
- Scriptable start = obj;\r
- do {\r
- if (obj.has(name, start))\r
- return true;\r
- obj = obj.getPrototype();\r
- } while (obj != null);\r
- return false;\r
- }\r
- \r
- /**\r
- * Returns whether an indexed property is defined in an object or any object \r
- * in its prototype chain.\r
- * <p>\r
- * Searches the prototype chain for a property with index <code>index</code>.\r
- * <p>\r
- * @param obj a JavaScript object \r
- * @param index a property index \r
- * @return the true if property was found\r
- * @since 1.5R2\r
- */\r
- public static boolean hasProperty(Scriptable obj, int index) {\r
- Scriptable start = obj;\r
- do {\r
- if (obj.has(index, start))\r
- return true;\r
- obj = obj.getPrototype();\r
- } while (obj != null);\r
- return false;\r
- }\r
-\r
- /**\r
- * Puts a named property in an object or in an object in its prototype chain.\r
- * <p>\r
- * Seaches for the named property in the prototype chain. If it is found,\r
- * the value of the property is changed. If it is not found, a new\r
- * property is added in <code>obj</code>.\r
- * @param obj a JavaScript object \r
- * @param name a property name\r
- * @param value any JavaScript value accepted by Scriptable.put \r
- * @since 1.5R2\r
- */\r
- public static void putProperty(Scriptable obj, String name, Object value) {\r
- Scriptable base = getBase(obj, name);\r
- if (base == null)\r
- base = obj;\r
- base.put(name, obj, value);\r
- }\r
-\r
- /**\r
- * Puts an indexed property in an object or in an object in its prototype chain.\r
- * <p>\r
- * Seaches for the indexed property in the prototype chain. If it is found,\r
- * the value of the property is changed. If it is not found, a new\r
- * property is added in <code>obj</code>.\r
- * @param obj a JavaScript object \r
- * @param index a property index\r
- * @param value any JavaScript value accepted by Scriptable.put \r
- * @since 1.5R2\r
- */\r
- public static void putProperty(Scriptable obj, int index, Object value) {\r
- Scriptable base = getBase(obj, index);\r
- if (base == null)\r
- base = obj;\r
- base.put(index, obj, value);\r
- }\r
-\r
- /**\r
- * Removes the property from an object or its prototype chain.\r
- * <p>\r
- * Searches for a property with <code>name</code> in obj or\r
- * its prototype chain. If it is found, the object's delete\r
- * method is called. \r
- * @param obj a JavaScript object\r
- * @param name a property name\r
- * @return true if the property doesn't exist or was successfully removed\r
- * @since 1.5R2\r
- */\r
- public static boolean deleteProperty(Scriptable obj, String name) {\r
- Scriptable base = getBase(obj, name);\r
- if (base == null)\r
- return true;\r
- base.delete(name);\r
- return base.get(name, obj) == NOT_FOUND;\r
- }\r
- \r
- /**\r
- * Removes the property from an object or its prototype chain.\r
- * <p>\r
- * Searches for a property with <code>index</code> in obj or\r
- * its prototype chain. If it is found, the object's delete\r
- * method is called. \r
- * @param obj a JavaScript object\r
- * @param index a property index\r
- * @return true if the property doesn't exist or was successfully removed\r
- * @since 1.5R2\r
- */\r
- public static boolean deleteProperty(Scriptable obj, int index) {\r
- Scriptable base = getBase(obj, index);\r
- if (base == null)\r
- return true;\r
- base.delete(index);\r
- return base.get(index, obj) == NOT_FOUND;\r
- }\r
- \r
- /**\r
- * Returns an array of all ids from an object and its prototypes.\r
- * <p>\r
- * @param obj a JavaScript object\r
- * @return an array of all ids from all object in the prototype chain.\r
- * If a given id occurs multiple times in the prototype chain,\r
- * it will occur only once in this list.\r
- * @since 1.5R2\r
- */\r
- public static Object[] getPropertyIds(Scriptable obj) {\r
- Hashtable h = new Hashtable(); // JDK1.2: use HashSet\r
- while (obj != null) {\r
- Object[] ids = obj.getIds();\r
- for (int i=0; i < ids.length; i++) {\r
- h.put(ids[i], ids[i]);\r
- }\r
- obj = (Scriptable)obj.getPrototype();\r
- }\r
- Object[] result = new Object[h.size()];\r
- java.util.Enumeration e = h.elements();\r
- int n = 0;\r
- while (e.hasMoreElements()) {\r
- result[n++] = e.nextElement();\r
- }\r
- return result;\r
- }\r
- \r
- /**\r
- * Call a method of an object.\r
- * <p>\r
- * @param obj the JavaScript object\r
- * @param methodName the name of the function property\r
- * @param args the arguments for the call\r
- * @exception JavaScriptException thrown if there were errors in the call\r
- */\r
- public static Object callMethod(Scriptable obj, String methodName, \r
- Object[] args)\r
- throws JavaScriptException\r
- {\r
- Context cx = Context.enter();\r
- try {\r
- Object fun = getProperty(obj, methodName);\r
- if (fun == NOT_FOUND)\r
- fun = Undefined.instance;\r
- return ScriptRuntime.call(cx, fun, obj, args, getTopLevelScope(obj));\r
- } finally {\r
- Context.exit();\r
- }\r
- }\r
- \r
- private static Scriptable getBase(Scriptable obj, String s) {\r
- Scriptable m = obj;\r
- while (m != null) {\r
- if (m.has(s, obj))\r
- return m;\r
- m = m.getPrototype();\r
- }\r
- return null;\r
- }\r
-\r
- private static Scriptable getBase(Scriptable obj, int index) {\r
- Scriptable m = obj;\r
- while (m != null) {\r
- if (m.has(index, obj))\r
- return m;\r
- m = m.getPrototype();\r
- }\r
- return null;\r
- }\r
- \r
- /**\r
- * Adds a property attribute to all properties.\r
- */\r
- synchronized void addPropertyAttribute(int attribute) {\r
- if (slots == null)\r
- return;\r
- for (int i=0; i < slots.length; i++) {\r
- Slot slot = slots[i];\r
- if (slot == null || slot == REMOVED)\r
- continue;\r
- if ((slot.flags & slot.HAS_SETTER) != 0 && attribute == READONLY)\r
- continue;\r
- slot.attributes |= attribute;\r
- }\r
- }\r
- \r
- private Slot getSlot(String id, int index, boolean shouldDelete) {\r
- Slot[] slots = this.slots;\r
- if (slots == null)\r
- return null;\r
- int start = (index & 0x7fffffff) % slots.length;\r
- int i = start;\r
- do {\r
- Slot slot = slots[i];\r
- if (slot == null)\r
- return null;\r
- if (slot != REMOVED && slot.intKey == index && \r
- (slot.stringKey == id || (id != null && \r
- id.equals(slot.stringKey))))\r
- {\r
- if (shouldDelete) {\r
- if ((slot.attributes & PERMANENT) == 0) {\r
- // Mark the slot as removed to handle a case when\r
- // another thread manages to put just removed slot\r
- // into lastAccess cache.\r
- slot.wasDeleted = (byte)1;\r
- slots[i] = REMOVED;\r
- count--;\r
- if (slot == lastAccess)\r
- lastAccess = REMOVED;\r
- }\r
- }\r
- return slot;\r
- }\r
- if (++i == slots.length)\r
- i = 0;\r
- } while (i != start);\r
- return null;\r
- }\r
-\r
- private Slot getSlotToSet(String id, int index, boolean getterSlot) {\r
- if (slots == null)\r
- slots = new Slot[5];\r
- int start = (index & 0x7fffffff) % slots.length;\r
- boolean sawRemoved = false;\r
- int i = start;\r
- do {\r
- Slot slot = slots[i];\r
- if (slot == null) {\r
- return addSlot(id, index, getterSlot);\r
- }\r
- if (slot == REMOVED) {\r
- sawRemoved = true;\r
- } else if (slot.intKey == index && \r
- (slot.stringKey == id || \r
- (id != null && id.equals(slot.stringKey))))\r
- {\r
- return slot;\r
- }\r
- if (++i == slots.length)\r
- i = 0;\r
- } while (i != start);\r
- if (sawRemoved) {\r
- // Table could be full, but with some REMOVED elements. \r
- // Call to addSlot will use a slot currently taken by \r
- // a REMOVED.\r
- return addSlot(id, index, getterSlot);\r
- }\r
- throw new RuntimeException("Hashtable internal error");\r
- }\r
-\r
- /**\r
- * Add a new slot to the hash table.\r
- *\r
- * This method must be synchronized since it is altering the hash\r
- * table itself. Note that we search again for the slot to set\r
- * since another thread could have added the given property or\r
- * caused the table to grow while this thread was searching.\r
- */\r
- private synchronized Slot addSlot(String id, int index, boolean getterSlot)\r
- {\r
- if (count == -1)\r
- throw Context.reportRuntimeError0("msg.add.sealed");\r
- int start = (index & 0x7fffffff) % slots.length;\r
- int i = start;\r
- do {\r
- Slot slot = slots[i];\r
- if (slot == null || slot == REMOVED) {\r
- if ((4 * (count+1)) > (3 * slots.length)) {\r
- grow();\r
- return getSlotToSet(id, index, getterSlot);\r
- }\r
- slot = getterSlot ? new GetterSlot() : new Slot();\r
- slot.stringKey = id;\r
- slot.intKey = index;\r
- slots[i] = slot;\r
- count++;\r
- return slot;\r
- }\r
- if (slot.intKey == index && \r
- (slot.stringKey == id || (id != null && \r
- id.equals(slot.stringKey)))) \r
- {\r
- return slot;\r
- }\r
- if (++i == slots.length)\r
- i = 0;\r
- } while (i != start);\r
- throw new RuntimeException("Hashtable internal error");\r
- }\r
-\r
- /**\r
- * Remove a slot from the hash table.\r
- *\r
- * This method must be synchronized since it is altering the hash\r
- * table itself. We might be able to optimize this more, but\r
- * deletes are not common.\r
- */\r
- private synchronized void removeSlot(String name, int index) {\r
- if (count == -1)\r
- throw Context.reportRuntimeError0("msg.remove.sealed");\r
- getSlot(name, index, true);\r
- }\r
-\r
- /**\r
- * Grow the hash table to accommodate new entries.\r
- *\r
- * Note that by assigning the new array back at the end we\r
- * can continue reading the array from other threads.\r
- */\r
- private synchronized void grow() {\r
- Slot[] newSlots = new Slot[slots.length*2 + 1];\r
- for (int j=slots.length-1; j >= 0 ; j--) {\r
- Slot slot = slots[j];\r
- if (slot == null || slot == REMOVED)\r
- continue;\r
- int k = (slot.intKey & 0x7fffffff) % newSlots.length;\r
- while (newSlots[k] != null)\r
- if (++k == newSlots.length)\r
- k = 0;\r
- // The end of the "synchronized" statement will cause the memory\r
- // writes to be propagated on a multiprocessor machine. We want\r
- // to make sure that the new table is prepared to be read.\r
- // XXX causes the 'this' pointer to be null in calling stack frames\r
- // on the MS JVM\r
- //synchronized (slot) { }\r
- newSlots[k] = slot;\r
- }\r
- slots = newSlots;\r
- }\r
-\r
- private static Hashtable getExclusionList() {\r
- if (exclusionList != null)\r
- return exclusionList;\r
- Hashtable result = new Hashtable(17);\r
- Method[] methods = ScriptRuntime.FunctionClass.getMethods();\r
- for (int i=0; i < methods.length; i++) {\r
- result.put(methods[i].getName(), Boolean.TRUE);\r
- }\r
- exclusionList = result;\r
- return result;\r
- }\r
- \r
- Object[] getIds(boolean getAll) {\r
- Slot[] s = slots;\r
- Object[] a = ScriptRuntime.emptyArgs;\r
- if (s == null)\r
- return a;\r
- int c = 0;\r
- for (int i=0; i < s.length; i++) {\r
- Slot slot = s[i];\r
- if (slot == null || slot == REMOVED)\r
- continue;\r
- if (getAll || (slot.attributes & DONTENUM) == 0) {\r
- if (c == 0)\r
- a = new Object[s.length - i];\r
- a[c++] = slot.stringKey != null\r
- ? (Object) slot.stringKey\r
- : new Integer(slot.intKey);\r
- }\r
- }\r
- if (c == a.length)\r
- return a;\r
- Object[] result = new Object[c];\r
- System.arraycopy(a, 0, result, 0, c);\r
- return result;\r
- }\r
-\r
- \r
- /**\r
- * The prototype of this object.\r
- */\r
- protected Scriptable prototype;\r
- \r
- /**\r
- * The parent scope of this object.\r
- */\r
- protected Scriptable parent;\r
-\r
- private static final Object HAS_STATIC_ACCESSORS = Void.TYPE;\r
- private static final Slot REMOVED = new Slot();\r
- private static Hashtable exclusionList = null;\r
- \r
- private Slot[] slots;\r
- private int count;\r
-\r
- // cache; may be removed for smaller memory footprint\r
- private Slot lastAccess = REMOVED;\r
-\r
- private static class Slot {\r
- static final int HAS_GETTER = 0x01;\r
- static final int HAS_SETTER = 0x02;\r
- \r
- int intKey;\r
- String stringKey;\r
- Object value;\r
- short attributes;\r
- byte flags;\r
- byte wasDeleted;\r
- }\r
-\r
- private static class GetterSlot extends Slot {\r
- Object delegateTo; // OPT: merge with "value"\r
- Method getter;\r
- Method setter;\r
- boolean setterReturnsValue;\r
- }\r
-\r
- private static final Class ContextClass = Context.class;\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-// API class\r
-\r
-package org.mozilla.javascript;\r
-\r
-/**\r
- * This class describes the support needed to implement security.\r
- * <p>\r
- * Three main pieces of functionality are required to implement\r
- * security for JavaScript. First, it must be possible to define\r
- * classes with an associated security context. (This security \r
- * context may be any object that has meaning to an embedding;\r
- * for a client-side JavaScript embedding this would typically\r
- * be an origin URL and/or a digital certificate.) Next it \r
- * must be possible to get the current class context so that\r
- * the implementation can determine securely which class is\r
- * requesting a privileged action. And finally, it must be \r
- * possible to map a class back into a security context so that\r
- * additional classes may be defined with that security context.\r
- * <p>\r
- * These three pieces of functionality are encapsulated in the\r
- * SecuritySupport class.\r
- * <p>\r
- * Additionally, an embedding may provide filtering on the \r
- * Java classes that are visible to scripts through the \r
- * <code>visibleToScripts</code> method.\r
- *\r
- * @see org.mozilla.javascript.Context\r
- * @see java.lang.ClassLoader\r
- * @since 1.4 Release 2\r
- * @author Norris Boyd\r
- */\r
-public interface SecuritySupport {\r
-\r
- /**\r
- * Define and load a Java class.\r
- * <p>\r
- * In embeddings that care about security, the securityDomain \r
- * must be associated with the defined class such that a call to\r
- * <code>getSecurityDomain</code> with that class will return this security\r
- * context.\r
- * <p>\r
- * @param name the name of the class\r
- * @param data the bytecode of the class\r
- * @param securityDomain some object specifying the security\r
- * context of the code that is defining this class.\r
- * Embeddings that don't care about security may allow\r
- * null here. This value propagated from the values passed\r
- * into methods of Context that evaluate scripts.\r
- */\r
- public Class defineClass(String name, byte[] data, \r
- Object securityDomain);\r
- \r
- /**\r
- * Get the current class Context.\r
- * <p> \r
- * This functionality is supplied by SecurityManager.getClassContext,\r
- * but only one SecurityManager may be instantiated in a single JVM\r
- * at any one time. So implementations that care about security must\r
- * provide access to this functionality through this interface.\r
- * <p>\r
- * Note that the 0th entry of the returned array should be the class\r
- * of the caller of this method. So if this method is implemented by\r
- * calling SecurityManager.getClassContext, this method must allocate\r
- * a new, shorter array to return.\r
- */\r
- public Class[] getClassContext();\r
- \r
- /**\r
- * Return the security context associated with the given class. \r
- * <p>\r
- * If <code>cl</code> is a class defined through a call to \r
- * SecuritySupport.defineClass, then return the security \r
- * context from that call. Otherwise return null.\r
- * @param cl a class potentially defined by defineClass\r
- * @return a security context object previously passed to defineClass\r
- */\r
- public Object getSecurityDomain(Class cl);\r
- \r
- /**\r
- * Return true iff the Java class with the given name should be exposed\r
- * to scripts.\r
- * <p>\r
- * An embedding may filter which Java classes are exposed through \r
- * LiveConnect to JavaScript scripts.\r
- * <p>\r
- * Due to the fact that there is no package reflection in Java,\r
- * this method will also be called with package names. There\r
- * is no way for Rhino to tell if "Packages.a.b" is a package name \r
- * or a class that doesn't exist. What Rhino does is attempt\r
- * to load each segment of "Packages.a.b.c": It first attempts to \r
- * load class "a", then attempts to load class "a.b", then\r
- * finally attempts to load class "a.b.c". On a Rhino installation \r
- * without any SecuritySupport set, and without any of the\r
- * above classes, the expression "Packages.a.b.c" will result in \r
- * a [JavaPackage a.b.c] and not an error.\r
- * <p>\r
- * With SecuritySupport supplied, Rhino will first call \r
- * visibleToScripts before attempting to look up the class name. If\r
- * visibleToScripts returns false, the class name lookup is not \r
- * performed and subsequent Rhino execution assumes the class is\r
- * not present. So for "java.lang.System.out.println" the lookup \r
- * of "java.lang.System" is skipped and thus Rhino assumes that\r
- * "java.lang.System" doesn't exist. So then for "java.lang.System.out",\r
- * Rhino attempts to load the class "java.lang.System.out" because \r
- * it assumes that "java.lang.System" is a package name.\r
- * <p>\r
- * @param fullClassName the full name of the class (including the package\r
- * name, with '.' as a delimiter). For example the \r
- * standard string class is "java.lang.String"\r
- * @return whether or not to reveal this class to scripts\r
- */\r
- public boolean visibleToScripts(String fullClassName);\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- * Roger Lawrence\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-import java.util.Enumeration;\r
-\r
-/**\r
- * This class implements a child iterator for the Node class.\r
- *\r
- * @see Node\r
- * @author Norris Boyd\r
- */\r
-public class ShallowNodeIterator implements Enumeration {\r
-\r
- public ShallowNodeIterator(Node n) {\r
- current = n;\r
- }\r
-\r
- public boolean hasMoreElements() {\r
- return current != null;\r
- }\r
-\r
- public Object nextElement() {\r
- return nextNode();\r
- }\r
-\r
- public Node nextNode() {\r
- Node result = current;\r
- current = current.next;\r
- return result;\r
- }\r
-\r
- private Node current;\r
-}\r
-\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * John Bandhauer\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-// DEBUG API class\r
-\r
-package org.mozilla.javascript;\r
-\r
-/**\r
- * This interface supports managing incrementally updated source text items.\r
- * <p>\r
- * Items have immutable names. They can be valid or invalid. They can \r
- * accumulate text, but existing text can not be overwritten. They can be \r
- * marked as 'complete', 'aborted', etc. They can be cleared of all text. \r
- * See status flags for details.\r
- *\r
- * @see org.mozilla.javascript.SourceTextManager\r
- * @author John Bandhauer\r
- */\r
-\r
-public interface SourceTextItem\r
-{\r
-\r
- /**\r
- * Possible status values...\r
- */\r
-\r
- /**\r
- * Item just created, no text added yet.\r
- */\r
- public static final int INITED = 0;\r
-\r
- /**\r
- * Item has some text, likely that more will be added.\r
- */\r
- public static final int PARTIAL = 1;\r
-\r
- /**\r
- * Item has all the text it is going to get.\r
- */\r
- public static final int COMPLETED = 2;\r
-\r
- /**\r
- * User aborted loading of text, some text may be in item.\r
- */\r
- public static final int ABORTED = 3;\r
-\r
- /**\r
- * Loading of text failed, some text may be in item.\r
- */\r
- public static final int FAILED = 4;\r
-\r
- /**\r
- * Whatever text was in item has been cleared by a consumer.\r
- */\r
- public static final int CLEARED = 5;\r
-\r
- /**\r
- * Item has be marked as invalid and has no useful information.\r
- */\r
- public static final int INVALID = 6;\r
-\r
- /**\r
- * Append some text.\r
- * <p>\r
- * This only succeeds if status is INITED or PARTIAL.\r
- *\r
- * @param text String to append\r
- * @return true if succeeded, false if failed\r
- */\r
- public boolean append(String text);\r
-\r
- /**\r
- * Append a char.\r
- * <p>\r
- * This only succeeds if status is INITED or PARTIAL.\r
- *\r
- * @param c char to append\r
- * @return true if succeeded, false if failed\r
- */\r
- public boolean append(char c);\r
-\r
- /**\r
- * Append a char from a char[].\r
- * <p>\r
- * This only succeeds if status is INITED or PARTIAL.\r
- *\r
- * @param buf char[] from which to append\r
- * @param offset offset into char[] from which to append\r
- * @param count count of chars to append\r
- * @return true if succeeded, false if failed\r
- */\r
- public boolean append(char[] buf, int offset, int count);\r
-\r
- /**\r
- * Set status to COMPLETED.\r
- * <p>\r
- * meaning: all the text is there, it is complete, no problems.\r
- * This only succeeds if status is INITED or PARTIAL.\r
- *\r
- * @return true if succeeded, false if failed\r
- */\r
- public boolean complete();\r
-\r
- /**\r
- * Set status to ABORTED.\r
- * <p>\r
- * meaning: some text might be there, but user aborted text loading.\r
- * This only succeeds if status is INITED or PARTIAL.\r
- *\r
- * @return true if succeeded, false if failed\r
- */\r
- public boolean abort();\r
-\r
- /**\r
- * Set status to FAILED.\r
- * <p>\r
- * meaning: some text might be there, but loading failed.\r
- * This only succeeds if status is INITED or PARTIAL.\r
- *\r
- * @return true if succeeded, false if failed\r
- */\r
- public boolean fail();\r
-\r
- /**\r
- * Clear the text and set status to CLEARED.\r
- * <p>\r
- * meaning: consumer of the text has what he wants, leave this \r
- * as an emptly placeholder.\r
- * This succeeds unless status is INVALID.\r
- *\r
- * @return true if succeeded, false if failed\r
- */\r
- public boolean clear();\r
-\r
- /**\r
- * Clear the text and set status to INVALID.\r
- * <p>\r
- * meaning: This item is not to be used, likely the SourceTextManager \r
- * has been asked to create a new item (with potentially different \r
- * text) in its place.\r
- * This succeeds unless status is INVALID.\r
- *\r
- * @return true if succeeded, false if failed\r
- */\r
- public boolean invalidate();\r
-\r
- /**\r
- * Get the Current Text.\r
- *\r
- * @return the text, null if INVALID\r
- */\r
- public String getText();\r
-\r
- /**\r
- * Get the name.\r
- *\r
- * @return the name (immutable).\r
- */\r
- public String getName();\r
-\r
- /**\r
- * Get the status.\r
- *\r
- * @return the current status\r
- */\r
- public int getStatus();\r
-\r
- /**\r
- * Get the validity status.\r
- *\r
- * @return true if item is valid, false if not\r
- */\r
- public boolean isValid();\r
-\r
- /**\r
- * Get a counter representing the modification count of the item.\r
- * <p>\r
- * Any consumer of the item may look at this value and store it at one\r
- * point in time and then later look at the value again. If the \r
- * value has increased, then the consumer can know that the item has \r
- * been modified in some way and can then take the appropriate action.\r
- * If the count has not changed from one point in time to another, \r
- * then the item is guarenteed to not have changed in any way.\r
- *\r
- * NOTE: this value is not guaranteed to start at 0;\r
- *\r
- * @return the alter count\r
- */\r
- public int getAlterCount();\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * John Bandhauer\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-// DEBUG API class\r
-\r
-package org.mozilla.javascript;\r
-\r
-import java.util.Enumeration;\r
-\r
-/**\r
- * This interface supports managing incrementally updated source text.\r
- *\r
- * @see org.mozilla.javascript.SourceTextItem\r
- * @see org.mozilla.javascript.Context#setSourceTextManager\r
- * @author John Bandhauer\r
- */\r
-\r
-public interface SourceTextManager\r
-{\r
- /**\r
- * Create a new item.\r
- * <p>\r
- * A new item is always created. If an item with this name already exists, \r
- * then that preexisting iten is is set as invalid. \r
- *\r
- * @param name item name - in most embedings this will be a URL or filename\r
- * @return new item\r
- */\r
- public SourceTextItem newItem(String name);\r
-\r
- /**\r
- * Get an existing item.\r
- * <p>\r
- * If an item with this name already exists, then return it. Otherwise, \r
- * return null.\r
- *\r
- * @param name item name - in most embedings this will be a URL or filename\r
- * @return existing item (or null if none)\r
- */\r
- public SourceTextItem getItem(String name);\r
-\r
- /**\r
- * Get all items.\r
- * <p>\r
- * Takes a snapshot of the list of all items and returns an Enumeration.\r
- *\r
- * @return snapshot Enumeration of all items\r
- */\r
- public Enumeration getAllItems();\r
-} \r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- * The contents of this file are subject to the Mozilla Public License\r
- * Version 1.1 (the "License"); you may not use this file except in\r
- * compliance with the License. You may obtain a copy of the License at\r
- * http://www.mozilla.org/MPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS IS"\r
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
- * License for the specific language governing rights and limitations\r
- * under the License.\r
- *\r
- * The Original Code is Synchronizer.java code, released Sep 27, 2000.\r
- *\r
- * The Initial Developer of the Original Code is Matthias Radestock\r
- * <matthias@sorted.org>. Portions created by Matthias Radestock are\r
- * Copyright (C) 2000 Matthias Radestock. All Rights Reserved.\r
- *\r
- * Contributor(s):\r
- * Redfig Ltd (http://www.redfig.com)\r
- * LShift Ltd (http://www.lshift.net)\r
- *\r
- * Alternatively, the contents of this file may be used under the terms\r
- * of the GNU Public License (the "GPL License"), in which case the\r
- * provisions of the GPL License are applicable instead of those\r
- * above. If you wish to allow use of your version of this file only\r
- * under the terms of the GPL License and not to allow others to use\r
- * your version of this file under the MPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice and\r
- * other provisions required by the GPL License. If you do not delete\r
- * the provisions above, a recipient may use your version of this file\r
- * under either the MPL or the GPL License.\r
- */\r
-\r
-// API class\r
-\r
-package org.mozilla.javascript;\r
-\r
-/**\r
- * This class provides support for implementing Java-style synchronized\r
- * methods in Javascript.\r
- *\r
- * Synchronized functions are created from ordinary Javascript\r
- * functions by the <code>Synchronizer</code> constructor, e.g.\r
- * <code>new Packages.org.mozilla.javascript.Synchronizer(fun)</code>.\r
- * The resulting object is a function that establishes an exclusive\r
- * lock on the <code>this</code> object of its invocation.\r
- *\r
- * The Rhino shell provides a short-cut for the creation of\r
- * synchronized methods: <code>sync(fun)</code> has the same effect as\r
- * calling the above constructor.\r
- *\r
- * @see org.mozilla.javascript.Delegator\r
- * @author Matthias Radestock\r
- */\r
-\r
-public class Synchronizer extends Delegator {\r
-\r
- /**\r
- * Create a new synchronized function from an existing one.\r
- *\r
- * @param obj the existing function\r
- */\r
- public Synchronizer(Scriptable obj) {\r
- super(obj);\r
- }\r
-\r
- /**\r
- * @see org.mozilla.javascript.Function#call\r
- */\r
- public Object call(Context cx, Scriptable scope, Scriptable thisObj,\r
- Object[] args)\r
- throws JavaScriptException {\r
- synchronized(thisObj) {\r
- return ((Function)obj).call(cx,scope,thisObj,args);\r
- }\r
- }\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Roger Lawrence\r
- * Mike McCabe\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-import java.io.*;\r
-\r
-/**\r
- * This class implements the JavaScript scanner.\r
- *\r
- * It is based on the C source files jsscan.c and jsscan.h\r
- * in the jsref package.\r
- *\r
- * @see org.mozilla.javascript.Parser\r
- *\r
- * @author Mike McCabe\r
- * @author Brendan Eich\r
- */\r
-\r
-public class TokenStream {\r
- /*\r
- * JSTokenStream flags, mirroring those in jsscan.h. These are used\r
- * by the parser to change/check the state of the scanner.\r
- */\r
-\r
- public final static int\r
- TSF_NEWLINES = 0x0001, // tokenize newlines\r
- TSF_FUNCTION = 0x0002, // scanning inside function body\r
- TSF_RETURN_EXPR = 0x0004, // function has 'return expr;'\r
- TSF_RETURN_VOID = 0x0008, // function has 'return;'\r
- TSF_REGEXP = 0x0010; // looking for a regular expression\r
-\r
- /*\r
- * For chars - because we need something out-of-range\r
- * to check. (And checking EOF by exception is annoying.)\r
- * Note distinction from EOF token type!\r
- */\r
- private final static int\r
- EOF_CHAR = -1;\r
-\r
- /**\r
- * Token types. These values correspond to JSTokenType values in\r
- * jsscan.c.\r
- */\r
-\r
- public final static int\r
- // start enum\r
- ERROR = -1, // well-known as the only code < EOF\r
- EOF = 0, // end of file token - (not EOF_CHAR)\r
- EOL = 1, // end of line\r
- // Beginning here are interpreter bytecodes. Their values\r
- // must not exceed 127.\r
- POPV = 2,\r
- ENTERWITH = 3,\r
- LEAVEWITH = 4,\r
- RETURN = 5,\r
- GOTO = 6,\r
- IFEQ = 7,\r
- IFNE = 8,\r
- DUP = 9,\r
- SETNAME = 10,\r
- BITOR = 11,\r
- BITXOR = 12,\r
- BITAND = 13,\r
- EQ = 14,\r
- NE = 15,\r
- LT = 16,\r
- LE = 17,\r
- GT = 18,\r
- GE = 19,\r
- LSH = 20,\r
- RSH = 21,\r
- URSH = 22,\r
- ADD = 23,\r
- SUB = 24,\r
- MUL = 25,\r
- DIV = 26,\r
- MOD = 27,\r
- BITNOT = 28,\r
- NEG = 29,\r
- NEW = 30,\r
- DELPROP = 31,\r
- TYPEOF = 32,\r
- NAMEINC = 33,\r
- PROPINC = 34,\r
- ELEMINC = 35,\r
- NAMEDEC = 36,\r
- PROPDEC = 37,\r
- ELEMDEC = 38,\r
- GETPROP = 39,\r
- SETPROP = 40,\r
- GETELEM = 41,\r
- SETELEM = 42,\r
- CALL = 43,\r
- NAME = 44,\r
- NUMBER = 45,\r
- STRING = 46,\r
- ZERO = 47,\r
- ONE = 48,\r
- NULL = 49,\r
- THIS = 50,\r
- FALSE = 51,\r
- TRUE = 52,\r
- SHEQ = 53, // shallow equality (===)\r
- SHNE = 54, // shallow inequality (!==)\r
- CLOSURE = 55,\r
- OBJECT = 56,\r
- POP = 57,\r
- POS = 58,\r
- VARINC = 59,\r
- VARDEC = 60,\r
- BINDNAME = 61,\r
- THROW = 62,\r
- IN = 63,\r
- INSTANCEOF = 64,\r
- GOSUB = 65,\r
- RETSUB = 66,\r
- CALLSPECIAL = 67,\r
- GETTHIS = 68,\r
- NEWTEMP = 69,\r
- USETEMP = 70,\r
- GETBASE = 71,\r
- GETVAR = 72,\r
- SETVAR = 73,\r
- UNDEFINED = 74,\r
- TRY = 75,\r
- ENDTRY = 76,\r
- NEWSCOPE = 77,\r
- TYPEOFNAME = 78,\r
- ENUMINIT = 79,\r
- ENUMNEXT = 80,\r
- GETPROTO = 81,\r
- GETPARENT = 82,\r
- SETPROTO = 83,\r
- SETPARENT = 84,\r
- SCOPE = 85,\r
- GETSCOPEPARENT = 86,\r
- THISFN = 87,\r
- JTHROW = 88,\r
- // End of interpreter bytecodes\r
- SEMI = 89, // semicolon\r
- LB = 90, // left and right brackets\r
- RB = 91,\r
- LC = 92, // left and right curlies (braces)\r
- RC = 93,\r
- LP = 94, // left and right parentheses\r
- RP = 95,\r
- COMMA = 96, // comma operator\r
- ASSIGN = 97, // assignment ops (= += -= etc.)\r
- HOOK = 98, // conditional (?:)\r
- COLON = 99,\r
- OR = 100, // logical or (||)\r
- AND = 101, // logical and (&&)\r
- EQOP = 102, // equality ops (== !=)\r
- RELOP = 103, // relational ops (< <= > >=)\r
- SHOP = 104, // shift ops (<< >> >>>)\r
- UNARYOP = 105, // unary prefix operator\r
- INC = 106, // increment/decrement (++ --)\r
- DEC = 107,\r
- DOT = 108, // member operator (.)\r
- PRIMARY = 109, // true, false, null, this\r
- FUNCTION = 110, // function keyword\r
- EXPORT = 111, // export keyword\r
- IMPORT = 112, // import keyword\r
- IF = 113, // if keyword\r
- ELSE = 114, // else keyword\r
- SWITCH = 115, // switch keyword\r
- CASE = 116, // case keyword\r
- DEFAULT = 117, // default keyword\r
- WHILE = 118, // while keyword\r
- DO = 119, // do keyword\r
- FOR = 120, // for keyword\r
- BREAK = 121, // break keyword\r
- CONTINUE = 122, // continue keyword\r
- VAR = 123, // var keyword\r
- WITH = 124, // with keyword\r
- CATCH = 125, // catch keyword\r
- FINALLY = 126, // finally keyword\r
- RESERVED = 127, // reserved keywords\r
-\r
- /** Added by Mike - these are JSOPs in the jsref, but I\r
- * don't have them yet in the java implementation...\r
- * so they go here. Also whatever I needed.\r
-\r
- * Most of these go in the 'op' field when returning\r
- * more general token types, eg. 'DIV' as the op of 'ASSIGN'.\r
- */\r
- NOP = 128, // NOP\r
- NOT = 129, // etc.\r
- PRE = 130, // for INC, DEC nodes.\r
- POST = 131,\r
-\r
- /**\r
- * For JSOPs associated with keywords...\r
- * eg. op = THIS; token = PRIMARY\r
- */\r
-\r
- VOID = 132,\r
-\r
- /* types used for the parse tree - these never get returned\r
- * by the scanner.\r
- */\r
- BLOCK = 133, // statement block\r
- ARRAYLIT = 134, // array literal\r
- OBJLIT = 135, // object literal\r
- LABEL = 136, // label\r
- TARGET = 137,\r
- LOOP = 138,\r
- ENUMDONE = 139,\r
- EXPRSTMT = 140,\r
- PARENT = 141,\r
- CONVERT = 142,\r
- JSR = 143,\r
- NEWLOCAL = 144,\r
- USELOCAL = 145,\r
- SCRIPT = 146, // top-level node for entire script\r
- \r
- /**\r
- * For the interpreted mode indicating a line number change in icodes.\r
- */\r
- LINE = 147,\r
- SOURCEFILE = 148,\r
- \r
- // For debugger\r
- \r
- BREAKPOINT = 149,\r
- ASSERT = 150; // XWT assert hack\r
- // end enum\r
-\r
-\r
- /* for mapping int token types to printable strings.\r
- * make sure to add 1 to index before using these!\r
- */\r
- private static String names[];\r
- private static void checkNames() {\r
- if (Context.printTrees && names == null) {\r
- String[] a = {\r
- "error",\r
- "eof",\r
- "eol",\r
- "popv",\r
- "enterwith",\r
- "leavewith",\r
- "return",\r
- "goto",\r
- "ifeq",\r
- "ifne",\r
- "dup",\r
- "setname",\r
- "bitor",\r
- "bitxor",\r
- "bitand",\r
- "eq",\r
- "ne",\r
- "lt",\r
- "le",\r
- "gt",\r
- "ge",\r
- "lsh",\r
- "rsh",\r
- "ursh",\r
- "add",\r
- "sub",\r
- "mul",\r
- "div",\r
- "mod",\r
- "bitnot",\r
- "neg",\r
- "new",\r
- "delprop",\r
- "typeof",\r
- "nameinc",\r
- "propinc",\r
- "eleminc",\r
- "namedec",\r
- "propdec",\r
- "elemdec",\r
- "getprop",\r
- "setprop",\r
- "getelem",\r
- "setelem",\r
- "call",\r
- "name",\r
- "number",\r
- "string",\r
- "zero",\r
- "one",\r
- "null",\r
- "this",\r
- "false",\r
- "true",\r
- "sheq",\r
- "shne",\r
- "closure",\r
- "object",\r
- "pop",\r
- "pos",\r
- "varinc",\r
- "vardec",\r
- "bindname",\r
- "throw",\r
- "in",\r
- "instanceof",\r
- "gosub",\r
- "retsub",\r
- "callspecial",\r
- "getthis",\r
- "newtemp",\r
- "usetemp",\r
- "getbase",\r
- "getvar",\r
- "setvar",\r
- "undefined",\r
- "try",\r
- "endtry",\r
- "newscope",\r
- "typeofname",\r
- "enuminit",\r
- "enumnext",\r
- "getproto",\r
- "getparent",\r
- "setproto",\r
- "setparent",\r
- "scope",\r
- "getscopeparent",\r
- "thisfn",\r
- "jthrow",\r
- "semi",\r
- "lb",\r
- "rb",\r
- "lc",\r
- "rc",\r
- "lp",\r
- "rp",\r
- "comma",\r
- "assign",\r
- "hook",\r
- "colon",\r
- "or",\r
- "and",\r
- "eqop",\r
- "relop",\r
- "shop",\r
- "unaryop",\r
- "inc",\r
- "dec",\r
- "dot",\r
- "primary",\r
- "function",\r
- "export",\r
- "import",\r
- "if",\r
- "else",\r
- "switch",\r
- "case",\r
- "default",\r
- "while",\r
- "do",\r
- "for",\r
- "break",\r
- "continue",\r
- "var",\r
- "with",\r
- "catch",\r
- "finally",\r
- "reserved",\r
- "nop",\r
- "not",\r
- "pre",\r
- "post",\r
- "void",\r
- "block",\r
- "arraylit",\r
- "objlit",\r
- "label",\r
- "target",\r
- "loop",\r
- "enumdone",\r
- "exprstmt",\r
- "parent",\r
- "convert",\r
- "jsr",\r
- "newlocal",\r
- "uselocal",\r
- "script",\r
- "line",\r
- "sourcefile",\r
- };\r
- names = a;\r
- }\r
- }\r
-\r
- /* This function uses the cached op, string and number fields in\r
- * TokenStream; if getToken has been called since the passed token\r
- * was scanned, the op or string printed may be incorrect.\r
- */\r
- public String tokenToString(int token) {\r
- if (Context.printTrees) {\r
- checkNames();\r
- if (token + 1 >= names.length)\r
- return null;\r
-\r
- if (token == UNARYOP ||\r
- token == ASSIGN ||\r
- token == PRIMARY ||\r
- token == EQOP ||\r
- token == SHOP ||\r
- token == RELOP) {\r
- return names[token + 1] + " " + names[this.op + 1];\r
- }\r
-\r
- if (token == STRING || token == OBJECT || token == NAME)\r
- return names[token + 1] + " `" + this.string + "'";\r
-\r
- if (token == NUMBER)\r
- return "NUMBER " + this.number;\r
-\r
- return names[token + 1];\r
- }\r
- return "";\r
- }\r
-\r
- public static String tokenToName(int type) {\r
- checkNames();\r
- return names == null ? "" : names[type + 1];\r
- }\r
-\r
-\r
- private int stringToKeyword(String name) {\r
-// #string_id_map#\r
-// The following assumes that EOF == 0\r
- final int \r
- Id_break = BREAK,\r
- Id_case = CASE,\r
- Id_continue = CONTINUE,\r
- Id_default = DEFAULT,\r
- Id_delete = DELPROP,\r
- Id_do = DO,\r
- Id_else = ELSE,\r
- Id_export = EXPORT,\r
- Id_false = PRIMARY | (FALSE << 8),\r
- Id_for = FOR,\r
- Id_function = FUNCTION,\r
- Id_if = IF,\r
- Id_in = RELOP | (IN << 8),\r
- Id_new = NEW,\r
- Id_null = PRIMARY | (NULL << 8),\r
- Id_return = RETURN,\r
- Id_switch = SWITCH,\r
- Id_this = PRIMARY | (THIS << 8),\r
- Id_true = PRIMARY | (TRUE << 8),\r
- Id_typeof = UNARYOP | (TYPEOF << 8),\r
- Id_var = VAR,\r
- Id_void = UNARYOP | (VOID << 8),\r
- Id_while = WHILE,\r
- Id_with = WITH,\r
-\r
- // the following are #ifdef RESERVE_JAVA_KEYWORDS in jsscan.c\r
- Id_abstract = RESERVED,\r
- Id_boolean = RESERVED,\r
- Id_byte = RESERVED,\r
- Id_catch = CATCH,\r
- Id_char = RESERVED,\r
- Id_class = RESERVED,\r
- Id_const = RESERVED,\r
- Id_debugger = RESERVED,\r
- Id_double = RESERVED,\r
- Id_enum = RESERVED,\r
- Id_extends = RESERVED,\r
- Id_final = RESERVED,\r
- Id_finally = FINALLY,\r
- Id_float = RESERVED,\r
- Id_goto = RESERVED,\r
- Id_implements = RESERVED,\r
- Id_import = IMPORT,\r
- Id_instanceof = RELOP | (INSTANCEOF << 8),\r
- Id_int = RESERVED,\r
- Id_interface = RESERVED,\r
- Id_long = RESERVED,\r
- Id_native = RESERVED,\r
- Id_package = RESERVED,\r
- Id_private = RESERVED,\r
- Id_protected = RESERVED,\r
- Id_public = RESERVED,\r
- Id_assert = ASSERT,\r
- Id_short = RESERVED,\r
- Id_static = RESERVED,\r
- Id_super = RESERVED,\r
- Id_synchronized = RESERVED,\r
- Id_throw = THROW,\r
- Id_throws = RESERVED,\r
- Id_transient = RESERVED,\r
- Id_try = TRY,\r
- Id_volatile = RESERVED;\r
- \r
- int id;\r
- String s = name;\r
-// #generated# Last update: 2001-06-01 17:45:01 CEST\r
- L0: { id = 0; String X = null; int c;\r
- L: switch (s.length()) {\r
- case 2: c=s.charAt(1);\r
- if (c=='f') { if (s.charAt(0)=='i') {id=Id_if; break L0;} }\r
- else if (c=='n') { if (s.charAt(0)=='i') {id=Id_in; break L0;} }\r
- else if (c=='o') { if (s.charAt(0)=='d') {id=Id_do; break L0;} }\r
- break L;\r
- case 3: switch (s.charAt(0)) {\r
- case 'f': if (s.charAt(2)=='r' && s.charAt(1)=='o') {id=Id_for; break L0;} break L;\r
- case 'i': if (s.charAt(2)=='t' && s.charAt(1)=='n') {id=Id_int; break L0;} break L;\r
- case 'n': if (s.charAt(2)=='w' && s.charAt(1)=='e') {id=Id_new; break L0;} break L;\r
- case 't': if (s.charAt(2)=='y' && s.charAt(1)=='r') {id=Id_try; break L0;} break L;\r
- case 'v': if (s.charAt(2)=='r' && s.charAt(1)=='a') {id=Id_var; break L0;} break L;\r
- } break L;\r
- case 4: switch (s.charAt(0)) {\r
- case 'b': X="byte";id=Id_byte; break L;\r
- case 'c': c=s.charAt(3);\r
- if (c=='e') { if (s.charAt(2)=='s' && s.charAt(1)=='a') {id=Id_case; break L0;} }\r
- else if (c=='r') { if (s.charAt(2)=='a' && s.charAt(1)=='h') {id=Id_char; break L0;} }\r
- break L;\r
- case 'e': c=s.charAt(3);\r
- if (c=='e') { if (s.charAt(2)=='s' && s.charAt(1)=='l') {id=Id_else; break L0;} }\r
- else if (c=='m') { if (s.charAt(2)=='u' && s.charAt(1)=='n') {id=Id_enum; break L0;} }\r
- break L;\r
- case 'g': X="goto";id=Id_goto; break L;\r
- case 'l': X="long";id=Id_long; break L;\r
- case 'n': X="null";id=Id_null; break L;\r
- case 't': c=s.charAt(3);\r
- if (c=='e') { if (s.charAt(2)=='u' && s.charAt(1)=='r') {id=Id_true; break L0;} }\r
- else if (c=='s') { if (s.charAt(2)=='i' && s.charAt(1)=='h') {id=Id_this; break L0;} }\r
- break L;\r
- case 'v': X="void";id=Id_void; break L;\r
- case 'w': X="with";id=Id_with; break L;\r
- } break L;\r
- case 5: switch (s.charAt(2)) {\r
- case 'a': X="class";id=Id_class; break L;\r
- case 'e': X="break";id=Id_break; break L;\r
- case 'i': X="while";id=Id_while; break L;\r
- case 'l': X="false";id=Id_false; break L;\r
- case 'n': c=s.charAt(0);\r
- if (c=='c') { X="const";id=Id_const; }\r
- else if (c=='f') { X="final";id=Id_final; }\r
- break L;\r
- case 'o': c=s.charAt(0);\r
- if (c=='f') { X="float";id=Id_float; }\r
- else if (c=='s') { X="short";id=Id_short; }\r
- break L;\r
- case 'p': X="super";id=Id_super; break L;\r
- case 'r': X="throw";id=Id_throw; break L;\r
- case 't': X="catch";id=Id_catch; break L;\r
- } break L;\r
- case 6: switch (s.charAt(1)) {\r
- case 'a': X="native";id=Id_native; break L;\r
- case 'e': c=s.charAt(0);\r
- if (c=='d') { X="delete";id=Id_delete; }\r
- else if (c=='r') { X="return";id=Id_return; }\r
- break L;\r
- case 'h': X="throws";id=Id_throws; break L;\r
- case 'm': X="import";id=Id_import; break L;\r
- case 'o': X="double";id=Id_double; break L;\r
-\r
- // commented out by Adam Megacz for XWT\r
- /*\r
- case 't': X="static";id=Id_static; break L;\r
- */\r
-\r
- case 's': X="assert";id=Id_assert; break L;\r
- case 'u': X="public";id=Id_public; break L;\r
- case 'w': X="switch";id=Id_switch; break L;\r
- case 'x': X="export";id=Id_export; break L;\r
- case 'y': X="typeof";id=Id_typeof; break L;\r
- } break L;\r
- case 7: switch (s.charAt(1)) {\r
- case 'a': X="package";id=Id_package; break L;\r
- case 'e': X="default";id=Id_default; break L;\r
- case 'i': X="finally";id=Id_finally; break L;\r
- case 'o': X="boolean";id=Id_boolean; break L;\r
- case 'r': X="private";id=Id_private; break L;\r
- case 'x': X="extends";id=Id_extends; break L;\r
- } break L;\r
- case 8: switch (s.charAt(0)) {\r
- case 'a': X="abstract";id=Id_abstract; break L;\r
- case 'c': X="continue";id=Id_continue; break L;\r
- case 'd': X="debugger";id=Id_debugger; break L;\r
- case 'f': X="function";id=Id_function; break L;\r
- case 'v': X="volatile";id=Id_volatile; break L;\r
- } break L;\r
- case 9: c=s.charAt(0);\r
- if (c=='i') { X="interface";id=Id_interface; }\r
- else if (c=='p') { X="protected";id=Id_protected; }\r
- else if (c=='t') { X="transient";id=Id_transient; }\r
- break L;\r
- case 10: c=s.charAt(1);\r
- if (c=='m') { X="implements";id=Id_implements; }\r
- else if (c=='n') { X="instanceof";id=Id_instanceof; }\r
- break L;\r
- case 12: X="synchronized";id=Id_synchronized; break L;\r
- }\r
- if (X!=null && X!=s && !X.equals(s)) id = 0;\r
- if (id == Id_const) Context.reportError("The 'const' keyword is not allowed in XWT scripts",\r
- getSourceName(), getLineno(), getLine(), getOffset());\r
- if (id == Id_instanceof) Context.reportError("The 'instanceof' keyword is not allowed in XWT scripts",\r
- getSourceName(), getLineno(), getLine(), getOffset());\r
- if (id == Id_delete) Context.reportError("The 'delete' keyword is not allowed in XWT scripts",\r
- getSourceName(), getLineno(), getLine(), getOffset());\r
-\r
- }\r
- if (id == Id_new) Context.reportError("The 'new' keyword is not allowed in XWT scripts",\r
- getSourceName(), getLineno(), getLine(), getOffset());\r
-// #/generated#\r
-// #/string_id_map#\r
- if (id == 0) { return EOF; }\r
- this.op = id >> 8;\r
- return id & 0xff;\r
- }\r
-\r
- public TokenStream(Reader in, Scriptable scope,\r
- String sourceName, int lineno)\r
- {\r
- this.in = new LineBuffer(in, lineno);\r
- this.scope = scope;\r
- this.pushbackToken = EOF;\r
- this.sourceName = sourceName;\r
- flags = 0;\r
- }\r
- \r
- public Scriptable getScope() { \r
- return scope;\r
- }\r
-\r
- /* return and pop the token from the stream if it matches...\r
- * otherwise return null\r
- */\r
- public boolean matchToken(int toMatch) throws IOException {\r
- int token = getToken();\r
- if (token == toMatch)\r
- return true;\r
-\r
- // didn't match, push back token\r
- tokenno--;\r
- this.pushbackToken = token;\r
- return false;\r
- }\r
-\r
- public void clearPushback() {\r
- this.pushbackToken = EOF;\r
- }\r
-\r
- public void ungetToken(int tt) {\r
- if (this.pushbackToken != EOF && tt != ERROR) {\r
- String message = Context.getMessage2("msg.token.replaces.pushback",\r
- tokenToString(tt), tokenToString(this.pushbackToken));\r
- throw new RuntimeException(message);\r
- }\r
- this.pushbackToken = tt;\r
- tokenno--;\r
- }\r
-\r
- public int peekToken() throws IOException {\r
- int result = getToken();\r
-\r
- this.pushbackToken = result;\r
- tokenno--;\r
- return result;\r
- }\r
-\r
- public int peekTokenSameLine() throws IOException {\r
- int result;\r
-\r
- flags |= TSF_NEWLINES; // SCAN_NEWLINES from jsscan.h\r
- result = peekToken();\r
- flags &= ~TSF_NEWLINES; // HIDE_NEWLINES from jsscan.h\r
- if (this.pushbackToken == EOL)\r
- this.pushbackToken = EOF;\r
- return result;\r
- }\r
-\r
- protected static boolean isJSIdentifier(String s) {\r
-\r
- int length = s.length();\r
-\r
- if (length == 0 || !Character.isJavaIdentifierStart(s.charAt(0)))\r
- return false;\r
-\r
- for (int i=1; i<length; i++) {\r
- char c = s.charAt(i);\r
- if (!Character.isJavaIdentifierPart(c))\r
- if (c == '\\')\r
- if (! ((i + 5) < length)\r
- && (s.charAt(i + 1) == 'u')\r
- && 0 <= xDigitToInt(s.charAt(i + 2))\r
- && 0 <= xDigitToInt(s.charAt(i + 3))\r
- && 0 <= xDigitToInt(s.charAt(i + 4))\r
- && 0 <= xDigitToInt(s.charAt(i + 5)))\r
- \r
- return false;\r
- }\r
-\r
- return true;\r
- }\r
-\r
- private static boolean isAlpha(int c) {\r
- return ((c >= 'a' && c <= 'z')\r
- || (c >= 'A' && c <= 'Z'));\r
- }\r
-\r
- static boolean isDigit(int c) {\r
- return (c >= '0' && c <= '9');\r
- }\r
-\r
- static int xDigitToInt(int c) {\r
- if ('0' <= c && c <= '9') { return c - '0'; }\r
- if ('a' <= c && c <= 'f') { return c - ('a' - 10); }\r
- if ('A' <= c && c <= 'F') { return c - ('A' - 10); }\r
- return -1;\r
- }\r
-\r
- /* As defined in ECMA. jsscan.c uses C isspace() (which allows\r
- * \v, I think.) note that code in in.read() implicitly accepts\r
- * '\r' == \u000D as well.\r
- */\r
- public static boolean isJSSpace(int c) {\r
- return (c == '\u0020' || c == '\u0009'\r
- || c == '\u000C' || c == '\u000B'\r
- || c == '\u00A0' \r
- || Character.getType((char)c) == Character.SPACE_SEPARATOR);\r
- }\r
-\r
- public static boolean isJSLineTerminator(int c) {\r
- return (c == '\n' || c == '\r'\r
- || c == 0x2028 || c == 0x2029);\r
- }\r
- \r
- public int getToken() throws IOException {\r
- int c;\r
- tokenno++;\r
-\r
- // Check for pushed-back token\r
- if (this.pushbackToken != EOF) {\r
- int result = this.pushbackToken;\r
- this.pushbackToken = EOF;\r
- return result;\r
- }\r
-\r
- // Eat whitespace, possibly sensitive to newlines.\r
- do {\r
- c = in.read();\r
- if (c == '\n')\r
- if ((flags & TSF_NEWLINES) != 0)\r
- break;\r
- } while (isJSSpace(c) || c == '\n');\r
-\r
- if (c == EOF_CHAR)\r
- return EOF;\r
-\r
- // HACK: XWT "and" as "&&" support
- if (c == 'a' || c == 'A') {
- if (in.match('n') || in.match('N')) {
- if (in.match('d') || in.match('D')) return AND;
- in.unread();
- }
- }
-
- // identifier/keyword/instanceof?\r
- // watch out for starting with a <backslash>\r
- boolean isUnicodeEscapeStart = false;\r
- if (c == '\\') {\r
- c = in.read();\r
- if (c == 'u')\r
- isUnicodeEscapeStart = true;\r
- else\r
- c = '\\';\r
- // always unread the 'u' or whatever, we need \r
- // to start the string below at the <backslash>.\r
- in.unread();\r
- }\r
- if (isUnicodeEscapeStart ||\r
- Character.isJavaIdentifierStart((char)c)) {\r
- in.startString();\r
-\r
- boolean containsEscape = isUnicodeEscapeStart; \r
- do {\r
- c = in.read();\r
- if (c == '\\') {\r
- c = in.read();\r
- containsEscape = (c == 'u');\r
- } \r
- } while (Character.isJavaIdentifierPart((char)c));\r
- in.unread();\r
-\r
- int result;\r
-\r
- String str = in.getString();\r
- // OPT we shouldn't have to make a string (object!) to\r
- // check if it's a keyword.\r
- \r
- // strictly speaking we should probably push-back\r
- // all the bad characters if the <backslash>uXXXX \r
- // sequence is malformed. But since there isn't a \r
- // correct context(is there?) for a bad Unicode \r
- // escape sequence after an identifier, we can report\r
- // an error here.\r
- if (containsEscape) {\r
- char ca[] = str.toCharArray();\r
- int L = str.length();\r
- int destination = 0;\r
- for (int i = 0; i != L;) {\r
- c = ca[i];\r
- ++i;\r
- if (c == '\\' && i != L && ca[i] == 'u') {\r
- boolean goodEscape = false;\r
- if (i + 4 < L) {\r
- int val = xDigitToInt(ca[i + 1]);\r
- if (val >= 0) {\r
- val = (val << 4) | xDigitToInt(ca[i + 2]);\r
- if (val >= 0) {\r
- val = (val << 4) | xDigitToInt(ca[i + 3]);\r
- if (val >= 0) {\r
- val = (val << 4) | xDigitToInt(ca[i + 4]);\r
- if (val >= 0) {\r
- c = (char)val;\r
- i += 5;\r
- goodEscape = true;\r
- }\r
- }\r
- }\r
- }\r
- }\r
- if (!goodEscape) {\r
- reportSyntaxError("msg.invalid.escape", null);\r
- return ERROR;\r
- }\r
- }\r
- ca[destination] = (char)c;\r
- ++destination;\r
- }\r
- str = new String(ca, 0, destination);\r
- }\r
- else\r
- // Return the corresponding token if it's a keyword\r
- if ((result = stringToKeyword(str)) != EOF) {\r
- return result;\r
- }\r
-\r
- this.string = str;\r
- return NAME;\r
- }\r
-\r
- // is it a number?\r
- if (isDigit(c) || (c == '.' && isDigit(in.peek()))) {\r
- int base = 10;\r
- in.startString();\r
-\r
- double dval = ScriptRuntime.NaN;\r
- long longval = 0;\r
- boolean isInteger = true;\r
-\r
- if (c == '0') {\r
- c = in.read();\r
- if (c == 'x' || c == 'X') {\r
- c = in.read();\r
- base = 16;\r
- // restart the string, losing leading 0x\r
- in.startString();\r
- } else if (isDigit(c)) {\r
- base = 8;\r
- }\r
- }\r
-\r
- while (0 <= xDigitToInt(c)) {\r
- if (base < 16) {\r
- if (isAlpha(c))\r
- break;\r
- /*\r
- * We permit 08 and 09 as decimal numbers, which\r
- * makes our behavior a superset of the ECMA\r
- * numeric grammar. We might not always be so\r
- * permissive, so we warn about it.\r
- */\r
- if (base == 8 && c >= '8') {\r
- Object[] errArgs = { c == '8' ? "8" : "9" };\r
- Context.reportWarning(\r
- Context.getMessage("msg.bad.octal.literal",\r
- errArgs),\r
- getSourceName(),\r
- in.getLineno(), getLine(), getOffset());\r
- base = 10;\r
- }\r
- }\r
- c = in.read();\r
- }\r
-\r
- if (base == 10 && (c == '.' || c == 'e' || c == 'E')) {\r
- isInteger = false;\r
- if (c == '.') {\r
- do {\r
- c = in.read();\r
- } while (isDigit(c));\r
- }\r
-\r
- if (c == 'e' || c == 'E') {\r
- c = in.read();\r
- if (c == '+' || c == '-') {\r
- c = in.read();\r
- }\r
- if (!isDigit(c)) {\r
- in.getString(); // throw away string in progress\r
- reportSyntaxError("msg.missing.exponent", null);\r
- return ERROR;\r
- }\r
- do {\r
- c = in.read();\r
- } while (isDigit(c));\r
- }\r
- }\r
- in.unread();\r
- String numString = in.getString();\r
-\r
- if (base == 10 && !isInteger) {\r
- try {\r
- // Use Java conversion to number from string...\r
- dval = (Double.valueOf(numString)).doubleValue();\r
- }\r
- catch (NumberFormatException ex) {\r
- Object[] errArgs = { ex.getMessage() };\r
- reportSyntaxError("msg.caught.nfe", errArgs);\r
- return ERROR;\r
- }\r
- } else {\r
- dval = ScriptRuntime.stringToNumber(numString, 0, base);\r
- longval = (long) dval;\r
-\r
- // is it an integral fits-in-a-long value?\r
- if (longval != dval)\r
- isInteger = false;\r
- }\r
-\r
- if (!isInteger) {\r
- /* Can't handle floats right now, because postfix INC/DEC\r
- generate Doubles, but I would generate a Float through this\r
- path, and it causes a stack mismatch. FIXME (MS)\r
- if (Float.MIN_VALUE <= dval && dval <= Float.MAX_VALUE)\r
- this.number = new Xloat((float) dval);\r
- else\r
- */\r
- this.number = new Double(dval);\r
- } else {\r
- // We generate the smallest possible type here\r
- if (Byte.MIN_VALUE <= longval && longval <= Byte.MAX_VALUE)\r
- this.number = new Byte((byte)longval);\r
- else if (Short.MIN_VALUE <= longval &&\r
- longval <= Short.MAX_VALUE)\r
- this.number = new Short((short)longval);\r
- else if (Integer.MIN_VALUE <= longval &&\r
- longval <= Integer.MAX_VALUE)\r
- this.number = new Integer((int)longval);\r
- else {\r
- // May lose some precision here, but that's the \r
- // appropriate semantics.\r
- this.number = new Double(longval);\r
- }\r
- }\r
- return NUMBER;\r
- }\r
-\r
- // is it a string?\r
- if (c == '"' || c == '\'') {\r
- // We attempt to accumulate a string the fast way, by\r
- // building it directly out of the reader. But if there\r
- // are any escaped characters in the string, we revert to\r
- // building it out of a StringBuffer.\r
-\r
- StringBuffer stringBuf = null;\r
-\r
- int quoteChar = c;\r
- int val = 0;\r
-\r
- c = in.read();\r
- in.startString(); // start after the first "\r
- while(c != quoteChar) {\r
- if (c == '\n' || c == EOF_CHAR) {\r
- in.unread();\r
- in.getString(); // throw away the string in progress\r
- reportSyntaxError("msg.unterminated.string.lit", null);\r
- return ERROR;\r
- }\r
-\r
- if (c == '\\') {\r
- // We've hit an escaped character; revert to the\r
- // slow method of building a string.\r
- if (stringBuf == null) {\r
- // Don't include the backslash\r
- in.unread();\r
- stringBuf = new StringBuffer(in.getString());\r
- in.read();\r
- }\r
-\r
- switch (c = in.read()) {\r
- case 'b': c = '\b'; break;\r
- case 'f': c = '\f'; break;\r
- case 'n': c = '\n'; break;\r
- case 'r': c = '\r'; break;\r
- case 't': c = '\t'; break;\r
- case 'v': c = '\u000B'; break;\r
- // \v a late addition to the ECMA spec.\r
- // '\v' doesn't seem to be valid Java.\r
-\r
- default:\r
- if (isDigit(c) && c < '8') {\r
- val = c - '0';\r
- c = in.read();\r
- if (isDigit(c) && c < '8') {\r
- val = 8 * val + c - '0';\r
- c = in.read();\r
- if (isDigit(c) && c < '8') {\r
- val = 8 * val + c - '0';\r
- c = in.read();\r
- }\r
- }\r
- in.unread();\r
- if (val > 0377) {\r
- reportSyntaxError("msg.oct.esc.too.large", null);\r
- return ERROR;\r
- }\r
- c = val;\r
- } else if (c == 'u') {\r
- /*\r
- * Get 4 hex digits; if the u escape is not\r
- * followed by 4 hex digits, use 'u' + the literal\r
- * character sequence that follows. Do some manual\r
- * match (OK because we're in a string) to avoid\r
- * multi-char match on the underlying stream.\r
- */\r
- int c1 = in.read();\r
- c = xDigitToInt(c1);\r
- if (c < 0) {\r
- in.unread();\r
- c = 'u';\r
- } else {\r
- int c2 = in.read();\r
- c = (c << 4) | xDigitToInt(c2);\r
- if (c < 0) {\r
- in.unread();\r
- stringBuf.append('u');\r
- c = c1;\r
- } else {\r
- int c3 = in.read();\r
- c = (c << 4) | xDigitToInt(c3);\r
- if (c < 0) {\r
- in.unread();\r
- stringBuf.append('u');\r
- stringBuf.append((char)c1);\r
- c = c2;\r
- } else {\r
- int c4 = in.read();\r
- c = (c << 4) | xDigitToInt(c4);\r
- if (c < 0) {\r
- in.unread();\r
- stringBuf.append('u');\r
- stringBuf.append((char)c1);\r
- stringBuf.append((char)c2);\r
- c = c3;\r
- } else {\r
- // got 4 hex digits! Woo Hoo!\r
- }\r
- }\r
- }\r
- }\r
- } else if (c == 'x') {\r
- /* Get 2 hex digits, defaulting to 'x' + literal\r
- * sequence, as above.\r
- */\r
- int c1 = in.read();\r
- c = xDigitToInt(c1);\r
- if (c < 0) {\r
- in.unread();\r
- c = 'x';\r
- } else {\r
- int c2 = in.read();\r
- c = (c << 4) | xDigitToInt(c2);\r
- if (c < 0) {\r
- in.unread();\r
- stringBuf.append('x');\r
- c = c1;\r
- } else {\r
- // got 2 hex digits\r
- }\r
- }\r
- }\r
- }\r
- }\r
- \r
- if (stringBuf != null)\r
- stringBuf.append((char) c);\r
- c = in.read();\r
- }\r
-\r
- if (stringBuf != null)\r
- this.string = stringBuf.toString();\r
- else {\r
- in.unread(); // miss the trailing "\r
- this.string = in.getString();\r
- in.read();\r
- }\r
- return STRING;\r
- }\r
-\r
- switch (c)\r
- {\r
- case '\n': return EOL;\r
- case ';': return SEMI;\r
- case '[': return LB;\r
- case ']': return RB;\r
- case '{': return LC;\r
- case '}': return RC;\r
- case '(': return LP;\r
- case ')': return RP;\r
- case ',': return COMMA;\r
- case '?': return HOOK;\r
- case ':': return COLON;\r
- case '.': return DOT;\r
-\r
- case '|':\r
- if (in.match('|')) {\r
- return OR;\r
- } else if (in.match('=')) {\r
- this.op = BITOR;\r
- return ASSIGN;\r
- } else {\r
- return BITOR;\r
- }\r
-\r
- case '^':\r
- if (in.match('=')) {\r
- this.op = BITXOR;\r
- return ASSIGN;\r
- } else {\r
- return BITXOR;\r
- }\r
-\r
- case '&':\r
- if (in.match('&')) {\r
- return AND;\r
- } else if (in.match('=')) {\r
- this.op = BITAND;\r
- return ASSIGN;\r
- } else {\r
- return BITAND;\r
- }\r
-\r
- case '=':\r
- if (in.match('=')) {\r
- if (in.match('='))\r
- this.op = SHEQ;\r
- else\r
- this.op = EQ;\r
- return EQOP;\r
- } else {\r
- this.op = NOP;\r
- return ASSIGN;\r
- }\r
-\r
- case '!':\r
- if (in.match('=')) {\r
- if (in.match('='))\r
- this.op = SHNE;\r
- else\r
- this.op = NE;\r
- return EQOP;\r
- } else {\r
- this.op = NOT;\r
- return UNARYOP;\r
- }\r
-\r
- case '<':\r
- /* NB:treat HTML begin-comment as comment-till-eol */\r
- if (in.match('!')) {\r
- if (in.match('-')) {\r
- if (in.match('-')) {\r
- while ((c = in.read()) != EOF_CHAR && c != '\n')\r
- /* skip to end of line */;\r
- in.unread();\r
- return getToken(); // in place of 'goto retry'\r
- }\r
- in.unread();\r
- }\r
- in.unread();\r
- }\r
- if (in.match('<')) {\r
- if (in.match('=')) {\r
- this.op = LSH;\r
- return ASSIGN;\r
- } else {\r
- this.op = LSH;\r
- return SHOP;\r
- }\r
- } else {\r
- if (in.match('=')) {\r
- this.op = LE;\r
- return RELOP;\r
- } else {\r
- this.op = LT;\r
- return RELOP;\r
- }\r
- }\r
-\r
- case '>':\r
- if (in.match('>')) {\r
- if (in.match('>')) {\r
- if (in.match('=')) {\r
- this.op = URSH;\r
- return ASSIGN;\r
- } else {\r
- this.op = URSH;\r
- return SHOP;\r
- }\r
- } else {\r
- if (in.match('=')) {\r
- this.op = RSH;\r
- return ASSIGN;\r
- } else {\r
- this.op = RSH;\r
- return SHOP;\r
- }\r
- }\r
- } else {\r
- if (in.match('=')) {\r
- this.op = GE;\r
- return RELOP;\r
- } else {\r
- this.op = GT;\r
- return RELOP;\r
- }\r
- }\r
-\r
- case '*':\r
- if (in.match('=')) {\r
- this.op = MUL;\r
- return ASSIGN;\r
- } else {\r
- return MUL;\r
- }\r
-\r
- case '/':\r
- // is it a // comment?\r
- if (in.match('/')) {\r
- while ((c = in.read()) != EOF_CHAR && c != '\n')\r
- /* skip to end of line */;\r
- in.unread();\r
- return getToken();\r
- }\r
- if (in.match('*')) {\r
- while ((c = in.read()) != -1\r
- && !(c == '*' && in.match('/'))) {\r
- if (c == '\n') {\r
- } else if (c == '/' && in.match('*')) {\r
- if (in.match('/'))\r
- return getToken();\r
- reportSyntaxError("msg.nested.comment", null);\r
- return ERROR;\r
- }\r
- }\r
- if (c == EOF_CHAR) {\r
- reportSyntaxError("msg.unterminated.comment", null);\r
- return ERROR;\r
- }\r
- return getToken(); // `goto retry'\r
- }\r
-\r
- // is it a regexp?\r
- if ((flags & TSF_REGEXP) != 0) {\r
- // We don't try to use the in.startString/in.getString\r
- // approach, because escaped characters (which break it)\r
- // seem likely to be common.\r
- StringBuffer re = new StringBuffer();\r
- while ((c = in.read()) != '/') {\r
- if (c == '\n' || c == EOF_CHAR) {\r
- in.unread();\r
- reportSyntaxError("msg.unterminated.re.lit", null);\r
- return ERROR;\r
- }\r
- if (c == '\\') {\r
- re.append((char) c);\r
- c = in.read();\r
- }\r
-\r
- re.append((char) c);\r
- }\r
-\r
- StringBuffer flagsBuf = new StringBuffer();\r
- while (true) {\r
- if (in.match('g'))\r
- flagsBuf.append('g');\r
- else if (in.match('i'))\r
- flagsBuf.append('i');\r
- else if (in.match('m'))\r
- flagsBuf.append('m');\r
- else\r
- break;\r
- }\r
-\r
- if (isAlpha(in.peek())) {\r
- reportSyntaxError("msg.invalid.re.flag", null);\r
- return ERROR;\r
- }\r
-\r
- this.string = re.toString();\r
- this.regExpFlags = flagsBuf.toString();\r
- return OBJECT;\r
- }\r
-\r
-\r
- if (in.match('=')) {\r
- this.op = DIV;\r
- return ASSIGN;\r
- } else {\r
- return DIV;\r
- }\r
-\r
- case '%':\r
- this.op = MOD;\r
- if (in.match('=')) {\r
- return ASSIGN;\r
- } else {\r
- return MOD;\r
- }\r
-\r
- case '~':\r
- this.op = BITNOT;\r
- return UNARYOP;\r
-\r
- case '+':\r
- case '-':\r
- if (in.match('=')) {\r
- if (c == '+') {\r
- this.op = ADD;\r
- return ASSIGN;\r
- } else {\r
- this.op = SUB;\r
- return ASSIGN;\r
- }\r
- } else if (in.match((char) c)) {\r
- if (c == '+') {\r
- return INC;\r
- } else {\r
- return DEC;\r
- }\r
- } else if (c == '-') {\r
- return SUB;\r
- } else {\r
- return ADD;\r
- }\r
-\r
- default:\r
- reportSyntaxError("msg.illegal.character", null);\r
- return ERROR;\r
- }\r
- }\r
-\r
- public void reportSyntaxError(String messageProperty, Object[] args) {\r
- String message = Context.getMessage(messageProperty, args);\r
- if (scope != null) {\r
- // We're probably in an eval. Need to throw an exception.\r
- throw NativeGlobal.constructError(\r
- Context.getContext(), "SyntaxError",\r
- message, scope, getSourceName(),\r
- getLineno(), getOffset(), getLine());\r
- } else {\r
- Context.reportError(message, getSourceName(),\r
- getLineno(), getLine(), getOffset());\r
- }\r
- }\r
-\r
- public String getSourceName() { return sourceName; }\r
- public int getLineno() { return in.getLineno(); }\r
- public int getOp() { return op; }\r
- public String getString() { return string; }\r
- public Number getNumber() { return number; }\r
- public String getLine() { return in.getLine(); }\r
- public int getOffset() { return in.getOffset(); }\r
- public int getTokenno() { return tokenno; }\r
- public boolean eof() { return in.eof(); }\r
-\r
- // instance variables\r
- private LineBuffer in;\r
-\r
-\r
- /* for TSF_REGEXP, etc.\r
- * should this be manipulated by gettor/settor functions?\r
- * should it be passed to getToken();\r
- */\r
- public int flags;\r
- public String regExpFlags;\r
-\r
- private String sourceName;\r
- private String line;\r
- private Scriptable scope;\r
- private int pushbackToken;\r
- private int tokenno;\r
-\r
- private int op;\r
-\r
- // Set this to an inital non-null value so that the Parser has\r
- // something to retrieve even if an error has occured and no\r
- // string is found. Fosters one class of error, but saves lots of\r
- // code.\r
- private String string = "";\r
- private Number number;\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-2000 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s):\r
- * Igor Bukanov\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-/**\r
- * Map to associate non-negative integers to objects or integers.\r
- * The map does not synchronize any of its operation, so either use\r
- * it from a single thread or do own synchronization or perform all mutation\r
- * operations on one thread before passing the map to others\r
- *\r
- * @author Igor Bukanov\r
- *\r
- */\r
-\r
-class UintMap {\r
-\r
-// Map implementation via hashtable,\r
-// follows "The Art of Computer Programming" by Donald E. Knuth\r
-\r
- public UintMap() {\r
- this(4);\r
- }\r
-\r
- public UintMap(int initialCapacity) {\r
- if (checkWorld) check(initialCapacity >= 0);\r
- // Table grow when number of stored keys >= 3/4 of max capacity\r
- int minimalCapacity = initialCapacity * 4 / 3;\r
- int i;\r
- for (i = 2; (1 << i) < minimalCapacity; ++i) { }\r
- minimalPower = i;\r
- if (checkSelf) check(minimalPower >= 2);\r
- }\r
-\r
- public boolean isEmpty() {\r
- return keyCount == 0;\r
- }\r
-\r
- public int size() {\r
- return keyCount;\r
- }\r
-\r
- public boolean has(int key) {\r
- if (checkWorld) check(key >= 0);\r
- return 0 <= findIndex(key);\r
- }\r
-\r
- public boolean isObjectType(int key) {\r
- if (checkWorld) check(key >= 0);\r
- int index = findIndex(key);\r
- return index >= 0 && isObjectTypeValue(index);\r
- }\r
-\r
- public boolean isIntType(int key) {\r
- if (checkWorld) check(key >= 0);\r
- int index = findIndex(key);\r
- return index >= 0 && !isObjectTypeValue(index);\r
- }\r
-\r
- /**\r
- * Get object value assigned with key.\r
- * @return key object value or null if key is absent or does\r
- * not have object value\r
- */\r
- public Object getObject(int key) {\r
- if (checkWorld) check(key >= 0);\r
- if (values != null) {\r
- int index = findIndex(key);\r
- if (0 <= index) {\r
- return values[index];\r
- }\r
- }\r
- return null;\r
- }\r
-\r
- /**\r
- * Get integer value assigned with key.\r
- * @return key integer value or defaultValue if key is absent or does\r
- * not have int value\r
- */\r
- public int getInt(int key, int defaultValue) {\r
- if (checkWorld) check(key >= 0);\r
- if (ivaluesShift != 0) {\r
- int index = findIndex(key);\r
- if (0 <= index) {\r
- if (!isObjectTypeValue(index)) {\r
- return keys[ivaluesShift + index];\r
- }\r
- }\r
- }\r
- return defaultValue;\r
- }\r
-\r
- /**\r
- * Get integer value assigned with key.\r
- * @return key integer value or defaultValue if key does not exist or does\r
- * not have int value\r
- * @throws RuntimeException if key does not exist or does\r
- * not have int value\r
- */\r
- public int getExistingInt(int key) {\r
- if (checkWorld) check(key >= 0);\r
- if (ivaluesShift != 0) {\r
- int index = findIndex(key);\r
- if (0 <= index) {\r
- if (!isObjectTypeValue(index)) {\r
- return keys[ivaluesShift + index];\r
- }\r
- }\r
- }\r
- // Key must exist\r
- if (checkWorld) check(false);\r
- return 0;\r
- }\r
-\r
- public void put(int key, Object value) {\r
- if (checkWorld) check(key >= 0 && value != null);\r
- int index = ensureIndex(key, false);\r
- if (values == null) {\r
- values = new Object[1 << power];\r
- }\r
- values[index] = value;\r
- }\r
-\r
- public void put(int key, int value) {\r
- if (checkWorld) check(key >= 0);\r
- int index = ensureIndex(key, true);\r
- if (ivaluesShift == 0) {\r
- int N = 1 << power;\r
- int[] tmp = new int[N * 2];\r
- System.arraycopy(keys, 0, tmp, 0, N);\r
- keys = tmp;\r
- ivaluesShift = N;\r
- }\r
- keys[ivaluesShift + index] = value;\r
- if (values != null) { values[index] = null; }\r
- }\r
-\r
- public void remove(int key) {\r
- if (checkWorld) check(key >= 0);\r
- int index = findIndex(key);\r
- if (0 <= index) {\r
- keys[index] = DELETED;\r
- --keyCount;\r
- if (values != null) { values[index] = null; }\r
- }\r
- }\r
-\r
- public void clear() {\r
- power = 0;\r
- keys = null;\r
- values = null;\r
- ivaluesShift = 0;\r
- keyCount = 0;\r
- occupiedCount = 0;\r
- }\r
-\r
- /** Return array of present keys */\r
- public int[] getKeys() {\r
- int[] keys = this.keys;\r
- int n = keyCount;\r
- int[] result = new int[n];\r
- for (int i = 0; n != 0; ++i) {\r
- int entry = keys[i];\r
- if (entry != EMPTY && entry != DELETED) {\r
- result[--n] = entry;\r
- }\r
- }\r
- return result;\r
- }\r
-\r
- private static int tableLookupStep(int fraction, int mask, int power) {\r
- int shift = 32 - 2 * power;\r
- if (shift >= 0) {\r
- return ((fraction >>> shift) & mask) | 1;\r
- }\r
- else {\r
- return (fraction & (mask >>> -shift)) | 1;\r
- }\r
- }\r
-\r
- private int findIndex(int key) {\r
- int[] keys = this.keys;\r
- if (keys != null) {\r
- int fraction = key * A;\r
- int index = fraction >>> (32 - power);\r
- int entry = keys[index];\r
- if (entry == key) { return index; }\r
- if (entry != EMPTY) {\r
- // Search in table after first failed attempt\r
- int mask = (1 << power) - 1;\r
- int step = tableLookupStep(fraction, mask, power);\r
- int n = 0;\r
- do {\r
- if (checkSelf) check(n++ < occupiedCount);\r
- index = (index + step) & mask;\r
- entry = keys[index];\r
- if (entry == key) { return index; }\r
- } while (entry != EMPTY);\r
- }\r
- }\r
- return -1;\r
- }\r
-\r
- private int getFreeIndex(int key) {\r
- int[] keys = this.keys;\r
- int fraction = key * A;\r
- int index = fraction >>> (32 - power);\r
- if (keys[index] != EMPTY) {\r
- int mask = (1 << power) - 1;\r
- int step = tableLookupStep(fraction, mask, power);\r
- int firstIndex = index;\r
- do {\r
- if (checkSelf) check(keys[index] != DELETED);\r
- index = (index + step) & mask;\r
- if (checkSelf) check(firstIndex != index);\r
- } while (keys[index] != EMPTY);\r
- }\r
- return index;\r
- }\r
-\r
- private void rehashTable(boolean ensureIntSpace) {\r
- if (keys == null) { power = minimalPower; }\r
- else {\r
- // Check if removing deleted entries would free enough space\r
- if (keyCount * 2 >= occupiedCount) {\r
- // Need to grow: less then half of deleted entries\r
- ++power;\r
- }\r
- }\r
- int N = 1 << power;\r
- int[] old = keys;\r
- int oldShift = ivaluesShift;\r
- if (oldShift == 0 && !ensureIntSpace) {\r
- keys = new int[N];\r
- }\r
- else {\r
- ivaluesShift = N; keys = new int[N * 2];\r
- }\r
- for (int i = 0; i != N; ++i) { keys[i] = EMPTY; }\r
-\r
- Object[] oldValues = values;\r
- if (oldValues != null) { values = new Object[N]; }\r
-\r
- if (old != null) {\r
- for (int i = 0, remaining = keyCount; remaining != 0; ++i) {\r
- int entry = old[i];\r
- if (entry != EMPTY && entry != DELETED) {\r
- int index = getFreeIndex(entry);\r
- keys[index] = entry;\r
- if (oldValues != null) {\r
- values[index] = oldValues[i];\r
- }\r
- if (oldShift != 0) {\r
- keys[ivaluesShift + index] = old[oldShift + i];\r
- }\r
- --remaining;\r
- }\r
- }\r
- }\r
- occupiedCount = keyCount;\r
- }\r
-\r
-// Ensure key index creating one if necessary\r
- private int ensureIndex(int key, boolean intType) {\r
- int index = -1;\r
- int firstDeleted = -1;\r
- int[] keys = this.keys;\r
- if (keys != null) {\r
- int fraction = key * A;\r
- index = fraction >>> (32 - power);\r
- int entry = keys[index];\r
- if (entry == key) { return index; }\r
- if (entry != EMPTY) {\r
- if (entry == DELETED) { firstDeleted = index; }\r
- // Search in table after first failed attempt\r
- int mask = (1 << power) - 1;\r
- int step = tableLookupStep(fraction, mask, power);\r
- int n = 0;\r
- do {\r
- if (checkSelf) check(n++ < occupiedCount);\r
- index = (index + step) & mask;\r
- entry = keys[index];\r
- if (entry == key) { return index; }\r
- if (entry == DELETED && firstDeleted < 0) {\r
- firstDeleted = index;\r
- }\r
- } while (entry != EMPTY);\r
- }\r
- }\r
- // Inserting of new key\r
- if (checkSelf) check(keys == null || keys[index] == EMPTY);\r
- if (firstDeleted >= 0) {\r
- index = firstDeleted;\r
- }\r
- else {\r
- // Need to consume empty entry: check occupation level\r
- if (keys == null || occupiedCount * 4 >= (1 << power) * 3) {\r
- // Too litle unused entries: rehash\r
- rehashTable(intType);\r
- keys = this.keys;\r
- index = getFreeIndex(key);\r
- }\r
- ++occupiedCount;\r
- }\r
- keys[index] = key;\r
- ++keyCount;\r
- return index;\r
- }\r
-\r
- private boolean isObjectTypeValue(int index) {\r
- if (checkSelf) check(index >= 0 && index < (1 << power));\r
- return values != null && values[index] != null;\r
- }\r
-\r
- private static void check(boolean condition) {\r
- if (!condition) { throw new RuntimeException(); }\r
- }\r
-\r
-// Rudimentary support for Design-by-Contract\r
- private static final boolean checkWorld = true;\r
- private static final boolean checkSelf = checkWorld && false;\r
-\r
-// A == golden_ratio * (1 << 32) = ((sqrt(5) - 1) / 2) * (1 << 32)\r
-// See Knuth etc.\r
- private static final int A = 0x9e3779b9;\r
-\r
- private static final int EMPTY = -1;\r
- private static final int DELETED = -2;\r
-\r
-// Structure of kyes and values arrays (N == 1 << power):\r
-// keys[0 <= i < N]: key value or EMPTY or DELETED mark\r
-// values[0 <= i < N]: value of key at keys[i]\r
-// keys[N <= i < 2N]: int values of keys at keys[i - N]\r
-\r
- private int[] keys;\r
- private Object[] values;\r
-\r
- private int minimalPower;\r
- private int power;\r
- private int keyCount;\r
- private int occupiedCount; // == keyCount + deleted_count\r
-\r
- // If ivaluesShift != 0, keys[ivaluesShift + index] contains integer\r
- // values associated with keys\r
- private int ivaluesShift;\r
-\r
-/*\r
- public static void main(String[] args) {\r
- UintMap map;\r
- map = new UintMap();\r
- testHash(map, 10 * 1000);\r
- map = new UintMap(30 * 1000);\r
- testHash(map, 10 * 100);\r
- map.clear();\r
- testHash(map, 4);\r
- map = new UintMap(0);\r
- testHash(map, 10 * 100);\r
- }\r
-\r
- private static void testHash(UintMap map, int N) {\r
- System.out.print("."); System.out.flush();\r
- for (int i = 0; i != N; ++i) {\r
- map.put(i, i);\r
- check(i == map.getInt(i, -1));\r
- }\r
-\r
- System.out.print("."); System.out.flush();\r
- for (int i = 0; i != N; ++i) {\r
- map.put(i, i);\r
- check(i == map.getInt(i, -1));\r
- }\r
-\r
- System.out.print("."); System.out.flush();\r
- for (int i = 0; i != N; ++i) {\r
- map.put(i, new Integer(i));\r
- check(-1 == map.getInt(i, -1));\r
- Integer obj = (Integer)map.getObject(i);\r
- check(obj != null && i == obj.intValue());\r
- }\r
-\r
- check(map.size() == N);\r
-\r
- System.out.print("."); System.out.flush();\r
- int[] keys = map.getKeys();\r
- check(keys.length == N);\r
- for (int i = 0; i != N; ++i) {\r
- int key = keys[i];\r
- check(map.has(key));\r
- check(!map.isIntType(key));\r
- check(map.isObjectType(key));\r
- Integer obj = (Integer) map.getObject(key);\r
- check(obj != null && key == obj.intValue());\r
- }\r
-\r
-\r
- System.out.print("."); System.out.flush();\r
- for (int i = 0; i != N; ++i) {\r
- check(-1 == map.getInt(i, -1));\r
- }\r
-\r
- System.out.print("."); System.out.flush();\r
- for (int i = 0; i != N; ++i) {\r
- map.put(i * i, i);\r
- check(i == map.getInt(i * i, -1));\r
- }\r
-\r
- System.out.print("."); System.out.flush();\r
- for (int i = 0; i != N; ++i) {\r
- check(i == map.getInt(i * i, -1));\r
- }\r
-\r
- System.out.print("."); System.out.flush();\r
- for (int i = 0; i != N; ++i) {\r
- map.put(i * i, new Integer(i));\r
- check(-1 == map.getInt(i * i, -1));\r
- map.remove(i * i);\r
- check(!map.has(i * i));\r
- map.put(i * i, i);\r
- check(map.isIntType(i * i));\r
- check(null == map.getObject(i * i));\r
- map.remove(i * i);\r
- check(!map.isObjectType(i * i));\r
- check(!map.isIntType(i * i));\r
- }\r
-\r
- int old_size = map.size();\r
- for (int i = 0; i != N; ++i) {\r
- map.remove(i * i);\r
- check(map.size() == old_size);\r
- }\r
-\r
- System.out.println(); System.out.flush();\r
- }\r
-//*/\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-/**\r
- * This class implements the Undefined value in JavaScript.\r
- */\r
-public class Undefined implements Scriptable {\r
-\r
- static final public Scriptable instance = new Undefined();\r
-\r
- public String getClassName() {\r
- return "undefined";\r
- }\r
-\r
- public boolean has(String id, Scriptable start) {\r
- return false;\r
- }\r
-\r
- public boolean has(int index, Scriptable start) {\r
- return false;\r
- }\r
-\r
- public Object get(String id, Scriptable start) {\r
- throw reportError();\r
- }\r
-\r
- public Object get(int index, Scriptable start) {\r
- throw reportError();\r
- }\r
-\r
- public void put(String id,Scriptable start, Object value) {\r
- throw reportError();\r
- }\r
-\r
- public void put(int index, Scriptable start, Object value) {\r
- throw reportError();\r
- }\r
-\r
- public void delete(String id) {\r
- throw reportError();\r
- }\r
-\r
- public void delete(int index) {\r
- throw reportError();\r
- }\r
-\r
- public short getAttributes(String id, Scriptable start) {\r
- throw reportError();\r
- }\r
-\r
- public short getAttributes(int index, Scriptable start) {\r
- throw reportError();\r
- }\r
-\r
- public void setAttributes(String id, Scriptable start, short attributes) {\r
- throw reportError();\r
- }\r
-\r
- public void setAttributes(int index, Scriptable start, short attributes) {\r
- throw reportError();\r
- }\r
-\r
- public Scriptable getPrototype() {\r
- throw reportError();\r
- }\r
-\r
- public void setPrototype(Scriptable prototype) {\r
- throw reportError();\r
- }\r
-\r
- public Scriptable getParentScope() {\r
- throw reportError();\r
- }\r
-\r
- public void setParentScope(Scriptable parent) {\r
- throw reportError();\r
- }\r
-\r
- public Object[] getIds() {\r
- throw reportError();\r
- }\r
-\r
- public Object getDefaultValue(Class cl) {\r
- if (cl == ScriptRuntime.StringClass)\r
- return "undefined";\r
- if (cl == ScriptRuntime.NumberClass)\r
- return ScriptRuntime.NaNobj;\r
- if (cl == ScriptRuntime.BooleanClass)\r
- return Boolean.FALSE;\r
- return this;\r
- }\r
-\r
- public boolean hasInstance(Scriptable value) {\r
- throw reportError();\r
- }\r
-\r
- public boolean instanceOf(Scriptable prototype) {\r
- return false;\r
- }\r
-\r
- private RuntimeException reportError() {\r
- return Context.reportRuntimeError0("msg.undefined");\r
- }\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Roger Lawrence\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-import java.io.*;\r
-import java.util.*;\r
-\r
-public class VariableTable {\r
-\r
- public int size() {\r
- return itsVariables.size();\r
- }\r
-\r
- public int getParameterCount(){\r
- return varStart;\r
- }\r
- \r
- public LocalVariable createLocalVariable(String name, boolean isParameter) \r
- {\r
- return new LocalVariable(name, isParameter);\r
- }\r
-\r
- public LocalVariable getVariable(int index) {\r
- return (LocalVariable)(itsVariables.elementAt(index));\r
- }\r
-\r
- public LocalVariable getVariable(String name) {\r
- Integer vIndex = (Integer)(itsVariableNames.get(name));\r
- if (vIndex != null)\r
- return (LocalVariable)(itsVariables.elementAt(vIndex.intValue()));\r
- else\r
- return null;\r
- }\r
-\r
- public int getOrdinal(String name) {\r
- Integer vIndex = (Integer)(itsVariableNames.get(name));\r
- if (vIndex != null)\r
- return vIndex.intValue();\r
- else\r
- return -1;\r
- }\r
-\r
- public String getName(int index) {\r
- return ((LocalVariable)(itsVariables.elementAt(index))).getName();\r
- }\r
-\r
- public String[] getAllNames() { \r
- int N = size();\r
- String[] result = null;\r
- if (N != 0) {\r
- result = new String[N];\r
- for (int i = 0; i != N; i++) {\r
- result[i] = getName(i);\r
- }\r
- }\r
- return result;\r
- }\r
-\r
- public void establishIndices() {\r
- for (int i = 0; i < itsVariables.size(); i++) {\r
- LocalVariable lVar = (LocalVariable)(itsVariables.elementAt(i));\r
- lVar.setIndex(i);\r
- }\r
- }\r
-\r
- public void addParameter(String pName) {\r
- Integer pIndex = (Integer)(itsVariableNames.get(pName));\r
- if (pIndex != null) {\r
- LocalVariable p = (LocalVariable)\r
- (itsVariables.elementAt(pIndex.intValue()));\r
- if (p.isParameter()) {\r
- String message = Context.getMessage1("msg.dup.parms", pName);\r
- Context.reportWarning(message, null, 0, null, 0);\r
- }\r
- else { // there's a local variable with this name, blow it off\r
- itsVariables.removeElementAt(pIndex.intValue());\r
- }\r
- }\r
- int curIndex = varStart++;\r
- LocalVariable lVar = createLocalVariable(pName, true);\r
- itsVariables.insertElementAt(lVar, curIndex);\r
- itsVariableNames.put(pName, new Integer(curIndex));\r
- }\r
-\r
- public void addLocal(String vName) {\r
- Integer vIndex = (Integer)(itsVariableNames.get(vName));\r
- if (vIndex != null) {\r
- // There's already a variable or parameter with this name.\r
- return;\r
- }\r
- int index = itsVariables.size();\r
- LocalVariable lVar = createLocalVariable(vName, false);\r
- itsVariables.addElement(lVar);\r
- itsVariableNames.put(vName, new Integer(index));\r
- }\r
- \r
- // This should only be called very early in compilation\r
- public void removeLocal(String name) {\r
- Integer i = (Integer) itsVariableNames.get(name);\r
- if (i != null) {\r
- itsVariables.removeElementAt(i.intValue());\r
- itsVariableNames.remove(name);\r
- Hashtable ht = new Hashtable(11);\r
- Enumeration e = itsVariableNames.keys();\r
- while (e.hasMoreElements()) {\r
- Object k = e.nextElement();\r
- Integer v = (Integer) itsVariableNames.get(k);\r
- int v2 = v.intValue();\r
- if (v2 > i.intValue())\r
- v = new Integer(v2 - 1);\r
- ht.put(k, v);\r
- }\r
- itsVariableNames = ht;\r
- }\r
- }\r
- \r
- // a list of the formal parameters and local variables\r
- protected Vector itsVariables = new Vector(); \r
-\r
- // mapping from name to index in list\r
- protected Hashtable itsVariableNames = new Hashtable(11); \r
-\r
- protected int varStart; // index in list of first variable\r
-\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-2000 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Marshall Cline\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-// API class\r
-\r
-package org.mozilla.javascript;\r
-\r
-/**\r
- * Embeddings that wish to provide their own custom wrappings for Java\r
- * objects may implement this interface and call Context.setWrapHandler.\r
- * @see org.mozilla.javascript.Context#setWrapHandler\r
- */\r
-public interface WrapHandler {\r
-\r
- /**\r
- * Wrap the object.\r
- * <p>\r
- * The value returned must be one of \r
- * <UL>\r
- * <LI>java.lang.Boolean</LI>\r
- * <LI>java.lang.String</LI>\r
- * <LI>java.lang.Number</LI>\r
- * <LI>org.mozilla.javascript.Scriptable objects</LI>\r
- * <LI>The value returned by Context.getUndefinedValue()</LI>\r
- * <LI>null</LI>\r
- * <p>\r
- * If null is returned, the value obj will be wrapped as if \r
- * no WrapHandler had been called.\r
- * </UL>\r
- * @param scope the scope of the executing script\r
- * @param obj the object to be wrapped\r
- * @staticType the static type of the object to be wrapped\r
- * @return the wrapped value.\r
- */\r
- public Object wrap(Scriptable scope, Object obj, Class staticType);\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-import java.lang.reflect.InvocationTargetException;\r
-\r
-/**\r
- * A wrapper for runtime exceptions.\r
- *\r
- * Used by the JavaScript runtime to wrap and propagate exceptions that occur\r
- * during runtime.\r
- *\r
- * @author Norris Boyd\r
- */\r
-public class WrappedException extends EvaluatorException implements Wrapper {\r
-\r
- /**\r
- * Create a new exception wrapped around an existing exception.\r
- *\r
- * @param exception the exception to wrap\r
- */\r
- public WrappedException(Throwable exception) {\r
- super(exception.getMessage());\r
- this.exception = exception.fillInStackTrace();\r
- }\r
-\r
- /**\r
- * Get the message for the exception.\r
- *\r
- * Delegates to the wrapped exception.\r
- */\r
- public String getMessage() {\r
- return "WrappedException of " + exception.toString();\r
- }\r
-\r
- /**\r
- * Gets the localized message.\r
- *\r
- * Delegates to the wrapped exception.\r
- */\r
- public String getLocalizedMessage() {\r
- return "WrappedException of " + exception.getLocalizedMessage();\r
- }\r
-\r
- /**\r
- * Get the wrapped exception.\r
- *\r
- * @return the exception that was presented as a argument to the\r
- * constructor when this object was created\r
- */\r
- public Throwable getWrappedException() {\r
- return exception;\r
- }\r
-\r
- /**\r
- * Get the wrapped exception.\r
- *\r
- * @return the exception that was presented as a argument to the\r
- * constructor when this object was created\r
- */\r
- public Object unwrap() {\r
- return exception;\r
- }\r
-\r
- /**\r
- * Wrap an exception.\r
- *\r
- * Provides special cases for EvaluatorExceptions (which are returned\r
- * as-is), and InvocationTargetExceptions (which are unwrapped and\r
- * passed to a recursive call to wrapException).<p>\r
- *\r
- * Otherwise the exception is simply wrapped in a WrappedException.\r
- */\r
- public static EvaluatorException wrapException(Throwable e) {\r
- if ((e instanceof InvocationTargetException))\r
- e = ((InvocationTargetException) e).getTargetException();\r
- if (e instanceof EvaluatorException)\r
- return (EvaluatorException) e;\r
- return new WrappedException(e);\r
- }\r
-\r
- private Throwable exception;\r
-}\r
+++ /dev/null
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation. Portions created by Netscape are\r
- * Copyright (C) 1997-2000 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL. If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-// API class\r
-\r
-package org.mozilla.javascript;\r
-\r
-/**\r
- * Objects that can wrap other values for reflection in the JS environment\r
- * will implement Wrapper. \r
- * \r
- * Wrapper defines a single method that can be called to unwrap the object.\r
- */\r
-\r
-public interface Wrapper {\r
-\r
- /**\r
- * Unwrap the object by returning the wrapped value.\r
- * \r
- * @return a wrapped value\r
- */\r
- public Object unwrap();\r
-}\r