UNPKG

@chainsafe/ssz

Version:

Simple Serialize

99 lines 4.21 kB
import { isCompositeType } from "../type/composite.js"; import { TreeViewDU } from "./abstract.js"; export class ContainerNodeStructTreeViewDU extends TreeViewDU { type; valueChanged = null; _rootNode; constructor(type, node) { super(); this.type = type; this._rootNode = node; } get node() { return this._rootNode; } get cache() { // biome-ignore lint/suspicious/useGetterReturn: There is no cache to return return; } get value() { return this.valueChanged ?? this._rootNode.value; } /** * There are 2 cases: * - normal commit() or hashTreeRoot(): hcByLevel is null, no need to compute root * - batchHashTreeRoot(): hcByLevel is not null, need to compute root because this does not support HashComputation */ commit(_, hcByLevel = null) { if (this.valueChanged !== null) { const value = this.valueChanged; this.valueChanged = null; this._rootNode = this.type.value_toTree(value); } if (this._rootNode.h0 === null && hcByLevel !== null) { // consumer is batchHashTreeRoot() this._rootNode.rootHashObject; } } clearCache() { this.valueChanged = null; } } export function getContainerTreeViewDUClass(type) { class CustomContainerTreeViewDU extends ContainerNodeStructTreeViewDU { } // Dynamically define prototype methods for (let index = 0; index < type.fieldsEntries.length; index++) { const { fieldName, fieldType } = type.fieldsEntries[index]; // If the field type is basic, the value to get and set will be the actual 'struct' value (i.e. a JS number). // The view must use the tree_getFromNode() and tree_setToNode() methods to persist the struct data to the node, // and use the cached views array to store the new node. if (fieldType.isBasic) { Object.defineProperty(CustomContainerTreeViewDU.prototype, fieldName, { configurable: false, enumerable: true, // TODO: Review the memory cost of this closures get: function () { return (this.valueChanged || this._rootNode.value)[fieldName]; }, set: function (value) { if (this.valueChanged === null) { this.valueChanged = this.type.clone(this._rootNode.value); } this.valueChanged[fieldName] = value; }, }); } // If the field type is composite, the value to get and set will be another TreeView. The parent TreeView must // cache the view itself to retain the caches of the child view. To set a value the view must return a node to // set it to the parent tree in the field gindex. else if (isCompositeType(fieldType)) { Object.defineProperty(CustomContainerTreeViewDU.prototype, fieldName, { configurable: false, enumerable: true, // Returns TreeViewDU of fieldName get: function () { const value = this.valueChanged || this._rootNode.value; return fieldType.toViewDU(value[fieldName]); }, // Expects TreeViewDU of fieldName set: function (view) { if (this.valueChanged === null) { this.valueChanged = this.type.clone(this._rootNode.value); } const value = fieldType.toValueFromViewDU(view); this.valueChanged[fieldName] = value; }, }); } // Should never happen else { /* istanbul ignore next - unreachable code */ throw Error(`Unknown fieldType ${fieldType.typeName} for fieldName ${String(fieldName)}`); } } // Change class name Object.defineProperty(CustomContainerTreeViewDU, "name", { value: type.typeName, writable: false }); return CustomContainerTreeViewDU; } //# sourceMappingURL=containerNodeStruct.js.map