Skip to content

fix(algorithm): port debug module and fix layout defects; relax style gates during port#7

Merged
StevenTCramer merged 7 commits into
masterfrom
dev
Jul 3, 2026
Merged

fix(algorithm): port debug module and fix layout defects; relax style gates during port#7
StevenTCramer merged 7 commits into
masterfrom
dev

Conversation

@StevenTCramer

Copy link
Copy Markdown
Contributor

Summary

Takes the library from non-compiling to a fully green test suite (756 passed, 0 failed, 3 pre-existing skips).

  • Port yoga/debug module (YogaAssert, YogaLog, YogaLogHandler, YogaAssertException) — these were referenced throughout but never ported (kanban task 112), so HEAD did not compile and CI has been red since 2025-12-18.
  • Add Yoga's owner semantics to Node child management (YGNodeInsertChild/RemoveChild/SwapChild/RemoveAllChildren). Previously Owner was never assigned, so CloneChildrenIfNeeded cloned every child on every pass and all layout results were written to throwaway clones — the root cause of 16 of the 20 failing integration tests (NaN dimensions, unpositioned children).
  • Restore the overflow-gated FitContent fallback in FlexBasis.ComputeFlexBasisForChild and correct the cross-axis stretch blocks to match computeFlexBasisForChild in CalculateLayout.cpp — root cause of the 4 measure-cache test failures.
  • Rewrite MeasureNodeWithMeasureFunc to match C++: StretchFit/StretchFit fast path (skip the measure callback), use available size for StretchFit axes, read resolved layout padding/border, clamp inner sizes at zero. Found via end-to-end verification, not covered by existing tests.
  • Temporarily relax style/analyzer gates (TreatWarningsAsErrors, EnforceCodeStyleInBuild) so the build can pass while the port is in progress; ported code doesn't yet conform to .editorconfig. Restoration tracked in kanban task 139.

Verification

  • dotnet build -c Release and dotnet test -c Release pass (the exact CI commands).
  • Library also verified end-to-end via a standalone consumer app: flexGrow distribution, main-axis positioning, RTL mirroring, measure-once behavior, RemoveChild reflow, and owner asserts all match Yoga semantics.

🤖 Generated with Claude Code

StevenTCramer and others added 7 commits July 3, 2026 11:29
The ported C++ code does not yet conform to .editorconfig (4-space vs
2-space indentation, naming rules), producing ~15,600 IDE0055 errors on
a plain build and keeping CI red. Disable TreatWarningsAsErrors and
EnforceCodeStyleInBuild temporarily; analyzers still run and report as
warnings. Restoration tracked in kanban task 139.

Co-Authored-By: Claude Fable 5 <[email protected]>
…egration tests

Four fixes that take the suite from non-compiling to 756/759 passing
(3 pre-existing skips):

1. Port yoga/debug (AssertFatal, Log) as source/timewarp-flexbox/debug.
   YogaAssert/YogaLog/YogaLogHandler/YogaAssertException were referenced
   throughout but never ported (task 112), so HEAD did not compile.

2. Add Yoga's public-API owner semantics to Node child management
   (YGNodeInsertChild/RemoveChild/SwapChild/RemoveAllChildren):
   InsertChild now asserts no existing owner, sets child owner, and marks
   dirty; RemoveChild/ClearChildren reset detached children's layout and
   owner with the dirtied callback suppressed; ReplaceChild sets owner.
   Previously Owner was never assigned, so CloneChildrenIfNeeded cloned
   every child on every pass and all layout results were written to
   throwaway clones - children came back with NaN dimensions and
   unpositioned edges.

3. Restore the overflow-gated FitContent fallback in
   FlexBasis.ComputeFlexBasisForChild and correct the cross-axis stretch
   blocks (childSizingMode != StretchFit guard, nested aspect-ratio
   adjustment, correct ordering) to match computeFlexBasisForChild in
   CalculateLayout.cpp. The FitContent block had been replaced by a
   duplicate of the stretch block, causing wrong measure constraints and
   measurement-cache misses.

4. Rewrite MeasureNode.MeasureNodeWithMeasureFunc to match C++:
   StretchFit/StretchFit fast path that skips the measure callback, use
   available size (not the measure result) for StretchFit axes, read
   resolved layout padding/border, and clamp inner sizes at zero.

