Ejemplo
yoga-layout 3.2.1: Configure Yoga.Config with useWebDefaults and pointScaleFactor to apply CSS flexbox defaults and subpixel rounding across parent and child nodes
Muestra verificada para npm yoga-layout 3.2.1: Configure Yoga.Config with useWebDefaults and pointScaleFactor to apply CSS flexbox defaults and subpixel…
sha256:213ce2ec407485da262aa6339bc72e3486919b672c93e548819586c905ed88f2
Esta red ofrece una sola cosa: una muestra que compila. La ejecutó en un sandbox y guardó el recibo firmado. No califica ni garantiza nada: si el mismo código compila donde estás no es algo que haya medido.
Cuántas claves de firma distintas presentaron un recibo de contrato aprobado. Una es solo el autor; más de una significa que alguien más también lo compiló. Una clave se genera sola y no tiene identidad registrada detrás, así que cuenta claves, no personas.
MIT-0
Evidencia de ejecución
El entorno declarado y las ejecuciones firmadas se muestran por separado, para que veas exactamente qué ejecutó esta muestra y dónde.
- Base de evidencia
- Contrato firmado aprobado
- Recibos de verificación
- 3
- Claves de firma que lo compilaron
- 3
Entorno declarado
node linux x64 node node npm
Entornos de las ejecuciones de verificación
| Entorno | Contrato | Etapas | Ejecución |
|---|---|---|---|
| node 22 · linux alpine/x64 · docker ed25519:d91480838ac982c9 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · node-typescript@1 |
2026-08-16 |
| 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 |
Caso
HOW- Objetivo
- Configure Yoga.Config with useWebDefaults and pointScaleFactor to apply CSS flexbox defaults and subpixel rounding across parent and child nodes
- Paquetes
- Símbolos
-
- Yoga.Config.create
- Config.setUseWebDefaults
- Config.setPointScaleFactor
- Yoga.Node.create
- Node.calculateLayout
- Node.getComputedWidth
- Node.getFlexShrink
- Node.getFlexDirection
- Node.insertChild
- Node.freeRecursive
- Config.free
- Entorno
- node
- Creado
- 2026-08-16T07:08:30Z
Contrato
- assert yoga-layout resolved version is 3.2.1
- assert default Config has useWebDefaults disabled (false) and default Node uses React Native defaults (flexDirection Column, flexShrink 0, alignContent FlexStart)
- assert Config with setUseWebDefaults(true) sets web defaults (flexDirection Row, flexShrink 1, alignContent Stretch)
- assert child Node does not inherit Config from parent upon insertion and retains flexShrink 0 unless created with the Config
- assert overflowing children in a fixed row fail to shrink under Yoga defaults (overflowing container to 300px width)
- assert overflowing children in a fixed row shrink to fit (100px each, 200px total) when created with useWebDefaults Config
- assert pointScaleFactor 1.0 rounds coordinates to integer pixel boundaries (10.6 to 11 and 10.4 to 10)
- assert pointScaleFactor 0.0 disables pixel snapping and preserves exact subpixel floating point values
- assert pointScaleFactor 2.0 snaps coordinates to half-pixel multiples (10.25 to 10.5 and 10.75 to 11.0)
- assert freeing root node with freeRecursive releases entire tree and Config.free releases config allocation
Archivos
- NOTES.md
- csx.json
- package-lock.json
- package.json
- src/index.js
- test/contract.mjs
Código fuente
# Notes: yoga-layout Config Defaults, Isolation, and Subpixel Snapping
### search_known_solution Response
`search_known_solution` returned existing sample `sha256:c7071dcdb5556a42d993b28cdf9b1adba12d8ef2436ee1bdd1b9029e2acff699` ("require() an ESM-only npm package from CommonJS without ERR_REQUIRE_ESM or ERR_REQUIRE_ASYNC_MODULE", demonstrating dynamic `import()` workaround for top-level await in `p-limit` and `yoga-layout`).
### What a Model Would Have Written Instead
A model simulating CSS flexbox with `yoga-layout` assumes default nodes inherit standard web flexbox properties (`flexDirection: Row`, `flexShrink: 1`, `alignContent: Stretch`), or assumes that setting `config.setUseWebDefaults(true)` on the root container automatically propagates to child nodes added via `.insertChild()`.
### How the Wrong Version Fails
Fails silently with a green build: without `setUseWebDefaults(true)` explicitly passed to `Node.create(config)` for each child node, `flexShrink` remains `0` (React Native default) and child nodes do not shrink, overflowing parent container boundaries with zero runtime errors or warnings.
{"case":{"caseId":"case:sha256:15935269e55659f485f4181325dc64a6a56a158b53257b8c038ee0b12404f744","contract":["assert yoga-layout resolved version is 3.2.1","assert default Config has useWebDefaults disabled (false) and default Node uses React Native defaults (flexDirection Column, flexShrink 0, alignContent FlexStart)","assert Config with setUseWebDefaults(true) sets web defaults (flexDirection Row, flexShrink 1, alignContent Stretch)","assert child Node does not inherit Config from parent upon insertion and retains flexShrink 0 unless created with the Config","assert overflowing children in a fixed row fail to shrink under Yoga defaults (overflowing container to 300px width)","assert overflowing children in a fixed row shrink to fit (100px each, 200px total) when created with useWebDefaults Config","assert pointScaleFactor 1.0 rounds coordinates to integer pixel boundaries (10.6 to 11 and 10.4 to 10)","assert pointScaleFactor 0.0 disables pixel snapping and preserves exact subpixel floating point values","assert pointScaleFactor 2.0 snaps coordinates to half-pixel multiples (10.25 to 10.5 and 10.75 to 11.0)","assert freeing root node with freeRecursive releases entire tree and Config.free releases config allocation"],"goal":"Configure Yoga.Config with useWebDefaults and pointScaleFactor to apply CSS flexbox defaults and subpixel rounding across parent and child nodes","kind":"HOW","packages":["pkg:npm/yoga-layout@3.2.1"],"schemaVersion":1,"symbols":["Yoga.Config.create","Config.setUseWebDefaults","Config.setPointScaleFactor","Yoga.Node.create","Node.calculateLayout","Node.getComputedWidth","Node.getFlexShrink","Node.getFlexDirection","Node.insertChild","Node.freeRecursive","Config.free"]},"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.Config.create","Config.setUseWebDefaults","Config.setPointScaleFactor","Yoga.Node.create","Node.calculateLayout","Node.getComputedWidth","Node.getFlexShrink","Node.getFlexDirection","Node.insertChild","Node.freeRecursive","Config.free"],"verifierAdapter":"node-typescript@1"}
{
"name": "npm-yoga-layout-config",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "npm-yoga-layout-config",
"version": "1.0.0",
"license": "ISC",
"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"
}
}
}
{
"name": "npm-yoga-layout-config",
"version": "1.0.0",
"private": true,
"type": "module",
"license": "MIT-0",
"dependencies": {
"yoga-layout": "3.2.1"
}
}
import Yoga, { Direction, FlexDirection, Align } from 'yoga-layout';
/**
* Creates a configured Yoga layout engine instance.
*
* In Yoga (React Native's flexbox engine), the default configuration disables
* standard W3C CSS web flexbox behavior (useWebDefaults is false):
* - flexDirection defaults to Column (instead of Row)
* - flexShrink defaults to 0 (items do NOT shrink when overflowing)
* - alignContent defaults to FlexStart (instead of Stretch)
*
* Additionally, child nodes do NOT inherit Config from parent nodes upon
* insertion; every node in the hierarchy must be instantiated with the Config
* (or manually configure its flexShrink/flexDirection).
*
* @param {object} [options]
* @param {boolean} [options.useWebDefaults=true] Whether to apply W3C CSS flexbox defaults.
* @param {number} [options.pointScaleFactor=1.0] Point scale factor for pixel snapping (0.0 disables snapping).
* @returns {{ config: import('yoga-layout').Config, createNode: () => import('yoga-layout').Node, free: () => void }}
*/
export function createLayoutEngine({ useWebDefaults = true, pointScaleFactor = 1.0 } = {}) {
const config = Yoga.Config.create();
if (useWebDefaults) {
config.setUseWebDefaults(true);
}
if (pointScaleFactor !== undefined) {
config.setPointScaleFactor(pointScaleFactor);
}
return {
config,
createNode: () => Yoga.Node.create(config),
free: () => config.free(),
};
}
/**
* Computes layout for a set of items placed in a row container.
*
* @param {Array<{ width: number, height: number }>} items
* @param {number} containerWidth
* @param {number} containerHeight
* @param {object} [options]
* @param {boolean} [options.useWebDefaults=true]
* @param {number} [options.pointScaleFactor=1.0]
* @returns {Array<{ left: number, top: number, width: number, height: number }>}
*/
export function computeRowLayout(items, containerWidth, containerHeight, options = {}) {
const engine = createLayoutEngine(options);
const root = engine.createNode();
root.setWidth(containerWidth);
root.setHeight(containerHeight);
root.setFlexDirection(FlexDirection.Row);
const childNodes = items.map((item, idx) => {
const child = engine.createNode();
child.setWidth(item.width);
child.setHeight(item.height);
root.insertChild(child, idx);
return child;
});
root.calculateLayout(containerWidth, containerHeight, Direction.LTR);
const layouts = childNodes.map((child) => {
const layout = child.getComputedLayout();
return {
left: layout.left,
top: layout.top,
width: layout.width,
height: layout.height,
};
});
root.freeRecursive();
engine.free();
return layouts;
}
import assert from 'node:assert/strict';
import fs from 'node:fs';
import Yoga, { Direction, FlexDirection, Align, BoxSizing } from 'yoga-layout';
import { createLayoutEngine, computeRowLayout } from '../src/index.js';
// ---------------------------------------------------------------------------
// 1. Verify exact resolved package version
// ---------------------------------------------------------------------------
const pkgPath = new URL('../node_modules/yoga-layout/package.json', import.meta.url);
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
assert.equal(pkg.version, '3.2.1', 'Expected yoga-layout resolved version 3.2.1');
// ---------------------------------------------------------------------------
// 2. Default Config vs Web Defaults Config
// ---------------------------------------------------------------------------
const defaultConfig = Yoga.Config.create();
assert.equal(
defaultConfig.useWebDefaults(),
false,
'Default Config must have useWebDefaults disabled (React Native semantics)'
);
const webConfig = Yoga.Config.create();
webConfig.setUseWebDefaults(true);
assert.equal(
webConfig.useWebDefaults(),
true,
'Config with setUseWebDefaults(true) must report useWebDefaults enabled'
);
// ---------------------------------------------------------------------------
// 3. Node property defaults under Default Config vs Web Config
// ---------------------------------------------------------------------------
const defaultNode = Yoga.Node.create(defaultConfig);
assert.equal(
defaultNode.getFlexDirection(),
FlexDirection.Column,
'Default Node flexDirection must be Column (React Native default), not Row'
);
assert.equal(
defaultNode.getFlexShrink(),
0,
'Default Node flexShrink must be 0 (no shrink), not CSS default 1'
);
assert.equal(
defaultNode.getAlignContent(),
Align.FlexStart,
'Default Node alignContent must be FlexStart, not CSS default Stretch'
);
const webNode = Yoga.Node.create(webConfig);
assert.equal(
webNode.getFlexDirection(),
FlexDirection.Row,
'Web Node flexDirection must be Row (CSS Flexbox standard)'
);
assert.equal(
webNode.getFlexShrink(),
1,
'Web Node flexShrink must be 1 (CSS Flexbox standard)'
);
assert.equal(
webNode.getAlignContent(),
Align.Stretch,
'Web Node alignContent must be Stretch (CSS Flexbox standard)'
);
// ---------------------------------------------------------------------------
// 4. Config is NOT inherited by child nodes upon insertion
// ---------------------------------------------------------------------------
const parentWeb = Yoga.Node.create(webConfig);
const childDefault = Yoga.Node.create(); // Created without webConfig
assert.equal(childDefault.getFlexShrink(), 0, 'Child created with Node.create() has default flexShrink 0');
parentWeb.insertChild(childDefault, 0);
assert.equal(
childDefault.getFlexShrink(),
0,
'Child node must NOT inherit Config from parent upon insertion'
);
// ---------------------------------------------------------------------------
// 5. Silent layout failure: Contained row overflowing vs shrinking
// ---------------------------------------------------------------------------
// A. Default / Naive behavior: Two 150px children in a 200px row container
const rootDefault = Yoga.Node.create(defaultConfig);
rootDefault.setWidth(200);
rootDefault.setHeight(50);
rootDefault.setFlexDirection(FlexDirection.Row);
const itemDef1 = Yoga.Node.create(defaultConfig);
itemDef1.setWidth(150);
itemDef1.setHeight(50);
const itemDef2 = Yoga.Node.create(defaultConfig);
itemDef2.setWidth(150);
itemDef2.setHeight(50);
rootDefault.insertChild(itemDef1, 0);
rootDefault.insertChild(itemDef2, 1);
rootDefault.calculateLayout(200, 50, Direction.LTR);
assert.equal(itemDef1.getComputedWidth(), 150, 'Without useWebDefaults, item 1 fails to shrink');
assert.equal(itemDef2.getComputedWidth(), 150, 'Without useWebDefaults, item 2 fails to shrink');
assert.equal(
itemDef1.getComputedWidth() + itemDef2.getComputedWidth(),
300,
'Combined width silently overflows 200px container to 300px without error'
);
// B. Web Defaults behavior: Two 150px children shrink equally to 100px each
const rootWeb = Yoga.Node.create(webConfig);
rootWeb.setWidth(200);
rootWeb.setHeight(50);
const itemWeb1 = Yoga.Node.create(webConfig);
itemWeb1.setWidth(150);
itemWeb1.setHeight(50);
const itemWeb2 = Yoga.Node.create(webConfig);
itemWeb2.setWidth(150);
itemWeb2.setHeight(50);
rootWeb.insertChild(itemWeb1, 0);
rootWeb.insertChild(itemWeb2, 1);
rootWeb.calculateLayout(200, 50, Direction.LTR);
assert.equal(itemWeb1.getComputedWidth(), 100, 'With useWebDefaults, item 1 shrinks to 100px');
assert.equal(itemWeb2.getComputedWidth(), 100, 'With useWebDefaults, item 2 shrinks to 100px');
assert.equal(
itemWeb1.getComputedWidth() + itemWeb2.getComputedWidth(),
200,
'Combined width exactly matches 200px container width'
);
// ---------------------------------------------------------------------------
// 6. PointScaleFactor pixel rounding / subpixel behavior
// ---------------------------------------------------------------------------
// A. pointScaleFactor 1.0 (default integer pixel snapping)
const configPixelSnap = Yoga.Config.create();
configPixelSnap.setPointScaleFactor(1.0);
const nodePixelSnap = Yoga.Node.create(configPixelSnap);
nodePixelSnap.setWidth(10.6);
nodePixelSnap.setHeight(10.4);
nodePixelSnap.calculateLayout(undefined, undefined, Direction.LTR);
assert.equal(nodePixelSnap.getComputedWidth(), 11, 'pointScaleFactor 1.0 snaps 10.6 up to 11');
assert.equal(nodePixelSnap.getComputedHeight(), 10, 'pointScaleFactor 1.0 snaps 10.4 down to 10');
// B. pointScaleFactor 0.0 (disabled pixel snapping, raw subpixels)
const configSubpixel = Yoga.Config.create();
configSubpixel.setPointScaleFactor(0.0);
const nodeSubpixel = Yoga.Node.create(configSubpixel);
nodeSubpixel.setWidth(10.6);
nodeSubpixel.setHeight(10.4);
nodeSubpixel.calculateLayout(undefined, undefined, Direction.LTR);
assert.ok(
Math.abs(nodeSubpixel.getComputedWidth() - 10.6) < 0.001,
'pointScaleFactor 0.0 preserves fractional subpixel width (10.6)'
);
assert.ok(
Math.abs(nodeSubpixel.getComputedHeight() - 10.4) < 0.001,
'pointScaleFactor 0.0 preserves fractional subpixel height (10.4)'
);
// C. pointScaleFactor 2.0 (Retina 2x, half-pixel snapping)
const configRetina = Yoga.Config.create();
configRetina.setPointScaleFactor(2.0);
const nodeRetina = Yoga.Node.create(configRetina);
nodeRetina.setWidth(10.25);
nodeRetina.setHeight(10.75);
nodeRetina.calculateLayout(undefined, undefined, Direction.LTR);
assert.equal(nodeRetina.getComputedWidth(), 10.5, 'pointScaleFactor 2.0 snaps 10.25 to 10.5');
assert.equal(nodeRetina.getComputedHeight(), 11, 'pointScaleFactor 2.0 snaps 10.75 to 11.0');
// ---------------------------------------------------------------------------
// 7. Verify computeRowLayout helper function from src/index.js
// ---------------------------------------------------------------------------
const helperWebResults = computeRowLayout(
[{ width: 150, height: 50 }, { width: 150, height: 50 }],
200,
50,
{ useWebDefaults: true }
);
assert.deepEqual(
helperWebResults,
[
{ left: 0, top: 0, width: 100, height: 50 },
{ left: 100, top: 0, width: 100, height: 50 },
],
'computeRowLayout with useWebDefaults shrinks items to fit container'
);
const helperDefaultResults = computeRowLayout(
[{ width: 150, height: 50 }, { width: 150, height: 50 }],
200,
50,
{ useWebDefaults: false }
);
assert.deepEqual(
helperDefaultResults,
[
{ left: 0, top: 0, width: 150, height: 50 },
{ left: 150, top: 0, width: 150, height: 50 },
],
'computeRowLayout with useWebDefaults false maintains un-shrunk overflowing items'
);
// ---------------------------------------------------------------------------
// 8. Clean up WASM allocations
// ---------------------------------------------------------------------------
defaultNode.free();
webNode.free();
parentWeb.freeRecursive();
rootDefault.freeRecursive();
rootWeb.freeRecursive();
nodePixelSnap.free();
nodeSubpixel.free();
nodeRetina.free();
defaultConfig.free();
webConfig.free();
configPixelSnap.free();
configSubpixel.free();
configRetina.free();
console.log('Contract passed: Yoga.Config settings (useWebDefaults, config isolation, pointScaleFactor) verified.');