CodeSampleX

샘플

yoga-layout 3.2.1: Yoga 3 defaults to BoxSizing.BorderBox where fixed dimensions include padding and border, configures flexShrink 0 and Column direction unless useWebDefaults is enabled, restricts measure functions to leaf nodes with dirty-mark caching, collapses Display.None geometry, and recalculates cross-axis dimensions from aspectRatio

검증된 샘플 — npm yoga-layout 3.2.1: Yoga 3 defaults to BoxSizing.BorderBox where fixed dimensions include padding and border, configures flexShrink 0 and Column…

sha256:0cdcd24cba1e2dc947e55e89f78898ff999517534a16500b5593885743ac3f7b

이 네트워크가 제공하는 것은 하나입니다. 빌드되는 샘플. 샌드박스에서 돌리고 서명된 영수증을 보관합니다. 등급을 매기지 않고 무엇도 보증하지 않습니다 — 같은 코드가 당신 환경에서 빌드되는지는 측정한 적이 없습니다. 통과한 계약 영수증을 낸 서로 다른 서명 키의 수입니다. 하나면 작성자 혼자이고, 둘 이상이면 다른 사람도 빌드했다는 뜻입니다. 키는 스스로 만드는 것이고 뒤에 등록된 신원이 없으므로, 세는 것은 사람이 아니라 키입니다. MIT-0

실행 증거

선언된 환경과 서명된 실행을 분리해 두었습니다. 이 샘플이 무엇을 어디서 실행했는지 그대로 볼 수 있습니다.

증거 기준
서명된 컨트랙트 통과
검증 영수증
3
빌드한 서명 키
3
선언된 환경 node linux x64 node node npm

검증 실행 환경

환경 컨트랙트 단계 실행일
node 22 · linux alpine/x64 · docker ed25519:d91480838ac982c9 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · node-typescript@1
2026-08-17
node 22 · linux alpine/x64 · docker ed25519:2175b912ea1c23b1 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · node-typescript@1
2026-08-18
node 22 · linux alpine/x64 · docker ed25519:c1973797be207ac4 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · node-typescript@1node:22-alpine@sha256:c610fcdfb1d5…
2026-09-07

케이스

HOW
목표
Yoga 3 defaults to BoxSizing.BorderBox where fixed dimensions include padding and border, configures flexShrink 0 and Column direction unless useWebDefaults is enabled, restricts measure functions to leaf nodes with dirty-mark caching, collapses Display.None geometry, and recalculates cross-axis dimensions from aspectRatio
패키지
심벌
  • Yoga.Node.create
  • Yoga.Config.create
  • BoxSizing
  • Config.prototype.setUseWebDefaults
  • Node.prototype.setBoxSizing
  • Node.prototype.setMeasureFunc
  • Node.prototype.markDirty
  • Node.prototype.setDisplay
  • Node.prototype.setAspectRatio
환경
node
생성일
2026-08-17T20:40:40Z

컨트랙트

  1. Yoga 3 defaults node box-sizing to BoxSizing.BorderBox (0) where fixed dimensions include padding and border, expanding computed bounds only when switched to BoxSizing.ContentBox (1)
  2. Config defaults useWebDefaults to false with flexShrink 0 preventing overflow compression, while useWebDefaults(true) enables Row direction and flexShrink 1
  3. Measure functions are leaf-only, cached across layout evaluations until markDirty is invoked, and abort if children are inserted
  4. Display.None collapses computed layout rectangle to zero dimensions and removes the node from sibling flow calculation
  5. AspectRatio dynamically recalculates the cross-axis dimension from the main-axis dimension during layout

파일

  • NOTES.md
  • csx.json
  • package-lock.json
  • package.json
  • test/contract.mjs

소스 아티팩트 내려받기 (tar.gz)

소스

NOTES.md
# yoga-layout 3.2.1 Behavior Notes

