UNPKG

@atlaskit/editor-plugin-limited-mode

Version:

LimitedMode plugin for @atlaskit/editor-core

92 lines (90 loc) • 3.26 kB
import { isPerformanceAPIAvailable, isPerformanceObserverLongTaskAvailable } from '@atlaskit/editor-common/is-performance-api-available'; /** * Wires browser performance signals into the supplied {@link LatchPolicy}. * * Holds no configuration and makes no decisions: it measures, and forwards. Everything tunable lives * on the policy, including the clock it reads. * * The measurement mirrors `editor-plugin-base/src/pm-plugins/frozen-editor.ts`, which already runs an * identical `longtask` observer and per-keystroke rAF measurement for every session to feed * `ACTION.SLOW_INPUT` / `ACTION.BROWSER_FREEZE`. It is duplicated rather than shared so that this * experiment stays self-contained inside the limited-mode plugin — no new cross-plugin dependency, * and deleting it is a single-directory revert if the experiment does not ship. The marginal cost is * one `performance.now()` and one `requestAnimationFrame` per keystroke. */ export const createLatchDetector = ({ onLatchCriteriaMet, policy }) => { // One clock for the whole subsystem, so measured durations and the policy's windows agree. const now = policy.now; let observer; let destroyed = false; const handleEvaluation = evaluation => { if (evaluation !== 'latched') { return; } // One-way latch: the policy will never evaluate again, so stop paying for the observers. teardownObservers(); const details = policy.getLatchDetails(); if (details) { onLatchCriteriaMet(details); } }; function teardownObservers() { var _observer; (_observer = observer) === null || _observer === void 0 ? void 0 : _observer.disconnect(); observer = undefined; } if (isPerformanceObserverLongTaskAvailable()) { try { observer = new PerformanceObserver(list => { for (const entry of list.getEntries()) { if (policy.isLatched()) { return; } handleEvaluation(policy.recordLongTask(entry.duration)); } }); observer.observe({ entryTypes: ['longtask'] }); } catch { // `longtask` is unsupported in some browsers even when PerformanceObserver exists. The // latency criterion alone is still a valid trigger, so carry on without freeze detection. observer = undefined; } } return { noteDocumentChange: ({ nodeSizeDelta, isDocumentReplaced }) => { if (destroyed || policy.isLatched()) { return; } if (isDocumentReplaced || policy.isBulkChange(nodeSizeDelta)) { policy.suppress(); } }, measureInput: () => { if (destroyed || policy.isLatched() || !isPerformanceAPIAvailable()) { return; } const start = now(); // Runs after every handleTextInput and all resulting plugin work, but before paint — the // same measurement point frozen-editor uses, so the numbers are comparable to existing // SLOW_INPUT telemetry. requestAnimationFrame(() => { if (destroyed || policy.isLatched()) { return; } handleEvaluation(policy.recordInputLatency(now() - start)); }); }, destroy: () => { destroyed = true; teardownObservers(); } }; };