Node.js module to iteratively freeze objects, arrays, and functions
ice-barrage is a drop-in replacement for deep-freeze, with the following improvements:
- Iterative traversal to avoid call stack overflow on deep objects
- Traversal into already-frozen objects, so mutable children are not left unfrozen
- Cyclic references terminate, even through values
Object.freezecannot freeze BufferandTypedArrayvalues that hold elements do not throw, and the rest of the graph is still frozen- Skipping of accessor properties to avoid side effects, including Proxy
getandsettraps - Support for Symbol keys
- Support for freezing objects with a null prototype
- TypeScript type definitions included
- Input validation, so primitives are rejected rather than silently returned unfrozen
In ice-barrage, as in any deep-freeze implementation, Object.freeze freezes only an object's own data properties.
At the time of writing, the states listed below stay mutable even though the container may report it as frozen:
Map,Set,WeakMapandWeakSetcontents, throughset(),add(),delete()andclear()Datevalues, through settersArrayBufferbytes, through any view over the same bufferSharedArrayBufferbytes, through any view, in any threadBufferandTypedArrayelements, as the view itself cannot be frozen- Properties of
BufferandTypedArrayviews longer than 65,536 elements, as key enumeration scales with view length and throws aRangeErrorpast 16,777,216 elements - Empty
TypedArrayviews over growableSharedArrayBufferstorage, which are left unfrozen to avoid a concurrent-growth race - Private class fields, through any method of the class
- Closure variables, through any call that reassigns them
- Values behind a getter or setter, which are never traversed
- The prototype chain, as only own properties are frozen
Install using npm:
npm i ice-barragePlease refer to the JSDoc comments in the source code or the generated type definitions for information on the available options.
Each call traverses the whole graph, frozen objects included, so freeze once rather than on every use. Traversal cost grows with the size of the graph, so it is recommended to only freeze trusted data such as local configuration objects rather than request bodies or other input of unbounded size:
"use strict";
const iceBarrage = require("ice-barrage");
// iceBarrage mutates and returns the input object
const config = iceBarrage({
a: 1,
b: {
c: 2,
d: [3, 4, 5],
},
});
console.log(Object.isFrozen(config)); // true
console.log(Object.isFrozen(config.b)); // true
console.log(Object.isFrozen(config.b.d)); // true
module.exports = config;Contributions are welcome, and any help is greatly appreciated!
See the contributing guide for details on how to get started. Please adhere to this project's Code of Conduct when contributing.
ice-barrage is licensed under the MIT license.