Replacing calls to XMLLib to construct special name objects to represent qulified names, attributes and descendants by calls to object to get Reference based on name type. It allowed to implement proper namespace resolution in qulified name without forcing activation creation and simplified code.

In addition XMLName is no longer leaked to interpretation stack which would allow to remove unnecessary casts to XMLName in future.
This commit is contained in:
igor%mir2.org 2004-09-30 22:52:40 +00:00
parent be537ec4bf
commit e048fa7512
14 changed files with 418 additions and 428 deletions

View File

@ -229,55 +229,6 @@ final class IRFactory
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
@ -1055,6 +1006,72 @@ final class IRFactory
throw Kit.codeBug();
}
Node createPropertyGet(Node target, String namespace, String name,
int memberTypeFlags)
{
if (namespace == null && memberTypeFlags == 0) {
if (target == null) {
return createName(name);
}
checkActivationName(name, Token.GETPROP);
if (ScriptRuntime.isSpecialProperty(name)) {
Node ref = new Node(Token.REF_SPECIAL, target);
ref.putProp(Node.NAME_PROP, name);
return new Node(Token.GET_REF, ref);
}
return new Node(Token.GETPROP, target, createString(name));
}
Node elem = createString(name);
memberTypeFlags |= Node.PROPERTY_FLAG;
return createMemberRefGet(target, namespace, elem, memberTypeFlags);
}
Node createElementGet(Node target, String namespace, Node elem,
int memberTypeFlags)
{
// OPT: could optimize to createPropertyGet
// iff elem is string that can not be number
if (namespace == null && memberTypeFlags == 0) {
// stand-alone [aaa] as primary expression is array literal
// declaration and should not come here!
if (target == null) throw Kit.codeBug();
return new Node(Token.GETELEM, target, elem);
}
return createMemberRefGet(target, namespace, elem, memberTypeFlags);
}
private Node createMemberRefGet(Node target, String namespace, Node elem,
int memberTypeFlags)
{
Node nsNode = null;
if (namespace != null) {
// See 11.1.2 in ECMA 357
if (namespace.equals("*")) {
nsNode = new Node(Token.NULL);
} else {
nsNode = createName(namespace);
}
}
Node ref;
if (target == null) {
if (namespace == null) {
ref = new Node(Token.REF_NAME, elem);
} else {
ref = new Node(Token.REF_NS_NAME, nsNode, elem);
}
} else {
if (namespace == null) {
ref = new Node(Token.REF_MEMBER, target, elem);
} else {
ref = new Node(Token.REF_NS_MEMBER, target, nsNode, elem);
}
}
if (memberTypeFlags != 0) {
ref.putIntProp(Node.MEMBER_TYPE_PROP, memberTypeFlags);
}
return new Node(Token.GET_REF, ref);
}
/**
* Binary
*/
@ -1062,38 +1079,6 @@ final class IRFactory
{
switch (nodeType) {
case Token.DOT:
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:
{
Node ref;
if (right.getType() == Token.NAME) {
right.setType(Token.STRING);
}
ref = new Node(Token.DESC_REF, left, right);
return new Node(Token.GET_REF, ref);
}
case Token.LB:
// OPT: could optimize to GETPROP iff string can't be a number
nodeType = Token.GETELEM;
break;
case Token.ADD:
// numerical addition and string concatenation
if (left.type == Token.STRING) {

View File

@ -990,13 +990,7 @@ public class Interpreter
addStringOp(Token.GETPROP, child.getString());
break;
case Token.GET_REF:
visitExpression(child, 0);
addToken(Token.GET_REF);
break;
case Token.GETELEM:
case Token.DESC_REF:
case Token.DELPROP:
case Token.BITAND:
case Token.BITOR:
@ -1032,6 +1026,7 @@ public class Interpreter
case Token.BITNOT:
case Token.TYPEOF:
case Token.VOID:
case Token.GET_REF:
case Token.DEL_REF:
visitExpression(child, 0);
if (type == Token.VOID) {
@ -1231,17 +1226,27 @@ public class Interpreter
visitLiteral(node, child);
break;
case Token.SPECIAL_REF:
{
String special = (String)node.getProp(Node.SPECIAL_PROP_PROP);
visitExpression(child, 0);
addStringOp(Token.SPECIAL_REF, special);
}
case Token.REF_SPECIAL:
visitExpression(child, 0);
addStringOp(type, (String)node.getProp(Node.NAME_PROP));
break;
case Token.XML_REF:
visitExpression(child, 0);
addToken(type);
case Token.REF_MEMBER:
case Token.REF_NS_MEMBER:
case Token.REF_NAME:
case Token.REF_NS_NAME:
{
int memberTypeFlags = node.getIntProp(Node.MEMBER_TYPE_PROP, 0);
// generate possible target, possible namespace and member
int childCount = 0;
do {
visitExpression(child, 0);
++childCount;
child = child.getNext();
} while (child != null);
addIndexOp(type, memberTypeFlags);
stackChange(1 - childCount);
}
break;
case Token.DOTQUERY:
@ -1260,22 +1265,10 @@ public class Interpreter
case Token.DEFAULTNAMESPACE :
case Token.ESCXMLATTR :
case Token.ESCXMLTEXT :
case Token.TOATTRNAME :
visitExpression(child, 0);
addToken(type);
break;
case Token.COLONCOLON :
{
if (child.getType() != Token.STRING)
throw badTree(child);
String namespace = child.getString();
child = child.getNext();
visitExpression(child, 0);
addStringOp(Token.COLONCOLON, namespace);
}
break;
default:
throw badTree(node);
}
@ -3229,28 +3222,54 @@ switch (op) {
: (Object)ScriptRuntime.enumId(val, cx);
continue Loop;
}
case Token.SPECIAL_REF : {
case Token.REF_SPECIAL : {
//stringReg: name of special property
Object lhs = stack[stackTop];
if (lhs == DBL_MRK) lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]);
stack[stackTop] = ScriptRuntime.specialReference(lhs, stringReg,
Object obj = stack[stackTop];
if (obj == DBL_MRK) obj = ScriptRuntime.wrapNumber(sDbl[stackTop]);
stack[stackTop] = ScriptRuntime.specialReference(obj, stringReg,
cx, frame.scope);
continue Loop;
}
case Token.DESC_REF : {
Object rhs = stack[stackTop];
if (rhs == DBL_MRK) rhs = ScriptRuntime.wrapNumber(sDbl[stackTop]);
case Token.REF_MEMBER: {
//indexReg: flags
Object elem = stack[stackTop];
if (elem == DBL_MRK) elem = ScriptRuntime.wrapNumber(sDbl[stackTop]);
--stackTop;
Object lhs = stack[stackTop];
if (lhs == DBL_MRK) lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]);
stack[stackTop] = ScriptRuntime.getDescendantsRef(lhs, rhs,
cx, frame.scope);
Object obj = stack[stackTop];
if (obj == DBL_MRK) obj = ScriptRuntime.wrapNumber(sDbl[stackTop]);
stack[stackTop] = ScriptRuntime.memberRef(obj, elem, cx, indexReg);
continue Loop;
}
case Token.XML_REF : {
Object lhs = stack[stackTop];
if (lhs == DBL_MRK) lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]);
stack[stackTop] = ScriptRuntime.xmlReference(lhs, cx, frame.scope);
case Token.REF_NS_MEMBER: {
//indexReg: flags
Object elem = stack[stackTop];
if (elem == DBL_MRK) elem = ScriptRuntime.wrapNumber(sDbl[stackTop]);
--stackTop;
Object ns = stack[stackTop];
if (ns == DBL_MRK) ns = ScriptRuntime.wrapNumber(sDbl[stackTop]);
--stackTop;
Object obj = stack[stackTop];
if (obj == DBL_MRK) obj = ScriptRuntime.wrapNumber(sDbl[stackTop]);
stack[stackTop] = ScriptRuntime.memberRef(obj, ns, elem, cx, indexReg);
continue Loop;
}
case Token.REF_NAME: {
//indexReg: flags
Object name = stack[stackTop];
if (name == DBL_MRK) name = ScriptRuntime.wrapNumber(sDbl[stackTop]);
stack[stackTop] = ScriptRuntime.nameRef(name, cx, frame.scope,
indexReg);
continue Loop;
}
case Token.REF_NS_NAME: {
//indexReg: flags
Object name = stack[stackTop];
if (name == DBL_MRK) name = ScriptRuntime.wrapNumber(sDbl[stackTop]);
--stackTop;
Object ns = stack[stackTop];
if (ns == DBL_MRK) ns = ScriptRuntime.wrapNumber(sDbl[stackTop]);
stack[stackTop] = ScriptRuntime.nameRef(ns, name, cx, frame.scope,
indexReg);
continue Loop;
}
case Icode_SCOPE :
@ -3349,20 +3368,6 @@ switch (op) {
}
continue Loop;
}
case Token.TOATTRNAME : {
Object value = stack[stackTop];
if (value == DBL_MRK) value = ScriptRuntime.wrapNumber(sDbl[stackTop]);
stack[stackTop] = ScriptRuntime.toAttributeName(value, cx);
continue Loop;
}
case Token.COLONCOLON : {
Object value = stack[stackTop];
if (value == DBL_MRK) value = ScriptRuntime.wrapNumber(sDbl[stackTop]);
// stringReg contains namespace
stack[stackTop] = ScriptRuntime.toQualifiedName(stringReg, value,
cx, frame.scope);
continue Loop;
}
case Icode_LINE :
frame.pcSourceLineStart = frame.pc;
if (frame.debuggerFrame != null) {

View File

@ -84,7 +84,7 @@ public final class NativeCall extends IdScriptableObject
for (int i = function.argCount; i != argNames.length; i++) {
String name = argNames[i];
if (!super.has(name, this)) {
defineProperty(name, Undefined.instance, PERMANENT);
defineProperty(name, Undefined.instance, PERMANENT);
}
}
}

