diff options
Diffstat (limited to 'dom/base/test/test_mutationobservers.html')
-rw-r--r-- | dom/base/test/test_mutationobservers.html | 913 |
1 files changed, 0 insertions, 913 deletions
diff --git a/dom/base/test/test_mutationobservers.html b/dom/base/test/test_mutationobservers.html deleted file mode 100644 index a6de89595..000000000 --- a/dom/base/test/test_mutationobservers.html +++ /dev/null @@ -1,913 +0,0 @@ -<!DOCTYPE HTML> -<html> -<!-- -https://bugzilla.mozilla.org/show_bug.cgi?id=641821 ---> -<head> - <meta charset="utf-8"> - <title>Test for Bug 641821</title> - <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> -</head> -<body onload="runTest()"> -<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=641821">Mozilla Bug 641821</a> -<p id="display"></p> -<div id="content" style="display: none"> - -</div> -<pre id="test"> -<script type="application/javascript"> - -/** Test for Bug 641821 **/ - -SimpleTest.requestFlakyTimeout("requestFlakyTimeout is silly. (But make sure marquee has time to initialize itself.)"); - -var div = document.createElement("div"); - -var M; -if ("MozMutationObserver" in window) { - M = window.MozMutationObserver; -} else if ("WebKitMutationObserver" in window) { - M = window.WebKitMutationObserver; -} else { - M = window.MutationObserver; -} - -function log(str) { - var d = document.createElement("div"); - d.textContent = str; - if (str.indexOf("PASSED") >= 0) { - d.setAttribute("style", "color: green;"); - } else { - d.setAttribute("style", "color: red;"); - } - document.getElementById("log").appendChild(d); -} - -// Some helper functions so that this test runs also outside mochitest. -if (!("ok" in window)) { - window.ok = function(val, str) { - log(str + (val ? " PASSED\n" : " FAILED\n")); - } -} - -if (!("is" in window)) { - window.is = function(val, refVal, str) { - log(str + (val == refVal? " PASSED " : " FAILED ") + - (val != refVal ? "expected " + refVal + " got " + val + "\n" : "\n")); - } -} - -if (!("isnot" in window)) { - window.isnot = function(val, refVal, str) { - log(str + (val != refVal? " PASSED " : " FAILED ") + - (val == refVal ? "Didn't expect " + refVal + "\n" : "\n")); - } -} - -if (!("SimpleTest" in window)) { - window.SimpleTest = - { - finish: function() { - document.getElementById("log").appendChild(document.createTextNode("DONE")); - }, - waitForExplicitFinish: function() {} - } -} - -function then(thenFn) { - setTimeout(function() { - if (thenFn) { - setTimeout(thenFn, 0); - } else { - SimpleTest.finish(); - } - }, 0); -} - -var m; -var m2; -var m3; -var m4; - -// Checks basic parameter validation and normal 'this' handling. -// Tests also basic attribute handling. -function runTest() { - m = new M(function(){}); - ok(m, "MutationObserver supported"); - - var e = null; - try { - m.observe(document, {}); - } catch (ex) { - e = ex; - } - ok(e, "Should have thrown an exception"); - is(e.name, "TypeError", "Should have thrown TypeError"); - - e = null; - try { - m.observe(document, { childList: true, attributeOldValue: true }); - } catch (ex) { - e = ex; - } - ok(!e, "Shouldn't have thrown an exception"); - - e = null; - try { - m.observe(document, { childList: true, attributeFilter: ["foo"] }); - } catch (ex) { - e = ex; - } - ok(!e, "Shouldn't have thrown an exception"); - - e = null; - try { - m.observe(document, { childList: true, characterDataOldValue: true }); - } catch (ex) { - e = ex; - } - ok(!e, "Shouldn't have thrown an exception"); - - e = null; - try { - m.observe(document); - } catch (ex) { - e = ex; - } - ok(e, "Should have thrown an exception"); - - m = new M(function(records, observer) { - is(observer, m, "2nd parameter should be the mutation observer"); - is(observer, this, "2nd parameter should be 'this'"); - is(records.length, 1, "Should have one record."); - is(records[0].type, "attributes", "Should have got attributes record"); - is(records[0].target, div, "Should have got div as target"); - is(records[0].attributeName, "foo", "Should have got record about foo attribute"); - observer.disconnect(); - then(testThisBind); - m = null; - }); - m.observe(div, { attributes: true, attributeFilter: ["foo"] }); - is(SpecialPowers.wrap(div).getBoundMutationObservers()[0].getObservingInfo()[0].attributes, true); - is(SpecialPowers.wrap(div).getBoundMutationObservers()[0].getObservingInfo()[0].attributeFilter.length, 1) - is(SpecialPowers.wrap(div).getBoundMutationObservers()[0].getObservingInfo()[0].attributeFilter[0], "foo") - div.setAttribute("foo", "bar"); -} - -// 'this' handling when fn.bind() is used. -function testThisBind() { - var child = div.appendChild(document.createElement("div")); - var gchild = child.appendChild(document.createElement("div")); - m = new M((function(records, observer) { - is(observer, m, "2nd parameter should be the mutation observer"); - isnot(observer, this, "2nd parameter should be 'this'"); - is(records.length, 3, "Should have one record."); - is(records[0].type, "attributes", "Should have got attributes record"); - is(records[0].target, div, "Should have got div as target"); - is(records[0].attributeName, "foo", "Should have got record about foo attribute"); - is(records[0].oldValue, "bar", "oldValue should be bar"); - is(records[1].type, "attributes", "Should have got attributes record"); - is(records[1].target, div, "Should have got div as target"); - is(records[1].attributeName, "foo", "Should have got record about foo attribute"); - is(records[1].oldValue, "bar2", "oldValue should be bar2"); - is(records[2].type, "attributes", "Should have got attributes record"); - is(records[2].target, gchild, "Should have got div as target"); - is(records[2].attributeName, "foo", "Should have got record about foo attribute"); - is(records[2].oldValue, null, "oldValue should be bar2"); - observer.disconnect(); - then(testCharacterData); - m = null; - }).bind(window)); - m.observe(div, { attributes: true, attributeOldValue: true, subtree: true }); - is(SpecialPowers.wrap(div).getBoundMutationObservers()[0].getObservingInfo()[0].attributes, true) - is(SpecialPowers.wrap(div).getBoundMutationObservers()[0].getObservingInfo()[0].attributeOldValue, true) - is(SpecialPowers.wrap(div).getBoundMutationObservers()[0].getObservingInfo()[0].subtree, true) - div.setAttribute("foo", "bar2"); - div.removeAttribute("foo"); - div.removeChild(child); - child.removeChild(gchild); - div.appendChild(gchild); - div.removeChild(gchild); - gchild.setAttribute("foo", "bar"); -} - -function testCharacterData() { - m = new M(function(records, observer) { - is(records[0].type, "characterData", "Should have got characterData"); - is(records[0].oldValue, null, "Shouldn't have got oldData"); - observer.disconnect(); - m = null; - }); - m2 = new M(function(records, observer) { - is(records[0].type, "characterData", "Should have got characterData"); - is(records[0].oldValue, "foo", "Should have got oldData"); - observer.disconnect(); - m2 = null; - }); - m3 = new M(function(records, observer) { - ok(false, "This should not be called!"); - observer.disconnect(); - m3 = null; - }); - m4 = new M(function(records, observer) { - is(records[0].oldValue, null, "Shouldn't have got oldData"); - observer.disconnect(); - m3.disconnect(); - m3 = null; - then(testChildList); - m4 = null; - }); - - div.appendChild(document.createTextNode("foo")); - m.observe(div, { characterData: true, subtree: true }); - m2.observe(div, { characterData: true, characterDataOldValue: true, subtree: true}); - // If observing the same node twice, only the latter option should apply. - m3.observe(div, { characterData: true, subtree: true }); - m3.observe(div, { characterData: true, subtree: false }); - m4.observe(div.firstChild, { characterData: true, subtree: false }); - - is(SpecialPowers.wrap(div).getBoundMutationObservers().length, 3) - is(SpecialPowers.wrap(div).getBoundMutationObservers()[2].getObservingInfo()[0].characterData, true) - is(SpecialPowers.wrap(div).getBoundMutationObservers()[2].getObservingInfo()[0].subtree, false) - - div.firstChild.data = "bar"; -} - -function testChildList() { - var fc = div.firstChild; - m = new M(function(records, observer) { - is(records[0].type, "childList", "Should have got childList"); - is(records[0].addedNodes.length, 0, "Shouldn't have got addedNodes"); - is(records[0].removedNodes.length, 1, "Should have got removedNodes"); - is(records[0].removedNodes[0], fc, "Should have removed a text node"); - observer.disconnect(); - then(testChildList2); - m = null; - }); - m.observe(div, { childList: true}); - div.removeChild(div.firstChild); -} - -function testChildList2() { - div.innerHTML = "<span>1</span><span>2</span>"; - m = new M(function(records, observer) { - is(records[0].type, "childList", "Should have got childList"); - is(records[0].removedNodes.length, 2, "Should have got removedNodes"); - is(records[0].addedNodes.length, 1, "Should have got addedNodes"); - observer.disconnect(); - then(testChildList3); - m = null; - }); - m.observe(div, { childList: true }); - div.innerHTML = "<span><span>foo</span></span>"; -} - -function testChildList3() { - m = new M(function(records, observer) { - is(records[0].type, "childList", "Should have got childList"); - is(records[0].removedNodes.length, 1, "Should have got removedNodes"); - is(records[0].addedNodes.length, 1, "Should have got addedNodes"); - observer.disconnect(); - then(testChildList4); - m = null; - }); - m.observe(div, { childList: true }); - div.textContent = "hello"; -} - -function testChildList4() { - div.textContent = null; - var df = document.createDocumentFragment(); - var t1 = df.appendChild(document.createTextNode("Hello ")); - var t2 = df.appendChild(document.createTextNode("world!")); - var s1 = div.appendChild(document.createElement("span")); - s1.textContent = "foo"; - var s2 = div.appendChild(document.createElement("span")); - function callback(records, observer) { - is(records.length, 3, "Should have got one record for removing nodes from document fragment and one record for adding them to div"); - is(records[0].removedNodes.length, 2, "Should have got removedNodes"); - is(records[0].removedNodes[0], t1, "Should be the 1st textnode"); - is(records[0].removedNodes[1], t2, "Should be the 2nd textnode"); - is(records[1].addedNodes.length, 2, "Should have got addedNodes"); - is(records[1].addedNodes[0], t1, "Should be the 1st textnode"); - is(records[1].addedNodes[1], t2, "Should be the 2nd textnode"); - is(records[1].previousSibling, s1, "Should have previousSibling"); - is(records[1].nextSibling, s2, "Should have nextSibling"); - is(records[2].type, "characterData", "3rd record should be characterData"); - is(records[2].target, t1, "target should be the textnode"); - is(records[2].oldValue, "Hello ", "oldValue was 'Hello '"); - observer.disconnect(); - then(testChildList5); - m = null; - }; - m = new M(callback); - m.observe(df, { childList: true, characterData: true, characterDataOldValue: true, subtree: true }); - is(SpecialPowers.wrap(df).getBoundMutationObservers()[0].getObservingInfo()[0].childList, true) - is(SpecialPowers.wrap(df).getBoundMutationObservers()[0].getObservingInfo()[0].characterData, true) - is(SpecialPowers.wrap(df).getBoundMutationObservers()[0].getObservingInfo()[0].characterDataOldValue, true) - is(SpecialPowers.wrap(df).getBoundMutationObservers()[0].getObservingInfo()[0].subtree, true) - ok(SpecialPowers.compare(SpecialPowers.wrap(df).getBoundMutationObservers()[0].mutationCallback, callback)) - m.observe(div, { childList: true }); - is(SpecialPowers.wrap(df).getBoundMutationObservers()[0].getObservingInfo().length, 2) - - // Make sure transient observers aren't leaked. - var leakTest = new M(function(){}); - leakTest.observe(div, { characterData: true, subtree: true }); - - div.insertBefore(df, s2); - s1.firstChild.data = "bar"; // This should *not* create a record. - t1.data = "Hello the whole "; // This should create a record. -} - -function testChildList5() { - div.textContent = null; - var c1 = div.appendChild(document.createElement("div")); - var c2 = document.createElement("div"); - var div2 = document.createElement("div"); - var c3 = div2.appendChild(document.createElement("div")); - var c4 = document.createElement("div"); - var c5 = document.createElement("div"); - var df = document.createDocumentFragment(); - var emptyDF = document.createDocumentFragment(); - var dfc1 = df.appendChild(document.createElement("div")); - var dfc2 = df.appendChild(document.createElement("div")); - var dfc3 = df.appendChild(document.createElement("div")); - m = new M(function(records, observer) { - is(records.length, 6 , ""); - is(records[0].removedNodes.length, 1, "Should have got removedNodes"); - is(records[0].removedNodes[0], c1, ""); - is(records[0].addedNodes.length, 1, "Should have got addedNodes"); - is(records[0].addedNodes[0], c2, ""); - is(records[0].previousSibling, null, ""); - is(records[0].nextSibling, null, ""); - is(records[1].removedNodes.length, 1, "Should have got removedNodes"); - is(records[1].removedNodes[0], c3, ""); - is(records[1].addedNodes.length, 0, "Shouldn't have got addedNodes"); - is(records[1].previousSibling, null, ""); - is(records[1].nextSibling, null, ""); - is(records[2].removedNodes.length, 1, "Should have got removedNodes"); - is(records[2].removedNodes[0], c2, ""); - is(records[2].addedNodes.length, 1, "Should have got addedNodes"); - is(records[2].addedNodes[0], c3, ""); - is(records[2].previousSibling, null, ""); - is(records[2].nextSibling, null, ""); - // Check document fragment handling - is(records[5].removedNodes.length, 1, ""); - is(records[5].removedNodes[0], c4, ""); - is(records[5].addedNodes.length, 3, ""); - is(records[5].addedNodes[0], dfc1, ""); - is(records[5].addedNodes[1], dfc2, ""); - is(records[5].addedNodes[2], dfc3, ""); - is(records[5].previousSibling, c3, ""); - is(records[5].nextSibling, c5, ""); - observer.disconnect(); - then(testAdoptNode); - m = null; - }); - m.observe(div, { childList: true, subtree: true }); - m.observe(div2, { childList: true, subtree: true }); - div.replaceChild(c2, c1); - div.replaceChild(c3, c2); - div.appendChild(c4); - div.appendChild(c5); - div.replaceChild(df, c4); - div.appendChild(emptyDF); // empty document shouldn't cause mutation records -} - -function testAdoptNode() { - var d1 = document.implementation.createHTMLDocument(null); - var d2 = document.implementation.createHTMLDocument(null); - var addedNode; - m = new M(function(records, observer) { - is(records.length, 3, "Should have 2 records"); - is(records[0].target.ownerDocument, d1, "ownerDocument should be the initial document") - is(records[1].target.ownerDocument, d2, "ownerDocument should be the new document"); - is(records[2].type, "attributes", "Should have got attribute mutation") - is(records[2].attributeName, "foo", "Should have got foo attribute mutation") - observer.disconnect(); - then(testOuterHTML); - m = null; - }); - m.observe(d1, { childList: true, subtree: true, attributes: true }); - d2.body.appendChild(d1.body); - addedNode = d2.body.lastChild.appendChild(d2.createElement("div")); - addedNode.setAttribute("foo", "bar"); -} - -function testOuterHTML() { - var doc = document.implementation.createHTMLDocument(null); - var d1 = doc.body.appendChild(document.createElement("div")); - var d2 = doc.body.appendChild(document.createElement("div")); - var d3 = doc.body.appendChild(document.createElement("div")); - var d4 = doc.body.appendChild(document.createElement("div")); - m = new M(function(records, observer) { - is(records.length, 4, "Should have 1 record"); - is(records[0].removedNodes.length, 1, "Should have 1 removed nodes"); - is(records[0].addedNodes.length, 2, "Should have 2 added nodes"); - is(records[0].previousSibling, null, ""); - is(records[0].nextSibling, d2, ""); - is(records[1].removedNodes.length, 1, "Should have 1 removed nodes"); - is(records[1].addedNodes.length, 2, "Should have 2 added nodes"); - is(records[1].previousSibling, records[0].addedNodes[1], ""); - is(records[1].nextSibling, d3, ""); - is(records[2].removedNodes.length, 1, "Should have 1 removed nodes"); - is(records[2].addedNodes.length, 2, "Should have 2 added nodes"); - is(records[2].previousSibling, records[1].addedNodes[1], ""); - is(records[2].nextSibling, d4, ""); - is(records[3].removedNodes.length, 1, "Should have 1 removed nodes"); - is(records[3].addedNodes.length, 0); - is(records[3].previousSibling, records[2].addedNodes[1], ""); - is(records[3].nextSibling, null, ""); - observer.disconnect(); - then(testInsertAdjacentHTML); - m = null; - }); - m.observe(doc, { childList: true, subtree: true }); - d1.outerHTML = "<div>1</div><div>1</div>"; - d2.outerHTML = "<div>2</div><div>2</div>"; - d3.outerHTML = "<div>3</div><div>3</div>"; - d4.outerHTML = ""; -} - -function testInsertAdjacentHTML() { - var doc = document.implementation.createHTMLDocument(null); - var d1 = doc.body.appendChild(document.createElement("div")); - var d2 = doc.body.appendChild(document.createElement("div")); - var d3 = doc.body.appendChild(document.createElement("div")); - var d4 = doc.body.appendChild(document.createElement("div")); - m = new M(function(records, observer) { - is(records.length, 4, ""); - is(records[0].target, doc.body, ""); - is(records[0].previousSibling, null, ""); - is(records[0].nextSibling, d1, ""); - is(records[1].target, d2, ""); - is(records[1].previousSibling, null, ""); - is(records[1].nextSibling, null, ""); - is(records[2].target, d3, ""); - is(records[2].previousSibling, null, ""); - is(records[2].nextSibling, null, ""); - is(records[3].target, doc.body, ""); - is(records[3].previousSibling, d4, ""); - is(records[3].nextSibling, null, ""); - observer.disconnect(); - then(testSyncXHR); - m = null; - }); - m.observe(doc, { childList: true, subtree: true }); - d1.insertAdjacentHTML("beforebegin", "<div></div><div></div>"); - d2.insertAdjacentHTML("afterbegin", "<div></div><div></div>"); - d3.insertAdjacentHTML("beforeend", "<div></div><div></div>"); - d4.insertAdjacentHTML("afterend", "<div></div><div></div>"); -} - - -var callbackHandled = false; - -function testSyncXHR() { - div.textContent = null; - m = new M(function(records, observer) { - is(records.length, 1, ""); - is(records[0].addedNodes.length, 1, ""); - callbackHandled = true; - observer.disconnect(); - m = null; - }); - m.observe(div, { childList: true, subtree: true }); - div.innerHTML = "<div>hello</div>"; - var x = new XMLHttpRequest(); - x.open("GET", window.location, false); - x.send(); - ok(!callbackHandled, "Shouldn't have called the mutation callback!"); - setTimeout(testSyncXHR2, 0); -} - -function testSyncXHR2() { - ok(callbackHandled, "Should have called the mutation callback!"); - then(testTakeRecords); -} - -function testTakeRecords() { - var s = "<span>1</span><span>2</span>"; - div.innerHTML = s; - var takenRecords; - m = new M(function(records, observer) { - is(records.length, 3, "Should have got 3 records"); - - is(records[0].type, "attributes", "Should have got attributes"); - is(records[0].attributeName, "foo", ""); - is(records[0].attributeNamespace, null, ""); - is(records[0].prevValue, null, ""); - is(records[1].type, "childList", "Should have got childList"); - is(records[1].removedNodes.length, 2, "Should have got removedNodes"); - is(records[1].addedNodes.length, 2, "Should have got addedNodes"); - is(records[2].type, "attributes", "Should have got attributes"); - is(records[2].attributeName, "foo", ""); - - is(records.length, takenRecords.length, "Should have had similar mutations"); - is(records[0].type, takenRecords[0].type, "Should have had similar mutations"); - is(records[1].type, takenRecords[1].type, "Should have had similar mutations"); - is(records[2].type, takenRecords[2].type, "Should have had similar mutations"); - - is(records[1].removedNodes.length, takenRecords[1].removedNodes.length, "Should have had similar mutations"); - is(records[1].addedNodes.length, takenRecords[1].addedNodes.length, "Should have had similar mutations"); - - is(m.takeRecords().length, 0, "Shouldn't have any records"); - observer.disconnect(); - then(testMutationObserverAndEvents); - m = null; - }); - m.observe(div, { childList: true, attributes: true }); - div.setAttribute("foo", "bar"); - div.innerHTML = s; - div.removeAttribute("foo"); - takenRecords = m.takeRecords(); - div.setAttribute("foo", "bar"); - div.innerHTML = s; - div.removeAttribute("foo"); -} - -function testTakeRecords() { - function mutationListener(e) { - ++mutationEventCount; - is(e.attrChange, MutationEvent.ADDITION, "unexpected change"); - } - - m = new M(function(records, observer) { - is(records.length, 2, "Should have got 2 records"); - is(records[0].type, "attributes", "Should have got attributes"); - is(records[0].attributeName, "foo", ""); - is(records[0].oldValue, null, ""); - is(records[1].type, "attributes", "Should have got attributes"); - is(records[1].attributeName, "foo", ""); - is(records[1].oldValue, "bar", ""); - observer.disconnect(); - div.removeEventListener("DOMAttrModified", mutationListener); - then(testExpandos); - m = null; - }); - m.observe(div, { attributes: true, attributeOldValue: true }); - // Note, [0] points to a mutation observer which is there for a leak test! - ok(SpecialPowers.compare(SpecialPowers.wrap(div).getBoundMutationObservers()[1], m)); - var mutationEventCount = 0; - div.addEventListener("DOMAttrModified", mutationListener); - div.setAttribute("foo", "bar"); - div.setAttribute("foo", "bar"); - is(mutationEventCount, 1, "Should have got only one mutation event!"); -} - -function testExpandos() { - var m2 = new M(function(records, observer) { - is(observer.expandoProperty, true); - observer.disconnect(); - then(testOutsideShadowDOM); - }); - m2.expandoProperty = true; - m2.observe(div, { attributes: true }); - m2 = null; - if (SpecialPowers) { - // Run GC several times to see if the expando property disappears. - - SpecialPowers.gc(); - SpecialPowers.gc(); - SpecialPowers.gc(); - SpecialPowers.gc(); - } - div.setAttribute("foo", "bar2"); -} - -function testOutsideShadowDOM() { - var m = new M(function(records, observer) { - is(records.length, 1); - is(records[0].type, "attributes", "Should have got attributes"); - observer.disconnect(); - then(testInsideShadowDOM); - }); - m.observe(div, { - attributes: true, - childList: true, - characterData: true, - subtree: true - }) - var sr = div.createShadowRoot(); - sr.innerHTML = "<div" + ">text</" + "div>"; - sr.firstChild.setAttribute("foo", "bar"); - sr.firstChild.firstChild.data = "text2"; - sr.firstChild.appendChild(document.createElement("div")); - div.setAttribute("foo", "bar"); -} - -function testInsideShadowDOM() { - var m = new M(function(records, observer) { - is(records.length, 4); - is(records[0].type, "childList"); - is(records[1].type, "attributes"); - is(records[2].type, "characterData"); - is(records[3].type, "childList"); - observer.disconnect(); - then(testMarquee); - }); - var sr = div.createShadowRoot(); - m.observe(sr, { - attributes: true, - childList: true, - characterData: true, - subtree: true - }); - - sr.innerHTML = "<div" + ">text</" + "div>"; - sr.firstChild.setAttribute("foo", "bar"); - sr.firstChild.firstChild.data = "text2"; - sr.firstChild.appendChild(document.createElement("div")); - div.setAttribute("foo", "bar2"); - -} - -function testMarquee() { - var m = new M(function(records, observer) { - is(records.length, 1); - is(records[0].type, "attributes"); - is(records[0].attributeName, "ok"); - is(records[0].oldValue, null); - observer.disconnect(); - then(testStyleCreate); - }); - var marquee = document.createElement("marquee"); - m.observe(marquee, { - attributes: true, - attributeOldValue: true, - childList: true, - characterData: true, - subtree: true - }); - document.body.appendChild(marquee); - setTimeout(function() {marquee.setAttribute("ok", "ok")}, 500); -} - -function testStyleCreate() { - m = new M(function(records, observer) { - is(records.length, 1, "number of records"); - is(records[0].type, "attributes", "record.type"); - is(records[0].attributeName, "style", "record.attributeName"); - is(records[0].oldValue, null, "record.oldValue"); - isnot(div.getAttribute("style"), null, "style attribute after creation"); - observer.disconnect(); - m = null; - div.removeAttribute("style"); - then(testStyleModify); - }); - m.observe(div, { attributes: true, attributeOldValue: true }); - is(div.getAttribute("style"), null, "style attribute before creation"); - div.style.color = "blue"; -} - -function testStyleModify() { - div.style.color = "yellow"; - m = new M(function(records, observer) { - is(records.length, 1, "number of records"); - is(records[0].type, "attributes", "record.type"); - is(records[0].attributeName, "style", "record.attributeName"); - isnot(div.getAttribute("style"), null, "style attribute after modification"); - observer.disconnect(); - m = null; - div.removeAttribute("style"); - then(testStyleRead); - }); - m.observe(div, { attributes: true }); - isnot(div.getAttribute("style"), null, "style attribute before modification"); - div.style.color = "blue"; -} - -function testStyleRead() { - m = new M(function(records, observer) { - is(records.length, 1, "number of records"); - is(records[0].type, "attributes", "record.type"); - is(records[0].attributeName, "data-test", "record.attributeName"); - is(div.getAttribute("style"), null, "style attribute after read"); - observer.disconnect(); - div.removeAttribute("data-test"); - m = null; - then(testStyleRemoveProperty); - }); - m.observe(div, { attributes: true }); - is(div.getAttribute("style"), null, "style attribute before read"); - var value = div.style.color; // shouldn't generate any mutation records - div.setAttribute("data-test", "a"); -} - -function testStyleRemoveProperty() { - div.style.color = "blue"; - m = new M(function(records, observer) { - is(records.length, 1, "number of records"); - is(records[0].type, "attributes", "record.type"); - is(records[0].attributeName, "style", "record.attributeName"); - isnot(div.getAttribute("style"), null, "style attribute after successful removeProperty"); - observer.disconnect(); - m = null; - div.removeAttribute("style"); - then(testStyleRemoveProperty2); - }); - m.observe(div, { attributes: true }); - isnot(div.getAttribute("style"), null, "style attribute before successful removeProperty"); - div.style.removeProperty("color"); -} - -function testStyleRemoveProperty2() { - m = new M(function(records, observer) { - is(records.length, 1, "number of records"); - is(records[0].type, "attributes", "record.type"); - is(records[0].attributeName, "data-test", "record.attributeName"); - is(div.getAttribute("style"), null, "style attribute after unsuccessful removeProperty"); - observer.disconnect(); - m = null; - div.removeAttribute("data-test"); - then(testAttributeRecordMerging1); - }); - m.observe(div, { attributes: true }); - is(div.getAttribute("style"), null, "style attribute before unsuccessful removeProperty"); - div.style.removeProperty("color"); // shouldn't generate any mutation records - div.setAttribute("data-test", "a"); -} - -function testAttributeRecordMerging1() { - ok(true, "testAttributeRecordMerging1"); - var m = new M(function(records, observer) { - is(records.length, 2); - is(records[0].type, "attributes"); - is(records[0].target, div); - is(records[0].attributeName, "foo"); - is(records[0].attributeNamespace, null); - is(records[0].oldValue, null); - - is(records[1].type, "attributes"); - is(records[1].target, div.firstChild); - is(records[1].attributeName, "foo"); - is(records[1].attributeNamespace, null); - is(records[1].oldValue, null); - observer.disconnect(); - div.innerHTML = ""; - div.removeAttribute("foo"); - then(testAttributeRecordMerging2); - }); - m.observe(div, { - attributes: true, - subtree: true - }); - SpecialPowers.wrap(m).mergeAttributeRecords = true; - - div.setAttribute("foo", "bar_1"); - div.setAttribute("foo", "bar_2"); - div.innerHTML = "<div></div>"; - div.firstChild.setAttribute("foo", "bar_1"); - div.firstChild.setAttribute("foo", "bar_2"); -} - -function testAttributeRecordMerging2() { - ok(true, "testAttributeRecordMerging2"); - var m = new M(function(records, observer) { - is(records.length, 2); - is(records[0].type, "attributes"); - is(records[0].target, div); - is(records[0].attributeName, "foo"); - is(records[0].attributeNamespace, null); - is(records[0].oldValue, "initial"); - - is(records[1].type, "attributes"); - is(records[1].target, div.firstChild); - is(records[1].attributeName, "foo"); - is(records[1].attributeNamespace, null); - is(records[1].oldValue, "initial"); - observer.disconnect(); - div.innerHTML = ""; - div.removeAttribute("foo"); - then(testAttributeRecordMerging3); - }); - - div.setAttribute("foo", "initial"); - div.innerHTML = "<div></div>"; - div.firstChild.setAttribute("foo", "initial"); - m.observe(div, { - attributes: true, - subtree: true, - attributeOldValue: true - }); - SpecialPowers.wrap(m).mergeAttributeRecords = true; - - div.setAttribute("foo", "bar_1"); - div.setAttribute("foo", "bar_2"); - div.firstChild.setAttribute("foo", "bar_1"); - div.firstChild.setAttribute("foo", "bar_2"); -} - -function testAttributeRecordMerging3() { - ok(true, "testAttributeRecordMerging3"); - var m = new M(function(records, observer) { - is(records.length, 4); - is(records[0].type, "attributes"); - is(records[0].target, div); - is(records[0].attributeName, "foo"); - is(records[0].attributeNamespace, null); - is(records[0].oldValue, "initial"); - - is(records[1].type, "attributes"); - is(records[1].target, div.firstChild); - is(records[1].attributeName, "foo"); - is(records[1].attributeNamespace, null); - is(records[1].oldValue, "initial"); - - is(records[2].type, "attributes"); - is(records[2].target, div); - is(records[2].attributeName, "foo"); - is(records[2].attributeNamespace, null); - is(records[2].oldValue, "bar_1"); - - is(records[3].type, "attributes"); - is(records[3].target, div.firstChild); - is(records[3].attributeName, "foo"); - is(records[3].attributeNamespace, null); - is(records[3].oldValue, "bar_1"); - - observer.disconnect(); - div.innerHTML = ""; - div.removeAttribute("foo"); - then(testAttributeRecordMerging4); - }); - - div.setAttribute("foo", "initial"); - div.innerHTML = "<div></div>"; - div.firstChild.setAttribute("foo", "initial"); - m.observe(div, { - attributes: true, - subtree: true, - attributeOldValue: true - }); - SpecialPowers.wrap(m).mergeAttributeRecords = true; - - // No merging should happen. - div.setAttribute("foo", "bar_1"); - div.firstChild.setAttribute("foo", "bar_1"); - div.setAttribute("foo", "bar_2"); - div.firstChild.setAttribute("foo", "bar_2"); -} - -function testAttributeRecordMerging4() { - ok(true, "testAttributeRecordMerging4"); - var m = new M(function(records, observer) { - }); - - div.setAttribute("foo", "initial"); - div.innerHTML = "<div></div>"; - div.firstChild.setAttribute("foo", "initial"); - m.observe(div, { - attributes: true, - subtree: true, - attributeOldValue: true - }); - SpecialPowers.wrap(m).mergeAttributeRecords = true; - - div.setAttribute("foo", "bar_1"); - div.setAttribute("foo", "bar_2"); - div.firstChild.setAttribute("foo", "bar_1"); - div.firstChild.setAttribute("foo", "bar_2"); - - var records = m.takeRecords(); - - is(records.length, 2); - is(records[0].type, "attributes"); - is(records[0].target, div); - is(records[0].attributeName, "foo"); - is(records[0].attributeNamespace, null); - is(records[0].oldValue, "initial"); - - is(records[1].type, "attributes"); - is(records[1].target, div.firstChild); - is(records[1].attributeName, "foo"); - is(records[1].attributeNamespace, null); - is(records[1].oldValue, "initial"); - m.disconnect(); - div.innerHTML = ""; - div.removeAttribute("foo"); - then(testChromeOnly); -} - -function testChromeOnly() { - // Content can't access nativeAnonymousChildList - try { - var mo = new M(function(records, observer) { }); - mo.observe(div, { nativeAnonymousChildList: true }); - ok(false, "Should have thrown when trying to observe with chrome-only init"); - } catch (e) { - ok(true, "Throws when trying to observe with chrome-only init"); - } - - then(); -} - -SimpleTest.waitForExplicitFinish(); - -</script> -</pre> -<div id="log"> -</div> -</body> -</html> |