Skip to content
Open
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: 21 additions & 4 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
module.exports = function deepFreeze (o) {
Object.freeze(o);
'use strict';
module.exports = function deepFreeze (o, method) {
if (!method) {
var method = 'freeze';
}

function isNotExtensible(o) {
return !Object.isExtensible(o);
}

var checkFn;
switch (method) {
case 'freeze': checkFn = Object.isFrozen; break;
case 'seal': checkFn = Object.isSealed; break;
case 'preventExtensions': checkFn = isNotExtensible; break;
default: throw new TypeError("Method must be 'freeze', 'seal', or 'preventExtensions'");
}

Object[method](o);

var oIsFunction = typeof o === "function";
var hasOwnProp = Object.prototype.hasOwnProperty;
Expand All @@ -9,8 +26,8 @@ module.exports = function deepFreeze (o) {
&& (oIsFunction ? prop !== 'caller' && prop !== 'callee' && prop !== 'arguments' : true )
&& o[prop] !== null
&& (typeof o[prop] === "object" || typeof o[prop] === "function")
&& !Object.isFrozen(o[prop])) {
deepFreeze(o[prop]);
&& !checkFn(o[prop])) {
deepFreeze(o[prop], method);
}
});

Expand Down
23 changes: 23 additions & 0 deletions readme.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,29 @@ var deepFreeze = require('deep-freeze-strict')
Call `Object.freeze(obj)` recursively on all unfrozen properties of `obj` that
are functions or objects.

## deepFreeze(obj, 'freeze')

Same as `deepFreeze(obj)`.

## deepFreeze(obj, 'seal')

Call `Object.seal(obj)` recursively on all unsealed properties of `obj` that
are functions or objects.

## deepFreeze(obj, 'preventExtensions')

Call `Object.preventExtensions(obj)` recursively on all not isExtensible properties of `obj` that
are functions or objects.

# Freeze, seal, and preventExtensions
`'preventExtensions'` is the least restrictive. It prevents arbitraty properties from added to an object.

`'seal'` does everything preventExtensions does, and also prevents altering the attributes of the properties on the object, as well as preventing deletion of properties on the object.

`'freeze'` is the most restrictive. It does everything preventExtensions and seal does, as well as making all of the existing properties on the object read-only.

Once an object is frozen (or sealed, or not extensible), it cannot be undone.

# license

public domain
Expand Down
23 changes: 23 additions & 0 deletions test/freeze.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
var test = require('tap').test;
var deepFreeze = require('../');

test('freeze', function (t) {
"use strict";

t.plan(6);

var a = {
// a function
b: function() {},
};

deepFreeze(a, 'freeze');
t.assert(!Object.isExtensible(a));
t.assert(!Object.isExtensible(a.b));

t.assert(Object.isSealed(a));
t.assert(Object.isSealed(a.b));

t.assert(Object.isFrozen(a));
t.assert(Object.isFrozen(a.b));
});
23 changes: 23 additions & 0 deletions test/preventExtensions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
var test = require('tap').test;
var deepFreeze = require('../');

test('preventExtensions', function (t) {
"use strict";

t.plan(6);

var a = {
// a function
b: function() {},
};

deepFreeze(a, 'preventExtensions');
t.assert(!Object.isExtensible(a));
t.assert(!Object.isExtensible(a.b));

t.assert(!Object.isSealed(a));
t.assert(Object.isSealed(a.b));

t.assert(!Object.isFrozen(a));
t.assert(!Object.isFrozen(a.b));
});
23 changes: 23 additions & 0 deletions test/seal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
var test = require('tap').test;
var deepFreeze = require('../');

test('seal', function (t) {
"use strict";

t.plan(6);

var a = {
// a function
b: function() {},
};

deepFreeze(a, 'seal');
t.assert(!Object.isExtensible(a));
t.assert(!Object.isExtensible(a.b));

t.assert(Object.isSealed(a));
t.assert(Object.isSealed(a.b));

t.assert(!Object.isFrozen(a));
t.assert(!Object.isFrozen(a.b));
});
44 changes: 44 additions & 0 deletions test/type.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
var test = require('tap').test;
var deepFreeze = require('../');

/**
* Test freeze method (freeze, seal, or preventExtensions).
*/

test('freeze', function (t) {
"use strict";

t.plan(4);

var a = {
// a function
b: function() {},
};

deepFreeze(a, 'freeze');
t.assert(Object.isFrozen(a));
t.assert(Object.isFrozen(a.b));
try {
a.x = 5;
} catch (e) {
t.ok('error thrown as expected');
}
t.equal(a.x, undefined);
});

test('bad type', function (t) {
"use strict";

t.plan(1);

var a = {
// a function
b: function() {},
};

try {
deepFreeze(a, 'whoops');
} catch (e) {
t.ok('error thrown as expected');
}
});