From e809ec82e46f7e5deea6c1700e4ed238d6a1d991 Mon Sep 17 00:00:00 2001 From: Domenic Denicola Date: Thu, 13 Dec 2018 18:15:32 +0900 Subject: [PATCH 1/3] Use mutation observer to avoid visible --- demos/tags/streaming-element.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/demos/tags/streaming-element.js b/demos/tags/streaming-element.js index dfc6b1781..78b98b9ad 100644 --- a/demos/tags/streaming-element.js +++ b/demos/tags/streaming-element.js @@ -22,6 +22,7 @@ customElements.define('streaming-element', class StreamingElement extends HTMLEl reset() { this.innerHTML = ''; + let mo; const iframeReady = new Promise(resolve => { const iframe = document.createElement('iframe'); iframe.style.display = 'none'; @@ -30,7 +31,17 @@ customElements.define('streaming-element', class StreamingElement extends HTMLEl iframe.onload = () => { iframe.onload = null; iframe.contentDocument.write(''); - this.appendChild(iframe.contentDocument.querySelector('streaming-element-inner')); + + const inner = iframe.contentDocument.querySelector('streaming-element-inner'); + mo = new MutationObserver(mutations => { + for (const mutation of mutations) { + for(const node of mutation.addedNodes) { + this.appendChild(node); + } + } + }); + + mo.observe(inner, { childList: true }); resolve(iframe); }; iframe.src = ''; @@ -41,6 +52,7 @@ customElements.define('streaming-element', class StreamingElement extends HTMLEl iframe.contentDocument.write(''); iframe.contentDocument.close(); iframe.remove(); + mo.disconnect(); } this.writable = new WritableStream({ From 5b6108359bd4e1ea8c04f6257565c72caf3c6235 Mon Sep 17 00:00:00 2001 From: Domenic Denicola Date: Thu, 13 Dec 2018 18:19:32 +0900 Subject: [PATCH 2/3] Use shadow DOM to avoid adding iframe to body --- demos/tags/streaming-element.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/demos/tags/streaming-element.js b/demos/tags/streaming-element.js index 78b98b9ad..21db5bfbd 100644 --- a/demos/tags/streaming-element.js +++ b/demos/tags/streaming-element.js @@ -16,6 +16,8 @@ customElements.define('streaming-element', class StreamingElement extends HTMLElement { constructor() { super(); + this._shadowRoot = this.attachShadow({ mode: 'closed' }); + this._shadowRoot.appendChild(document.createElement('slot')); this.reset(); } @@ -26,7 +28,7 @@ customElements.define('streaming-element', class StreamingElement extends HTMLEl const iframeReady = new Promise(resolve => { const iframe = document.createElement('iframe'); iframe.style.display = 'none'; - document.body.appendChild(iframe); + this._shadowRoot.appendChild(iframe); iframe.onload = () => { iframe.onload = null; From 4c1f98789c3d56d41da30986934e1fce4a6f7b10 Mon Sep 17 00:00:00 2001 From: Domenic Denicola Date: Thu, 13 Dec 2018 18:28:22 +0900 Subject: [PATCH 3/3] Add further TODOs for the record --- demos/tags/streaming-element.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/demos/tags/streaming-element.js b/demos/tags/streaming-element.js index 21db5bfbd..3ced14505 100644 --- a/demos/tags/streaming-element.js +++ b/demos/tags/streaming-element.js @@ -13,6 +13,18 @@ // limitations under the License. 'use strict'; +// TODO: +// - Be webby: need to put writable as a getter on the prototype +// - Use textContent instead of innerHTML because simpler/maybe more optimized +// - Add onabort and onclose events---allows custom error display, footers, etc. +// - Maybe backpressure; needs more discussion +// - Could maybe use display locking!? +// - Get scheduling/rendering team to help +// - Additional modes and features: +// - Put the content into a shadow DOM (can't be styled from the outside) +// - Display lock the content (no incremental display, but the ultimate in no-jank streaming of content) + + customElements.define('streaming-element', class StreamingElement extends HTMLElement { constructor() { super();