@vectojs/core 1.18.0 → 1.20.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/{chunk-XWBVBXFZ.mjs → chunk-TJCXB2F6.mjs} +18 -0
- package/dist/{chunk-IA3KW4CG.js → chunk-YLH7F4ZV.js} +43 -25
- package/dist/index.js +294 -170
- package/dist/index.mjs +126 -2
- package/dist/text.js +2 -2
- package/dist/text.mjs +1 -1
- package/dist/tree/Entity.d.ts +60 -0
- package/dist/tree/Scene.d.ts +66 -0
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
MSDFTextEntity,
|
|
14
14
|
SVGEntity,
|
|
15
15
|
VectoJSEvent
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-TJCXB2F6.mjs";
|
|
17
17
|
|
|
18
18
|
// src/tree/Scene.ts
|
|
19
19
|
import { SpringDriver, TweenDriver } from "@vectojs/animation";
|
|
@@ -1538,6 +1538,70 @@ var Scene = class _Scene {
|
|
|
1538
1538
|
renderMode = "always";
|
|
1539
1539
|
/** Cap on distinct recorded dirty reasons (see `recordDirtyReason`). */
|
|
1540
1540
|
static MAX_DIRTY_REASONS = 200;
|
|
1541
|
+
_phaseTiming = false;
|
|
1542
|
+
_phaseTotals = /* @__PURE__ */ new Map();
|
|
1543
|
+
/**
|
|
1544
|
+
* Start or stop per-phase render timing.
|
|
1545
|
+
*
|
|
1546
|
+
* Off by default, and the probes compile to a single boolean test when off:
|
|
1547
|
+
* these sit on the frame path, so the disabled cost has to be nothing. Enable,
|
|
1548
|
+
* run the scene, then read {@link renderPhases}.
|
|
1549
|
+
*
|
|
1550
|
+
* Exists because a frame total cannot tell you where the time went. The
|
|
1551
|
+
* markdown streaming benchmark put render at 85-99% of an append's cost, and
|
|
1552
|
+
* there was no way to decompose that number further — which is exactly the
|
|
1553
|
+
* position that led to two wrong optimisation guesses earlier
|
|
1554
|
+
* (`CodeBlock` reuse, hit-grid fusion), both of which measured as no change.
|
|
1555
|
+
*/
|
|
1556
|
+
setPhaseTiming(enabled) {
|
|
1557
|
+
this._phaseTiming = enabled;
|
|
1558
|
+
if (!enabled) this.clearRenderPhases();
|
|
1559
|
+
}
|
|
1560
|
+
/** Whether per-phase render timing is being recorded. */
|
|
1561
|
+
get phaseTiming() {
|
|
1562
|
+
return this._phaseTiming;
|
|
1563
|
+
}
|
|
1564
|
+
/**
|
|
1565
|
+
* Accumulate one phase sample.
|
|
1566
|
+
*
|
|
1567
|
+
* Totals rather than a per-frame log: the question is always "which phase owns
|
|
1568
|
+
* the frame", and a log of thousands of samples answers it less directly while
|
|
1569
|
+
* costing far more memory. `maxMs` is kept because a phase that is cheap on
|
|
1570
|
+
* average but spikes is a different problem from one that is uniformly slow.
|
|
1571
|
+
*/
|
|
1572
|
+
_recordPhase(phase, ms) {
|
|
1573
|
+
const existing = this._phaseTotals.get(phase);
|
|
1574
|
+
if (existing) {
|
|
1575
|
+
existing.totalMs += ms;
|
|
1576
|
+
existing.calls++;
|
|
1577
|
+
if (ms > existing.maxMs) existing.maxMs = ms;
|
|
1578
|
+
return;
|
|
1579
|
+
}
|
|
1580
|
+
this._phaseTotals.set(phase, { totalMs: ms, calls: 1, maxMs: ms });
|
|
1581
|
+
}
|
|
1582
|
+
/**
|
|
1583
|
+
* Recorded phase timings, most expensive first, with each phase's share of the
|
|
1584
|
+
* measured total.
|
|
1585
|
+
*
|
|
1586
|
+
* `share` is the number that matters: a phase at 4% cannot be worth optimising
|
|
1587
|
+
* however inefficient it looks in isolation.
|
|
1588
|
+
*/
|
|
1589
|
+
get renderPhases() {
|
|
1590
|
+
const entries = [...this._phaseTotals.entries()];
|
|
1591
|
+
const denominator = entries.filter(([phase]) => phase !== "render").reduce((sum, [, v]) => sum + v.totalMs, 0);
|
|
1592
|
+
return entries.map(([phase, v]) => ({
|
|
1593
|
+
phase,
|
|
1594
|
+
totalMs: +v.totalMs.toFixed(3),
|
|
1595
|
+
calls: v.calls,
|
|
1596
|
+
avgMs: +(v.totalMs / Math.max(1, v.calls)).toFixed(4),
|
|
1597
|
+
maxMs: +v.maxMs.toFixed(3),
|
|
1598
|
+
share: phase === "render" ? null : +(100 * v.totalMs / Math.max(1e-9, denominator)).toFixed(1)
|
|
1599
|
+
})).sort((a, b) => b.totalMs - a.totalMs);
|
|
1600
|
+
}
|
|
1601
|
+
/** Drop recorded phase timings, keeping timing enabled. */
|
|
1602
|
+
clearRenderPhases() {
|
|
1603
|
+
this._phaseTotals.clear();
|
|
1604
|
+
}
|
|
1541
1605
|
_dirtyTracking = false;
|
|
1542
1606
|
_dirtyReasons = /* @__PURE__ */ new Map();
|
|
1543
1607
|
dirty = true;
|
|
@@ -2834,6 +2898,20 @@ var Scene = class _Scene {
|
|
|
2834
2898
|
delete el.dataset.vectoGridCalibrationMs;
|
|
2835
2899
|
this.releaseContentSelectionForRebuild(el);
|
|
2836
2900
|
}
|
|
2901
|
+
/**
|
|
2902
|
+
* Drop any projected elements under `node` without touching the entity tree.
|
|
2903
|
+
*
|
|
2904
|
+
* Used when the walk reaches an invisible subtree: the entities stay put (a
|
|
2905
|
+
* later `show()` re-projects them), but nothing under here may remain
|
|
2906
|
+
* focusable or announced while hidden.
|
|
2907
|
+
*/
|
|
2908
|
+
pruneA11ySubtree(node) {
|
|
2909
|
+
if (this.a11yElements.has(node.id) || this.contentElements.has(node.id)) {
|
|
2910
|
+
this.removeA11yRecursively(node);
|
|
2911
|
+
return;
|
|
2912
|
+
}
|
|
2913
|
+
for (const child of node.children) this.pruneA11ySubtree(child);
|
|
2914
|
+
}
|
|
2837
2915
|
removeA11yRecursively(node) {
|
|
2838
2916
|
if (node.isDOMPortal) {
|
|
2839
2917
|
node.releaseDOMBindings();
|
|
@@ -3151,7 +3229,9 @@ var Scene = class _Scene {
|
|
|
3151
3229
|
step(dt) {
|
|
3152
3230
|
const time = this.lastTime + dt;
|
|
3153
3231
|
this.lastTime = time;
|
|
3232
|
+
const t0 = this._phaseTiming ? performance.now() : 0;
|
|
3154
3233
|
this.render(this.renderer, dt, time);
|
|
3234
|
+
if (this._phaseTiming) this._recordPhase("render", performance.now() - t0);
|
|
3155
3235
|
this.dirty = false;
|
|
3156
3236
|
}
|
|
3157
3237
|
/**
|
|
@@ -3286,6 +3366,10 @@ var Scene = class _Scene {
|
|
|
3286
3366
|
if (node.isDOMPortal) {
|
|
3287
3367
|
return;
|
|
3288
3368
|
}
|
|
3369
|
+
if (node.a11yHidden) {
|
|
3370
|
+
this.pruneA11ySubtree(node);
|
|
3371
|
+
return;
|
|
3372
|
+
}
|
|
3289
3373
|
if (this.shouldProjectA11y(node)) {
|
|
3290
3374
|
let el = this.a11yElements.get(node.id);
|
|
3291
3375
|
const attrs = node.getA11yAttributes();
|
|
@@ -3559,6 +3643,28 @@ var Scene = class _Scene {
|
|
|
3559
3643
|
"aria-level",
|
|
3560
3644
|
attrs.level === void 0 ? void 0 : String(attrs.level)
|
|
3561
3645
|
);
|
|
3646
|
+
this.syncOptionalAttribute(
|
|
3647
|
+
el,
|
|
3648
|
+
"aria-posinset",
|
|
3649
|
+
attrs.posInSet === void 0 ? void 0 : String(attrs.posInSet)
|
|
3650
|
+
);
|
|
3651
|
+
this.syncOptionalAttribute(
|
|
3652
|
+
el,
|
|
3653
|
+
"aria-setsize",
|
|
3654
|
+
attrs.setSize === void 0 ? void 0 : String(attrs.setSize)
|
|
3655
|
+
);
|
|
3656
|
+
this.syncOptionalAttribute(
|
|
3657
|
+
el,
|
|
3658
|
+
"aria-rowcount",
|
|
3659
|
+
attrs.rowCount === void 0 ? void 0 : String(attrs.rowCount)
|
|
3660
|
+
);
|
|
3661
|
+
this.syncOptionalAttribute(
|
|
3662
|
+
el,
|
|
3663
|
+
"aria-rowindex",
|
|
3664
|
+
attrs.rowIndex === void 0 ? void 0 : String(attrs.rowIndex)
|
|
3665
|
+
);
|
|
3666
|
+
this.syncOptionalAttribute(el, "aria-valuetext", attrs.valueText);
|
|
3667
|
+
this.syncOptionalAttribute(el, "aria-orientation", attrs.orientation);
|
|
3562
3668
|
if (attrs.value !== void 0) {
|
|
3563
3669
|
if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement) {
|
|
3564
3670
|
if (el.value !== attrs.value) {
|
|
@@ -4350,7 +4456,9 @@ var Scene = class _Scene {
|
|
|
4350
4456
|
}
|
|
4351
4457
|
this._lastRenderTick = time;
|
|
4352
4458
|
this._lastDt = dt;
|
|
4459
|
+
const phaseClock = this._phaseTiming ? performance.now() : 0;
|
|
4353
4460
|
this.render(this.renderer, dt, time);
|
|
4461
|
+
if (this._phaseTiming) this._recordPhase("render", performance.now() - phaseClock);
|
|
4354
4462
|
this._lastFrameMs = (typeof performance !== "undefined" ? performance.now() : time) - now;
|
|
4355
4463
|
this._renderedFrames++;
|
|
4356
4464
|
const hasActiveAnimation = this.frameHadAnimation;
|
|
@@ -4360,9 +4468,13 @@ var Scene = class _Scene {
|
|
|
4360
4468
|
if ((hasInteractive || this.a11yElements.size > 0 || wantsContentSync) && (shouldSyncInterval || this.a11yPendingSyncAfterAnimation)) {
|
|
4361
4469
|
this.lastA11ySync = time;
|
|
4362
4470
|
if (hasInteractive || wantsContentSync) {
|
|
4471
|
+
const t0 = this._phaseTiming ? performance.now() : 0;
|
|
4363
4472
|
this.syncA11y(this.root);
|
|
4473
|
+
if (this._phaseTiming) this._recordPhase("a11ySync", performance.now() - t0);
|
|
4364
4474
|
}
|
|
4475
|
+
const t1 = this._phaseTiming ? performance.now() : 0;
|
|
4365
4476
|
this.enforceA11yDomOrder();
|
|
4477
|
+
if (this._phaseTiming) this._recordPhase("a11yOrder", performance.now() - t1);
|
|
4366
4478
|
this.a11yPendingSyncAfterAnimation = hasActiveAnimation;
|
|
4367
4479
|
} else if (hasActiveAnimation) {
|
|
4368
4480
|
this.a11yPendingSyncAfterAnimation = true;
|
|
@@ -4536,7 +4648,9 @@ var Scene = class _Scene {
|
|
|
4536
4648
|
updateWalk(this.root);
|
|
4537
4649
|
for (const overlay of this.overlayRoot.children) updateWalk(overlay);
|
|
4538
4650
|
}
|
|
4651
|
+
const wasmT0 = this._phaseTiming ? performance.now() : 0;
|
|
4539
4652
|
const wasmWorld = wasmMain ? this._syncWasmStore() : null;
|
|
4653
|
+
if (this._phaseTiming) this._recordPhase("transform", performance.now() - wasmT0);
|
|
4540
4654
|
const wasmSlotEntity = this._slotEntity;
|
|
4541
4655
|
const renderNode = (node, pa, pb, pc, pd, pe, pf, parentOpacity) => {
|
|
4542
4656
|
if (isMainRenderer && !wasmMain) {
|
|
@@ -4666,7 +4780,13 @@ var Scene = class _Scene {
|
|
|
4666
4780
|
);
|
|
4667
4781
|
}
|
|
4668
4782
|
} else {
|
|
4669
|
-
|
|
4783
|
+
if (this._phaseTiming) {
|
|
4784
|
+
const t0 = performance.now();
|
|
4785
|
+
node.render(renderer);
|
|
4786
|
+
this._recordPhase("entityPaint", performance.now() - t0);
|
|
4787
|
+
} else {
|
|
4788
|
+
node.render(renderer);
|
|
4789
|
+
}
|
|
4670
4790
|
}
|
|
4671
4791
|
}
|
|
4672
4792
|
if (node.clipChildren) {
|
|
@@ -4678,20 +4798,24 @@ var Scene = class _Scene {
|
|
|
4678
4798
|
renderer.flush();
|
|
4679
4799
|
renderer.restore();
|
|
4680
4800
|
};
|
|
4801
|
+
const drawT0 = this._phaseTiming ? performance.now() : 0;
|
|
4681
4802
|
renderNode(this.root, 1, 0, 0, 1, 0, 0, 1);
|
|
4682
4803
|
for (const overlay of this.overlayRoot.children) {
|
|
4683
4804
|
renderNode(overlay, 1, 0, 0, 1, 0, 0, 1);
|
|
4684
4805
|
}
|
|
4806
|
+
if (this._phaseTiming) this._recordPhase("drawWalk", performance.now() - drawT0);
|
|
4685
4807
|
if (isMainRenderer) {
|
|
4686
4808
|
this.frameHadAnimation = walkHadAnimation;
|
|
4687
4809
|
this.frameHadInteractive = walkHadInteractive;
|
|
4688
4810
|
this.reconcilePortals();
|
|
4689
4811
|
}
|
|
4812
|
+
const flushT0 = this._phaseTiming ? performance.now() : 0;
|
|
4690
4813
|
renderer.flush();
|
|
4691
4814
|
if (isMainRenderer) {
|
|
4692
4815
|
this.pointRenderer?.flush();
|
|
4693
4816
|
}
|
|
4694
4817
|
renderer.present?.();
|
|
4818
|
+
if (this._phaseTiming) this._recordPhase("flush", performance.now() - flushT0);
|
|
4695
4819
|
if (this._devActive) {
|
|
4696
4820
|
this._devFrameCount++;
|
|
4697
4821
|
this._devRunChecks();
|
package/dist/text.js
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
var
|
|
5
|
+
var _chunkYLH7F4ZVjs = require('./chunk-YLH7F4ZV.js');
|
|
6
6
|
|
|
7
7
|
// src/text/index.ts
|
|
8
8
|
var _text = require('@vectojs/text'); _createStarExport(_text);
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
exports.MSDFTextEntity =
|
|
12
|
+
exports.MSDFTextEntity = _chunkYLH7F4ZVjs.MSDFTextEntity; exports.SVGEntity = _chunkYLH7F4ZVjs.SVGEntity;
|
package/dist/text.mjs
CHANGED
package/dist/tree/Entity.d.ts
CHANGED
|
@@ -221,6 +221,48 @@ export interface A11yAttributes {
|
|
|
221
221
|
/** `aria-invalid`: the field's current value fails validation. */
|
|
222
222
|
invalid?: boolean;
|
|
223
223
|
/** `aria-level`: hierarchical level (headings, tree items, etc.). */
|
|
224
|
+
/**
|
|
225
|
+
* Position within a set, 1-based — projected as `aria-posinset`.
|
|
226
|
+
*
|
|
227
|
+
* Required whenever the DOM contains only part of the set, which is exactly
|
|
228
|
+
* what virtualization produces: a list rendering rows 40-52 of 10,000 otherwise
|
|
229
|
+
* announces "item 3 of 12", because that is all the accessibility tree can see.
|
|
230
|
+
* Pair with {@link setSize}.
|
|
231
|
+
*/
|
|
232
|
+
posInSet?: number;
|
|
233
|
+
/**
|
|
234
|
+
* Total size of the set the element belongs to — projected as `aria-setsize`.
|
|
235
|
+
*
|
|
236
|
+
* `-1` is the ARIA-defined value for "unknown but non-empty", appropriate for a
|
|
237
|
+
* lazily loaded set whose total is not yet known.
|
|
238
|
+
*/
|
|
239
|
+
setSize?: number;
|
|
240
|
+
/**
|
|
241
|
+
* Total row count of a grid whose DOM holds only the visible rows — projected
|
|
242
|
+
* as `aria-rowcount`. Same rationale as {@link posInSet}: a virtualized table
|
|
243
|
+
* needs to state the real total, not the rendered one.
|
|
244
|
+
*/
|
|
245
|
+
rowCount?: number;
|
|
246
|
+
/** 1-based row index within the full grid — projected as `aria-rowindex`. */
|
|
247
|
+
rowIndex?: number;
|
|
248
|
+
/**
|
|
249
|
+
* Human-readable form of a range widget's current value — projected as
|
|
250
|
+
* `aria-valuetext`.
|
|
251
|
+
*
|
|
252
|
+
* A bare `aria-valuenow` is announced as a number out of context: "40" rather
|
|
253
|
+
* than "40 percent" or "Medium". Only set this when the number alone is
|
|
254
|
+
* genuinely ambiguous; a redundant valuetext makes announcements longer for no
|
|
255
|
+
* gain.
|
|
256
|
+
*/
|
|
257
|
+
valueText?: string;
|
|
258
|
+
/**
|
|
259
|
+
* Orientation of a composite widget — projected as `aria-orientation`.
|
|
260
|
+
*
|
|
261
|
+
* Worth setting when it differs from the role's default (`slider` and
|
|
262
|
+
* `separator` default horizontal; `listbox`, `menu`, `tree` default vertical),
|
|
263
|
+
* because it tells assistive technology which arrow keys to expect.
|
|
264
|
+
*/
|
|
265
|
+
orientation?: 'horizontal' | 'vertical';
|
|
224
266
|
level?: number;
|
|
225
267
|
/** `aria-modal`: marks a `role="dialog"` as modal so assistive tech confines
|
|
226
268
|
* reading to it. Set on a modal dialog's shell. */
|
|
@@ -374,6 +416,24 @@ export declare abstract class Entity {
|
|
|
374
416
|
* nodes, so on-top components stay clickable.
|
|
375
417
|
*/
|
|
376
418
|
a11yFullViewport: boolean;
|
|
419
|
+
/**
|
|
420
|
+
* Hide this entity AND its whole subtree from the accessibility/automation
|
|
421
|
+
* projection, regardless of each node's own `interactive` flag.
|
|
422
|
+
*
|
|
423
|
+
* For a container that is logically closed while still mounted — an `Overlay`
|
|
424
|
+
* after `hide()`, a collapsed panel kept in the tree for its transition. Setting
|
|
425
|
+
* `interactive = false` on the container alone is not enough: the projection walk
|
|
426
|
+
* still descends, and any still-interactive child is re-created on the next
|
|
427
|
+
* frame. Measured before this existed: after `Popover.hide()` the popover's own
|
|
428
|
+
* element was gone while its button stayed projected with `tabIndex: 0` and a
|
|
429
|
+
* live box, so a keyboard user could Tab into a hidden popover.
|
|
430
|
+
*
|
|
431
|
+
* Deliberately NOT inferred from `opacity`: `Overlay.hide()` springs opacity
|
|
432
|
+
* toward 0, so mid-transition it reads nonzero (~0.26 when measured) and an
|
|
433
|
+
* `=== 0` test never fires; a threshold would instead silently un-project a
|
|
434
|
+
* faint-but-live control.
|
|
435
|
+
*/
|
|
436
|
+
a11yHidden: boolean;
|
|
377
437
|
/**
|
|
378
438
|
* Clip this node's children to its local box (`[0,0]–[width,height]`) while
|
|
379
439
|
* rendering. Combined with translating a content child, this is how
|
package/dist/tree/Scene.d.ts
CHANGED
|
@@ -17,6 +17,27 @@ import { type CoreWasmRuntime } from '../wasm/runtime';
|
|
|
17
17
|
import { type HitModuleSource, type HitTestBackend } from '../wasm/hit-backend';
|
|
18
18
|
import { type AnimModuleSource, type AnimBackend } from '../wasm/anim-backend';
|
|
19
19
|
import { type ParticleModuleSource, type ParticleBackend } from '../wasm/particle-backend';
|
|
20
|
+
/**
|
|
21
|
+
* A timed phase of a frame.
|
|
22
|
+
*
|
|
23
|
+
* `render` is the ENCLOSING phase — it contains `transform`, `drawWalk` and
|
|
24
|
+
* `flush` — so it is reported without a share to avoid double-counting.
|
|
25
|
+
* `a11ySync` and `a11yOrder` run after `render` in the frame loop, so they are
|
|
26
|
+
* siblings of it, not children.
|
|
27
|
+
*/
|
|
28
|
+
export type RenderPhase = 'render' | 'transform' | 'drawWalk' | 'flush' | 'a11ySync' | 'a11yOrder'
|
|
29
|
+
/** Sum of every entity's own render(), nested inside drawWalk. */
|
|
30
|
+
| 'entityPaint';
|
|
31
|
+
export interface RenderPhaseEntry {
|
|
32
|
+
phase: RenderPhase;
|
|
33
|
+
totalMs: number;
|
|
34
|
+
calls: number;
|
|
35
|
+
avgMs: number;
|
|
36
|
+
/** Worst single sample — a spiky phase is a different problem from a slow one. */
|
|
37
|
+
maxMs: number;
|
|
38
|
+
/** Percent of the measured total, or `null` for the enclosing `render` phase. */
|
|
39
|
+
share: number | null;
|
|
40
|
+
}
|
|
20
41
|
/**
|
|
21
42
|
* Who marked the scene dirty, and why.
|
|
22
43
|
*
|
|
@@ -230,6 +251,43 @@ export declare class Scene {
|
|
|
230
251
|
renderMode: 'always' | 'onDemand';
|
|
231
252
|
/** Cap on distinct recorded dirty reasons (see `recordDirtyReason`). */
|
|
232
253
|
private static readonly MAX_DIRTY_REASONS;
|
|
254
|
+
private _phaseTiming;
|
|
255
|
+
private _phaseTotals;
|
|
256
|
+
/**
|
|
257
|
+
* Start or stop per-phase render timing.
|
|
258
|
+
*
|
|
259
|
+
* Off by default, and the probes compile to a single boolean test when off:
|
|
260
|
+
* these sit on the frame path, so the disabled cost has to be nothing. Enable,
|
|
261
|
+
* run the scene, then read {@link renderPhases}.
|
|
262
|
+
*
|
|
263
|
+
* Exists because a frame total cannot tell you where the time went. The
|
|
264
|
+
* markdown streaming benchmark put render at 85-99% of an append's cost, and
|
|
265
|
+
* there was no way to decompose that number further — which is exactly the
|
|
266
|
+
* position that led to two wrong optimisation guesses earlier
|
|
267
|
+
* (`CodeBlock` reuse, hit-grid fusion), both of which measured as no change.
|
|
268
|
+
*/
|
|
269
|
+
setPhaseTiming(enabled: boolean): void;
|
|
270
|
+
/** Whether per-phase render timing is being recorded. */
|
|
271
|
+
get phaseTiming(): boolean;
|
|
272
|
+
/**
|
|
273
|
+
* Accumulate one phase sample.
|
|
274
|
+
*
|
|
275
|
+
* Totals rather than a per-frame log: the question is always "which phase owns
|
|
276
|
+
* the frame", and a log of thousands of samples answers it less directly while
|
|
277
|
+
* costing far more memory. `maxMs` is kept because a phase that is cheap on
|
|
278
|
+
* average but spikes is a different problem from one that is uniformly slow.
|
|
279
|
+
*/
|
|
280
|
+
private _recordPhase;
|
|
281
|
+
/**
|
|
282
|
+
* Recorded phase timings, most expensive first, with each phase's share of the
|
|
283
|
+
* measured total.
|
|
284
|
+
*
|
|
285
|
+
* `share` is the number that matters: a phase at 4% cannot be worth optimising
|
|
286
|
+
* however inefficient it looks in isolation.
|
|
287
|
+
*/
|
|
288
|
+
get renderPhases(): RenderPhaseEntry[];
|
|
289
|
+
/** Drop recorded phase timings, keeping timing enabled. */
|
|
290
|
+
clearRenderPhases(): void;
|
|
233
291
|
private _dirtyTracking;
|
|
234
292
|
private _dirtyReasons;
|
|
235
293
|
private dirty;
|
|
@@ -779,6 +837,14 @@ export declare class Scene {
|
|
|
779
837
|
*/
|
|
780
838
|
add(entity: Entity): this;
|
|
781
839
|
private clearContentGridState;
|
|
840
|
+
/**
|
|
841
|
+
* Drop any projected elements under `node` without touching the entity tree.
|
|
842
|
+
*
|
|
843
|
+
* Used when the walk reaches an invisible subtree: the entities stay put (a
|
|
844
|
+
* later `show()` re-projects them), but nothing under here may remain
|
|
845
|
+
* focusable or announced while hidden.
|
|
846
|
+
*/
|
|
847
|
+
private pruneA11ySubtree;
|
|
782
848
|
private removeA11yRecursively;
|
|
783
849
|
/**
|
|
784
850
|
* If `el` is about to be removed from the DOM while it holds browser focus,
|