diff --git a/src/core/context/node.js b/src/core/context/node.js index cf6d5a6a80a0..7ac6d0624a24 100644 --- a/src/core/context/node.js +++ b/src/core/context/node.js @@ -15,6 +15,7 @@ import {Values} from './values'; const NODE_PROP = '__AMP_NODE'; const ASSIGNED_SLOT_PROP = '__AMP_ASSIGNED_SLOT'; const AMP_PREFIX = 'AMP-'; +const AMPDOC_PROP = '__AMPDOC'; // Relevant node types. // See https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType. @@ -192,14 +193,14 @@ export class ContextNode { this.name = name; /** - * Whether this node is a root. The Document DOM nodes are automatically + * Whether this node is a root. The Document DOM nodes and ampdoc roots are automatically * considered as roots. But other nodes can become roots as well * (e.g. shadow roots) via `setIsRoot()` API. * * @package * @type {boolean} */ - this.isRoot = node.nodeType == DOCUMENT_NODE; + this.isRoot = node.nodeType == DOCUMENT_NODE || !!node[AMPDOC_PROP]; /** * The root context node. Always available for a DOM node connected to a diff --git a/src/core/context/types.d.ts b/src/core/context/types.d.ts index 931c829535cc..3284e911432d 100644 --- a/src/core/context/types.d.ts +++ b/src/core/context/types.d.ts @@ -1,4 +1,5 @@ import {ContextNode} from './node'; + export interface IContextProp { /** * A globally unique key. Extensions must use a fully qualified name such @@ -92,5 +93,7 @@ declare global { // Used to map a Node to its assigned slot. __AMP_ASSIGNED_SLOT?: Node; + + __AMPDOC?: import('../../service/ampdoc-impl').AmpDoc; } } diff --git a/test/unit/core/context/test-node-discover.js b/test/unit/core/context/test-node-discover.js index 71147679e045..77f48072f461 100644 --- a/test/unit/core/context/test-node-discover.js +++ b/test/unit/core/context/test-node-discover.js @@ -161,6 +161,23 @@ describes.realWin('ContextNode', {}, (env) => { }); }); + it('should create a ampdoc holder shadow root', () => { + const frag = doc.createDocumentFragment(); + + frag.__AMPDOC = {}; + + const cn = ContextNode.get(frag); + expect(cn.node).to.equal(frag); + // Parent always starts as null. + expectContext(cn, { + parent: null, + isRoot: true, + root: frag, + children: [], + discoverable: false, + }); + }); + it('should create a document node', () => { const cn = ContextNode.get(doc); expect(cn.node).to.equal(doc);