Skip to content

Commit

Permalink
feat: support shadow dom
Browse files Browse the repository at this point in the history
  • Loading branch information
surunzi committed Sep 26, 2024
1 parent 3a14def commit f0908c1
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 7 deletions.
13 changes: 13 additions & 0 deletions devtools/target.html
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,19 @@
console.log('touch')
})
</script>
<div id="shadow1">
<template shadowrootmode="open">
<span>I'm in the shadow DOM</span>
</template>
</div>
<div id="shadow2"></div>
<script>
setTimeout(() => {
const shadow2 = document.getElementById('shadow2')
const shadow2Root = shadow2.attachShadow({ mode: 'closed' })
shadow2Root.innerHTML = "<span>I'm in the shadow DOM</span>"
}, 2000)
</script>
<div class="scroll">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus.
Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies
Expand Down
34 changes: 33 additions & 1 deletion src/domains/DOM.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,43 @@ export function copyTo(params: DOM.CopyToRequest): DOM.CopyToResponse {
}
}

let isEnable = false

export function enable() {
mutationObserver.observe()
isEnable = true

mutationObserver.disconnect()
mutationObserver.observe(document.documentElement)
nodeManager.clear()
}

function hookAttachShadow() {
const origAttachShadow = Element.prototype.attachShadow
if (origAttachShadow) {
Element.prototype.attachShadow = function (init) {
const shadowRoot = origAttachShadow.apply(this, [init])
if (!nodeManager.isValidNode(this)) {
return shadowRoot
}

;(this as any).__shadowRoot__ = shadowRoot
if (isEnable) {
mutationObserver.observe(shadowRoot)
const hostId = getNodeId(this)
if (hostId) {
connector.trigger('DOM.shadowRootPushed', {
hostId,
root: nodeManager.wrap(shadowRoot, { depth: 1 }),
})
}
}
return shadowRoot
}
}
}

hookAttachShadow()

export function getDocument() {
return {
root: nodeManager.wrap(document, {
Expand Down
10 changes: 5 additions & 5 deletions src/lib/mutationObserver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@ class Observer extends Emitter {
each(mutations, mutation => this.handleMutation(mutation))
})
}
observe() {
const { observer } = this

observer.disconnect()
observer.observe(document.documentElement, {
observe(node: Node) {
this.observer.observe(node, {
attributes: true,
childList: true,
characterData: true,
subtree: true,
})
}
disconnect() {
this.observer.disconnect()
}
private handleMutation(mutation: MutationRecord) {
if (mutation.type === 'attributes') {
this.emit('attributes', mutation.target, mutation.attributeName)
Expand Down
19 changes: 18 additions & 1 deletion src/lib/nodeManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,15 @@ export function wrap(node: any, { depth = 1 } = {}) {
ret.attributes = attributes
}

if (node.shadowRoot) {
ret.shadowRoots = [wrap(node.shadowRoot, { depth: 1 })]
} else if (node.__shadowRoot__) {
ret.shadowRoots = [wrap(node.__shadowRoot__, { depth: 1 })]
}
if (isShadowRoot(node)) {
ret.shadowRootType = node.mode || 'user-agent'
}

const childNodes = filterNodes(node.childNodes)
ret.childNodeCount = childNodes.length
const hasOneTextNode =
Expand Down Expand Up @@ -114,9 +123,17 @@ export function isValidNode(node: Node): boolean {
export function getNode(nodeId: number) {
const node = nodes.get(nodeId)

if (!node || node.nodeType === 10) {
if (!node || node.nodeType === 10 || node.nodeType === 11) {
throw createErr(-32000, 'Could not find node with given id')
}

return node
}

function isShadowRoot(node: any) {
if (window.ShadowRoot) {
return node instanceof ShadowRoot
}

return false
}

0 comments on commit f0908c1

Please sign in to comment.