mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-13 11:38:16 +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_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_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_InitNamespaceClass, LAZILY_PINNED_ATOM(Namespace)},
|
||||
{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(XMLList)},
|
||||
#endif
|
||||
|
@ -210,6 +210,8 @@ struct JSAtomState {
|
||||
|
||||
/* Less frequently used atoms, pinned lazily by JS_ResolveStandardClass. */
|
||||
struct {
|
||||
JSAtom *AnyNameAtom;
|
||||
JSAtom *AttributeNameAtom;
|
||||
JSAtom *EvalErrorAtom;
|
||||
JSAtom *InfinityAtom;
|
||||
JSAtom *InternalErrorAtom;
|
||||
|
@ -4240,12 +4240,12 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
||||
case TOK_FILTER:
|
||||
if (!js_EmitTree(cx, cg, pn->pn_left))
|
||||
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)
|
||||
return JS_FALSE;
|
||||
if (!js_EmitTree(cx, cg, pn->pn_right))
|
||||
return JS_FALSE;
|
||||
if (js_Emit1(cx, cg, JSOP_POPV) < 0)
|
||||
if (js_Emit1(cx, cg, JSOP_ENDFILTER) < 0)
|
||||
return JS_FALSE;
|
||||
CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, jmp);
|
||||
break;
|
||||
|
@ -1303,7 +1303,7 @@ have_fun:
|
||||
frame.scopeChain = funobj;
|
||||
#endif
|
||||
}
|
||||
ok = js_Interpret(cx, &v);
|
||||
ok = js_Interpret(cx, script->code, &v);
|
||||
} else {
|
||||
/* fun might be onerror trying to report a syntax error in itself. */
|
||||
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
|
||||
* GC activations nested within this js_Interpret.
|
||||
*/
|
||||
ok = js_Interpret(cx, &frame.rval);
|
||||
ok = js_Interpret(cx, script->code, &frame.rval);
|
||||
*result = frame.rval;
|
||||
|
||||
if (hookData) {
|
||||
@ -1774,7 +1774,7 @@ InternNonIntElementId(JSContext *cx, jsval idval, jsid *idp)
|
||||
#define MAX_INLINE_CALL_COUNT 1000
|
||||
|
||||
JSBool
|
||||
js_Interpret(JSContext *cx, jsval *result)
|
||||
js_Interpret(JSContext *cx, jsbytecode *pc, jsval *result)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
JSStackFrame *fp;
|
||||
@ -1788,7 +1788,7 @@ js_Interpret(JSContext *cx, jsval *result)
|
||||
jsint depth, len;
|
||||
jsval *sp, *newsp;
|
||||
void *mark;
|
||||
jsbytecode *pc, *pc2, *endpc;
|
||||
jsbytecode *endpc, *pc2;
|
||||
JSOp op, op2;
|
||||
const JSCodeSpec *cs;
|
||||
JSAtom *atom;
|
||||
@ -1876,11 +1876,6 @@ js_Interpret(JSContext *cx, jsval *result)
|
||||
|
||||
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. */
|
||||
if (++cx->interpLevel == MAX_INTERP_LEVEL ||
|
||||
!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.
|
||||
*/
|
||||
depth = (jsint) script->depth;
|
||||
newsp = js_AllocRawStack(cx, (uintN)(2 * depth), &mark);
|
||||
if (!newsp) {
|
||||
ok = JS_FALSE;
|
||||
@ -1901,6 +1897,7 @@ js_Interpret(JSContext *cx, jsval *result)
|
||||
fp->spbase = sp;
|
||||
SAVE_SP(fp);
|
||||
|
||||
endpc = script->code + script->length;
|
||||
while (pc < endpc) {
|
||||
fp->pc = pc;
|
||||
op = (JSOp) *pc;
|
||||
@ -5141,13 +5138,16 @@ js_Interpret(JSContext *cx, jsval *result)
|
||||
VALUE_TO_OBJECT(cx, lval, obj);
|
||||
len = GET_JUMP_OFFSET(pc);
|
||||
SAVE_SP(fp);
|
||||
ok = js_FilterXMLList(cx, obj, pc + cs->length, len - cs->length,
|
||||
&rval);
|
||||
ok = js_FilterXMLList(cx, obj, pc + cs->length, &rval);
|
||||
if (!ok)
|
||||
goto out;
|
||||
STORE_OPND(-1, rval);
|
||||
break;
|
||||
|
||||
case JSOP_ENDFILTER:
|
||||
*result = POP_OPND();
|
||||
goto out;
|
||||
|
||||
case JSOP_TOXML:
|
||||
rval = FETCH_OPND(-1);
|
||||
SAVE_SP(fp);
|
||||
|
@ -297,7 +297,7 @@ js_CheckRedeclaration(JSContext *cx, JSObject *obj, jsid id, uintN attrs,
|
||||
JSObject **objp, JSProperty **propp);
|
||||
|
||||
extern JSBool
|
||||
js_Interpret(JSContext *cx, jsval *result);
|
||||
js_Interpret(JSContext *cx, jsbytecode *pc, jsval *result);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
|
@ -2433,14 +2433,20 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
||||
case JSOP_XMLNAME:
|
||||
case JSOP_XMLTAGEXPR:
|
||||
case JSOP_XMLELTEXPR:
|
||||
case JSOP_FILTER:
|
||||
case JSOP_TOXML:
|
||||
case JSOP_TOXMLLIST:
|
||||
case JSOP_FOREACH:
|
||||
case JSOP_FILTER:
|
||||
/* Conversion and prefix ops do nothing in the decompiler. */
|
||||
todo = -2;
|
||||
break;
|
||||
|
||||
case JSOP_ENDFILTER:
|
||||
rval = POP_STR();
|
||||
lval = POP_STR();
|
||||
todo = Sprint(&ss->sprinter, "%s.(%s)", lval, rval);
|
||||
break;
|
||||
|
||||
case JSOP_DESCENDANTS:
|
||||
rval = 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_DESCENDANTS, 173,"descendants",NULL, 1, 2, 1, 11, JOF_BYTE)
|
||||
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_TOXMLLIST, 176,"toxmllist", NULL, 1, 1, 1, 12, JOF_BYTE)
|
||||
OPDEF(JSOP_XMLTAGEXPR, 177,"xmltagexpr", NULL, 1, 1, 1, 12, JOF_BYTE)
|
||||
OPDEF(JSOP_XMLELTEXPR, 178,"xmleltexpr", NULL, 1, 1, 1, 12, JOF_BYTE)
|
||||
OPDEF(JSOP_XMLOBJECT, 179,"xmlobject", NULL, 3, 0, 1, 12, JOF_CONST)
|
||||
OPDEF(JSOP_XMLCDATA, 180,"xmlcdata", NULL, 3, 0, 1, 12, JOF_CONST)
|
||||
OPDEF(JSOP_XMLCOMMENT, 181,"xmlcomment", NULL, 3, 0, 1, 12, JOF_CONST)
|
||||
OPDEF(JSOP_XMLPI, 182,"xmlpi", NULL, 5, 0, 1, 12, JOF_CONST2)
|
||||
OPDEF(JSOP_GETMETHOD, 183,"getmethod", NULL, 3, 1, 1, 11, JOF_CONST|JOF_PROP)
|
||||
OPDEF(JSOP_GETFUNNS, 184,"getfunns", NULL, 1, 0, 1, 12, JOF_BYTE)
|
||||
OPDEF(JSOP_FOREACH, 185,"foreach", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_DELDESC, 186,"deldesc", NULL, 1, 2, 1, 10, JOF_BYTE |JOF_ELEM|JOF_DEL)
|
||||
OPDEF(JSOP_ENDFILTER, 175,"endfilter", NULL, 1, 1, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_TOXML, 176,"toxml", NULL, 1, 1, 1, 12, JOF_BYTE)
|
||||
OPDEF(JSOP_TOXMLLIST, 177,"toxmllist", NULL, 1, 1, 1, 12, JOF_BYTE)
|
||||
OPDEF(JSOP_XMLTAGEXPR, 178,"xmltagexpr", NULL, 1, 1, 1, 12, JOF_BYTE)
|
||||
OPDEF(JSOP_XMLELTEXPR, 179,"xmleltexpr", NULL, 1, 1, 1, 12, JOF_BYTE)
|
||||
OPDEF(JSOP_XMLOBJECT, 180,"xmlobject", NULL, 3, 0, 1, 12, JOF_CONST)
|
||||
OPDEF(JSOP_XMLCDATA, 181,"xmlcdata", NULL, 3, 0, 1, 12, JOF_CONST)
|
||||
OPDEF(JSOP_XMLCOMMENT, 182,"xmlcomment", NULL, 3, 0, 1, 12, JOF_CONST)
|
||||
OPDEF(JSOP_XMLPI, 183,"xmlpi", NULL, 5, 0, 1, 12, JOF_CONST2)
|
||||
OPDEF(JSOP_GETMETHOD, 184,"getmethod", NULL, 3, 1, 1, 11, JOF_CONST|JOF_PROP)
|
||||
OPDEF(JSOP_GETFUNNS, 185,"getfunns", NULL, 1, 0, 1, 12, JOF_BYTE)
|
||||
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_op = JSOP_GETELEM;
|
||||
} 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_op = JSOP_FILTER;
|
||||
} else {
|
||||
|
179
js/src/jsxml.c
179
js/src/jsxml.c
@ -112,20 +112,22 @@ static struct {
|
||||
/*
|
||||
* Random utilities and global functions.
|
||||
*/
|
||||
const char js_isXMLName_str[] = "isXMLName";
|
||||
const char js_Namespace_str[] = "Namespace";
|
||||
const char js_QName_str[] = "QName";
|
||||
const char js_XML_str[] = "XML";
|
||||
const char js_XMLList_str[] = "XMLList";
|
||||
const char js_localName_str[] = "localName";
|
||||
const char js_prefix_str[] = "prefix";
|
||||
const char js_toXMLString_str[] = "toXMLString";
|
||||
const char js_uri_str[] = "uri";
|
||||
const char js_AnyName_str[] = "AnyName";
|
||||
const char js_AttributeName_str[] = "AttributeName";
|
||||
const char js_isXMLName_str[] = "isXMLName";
|
||||
const char js_Namespace_str[] = "Namespace";
|
||||
const char js_QName_str[] = "QName";
|
||||
const char js_XML_str[] = "XML";
|
||||
const char js_XMLList_str[] = "XMLList";
|
||||
const char js_localName_str[] = "localName";
|
||||
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_gt_entity_str[] = ">";
|
||||
const char js_lt_entity_str[] = "<";
|
||||
const char js_quot_entity_str[] = """;
|
||||
const char js_amp_entity_str[] = "&";
|
||||
const char js_gt_entity_str[] = ">";
|
||||
const char js_lt_entity_str[] = "<";
|
||||
const char js_quot_entity_str[] = """;
|
||||
|
||||
#define IS_EMPTY(str) (JSSTRING_LENGTH(str) == 0)
|
||||
#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.
|
||||
*/
|
||||
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_EnumerateStub, JS_ResolveStub, JS_ConvertStub, qname_finalize,
|
||||
NULL, NULL, NULL, NULL,
|
||||
@ -488,7 +490,7 @@ JSClass js_AttributeNameClass = {
|
||||
};
|
||||
|
||||
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_EnumerateStub, JS_ResolveStub, JS_ConvertStub, qname_finalize,
|
||||
NULL, NULL, NULL, NULL,
|
||||
@ -508,13 +510,21 @@ static JSBool
|
||||
qname_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
{
|
||||
JSClass *clasp;
|
||||
JSXMLQName *qn;
|
||||
JSString *str, *qualstr;
|
||||
size_t length;
|
||||
jschar *chars;
|
||||
|
||||
qn = (JSXMLQName *)
|
||||
JS_GetInstancePrivate(cx, obj, &js_QNameClass.base, argv);
|
||||
if (!qn)
|
||||
return JS_FALSE;
|
||||
clasp = OBJ_GET_CLASS(cx, obj);
|
||||
if (clasp == &js_AttributeNameClass || clasp == &js_AnyNameClass) {
|
||||
qn = (JSXMLQName *) JS_GetPrivate(cx, obj);
|
||||
} else {
|
||||
qn = (JSXMLQName *)
|
||||
JS_GetInstancePrivate(cx, obj, &js_QNameClass.base, argv);
|
||||
if (!qn)
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (!qn->uri) {
|
||||
/* 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);
|
||||
if (!str)
|
||||
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);
|
||||
return JS_TRUE;
|
||||
}
|
||||
@ -610,13 +636,27 @@ js_GetXMLQNameObject(JSContext *cx, JSXMLQName *qn)
|
||||
JSObject *
|
||||
js_GetAttributeNameObject(JSContext *cx, JSXMLQName *qn)
|
||||
{
|
||||
JSXMLQName *origqn;
|
||||
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);
|
||||
if (!obj || !JS_SetPrivate(cx, obj, qn)) {
|
||||
cx->newborn[GCX_OBJECT] = NULL;
|
||||
if (qn != origqn)
|
||||
js_DestroyXMLQName(cx, qn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
qn->object = obj;
|
||||
qn->markflag = JSXML_MARK_CLEAR;
|
||||
METER(xml_stats.qnameobj);
|
||||
@ -836,8 +876,16 @@ QName(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
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)
|
||||
return JS_FALSE;
|
||||
*rval = OBJECT_TO_JSVAL(obj);
|
||||
@ -933,6 +981,24 @@ out:
|
||||
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.
|
||||
*/
|
||||
@ -5937,9 +6003,7 @@ xml_name(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
if (!xml->name) {
|
||||
*rval = JSVAL_NULL;
|
||||
} else {
|
||||
nameobj = ((xml->xml_class == JSXML_CLASS_ATTRIBUTE)
|
||||
? js_GetAttributeNameObject
|
||||
: js_GetXMLQNameObject)(cx, xml->name);
|
||||
nameobj = js_GetXMLQNameObject(cx, xml->name);
|
||||
if (!nameobj)
|
||||
return JS_FALSE;
|
||||
*rval = OBJECT_TO_JSVAL(nameobj);
|
||||
@ -7144,7 +7208,12 @@ js_InitNamespaceClass(JSContext *cx, JSObject *obj)
|
||||
JSObject *
|
||||
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)) {
|
||||
return NULL;
|
||||
}
|
||||
@ -7498,6 +7567,18 @@ js_FindXMLProperty(JSContext *cx, jsval name, JSObject **objp, jsval *namep)
|
||||
lastobj = obj;
|
||||
} 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;
|
||||
*namep = JSVAL_VOID;
|
||||
return JS_TRUE;
|
||||
@ -7561,24 +7642,21 @@ js_DeleteXMLListElements(JSContext *cx, JSObject *listobj)
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_FilterXMLList(JSContext *cx, JSObject *obj, jsbytecode *pc, uint32 len,
|
||||
jsval *vp)
|
||||
js_FilterXMLList(JSContext *cx, JSObject *obj, jsbytecode *pc, jsval *vp)
|
||||
{
|
||||
JSBool ok, inLRS, match;
|
||||
JSStackFrame *fp, frame;
|
||||
JSObject *listobj, *resobj, *withobj, *kidobj;
|
||||
JSBool ok, match;
|
||||
JSStackFrame *fp;
|
||||
JSObject *scobj, *listobj, *resobj, *withobj, *kidobj;
|
||||
JSXML *xml, *list, *result, *kid;
|
||||
JSScript script;
|
||||
uint32 i, n;
|
||||
|
||||
ok = JS_TRUE;
|
||||
inLRS = JS_FALSE;
|
||||
fp = cx->fp;
|
||||
frame = *fp;
|
||||
frame.down = fp;
|
||||
frame.flags |= JSFRAME_EVAL;
|
||||
cx->fp = &frame;
|
||||
ok = JS_EnterLocalRootScope(cx);
|
||||
if (!ok)
|
||||
return JS_FALSE;
|
||||
|
||||
/* 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");
|
||||
if (!xml)
|
||||
goto bad;
|
||||
@ -7586,10 +7664,6 @@ js_FilterXMLList(JSContext *cx, JSObject *obj, jsbytecode *pc, uint32 len,
|
||||
if (xml->xml_class == JSXML_CLASS_LIST) {
|
||||
list = xml;
|
||||
} else {
|
||||
ok = JS_EnterLocalRootScope(cx);
|
||||
if (!ok)
|
||||
goto out;
|
||||
inLRS = JS_TRUE;
|
||||
listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST);
|
||||
if (!listobj)
|
||||
goto bad;
|
||||
@ -7599,24 +7673,16 @@ js_FilterXMLList(JSContext *cx, JSObject *obj, jsbytecode *pc, uint32 len,
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Root resobj via frame.rval, whether or not we are inLRS. */
|
||||
resobj = js_NewXMLObject(cx, JSXML_CLASS_LIST);
|
||||
if (!resobj)
|
||||
goto bad;
|
||||
result = (JSXML *) JS_GetPrivate(cx, resobj);
|
||||
frame.rval = OBJECT_TO_JSVAL(resobj);
|
||||
|
||||
/* 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)
|
||||
goto bad;
|
||||
frame.scopeChain = withobj;
|
||||
|
||||
script = *fp->script;
|
||||
script.code = script.main = pc;
|
||||
script.length = len;
|
||||
frame.script = &script;
|
||||
js_CallNewScriptHook(cx, &script, fp->fun);
|
||||
fp->scopeChain = withobj;
|
||||
|
||||
for (i = 0, n = list->xml_kids.length; i < n; i++) {
|
||||
kid = XMLARRAY_MEMBER(&list->xml_kids, i, JSXML);
|
||||
@ -7624,7 +7690,7 @@ js_FilterXMLList(JSContext *cx, JSObject *obj, jsbytecode *pc, uint32 len,
|
||||
if (!kidobj)
|
||||
goto bad;
|
||||
OBJ_SET_PROTO(cx, withobj, kidobj);
|
||||
ok = js_Interpret(cx, vp);
|
||||
ok = js_Interpret(cx, pc, vp);
|
||||
if (!ok)
|
||||
goto out;
|
||||
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);
|
||||
|
||||
out:
|
||||
if (frame.script == &script)
|
||||
js_CallDestroyScriptHook(cx, &script);
|
||||
if (inLRS)
|
||||
JS_LeaveLocalRootScope(cx);
|
||||
cx->fp = fp;
|
||||
fp->scopeChain = scobj;
|
||||
JS_LeaveLocalRootScope(cx);
|
||||
return ok;
|
||||
bad:
|
||||
ok = JS_FALSE;
|
||||
|
@ -42,6 +42,8 @@
|
||||
#include "jsstddef.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_Namespace_str[];
|
||||
extern const char js_QName_str[];
|
||||
@ -178,7 +180,6 @@ struct JSXML {
|
||||
JSXMLArray attrs;
|
||||
} elem;
|
||||
JSString *value;
|
||||
jsdouble align;
|
||||
} u;
|
||||
|
||||
/* Don't add anything after u -- see js_NewXML for why. */
|
||||
@ -300,8 +301,7 @@ extern JSBool
|
||||
js_DeleteXMLListElements(JSContext *cx, JSObject *listobj);
|
||||
|
||||
extern JSBool
|
||||
js_FilterXMLList(JSContext *cx, JSObject *obj, jsbytecode *pc, uint32 len,
|
||||
jsval *vp);
|
||||
js_FilterXMLList(JSContext *cx, JSObject *obj, jsbytecode *pc, jsval *vp);
|
||||
|
||||
extern JSObject *
|
||||
js_ValueToXMLObject(JSContext *cx, jsval v);
|
||||
|
Loading…
x
Reference in New Issue
Block a user