Bug 710932 - Create <?target data?> expressions using a constructor that doesn't examine the token stream. r=jorendorff

--HG--
extra : rebase_source : f3b8ca1065e7694cb411d14800052e7cef48f853
This commit is contained in:
Jeff Walden 2011-12-09 23:28:59 -05:00
Родитель e57cbd8a79
Коммит f91bbb6233
7 изменённых файлов: 78 добавлений и 46 удалений

Просмотреть файл

@ -1863,23 +1863,29 @@ EmitIndexOp(JSContext *cx, JSOp op, uintN index, BytecodeEmitter *bce, JSOp *psu
JS_END_MACRO JS_END_MACRO
static bool static bool
EmitAtomOp(JSContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce, JSOp *psuffix = NULL) EmitAtomOp(JSContext *cx, JSAtom *atom, JSOp op, BytecodeEmitter *bce, JSOp *psuffix = NULL)
{ {
JS_ASSERT(JOF_OPTYPE(op) == JOF_ATOM); JS_ASSERT(JOF_OPTYPE(op) == JOF_ATOM);
if (op == JSOP_GETPROP && if (op == JSOP_GETPROP && atom == cx->runtime->atomState.lengthAtom) {
pn->pn_atom == cx->runtime->atomState.lengthAtom) {
/* Specialize length accesses for the interpreter. */ /* Specialize length accesses for the interpreter. */
op = JSOP_LENGTH; op = JSOP_LENGTH;
} }
jsatomid index; jsatomid index;
if (!bce->makeAtomIndex(pn->pn_atom, &index)) if (!bce->makeAtomIndex(atom, &index))
return false; return false;
return EmitIndexOp(cx, op, index, bce, psuffix); return EmitIndexOp(cx, op, index, bce, psuffix);
} }
static bool
EmitAtomOp(JSContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce, JSOp *psuffix = NULL)
{
JS_ASSERT(pn->pn_atom != NULL);
return EmitAtomOp(cx, pn->pn_atom, op, bce, psuffix);
}
static JSBool static JSBool
EmitObjectOp(JSContext *cx, ObjectBox *objbox, JSOp op, BytecodeEmitter *bce) EmitObjectOp(JSContext *cx, ObjectBox *objbox, JSOp op, BytecodeEmitter *bce)
{ {
@ -5478,16 +5484,16 @@ EmitXMLTag(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
} }
static bool static bool
EmitXMLProcessingInstruction(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn) EmitXMLProcessingInstruction(JSContext *cx, BytecodeEmitter *bce, XMLProcessingInstruction &pi)
{ {
JS_ASSERT(!bce->inStrictMode()); JS_ASSERT(!bce->inStrictMode());
jsatomid index; jsatomid index;
if (!bce->makeAtomIndex(pn->pn_pidata, &index)) if (!bce->makeAtomIndex(pi.data(), &index))
return false; return false;
if (!EmitIndexOp(cx, JSOP_QNAMEPART, index, bce)) if (!EmitIndexOp(cx, JSOP_QNAMEPART, index, bce))
return false; return false;
if (!EmitAtomOp(cx, pn, JSOP_XMLPI, bce)) if (!EmitAtomOp(cx, pi.target(), JSOP_XMLPI, bce))
return false; return false;
return true; return true;
} }
@ -7594,7 +7600,7 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
break; break;
case PNK_XMLPI: case PNK_XMLPI:
if (!EmitXMLProcessingInstruction(cx, bce, pn)) if (!EmitXMLProcessingInstruction(cx, bce, pn->asXMLProcessingInstruction()))
return false; return false;
break; break;
#endif /* JS_HAS_XML_SUPPORT */ #endif /* JS_HAS_XML_SUPPORT */

Просмотреть файл

@ -273,11 +273,13 @@ FoldXMLConstants(JSContext *cx, ParseNode *pn, TreeContext *tc)
return JS_FALSE; return JS_FALSE;
break; break;
case PNK_XMLPI: case PNK_XMLPI: {
str = js_MakeXMLPIString(cx, pn2->pn_pitarget, pn2->pn_pidata); XMLProcessingInstruction &pi = pn2->asXMLProcessingInstruction();
str = js_MakeXMLPIString(cx, pi.target(), pi.data());
if (!str) if (!str)
return JS_FALSE; return JS_FALSE;
break; break;
}
cantfold: cantfold:
default: default:

Просмотреть файл

@ -485,6 +485,7 @@ struct Definition;
class LoopControlStatement; class LoopControlStatement;
class BreakStatement; class BreakStatement;
class ContinueStatement; class ContinueStatement;
class XMLProcessingInstruction;
struct ParseNode { struct ParseNode {
private: private:
@ -617,15 +618,16 @@ struct ParseNode {
AtomDefnMapPtr defnMap; AtomDefnMapPtr defnMap;
ParseNode *tree; /* sub-tree containing name uses */ ParseNode *tree; /* sub-tree containing name uses */
} nameset; } nameset;
struct { /* PN_NULLARY variant for E4X XML PI */
PropertyName *target; /* target in <?target data?> */
JSAtom *data; /* data (or null) in <?target data?> */
} xmlpi;
jsdouble dval; /* aligned numeric literal value */ jsdouble dval; /* aligned numeric literal value */
class { class {
friend class LoopControlStatement; friend class LoopControlStatement;
PropertyName *label; /* target of break/continue statement */ PropertyName *label; /* target of break/continue statement */
} loopControl; } loopControl;
class { /* E4X <?target data?> XML PI */
friend class XMLProcessingInstruction;
PropertyName *target; /* non-empty */
JSAtom *data; /* may be empty, never null */
} xmlpi;
} pn_u; } pn_u;
#define pn_funbox pn_u.name.funbox #define pn_funbox pn_u.name.funbox
@ -656,8 +658,6 @@ struct ParseNode {
#define pn_names pn_u.nameset.defnMap #define pn_names pn_u.nameset.defnMap
#define pn_tree pn_u.nameset.tree #define pn_tree pn_u.nameset.tree
#define pn_dval pn_u.dval #define pn_dval pn_u.dval
#define pn_pitarget pn_u.xmlpi.target
#define pn_pidata pn_u.xmlpi.data
protected: protected:
void init(TokenKind type, JSOp op, ParseNodeArity arity) { void init(TokenKind type, JSOp op, ParseNodeArity arity) {
@ -924,6 +924,9 @@ struct ParseNode {
/* Casting operations. */ /* Casting operations. */
inline BreakStatement &asBreakStatement(); inline BreakStatement &asBreakStatement();
inline ContinueStatement &asContinueStatement(); inline ContinueStatement &asContinueStatement();
#if JS_HAS_XML_SUPPORT
inline XMLProcessingInstruction &asXMLProcessingInstruction();
#endif
}; };
struct NullaryNode : public ParseNode { struct NullaryNode : public ParseNode {
@ -1066,6 +1069,35 @@ class DebuggerStatement : public ParseNode {
{ } { }
}; };
#if JS_HAS_XML_SUPPORT
class XMLProcessingInstruction : public ParseNode {
public:
XMLProcessingInstruction(PropertyName *target, JSAtom *data, const TokenPos &pos)
: ParseNode(PNK_XMLPI, JSOP_NOP, PN_NULLARY, pos)
{
pn_u.xmlpi.target = target;
pn_u.xmlpi.data = data;
}
PropertyName *target() const {
return pn_u.xmlpi.target;
}
JSAtom *data() const {
return pn_u.xmlpi.data;
}
};
inline XMLProcessingInstruction &
ParseNode::asXMLProcessingInstruction()
{
JS_ASSERT(isKind(PNK_XMLPI));
JS_ASSERT(isOp(JSOP_NOP));
JS_ASSERT(pn_arity == PN_NULLARY);
return *static_cast<XMLProcessingInstruction *>(this);
}
#endif
ParseNode * ParseNode *
CloneLeftHandSide(ParseNode *opn, TreeContext *tc); CloneLeftHandSide(ParseNode *opn, TreeContext *tc);

Просмотреть файл

@ -6363,13 +6363,10 @@ Parser::xmlElementContent(ParseNode *pn)
pn2->pn_xflags &= ~PNX_XMLROOT; pn2->pn_xflags &= ~PNX_XMLROOT;
pn->pn_xflags |= pn2->pn_xflags; pn->pn_xflags |= pn2->pn_xflags;
} else if (tt == TOK_XMLPI) { } else if (tt == TOK_XMLPI) {
pn2 = NullaryNode::create(PNK_XMLPI, tc); const Token &tok = tokenStream.currentToken();
pn2 = new_<XMLProcessingInstruction>(tok.xmlPITarget(), tok.xmlPIData(), tok.pos);
if (!pn2) if (!pn2)
return false; return false;
const Token &tok = tokenStream.currentToken();
pn2->setOp(tok.t_op);
pn2->pn_pitarget = tok.xmlPITarget();
pn2->pn_pidata = tok.xmlPIData();
} else { } else {
JS_ASSERT(tt == TOK_XMLCDATA || tt == TOK_XMLCOMMENT); JS_ASSERT(tt == TOK_XMLCDATA || tt == TOK_XMLCOMMENT);
pn2 = atomNode(tt == TOK_XMLCDATA ? PNK_XMLCDATA : PNK_XMLCOMMENT, pn2 = atomNode(tt == TOK_XMLCDATA ? PNK_XMLCDATA : PNK_XMLCOMMENT,
@ -7053,14 +7050,14 @@ Parser::primaryExpr(TokenKind tt, JSBool afterDot)
break; break;
#if JS_HAS_XML_SUPPORT #if JS_HAS_XML_SUPPORT
case TOK_XMLPI: case TOK_XMLPI: {
JS_ASSERT(!tc->inStrictMode()); JS_ASSERT(!tc->inStrictMode());
pn = NullaryNode::create(PNK_XMLPI, tc); const Token &tok = tokenStream.currentToken();
pn = new_<XMLProcessingInstruction>(tok.xmlPITarget(), tok.xmlPIData(), tok.pos);
if (!pn) if (!pn)
return NULL; return NULL;
pn->pn_pitarget = tokenStream.currentToken().xmlPITarget();
pn->pn_pidata = tokenStream.currentToken().xmlPIData();
break; break;
}
#endif #endif
case TOK_NAME: case TOK_NAME:

Просмотреть файл

@ -330,8 +330,8 @@ struct Token {
private: private:
friend struct Token; friend struct Token;
struct { /* pair for <?target data?> XML PI */ struct { /* pair for <?target data?> XML PI */
JSAtom *data; /* auxiliary atom table entry */ PropertyName *target; /* non-empty */
PropertyName *target; /* main atom table entry */ JSAtom *data; /* maybe empty, never null */
} xmlpi; } xmlpi;
uint16_t sharpNumber; /* sharp variable number: #1# or #1= */ uint16_t sharpNumber; /* sharp variable number: #1# or #1= */
jsdouble number; /* floating point number */ jsdouble number; /* floating point number */
@ -359,6 +359,9 @@ struct Token {
} }
void setProcessingInstruction(PropertyName *target, JSAtom *data) { void setProcessingInstruction(PropertyName *target, JSAtom *data) {
JS_ASSERT(target);
JS_ASSERT(data);
JS_ASSERT(!target->empty());
u.xmlpi.target = target; u.xmlpi.target = target;
u.xmlpi.data = data; u.xmlpi.data = data;
} }

Просмотреть файл

@ -619,8 +619,6 @@ class NodeBuilder
bool xmlComment(Value text, TokenPos *pos, Value *dst); bool xmlComment(Value text, TokenPos *pos, Value *dst);
bool xmlPI(Value target, TokenPos *pos, Value *dst);
bool xmlPI(Value target, Value content, TokenPos *pos, Value *dst); bool xmlPI(Value target, Value content, TokenPos *pos, Value *dst);
}; };
@ -1570,12 +1568,6 @@ NodeBuilder::xmlComment(Value text, TokenPos *pos, Value *dst)
return newNode(AST_XMLCOMMENT, pos, "contents", text, dst); return newNode(AST_XMLCOMMENT, pos, "contents", text, dst);
} }
bool
NodeBuilder::xmlPI(Value target, TokenPos *pos, Value *dst)
{
return xmlPI(target, NullValue(), pos, dst);
}
bool bool
NodeBuilder::xmlPI(Value target, Value contents, TokenPos *pos, Value *dst) NodeBuilder::xmlPI(Value target, Value contents, TokenPos *pos, Value *dst)
{ {
@ -2795,14 +2787,13 @@ ASTSerializer::xml(ParseNode *pn, Value *dst)
case PNK_XMLCOMMENT: case PNK_XMLCOMMENT:
return builder.xmlComment(atomContents(pn->pn_atom), &pn->pn_pos, dst); return builder.xmlComment(atomContents(pn->pn_atom), &pn->pn_pos, dst);
case PNK_XMLPI: case PNK_XMLPI: {
if (!pn->pn_pidata) XMLProcessingInstruction &pi = pn->asXMLProcessingInstruction();
return builder.xmlPI(atomContents(pn->pn_pitarget), &pn->pn_pos, dst); return builder.xmlPI(atomContents(pi.target()),
else atomContents(pi.data()),
return builder.xmlPI(atomContents(pn->pn_pitarget), &pi.pn_pos,
atomContents(pn->pn_pidata), dst);
&pn->pn_pos, }
dst);
#endif #endif
default: default:

Просмотреть файл

@ -1621,11 +1621,12 @@ ParseNodeToXML(Parser *parser, ParseNode *pn,
goto skip_child; goto skip_child;
xml_class = JSXML_CLASS_COMMENT; xml_class = JSXML_CLASS_COMMENT;
} else if (pn->isKind(PNK_XMLPI)) { } else if (pn->isKind(PNK_XMLPI)) {
XMLProcessingInstruction &pi = pn->asXMLProcessingInstruction();
if (IS_XML(str)) { if (IS_XML(str)) {
Value v = StringValue(str); Value v = StringValue(str);
JSAutoByteString bytes; JSAutoByteString bytes;
if (js_ValueToPrintable(cx, v, &bytes)) { if (js_ValueToPrintable(cx, v, &bytes)) {
ReportCompileErrorNumber(cx, &parser->tokenStream, pn, ReportCompileErrorNumber(cx, &parser->tokenStream, &pi,
JSREPORT_ERROR, JSMSG_RESERVED_ID, bytes.ptr()); JSREPORT_ERROR, JSMSG_RESERVED_ID, bytes.ptr());
} }
goto fail; goto fail;
@ -1634,11 +1635,11 @@ ParseNodeToXML(Parser *parser, ParseNode *pn,
if (flags & XSF_IGNORE_PROCESSING_INSTRUCTIONS) if (flags & XSF_IGNORE_PROCESSING_INSTRUCTIONS)
goto skip_child; goto skip_child;
qn = ParseNodeToQName(parser, pn, inScopeNSes, JS_FALSE); qn = ParseNodeToQName(parser, &pi, inScopeNSes, JS_FALSE);
if (!qn) if (!qn)
goto fail; goto fail;
str = pn->pn_pidata ? pn->pn_pidata : cx->runtime->emptyString; str = pi.data();
xml_class = JSXML_CLASS_PROCESSING_INSTRUCTION; xml_class = JSXML_CLASS_PROCESSING_INSTRUCTION;
} else { } else {
/* CDATA section content, or element text. */ /* CDATA section content, or element text. */