| <!DOCTYPE html> |
| <script src="../../../resources/testharness.js"></script> |
| <script src="../../../resources/testharnessreport.js"></script> |
| <script src="test-harness-utils.js"></script> |
| <body> |
| <script> |
| test(function() { |
| var createdInvocations = 0; |
| function created() { |
| createdInvocations++; |
| } |
| |
| var getterInvocations = 0; |
| function getter() { |
| getterInvocations++; |
| return created; |
| } |
| |
| function failer() { |
| assert_unreached('the created callback must not be retrieved after registration'); |
| } |
| |
| var proto = Object.create(HTMLElement.prototype, { |
| createdCallback: { |
| get: getter |
| } |
| }); |
| var ctor = document.registerElement('x-a', {prototype: proto}); |
| assert_equals(getterInvocations, 1, 'the created callback must have been retrieved'); |
| |
| proto.createdCallback = failer; |
| var element = new ctor(); |
| assert_equals(createdInvocations, 1, 'the created callback retrieved at registration must be invoked'); |
| }, 'transfer created callback'); |
| |
| (function() { |
| |
| t = async_test('__proto__, :unresolved and created callback timing'); |
| t.step(function() { |
| var createdInvocations = 0; |
| function created() { |
| createdInvocations++; |
| |
| if (this.id != 'u') |
| return; |
| |
| t.step(function() { |
| var t = div.querySelector('#t'); |
| var v = div.querySelector('#v'); |
| var w = div.querySelector('#w'); |
| |
| assert_equals(div.querySelector('x-b:not(:unresolved)'), this, 'the :unresolved pseudoclass should cease to apply when the created callback is invoked'); |
| assert_array_equals(div.querySelectorAll(':unresolved'), [v, w], 'the :unresolved pseudoclass should be processed in order'); |
| |
| assert_true(t instanceof C, 'prototype upgrade should happen in order (#t)'); |
| assert_false(v instanceof C, 'prototype upgrade should happen in order (#v)'); |
| }, this); |
| } |
| |
| var protoB = Object.create(HTMLElement.prototype); |
| var B = document.registerElement('x-b', {prototype: protoB}); |
| |
| var protoC = Object.create(HTMLElement.prototype); |
| protoC.createdCallback = created; |
| var C = document.registerElement('x-c', {prototype: protoC}); |
| |
| var div = document.createElement('div'); |
| div.innerHTML = '<x-c id="t"></x-c>' + |
| '<x-b id="u"></x-b>' + |
| '<x-c id="v"></x-c>' + |
| '<x-b id="w"></x-b>'; |
| assert_equals(createdInvocations, 2, 'the created callback should have been invoked once for each x-c element'); |
| assert_true(div.querySelector('#w') instanceof B, '#w\'s prototype should have ultimately been upgraded'); |
| t.done(); |
| }); |
| |
| })(); |
| |
| (function() { |
| |
| t = async_test('other callbacks for a given element are queued during the ' + |
| 'created callback and dispatched when the created callback ' + |
| 'completes'); |
| withFrame(t.step_func(function(frame) { |
| var messages = []; |
| function log(msg) { |
| messages.push(msg); |
| } |
| |
| var proto = Object.create(frame.contentWindow.HTMLElement.prototype); |
| proto.createdCallback = function() { |
| log('created started'); |
| this.remove(); |
| this.setAttribute('prey', 'gargoyles'); |
| log('created finished'); |
| }; |
| proto.attachedCallback = function() { log('entered'); }; |
| proto.detachedCallback = function() { log('left'); }; |
| proto.attributeChangedCallback = function() { log('attribute changed'); }; |
| var D = frame.contentDocument.registerElement('x-d', {prototype: proto}); |
| |
| frame.contentDocument.body.innerHTML = '<x-d></x-d>'; |
| log('done'); |
| |
| assert_array_equals( |
| messages, |
| ['created started', 'created finished', 'entered', 'left', |
| 'attribute changed', 'done'], |
| 'callbacks should not be dispatched until the created callback has ' + |
| 'finished'); |
| t.done(); |
| })); |
| |
| })(); |
| |
| (function() { |
| |
| t = async_test('callback is called even if the element is moved to foreign document'); |
| var callbackInvoked = false; |
| |
| withFrame(t.step_func(function(originalFrame) { |
| withFrame(function(destinationFrame) { |
| var protoA = Object.create(originalFrame.contentWindow.HTMLElement.prototype); |
| protoA.createdCallback = function() { |
| var toBeMoved = originalFrame.contentDocument.getElementById('toBeMoved'); |
| destinationFrame.contentDocument.body.appendChild(toBeMoved); |
| }; |
| |
| var protoB = Object.create(originalFrame.contentWindow.HTMLElement.prototype); |
| protoB.createdCallback = function() { |
| callbackInvoked = true; |
| }; |
| |
| originalFrame.contentDocument.registerElement('x-a', {prototype: protoA}); |
| originalFrame.contentDocument.registerElement('x-b', {prototype: protoB}); |
| originalFrame.contentDocument.body.innerHTML = '<x-a></x-a><x-b id="toBeMoved"></x-b>'; |
| assert_true(callbackInvoked); |
| |
| t.done(); |
| }); |
| })); |
| |
| })(); |
| </script> |