clarity-js 0.7.56 → 0.7.57

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  import { Priority, Task, Timer } from "@clarity-types/core";
2
2
  import { Code, Event, Metric, Severity } from "@clarity-types/data";
3
- import { Constant, MutationHistory, MutationQueue, Setting, Source } from "@clarity-types/layout";
3
+ import { Constant, MutationHistory, MutationRecordWithTime, MutationQueue, Setting, Source } from "@clarity-types/layout";
4
4
  import api from "@src/core/api";
5
5
  import * as core from "@src/core";
6
6
  import { bind } from "@src/core/event";
@@ -21,6 +21,7 @@ import config from "@src/core/config";
21
21
 
22
22
  let observers: MutationObserver[] = [];
23
23
  let mutations: MutationQueue[] = [];
24
+ let throttledMutations: { [key: number]: MutationRecordWithTime } = {};
24
25
  let insertRule: (rule: string, index?: number) => number = null;
25
26
  let deleteRule: (index?: number) => void = null;
26
27
  let attachShadow: (init: ShadowRootInit) => ShadowRoot = null;
@@ -28,6 +29,7 @@ let mediaInsertRule: (rule: string, index?: number) => number = null;
28
29
  let mediaDeleteRule: (index?: number) => void = null;
29
30
  let queue: Node[] = [];
30
31
  let timeout: number = null;
32
+ let throttleDelay: number = null;
31
33
  let activePeriod = null;
32
34
  let history: MutationHistory = {};
33
35
 
@@ -117,6 +119,7 @@ export function stop(): void {
117
119
  observers = [];
118
120
  history = {};
119
121
  mutations = [];
122
+ throttledMutations = [];
120
123
  queue = [];
121
124
  activePeriod = 0;
122
125
  timeout = null;
@@ -137,6 +140,30 @@ function handle(m: MutationRecord[]): void {
137
140
  });
138
141
  }
139
142
 
143
+ async function processMutation(timer: Timer, mutation: MutationRecord, instance: number, timestamp: number): Promise<void> {
144
+ let state = task.state(timer);
145
+ if (state === Task.Wait) { state = await task.suspend(timer); }
146
+ if (state === Task.Stop) { return; }
147
+ let target = mutation.target;
148
+ let type = config.throttleDom ? track(mutation, timer, instance, timestamp) : mutation.type;
149
+ if (type && target && target.ownerDocument) { dom.parse(target.ownerDocument); }
150
+ if (type && target && target.nodeType == Node.DOCUMENT_FRAGMENT_NODE && (target as ShadowRoot).host) { dom.parse(target as ShadowRoot); }
151
+ switch (type) {
152
+ case Constant.Attributes:
153
+ processNode(target, Source.Attributes, timestamp);
154
+ break;
155
+ case Constant.CharacterData:
156
+ processNode(target, Source.CharacterData, timestamp);
157
+ break;
158
+ case Constant.ChildList:
159
+ processNodeList(mutation.addedNodes, Source.ChildListAdd, timer, timestamp);
160
+ processNodeList(mutation.removedNodes, Source.ChildListRemove, timer, timestamp);
161
+ break;
162
+ case Constant.Throttle:
163
+ default:
164
+ break;
165
+ }
166
+ }
140
167
  async function process(): Promise<void> {
141
168
  let timer: Timer = { id: id(), cost: Metric.LayoutCost };
142
169
  task.start(timer);
@@ -144,34 +171,28 @@ async function process(): Promise<void> {
144
171
  let record = mutations.shift();
145
172
  let instance = time();
146
173
  for (let mutation of record.mutations) {
147
- let state = task.state(timer);
148
- if (state === Task.Wait) { state = await task.suspend(timer); }
149
- if (state === Task.Stop) { break; }
150
- let target = mutation.target;
151
- let type = config.throttleDom ? track(mutation, timer, instance, record.time) : mutation.type;
152
- if (type && target && target.ownerDocument) { dom.parse(target.ownerDocument); }
153
- if (type && target && target.nodeType == Node.DOCUMENT_FRAGMENT_NODE && (target as ShadowRoot).host) { dom.parse(target as ShadowRoot); }
154
- switch (type) {
155
- case Constant.Attributes:
156
- processNode(target, Source.Attributes, record.time);
157
- break;
158
- case Constant.CharacterData:
159
- processNode(target, Source.CharacterData, record.time);
160
- break;
161
- case Constant.ChildList:
162
- processNodeList(mutation.addedNodes, Source.ChildListAdd, timer, record.time);
163
- processNodeList(mutation.removedNodes, Source.ChildListRemove, timer, record.time);
164
- break;
165
- case Constant.Suspend:
166
- let value = dom.get(target);
167
- if (value) { value.metadata.suspend = true; }
168
- break;
169
- default:
170
- break;
171
- }
174
+ processMutation(timer, mutation, instance, record.time)
172
175
  }
173
176
  await encode(Event.Mutation, timer, record.time);
174
177
  }
178
+
179
+ let processedMutations = false;
180
+ for (var key of Object.keys(throttledMutations)) {
181
+ let throttledMutationToProcess: MutationRecordWithTime = throttledMutations[key];
182
+ delete throttledMutations[key];
183
+ processMutation(timer, throttledMutationToProcess.mutation, time(), throttledMutationToProcess.timestamp);
184
+ processedMutations = true;
185
+ }
186
+
187
+ if (Object.keys(throttledMutations).length > 0) {
188
+ processThrottledMutations();
189
+ }
190
+
191
+ // ensure we encode the previously throttled mutations once we have finished them
192
+ if (Object.keys(throttledMutations).length === 0 && processedMutations) {
193
+ await encode(Event.Mutation, timer, time());
194
+ }
195
+
175
196
  task.stop(timer);
176
197
  }
