mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-21 17:59:34 +00:00
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:
parent
be537ec4bf
commit
e048fa7512
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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";
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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:
|
||||
|
Loading…
x
Reference in New Issue
Block a user