Index: LayoutTests/fast/dom/custom/registration-context-sharing.html |
diff --git a/LayoutTests/fast/dom/custom/registration-context-sharing.html b/LayoutTests/fast/dom/custom/registration-context-sharing.html |
new file mode 100644 |
index 0000000000000000000000000000000000000000..4016a95359bd542251bc5f0e4f9cde6718ee9bc1 |
--- /dev/null |
+++ b/LayoutTests/fast/dom/custom/registration-context-sharing.html |
@@ -0,0 +1,182 @@ |
+<!DOCTYPE html> |
+<script src="../../../resources/testharness.js"></script> |
+<script src="../../../resources/testharnessreport.js"></script> |
+<body> |
+<script> |
+// Creates an iframe and calls f after the iframe's onload event. |
+function withIframe(f, opt_document) { |
+ var doc = opt_document || document; |
+ var iframe = doc.createElement('iframe'); |
+ iframe.src = 'data:text/html,'; |
+ iframe.onload = function () { f(iframe); }; |
+ doc.body.appendChild(iframe); |
+} |
+ |
+function testRegistrationContextIsNotShared(contentWindowA, documentA, |
+ contentWindowB, documentB) { |
+ // Test that element x-u registered in document A is not activated when |
+ // x-u is parsed in document B |
+ |
+ var protoU = Object.create(contentWindowA.HTMLElement.prototype); |
+ protoU.createdCallback = function () { |
+ assert_unreached('creating an x-u in a different context should ' + |
+ 'not invoke a callback in this context'); |
+ }; |
+ documentA.register('x-u', {prototype: protoU}); |
+ documentB.body.innerHTML = '<x-u></x-u>'; |
+ // if protoU.createdCallback is not invoked; this passed |
+ |
+ // Test that registering two different custom elements with the same |
+ // tag name in each document doesn't lead to any crossed wires |
+ |
+ var invocations = []; |
+ function created(name) { |
+ return function () { |
+ invocations.push('created ' + name + ' in ' + this.dataset.doc); |
+ }; |
+ } |
+ |
+ var protoAV = Object.create(contentWindowA.HTMLElement.prototype); |
+ protoAV.createdCallback = created('document A\'s element V'); |
+ documentA.register('x-v', {prototype: protoAV}); |
+ |
+ var protoBV = Object.create(contentWindowB.HTMLElement.prototype); |
+ protoBV.createdCallback = created('document B\'s element V'); |
+ documentB.register('x-v', {prototype: protoBV}); |
+ |
+ documentB.body.innerHTML = '<x-v data-doc="document B"></x-v>'; |
+ var div = documentA.createElement('div'); |
+ div.innerHTML = '<x-v data-doc="document A"></x-v>'; |
+ |
+ assert_array_equals( |
+ invocations, |
+ ['created document B\'s element V in document B', |
+ 'created document A\'s element V in document A'], |
+ 'should have invoked the created callbacks in reverse creation order'); |
+ |
+ assert_equals( |
+ Object.getPrototypeOf(div.firstChild), |
+ protoAV, |
+ 'the prototype of element V in document A should be the prototype ' + |
+ 'registered in document A'); |
+ |
+ assert_equals( |
+ Object.getPrototypeOf(documentB.body.firstChild), |
+ protoBV, |
+ 'the prototype of element V in document B should be the prototype ' + |
+ 'registered in document B'); |
+ |
+ // Similarly, test that registering two different custom elements with |
+ // the same tag name doesn't mix up prototypes. These do not have |
+ // any callbacks, to try to tickle lazy wrapping. |
+ |
+ var protoAW = Object.create(contentWindowA.HTMLElement.prototype); |
+ documentA.register('x-w', {prototype: protoAW}); |
+ |
+ var protoBW = Object.create(contentWindowB.HTMLElement.prototype); |
+ documentB.register('x-w', {prototype: protoBW}); |
+ |
+ var elementA = documentA.createElement('x-w'); |
+ var elementB = documentB.createElement('x-w'); |
+ |
+ assert_equals( |
+ Object.getPrototypeOf(elementB), protoBW, |
+ 'the prototype of element W in document B should be the prototype ' + |
+ 'registered in document B'); |
+ |
+ assert_equals( |
+ Object.getPrototypeOf(elementA), protoAW, |
+ 'the prototype of element W in document A should be the prototype ' + |
+ 'registered in document A'); |
+} |
+ |
+(function () { |
+ |
+var t = async_test('registration context should not be shared with an ' + |
+ 'iframe\'s document'); |
+ |
+withIframe(t.step_func(function (frameA) { |
+ withIframe(t.step_func(function (frameB) { |
+ var documentA = frameA.contentDocument; |
+ var documentB = frameB.contentDocument; |
+ testRegistrationContextIsNotShared( |
+ frameA.contentWindow, frameA.contentDocument, |
+ frameB.contentWindow, frameB.contentDocument); |
+ frameA.remove(); |
+ frameB.remove(); |
+ t.done(); |
+ }), frameA.contentDocument); |
+})); |
+ |
+})(); |
+ |
+function testSharedRegistrationContext(contentWindow, documentA, documentB) { |
+ var documentAUpgradeCandidate = documentA.createElement('x-u'); |
+ documentAUpgradeCandidate.dataset.name = 'document A upgrade candidate'; |
+ |
+ var documentBUpgradeCandidate = documentB.createElement('x-u'); |
+ documentBUpgradeCandidate.dataset.name = 'document B upgrade candidate'; |
+ |
+ var invocations = []; |
+ function created() { |
+ invocations.push('created ' + this.dataset.name + ' with prototype ' + |
+ 'tagged ' + this.prototypeTag); |
+ } |
+ |
+ var protoU = Object.create(contentWindow.HTMLElement.prototype); |
+ protoU.prototypeTag = 'U'; |
+ protoU.createdCallback = created; |
+ documentB.register('x-u', {prototype: protoU}); |
+ |
+ assert_array_equals( |
+ invocations, |
+ ['created document B upgrade candidate with prototype tagged U', |
+ 'created document A upgrade candidate with prototype tagged U'], |
+ 'the created callback should have been called for both elements' + |
+ 'in reverse creation order'); |
+ |
+ var protoV = Object.create(contentWindow.HTMLElement.prototype); |
+ protoV.prototypeTag = 'V'; |
+ protoV.createdCallback = created; |
+ documentA.register('x-v', {prototype: protoV}); |
+ |
+ invocations = []; |
+ var div = documentB.createElement('div'); |
+ div.innerHTML = '<x-v data-name="document B element V"></x-v>'; |
+ assert_array_equals( |
+ invocations, |
+ ['created document B element V with prototype tagged V'], |
+ 'the created callback should have been called for the x-v element'); |
+} |
+ |
+(function () { |
+ |
+var t = async_test('registration context is shared with ' + |
+ 'DOMImplementation.createDocument'); |
+ |
+withIframe(t.step_func(function (frame) { |
+ var documentA = frame.contentDocument; |
+ var documentB = documentA.implementation.createHTMLDocument(); |
+ testSharedRegistrationContext(frame.contentWindow, documentA, documentB); |
+ frame.remove(); |
+ t.done(); |
+})); |
+ |
+})(); |
+ |
+(function () { |
+ |
+var t = async_test('registration context is shared with the template document'); |
+ |
+withIframe(t.step_func(function (frame) { |
+ var documentA = frame.contentDocument; |
+ documentA.body.innerHTML = '<template>foo</template>'; |
+ var documentB = documentA.body.firstChild.content.ownerDocument; |
+ testSharedRegistrationContext(frame.contentWindow, documentA, documentB); |
+ frame.remove(); |
+ t.done(); |
+})); |
+ |
+})(); |
+ |
+</script> |