From 3ac8b7a18a5b7d09e016266499d2ed80ab0c6cf5 Mon Sep 17 00:00:00 2001 From: mrkishi Date: Sun, 20 Oct 2019 12:11:17 -0300 Subject: [PATCH] support dimension bindings in cross-origin mode --- .../render_dom/wrappers/Element/index.ts | 2 +- src/runtime/internal/dom.ts | 69 ++++++++++++------- test/js/samples/bind-width-height/expected.js | 2 +- 3 files changed, 48 insertions(+), 25 deletions(-) diff --git a/src/compiler/compile/render_dom/wrappers/Element/index.ts b/src/compiler/compile/render_dom/wrappers/Element/index.ts index d7c1c7686b7f..e9fc61fd32d9 100644 --- a/src/compiler/compile/render_dom/wrappers/Element/index.ts +++ b/src/compiler/compile/render_dom/wrappers/Element/index.ts @@ -513,7 +513,7 @@ export default class ElementWrapper extends Wrapper { ); block.chunks.destroy.push( - b`${resize_listener}.cancel();` + b`${resize_listener}();` ); } else { block.event_listeners.push( diff --git a/src/runtime/internal/dom.ts b/src/runtime/internal/dom.ts index 481fb7d74a0c..c7e0f06c9397 100644 --- a/src/runtime/internal/dom.ts +++ b/src/runtime/internal/dom.ts @@ -56,7 +56,7 @@ export function empty() { return text(''); } -export function listen(node: Node, event: string, handler: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions | EventListenerOptions) { +export function listen(node: EventTarget, event: string, handler: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions | EventListenerOptions) { node.addEventListener(event, handler, options); return () => node.removeEventListener(event, handler, options); } @@ -226,36 +226,59 @@ export function select_multiple_value(select) { return [].map.call(select.querySelectorAll(':checked'), option => option.__value); } -export function add_resize_listener(element, fn) { - if (getComputedStyle(element).position === 'static') { - element.style.position = 'relative'; +// unfortunately this can't be a constant as that wouldn't be tree-shakeable +// so we cache the result instead +let crossorigin: boolean; + +export function is_crossorigin() { + if (crossorigin === undefined) { + crossorigin = false; + + try { + if (typeof window !== 'undefined' && window.parent) { + void window.parent.document; + } + } catch (error) { + crossorigin = true; + } } - const object = document.createElement('object'); - object.setAttribute('style', 'display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden; pointer-events: none; z-index: -1;'); - object.type = 'text/html'; - object.tabIndex = -1; + return crossorigin; +} - let win; +export function add_resize_listener(node: HTMLElement, fn: () => void) { + const computed_style = getComputedStyle(node); + const z_index = (parseInt(computed_style.zIndex) || 0) - 1; - object.onload = () => { - win = object.contentDocument.defaultView; - win.addEventListener('resize', fn); - }; + if (computed_style.position === 'static') { + node.style.position = 'relative'; + } + + const iframe = element('iframe'); + iframe.setAttribute('style', + `display: block; position: absolute; top: 0; left: 0; width: 100%; height: 100%; ` + + `overflow: hidden; border: 0; opacity: 0; pointer-events: none; z-index: ${z_index};` + ); + + let unsubscribe: () => void; - if (/Trident/.test(navigator.userAgent)) { - element.appendChild(object); - object.data = 'about:blank'; + if (is_crossorigin()) { + iframe.src = `data:text/html,`; + unsubscribe = listen(window, 'message', (event: MessageEvent) => { + if (event.source === iframe.contentWindow) fn(); + }); } else { - object.data = 'about:blank'; - element.appendChild(object); + iframe.src = 'about:blank'; + iframe.onload = () => { + unsubscribe = listen(iframe.contentWindow, 'resize', fn); + }; } - return { - cancel: () => { - win && win.removeEventListener && win.removeEventListener('resize', fn); - element.removeChild(object); - } + append(node, iframe); + + return () => { + detach(iframe); + if (unsubscribe) unsubscribe(); }; } diff --git a/test/js/samples/bind-width-height/expected.js b/test/js/samples/bind-width-height/expected.js index b10074ce2b2c..9873ed7c2145 100644 --- a/test/js/samples/bind-width-height/expected.js +++ b/test/js/samples/bind-width-height/expected.js @@ -29,7 +29,7 @@ function create_fragment(ctx) { o: noop, d(detaching) { if (detaching) detach(div); - div_resize_listener.cancel(); + div_resize_listener(); } }; }