Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 1 addition & 24 deletions gentest/gentest-javascript.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ JavascriptEmitter.prototype = Object.create(Emitter.prototype, {
this.push(`${testFn}('${name}', () => {`);
this.pushIndent();
this.push('const config = Yoga.Config.create();');
this.push('let root;');
this.push('');

if (experiments.length > 0) {
Expand All @@ -70,39 +69,17 @@ JavascriptEmitter.prototype = Object.create(Emitter.prototype, {
}
this.push('');
}

this.push('try {');
this.pushIndent();
},
},

emitTestTreePrologue: {
value: function (nodeName) {
if (nodeName === 'root') {
this.push(`root = Yoga.Node.create(config);`);
} else {
this.push(`const ${nodeName} = Yoga.Node.create(config);`);
}
this.push(`const ${nodeName} = Yoga.Node.create(config);`);
},
},

emitTestEpilogue: {
value: function (_experiments) {
this.popIndent();
this.push('} finally {');
this.pushIndent();

this.push("if (typeof root !== 'undefined') {");
this.pushIndent();
this.push('root.freeRecursive();');
this.popIndent();
this.push('}');
this.push('');
this.push('config.free();');

this.popIndent();
this.push('}');

this.popIndent();
this.push('});');
},
Expand Down
13 changes: 0 additions & 13 deletions javascript/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,6 @@ const node = Yoga.Node.create();
node.setAlignContent(Align.Center);
```

Objects created by `Yoga.<>.create()` are not automatically garbage collected and should be freed once they are no longer in use.

```ts
// Free a config
config.free();

// Free a tree of Nodes
node.freeRecursive();

// Free a single Node
node.free();
```

## Requirements

`yoga-layout` requires a toolchain that supports ES Modules and top-level await.
Expand Down
59 changes: 18 additions & 41 deletions javascript/src/wrapAssembly.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ type Value = {
};

export type Config = {
free(): void;
isExperimentalFeatureEnabled(feature: ExperimentalFeature): boolean;
setExperimentalFeatureEnabled(
feature: ExperimentalFeature,
Expand Down Expand Up @@ -77,8 +76,6 @@ export type Node = {
direction?: Direction,
): void;
copyStyle(node: Node): void;
free(): void;
freeRecursive(): void;
getAlignContent(): Align;
getAlignItems(): Align;
getAlignSelf(): Align;
Expand Down Expand Up @@ -263,13 +260,11 @@ export type Node = {
export type Yoga = {
Config: {
create(): Config;
destroy(config: Config): void;
};
Node: {
create(config?: Config): Node;
createDefault(): Node;
createWithConfig(config: Config): Node;
destroy(node: Node): void;
};
} & typeof YGEnums;

Expand Down Expand Up @@ -365,16 +360,24 @@ export default function wrapAssembly(lib: any): Yoga {
}
}

// --- FinalizationRegistry for automatic cleanup ---
const configRegistry = new FinalizationRegistry((ptr: number) => {
lib._YGConfigFree(ptr);
});

const nodeRegistry = new FinalizationRegistry((ptr: number) => {
lib._yogaMeasureFuncs.delete(ptr);
lib._yogaDirtiedFuncs.delete(ptr);
lib._YGNodeFinalize(ptr);
});

// --- Config class ---
class ConfigImpl {
_ptr: number;

constructor(ptr: number) {
this._ptr = ptr;
}

free(): void {
lib._YGConfigFree(this._ptr);
configRegistry.register(this, ptr, this);
}

setExperimentalFeatureEnabled(
Expand Down Expand Up @@ -423,6 +426,7 @@ export default function wrapAssembly(lib: any): Yoga {
this._ptr = ptr;
this._children = [];
this._parent = null;
nodeRegistry.register(this, ptr, this);
}

// --- Tree hierarchy ---
Expand Down Expand Up @@ -454,31 +458,6 @@ export default function wrapAssembly(lib: any): Yoga {
}

// --- Lifecycle ---
free(): void {
lib._yogaMeasureFuncs.delete(this._ptr);
lib._yogaDirtiedFuncs.delete(this._ptr);

// Clear JS tree references
if (this._parent) {
const idx = this._parent._children.indexOf(this);
if (idx !== -1) {
this._parent._children.splice(idx, 1);
}
this._parent = null;
}
this._children = [];

lib._YGNodeFree(this._ptr);
}

freeRecursive(): void {
// Walk children in JS, calling freeRecursive on each
while (this._children.length > 0) {
this._children[0].freeRecursive();
}
this.free();
}

reset(): void {
lib._yogaMeasureFuncs.delete(this._ptr);
lib._yogaDirtiedFuncs.delete(this._ptr);
Expand Down Expand Up @@ -920,7 +899,11 @@ export default function wrapAssembly(lib: any): Yoga {

setDirtiedFunc(dirtiedFunc: DirtiedFunction | null): void {
if (dirtiedFunc) {
lib._yogaDirtiedFuncs.set(this._ptr, () => dirtiedFunc(this));
const nodeWeakRef = new WeakRef(this);
lib._yogaDirtiedFuncs.set(this._ptr, () => {
const node = nodeWeakRef.deref();
if (node) dirtiedFunc(node);
});
lib._jswrap_YGNodeSetDirtiedFunc(this._ptr);
} else {
this.unsetDirtiedFunc();
Expand Down Expand Up @@ -1011,9 +994,6 @@ export default function wrapAssembly(lib: any): Yoga {
create(): Config {
return new ConfigImpl(lib._YGConfigNew());
},
destroy(config: Config): void {
(config as ConfigImpl).free();
},
},
Node: {
create(config?: Config): Node {
Expand All @@ -1032,9 +1012,6 @@ export default function wrapAssembly(lib: any): Yoga {
lib._YGNodeNewWithConfig((config as ConfigImpl)._ptr),
);
},
destroy(node: Node): void {
(node as NodeImpl).free();
},
},
...YGEnums,
};
Expand Down
4 changes: 0 additions & 4 deletions javascript/tests/Benchmarks/YGBenchmark.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ YGBENCHMARK('Stack with flex', () => {
}

root.calculateLayout(undefined, undefined, Yoga.DIRECTION_LTR);
root.freeRecursive();
});

YGBENCHMARK('Align stretch in undefined axis', () => {
Expand All @@ -43,7 +42,6 @@ YGBENCHMARK('Align stretch in undefined axis', () => {
}

root.calculateLayout(undefined, undefined, Yoga.DIRECTION_LTR);
root.freeRecursive();
});

YGBENCHMARK('Nested flex', () => {
Expand All @@ -67,7 +65,6 @@ YGBENCHMARK('Nested flex', () => {
}

root.calculateLayout(undefined, undefined, Yoga.DIRECTION_LTR);
root.freeRecursive();
});

YGBENCHMARK('Huge nested layout', () => {
Expand Down Expand Up @@ -110,5 +107,4 @@ YGBENCHMARK('Huge nested layout', () => {
}

root.calculateLayout(undefined, undefined, Yoga.DIRECTION_LTR);
root.freeRecursive();
});
Loading
Loading