Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 <!DOCTYPE html> | |
| 2 <script src="../../../resources/testharness.js"></script> | |
| 3 <script src="../../../resources/testharnessreport.js"></script> | |
| 4 <body> | |
| 5 <template id="expected">A entered | |
| 6 A removing parent node | |
| 7 A left | |
| 8 A inserting parent node | |
| 9 A entered | |
| 10 A removing parent node | |
| 11 A left | |
| 12 A inserting parent node | |
| 13 A entered | |
| 14 B entered | |
| 15 B left | |
| 16 B entered | |
| 17 B setting attribute on C | |
| 18 C entered | |
| 19 C left | |
| 20 C entered | |
| 21 C left | |
| 22 C entered | |
| 23 C@by null->b | |
| 24 C setting attribute on B | |
| 25 B left | |
| 26 B entered | |
| 27 B@by null->c | |
| 28 B setting attribute on A | |
| 29 A@by null->b | |
| 30 B set attribute on A | |
| 31 C set attribute on B | |
| 32 B set attribute on C | |
| 33 A inserted parent node | |
| 34 A removed parent node | |
| 35 A inserted parent node | |
| 36 A removed parent node</template> | |
| 37 <script> | |
| 38 test(function () { | |
| 39 // Helpers for logging | |
| 40 var buffer = []; | |
| 41 var indentation = ''; | |
| 42 function log(msg) { | |
| 43 buffer.push(indentation + msg); | |
| 44 } | |
| 45 function indent() { | |
| 46 indentation += ' '; | |
| 47 } | |
| 48 function unindent() { | |
| 49 indentation = indentation.substring(3); | |
| 50 } | |
|
Yuta Kitamura
2013/07/08 03:40:49
I see a lot of instances of:
- "log(...); indent()
| |
| 51 | |
| 52 // This tests recursion and the processing stack. Specifically: | |
| 53 // | |
| 54 // (1) Scheduling callbacks for an element that has callbacks | |
| 55 // scheduled at an outer level of recursion, but that have not | |
| 56 // begun to be processed yet. | |
| 57 // | |
| 58 // (2) Scheduling callbacks for an element that is in the middle | |
| 59 // of processing callbacks at an outer level of recursion. | |
| 60 // | |
| 61 // (3) Scheduling callbacks for an element that exhaustively | |
| 62 // processed callbacks at an outer level of recursion. | |
| 63 // | |
| 64 // appendChild and remove are used on a subtree containing | |
| 65 // multiple custom elements. In this way it is possible to | |
| 66 // schedule callbacks for multiple custom elements with one DOM | |
| 67 // call. | |
| 68 // | |
| 69 // The test creates this tree: | |
| 70 // | |
| 71 // <div> | |
| 72 // <x-a></x-a> | |
| 73 // <x-b></x-b> | |
| 74 // <x-c></x-c> | |
| 75 // </div> | |
| 76 // | |
| 77 // x-a pushes its parent in and out of the document, thus scheduling | |
| 78 // work for x-b and x-c at every level of recursion. | |
| 79 // | |
| 80 // Then x-b processes half its queue before setting an attribute | |
| 81 // on x-c. This tests case (1) because x-c has not begun its queue | |
| 82 // yet. | |
| 83 // | |
| 84 // x-c turns around and sets and attribute on x-b. This tests case | |
| 85 // (2) because x-b is half way through processing its queue. | |
| 86 // | |
| 87 // x-b turns around and sets an attribute on x-a. This tests case | |
| 88 // (3) because x-a has finished processing its queue. | |
| 89 | |
| 90 var protoA = Object.create(HTMLElement.prototype); | |
| 91 var n = 0; | |
| 92 protoA.enteredDocumentCallback = function () { | |
| 93 log('A entered'); | |
| 94 n++; | |
| 95 if (n < 3) { | |
| 96 log('A removing parent node'); indent(); | |
| 97 this.parentNode.remove(); | |
| 98 unindent(); log('A removed parent node'); | |
| 99 } | |
| 100 }; | |
| 101 protoA.leftDocumentCallback = function () { | |
| 102 log('A left'); | |
| 103 log('A inserting parent node'); indent(); | |
| 104 document.body.appendChild(this.parentNode); | |
| 105 unindent(); log('A inserted parent node'); | |
| 106 }; | |
| 107 protoA.attributeChangedCallback = function (name, oldValue, newValue) { | |
| 108 log('A@' + name + ' ' + oldValue + '->' + newValue); | |
| 109 }; | |
| 110 var A = document.register('x-a', {prototype: protoA}); | |
| 111 | |
| 112 var protoB = Object.create(HTMLElement.prototype); | |
| 113 var m = 0; | |
| 114 protoB.enteredDocumentCallback = function () { | |
| 115 log('B entered'); | |
| 116 m++; | |
| 117 if (m == 2) { | |
| 118 log('B setting attribute on C'); indent(); | |
| 119 this.parentNode.querySelector('x-c').setAttribute('by', 'b'); | |
| 120 unindent(); log('B set attribute on C'); | |
| 121 } | |
| 122 }; | |
| 123 protoB.leftDocumentCallback = function () { | |
| 124 log('B left'); | |
| 125 }; | |
| 126 protoB.attributeChangedCallback = function (name, oldValue, newValue) { | |
| 127 log('B@' + name + ' ' + oldValue + '->' + newValue); | |
| 128 log('B setting attribute on A'); indent(); | |
| 129 this.parentNode.querySelector('x-a').setAttribute('by', 'b'); | |
| 130 unindent(); log('B set attribute on A'); | |
| 131 }; | |
| 132 var B = document.register('x-b', {prototype: protoB}); | |
| 133 | |
| 134 var protoC = Object.create(HTMLElement.prototype); | |
| 135 protoC.enteredDocumentCallback = function () { | |
| 136 log('C entered'); | |
| 137 }; | |
| 138 protoC.leftDocumentCallback = function () { | |
| 139 log('C left'); | |
| 140 }; | |
| 141 protoC.attributeChangedCallback = function (name, oldValue, newValue) { | |
| 142 log('C@' + name + ' ' + oldValue + '->' + newValue); | |
| 143 log('C setting attribute on B'); indent(); | |
| 144 this.parentNode.querySelector('x-b').setAttribute('by', 'c'); | |
| 145 unindent(); log('C set attribute on B'); | |
| 146 }; | |
| 147 var C = document.register('x-c', {prototype: protoC}); | |
| 148 | |
| 149 var div = document.createElement('div'); | |
| 150 div.innerHTML = '<div><x-a></x-a><x-b></x-b><x-c></x-c></div>'; | |
| 151 document.body.appendChild(div); | |
| 152 | |
| 153 assert_equals(buffer.join('\n'), expected.content.textContent, 'should have generated an identical log'); | |
| 154 }, 'recursively scheduled callbacks'); | |
| 155 </script> | |
| OLD | NEW |