From 8a5c1e9b2d2755db838fb8b9ea5b8da472ddb661 Mon Sep 17 00:00:00 2001 From: Daniel Freedman Date: Mon, 20 May 2019 14:33:58 -0700 Subject: [PATCH] Make sure scopeSubtree does not recurse through other ShadowRoots Polymer v1 implementation of `scopeSubtree` actually only added scoping classes, and thus would have most of the effect of stopping at ShadowRoot boundaries. This change is more consistent with Polymer v1 behavior, without a weird intersection of styling behavior. --- lib/utils/scope-subtree.js | 19 ++++++++++++ test/unit/styling-scoped-nopatch.html | 42 +++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/lib/utils/scope-subtree.js b/lib/utils/scope-subtree.js index 7932d27f81..f99a7fb724 100644 --- a/lib/utils/scope-subtree.js +++ b/lib/utils/scope-subtree.js @@ -9,10 +9,22 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN */ import './boot.js'; +import {wrap} from './wrap.js'; const ShadyDOM = window.ShadyDOM; const ShadyCSS = window.ShadyCSS; +/** + * Return true if node scope is correct. + * + * @param {!Element} node Node to check scope + * @param {!Node} scope Scope reference + * @return {boolean} True if node is in scope + */ +function sameScope(node, scope) { + return wrap(node).getRootNode() === scope; +} + /** * Ensure that elements in a ShadowDOM container are scoped correctly. * This function is only needed when ShadyDOM is used and unpatched DOM APIs are used in third party code. @@ -38,13 +50,20 @@ export function scopeSubtree(container, shouldObserve = false) { } // capture correct scope for container const containerScope = ScopingShim['scopeForNode'](container); + const root = wrap(container).getRootNode(); const scopify = (node) => { + if (!sameScope(node, root)) { + return; + } // NOTE: native qSA does not honor scoped DOM, but it is faster, and the same behavior as Polymer v1 const elements = Array.from(ShadyDOM['nativeMethods']['querySelectorAll'].call(node, '*')); elements.push(node); for (let i = 0; i < elements.length; i++) { const el = elements[i]; + if (!sameScope(el, root)) { + continue; + } const currentScope = ScopingShim['currentScopeForNode'](el); if (currentScope !== containerScope) { if (currentScope !== '') { diff --git a/test/unit/styling-scoped-nopatch.html b/test/unit/styling-scoped-nopatch.html index b1f82b1fea..e31b7da2a8 100644 --- a/test/unit/styling-scoped-nopatch.html +++ b/test/unit/styling-scoped-nopatch.html @@ -50,6 +50,24 @@ customElements.define('scope-subtree-element', ScopeSubtreeElement); + + + + + +