add time to style events based on original dom event

This commit is contained in:
Swaathee Radhakrishnan
2024-04-15 11:43:09 -07:00
parent 4ebededa9f
commit 16d7d48a27
6 changed files with 29 additions and 23 deletions

View File

@@ -23,8 +23,8 @@ async function discover(): Promise<void> {
let timer: Timer = { id: id(), cost: Metric.LayoutCost };
task.start(timer);
await traverse(document, timer, Source.Discover);
checkDocumentStyles(document);
await traverse(document, timer, Source.Discover, ts);
checkDocumentStyles(document, ts);
await encode(Event.Discover, timer, ts);
task.stop(timer);
}

View File

@@ -129,19 +129,19 @@ async function process(): Promise<void> {
if (state === Task.Wait) { state = await task.suspend(timer); }
if (state === Task.Stop) { break; }
let target = mutation.target;
let type = track(mutation, timer, instance);
let type = track(mutation, timer, instance, record.time);
if (type && target && target.ownerDocument) { dom.parse(target.ownerDocument); }
if (type && target && target.nodeType == Node.DOCUMENT_FRAGMENT_NODE && (target as ShadowRoot).host) { dom.parse(target as ShadowRoot); }
switch (type) {
case Constant.Attributes:
processNode(target, Source.Attributes);
processNode(target, Source.Attributes, record.time);
break;
case Constant.CharacterData:
processNode(target, Source.CharacterData);
processNode(target, Source.CharacterData, record.time);
break;
case Constant.ChildList:
processNodeList(mutation.addedNodes, Source.ChildListAdd, timer);
processNodeList(mutation.removedNodes, Source.ChildListRemove, timer);
processNodeList(mutation.addedNodes, Source.ChildListAdd, timer, record.time);
processNodeList(mutation.removedNodes, Source.ChildListRemove, timer, record.time);
break;
case Constant.Suspend:
let value = dom.get(target);
@@ -156,7 +156,7 @@ async function process(): Promise<void> {
task.stop(timer);
}
function track(m: MutationRecord, timer: Timer, instance: number): string {
function track(m: MutationRecord, timer: Timer, instance: number, timestamp: number): string {
let value = m.target ? dom.get(m.target.parentNode) : null;
// Check if the parent is already discovered and that the parent is not the document root
if (value && value.data.tag !== Constant.HTML) {
@@ -172,7 +172,7 @@ function track(m: MutationRecord, timer: Timer, instance: number): string {
history[key] = key in history ? history[key] : [0, instance];
let h = history[key];
// Lookup any pending nodes queued up for removal, and process them now if we suspended a mutation before
if (inactive === false && h[0] >= Setting.MutationSuspendThreshold) { processNodeList(h[2], Source.ChildListRemove, timer); }
if (inactive === false && h[0] >= Setting.MutationSuspendThreshold) { processNodeList(h[2], Source.ChildListRemove, timer, timestamp); }
// Update the counter
h[0] = inactive ? (h[1] === instance ? h[0] : h[0] + 1) : 1;
h[1] = instance;
@@ -195,16 +195,16 @@ function names(nodes: NodeList): string {
return output.join();
}
async function processNodeList(list: NodeList, source: Source, timer: Timer): Promise<void> {
async function processNodeList(list: NodeList, source: Source, timer: Timer, timestamp: number): Promise<void> {
let length = list ? list.length : 0;
for (let i = 0; i < length; i++) {
if (source === Source.ChildListAdd) {
traverse(list[i], timer, source);
traverse(list[i], timer, source, timestamp);
} else {
let state = task.state(timer);
if (state === Task.Wait) { state = await task.suspend(timer); }
if (state === Task.Stop) { break; }
processNode(list[i], source);
processNode(list[i], source, timestamp);
}
}
}

View File

@@ -12,7 +12,7 @@ import { electron } from "@src/data/metadata";
const IGNORE_ATTRIBUTES = ["title", "alt", "onload", "onfocus", "onerror", "data-drupal-form-submit-last"];
const newlineRegex = /[\r\n]+/g;
export default function (node: Node, source: Source): Node {
export default function (node: Node, source: Source, timestamp: number): Node {
let child: Node = null;
// Do not track this change if we are attempting to remove a node before discovering it
@@ -43,7 +43,7 @@ export default function (node: Node, source: Source): Node {
// We check for regions in the beginning when discovering document and
// later whenever there are new additions or modifications to DOM (mutations)
if (node === document) dom.parse(document);
checkDocumentStyles(node as Document);
checkDocumentStyles(node as Document, timestamp);
observe(node);
break;
case Node.DOCUMENT_FRAGMENT_NODE:
@@ -67,7 +67,7 @@ export default function (node: Node, source: Source): Node {
// the same way we observe real shadow DOM nodes (encapsulation provided by the browser).
dom[call](node, shadowRoot.host, { tag: Constant.PolyfillShadowDomTag, attributes: {} }, source);
}
checkDocumentStyles(node as Document);
checkDocumentStyles(node as Document, timestamp);
}
break;
case Node.TEXT_NODE:

View File

@@ -14,6 +14,7 @@ let replaceSync: (text?: string) => void = null;
const styleSheetId = 'claritySheetId';
const styleSheetPageNum = 'claritySheetNum';
let styleSheetMap = {};
let styleTimeMap: {[key: string]: number} = {};
export function start(): void {
reset();
@@ -56,7 +57,8 @@ function bootStrapStyleSheet(styleSheet: CSSStyleSheet): void {
}
}
export function checkDocumentStyles(documentNode: Document): void {
export function checkDocumentStyles(documentNode: Document, timestamp: number): void {
timestamp = timestamp || time();
if (!documentNode?.adoptedStyleSheets) {
// if we don't have adoptedStyledSheets on the Node passed to us, we can short circuit.
return;
@@ -69,8 +71,8 @@ export function checkDocumentStyles(documentNode: Document): void {
if (styleSheet[styleSheetPageNum] !== pageNum) {
styleSheet[styleSheetPageNum] = pageNum;
styleSheet[styleSheetId] = shortid();
trackStyleChange(time(), styleSheet[styleSheetId], StyleSheetOperation.Create);
trackStyleChange(time(), styleSheet[styleSheetId], StyleSheetOperation.ReplaceSync, getCssRules(styleSheet));
trackStyleChange(timestamp, styleSheet[styleSheetId], StyleSheetOperation.Create);
trackStyleChange(timestamp, styleSheet[styleSheetId], StyleSheetOperation.ReplaceSync, getCssRules(styleSheet));
}
currentStyleSheets.push(styleSheet[styleSheetId]);
}
@@ -81,14 +83,16 @@ export function checkDocumentStyles(documentNode: Document): void {
}
if (!arraysEqual(currentStyleSheets, styleSheetMap[documentId])) {
// Using -1 to signify the root document node as we don't track that as part of our nodeMap
trackStyleAdoption(time(), documentNode == document ? -1 : getId(documentNode), StyleSheetOperation.SetAdoptedStyles, currentStyleSheets);
trackStyleAdoption(timestamp, documentNode == document ? -1 : getId(documentNode), StyleSheetOperation.SetAdoptedStyles, currentStyleSheets);
styleSheetMap[documentId] = currentStyleSheets;
styleTimeMap[documentId] = timestamp;
}
}
export function compute(): void {
checkDocumentStyles(document);
Object.keys(styleSheetMap).forEach((x) => checkDocumentStyles(getNode(parseInt(x, 10)) as Document));
let ts = -1 in styleTimeMap ? styleTimeMap[-1] : null;
checkDocumentStyles(document, ts);
Object.keys(styleSheetMap).forEach((x) => checkDocumentStyles(getNode(parseInt(x, 10)) as Document, styleTimeMap[x]));
}
export function reset(): void {
@@ -97,6 +101,7 @@ export function reset(): void {
export function stop(): void {
styleSheetMap = {};
styleTimeMap = {};
reset();
}

View File

@@ -3,7 +3,7 @@ import { Source } from "@clarity-types/layout";
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> {
export default async function(root: Node, timer: Timer, source: Source, timestamp: number): Promise<void> {
let queue = [root];
while (queue.length > 0) {
let entry = queue.shift();
@@ -22,7 +22,7 @@ export default async function(root: Node, timer: Timer, source: Source): Promise
// 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);
let subnode = node(entry, source, timestamp);
if (subnode) { queue.push(subnode); }
}
}

View File

@@ -185,6 +185,7 @@ export class Visualizer implements VisualizerType {
case Data.Event.StyleSheetAdoption:
case Data.Event.StyleSheetUpdate:
this.layout.styleChange(entry as Layout.StyleSheetEvent);
break;
case Data.Event.Animation:
this.layout.animateChange(entry as Layout.AnimationEvent);
break;