diff options
Diffstat (limited to 'systrace/catapult/third_party/polymer/components/shadycss/src/document-watcher.js')
-rw-r--r-- | systrace/catapult/third_party/polymer/components/shadycss/src/document-watcher.js | 198 |
1 files changed, 0 insertions, 198 deletions
diff --git a/systrace/catapult/third_party/polymer/components/shadycss/src/document-watcher.js b/systrace/catapult/third_party/polymer/components/shadycss/src/document-watcher.js deleted file mode 100644 index 9cf34f0..0000000 --- a/systrace/catapult/third_party/polymer/components/shadycss/src/document-watcher.js +++ /dev/null @@ -1,198 +0,0 @@ -/** -@license -Copyright (c) 2017 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt -*/ - -'use strict'; - -import {nativeShadow} from './style-settings.js'; -import StyleTransformer from './style-transformer.js'; -import {getIsExtends, elementHasBuiltCss, wrap} from './style-util.js'; - -export let flush = function() {}; - -/** - * @param {!Element} element - * @return {string} - */ -function getClasses(element) { - if (element.classList && element.classList.value) { - return element.classList.value; - } else { - // NOTE: className is patched to remove scoping classes in ShadyDOM - // use getAttribute('class') instead, which is unpatched - return element.getAttribute('class') || ''; - } -} - -const scopeRegExp = new RegExp(`${StyleTransformer.SCOPE_NAME}\\s*([^\\s]*)`); - -/** - * @param {!Element} element - * @return {string} - */ -export function getCurrentScope(element) { - const match = getClasses(element).match(scopeRegExp); - if (match) { - return match[1]; - } else { - return ''; - } -} - -/** - * @param {!Node} node - */ -export function getOwnerScope(node) { - const ownerRoot = wrap(node).getRootNode(); - if (ownerRoot === node || ownerRoot === node.ownerDocument) { - return ''; - } - const host = /** @type {!ShadowRoot} */(ownerRoot).host; - if (!host) { - // this may actually be a document fragment - return ''; - } - return getIsExtends(host).is; -} - -/** - * @param {!Element} element - */ -export function ensureCorrectScope(element) { - const currentScope = getCurrentScope(element); - const ownerRoot = wrap(element).getRootNode(); - if (ownerRoot === element) { - return; - } - if (currentScope && ownerRoot === element.ownerDocument) { - // node was scoped, but now is in document - StyleTransformer.domRemoveScope(element, currentScope); - } else if (ownerRoot instanceof ShadowRoot) { - const ownerScope = getOwnerScope(element); - if (ownerScope !== currentScope) { - // node was scoped, but not by its current owner - StyleTransformer.domReplaceScope(element, currentScope, ownerScope); - } - } -} - -/** - * @param {!HTMLElement|!HTMLDocument} element - */ -export function ensureCorrectSubtreeScoping(element) { - // find unscoped subtree nodes - const unscopedNodes = window['ShadyDOM']['nativeMethods']['querySelectorAll'].call( - element, `:not(.${StyleTransformer.SCOPE_NAME})`); - - for (let j = 0; j < unscopedNodes.length; j++) { - // it's possible, during large batch inserts, that nodes that aren't - // scoped within the current scope were added. - // To make sure that any unscoped nodes that were inserted in the current batch are correctly styled, - // query all unscoped nodes and force their style-scope to be applied. - // This could happen if a sub-element appended an unscoped node in its shadowroot and this function - // runs on a parent element of the host of that unscoped node: - // parent-element -> element -> unscoped node - // Here unscoped node should have the style-scope element, not parent-element. - const unscopedNode = unscopedNodes[j]; - const scopeForPreviouslyUnscopedNode = getOwnerScope(unscopedNode); - if (scopeForPreviouslyUnscopedNode) { - StyleTransformer.element(unscopedNode, scopeForPreviouslyUnscopedNode); - } - } -} - -/** - * @param {HTMLElement} el - * @return {boolean} - */ -function isElementWithBuiltCss(el) { - if (el.localName === 'style' || el.localName === 'template') { - return elementHasBuiltCss(el); - } - return false; -} - -/** - * @param {Array<MutationRecord|null>|null} mxns - */ -function handler(mxns) { - for (let x=0; x < mxns.length; x++) { - let mxn = mxns[x]; - if (mxn.target === document.documentElement || - mxn.target === document.head) { - continue; - } - for (let i=0; i < mxn.addedNodes.length; i++) { - let n = mxn.addedNodes[i]; - if (n.nodeType !== Node.ELEMENT_NODE) { - continue; - } - n = /** @type {HTMLElement} */(n); // eslint-disable-line no-self-assign - let root = n.getRootNode(); - let currentScope = getCurrentScope(n); - // node was scoped, but now is in document - // If this element has built css, we must not remove scoping as this node - // will be used as a template or style without re - applying scoping as an optimization - if (currentScope && root === n.ownerDocument && !isElementWithBuiltCss(n)) { - StyleTransformer.domRemoveScope(n, currentScope); - } else if (root instanceof ShadowRoot) { - const newScope = getOwnerScope(n); - // rescope current node and subtree if necessary - if (newScope !== currentScope) { - StyleTransformer.domReplaceScope(n, currentScope, newScope); - } - // make sure all the subtree elements are scoped correctly - ensureCorrectSubtreeScoping(n); - } - } - } -} - -// if native Shadow DOM is being used, or ShadyDOM handles dynamic scoiping, do not activate the MutationObserver -if (!nativeShadow && !(window['ShadyDOM'] && window['ShadyDOM']['handlesDynamicScoping'])) { - let observer = new MutationObserver(handler); - let start = (node) => { - observer.observe(node, {childList: true, subtree: true}); - } - let nativeCustomElements = (window['customElements'] && - !window['customElements']['polyfillWrapFlushCallback']); - // need to start immediately with native custom elements - // TODO(dfreedm): with polyfilled HTMLImports and native custom elements - // excessive mutations may be observed; this can be optimized via cooperation - // with the HTMLImports polyfill. - if (nativeCustomElements) { - start(document); - } else { - let delayedStart = () => { - start(document.body); - } - // use polyfill timing if it's available - if (window['HTMLImports']) { - window['HTMLImports']['whenReady'](delayedStart); - // otherwise push beyond native imports being ready - // which requires RAF + readystate interactive. - } else { - requestAnimationFrame(function() { - if (document.readyState === 'loading') { - let listener = function() { - delayedStart(); - document.removeEventListener('readystatechange', listener); - } - document.addEventListener('readystatechange', listener); - } else { - delayedStart(); - } - }); - } - } - - flush = function() { - handler(observer.takeRecords()); - } -} |