gesso-core 0.6.23 → 0.6.25

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/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # gesso-core
2
2
 
3
+ ## 0.6.25
4
+
5
+ ### Patch Changes
6
+
7
+ - A binding stamps its emissions with a clock read once per turn rather than once per emission. A window that connects thousands of bindings in a frame read the clock thousands of times to stamp the same frame; the age the inspector reports is still good to a frame.
8
+ - The text measurer's paragraph cache moves an entry to the recent end only once it has aged into the older half, instead of on every hit. A scrollbar drag through a sheet asks the cache about 500 times a frame, and moving the entry on every hit cost 4.5 ms of a 21 ms frame. Eviction still takes the least recently asked for.
9
+ - `LazySheet` takes `recycleRows`. Each row in view is mounted in a slot that outlives it and keyed by the slot, and the row renderer is told which slot it is in as a fourth argument. A row coming into view takes a slot a row leaving has just given up, so its node is reused; a renderer that keeps its cells by slot hands back the same elements, and the reconciler passes over them. A scrollbar drag through a long sheet used to build and tear down every cell on screen every frame; in gessosheet it now draws at a 4.9 ms median frame instead of 20 ms. Frozen rows are keyed by row as before, and a sheet without `recycleRows` is unchanged.
10
+
11
+ ## 0.6.24
12
+
3
13
  ## 0.6.23
4
14
 
5
15
  ### Patch Changes
