Skip to content

Commit

Permalink
Merge pull request #554 from microsoft/samart/slotHandling
Browse files Browse the repository at this point in the history
Samart/slot handling
  • Loading branch information
ender336 authored Mar 18, 2024
2 parents bfca871 + 3ec82ad commit 5f6aed7
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 31 deletions.
4 changes: 2 additions & 2 deletions packages/clarity-decode/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "clarity-decode",
"version": "0.7.24",
"version": "0.7.25",
"description": "An analytics library that uses web page interactions to generate aggregated insights",
"author": "Microsoft Corp.",
"license": "MIT",
Expand All @@ -26,7 +26,7 @@
"url": "https://github.com/Microsoft/clarity/issues"
},
"dependencies": {
"clarity-js": "^0.7.24"
"clarity-js": "^0.7.25"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^24.0.0",
Expand Down
8 changes: 4 additions & 4 deletions packages/clarity-devtools/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "clarity-devtools",
"version": "0.7.24",
"version": "0.7.25",
"private": true,
"description": "Adds Clarity debugging support to browser devtools",
"author": "Microsoft Corp.",
Expand All @@ -24,9 +24,9 @@
"url": "https://github.com/Microsoft/clarity/issues"
},
"dependencies": {
"clarity-decode": "^0.7.24",
"clarity-js": "^0.7.24",
"clarity-visualize": "^0.7.24"
"clarity-decode": "^0.7.25",
"clarity-js": "^0.7.25",
"clarity-visualize": "^0.7.25"
},
"devDependencies": {
"@rollup/plugin-node-resolve": "^15.0.0",
Expand Down
4 changes: 2 additions & 2 deletions packages/clarity-devtools/static/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
"manifest_version": 2,
"name": "Microsoft Clarity Developer Tools",
"description": "Clarity helps you understand how users are interacting with your website.",
"version": "0.7.24",
"version_name": "0.7.24",
"version": "0.7.25",
"version_name": "0.7.25",
"minimum_chrome_version": "50",
"devtools_page": "devtools.html",
"icons": {
Expand Down
2 changes: 1 addition & 1 deletion packages/clarity-js/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "clarity-js",
"version": "0.7.24",
"version": "0.7.25",
"description": "An analytics library that uses web page interactions to generate aggregated insights",
"author": "Microsoft Corp.",
"license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion packages/clarity-js/src/core/version.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
let version = "0.7.24";
let version = "0.7.25";
export default version;
6 changes: 6 additions & 0 deletions packages/clarity-js/src/layout/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,12 @@ export default function (node: Node, source: Source): Node {
// In some cases, external libraries like vue-fragment, can modify parentNode property to not be in sync with the DOM
// For correctness, we first look at parentElement and if it not present then fall back to using parentNode
parent = node.parentElement ? node.parentElement : (node.parentNode ? node.parentNode as HTMLElement : null);
// For HTML slots, the parentElement doesn't actually match what is rendered. If we have an assignedSlot, we use that
// as the parent to ensure our visualizations match the browser behavior for end users.
var slottedParent = (node as HTMLElement).assignedSlot;
if (slottedParent) {
parent = slottedParent;
}
// If we encounter a node that is part of SVG namespace, prefix the tag with SVG_PREFIX
if (element.namespaceURI === Constant.SvgNamespace) { tag = Constant.SvgPrefix + tag; }

Expand Down
54 changes: 35 additions & 19 deletions packages/clarity-js/src/layout/traverse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,41 @@ import * as task from "@src/core/task";
import node from "@src/layout/node";

export default async function(root: Node, timer: Timer, source: Source): Promise<void> {
let queue = [root];
while (queue.length > 0) {
let entry = queue.shift();
let next = entry.firstChild;

while (next) {
queue.push(next);
next = next.nextSibling;
let primaryQueue = [root];
let slottedNodesQueue: Node[] = [];
for (var currentQueue of [primaryQueue, slottedNodesQueue]) {
while (currentQueue.length > 0) {
let entry = currentQueue.shift();
let next = entry.firstChild;

while (next) {
// During traversal there is not a guarantee that the assigned child here is being found after the slot to which it is placed
// as the typical parent/child methods don't reflect what is rendered. We need to make sure all other mutations and
// discoveries are processed before we process a slotted element. Once we are processing the slottedNodesQueue we can
// skip this effort and go directly to our breadth first traversal.
if (currentQueue == primaryQueue) {
var slottedParent = (next as HTMLElement).assignedSlot;
if (slottedParent) {
slottedNodesQueue.push(next);
} else {
currentQueue.push(next);
}
} else {
currentQueue.push(next);
}
next = next.nextSibling;
}

// Check the status of current task to see if we should yield before continuing
let state = task.state(timer);
if (state === Task.Wait) { state = await task.suspend(timer); }
if (state === Task.Stop) { break; }

// Check if processing a node gives us a pointer to one of its sub nodes for traversal
// E.g. an element node may give us a pointer to traverse shadowDom if shadowRoot property is set
// Or, an iframe from the same origin could give a pointer to it's document for traversing contents of iframe.
let subnode = node(entry, source);
if (subnode) { currentQueue.push(subnode); }
}

// Check the status of current task to see if we should yield before continuing
let state = task.state(timer);
if (state === Task.Wait) { state = await task.suspend(timer); }
if (state === Task.Stop) { break; }

// Check if processing a node gives us a pointer to one of its sub nodes for traversal
// E.g. an element node may give us a pointer to traverse shadowDom if shadowRoot property is set
// Or, an iframe from the same origin could give a pointer to it's document for traversing contents of iframe.
let subnode = node(entry, source);
if (subnode) { queue.push(subnode); }
}
}
4 changes: 2 additions & 2 deletions packages/clarity-visualize/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "clarity-visualize",
"version": "0.7.24",
"version": "0.7.25",
"description": "An analytics library that uses web page interactions to generate aggregated insights",
"author": "Microsoft Corp.",
"license": "MIT",
Expand All @@ -27,7 +27,7 @@
"url": "https://github.com/Microsoft/clarity/issues"
},
"dependencies": {
"clarity-decode": "^0.7.24"
"clarity-decode": "^0.7.25"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^24.0.0",
Expand Down

0 comments on commit 5f6aed7

Please sign in to comment.