* By default {@link #hasFeature(int)} returns true only if * the current JS version is set to {@link #VERSION_1_2}. */ public static final int FEATURE_TO_STRING_AS_SOURCE = 4; /** * Control if properties __proto__ and __parent__ @@ -195,14 +200,24 @@ * x["__proto__"] = y simply assigns a new value to the property * __proto__ in x even when the feature is on. * * By default {@link #hasFeature(int)} returns true. */ public static final int FEATURE_PARENT_PROTO_PROPRTIES = 5; + /** + * Control if support for E4X(ECMAScript for XML) extension is available. + * If hasFeature(FEATURE_E4X) returns true, the XML syntax is available. + *
+ * By default {@link #hasFeature(int)} returns true if
+ * the current JS version is set to {@link #VERSION_DEFAULT}
+ * or is greater then {@link #VERSION_1_6}.
+ */
+ public static final int FEATURE_E4X = 6;
+
public static final String languageVersionProperty = "language version";
public static final String errorReporterProperty = "error reporter";
/**
* Convinient value to use as zero-length array of objects.
*/
public static final Object[] emptyArgs = ScriptRuntime.emptyArgs;
@@ -1113,30 +1128,42 @@
NativeDate.init(this, scope, sealed);
NativeMath.init(this, scope, sealed);
NativeWith.init(this, scope, sealed);
NativeCall.init(this, scope, sealed);
NativeScript.init(this, scope, sealed);
+ boolean withXml = hasFeature(FEATURE_E4X);
+
for (int i = 0; i != lazilyNames.length; i += 2) {
String topProperty = lazilyNames[i];
String className = lazilyNames[i + 1];
+ if (!withXml && className == XML_INIT_CLASS) {
+ continue;
+ }
new LazilyLoadedCtor(scope, topProperty, className, sealed);
}
return scope;
}
+ private static final String
+ XML_INIT_CLASS = "org.mozilla.javascript.xmlimpl.XMLLibImpl";
+
private static final String[] lazilyNames = {
"RegExp", "org.mozilla.javascript.regexp.NativeRegExp",
"Packages", "org.mozilla.javascript.NativeJavaTopPackage",
"java", "org.mozilla.javascript.NativeJavaTopPackage",
"getClass", "org.mozilla.javascript.NativeJavaTopPackage",
"JavaAdapter", "org.mozilla.javascript.JavaAdapter",
"JavaImporter", "org.mozilla.javascript.ImporterTopLevel",
+ "XML", XML_INIT_CLASS,
+ "XMLList", XML_INIT_CLASS,
+ "Namespace", XML_INIT_CLASS,
+ "QName", XML_INIT_CLASS,
};
/**
* Get the singleton object that represents the JavaScript Undefined value.
*/
public static Object getUndefinedValue()
{
@@ -1945,19 +1972,25 @@
* @deprecated Use {@link ClassCache#get(Scriptable)} and
* {@link ClassCache#setCachingEnabled(boolean)}.
*/
public static void setCachingEnabled(boolean cachingEnabled)
{
}
- // Proxy to allow to use deprecated WrapHandler in place of WrapFactory
+ /**
+ * @deprecated Proxy to allow to use deprecated WrapHandler in place
+ * of WrapFactory.
+ */
private static class WrapHandlerProxy extends WrapFactory
{
WrapHandler _handler;
+ /**
+ * @deprecated
+ */
WrapHandlerProxy(WrapHandler handler)
{
_handler = handler;
}
public Object wrap(Context cx, Scriptable scope,
Object obj, Class staticType)
@@ -2076,14 +2109,15 @@
* @param featureIndex feature index to check
* @return true if the featureIndex
feature is turned on
* @see #FEATURE_NON_ECMA_GET_YEAR
* @see #FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME
* @see #FEATURE_RESERVED_KEYWORD_AS_IDENTIFIER
* @see #FEATURE_TO_STRING_AS_SOURCE
* @see #FEATURE_PARENT_PROTO_PROPRTIES
+ * @see #FEATURE_E4X
*/
public boolean hasFeature(int featureIndex)
{
switch (featureIndex) {
case FEATURE_NON_ECMA_GET_YEAR:
/*
* During the great date rewrite of 1.3, we tried to track the
@@ -2092,29 +2126,32 @@
* implemented, not realizing that it was incompatible with
* the old behavior... now, rather than thrash the behavior
* yet again, we've decided to leave it with the - 1900
* behavior and point people to the getFullYear method. But
* we try to protect existing scripts that have specified a
* version...
*/
- return (version == Context.VERSION_1_0
- || version == Context.VERSION_1_1
- || version == Context.VERSION_1_2);
+ return (version == VERSION_1_0
+ || version == VERSION_1_1
+ || version == VERSION_1_2);
case FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME:
return false;
case FEATURE_RESERVED_KEYWORD_AS_IDENTIFIER:
return false;
case FEATURE_TO_STRING_AS_SOURCE:
return version == VERSION_1_2;
case FEATURE_PARENT_PROTO_PROPRTIES:
return true;
+
+ case FEATURE_E4X:
+ return version == VERSION_DEFAULT || version >= VERSION_1_6;
}
// It is a bug to call the method with unknown featureIndex
throw new IllegalArgumentException(String.valueOf(featureIndex));
}
/**
* Get/Set threshold of executed instructions counter that triggers call to
@@ -2568,18 +2605,20 @@
}
}
private ContextFactory factory;
private boolean sealed;
private Object sealKey;
- /**
- * The activation of the currently executing function or script.
- */
- NativeCall currentActivation;
+ Scriptable topActivationScope;
+ NativeCall currentActivationCall;
+ Scriptable currentActivationScope;
+ int currentActivationDepth;
+
+ XMLLib cachedXMLLib;
// for Objects, Arrays to tag themselves as being printed out,
// so they don't print themselves out recursively.
// Use ObjToIntMap instead of java.util.HashSet for JDK 1.1 compatibility
ObjToIntMap iterating;
Object interpreterSecurityDomain;
@@ -2614,8 +2653,11 @@
// For the interpreter to indicate line/source for error reports.
int interpreterLineIndex;
InterpreterData interpreterData;
// For instruction counting (interpreter only)
int instructionCount;
int instructionThreshold;
+
+ // It can be used to return the second long or uint32 result from function
+ long scratchLong;
}
Index: src/org/mozilla/javascript/Decompiler.java
===================================================================
RCS file: /cvsroot/mozilla/js/rhino/src/org/mozilla/javascript/Decompiler.java,v
retrieving revision 1.16
diff -U7 -r1.16 Decompiler.java
--- src/org/mozilla/javascript/Decompiler.java 4 Jul 2004 17:26:50 -0000 1.16
+++ src/org/mozilla/javascript/Decompiler.java 28 Jul 2004 15:32:22 -0000
@@ -785,14 +785,26 @@
result.append(" / ");
break;
case Token.MOD:
result.append(" % ");
break;
+ case Token.COLONCOLON:
+ result.append("::");
+ break;
+
+ case Token.DOTDOT:
+ result.append("..");
+ break;
+
+ case Token.XMLATTR:
+ result.append('@');
+ break;
+
default:
// If we don't know how to decompile it, raise an exception.
throw new RuntimeException();
}
++i;
}
Index: src/org/mozilla/javascript/IRFactory.java
===================================================================
RCS file: /cvsroot/mozilla/js/rhino/src/org/mozilla/javascript/IRFactory.java,v
retrieving revision 1.85
diff -U7 -r1.85 IRFactory.java
--- src/org/mozilla/javascript/IRFactory.java 2 Jul 2004 13:11:06 -0000 1.85
+++ src/org/mozilla/javascript/IRFactory.java 28 Jul 2004 15:32:22 -0000
@@ -17,14 +17,17 @@
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Norris Boyd
* Igor Bukanov
+ * Ethan Hugg
+ * Terry Lucas
+ * Milen Nankov
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License (the "GPL"), in which case the
* provisions of the GPL are applicable instead of those above.
* If you wish to allow use of your version of this file only
* under the terms of the GPL and not to allow others to use your
* version of this file under the NPL, indicate your decision by
@@ -103,14 +106,23 @@
}
Node createExprStatementNoReturn(Node expr, int lineno)
{
return new Node(Token.EXPR_VOID, expr, lineno);
}
+ Node createDefaultNamespace(Node expr, int lineno)
+ {
+ // default xml namespace requires activation
+ setRequiresActivation();
+ Node n = createUnary(Token.DEFAULTNAMESPACE, expr);
+ Node result = createExprStatement(n, lineno);
+ return result;
+ }
+
/**
* Name
*/
Node createName(String name)
{
checkActivationName(name, Token.NAME);
return Node.newString(Token.NAME, name);
@@ -129,14 +141,63 @@
*/
Node createNumber(double number)
{
return Node.newNumber(number);
}
/**
+ * PropertySelector :: PropertySelector
+ */
+ Node createQualifiedName(String namespace, String name)
+ {
+ Node namespaceNode = createString(namespace);
+ Node nameNode = createString(name);
+ return new Node(Token.COLONCOLON, namespaceNode, nameNode);
+ }
+
+ /**
+ * PropertySelector :: [Expression]
+ */
+ Node createQualifiedExpr(String namespace, Node expr)
+ {
+ Node namespaceNode = createString(namespace);
+ return new Node(Token.COLONCOLON, namespaceNode, expr);
+ }
+
+ /**
+ * @PropertySelector or @QualifiedIdentifier
+ */
+ Node createAttributeName(Node nameNode)
+ {
+ int type = nameNode.getType();
+ if (type == Token.NAME) {
+ nameNode.setType(Token.STRING);
+ } else {
+ // If not name, then it should come from createQualifiedExpr
+ if (type != Token.COLONCOLON)
+ throw new IllegalArgumentException(String.valueOf(type));
+ }
+ return new Node(Token.TOATTRNAME, nameNode);
+ }
+
+ /**
+ * @::[Expression]
+ */
+ Node createAttributeExpr(Node expr)
+ {
+ return new Node(Token.TOATTRNAME, expr);
+ }
+
+ Node createXMLPrimary(Node xmlName)
+ {
+ Node xmlRef = new Node(Token.XML_REF, xmlName);
+ return new Node(Token.GET_REF, xmlRef);
+ }
+
+ /**
* Catch clause of try/catch/finally
* @param varName the name of the variable to bind to the exception
* @param catchCond the condition under which to catch the exception.
* May be null if no condition is given.
* @param stmts the statements in the catch clause
* @param lineno the starting line number of the catch clause
*/
@@ -358,15 +419,16 @@
return result;
}
/**
* For .. In
*
*/
- Node createForIn(Node lhs, Node obj, Node body, int lineno)
+ Node createForIn(Node lhs, Node obj, Node body, boolean isForEach,
+ int lineno)
{
String name;
int type = lhs.getType();
Node lvalue = lhs;
switch (type) {
@@ -393,15 +455,17 @@
default:
parser.reportError("msg.bad.for.in.lhs");
return obj;
}
Node localBlock = new Node(Token.LOCAL_BLOCK);
- Node init = new Node(Token.ENUM_INIT, obj);
+ int initType = (isForEach) ? Token.ENUM_INIT_VALUES
+ : Token.ENUM_INIT_KEYS;
+ Node init = new Node(initType, obj);
init.putProp(Node.LOCAL_BLOCK_PROP, localBlock);
Node cond = new Node(Token.ENUM_NEXT);
cond.putProp(Node.LOCAL_BLOCK_PROP, localBlock);
Node id = new Node(Token.ENUM_ID);
id.putProp(Node.LOCAL_BLOCK_PROP, localBlock);
Node newBody = new Node(Token.BLOCK);
@@ -589,23 +653,33 @@
*/
/**
* With
*/
Node createWith(Node obj, Node body, int lineno)
{
- parser.setRequiresActivation();
+ setRequiresActivation();
Node result = new Node(Token.BLOCK, lineno);
result.addChildToBack(new Node(Token.ENTERWITH, obj));
Node bodyNode = new Node(Token.WITH, body, lineno);
result.addChildrenToBack(bodyNode);
result.addChildToBack(new Node(Token.LEAVEWITH));
return result;
}
+ /**
+ * DOTQUERY
+ */
+ public Node createDotQuery (Node obj, Node body, int lineno)
+ {
+ setRequiresActivation();
+ Node result = new Node(Token.DOTQUERY, obj, body, lineno);
+ return result;
+ }
+
Node createArrayLiteral(ObjArray elems, int skipCount)
{
int length = elems.size();
int[] skipIndexes = null;
if (skipCount != 0) {
skipIndexes = new int[skipCount];
}
@@ -714,33 +788,38 @@
* Unary
*/
Node createUnary(int nodeType, Node child)
{
int childType = child.getType();
switch (nodeType) {
case Token.DELPROP: {
- Node left;
- Node right;
+ Node n;
if (childType == Token.NAME) {
// Transform Delete(Name "a")
// to Delete(Bind("a"), String("a"))
child.setType(Token.BINDNAME);
- left = child;
- right = Node.newString(child.getString());
+ Node left = child;
+ Node right = Node.newString(child.getString());
+ n = new Node(nodeType, left, right);
} else if (childType == Token.GETPROP ||
childType == Token.GETELEM)
{
- left = child.getFirstChild();
- right = child.getLastChild();
+ Node left = child.getFirstChild();
+ Node right = child.getLastChild();
child.removeChild(left);
child.removeChild(right);
+ n = new Node(nodeType, left, right);
+ } else if (childType == Token.GET_REF) {
+ Node ref = child.getFirstChild();
+ child.removeChild(ref);
+ n = new Node(Token.DELPROP, ref);
} else {
- return new Node(Token.TRUE);
+ n = new Node(Token.TRUE);
}
- return new Node(nodeType, left, right);
+ return n;
}
case Token.TYPEOF:
if (childType == Token.NAME) {
child.setType(Token.TYPEOFNAME);
return child;
}
break;
@@ -793,15 +872,15 @@
if (name.equals("eval")) {
type = Node.SPECIALCALL_EVAL;
}
}
Node node = new Node(nodeType, child);
if (type != Node.NON_SPECIALCALL) {
// Calls to these functions require activation objects.
- parser.setRequiresActivation();
+ setRequiresActivation();
node.putIntProp(Node.SPECIALCALL_PROP, type);
}
return node;
}
Node createIncDec(int nodeType, boolean post, Node child)
{
@@ -843,23 +922,36 @@
* Binary
*/
Node createBinary(int nodeType, Node left, Node right)
{
switch (nodeType) {
case Token.DOT:
- nodeType = Token.GETPROP;
- right.setType(Token.STRING);
- String id = right.getString();
- if (ScriptRuntime.isSpecialProperty(id)) {
- Node ref = new Node(Token.SPECIAL_REF, left);
- ref.putProp(Node.SPECIAL_PROP_PROP, id);
- return new Node(Token.GET_REF, ref);
+ if (right.getType() == Token.NAME) {
+ String id = right.getString();
+ if (ScriptRuntime.isSpecialProperty(id)) {
+ Node ref = new Node(Token.SPECIAL_REF, left);
+ ref.putProp(Node.SPECIAL_PROP_PROP, id);
+ return new Node(Token.GET_REF, ref);
+ }
+ nodeType = Token.GETPROP;
+ right.setType(Token.STRING);
+ checkActivationName(id, Token.GETPROP);
+ } else {
+ // corresponds to name.@... or name.namespace::...
+ nodeType = Token.GETELEM;
+ }
+ break;
+
+ case Token.DOTDOT:
+ if (right.getType() == Token.NAME) {
+ right.setType(Token.STRING);
}
- checkActivationName(id, Token.GETPROP);
+ right = new Node(Token.DESCENDANTS, right);
+ nodeType = Token.GETELEM;
break;
case Token.LB:
// OPT: could optimize to GETPROP iff string can't be a number
nodeType = Token.GETELEM;
break;
@@ -1131,19 +1223,26 @@
== Context.VERSION_1_2)
{
// Use of "length" in 1.2 requires an activation object.
activation = true;
}
}
if (activation) {
- parser.setRequiresActivation();
+ setRequiresActivation();
}
}
}
+ private void setRequiresActivation()
+ {
+ if (parser.insideFunction()) {
+ ((FunctionNode)parser.currentScriptOrFn).setRequiresActivation();
+ }
+ }
+
// Only needed to call reportCurrentLineError.
private Parser parser;
private static final int LOOP_DO_WHILE = 0;
private static final int LOOP_WHILE = 1;
private static final int LOOP_FOR = 2;
Index: src/org/mozilla/javascript/Interpreter.java
===================================================================
RCS file: /cvsroot/mozilla/js/rhino/src/org/mozilla/javascript/Interpreter.java,v
retrieving revision 1.252
diff -U7 -r1.252 Interpreter.java
--- src/org/mozilla/javascript/Interpreter.java 5 Jul 2004 15:08:33 -0000 1.252
+++ src/org/mozilla/javascript/Interpreter.java 28 Jul 2004 15:32:23 -0000
@@ -18,15 +18,18 @@
* Copyright (C) 1997-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Patrick Beard
* Norris Boyd
* Igor Bukanov
+ * Ethan Hugg
+ * Terry Lucas
* Roger Lawrence
+ * Milen Nankov
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License (the "GPL"), in which case the
* provisions of the GPL are applicable instead of those above.
* If you wish to allow use of your version of this file only
* under the terms of the GPL and not to allow others to use your
* version of this file under the NPL, indicate your decision by
@@ -38,14 +41,16 @@
package org.mozilla.javascript;
import java.io.*;
import org.mozilla.javascript.debug.*;
+import org.mozilla.javascript.xml.XMLObject;
+
public class Interpreter
{
// Additional interpreter-specific codes
private static final int
@@ -137,16 +142,20 @@
Icode_SETVAR1 = -47,
// Load unefined
Icode_UNDEF = -48,
Icode_ZERO = -49,
Icode_ONE = -50,
+ // entrance and exit from .()
+ Icode_ENTERDQ = -51,
+ Icode_LEAVEDQ = -52,
+
// Last icode
- MIN_ICODE = -50;
+ MIN_ICODE = -52;
static {
// Checks for byte code consistencies, good compiler can eliminate them
if (Token.LAST_BYTECODE_TOKEN > 127) {
String str = "Violation of Token.LAST_BYTECODE_TOKEN <= 127";
System.err.println(str);
@@ -220,14 +229,16 @@
case Icode_REG_STR2: return "LOAD_STR2";
case Icode_REG_STR4: return "LOAD_STR4";
case Icode_GETVAR1: return "GETVAR1";
case Icode_SETVAR1: return "SETVAR1";
case Icode_UNDEF: return "UNDEF";
case Icode_ZERO: return "ZERO";
case Icode_ONE: return "ONE";
+ case Icode_ENTERDQ: return "ENTERDQ";
+ case Icode_LEAVEDQ: return "LEAVEDQ";
}
// icode without name
throw new IllegalStateException(String.valueOf(bytecode));
}
private static boolean validIcode(int icode)
@@ -696,17 +707,18 @@
break;
case Token.RETURN_RESULT:
iCodeTop = updateLineNumber(node, iCodeTop);
iCodeTop = addToken(Token.RETURN_RESULT, iCodeTop);
break;
- case Token.ENUM_INIT:
+ case Token.ENUM_INIT_KEYS:
+ case Token.ENUM_INIT_VALUES :
iCodeTop = visitExpression(child, iCodeTop);
- iCodeTop = addIndexOp(Token.ENUM_INIT, getLocalBlockRef(node), iCodeTop);
+ iCodeTop = addIndexOp(type, getLocalBlockRef(node), iCodeTop);
stackChange(-1);
break;
default:
throw badTree(node);
}
@@ -887,14 +899,15 @@
case Token.POS:
case Token.NEG:
case Token.NOT:
case Token.BITNOT:
case Token.TYPEOF:
case Token.VOID:
+ case Token.DEL_REF:
iCodeTop = visitExpression(child, iCodeTop);
if (type == Token.VOID) {
iCodeTop = addIcode(Icode_POP, iCodeTop);
iCodeTop = addIcode(Icode_UNDEF, iCodeTop);
} else {
iCodeTop = addToken(type, iCodeTop);
}
@@ -1067,18 +1080,43 @@
case Token.SPECIAL_REF: {
iCodeTop = visitExpression(child, iCodeTop);
String special = (String)node.getProp(Node.SPECIAL_PROP_PROP);
iCodeTop = addStringOp(Token.SPECIAL_REF, special, iCodeTop);
break;
}
+ case Token.XML_REF:
case Token.GENERIC_REF:
iCodeTop = visitExpression(child, iCodeTop);
- iCodeTop = addToken(Token.GENERIC_REF, iCodeTop);
+ iCodeTop = addToken(type, iCodeTop);
+ break;
+
+ case Token.DOTQUERY:
+ iCodeTop = visitDotQery(node, child, iCodeTop);
+ break;
+
+ case Token.DEFAULTNAMESPACE :
+ case Token.ESCXMLATTR :
+ case Token.ESCXMLTEXT :
+ case Token.TOATTRNAME :
+ case Token.DESCENDANTS :
+ iCodeTop = visitExpression(child, iCodeTop);
+ iCodeTop = addToken(type, iCodeTop);
+ break;
+
+ case Token.COLONCOLON : {
+ if (child.getType() != Token.STRING)
+ throw badTree(child);
+ String namespace = child.getString();
+ child = child.getNext();
+ iCodeTop = visitExpression(child, iCodeTop);
+ iCodeTop = addStringOp(Token.COLONCOLON, namespace, iCodeTop);
break;
+ }
+
default:
throw badTree(node);
}
if (savedStackDepth + 1 != itsStackDepth) {
Kit.codeBug();
}
@@ -1290,14 +1328,29 @@
int index = itsLiteralIds.size();
itsLiteralIds.add(propertyIds);
iCodeTop = addIndexOp(Token.OBJECTLIT, index, iCodeTop);
}
return iCodeTop;
}
+ private int visitDotQery(Node node, Node child, int iCodeTop)
+ {
+ iCodeTop = updateLineNumber(node, iCodeTop);
+ iCodeTop = visitExpression(child, iCodeTop);
+ iCodeTop = addIcode(Icode_ENTERDQ, iCodeTop);
+ stackChange(-1);
+ int queryPC = iCodeTop;
+ iCodeTop = visitExpression(child.getNext(), iCodeTop);
+ int leavePC = iCodeTop;
+ iCodeTop = addIcode(Icode_LEAVEDQ, iCodeTop);
+ recordJump(leavePC, queryPC);
+ iCodeTop += 2;
+ return iCodeTop;
+ }
+
private int getLocalBlockRef(Node node)
{
Node localBlock = (Node)node.getProp(Node.LOCAL_BLOCK_PROP);
return localBlock.getExistingIntProp(Node.LOCAL_PROP);
}
private int getTargetLabel(Node.Target target)
@@ -1651,15 +1704,16 @@
out.println(tname);
break;
case Icode_GOSUB :
case Token.GOTO :
case Token.IFEQ :
case Token.IFNE :
- case Icode_IFEQ_POP : {
+ case Icode_IFEQ_POP :
+ case Icode_LEAVEDQ : {
int newPC = pc + getShort(iCode, pc) - 1;
out.println(tname + " " + newPC);
pc += 2;
break;
}
case Icode_VAR_INC_DEC :
case Icode_NAME_INC_DEC :
@@ -1805,14 +1859,15 @@
return 1 + 2;
case Icode_GOSUB :
case Token.GOTO :
case Token.IFEQ :
case Token.IFNE :
case Icode_IFEQ_POP :
+ case Icode_LEAVEDQ :
// target pc offset
return 1 + 2;
case Icode_CALLSPECIAL :
// call type
// is new
// line number
@@ -2020,21 +2075,21 @@
if (idata.itsNeedsActivation) {
if (argsDbl != null) {
args = getArgsArray(args, argsDbl, argShift, argCount);
argShift = 0;
argsDbl = null;
}
- scope = ScriptRuntime.initVarObj(cx, scope, fnOrScript,
- thisObj, args);
+ scope = ScriptRuntime.enterActivationFunction(cx, scope,
+ fnOrScript,
+ thisObj, args);
}
} else {
- ScriptRuntime.initScript(cx, scope, fnOrScript, thisObj,
- idata.itsFromEvalCode);
+ scope = ScriptRuntime.enterScript(cx, scope, fnOrScript, thisObj);
}
if (idata.itsNestedFunctions != null) {
if (idata.itsFunctionType != 0 && !idata.itsNeedsActivation)
Kit.codeBug();
for (int i = 0; i < idata.itsNestedFunctions.length; i++) {
InterpreterData fdata = idata.itsNestedFunctions[i];
@@ -2054,16 +2109,17 @@
if (argsDbl != null) {
args = getArgsArray(args, argsDbl, argShift, argCount);
argShift = 0;
argsDbl = null;
}
if (idata.itsFunctionType != 0 && !idata.itsNeedsActivation) {
useActivationVars = true;
- scope = ScriptRuntime.initVarObj(cx, scope, fnOrScript,
- thisObj, args);
+ scope = ScriptRuntime.enterActivationFunction(cx, scope,
+ fnOrScript,
+ thisObj, args);
}
debuggerFrame.onEnter(cx, scope, thisObj, args);
}
InterpreterData savedData = cx.interpreterData;
cx.interpreterData = idata;
cx.interpreterLineIndex = idata.firstLinePC;
@@ -2201,25 +2257,25 @@
continue Loop;
case Token.IN : {
Object rhs = stack[stackTop];
if (rhs == DBL_MRK) rhs = doubleWrap(sDbl[stackTop]);
--stackTop;
Object lhs = stack[stackTop];
if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);
- boolean valBln = ScriptRuntime.in(lhs, rhs, scope);
+ boolean valBln = ScriptRuntime.in(lhs, rhs, cx, scope);
stack[stackTop] = valBln ? Boolean.TRUE : Boolean.FALSE;
continue Loop;
}
case Token.INSTANCEOF : {
Object rhs = stack[stackTop];
if (rhs == DBL_MRK) rhs = doubleWrap(sDbl[stackTop]);
--stackTop;
Object lhs = stack[stackTop];
if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);
- boolean valBln = ScriptRuntime.instanceOf(lhs, rhs, scope);
+ boolean valBln = ScriptRuntime.instanceOf(lhs, rhs, cx, scope);
stack[stackTop] = valBln ? Boolean.TRUE : Boolean.FALSE;
continue Loop;
}
case Token.EQ :
case Token.NE :
stackTop = do_eq(stack, sDbl, stackTop, op);
continue Loop;
@@ -2375,15 +2431,15 @@
case Token.POS : {
double rDbl = stack_double(stack, sDbl, stackTop);
stack[stackTop] = DBL_MRK;
sDbl[stackTop] = rDbl;
continue Loop;
}
case Token.ADD :
- stackTop = do_add(stack, sDbl, stackTop);
+ stackTop = do_add(stack, sDbl, stackTop, cx);
continue Loop;
case Token.SUB : {
double rDbl = stack_double(stack, sDbl, stackTop);
--stackTop;
double lDbl = stack_double(stack, sDbl, stackTop);
stack[stackTop] = DBL_MRK;
sDbl[stackTop] = lDbl - rDbl;
@@ -2415,46 +2471,48 @@
continue Loop;
}
case Token.NOT :
stack[stackTop] = stack_boolean(stack, sDbl, stackTop)
? Boolean.FALSE : Boolean.TRUE;
continue Loop;
case Token.BINDNAME :
- stack[++stackTop] = ScriptRuntime.bind(scope, stringReg);
+ stack[++stackTop] = ScriptRuntime.bind(cx, scope, stringReg);
continue Loop;
case Token.SETNAME : {
Object rhs = stack[stackTop];
if (rhs == DBL_MRK) rhs = doubleWrap(sDbl[stackTop]);
--stackTop;
Scriptable lhs = (Scriptable)stack[stackTop];
- stack[stackTop] = ScriptRuntime.setName(lhs, rhs, scope, stringReg);
+ stack[stackTop] = ScriptRuntime.setName(lhs, rhs, cx, stringReg);
continue Loop;
}
case Token.DELPROP : {
Object rhs = stack[stackTop];
if (rhs == DBL_MRK) rhs = doubleWrap(sDbl[stackTop]);
--stackTop;
Object lhs = stack[stackTop];
if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);
stack[stackTop] = ScriptRuntime.delete(cx, scope, lhs, rhs);
continue Loop;
}
case Token.GETPROP : {
Object lhs = stack[stackTop];
if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);
- stack[stackTop] = ScriptRuntime.getProp(lhs, stringReg, scope);
+ stack[stackTop] = ScriptRuntime.getObjectProp(lhs, stringReg,
+ cx, scope);
continue Loop;
}
case Token.SETPROP : {
Object rhs = stack[stackTop];
if (rhs == DBL_MRK) rhs = doubleWrap(sDbl[stackTop]);
--stackTop;
Object lhs = stack[stackTop];
if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);
- stack[stackTop] = ScriptRuntime.setProp(lhs, stringReg, rhs, scope);
+ stack[stackTop] = ScriptRuntime.setObjectProp(lhs, stringReg, rhs,
+ cx, scope);
continue Loop;
}
case Icode_PROP_INC_DEC : {
Object lhs = stack[stackTop];
if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);
stack[stackTop] = ScriptRuntime.propIncrDecr(lhs, stringReg, scope,
iCode[pc]);
@@ -2469,15 +2527,15 @@
continue Loop;
case Icode_ELEM_INC_DEC: {
Object rhs = stack[stackTop];
if (rhs == DBL_MRK) rhs = doubleWrap(sDbl[stackTop]);
--stackTop;
Object lhs = stack[stackTop];
if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);
- stack[stackTop] = ScriptRuntime.elemIncrDecr(lhs, rhs, scope,
+ stack[stackTop] = ScriptRuntime.elemIncrDecr(lhs, rhs, cx, scope,
iCode[pc]);
++pc;
continue Loop;
}
case Token.GET_REF : {
Object lhs = stack[stackTop];
if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);
@@ -2489,14 +2547,20 @@
if (rhs == DBL_MRK) rhs = doubleWrap(sDbl[stackTop]);
--stackTop;
Object lhs = stack[stackTop];
if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);
stack[stackTop] = ScriptRuntime.setReference(lhs, rhs);
continue Loop;
}
+ case Token.DEL_REF : {
+ Object lhs = stack[stackTop];
+ if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);
+ stack[stackTop] = ScriptRuntime.deleteReference(lhs);
+ continue Loop;
+ }
case Icode_REF_INC_DEC : {
Object lhs = stack[stackTop];
if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);
stack[stackTop] = ScriptRuntime.referenceIncrDecr(lhs, iCode[pc]);
++pc;
continue Loop;
}
@@ -2666,15 +2730,15 @@
continue Loop;
case Token.NUMBER :
++stackTop;
stack[stackTop] = DBL_MRK;
sDbl[stackTop] = idata.itsDoubleTable[indexReg];
continue Loop;
case Token.NAME :
- stack[++stackTop] = ScriptRuntime.name(scope, stringReg);
+ stack[++stackTop] = ScriptRuntime.name(cx, scope, stringReg);
continue Loop;
case Icode_NAME_INC_DEC :
stack[++stackTop] = ScriptRuntime.nameIncrDecr(scope, stringReg,
iCode[pc]);
++pc;
continue Loop;
case Icode_SETVAR1:
@@ -2768,21 +2832,28 @@
scope = ScriptRuntime.leaveWith(scope);
--withDepth;
continue Loop;
case Token.CATCH_SCOPE :
stack[stackTop] = ScriptRuntime.newCatchScope(stringReg,
stack[stackTop]);
continue Loop;
- case Token.ENUM_INIT : {
+ case Token.ENUM_INIT_KEYS : {
Object lhs = stack[stackTop];
if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);
--stackTop;
stack[LOCAL_SHFT + indexReg] = ScriptRuntime.enumInit(lhs, scope);
continue Loop;
}
+ case Token.ENUM_INIT_VALUES : {
+ Object lhs = stack[stackTop];
+ if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);
+ --stackTop;
+ stack[LOCAL_SHFT + indexReg] = ScriptRuntime.enumValuesInit(lhs, scope);
+ continue Loop;
+ }
case Token.ENUM_NEXT :
case Token.ENUM_ID : {
Object val = stack[LOCAL_SHFT + indexReg];
++stackTop;
stack[stackTop] = (op == Token.ENUM_NEXT)
? (Object)ScriptRuntime.enumNext(val)
: (Object)ScriptRuntime.enumId(val);
@@ -2798,14 +2869,20 @@
//stringReg: name of special property
Object lhs = stack[stackTop];
if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);
stack[stackTop] = ScriptRuntime.specialReference(lhs, stringReg,
cx, scope);
continue Loop;
}
+ case Token.XML_REF : {
+ Object lhs = stack[stackTop];
+ if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);
+ stack[stackTop] = ScriptRuntime.xmlReference(lhs, cx, scope);
+ continue Loop;
+ }
case Token.GENERIC_REF : {
Object lhs = stack[stackTop];
if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);
stack[stackTop] = ScriptRuntime.genericReference(lhs, cx, scope);
continue Loop;
}
case Icode_SCOPE :
@@ -2864,14 +2941,76 @@
skipIndexces = (int[])idata.literalIds[indexReg];
}
val = ScriptRuntime.newArrayLiteral(data, skipIndexces, cx, scope);
}
stack[stackTop] = val;
continue Loop;
}
+ case Icode_ENTERDQ : {
+ Object lhs = stack[stackTop];
+ if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);
+ --stackTop;
+ scope = ScriptRuntime.enterDotQuery(lhs, scope);
+ ++withDepth;
+ continue Loop;
+ }
+ case Icode_LEAVEDQ : {
+ boolean valBln = stack_boolean(stack, sDbl, stackTop);
+ Object x = ScriptRuntime.updateDotQuery(valBln, scope);
+ if (x == null) {
+ // reset stack and PC to code after ENTERDQ
+ --stackTop;
+ break;
+ }
+ stack[stackTop] = x;
+ scope = ScriptRuntime.leaveDotQuery(scope);
+ --withDepth;
+ pc += 2;
+ continue Loop;
+ }
+ case Token.DEFAULTNAMESPACE : {
+ Object value = stack[stackTop];
+ if (value == DBL_MRK) value = doubleWrap(sDbl[stackTop]);
+ stack[stackTop] = ScriptRuntime.setDefaultNamespace(value, cx);
+ continue Loop;
+ }
+ case Token.ESCXMLATTR : {
+ Object value = stack[stackTop];
+ if (value != DBL_MRK) {
+ stack[stackTop] = ScriptRuntime.escapeAttributeValue(value, cx);
+ }
+ continue Loop;
+ }
+ case Token.ESCXMLTEXT : {
+ Object value = stack[stackTop];
+ if (value != DBL_MRK) {
+ stack[stackTop] = ScriptRuntime.escapeTextValue(value, cx);
+ }
+ continue Loop;
+ }
+ case Token.TOATTRNAME : {
+ Object value = stack[stackTop];
+ if (value == DBL_MRK) value = doubleWrap(sDbl[stackTop]);
+ stack[stackTop] = ScriptRuntime.toAttributeName(value, cx);
+ continue Loop;
+ }
+ case Token.DESCENDANTS : {
+ Object value = stack[stackTop];
+ if(value == DBL_MRK) value = doubleWrap(sDbl[stackTop]);
+ stack[stackTop] = ScriptRuntime.toDescendantsName(value, cx);
+ continue Loop;
+ }
+ case Token.COLONCOLON : {
+ Object value = stack[stackTop];
+ if (value == DBL_MRK) value = doubleWrap(sDbl[stackTop]);
+ // stringReg contains namespace
+ stack[stackTop] = ScriptRuntime.toQualifiedName(stringReg, value,
+ cx, scope);
+ continue Loop;
+ }
case Icode_LINE :
cx.interpreterLineIndex = pc;
if (debuggerFrame != null) {
int line = getShort(iCode, pc);
debuggerFrame.onLineChange(cx, line);
}
pc += 2;
@@ -2969,16 +3108,21 @@
if (debuggerFrame != null) {
if (javaException != null) {
debuggerFrame.onExit(cx, true, javaException);
} else {
debuggerFrame.onExit(cx, false, result);
}
}
- if (idata.itsNeedsActivation || debuggerFrame != null) {
- ScriptRuntime.popActivation(cx);
+
+ if (idata.itsFunctionType != 0) {
+ if (idata.itsNeedsActivation || debuggerFrame != null) {
+ ScriptRuntime.exitActivationFunction(cx);
+ }
+ } else {
+ ScriptRuntime.exitScript(cx);
}
if (javaException != null) {
if (javaException instanceof RuntimeException) {
throw (RuntimeException)javaException;
} else {
// Must be instance of Error or code bug
@@ -3031,29 +3175,34 @@
} else if (x instanceof Boolean) {
return ((Boolean)x).booleanValue();
} else {
return ScriptRuntime.toBoolean(x);
}
}
- private static int do_add(Object[] stack, double[] sDbl, int stackTop)
+ private static int do_add(Object[] stack, double[] sDbl, int stackTop,
+ Context cx)
{
--stackTop;
Object rhs = stack[stackTop + 1];
Object lhs = stack[stackTop];
if (rhs == DBL_MRK) {
double rDbl = sDbl[stackTop + 1];
if (lhs == DBL_MRK) {
sDbl[stackTop] += rDbl;
} else {
do_add(lhs, rDbl, stack, sDbl, stackTop, true);
}
} else if (lhs == DBL_MRK) {
do_add(rhs, sDbl[stackTop], stack, sDbl, stackTop, false);
} else {
+ if (lhs instanceof XMLObject || rhs instanceof XMLObject) {
+ stack[stackTop] = ScriptRuntime.add(lhs, rhs, cx);
+ return stackTop;
+ }
if (lhs instanceof Scriptable)
lhs = ((Scriptable) lhs).getDefaultValue(null);
if (rhs instanceof Scriptable)
rhs = ((Scriptable) rhs).getDefaultValue(null);
if (lhs instanceof String) {
String lstr = (String)lhs;
String rstr = ScriptRuntime.toString(rhs);
@@ -3232,30 +3381,30 @@
{
Object lhs = stack[stackTop - 1];
if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop - 1]);
Object result;
Object id = stack[stackTop];
if (id != DBL_MRK) {
- result = ScriptRuntime.getElem(lhs, id, scope);
+ result = ScriptRuntime.getObjectId(lhs, id, cx, scope);
} else {
double val = sDbl[stackTop];
if (lhs == null || lhs == Undefined.instance) {
throw ScriptRuntime.undefReadError(
lhs, ScriptRuntime.toString(val));
}
Scriptable obj = (lhs instanceof Scriptable)
? (Scriptable)lhs
: ScriptRuntime.toObject(cx, scope, lhs);
int index = (int)val;
if (index == val) {
- result = ScriptRuntime.getElem(obj, index);
+ result = ScriptRuntime.getObjectIndex(obj, index, cx);
} else {
String s = ScriptRuntime.toString(val);
- result = ScriptRuntime.getProp(obj, s);
+ result = ScriptRuntime.getObjectProp(obj, s, cx);
}
}
--stackTop;
stack[stackTop] = result;
return stackTop;
}
@@ -3266,30 +3415,30 @@
if (rhs == DBL_MRK) rhs = doubleWrap(sDbl[stackTop]);
Object lhs = stack[stackTop - 2];
if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop - 2]);
Object result;
Object id = stack[stackTop - 1];
if (id != DBL_MRK) {
- result = ScriptRuntime.setElem(lhs, id, rhs, scope);
+ result = ScriptRuntime.setObjectId(lhs, id, rhs, cx, scope);
} else {
double val = sDbl[stackTop - 1];
if (lhs == null || lhs == Undefined.instance) {
throw ScriptRuntime.undefWriteError(
lhs, ScriptRuntime.toString(val), rhs);
}
Scriptable obj = (lhs instanceof Scriptable)
? (Scriptable)lhs
: ScriptRuntime.toObject(cx, scope, lhs);
int index = (int)val;
if (index == val) {
- result = ScriptRuntime.setElem(obj, index, rhs);
+ result = ScriptRuntime.setObjectIndex(obj, index, rhs, cx);
} else {
String s = ScriptRuntime.toString(val);
- result = ScriptRuntime.setProp(obj, s, rhs);
+ result = ScriptRuntime.setObjectProp(obj, s, rhs, cx);
}
}
stackTop -= 2;
stack[stackTop] = result;
return stackTop;
}
Index: src/org/mozilla/javascript/NativeArray.java
===================================================================
RCS file: /cvsroot/mozilla/js/rhino/src/org/mozilla/javascript/NativeArray.java,v
retrieving revision 1.50
diff -U7 -r1.50 NativeArray.java
--- src/org/mozilla/javascript/NativeArray.java 28 Jul 2004 11:40:37 -0000 1.50
+++ src/org/mozilla/javascript/NativeArray.java 28 Jul 2004 15:32:23 -0000
@@ -422,66 +422,76 @@
/* Support for generic Array-ish objects. Most of the Array
* functions try to be generic; anything that has a length
* property is assumed to be an array.
* getLengthProperty returns 0 if obj does not have the length property
* or its value is not convertible to a number.
*/
- static long getLengthProperty(Scriptable obj) {
+ static long getLengthProperty(Context cx, Scriptable obj) {
// These will both give numeric lengths within Uint32 range.
if (obj instanceof NativeString) {
return ((NativeString)obj).getLength();
} else if (obj instanceof NativeArray) {
return ((NativeArray)obj).getLength();
} else if (!(obj instanceof Scriptable)) {
return 0;
}
- return ScriptRuntime.toUint32(ScriptRuntime
- .getProp(obj, "length", obj));
+ return ScriptRuntime.toUint32(
+ ScriptRuntime.getObjectProp(obj, "length", cx));
+ }
+
+ private static Object setLengthProperty(Context cx, Scriptable target,
+ long length)
+ {
+ return ScriptRuntime.setObjectProp(target, "length",
+ new Double(length), cx);
}
/* Utility functions to encapsulate index > Integer.MAX_VALUE
* handling. Also avoids unnecessary object creation that would
* be necessary to use the general ScriptRuntime.get/setElem
* functions... though this is probably premature optimization.
*/
private static void deleteElem(Scriptable target, long index) {
int i = (int)index;
if (i == index) { target.delete(i); }
else { target.delete(Long.toString(index)); }
}
- private static Object getElem(Scriptable target, long index) {
+ private static Object getElem(Context cx, Scriptable target, long index)
+ {
if (index > Integer.MAX_VALUE) {
String id = Long.toString(index);
- return ScriptRuntime.getProp(target, id);
+ return ScriptRuntime.getObjectProp(target, id, cx);
} else {
- return ScriptRuntime.getElem(target, (int)index);
+ return ScriptRuntime.getObjectIndex(target, (int)index, cx);
}
}
- private static void setElem(Scriptable target, long index, Object value) {
+ private static void setElem(Context cx, Scriptable target, long index,
+ Object value)
+ {
if (index > Integer.MAX_VALUE) {
String id = Long.toString(index);
- ScriptRuntime.setProp(target, id, value);
+ ScriptRuntime.setObjectProp(target, id, value, cx);
} else {
- ScriptRuntime.setElem(target, (int)index, value);
+ ScriptRuntime.setObjectIndex(target, (int)index, value, cx);
}
}
private static String toStringHelper(Context cx, Scriptable scope,
Scriptable thisObj,
boolean toSource, boolean toLocale)
throws JavaScriptException
{
/* It's probably redundant to handle long lengths in this
* function; StringBuffers are limited to 2^31 in java.
*/
- long length = getLengthProperty(thisObj);
+ long length = getLengthProperty(cx, thisObj);
StringBuffer result = new StringBuffer(256);
// whether to return '4,unquoted,5' or '[4, "quoted", 5]'
String separator;
if (toSource) {
@@ -507,15 +517,15 @@
// Make sure cx.iterating is set to null when done
// so we don't leak memory
try {
if (!iterating) {
cx.iterating.put(thisObj, 0); // stop recursion.
for (i = 0; i < length; i++) {
if (i > 0) result.append(separator);
- Object elem = getElem(thisObj, i);
+ Object elem = getElem(cx, thisObj, i);
if (elem == null || elem == Undefined.instance) {
haslast = false;
continue;
}
haslast = true;
if (toSource) {
@@ -534,15 +544,15 @@
} else {
if (toLocale && elem != Undefined.instance &&
elem != null)
{
Scriptable obj = ScriptRuntime.
toObject(cx, thisObj, elem);
Object tls = ScriptRuntime.
- getProp(obj, "toLocaleString", thisObj);
+ getObjectProp(obj, "toLocaleString", cx);
elem = ScriptRuntime.call(cx, tls, elem,
ScriptRuntime.emptyArgs);
}
result.append(ScriptRuntime.toString(elem));
}
}
}
@@ -566,15 +576,15 @@
* See ECMA 15.4.4.3
*/
private static String js_join(Context cx, Scriptable thisObj,
Object[] args)
{
String separator;
- long llength = getLengthProperty(thisObj);
+ long llength = getLengthProperty(cx, thisObj);
int length = (int)llength;
if (llength != length) {
throw Context.reportRuntimeError1(
"msg.arraylength.too.big", String.valueOf(llength));
}
// if no args, use "," as separator
if (args.length < 1 || args[0] == Undefined.instance) {
@@ -584,15 +594,15 @@
}
if (length == 0) {
return "";
}
String[] buf = new String[length];
int total_size = 0;
for (int i = 0; i != length; i++) {
- Object temp = getElem(thisObj, i);
+ Object temp = getElem(cx, thisObj, i);
if (temp != null && temp != Undefined.instance) {
String str = ScriptRuntime.toString(temp);
total_size += str.length();
buf[i] = str;
}
}
total_size += (length - 1) * separator.length();
@@ -612,35 +622,35 @@
/**
* See ECMA 15.4.4.4
*/
private static Scriptable js_reverse(Context cx, Scriptable thisObj,
Object[] args)
{
- long len = getLengthProperty(thisObj);
+ long len = getLengthProperty(cx, thisObj);
long half = len / 2;
for(long i=0; i < half; i++) {
long j = len - i - 1;
- Object temp1 = getElem(thisObj, i);
- Object temp2 = getElem(thisObj, j);
- setElem(thisObj, i, temp2);
- setElem(thisObj, j, temp1);
+ Object temp1 = getElem(cx, thisObj, i);
+ Object temp2 = getElem(cx, thisObj, j);
+ setElem(cx, thisObj, i, temp2);
+ setElem(cx, thisObj, j, temp1);
}
return thisObj;
}
/**
* See ECMA 15.4.4.5
*/
private static Scriptable js_sort(Context cx, Scriptable scope,
Scriptable thisObj, Object[] args)
throws JavaScriptException
{
- long length = getLengthProperty(thisObj);
+ long length = getLengthProperty(cx, thisObj);
if (length <= 1) { return thisObj; }
Object compare;
Object[] cmpBuf;
if (args.length > 0 && Undefined.instance != args[0]) {
@@ -659,22 +669,22 @@
}
else {
int ilength = (int)length;
// copy the JS array into a working array, so it can be
// sorted cheaply.
Object[] working = new Object[ilength];
for (int i = 0; i != ilength; ++i) {
- working[i] = getElem(thisObj, i);
+ working[i] = getElem(cx, thisObj, i);
}
heapsort(cx, scope, working, ilength, compare, cmpBuf);
// copy the working array back into thisObj
for (int i = 0; i != ilength; ++i) {
- setElem(thisObj, i, working[i]);
+ setElem(cx, thisObj, i, working[i]);
}
}
return thisObj;
}
// Return true only if x > y
private static boolean isBigger(Context cx, Scriptable scope,
@@ -786,23 +796,23 @@
throws JavaScriptException
{
if (length <= 1) Kit.codeBug();
// Build heap
for (long i = length / 2; i != 0;) {
--i;
- Object pivot = getElem(target, i);
+ Object pivot = getElem(cx, target, i);
heapify_extended(cx, scope, pivot, target, i, length, cmp, cmpBuf);
}
// Sort heap
for (long i = length; i != 1;) {
--i;
- Object pivot = getElem(target, i);
- setElem(target, i, getElem(target, 0));
+ Object pivot = getElem(cx, target, i);
+ setElem(cx, target, i, getElem(cx, target, 0));
heapify_extended(cx, scope, pivot, target, 0, i, cmp, cmpBuf);
}
}
private static void heapify_extended(Context cx, Scriptable scope,
Object pivot, Scriptable target,
long i, long end,
@@ -810,45 +820,44 @@
throws JavaScriptException
{
for (;;) {
long child = i * 2 + 1;
if (child >= end) {
break;
}
- Object childVal = getElem(target, child);
+ Object childVal = getElem(cx, target, child);
if (child + 1 < end) {
- Object nextVal = getElem(target, child + 1);
+ Object nextVal = getElem(cx, target, child + 1);
if (isBigger(cx, scope, nextVal, childVal, cmp, cmpBuf)) {
++child; childVal = nextVal;
}
}
if (!isBigger(cx, scope, childVal, pivot, cmp, cmpBuf)) {
break;
}
- setElem(target, i, childVal);
+ setElem(cx, target, i, childVal);
i = child;
}
- setElem(target, i, pivot);
+ setElem(cx, target, i, pivot);
}
/**
* Non-ECMA methods.
*/
private static Object js_push(Context cx, Scriptable thisObj,
Object[] args)
{
- long length = getLengthProperty(thisObj);
+ long length = getLengthProperty(cx, thisObj);
for (int i = 0; i < args.length; i++) {
- setElem(thisObj, length + i, args[i]);
+ setElem(cx, thisObj, length + i, args[i]);
}
length += args.length;
- Double lengthObj = new Double(length);
- ScriptRuntime.setProp(thisObj, "length", lengthObj);
+ Object lengthObj = setLengthProperty(cx, thisObj, length);
/*
* If JS1.2, follow Perl4 by returning the last thing pushed.
* Otherwise, return the new array length.
*/
if (cx.getLanguageVersion() == Context.VERSION_1_2)
// if JS1.2 && no arguments, return undefined.
@@ -860,102 +869,102 @@
return lengthObj;
}
private static Object js_pop(Context cx, Scriptable thisObj,
Object[] args)
{
Object result;
- long length = getLengthProperty(thisObj);
+ long length = getLengthProperty(cx, thisObj);
if (length > 0) {
length--;
// Get the to-be-deleted property's value.
- result = getElem(thisObj, length);
+ result = getElem(cx, thisObj, length);
// We don't need to delete the last property, because
// setLength does that for us.
} else {
result = Context.getUndefinedValue();
}
// necessary to match js even when length < 0; js pop will give a
// length property to any target it is called on.
- ScriptRuntime.setProp(thisObj, "length", new Double(length));
+ setLengthProperty(cx, thisObj, length);
return result;
}
private static Object js_shift(Context cx, Scriptable thisObj,
Object[] args)
{
Object result;
- long length = getLengthProperty(thisObj);
+ long length = getLengthProperty(cx, thisObj);
if (length > 0) {
long i = 0;
length--;
// Get the to-be-deleted property's value.
- result = getElem(thisObj, i);
+ result = getElem(cx, thisObj, i);
/*
* Slide down the array above the first element. Leave i
* set to point to the last element.
*/
if (length > 0) {
for (i = 1; i <= length; i++) {
- Object temp = getElem(thisObj, i);
- setElem(thisObj, i - 1, temp);
+ Object temp = getElem(cx, thisObj, i);
+ setElem(cx, thisObj, i - 1, temp);
}
}
// We don't need to delete the last property, because
// setLength does that for us.
} else {
result = Context.getUndefinedValue();
}
- ScriptRuntime.setProp(thisObj, "length", new Double(length));
+ setLengthProperty(cx, thisObj, length);
return result;
}
private static Object js_unshift(Context cx, Scriptable thisObj,
Object[] args)
{
Object result;
- double length = (double)getLengthProperty(thisObj);
+ long length = getLengthProperty(cx, thisObj);
int argc = args.length;
if (args.length > 0) {
/* Slide up the array to make room for args at the bottom */
if (length > 0) {
- for (long last = (long)length - 1; last >= 0; last--) {
- Object temp = getElem(thisObj, last);
- setElem(thisObj, last + argc, temp);
+ for (long last = length - 1; last >= 0; last--) {
+ Object temp = getElem(cx, thisObj, last);
+ setElem(cx, thisObj, last + argc, temp);
}
}
/* Copy from argv to the bottom of the array. */
for (int i = 0; i < args.length; i++) {
- setElem(thisObj, i, args[i]);
+ setElem(cx, thisObj, i, args[i]);
}
/* Follow Perl by returning the new array length. */
length += args.length;
- ScriptRuntime.setProp(thisObj, "length", new Double(length));
+ return setLengthProperty(cx, thisObj, length);
}
- return new Long((long)length);
+ return new Double(length);
}
private static Object js_splice(Context cx, Scriptable scope,
Scriptable thisObj, Object[] args)
{
/* create an empty Array to return. */
scope = getTopLevelScope(scope);
Object result = ScriptRuntime.newObject(cx, scope, "Array", null);
int argc = args.length;
if (argc == 0)
return result;
- long length = getLengthProperty(thisObj);
+ long length = getLengthProperty(cx, thisObj);
/* Convert the first argument into a starting index. */
long begin = toSliceIndex(ScriptRuntime.toInteger(args[0]), length);
argc--;
/* Convert the second argument into count */
long count;
@@ -987,53 +996,52 @@
* as Perl push's first argument, for instance.
*
* JS1.2 emulated Perl too closely and returned a non-Array for
* the single-splice-out case, requiring callers to test and
* wrap in [] if necessary. So JS1.3, default, and other
* versions all return an array of length 1 for uniformity.
*/
- result = getElem(thisObj, begin);
+ result = getElem(cx, thisObj, begin);
} else {
for (long last = begin; last != end; last++) {
Scriptable resultArray = (Scriptable)result;
- Object temp = getElem(thisObj, last);
- setElem(resultArray, last - begin, temp);
+ Object temp = getElem(cx, thisObj, last);
+ setElem(cx, resultArray, last - begin, temp);
}
}
} else if (count == 0
&& cx.getLanguageVersion() == Context.VERSION_1_2)
{
/* Emulate C JS1.2; if no elements are removed, return undefined. */
result = Context.getUndefinedValue();
}
/* Find the direction (up or down) to copy and make way for argv. */
long delta = argc - count;
if (delta > 0) {
for (long last = length - 1; last >= end; last--) {
- Object temp = getElem(thisObj, last);
- setElem(thisObj, last + delta, temp);
+ Object temp = getElem(cx, thisObj, last);
+ setElem(cx, thisObj, last + delta, temp);
}
} else if (delta < 0) {
for (long last = end; last < length; last++) {
- Object temp = getElem(thisObj, last);
- setElem(thisObj, last + delta, temp);
+ Object temp = getElem(cx, thisObj, last);
+ setElem(cx, thisObj, last + delta, temp);
}
}
/* Copy from argv into the hole to complete the splice. */
int argoffset = args.length - argc;
for (int i = 0; i < argc; i++) {
- setElem(thisObj, begin + i, args[i + argoffset]);
+ setElem(cx, thisObj, begin + i, args[i + argoffset]);
}
/* Update length in case we deleted elements from the end. */
- ScriptRuntime.setProp(thisObj, "length",
- new Double(length + delta));
+ setLengthProperty(cx, thisObj, length + delta);
return result;
}
/*
* See Ecma 262v3 15.4.4.4
*/
private static Scriptable js_concat(Context cx, Scriptable scope,
@@ -1046,52 +1054,52 @@
Scriptable result = ctor.construct(cx, scope, ScriptRuntime.emptyArgs);
long length;
long slot = 0;
/* Put the target in the result array; only add it as an array
* if it looks like one.
*/
- if (ScriptRuntime.instanceOf(thisObj, ctor, scope)) {
- length = getLengthProperty(thisObj);
+ if (ScriptRuntime.instanceOf(thisObj, ctor, cx, scope)) {
+ length = getLengthProperty(cx, thisObj);
// Copy from the target object into the result
for (slot = 0; slot < length; slot++) {
- Object temp = getElem(thisObj, slot);
- setElem(result, slot, temp);
+ Object temp = getElem(cx, thisObj, slot);
+ setElem(cx, result, slot, temp);
}
} else {
- setElem(result, slot++, thisObj);
+ setElem(cx, result, slot++, thisObj);
}
/* Copy from the arguments into the result. If any argument
* has a numeric length property, treat it as an array and add
* elements separately; otherwise, just copy the argument.
*/
for (int i = 0; i < args.length; i++) {
- if (ScriptRuntime.instanceOf(args[i], ctor, scope)) {
+ if (ScriptRuntime.instanceOf(args[i], ctor, cx, scope)) {
// ScriptRuntime.instanceOf => instanceof Scriptable
Scriptable arg = (Scriptable)args[i];
- length = getLengthProperty(arg);
+ length = getLengthProperty(cx, arg);
for (long j = 0; j < length; j++, slot++) {
- Object temp = getElem(arg, j);
- setElem(result, slot, temp);
+ Object temp = getElem(cx, arg, j);
+ setElem(cx, result, slot, temp);
}
} else {
- setElem(result, slot++, args[i]);
+ setElem(cx, result, slot++, args[i]);
}
}
return result;
}
private Scriptable js_slice(Context cx, Scriptable thisObj,
Object[] args)
{
Scriptable scope = getTopLevelScope(this);
Scriptable result = ScriptRuntime.newObject(cx, scope, "Array", null);
- long length = getLengthProperty(thisObj);
+ long length = getLengthProperty(cx, thisObj);
long begin, end;
if (args.length == 0) {
begin = 0;
end = length;
} else {
begin = toSliceIndex(ScriptRuntime.toInteger(args[0]), length);
@@ -1099,16 +1107,16 @@
end = length;
} else {
end = toSliceIndex(ScriptRuntime.toInteger(args[1]), length);
}
}
for (long slot = begin; slot < end; slot++) {
- Object temp = getElem(thisObj, slot);
- setElem(result, slot - begin, temp);
+ Object temp = getElem(cx, thisObj, slot);
+ setElem(cx, result, slot - begin, temp);
}
return result;
}
private static long toSliceIndex(double value, long length) {
long result;
Index: src/org/mozilla/javascript/NativeCall.java
===================================================================
RCS file: /cvsroot/mozilla/js/rhino/src/org/mozilla/javascript/NativeCall.java,v
retrieving revision 1.22
diff -U7 -r1.22 NativeCall.java
--- src/org/mozilla/javascript/NativeCall.java 28 Jul 2004 11:40:37 -0000 1.22
+++ src/org/mozilla/javascript/NativeCall.java 28 Jul 2004 15:32:23 -0000
@@ -51,27 +51,23 @@
{
NativeCall obj = new NativeCall();
obj.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed);
}
NativeCall() { }
- NativeCall(Context cx, Scriptable scope, NativeFunction funObj,
+ NativeCall(Scriptable scope, NativeFunction funObj,
Scriptable thisObj, Object[] args)
{
this.funObj = funObj;
this.thisObj = thisObj;
setParentScope(scope);
// leave prototype null
- // save current activation
- this.caller = cx.currentActivation;
- cx.currentActivation = this;
-
this.originalArgs = (args == null) ? ScriptRuntime.emptyArgs : args;
// initialize values of arguments
String[] argNames = funObj.argNames;
if (argNames != null) {
for (int i=0; i < funObj.argCount; i++) {
Object val = i < args.length ? args[i]
@@ -97,53 +93,42 @@
}
public String getClassName()
{
return "Call";
}
- NativeCall getActivation(Function f)
- {
- NativeCall x = this;
- do {
- if (x.funObj == f)
- return x;
- x = x.caller;
- } while (x != null);
- return null;
- }
-
- public Function getFunctionObject()
+ NativeFunction getFunctionObject()
{
return funObj;
}
- public Object[] getOriginalArguments()
+ Object[] getOriginalArguments()
{
return originalArgs;
}
- public NativeCall getCaller()
+ Scriptable getThisObj()
{
- return caller;
+ return thisObj;
}
- public Scriptable getThisObj()
+ protected int findPrototypeId(String s)
{
- return thisObj;
+ return s.equals("constructor") ? Id_constructor : 0;
}
protected void initPrototypeId(int id)
{
String s;
int arity;
if (id == Id_constructor) {
arity=1; s="constructor";
} else {
- throw new IllegalArgumentException(String.valueOf(id));
+ throw new IllegalArgumentException(String.valueOf(id));
}
initPrototypeMethod(CALL_TAG, id, s, arity);
}
public Object execMethod(IdFunction f, Context cx, Scriptable scope,
Scriptable thisObj, Object[] args)
{
@@ -159,23 +144,19 @@
NativeCall result = new NativeCall();
result.setPrototype(getObjectPrototype(scope));
return result;
}
throw new IllegalArgumentException(String.valueOf(id));
}
- protected int findPrototypeId(String s)
- {
- return s.equals("constructor") ? Id_constructor : 0;
- }
-
private static final int
Id_constructor = 1,
MAX_PROTOTYPE_ID = 1;
-
- NativeCall caller;
- NativeFunction funObj;
- Scriptable thisObj;
+ private NativeFunction funObj;
+ private Scriptable thisObj;
private Object[] originalArgs;
+
+ NativeCall parentActivationCall;
+ Scriptable parentActivationScope;
}
Index: src/org/mozilla/javascript/NativeFunction.java
===================================================================
RCS file: /cvsroot/mozilla/js/rhino/src/org/mozilla/javascript/NativeFunction.java,v
retrieving revision 1.55
diff -U7 -r1.55 NativeFunction.java
--- src/org/mozilla/javascript/NativeFunction.java 18 Mar 2004 13:37:29 -0000 1.55
+++ src/org/mozilla/javascript/NativeFunction.java 28 Jul 2004 15:32:23 -0000
@@ -83,15 +83,16 @@
}
}
public int getLength()
{
if (version != Context.VERSION_1_2)
return argCount;
- NativeCall activation = getActivation(Context.getContext());
+ Context cx = Context.getContext();
+ NativeCall activation = ScriptRuntime.findFunctionActivation(cx, this);
if (activation == null)
return argCount;
return activation.getOriginalArguments().length;
}
public int getArity()
{
Index: src/org/mozilla/javascript/NativeGlobal.java
===================================================================
RCS file: /cvsroot/mozilla/js/rhino/src/org/mozilla/javascript/NativeGlobal.java,v
retrieving revision 1.70
diff -U7 -r1.70 NativeGlobal.java
--- src/org/mozilla/javascript/NativeGlobal.java 28 Jul 2004 11:40:37 -0000 1.70
+++ src/org/mozilla/javascript/NativeGlobal.java 28 Jul 2004 15:32:23 -0000
@@ -34,15 +34,16 @@
* the provisions above, a recipient may use your version of this
* file under either the NPL or the GPL.
*/
package org.mozilla.javascript;
import java.io.Serializable;
-import java.lang.reflect.Method;
+
+import org.mozilla.javascript.xml.XMLLib;
/**
* This class implements the global native object (function and value
* properties only).
*
* See ECMA 15.1.[12].
*
@@ -79,14 +80,17 @@
break;
case Id_isFinite:
name = "isFinite";
break;
case Id_isNaN:
name = "isNaN";
break;
+ case Id_isXMLName:
+ name = "isXMLName";
+ break;
case Id_parseFloat:
name = "parseFloat";
break;
case Id_parseInt:
name = "parseInt";
arity = 2;
break;
@@ -191,14 +195,22 @@
// The global method isNaN, as per ECMA-262 15.1.2.6.
if (args.length < 1)
return Boolean.TRUE;
double d = ScriptRuntime.toNumber(args[0]);
return (d != d) ? Boolean.TRUE : Boolean.FALSE;
}
+ case Id_isXMLName: {
+ Object name = (args.length == 0)
+ ? Undefined.instance : args[0];
+ XMLLib xmlLib = XMLLib.extractFromScope(scope);
+ return ScriptRuntime.wrapBoolean(
+ xmlLib.isXMLName(cx, name));
+ }
+
case Id_parseFloat:
return js_parseFloat(args);
case Id_parseInt:
return js_parseInt(args);
case Id_unescape:
@@ -752,16 +764,17 @@
Id_decodeURIComponent = 2,
Id_encodeURI = 3,
Id_encodeURIComponent = 4,
Id_escape = 5,
Id_eval = 6,
Id_isFinite = 7,
Id_isNaN = 8,
- Id_parseFloat = 9,
- Id_parseInt = 10,
- Id_unescape = 11,
- Id_uneval = 12,
+ Id_isXMLName = 9,
+ Id_parseFloat = 10,
+ Id_parseInt = 11,
+ Id_unescape = 12,
+ Id_uneval = 13,
- LAST_SCOPE_FUNCTION_ID = 12,
+ LAST_SCOPE_FUNCTION_ID = 13,
- Id_new_CommonError = 13;
+ Id_new_CommonError = 14;
}
Index: src/org/mozilla/javascript/NativeJavaObject.java
===================================================================
RCS file: /cvsroot/mozilla/js/rhino/src/org/mozilla/javascript/NativeJavaObject.java,v
retrieving revision 1.62
diff -U7 -r1.62 NativeJavaObject.java
--- src/org/mozilla/javascript/NativeJavaObject.java 28 Jul 2004 09:49:19 -0000 1.62
+++ src/org/mozilla/javascript/NativeJavaObject.java 28 Jul 2004 15:32:23 -0000
@@ -358,18 +358,18 @@
return CONVERSION_NONTRIVIAL;
}
}
break;
case JSTYPE_OBJECT:
// Other objects takes #1-#3 spots
- if (to == fromObj.getClass()) {
- // No conversion required
- return 1;
- }
+ if (to == fromObj.getClass()) {
+ // No conversion required
+ return 1;
+ }
if (to.isArray()) {
if (fromObj instanceof NativeArray) {
// This is a native array conversion to a java array
// Array conversions are all equal, and preferable to object
// and string conversion, per LC3.
return 1;
}
@@ -398,15 +398,14 @@
else if (to.isPrimitive() && to != Boolean.TYPE) {
return 3 + getSizeRank(to);
}
break;
}
return CONVERSION_NONE;
-
}
static int getSizeRank(Class aType) {
if (aType == Double.TYPE) {
return 1;
}
else if (aType == Float.TYPE) {
Index: src/org/mozilla/javascript/NativeWith.java
===================================================================
RCS file: /cvsroot/mozilla/js/rhino/src/org/mozilla/javascript/NativeWith.java,v
retrieving revision 1.22
diff -U7 -r1.22 NativeWith.java
--- src/org/mozilla/javascript/NativeWith.java 28 Jul 2004 13:27:39 -0000 1.22
+++ src/org/mozilla/javascript/NativeWith.java 28 Jul 2004 15:32:23 -0000
@@ -143,14 +143,23 @@
return prototype.getDefaultValue(typeHint);
}
public boolean hasInstance(Scriptable value) {
return prototype.hasInstance(value);
}
+ /**
+ * Must return null to continue looping or the final collection result.
+ */
+ public Object updateDotQuery(boolean value)
+ {
+ // NativeWith itself does not support it
+ throw new IllegalStateException();
+ }
+
public Object execMethod(IdFunction f, Context cx, Scriptable scope,
Scriptable thisObj, Object[] args)
{
if (f.hasTag(FTAG)) {
if (f.methodId() == Id_constructor) {
throw Context.reportRuntimeError1("msg.cant.call.indirect", "With");
}
Index: src/org/mozilla/javascript/Parser.java
===================================================================
RCS file: /cvsroot/mozilla/js/rhino/src/org/mozilla/javascript/Parser.java,v
retrieving revision 1.82
diff -U7 -r1.82 Parser.java
--- src/org/mozilla/javascript/Parser.java 5 Jul 2004 15:07:25 -0000 1.82
+++ src/org/mozilla/javascript/Parser.java 28 Jul 2004 15:32:23 -0000
@@ -17,15 +17,18 @@
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Mike Ang
* Igor Bukanov
+ * Ethan Hugg
+ * Terry Lucas
* Mike McCabe
+ * Milen Nankov
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License (the "GPL"), in which case the
* provisions of the GPL are applicable instead of those above.
* If you wish to allow use of your version of this file only
* under the terms of the GPL and not to allow others to use your
* version of this file under the NPL, indicate your decision by
@@ -99,21 +102,26 @@
throws IOException
{
this.ts = new TokenStream(compilerEnv, sourceReader, null,
sourceLocation, lineno);
return parse();
}
+ private void mustHaveXML()
+ {
+ if (!compilerEnv.isXmlAvailable()) {
+ reportError("msg.XML.not.available");
+ }
+ }
+
private void mustMatchToken(int toMatch, String messageId)
throws IOException, ParserException
{
- int tt;
- if ((tt = ts.getToken()) != toMatch) {
+ if (!ts.matchToken(toMatch)) {
reportError(messageId);
- ts.ungetToken(tt); // In case the parser decides to continue
}
}
void reportError(String messageId)
{
this.ok = false;
ts.reportCurrentLineError(Context.getMessage0(messageId));
@@ -206,21 +214,14 @@
}
boolean insideFunction()
{
return nestingOfFunction != 0;
}
- void setRequiresActivation()
- {
- if (insideFunction()) {
- ((FunctionNode)currentScriptOrFn).setRequiresActivation();
- }
- }
-
/*
* The C version of this function takes an argument list,
* which doesn't seem to be needed for tree generation...
* it'd only be useful for checking argument hiding, which
* I'm not doing anyway...
*/
private Node parseFunctionBody()
@@ -597,24 +598,35 @@
Node cond = condition();
pn = nf.createDoWhile(body, cond, lineno);
break;
}
case Token.FOR: {
+ boolean isForEach = false;
skipsemi = true;
decompiler.addToken(Token.FOR);
int lineno = ts.getLineno();
Node init; // Node init is also foo in 'foo in Object'
Node cond; // Node cond is also object in 'foo in Object'
Node incr = null; // to kill warning
Node body;
+ // See if this is a for each () instead of just a for ()
+ if (ts.matchToken(Token.NAME)) {
+ decompiler.addName(ts.getString());
+ if (ts.getString().equals("each")) {
+ isForEach = true;
+ } else {
+ reportError("msg.no.paren.for");
+ }
+ }
+
mustMatchToken(Token.LP, "msg.no.paren.for");
decompiler.addToken(Token.LP);
tt = ts.peekToken();
if (tt == Token.SEMI) {
init = nf.createLeaf(Token.EMPTY);
} else {
if (tt == Token.VAR) {
@@ -654,15 +666,15 @@
decompiler.addToken(Token.RP);
decompiler.addEOL(Token.LC);
body = statement();
decompiler.addEOL(Token.RC);
if (incr == null) {
// cond could be null if 'in obj' got eaten by the init node.
- pn = nf.createForIn(init, cond, body, lineno);
+ pn = nf.createForIn(init, cond, body, isForEach, lineno);
} else {
pn = nf.createFor(init, cond, incr, body, lineno);
}
break;
}
case Token.TRY: {
@@ -838,14 +850,41 @@
break;
case Token.FUNCTION: {
pn = function(FunctionNode.FUNCTION_EXPRESSION_STATEMENT);
break;
}
+ case Token.DEFAULT :
+ mustHaveXML();
+ int nsLine = ts.getLineno();
+
+ if (!(ts.matchToken(Token.NAME)
+ && ts.getString().equals("xml")))
+ {
+ reportError("msg.bad.namespace");
+ }
+ decompiler.addName(ts.getString());
+
+ if (!(ts.matchToken(Token.NAME)
+ && ts.getString().equals("namespace")))
+ {
+ reportError("msg.bad.namespace");
+ }
+ decompiler.addName(ts.getString());
+
+ if (!ts.matchToken(Token.ASSIGN)) {
+ reportError("msg.bad.namespace");
+ }
+ decompiler.addToken(Token.ASSIGN);
+
+ Node expr = expr(false);
+ pn = nf.createDefaultNamespace(expr, nsLine);
+ break;
+
default: {
int lastExprType = tt;
int tokenno = ts.getTokenno();
ts.ungetToken(tt);
int lineno = ts.getLineno();
pn = expr(false);
@@ -1199,14 +1238,22 @@
case Token.DELPROP:
decompiler.addToken(Token.DELPROP);
return nf.createUnary(Token.DELPROP, unaryExpr());
case Token.ERROR:
break;
+ // XML stream encountered in expression.
+ case Token.LT:
+ if (compilerEnv.isXmlAvailable()) {
+ Node pn = xmlInitializer();
+ return memberExprTail(true, pn);
+ }
+ // Fall thru to the default handling of RELOP
+
default:
ts.ungetToken(tt);
int lineno = ts.getLineno();
Node pn = memberExpr(true);
@@ -1228,14 +1275,82 @@
}
return pn;
}
return nf.createName("err"); // Only reached on error. Try to continue.
}
+ private Node xmlInitializer() throws IOException
+ {
+ int tt = ts.getFirstXMLToken();
+ if (tt != Token.XML && tt != Token.XMLEND) {
+ reportError("msg.syntax");
+ return null;
+ }
+
+ /* Make a NEW node to append to. */
+ Node pnXML = nf.createLeaf(Token.NEW);
+ decompiler.addToken(Token.NEW);
+ decompiler.addToken(Token.DOT);
+
+ String xml = ts.getString();
+ boolean fAnonymous = xml.trim().startsWith("<>");
+
+ decompiler.addName(fAnonymous ? "XMLList" : "XML");
+ Node pn = nf.createName(fAnonymous ? "XMLList" : "XML");
+ nf.addChildToBack(pnXML, pn);
+
+ pn = null;
+ Node expr;
+ for (;;tt = ts.getNextXMLToken()) {
+ switch (tt) {
+ case Token.XML:
+ xml = ts.getString();
+ decompiler.addString(xml);
+ mustMatchToken(Token.LC, "msg.syntax");
+ decompiler.addToken(Token.LC);
+ expr = (ts.peekToken() == Token.RC)
+ ? nf.createString("")
+ : expr(false);
+ mustMatchToken(Token.RC, "msg.syntax");
+ decompiler.addToken(Token.RC);
+ if (pn == null) {
+ pn = nf.createString(xml);
+ } else {
+ pn = nf.createBinary(Token.ADD, pn, nf.createString(xml));
+ }
+ if (ts.isXMLAttribute()) {
+ pn = nf.createBinary(Token.ADD, pn, nf.createString("\""));
+ expr = nf.createUnary(Token.ESCXMLATTR, expr);
+ pn = nf.createBinary(Token.ADD, pn, expr);
+ pn = nf.createBinary(Token.ADD, pn, nf.createString("\""));
+ } else {
+ expr = nf.createUnary(Token.ESCXMLTEXT, expr);
+ pn = nf.createBinary(Token.ADD, pn, expr);
+ }
+ break;
+ case Token.XMLEND:
+ xml = ts.getString();
+ decompiler.addString(xml);
+ if (pn == null) {
+ pn = nf.createString(xml);
+ } else {
+ pn = nf.createBinary(Token.ADD, pn, nf.createString(xml));
+ }
+
+ nf.addChildToBack(pnXML, pn);
+ return pnXML;
+ default:
+ ts.ungetToken(tt);
+ reportError("msg.syntax");
+ return null;
+ }
+ }
+ }
+
private void argumentList(Node listNode)
throws IOException, ParserException
{
boolean matched;
ts.allowRegExp = true;
matched = ts.matchToken(Token.RP);
ts.allowRegExp = false;
@@ -1298,41 +1413,199 @@
return memberExprTail(allowCallSyntax, pn);
}
private Node memberExprTail(boolean allowCallSyntax, Node pn)
throws IOException, ParserException
{
int tt;
- while ((tt = ts.getToken()) > Token.EOF) {
- if (tt == Token.DOT) {
+ tailLoop:
+ while ((tt = ts.getToken()) != Token.EOF) {
+ switch (tt) {
+ case Token.DOT: {
decompiler.addToken(Token.DOT);
- mustMatchToken(Token.NAME, "msg.no.name.after.dot");
- String s = ts.getString();
- decompiler.addName(s);
- pn = nf.createBinary(Token.DOT, pn, nf.createName(s));
- } else if (tt == Token.LB) {
+ Node n;
+ if (compilerEnv.isXmlAvailable()) {
+ n = nameOrPropertyIdentifier();
+ } else {
+ mustMatchToken(Token.NAME, "msg.no.name.after.dot");
+ String s = ts.getString();
+ decompiler.addName(s);
+ n = nf.createName(s);
+ }
+ pn = nf.createBinary(Token.DOT, pn, n);
+ break;
+ }
+
+ case Token.DOTDOT: {
+ mustHaveXML();
+ decompiler.addToken(Token.DOTDOT);
+ Node n = nameOrPropertyIdentifier();
+ pn = nf.createBinary(Token.DOTDOT, pn, n);
+ break;
+ }
+
+ case Token.DOTQUERY:
+ mustHaveXML();
+ decompiler.addToken(Token.DOTQUERY);
+ pn = nf.createDotQuery(pn, expr(false), ts.getLineno());
+ mustMatchToken(Token.RP, "msg.no.paren");
+ break;
+
+ case Token.LB:
decompiler.addToken(Token.LB);
pn = nf.createBinary(Token.LB, pn, expr(false));
-
mustMatchToken(Token.RB, "msg.no.bracket.index");
decompiler.addToken(Token.RB);
- } else if (allowCallSyntax && tt == Token.LP) {
- /* make a call node */
+ break;
+
+ case Token.LP:
+ if (!allowCallSyntax) {
+ ts.ungetToken(tt);
+ break tailLoop;
+ }
decompiler.addToken(Token.LP);
pn = nf.createCallOrNew(Token.CALL, pn);
-
/* Add the arguments to pn, if any are supplied. */
argumentList(pn);
- } else {
+ break;
+
+ default:
ts.ungetToken(tt);
+ break tailLoop;
+ }
+ }
+ return pn;
+ }
+
+ private Node nameOrPropertyIdentifier()
+ throws IOException, ParserException
+ {
+ Node pn;
+ int tt = ts.getToken();
+
+ switch (tt) {
+ // handles: name, ns::name, ns::*, ns::[expr]
+ case Token.NAME: {
+ String s = ts.getString();
+ decompiler.addName(s);
+ pn = nameOrQualifiedName(s, false);
+ break;
+ }
+
+ // handles: *, *::name, *::*, *::[expr]
+ case Token.MUL:
+ decompiler.addName("*");
+ pn = nameOrQualifiedName("*", false);
+ break;
+
+ // handles: '@attr', '@ns::attr', '@ns::*', '@ns::*',
+ // '@::attr', '@::*', '@*', '@*::attr', '@*::*'
+ case Token.XMLATTR:
+ decompiler.addToken(Token.XMLATTR);
+ pn = attributeIdentifier();
+ break;
+
+ default:
+ reportError("msg.no.name.after.dot");
+ pn = nf.createName("?");
+ }
+
+ return pn;
+ }
+
+ /*
+ * Xml attribute expression:
+ * '@attr', '@ns::attr', '@ns::*', '@ns::*', '@*', '@*::attr', '@*::*'
+ */
+ private Node attributeIdentifier()
+ throws IOException
+ {
+ Node pn;
+ int tt = ts.getToken();
+
+ switch (tt) {
+ // handles: @name, @ns::name, @ns::*, @ns::[expr]
+ case Token.NAME: {
+ String s = ts.getString();
+ decompiler.addName(s);
+ pn = nf.createAttributeName(nameOrQualifiedName(s, false));
+ break;
+ }
+
+ // handles: @*, @*::name, @*::*, @*::[expr]
+ case Token.MUL:
+ decompiler.addName("*");
+ pn = nf.createAttributeName(nameOrQualifiedName("*", false));
+ break;
+
+ // handles @[expr]
+ case Token.LB:
+ decompiler.addToken(Token.LB);
+ pn = nf.createAttributeExpr(expr(false));
+ mustMatchToken(Token.RB, "msg.no.bracket.index");
+ decompiler.addToken(Token.RB);
+ break;
+
+ default:
+ reportError("msg.no.name.after.xmlAttr");
+ pn = nf.createAttributeExpr(nf.createString("?"));
+ break;
+ }
+
+ return pn;
+ }
+
+ /**
+ * Check if :: follows name in which case it becomes qualified name
+ */
+ private Node nameOrQualifiedName(String name, boolean primaryContext)
+ throws IOException, ParserException
+ {
+ colonColonCheck:
+ if (ts.matchToken(Token.COLONCOLON)) {
+ decompiler.addToken(Token.COLONCOLON);
+ Node pn;
+ int tt = ts.getToken();
+
+ switch (tt) {
+ // handles name::name
+ case Token.NAME: {
+ String s = ts.getString();
+ decompiler.addName(s);
+ pn = nf.createQualifiedName(name, s);
break;
+ }
+
+ // handles name::*
+ case Token.MUL:
+ decompiler.addName("*");
+ pn = nf.createQualifiedName(name, "*");
+ break;
+
+ // handles name::[expr]
+ case Token.LB:
+ decompiler.addToken(Token.LB);
+ pn = nf.createQualifiedExpr(name, expr(false));
+ mustMatchToken(Token.RB, "msg.no.bracket.index");
+ decompiler.addToken(Token.RB);
+ break;
+
+ default:
+ reportError("msg.no.name.after.coloncolon");
+ break colonColonCheck;
+ }
+
+ if (primaryContext) {
+ pn = nf.createXMLPrimary(pn);
}
+ return pn;
}
- return pn;
+
+ return nf.createName(name);
}
private Node primaryExpr()
throws IOException, ParserException
{
int tt;
@@ -1448,18 +1721,30 @@
* think) in the C IR as 'function call.' */
decompiler.addToken(Token.LP);
pn = expr(false);
decompiler.addToken(Token.RP);
mustMatchToken(Token.RP, "msg.no.paren");
return pn;
- case Token.NAME:
+ case Token.XMLATTR:
+ mustHaveXML();
+ decompiler.addToken(Token.XMLATTR);
+ pn = attributeIdentifier();
+ return nf.createXMLPrimary(pn);
+
+ case Token.NAME: {
String name = ts.getString();
decompiler.addName(name);
- return nf.createName(name);
+ if (compilerEnv.isXmlAvailable()) {
+ pn = nameOrQualifiedName(name, true);
+ } else {
+ pn = nf.createName(name);
+ }
+ return pn;
+ }
case Token.NUMBER:
double n = ts.getNumber();
decompiler.addNumber(n);
return nf.createNumber(n);
case Token.STRING:
@@ -1503,15 +1788,15 @@
CompilerEnvirons compilerEnv;
private TokenStream ts;
private IRFactory nf;
private boolean ok; // Did the parse encounter an error?
- private ScriptOrFnNode currentScriptOrFn;
+ ScriptOrFnNode currentScriptOrFn;
private int nestingOfFunction;
private int nestingOfWith;
private Decompiler decompiler;
private String encodedSource;
Index: src/org/mozilla/javascript/ScriptRuntime.java
===================================================================
RCS file: /cvsroot/mozilla/js/rhino/src/org/mozilla/javascript/ScriptRuntime.java,v
retrieving revision 1.183
diff -U7 -r1.183 ScriptRuntime.java
--- src/org/mozilla/javascript/ScriptRuntime.java 28 Jul 2004 09:51:02 -0000 1.183
+++ src/org/mozilla/javascript/ScriptRuntime.java 28 Jul 2004 15:32:23 -0000
@@ -18,16 +18,19 @@
* Copyright (C) 1997-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Patrick Beard
* Norris Boyd
* Igor Bukanov
+ * Ethan Hugg
* Roger Lawrence
+ * Terry Lucas
* Frank Mitchell
+ * Milen Nankov
* Andrew Wason
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License (the "GPL"), in which case the
* provisions of the GPL are applicable instead of those above.
* If you wish to allow use of your version of this file only
* under the terms of the GPL and not to allow others to use your
@@ -38,14 +41,17 @@
* file under either the NPL or the GPL.
*/
package org.mozilla.javascript;
import java.lang.reflect.*;
+import org.mozilla.javascript.xml.XMLObject;
+import org.mozilla.javascript.xml.XMLLib;
+
/**
* This is the class that implements the runtime.
*
* @author Norris Boyd
*/
public class ScriptRuntime {
@@ -713,14 +719,17 @@
{
if (val instanceof Scriptable) {
if (val == Undefined.instance) {
throw typeError0("msg.undef.to.object");
}
return (Scriptable) val;
}
+ if (val == null) {
+ throw typeError0("msg.null.to.object");
+ }
String className = val instanceof String ? "String" :
val instanceof Number ? "Number" :
val instanceof Boolean ? "Boolean" :
null;
if (className != null) {
Object[] args = { val };
@@ -728,17 +737,14 @@
return newObject(cx, scope, className, args);
}
// Extension: Wrap as a LiveConnect object.
Object wrapped = cx.getWrapFactory().wrap(cx, scope, val, null);
if (wrapped instanceof Scriptable)
return (Scriptable) wrapped;
- if (wrapped == null) {
- throw typeError0("msg.null.to.object");
- }
throw errorWithClassName("msg.invalid.type", val);
}
/**
* @deprecated Use {@link #toObject(Context, Scriptable, Object)} instead.
*/
public static Scriptable toObject(Context cx, Scriptable scope, Object val,
@@ -966,55 +972,63 @@
}
Scriptable errorObject = cx.newObject(scope, errorName, args);
ScriptableObject.putProperty(errorObject, "name", errorName);
return errorObject;
}
- public static Object getProp(Object obj, String id, Scriptable scope)
- {
- if (obj == null || obj == Undefined.instance) {
- throw undefReadError(obj, id);
- }
- Scriptable sobj;
- if (obj instanceof Scriptable) {
- sobj = (Scriptable)obj;
+ // XXX: this is until setDefaultNamespace will learn how to store NS
+ // properly and separates namespace form Scriptable.get etc.
+ private static final String DEFAULT_NS_TAG = "__default_namespace__";
+
+ public static Object setDefaultNamespace(Object namespace, Context cx)
+ {
+ Scriptable scope = cx.currentActivationScope;
+ if (scope == null)
+ throw new IllegalStateException();
+
+ XMLLib xmlLib = currentXMLLib(cx);
+ Object ns = xmlLib.toDefaultXmlNamespace(cx, namespace);
+
+ // XXX : this should be in separated namesapce from Scriptable.get/put
+ if (!scope.has(DEFAULT_NS_TAG, scope)) {
+ // XXX: this is racy of cause
+ ScriptableObject.defineProperty(scope, DEFAULT_NS_TAG, ns,
+ ScriptableObject.PERMANENT
+ | ScriptableObject.DONTENUM);
} else {
- sobj = toObject(scope, obj);
+ scope.put(DEFAULT_NS_TAG, scope, ns);
}
- return getProp(sobj, id);
- }
- public static Object setProp(Object obj, String id, Object value,
- Scriptable scope)
- {
- if (obj == null || obj == Undefined.instance) {
- throw undefWriteError(obj, id, value);
- }
- Scriptable sobj;
- if (obj instanceof Scriptable) {
- sobj = (Scriptable)obj;
- } else {
- sobj = toObject(scope, obj);
- }
- return setProp(sobj, id, value);
- }
-
- static Object getProp(Scriptable obj, String id)
- {
- Object result = ScriptableObject.getProperty(obj, id);
- if (result != Scriptable.NOT_FOUND)
- return result;
return Undefined.instance;
}
- static Object setProp(Scriptable obj, String id, Object value)
+ public static Object searchDefaultNamespace(Context cx)
{
- ScriptableObject.putProperty(obj, id, value);
- return value;
+ Scriptable scope = cx.currentActivationScope;
+ if (scope == null) {
+ return null;
+ }
+ Object nsObject;
+ for (;;) {
+ Scriptable parent = scope.getParentScope();
+ if (parent == null) {
+ nsObject = ScriptableObject.getProperty(scope, DEFAULT_NS_TAG);
+ if (nsObject == Scriptable.NOT_FOUND) {
+ return null;
+ }
+ break;
+ }
+ nsObject = scope.get(DEFAULT_NS_TAG, scope);
+ if (nsObject != Scriptable.NOT_FOUND) {
+ break;
+ }
+ scope = parent;
+ }
+ return nsObject;
}
public static Object getTopLevelProp(Scriptable scope, String id) {
scope = ScriptableObject.getTopLevelScope(scope);
return ScriptableObject.getProperty(scope, id);
}
@@ -1119,14 +1133,65 @@
}
}
}
return -1L;
}
/**
+ * If str is a decimal presentation of Uint32 value, return it as long.
+ * Othewise return -1L;
+ */
+ public static long testUint32String(String str)
+ {
+ // The length of the decimal string representation of
+ // UINT32_MAX_VALUE, 4294967296
+ final int MAX_VALUE_LENGTH = 10;
+
+ int len = str.length();
+ if (1 <= len && len <= MAX_VALUE_LENGTH) {
+ int c = str.charAt(0);
+ c -= '0';
+ if (c == 0) {
+ // Note that 00,01 etc. are not valid Uint32 presentations
+ return (len == 1) ? 0L : -1L;
+ }
+ if (1 <= c && c <= 9) {
+ long v = c;
+ for (int i = 1; i != len; ++i) {
+ c = str.charAt(i) - '0';
+ if (!(0 <= c && c <= 9)) {
+ return -1;
+ }
+ v = 10 * v + c;
+ }
+ // Check for overflow
+ if ((v >>> 32) == 0) {
+ return v;
+ }
+ }
+ }
+ return -1;
+ }
+
+ public static void storeUint32Result(Context cx, long value)
+ {
+ if ((value >>> 32) != 0)
+ throw new IllegalArgumentException();
+ cx.scratchLong = value;
+ }
+
+ public static long lastUint32Result(Context cx)
+ {
+ long value = cx.scratchLong;
+ if ((value >>> 32) != 0)
+ throw new IllegalStateException();
+ return value;
+ }
+
+ /**
* If s represents index, then return index value wrapped as Integer
* and othewise return s.
*/
static Object getIndexObject(String s)
{
long indexTest = indexFromString(s);
if (indexTest >= 0) {
@@ -1176,16 +1241,37 @@
String s = toString(id);
long indexTest = indexFromString(s);
if (indexTest >= 0)
return (int)indexTest;
return 0;
}
+ public static Object getObjectId(Object obj, Object id,
+ Context cx, Scriptable scope)
+ {
+ if (obj == null || obj == Undefined.instance) {
+ throw undefReadError(obj, id);
+ }
+ Scriptable sobj;
+ if (obj instanceof Scriptable) {
+ sobj = (Scriptable)obj;
+ } else {
+ sobj = toObject(cx, scope, obj);
+ }
+ return getObjectId(sobj, id, cx);
+ }
+
+ public static Object getObjectId(Scriptable obj, Object id,
+ Context cx)
+ {
+ if (obj instanceof XMLObject) {
+ XMLObject xmlObject = (XMLObject)obj;
+ return xmlObject.ecmaGet(cx, id);
+ }
- public static Object getElem(Object obj, Object id, Scriptable scope) {
int index;
String s;
if (id instanceof Number) {
double d = ((Number) id).doubleValue();
index = (int) d;
s = ((double) index) == d ? null : toString(id);
} else {
@@ -1194,42 +1280,111 @@
if (indexTest >= 0) {
index = (int)indexTest;
s = null;
} else {
index = 0;
}
}
+
+ Object result;
+ if (s != null) {
+ result = ScriptableObject.getProperty(obj, s);
+ } else {
+ result = ScriptableObject.getProperty(obj, index);
+ }
+
+ if (result == Scriptable.NOT_FOUND) {
+ result = Undefined.instance;
+ }
+
+ return result;
+ }
+
+ /**
+ * Version of getObjectId when id is string which is not decimal
+ * presentation of int32.
+ */
+ public static Object getObjectProp(Object obj, String property,
+ Context cx, Scriptable scope)
+ {
if (obj == null || obj == Undefined.instance) {
- String property = (s != null) ? s : Integer.toString(index);
throw undefReadError(obj, property);
}
- Scriptable start = toObject(scope, obj);
- if (s != null) {
- return getProp(start, s);
- }
- else {
- return getElem(start, index);
+ Scriptable sobj;
+ if (obj instanceof Scriptable) {
+ sobj = (Scriptable)obj;
+ } else {
+ sobj = toObject(cx, scope, obj);
}
+ return getObjectProp(sobj, property, cx);
}
+ public static Object getObjectProp(Scriptable obj, String property,
+ Context cx)
+ {
+ if (obj instanceof XMLObject) {
+ XMLObject xmlObject = (XMLObject)obj;
+ return xmlObject.ecmaGet(cx, property);
+ }
+
+ Object result = ScriptableObject.getProperty(obj, property);
+ if (result == Scriptable.NOT_FOUND) {
+ result = Undefined.instance;
+ }
+
+ return result;
+ }
/*
* A cheaper and less general version of the above for well-known argument
* types.
*/
- public static Object getElem(Scriptable obj, int index) {
+ public static Object getObjectIndex(Scriptable obj, int index,
+ Context cx)
+ {
+ if (obj instanceof XMLObject) {
+ XMLObject xmlObject = (XMLObject)obj;
+ return xmlObject.ecmaGet(cx, new Integer(index));
+ }
+
Object result = ScriptableObject.getProperty(obj, index);
- if (result != Scriptable.NOT_FOUND)
- return result;
- return Undefined.instance;
+ if (result == Scriptable.NOT_FOUND) {
+ result = Undefined.instance;
+ }
+
+ return result;
+ }
+
+ /*
+ * Generic assignment to member element.
+ */
+ public static Object setObjectId(Object obj, Object id, Object value,
+ Context cx, Scriptable scope)
+ {
+ if (obj == null || obj == Undefined.instance) {
+ throw undefWriteError(obj, id, value);
+ }
+ Scriptable sobj;
+ if (obj instanceof Scriptable) {
+ sobj = (Scriptable)obj;
+ } else {
+ sobj = toObject(cx, scope, obj);
+ }
+ return setObjectId(sobj, id, value, cx);
}
- public static Object setElem(Object obj, Object id, Object value,
- Scriptable scope)
+ public static Object setObjectId(Scriptable obj, Object id, Object value,
+ Context cx)
{
+ if (obj instanceof XMLObject) {
+ XMLObject xmlObject = (XMLObject)obj;
+ xmlObject.ecmaPut(cx, id, value);
+ return value;
+ }
+
int index;
String s;
if (id instanceof Number) {
double d = ((Number) id).doubleValue();
index = (int) d;
s = ((double) index) == d ? null : toString(id);
} else {
@@ -1238,70 +1393,97 @@
if (indexTest >= 0) {
index = (int)indexTest;
s = null;
} else {
index = 0;
}
}
+ if (s != null) {
+ ScriptableObject.putProperty(obj, s, value);
+ } else {
+ ScriptableObject.putProperty(obj, index, value);
+ }
+ return value;
+ }
+
+ /**
+ * Version of setObjectId when id is string which is not decimal
+ * presentation of int32.
+ */
+ public static Object setObjectProp(Object obj, String property,
+ Object value,
+ Context cx, Scriptable scope)
+ {
if (obj == null || obj == Undefined.instance) {
- String property = (s != null) ? s : Integer.toString(index);
throw undefWriteError(obj, property, value);
}
- Scriptable start;
+ Scriptable sobj;
if (obj instanceof Scriptable) {
- start = (Scriptable) obj;
+ sobj = (Scriptable)obj;
} else {
- start = toObject(scope, obj);
+ sobj = toObject(cx, scope, obj);
}
- if (s != null) {
- return setProp(start, s, value, scope);
- }
- else {
- return setElem(start, index, value);
+ return setObjectProp(sobj, property, value, cx);
+ }
+
+ public static Object setObjectProp(Scriptable obj, String property,
+ Object value, Context cx)
+ {
+ if (obj instanceof XMLObject) {
+ XMLObject xmlObject = (XMLObject)obj;
+ xmlObject.ecmaPut(cx, property, value);
+ } else {
+ ScriptableObject.putProperty(obj, property, value);
}
+ return value;
}
/*
* A cheaper and less general version of the above for well-known argument
* types.
*/
- public static Object setElem(Scriptable obj, int index, Object value) {
- ScriptableObject.putProperty(obj, index, value);
+ public static Object setObjectIndex(Scriptable obj, int index, Object value,
+ Context cx)
+ {
+ if (obj instanceof XMLObject) {
+ XMLObject xmlObject = (XMLObject)obj;
+ xmlObject.ecmaPut(cx, new Integer(index), value);
+ } else {
+ ScriptableObject.putProperty(obj, index, value);
+ }
return value;
}
public static Object getReference(Object obj)
{
- if (!(obj instanceof Reference)) {
- String msg = getMessage1("msg.no.ref.to.get", toString(obj));
- throw constructError("ReferenceError", msg);
- }
Reference ref = (Reference)obj;
return ref.get();
}
public static Object setReference(Object obj, Object value)
{
- if (!(obj instanceof Reference)) {
- String msg = getMessage2("msg.no.ref.to.set",
- toString(obj), toString(value));
- throw constructError("ReferenceError", msg);
- }
Reference ref = (Reference)obj;
return ref.set(value);
}
+ public static Object deleteReference(Object obj)
+ {
+ Reference ref = (Reference)obj;
+ ref.delete();
+ return ref.has() ? Boolean.FALSE : Boolean.TRUE;
+ }
+
static boolean isSpecialProperty(String s)
{
return s.equals("__proto__") || s.equals("__parent__");
}
public static Object specialReference(final Object obj,
final String specialProperty,
- Context cx,
+ final Context cx,
final Scriptable scope)
{
final int PROTO = 0;
final int PARENT = 1;
final int id;
if (specialProperty.equals("__proto__")) {
id = PROTO;
@@ -1314,27 +1496,27 @@
specials = cx.hasFeature(Context.FEATURE_PARENT_PROTO_PROPRTIES);
final Scriptable sobj = toObject(scope, obj);
return new Reference() {
public Object get()
{
if (!specials) {
- return getProp(sobj, specialProperty);
+ return getObjectProp(sobj, specialProperty, cx);
}
if (id == PROTO) {
return getProto(sobj, scope);
} else {
return getParent(sobj, scope);
}
}
public Object set(Object value)
{
if (!specials) {
- return setProp(sobj, specialProperty, value);
+ return setObjectProp(sobj, specialProperty, value, cx);
}
Scriptable result;
if (value == null) {
result = null;
} else {
result = toObject(scope, value);
Scriptable s = result;
@@ -1376,32 +1558,68 @@
* method doesn't return a value.
*/
public static Object delete(Context cx, Scriptable scope,
Object obj, Object id)
{
Scriptable sobj = (obj instanceof Scriptable)
? (Scriptable)obj : toObject(cx, scope, obj);
- String s = getStringId(id);
- boolean result = (s != null)
- ? ScriptableObject.deleteProperty(sobj, s)
- : ScriptableObject.deleteProperty(sobj, getIntId(id));
+ boolean result;
+ if (sobj instanceof XMLObject) {
+ XMLObject xmlObject = (XMLObject)sobj;
+ result = xmlObject.ecmaDelete(cx, id);
+ } else {
+ String s = getStringId(id);
+ if (s != null) {
+ result = ScriptableObject.deleteProperty(sobj, s);
+ } else {
+ result = ScriptableObject.deleteProperty(sobj, getIntId(id));
+ }
+ }
return result ? Boolean.TRUE : Boolean.FALSE;
}
/**
* Looks up a name in the scope chain and returns its value.
*/
- public static Object name(Scriptable scopeChain, String id) {
+ public static Object name(Context cx, Scriptable scopeChain, String id)
+ {
Scriptable obj = scopeChain;
+ XMLObject firstXMLObject = null;
while (obj != null) {
- Object result = ScriptableObject.getProperty(obj, id);
- if (result != Scriptable.NOT_FOUND)
- return result;
+ if (obj instanceof NativeWith) {
+ Scriptable withObj = obj.getPrototype();
+ if (withObj instanceof XMLObject) {
+ XMLObject xmlObj = (XMLObject)withObj;
+ if (xmlObj.ecmaHas(cx, id)) {
+ return xmlObj.ecmaGet(cx, id);
+ }
+ if (firstXMLObject == null) {
+ firstXMLObject = xmlObj;
+ }
+ } else {
+ Object result = ScriptableObject.getProperty(withObj, id);
+ if (result != Scriptable.NOT_FOUND) {
+ return result;
+ }
+ }
+ } else {
+ Object result = ScriptableObject.getProperty(obj, id);
+ if (result != Scriptable.NOT_FOUND) {
+ return result;
+ }
+ }
obj = obj.getParentScope();
}
+
+ if (firstXMLObject != null) {
+ // The name was not found, but we did find an XML object in the
+ // scope chain. The result should be an empty XMLList
+ return firstXMLObject.ecmaGet(cx, id);
+ }
+
throw notFoundError(scopeChain, id);
}
/**
* Returns the object in the scope chain that has a given property.
*
* The order of evaluation of an assignment expression involves
@@ -1410,26 +1628,50 @@
* to 'bind' the given name to an object containing that property
* so that the side effects of evaluating the rhs do not affect
* which property is modified.
* Typically used in conjunction with setName.
*
* See ECMA 10.1.4
*/
- public static Scriptable bind(Scriptable scope, String id) {
- while (!ScriptableObject.hasProperty(scope, id)) {
- scope = scope.getParentScope();
- if (scope == null) {
- break;
+ public static Scriptable bind(Context cx, Scriptable scope, String id)
+ {
+ Scriptable obj = scope;
+ Scriptable firstXMLObject = null;
+ for (;;) {
+ if (obj instanceof NativeWith) {
+ Scriptable withObj = obj.getPrototype();
+ if (withObj instanceof XMLObject) {
+ XMLObject xmlObject = (XMLObject)withObj;
+ if (xmlObject.ecmaHas(cx, id)) {
+ return xmlObject;
+ }
+ if (firstXMLObject == null) {
+ firstXMLObject = xmlObject;
+ }
+ } else {
+ if (ScriptableObject.hasProperty(withObj, id)) {
+ return withObj;
+ }
+ }
+ } else {
+ if (ScriptableObject.hasProperty(obj, id)) {
+ return obj;
+ }
+ }
+ obj = obj.getParentScope();
+ if (obj == null) {
+ // XML objects always bind so return it if it was found
+ return firstXMLObject;
}
}
- return scope;
}
- public static Scriptable getBase(Scriptable scope, String id) {
- Scriptable base = bind(scope, id);
+ public static Scriptable getBase(Context cx, Scriptable scope, String id)
+ {
+ Scriptable base = bind(cx, scope, id);
if (base != null) {
return base;
}
throw notFoundError(scope, id);
}
public static Scriptable getThis(Scriptable base) {
@@ -1437,23 +1679,29 @@
base = base.getPrototype();
if (base instanceof NativeCall)
base = ScriptableObject.getTopLevelScope(base);
return base;
}
public static Object setName(Scriptable bound, Object value,
- Scriptable scope, String id)
+ Context cx, String id)
{
if (bound != null) {
- ScriptableObject.putProperty(bound, id, value);
- }else {
+ if (bound instanceof XMLObject) {
+ XMLObject xmlObject = (XMLObject)bound;
+ xmlObject.ecmaPut(cx, id, value);
+ } else {
+ ScriptableObject.putProperty(bound, id, value);
+ }
+ } else {
// "newname = 7;", where 'newname' has not yet
// been defined, creates a new property in the
// global object. Find the global object by
// walking up the scope chain.
+ Scriptable scope = cx.currentActivationScope;
bound = ScriptableObject.getTopLevelScope(scope);
bound.put(id, bound, value);
/*
This code is causing immense performance problems in
scripts that assign to the variables as a way of creating them.
XXX need strict mode
String message = getMessage1("msg.assn.create", id);
@@ -1482,14 +1730,26 @@
private static class IdEnumeration
{
Scriptable obj;
Object[] ids;
int index;
ObjToIntMap used;
String currentId;
+ boolean enumValues;
+ }
+
+ public static Object enumValuesInit(Object value, Scriptable scope)
+ {
+ IdEnumeration x = new IdEnumeration();
+ if (!(value == null || value == Undefined.instance)) {
+ x.obj = toObject(scope, value);
+ x.enumValues = true;
+ enumChangeObject(x);
+ }
+ return x;
}
public static Object enumInit(Object value, Scriptable scope)
{
IdEnumeration x = new IdEnumeration();
if (!(value == null || value == Undefined.instance)) {
x.obj = toObject(scope, value);
@@ -1529,17 +1789,23 @@
x.currentId = String.valueOf(intId);
}
break;
}
return Boolean.TRUE;
}
- public static String enumId(Object enumObj)
+ public static Object enumId(Object enumObj)
{
- return ((IdEnumeration)enumObj).currentId;
+ IdEnumeration x = (IdEnumeration)enumObj;
+ if (!x.enumValues) return x.currentId;
+
+ String s = getStringId(x.currentId);
+ return (s == null)
+ ? x.obj.get(getIntId(x.currentId), null)
+ : x.obj.get(s, null);
}
private static void enumChangeObject(IdEnumeration x)
{
Object[] ids = null;
while (x.obj != null) {
ids = x.obj.getIds();
@@ -1617,15 +1883,15 @@
if (function instanceof BaseFunction) {
BaseFunction bf = (BaseFunction)function;
Reference ref = bf.referenceCall(cx, scope, thisObj, args);
if (ref != null) { return ref; }
}
// No runtime support for now
String msg = getMessage1("msg.no.ref.from.function",
- toString(getProp(fun, "name", scope)));
+ toString(fun));
throw constructError("ReferenceError", msg);
}
/**
* Operator new.
*
* See ECMA 11.2.2
@@ -1729,57 +1995,80 @@
Callable c = (Callable)script;
return c.call(cx, scope, (Scriptable)thisArg, ScriptRuntime.emptyArgs);
}
/**
* The typeof operator
*/
- public static String typeof(Object value) {
+ public static String typeof(Object value)
+ {
if (value == Undefined.instance)
return "undefined";
if (value == null)
return "object";
if (value instanceof Scriptable)
+ {
+ if (value instanceof XMLObject)
+ return "xml";
+
return (value instanceof Function) ? "function" : "object";
+ }
if (value instanceof String)
return "string";
if (value instanceof Number)
return "number";
if (value instanceof Boolean)
return "boolean";
- throw Kit.badTypeJS(value);
+ throw errorWithClassName("msg.invalid.type", value);
}
/**
* The typeof operator that correctly handles the undefined case
*/
- public static String typeofName(Scriptable scope, String id) {
- Object val = bind(scope, id);
+ public static String typeofName(Scriptable scope, String id)
+ {
+ Context cx = Context.getContext();
+ Scriptable val = bind(cx, scope, id);
if (val == null)
return "undefined";
- return typeof(getProp(val, id, scope));
+ return typeof(getObjectProp(val, id, cx));
}
// neg:
// implement the '-' operator inline in the caller
// as "-toNumber(val)"
// not:
// implement the '!' operator inline in the caller
// as "!toBoolean(val)"
// bitnot:
// implement the '~' operator inline in the caller
// as "~toInt32(val)"
- public static Object add(Object val1, Object val2) {
+ public static Object add(Object val1, Object val2, Context cx)
+ {
if(val1 instanceof Number && val2 instanceof Number) {
return new Double(((Number)val1).doubleValue() +
((Number)val2).doubleValue());
}
+
+ if (val1 instanceof XMLObject && val2 instanceof XMLObject) {
+ XMLObject xml1 = (XMLObject)val1;
+ XMLObject xml2 = (XMLObject)val2;
+ XMLLib xmlLib = xml1.lib();
+ return xmlLib.addXMLObjects(cx, xml1, xml2);
+ } else if (val1 == Undefined.instance && val2 instanceof XMLObject) {
+ // Undefined added to any XML or XMLList the undefined needs
+ // to be "".
+ val1 = "";
+ } else if (val2 == Undefined.instance && val1 instanceof XMLObject) {
+ val2 = "";
+ }
+
if (val1 instanceof Scriptable)
val1 = ((Scriptable) val1).getDefaultValue(null);
if (val2 instanceof Scriptable)
val2 = ((Scriptable) val2).getDefaultValue(null);
if (!(val1 instanceof String) && !(val2 instanceof String))
if ((val1 instanceof Number) && (val2 instanceof Number))
return new Double(((Number)val1).doubleValue() +
@@ -1861,17 +2150,18 @@
return value;
} else {
return result;
}
}
public static Object elemIncrDecr(Object obj, Object index,
- Scriptable scope, int incrDecrMask)
+ Context cx, Scriptable scope,
+ int incrDecrMask)
{
- Object value = getElem(obj, index, scope);
+ Object value = getObjectId(obj, index, cx, scope);
boolean post = ((incrDecrMask & Node.POST_FLAG) != 0);
double number;
if (value instanceof Number) {
number = ((Number)value).doubleValue();
} else {
number = toNumber(value);
if (post) {
@@ -1881,15 +2171,15 @@
}
if ((incrDecrMask & Node.DECR_FLAG) == 0) {
++number;
} else {
--number;
}
Number result = new Double(number);
- setElem(obj, index, result, scope);
+ setObjectId(obj, index, result, cx, scope);
if (post) {
return value;
} else {
return result;
}
}
@@ -1923,48 +2213,82 @@
public static Object toPrimitive(Object val) {
if (val == null || !(val instanceof Scriptable)) {
return val;
}
Scriptable s = (Scriptable)val;
Object result = s.getDefaultValue(null);
- if (result != null && result instanceof Scriptable)
+ if (result instanceof Scriptable)
throw typeError0("msg.bad.default.value");
return result;
}
/**
* Equality
*
* See ECMA 11.9
*/
public static boolean eq(Object x, Object y)
{
if (x == null || x == Undefined.instance) {
- return y == null || y == Undefined.instance;
+ if (y == null || y == Undefined.instance) {
+ return true;
+ }
+ if (y instanceof ScriptableObject) {
+ Boolean test = ((ScriptableObject)y).equivalentValues(x);
+ if (test != null) {
+ return test.booleanValue();
+ }
+ }
+ return false;
} else if (x instanceof Number) {
return eqNumber(((Number)x).doubleValue(), y);
} else if (x instanceof String) {
return eqString((String)x, y);
} else if (x instanceof Boolean) {
boolean b = ((Boolean)x).booleanValue();
if (y instanceof Boolean) {
return b == ((Boolean)y).booleanValue();
}
+ if (y instanceof ScriptableObject) {
+ Boolean test = ((ScriptableObject)y).equivalentValues(x);
+ if (test != null) {
+ return test.booleanValue();
+ }
+ }
return eqNumber(b ? 1.0 : 0.0, y);
} else if (x instanceof Scriptable) {
if (y instanceof Scriptable) {
// Generic test also works for y == Undefined.instance
- if (x == y)
+ if (x == y) {
return true;
+ }
+ if (x instanceof ScriptableObject) {
+ Boolean test = ((ScriptableObject)x).equivalentValues(y);
+ if (test != null) {
+ return test.booleanValue();
+ }
+ }
+ if (y instanceof ScriptableObject) {
+ Boolean test = ((ScriptableObject)y).equivalentValues(x);
+ if (test != null) {
+ return test.booleanValue();
+ }
+ }
if (x instanceof Wrapper && y instanceof Wrapper) {
return ((Wrapper)x).unwrap() == ((Wrapper)y).unwrap();
}
return false;
} else if (y instanceof Boolean) {
+ if (x instanceof ScriptableObject) {
+ Boolean test = ((ScriptableObject)x).equivalentValues(y);
+ if (test != null) {
+ return test.booleanValue();
+ }
+ }
double d = ((Boolean)y).booleanValue() ? 1.0 : 0.0;
return eqNumber(d, x);
} else if (y instanceof Number) {
return eqNumber(((Number)y).doubleValue(), x);
} else if (y instanceof String) {
return eqString((String)y, x);
}
@@ -1983,14 +2307,21 @@
return x == ((Number)y).doubleValue();
} else if (y instanceof String) {
return x == toNumber(y);
} else if (y instanceof Boolean) {
return x == (((Boolean)y).booleanValue() ? 1.0 : +0.0);
} else if (y instanceof Scriptable) {
if (y == Undefined.instance) { return false; }
+ if (y instanceof ScriptableObject) {
+ Object xval = new Double(x);
+ Boolean test = ((ScriptableObject)y).equivalentValues(xval);
+ if (test != null) {
+ return test.booleanValue();
+ }
+ }
y = toPrimitive(y);
} else {
throw Kit.badTypeJS(y);
}
}
}
@@ -2003,22 +2334,27 @@
return x.equals(y);
} else if (y instanceof Number) {
return toNumber(x) == ((Number)y).doubleValue();
} else if (y instanceof Boolean) {
return toNumber(x) == (((Boolean)y).booleanValue() ? 1.0 : 0.0);
} else if (y instanceof Scriptable) {
if (y == Undefined.instance) { return false; }
+ if (y instanceof ScriptableObject) {
+ Boolean test = ((ScriptableObject)y).equivalentValues(x);
+ if (test != null) {
+ return test.booleanValue();
+ }
+ }
y = toPrimitive(y);
+ continue;
} else {
throw Kit.badTypeJS(y);
}
- return false;
}
}
-
public static boolean shallowEq(Object x, Object y)
{
if (x == y) {
if (!(x instanceof Number)) {
return true;
}
// NaN check
@@ -2051,15 +2387,16 @@
}
/**
* The instanceof operator.
*
* @return a instanceof b
*/
- public static boolean instanceOf(Object a, Object b, Scriptable scope)
+ public static boolean instanceOf(Object a, Object b,
+ Context cx, Scriptable scope)
{
// Check RHS is an object
if (! (b instanceof Scriptable)) {
throw typeError0("msg.instanceof.not.object");
}
// for primitive values on LHS, return false
@@ -2097,22 +2434,28 @@
*
- it doesn't perform ToObject on the right hand side
*
- it returns true for DontEnum properties.
* @param a the left hand operand
* @param b the right hand operand
*
* @return true if property name or element number a is a property of b
*/
- public static boolean in(Object a, Object b, Scriptable scope) {
+ public static boolean in(Object a, Object b, Context cx, Scriptable scope)
+ {
if (!(b instanceof Scriptable)) {
throw typeError0("msg.instanceof.not.object");
}
String s = getStringId(a);
- return s != null
- ? ScriptableObject.hasProperty((Scriptable) b, s)
- : ScriptableObject.hasProperty((Scriptable) b, getIntId(a));
+ if (s == null) {
+ return ScriptableObject.hasProperty((Scriptable) b, getIntId(a));
+ }
+ if (b instanceof XMLObject) {
+ XMLObject xmlObject = (XMLObject)b;
+ return xmlObject.ecmaHas(cx, a);
+ }
+ return ScriptableObject.hasProperty((Scriptable) b, s);
}
public static boolean cmp_LT(Object val1, Object val2)
{
double d1, d2;
if (val1 instanceof Number && val2 instanceof Number) {
d1 = ((Number)val1).doubleValue();
@@ -2173,77 +2516,191 @@
} catch (InstantiationException e) {
// fall through...
}
}
return new ImporterTopLevel(cx);
}
- public static void initScript(Context cx, final Scriptable scope,
- NativeFunction funObj,
- Scriptable thisObj,
- boolean fromEvalCode)
- {
+ public static Scriptable enterScript(Context cx, Scriptable scope,
+ NativeFunction funObj,
+ Scriptable thisObj)
+ {
+ boolean topLevel = (cx.currentActivationDepth == 0);
+
+ Scriptable varScope = scope;
+ // Never define any variables from var statements inside with object.
+ // See bug 38590.
+ while (varScope instanceof NativeWith) {
+ varScope = varScope.getParentScope();
+ }
+
String[] argNames = funObj.argNames;
if (argNames != null) {
- Scriptable varScope = scope;
- if (fromEvalCode) {
- // When executing an eval() inside a with statement,
- // define any variables resulting from var statements
- // in the first non-with scope. See bug 38590.
- varScope = scope;
- while (varScope instanceof NativeWith)
- varScope = varScope.getParentScope();
- }
for (int i = argNames.length; i-- != 0;) {
String name = argNames[i];
// Don't overwrite existing def if already defined in object
// or prototypes of object.
if (!hasProp(scope, name)) {
- if (!fromEvalCode) {
+ if (topLevel) {
// Global var definitions are supposed to be DONTDELETE
- ScriptableObject.defineProperty
- (scope, name, Undefined.instance,
- ScriptableObject.PERMANENT);
+ ScriptableObject.defineProperty(
+ varScope, name, Undefined.instance,
+ ScriptableObject.PERMANENT);
} else {
varScope.put(name, varScope, Undefined.instance);
}
}
}
}
+
+ if (topLevel) {
+ if (cx.currentActivationScope != null)
+ throw new IllegalStateException();
+ cx.currentActivationScope = varScope;
+ }
+
+ increaseActivationDepth(cx);
+
+ return scope;
}
- public static Scriptable initVarObj(Context cx, Scriptable scope,
- NativeFunction funObj,
- Scriptable thisObj, Object[] args)
+ public static void exitScript(Context cx)
{
- return new NativeCall(cx, scope, funObj, thisObj, args);
+ if (cx.currentActivationDepth == 0)
+ throw new IllegalStateException();
+ if (cx.currentActivationScope == null)
+ throw new IllegalStateException();
+
+ if (cx.currentActivationDepth == 1) {
+ cx.currentActivationScope = null;
+ }
+ decreaseActivationDepth(cx);
+ }
+
+ public static Scriptable enterActivationFunction(Context cx,
+ Scriptable scope,
+ NativeFunction funObj,
+ Scriptable thisObj,
+ Object[] args)
+ {
+ NativeCall call = new NativeCall(scope, funObj, thisObj, args);
+ call.parentActivationCall = cx.currentActivationCall;
+ call.parentActivationScope = cx.currentActivationScope;
+
+ cx.currentActivationCall = call;
+ cx.currentActivationScope = call;
+
+ increaseActivationDepth(cx);
+
+ return call;
}
- public static void popActivation(Context cx) {
- NativeCall current = cx.currentActivation;
- if (current != null) {
- cx.currentActivation = current.caller;
- current.caller = null;
+ public static void exitActivationFunction(Context cx)
+ {
+ if (cx.currentActivationDepth == 0)
+ throw new IllegalStateException();
+ if (cx.currentActivationScope == null)
+ throw new IllegalStateException();
+ if (cx.currentActivationCall != cx.currentActivationScope)
+ throw new IllegalStateException();
+
+ NativeCall call = cx.currentActivationCall;
+ cx.currentActivationCall = call.parentActivationCall;
+ cx.currentActivationScope = call.parentActivationScope;
+
+ call.parentActivationCall = null;
+ call.parentActivationScope = null;
+
+ decreaseActivationDepth(cx);
+ }
+
+ private static void increaseActivationDepth(Context cx)
+ {
+ // The caller should initialize this already
+ if (cx.currentActivationScope == null)
+ throw new IllegalStateException();
+
+ if (cx.currentActivationDepth == 0) {
+ cx.topActivationScope = cx.currentActivationScope;
}
+ ++cx.currentActivationDepth;
+ }
+
+ private static void decreaseActivationDepth(Context cx)
+ {
+ --cx.currentActivationDepth;
+
+ if (cx.currentActivationDepth == 0) {
+ // The caller should do proper cleanup
+ if (cx.currentActivationScope != null)
+ throw new IllegalStateException();
+ if (cx.currentActivationCall != null)
+ throw new IllegalStateException();
+ cx.topActivationScope = null;
+ cx.cachedXMLLib = null;
+ }
+ }
+
+ static NativeCall findFunctionActivation(Context cx, Function f)
+ {
+ NativeCall call = cx.currentActivationCall;
+ while (call != null) {
+ if (call.getFunctionObject() == f)
+ return call;
+ call = call.parentActivationCall;
+ }
+ return null;
}
public static Scriptable newCatchScope(String exceptionName,
Object exceptionObject)
{
Scriptable scope = new NativeObject();
ScriptableObject.putProperty(scope, exceptionName, exceptionObject);
return scope;
}
public static Scriptable enterWith(Object value, Scriptable scope) {
+ if (value instanceof XMLObject) {
+ XMLObject object = (XMLObject)value;
+ XMLLib xmlLib = object.lib();
+ return xmlLib.enterXMLWith(object, scope);
+ }
return new NativeWith(scope, toObject(scope, value));
}
- public static Scriptable leaveWith(Scriptable scope) {
- return scope.getParentScope();
+ public static Scriptable leaveWith(Scriptable scope)
+ {
+ NativeWith nw = (NativeWith)scope;
+ return nw.getParentScope();
+ }
+
+ public static Scriptable enterDotQuery(Object value, Scriptable scope)
+ {
+ if (!(value instanceof XMLObject))
+ {
+ throw ScriptRuntime.typeError1("msg.isnt.xml.object",
+ ScriptRuntime.toString(value));
+ }
+ XMLObject object = (XMLObject)value;
+ XMLLib xmlLib = object.lib();
+ return xmlLib.enterDotQuery(object, scope);
+ }
+
+ public static Object updateDotQuery(boolean value, Scriptable scope)
+ {
+ // Return null to continue looping
+ NativeWith nw = (NativeWith)scope;
+ return nw.updateDotQuery(value);
+ }
+
+ public static Scriptable leaveDotQuery(Scriptable scope)
+ {
+ NativeWith nw = (NativeWith)scope;
+ return nw.getParentScope();
}
public static void setFunctionProtoAndParent(Scriptable scope,
Function fn)
{
fn.setPrototype(ScriptableObject.getFunctionPrototype(scope));
fn.setParentScope(scope);
@@ -2338,15 +2795,16 @@
public static boolean isArrayObject(Object obj)
{
return obj instanceof NativeArray || obj instanceof Arguments;
}
public static Object[] getArrayElements(Scriptable object)
{
- long longLen = NativeArray.getLengthProperty(object);
+ Context cx = Context.getContext();
+ long longLen = NativeArray.getLengthProperty(cx, object);
if (longLen > Integer.MAX_VALUE) {
// arrays beyond MAX_INT is not in Java in any case
throw new IllegalArgumentException();
}
int len = (int) longLen;
if (len == 0) {
return ScriptRuntime.emptyArgs;
@@ -2410,48 +2868,56 @@
String lineSource,
int columnNumber)
{
return new EcmaError(error, message, sourceName,
lineNumber, lineSource, columnNumber);
}
+ public static EcmaError typeError(String message)
+ {
+ return constructError("TypeError", message);
+ }
+
public static EcmaError typeError0(String messageId)
{
String msg = getMessage0(messageId);
- return constructError("TypeError", msg);
+ return typeError(msg);
}
public static EcmaError typeError1(String messageId, String arg1)
{
String msg = getMessage1(messageId, arg1);
- return constructError("TypeError", msg);
+ return typeError(msg);
}
public static EcmaError typeError2(String messageId, String arg1,
String arg2)
{
String msg = getMessage2(messageId, arg1, arg2);
- return constructError("TypeError", msg);
+ return typeError(msg);
}
- public static RuntimeException undefReadError(Object object, String property)
+ public static RuntimeException undefReadError(Object object, Object id)
{
String messageId = (object == null) ? "msg.null.prop.read"
: "msg.undef.prop.read";
- return typeError1(messageId, property);
+ String idStr = (id == null) ? "null" : id.toString();
+ return typeError1(messageId, idStr);
}
- static RuntimeException undefWriteError(Object object, String property,
- Object value)
+ public static RuntimeException undefWriteError(Object object,
+ Object id,
+ Object value)
{
String messageId = (object == null) ? "msg.null.prop.write"
: "msg.undef.prop.write";
String valueStr = (value instanceof Scriptable)
? value.toString() : toString(value);
- String msg = getMessage2(messageId, property, valueStr);
+ String idStr = (id == null) ? "null" : id.toString();
+ String msg = getMessage2(messageId, idStr, valueStr);
return typeError2(messageId, valueStr, msg);
}
public static RuntimeException notFoundError(Scriptable object, String property)
{
// XXX: use object to improve the error message
String msg = getMessage1("msg.is.not.defined", property);
@@ -2468,24 +2934,84 @@
RegExpProxy result = getRegExpProxy(cx);
if (result == null) {
throw cx.reportRuntimeError0("msg.no.regexp");
}
return result;
}
- public static NativeCall getCurrentActivation(Context cx) {
- return cx.currentActivation;
+ private static XMLLib currentXMLLib(Context cx)
+ {
+ // Scripts should be running to access this
+ if (cx.topActivationScope == null)
+ throw new IllegalStateException();
+
+ XMLLib xmlLib = cx.cachedXMLLib;
+ if (xmlLib == null) {
+ xmlLib = XMLLib.extractFromScope(cx.topActivationScope);
+ if (xmlLib == null)
+ throw new IllegalStateException();
+ cx.cachedXMLLib = xmlLib;
+ }
+
+ return xmlLib;
+ }
+
+ /**
+ * Escapes the reserved characters in a value of an attribute
+ *
+ * @param value Unescaped text
+ * @return The escaped text
+ */
+ public static String escapeAttributeValue(Object value, Context cx)
+ {
+ XMLLib xmlLib = currentXMLLib(cx);
+ return xmlLib.escapeAttributeValue(value);
+ }
+
+ /**
+ * Escapes the reserved characters in a value of a text node
+ *
+ * @param value Unescaped text
+ * @return The escaped text
+ */
+ public static String escapeTextValue(Object value, Context cx)
+ {
+ XMLLib xmlLib = currentXMLLib(cx);
+ return xmlLib.escapeTextValue(value);
}
- public static void setCurrentActivation(Context cx,
- NativeCall activation)
+ public static Object toAttributeName(Object name, Context cx)
{
- cx.currentActivation = activation;
+ XMLLib xmlLib = currentXMLLib(cx);
+ return xmlLib.toAttributeName(cx, name);
}
+ public static Object toDescendantsName(Object name, Context cx)
+ {
+ XMLLib xmlLib = currentXMLLib(cx);
+ return xmlLib.toDescendantsName(cx, name);
+ }
+
+ public static Object toQualifiedName(String namespace,
+ Object name,
+ Context cx, Scriptable scope)
+ {
+ XMLLib xmlLib = currentXMLLib(cx);
+ return xmlLib.toQualifiedName(namespace, name, scope);
+ }
+
+ public static Object xmlReference(Object xmlName,
+ Context cx,
+ Scriptable scope)
+ {
+ XMLLib xmlLib = currentXMLLib(cx);
+ return xmlLib.xmlPrimaryReference(xmlName, scope);
+ }
+
+
static boolean hasProp(Scriptable start, String name) {
Scriptable m = start;
do {
if (m.has(name, start))
return true;
m = m.getPrototype();
} while (m != null);
Index: src/org/mozilla/javascript/Token.java
===================================================================
RCS file: /cvsroot/mozilla/js/rhino/src/org/mozilla/javascript/Token.java,v
retrieving revision 1.27
diff -U7 -r1.27 Token.java
--- src/org/mozilla/javascript/Token.java 5 Jul 2004 15:08:34 -0000 1.27
+++ src/org/mozilla/javascript/Token.java 28 Jul 2004 15:32:23 -0000
@@ -18,14 +18,15 @@
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Roger Lawrence
* Mike McCabe
* Igor Bukanov
+ * Milen Nankov
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License (the "GPL"), in which case the
* provisions of the GPL are applicable instead of those above.
* If you wish to allow use of your version of this file only
* under the terms of the GPL and not to allow others to use your
* version of this file under the NPL, indicate your decision by
@@ -124,90 +125,108 @@
IN = 50,
INSTANCEOF = 51,
LOCAL_SAVE = 52,
LOCAL_LOAD = 53,
GETVAR = 54,
SETVAR = 55,
CATCH_SCOPE = 56,
- ENUM_INIT = 57,
- ENUM_NEXT = 58,
- ENUM_ID = 59,
- THISFN = 60,
- RETURN_RESULT = 61, // to return prevoisly stored return result
- ARRAYLIT = 62, // array literal
- OBJECTLIT = 63, // object literal
- GET_REF = 64, // *reference
- SET_REF = 65, // *reference = something
- REF_CALL = 66, // f(args) = something or f(args)++
- SPECIAL_REF = 67, // reference for special properties like __proto
- GENERIC_REF = 68, // generic reference to generate runtime ref errors
+ ENUM_INIT_KEYS = 57,
+ ENUM_INIT_VALUES = 58,
+ ENUM_NEXT = 59,
+ ENUM_ID = 60,
+ THISFN = 61,
+ RETURN_RESULT = 62, // to return prevoisly stored return result
+ ARRAYLIT = 63, // array literal
+ OBJECTLIT = 64, // object literal
+ GET_REF = 65, // *reference
+ SET_REF = 66, // *reference = something
+ DEL_REF = 67, // delete reference
+ REF_CALL = 68, // f(args) = something or f(args)++
+ SPECIAL_REF = 69, // reference for special properties like __proto
+ GENERIC_REF = 70, // generic reference to generate runtime ref errors
+
+ // For XML support:
+ DEFAULTNAMESPACE = 71, // default xml namespace =
+ COLONCOLON = 72, // ::
+ ESCXMLATTR = 73,
+ ESCXMLTEXT = 74,
+ TOATTRNAME = 75,
+ DESCENDANTS = 76,
+ XML_REF = 77,
- LAST_BYTECODE_TOKEN = 68,
+ LAST_BYTECODE_TOKEN = 77,
// End of interpreter bytecodes
- TRY = 69,
- SEMI = 70, // semicolon
- LB = 71, // left and right brackets
- RB = 72,
- LC = 73, // left and right curlies (braces)
- RC = 74,
- LP = 75, // left and right parentheses
- RP = 76,
- COMMA = 77, // comma operator
- ASSIGN = 78, // simple assignment (=)
- ASSIGNOP = 79, // assignment with operation (+= -= etc.)
- HOOK = 80, // conditional (?:)
- COLON = 81,
- OR = 82, // logical or (||)
- AND = 83, // logical and (&&)
- INC = 84, // increment/decrement (++ --)
- DEC = 85,
- DOT = 86, // member operator (.)
- FUNCTION = 87, // function keyword
- EXPORT = 88, // export keyword
- IMPORT = 89, // import keyword
- IF = 90, // if keyword
- ELSE = 91, // else keyword
- SWITCH = 92, // switch keyword
- CASE = 93, // case keyword
- DEFAULT = 94, // default keyword
- WHILE = 95, // while keyword
- DO = 96, // do keyword
- FOR = 97, // for keyword
- BREAK = 98, // break keyword
- CONTINUE = 99, // continue keyword
- VAR = 100, // var keyword
- WITH = 101, // with keyword
- CATCH = 102, // catch keyword
- FINALLY = 103, // finally keyword
- VOID = 104, // void keyword
- RESERVED = 105, // reserved keywords
+ TRY = 78,
+ SEMI = 79, // semicolon
+ LB = 80, // left and right brackets
+ RB = 81,
+ LC = 82, // left and right curlies (braces)
+ RC = 83,
+ LP = 84, // left and right parentheses
+ RP = 85,
+ COMMA = 86, // comma operator
+ ASSIGN = 87, // simple assignment (=)
+ ASSIGNOP = 88, // assignment with operation (+= -= etc.)
+ HOOK = 89, // conditional (?:)
+ COLON = 90,
+ OR = 91, // logical or (||)
+ AND = 92, // logical and (&&)
+ INC = 93, // increment/decrement (++ --)
+ DEC = 94,
+ DOT = 95, // member operator (.)
+ FUNCTION = 96, // function keyword
+ EXPORT = 97, // export keyword
+ IMPORT = 98, // import keyword
+ IF = 99, // if keyword
+ ELSE = 100, // else keyword
+ SWITCH = 101, // switch keyword
+ CASE = 102, // case keyword
+ DEFAULT = 103, // default keyword
+ WHILE = 104, // while keyword
+ DO = 105, // do keyword
+ FOR = 106, // for keyword
+ BREAK = 107, // break keyword
+ CONTINUE = 108, // continue keyword
+ VAR = 109, // var keyword
+ WITH = 110, // with keyword
+ CATCH = 111, // catch keyword
+ FINALLY = 112, // finally keyword
+ VOID = 113, // void keyword
+ RESERVED = 114, // reserved keywords
- EMPTY = 106,
+ EMPTY = 115,
/* types used for the parse tree - these never get returned
* by the scanner.
*/
- BLOCK = 107, // statement block
- LABEL = 108, // label
- TARGET = 109,
- LOOP = 110,
- EXPR_VOID = 111, // expression statement in functions
- EXPR_RESULT = 112, // expression statement in scripts
- JSR = 113,
- SCRIPT = 114, // top-level node for entire script
- TYPEOFNAME = 115, // for typeof(simple-name)
- USE_STACK = 116,
- SETPROP_OP = 117, // x.y op= something
- SETELEM_OP = 118, // x[y] op= something
- LOCAL_BLOCK = 119,
- SET_REF_OP = 120, // *reference op= something
+ BLOCK = 116, // statement block
+ LABEL = 117, // label
+ TARGET = 118,
+ LOOP = 119,
+ EXPR_VOID = 120, // expression statement in functions
+ EXPR_RESULT = 121, // expression statement in scripts
+ JSR = 122,
+ SCRIPT = 123, // top-level node for entire script
+ TYPEOFNAME = 124, // for typeof(simple-name)
+ USE_STACK = 125,
+ SETPROP_OP = 126, // x.y op= something
+ SETELEM_OP = 127, // x[y] op= something
+ LOCAL_BLOCK = 128,
+ SET_REF_OP = 129, // *reference op= something
+
+ // For XML support:
+ DOTDOT = 130, // member operator (..)
+ XML = 131, // XML type
+ DOTQUERY = 132, // .() -- e.g., x.emps.emp.(name == "terry")
+ XMLATTR = 133, // @
+ XMLEND = 134,
- LAST_TOKEN = 120;
+ LAST_TOKEN = 134;
public static String name(int token)
{
if (!(-1 <= token && token <= LAST_TOKEN)) {
throw new IllegalArgumentException(String.valueOf(token));
}
@@ -270,26 +289,35 @@
case IN: return "IN";
case INSTANCEOF: return "INSTANCEOF";
case LOCAL_SAVE: return "LOCAL_SAVE";
case LOCAL_LOAD: return "LOCAL_LOAD";
case GETVAR: return "GETVAR";
case SETVAR: return "SETVAR";
case CATCH_SCOPE: return "CATCH_SCOPE";
- case ENUM_INIT: return "ENUM_INIT";
+ case ENUM_INIT_KEYS: return "ENUM_INIT_KEYS";
+ case ENUM_INIT_VALUES: return "ENUM_INIT_VALUES";
case ENUM_NEXT: return "ENUM_NEXT";
case ENUM_ID: return "ENUM_ID";
case THISFN: return "THISFN";
case RETURN_RESULT: return "RETURN_RESULT";
case ARRAYLIT: return "ARRAYLIT";
case OBJECTLIT: return "OBJECTLIT";
case GET_REF: return "GET_REF";
case SET_REF: return "SET_REF";
+ case DEL_REF: return "DEL_REF";
case REF_CALL: return "REF_CALL";
case SPECIAL_REF: return "SPECIAL_REF";
case GENERIC_REF: return "GENERIC_REF";
+ case DEFAULTNAMESPACE:return "DEFAULTNAMESPACE";
+ case COLONCOLON: return "COLONCOLON";
+ case ESCXMLTEXT: return "ESCXMLTEXT";
+ case ESCXMLATTR: return "ESCXMLATTR";
+ case TOATTRNAME: return "TOATTRNAME";
+ case DESCENDANTS: return "DESCENDANTS";
+ case XML_REF: return "XML_REF";
case TRY: return "TRY";
case SEMI: return "SEMI";
case LB: return "LB";
case RB: return "RB";
case LC: return "LC";
case RC: return "RC";
case LP: return "LP";
@@ -333,13 +361,18 @@
case SCRIPT: return "SCRIPT";
case TYPEOFNAME: return "TYPEOFNAME";
case USE_STACK: return "USE_STACK";
case SETPROP_OP: return "SETPROP_OP";
case SETELEM_OP: return "SETELEM_OP";
case LOCAL_BLOCK: return "LOCAL_BLOCK";
case SET_REF_OP: return "SET_REF_OP";
+ case DOTDOT: return "DOTDOT";
+ case XML: return "XML";
+ case DOTQUERY: return "DOTQUERY";
+ case XMLATTR: return "XMLATTR";
+ case XMLEND: return "XMLEND";
}
// Token without name
throw new IllegalStateException(String.valueOf(token));
}
}
Index: src/org/mozilla/javascript/TokenStream.java
===================================================================
RCS file: /cvsroot/mozilla/js/rhino/src/org/mozilla/javascript/TokenStream.java,v
retrieving revision 1.55
diff -U7 -r1.55 TokenStream.java
--- src/org/mozilla/javascript/TokenStream.java 1 Jul 2004 14:52:22 -0000 1.55
+++ src/org/mozilla/javascript/TokenStream.java 28 Jul 2004 15:32:23 -0000
@@ -18,14 +18,17 @@
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Roger Lawrence
* Mike McCabe
* Igor Bukanov
+ * Ethan Hugg
+ * Terry Lucas
+ * Milen Nankov
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License (the "GPL"), in which case the
* provisions of the GPL are applicable instead of those above.
* If you wish to allow use of your version of this file only
* under the terms of the GPL and not to allow others to use your
* version of this file under the NPL, indicate your decision by
@@ -376,14 +379,16 @@
if (c != '-') {
dirtyLine = true;
}
break;
}
}
+ if (c == '@') return Token.XMLATTR;
+
// identifier/keyword/instanceof?
// watch out for starting with a