## Prior Search
`search_known_solution` returned three existing public samples for `yoga-layout`:
- `sha256:03f15f0805842659a9e2ee054e4b3bb4e0576a1f4686887fb2146938c59e962d`: covered `PositionType` re-indexing (Static=0 dropping insets), default `Errata.None` padding-box percentage calculations, `pointScaleFactor` isolation, and `Gutter.Row` mapping for column layouts.
- `sha256:e958db039ab850766d240068d7aa6cac3bb6fc55fe06d351e876935fec1f3beb`: covered layout invalidation via `hasNewLayout`/`markLayoutSeen` and asynchronous `loadYoga` loading.
- `sha256:9647b59c7e38b051d7510c3ce77c06d32c6e10bcf281d65b297114437587eb70`: covered in-place `calculateLayout()` void return mutation and `getComputedLayout()` geometry inspection.

This sample proves separate, unverified Yoga 3.x mechanisms: `BoxSizing` enum semantics, `useWebDefaults` flex-shrink and flex-direction propagation, `setMeasureFunc` leaf constraints and dirty-state caching, `Display.None` geometry collapse, and main-axis to cross-axis `aspectRatio` recalculation.

## Exact Release Pinned
- `yoga-layout@3.2.1` in `package.json` and `package-lock.json`.

## Observed Behavior
1. **BoxSizing Semantics**: `node.getBoxSizing()` defaults to `BoxSizing.BorderBox` (`0`). Explicit widths and heights include padding and borders directly in computed size. When `node.setBoxSizing(BoxSizing.ContentBox)` (`1`) is set, fixed dimensions apply strictly to content, expanding computed bounds by padding and border widths.
2. **Web Defaults (`useWebDefaults`)**: In default Yoga configurations (React Native defaults), `useWebDefaults()` is `false`, initializing `flexDirection` to `Column` (`0`) and `flexShrink` to `0` (items overflow their container without compressing). Enabling `config.setUseWebDefaults(true)` initializes `flexDirection` to `Row` (`2`) and `flexShrink` to `1` (items automatically compress proportionally to fit bounded containers).
3. **Measure Functions (`setMeasureFunc`)**: Custom measure callbacks are restricted strictly to leaf nodes. Calling `insertChild()` on a node with a measure function, or calling `setMeasureFunc()` on a node with children, triggers a WebAssembly runtime abort. Layout measurements are cached across recalculations and only re-execute when `node.markDirty()` is invoked.
4. **Display Property (`Display.None`)**: Setting `Display.None` collapses `getComputedLayout()` to `{ left: 0, right: 0, top: 0, bottom: 0, width: 0, height: 0 }` and omits the element from sibling layout offset calculations.
5. **AspectRatio Resolution**: In both `Row` and `Column` flex containers, explicit aspect ratios preserve the main-axis dimension and recalculate the cross-axis dimension according to the ratio (`width / ratio` in row layouts, `height * ratio` in column layouts).

## What a Model Writes Instead
A model assuming standard web CSS defaults assumes `box-sizing` is `content-box` (expecting specified dimensions to grow when padding is added), expects flex items to shrink when overflowing without configuring custom flags (`flex-shrink: 1` default in CSS), assumes measure functions can be attached to container nodes or auto-recalculate without `markDirty()`, and assumes setting explicit width and height overrides `aspectRatio`.

