uicore-ts 1.1.310 → 1.1.312

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/scripts/UIView.ts CHANGED
@@ -6,6 +6,7 @@ import "./UICoreExtensions"
6
6
  import type { UIDialogView } from "./UIDialogView"
7
7
  import { UILocalizedTextObject } from "./UIInterfaces"
8
8
  import { UILayoutCycleTracer } from "./UILayoutCycleTracer"
9
+ import { UILayoutDebugger } from "./UILayoutDebugger"
9
10
  import {
10
11
  FIRST,
11
12
  FIRST_OR_NIL,
@@ -2033,6 +2034,7 @@ export class UIView extends UIObject {
2033
2034
  }
2034
2035
 
2035
2036
  window.UILayoutCycleTracer?.willBeginLayoutPass()
2037
+ window.UILayoutDebugger?.willBeginLayoutPass(UIView._viewsToLayout)
2036
2038
 
2037
2039
  const maxIterations = 10
2038
2040
  let iteration = 0
@@ -2041,6 +2043,7 @@ export class UIView extends UIObject {
2041
2043
  while (UIView._viewsToLayout.length > 0 && iteration < maxIterations) {
2042
2044
 
2043
2045
  window.UILayoutCycleTracer?.willBeginIteration(iteration)
2046
+ window.UILayoutDebugger?.willBeginIteration(iteration)
2044
2047
 
2045
2048
  const viewsToProcess = UIView._viewsToLayout
2046
2049
  UIView._viewsToLayout = []
@@ -2069,15 +2072,21 @@ export class UIView extends UIObject {
2069
2072
 
2070
2073
  for (let i = 0; i < sortedViews.length; i++) {
2071
2074
  const view = sortedViews[i]
2075
+ window.UILayoutDebugger?.willLayoutView(view)
2076
+ if (window.UILayoutDebugger?._shouldHitBreakpoint(view)) {
2077
+ const breakpointOnThisLine = "Add a breakpoint on this line to step through layout."
2078
+ }
2072
2079
  view.layoutIfNeeded()
2073
2080
  layoutCounts.set(view, (layoutCounts.get(view) || 0) + 1)
2074
2081
  window.UILayoutCycleTracer?.didLayoutView(view)
2082
+ window.UILayoutDebugger?.didLayoutView(view)
2075
2083
  }
2076
2084
 
2077
2085
  iteration++
2078
2086
  }
2079
2087
 
2080
2088
  window.UILayoutCycleTracer?.didFinishLayoutPass(iteration)
2089
+ window.UILayoutDebugger?.didFinishLayoutPass(iteration)
2081
2090
 
2082
2091
  // console.log(iteration + " iterations to finish layout")
2083
2092
 
@@ -2097,6 +2106,7 @@ export class UIView extends UIObject {
2097
2106
  this.clearIntrinsicSizeCache()
2098
2107
 
2099
2108
  window.UILayoutCycleTracer?.viewDidCallSetNeedsLayout(this)
2109
+ window.UILayoutDebugger?.viewDidCallSetNeedsLayout(this)
2100
2110
 
2101
2111
  // // Auto-propagate if intrinsic height changed
2102
2112
  // if (IS(this.superview) && this.superview.usesVirtualLayoutingForIntrinsicSizing) {
@@ -2133,7 +2143,7 @@ export class UIView extends UIObject {
2133
2143
 
2134
2144
  try {
2135
2145
 
2136
- if (this.bounds.width < 0) {
2146
+ if (this.bounds.width < 0 || (!this.isVirtualLayouting && !this.isMemberOfViewTree)) {
2137
2147
  return
2138
2148
  }
2139
2149
 
@@ -2167,12 +2177,14 @@ export class UIView extends UIObject {
2167
2177
 
2168
2178
  this.applyClassesAndStyles()
2169
2179
 
2180
+ window.UILayoutDebugger?.willSetSubviewFrames(this)
2170
2181
  for (let i = 0; i < this.subviews?.length; i++) {
2171
2182
 
2172
2183
  const subview = this.subviews[i]
2173
2184
  subview.calculateAndSetViewFrame()
2174
2185
 
2175
2186
  }
2187
+ window.UILayoutDebugger?.didSetSubviewFrames(this)
2176
2188
 
2177
2189
  // if (this._loadingView && this._loadingView.superview == this) {
2178
2190
  // this._loadingView.setFrame(this.bounds)
@@ -4111,9 +4123,11 @@ export class UIView extends UIObject {
4111
4123
  UIView._sharedIntrinsicSizeCaches.set(this.sharedIntrinsicSizeCacheIdentifier, bucket)
4112
4124
  }
4113
4125
  bucket[cacheKey] = size.copy()
4126
+ window.UILayoutDebugger?.didSetCachedIntrinsicSize(this, cacheKey, size)
4114
4127
  return
4115
4128
  }
4116
4129
  this._intrinsicSizesCache[cacheKey] = size.copy()
4130
+ window.UILayoutDebugger?.didSetCachedIntrinsicSize(this, cacheKey, size)
4117
4131
  }
4118
4132
 
4119
4133
  // clearIntrinsicSizeCache(): void {
@@ -4363,6 +4377,66 @@ export class UIView extends UIObject {
4363
4377
  }
4364
4378
 
4365
4379
 
4380
+ /**
4381
+ * ⚠️ NUCLEAR OPTION — DO NOT CALL IN NORMAL CODE ⚠️
4382
+ *
4383
+ * Performs a full-scorched-earth cache purge across the entire view subtree rooted
4384
+ * at `this`, then drives an immediate synchronous layout pass, as if the app had
4385
+ * just cold-started.
4386
+ *
4387
+ * What gets destroyed:
4388
+ * • Every per-instance intrinsic-size cache entry (`_intrinsicSizesCache`)
4389
+ * • Every shared intrinsic-size cache bucket (`UIView._sharedIntrinsicSizeCaches`)
4390
+ * • Every frame cache (`_frameCache`) and virtual-layout frame cache
4391
+ * (`_frameCacheForVirtualLayouting`) on every view in the subtree
4392
+ * • Every UITextMeasurement style cache (canvas glyph metrics,
4393
+ * computed-style snapshots, etc.)
4394
+ *
4395
+ * After the purge every view in the subtree is unconditionally marked dirty via
4396
+ * `setNeedsLayout()`, then `UIView.layoutViewsIfNeeded()` is called immediately
4397
+ * to flush the queue rather than waiting for the next rAF tick.
4398
+ *
4399
+ * Legitimate uses (exhaustive list):
4400
+ * - Recovery from a confirmed cache-corruption bug while a proper fix ships
4401
+ * - Test harness reset between isolated rendering assertions
4402
+ * - Post-hot-module-replacement refresh in development tooling
4403
+ *
4404
+ * Do NOT use this to fix a layout glitch you don't understand.
4405
+ * Fix the root cause instead. If you find yourself calling this in production
4406
+ * code for any reason other than the above, that is a bug — file it.
4407
+ *
4408
+ * Complexity: O(n) where n = total views in the subtree.
4409
+ * All shared caches are wiped globally, not just for the subtree.
4410
+ */
4411
+ performForcedSubtreeLayout(): void {
4412
+
4413
+ // 1. Nuke all text measurement caches globally — these are shared across
4414
+ // the entire document and cannot be scoped to a subtree.
4415
+ UITextMeasurement.clearCaches()
4416
+
4417
+ // 2. Wipe all shared intrinsic-size cache buckets globally. These are
4418
+ // keyed by sharedIntrinsicSizeCacheIdentifier and may be shared across
4419
+ // views outside this subtree, but stale global state is worse than a
4420
+ // cold remeasure of an unrelated view.
4421
+ UIView.invalidateAllSharedIntrinsicSizeCaches()
4422
+
4423
+ // 3. Walk every view in the subtree and obliterate all per-instance caches,
4424
+ // then unconditionally schedule it for layout.
4425
+ this.forEachViewInSubtree(view => {
4426
+ view._intrinsicSizesCache = {}
4427
+ view._frameCache = undefined
4428
+ view._frameCacheForVirtualLayouting = undefined
4429
+ view.setNeedsLayout()
4430
+ })
4431
+
4432
+ // 4. Drive the layout queue right now, synchronously — don't wait for the
4433
+ // scheduled rAF tick. Callers of this method expect the tree to be
4434
+ // fully laid out by the time the call returns.
4435
+ UIView.layoutViewsIfNeeded()
4436
+
4437
+ }
4438
+
4439
+
4366
4440
  }
4367
4441
 
4368
4442
 
@@ -187,6 +187,9 @@ export class UIViewController extends UIObject {
187
187
  if (IS(controller.view)) {
188
188
  controller.view.removeFromSuperview()
189
189
  }
190
+ else {
191
+ var asd = 1
192
+ }
190
193
  controller.viewDidDisappear()
191
194
 
192
195
  }
@@ -197,8 +200,12 @@ export class UIViewController extends UIObject {
197
200
  controller = FIRST_OR_NIL(controller)
198
201
  containerView = FIRST_OR_NIL(containerView)
199
202
  controller.viewWillAppear()
200
- this.addChildViewController(controller)
201
- containerView.addSubview(controller.view)
203
+ if (!this.hasChildViewController(controller)) {
204
+ controller.willMoveToParentViewController(this)
205
+ this.childViewControllers.push(controller)
206
+ containerView.addSubview(controller.view)
207
+ controller.didMoveToParentViewController(this)
208
+ }
202
209
 
203
210
  controller.handleRouteRecursively(UIRoute.currentRoute)
204
211