- 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:
brendan%mozilla.org 2004-12-18 02:28:21 +00:00
Родитель b397544e5e
Коммит d1291966ce
11 изменённых файлов: 169 добавлений и 88 удалений

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

@ -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 {

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

@ -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[] = "&amp;";
const char js_gt_entity_str[] = "&gt;";
const char js_lt_entity_str[] = "&lt;";
const char js_quot_entity_str[] = "&quot;";
const char js_amp_entity_str[] = "&amp;";
const char js_gt_entity_str[] = "&gt;";
const char js_lt_entity_str[] = "&lt;";
const char js_quot_entity_str[] = "&quot;";
#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);