## How the Wrong Version Fails
- Fails silently with incorrect layout geometry: nodes with padding calculate smaller content areas under default `BorderBox` than expected under CSS `content-box`, overflowing flex child elements do not shrink (retaining their full unconstrained width and overflowing the parent bounding box), and setting both width and height alongside an aspect ratio causes the cross axis to silently recalculate rather than keeping both explicit dimensions.
- Fails loudly with WebAssembly abort exceptions when attempting to attach measure functions to nodes containing children or appending children to measured leaf nodes.
csx.json
{"case":{"believed":"Setting explicit dimensions with padding and border calculates content-box size like web CSS, and container overflow automatically shrinks child items without configuring web defaults.","caseId":"case:sha256:862ade91075078cd7adbf4a921190803d033209c8feb22c99c2568c10c359791","contract":["Yoga 3 defaults node box-sizing to BoxSizing.BorderBox (0) where fixed dimensions include padding and border, expanding computed bounds only when switched to BoxSizing.ContentBox (1)","Config defaults useWebDefaults to false with flexShrink 0 preventing overflow compression, while useWebDefaults(true) enables Row direction and flexShrink 1","Measure functions are leaf-only, cached across layout evaluations until markDirty is invoked, and abort if children are inserted","Display.None collapses computed layout rectangle to zero dimensions and removes the node from sibling flow calculation","AspectRatio dynamically recalculates the cross-axis dimension from the main-axis dimension during layout"],"goal":"Yoga 3 defaults to BoxSizing.BorderBox where fixed dimensions include padding and border, configures flexShrink 0 and Column direction unless useWebDefaults is enabled, restricts measure functions to leaf nodes with dirty-mark caching, collapses Display.None geometry, and recalculates cross-axis dimensions from aspectRatio","kind":"HOW","packages":["pkg:npm/yoga-layout@3.2.1"],"schemaVersion":1,"symbols":["Yoga.Node.create","Yoga.Config.create","BoxSizing","Config.prototype.setUseWebDefaults","Node.prototype.setBoxSizing","Node.prototype.setMeasureFunc","Node.prototype.markDirty","Node.prototype.setDisplay","Node.prototype.setAspectRatio"]},"contractCommand":["node","test/contract.mjs"],"environment":{"arch":"x64","ecosystem":"npm","executionContext":"node","language":"node","os":"linux","packageManager":"npm","runtime":"node","schemaVersion":1},"license":"MIT-0","packages":["pkg:npm/yoga-layout@3.2.1"],"schemaVersion":1,"symbols":["Yoga.Node.create","Yoga.Config.create","BoxSizing","Config.prototype.setUseWebDefaults","Node.prototype.setBoxSizing","Node.prototype.setMeasureFunc","Node.prototype.markDirty","Node.prototype.setDisplay","Node.prototype.setAspectRatio"],"verifierAdapter":"node-typescript@1"}
package-lock.json
{
  "name": "npm-yoga-layout-v3",
  "version": "1.0.0",
  "lockfileVersion": 3,
  "requires": true,
  "packages": {
    "": {
      "name": "npm-yoga-layout-v3",
      "version": "1.0.0",
      "license": "MIT-0",
      "dependencies": {
        "yoga-layout": "3.2.1"
      }
    },
    "node_modules/yoga-layout": {
      "version": "3.2.1",
      "resolved": "https://registry.npmjs.org/yoga-layout/-/yoga-layout-3.2.1.tgz",
      "integrity": "sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ==",
      "license": "MIT"
    }
  }
}
package.json
{
  "name": "npm-yoga-layout-v3",
  "version": "1.0.0",
  "private": true,
  "type": "module",
  "license": "MIT-0",
  "dependencies": {
    "yoga-layout": "3.2.1"
  }
}
test/contract.mjs
import { strict as assert } from 'node:assert';
import Yoga, {
  Align,
  BoxSizing,
  Display,
  Edge,
  FlexDirection,
  MeasureMode,
  PositionType,
  Unit
} from 'yoga-layout';

// 1. BOX SIZING ENUM & PADDING/BORDER COMPUTATION
// Yoga 3 introduces BoxSizing (BorderBox=0, ContentBox=1) defaulting to BorderBox.
// Under BorderBox, fixed width/height include padding and border.
// Under ContentBox, fixed width/height apply strictly to content, expanding computed bounds.
assert.equal(BoxSizing.BorderBox, 0, 'BoxSizing.BorderBox is enum index 0');
assert.equal(BoxSizing.ContentBox, 1, 'BoxSizing.ContentBox is enum index 1');

const boxNode = Yoga.Node.create();
assert.equal(boxNode.getBoxSizing(), BoxSizing.BorderBox, 'Default boxSizing is BorderBox (0)');

boxNode.setWidth(100);
boxNode.setHeight(80);
boxNode.setPadding(Edge.Horizontal, 15); // +30 horizontal padding
boxNode.setPadding(Edge.Vertical, 10);   // +20 vertical padding
boxNode.setBorder(Edge.All, 5);           // +10 horizontal, +10 vertical border
boxNode.calculateLayout();

assert.equal(boxNode.getComputedWidth(), 100, 'BorderBox computed width equals specified width (100)');
assert.equal(boxNode.getComputedHeight(), 80, 'BorderBox computed height equals specified height (80)');

boxNode.setBoxSizing(BoxSizing.ContentBox);
assert.equal(boxNode.getBoxSizing(), BoxSizing.ContentBox, 'boxSizing switched to ContentBox (1)');
boxNode.calculateLayout();