177
198
 
@@ -197,13 +218,16 @@ function track(m: MutationRecord, timer: Timer, instance: number, timestamp: num
197
218
  h[0] = inactive ? (h[1] === instance ? h[0] : h[0] + 1) : 1;
198
219
  h[1] = instance;
199
220
  // Return updated mutation type based on if we have already hit the threshold or not
200
- if (h[0] === Setting.MutationSuspendThreshold) {
221
+ if (h[0] >= Setting.MutationSuspendThreshold) {
201
222
  // Store a reference to removedNodes so we can process them later
202
223
  // when we resume mutations again on user interactions
203
224
  h[2] = m.removedNodes;
204
- return Constant.Suspend;
205
- } else if (h[0] > Setting.MutationSuspendThreshold) {
206
- return Constant.Empty;
225
+ if (instance > timestamp + Setting.MutationActivePeriod) {
226
+ return m.type;
227
+ }
228
+ // we only store the most recent mutation for a given key if it is being throttled
229
+ throttledMutations[key] = {mutation: m, timestamp};
230
+ return Constant.Throttle;
207
231
  }
208
232
  }
209
233
  return m.type;
@@ -229,6 +253,13 @@ async function processNodeList(list: NodeList, source: Source, timer: Timer, tim
229
253
  }
230
254
  }
231
255
 
256
+ function processThrottledMutations(): void {
257
+ if (throttleDelay) {
258
+ clearTimeout(throttleDelay);
259
+ }
260
+ throttleDelay = setTimeout(() => { task.schedule(process, Priority.High) }, Setting.LookAhead);
261
+ }
262
+
232
263
  export function schedule(node: Node): Node {
233
264
  // Only schedule manual trigger for this node if it's not already in the queue
234
265
  if (queue.indexOf(node) < 0) { queue.push(node); }
package/types/core.d.ts CHANGED
@@ -137,6 +137,7 @@ export interface Config {
137
137
  throttleDom?: boolean;
138
138
  conversions?: boolean;
139
139
  longTask?: number;
140
+ includeSubdomains?: boolean;
140
141
  }
141
142
 
142
143
  export const enum Constant {
package/types/layout.d.ts CHANGED
@@ -7,7 +7,8 @@ export const enum AnimationOperation {
7
7
  Play = 1,
8
8
  Pause = 2,
9
9
  Cancel = 3,
10
- Finish = 4
10
+ Finish = 4,
11
+ CommitStyles = 5
11
12
  }
12
13
 
13
14
  export const enum Source {
@@ -105,7 +106,7 @@ export const enum Constant {
105
106
  ChildList = "childList",
106
107
  Attributes = "attributes",
107
108
  CharacterData = "characterData",
108
- Suspend = "suspend",
109
+ Throttle = "throttle",
109
110
  LoadEvent = "load",
110
111
  Pixel = "px",
111
112
  BorderBox = "border-box",
@@ -217,6 +218,11 @@ export interface MutationQueue {
217
218
  mutations: MutationRecord[];
218
219
  }
219
220
 
221
+ export interface MutationRecordWithTime {
222
+ timestamp: number;
223
+ mutation: MutationRecord;
224
+ }
225
+
220
226
  export interface MutationHistory {
221
227
  [key: string]: [/* Count */ number, /* Instance */ number, /* Remove Nodes Buffer */ NodeList?];
222
228
  }