View File

@ -89,7 +89,7 @@ public class NativeJavaArray extends NativeJavaObject {
return new Integer(length);
Object result = super.get(id, start);
if (result == NOT_FOUND &&
!ScriptRuntime.hasProp(getPrototype(), id))
!ScriptableObject.hasProperty(getPrototype(), id))
{
throw Context.reportRuntimeError2(
"msg.java.member.not.found", array.getClass().getName(), id);

View File

@ -52,7 +52,6 @@ public class Node
LOCAL_BLOCK_PROP = 3,
REGEXP_PROP = 4,
CASEARRAY_PROP = 5,
SPECIAL_PROP_PROP = 6,
/*
the following properties are defined and manipulated by the
optimizer -
@ -65,17 +64,19 @@ public class Node
matches.
*/
TARGETBLOCK_PROP = 7,
VARIABLE_PROP = 8,
ISNUMBER_PROP = 9,
DIRECTCALL_PROP = 10,
SPECIALCALL_PROP = 11,
SKIP_INDEXES_PROP = 12, // array of skipped indexes of array literal
OBJECT_IDS_PROP = 13, // array of properties for object literal
INCRDECR_PROP = 14, // pre or post type of increment/decerement
CATCH_SCOPE_PROP = 15, // Index of catch scope block in catch
LABEL_ID_PROP = 16, // Label id: code generation uses it
LAST_PROP = 16;
TARGETBLOCK_PROP = 6,
VARIABLE_PROP = 7,
ISNUMBER_PROP = 8,
DIRECTCALL_PROP = 9,
SPECIALCALL_PROP = 10,
SKIP_INDEXES_PROP = 11, // array of skipped indexes of array literal
OBJECT_IDS_PROP = 12, // array of properties for object literal
INCRDECR_PROP = 13, // pre or post type of increment/decerement
CATCH_SCOPE_PROP = 14, // index of catch scope block in catch
LABEL_ID_PROP = 15, // label id: code generation uses it
MEMBER_TYPE_PROP = 16, // type of element access operation
NAME_PROP = 17, // property name
LAST_PROP = 17;
// values of ISNUMBER_PROP to specify
// which of the children are Number types
@ -93,6 +94,11 @@ public class Node
DECR_FLAG = 0x1,
POST_FLAG = 0x2;
public static final int // flags for MEMBER_TYPE_PROP
PROPERTY_FLAG = 0x1, // property access: element is valid name
ATTRIBUTE_FLAG = 0x2, // x.@y or x..@y
DESCENDANTS_FLAG = 0x4; // x..y or x..@i
private static class NumberNode extends Node
{
NumberNode(double number)
@ -432,7 +438,6 @@ public class Node
case LOCAL_BLOCK_PROP: return "local_block";
case REGEXP_PROP: return "regexp";
case CASEARRAY_PROP: return "casearray";
case SPECIAL_PROP_PROP: return "special_prop";
case TARGETBLOCK_PROP: return "targetblock";
case VARIABLE_PROP: return "variable";
@ -445,6 +450,8 @@ public class Node
case INCRDECR_PROP: return "incrdecr_prop";
case CATCH_SCOPE_PROP: return "catch_scope_prop";
case LABEL_ID_PROP: return "label_id_prop";
case MEMBER_TYPE_PROP: return "member_type_prop";
case NAME_PROP: return "name_prop";
default: Kit.codeBug();
}

View File

@ -1648,30 +1648,54 @@ public class Parser
int tt = peekToken();
switch (tt) {
case Token.DOT: {
consumeToken();
decompiler.addToken(Token.DOT);
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.DOT:
case Token.DOTDOT:
{
int memberTypeFlags;
String s;
case Token.DOTDOT: {
consumeToken();
mustHaveXML();
decompiler.addToken(Token.DOTDOT);
Node n = nameOrPropertyIdentifier();
pn = nf.createBinary(Token.DOTDOT, pn, n);
consumeToken();
decompiler.addToken(tt);
memberTypeFlags = 0;
if (tt == Token.DOTDOT) {
mustHaveXML();
memberTypeFlags = Node.DESCENDANTS_FLAG;
}
if (!compilerEnv.isXmlAvailable()) {
mustMatchToken(Token.NAME, "msg.no.name.after.dot");
s = ts.getString();
decompiler.addName(s);
pn = nf.createPropertyGet(pn, null, s, memberTypeFlags);
break;
}
tt = nextToken();
switch (tt) {
// handles: name, ns::name, ns::*, ns::[expr]
case Token.NAME:
s = ts.getString();
decompiler.addName(s);
pn = propertyName(pn, s, memberTypeFlags);
break;
// handles: *, *::name, *::*, *::[expr]
case Token.MUL:
decompiler.addName("*");
pn = propertyName(pn, "*", memberTypeFlags);
break;
// handles: '@attr', '@ns::attr', '@ns::*', '@ns::*',
// '@::attr', '@::*', '@*', '@*::attr', '@*::*'
case Token.XMLATTR:
decompiler.addToken(Token.XMLATTR);
pn = attributeAccess(pn, memberTypeFlags);
break;
default:
reportError("msg.no.name.after.dot");
}
}
break;
}
case Token.DOTQUERY:
consumeToken();
@ -1684,7 +1708,7 @@ public class Parser
case Token.LB:
consumeToken();
decompiler.addToken(Token.LB);
pn = nf.createBinary(Token.LB, pn, expr(false));
pn = nf.createElementGet(pn, null, expr(false), 0);
mustMatchToken(Token.RB, "msg.no.bracket.index");
decompiler.addToken(Token.RB);
break;
@ -1707,78 +1731,43 @@ public class Parser
return pn;
}
private Node nameOrPropertyIdentifier()
throws IOException, ParserException
{
Node pn;
int tt = nextToken();
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()
private Node attributeAccess(Node pn, int memberTypeFlags)
throws IOException
{
Node pn;
memberTypeFlags |= Node.ATTRIBUTE_FLAG;
int tt = nextToken();
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));
case Token.NAME:
{
String s = ts.getString();
decompiler.addName(s);
pn = propertyName(pn, s, memberTypeFlags);
}
break;
}
// handles: @*, @*::name, @*::*, @*::[expr]
case Token.MUL:
decompiler.addName("*");
pn = nf.createAttributeName(nameOrQualifiedName("*", false));
pn = propertyName(pn, "*", memberTypeFlags);
break;
// handles @[expr]
case Token.LB:
decompiler.addToken(Token.LB);
pn = nf.createAttributeExpr(expr(false));
pn = nf.createElementGet(pn, null, expr(false), memberTypeFlags);
mustMatchToken(Token.RB, "msg.no.bracket.index");
decompiler.addToken(Token.RB);
break;
default:
reportError("msg.no.name.after.xmlAttr");
pn = nf.createAttributeExpr(nf.createString("?"));
pn = nf.createPropertyGet(pn, null, "?", memberTypeFlags);
break;
}
@ -1788,51 +1777,45 @@ public class Parser
/**
* Check if :: follows name in which case it becomes qualified name
*/
private Node nameOrQualifiedName(String name, boolean primaryContext)
private Node propertyName(Node pn, String name, int memberTypeFlags)
throws IOException, ParserException
{
colonColonCheck:
String namespace = null;
if (matchToken(Token.COLONCOLON)) {
decompiler.addToken(Token.COLONCOLON);
namespace = name;
Node pn;
int tt = nextToken();
switch (tt) {
// handles name::name
case Token.NAME: {
String s = ts.getString();
decompiler.addName(s);
pn = nf.createQualifiedName(name, s);
case Token.NAME:
name = ts.getString();
decompiler.addName(name);
break;
}
// handles name::*
case Token.MUL:
decompiler.addName("*");
pn = nf.createQualifiedName(name, "*");
name = "*";
break;
// handles name::[expr]
case Token.LB:
decompiler.addToken(Token.LB);
pn = nf.createQualifiedExpr(name, expr(false));
pn = nf.createElementGet(pn, namespace, expr(false),
memberTypeFlags);
mustMatchToken(Token.RB, "msg.no.bracket.index");
decompiler.addToken(Token.RB);
break;
return pn;
default:
reportError("msg.no.name.after.coloncolon");
break colonColonCheck;
name = "?";
}
if (primaryContext) {
pn = nf.createXMLPrimary(pn);
}
return pn;
}
return nf.createName(name);
pn = nf.createPropertyGet(pn, namespace, name, memberTypeFlags);
return pn;
}
private Node primaryExpr()
@ -1956,8 +1939,8 @@ public class Parser
case Token.XMLATTR:
mustHaveXML();
decompiler.addToken(Token.XMLATTR);
pn = attributeIdentifier();
return nf.createXMLPrimary(pn);
pn = attributeAccess(null, 0);
return pn;
case Token.NAME: {
String name = ts.getString();
@ -1972,7 +1955,7 @@ public class Parser
decompiler.addName(name);
if (compilerEnv.isXmlAvailable()) {
pn = nameOrQualifiedName(name, true);
pn = propertyName(null, name, 0);
} else {
pn = nf.createName(name);
}

View File

@ -2898,7 +2898,7 @@ public class ScriptRuntime {
String name = argNames[i];
// Don't overwrite existing def if already defined in object
// or prototypes of object.
if (!hasProp(scope, name)) {
if (!ScriptableObject.hasProperty(scope, name)) {
if (!evalScript) {
// Global var definitions are supposed to be DONTDELETE
ScriptableObject.defineProperty(
@ -3444,47 +3444,39 @@ public class ScriptRuntime {
return xmlLib.escapeTextValue(value);
}
public static Object toAttributeName(Object name, Context cx)
{
XMLLib xmlLib = currentXMLLib(cx);
return xmlLib.toAttributeName(cx, name);
}
public static Reference getDescendantsRef(Object obj, Object elem,
Context cx, Scriptable scope)
public static Reference memberRef(Object obj, Object elem, Context cx,
int memberTypeFlags)
{
if (!(obj instanceof XMLObject)) {
throw notXmlError(obj);
}
XMLObject xmlObject = (XMLObject)obj;
return xmlObject.getDescendantsRef(cx, elem);
return xmlObject.memberRef(cx, elem, memberTypeFlags);
}
public static Object toQualifiedName(String namespace,
Object name,
Context cx, Scriptable scope)
public static Reference memberRef(Object obj, Object namespace,
Object elem, Context cx,
int memberTypeFlags)
{
if (!(obj instanceof XMLObject)) {
throw notXmlError(obj);
}
XMLObject xmlObject = (XMLObject)obj;
return xmlObject.memberRef(cx, namespace, elem, memberTypeFlags);
}
public static Reference nameRef(Object name, Context cx,
Scriptable scope, int memberTypeFlags)
{
XMLLib xmlLib = currentXMLLib(cx);
return xmlLib.toQualifiedName(namespace, name, scope);
return xmlLib.nameRef(cx, name, scope, memberTypeFlags);
}
public static Reference xmlReference(Object xmlName,
Context cx,
Scriptable scope)
public static Reference nameRef(Object namespace, Object name, Context cx,
Scriptable scope, int memberTypeFlags)
{
XMLLib xmlLib = currentXMLLib(cx);
return xmlLib.xmlPrimaryReference(cx, 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);
return false;
return xmlLib.nameRef(cx, namespace, name, scope, memberTypeFlags);
}
private static void storeIndexResult(Context cx, int index)

View File

@ -141,20 +141,20 @@ public class Token
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
REF_SPECIAL = 69, // reference for special properties like __proto
// For XML support:
DEFAULTNAMESPACE = 70, // default xml namespace =
COLONCOLON = 71, // ::
ESCXMLATTR = 72,
ESCXMLTEXT = 73,
TOATTRNAME = 74,
DESC_REF = 75, // Descendants reference to implement x..y
XML_REF = 76;
ESCXMLATTR = 71,
ESCXMLTEXT = 72,
REF_MEMBER = 73, // Reference for x.@y, x..y etc.
REF_NS_MEMBER = 74, // Reference for x.ns::y, x..ns::y etc.
REF_NAME = 75, // Reference for @y, @[y] etc.
REF_NS_NAME = 76; // Reference for ns::y, @ns::y@[y] etc.
// End of interpreter bytecodes
public final static int
LAST_BYTECODE_TOKEN = XML_REF,
LAST_BYTECODE_TOKEN = REF_NS_NAME,
TRY = 77,
SEMI = 78, // semicolon
@ -233,12 +233,13 @@ public class Token
// For XML support:
DOTDOT = 139, // member operator (..)
XML = 140, // XML type
DOTQUERY = 141, // .() -- e.g., x.emps.emp.(name == "terry")
XMLATTR = 142, // @
XMLEND = 143,
COLONCOLON = 140, // namespace::name
XML = 141, // XML type
DOTQUERY = 142, // .() -- e.g., x.emps.emp.(name == "terry")
XMLATTR = 143, // @
XMLEND = 144,
LAST_TOKEN = 143;
LAST_TOKEN = 144;
public static String name(int token)
{
@ -322,14 +323,14 @@ public class Token
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 REF_SPECIAL: return "REF_SPECIAL";
case DEFAULTNAMESPACE:return "DEFAULTNAMESPACE";
case COLONCOLON: return "COLONCOLON";
case ESCXMLTEXT: return "ESCXMLTEXT";
case ESCXMLATTR: return "ESCXMLATTR";
case TOATTRNAME: return "TOATTRNAME";
case DESC_REF: return "DESC_REF";
case XML_REF: return "XML_REF";
case REF_MEMBER: return "REF_MEMBER";
case REF_NS_MEMBER: return "REF_NS_MEMBER";
case REF_NAME: return "REF_NAME";
case REF_NS_NAME: return "REF_NS_NAME";
case TRY: return "TRY";
case SEMI: return "SEMI";
case LB: return "LB";
@ -392,6 +393,7 @@ public class Token
case LOCAL_BLOCK: return "LOCAL_BLOCK";
case SET_REF_OP: return "SET_REF_OP";
case DOTDOT: return "DOTDOT";
case COLONCOLON: return "COLONCOLON";
case XML: return "XML";
case DOTQUERY: return "DOTQUERY";
case XMLATTR: return "XMLATTR";

View File

@ -2123,10 +2123,9 @@ class BodyCodegen
cfw.addALoad(getLocalBlockRegister(node));
break;
case Token.SPECIAL_REF:
case Token.REF_SPECIAL:
{
String special
= (String)node.getProp(Node.SPECIAL_PROP_PROP);
String special = (String)node.getProp(Node.NAME_PROP);
generateExpression(child, node);
cfw.addPush(special);
cfw.addALoad(contextLocal);
@ -2140,16 +2139,61 @@ class BodyCodegen
}
break;
case Token.XML_REF:
case Token.REF_MEMBER:
case Token.REF_NS_MEMBER:
case Token.REF_NAME:
case Token.REF_NS_NAME:
{
generateExpression(child, node);
int memberTypeFlags
= node.getIntProp(Node.MEMBER_TYPE_PROP, 0);
// generate possible target, possible namespace and member
do {
generateExpression(child, node);
child = child.getNext();
} while (child != null);
cfw.addALoad(contextLocal);
cfw.addALoad(variableObjectLocal);
addScriptRuntimeInvoke("xmlReference",
"(Ljava/lang/Object;"
+"Lorg/mozilla/javascript/Context;"
+"Lorg/mozilla/javascript/Scriptable;"
+")Lorg/mozilla/javascript/Reference;");
String methodName, signature;
switch (type) {
case Token.REF_MEMBER:
methodName = "memberRef";
signature = "(Ljava/lang/Object;"
+"Ljava/lang/Object;"
+"Lorg/mozilla/javascript/Context;"
+"I"
+")Lorg/mozilla/javascript/Reference;";
break;
case Token.REF_NS_MEMBER:
methodName = "memberRef";
signature = "(Ljava/lang/Object;"
+"Ljava/lang/Object;"
+"Ljava/lang/Object;"
+"Lorg/mozilla/javascript/Context;"
+"I"
+")Lorg/mozilla/javascript/Reference;";
break;
case Token.REF_NAME:
methodName = "nameRef";
signature = "(Ljava/lang/Object;"
+"Lorg/mozilla/javascript/Context;"
+"Lorg/mozilla/javascript/Scriptable;"
+"I"
+")Lorg/mozilla/javascript/Reference;";
cfw.addALoad(variableObjectLocal);
break;
case Token.REF_NS_NAME:
methodName = "nameRef";
signature = "(Ljava/lang/Object;"
+"Lorg/mozilla/javascript/Context;"
+"Lorg/mozilla/javascript/Scriptable;"
+"I"
+")Lorg/mozilla/javascript/Reference;";
cfw.addALoad(variableObjectLocal);
break;
default:
throw Kit.codeBug();
}
cfw.addPush(memberTypeFlags);
addScriptRuntimeInvoke(methodName, signature);
}
break;
@ -2183,45 +2227,6 @@ class BodyCodegen
+"Lorg/mozilla/javascript/Context;"
+")Ljava/lang/Object;");
break;
case Token.TOATTRNAME:
generateExpression(child, node);
cfw.addALoad(contextLocal);
addScriptRuntimeInvoke("toAttributeName",
"(Ljava/lang/Object;"
+"Lorg/mozilla/javascript/Context;"
+")Ljava/lang/Object;");
break;
case Token.DESC_REF:
generateExpression(child, node);
generateExpression(child.getNext(), node);
cfw.addALoad(contextLocal);
cfw.addALoad(variableObjectLocal);
addScriptRuntimeInvoke("getDescendantsRef",
"(Ljava/lang/Object;"
+"Ljava/lang/Object;"
+"Lorg/mozilla/javascript/Context;"
+"Lorg/mozilla/javascript/Scriptable;"
+")Lorg/mozilla/javascript/Reference;");
break;
case Token.COLONCOLON : {
if (child.getType() != Token.STRING)
throw Codegen.badTree();
String namespace = child.getString();
cfw.addPush(namespace);
child = child.getNext();
generateExpression(child, node);
cfw.addALoad(contextLocal);
cfw.addALoad(variableObjectLocal);
addScriptRuntimeInvoke("toQualifiedName",
"(Ljava/lang/String;"
+"Ljava/lang/Object;"
+"Lorg/mozilla/javascript/Context;"
+"Lorg/mozilla/javascript/Scriptable;"
+")Ljava/lang/Object;");
break;
}
default:
throw new RuntimeException("Unexpected node type "+type);

View File

@ -78,15 +78,11 @@ public abstract class XMLLib
public abstract boolean isXMLName(Context cx, Object name);
public abstract Object toQualifiedName(String namespace,
Object nameValue,
Scriptable scope);
public abstract Reference nameRef(Context cx, Object name,
Scriptable scope, int memberTypeFlags);
public abstract Object toAttributeName(Context cx, Object nameValue);
public abstract Reference xmlPrimaryReference(Context cx,
Object nameObject,
Scriptable scope);
public abstract Reference nameRef(Context cx, Object namespace, Object name,
Scriptable scope, int memberTypeFlags);
/**
* Escapes the reserved characters in a value of an attribute

View File

@ -77,9 +77,16 @@ public abstract class XMLObject extends IdScriptableObject
public abstract boolean ecmaDelete(Context cx, Object id);
/**
* To implement ECMAScript [[Descendants]].
* Generic reference to implement x.@y, x..y etc.
*/
public abstract Reference getDescendantsRef(Context cx, Object id);
public abstract Reference memberRef(Context cx, Object elem,
int memberTypeFlags);
/**
* Generic reference to implement x::ns, x.@ns::y, x..@ns::y etc.
*/
public abstract Reference memberRef(Context cx, Object namespace,
Object elem, int memberTypeFlags);
/**
* Wrap this object into NativeWith to implement the with statement.

View File

@ -287,17 +287,17 @@ class XML extends XMLObjectImpl
XmlOptions options = new XmlOptions();
if (lib.ignoreComments())
if (lib.ignoreComments)
{
options.put(XmlOptions.LOAD_STRIP_COMMENTS);
}
if (lib.ignoreProcessingInstructions())
if (lib.ignoreProcessingInstructions)
{
options.put(XmlOptions.LOAD_STRIP_PROCINSTS);
}
if (lib.ignoreWhitespace())
if (lib.ignoreWhitespace)
{
options.put(XmlOptions.LOAD_STRIP_WHITESPACE);
}
@ -476,25 +476,25 @@ todo need to handle namespace prefix not found in XML look for namespace type in
{
XmlOptions options = new XmlOptions();
if (lib.ignoreComments())
if (lib.ignoreComments)
{
options.put(XmlOptions.LOAD_STRIP_COMMENTS);
}
if (lib.ignoreProcessingInstructions())
if (lib.ignoreProcessingInstructions)
{
options.put(XmlOptions.LOAD_STRIP_PROCINSTS);
}
if (lib.ignoreWhitespace())
if (lib.ignoreWhitespace)
{
options.put(XmlOptions.LOAD_STRIP_WHITESPACE);
}
if (lib.prettyPrinting())
if (lib.prettyPrinting)
{
options.put(XmlOptions.SAVE_PRETTY_PRINT, null);
options.put(XmlOptions.SAVE_PRETTY_PRINT_INDENT, new Integer(lib.prettyIndent()));
options.put(XmlOptions.SAVE_PRETTY_PRINT_INDENT, new Integer(lib.prettyIndent));
}
return options;

View File

@ -100,55 +100,7 @@ public final class XMLLibImpl extends XMLLib
prettyIndent = 2;
}
boolean ignoreComments()
{
return ignoreComments;
}
boolean ignoreProcessingInstructions()
{
return ignoreProcessingInstructions;
}
boolean ignoreWhitespace()
{
return ignoreWhitespace;
}
boolean prettyPrinting()
{
return prettyPrinting;
}
int prettyIndent()
{
return prettyIndent;
}
private Namespace resolveNamespace(String prefix, Scriptable scope)
{
Namespace ns = null;
Scriptable nsScope = scope;
while (nsScope != null) {
Object obj = ScriptableObject.getProperty(nsScope, prefix);
if (obj instanceof Namespace) {
ns = (Namespace)obj;
break;
}
nsScope = nsScope.getParentScope();
}
if (ns == null) {
// Only namespace type allowed to left of :: operator.
throw Context.reportRuntimeError(
ScriptRuntime.getMessage1("msg.namespace.expected", prefix));
}
return ns;
}
XMLName toAttributeNameImpl(Context cx, Object nameValue)
XMLName toAttributeName(Context cx, Object nameValue)
{
String uri;
String localName;
@ -531,10 +483,12 @@ public final class XMLLibImpl extends XMLLib
return true;
}
public Object toQualifiedName(String namespace,
Object nameValue,
Scriptable scope)
XMLName toQualifiedName(Context cx, Object namespaceValue,
Object nameValue)
{
// This is duplication of constructQName(cx, namespaceValue, nameValue)
// but for XMLName
String uri;
String localName;
@ -545,31 +499,57 @@ public final class XMLLibImpl extends XMLLib
localName = ScriptRuntime.toString(nameValue);
}
if ("*".equals(namespace)) {
Namespace ns;
if (namespaceValue == Undefined.instance) {
if ("*".equals(localName)) {
ns = null;
} else {
ns = getDefaultNamespace(cx);
}
} else if (namespaceValue == null) {
ns = null;
} else if (namespaceValue instanceof Namespace) {
ns = (Namespace)namespaceValue;
} else {
ns = constructNamespace(cx, namespaceValue);
}
if (ns == null) {
uri = null;
} else {
uri = resolveNamespace(namespace, scope).uri();
uri = ns.uri();
}
return XMLName.formProperty(uri, localName);
}
public Object toAttributeName(Context cx, Object nameValue)
public Reference nameRef(Context cx, Object name,
Scriptable scope, int memberTypeFlags)
{
return toAttributeNameImpl(cx, nameValue);
if ((memberTypeFlags & Node.ATTRIBUTE_FLAG) == 0) {
// should only be called foir cases like @name or @[expr]
throw Kit.codeBug();
}
XMLName xmlName = toAttributeName(cx, name);
return xmlPrimaryReference(cx, xmlName, scope);
}
/**
* See E4X 11.1 PrimaryExpression : PropertyIdentifier production
*/
public Reference xmlPrimaryReference(Context cx,
Object nameObject,
Scriptable scope)
public Reference nameRef(Context cx, Object namespace, Object name,
Scriptable scope, int memberTypeFlags)
{
if (!(nameObject instanceof XMLName))
throw new IllegalArgumentException();
XMLName xmlName = toQualifiedName(cx, namespace, name);
if ((memberTypeFlags & Node.ATTRIBUTE_FLAG) != 0) {
if (!xmlName.isAttributeName()) {
xmlName.setAttributeName();
}
}
return xmlPrimaryReference(cx, xmlName, scope);
}
XMLName xmlName = (XMLName)nameObject;
private Reference xmlPrimaryReference(Context cx,
XMLName xmlName,
Scriptable scope)
{
XMLObjectImpl xmlObj;
XMLObjectImpl firstXmlObject = null;
for (;;) {
@ -606,7 +586,7 @@ public final class XMLLibImpl extends XMLLib
{
String text = ScriptRuntime.toString(value);
if (text.length() == 0) return text;
if (text.length() == 0) return "\"\"";
XmlObject xo = XmlObject.Factory.newInstance();

View File

@ -245,10 +245,38 @@ abstract class XMLObjectImpl extends XMLObject
return true;
}
public Reference getDescendantsRef(Context cx, Object id)
public Reference memberRef(Context cx, Object elem, int memberTypeFlags)
{
XMLName xmlName = lib.toXMLName(cx, id);
return new XMLReference(true, this, xmlName);
XMLName xmlName;
if ((memberTypeFlags & Node.ATTRIBUTE_FLAG) != 0) {
xmlName = lib.toAttributeName(cx, elem);
} else {
if ((memberTypeFlags & Node.DESCENDANTS_FLAG) == 0) {
// Code generation would use ecma(Get|Has|Delete|Set) for
// normal name idenrifiers so one ATTRIBUTE_FLAG
// or DESCENDANTS_FLAG has to be set
throw Kit.codeBug();
}
xmlName = lib.toXMLName(cx, elem);
}
boolean descendants = ((memberTypeFlags & Node.DESCENDANTS_FLAG) != 0);
return new XMLReference(descendants, this, xmlName);
}
/**
* Generic reference to implement x::ns, x.@ns::y, x..@ns::y etc.
*/
public Reference memberRef(Context cx, Object namespace, Object elem,
int memberTypeFlags)
{
XMLName xmlName = lib.toQualifiedName(cx, namespace, elem);
if ((memberTypeFlags & Node.ATTRIBUTE_FLAG) != 0) {
if (!xmlName.isAttributeName()) {
xmlName.setAttributeName();
}
}
boolean descendants = ((memberTypeFlags & Node.DESCENDANTS_FLAG) != 0);
return new XMLReference(descendants, this, xmlName);
}
public NativeWith enterWith(Scriptable scope)
@ -523,7 +551,7 @@ abstract class XMLObjectImpl extends XMLObject
// it should be OK. Trust test suite for now.
arg0 = ScriptRuntime.toString(arg0);
}
XMLName xmlName = lib.toAttributeNameImpl(cx, arg0);
XMLName xmlName = lib.toAttributeName(cx, arg0);
return realThis.attribute(xmlName);
}
case Id_attributes: