move-node-local-root-events-still-fire.html (3096B)
1 <!DOCTYPE html> 2 <title>Node moves to another document</title> 3 <link rel="author" title="Dominic Farolino" href="mailto:dom@chromium.org"> 4 <link rel="help" href="https://crbug.com/40277823"> 5 <script src="/resources/testharness.js"></script> 6 <script src="/resources/testharnessreport.js"></script> 7 <script src="/resources/testdriver.js"></script> 8 <script src="/resources/testdriver-vendor.js"></script> 9 <script src="/resources/testdriver-actions.js"></script> 10 11 <script src="/common/get-host-info.sub.js"></script> 12 13 <body> 14 <script> 15 // This is a regression test for a Chromium bug: https://crbug.com/40277823. 16 // The test is reproducible by: 17 // 1. Creating a node with an event listener that the compositor cares about, 18 // in a different local root than this one. 19 // 2. Moving the node to *this* local root, which is different from the one it 20 // was created in. 21 // 3. Clicking the node, or otherwise firing an event at it for the event that 22 // the compositor cares about. The node's current local root (this 23 // document)'s EventHandlerRegistry should know that a node with this kind 24 // event listener has been added to this local root, and the compositor 25 // shouldn't be able to fast-path around the event. The event should invoke 26 // the event listener. In Chromium before https://crrev.com/c/6674259, the 27 // node's new local root's EventHandlerRegistry would not be updated to 28 // learn about the node's event listener, and when the event comes in, the 29 // compositor would fast-path around it and fail to fire the listener. This 30 // test ensures that the listener is fired, even after the cross-local-root 31 // adoption. 32 promise_test(async t => { 33 const crossOriginChild = document.createElement('iframe'); 34 const crossOriginChildURL = 35 new URL('resources/cross-origin-middle-frame-2.html', 36 get_host_info().HTTP_REMOTE_ORIGIN + location.pathname); 37 crossOriginChild.src = crossOriginChildURL; 38 39 const grandchildLoadPromise = new Promise(resolve => { 40 window.onmessage = e => { 41 if (e.data === 'grandchild loaded') { 42 resolve(); 43 } 44 } 45 }); 46 document.body.append(crossOriginChild); 47 await grandchildLoadPromise; 48 49 const sameOriginGrandchild = window.frames[0][0]; 50 assert_not_equals(sameOriginGrandchild.document, null, 51 "same-origin grandchild frame exists"); 52 53 const grandchildButton = sameOriginGrandchild.button; 54 assert_not_equals(grandchildButton, null); 55 56 // After this current document adopts the node with an event listener from a 57 // different local frame root, the event listener should still function on the 58 // adopted node. 59 document.body.append(grandchildButton); 60 await test_driver.click(grandchildButton); 61 assert_array_equals(sameOriginGrandchild.events, ['pointerdown'], 62 "the document now hosting the adopted node recognizes the pointerdown " + 63 "event handler on the adopted node, and allows it to fire after " + 64 "adoption"); 65 }, "Event handler-bearing node moved across local roots and its event " + 66 "listeners still work"); 67 </script> 68 </body>