Skip to content

Commit

Permalink
support dimension bindings in cross-origin mode (#2989)
Browse files Browse the repository at this point in the history
  • Loading branch information
mrkishi authored Apr 20, 2020
1 parent cc3c7fa commit ff5f252
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 31 deletions.
2 changes: 1 addition & 1 deletion src/compiler/compile/render_dom/wrappers/Element/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -586,7 +586,7 @@ export default class ElementWrapper extends Wrapper {
);

block.chunks.destroy.push(
b`${resize_listener}.cancel();`
b`${resize_listener}();`
);
} else {
block.event_listeners.push(
Expand Down
74 changes: 49 additions & 25 deletions src/runtime/internal/dom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,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);
}
Expand Down Expand Up @@ -234,37 +234,61 @@ 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.setAttribute('aria-hidden', 'true');
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';
}

if (/Trident/.test(navigator.userAgent)) {
element.appendChild(object);
object.data = 'about:blank';
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};`
);
iframe.setAttribute('aria-hidden', 'true');
iframe.tabIndex = -1;

let unsubscribe: () => void;

if (is_crossorigin()) {
iframe.src = `data:text/html,<script>onresize=function(){parent.postMessage(0,'*')}</script>`;
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();
};
}

Expand Down Expand Up @@ -316,4 +340,4 @@ export class HtmlTag {
d() {
this.n.forEach(detach);
}
}
}
2 changes: 1 addition & 1 deletion test/js/samples/bind-width-height/expected.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ function create_fragment(ctx) {
o: noop,
d(detaching) {
if (detaching) detach(div);
div_resize_listener.cancel();
div_resize_listener();
}
};
}
Expand Down
2 changes: 1 addition & 1 deletion test/js/samples/video-bindings/expected.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ function create_fragment(ctx) {
o: noop,
d(detaching) {
if (detaching) detach(video);
video_resize_listener.cancel();
video_resize_listener();
run_all(dispose);
}
};
Expand Down
6 changes: 3 additions & 3 deletions test/runtime/samples/binding-width-height-a11y/_config.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
export default {
async test({ assert, target }) {
const object = target.querySelector('object');
const iframe = target.querySelector('iframe');

assert.equal(object.getAttribute('aria-hidden'), "true");
assert.equal(object.getAttribute('tabindex'), "-1");
assert.equal(iframe.getAttribute('aria-hidden'), "true");
assert.equal(iframe.getAttribute('tabindex'), "-1");
}
};

0 comments on commit ff5f252

Please sign in to comment.