mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Remove LegacyImmutableObject
We don't use it and it's not part of the build so nobody else is using it. You should probably use immutable instead anyway.
This commit is contained in:
@@ -1,187 +0,0 @@
|
||||
/**
|
||||
* Copyright 2013-2014, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule LegacyImmutableObject
|
||||
* @typechecks
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
var assign = require('Object.assign');
|
||||
var invariant = require('invariant');
|
||||
var isNode = require('isNode');
|
||||
var mergeHelpers = require('mergeHelpers');
|
||||
|
||||
var checkMergeObjectArgs = mergeHelpers.checkMergeObjectArgs;
|
||||
var isTerminal = mergeHelpers.isTerminal;
|
||||
|
||||
/**
|
||||
* Wrapper around JavaScript objects that provide a guarantee of immutability at
|
||||
* developer time when strict mode is used. The extra computations required to
|
||||
* enforce immutability is stripped out in production for performance reasons.
|
||||
*/
|
||||
var LegacyImmutableObject;
|
||||
|
||||
function assertLegacyImmutableObject(immutableObject) {
|
||||
invariant(
|
||||
immutableObject instanceof LegacyImmutableObject,
|
||||
'LegacyImmutableObject: Attempted to set fields on an object that is not ' +
|
||||
'an instance of LegacyImmutableObject.'
|
||||
);
|
||||
}
|
||||
|
||||
if (__DEV__) {
|
||||
/**
|
||||
* Constructs an instance of `LegacyImmutableObject`.
|
||||
*
|
||||
* @param {?object} initialProperties The initial set of properties.
|
||||
* @constructor
|
||||
*/
|
||||
LegacyImmutableObject = function LegacyImmutableObject(initialProperties) {
|
||||
assign(this, initialProperties);
|
||||
deepFreeze(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if an object should be deep frozen. Instances of
|
||||
* `LegacyImmutableObject` are assumed to have already been deep frozen.
|
||||
*
|
||||
* @param {*} object The object to check.
|
||||
* @return {boolean} Whether or not deep freeze is needed.
|
||||
*/
|
||||
var shouldRecurseFreeze = function(object) {
|
||||
return (
|
||||
typeof object === 'object' &&
|
||||
!(object instanceof LegacyImmutableObject) &&
|
||||
object !== null
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Freezes the supplied object deeply.
|
||||
*
|
||||
* @param {*} object The object to freeze.
|
||||
*/
|
||||
var deepFreeze = function(object) {
|
||||
if (isNode(object)) {
|
||||
return; // Don't try to freeze DOM nodes.
|
||||
}
|
||||
Object.freeze(object); // First freeze the object.
|
||||
for (var prop in object) {
|
||||
if (object.hasOwnProperty(prop)) {
|
||||
var field = object[prop];
|
||||
if (shouldRecurseFreeze(field)) {
|
||||
deepFreeze(field);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a new LegacyImmutableObject that is identical to the supplied
|
||||
* object but with the supplied changes, `put`.
|
||||
*
|
||||
* @param {LegacyImmutableObject} immutableObject Starting object.
|
||||
* @param {?object} put Fields to merge into the object.
|
||||
* @return {LegacyImmutableObject} The result of merging in `put` fields.
|
||||
*/
|
||||
LegacyImmutableObject.set = function(immutableObject, put) {
|
||||
assertLegacyImmutableObject(immutableObject);
|
||||
var totalNewFields = assign({}, immutableObject, put);
|
||||
return new LegacyImmutableObject(totalNewFields);
|
||||
};
|
||||
|
||||
} else {
|
||||
/**
|
||||
* Constructs an instance of `LegacyImmutableObject`.
|
||||
*
|
||||
* @param {?object} initialProperties The initial set of properties.
|
||||
* @constructor
|
||||
*/
|
||||
LegacyImmutableObject = function LegacyImmutableObject(initialProperties) {
|
||||
assign(this, initialProperties);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a new LegacyImmutableObject that is identical to the supplied
|
||||
* object but with the supplied changes, `put`.
|
||||
*
|
||||
* @param {LegacyImmutableObject} immutableObject Starting object.
|
||||
* @param {?object} put Fields to merge into the object.
|
||||
* @return {LegacyImmutableObject} The result of merging in `put` fields.
|
||||
*/
|
||||
LegacyImmutableObject.set = function(immutableObject, put) {
|
||||
assertLegacyImmutableObject(immutableObject);
|
||||
var newMap = new LegacyImmutableObject(immutableObject);
|
||||
assign(newMap, put);
|
||||
return newMap;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Sugar for:
|
||||
* `LegacyImmutableObject.set(LegacyImmutableObject, {fieldName: putField})`.
|
||||
*
|
||||
* @param {LegacyImmutableObject} immutableObject Object on which to set field.
|
||||
* @param {string} fieldName Name of the field to set.
|
||||
* @param {*} putField Value of the field to set.
|
||||
* @return {LegacyImmutableObject} [description]
|
||||
*/
|
||||
LegacyImmutableObject.setField = function(immutableObject, fieldName, putField) {
|
||||
var put = {};
|
||||
put[fieldName] = putField;
|
||||
return LegacyImmutableObject.set(immutableObject, put);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a new LegacyImmutableObject that is identical to the supplied object
|
||||
* but with the supplied changes recursively applied.
|
||||
*
|
||||
* @param {LegacyImmutableObject} immutableObject Object on which to set fields.
|
||||
* @param {object} put Fields to merge into the object.
|
||||
* @return {LegacyImmutableObject} The result of merging in `put` fields.
|
||||
*/
|
||||
LegacyImmutableObject.setDeep = function(immutableObject, put) {
|
||||
assertLegacyImmutableObject(immutableObject);
|
||||
return _setDeep(immutableObject, put);
|
||||
};
|
||||
|
||||
function _setDeep(object, put) {
|
||||
checkMergeObjectArgs(object, put);
|
||||
var totalNewFields = {};
|
||||
|
||||
// To maintain the order of the keys, copy the base object's entries first.
|
||||
var keys = Object.keys(object);
|
||||
for (var ii = 0; ii < keys.length; ii++) {
|
||||
var key = keys[ii];
|
||||
if (!put.hasOwnProperty(key)) {
|
||||
totalNewFields[key] = object[key];
|
||||
} else if (isTerminal(object[key]) || isTerminal(put[key])) {
|
||||
totalNewFields[key] = put[key];
|
||||
} else {
|
||||
totalNewFields[key] = _setDeep(object[key], put[key]);
|
||||
}
|
||||
}
|
||||
|
||||
// Apply any new keys that the base object didn't have.
|
||||
var newKeys = Object.keys(put);
|
||||
for (ii = 0; ii < newKeys.length; ii++) {
|
||||
var newKey = newKeys[ii];
|
||||
if (object.hasOwnProperty(newKey)) {
|
||||
continue;
|
||||
}
|
||||
totalNewFields[newKey] = put[newKey];
|
||||
}
|
||||
|
||||
return (object instanceof LegacyImmutableObject ||
|
||||
put instanceof LegacyImmutableObject) ?
|
||||
new LegacyImmutableObject(totalNewFields) :
|
||||
totalNewFields;
|
||||
}
|
||||
|
||||
module.exports = LegacyImmutableObject;
|
||||
@@ -1,293 +0,0 @@
|
||||
/**
|
||||
* Copyright 2013-2014, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @emails react-core
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
require('mock-modules')
|
||||
.dontMock('LegacyImmutableObject');
|
||||
|
||||
var LegacyImmutableObject;
|
||||
|
||||
/**
|
||||
* To perform performance testing of using `LegacyImmutableObject` vs. not using
|
||||
* `LegacyImmutableObject`, such testing must be done with __DEV__ set to false.
|
||||
*/
|
||||
describe('LegacyImmutableObject', function() {
|
||||
var message;
|
||||
beforeEach(function() {
|
||||
require('mock-modules').dumpCache();
|
||||
LegacyImmutableObject = require('LegacyImmutableObject');
|
||||
this.addMatchers({
|
||||
/**
|
||||
* Equivalent with respect to serialization. Must stringify because
|
||||
* constructors are different and other comparison methods will not
|
||||
* consider them structurally equal. Probably not useful for use outside
|
||||
* of this test module.
|
||||
*/
|
||||
toBeSeriallyEqualTo: function(expected) {
|
||||
var actual = this.actual;
|
||||
var notText = this.isNot ? " not" : "";
|
||||
this.message = function() {
|
||||
return "Expected " + JSON.stringify(actual) + notText +
|
||||
" to be serially equal to " + JSON.stringify(expected);
|
||||
};
|
||||
|
||||
return JSON.stringify(actual) === JSON.stringify(expected);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* We are in __DEV__ by default.
|
||||
*/
|
||||
var testDev = function(message, testFunc) {
|
||||
it(message, testFunc);
|
||||
};
|
||||
|
||||
var testProd = function(message, testFunc) {
|
||||
// Temporarily enter production mode
|
||||
window.__DEV__ = false;
|
||||
it(message, testFunc);
|
||||
window.__DEV__ = true;
|
||||
};
|
||||
|
||||
var testDevAndProd = function(message, testFunc) {
|
||||
testDev(message + ':DEV', testFunc);
|
||||
testProd(message + ':PROD', testFunc);
|
||||
};
|
||||
|
||||
testDev('should be running in DEV', function() {
|
||||
expect(window.__DEV__).toBe(true);
|
||||
});
|
||||
|
||||
testDev('should not require initial map to be an object', function() {
|
||||
// These won't throw because they're coerced
|
||||
|
||||
expect(function() {
|
||||
new LegacyImmutableObject([1,2,3]);
|
||||
}).not.toThrow();
|
||||
|
||||
expect(function() {
|
||||
new LegacyImmutableObject('asdf');
|
||||
}).not.toThrow();
|
||||
|
||||
expect(function() {
|
||||
new LegacyImmutableObject({oldField: 'asdf', fieldTwo: null});
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
testDev('should not exceed maximum call stack size with nodes', function() {
|
||||
var node = document.createElement('div');
|
||||
var object = new LegacyImmutableObject({node: node});
|
||||
expect(object.node).toBe(node);
|
||||
});
|
||||
|
||||
testDevAndProd('should not throw when not mutating directly', function() {
|
||||
var io = new LegacyImmutableObject({oldField: 'asdf'});
|
||||
expect(function() {
|
||||
LegacyImmutableObject.set(io, {newField: null}); // not a mutation!
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
testDev('should prevent shallow field addition when strict', function() {
|
||||
expect(function() {
|
||||
var io = new LegacyImmutableObject({oldField: 'asdf'});
|
||||
io.newField = 'this will not work';
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
testDev('should prevent shallow field mutation when strict', function() {
|
||||
expect(function() {
|
||||
var io = new LegacyImmutableObject({oldField: 'asdf'});
|
||||
io.oldField = 'this will not work!';
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
testDev('should prevent deep field addition when strict', function() {
|
||||
expect(function() {
|
||||
var io =
|
||||
new LegacyImmutableObject(
|
||||
{shallowField: {deepField: {oldField: null}}}
|
||||
);
|
||||
io.shallowField.deepField.oldField = 'this will not work!';
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
testDev('should prevent deep field mutation when strict', function() {
|
||||
expect(function() {
|
||||
var io =
|
||||
new LegacyImmutableObject(
|
||||
{shallowField: {deepField: {oldField: null}}}
|
||||
);
|
||||
io.shallowField.deepField.newField = 'this will not work!';
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
testDevAndProd(
|
||||
'should create object with same structure when set with {}',
|
||||
function() {
|
||||
var beforeIO =
|
||||
new LegacyImmutableObject(
|
||||
{shallowField: {deepField: {oldField: null}}}
|
||||
);
|
||||
var afterIO = LegacyImmutableObject.set(beforeIO, {});
|
||||
expect(afterIO).toBeSeriallyEqualTo(beforeIO);
|
||||
expect(afterIO).not.toBe(beforeIO);
|
||||
}
|
||||
);
|
||||
|
||||
testDevAndProd(
|
||||
'should create distinct object with shallow field insertion',
|
||||
function() {
|
||||
var beforeStructure = {
|
||||
oldShallowField: {
|
||||
deepField: {
|
||||
oldField: null
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var delta = {
|
||||
newShallowField: 'newShallowFieldHere'
|
||||
};
|
||||
|
||||
var expectedAfterStructure = {
|
||||
oldShallowField: {
|
||||
deepField: {
|
||||
oldField: null
|
||||
}
|
||||
},
|
||||
newShallowField: 'newShallowFieldHere'
|
||||
};
|
||||
|
||||
var beforeIO = new LegacyImmutableObject(beforeStructure);
|
||||
var afterIO = LegacyImmutableObject.set(beforeIO, delta);
|
||||
expect(afterIO).toBeSeriallyEqualTo(expectedAfterStructure);
|
||||
expect(afterIO).not.toBe(beforeIO);
|
||||
}
|
||||
);
|
||||
|
||||
testDevAndProd(
|
||||
'should create distinct object with shallow field mutation',
|
||||
function() {
|
||||
var beforeStructure = {
|
||||
oldShallowField: {
|
||||
deepField: {
|
||||
oldField: null
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var delta = {
|
||||
oldShallowField: 'this will clobber the old field'
|
||||
};
|
||||
|
||||
var expectedAfterStructure = {
|
||||
oldShallowField: 'this will clobber the old field'
|
||||
};
|
||||
|
||||
var beforeIO = new LegacyImmutableObject(beforeStructure);
|
||||
var afterIO = LegacyImmutableObject.set(beforeIO, delta);
|
||||
expect(afterIO).toBeSeriallyEqualTo(expectedAfterStructure);
|
||||
expect(afterIO).not.toBe(beforeIO);
|
||||
}
|
||||
);
|
||||
|
||||
message = 'should create distinct object with deep field insertion';
|
||||
testDevAndProd(message, function() {
|
||||
var beforeStructure = {
|
||||
oldShallowField: {
|
||||
deepField: {
|
||||
oldField: null
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var delta = {
|
||||
oldShallowField: {newDeepField: 'hello'}
|
||||
};
|
||||
|
||||
// LegacyImmutableObject does not yet support deep merging with
|
||||
// LegacyImmutableObject.set().
|
||||
var expectedAfterStructure = {
|
||||
oldShallowField: {newDeepField: 'hello'}
|
||||
};
|
||||
|
||||
var beforeIO = new LegacyImmutableObject(beforeStructure);
|
||||
var afterIO = LegacyImmutableObject.set(beforeIO, delta);
|
||||
expect(afterIO).toBeSeriallyEqualTo(expectedAfterStructure);
|
||||
expect(afterIO).not.toBe(beforeIO);
|
||||
});
|
||||
|
||||
message =
|
||||
'should tolerate arrays at deeper levels and prevent mutation on them';
|
||||
testDevAndProd(message, function() {
|
||||
if (window.callPhantom) {
|
||||
// PhantomJS has a bug with Object.freeze and Arrays.
|
||||
// https://github.com/ariya/phantomjs/issues/10817
|
||||
return;
|
||||
}
|
||||
var beforeStructure = {
|
||||
shallowField: [1,'second field',3]
|
||||
};
|
||||
var io = new LegacyImmutableObject(beforeStructure);
|
||||
expect(function() {
|
||||
io.newField = 'nope!';
|
||||
}).toThrow();
|
||||
expect(function() {
|
||||
io.shallowField[0] = 'nope!';
|
||||
}).toThrow();
|
||||
expect(io.shallowField[1]).toEqual('second field');
|
||||
});
|
||||
|
||||
message = 'should provide a setField interface as sugar for set()';
|
||||
testDevAndProd(message, function() {
|
||||
var beforeIO = new LegacyImmutableObject({initialField: null});
|
||||
var afterIO =
|
||||
LegacyImmutableObject.setField(beforeIO, 'anotherField', 'anotherValue');
|
||||
expect(afterIO).toBeSeriallyEqualTo({
|
||||
initialField: null,
|
||||
anotherField: 'anotherValue'
|
||||
});
|
||||
expect(afterIO).not.toBe(beforeIO);
|
||||
});
|
||||
|
||||
message = 'should recursively create distinct objects when deep copying';
|
||||
testDevAndProd(message, function() {
|
||||
var beforeIO = new LegacyImmutableObject({
|
||||
a: {b: 'b', c: {}, d: 'd', e: new LegacyImmutableObject({f: 'f'}) }
|
||||
});
|
||||
var afterIO = LegacyImmutableObject.setDeep(beforeIO, {
|
||||
a: {b: {}, c: 'C', e: {f: 'F', g: 'G'}, h: 'H'}
|
||||
});
|
||||
expect(afterIO).toBeSeriallyEqualTo({
|
||||
a: {b: {}, c: 'C', d: 'd', e: {f: 'F', g: 'G'}, h: 'H'}
|
||||
});
|
||||
expect(afterIO).not.toBe(beforeIO);
|
||||
expect(afterIO.a).not.toBe(beforeIO.a);
|
||||
expect(afterIO.a.e).not.toBe(beforeIO.a.e);
|
||||
});
|
||||
|
||||
testDevAndProd('should deep copy member immutability', function() {
|
||||
var beforeIO = new LegacyImmutableObject({
|
||||
a: {b: new LegacyImmutableObject({c: 'c'}), e: {f: 'f'}}
|
||||
});
|
||||
var afterIO = LegacyImmutableObject.setDeep(beforeIO, {
|
||||
a: {b: {d: 'D'}, e: new LegacyImmutableObject({g: 'G'})}
|
||||
});
|
||||
expect(afterIO).toBeSeriallyEqualTo({
|
||||
a: {b: {c: 'c', d: 'D'}, e: {f: 'f', g: 'G'}}
|
||||
});
|
||||
expect(afterIO instanceof LegacyImmutableObject).toBe(true);
|
||||
expect(afterIO.a.b instanceof LegacyImmutableObject).toBe(true);
|
||||
expect(afterIO.a.e instanceof LegacyImmutableObject).toBe(true);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user