Test updates: drop pre-fix "child.Owner = root" workarounds in
NodeTests (InsertChild now sets the owner and asserts it was unset);
MeasureNodeTests that call MeasureNodeWithMeasureFunc directly now
establish the resolved layout padding/border precondition that
CalculateLayoutCore guarantees, as in C++.

Co-Authored-By: Claude Fable 5 <[email protected]>
…alignment defects

Add runfiles/port-generated-tests.cs, a converter that mechanically
translates Yoga's generated gtest files (tests/generated/YG*Test.cpp)
into C# Fixie tests, and convert the first seven files (FlexDirection,
JustifyContent, AlignItems, AlignContent, FlexWrap, Flex,
AbsolutePosition): 241 conformance tests. Tests Yoga itself disables
via GTEST_SKIP are excluded automatically.

The new tests exposed 17 conformance failures, all traced to two
mistranslations against the C++:

1. PerformMultiLineContentAlignment (CalculateLayoutCore.cs) had
   collapsed C++ STEP 8's two-pass-per-line structure into a single
   pass, positioning children against partially accumulated line
   heights; it also dropped the maxDescentForCurrentLine accumulator
   and added the cross-axis gap using the previous line's index, losing
   the gap between the first two lines. Restored the faithful two-pass
   form.

2. LayoutHelpers.ConstrainMaxSizeForMode deviated from the C++ three
   ways: demoted StretchFit to FitContent whenever a max was defined,
   omitted the axis margin from maxSize, and ignored the MaxContent
   case. Rewrote to mirror constrainMaxSizeForMode exactly. Six
   LayoutHelpersTests expectations that had codified the old behavior
   updated to the C++-faithful semantics.

Suite: 997 passed, 0 failed, 3 skipped (was 756 tests before this
change).

Co-Authored-By: Claude Fable 5 <[email protected]>
…s they exposed

Hand-port YGMeasureTest, YGMeasureCacheTest, YGMeasureModeTest, and
YGRelayoutTest from C++ (49 tests). Seven initially failed; four were
already cured by the multi-line alignment and ConstrainMaxSizeForMode
fixes. The remaining three exposed distinct port defects, all fixed:

1. FlexBasis.cs used HasErrata(Errata.None) - always false since
   (x & 0) != 0 never holds - where the C++ checks the WebFlexBasis
   experimental feature, so computed flex basis was wrongly reused
   across layout generations.

2. Style mutations never dirtied the owning node. C++ Yoga routes all
   style writes through updateStyle, which compares old and new values
   and calls markDirtyAndPropagate on change; the C# port exposes Style
   directly, so relayout after a style change hit stale caches. Style
   setters now compare-and-dirty via an internal owner reference,
   attached at the end of Node construction so creating or cloning a
   node never dirties it.

3. JustifyMainAxis's canSkipFlex measure path added the child's raw
   ComputedFlexBasis to the line main dimension; the C++ clamps it with
   boundAxisWithinMinAndMax first, so a child min-width larger than its
   width did not propagate to an auto-sized parent.

Suite: 1046 passed, 0 failed, 3 skipped.

Co-Authored-By: Claude Fable 5 <[email protected]>
Convert the medium- and low-priority generated files with
runfiles/port-generated-tests.cs: Margin, Padding, Border,
MinMaxDimension, Percentage, Gap, Display, BoxSizing, StaticPosition,
Rounding, AlignSelf, AspectRatio, Auto, Dimension, DisplayContents,
FlexBasisFitContent, IntrinsicSize, SizeOverflow — 289 new tests, all
passing on first run. Exclusions are upstream GTEST_SKIPs plus tests
requiring text-measurement contexts (IntrinsicSize) or the
FixFlexBasisFitContent experimental feature, which the port does not
implement yet.

Suite: 1335 passed, 0 failed, 3 skipped.

Co-Authored-By: Claude Fable 5 <[email protected]>
@StevenTCramer StevenTCramer merged commit c61373d into master Jul 3, 2026
1 check passed
StevenTCramer added a commit that referenced this pull request Jul 3, 2026
Move 101 (yoga-csharp-port epic), 123 (algorithm-helpers),
124 (absolute-layout), 125 (calculate-layout epic), and
138 (integration-testing) to done with results. The port is complete
and conformance-verified (1335/0/3, merged via PR #7). Task 139
(restore style enforcement / field naming) stays in to-do; remaining
low-priority unit tests and benchmarks are noted in 138's results for
future pickup.

Co-Authored-By: Claude Fable 5 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant