mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-13 19:41:49 +00:00
- Added strict warning "reference to undefined XML name {0}" to cope with
ECMA-357 botch where * or @b or (given valid namespace reference n) n::id results in undefined, instead of a TypeError. - Lazily bootstrap AnyName and AttributeName classes, instead of leaving the former uninitialized, and initializing the latter only if QName is init'ed. These classes, representing ECMA-357 internal types, must be initialized in order to string conversion and default value on them to return useful results. So this change also requires the shared qname_toString to cope with these classes, which ape QName in having a JSXMLQName as private data. - Revise Filtering Predicate Expressions bytecode schema to avoid bogo-script creating in js_FilterXMLObject. With a new JSOP_ENDFILTER bytecode acting in lieu of JSOP_POPV, but also exiting the nested js_Interpret() call, the runtime can avoid trying to fake a JSScript for the subsequence of script bytecode in parens in x.(e), that contains the bytecode for e plus the pop or endfilter op. This requires a historic reparameterization of js_Interpret to take the starting pc! I cleaned up order of declaration, use, and useless init nits for a few variables while messing with it. - Based on the above change, fix the decompiler to handle filtered predicate expressions -- that code was stubbed out till now, and I forgot to go back. All better now, especially thanks to JSOP_ENDFILTER. - Also while fixing filtered predicates, eliminate the useless TOK_RP parse node above the parenthesized expression, to avoid a JSOP_GROUP bytecode. - Fix js_GetAttributeNameObject so it doesn't take over its QName parameter's object and rebind it to an object of class AttributeName -- instead, clone the qn if necessary. This is important to cope with the errata, noticed a while ago but finally recorded: 9.2.1.2 Step 2(e)(i, ii), 9.2.1.2 Step 7(e)(i), 9.2.1.3 Step 2(b)(ii)(1)(a) All uses of a.[[Name]] for an attribute a in these sections that pass that QName object to [[Delete]] must pass an AttributeName cloned from a.[[Name]]. The [[Name]] internal property is always a QName instance and never an AttributeName or AnyName instance. But [[Delete]] will not operate on x.[[Attributes]] when given a QName by these sections, so a child could be wrongly deleted instead of the attribute of the same name. This rework exposed a bug in the XML.prototype.name() impl, where it was returning an AttributeName, not a QName, for attribute-class XML objects. Clearly wrong -- the E4X spec makes plain early on that [[Name]] is always a QName -- but the spec and e4x testsuite seemed to require it due to the above-noted errata.
This commit is contained in:
parent
b397544e5e
commit
d1291966ce
@ -276,3 +276,4 @@ MSG_DEF(JSMSG_BAD_FOR_EACH_LOOP, 193, 0, JSEXN_SYNTAXERR, "invalid for each
|
|||||||
MSG_DEF(JSMSG_BAD_XMLLIST_PUT, 194, 1, JSEXN_TYPEERR, "can't set property {0} in XMLList")
|
MSG_DEF(JSMSG_BAD_XMLLIST_PUT, 194, 1, JSEXN_TYPEERR, "can't set property {0} in XMLList")
|
||||||
MSG_DEF(JSMSG_UNKNOWN_XML_ENTITY, 195, 1, JSEXN_TYPEERR, "unknown XML entity {0}")
|
MSG_DEF(JSMSG_UNKNOWN_XML_ENTITY, 195, 1, JSEXN_TYPEERR, "unknown XML entity {0}")
|
||||||
MSG_DEF(JSMSG_BAD_XML_NCR, 196, 1, JSEXN_TYPEERR, "malformed XML character {0}")
|
MSG_DEF(JSMSG_BAD_XML_NCR, 196, 1, JSEXN_TYPEERR, "malformed XML character {0}")
|
||||||
|
MSG_DEF(JSMSG_UNDEFINED_XML_NAME, 197, 1, JSEXN_TYPEERR, "reference to undefined XML name {0}")
|
||||||
|
@ -1305,6 +1305,8 @@ static JSStdName standard_class_names[] = {
|
|||||||
{js_InitXMLClass, LAZILY_PINNED_ATOM(isXMLName)},
|
{js_InitXMLClass, LAZILY_PINNED_ATOM(isXMLName)},
|
||||||
{js_InitNamespaceClass, LAZILY_PINNED_ATOM(Namespace)},
|
{js_InitNamespaceClass, LAZILY_PINNED_ATOM(Namespace)},
|
||||||
{js_InitQNameClass, LAZILY_PINNED_ATOM(QName)},
|
{js_InitQNameClass, LAZILY_PINNED_ATOM(QName)},
|
||||||
|
{js_InitQNameClass, LAZILY_PINNED_ATOM(AnyName)},
|
||||||
|
{js_InitQNameClass, LAZILY_PINNED_ATOM(AttributeName)},
|
||||||
{js_InitXMLClass, LAZILY_PINNED_ATOM(XML)},
|
{js_InitXMLClass, LAZILY_PINNED_ATOM(XML)},
|
||||||
{js_InitXMLClass, LAZILY_PINNED_ATOM(XMLList)},
|
{js_InitXMLClass, LAZILY_PINNED_ATOM(XMLList)},
|
||||||
#endif
|
#endif
|
||||||
|
@ -210,6 +210,8 @@ struct JSAtomState {
|
|||||||
|
|
||||||
/* Less frequently used atoms, pinned lazily by JS_ResolveStandardClass. */
|
/* Less frequently used atoms, pinned lazily by JS_ResolveStandardClass. */
|
||||||
struct {
|
struct {
|
||||||
|
JSAtom *AnyNameAtom;
|
||||||
|
JSAtom *AttributeNameAtom;
|
||||||
JSAtom *EvalErrorAtom;
|
JSAtom *EvalErrorAtom;
|
||||||
JSAtom *InfinityAtom;
|
JSAtom *InfinityAtom;
|
||||||
JSAtom *InternalErrorAtom;
|
JSAtom *InternalErrorAtom;
|
||||||
|
@ -4240,12 +4240,12 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
|||||||
case TOK_FILTER:
|
case TOK_FILTER:
|
||||||
if (!js_EmitTree(cx, cg, pn->pn_left))
|
if (!js_EmitTree(cx, cg, pn->pn_left))
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
jmp = js_Emit3(cx, cg, pn->pn_op, 0, 0);
|
jmp = js_Emit3(cx, cg, JSOP_FILTER, 0, 0);
|
||||||
if (jmp < 0)
|
if (jmp < 0)
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
if (!js_EmitTree(cx, cg, pn->pn_right))
|
if (!js_EmitTree(cx, cg, pn->pn_right))
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
if (js_Emit1(cx, cg, JSOP_POPV) < 0)
|
if (js_Emit1(cx, cg, JSOP_ENDFILTER) < 0)
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, jmp);
|
CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, jmp);
|
||||||
break;
|
break;
|
||||||
|
@ -1303,7 +1303,7 @@ have_fun:
|
|||||||
frame.scopeChain = funobj;
|
frame.scopeChain = funobj;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
ok = js_Interpret(cx, &v);
|
ok = js_Interpret(cx, script->code, &v);
|
||||||
} else {
|
} else {
|
||||||
/* fun might be onerror trying to report a syntax error in itself. */
|
/* fun might be onerror trying to report a syntax error in itself. */
|
||||||
frame.scopeChain = NULL;
|
frame.scopeChain = NULL;
|
||||||
@ -1513,7 +1513,7 @@ js_Execute(JSContext *cx, JSObject *chain, JSScript *script,
|
|||||||
* Use frame.rval, not result, so the last result stays rooted across any
|
* Use frame.rval, not result, so the last result stays rooted across any
|
||||||
* GC activations nested within this js_Interpret.
|
* GC activations nested within this js_Interpret.
|
||||||
*/
|
*/
|
||||||
ok = js_Interpret(cx, &frame.rval);
|
ok = js_Interpret(cx, script->code, &frame.rval);
|
||||||
*result = frame.rval;
|
*result = frame.rval;
|
||||||
|
|
||||||
if (hookData) {
|
if (hookData) {
|
||||||
@ -1774,7 +1774,7 @@ InternNonIntElementId(JSContext *cx, jsval idval, jsid *idp)
|
|||||||
#define MAX_INLINE_CALL_COUNT 1000
|
#define MAX_INLINE_CALL_COUNT 1000
|
||||||
|
|
||||||
JSBool
|
JSBool
|
||||||
js_Interpret(JSContext *cx, jsval *result)
|
js_Interpret(JSContext *cx, jsbytecode *pc, jsval *result)
|
||||||
{
|
{
|
||||||
JSRuntime *rt;
|
JSRuntime *rt;
|
||||||
JSStackFrame *fp;
|
JSStackFrame *fp;
|
||||||
@ -1788,7 +1788,7 @@ js_Interpret(JSContext *cx, jsval *result)
|
|||||||
jsint depth, len;
|
jsint depth, len;
|
||||||
jsval *sp, *newsp;
|
jsval *sp, *newsp;
|
||||||
void *mark;
|
void *mark;
|
||||||
jsbytecode *pc, *pc2, *endpc;
|
jsbytecode *endpc, *pc2;
|
||||||
JSOp op, op2;
|
JSOp op, op2;
|
||||||
const JSCodeSpec *cs;
|
const JSCodeSpec *cs;
|
||||||
JSAtom *atom;
|
JSAtom *atom;
|
||||||
@ -1876,11 +1876,6 @@ js_Interpret(JSContext *cx, jsval *result)
|
|||||||
|
|
||||||
LOAD_INTERRUPT_HANDLER(rt);
|
LOAD_INTERRUPT_HANDLER(rt);
|
||||||
|
|
||||||
pc = script->code;
|
|
||||||
endpc = pc + script->length;
|
|
||||||
depth = (jsint) script->depth;
|
|
||||||
len = -1;
|
|
||||||
|
|
||||||
/* Check for too much js_Interpret nesting, or too deep a C stack. */
|
/* Check for too much js_Interpret nesting, or too deep a C stack. */
|
||||||
if (++cx->interpLevel == MAX_INTERP_LEVEL ||
|
if (++cx->interpLevel == MAX_INTERP_LEVEL ||
|
||||||
!JS_CHECK_STACK_SIZE(cx, stackDummy)) {
|
!JS_CHECK_STACK_SIZE(cx, stackDummy)) {
|
||||||
@ -1892,6 +1887,7 @@ js_Interpret(JSContext *cx, jsval *result)
|
|||||||
/*
|
/*
|
||||||
* Allocate operand and pc stack slots for the script's worst-case depth.
|
* Allocate operand and pc stack slots for the script's worst-case depth.
|
||||||
*/
|
*/
|
||||||
|
depth = (jsint) script->depth;
|
||||||
newsp = js_AllocRawStack(cx, (uintN)(2 * depth), &mark);
|
newsp = js_AllocRawStack(cx, (uintN)(2 * depth), &mark);
|
||||||
if (!newsp) {
|
if (!newsp) {
|
||||||
ok = JS_FALSE;
|
ok = JS_FALSE;
|
||||||
@ -1901,6 +1897,7 @@ js_Interpret(JSContext *cx, jsval *result)
|
|||||||
fp->spbase = sp;
|
fp->spbase = sp;
|
||||||
SAVE_SP(fp);
|
SAVE_SP(fp);
|
||||||
|
|
||||||
|
endpc = script->code + script->length;
|
||||||
while (pc < endpc) {
|
while (pc < endpc) {
|
||||||
fp->pc = pc;
|
fp->pc = pc;
|
||||||
op = (JSOp) *pc;
|
op = (JSOp) *pc;
|
||||||
@ -5141,13 +5138,16 @@ js_Interpret(JSContext *cx, jsval *result)
|
|||||||
VALUE_TO_OBJECT(cx, lval, obj);
|
VALUE_TO_OBJECT(cx, lval, obj);
|
||||||
len = GET_JUMP_OFFSET(pc);
|
len = GET_JUMP_OFFSET(pc);
|
||||||
SAVE_SP(fp);
|
SAVE_SP(fp);
|
||||||
ok = js_FilterXMLList(cx, obj, pc + cs->length, len - cs->length,
|
ok = js_FilterXMLList(cx, obj, pc + cs->length, &rval);
|
||||||
&rval);
|
|
||||||
if (!ok)
|
if (!ok)
|
||||||
goto out;
|
goto out;
|
||||||
STORE_OPND(-1, rval);
|
STORE_OPND(-1, rval);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case JSOP_ENDFILTER:
|
||||||
|
*result = POP_OPND();
|
||||||
|
goto out;
|
||||||
|
|
||||||
case JSOP_TOXML:
|
case JSOP_TOXML:
|
||||||
rval = FETCH_OPND(-1);
|
rval = FETCH_OPND(-1);
|
||||||
SAVE_SP(fp);
|
SAVE_SP(fp);
|
||||||
|
@ -297,7 +297,7 @@ js_CheckRedeclaration(JSContext *cx, JSObject *obj, jsid id, uintN attrs,
|
|||||||
JSObject **objp, JSProperty **propp);
|
JSObject **objp, JSProperty **propp);
|
||||||
|
|
||||||
extern JSBool
|
extern JSBool
|
||||||
js_Interpret(JSContext *cx, jsval *result);
|
js_Interpret(JSContext *cx, jsbytecode *pc, jsval *result);
|
||||||
|
|
||||||
JS_END_EXTERN_C
|
JS_END_EXTERN_C
|
||||||
|
|
||||||
|
@ -2433,14 +2433,20 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
|||||||
case JSOP_XMLNAME:
|
case JSOP_XMLNAME:
|
||||||
case JSOP_XMLTAGEXPR:
|
case JSOP_XMLTAGEXPR:
|
||||||
case JSOP_XMLELTEXPR:
|
case JSOP_XMLELTEXPR:
|
||||||
case JSOP_FILTER:
|
|
||||||
case JSOP_TOXML:
|
case JSOP_TOXML:
|
||||||
case JSOP_TOXMLLIST:
|
case JSOP_TOXMLLIST:
|
||||||
case JSOP_FOREACH:
|
case JSOP_FOREACH:
|
||||||
|
case JSOP_FILTER:
|
||||||
/* Conversion and prefix ops do nothing in the decompiler. */
|
/* Conversion and prefix ops do nothing in the decompiler. */
|
||||||
todo = -2;
|
todo = -2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case JSOP_ENDFILTER:
|
||||||
|
rval = POP_STR();
|
||||||
|
lval = POP_STR();
|
||||||
|
todo = Sprint(&ss->sprinter, "%s.(%s)", lval, rval);
|
||||||
|
break;
|
||||||
|
|
||||||
case JSOP_DESCENDANTS:
|
case JSOP_DESCENDANTS:
|
||||||
rval = POP_STR();
|
rval = POP_STR();
|
||||||
lval = POP_STR();
|
lval = POP_STR();
|
||||||
|
@ -358,15 +358,16 @@ OPDEF(JSOP_SETXMLNAME, 171,"setxmlname", NULL, 1, 3, 1, 1, JOF_BYTE|J
|
|||||||
OPDEF(JSOP_XMLNAME, 172,"xmlname", NULL, 1, 1, 1, 12, JOF_BYTE|JOF_XMLNAME)
|
OPDEF(JSOP_XMLNAME, 172,"xmlname", NULL, 1, 1, 1, 12, JOF_BYTE|JOF_XMLNAME)
|
||||||
OPDEF(JSOP_DESCENDANTS, 173,"descendants",NULL, 1, 2, 1, 11, JOF_BYTE)
|
OPDEF(JSOP_DESCENDANTS, 173,"descendants",NULL, 1, 2, 1, 11, JOF_BYTE)
|
||||||
OPDEF(JSOP_FILTER, 174,"filter", NULL, 3, 1, 1, 11, JOF_JUMP)
|
OPDEF(JSOP_FILTER, 174,"filter", NULL, 3, 1, 1, 11, JOF_JUMP)
|
||||||
OPDEF(JSOP_TOXML, 175,"toxml", NULL, 1, 1, 1, 12, JOF_BYTE)
|
OPDEF(JSOP_ENDFILTER, 175,"endfilter", NULL, 1, 1, 0, 0, JOF_BYTE)
|
||||||
OPDEF(JSOP_TOXMLLIST, 176,"toxmllist", NULL, 1, 1, 1, 12, JOF_BYTE)
|
OPDEF(JSOP_TOXML, 176,"toxml", NULL, 1, 1, 1, 12, JOF_BYTE)
|
||||||
OPDEF(JSOP_XMLTAGEXPR, 177,"xmltagexpr", NULL, 1, 1, 1, 12, JOF_BYTE)
|
OPDEF(JSOP_TOXMLLIST, 177,"toxmllist", NULL, 1, 1, 1, 12, JOF_BYTE)
|
||||||
OPDEF(JSOP_XMLELTEXPR, 178,"xmleltexpr", NULL, 1, 1, 1, 12, JOF_BYTE)
|
OPDEF(JSOP_XMLTAGEXPR, 178,"xmltagexpr", NULL, 1, 1, 1, 12, JOF_BYTE)
|
||||||
OPDEF(JSOP_XMLOBJECT, 179,"xmlobject", NULL, 3, 0, 1, 12, JOF_CONST)
|
OPDEF(JSOP_XMLELTEXPR, 179,"xmleltexpr", NULL, 1, 1, 1, 12, JOF_BYTE)
|
||||||
OPDEF(JSOP_XMLCDATA, 180,"xmlcdata", NULL, 3, 0, 1, 12, JOF_CONST)
|
OPDEF(JSOP_XMLOBJECT, 180,"xmlobject", NULL, 3, 0, 1, 12, JOF_CONST)
|
||||||
OPDEF(JSOP_XMLCOMMENT, 181,"xmlcomment", NULL, 3, 0, 1, 12, JOF_CONST)
|
OPDEF(JSOP_XMLCDATA, 181,"xmlcdata", NULL, 3, 0, 1, 12, JOF_CONST)
|
||||||
OPDEF(JSOP_XMLPI, 182,"xmlpi", NULL, 5, 0, 1, 12, JOF_CONST2)
|
OPDEF(JSOP_XMLCOMMENT, 182,"xmlcomment", NULL, 3, 0, 1, 12, JOF_CONST)
|
||||||
OPDEF(JSOP_GETMETHOD, 183,"getmethod", NULL, 3, 1, 1, 11, JOF_CONST|JOF_PROP)
|
OPDEF(JSOP_XMLPI, 183,"xmlpi", NULL, 5, 0, 1, 12, JOF_CONST2)
|
||||||
OPDEF(JSOP_GETFUNNS, 184,"getfunns", NULL, 1, 0, 1, 12, JOF_BYTE)
|
OPDEF(JSOP_GETMETHOD, 184,"getmethod", NULL, 3, 1, 1, 11, JOF_CONST|JOF_PROP)
|
||||||
OPDEF(JSOP_FOREACH, 185,"foreach", NULL, 1, 0, 0, 0, JOF_BYTE)
|
OPDEF(JSOP_GETFUNNS, 185,"getfunns", NULL, 1, 0, 1, 12, JOF_BYTE)
|
||||||
OPDEF(JSOP_DELDESC, 186,"deldesc", NULL, 1, 2, 1, 10, JOF_BYTE |JOF_ELEM|JOF_DEL)
|
OPDEF(JSOP_FOREACH, 186,"foreach", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||||
|
OPDEF(JSOP_DELDESC, 187,"deldesc", NULL, 1, 2, 1, 10, JOF_BYTE |JOF_ELEM|JOF_DEL)
|
||||||
|
@ -2871,6 +2871,12 @@ MemberExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
|
|||||||
pn2->pn_type = TOK_LB;
|
pn2->pn_type = TOK_LB;
|
||||||
pn2->pn_op = JSOP_GETELEM;
|
pn2->pn_op = JSOP_GETELEM;
|
||||||
} else if (tt == TOK_RP) {
|
} else if (tt == TOK_RP) {
|
||||||
|
JSParseNode *group = pn3;
|
||||||
|
|
||||||
|
/* Recycle the useless TOK_RP/JSOP_GROUP node. */
|
||||||
|
pn3 = group->pn_kid;
|
||||||
|
group->pn_kid = NULL;
|
||||||
|
RecycleTree(group, tc);
|
||||||
pn2->pn_type = TOK_FILTER;
|
pn2->pn_type = TOK_FILTER;
|
||||||
pn2->pn_op = JSOP_FILTER;
|
pn2->pn_op = JSOP_FILTER;
|
||||||
} else {
|
} else {
|
||||||
|
179
js/src/jsxml.c
179
js/src/jsxml.c
@ -112,20 +112,22 @@ static struct {
|
|||||||
/*
|
/*
|
||||||
* Random utilities and global functions.
|
* Random utilities and global functions.
|
||||||
*/
|
*/
|
||||||
const char js_isXMLName_str[] = "isXMLName";
|
const char js_AnyName_str[] = "AnyName";
|
||||||
const char js_Namespace_str[] = "Namespace";
|
const char js_AttributeName_str[] = "AttributeName";
|
||||||
const char js_QName_str[] = "QName";
|
const char js_isXMLName_str[] = "isXMLName";
|
||||||
const char js_XML_str[] = "XML";
|
const char js_Namespace_str[] = "Namespace";
|
||||||
const char js_XMLList_str[] = "XMLList";
|
const char js_QName_str[] = "QName";
|
||||||
const char js_localName_str[] = "localName";
|
const char js_XML_str[] = "XML";
|
||||||
const char js_prefix_str[] = "prefix";
|
const char js_XMLList_str[] = "XMLList";
|
||||||
const char js_toXMLString_str[] = "toXMLString";
|
const char js_localName_str[] = "localName";
|
||||||
const char js_uri_str[] = "uri";
|
const char js_prefix_str[] = "prefix";
|
||||||
|
const char js_toXMLString_str[] = "toXMLString";
|
||||||
|
const char js_uri_str[] = "uri";
|
||||||
|
|
||||||
const char js_amp_entity_str[] = "&";
|
const char js_amp_entity_str[] = "&";
|
||||||
const char js_gt_entity_str[] = ">";
|
const char js_gt_entity_str[] = ">";
|
||||||
const char js_lt_entity_str[] = "<";
|
const char js_lt_entity_str[] = "<";
|
||||||
const char js_quot_entity_str[] = """;
|
const char js_quot_entity_str[] = """;
|
||||||
|
|
||||||
#define IS_EMPTY(str) (JSSTRING_LENGTH(str) == 0)
|
#define IS_EMPTY(str) (JSSTRING_LENGTH(str) == 0)
|
||||||
#define IS_STAR(str) (JSSTRING_LENGTH(str) == 1 && *JSSTRING_CHARS(str) == '*')
|
#define IS_STAR(str) (JSSTRING_LENGTH(str) == 1 && *JSSTRING_CHARS(str) == '*')
|
||||||
@ -480,7 +482,7 @@ JSExtendedClass js_QNameClass = {
|
|||||||
* except that they're never constructed and they have no getters.
|
* except that they're never constructed and they have no getters.
|
||||||
*/
|
*/
|
||||||
JSClass js_AttributeNameClass = {
|
JSClass js_AttributeNameClass = {
|
||||||
"AttributeName", JSCLASS_HAS_PRIVATE | JSCLASS_CONSTRUCT_PROTOTYPE,
|
js_AttributeName_str, JSCLASS_HAS_PRIVATE | JSCLASS_CONSTRUCT_PROTOTYPE,
|
||||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, qname_finalize,
|
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, qname_finalize,
|
||||||
NULL, NULL, NULL, NULL,
|
NULL, NULL, NULL, NULL,
|
||||||
@ -488,7 +490,7 @@ JSClass js_AttributeNameClass = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
JSClass js_AnyNameClass = {
|
JSClass js_AnyNameClass = {
|
||||||
"AnyName", JSCLASS_HAS_PRIVATE,
|
js_AnyName_str, JSCLASS_HAS_PRIVATE | JSCLASS_CONSTRUCT_PROTOTYPE,
|
||||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, qname_finalize,
|
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, qname_finalize,
|
||||||
NULL, NULL, NULL, NULL,
|
NULL, NULL, NULL, NULL,
|
||||||
@ -508,13 +510,21 @@ static JSBool
|
|||||||
qname_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
qname_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||||
jsval *rval)
|
jsval *rval)
|
||||||
{
|
{
|
||||||
|
JSClass *clasp;
|
||||||
JSXMLQName *qn;
|
JSXMLQName *qn;
|
||||||
JSString *str, *qualstr;
|
JSString *str, *qualstr;
|
||||||
|
size_t length;
|
||||||
|
jschar *chars;
|
||||||
|
|
||||||
qn = (JSXMLQName *)
|
clasp = OBJ_GET_CLASS(cx, obj);
|
||||||
JS_GetInstancePrivate(cx, obj, &js_QNameClass.base, argv);
|
if (clasp == &js_AttributeNameClass || clasp == &js_AnyNameClass) {
|
||||||
if (!qn)
|
qn = (JSXMLQName *) JS_GetPrivate(cx, obj);
|
||||||
return JS_FALSE;
|
} else {
|
||||||
|
qn = (JSXMLQName *)
|
||||||
|
JS_GetInstancePrivate(cx, obj, &js_QNameClass.base, argv);
|
||||||
|
if (!qn)
|
||||||
|
return JS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (!qn->uri) {
|
if (!qn->uri) {
|
||||||
/* No uri means wildcard qualifier. */
|
/* No uri means wildcard qualifier. */
|
||||||
@ -531,6 +541,22 @@ qname_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||||||
str = js_ConcatStrings(cx, str, qn->localName);
|
str = js_ConcatStrings(cx, str, qn->localName);
|
||||||
if (!str)
|
if (!str)
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
|
|
||||||
|
if (str && clasp == &js_AttributeNameClass) {
|
||||||
|
length = JSSTRING_LENGTH(str);
|
||||||
|
chars = (jschar *) JS_malloc(cx, (length + 2) * sizeof(jschar));
|
||||||
|
if (!chars)
|
||||||
|
return JS_FALSE;
|
||||||
|
*chars = '@';
|
||||||
|
js_strncpy(chars + 1, JSSTRING_CHARS(str), length);
|
||||||
|
chars[++length] = 0;
|
||||||
|
str = js_NewString(cx, chars, length, 0);
|
||||||
|
if (!str) {
|
||||||
|
JS_free(cx, chars);
|
||||||
|
return JS_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
*rval = STRING_TO_JSVAL(str);
|
*rval = STRING_TO_JSVAL(str);
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
@ -610,13 +636,27 @@ js_GetXMLQNameObject(JSContext *cx, JSXMLQName *qn)
|
|||||||
JSObject *
|
JSObject *
|
||||||
js_GetAttributeNameObject(JSContext *cx, JSXMLQName *qn)
|
js_GetAttributeNameObject(JSContext *cx, JSXMLQName *qn)
|
||||||
{
|
{
|
||||||
|
JSXMLQName *origqn;
|
||||||
JSObject *obj;
|
JSObject *obj;
|
||||||
|
|
||||||
|
origqn = qn;
|
||||||
|
obj = qn->object;
|
||||||
|
if (obj) {
|
||||||
|
if (OBJ_GET_CLASS(cx, obj) == &js_AttributeNameClass)
|
||||||
|
return obj;
|
||||||
|
qn = js_NewXMLQName(cx, qn->uri, qn->prefix, qn->localName);
|
||||||
|
if (!qn)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
obj = js_NewObject(cx, &js_AttributeNameClass, NULL, NULL);
|
obj = js_NewObject(cx, &js_AttributeNameClass, NULL, NULL);
|
||||||
if (!obj || !JS_SetPrivate(cx, obj, qn)) {
|
if (!obj || !JS_SetPrivate(cx, obj, qn)) {
|
||||||
cx->newborn[GCX_OBJECT] = NULL;
|
cx->newborn[GCX_OBJECT] = NULL;
|
||||||
|
if (qn != origqn)
|
||||||
|
js_DestroyXMLQName(cx, qn);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
qn->object = obj;
|
qn->object = obj;
|
||||||
qn->markflag = JSXML_MARK_CLEAR;
|
qn->markflag = JSXML_MARK_CLEAR;
|
||||||
METER(xml_stats.qnameobj);
|
METER(xml_stats.qnameobj);
|
||||||
@ -836,8 +876,16 @@ QName(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create and return a new QName object exactly as if constructed. */
|
/*
|
||||||
obj = js_NewObject(cx, &js_QNameClass.base, NULL, NULL);
|
* Create and return a new QName object exactly as if constructed.
|
||||||
|
* Use the constructor's clasp so we can be shared by AttributeName
|
||||||
|
* (see below after this function).
|
||||||
|
*/
|
||||||
|
obj = js_NewObject(cx,
|
||||||
|
argv
|
||||||
|
? JS_ValueToFunction(cx, argv[-2])->clasp
|
||||||
|
: &js_QNameClass.base,
|
||||||
|
NULL, NULL);
|
||||||
if (!obj)
|
if (!obj)
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
*rval = OBJECT_TO_JSVAL(obj);
|
*rval = OBJECT_TO_JSVAL(obj);
|
||||||
@ -933,6 +981,24 @@ out:
|
|||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static JSBool
|
||||||
|
AnyName(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||||
|
{
|
||||||
|
/* Return the one true AnyName instance. */
|
||||||
|
return js_GetAnyName(cx, rval);
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSBool
|
||||||
|
AttributeName(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||||
|
jsval *rval)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Since js_AttributeNameClass was initialized, obj will have that as its
|
||||||
|
* class, not js_QNameClass.
|
||||||
|
*/
|
||||||
|
return QName(cx, obj, argc, argv, rval);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XMLArray library functions.
|
* XMLArray library functions.
|
||||||
*/
|
*/
|
||||||
@ -5937,9 +6003,7 @@ xml_name(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||||||
if (!xml->name) {
|
if (!xml->name) {
|
||||||
*rval = JSVAL_NULL;
|
*rval = JSVAL_NULL;
|
||||||
} else {
|
} else {
|
||||||
nameobj = ((xml->xml_class == JSXML_CLASS_ATTRIBUTE)
|
nameobj = js_GetXMLQNameObject(cx, xml->name);
|
||||||
? js_GetAttributeNameObject
|
|
||||||
: js_GetXMLQNameObject)(cx, xml->name);
|
|
||||||
if (!nameobj)
|
if (!nameobj)
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
*rval = OBJECT_TO_JSVAL(nameobj);
|
*rval = OBJECT_TO_JSVAL(nameobj);
|
||||||
@ -7144,7 +7208,12 @@ js_InitNamespaceClass(JSContext *cx, JSObject *obj)
|
|||||||
JSObject *
|
JSObject *
|
||||||
js_InitQNameClass(JSContext *cx, JSObject *obj)
|
js_InitQNameClass(JSContext *cx, JSObject *obj)
|
||||||
{
|
{
|
||||||
if (!JS_InitClass(cx, obj, NULL, &js_AttributeNameClass, QName, 2,
|
if (!JS_InitClass(cx, obj, NULL, &js_AttributeNameClass, AttributeName, 2,
|
||||||
|
qname_props, qname_methods, NULL, NULL)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!JS_InitClass(cx, obj, NULL, &js_AnyNameClass, AnyName, 0,
|
||||||
qname_props, qname_methods, NULL, NULL)) {
|
qname_props, qname_methods, NULL, NULL)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -7498,6 +7567,18 @@ js_FindXMLProperty(JSContext *cx, jsval name, JSObject **objp, jsval *namep)
|
|||||||
lastobj = obj;
|
lastobj = obj;
|
||||||
} while ((obj = OBJ_GET_PARENT(cx, obj)) != NULL);
|
} while ((obj = OBJ_GET_PARENT(cx, obj)) != NULL);
|
||||||
|
|
||||||
|
if (JS_HAS_STRICT_OPTION(cx)) {
|
||||||
|
JSString *str = js_ValueToString(cx, name);
|
||||||
|
if (!str ||
|
||||||
|
!JS_ReportErrorFlagsAndNumber(cx,
|
||||||
|
JSREPORT_WARNING|JSREPORT_STRICT,
|
||||||
|
js_GetErrorMessage, NULL,
|
||||||
|
JSMSG_UNDEFINED_XML_NAME,
|
||||||
|
JS_GetStringBytes(str))) {
|
||||||
|
return JS_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
*objp = lastobj;
|
*objp = lastobj;
|
||||||
*namep = JSVAL_VOID;
|
*namep = JSVAL_VOID;
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
@ -7561,24 +7642,21 @@ js_DeleteXMLListElements(JSContext *cx, JSObject *listobj)
|
|||||||
}
|
}
|
||||||
|
|
||||||
JSBool
|
JSBool
|
||||||
js_FilterXMLList(JSContext *cx, JSObject *obj, jsbytecode *pc, uint32 len,
|
js_FilterXMLList(JSContext *cx, JSObject *obj, jsbytecode *pc, jsval *vp)
|
||||||
jsval *vp)
|
|
||||||
{
|
{
|
||||||
JSBool ok, inLRS, match;
|
JSBool ok, match;
|
||||||
JSStackFrame *fp, frame;
|
JSStackFrame *fp;
|
||||||
JSObject *listobj, *resobj, *withobj, *kidobj;
|
JSObject *scobj, *listobj, *resobj, *withobj, *kidobj;
|
||||||
JSXML *xml, *list, *result, *kid;
|
JSXML *xml, *list, *result, *kid;
|
||||||
JSScript script;
|
|
||||||
uint32 i, n;
|
uint32 i, n;
|
||||||
|
|
||||||
ok = JS_TRUE;
|
ok = JS_EnterLocalRootScope(cx);
|
||||||
inLRS = JS_FALSE;
|
if (!ok)
|
||||||
fp = cx->fp;
|
return JS_FALSE;
|
||||||
frame = *fp;
|
|
||||||
frame.down = fp;
|
|
||||||
frame.flags |= JSFRAME_EVAL;
|
|
||||||
cx->fp = &frame;
|
|
||||||
|
|
||||||
|
/* All control flow after this point must exit via label out or bad. */
|
||||||
|
fp = cx->fp;
|
||||||
|
scobj = fp->scopeChain;
|
||||||
xml = GetPrivate(cx, obj, "filtering predicate operator");
|
xml = GetPrivate(cx, obj, "filtering predicate operator");
|
||||||
if (!xml)
|
if (!xml)
|
||||||
goto bad;
|
goto bad;
|
||||||
@ -7586,10 +7664,6 @@ js_FilterXMLList(JSContext *cx, JSObject *obj, jsbytecode *pc, uint32 len,
|
|||||||
if (xml->xml_class == JSXML_CLASS_LIST) {
|
if (xml->xml_class == JSXML_CLASS_LIST) {
|
||||||
list = xml;
|
list = xml;
|
||||||
} else {
|
} else {
|
||||||
ok = JS_EnterLocalRootScope(cx);
|
|
||||||
if (!ok)
|
|
||||||
goto out;
|
|
||||||
inLRS = JS_TRUE;
|
|
||||||
listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST);
|
listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST);
|
||||||
if (!listobj)
|
if (!listobj)
|
||||||
goto bad;
|
goto bad;
|
||||||
@ -7599,24 +7673,16 @@ js_FilterXMLList(JSContext *cx, JSObject *obj, jsbytecode *pc, uint32 len,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Root resobj via frame.rval, whether or not we are inLRS. */
|
|
||||||
resobj = js_NewXMLObject(cx, JSXML_CLASS_LIST);
|
resobj = js_NewXMLObject(cx, JSXML_CLASS_LIST);
|
||||||
if (!resobj)
|
if (!resobj)
|
||||||
goto bad;
|
goto bad;
|
||||||
result = (JSXML *) JS_GetPrivate(cx, resobj);
|
result = (JSXML *) JS_GetPrivate(cx, resobj);
|
||||||
frame.rval = OBJECT_TO_JSVAL(resobj);
|
|
||||||
|
|
||||||
/* Hoist the scope chain update out of the loop over kids. */
|
/* Hoist the scope chain update out of the loop over kids. */
|
||||||
withobj = js_NewObject(cx, &js_WithClass, NULL, fp->scopeChain);
|
withobj = js_NewObject(cx, &js_WithClass, NULL, scobj);
|
||||||
if (!withobj)
|
if (!withobj)
|
||||||
goto bad;
|
goto bad;
|
||||||
frame.scopeChain = withobj;
|
fp->scopeChain = withobj;
|
||||||
|
|
||||||
script = *fp->script;
|
|
||||||
script.code = script.main = pc;
|
|
||||||
script.length = len;
|
|
||||||
frame.script = &script;
|
|
||||||
js_CallNewScriptHook(cx, &script, fp->fun);
|
|
||||||
|
|
||||||
for (i = 0, n = list->xml_kids.length; i < n; i++) {
|
for (i = 0, n = list->xml_kids.length; i < n; i++) {
|
||||||
kid = XMLARRAY_MEMBER(&list->xml_kids, i, JSXML);
|
kid = XMLARRAY_MEMBER(&list->xml_kids, i, JSXML);
|
||||||
@ -7624,7 +7690,7 @@ js_FilterXMLList(JSContext *cx, JSObject *obj, jsbytecode *pc, uint32 len,
|
|||||||
if (!kidobj)
|
if (!kidobj)
|
||||||
goto bad;
|
goto bad;
|
||||||
OBJ_SET_PROTO(cx, withobj, kidobj);
|
OBJ_SET_PROTO(cx, withobj, kidobj);
|
||||||
ok = js_Interpret(cx, vp);
|
ok = js_Interpret(cx, pc, vp);
|
||||||
if (!ok)
|
if (!ok)
|
||||||
goto out;
|
goto out;
|
||||||
ok = js_ValueToBoolean(cx, *vp, &match);
|
ok = js_ValueToBoolean(cx, *vp, &match);
|
||||||
@ -7640,11 +7706,8 @@ js_FilterXMLList(JSContext *cx, JSObject *obj, jsbytecode *pc, uint32 len,
|
|||||||
*vp = OBJECT_TO_JSVAL(resobj);
|
*vp = OBJECT_TO_JSVAL(resobj);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (frame.script == &script)
|
fp->scopeChain = scobj;
|
||||||
js_CallDestroyScriptHook(cx, &script);
|
JS_LeaveLocalRootScope(cx);
|
||||||
if (inLRS)
|
|
||||||
JS_LeaveLocalRootScope(cx);
|
|
||||||
cx->fp = fp;
|
|
||||||
return ok;
|
return ok;
|
||||||
bad:
|
bad:
|
||||||
ok = JS_FALSE;
|
ok = JS_FALSE;
|
||||||
|
@ -42,6 +42,8 @@
|
|||||||
#include "jsstddef.h"
|
#include "jsstddef.h"
|
||||||
#include "jspubtd.h"
|
#include "jspubtd.h"
|
||||||
|
|
||||||
|
extern const char js_AnyName_str[];
|
||||||
|
extern const char js_AttributeName_str[];
|
||||||
extern const char js_isXMLName_str[];
|
extern const char js_isXMLName_str[];
|
||||||
extern const char js_Namespace_str[];
|
extern const char js_Namespace_str[];
|
||||||
extern const char js_QName_str[];
|
extern const char js_QName_str[];
|
||||||
@ -178,7 +180,6 @@ struct JSXML {
|
|||||||
JSXMLArray attrs;
|
JSXMLArray attrs;
|
||||||
} elem;
|
} elem;
|
||||||
JSString *value;
|
JSString *value;
|
||||||
jsdouble align;
|
|
||||||
} u;
|
} u;
|
||||||
|
|
||||||
/* Don't add anything after u -- see js_NewXML for why. */
|
/* Don't add anything after u -- see js_NewXML for why. */
|
||||||
@ -300,8 +301,7 @@ extern JSBool
|
|||||||
js_DeleteXMLListElements(JSContext *cx, JSObject *listobj);
|
js_DeleteXMLListElements(JSContext *cx, JSObject *listobj);
|
||||||
|
|
||||||
extern JSBool
|
extern JSBool
|
||||||
js_FilterXMLList(JSContext *cx, JSObject *obj, jsbytecode *pc, uint32 len,
|
js_FilterXMLList(JSContext *cx, JSObject *obj, jsbytecode *pc, jsval *vp);
|
||||||
jsval *vp);
|
|
||||||
|
|
||||||
extern JSObject *
|
extern JSObject *
|
||||||
js_ValueToXMLObject(JSContext *cx, jsval v);
|
js_ValueToXMLObject(JSContext *cx, jsval v);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user