зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
e57cbd8a79
Коммит
f91bbb6233
|
@ -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. */
|
||||||
|
|
Загрузка…
Ссылка в новой задаче