Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ and this project adheres to

## [Unreleased][unreleased]

- Implement `deepFreeze` and `freezeNamespaces`

## [2.2.0][] - 2020-07-10

### Added
Expand Down
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,8 @@ $ npm install @metarhia/common
- [parseHost](#parsehosthost)
- [override](#overrideobj-fn)
- [mixin](#mixintarget-source)
- [deepFreeze](#deepfreezeinstance)
- [freezeNamespaces](#freezenamespacesnamespaces-exceptnames)
- [Pool](#class-pool)
- [Pool.prototype.constructor](#poolprototypeconstructorfactory--null)
- [Pool.prototype.get](#poolprototypeget)
Expand Down Expand Up @@ -1334,6 +1336,24 @@ Previous function will be accessible by obj.fnName.inherited

Mixin for ES6 classes without overriding existing methods

### deepFreeze(instance)

- `instance`: [`<Object>`][object] target nested objects structure

_Returns:_ [`<Object>`][object] - deep freezed instance

Deep freeze object structure

### freezeNamespaces(namespaces, exceptNames)

- `namespaces`: [`<Object>`][object] target nested objects structure
- `exceptNames`: [`<Array>`][array] nemes to be skipped for freezing at first
level

_Returns:_ undefined

Deep freeze namespaces

### class Pool

#### Pool.prototype.constructor(factory = null)
Expand Down
36 changes: 36 additions & 0 deletions lib/oop.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,43 @@ const mixin = (target, source) => {
Object.assign(target, mix);
};

const REF_TYPES = ['object', 'function'];

// Deep freeze object structure
// instance - <Object>, target nested objects structure
// Returns: <Object> - deep freezed instance
//
const deepFreeze = instance => {
Object.freeze(instance);
const fields = Object.getOwnPropertyNames(instance);
for (const fieldName of fields) {
const value = instance[fieldName];
if (value === null) continue;
if (!REF_TYPES.includes(typeof value) || Object.isFrozen(value)) continue;
deepFreeze(value);
}
return instance;
};

// Deep freeze namespaces
// namespaces - <Object>, target nested objects structure
// exceptNames - <Array>, nemes to be skipped for freezing at first level
// Returns: undefined
//
const freezeNamespaces = (namespaces, exceptNames) => {
for (const namespace of namespaces) {
const names = Object.keys(namespace);
for (const name of names) {
const target = namespace[name];
if (exceptNames.includes(name)) continue;
deepFreeze(target);
}
}
};

module.exports = {
override,
mixin,
deepFreeze,
freezeNamespaces,
};