@@ -36,9 +36,9 @@ var UiBinding = class {
36
36
  * the question they answer — "is this prop bound, to what, and is it
37
37
  * still emitting" — is asked *after* something has already gone
38
38
  * wrong, and a counter that only starts when the panel opens would
39
- * answer it about a different run. The cost is an increment and one
40
- * `performance.now()` per emission, against a write that already
41
- * walks the override cascade and marks a node dirty.
39
+ * answer it about a different run. The cost is an increment and a
40
+ * read of `turnNow`, against a write that already walks the override
41
+ * cascade and marks a node dirty.
42
42
  *
43
43
  * `emittedAt` is on the emitting thread's clock, which is why the
44
44
  * node report sends an age rather than the reading itself: a panel
@@ -55,7 +55,7 @@ var UiBinding = class {
55
55
  next: (value) => {
56
56
  this.currentValue = value;
57
57
  this.emissions++;
58
- this.lastEmittedAt = now();
58
+ this.lastEmittedAt = turnNow();
59
59
  this.graph.updateNodeProperty(this.node, this.property, value, this.dirtyFlags);
60
60
  },
61
61
  error: (error) => {
@@ -98,6 +98,28 @@ var UiBinding = class {
98
98
  function now() {
99
99
  return typeof performance === "undefined" ? Date.now() : performance.now();
100
100
  }
101
+ /** The clock as `turnNow` last read it, or -1 when it is to be read again. */
102
+ let turnTime = -1;
103
+ /**
104
+ * The clock, read once per turn of the event loop.
105
+ *
106
+ * `performance.now()` per emission was 6% of a scrollbar drag through a
107
+ * sheet: a window jump connects about five thousand bindings a frame and
108
+ * each emits at once, so the clock was read eleven thousand times to
109
+ * stamp the same frame. An age a panel reports is good to a turn, which
110
+ * is a frame at worst, so the first emission of a turn reads the clock
111
+ * and the rest share it.
112
+ */
113
+ function turnNow() {
114
+ if (turnTime < 0) {
115
+ turnTime = now();
116
+ queueMicrotask(forgetTurnTime);
117
+ }
118
+ return turnTime;
119
+ }
120
+ function forgetTurnTime() {
121
+ turnTime = -1;
122
+ }
101
123
  //#endregion
102
124
  //#region src/graph/DirtyFlags.ts
103
125
  let DirtyFlags = /* @__PURE__ */ function(DirtyFlags) {
@@ -3008,6 +3030,8 @@ function validateGradient(value) {
3008
3030
  }
3009
3031
  }
3010
3032
  if (placed !== 0 && placed !== stops.length) return `backgroundGradient: ${placed} of ${stops.length} stops carry an offset. Give every stop an offset, or none of them, in which case they spread evenly.`;
3033
+ const pixelOffsets = stops.map((stop) => stop.offset).filter((offset) => typeof offset === "number");
3034
+ if (pixelOffsets.length > 1 && pixelOffsets.every((offset) => offset >= 0 && offset <= 1)) return `backgroundGradient: the stop offsets ${pixelOffsets.join(", ")} all lie within 0 to 1, which reads as fractions, but a number is a pixel length along the ramp, so this gradient would be one pixel wide. Write a fraction as percent(45).`;
3011
3035
  if (gradient.kind === "radial") {
3012
3036
  const radial = gradient;
3013
3037
  for (const [name, offset] of [
@@ -7469,6 +7493,8 @@ var ParagraphLru = class {
7469
7493
  maxText;
7470
7494
  entries = /* @__PURE__ */ new Map();
7471
7495
  text = 0;
7496
+ /** Counts insertions, so an entry knows how far back in the map's order it sits. */
7497
+ tick = 0;
7472
7498
  constructor(maxEntries, maxText) {
7473
7499
  this.maxEntries = maxEntries;
7474
7500
  this.maxText = maxText;
@@ -7479,8 +7505,11 @@ var ParagraphLru = class {
7479
7505
  get(key) {
7480
7506
  const entry = this.entries.get(key);
7481
7507
  if (entry === void 0) return;
7482
- this.entries.delete(key);
7483
- this.entries.set(key, entry);
7508
+ if (this.tick - entry.at > this.entries.size / 2) {
7509
+ this.entries.delete(key);
7510
+ entry.at = ++this.tick;
7511
+ this.entries.set(key, entry);
7512
+ }
7484
7513
  return entry.paragraph;
7485
7514
  }
7486
7515
  set(key, paragraph, text) {
@@ -7496,7 +7525,8 @@ var ParagraphLru = class {
7496
7525
  }
7497
7526
  this.entries.set(key, {
7498
7527
  paragraph,
7499
- text
7528
+ text,
7529
+ at: ++this.tick
7500
7530
  });
7501
7531
  this.text += text;
7502
7532
  }
@@ -22581,4 +22611,4 @@ function createCanvasSurface(host) {
22581
22611
  //#endregion
22582
22612
  export { isImeKey as $, visualStatesEqual as $a, scaleSpacing as $i, spannedRunsFor as $n, transformIsIdentity as $r, registerFontStack as $t, withOverrideSource as A, UiBasicColors as Aa, noInsets as Ai, clearLinkHover as An, inheritedPropertyFlags as Ar, adjacentField as At, FlexDirection as B, findEnvironmentKey as Ba, withDensity as Bi, editorFor as Bn, isUiSemanticState as Br, createCanvasTextStyle as Bt, SCROLLBAR_LINGER_MS as C, spansDifferOnlyInPaint as Ca, normalizeBorderRadius as Ci, isNodeInert as Cn, resolveNumber as Cr, hasDrawnText as Ct, formatExplanation as D, colorsEqualPalette as Da, UiEnvironmentKeys as Di, isSubtreeInert as Dn, closestPropertyName as Dr, selectionRectsIn as Dt, formatConstraints as E, textStylesEqual as Ea, propertyValuesEqual as Ei, isPressable as En, resolveString as Er, paragraphGeometryFrom as Et, clampSize as F, normalizeColor as Fa, unknownContainerSize as Fi, setLinkHover as Fn, propertyValuesEqualByName as Fr, detectEditingPlatform as Ft, CrossAxisAlignment as G, overrideSources as Ga, themeExtensionsEqual as Gi, maskText as Gn, UI_SUBGRID_AXES as Gr, runFontString as Gt, placeGridItems as H, UiNode as Ha, hasThemeExtension as Hi, isEditableNode as Hn, statesEqual as Hr, fillTextRects as Ht, constraintsEqual as I, parseColor as Ia, darkTheme as Ii, CARET_BLINK_MS as In, UiProperties as Ir, isPrintable as It, parseCrossAxisAlignment as J, writeOverrideProperty as Ja, highContrastColors as Ji, resolveColorValue as Jn, paintValuesEqual as Jr, textRunBackgrounds as Jt, MainAxisAlignment as K, resetOverrideWarnings as Ka, withThemeExtension as Ki, nextCaretToggle as Kn, validateSubgrid as Kr, spanOf as Kt, tightenConstraints as L, rgb8 as La, lightTheme as Li, CARET_WIDTH as Ln, UI_ROLES as Lr, EditableLayout as Lt, contentOffset as M, colorToRgba as Ma, UiContainerSizeSource as Mi, linkHoverOf as Mn, propertyEffects as Mr, edgeField as Mt, LayoutRecord as N, colorValuesEqual as Na, bandOf as Ni, linkOf as Nn, propertyIsInherited as Nr, editingGroupOf as Nt, formatNumber as O, darkColors as Oa, UiInsetRegistry as Oi, pointerEventsOf as On, findPropertyDefinition as Or, wordRangeIn as Ot, Constraints as P, colorsEqual as Pa, containerBands as Pi, linkRunAtPointIn as Pn, propertyNarrowers as Pr, commandForKey as Pt, capturePointer as Q, visualState as Qa, defaultSpacing as Qi, ParagraphTextMeasurer as Qn, transform as Qr, fontStackFor as Qt, MAX_MEASURES_PER_CHILD as R, rgba as Ra, themesEqual as Ri, EDITOR_PROP as Rn, UI_SEMANTIC_STATES as Rr, applyCanvasTextStyle as Rt, SCROLLBAR_FADE_MS as S, spannedTextOf as Sa, borderRadiusValuesEqual as Si, isNodeHitTestable as Sn, resolveBoolean as Sr, UiInputDispatcher as St, describeOverrides as T, textSpansEqual as Ta, defineProperty as Ti, isNodeTabStop as Tn, resolvePropertyByName as Tr, paragraphGeometry as Tt, sizeGridTracks as U, DirtyNodeSet as Ua, noThemeExtensions as Ui, isMultiline as Un, validateRole as Ur, layoutTextLines as Ut, parseFlexDirection as V, UiEnvironment as Va, defineThemeExtension as Vi, editorOf as Vn, normalizeStates as Vr, drawText as Vt, AlignContent as W, clearOverrideProperty as Wa, themeExtension as Wi, isReadOnly as Wn, validateStates as Wr, runCanvasStyleInto as Wt, CanvasPlatformSurface as X, defaultVisualState as Xa, relativeLuminance as Xi, videoFrameSize as Xn, UiTransforms as Xr, bumpFontStack as Xt, parseMainAxisAlignment as Y, UiVisualState as Ya, raiseContrast as Yi, isVideoSurface as Yn, pathValuesEqual as Yr, textRunDecorations as Yt, UiPlatformAdapter as Z, hasVisualState as Za, densityFactors as Zi, CharacterCountTextMeasurer as Zn, parseTransform as Zr, clearFontStacks as Zt, LABEL_PADDING_X as _, editableSpansOf as _a, UiBorderRadiuses as _i, selectableTextNodes as _n, UiNodeType as _o, previousGraphemeStart as _r, scrollLeaderOf as _t, PaintPictureCache as a, boxShadow as aa, radialGradient as ai, computeObjectFitRect as an, UiGestureEvent as ao, lineIndexForOffset as ar, UiGestureRecognizer as at, snapScroll as b, resolvedSpansOf as ba, borderRadiusEqual as bi, setSelectionRange as bn, UiGraph as br, scrollbarThumbs as bt, EMPTY_RECORDING as c, boxShadowReach as ca, fr as ci, normalizeTextAlign as cn, UiPasteEvent as co, offsetAtX as cr, isScrollContainer as ct, tracePathData as d, isShapeName as da, isMinMaxTrack as di, TEXT_MATCHES_PROP as dn, UiSelectionChangeEvent as do, EditableTextModel as dr, UiFocusManager as dt, spacingEqual as ea, transformsEqual as ei, DEFAULT_FONT_FAMILY as en, MOUSE_POINTER as eo, ELLIPSIS as er, pointerDeviceOf as et, ScaledImageCache as f, shapesEqual as fa, isPercentLength as fi, clearMatchRanges as fn, UiTextChangeEvent as fo, graphemeBoundaries as fr, UiHitTester as ft, paintsAfterChildren as g, defaultTextStyle as ga, resolveLength as gi, clearSelectionRange as gn, wheelDeltaYOf as go, nextWordEnd as gr, SCROLLBAR_THICKNESS as gt, hasDecorationPhase as h, typographyEqual as ha, repeat as hi, TEXT_SELECTION_PROP as hn, noKeyModifiers as ho, nextGraphemeEnd as hr, SCROLLBAR_MIN_THUMB as ht, traceRoundedRect as i, BOX_SHADOW_BLUR_REACH as ia, linearGradient as ii, colorToCss as in, UiFocusEvent as io, lineIndexAtY as ir, UiTouchScroller as it, accumulatedOffsetTo as j, colorToHex as ja, observeViewportInsets as ji, hasTextLinks as jn, inheritedPropertyNames as jr, comparePositions as jt, labelNode as k, lightColors as ka, insetsEqual as ki, resolveCursor as kn, getPropertyNames as kr, textInputOf as kt, PaintRecorder as l, boxShadowsEqual as la, isAutoLength as li, normalizeVerticalAlign as ln, UiPinchEvent as lo, offsetForVerticalMove as lr, UiKeyboardController as lt, decorationRect as m, isTypographyRole as ma, percent as mi, setMatchRanges as mn, UiWheelEvent as mo, lineStartAt as mr, SCROLLBAR_INSET as mt, createCanvasSurface as n, defaultShadows as na, gradientPaint as ni, DEFAULT_FONT_WEIGHT as nn, UiCompositionEvent as no, proportionalFontMetrics as nr, touchActionFor as nt, paintPictures as o, boxShadowArraysEqual as oa, validateGradient as oi, createPaintState as on, UiInputEvent as oo, lineLimit as or, UiPinchRecognizer as ot, decorationColor as p, defaultTypography as pa, minmax as pi, matchRangesOf as pn, UiWheelDeltaMode as po, lineEndAt as pr, SCROLLBAR_HOVER_ZONE as pt, parseAlignContent as q, writeDeclaredProperty as qa, contrastRatio as qi, syncEditorValue as qn, inputsEqual as qr, textMeasureRequest as qt, Canvas2DRenderer as r, shadowsEqual as ra, gradientsEqual as ri, DEFAULT_TEXT_COLOR as rn, UiEventType as ro, caretRectFor as rr, UiEditingController as rt, PaintTarget as s, boxShadowRadius as sa, auto as si, isPaintVisible as sn, UiKeyboardEvent as so, offsetAtPoint as sr, UiWheelController as st, CanvasSurface as t, spacingSteps as ta, MAX_GRADIENT_STOPS as ti, DEFAULT_FONT_SIZE as tn, UiBeforeInputEvent as to, layoutParagraph as tr, prepareInputSurface as tt, replayPaint as u, defaultShapes as ua, isFrLength as ui, resolvePaintState as un, UiPointerEvent as uo, selectionRects as ur, UiPointerController as ut, drawOverlayShapes as v, flattenTextSpans as va, borderRadius as vi, selectableTextOf as vn, DirtyFlags as vo, previousWordStart as vr, scrollRange as vt, describeLength as w, textContentOf as wa, uniformBorderRadius as wi, isNodeSelectable as wn, resolveProperty as wr, offsetAtPointIn as wt, LayoutEngine as x, spanAtOffset as xa, borderRadiusIsZero as xi, isNodeFocusable as xn, DEFAULT_LINE_HEIGHT_FACTOR as xr, scrollbarZoneAt as xt, labelOrigin as y, hiddenRangesOf as ya, borderRadiusCorners as yi, selectionRangeOf as yn, UiBinding as yo, wordRangeAt as yr, scrollbarThumb as yt, isLayoutProtocol as z, createEnvironmentKey as za, withContrast as zi, caretVisibleAt as zn, isUiRole as zr, buildFontString as zt };
22583
22613
 
22584
- //# sourceMappingURL=CanvasSurface-D5QaKaWH.js.map
22614
+ //# sourceMappingURL=CanvasSurface-BZ-F5ASX.js.map