mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-08 04:27:37 +00:00
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:
parent
e57cbd8a79
commit
f91bbb6233
@ -1863,23 +1863,29 @@ EmitIndexOp(JSContext *cx, JSOp op, uintN index, BytecodeEmitter *bce, JSOp *psu
|
||||
JS_END_MACRO
|
||||
|
||||
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);
|
||||
|
||||
if (op == JSOP_GETPROP &&
|
||||
pn->pn_atom == cx->runtime->atomState.lengthAtom) {
|
||||
if (op == JSOP_GETPROP && atom == cx->runtime->atomState.lengthAtom) {
|
||||
/* Specialize length accesses for the interpreter. */
|
||||
op = JSOP_LENGTH;
|
||||
}
|
||||
|
||||
jsatomid index;
|
||||
if (!bce->makeAtomIndex(pn->pn_atom, &index))
|
||||
if (!bce->makeAtomIndex(atom, &index))
|
||||
return false;
|
||||
|
||||
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
|
||||
EmitObjectOp(JSContext *cx, ObjectBox *objbox, JSOp op, BytecodeEmitter *bce)
|
||||
{
|
||||
@ -5478,16 +5484,16 @@ EmitXMLTag(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||
}
|
||||
|
||||
static bool
|
||||
EmitXMLProcessingInstruction(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||
EmitXMLProcessingInstruction(JSContext *cx, BytecodeEmitter *bce, XMLProcessingInstruction &pi)
|
||||
{
|
||||
JS_ASSERT(!bce->inStrictMode());
|
||||
|
||||
jsatomid index;
|
||||
if (!bce->makeAtomIndex(pn->pn_pidata, &index))
|
||||
if (!bce->makeAtomIndex(pi.data(), &index))
|
||||
return false;
|
||||
if (!EmitIndexOp(cx, JSOP_QNAMEPART, index, bce))
|
||||
return false;
|
||||
if (!EmitAtomOp(cx, pn, JSOP_XMLPI, bce))
|
||||
if (!EmitAtomOp(cx, pi.target(), JSOP_XMLPI, bce))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
@ -7594,7 +7600,7 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||
break;
|
||||
|
||||
case PNK_XMLPI:
|
||||
if (!EmitXMLProcessingInstruction(cx, bce, pn))
|
||||
if (!EmitXMLProcessingInstruction(cx, bce, pn->asXMLProcessingInstruction()))
|
||||
return false;
|
||||
break;
|
||||
#endif /* JS_HAS_XML_SUPPORT */
|
||||
|
@ -273,11 +273,13 @@ FoldXMLConstants(JSContext *cx, ParseNode *pn, TreeContext *tc)
|
||||
return JS_FALSE;
|
||||
break;
|
||||
|
||||
case PNK_XMLPI:
|
||||
str = js_MakeXMLPIString(cx, pn2->pn_pitarget, pn2->pn_pidata);
|
||||
case PNK_XMLPI: {
|
||||
XMLProcessingInstruction &pi = pn2->asXMLProcessingInstruction();
|
||||
str = js_MakeXMLPIString(cx, pi.target(), pi.data());
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
cantfold:
|
||||
default:
|
||||
|
@ -485,6 +485,7 @@ struct Definition;
|
||||
class LoopControlStatement;
|
||||
class BreakStatement;
|
||||
class ContinueStatement;
|
||||
class XMLProcessingInstruction;
|
||||
|
||||
struct ParseNode {
|
||||
private:
|
||||
@ -617,15 +618,16 @@ struct ParseNode {
|
||||
AtomDefnMapPtr defnMap;
|
||||
ParseNode *tree; /* sub-tree containing name uses */
|
||||
} 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 */
|
||||
class {
|
||||
friend class LoopControlStatement;
|
||||
PropertyName *label; /* target of break/continue statement */
|
||||
} loopControl;
|
||||
class { /* E4X <?target data?> XML PI */
|
||||
friend class XMLProcessingInstruction;
|
||||
PropertyName *target; /* non-empty */
|
||||
JSAtom *data; /* may be empty, never null */
|
||||
} xmlpi;
|
||||
} pn_u;
|
||||
|
||||
#define pn_funbox pn_u.name.funbox
|
||||
@ -656,8 +658,6 @@ struct ParseNode {
|
||||
#define pn_names pn_u.nameset.defnMap
|
||||
#define pn_tree pn_u.nameset.tree
|
||||
#define pn_dval pn_u.dval
|
||||
#define pn_pitarget pn_u.xmlpi.target
|
||||
#define pn_pidata pn_u.xmlpi.data
|
||||
|
||||
protected:
|
||||
void init(TokenKind type, JSOp op, ParseNodeArity arity) {
|
||||
@ -924,6 +924,9 @@ struct ParseNode {
|
||||
/* Casting operations. */
|
||||
inline BreakStatement &asBreakStatement();
|
||||
inline ContinueStatement &asContinueStatement();
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
inline XMLProcessingInstruction &asXMLProcessingInstruction();
|
||||
#endif
|
||||
};
|
||||
|
||||
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 *
|
||||
CloneLeftHandSide(ParseNode *opn, TreeContext *tc);
|
||||
|
||||
|
@ -6363,13 +6363,10 @@ Parser::xmlElementContent(ParseNode *pn)
|
||||
pn2->pn_xflags &= ~PNX_XMLROOT;
|
||||
pn->pn_xflags |= pn2->pn_xflags;
|
||||
} 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)
|
||||
return false;
|
||||
const Token &tok = tokenStream.currentToken();
|
||||
pn2->setOp(tok.t_op);
|
||||
pn2->pn_pitarget = tok.xmlPITarget();
|
||||
pn2->pn_pidata = tok.xmlPIData();
|
||||
} else {
|
||||
JS_ASSERT(tt == TOK_XMLCDATA || tt == TOK_XMLCOMMENT);
|
||||
pn2 = atomNode(tt == TOK_XMLCDATA ? PNK_XMLCDATA : PNK_XMLCOMMENT,
|
||||
@ -7053,14 +7050,14 @@ Parser::primaryExpr(TokenKind tt, JSBool afterDot)
|
||||
break;
|
||||
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
case TOK_XMLPI:
|
||||
case TOK_XMLPI: {
|
||||
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)
|
||||
return NULL;
|
||||
pn->pn_pitarget = tokenStream.currentToken().xmlPITarget();
|
||||
pn->pn_pidata = tokenStream.currentToken().xmlPIData();
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
case TOK_NAME:
|
||||
|
@ -330,8 +330,8 @@ struct Token {
|
||||
private:
|
||||
friend struct Token;
|
||||
struct { /* pair for <?target data?> XML PI */
|
||||
JSAtom *data; /* auxiliary atom table entry */
|
||||
PropertyName *target; /* main atom table entry */
|
||||
PropertyName *target; /* non-empty */
|
||||
JSAtom *data; /* maybe empty, never null */
|
||||
} xmlpi;
|
||||
uint16_t sharpNumber; /* sharp variable number: #1# or #1= */
|
||||
jsdouble number; /* floating point number */
|
||||
@ -359,6 +359,9 @@ struct Token {
|
||||
}
|
||||
|
||||
void setProcessingInstruction(PropertyName *target, JSAtom *data) {
|
||||
JS_ASSERT(target);
|
||||
JS_ASSERT(data);
|
||||
JS_ASSERT(!target->empty());
|
||||
u.xmlpi.target = target;
|
||||
u.xmlpi.data = data;
|
||||
}
|
||||
|
@ -619,8 +619,6 @@ class NodeBuilder
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
@ -1570,12 +1568,6 @@ NodeBuilder::xmlComment(Value text, TokenPos *pos, Value *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
|
||||
NodeBuilder::xmlPI(Value target, Value contents, TokenPos *pos, Value *dst)
|
||||
{
|
||||
@ -2795,14 +2787,13 @@ ASTSerializer::xml(ParseNode *pn, Value *dst)
|
||||
case PNK_XMLCOMMENT:
|
||||
return builder.xmlComment(atomContents(pn->pn_atom), &pn->pn_pos, dst);
|
||||
|
||||
case PNK_XMLPI:
|
||||
if (!pn->pn_pidata)
|
||||
return builder.xmlPI(atomContents(pn->pn_pitarget), &pn->pn_pos, dst);
|
||||
else
|
||||
return builder.xmlPI(atomContents(pn->pn_pitarget),
|
||||
atomContents(pn->pn_pidata),
|
||||
&pn->pn_pos,
|
||||
dst);
|
||||
case PNK_XMLPI: {
|
||||
XMLProcessingInstruction &pi = pn->asXMLProcessingInstruction();
|
||||
return builder.xmlPI(atomContents(pi.target()),
|
||||
atomContents(pi.data()),
|
||||
&pi.pn_pos,
|
||||
dst);
|
||||
}
|
||||
#endif
|
||||
|
||||
default:
|
||||
|
@ -1621,11 +1621,12 @@ ParseNodeToXML(Parser *parser, ParseNode *pn,
|
||||
goto skip_child;
|
||||
xml_class = JSXML_CLASS_COMMENT;
|
||||
} else if (pn->isKind(PNK_XMLPI)) {
|
||||
XMLProcessingInstruction &pi = pn->asXMLProcessingInstruction();
|
||||
if (IS_XML(str)) {
|
||||
Value v = StringValue(str);
|
||||
JSAutoByteString bytes;
|
||||
if (js_ValueToPrintable(cx, v, &bytes)) {
|
||||
ReportCompileErrorNumber(cx, &parser->tokenStream, pn,
|
||||
ReportCompileErrorNumber(cx, &parser->tokenStream, &pi,
|
||||
JSREPORT_ERROR, JSMSG_RESERVED_ID, bytes.ptr());
|
||||
}
|
||||
goto fail;
|
||||
@ -1634,11 +1635,11 @@ ParseNodeToXML(Parser *parser, ParseNode *pn,
|
||||
if (flags & XSF_IGNORE_PROCESSING_INSTRUCTIONS)
|
||||
goto skip_child;
|
||||
|
||||
qn = ParseNodeToQName(parser, pn, inScopeNSes, JS_FALSE);
|
||||
qn = ParseNodeToQName(parser, &pi, inScopeNSes, JS_FALSE);
|
||||
if (!qn)
|
||||
goto fail;
|
||||
|
||||
str = pn->pn_pidata ? pn->pn_pidata : cx->runtime->emptyString;
|
||||
str = pi.data();
|
||||
xml_class = JSXML_CLASS_PROCESSING_INSTRUCTION;
|
||||
} else {
|
||||
/* CDATA section content, or element text. */
|
||||
|
Loading…
Reference in New Issue
Block a user