html2canvas-pro 2.1.0 → 2.2.0
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.
- package/dist/html2canvas-pro.esm.js +10226 -10526
- package/dist/html2canvas-pro.esm.js.map +1 -1
- package/dist/html2canvas-pro.js +10869 -11171
- package/dist/html2canvas-pro.js.map +1 -1
- package/dist/html2canvas-pro.min.js +8 -8
- package/dist/lib/config.js +0 -22
- package/dist/lib/core/cache-storage.js +3 -40
- package/dist/lib/core/constants.js +25 -0
- package/dist/lib/core/context.js +1 -0
- package/dist/lib/core/features.js +3 -2
- package/dist/lib/core/validator.js +3 -3
- package/dist/lib/css/grouped/background-styles.js +36 -0
- package/dist/lib/css/grouped/border-styles.js +75 -0
- package/dist/lib/css/grouped/font-styles.js +93 -0
- package/dist/lib/css/grouped/layout-styles.js +127 -0
- package/dist/lib/css/index.js +74 -46
- package/dist/lib/css/layout/text.js +7 -6
- package/dist/lib/css/property-descriptors/background-blend-mode.js +41 -0
- package/dist/lib/css/property-descriptors/border-image-repeat.js +42 -0
- package/dist/lib/css/property-descriptors/border-image-slice.js +45 -0
- package/dist/lib/css/property-descriptors/border-image-source.js +21 -0
- package/dist/lib/css/property-descriptors/border-radius.js +1 -1
- package/dist/lib/css/property-descriptors/box-decoration-break.js +18 -0
- package/dist/lib/css/property-descriptors/counter-increment.js +17 -12
- package/dist/lib/css/property-descriptors/counter-reset.js +4 -12
- package/dist/lib/css/property-descriptors/filter.js +76 -0
- package/dist/lib/css/property-descriptors/font-variant-ligatures.js +34 -0
- package/dist/lib/css/property-descriptors/object-fit.js +1 -1
- package/dist/lib/css/property-descriptors/object-position.js +42 -0
- package/dist/lib/css/property-descriptors/visibility.js +1 -1
- package/dist/lib/css/property-descriptors/zoom.js +18 -0
- package/dist/lib/css/syntax/parser.js +0 -1
- package/dist/lib/css/types/color.js +5 -1
- package/dist/lib/css/types/functions/repeating-linear-gradient.js +9 -0
- package/dist/lib/css/types/image.js +12 -2
- package/dist/lib/css/types/length-percentage.js +6 -2
- package/dist/lib/css/types/safe-eval.js +80 -0
- package/dist/lib/dom/document-cloner.js +23 -163
- package/dist/lib/dom/slot-cloner.js +176 -0
- package/dist/lib/index.js +1 -17
- package/dist/lib/render/canvas/background-renderer.js +169 -30
- package/dist/lib/render/canvas/border-image-renderer.js +153 -0
- package/dist/lib/render/canvas/canvas-renderer.js +39 -190
- package/dist/lib/render/canvas/content-renderer.js +202 -0
- package/dist/lib/render/canvas/effects-renderer.js +3 -0
- package/dist/lib/render/canvas/foreignobject-renderer.js +5 -1
- package/dist/lib/render/canvas/text/text-decoration-renderer.js +99 -0
- package/dist/lib/render/canvas/text-renderer.js +100 -224
- package/dist/lib/render/effects.js +38 -3
- package/dist/lib/render/object-fit.js +19 -15
- package/dist/lib/render/stacking-context.js +11 -0
- package/dist/types/config.d.ts +0 -10
- package/dist/types/core/cache-storage.d.ts +0 -24
- package/dist/types/core/constants.d.ts +22 -0
- package/dist/types/core/context.d.ts +3 -0
- package/dist/types/core/performance-monitor.d.ts +4 -4
- package/dist/types/core/validator.d.ts +6 -8
- package/dist/types/css/grouped/background-styles.d.ts +16 -0
- package/dist/types/css/grouped/border-styles.d.ts +31 -0
- package/dist/types/css/grouped/font-styles.d.ts +35 -0
- package/dist/types/css/grouped/layout-styles.d.ts +46 -0
- package/dist/types/css/index.d.ts +30 -0
- package/dist/types/css/property-descriptors/background-blend-mode.d.ts +23 -0
- package/dist/types/css/property-descriptors/border-image-repeat.d.ts +12 -0
- package/dist/types/css/property-descriptors/border-image-slice.d.ts +10 -0
- package/dist/types/css/property-descriptors/border-image-source.d.ts +4 -0
- package/dist/types/css/property-descriptors/box-decoration-break.d.ts +6 -0
- package/dist/types/css/property-descriptors/counter-increment.d.ts +3 -0
- package/dist/types/css/property-descriptors/filter.d.ts +3 -0
- package/dist/types/css/property-descriptors/font-variant-ligatures.d.ts +14 -0
- package/dist/types/css/property-descriptors/object-position.d.ts +4 -0
- package/dist/types/css/property-descriptors/zoom.d.ts +3 -0
- package/dist/types/css/types/functions/repeating-linear-gradient.d.ts +4 -0
- package/dist/types/css/types/image.d.ts +4 -2
- package/dist/types/css/types/safe-eval.d.ts +8 -0
- package/dist/types/dom/document-cloner.d.ts +3 -44
- package/dist/types/dom/slot-cloner.d.ts +66 -0
- package/dist/types/index.d.ts +3 -7
- package/dist/types/options.d.ts +11 -0
- package/dist/types/render/canvas/background-renderer.d.ts +23 -0
- package/dist/types/render/canvas/border-image-renderer.d.ts +18 -0
- package/dist/types/render/canvas/canvas-renderer.d.ts +1 -0
- package/dist/types/render/canvas/content-renderer.d.ts +44 -0
- package/dist/types/render/canvas/text/text-decoration-renderer.d.ts +18 -0
- package/dist/types/render/canvas/text-renderer.d.ts +12 -1
- package/dist/types/render/effects.d.ts +12 -2
- package/dist/types/render/object-fit.d.ts +2 -1
- package/dist/types/render/renderer-interface.d.ts +11 -9
- package/package.json +7 -20
- package/dist/lib/dom/replaced-elements/pseudo-elements.js +0 -0
- package/dist/lib/invariant.js +0 -9
- package/dist/types/dom/replaced-elements/pseudo-elements.d.ts +0 -0
- package/dist/types/invariant.d.ts +0 -1
- package/src/__tests__/index.ts +0 -99
- package/src/config.ts +0 -107
- package/src/core/__mocks__/cache-storage.ts +0 -1
- package/src/core/__mocks__/context.ts +0 -19
- package/src/core/__mocks__/features.ts +0 -8
- package/src/core/__mocks__/logger.ts +0 -17
- package/src/core/__tests__/cache-storage.test.ts +0 -205
- package/src/core/__tests__/cache-storage.ts +0 -278
- package/src/core/__tests__/logger.ts +0 -29
- package/src/core/__tests__/validator.ts +0 -359
- package/src/core/bitwise.ts +0 -1
- package/src/core/cache-storage.ts +0 -315
- package/src/core/context.ts +0 -31
- package/src/core/debugger.ts +0 -32
- package/src/core/features.ts +0 -222
- package/src/core/logger.ts +0 -64
- package/src/core/origin-checker.ts +0 -57
- package/src/core/performance-monitor.ts +0 -241
- package/src/core/render-element.ts +0 -272
- package/src/core/util.ts +0 -1
- package/src/core/validator.ts +0 -593
- package/src/css/index.ts +0 -427
- package/src/css/layout/__mocks__/bounds.ts +0 -6
- package/src/css/layout/bounds.ts +0 -79
- package/src/css/layout/text.ts +0 -161
- package/src/css/property-descriptor.ts +0 -49
- package/src/css/property-descriptors/__tests__/background-tests.ts +0 -65
- package/src/css/property-descriptors/__tests__/clip-path.test.ts +0 -280
- package/src/css/property-descriptors/__tests__/font-family.ts +0 -25
- package/src/css/property-descriptors/__tests__/image-rendering-integration.test.ts +0 -153
- package/src/css/property-descriptors/__tests__/image-rendering-performance.test.ts +0 -175
- package/src/css/property-descriptors/__tests__/image-rendering.test.ts +0 -72
- package/src/css/property-descriptors/__tests__/paint-order.ts +0 -87
- package/src/css/property-descriptors/__tests__/text-shadow.ts +0 -94
- package/src/css/property-descriptors/__tests__/transform-tests.ts +0 -18
- package/src/css/property-descriptors/background-clip.ts +0 -30
- package/src/css/property-descriptors/background-color.ts +0 -9
- package/src/css/property-descriptors/background-image.ts +0 -27
- package/src/css/property-descriptors/background-origin.ts +0 -31
- package/src/css/property-descriptors/background-position.ts +0 -38
- package/src/css/property-descriptors/background-repeat.ts +0 -44
- package/src/css/property-descriptors/background-size.ts +0 -27
- package/src/css/property-descriptors/border-color.ts +0 -13
- package/src/css/property-descriptors/border-radius.ts +0 -19
- package/src/css/property-descriptors/border-style.ts +0 -34
- package/src/css/property-descriptors/border-width.ts +0 -20
- package/src/css/property-descriptors/box-shadow.ts +0 -60
- package/src/css/property-descriptors/clip-path.ts +0 -271
- package/src/css/property-descriptors/color.ts +0 -9
- package/src/css/property-descriptors/content.ts +0 -26
- package/src/css/property-descriptors/counter-increment.ts +0 -43
- package/src/css/property-descriptors/counter-reset.ts +0 -36
- package/src/css/property-descriptors/direction.ts +0 -23
- package/src/css/property-descriptors/display.ts +0 -117
- package/src/css/property-descriptors/duration.ts +0 -14
- package/src/css/property-descriptors/float.ts +0 -29
- package/src/css/property-descriptors/font-family.ts +0 -38
- package/src/css/property-descriptors/font-size.ts +0 -9
- package/src/css/property-descriptors/font-style.ts +0 -25
- package/src/css/property-descriptors/font-variant.ts +0 -12
- package/src/css/property-descriptors/font-weight.ts +0 -26
- package/src/css/property-descriptors/image-rendering.ts +0 -33
- package/src/css/property-descriptors/letter-spacing.ts +0 -25
- package/src/css/property-descriptors/line-break.ts +0 -22
- package/src/css/property-descriptors/line-height.ts +0 -22
- package/src/css/property-descriptors/list-style-image.ts +0 -19
- package/src/css/property-descriptors/list-style-position.ts +0 -22
- package/src/css/property-descriptors/list-style-type.ts +0 -179
- package/src/css/property-descriptors/margin.ts +0 -13
- package/src/css/property-descriptors/mix-blend-mode.ts +0 -35
- package/src/css/property-descriptors/object-fit.ts +0 -39
- package/src/css/property-descriptors/opacity.ts +0 -15
- package/src/css/property-descriptors/overflow-wrap.ts +0 -22
- package/src/css/property-descriptors/overflow.ts +0 -34
- package/src/css/property-descriptors/padding.ts +0 -14
- package/src/css/property-descriptors/paint-order.ts +0 -42
- package/src/css/property-descriptors/position.ts +0 -30
- package/src/css/property-descriptors/quotes.ts +0 -57
- package/src/css/property-descriptors/rotate.ts +0 -34
- package/src/css/property-descriptors/text-align.ts +0 -26
- package/src/css/property-descriptors/text-decoration-color.ts +0 -9
- package/src/css/property-descriptors/text-decoration-line.ts +0 -38
- package/src/css/property-descriptors/text-decoration-style.ts +0 -32
- package/src/css/property-descriptors/text-decoration-thickness.ts +0 -30
- package/src/css/property-descriptors/text-overflow.ts +0 -23
- package/src/css/property-descriptors/text-shadow.ts +0 -52
- package/src/css/property-descriptors/text-transform.ts +0 -27
- package/src/css/property-descriptors/text-underline-offset.ts +0 -27
- package/src/css/property-descriptors/transform-origin.ts +0 -29
- package/src/css/property-descriptors/transform.ts +0 -74
- package/src/css/property-descriptors/visibility.ts +0 -25
- package/src/css/property-descriptors/webkit-line-clamp.ts +0 -30
- package/src/css/property-descriptors/webkit-text-stroke-color.ts +0 -8
- package/src/css/property-descriptors/webkit-text-stroke-width.ts +0 -15
- package/src/css/property-descriptors/word-break.ts +0 -25
- package/src/css/property-descriptors/writing-mode.ts +0 -37
- package/src/css/property-descriptors/z-index.ts +0 -27
- package/src/css/syntax/__tests__/tokernizer-tests.ts +0 -29
- package/src/css/syntax/parser.ts +0 -188
- package/src/css/syntax/tokenizer.ts +0 -822
- package/src/css/type-descriptor.ts +0 -7
- package/src/css/types/__tests__/color-tests.ts +0 -147
- package/src/css/types/__tests__/image-tests.ts +0 -239
- package/src/css/types/angle.ts +0 -86
- package/src/css/types/color-math.ts +0 -22
- package/src/css/types/color-spaces/a98.ts +0 -86
- package/src/css/types/color-spaces/p3.ts +0 -92
- package/src/css/types/color-spaces/pro-photo.ts +0 -87
- package/src/css/types/color-spaces/rec2020.ts +0 -90
- package/src/css/types/color-spaces/srgb.ts +0 -87
- package/src/css/types/color-utilities.ts +0 -452
- package/src/css/types/color.ts +0 -485
- package/src/css/types/functions/-prefix-linear-gradient.ts +0 -35
- package/src/css/types/functions/-prefix-radial-gradient.ts +0 -106
- package/src/css/types/functions/-webkit-gradient.ts +0 -69
- package/src/css/types/functions/__tests__/radial-gradient.ts +0 -69
- package/src/css/types/functions/counter.ts +0 -511
- package/src/css/types/functions/gradient.ts +0 -206
- package/src/css/types/functions/linear-gradient.ts +0 -28
- package/src/css/types/functions/radial-gradient.ts +0 -101
- package/src/css/types/image.ts +0 -120
- package/src/css/types/index.ts +0 -1
- package/src/css/types/length-percentage.ts +0 -137
- package/src/css/types/length.ts +0 -7
- package/src/css/types/time.ts +0 -20
- package/src/dom/__mocks__/document-cloner.ts +0 -22
- package/src/dom/__tests__/dom-normalizer.test.ts +0 -133
- package/src/dom/__tests__/element-container.test.ts +0 -129
- package/src/dom/document-cloner.ts +0 -929
- package/src/dom/dom-normalizer.ts +0 -133
- package/src/dom/element-container.ts +0 -75
- package/src/dom/elements/li-element-container.ts +0 -10
- package/src/dom/elements/ol-element-container.ts +0 -12
- package/src/dom/elements/select-element-container.ts +0 -10
- package/src/dom/elements/textarea-element-container.ts +0 -9
- package/src/dom/node-parser.ts +0 -177
- package/src/dom/node-type-guards.ts +0 -70
- package/src/dom/replaced-elements/canvas-element-container.ts +0 -15
- package/src/dom/replaced-elements/iframe-element-container.ts +0 -55
- package/src/dom/replaced-elements/image-element-container.ts +0 -16
- package/src/dom/replaced-elements/index.ts +0 -5
- package/src/dom/replaced-elements/input-element-container.ts +0 -105
- package/src/dom/replaced-elements/pseudo-elements.ts +0 -0
- package/src/dom/replaced-elements/svg-element-container.ts +0 -23
- package/src/dom/text-container.ts +0 -42
- package/src/global.d.ts +0 -19
- package/src/index.ts +0 -82
- package/src/invariant.ts +0 -5
- package/src/options.ts +0 -55
- package/src/render/__tests__/object-fit.test.ts +0 -85
- package/src/render/background.ts +0 -298
- package/src/render/bezier-curve.ts +0 -47
- package/src/render/border.ts +0 -165
- package/src/render/bound-curves.ts +0 -388
- package/src/render/box-sizing.ts +0 -31
- package/src/render/canvas/__tests__/background-renderer.test.ts +0 -72
- package/src/render/canvas/__tests__/border-renderer.test.ts +0 -24
- package/src/render/canvas/__tests__/effects-renderer.test.ts +0 -32
- package/src/render/canvas/__tests__/text-renderer.test.ts +0 -471
- package/src/render/canvas/background-renderer.ts +0 -271
- package/src/render/canvas/border-renderer.ts +0 -224
- package/src/render/canvas/canvas-path.ts +0 -31
- package/src/render/canvas/canvas-renderer.ts +0 -641
- package/src/render/canvas/effects-renderer.ts +0 -130
- package/src/render/canvas/foreignobject-renderer.ts +0 -53
- package/src/render/canvas/text-renderer.ts +0 -700
- package/src/render/effects.ts +0 -75
- package/src/render/font-metrics.ts +0 -72
- package/src/render/object-fit.ts +0 -100
- package/src/render/path.ts +0 -37
- package/src/render/renderer-interface.ts +0 -28
- package/src/render/stacking-context.ts +0 -386
- package/src/render/vector.ts +0 -19
package/src/core/context.ts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { Logger } from './logger';
|
|
2
|
-
import { Cache, ResourceOptions } from './cache-storage';
|
|
3
|
-
import { Bounds } from '../css/layout/bounds';
|
|
4
|
-
import { OriginChecker } from './origin-checker';
|
|
5
|
-
import { Html2CanvasConfig } from '../config';
|
|
6
|
-
|
|
7
|
-
export type ContextOptions = {
|
|
8
|
-
logging: boolean;
|
|
9
|
-
cache?: Cache;
|
|
10
|
-
} & ResourceOptions;
|
|
11
|
-
|
|
12
|
-
export class Context {
|
|
13
|
-
private readonly instanceName = `#${Context.instanceCount++}`;
|
|
14
|
-
readonly logger: Logger;
|
|
15
|
-
readonly cache: Cache;
|
|
16
|
-
readonly originChecker: OriginChecker;
|
|
17
|
-
readonly config: Html2CanvasConfig;
|
|
18
|
-
|
|
19
|
-
private static instanceCount = 1;
|
|
20
|
-
|
|
21
|
-
constructor(
|
|
22
|
-
options: ContextOptions,
|
|
23
|
-
public windowBounds: Bounds,
|
|
24
|
-
config: Html2CanvasConfig
|
|
25
|
-
) {
|
|
26
|
-
this.config = config;
|
|
27
|
-
this.logger = new Logger({ id: this.instanceName, enabled: options.logging });
|
|
28
|
-
this.originChecker = new OriginChecker(config.window);
|
|
29
|
-
this.cache = options.cache ?? config.cache ?? new Cache(this, options);
|
|
30
|
-
}
|
|
31
|
-
}
|
package/src/core/debugger.ts
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
const elementDebuggerAttribute = 'data-html2canvas-debug';
|
|
2
|
-
export const enum DebuggerType {
|
|
3
|
-
NONE,
|
|
4
|
-
ALL,
|
|
5
|
-
CLONE,
|
|
6
|
-
PARSE,
|
|
7
|
-
RENDER
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
const getElementDebugType = (element: Element): DebuggerType => {
|
|
11
|
-
if (typeof element.getAttribute !== 'function') {
|
|
12
|
-
return DebuggerType.NONE;
|
|
13
|
-
}
|
|
14
|
-
const attribute = element.getAttribute(elementDebuggerAttribute);
|
|
15
|
-
switch (attribute) {
|
|
16
|
-
case 'all':
|
|
17
|
-
return DebuggerType.ALL;
|
|
18
|
-
case 'clone':
|
|
19
|
-
return DebuggerType.CLONE;
|
|
20
|
-
case 'parse':
|
|
21
|
-
return DebuggerType.PARSE;
|
|
22
|
-
case 'render':
|
|
23
|
-
return DebuggerType.RENDER;
|
|
24
|
-
default:
|
|
25
|
-
return DebuggerType.NONE;
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
export const isDebugging = (element: Element, type: Omit<DebuggerType, DebuggerType.NONE>): boolean => {
|
|
30
|
-
const elementType = getElementDebugType(element);
|
|
31
|
-
return elementType === DebuggerType.ALL || type === elementType;
|
|
32
|
-
};
|
package/src/core/features.ts
DELETED
|
@@ -1,222 +0,0 @@
|
|
|
1
|
-
import { fromCodePoint, toCodePoints } from 'css-line-break';
|
|
2
|
-
|
|
3
|
-
const testRangeBounds = (document: Document) => {
|
|
4
|
-
const TEST_HEIGHT = 123;
|
|
5
|
-
|
|
6
|
-
if (document.createRange) {
|
|
7
|
-
const range = document.createRange();
|
|
8
|
-
if (range.getBoundingClientRect) {
|
|
9
|
-
const testElement = document.createElement('boundtest');
|
|
10
|
-
testElement.style.height = `${TEST_HEIGHT}px`;
|
|
11
|
-
testElement.style.display = 'block';
|
|
12
|
-
document.body.appendChild(testElement);
|
|
13
|
-
|
|
14
|
-
range.selectNode(testElement);
|
|
15
|
-
const rangeBounds = range.getBoundingClientRect();
|
|
16
|
-
const rangeHeight = Math.round(rangeBounds.height);
|
|
17
|
-
document.body.removeChild(testElement);
|
|
18
|
-
if (rangeHeight === TEST_HEIGHT) {
|
|
19
|
-
return true;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
return false;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
const testIOSLineBreak = (document: Document) => {
|
|
28
|
-
const testElement = document.createElement('boundtest');
|
|
29
|
-
testElement.style.width = '50px';
|
|
30
|
-
testElement.style.display = 'block';
|
|
31
|
-
testElement.style.fontSize = '12px';
|
|
32
|
-
testElement.style.letterSpacing = '0px';
|
|
33
|
-
testElement.style.wordSpacing = '0px';
|
|
34
|
-
document.body.appendChild(testElement);
|
|
35
|
-
const range = document.createRange();
|
|
36
|
-
|
|
37
|
-
testElement.innerHTML = typeof ''.repeat === 'function' ? '👨'.repeat(10) : '';
|
|
38
|
-
|
|
39
|
-
const node = testElement.firstChild as Text;
|
|
40
|
-
|
|
41
|
-
const textList = toCodePoints(node.data).map((i) => fromCodePoint(i));
|
|
42
|
-
let offset = 0;
|
|
43
|
-
let prev: DOMRect = {} as DOMRect;
|
|
44
|
-
|
|
45
|
-
// ios 13 does not handle range getBoundingClientRect line changes correctly #2177
|
|
46
|
-
const supports = textList.every((text, i) => {
|
|
47
|
-
range.setStart(node, offset);
|
|
48
|
-
range.setEnd(node, offset + text.length);
|
|
49
|
-
const rect = range.getBoundingClientRect();
|
|
50
|
-
|
|
51
|
-
offset += text.length;
|
|
52
|
-
const boundAhead = rect.x > prev.x || rect.y > prev.y;
|
|
53
|
-
|
|
54
|
-
prev = rect;
|
|
55
|
-
if (i === 0) {
|
|
56
|
-
return true;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
return boundAhead;
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
document.body.removeChild(testElement);
|
|
63
|
-
return supports;
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
const testCORS = (): boolean => typeof new Image().crossOrigin !== 'undefined';
|
|
67
|
-
|
|
68
|
-
const testResponseType = (): boolean => typeof new XMLHttpRequest().responseType === 'string';
|
|
69
|
-
|
|
70
|
-
const testSVG = (document: Document): boolean => {
|
|
71
|
-
const img = new Image();
|
|
72
|
-
const canvas = document.createElement('canvas');
|
|
73
|
-
const ctx = canvas.getContext('2d');
|
|
74
|
-
if (!ctx) {
|
|
75
|
-
return false;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
img.src = `data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'></svg>`;
|
|
79
|
-
|
|
80
|
-
try {
|
|
81
|
-
ctx.drawImage(img, 0, 0);
|
|
82
|
-
canvas.toDataURL();
|
|
83
|
-
} catch (e) {
|
|
84
|
-
return false;
|
|
85
|
-
}
|
|
86
|
-
return true;
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
const isGreenPixel = (data: Uint8ClampedArray): boolean =>
|
|
90
|
-
data[0] === 0 && data[1] === 255 && data[2] === 0 && data[3] === 255;
|
|
91
|
-
|
|
92
|
-
const testForeignObject = (document: Document): Promise<boolean> => {
|
|
93
|
-
const canvas = document.createElement('canvas');
|
|
94
|
-
const size = 100;
|
|
95
|
-
canvas.width = size;
|
|
96
|
-
canvas.height = size;
|
|
97
|
-
const ctx = canvas.getContext('2d');
|
|
98
|
-
if (!ctx) {
|
|
99
|
-
return Promise.reject(false);
|
|
100
|
-
}
|
|
101
|
-
ctx.fillStyle = 'rgb(0, 255, 0)';
|
|
102
|
-
ctx.fillRect(0, 0, size, size);
|
|
103
|
-
|
|
104
|
-
const img = new Image();
|
|
105
|
-
const greenImageSrc = canvas.toDataURL();
|
|
106
|
-
img.src = greenImageSrc;
|
|
107
|
-
const svg = createForeignObjectSVG(size, size, 0, 0, img);
|
|
108
|
-
ctx.fillStyle = 'red';
|
|
109
|
-
ctx.fillRect(0, 0, size, size);
|
|
110
|
-
|
|
111
|
-
return loadSerializedSVG(svg)
|
|
112
|
-
.then((img: HTMLImageElement) => {
|
|
113
|
-
ctx.drawImage(img, 0, 0);
|
|
114
|
-
const data = ctx.getImageData(0, 0, size, size).data;
|
|
115
|
-
ctx.fillStyle = 'red';
|
|
116
|
-
ctx.fillRect(0, 0, size, size);
|
|
117
|
-
|
|
118
|
-
const node = document.createElement('div');
|
|
119
|
-
node.style.backgroundImage = `url(${greenImageSrc})`;
|
|
120
|
-
node.style.height = `${size}px`;
|
|
121
|
-
// Firefox 55 does not render inline <img /> tags
|
|
122
|
-
return isGreenPixel(data)
|
|
123
|
-
? loadSerializedSVG(createForeignObjectSVG(size, size, 0, 0, node))
|
|
124
|
-
: Promise.reject(false);
|
|
125
|
-
})
|
|
126
|
-
.then((img: HTMLImageElement) => {
|
|
127
|
-
ctx.drawImage(img, 0, 0);
|
|
128
|
-
// Edge does not render background-images
|
|
129
|
-
return isGreenPixel(ctx.getImageData(0, 0, size, size).data);
|
|
130
|
-
})
|
|
131
|
-
.catch(() => false);
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
export const createForeignObjectSVG = (
|
|
135
|
-
width: number,
|
|
136
|
-
height: number,
|
|
137
|
-
x: number,
|
|
138
|
-
y: number,
|
|
139
|
-
node: Node
|
|
140
|
-
): SVGForeignObjectElement => {
|
|
141
|
-
const xmlns = 'http://www.w3.org/2000/svg';
|
|
142
|
-
const svg = document.createElementNS(xmlns, 'svg');
|
|
143
|
-
const foreignObject = document.createElementNS(xmlns, 'foreignObject');
|
|
144
|
-
svg.setAttributeNS(null, 'width', width.toString());
|
|
145
|
-
svg.setAttributeNS(null, 'height', height.toString());
|
|
146
|
-
|
|
147
|
-
foreignObject.setAttributeNS(null, 'width', '100%');
|
|
148
|
-
foreignObject.setAttributeNS(null, 'height', '100%');
|
|
149
|
-
foreignObject.setAttributeNS(null, 'x', x.toString());
|
|
150
|
-
foreignObject.setAttributeNS(null, 'y', y.toString());
|
|
151
|
-
foreignObject.setAttributeNS(null, 'externalResourcesRequired', 'true');
|
|
152
|
-
svg.appendChild(foreignObject);
|
|
153
|
-
|
|
154
|
-
foreignObject.appendChild(node);
|
|
155
|
-
|
|
156
|
-
return svg;
|
|
157
|
-
};
|
|
158
|
-
|
|
159
|
-
export const loadSerializedSVG = (svg: Node): Promise<HTMLImageElement> => {
|
|
160
|
-
return new Promise((resolve, reject) => {
|
|
161
|
-
const img = new Image();
|
|
162
|
-
img.onload = () => resolve(img);
|
|
163
|
-
img.onerror = reject;
|
|
164
|
-
|
|
165
|
-
img.src = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(new XMLSerializer().serializeToString(svg))}`;
|
|
166
|
-
});
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
export const FEATURES = {
|
|
170
|
-
get SUPPORT_RANGE_BOUNDS(): boolean {
|
|
171
|
-
'use strict';
|
|
172
|
-
const value = testRangeBounds(document);
|
|
173
|
-
Object.defineProperty(FEATURES, 'SUPPORT_RANGE_BOUNDS', { value });
|
|
174
|
-
return value;
|
|
175
|
-
},
|
|
176
|
-
get SUPPORT_WORD_BREAKING(): boolean {
|
|
177
|
-
'use strict';
|
|
178
|
-
const value = FEATURES.SUPPORT_RANGE_BOUNDS && testIOSLineBreak(document);
|
|
179
|
-
Object.defineProperty(FEATURES, 'SUPPORT_WORD_BREAKING', { value });
|
|
180
|
-
return value;
|
|
181
|
-
},
|
|
182
|
-
get SUPPORT_SVG_DRAWING(): boolean {
|
|
183
|
-
'use strict';
|
|
184
|
-
const value = testSVG(document);
|
|
185
|
-
Object.defineProperty(FEATURES, 'SUPPORT_SVG_DRAWING', { value });
|
|
186
|
-
return value;
|
|
187
|
-
},
|
|
188
|
-
get SUPPORT_FOREIGNOBJECT_DRAWING(): Promise<boolean> {
|
|
189
|
-
'use strict';
|
|
190
|
-
const value =
|
|
191
|
-
typeof Array.from === 'function' && typeof window.fetch === 'function'
|
|
192
|
-
? testForeignObject(document)
|
|
193
|
-
: Promise.resolve(false);
|
|
194
|
-
Object.defineProperty(FEATURES, 'SUPPORT_FOREIGNOBJECT_DRAWING', { value });
|
|
195
|
-
return value;
|
|
196
|
-
},
|
|
197
|
-
get SUPPORT_CORS_IMAGES(): boolean {
|
|
198
|
-
'use strict';
|
|
199
|
-
const value = testCORS();
|
|
200
|
-
Object.defineProperty(FEATURES, 'SUPPORT_CORS_IMAGES', { value });
|
|
201
|
-
return value;
|
|
202
|
-
},
|
|
203
|
-
get SUPPORT_RESPONSE_TYPE(): boolean {
|
|
204
|
-
'use strict';
|
|
205
|
-
const value = testResponseType();
|
|
206
|
-
Object.defineProperty(FEATURES, 'SUPPORT_RESPONSE_TYPE', { value });
|
|
207
|
-
return value;
|
|
208
|
-
},
|
|
209
|
-
get SUPPORT_CORS_XHR(): boolean {
|
|
210
|
-
'use strict';
|
|
211
|
-
const value = 'withCredentials' in new XMLHttpRequest();
|
|
212
|
-
Object.defineProperty(FEATURES, 'SUPPORT_CORS_XHR', { value });
|
|
213
|
-
return value;
|
|
214
|
-
},
|
|
215
|
-
get SUPPORT_NATIVE_TEXT_SEGMENTATION(): boolean {
|
|
216
|
-
'use strict';
|
|
217
|
-
|
|
218
|
-
const value = !!(typeof Intl !== 'undefined' && (Intl as any).Segmenter);
|
|
219
|
-
Object.defineProperty(FEATURES, 'SUPPORT_NATIVE_TEXT_SEGMENTATION', { value });
|
|
220
|
-
return value;
|
|
221
|
-
}
|
|
222
|
-
};
|
package/src/core/logger.ts
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
export interface LoggerOptions {
|
|
2
|
-
id: string;
|
|
3
|
-
enabled: boolean;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
export class Logger {
|
|
7
|
-
static instances: { [key: string]: Logger } = {};
|
|
8
|
-
|
|
9
|
-
private readonly id: string;
|
|
10
|
-
private readonly enabled: boolean;
|
|
11
|
-
private readonly start: number;
|
|
12
|
-
|
|
13
|
-
constructor({ id, enabled }: LoggerOptions) {
|
|
14
|
-
this.id = id;
|
|
15
|
-
this.enabled = enabled;
|
|
16
|
-
this.start = Date.now();
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
debug(...args: unknown[]): void {
|
|
20
|
-
if (this.enabled) {
|
|
21
|
-
// eslint-disable-next-line no-console
|
|
22
|
-
if (typeof window !== 'undefined' && window.console && typeof console.debug === 'function') {
|
|
23
|
-
// eslint-disable-next-line no-console
|
|
24
|
-
console.debug(this.id, `${this.getTime()}ms`, ...args);
|
|
25
|
-
} else {
|
|
26
|
-
this.info(...args);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
getTime(): number {
|
|
32
|
-
return Date.now() - this.start;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
info(...args: unknown[]): void {
|
|
36
|
-
if (this.enabled) {
|
|
37
|
-
// eslint-disable-next-line no-console
|
|
38
|
-
if (typeof window !== 'undefined' && window.console && typeof console.info === 'function') {
|
|
39
|
-
// eslint-disable-next-line no-console
|
|
40
|
-
console.info(this.id, `${this.getTime()}ms`, ...args);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
warn(...args: unknown[]): void {
|
|
46
|
-
if (this.enabled) {
|
|
47
|
-
if (typeof window !== 'undefined' && window.console && typeof console.warn === 'function') {
|
|
48
|
-
console.warn(this.id, `${this.getTime()}ms`, ...args);
|
|
49
|
-
} else {
|
|
50
|
-
this.info(...args);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
error(...args: unknown[]): void {
|
|
56
|
-
if (this.enabled) {
|
|
57
|
-
if (typeof window !== 'undefined' && window.console && typeof console.error === 'function') {
|
|
58
|
-
console.error(this.id, `${this.getTime()}ms`, ...args);
|
|
59
|
-
} else {
|
|
60
|
-
this.info(...args);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Origin Checker
|
|
3
|
-
*
|
|
4
|
-
* Provides origin checking functionality without global static state.
|
|
5
|
-
* Each instance maintains its own anchor element and origin reference.
|
|
6
|
-
*
|
|
7
|
-
* Replaces the static methods in CacheStorage with instance-based approach.
|
|
8
|
-
*/
|
|
9
|
-
export class OriginChecker {
|
|
10
|
-
private readonly link: HTMLAnchorElement;
|
|
11
|
-
private readonly origin: string;
|
|
12
|
-
|
|
13
|
-
constructor(window: Window) {
|
|
14
|
-
if (!window || !window.document) {
|
|
15
|
-
throw new Error('Valid window object required for OriginChecker');
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
if (!window.location || !window.location.href) {
|
|
19
|
-
throw new Error('Window object must have valid location');
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
this.link = window.document.createElement('a');
|
|
23
|
-
this.origin = this.getOrigin(window.location.href);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Get the origin (protocol + hostname + port) of a URL
|
|
28
|
-
*
|
|
29
|
-
* @param url - URL to parse
|
|
30
|
-
* @returns Origin string (e.g., "https://example.com:8080")
|
|
31
|
-
*/
|
|
32
|
-
getOrigin(url: string): string {
|
|
33
|
-
this.link.href = url;
|
|
34
|
-
// IE9 hack: accessing href twice to ensure it's properly parsed
|
|
35
|
-
this.link.href = this.link.href;
|
|
36
|
-
return this.link.protocol + this.link.hostname + this.link.port;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Check if a URL is from the same origin as the context
|
|
41
|
-
*
|
|
42
|
-
* @param src - URL to check
|
|
43
|
-
* @returns true if same origin, false otherwise
|
|
44
|
-
*/
|
|
45
|
-
isSameOrigin(src: string): boolean {
|
|
46
|
-
return this.getOrigin(src) === this.origin;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Get the current context origin
|
|
51
|
-
*
|
|
52
|
-
* @returns The origin of the context window
|
|
53
|
-
*/
|
|
54
|
-
getContextOrigin(): string {
|
|
55
|
-
return this.origin;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
@@ -1,241 +0,0 @@
|
|
|
1
|
-
import { Context } from './context';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Performance Metric
|
|
5
|
-
*
|
|
6
|
-
* Represents a single performance measurement
|
|
7
|
-
*/
|
|
8
|
-
export interface PerformanceMetric {
|
|
9
|
-
name: string;
|
|
10
|
-
startTime: number;
|
|
11
|
-
endTime?: number;
|
|
12
|
-
duration?: number;
|
|
13
|
-
metadata?: Record<string, any>;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Performance Summary
|
|
18
|
-
*
|
|
19
|
-
* Aggregated performance data
|
|
20
|
-
*/
|
|
21
|
-
export interface PerformanceSummary {
|
|
22
|
-
totalDuration: number;
|
|
23
|
-
metrics: PerformanceMetric[];
|
|
24
|
-
breakdown: Array<{
|
|
25
|
-
name: string;
|
|
26
|
-
duration: number;
|
|
27
|
-
percentage: string;
|
|
28
|
-
}>;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Performance Monitor
|
|
33
|
-
*
|
|
34
|
-
* Tracks performance metrics throughout the rendering pipeline.
|
|
35
|
-
* Provides insights into where time is spent during rendering.
|
|
36
|
-
*
|
|
37
|
-
* Usage:
|
|
38
|
-
* ```typescript
|
|
39
|
-
* const monitor = new PerformanceMonitor(context);
|
|
40
|
-
*
|
|
41
|
-
* monitor.start('clone');
|
|
42
|
-
* await cloneDocument();
|
|
43
|
-
* monitor.end('clone');
|
|
44
|
-
*
|
|
45
|
-
* const summary = monitor.getSummary();
|
|
46
|
-
* ```
|
|
47
|
-
*/
|
|
48
|
-
export class PerformanceMonitor {
|
|
49
|
-
private readonly activeMetrics: Map<string, PerformanceMetric> = new Map();
|
|
50
|
-
private readonly completedMetrics: PerformanceMetric[] = [];
|
|
51
|
-
private readonly enabled: boolean;
|
|
52
|
-
private readonly getTime: () => number;
|
|
53
|
-
|
|
54
|
-
constructor(
|
|
55
|
-
private readonly context: Context | null,
|
|
56
|
-
enabled: boolean = true
|
|
57
|
-
) {
|
|
58
|
-
this.enabled = enabled;
|
|
59
|
-
|
|
60
|
-
// Fallback for environments without performance.now()
|
|
61
|
-
this.getTime =
|
|
62
|
-
typeof performance !== 'undefined' && typeof performance.now === 'function'
|
|
63
|
-
? () => performance.now()
|
|
64
|
-
: () => Date.now();
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Start measuring a performance metric
|
|
69
|
-
*
|
|
70
|
-
* @param name - Unique name for this metric
|
|
71
|
-
* @param metadata - Optional metadata to attach
|
|
72
|
-
*/
|
|
73
|
-
start(name: string, metadata?: Record<string, any>): void {
|
|
74
|
-
if (!this.enabled) {
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
if (this.activeMetrics.has(name)) {
|
|
79
|
-
this.context?.logger.warn(`Performance metric '${name}' already started. Overwriting.`);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
this.activeMetrics.set(name, {
|
|
83
|
-
name,
|
|
84
|
-
startTime: this.getTime(),
|
|
85
|
-
metadata
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* End measuring a performance metric
|
|
91
|
-
*
|
|
92
|
-
* @param name - Name of the metric to end
|
|
93
|
-
* @returns The completed metric, or undefined if not found
|
|
94
|
-
*/
|
|
95
|
-
end(name: string): PerformanceMetric | undefined {
|
|
96
|
-
if (!this.enabled) {
|
|
97
|
-
return undefined;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const metric = this.activeMetrics.get(name);
|
|
101
|
-
|
|
102
|
-
if (!metric) {
|
|
103
|
-
this.context?.logger.warn(`Performance metric '${name}' not found. Was start() called?`);
|
|
104
|
-
return undefined;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
metric.endTime = this.getTime();
|
|
108
|
-
metric.duration = metric.endTime - metric.startTime;
|
|
109
|
-
|
|
110
|
-
this.completedMetrics.push(metric);
|
|
111
|
-
this.activeMetrics.delete(name);
|
|
112
|
-
|
|
113
|
-
this.context?.logger.debug(`⏱️ ${name}: ${metric.duration.toFixed(2)}ms`, metric.metadata);
|
|
114
|
-
|
|
115
|
-
return metric;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Measure a synchronous function
|
|
120
|
-
*
|
|
121
|
-
* @param name - Name for this measurement
|
|
122
|
-
* @param fn - Function to measure
|
|
123
|
-
* @param metadata - Optional metadata
|
|
124
|
-
* @returns The function's return value
|
|
125
|
-
*/
|
|
126
|
-
measure<T>(name: string, fn: () => T, metadata?: Record<string, any>): T {
|
|
127
|
-
this.start(name, metadata);
|
|
128
|
-
try {
|
|
129
|
-
const result = fn();
|
|
130
|
-
this.end(name);
|
|
131
|
-
return result;
|
|
132
|
-
} catch (error) {
|
|
133
|
-
this.end(name);
|
|
134
|
-
throw error;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Measure an asynchronous function
|
|
140
|
-
*
|
|
141
|
-
* @param name - Name for this measurement
|
|
142
|
-
* @param fn - Async function to measure
|
|
143
|
-
* @param metadata - Optional metadata
|
|
144
|
-
* @returns Promise resolving to the function's return value
|
|
145
|
-
*/
|
|
146
|
-
async measureAsync<T>(name: string, fn: () => Promise<T>, metadata?: Record<string, any>): Promise<T> {
|
|
147
|
-
this.start(name, metadata);
|
|
148
|
-
try {
|
|
149
|
-
const result = await fn();
|
|
150
|
-
this.end(name);
|
|
151
|
-
return result;
|
|
152
|
-
} catch (error) {
|
|
153
|
-
this.end(name);
|
|
154
|
-
throw error;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* Get all completed metrics
|
|
160
|
-
*
|
|
161
|
-
* @returns Array of completed performance metrics
|
|
162
|
-
*/
|
|
163
|
-
getMetrics(): PerformanceMetric[] {
|
|
164
|
-
return [...this.completedMetrics];
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* Get a specific metric by name
|
|
169
|
-
*
|
|
170
|
-
* @param name - Metric name
|
|
171
|
-
* @returns The metric, or undefined if not found
|
|
172
|
-
*/
|
|
173
|
-
getMetric(name: string): PerformanceMetric | undefined {
|
|
174
|
-
return this.completedMetrics.find((m) => m.name === name);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Get performance summary
|
|
179
|
-
*
|
|
180
|
-
* @returns Aggregated performance data
|
|
181
|
-
*/
|
|
182
|
-
getSummary(): PerformanceSummary {
|
|
183
|
-
const totalDuration = this.completedMetrics.reduce((sum, metric) => sum + (metric.duration || 0), 0);
|
|
184
|
-
|
|
185
|
-
const breakdown = this.completedMetrics.map((metric) => ({
|
|
186
|
-
name: metric.name,
|
|
187
|
-
duration: metric.duration || 0,
|
|
188
|
-
percentage: totalDuration > 0 ? (((metric.duration || 0) / totalDuration) * 100).toFixed(1) + '%' : '0%'
|
|
189
|
-
}));
|
|
190
|
-
|
|
191
|
-
return {
|
|
192
|
-
totalDuration,
|
|
193
|
-
metrics: this.getMetrics(),
|
|
194
|
-
breakdown
|
|
195
|
-
};
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* Log performance summary to console
|
|
200
|
-
*/
|
|
201
|
-
logSummary(): void {
|
|
202
|
-
if (!this.enabled || this.completedMetrics.length === 0 || !this.context) {
|
|
203
|
-
return;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
const summary = this.getSummary();
|
|
207
|
-
|
|
208
|
-
this.context.logger.info(`\n📊 Performance Summary (Total: ${summary.totalDuration.toFixed(2)}ms):`);
|
|
209
|
-
|
|
210
|
-
summary.breakdown
|
|
211
|
-
.sort((a, b) => b.duration - a.duration)
|
|
212
|
-
.forEach((item) => {
|
|
213
|
-
this.context!.logger.info(
|
|
214
|
-
` ${item.name.padEnd(20)} ${item.duration.toFixed(2).padStart(8)}ms ${item.percentage.padStart(6)}`
|
|
215
|
-
);
|
|
216
|
-
});
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
/**
|
|
220
|
-
* Clear all metrics
|
|
221
|
-
*/
|
|
222
|
-
clear(): void {
|
|
223
|
-
this.activeMetrics.clear();
|
|
224
|
-
this.completedMetrics.splice(0);
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* Check if monitoring is enabled
|
|
229
|
-
*/
|
|
230
|
-
isEnabled(): boolean {
|
|
231
|
-
return this.enabled;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
/**
|
|
235
|
-
* Get active (uncompleted) metrics
|
|
236
|
-
* Useful for debugging leaked measurements
|
|
237
|
-
*/
|
|
238
|
-
getActiveMetrics(): string[] {
|
|
239
|
-
return Array.from(this.activeMetrics.keys());
|
|
240
|
-
}
|
|
241
|
-
}
|