From 3ef66e17e4aac7a188849273609d6a1ce7a007c9 Mon Sep 17 00:00:00 2001 From: Aaron Jensen Date: Sun, 2 Aug 2015 00:15:52 -0700 Subject: [PATCH] Add freeze --- lib/freeze.js | 32 ++++++++++++++++++++++++++++++ test/.eslintrc | 5 +++++ test/freeze.js | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+) create mode 100644 lib/freeze.js create mode 100644 test/.eslintrc create mode 100644 test/freeze.js diff --git a/lib/freeze.js b/lib/freeze.js new file mode 100644 index 0000000..e4d8eb4 --- /dev/null +++ b/lib/freeze.js @@ -0,0 +1,32 @@ +function isFreezable(obj) { + if (Object.isFrozen(obj)) { + return false; + } + + return Array.isArray(obj) || typeof obj === 'object'; +} + +function recur(obj) { + Object.freeze(obj); + + Object.keys(obj).forEach((key) => { + const value = obj[key]; + if (isFreezable(value)) { + recur(value); + } + }); + + return obj; +} + +export default function freeze(obj) { + if (process.env.NODE_ENV === 'production') { + return obj; + } + + if (isFreezable(obj)) { + recur(obj); + } + + return obj; +} diff --git a/test/.eslintrc b/test/.eslintrc new file mode 100644 index 0000000..3a2e250 --- /dev/null +++ b/test/.eslintrc @@ -0,0 +1,5 @@ +{ + "rules": { + "no-unused-expressions": 0 + } +} diff --git a/test/freeze.js b/test/freeze.js new file mode 100644 index 0000000..ca4a381 --- /dev/null +++ b/test/freeze.js @@ -0,0 +1,53 @@ +import { expect } from 'chai'; +import freeze from '../lib/freeze'; + +describe('freeze', () => { + afterEach(() => { + delete process.env.NODE_ENV; + }); + + it('freezes objects', () => { + const obj = {}; + freeze(obj); + + expect(Object.isFrozen(obj)).to.be.true; + }); + + it('freezes nested objects', () => { + const obj = { foo: { bar: 3 } }; + freeze(obj); + + expect(Object.isFrozen(obj.foo)).to.be.true; + }); + + it('freezes nested arrays', () => { + const obj = [[0]]; + freeze(obj); + + expect(Object.isFrozen(obj)).to.be.true; + expect(Object.isFrozen(obj[0])).to.be.true; + }); + + it('ignores functions', () => { + const obj = { foo: () => 1 }; + freeze(obj); + + expect(Object.isFrozen(obj.foo)).to.be.false; + }); + + it('does not freeze children if the parent is already frozen', () => { + const obj = { foo: {} }; + Object.freeze(obj); + freeze(obj); + + expect(Object.isFrozen(obj.foo)).to.be.false; + }); + + it('does not freeze in production', () => { + process.env.NODE_ENV = 'production'; + const obj = {}; + freeze(obj); + + expect(Object.isFrozen(obj)).to.be.false; + }); +});