Bug 680858 - Setting the namespace of an existing attribute may cause it to duplicate another existing attribute (E4X spec bug). Remove the already-existing attribute before mutating the attribute's namespace to not introduce duplicate attributes. r=jwalden

--HG--
extra : rebase_source : c99c0efad1e78c5a63ed6e04beb0fdedbf3e4967
This commit is contained in:
Rasmus Jensen 2011-10-26 15:35:32 -07:00
parent ddb3e139c0
commit 9a4902d909
2 changed files with 33 additions and 0 deletions

View File

@ -6810,6 +6810,12 @@ xml_setName(JSContext *cx, uintN argc, jsval *vp)
return JS_TRUE;
}
/* Utility function used within xml_setNamespace */
static JSBool qn_match(const void *xml, const void *qn) {
return qname_identity(((JSXML *)xml)->name, (JSObject *)qn);
}
/* ECMA-357 13.4.4.36 */
static JSBool
xml_setNamespace(JSContext *cx, uintN argc, jsval *vp)
{
@ -6838,6 +6844,22 @@ xml_setNamespace(JSContext *cx, uintN argc, jsval *vp)
if (!qn)
return JS_FALSE;
/*
* Erratum: setting the namespace of an attribute may cause it to duplicate
* an already-existing attribute. To preserve the invariant that there are
* not multiple attributes with the same name, we delete the existing
* attribute so that the mutated attribute will not be a duplicate.
*/
if (xml->xml_class == JSXML_CLASS_ATTRIBUTE &&
xml->parent && xml->parent->xml_class == JSXML_CLASS_ELEMENT &&
!qn_match(xml, qn))
{
JSXMLArray *array = &xml->parent->xml_attrs;
uint32 i = XMLArrayFindMember(array, qn, qn_match);
if (i != XML_NOT_FOUND)
XMLArrayDelete(cx, array, i, JS_TRUE);
}
xml->name = qn;
/*

View File

@ -68,4 +68,15 @@ TEST(3, 1, xhtml.namespaceDeclarations().length);
TEST(4, xhtml1NS, xhtml.namespace());
var xml = <root xmlns:ns="http://example.org/"><blah/></root>
var ns = new Namespace('ns','http://example.org/');
xml.blah.@foo = 'bar';
xml.blah.@foo.setNamespace(ns);
xml.blah.@foo = 'baz';
xml.blah.@foo.setNamespace(ns);
var expected = <root xmlns:ns="http://example.org/"><blah ns:foo="baz"/></root>;
TEST(5, xml, expected);
END();