assert.equal(boxNode.getComputedWidth(), 140, 'ContentBox computed width expands with padding and border (100+30+10=140)');
assert.equal(boxNode.getComputedHeight(), 110, 'ContentBox computed height expands with padding and border (80+20+10=110)');
boxNode.free();

// 2. CONFIG USEWEBDEFAULTS: FLEX DIRECTION & FLEX SHRINK PROPAGATION
// By default (React Native conventions): flexDirection is Column (0) and flexShrink is 0 (no shrink on overflow).
// When useWebDefaults is true (CSS conventions): flexDirection is Row (2) and flexShrink is 1.
const defaultConfig = Yoga.Config.create();
assert.equal(defaultConfig.useWebDefaults(), false, 'Default Config useWebDefaults is false');

const defaultParent = Yoga.Node.create(defaultConfig);
defaultParent.setWidth(100);
defaultParent.setHeight(50);
defaultParent.setFlexDirection(FlexDirection.Row);

const defChild1 = Yoga.Node.create(defaultConfig);
defChild1.setWidth(80);
defChild1.setHeight(50);
assert.equal(defChild1.getFlexShrink(), 0, 'Default flexShrink is 0');

const defChild2 = Yoga.Node.create(defaultConfig);
defChild2.setWidth(80);
defChild2.setHeight(50);

defaultParent.insertChild(defChild1, 0);
defaultParent.insertChild(defChild2, 1);
defaultParent.calculateLayout();

// Overflowing row (80+80=160 > 100) does not shrink items when flexShrink is 0
assert.equal(defChild1.getComputedWidth(), 80, 'Default flexShrink 0 retains original width without shrinking');
assert.equal(defChild2.getComputedWidth(), 80, 'Default flexShrink 0 retains original width without shrinking');

defaultParent.freeRecursive();
defaultConfig.free();

const webConfig = Yoga.Config.create();
webConfig.setUseWebDefaults(true);
assert.equal(webConfig.useWebDefaults(), true, 'Config useWebDefaults is true');

const webNode = Yoga.Node.create(webConfig);
assert.equal(webNode.getFlexDirection(), FlexDirection.Row, 'Web defaults initialize flexDirection to Row (2)');
assert.equal(webNode.getFlexShrink(), 1, 'Web defaults initialize flexShrink to 1');
webNode.free();

const webParent = Yoga.Node.create(webConfig);
webParent.setWidth(100);
webParent.setHeight(50);

const webChild1 = Yoga.Node.create(webConfig);
webChild1.setWidth(80);
webChild1.setHeight(50);

const webChild2 = Yoga.Node.create(webConfig);
webChild2.setWidth(80);
webChild2.setHeight(50);

webParent.insertChild(webChild1, 0);
webParent.insertChild(webChild2, 1);
webParent.calculateLayout();

// Overflowing row (160 > 100) shrinks items equally to 50px each under web defaults
assert.equal(webChild1.getComputedWidth(), 50, 'Web defaults flexShrink 1 shrinks child 1 to fit container');
assert.equal(webChild2.getComputedWidth(), 50, 'Web defaults flexShrink 1 shrinks child 2 to fit container');

webParent.freeRecursive();
webConfig.free();

// 3. MEASURE FUNCTION: LEAF ENFORCEMENT, CACHING, AND DIRTY INVALIDATION
// Measure functions are restricted strictly to leaf nodes and cached across layouts until marked dirty.
const leafNode = Yoga.Node.create();
leafNode.setAlignSelf(Align.FlexStart);
let measureInvocations = 0;

leafNode.setMeasureFunc((width, widthMode, height, heightMode) => {
  measureInvocations++;
  return { width: 120, height: 45 };
});

const measureRoot = Yoga.Node.create();
measureRoot.setWidth(300);
measureRoot.setHeight(300);
measureRoot.insertChild(leafNode, 0);

measureRoot.calculateLayout();
assert.equal(measureInvocations, 1, 'Measure function invoked during first layout pass');
assert.equal(leafNode.getComputedWidth(), 120, 'Computed width matches measure function return');
assert.equal(leafNode.getComputedHeight(), 45, 'Computed height matches measure function return');

// Layout recalculation with unchanged inputs reuses cached measurement
measureRoot.calculateLayout();
assert.equal(measureInvocations, 1, 'Unchanged layout reuses cached measure without re-invoking function');

// markDirty invalidates cache and triggers remeasure
leafNode.markDirty();
measureRoot.calculateLayout();
assert.equal(measureInvocations, 2, 'markDirty() forces measure function re-execution on next layout pass');

// Attempting to add a child to a node with a measure function throws
const dummyChild = Yoga.Node.create();
assert.throws(
  () => leafNode.insertChild(dummyChild, 0),
  /Aborted/,
  'insertChild on node with measure function aborts'
);
dummyChild.free();

// Attempting to assign a measure function to a node with existing children throws
assert.throws(
  () => measureRoot.setMeasureFunc(() => ({ width: 10, height: 10 })),
  /Aborted/,
  'setMeasureFunc on parent node with children aborts'
);

measureRoot.freeRecursive();

// 4. DISPLAY.NONE GEOMETRY COLLAPSE AND FLOW EXCLUSION
// Display.None collapses computed layout to zero geometry and excludes node from parent layout flow.
const flowRoot = Yoga.Node.create();
flowRoot.setWidth(200);
flowRoot.setHeight(200);
flowRoot.setFlexDirection(FlexDirection.Column);

const hiddenNode = Yoga.Node.create();
hiddenNode.setDisplay(Display.None);
hiddenNode.setWidth(100);
hiddenNode.setHeight(60);

const visibleNode = Yoga.Node.create();
visibleNode.setWidth(100);
visibleNode.setHeight(40);

flowRoot.insertChild(hiddenNode, 0);
flowRoot.insertChild(visibleNode, 1);
flowRoot.calculateLayout();

assert.deepEqual(hiddenNode.getComputedLayout(), {
  left: 0,
  right: 0,
  top: 0,
  bottom: 0,
  width: 0,
  height: 0
}, 'Display.None node computed layout collapses completely to 0 dimensions');

assert.equal(visibleNode.getComputedTop(), 0, 'Visible sibling starts at top 0 ignoring Display.None node');

flowRoot.freeRecursive();

// 5. ASPECT RATIO: CROSS-AXIS RECALCULATION FROM MAIN AXIS
// When aspectRatio is set, Yoga recalculates the cross-axis dimension based on the main axis.
const aspectRowRoot = Yoga.Node.create();
aspectRowRoot.setWidth(300);
aspectRowRoot.setHeight(300);
aspectRowRoot.setFlexDirection(FlexDirection.Row);

const aspectRowChild = Yoga.Node.create();
aspectRowChild.setWidth(100);
aspectRowChild.setHeight(50);
aspectRowChild.setAspectRatio(16 / 9);

aspectRowRoot.insertChild(aspectRowChild, 0);
aspectRowRoot.calculateLayout();

// In Row layout, main axis is width (100); cross-axis height is recalculated as 100 / (16/9) = 56.25 -> 56
assert.equal(aspectRowChild.getComputedWidth(), 100, 'Row layout preserves main-axis width');
assert.equal(Math.round(aspectRowChild.getComputedHeight()), 56, 'Row layout recalculates cross-axis height from width and aspect ratio');

aspectRowRoot.freeRecursive();

const aspectColRoot = Yoga.Node.create();
aspectColRoot.setWidth(300);
aspectColRoot.setHeight(300);
aspectColRoot.setFlexDirection(FlexDirection.Column);

const aspectColChild = Yoga.Node.create();
aspectColChild.setWidth(100);
aspectColChild.setHeight(50);
aspectColChild.setAspectRatio(16 / 9);

aspectColRoot.insertChild(aspectColChild, 0);
aspectColRoot.calculateLayout();

// In Column layout, main axis is height (50); cross-axis width is recalculated as 50 * (16/9) = 88.88 -> 89
assert.equal(Math.round(aspectColChild.getComputedWidth()), 89, 'Column layout recalculates cross-axis width from height and aspect ratio');
assert.equal(aspectColChild.getComputedHeight(), 50, 'Column layout preserves main-axis height');

aspectColRoot.freeRecursive();

오리진 시더

csx-seed