Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

immutable-assign

Package Overview
Dependencies
Maintainers
1
Versions
51
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

immutable-assign - npm Package Compare versions

Comparing version 1.0.12 to 1.0.14

deploy/Libs/deep-freeze.js

2

deploy/iassign.d.ts

@@ -27,1 +27,3 @@

}
declare var iassign: ImmutableAssign.IIassign;

460

deploy/iassign.js
"use strict";
//import deepFreeze = require("deep-freeze");
try {
var deepFreeze = require("deep-freeze");
}
catch (ex) {
console.warn("Cannot load deep-freeze module, however you can still use iassign() function.");
}
var iassign = _iassign;
// Immutable Assign
function _iassign(obj, // Object to set property, it will not be modified.
getProp, // Function to get property to be updated. Must be pure function.
setProp, // Function to set property.
context, // (Optional) Context to be used in getProp().
option) {
if (option) {
option = extend({}, iassign, option);
(function (root, factory) {
if (typeof module === 'object' && typeof module.exports === 'object') {
var v = factory(require, exports);
if (v !== undefined)
module.exports = v;
}
else if (typeof define === 'function' && define.amd) {
define(["require", "exports"], factory);
}
else {
option = iassign;
// Browser globals (root is window)
var require_1 = function (name) {
if (name == "deep-freeze" && root.deepFreeze) {
return root.deepFreeze;
}
throw new Error("Unable to require: " + name);
};
root.iassign = factory(require_1, {});
}
if (deepFreeze && (option.freeze || option.freezeInput)) {
deepFreeze(obj);
})(this, function (require, exports) {
//import deepFreeze = require("deep-freeze");
try {
var deepFreeze = require("deep-freeze");
}
// Check if getProp() is valid
var value = getProp(obj, context);
var getPropFuncInfo = parseGetPropFuncInfo(getProp, option);
var accessorText = getPropFuncInfo.accessorText;
var propIndex = 0;
var propValue = undefined;
while (accessorText) {
var openBracketIndex = accessorText.indexOf("[");
var closeBracketIndex = accessorText.indexOf("]");
var dotIndex = accessorText.indexOf(".");
var propName = "";
var propNameSource = ePropNameSource.none;
// if (dotIndex == 0) {
// accessorText = accessorText.substr(dotIndex + 1);
// continue;
// }
if (openBracketIndex > -1 && closeBracketIndex <= -1) {
throw new Error("Found open bracket but not close bracket.");
catch (ex) {
console.warn("Cannot load deep-freeze module, however you can still use iassign() function.");
}
var iassign = _iassign;
// Immutable Assign
function _iassign(obj, // Object to set property, it will not be modified.
getProp, // Function to get property to be updated. Must be pure function.
setProp, // Function to set property.
context, // (Optional) Context to be used in getProp().
option) {
if (option) {
option = extend({}, iassign, option);
}
if (openBracketIndex <= -1 && closeBracketIndex > -1) {
throw new Error("Found close bracket but not open bracket.");
else {
option = iassign;
}
if (dotIndex > -1 && (dotIndex < openBracketIndex || openBracketIndex <= -1)) {
propName = accessorText.substr(0, dotIndex);
accessorText = accessorText.substr(dotIndex + 1);
propNameSource = ePropNameSource.beforeDot;
if (deepFreeze && (option.freeze || option.freezeInput)) {
deepFreeze(obj);
}
else if (openBracketIndex > -1 && (openBracketIndex < dotIndex || dotIndex <= -1)) {
if (openBracketIndex > 0) {
propName = accessorText.substr(0, openBracketIndex);
accessorText = accessorText.substr(openBracketIndex);
propNameSource = ePropNameSource.beforeBracket;
// Check if getProp() is valid
var value = getProp(obj, context);
var getPropFuncInfo = parseGetPropFuncInfo(getProp, option);
var accessorText = getPropFuncInfo.accessorText;
var propIndex = 0;
var propValue = undefined;
while (accessorText) {
var openBracketIndex = accessorText.indexOf("[");
var closeBracketIndex = accessorText.indexOf("]");
var dotIndex = accessorText.indexOf(".");
var propName = "";
var propNameSource = ePropNameSource.none;
// if (dotIndex == 0) {
// accessorText = accessorText.substr(dotIndex + 1);
// continue;
// }
if (openBracketIndex > -1 && closeBracketIndex <= -1) {
throw new Error("Found open bracket but not close bracket.");
}
if (openBracketIndex <= -1 && closeBracketIndex > -1) {
throw new Error("Found close bracket but not open bracket.");
}
if (dotIndex > -1 && (dotIndex < openBracketIndex || openBracketIndex <= -1)) {
propName = accessorText.substr(0, dotIndex);
accessorText = accessorText.substr(dotIndex + 1);
propNameSource = ePropNameSource.beforeDot;
}
else if (openBracketIndex > -1 && (openBracketIndex < dotIndex || dotIndex <= -1)) {
if (openBracketIndex > 0) {
propName = accessorText.substr(0, openBracketIndex);
accessorText = accessorText.substr(openBracketIndex);
propNameSource = ePropNameSource.beforeBracket;
}
else {
propName = accessorText.substr(openBracketIndex + 1, closeBracketIndex - 1);
accessorText = accessorText.substr(closeBracketIndex + 1);
propNameSource = ePropNameSource.inBracket;
}
}
else {
propName = accessorText.substr(openBracketIndex + 1, closeBracketIndex - 1);
accessorText = accessorText.substr(closeBracketIndex + 1);
propNameSource = ePropNameSource.inBracket;
propName = accessorText;
accessorText = "";
propNameSource = ePropNameSource.last;
}
}
else {
propName = accessorText;
accessorText = "";
propNameSource = ePropNameSource.last;
}
propName = propName.trim();
if (propName == "") {
continue;
}
//console.log(propName);
if (propIndex <= 0) {
propValue = quickCopy(obj);
if (!accessorText) {
propValue = setProp(propValue);
propName = propName.trim();
if (propName == "") {
continue;
}
obj = propValue;
}
else {
var prevPropValue = propValue;
if (propNameSource == ePropNameSource.inBracket && isNaN(propName)) {
if (propName[0] == "#") {
var quotedPropName = getPropFuncInfo.quotedTextInfos[propName];
if (!quotedPropName) {
throw new Error("Cannot find quoted text for " + quotedPropName);
}
propName = eval(quotedPropName);
//console.log(propName);
if (propIndex <= 0) {
propValue = quickCopy(obj);
if (!accessorText) {
propValue = setProp(propValue);
}
else {
var statement = "'use strict';\n";
if (getPropFuncInfo.objParameterName) {
statement += "var " + getPropFuncInfo.objParameterName + " = arguments[1];\n";
obj = propValue;
}
else {
var prevPropValue = propValue;
if (propNameSource == ePropNameSource.inBracket && isNaN(propName)) {
if (propName[0] == "#") {
var quotedPropName = getPropFuncInfo.quotedTextInfos[propName];
if (!quotedPropName) {
throw new Error("Cannot find quoted text for " + quotedPropName);
}
propName = eval(quotedPropName);
}
if (getPropFuncInfo.cxtParameterName) {
statement += "var " + getPropFuncInfo.cxtParameterName + " = arguments[2];\n";
else {
var statement = "'use strict';\n";
if (getPropFuncInfo.objParameterName) {
statement += "var " + getPropFuncInfo.objParameterName + " = arguments[1];\n";
}
if (getPropFuncInfo.cxtParameterName) {
statement += "var " + getPropFuncInfo.cxtParameterName + " = arguments[2];\n";
}
statement += "" + propName;
propName = evalStatement(statement, obj, context);
}
statement += "" + propName;
propName = evalStatement(statement, obj, context);
}
propValue = propValue[propName];
propValue = quickCopy(propValue);
if (!accessorText) {
propValue = setProp(propValue);
}
prevPropValue[propName] = propValue;
}
propValue = propValue[propName];
propValue = quickCopy(propValue);
if (!accessorText) {
propValue = setProp(propValue);
}
prevPropValue[propName] = propValue;
//console.log(propValue);
propIndex++;
}
//console.log(propValue);
propIndex++;
}
if (deepFreeze && (option.freeze || option.freezeOutput)) {
deepFreeze(obj);
}
return obj;
}
var ePropNameSource;
(function (ePropNameSource) {
ePropNameSource[ePropNameSource["none"] = 0] = "none";
ePropNameSource[ePropNameSource["beforeDot"] = 1] = "beforeDot";
ePropNameSource[ePropNameSource["beforeBracket"] = 2] = "beforeBracket";
ePropNameSource[ePropNameSource["inBracket"] = 3] = "inBracket";
ePropNameSource[ePropNameSource["last"] = 4] = "last";
})(ePropNameSource || (ePropNameSource = {}));
function parseGetPropFuncInfo(func, option) {
var funcText = func.toString();
var matches = /\(([^\)]*)\)/.exec(funcText);
var objParameterName = undefined;
var cxtParameterName = undefined;
if (matches) {
var parametersText = matches[1];
var parameters = parametersText.split(",");
objParameterName = parameters[0];
cxtParameterName = parameters[1];
}
if (objParameterName) {
objParameterName = objParameterName.trim();
}
if (cxtParameterName) {
cxtParameterName = cxtParameterName.trim();
}
var bodyText = funcText.substring(funcText.indexOf("{") + 1, funcText.lastIndexOf("}"));
var accessorTextInfo = getAccessorTextInfo(bodyText, option);
return {
objParameterName: objParameterName,
cxtParameterName: cxtParameterName,
bodyText: bodyText,
accessorText: accessorTextInfo.accessorText,
quotedTextInfos: accessorTextInfo.quotedTextInfos,
};
}
function getAccessorTextInfo(bodyText, option) {
var returnIndex = bodyText.indexOf("return ");
if (!option.disableAllCheck && !option.disableHasReturnCheck) {
if (returnIndex <= -1) {
throw new Error("getProp() function has no 'return' keyword.");
if (deepFreeze && (option.freeze || option.freezeOutput)) {
deepFreeze(obj);
}
return obj;
}
if (!option.disableAllCheck && !option.disableExtraStatementCheck) {
var otherBodyText = bodyText.substr(0, returnIndex).trim();
if (otherBodyText != "") {
throw new Error("getProp() function has statements other than 'return': " + otherBodyText);
var ePropNameSource;
(function (ePropNameSource) {
ePropNameSource[ePropNameSource["none"] = 0] = "none";
ePropNameSource[ePropNameSource["beforeDot"] = 1] = "beforeDot";
ePropNameSource[ePropNameSource["beforeBracket"] = 2] = "beforeBracket";
ePropNameSource[ePropNameSource["inBracket"] = 3] = "inBracket";
ePropNameSource[ePropNameSource["last"] = 4] = "last";
})(ePropNameSource || (ePropNameSource = {}));
function parseGetPropFuncInfo(func, option) {
var funcText = func.toString();
var matches = /\(([^\)]*)\)/.exec(funcText);
var objParameterName = undefined;
var cxtParameterName = undefined;
if (matches) {
var parametersText = matches[1];
var parameters = parametersText.split(",");
objParameterName = parameters[0];
cxtParameterName = parameters[1];
}
if (objParameterName) {
objParameterName = objParameterName.trim();
}
if (cxtParameterName) {
cxtParameterName = cxtParameterName.trim();
}
var bodyText = funcText.substring(funcText.indexOf("{") + 1, funcText.lastIndexOf("}"));
var accessorTextInfo = getAccessorTextInfo(bodyText, option);
return {
objParameterName: objParameterName,
cxtParameterName: cxtParameterName,
bodyText: bodyText,
accessorText: accessorTextInfo.accessorText,
quotedTextInfos: accessorTextInfo.quotedTextInfos,
};
}
var accessorText = bodyText.substr(returnIndex + 7).trim();
if (accessorText[accessorText.length - 1] == ";") {
accessorText = accessorText.substring(0, accessorText.length - 1);
}
accessorText = accessorText.trim();
return parseTextInQuotes(accessorText, option);
}
function parseTextInQuotes(accessorText, option) {
var quotedTextInfos = {};
var index = 0;
while (true) {
var singleQuoteIndex = accessorText.indexOf("'");
var doubleQuoteIndex = accessorText.indexOf('"');
var varName = "#" + index++;
if (singleQuoteIndex <= -1 && doubleQuoteIndex <= -1)
break;
var matches = undefined;
var quoteIndex = void 0;
if (doubleQuoteIndex > -1 && (doubleQuoteIndex < singleQuoteIndex || singleQuoteIndex <= -1)) {
matches = /("[^"\\]*(?:\\.[^"\\]*)*")/.exec(accessorText);
quoteIndex = doubleQuoteIndex;
function getAccessorTextInfo(bodyText, option) {
var returnIndex = bodyText.indexOf("return ");
if (!option.disableAllCheck && !option.disableHasReturnCheck) {
if (returnIndex <= -1) {
throw new Error("getProp() function has no 'return' keyword.");
}
}
else if (singleQuoteIndex > -1 && (singleQuoteIndex < doubleQuoteIndex || doubleQuoteIndex <= -1)) {
matches = /('[^'\\]*(?:\\.[^'\\]*)*')/.exec(accessorText);
quoteIndex = singleQuoteIndex;
if (!option.disableAllCheck && !option.disableExtraStatementCheck) {
var otherBodyText = bodyText.substr(0, returnIndex).trim();
if (otherBodyText != "") {
throw new Error("getProp() function has statements other than 'return': " + otherBodyText);
}
}
if (matches) {
quotedTextInfos[varName] = matches[1];
accessorText =
accessorText.substr(0, quoteIndex) +
varName +
accessorText.substr(matches.index + matches[1].length);
var accessorText = bodyText.substr(returnIndex + 7).trim();
if (accessorText[accessorText.length - 1] == ";") {
accessorText = accessorText.substring(0, accessorText.length - 1);
}
else {
throw new Error("Invalid text in quotes: " + accessorText);
accessorText = accessorText.trim();
return parseTextInQuotes(accessorText, option);
}
function parseTextInQuotes(accessorText, option) {
var quotedTextInfos = {};
var index = 0;
while (true) {
var singleQuoteIndex = accessorText.indexOf("'");
var doubleQuoteIndex = accessorText.indexOf('"');
var varName = "#" + index++;
if (singleQuoteIndex <= -1 && doubleQuoteIndex <= -1)
break;
var matches = undefined;
var quoteIndex = void 0;
if (doubleQuoteIndex > -1 && (doubleQuoteIndex < singleQuoteIndex || singleQuoteIndex <= -1)) {
matches = /("[^"\\]*(?:\\.[^"\\]*)*")/.exec(accessorText);
quoteIndex = doubleQuoteIndex;
}
else if (singleQuoteIndex > -1 && (singleQuoteIndex < doubleQuoteIndex || doubleQuoteIndex <= -1)) {
matches = /('[^'\\]*(?:\\.[^'\\]*)*')/.exec(accessorText);
quoteIndex = singleQuoteIndex;
}
if (matches) {
quotedTextInfos[varName] = matches[1];
accessorText =
accessorText.substr(0, quoteIndex) +
varName +
accessorText.substr(matches.index + matches[1].length);
}
else {
throw new Error("Invalid text in quotes: " + accessorText);
}
}
return {
accessorText: accessorText,
quotedTextInfos: quotedTextInfos,
};
}
return {
accessorText: accessorText,
quotedTextInfos: quotedTextInfos,
};
}
function quickCopy(value) {
if (value != undefined && !(value instanceof Date)) {
if (value instanceof Array) {
return value.slice();
function quickCopy(value) {
if (value != undefined && !(value instanceof Date)) {
if (value instanceof Array) {
return value.slice();
}
else if (typeof (value) === "object") {
return extend({}, value);
}
}
else if (typeof (value) === "object") {
return extend({}, value);
return value;
}
function extend(destination) {
var sources = [];
for (var _i = 1; _i < arguments.length; _i++) {
sources[_i - 1] = arguments[_i];
}
}
return value;
}
function extend(destination) {
var sources = [];
for (var _i = 1; _i < arguments.length; _i++) {
sources[_i - 1] = arguments[_i];
}
for (var _a = 0, sources_1 = sources; _a < sources_1.length; _a++) {
var source = sources_1[_a];
for (var key in source) {
var value = source[key];
if (value !== undefined) {
destination[key] = value;
for (var _a = 0, sources_1 = sources; _a < sources_1.length; _a++) {
var source = sources_1[_a];
for (var key in source) {
if (!Object.prototype.hasOwnProperty.call(source, key)) {
continue;
}
var value = source[key];
if (value !== undefined) {
destination[key] = value;
}
}
}
return destination;
}
return destination;
}
function evalStatement() {
return eval(arguments[0]);
}
module.exports = iassign;
function evalStatement() {
return eval(arguments[0]);
}
// function isTextInQuote(text: string): boolean {
// let quoteMarks = ["'", '"'];
// for (let mark of quoteMarks) {
// if (text[0] == mark && text[text.length-1] == mark) {
// return true;
// }
// }
// return false;
// }
// function extractTextInQuote(text: string): string {
// let quoteMarks = ["'", '"'];
// for (let mark of quoteMarks) {
// if (text[0] == mark) {
// let regex = new RegExp(`^[${mark}]([^${mark}]*)[${mark}]$`);
// let match = regex.exec(text);
// if (match) {
// return match[1];
// }
// }
// }
// return undefined;
// }
return iassign;
});
//declare var iassign: IIassign;
//export = iassign;
{
"name": "immutable-assign",
"version": "1.0.12",
"version": "1.0.14",
"description": "",

@@ -8,2 +8,3 @@ "main": "src/iassign.js",

"test": "node_modules\\.bin\\jasmine",
"test-karma": "node_modules\\.bin\\karma start",
"cover": "node_modules\\.bin\\istanbul cover node_modules\\jasmine\\bin\\jasmine.js",

@@ -30,3 +31,3 @@ "build": "gulp"

"dependencies": {},
"optionalDependencies":{
"optionalDependencies": {
"deep-freeze": "0.0.1"

@@ -41,2 +42,5 @@ },

"jasmine": "^2.4.1",
"karma": "^1.1.2",
"karma-chrome-launcher": "^1.0.1",
"karma-jasmine": "^1.0.2",
"lodash": "^4.13.1",

@@ -46,2 +50,2 @@ "merge2": "^1.0.2",

}
}
}

@@ -7,7 +7,8 @@ # immutable-assign (iassign.js)

* Most immutable JavaScript libraries try to encapsulate the data, and provide proprietary APIs to work with the data. They are more verbose than normal JavaScript syntax. E.g., map1.get('b') vs map1.b, nested2.getIn(['a', 'b', 'd']) vs nested2.a.b.d, etc.
* Most immutable JavaScript libraries try to encapsulate the data and provide proprietary APIs to work with the data. They are more verbose than normal JavaScript syntax. E.g., map1.get('b') vs map1.b, nested2.getIn(['a', 'b', 'd']) vs nested2.a.b.d, etc.
* Encapsulated data is no more POJO, therefore cannot be easily used with other libraries, e.g., lodash, underscore, etc.
* The use of most immutable libraries will leak themselves throughout your entire application (stores and components), however, it should have been encapsulated inside the stores where you update your states. This is a pain when you need to change to another immutable library that has its own API.
* [seamless-immutable](https://github.com/rtfeldman/seamless-immutable) address some of above issues when reading the properties, but still use verbose APIs to write properties.
* [Immutability Helpers](https://facebook.github.io/react/docs/update.html) allows us work with POJO, but it has still introduced some magic keywords, such as $set, $push, etc.
* Most importantly (in my opinion), we lost TypeScript type checking. E.g., when calling nested2.getIn(['a', 'b', 'd']), TypeScript won't be able to warn me if I changed property 'd' to 'e'.
* In addition, we lost TypeScript type checking. E.g., when calling nested2.getIn(['a', 'b', 'd']), TypeScript won't be able to warn me if I changed property 'd' to 'e'.

@@ -14,0 +15,0 @@ This library has only one method **iassign()**, which accept a POJO object and return you a new POJO object with specific property updated. I have added some options to freeze input and output using [deep-freeze](https://github.com/substack/deep-freeze), which can be used in development to make sure they don't change unintentionally by us or the 3rd party libraries.

"use strict";
var iassign = require("../src/iassign");
var deepFreeze = require("deep-freeze");
var _ = require("lodash");
// Uncomment following line to test code coverage: npm run cover
// iassign.disableExtraStatementCheck = true;
(function (root, factory) {
if (typeof module === 'object' && typeof module.exports === 'object') {
var v = factory(require, exports); if (v !== undefined) module.exports = v;
}
else if (typeof define === 'function' && define.amd) {
define(["require", "exports"], factory);
} else {
// Browser globals (root is window)
let require = (name) => {
if (name == "deep-freeze" && root.deepFreeze) {
return root.deepFreeze;
}
describe("Test 2", function () {
beforeEach(function () {
});
it("No semicolon at the end", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
if (name == "lodash" && root._) {
return root._;
}
var o2 = iassign(o1, function (o) { return o.a.b.c[0][0] }, function (ci) { ci.d++; return ci; });
if (name.indexOf("iassign") > -1 && root.iassign) {
return root.iassign;
}
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).not.toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).not.toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[0][0].d).not.toBe(o1.a.b.c[0][0].d);
throw new Error("Unable to require: " + name);
}
expect(o2.a.b.c[0][0].d).toBe(12);
});
factory(require, {});
}
})(this, function (require, exports) {
var iassign = require("../src/iassign");
var deepFreeze = require("deep-freeze");
var _ = require("lodash");
it("Spaces and new lines between property names", function () {
var o1 = { a: { "prop b": { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
var o2 = iassign(o1, function (o) {
return o
.
a
[
"prop b"
]
.
c
[
0
]
[
0
]
// Uncomment following line to test code coverage: npm run cover
// iassign.disableExtraStatementCheck = true;
}, function (ci) { ci.d++; return ci; });
describe("Test 2", function () {
beforeEach(function () {
});
it("No semicolon at the end", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a["prop b"]).not.toBe(o1.a["prop b"]);
expect(o2.a["prop b"].c).not.toBe(o1.a["prop b"].c);
expect(o2.a["prop b"].c[0]).not.toBe(o1.a["prop b"].c[0]);
expect(o2.a["prop b"].c[0][0]).not.toBe(o1.a["prop b"].c[0][0]);
expect(o2.a["prop b"].c[0][0].d).not.toBe(o1.a["prop b"].c[0][0].d);
var o2 = iassign(o1, function (o) { return o.a.b.c[0][0] }, function (ci) { ci.d++; return ci; });
expect(o2.a["prop b"].c[0][0].d).toBe(12);
});
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).not.toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).not.toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[0][0].d).not.toBe(o1.a.b.c[0][0].d);
it("Access array using context parameter", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
var p1 = { a: 0 };
expect(o2.a.b.c[0][0].d).toBe(12);
});
var o2 = iassign(
o1,
function (o, ctx) {
it("Spaces and new lines between property names", function () {
var o1 = { a: { "prop b": { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
var o2 = iassign(o1, function (o) {
return o
.
a
[
"prop b"
]
.
b
.
c
[
ctx
.
p1
.
a
0
]

@@ -86,469 +76,509 @@ [

]
;
},
function (ci) { ci.d++; return ci; },
{ p1: p1 }
);
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).not.toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).not.toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[0][0].d).not.toBe(o1.a.b.c[0][0].d);
expect(o2.a.b.c[0][0].d).toBe(12);
});
it("Access array using context parameter 2", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
var p1 = { a: 0 };
}, function (ci) { ci.d++; return ci; });
var o2 = iassign(
o1,
function (o, c) {
return o
.
a
.
b
.
c
[
c
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a["prop b"]).not.toBe(o1.a["prop b"]);
expect(o2.a["prop b"].c).not.toBe(o1.a["prop b"].c);
expect(o2.a["prop b"].c[0]).not.toBe(o1.a["prop b"].c[0]);
expect(o2.a["prop b"].c[0][0]).not.toBe(o1.a["prop b"].c[0][0]);
expect(o2.a["prop b"].c[0][0].d).not.toBe(o1.a["prop b"].c[0][0].d);
expect(o2.a["prop b"].c[0][0].d).toBe(12);
});
it("Access array using context parameter", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
var p1 = { a: 0 };
var o2 = iassign(
o1,
function (o, ctx) {
return o
.
p1
a
.
b
.
c
[
ctx
.
p1
.
a
]
[
0
]
;
},
function (ci) { ci.d++; return ci; },
{ p1: p1 }
);
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).not.toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).not.toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[0][0].d).not.toBe(o1.a.b.c[0][0].d);
expect(o2.a.b.c[0][0].d).toBe(12);
});
it("Access array using context parameter 2", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
var p1 = { a: 0 };
var o2 = iassign(
o1,
function (o, c) {
return o
.
a
]
[
0
]
;
},
function (ci) { ci.d++; return ci; },
{ p1: p1 }
);
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).not.toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).not.toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[0][0].d).not.toBe(o1.a.b.c[0][0].d);
expect(o2.a.b.c[0][0].d).toBe(12);
});
.
b
.
c
[
c
.
p1
.
a
]
[
0
]
;
},
function (ci) { ci.d++; return ci; },
{ p1: p1 }
);
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).not.toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).not.toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[0][0].d).not.toBe(o1.a.b.c[0][0].d);
expect(o2.a.b.c[0][0].d).toBe(12);
});
it("Access array using context parameter 3", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
var p1 = { a: 0 };
it("Access array using context parameter 3", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
var p1 = { a: 0 };
var o2 = iassign(
o1,
function (o, context) {
return o
.
a
.
b
.
c
[
context
var o2 = iassign(
o1,
function (o, context) {
return o
.
p1
a
.
a
]
[
0
]
;
},
function (ci) { ci.d++; return ci; },
{ p1: p1 }
);
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).not.toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).not.toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[0][0].d).not.toBe(o1.a.b.c[0][0].d);
expect(o2.a.b.c[0][0].d).toBe(12);
});
b
.
c
[
context
.
p1
.
a
]
[
0
]
;
},
function (ci) { ci.d++; return ci; },
{ p1: p1 }
);
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).not.toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).not.toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[0][0].d).not.toBe(o1.a.b.c[0][0].d);
expect(o2.a.b.c[0][0].d).toBe(12);
});
it("Access array using context parameter 4", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
var p1 = { a: 0 };
it("Access array using context parameter 4", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
var p1 = { a: 0 };
var o2 = iassign(
o1,
function (
o
,
b
) {
return o
.
a
.
var o2 = iassign(
o1,
function (
o
,
b
.
c
[
b
) {
return o
.
p1
a
.
a
]
[
0
]
;
},
function (ci) { ci.d++; return ci; },
{ p1: p1 }
);
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).not.toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).not.toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[0][0].d).not.toBe(o1.a.b.c[0][0].d);
expect(o2.a.b.c[0][0].d).toBe(12);
});
b
.
c
[
b
.
p1
.
a
]
[
0
]
;
},
function (ci) { ci.d++; return ci; },
{ p1: p1 }
);
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).not.toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).not.toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[0][0].d).not.toBe(o1.a.b.c[0][0].d);
expect(o2.a.b.c[0][0].d).toBe(12);
});
it("Access array using context parameter 5", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } }, a2: 0 };
deepFreeze(o1);
var p1 = { a: 0 };
it("Access array using context parameter 5", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } }, a2: 0 };
deepFreeze(o1);
var p1 = { a: 0 };
var o2 = iassign(
o1,
function (
o
) {
return o
.
a
.
b
.
c
[
var o2 = iassign(
o1,
function (
o
) {
return o
.
a2
]
[
0
]
;
},
function (ci) { ci.d++; return ci; },
{ p1: p1 }
);
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).not.toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).not.toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[0][0].d).not.toBe(o1.a.b.c[0][0].d);
expect(o2.a.b.c[0][0].d).toBe(12);
});
a
.
b
.
c
[
o
.
a2
]
[
0
]
;
},
function (ci) { ci.d++; return ci; },
{ p1: p1 }
);
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).not.toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).not.toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[0][0].d).not.toBe(o1.a.b.c[0][0].d);
expect(o2.a.b.c[0][0].d).toBe(12);
});
xit("extra '[' should throw exception", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
xit("extra '[' should throw exception", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
expect(() => {
var o2 = iassign(o1, function (o) {
return o.a.b.c[0]["["]
}, function (ci) { ci.d++; return ci; });
}).toThrow(/Found open bracket but not close bracket/);
});
expect(() => {
var o2 = iassign(o1, function (o) {
return o.a.b.c[0]["["]
}, function (ci) { ci.d++; return ci; });
}).toThrow(/Found open bracket but not close bracket/);
});
xit("extra ']' should throw exception", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
xit("extra ']' should throw exception", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
expect(() => {
var o2 = iassign(o1, function (o) {
return o.a.b.c[0]["]"]
}, function (ci) { ci.d++; return ci; });
}).toThrow(/Found close bracket but not open bracket/);
});
expect(() => {
var o2 = iassign(o1, function (o) {
return o.a.b.c[0]["]"]
}, function (ci) { ci.d++; return ci; });
}).toThrow(/Found close bracket but not open bracket/);
});
it("getProp() function without return should throw exception", function () {
if (iassign.disableHasReturnCheck)
return;
it("getProp() function without return should throw exception", function () {
if (iassign.disableHasReturnCheck)
return;
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
expect(() => {
var o2 = iassign(o1, function (o) {
o.a.b.c[0][0]
}, function (ci) { ci.d++; return ci; });
}).toThrowError(/has no 'return' keyword/);
});
expect(() => {
var o2 = iassign(o1, function (o) {
o.a.b.c[0][0]
}, function (ci) { ci.d++; return ci; });
}).toThrowError(/has no 'return' keyword/);
});
it("getProp() function has other statements should throw exception", function () {
if (iassign.disableExtraStatementCheck)
return;
it("getProp() function has other statements should throw exception", function () {
if (iassign.disableExtraStatementCheck)
return;
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
expect(() => {
var o2 = iassign(o1, function (o) {
var text = "unexpected text";
return o.a.b.c[0][0]
}, function (ci) { ci.d++; return ci; });
}).toThrowError(/has statements other than 'return'/);
});
expect(() => {
var o2 = iassign(o1, function (o) {
var text = "unexpected text";
return o.a.b.c[0][0]
}, function (ci) { ci.d++; return ci; });
}).toThrowError(/has statements other than 'return'/);
});
it("Access array item", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }]], c2: {} }, b2: {} }, a2: {} };
deepFreeze(o1); // Ensure o1 is not changed, for testing only
it("Access array item", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }]], c2: {} }, b2: {} }, a2: {} };
deepFreeze(o1); // Ensure o1 is not changed, for testing only
//
// Calling iassign() to increment o1.a.b.c[0][0].d
//
var o2 = iassign(
o1,
function (o) { return o.a.b.c[0][0]; },
function (ci) { ci.d++; return ci; }
);
//
// Calling iassign() to increment o1.a.b.c[0][0].d
//
var o2 = iassign(
o1,
function (o) { return o.a.b.c[0][0]; },
function (ci) { ci.d++; return ci; }
);
//
// Jasmine Tests
//
//
// Jasmine Tests
//
// expect o1 has not been changed
expect(o1).toEqual({ a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }]], c2: {} }, b2: {} }, a2: {} });
// expect o1 has not been changed
expect(o1).toEqual({ a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }]], c2: {} }, b2: {} }, a2: {} });
// expect o2 inner property has been updated.
expect(o2.a.b.c[0][0].d).toBe(12);
// expect o2 inner property has been updated.
expect(o2.a.b.c[0][0].d).toBe(12);
// expect object graph for changed property in o2 is now different from (!==) o1.
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).not.toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).not.toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[0][0].d).not.toBe(o1.a.b.c[0][0].d);
// expect object graph for changed property in o2 is now different from (!==) o1.
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).not.toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).not.toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[0][0].d).not.toBe(o1.a.b.c[0][0].d);
// expect object graph for unchanged property in o2 is still equal to (===) o1.
expect(o2.a2).toBe(o1.a2);
expect(o2.a.b2).toBe(o1.a.b2);
expect(o2.a.b.c2).toBe(o1.a.b.c2);
expect(o2.a.b.c[0][0].e).toBe(o1.a.b.c[0][0].e);
expect(o2.a.b.c[1][0]).toBe(o1.a.b.c[1][0]);
});
// expect object graph for unchanged property in o2 is still equal to (===) o1.
expect(o2.a2).toBe(o1.a2);
expect(o2.a.b2).toBe(o1.a.b2);
expect(o2.a.b.c2).toBe(o1.a.b.c2);
expect(o2.a.b.c[0][0].e).toBe(o1.a.b.c[0][0].e);
expect(o2.a.b.c[1][0]).toBe(o1.a.b.c[1][0]);
});
it("Access array 1", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }]], c2: {} }, b2: {} }, a2: {} };
deepFreeze(o1); // Ensure o1 is not changed, for testing only
it("Access array 1", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }]], c2: {} }, b2: {} }, a2: {} };
deepFreeze(o1); // Ensure o1 is not changed, for testing only
//
// Calling iassign() to push new item to o1.a.b.c[1]
//
var o2 = iassign(
o1,
function (o) { return o.a.b.c[1]; },
function (c) { c.push(101); return c; }
);
//
// Calling iassign() to push new item to o1.a.b.c[1]
//
var o2 = iassign(
o1,
function (o) { return o.a.b.c[1]; },
function (c) { c.push(101); return c; }
);
//
// Jasmine Tests
//
//
// Jasmine Tests
//
// expect o1 has not been changed
expect(o1).toEqual({ a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }]], c2: {} }, b2: {} }, a2: {} });
// expect o1 has not been changed
expect(o1).toEqual({ a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }]], c2: {} }, b2: {} }, a2: {} });
// expect o2 inner property has been updated.
expect(o2.a.b.c[1][1]).toBe(101);
// expect o2 inner property has been updated.
expect(o2.a.b.c[1][1]).toBe(101);
// expect object graph for changed property in o2 is now different from (!==) o1.
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[1]).not.toBe(o1.a.b.c[1]);
// expect object graph for changed property in o2 is now different from (!==) o1.
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[1]).not.toBe(o1.a.b.c[1]);
// expect object graph for unchanged property in o2 is still equal to (===) o1.
expect(o2.a2).toBe(o1.a2);
expect(o2.a.b2).toBe(o1.a.b2);
expect(o2.a.b.c2).toBe(o1.a.b.c2);
expect(o2.a.b.c[0]).toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[1][0]).toBe(o1.a.b.c[1][0]);
});
// expect object graph for unchanged property in o2 is still equal to (===) o1.
expect(o2.a2).toBe(o1.a2);
expect(o2.a.b2).toBe(o1.a.b2);
expect(o2.a.b.c2).toBe(o1.a.b.c2);
expect(o2.a.b.c[0]).toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[1][0]).toBe(o1.a.b.c[1][0]);
});
it("Access array using context parameter", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }]] } } };
deepFreeze(o1); // Ensure o1 is not changed, for testing only
it("Access array using context parameter", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }]] } } };
deepFreeze(o1); // Ensure o1 is not changed, for testing only
//
// Calling iassign() to push increment to o1.a.b.c[0].d
//
var p1 = { a: 0 };
var o2 = iassign(
o1,
function (o, ctx) { return o.a.b.c[ctx.p1.a][0]; },
function (ci) { ci.d++; return ci; },
{ p1: p1 }
);
//
// Calling iassign() to push increment to o1.a.b.c[0].d
//
var p1 = { a: 0 };
var o2 = iassign(
o1,
function (o, ctx) { return o.a.b.c[ctx.p1.a][0]; },
function (ci) { ci.d++; return ci; },
{ p1: p1 }
);
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).not.toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).not.toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[0][0].d).not.toBe(o1.a.b.c[0][0].d);
expect(o2.a.b.c[0][0].d).toBe(12);
});
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).not.toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).not.toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[0][0].d).not.toBe(o1.a.b.c[0][0].d);
expect(o2.a.b.c[0][0].d).toBe(12);
});
it("Update array using lodash 2", function () {
var o1 = { a: { b: { c: [1, 2, 3] } } };
it("Update array using lodash 2", function () {
var o1 = { a: { b: { c: [1, 2, 3] } } };
deepFreeze(o1); // Ensure o1 is not changed, for testing only
deepFreeze(o1); // Ensure o1 is not changed, for testing only
//
// Calling iassign() and _.map() to increment to every item in "c" array
//
var o2 = iassign(
o1,
function (o) { return o.a.b.c; },
function (c) {
return _.map(c, function (i) { return i + 1; });
}
);
//
// Calling iassign() and _.map() to increment to every item in "c" array
//
var o2 = iassign(
o1,
function (o) { return o.a.b.c; },
function (c) {
return _.map(c, function (i) { return i + 1; });
}
);
// expect o1 has not been changed
expect(o1).toEqual({ a: { b: { c: [1, 2, 3] } } });
// expect o1 has not been changed
expect(o1).toEqual({ a: { b: { c: [1, 2, 3] } } });
// expect o2.a.b.c has been updated.
expect(o2.a.b.c).toEqual([2, 3, 4]);
// expect o2.a.b.c has been updated.
expect(o2.a.b.c).toEqual([2, 3, 4]);
// expect object graph for changed property in o2 is now different from (!==) o1.
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).not.toBe(o1.a.b.c[0]);
});
// expect object graph for changed property in o2 is now different from (!==) o1.
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).not.toBe(o1.a.b.c[0]);
});
it("Test root is an array, and try to update root array", function () {
var o1 = [{ d: 11, e: 12 }, { d: 13, e: 14 }, { d: 21, e: 22 }];
deepFreeze(o1); // Ensure o1 is not changed, for testing only
it("Test root is an array, and try to update root array", function () {
var o1 = [{ d: 11, e: 12 }, { d: 13, e: 14 }, { d: 21, e: 22 }];
deepFreeze(o1); // Ensure o1 is not changed, for testing only
//
// Calling iassign() and _.map() to increment to every item in "c" array
//
var o2 = iassign(
o1,
function (o) { return o
; },
function (o) {
return _.map(o, function (item, index) {
if (index < 2) {
item = _.cloneDeep(item);
item.d++;
}
return item;
//
// Calling iassign() and _.map() to increment to every item in "c" array
//
var o2 = iassign(
o1,
function (o) { return o
; },
function (o) {
return _.map(o, function (item, index) {
if (index < 2) {
item = _.cloneDeep(item);
item.d++;
}
return item;
});
});
});
// expect o1 has not been changed
expect(o1).toEqual([{ d: 11, e: 12 }, { d: 13, e: 14 }, { d: 21, e: 22 }]);
// expect o1 has not been changed
expect(o1).toEqual([{ d: 11, e: 12 }, { d: 13, e: 14 }, { d: 21, e: 22 }]);
// expect o2.a.b.c has been updated.
expect(o2).toEqual([{ d: 12, e: 12 }, { d: 14, e: 14 }, { d: 21, e: 22 }]);
// expect o2.a.b.c has been updated.
expect(o2).toEqual([{ d: 12, e: 12 }, { d: 14, e: 14 }, { d: 21, e: 22 }]);
// expect object graph for changed property in o2 is now different from (!==) o1.
expect(o2).not.toBe(o1);
expect(o2[0]).not.toBe(o1[0]);
expect(o2[1]).not.toBe(o1[1]);
// expect object graph for changed property in o2 is now different from (!==) o1.
expect(o2).not.toBe(o1);
expect(o2[0]).not.toBe(o1[0]);
expect(o2[1]).not.toBe(o1[1]);
// expect object graph for unchanged property in o2 is still equal to (===) o1.
expect(o2[2]).toBe(o1[2]);
});
// expect object graph for unchanged property in o2 is still equal to (===) o1.
expect(o2[2]).toBe(o1[2]);
});
it("Test root is an object, and try to update root object", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }]], c2: {} }, b2: {} }, a2: {} };
deepFreeze(o1); // Ensure o1 is not changed, for testing only
it("Test root is an object, and try to update root object", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }]], c2: {} }, b2: {} }, a2: {} };
deepFreeze(o1); // Ensure o1 is not changed, for testing only
var o2 = iassign(
o1,
function (o) { return o },
function (o) { o.a = { b: 1 }; return o; });
// expect o1 has not been changed
expect(o1).toEqual({ a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }]], c2: {} }, b2: {} }, a2: {} });
var o2 = iassign(
o1,
function (o) { return o },
function (o) { o.a = { b: 1 }; return o; });
// expect o1 has not been changed
expect(o1).toEqual({ a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }]], c2: {} }, b2: {} }, a2: {} });
// expect o2 inner property has been updated.
expect(o2).toEqual({ a: { b: 1 }, a2: {} });
// expect o2 inner property has been updated.
expect(o2).toEqual({ a: { b: 1 }, a2: {} });
// expect object graph for changed property in o2 is now different from (!==) o1.
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
// expect object graph for changed property in o2 is now different from (!==) o1.
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
// expect object graph for unchanged property in o2 is still equal to (===) o1.
expect(o2.a2).toBe(o1.a2);
});
// expect object graph for unchanged property in o2 is still equal to (===) o1.
expect(o2.a2).toBe(o1.a2);
});
it("Access object property using string 4", function () {
var propBName = "p\\r\"o.p t[] e.s't\'B";
var propCName = "h\\e'llo w\'or\"ld";
var propDName = 'h\\e"llo w\"or\'ld';
var propEName = 'p\\r\'o.p t[] e.s"t\"B';
var o1 = { a: (_a = {}, _a[propBName] = (_b = {}, _b[propCName] = (_c = {}, _c[propDName] = (_d = {}, _d[propEName] = [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]], _d), _c), _b), _a) };
deepFreeze(o1);
var o2 = iassign(o1, function (o) { return o
.
a
[
"p\\r\"o.p t[] e.s't\'B"
]
[
"h\\e'llo w\'or\"ld"
]
[
'h\\e"llo w\"or\'ld'
]
it("Access object property using string 4", function () {
var propBName = "p\\r\"o.p t[] e.s't\'B";
var propCName = "h\\e'llo w\'or\"ld";
var propDName = 'h\\e"llo w\"or\'ld';
var propEName = 'p\\r\'o.p t[] e.s"t\"B';
var o1 = { a: (_a = {}, _a[propBName] = (_b = {}, _b[propCName] = (_c = {}, _c[propDName] = (_d = {}, _d[propEName] = [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]], _d), _c), _b), _a) };
deepFreeze(o1);
var o2 = iassign(o1, function (o) { return o
.
a
[
"p\\r\"o.p t[] e.s't\'B"
]
[
"h\\e'llo w\'or\"ld"
]
[
'p\\r\'o.p t[] e.s"t\"B'
]
'h\\e"llo w\"or\'ld'
]
[
"1"
]
[
0
]
.
d
; }, function (d) { return d + 1; });
expect(o2.a[propBName][propCName][propDName][propEName][1][0].d).toBe(22);
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a[propBName]).not.toBe(o1.a[propBName]);
expect(o2.a[propBName][propCName]).not.toBe(o1.a[propBName][propCName]);
expect(o2.a[propBName][propCName][propDName]).not.toBe(o1.a[propBName][propCName][propDName]);
expect(o2.a[propBName][propCName][propDName][propEName]).not.toBe(o1.a[propBName][propCName][propDName][propEName]);
expect(o2.a[propBName][propCName][propDName][propEName][1]).not.toBe(o1.a[propBName][propCName][propDName][propEName][1]);
expect(o2.a[propBName][propCName][propDName][propEName][1][0]).not.toBe(o1.a[propBName][propCName][propDName][propEName][1][0]);
expect(o2.a[propBName][propCName][propDName][propEName][1][0].d).not.toBe(o1.a[propBName][propCName][propDName][propEName][1][0].d);
var _a, _b, _c, _d;
'p\\r\'o.p t[] e.s"t\"B'
]
[
"1"
]
[
0
]
.
d
; }, function (d) { return d + 1; });
expect(o2.a[propBName][propCName][propDName][propEName][1][0].d).toBe(22);
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a[propBName]).not.toBe(o1.a[propBName]);
expect(o2.a[propBName][propCName]).not.toBe(o1.a[propBName][propCName]);
expect(o2.a[propBName][propCName][propDName]).not.toBe(o1.a[propBName][propCName][propDName]);
expect(o2.a[propBName][propCName][propDName][propEName]).not.toBe(o1.a[propBName][propCName][propDName][propEName]);
expect(o2.a[propBName][propCName][propDName][propEName][1]).not.toBe(o1.a[propBName][propCName][propDName][propEName][1]);
expect(o2.a[propBName][propCName][propDName][propEName][1][0]).not.toBe(o1.a[propBName][propCName][propDName][propEName][1][0]);
expect(o2.a[propBName][propCName][propDName][propEName][1][0].d).not.toBe(o1.a[propBName][propCName][propDName][propEName][1][0].d);
var _a, _b, _c, _d;
});
});
});
"use strict";
var iassign = require("../src/iassign");
var deepFreeze = require("deep-freeze");
var _ = require("lodash");
describe("Test", function () {
beforeEach(function () {
});
it("Access array item", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]], c2: {} }, b2: {} }, a2: {} };
deepFreeze(o1);
var o2 = iassign(o1, function (o) { return o.a.b.c[0][0]; }, function (ci) { ci.d++; return ci; });
//
// Jasmine Tests
//
// expect o1 has not been changed
expect(o1).toEqual({ a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]], c2: {} }, b2: {} }, a2: {} });
// expect o2 inner property has been updated.
expect(o2.a.b.c[0][0].d).toBe(12);
// expect object graph for changed property in o2 is now different from (!==) o1.
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).not.toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).not.toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[0][0].d).not.toBe(o1.a.b.c[0][0].d);
// expect object graph for unchanged property in o2 is still equal to (===) o1.
expect(o2.a2).toBe(o1.a2);
expect(o2.a.b2).toBe(o1.a.b2);
expect(o2.a.b.c2).toBe(o1.a.b.c2);
expect(o2.a.b.c[0][0].e).toBe(o1.a.b.c[0][0].e);
expect(o2.a.b.c[1][0]).toBe(o1.a.b.c[1][0]);
expect(o2.a.b.c[2][0]).toBe(o1.a.b.c[2][0]);
});
it("Access array 1", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]], c2: {} }, b2: {} }, a2: {} };
deepFreeze(o1);
var o2 = iassign(o1, function (o) { return o.a.b.c[1]; }, function (c) { c.push(101); return c; });
//
// Jasmine Tests
//
// expect o1 has not been changed
expect(o1).toEqual({ a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]], c2: {} }, b2: {} }, a2: {} });
// expect o2 inner property has been updated.
expect(o2.a.b.c[1][1]).toBe(101);
// expect object graph for changed property in o2 is now different from (!==) o1.
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[1]).not.toBe(o1.a.b.c[1]);
// expect object graph for unchanged property in o2 is still equal to (===) o1.
expect(o2.a2).toBe(o1.a2);
expect(o2.a.b2).toBe(o1.a.b2);
expect(o2.a.b.c2).toBe(o1.a.b.c2);
expect(o2.a.b.c[0]).toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[1][0]).toBe(o1.a.b.c[1][0]);
expect(o2.a.b.c[2]).toBe(o1.a.b.c[2]);
expect(o2.a.b.c[2][0]).toBe(o1.a.b.c[2][0]);
});
it("Access array 2", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
var o2 = iassign(o1, function (o) { return o.a.b.c; }, function (c) { c.pop(); return c; });
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).toBe(o1.a.b.c[0]);
expect(o2.a.b.c[1]).toBe(o1.a.b.c[1]);
expect(o2.a.b.c[2]).toBe(undefined);
});
it("Access object", function () {
var o1 = { a: { b: { c: { d: 11, e: 12 } } } };
deepFreeze(o1);
var o2 = iassign(o1, function (o) { return o.a.b.c; }, function (c) { c.d++; return c; });
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c.d).not.toBe(o1.a.b.c.d);
expect(o2.a.b.c.d).toBe(12);
});
it("Access primitive", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
var o2 = iassign(o1, function (o) { return o.a.b.c[0][0].d; }, function (d) { return d + 1; });
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).not.toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).not.toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[0][0].d).not.toBe(o1.a.b.c[0][0].d);
expect(o2.a.b.c[0][0].d).toBe(12);
});
it("Access date", function () {
var o1 = { a: { b: { c: { d: 11, e: 12, f: new Date() } } } };
deepFreeze(o1);
var o2 = iassign(o1, function (o) { return o.a.b.c.f; }, function (f) { return new Date(2016, 1, 1); });
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c.f).not.toBe(o1.a.b.c.f);
expect(o2.a.b.c.f).toEqual(new Date(2016, 1, 1));
});
it("Access array item using string", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
var o2 = iassign(o1, function (o) { return o.a.b.c["1"]["0"].d; }, function (d) { return d + 1; });
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[1]).not.toBe(o1.a.b.c[1]);
expect(o2.a.b.c[1][0]).not.toBe(o1.a.b.c[1][0]);
expect(o2.a.b.c[1][0].d).not.toBe(o1.a.b.c[1][0].d);
expect(o2.a.b.c[1][0].d).toBe(22);
});
it("Access object property using string", function () {
var o1 = { a: { propB: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
var o2 = iassign(o1, function (o) { return o.a["propB"].c["1"][0].d; }, function (d) { return d + 1; });
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.propB).not.toBe(o1.a.propB);
expect(o2.a.propB.c).not.toBe(o1.a.propB.c);
expect(o2.a.propB.c[1]).not.toBe(o1.a.propB.c[1]);
expect(o2.a.propB.c[1][0]).not.toBe(o1.a.propB.c[1][0]);
expect(o2.a.propB.c[1][0].d).not.toBe(o1.a.propB.c[1][0].d);
expect(o2.a.propB.c[1][0].d).toBe(22);
});
it("Access object property using string 2", function () {
var propBName = "p\\r\"o.p t[] e.s\'t'B";
var propCName = "h\\e'llo w\'or\"ld";
var o1 = { a: (_a = {}, _a[propBName] = (_b = {}, _b[propCName] = [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]], _b), _a) };
deepFreeze(o1);
var o2 = iassign(o1, function (o) { return o.a["p\\r\"o.p t[] e.s\'t'B"]["h\\e'llo w\'or\"ld"]["1"][0].d; }, function (d) { return d + 1; });
expect(o2.a[propBName][propCName][1][0].d).toBe(22);
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a[propBName]).not.toBe(o1.a[propBName]);
expect(o2.a[propBName][propCName]).not.toBe(o1.a[propBName][propCName]);
expect(o2.a[propBName][propCName][1]).not.toBe(o1.a[propBName][propCName][1]);
expect(o2.a[propBName][propCName][1][0]).not.toBe(o1.a[propBName][propCName][1][0]);
expect(o2.a[propBName][propCName][1][0].d).not.toBe(o1.a[propBName][propCName][1][0].d);
var _a, _b;
});
it("Access object property using string 3", function () {
var propBName = "p\\ro.p t[] e.stB";
var propCName = "h\\e'llo w\'or\"ld";
var propDName = 'h\\e"llo w\"or\'ld';
var propEName = 'p\\ro.p t[] e.stB';
var o1 = { a: (_a = {}, _a[propBName] = (_b = {}, _b[propCName] = (_c = {}, _c[propDName] = (_d = {}, _d[propEName] = [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]], _d), _c), _b), _a) };
deepFreeze(o1);
var o2 = iassign(o1, function (o) { return o.a["p\\ro.p t[] e.stB"]["h\\e'llo w\'or\"ld"]['h\\e"llo w\"or\'ld']['p\\ro.p t[] e.stB']["1"][0].d; }, function (d) { return d + 1; });
expect(o2.a[propBName][propCName][propDName][propEName][1][0].d).toBe(22);
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a[propBName]).not.toBe(o1.a[propBName]);
expect(o2.a[propBName][propCName]).not.toBe(o1.a[propBName][propCName]);
expect(o2.a[propBName][propCName][propDName]).not.toBe(o1.a[propBName][propCName][propDName]);
expect(o2.a[propBName][propCName][propDName][propEName]).not.toBe(o1.a[propBName][propCName][propDName][propEName]);
expect(o2.a[propBName][propCName][propDName][propEName][1]).not.toBe(o1.a[propBName][propCName][propDName][propEName][1]);
expect(o2.a[propBName][propCName][propDName][propEName][1][0]).not.toBe(o1.a[propBName][propCName][propDName][propEName][1][0]);
expect(o2.a[propBName][propCName][propDName][propEName][1][0].d).not.toBe(o1.a[propBName][propCName][propDName][propEName][1][0].d);
var _a, _b, _c, _d;
});
it("Access object property using string 4", function () {
var propBName = "p\\r\"o.p t[] e.s't\'B";
var propCName = "h\\e'llo w\'or\"ld";
var propDName = 'h\\e"llo w\"or\'ld';
var propEName = 'p\\r\'o.p t[] e.s"t\"B';
var o1 = { a: (_a = {}, _a[propBName] = (_b = {}, _b[propCName] = (_c = {}, _c[propDName] = (_d = {}, _d[propEName] = [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]], _d), _c), _b), _a) };
deepFreeze(o1);
var o2 = iassign(o1, function (o) { return o.a["p\\r\"o.p t[] e.s't\'B"]["h\\e'llo w\'or\"ld"]['h\\e"llo w\"or\'ld']['p\\r\'o.p t[] e.s"t\"B']["1"][0].d; }, function (d) { return d + 1; });
expect(o2.a[propBName][propCName][propDName][propEName][1][0].d).toBe(22);
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a[propBName]).not.toBe(o1.a[propBName]);
expect(o2.a[propBName][propCName]).not.toBe(o1.a[propBName][propCName]);
expect(o2.a[propBName][propCName][propDName]).not.toBe(o1.a[propBName][propCName][propDName]);
expect(o2.a[propBName][propCName][propDName][propEName]).not.toBe(o1.a[propBName][propCName][propDName][propEName]);
expect(o2.a[propBName][propCName][propDName][propEName][1]).not.toBe(o1.a[propBName][propCName][propDName][propEName][1]);
expect(o2.a[propBName][propCName][propDName][propEName][1][0]).not.toBe(o1.a[propBName][propCName][propDName][propEName][1][0]);
expect(o2.a[propBName][propCName][propDName][propEName][1][0].d).not.toBe(o1.a[propBName][propCName][propDName][propEName][1][0].d);
var _a, _b, _c, _d;
});
it("Access array using context parameter", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
var p1 = { a: 0 };
var o2 = iassign(o1, function (o, ctx) { return o.a.b.c[ctx.p1.a][0]; }, function (ci) { ci.d++; return ci; }, { p1: p1 });
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).not.toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).not.toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[0][0].d).not.toBe(o1.a.b.c[0][0].d);
expect(o2.a.b.c[0][0].d).toBe(12);
});
it("Try to modify freezed object should throw error.", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
expect(function () {
iassign(o1, function (o) { return o.a.b.c; }, function (ci) { ci[0].push(3); return ci; });
}).toThrowError(TypeError, /Can't add property/);
expect(function () {
iassign(o1, function (o) { return o.a.b.c[0]; }, function (ci) { ci[0].d++; return ci; });
}).toThrowError(TypeError, /Cannot assign to read only property/);
expect(function () {
iassign(o1, function (o) { return o.a.b.c[0]; }, function (ci) { ci[0].g = 1; return ci; });
}).toThrowError(TypeError, /Can't add property/);
expect(function () {
iassign(o1, function (o) { return o.a.b.c; }, function (ci) { ci[0].pop(); return ci; });
}).toThrowError(TypeError, /object is not extensible/);
});
it("Update array using lodash", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }, { d: 13, e: 14 }], [{ d: 21, e: 22 }]] } }, a2: {} };
deepFreeze(o1); // Ensure o1 is not changed, for testing only
//
// Calling iassign() and _.map() to increment to d in c[0] array
//
var o2 = iassign(o1, function (o) { return o.a.b.c[0]; }, function (c) {
return _.map(c, function (item) { return iassign(item, function (o) { return o.d; }, function (d) { return d + 1; }); });
(function (root, factory) {
if (typeof module === 'object' && typeof module.exports === 'object') {
var v = factory(require, exports);
if (v !== undefined)
module.exports = v;
}
else if (typeof define === 'function' && define.amd) {
define(["require", "exports"], factory);
}
else {
// Browser globals (root is window)
var require_1 = function (name) {
if (name == "deep-freeze" && root.deepFreeze) {
return root.deepFreeze;
}
if (name == "lodash" && root._) {
return root._;
}
if (name.indexOf("iassign") > -1 && root.iassign) {
return root.iassign;
}
throw new Error("Unable to require: " + name);
};
factory(require_1, {});
}
})(this, function (require, exports) {
var iassign = require("../src/iassign");
var deepFreeze = require("deep-freeze");
var _ = require("lodash");
describe("Test", function () {
beforeEach(function () {
});
// expect o1 has not been changed
expect(o1).toEqual({ a: { b: { c: [[{ d: 11, e: 12 }, { d: 13, e: 14 }], [{ d: 21, e: 22 }]] } }, a2: {} });
expect(o2).toEqual({ a: { b: { c: [[{ d: 12, e: 12 }, { d: 14, e: 14 }], [{ d: 21, e: 22 }]] } }, a2: {} });
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).not.toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).not.toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[0][1]).not.toBe(o1.a.b.c[0][1]);
expect(o2.a.b.c[1][0]).toBe(o1.a.b.c[1][0]);
});
it("Update array using lodash 2", function () {
var o1 = { a: { b: { c: [1, 2, 3] } } };
deepFreeze(o1); // Ensure o1 is not changed, for testing only
//
// Calling iassign() and _.map() to increment to every item in "c" array
//
var o2 = iassign(o1, function (o) { return o.a.b.c; }, function (c) { return _.map(c, function (i) { return i + 1; }); });
// expect o1 has not been changed
expect(o1).toEqual({ a: { b: { c: [1, 2, 3] } } });
// expect o2.a.b.c has been updated.
expect(o2.a.b.c).toEqual([2, 3, 4]);
// expect object graph for changed property in o2 is now different from (!==) o1.
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
});
it("Test root object is an array", function () {
var o1 = [[{ d: 11, e: 12 }, { d: 13, e: 14 }, { d: 21, e: 22 }]];
deepFreeze(o1); // Ensure o1 is not changed, for testing only
//
// Calling iassign() and _.map() to increment to every item in "c" array
//
var o2 = iassign(o1, function (o) { return o[0]; }, function (o) {
return _.map(o, function (item, index) {
if (index < 2) {
item = _.cloneDeep(item);
item.d++;
}
return item;
it("Access array item", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]], c2: {} }, b2: {} }, a2: {} };
deepFreeze(o1);
var o2 = iassign(o1, function (o) { return o.a.b.c[0][0]; }, function (ci) { ci.d++; return ci; });
//
// Jasmine Tests
//
// expect o1 has not been changed
expect(o1).toEqual({ a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]], c2: {} }, b2: {} }, a2: {} });
// expect o2 inner property has been updated.
expect(o2.a.b.c[0][0].d).toBe(12);
// expect object graph for changed property in o2 is now different from (!==) o1.
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).not.toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).not.toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[0][0].d).not.toBe(o1.a.b.c[0][0].d);
// expect object graph for unchanged property in o2 is still equal to (===) o1.
expect(o2.a2).toBe(o1.a2);
expect(o2.a.b2).toBe(o1.a.b2);
expect(o2.a.b.c2).toBe(o1.a.b.c2);
expect(o2.a.b.c[0][0].e).toBe(o1.a.b.c[0][0].e);
expect(o2.a.b.c[1][0]).toBe(o1.a.b.c[1][0]);
expect(o2.a.b.c[2][0]).toBe(o1.a.b.c[2][0]);
});
it("Access array 1", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]], c2: {} }, b2: {} }, a2: {} };
deepFreeze(o1);
var o2 = iassign(o1, function (o) { return o.a.b.c[1]; }, function (c) { c.push(101); return c; });
//
// Jasmine Tests
//
// expect o1 has not been changed
expect(o1).toEqual({ a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]], c2: {} }, b2: {} }, a2: {} });
// expect o2 inner property has been updated.
expect(o2.a.b.c[1][1]).toBe(101);
// expect object graph for changed property in o2 is now different from (!==) o1.
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[1]).not.toBe(o1.a.b.c[1]);
// expect object graph for unchanged property in o2 is still equal to (===) o1.
expect(o2.a2).toBe(o1.a2);
expect(o2.a.b2).toBe(o1.a.b2);
expect(o2.a.b.c2).toBe(o1.a.b.c2);
expect(o2.a.b.c[0]).toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[1][0]).toBe(o1.a.b.c[1][0]);
expect(o2.a.b.c[2]).toBe(o1.a.b.c[2]);
expect(o2.a.b.c[2][0]).toBe(o1.a.b.c[2][0]);
});
it("Access array 2", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
var o2 = iassign(o1, function (o) { return o.a.b.c; }, function (c) { c.pop(); return c; });
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).toBe(o1.a.b.c[0]);
expect(o2.a.b.c[1]).toBe(o1.a.b.c[1]);
expect(o2.a.b.c[2]).toBe(undefined);
});
it("Access object", function () {
var o1 = { a: { b: { c: { d: 11, e: 12 } } } };
deepFreeze(o1);
var o2 = iassign(o1, function (o) { return o.a.b.c; }, function (c) { c.d++; return c; });
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c.d).not.toBe(o1.a.b.c.d);
expect(o2.a.b.c.d).toBe(12);
});
it("Access primitive", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
var o2 = iassign(o1, function (o) { return o.a.b.c[0][0].d; }, function (d) { return d + 1; });
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).not.toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).not.toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[0][0].d).not.toBe(o1.a.b.c[0][0].d);
expect(o2.a.b.c[0][0].d).toBe(12);
});
it("Access date", function () {
var o1 = { a: { b: { c: { d: 11, e: 12, f: new Date() } } } };
deepFreeze(o1);
var o2 = iassign(o1, function (o) { return o.a.b.c.f; }, function (f) { return new Date(2016, 1, 1); });
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c.f).not.toBe(o1.a.b.c.f);
expect(o2.a.b.c.f).toEqual(new Date(2016, 1, 1));
});
it("Access array item using string", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
var o2 = iassign(o1, function (o) { return o.a.b.c["1"]["0"].d; }, function (d) { return d + 1; });
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[1]).not.toBe(o1.a.b.c[1]);
expect(o2.a.b.c[1][0]).not.toBe(o1.a.b.c[1][0]);
expect(o2.a.b.c[1][0].d).not.toBe(o1.a.b.c[1][0].d);
expect(o2.a.b.c[1][0].d).toBe(22);
});
it("Access object property using string", function () {
var o1 = { a: { propB: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
var o2 = iassign(o1, function (o) { return o.a["propB"].c["1"][0].d; }, function (d) { return d + 1; });
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.propB).not.toBe(o1.a.propB);
expect(o2.a.propB.c).not.toBe(o1.a.propB.c);
expect(o2.a.propB.c[1]).not.toBe(o1.a.propB.c[1]);
expect(o2.a.propB.c[1][0]).not.toBe(o1.a.propB.c[1][0]);
expect(o2.a.propB.c[1][0].d).not.toBe(o1.a.propB.c[1][0].d);
expect(o2.a.propB.c[1][0].d).toBe(22);
});
it("Access object property using string 2", function () {
var propBName = "p\\r\"o.p t[] e.s\'t'B";
var propCName = "h\\e'llo w\'or\"ld";
var o1 = { a: (_a = {}, _a[propBName] = (_b = {}, _b[propCName] = [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]], _b), _a) };
deepFreeze(o1);
var o2 = iassign(o1, function (o) { return o.a["p\\r\"o.p t[] e.s\'t'B"]["h\\e'llo w\'or\"ld"]["1"][0].d; }, function (d) { return d + 1; });
expect(o2.a[propBName][propCName][1][0].d).toBe(22);
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a[propBName]).not.toBe(o1.a[propBName]);
expect(o2.a[propBName][propCName]).not.toBe(o1.a[propBName][propCName]);
expect(o2.a[propBName][propCName][1]).not.toBe(o1.a[propBName][propCName][1]);
expect(o2.a[propBName][propCName][1][0]).not.toBe(o1.a[propBName][propCName][1][0]);
expect(o2.a[propBName][propCName][1][0].d).not.toBe(o1.a[propBName][propCName][1][0].d);
var _a, _b;
});
it("Access object property using string 3", function () {
var propBName = "p\\ro.p t[] e.stB";
var propCName = "h\\e'llo w\'or\"ld";
var propDName = 'h\\e"llo w\"or\'ld';
var propEName = 'p\\ro.p t[] e.stB';
var o1 = { a: (_a = {}, _a[propBName] = (_b = {}, _b[propCName] = (_c = {}, _c[propDName] = (_d = {}, _d[propEName] = [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]], _d), _c), _b), _a) };
deepFreeze(o1);
var o2 = iassign(o1, function (o) { return o.a["p\\ro.p t[] e.stB"]["h\\e'llo w\'or\"ld"]['h\\e"llo w\"or\'ld']['p\\ro.p t[] e.stB']["1"][0].d; }, function (d) { return d + 1; });
expect(o2.a[propBName][propCName][propDName][propEName][1][0].d).toBe(22);
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a[propBName]).not.toBe(o1.a[propBName]);
expect(o2.a[propBName][propCName]).not.toBe(o1.a[propBName][propCName]);
expect(o2.a[propBName][propCName][propDName]).not.toBe(o1.a[propBName][propCName][propDName]);
expect(o2.a[propBName][propCName][propDName][propEName]).not.toBe(o1.a[propBName][propCName][propDName][propEName]);
expect(o2.a[propBName][propCName][propDName][propEName][1]).not.toBe(o1.a[propBName][propCName][propDName][propEName][1]);
expect(o2.a[propBName][propCName][propDName][propEName][1][0]).not.toBe(o1.a[propBName][propCName][propDName][propEName][1][0]);
expect(o2.a[propBName][propCName][propDName][propEName][1][0].d).not.toBe(o1.a[propBName][propCName][propDName][propEName][1][0].d);
var _a, _b, _c, _d;
});
it("Access object property using string 4", function () {
var propBName = "p\\r\"o.p t[] e.s't\'B";
var propCName = "h\\e'llo w\'or\"ld";
var propDName = 'h\\e"llo w\"or\'ld';
var propEName = 'p\\r\'o.p t[] e.s"t\"B';
var o1 = { a: (_a = {}, _a[propBName] = (_b = {}, _b[propCName] = (_c = {}, _c[propDName] = (_d = {}, _d[propEName] = [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]], _d), _c), _b), _a) };
deepFreeze(o1);
var o2 = iassign(o1, function (o) { return o.a["p\\r\"o.p t[] e.s't\'B"]["h\\e'llo w\'or\"ld"]['h\\e"llo w\"or\'ld']['p\\r\'o.p t[] e.s"t\"B']["1"][0].d; }, function (d) { return d + 1; });
expect(o2.a[propBName][propCName][propDName][propEName][1][0].d).toBe(22);
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a[propBName]).not.toBe(o1.a[propBName]);
expect(o2.a[propBName][propCName]).not.toBe(o1.a[propBName][propCName]);
expect(o2.a[propBName][propCName][propDName]).not.toBe(o1.a[propBName][propCName][propDName]);
expect(o2.a[propBName][propCName][propDName][propEName]).not.toBe(o1.a[propBName][propCName][propDName][propEName]);
expect(o2.a[propBName][propCName][propDName][propEName][1]).not.toBe(o1.a[propBName][propCName][propDName][propEName][1]);
expect(o2.a[propBName][propCName][propDName][propEName][1][0]).not.toBe(o1.a[propBName][propCName][propDName][propEName][1][0]);
expect(o2.a[propBName][propCName][propDName][propEName][1][0].d).not.toBe(o1.a[propBName][propCName][propDName][propEName][1][0].d);
var _a, _b, _c, _d;
});
it("Access array using context parameter", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
var p1 = { a: 0 };
var o2 = iassign(o1, function (o, ctx) { return o.a.b.c[ctx.p1.a][0]; }, function (ci) { ci.d++; return ci; }, { p1: p1 });
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).not.toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).not.toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[0][0].d).not.toBe(o1.a.b.c[0][0].d);
expect(o2.a.b.c[0][0].d).toBe(12);
});
it("Try to modify freezed object should throw error.", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
expect(function () {
iassign(o1, function (o) { return o.a.b.c; }, function (ci) { ci[0].push(3); return ci; });
}).toThrowError(TypeError, /Can't add property/);
expect(function () {
iassign(o1, function (o) { return o.a.b.c[0]; }, function (ci) { ci[0].d++; return ci; });
}).toThrowError(TypeError, /Cannot assign to read only property/);
expect(function () {
iassign(o1, function (o) { return o.a.b.c[0]; }, function (ci) { ci[0].g = 1; return ci; });
}).toThrowError(TypeError, /Can't add property/);
expect(function () {
iassign(o1, function (o) { return o.a.b.c; }, function (ci) { ci[0].pop(); return ci; });
}).toThrowError(TypeError, /object is not extensible|Cannot delete property/);
});
it("Update array using lodash", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }, { d: 13, e: 14 }], [{ d: 21, e: 22 }]] } }, a2: {} };
deepFreeze(o1); // Ensure o1 is not changed, for testing only
//
// Calling iassign() and _.map() to increment to d in c[0] array
//
var o2 = iassign(o1, function (o) { return o.a.b.c[0]; }, function (c) {
return _.map(c, function (item) { return iassign(item, function (o) { return o.d; }, function (d) { return d + 1; }); });
});
// expect o1 has not been changed
expect(o1).toEqual({ a: { b: { c: [[{ d: 11, e: 12 }, { d: 13, e: 14 }], [{ d: 21, e: 22 }]] } }, a2: {} });
expect(o2).toEqual({ a: { b: { c: [[{ d: 12, e: 12 }, { d: 14, e: 14 }], [{ d: 21, e: 22 }]] } }, a2: {} });
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).not.toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).not.toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[0][1]).not.toBe(o1.a.b.c[0][1]);
expect(o2.a.b.c[1][0]).toBe(o1.a.b.c[1][0]);
});
// expect o1 has not been changed
expect(o1).toEqual([[{ d: 11, e: 12 }, { d: 13, e: 14 }, { d: 21, e: 22 }]]);
// expect o2.a.b.c has been updated.
expect(o2).toEqual([[{ d: 12, e: 12 }, { d: 14, e: 14 }, { d: 21, e: 22 }]]);
// expect object graph for changed property in o2 is now different from (!==) o1.
expect(o2).not.toBe(o1);
expect(o2[0]).not.toBe(o1[0]);
expect(o2[0][0]).not.toBe(o1[0][0]);
expect(o2[0][1]).not.toBe(o1[0][1]);
// expect object graph for unchanged property in o2 is still equal to (===) o1.
expect(o2[0][2]).toBe(o1[0][2]);
});
it("Test root is an array, and try to update root array", function () {
var o1 = [{ d: 11, e: 12 }, { d: 13, e: 14 }, { d: 21, e: 22 }];
deepFreeze(o1); // Ensure o1 is not changed, for testing only
//
// Calling iassign() and _.map() to increment to every item in "c" array
//
var o2 = iassign(o1, function (o) { return o; }, function (o) {
return _.map(o, function (item, index) {
if (index < 2) {
item = _.cloneDeep(item);
item.d++;
}
return item;
it("Update array using lodash 2", function () {
var o1 = { a: { b: { c: [1, 2, 3] } } };
deepFreeze(o1); // Ensure o1 is not changed, for testing only
//
// Calling iassign() and _.map() to increment to every item in "c" array
//
var o2 = iassign(o1, function (o) { return o.a.b.c; }, function (c) { return _.map(c, function (i) { return i + 1; }); });
// expect o1 has not been changed
expect(o1).toEqual({ a: { b: { c: [1, 2, 3] } } });
// expect o2.a.b.c has been updated.
expect(o2.a.b.c).toEqual([2, 3, 4]);
// expect object graph for changed property in o2 is now different from (!==) o1.
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
});
it("Test root object is an array", function () {
var o1 = [[{ d: 11, e: 12 }, { d: 13, e: 14 }, { d: 21, e: 22 }]];
deepFreeze(o1); // Ensure o1 is not changed, for testing only
//
// Calling iassign() and _.map() to increment to every item in "c" array
//
var o2 = iassign(o1, function (o) { return o[0]; }, function (o) {
return _.map(o, function (item, index) {
if (index < 2) {
item = _.cloneDeep(item);
item.d++;
}
return item;
});
});
// expect o1 has not been changed
expect(o1).toEqual([[{ d: 11, e: 12 }, { d: 13, e: 14 }, { d: 21, e: 22 }]]);
// expect o2.a.b.c has been updated.
expect(o2).toEqual([[{ d: 12, e: 12 }, { d: 14, e: 14 }, { d: 21, e: 22 }]]);
// expect object graph for changed property in o2 is now different from (!==) o1.
expect(o2).not.toBe(o1);
expect(o2[0]).not.toBe(o1[0]);
expect(o2[0][0]).not.toBe(o1[0][0]);
expect(o2[0][1]).not.toBe(o1[0][1]);
// expect object graph for unchanged property in o2 is still equal to (===) o1.
expect(o2[0][2]).toBe(o1[0][2]);
});
// expect o1 has not been changed
expect(o1).toEqual([{ d: 11, e: 12 }, { d: 13, e: 14 }, { d: 21, e: 22 }]);
// expect o2.a.b.c has been updated.
expect(o2).toEqual([{ d: 12, e: 12 }, { d: 14, e: 14 }, { d: 21, e: 22 }]);
// expect object graph for changed property in o2 is now different from (!==) o1.
expect(o2).not.toBe(o1);
expect(o2[0]).not.toBe(o1[0]);
expect(o2[1]).not.toBe(o1[1]);
// expect object graph for unchanged property in o2 is still equal to (===) o1.
expect(o2[2]).toBe(o1[2]);
});
it("Test root is an object, and try to update root object", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }]], c2: {} }, b2: {} }, a2: {} };
deepFreeze(o1);
var o2 = iassign(o1, function (o) { return o; }, function (o) { o.a = { b: 1 }; return o; });
//
// Jasmine Tests
//
// expect o1 has not been changed
expect(o1).toEqual({ a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }]], c2: {} }, b2: {} }, a2: {} });
// expect o2 inner property has been updated.
expect(o2).toEqual({ a: { b: 1 }, a2: {} });
// expect object graph for changed property in o2 is now different from (!==) o1.
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
// expect object graph for unchanged property in o2 is still equal to (===) o1.
expect(o2.a2).toBe(o1.a2);
});
it("Use built-in deep freeze to protect input", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
iassign.freezeInput = true;
expect(function () {
iassign(o1, function (o) { return o.a.b.c; }, function (ci) { ci[0].push(3); return ci; });
}).toThrowError(TypeError, /Can't add property/);
expect(function () {
iassign(o1, function (o) { return o.a.b.c[0]; }, function (ci) { ci[0].d++; return ci; });
}).toThrowError(TypeError, /Cannot assign to read only property/);
expect(function () {
iassign(o1, function (o) { return o.a.b.c[0]; }, function (ci) { ci[0].g = 1; return ci; });
}).toThrowError(TypeError, /Can't add property/);
expect(function () {
iassign(o1, function (o) { return o.a.b.c; }, function (ci) { ci[0].pop(); return ci; });
}).toThrowError(TypeError, /object is not extensible/);
iassign.freezeInput = undefined;
});
it("Use built-in deep freeze to protect output", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }, { d: 13, e: 14 }, { d: 21, e: 22 }]] } } };
iassign.freezeOutput = true;
var o2 = iassign(o1, function (o) { return o.a.b.c[0]; }, function (c) {
return _.map(c, function (item) { return iassign(item, function (o) { return o.d; }, function (d) { return d + 1; }); });
it("Test root is an array, and try to update root array", function () {
var o1 = [{ d: 11, e: 12 }, { d: 13, e: 14 }, { d: 21, e: 22 }];
deepFreeze(o1); // Ensure o1 is not changed, for testing only
//
// Calling iassign() and _.map() to increment to every item in "c" array
//
var o2 = iassign(o1, function (o) { return o; }, function (o) {
return _.map(o, function (item, index) {
if (index < 2) {
item = _.cloneDeep(item);
item.d++;
}
return item;
});
});
// expect o1 has not been changed
expect(o1).toEqual([{ d: 11, e: 12 }, { d: 13, e: 14 }, { d: 21, e: 22 }]);
// expect o2.a.b.c has been updated.
expect(o2).toEqual([{ d: 12, e: 12 }, { d: 14, e: 14 }, { d: 21, e: 22 }]);
// expect object graph for changed property in o2 is now different from (!==) o1.
expect(o2).not.toBe(o1);
expect(o2[0]).not.toBe(o1[0]);
expect(o2[1]).not.toBe(o1[1]);
// expect object graph for unchanged property in o2 is still equal to (===) o1.
expect(o2[2]).toBe(o1[2]);
});
// expect o1 has not been changed
expect(o1).toEqual({ a: { b: { c: [[{ d: 11, e: 12 }, { d: 13, e: 14 }, { d: 21, e: 22 }]] } } });
expect(o2.a.b.c[0][0].d).toBe(12);
expect(o2.a.b.c[0][1].d).toBe(14);
expect(o2.a.b.c[0][2].d).toBe(22);
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).not.toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).not.toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[0][1]).not.toBe(o1.a.b.c[0][1]);
expect(o2.a.b.c[0][2]).not.toBe(o1.a.b.c[0][2]);
expect(function () {
o2.a.b.c[0].push(3);
}).toThrowError(TypeError, /Can't add property/);
expect(function () {
o2.a.b.c[0][0].d++;
}).toThrowError(TypeError, /Cannot assign to read only property/);
expect(function () {
o2.a.b.c[0][0].g = 1;
}).toThrowError(TypeError, /Can't add property/);
expect(function () {
o2.a.b.c[0].pop();
}).toThrowError(TypeError, /object is not extensible/);
iassign.freezeOutput = undefined;
it("Test root is an object, and try to update root object", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }]], c2: {} }, b2: {} }, a2: {} };
deepFreeze(o1);
var o2 = iassign(o1, function (o) { return o; }, function (o) { o.a = { b: 1 }; return o; });
//
// Jasmine Tests
//
// expect o1 has not been changed
expect(o1).toEqual({ a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }]], c2: {} }, b2: {} }, a2: {} });
// expect o2 inner property has been updated.
expect(o2).toEqual({ a: { b: 1 }, a2: {} });
// expect object graph for changed property in o2 is now different from (!==) o1.
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
// expect object graph for unchanged property in o2 is still equal to (===) o1.
expect(o2.a2).toBe(o1.a2);
});
it("Use built-in deep freeze to protect input", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
iassign.freezeInput = true;
expect(function () {
iassign(o1, function (o) { return o.a.b.c; }, function (ci) { ci[0].push(3); return ci; });
}).toThrowError(TypeError, /Can't add property/);
expect(function () {
iassign(o1, function (o) { return o.a.b.c[0]; }, function (ci) { ci[0].d++; return ci; });
}).toThrowError(TypeError, /Cannot assign to read only property/);
expect(function () {
iassign(o1, function (o) { return o.a.b.c[0]; }, function (ci) { ci[0].g = 1; return ci; });
}).toThrowError(TypeError, /Can't add property/);
expect(function () {
iassign(o1, function (o) { return o.a.b.c; }, function (ci) { ci[0].pop(); return ci; });
}).toThrowError(TypeError, /object is not extensible|Cannot delete property/);
iassign.freezeInput = undefined;
});
it("Use built-in deep freeze to protect output", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }, { d: 13, e: 14 }, { d: 21, e: 22 }]] } } };
iassign.freezeOutput = true;
var o2 = iassign(o1, function (o) { return o.a.b.c[0]; }, function (c) {
return _.map(c, function (item) { return iassign(item, function (o) { return o.d; }, function (d) { return d + 1; }); });
});
// expect o1 has not been changed
expect(o1).toEqual({ a: { b: { c: [[{ d: 11, e: 12 }, { d: 13, e: 14 }, { d: 21, e: 22 }]] } } });
expect(o2.a.b.c[0][0].d).toBe(12);
expect(o2.a.b.c[0][1].d).toBe(14);
expect(o2.a.b.c[0][2].d).toBe(22);
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).not.toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).not.toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[0][1]).not.toBe(o1.a.b.c[0][1]);
expect(o2.a.b.c[0][2]).not.toBe(o1.a.b.c[0][2]);
expect(function () {
o2.a.b.c[0].push(3);
}).toThrowError(TypeError, /Can't add property/);
expect(function () {
o2.a.b.c[0][0].d++;
}).toThrowError(TypeError, /Cannot assign to read only property/);
expect(function () {
o2.a.b.c[0][0].g = 1;
}).toThrowError(TypeError, /Can't add property/);
expect(function () {
o2.a.b.c[0].pop();
}).toThrowError(TypeError, /object is not extensible|Cannot delete property/);
iassign.freezeOutput = undefined;
});
});
});
import iassign = require("../src/iassign");
import deepFreeze = require("deep-freeze");
import _ = require("lodash");
"use strict";
describe("Test", function () {
(function (root, factory) {
if (typeof module === 'object' && typeof module.exports === 'object') {
var v = factory(require, exports); if (v !== undefined) module.exports = v;
}
else if (typeof define === 'function' && define.amd) {
define(["require", "exports"], factory);
} else {
// Browser globals (root is window)
let require = (name) => {
if (name == "deep-freeze" && root.deepFreeze) {
return root.deepFreeze;
}
beforeEach(function () {
});
if (name == "lodash" && root._) {
return root._;
}
it("Access array item", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]], c2: {} }, b2: {} }, a2: {} };
deepFreeze(o1);
if (name.indexOf("iassign") > -1 && root.iassign) {
return root.iassign;
}
var o2 = iassign(
o1,
(o) => o.a.b.c[0][0],
(ci) => { ci.d++; return ci; }
);
throw new Error("Unable to require: " + name);
}
factory(require, {});
}
})(this, function (require, exports) {
//
// Jasmine Tests
//
var iassign: IIassign = require("../src/iassign");
var deepFreeze: DeepFreeze.DeepFreezeInterface = require("deep-freeze");
var _: _.LoDashStatic = require("lodash");
// expect o1 has not been changed
expect(o1).toEqual({ a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]], c2: {} }, b2: {} }, a2: {} })
describe("Test", function () {
// expect o2 inner property has been updated.
expect(o2.a.b.c[0][0].d).toBe(12);
beforeEach(function () {
});
// expect object graph for changed property in o2 is now different from (!==) o1.
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).not.toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).not.toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[0][0].d).not.toBe(o1.a.b.c[0][0].d);
it("Access array item", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]], c2: {} }, b2: {} }, a2: {} };
deepFreeze(o1);
// expect object graph for unchanged property in o2 is still equal to (===) o1.
expect(o2.a2).toBe(o1.a2);
expect(o2.a.b2).toBe(o1.a.b2);
expect(o2.a.b.c2).toBe(o1.a.b.c2);
expect(o2.a.b.c[0][0].e).toBe(o1.a.b.c[0][0].e);
expect(o2.a.b.c[1][0]).toBe(o1.a.b.c[1][0]);
expect(o2.a.b.c[2][0]).toBe(o1.a.b.c[2][0]);
});
var o2 = iassign(
o1,
(o) => o.a.b.c[0][0],
(ci) => { ci.d++; return ci; }
);
it("Access array 1", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]], c2: {} }, b2: {} }, a2: {} };
deepFreeze(o1);
//
// Jasmine Tests
//
var o2 = iassign(
o1,
(o) => o.a.b.c[1],
(c) => { c.push(<any>101); return c; }
);
// expect o1 has not been changed
expect(o1).toEqual({ a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]], c2: {} }, b2: {} }, a2: {} })
//
// Jasmine Tests
//
// expect o2 inner property has been updated.
expect(o2.a.b.c[0][0].d).toBe(12);
// expect o1 has not been changed
expect(o1).toEqual({ a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]], c2: {} }, b2: {} }, a2: {} })
// expect object graph for changed property in o2 is now different from (!==) o1.
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).not.toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).not.toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[0][0].d).not.toBe(o1.a.b.c[0][0].d);
// expect o2 inner property has been updated.
expect(o2.a.b.c[1][1]).toBe(101);
// expect object graph for unchanged property in o2 is still equal to (===) o1.
expect(o2.a2).toBe(o1.a2);
expect(o2.a.b2).toBe(o1.a.b2);
expect(o2.a.b.c2).toBe(o1.a.b.c2);
expect(o2.a.b.c[0][0].e).toBe(o1.a.b.c[0][0].e);
expect(o2.a.b.c[1][0]).toBe(o1.a.b.c[1][0]);
expect(o2.a.b.c[2][0]).toBe(o1.a.b.c[2][0]);
});
// expect object graph for changed property in o2 is now different from (!==) o1.
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[1]).not.toBe(o1.a.b.c[1]);
it("Access array 1", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]], c2: {} }, b2: {} }, a2: {} };
deepFreeze(o1);
// expect object graph for unchanged property in o2 is still equal to (===) o1.
expect(o2.a2).toBe(o1.a2);
expect(o2.a.b2).toBe(o1.a.b2);
expect(o2.a.b.c2).toBe(o1.a.b.c2);
expect(o2.a.b.c[0]).toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[1][0]).toBe(o1.a.b.c[1][0]);
expect(o2.a.b.c[2]).toBe(o1.a.b.c[2]);
expect(o2.a.b.c[2][0]).toBe(o1.a.b.c[2][0]);
});
var o2 = iassign(
o1,
(o) => o.a.b.c[1],
(c) => { c.push(<any>101); return c; }
);
it("Access array 2", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
//
// Jasmine Tests
//
var o2 = iassign(o1, function (o) { return o.a.b.c; }, function (c) { c.pop(); return c; });
// expect o1 has not been changed
expect(o1).toEqual({ a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]], c2: {} }, b2: {} }, a2: {} })
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).toBe(o1.a.b.c[0]);
expect(o2.a.b.c[1]).toBe(o1.a.b.c[1]);
expect(o2.a.b.c[2]).toBe(undefined);
});
// expect o2 inner property has been updated.
expect(o2.a.b.c[1][1]).toBe(101);
it("Access object", function () {
var o1 = { a: { b: { c: { d: 11, e: 12 } } } };
deepFreeze(o1);
// expect object graph for changed property in o2 is now different from (!==) o1.
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[1]).not.toBe(o1.a.b.c[1]);
let o2 = iassign(o1, (o) => o.a.b.c, (c) => { c.d++; return c });
// expect object graph for unchanged property in o2 is still equal to (===) o1.
expect(o2.a2).toBe(o1.a2);
expect(o2.a.b2).toBe(o1.a.b2);
expect(o2.a.b.c2).toBe(o1.a.b.c2);
expect(o2.a.b.c[0]).toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[1][0]).toBe(o1.a.b.c[1][0]);
expect(o2.a.b.c[2]).toBe(o1.a.b.c[2]);
expect(o2.a.b.c[2][0]).toBe(o1.a.b.c[2][0]);
});
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c.d).not.toBe(o1.a.b.c.d);
expect(o2.a.b.c.d).toBe(12);
});
it("Access array 2", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
it("Access primitive", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
var o2 = iassign(o1, function (o) { return o.a.b.c; }, function (c) { c.pop(); return c; });
let o2 = iassign(o1, (o) => o.a.b.c[0][0].d, (d) => { return d + 1; });
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).toBe(o1.a.b.c[0]);
expect(o2.a.b.c[1]).toBe(o1.a.b.c[1]);
expect(o2.a.b.c[2]).toBe(undefined);
});
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).not.toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).not.toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[0][0].d).not.toBe(o1.a.b.c[0][0].d);
expect(o2.a.b.c[0][0].d).toBe(12);
});
it("Access object", function () {
var o1 = { a: { b: { c: { d: 11, e: 12 } } } };
deepFreeze(o1);
it("Access date", function () {
var o1 = { a: { b: { c: { d: 11, e: 12, f: new Date() } } } };
deepFreeze(o1);
let o2 = iassign(o1, (o) => o.a.b.c, (c) => { c.d++; return c });
let o2 = iassign(o1, (o) => o.a.b.c.f, (f) => { return new Date(2016, 1, 1) });
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c.d).not.toBe(o1.a.b.c.d);
expect(o2.a.b.c.d).toBe(12);
});
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c.f).not.toBe(o1.a.b.c.f);
expect(o2.a.b.c.f).toEqual(new Date(2016, 1, 1));
});
it("Access primitive", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
it("Access array item using string", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
let o2 = iassign(o1, (o) => o.a.b.c[0][0].d, (d) => { return d + 1; });
let o2 = iassign(o1, (o) => o.a.b.c["1"]["0"].d, (d) => { return d + 1; });
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).not.toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).not.toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[0][0].d).not.toBe(o1.a.b.c[0][0].d);
expect(o2.a.b.c[0][0].d).toBe(12);
});
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[1]).not.toBe(o1.a.b.c[1]);
expect(o2.a.b.c[1][0]).not.toBe(o1.a.b.c[1][0]);
expect(o2.a.b.c[1][0].d).not.toBe(o1.a.b.c[1][0].d);
expect(o2.a.b.c[1][0].d).toBe(22);
});
it("Access date", function () {
var o1 = { a: { b: { c: { d: 11, e: 12, f: new Date() } } } };
deepFreeze(o1);
it("Access object property using string", function () {
var o1 = { a: { propB: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
let o2 = iassign(o1, (o) => o.a.b.c.f, (f) => { return new Date(2016, 1, 1) });
let o2 = iassign(o1, (o) => o.a["propB"].c["1"][0].d, (d) => { return d + 1; });
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c.f).not.toBe(o1.a.b.c.f);
expect(o2.a.b.c.f).toEqual(new Date(2016, 1, 1));
});
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.propB).not.toBe(o1.a.propB);
expect(o2.a.propB.c).not.toBe(o1.a.propB.c);
expect(o2.a.propB.c[1]).not.toBe(o1.a.propB.c[1]);
expect(o2.a.propB.c[1][0]).not.toBe(o1.a.propB.c[1][0]);
expect(o2.a.propB.c[1][0].d).not.toBe(o1.a.propB.c[1][0].d);
expect(o2.a.propB.c[1][0].d).toBe(22);
});
it("Access array item using string", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
it("Access object property using string 2", function () {
let propBName = "p\\r\"o.p t[] e.s\'t'B";
let propCName = "h\\e'llo w\'or\"ld";
var o1 = { a: { [propBName]: { [propCName]: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
let o2 = iassign(o1, (o) => o.a.b.c["1"]["0"].d, (d) => { return d + 1; });
let o2 = iassign(o1, (o) => o.a["p\\r\"o.p t[] e.s\'t'B"]["h\\e'llo w\'or\"ld"]["1"][0].d, (d) => { return d + 1; });
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[1]).not.toBe(o1.a.b.c[1]);
expect(o2.a.b.c[1][0]).not.toBe(o1.a.b.c[1][0]);
expect(o2.a.b.c[1][0].d).not.toBe(o1.a.b.c[1][0].d);
expect(o2.a.b.c[1][0].d).toBe(22);
});
expect(o2.a[propBName][propCName][1][0].d).toBe(22);
it("Access object property using string", function () {
var o1 = { a: { propB: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a[propBName]).not.toBe(o1.a[propBName]);
expect(o2.a[propBName][propCName]).not.toBe(o1.a[propBName][propCName]);
expect(o2.a[propBName][propCName][1]).not.toBe(o1.a[propBName][propCName][1]);
expect(o2.a[propBName][propCName][1][0]).not.toBe(o1.a[propBName][propCName][1][0]);
expect(o2.a[propBName][propCName][1][0].d).not.toBe(o1.a[propBName][propCName][1][0].d);
});
let o2 = iassign(o1, (o) => o.a["propB"].c["1"][0].d, (d) => { return d + 1; });
it("Access object property using string 3", function () {
let propBName = "p\\ro.p t[] e.stB";
let propCName = "h\\e'llo w\'or\"ld";
let propDName = 'h\\e"llo w\"or\'ld';
let propEName = 'p\\ro.p t[] e.stB';
var o1 = { a: { [propBName]: { [propCName]: { [propDName]: { [propEName]: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } } } };
deepFreeze(o1);
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.propB).not.toBe(o1.a.propB);
expect(o2.a.propB.c).not.toBe(o1.a.propB.c);
expect(o2.a.propB.c[1]).not.toBe(o1.a.propB.c[1]);
expect(o2.a.propB.c[1][0]).not.toBe(o1.a.propB.c[1][0]);
expect(o2.a.propB.c[1][0].d).not.toBe(o1.a.propB.c[1][0].d);
expect(o2.a.propB.c[1][0].d).toBe(22);
});
let o2 = iassign(o1, (o) => o.a["p\\ro.p t[] e.stB"]["h\\e'llo w\'or\"ld"]['h\\e"llo w\"or\'ld']['p\\ro.p t[] e.stB']["1"][0].d, (d) => { return d + 1; });
it("Access object property using string 2", function () {
let propBName = "p\\r\"o.p t[] e.s\'t'B";
let propCName = "h\\e'llo w\'or\"ld";
var o1 = { a: { [propBName]: { [propCName]: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
expect(o2.a[propBName][propCName][propDName][propEName][1][0].d).toBe(22);
let o2 = iassign(o1, (o) => o.a["p\\r\"o.p t[] e.s\'t'B"]["h\\e'llo w\'or\"ld"]["1"][0].d, (d) => { return d + 1; });
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a[propBName]).not.toBe(o1.a[propBName]);
expect(o2.a[propBName][propCName]).not.toBe(o1.a[propBName][propCName]);
expect(o2.a[propBName][propCName][propDName]).not.toBe(o1.a[propBName][propCName][propDName]);
expect(o2.a[propBName][propCName][propDName][propEName]).not.toBe(o1.a[propBName][propCName][propDName][propEName]);
expect(o2.a[propBName][propCName][propDName][propEName][1]).not.toBe(o1.a[propBName][propCName][propDName][propEName][1]);
expect(o2.a[propBName][propCName][propDName][propEName][1][0]).not.toBe(o1.a[propBName][propCName][propDName][propEName][1][0]);
expect(o2.a[propBName][propCName][propDName][propEName][1][0].d).not.toBe(o1.a[propBName][propCName][propDName][propEName][1][0].d);
});
expect(o2.a[propBName][propCName][1][0].d).toBe(22);
it("Access object property using string 4", function () {
let propBName = "p\\r\"o.p t[] e.s't\'B";
let propCName = "h\\e'llo w\'or\"ld";
let propDName = 'h\\e"llo w\"or\'ld';
let propEName = 'p\\r\'o.p t[] e.s"t\"B';
var o1 = { a: { [propBName]: { [propCName]: { [propDName]: { [propEName]: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } } } };
deepFreeze(o1);
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a[propBName]).not.toBe(o1.a[propBName]);
expect(o2.a[propBName][propCName]).not.toBe(o1.a[propBName][propCName]);
expect(o2.a[propBName][propCName][1]).not.toBe(o1.a[propBName][propCName][1]);
expect(o2.a[propBName][propCName][1][0]).not.toBe(o1.a[propBName][propCName][1][0]);
expect(o2.a[propBName][propCName][1][0].d).not.toBe(o1.a[propBName][propCName][1][0].d);
});
let o2 = iassign(o1, (o) => o.a["p\\r\"o.p t[] e.s't\'B"]["h\\e'llo w\'or\"ld"]['h\\e"llo w\"or\'ld']['p\\r\'o.p t[] e.s"t\"B']["1"][0].d, (d) => { return d + 1; });
it("Access object property using string 3", function () {
let propBName = "p\\ro.p t[] e.stB";
let propCName = "h\\e'llo w\'or\"ld";
let propDName = 'h\\e"llo w\"or\'ld';
let propEName = 'p\\ro.p t[] e.stB';
var o1 = { a: { [propBName]: { [propCName]: { [propDName]: { [propEName]: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } } } };
deepFreeze(o1);
expect(o2.a[propBName][propCName][propDName][propEName][1][0].d).toBe(22);
let o2 = iassign(o1, (o) => o.a["p\\ro.p t[] e.stB"]["h\\e'llo w\'or\"ld"]['h\\e"llo w\"or\'ld']['p\\ro.p t[] e.stB']["1"][0].d, (d) => { return d + 1; });
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a[propBName]).not.toBe(o1.a[propBName]);
expect(o2.a[propBName][propCName]).not.toBe(o1.a[propBName][propCName]);
expect(o2.a[propBName][propCName][propDName]).not.toBe(o1.a[propBName][propCName][propDName]);
expect(o2.a[propBName][propCName][propDName][propEName]).not.toBe(o1.a[propBName][propCName][propDName][propEName]);
expect(o2.a[propBName][propCName][propDName][propEName][1]).not.toBe(o1.a[propBName][propCName][propDName][propEName][1]);
expect(o2.a[propBName][propCName][propDName][propEName][1][0]).not.toBe(o1.a[propBName][propCName][propDName][propEName][1][0]);
expect(o2.a[propBName][propCName][propDName][propEName][1][0].d).not.toBe(o1.a[propBName][propCName][propDName][propEName][1][0].d);
});
expect(o2.a[propBName][propCName][propDName][propEName][1][0].d).toBe(22);
it("Access array using context parameter", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a[propBName]).not.toBe(o1.a[propBName]);
expect(o2.a[propBName][propCName]).not.toBe(o1.a[propBName][propCName]);
expect(o2.a[propBName][propCName][propDName]).not.toBe(o1.a[propBName][propCName][propDName]);
expect(o2.a[propBName][propCName][propDName][propEName]).not.toBe(o1.a[propBName][propCName][propDName][propEName]);
expect(o2.a[propBName][propCName][propDName][propEName][1]).not.toBe(o1.a[propBName][propCName][propDName][propEName][1]);
expect(o2.a[propBName][propCName][propDName][propEName][1][0]).not.toBe(o1.a[propBName][propCName][propDName][propEName][1][0]);
expect(o2.a[propBName][propCName][propDName][propEName][1][0].d).not.toBe(o1.a[propBName][propCName][propDName][propEName][1][0].d);
});
var p1 = { a: 0 };
var o2 = iassign(o1, function (o, ctx) { return o.a.b.c[ctx.p1.a][0]; }, function (ci) { ci.d++; return ci; }, { p1 });
it("Access object property using string 4", function () {
let propBName = "p\\r\"o.p t[] e.s't\'B";
let propCName = "h\\e'llo w\'or\"ld";
let propDName = 'h\\e"llo w\"or\'ld';
let propEName = 'p\\r\'o.p t[] e.s"t\"B';
var o1 = { a: { [propBName]: { [propCName]: { [propDName]: { [propEName]: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } } } };
deepFreeze(o1);
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).not.toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).not.toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[0][0].d).not.toBe(o1.a.b.c[0][0].d);
expect(o2.a.b.c[0][0].d).toBe(12);
});
let o2 = iassign(o1, (o) => o.a["p\\r\"o.p t[] e.s't\'B"]["h\\e'llo w\'or\"ld"]['h\\e"llo w\"or\'ld']['p\\r\'o.p t[] e.s"t\"B']["1"][0].d, (d) => { return d + 1; });
it("Try to modify freezed object should throw error.", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
expect(o2.a[propBName][propCName][propDName][propEName][1][0].d).toBe(22);
expect(() => {
iassign(o1, function (o) { return o.a.b.c; }, function (ci) { ci[0].push(<any>3); return ci; });
}).toThrowError(TypeError, /Can't add property/);
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a[propBName]).not.toBe(o1.a[propBName]);
expect(o2.a[propBName][propCName]).not.toBe(o1.a[propBName][propCName]);
expect(o2.a[propBName][propCName][propDName]).not.toBe(o1.a[propBName][propCName][propDName]);
expect(o2.a[propBName][propCName][propDName][propEName]).not.toBe(o1.a[propBName][propCName][propDName][propEName]);
expect(o2.a[propBName][propCName][propDName][propEName][1]).not.toBe(o1.a[propBName][propCName][propDName][propEName][1]);
expect(o2.a[propBName][propCName][propDName][propEName][1][0]).not.toBe(o1.a[propBName][propCName][propDName][propEName][1][0]);
expect(o2.a[propBName][propCName][propDName][propEName][1][0].d).not.toBe(o1.a[propBName][propCName][propDName][propEName][1][0].d);
});
expect(() => {
iassign(o1, function (o) { return o.a.b.c[0]; }, function (ci) { ci[0].d++; return ci; });
}).toThrowError(TypeError, /Cannot assign to read only property/);
it("Access array using context parameter", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
expect(() => {
iassign(o1, function (o) { return o.a.b.c[0]; }, function (ci) { (<any>ci[0]).g = 1; return ci; });
}).toThrowError(TypeError, /Can't add property/);
var p1 = { a: 0 };
var o2 = iassign(o1, function (o, ctx) { return o.a.b.c[ctx.p1.a][0]; }, function (ci) { ci.d++; return ci; }, { p1 });
expect(() => {
iassign(o1, function (o) { return o.a.b.c; }, function (ci) { ci[0].pop(); return ci; });
}).toThrowError(TypeError, /object is not extensible/);
});
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).not.toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).not.toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[0][0].d).not.toBe(o1.a.b.c[0][0].d);
expect(o2.a.b.c[0][0].d).toBe(12);
});
it("Update array using lodash", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }, { d: 13, e: 14 }], [{ d: 21, e: 22 }]] } }, a2: {} };
it("Try to modify freezed object should throw error.", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
deepFreeze(o1);
deepFreeze(o1); // Ensure o1 is not changed, for testing only
expect(() => {
iassign(o1, function (o) { return o.a.b.c; }, function (ci) { ci[0].push(<any>3); return ci; });
}).toThrowError(TypeError, /Can't add property/);
//
// Calling iassign() and _.map() to increment to d in c[0] array
//
let o2 = iassign(
o1,
(o) => o.a.b.c[0],
(c) => {
return _.map(c, (item) => { return iassign(item, (o) => o.d, (d) => d + 1); });
});
expect(() => {
iassign(o1, function (o) { return o.a.b.c[0]; }, function (ci) { ci[0].d++; return ci; });
}).toThrowError(TypeError, /Cannot assign to read only property/);
// expect o1 has not been changed
expect(o1).toEqual({ a: { b: { c: [[{ d: 11, e: 12 }, { d: 13, e: 14 }], [{ d: 21, e: 22 }]] } }, a2: {} })
expect(() => {
iassign(o1, function (o) { return o.a.b.c[0]; }, function (ci) { (<any>ci[0]).g = 1; return ci; });
}).toThrowError(TypeError, /Can't add property/);
expect(o2).toEqual({ a: { b: { c: [[{ d: 12, e: 12 }, { d: 14, e: 14 }], [{ d: 21, e: 22 }]] } }, a2: {} });
expect(() => {
iassign(o1, function (o) { return o.a.b.c; }, function (ci) { ci[0].pop(); return ci; });
}).toThrowError(TypeError, /object is not extensible|Cannot delete property/);
});
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).not.toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).not.toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[0][1]).not.toBe(o1.a.b.c[0][1]);
it("Update array using lodash", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }, { d: 13, e: 14 }], [{ d: 21, e: 22 }]] } }, a2: {} };
expect(o2.a.b.c[1][0]).toBe(o1.a.b.c[1][0]);
});
deepFreeze(o1); // Ensure o1 is not changed, for testing only
it("Update array using lodash 2", function () {
var o1 = { a: { b: { c: [1, 2, 3] } } };
//
// Calling iassign() and _.map() to increment to d in c[0] array
//
let o2 = iassign(
o1,
(o) => o.a.b.c[0],
(c) => {
return _.map(c, (item) => { return iassign(item, (o) => o.d, (d) => d + 1); });
});
deepFreeze(o1); // Ensure o1 is not changed, for testing only
// expect o1 has not been changed
expect(o1).toEqual({ a: { b: { c: [[{ d: 11, e: 12 }, { d: 13, e: 14 }], [{ d: 21, e: 22 }]] } }, a2: {} })
//
// Calling iassign() and _.map() to increment to every item in "c" array
//
let o2 = iassign(
o1,
(o) => o.a.b.c,
(c) => { return _.map(c, (i) => i + 1); }
);
expect(o2).toEqual({ a: { b: { c: [[{ d: 12, e: 12 }, { d: 14, e: 14 }], [{ d: 21, e: 22 }]] } }, a2: {} });
// expect o1 has not been changed
expect(o1).toEqual({ a: { b: { c: [1, 2, 3] } } })
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).not.toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).not.toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[0][1]).not.toBe(o1.a.b.c[0][1]);
// expect o2.a.b.c has been updated.
expect(o2.a.b.c).toEqual([2, 3, 4]);
expect(o2.a.b.c[1][0]).toBe(o1.a.b.c[1][0]);
});
// expect object graph for changed property in o2 is now different from (!==) o1.
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
});
it("Update array using lodash 2", function () {
var o1 = { a: { b: { c: [1, 2, 3] } } };
it("Test root object is an array", function () {
var o1 = [[{ d: 11, e: 12 }, { d: 13, e: 14 }, { d: 21, e: 22 }]];
deepFreeze(o1); // Ensure o1 is not changed, for testing only
deepFreeze(o1); // Ensure o1 is not changed, for testing only
//
// Calling iassign() and _.map() to increment to every item in "c" array
//
let o2 = iassign(
o1,
(o) => o.a.b.c,
(c) => { return _.map(c, (i) => i + 1); }
);
//
// Calling iassign() and _.map() to increment to every item in "c" array
//
let o2 = iassign(
o1,
(o) => o[0],
(o) => {
return _.map(o, (item, index) => {
if (index < 2) {
item = _.cloneDeep(item);
item.d++;
}
return item;
});
}
);
// expect o1 has not been changed
expect(o1).toEqual({ a: { b: { c: [1, 2, 3] } } })
// expect o1 has not been changed
expect(o1).toEqual([[{ d: 11, e: 12 }, { d: 13, e: 14 }, { d: 21, e: 22 }]])
// expect o2.a.b.c has been updated.
expect(o2.a.b.c).toEqual([2, 3, 4]);
// expect o2.a.b.c has been updated.
expect(o2).toEqual([[{ d: 12, e: 12 }, { d: 14, e: 14 }, { d: 21, e: 22 }]]);
// expect object graph for changed property in o2 is now different from (!==) o1.
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
});
// expect object graph for changed property in o2 is now different from (!==) o1.
expect(o2).not.toBe(o1);
expect(o2[0]).not.toBe(o1[0]);
expect(o2[0][0]).not.toBe(o1[0][0]);
expect(o2[0][1]).not.toBe(o1[0][1]);
it("Test root object is an array", function () {
var o1 = [[{ d: 11, e: 12 }, { d: 13, e: 14 }, { d: 21, e: 22 }]];
// expect object graph for unchanged property in o2 is still equal to (===) o1.
expect(o2[0][2]).toBe(o1[0][2]);
});
deepFreeze(o1); // Ensure o1 is not changed, for testing only
it("Test root is an array, and try to update root array", function () {
var o1 = [{ d: 11, e: 12 }, { d: 13, e: 14 }, { d: 21, e: 22 }];
//
// Calling iassign() and _.map() to increment to every item in "c" array
//
let o2 = iassign(
o1,
(o) => o[0],
(o) => {
return _.map(o, (item, index) => {
if (index < 2) {
item = _.cloneDeep(item);
item.d++;
}
return item;
});
}
);
deepFreeze(o1); // Ensure o1 is not changed, for testing only
// expect o1 has not been changed
expect(o1).toEqual([[{ d: 11, e: 12 }, { d: 13, e: 14 }, { d: 21, e: 22 }]])
//
// Calling iassign() and _.map() to increment to every item in "c" array
//
let o2 = iassign(
o1,
(o) => o,
(o) => {
return _.map(o, (item, index) => {
if (index < 2) {
item = _.cloneDeep(item);
item.d++;
}
return item;
});
}
);
// expect o2.a.b.c has been updated.
expect(o2).toEqual([[{ d: 12, e: 12 }, { d: 14, e: 14 }, { d: 21, e: 22 }]]);
// expect o1 has not been changed
expect(o1).toEqual([{ d: 11, e: 12 }, { d: 13, e: 14 }, { d: 21, e: 22 }])
// expect object graph for changed property in o2 is now different from (!==) o1.
expect(o2).not.toBe(o1);
expect(o2[0]).not.toBe(o1[0]);
expect(o2[0][0]).not.toBe(o1[0][0]);
expect(o2[0][1]).not.toBe(o1[0][1]);
// expect o2.a.b.c has been updated.
expect(o2).toEqual([{ d: 12, e: 12 }, { d: 14, e: 14 }, { d: 21, e: 22 }]);
// expect object graph for unchanged property in o2 is still equal to (===) o1.
expect(o2[0][2]).toBe(o1[0][2]);
});
// expect object graph for changed property in o2 is now different from (!==) o1.
expect(o2).not.toBe(o1);
expect(o2[0]).not.toBe(o1[0]);
expect(o2[1]).not.toBe(o1[1]);
it("Test root is an array, and try to update root array", function () {
var o1 = [{ d: 11, e: 12 }, { d: 13, e: 14 }, { d: 21, e: 22 }];
// expect object graph for unchanged property in o2 is still equal to (===) o1.
expect(o2[2]).toBe(o1[2]);
});
deepFreeze(o1); // Ensure o1 is not changed, for testing only
it("Test root is an object, and try to update root object", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }]], c2: {} }, b2: {} }, a2: {} };
deepFreeze(o1);
//
// Calling iassign() and _.map() to increment to every item in "c" array
//
let o2 = iassign(
o1,
(o) => o,
(o) => {
return _.map(o, (item, index) => {
if (index < 2) {
item = _.cloneDeep(item);
item.d++;
}
return item;
});
}
);
var o2 = iassign(
o1,
(o) => o,
(o) => { o.a = <any>{ b: 1 }; return o; }
);
// expect o1 has not been changed
expect(o1).toEqual([{ d: 11, e: 12 }, { d: 13, e: 14 }, { d: 21, e: 22 }])
//
// Jasmine Tests
//
// expect o2.a.b.c has been updated.
expect(o2).toEqual([{ d: 12, e: 12 }, { d: 14, e: 14 }, { d: 21, e: 22 }]);
// expect o1 has not been changed
expect(o1).toEqual({ a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }]], c2: {} }, b2: {} }, a2: {} });
// expect object graph for changed property in o2 is now different from (!==) o1.
expect(o2).not.toBe(o1);
expect(o2[0]).not.toBe(o1[0]);
expect(o2[1]).not.toBe(o1[1]);
// expect o2 inner property has been updated.
expect(o2).toEqual({ a: { b: 1 }, a2: {} });
// expect object graph for unchanged property in o2 is still equal to (===) o1.
expect(o2[2]).toBe(o1[2]);
});
// expect object graph for changed property in o2 is now different from (!==) o1.
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
it("Test root is an object, and try to update root object", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }]], c2: {} }, b2: {} }, a2: {} };
deepFreeze(o1);
// expect object graph for unchanged property in o2 is still equal to (===) o1.
expect(o2.a2).toBe(o1.a2);
});
var o2 = iassign(
o1,
(o) => o,
(o) => { o.a = <any>{ b: 1 }; return o; }
);
it("Use built-in deep freeze to protect input", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
iassign.freezeInput = true;
//
// Jasmine Tests
//
expect(() => {
iassign(o1, function (o) { return o.a.b.c; }, function (ci) { ci[0].push(<any>3); return ci; });
}).toThrowError(TypeError, /Can't add property/);
// expect o1 has not been changed
expect(o1).toEqual({ a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }]], c2: {} }, b2: {} }, a2: {} });
expect(() => {
iassign(o1, function (o) { return o.a.b.c[0]; }, function (ci) { ci[0].d++; return ci; });
}).toThrowError(TypeError, /Cannot assign to read only property/);
// expect o2 inner property has been updated.
expect(o2).toEqual({ a: { b: 1 }, a2: {} });
expect(() => {
iassign(o1, function (o) { return o.a.b.c[0]; }, function (ci) { (<any>ci[0]).g = 1; return ci; });
}).toThrowError(TypeError, /Can't add property/);
// expect object graph for changed property in o2 is now different from (!==) o1.
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(() => {
iassign(o1, function (o) { return o.a.b.c; }, function (ci) { ci[0].pop(); return ci; });
}).toThrowError(TypeError, /object is not extensible/);
// expect object graph for unchanged property in o2 is still equal to (===) o1.
expect(o2.a2).toBe(o1.a2);
});
iassign.freezeInput = undefined;
});
it("Use built-in deep freeze to protect input", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }], [{ d: 31, e: 32 }]] } } };
iassign.freezeInput = true;
it("Use built-in deep freeze to protect output", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }, { d: 13, e: 14 }, { d: 21, e: 22 }]] } } };
iassign.freezeOutput = true;
expect(() => {
iassign(o1, function (o) { return o.a.b.c; }, function (ci) { ci[0].push(<any>3); return ci; });
}).toThrowError(TypeError, /Can't add property/);
let o2 = iassign(
o1,
(o) => o.a.b.c[0],
(c) => {
return _.map(c, (item) => { return iassign(item, (o) => o.d, (d) => d + 1); });
});
expect(() => {
iassign(o1, function (o) { return o.a.b.c[0]; }, function (ci) { ci[0].d++; return ci; });
}).toThrowError(TypeError, /Cannot assign to read only property/);
// expect o1 has not been changed
expect(o1).toEqual({ a: { b: { c: [[{ d: 11, e: 12 }, { d: 13, e: 14 }, { d: 21, e: 22 }]] } } })
expect(() => {
iassign(o1, function (o) { return o.a.b.c[0]; }, function (ci) { (<any>ci[0]).g = 1; return ci; });
}).toThrowError(TypeError, /Can't add property/);
expect(o2.a.b.c[0][0].d).toBe(12);
expect(o2.a.b.c[0][1].d).toBe(14);
expect(o2.a.b.c[0][2].d).toBe(22);
expect(() => {
iassign(o1, function (o) { return o.a.b.c; }, function (ci) { ci[0].pop(); return ci; });
}).toThrowError(TypeError, /object is not extensible|Cannot delete property/);
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).not.toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).not.toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[0][1]).not.toBe(o1.a.b.c[0][1]);
expect(o2.a.b.c[0][2]).not.toBe(o1.a.b.c[0][2]);
iassign.freezeInput = undefined;
});
expect(() => {
o2.a.b.c[0].push(<any>3);
}).toThrowError(TypeError, /Can't add property/);
it("Use built-in deep freeze to protect output", function () {
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }, { d: 13, e: 14 }, { d: 21, e: 22 }]] } } };
iassign.freezeOutput = true;
expect(() => {
o2.a.b.c[0][0].d++;
}).toThrowError(TypeError, /Cannot assign to read only property/);
let o2 = iassign(
o1,
(o) => o.a.b.c[0],
(c) => {
return _.map(c, (item) => { return iassign(item, (o) => o.d, (d) => d + 1); });
});
expect(() => {
(<any>o2.a.b.c[0][0]).g = 1;
}).toThrowError(TypeError, /Can't add property/);
// expect o1 has not been changed
expect(o1).toEqual({ a: { b: { c: [[{ d: 11, e: 12 }, { d: 13, e: 14 }, { d: 21, e: 22 }]] } } })
expect(() => {
o2.a.b.c[0].pop();
}).toThrowError(TypeError, /object is not extensible/);
expect(o2.a.b.c[0][0].d).toBe(12);
expect(o2.a.b.c[0][1].d).toBe(14);
expect(o2.a.b.c[0][2].d).toBe(22);
iassign.freezeOutput = undefined;
expect(o2).not.toBe(o1);
expect(o2.a).not.toBe(o1.a);
expect(o2.a.b).not.toBe(o1.a.b);
expect(o2.a.b.c).not.toBe(o1.a.b.c);
expect(o2.a.b.c[0]).not.toBe(o1.a.b.c[0]);
expect(o2.a.b.c[0][0]).not.toBe(o1.a.b.c[0][0]);
expect(o2.a.b.c[0][1]).not.toBe(o1.a.b.c[0][1]);
expect(o2.a.b.c[0][2]).not.toBe(o1.a.b.c[0][2]);
expect(() => {
o2.a.b.c[0].push(<any>3);
}).toThrowError(TypeError, /Can't add property/);
expect(() => {
o2.a.b.c[0][0].d++;
}).toThrowError(TypeError, /Cannot assign to read only property/);
expect(() => {
(<any>o2.a.b.c[0][0]).g = 1;
}).toThrowError(TypeError, /Can't add property/);
expect(() => {
o2.a.b.c[0].pop();
}).toThrowError(TypeError, /object is not extensible|Cannot delete property/);
iassign.freezeOutput = undefined;
});
});
});
});

@@ -27,1 +27,3 @@

}
declare var iassign: ImmutableAssign.IIassign;
"use strict";
//import deepFreeze = require("deep-freeze");
try {
var deepFreeze = require("deep-freeze");
}
catch (ex) {
console.warn("Cannot load deep-freeze module, however you can still use iassign() function.");
}
var iassign = _iassign;
// Immutable Assign
function _iassign(obj, // Object to set property, it will not be modified.
getProp, // Function to get property to be updated. Must be pure function.
setProp, // Function to set property.
context, // (Optional) Context to be used in getProp().
option) {
if (option) {
option = extend({}, iassign, option);
(function (root, factory) {
if (typeof module === 'object' && typeof module.exports === 'object') {
var v = factory(require, exports);
if (v !== undefined)
module.exports = v;
}
else if (typeof define === 'function' && define.amd) {
define(["require", "exports"], factory);
}
else {
option = iassign;
// Browser globals (root is window)
var require_1 = function (name) {
if (name == "deep-freeze" && root.deepFreeze) {
return root.deepFreeze;
}
throw new Error("Unable to require: " + name);
};
root.iassign = factory(require_1, {});
}
if (deepFreeze && (option.freeze || option.freezeInput)) {
deepFreeze(obj);
})(this, function (require, exports) {
//import deepFreeze = require("deep-freeze");
try {
var deepFreeze = require("deep-freeze");
}
// Check if getProp() is valid
var value = getProp(obj, context);
var getPropFuncInfo = parseGetPropFuncInfo(getProp, option);
var accessorText = getPropFuncInfo.accessorText;
var propIndex = 0;
var propValue = undefined;
while (accessorText) {
var openBracketIndex = accessorText.indexOf("[");
var closeBracketIndex = accessorText.indexOf("]");
var dotIndex = accessorText.indexOf(".");
var propName = "";
var propNameSource = ePropNameSource.none;
// if (dotIndex == 0) {
// accessorText = accessorText.substr(dotIndex + 1);
// continue;
// }
if (openBracketIndex > -1 && closeBracketIndex <= -1) {
throw new Error("Found open bracket but not close bracket.");
catch (ex) {
console.warn("Cannot load deep-freeze module, however you can still use iassign() function.");
}
var iassign = _iassign;
// Immutable Assign
function _iassign(obj, // Object to set property, it will not be modified.
getProp, // Function to get property to be updated. Must be pure function.
setProp, // Function to set property.
context, // (Optional) Context to be used in getProp().
option) {
if (option) {
option = extend({}, iassign, option);
}
if (openBracketIndex <= -1 && closeBracketIndex > -1) {
throw new Error("Found close bracket but not open bracket.");
else {
option = iassign;
}
if (dotIndex > -1 && (dotIndex < openBracketIndex || openBracketIndex <= -1)) {
propName = accessorText.substr(0, dotIndex);
accessorText = accessorText.substr(dotIndex + 1);
propNameSource = ePropNameSource.beforeDot;
if (deepFreeze && (option.freeze || option.freezeInput)) {
deepFreeze(obj);
}
else if (openBracketIndex > -1 && (openBracketIndex < dotIndex || dotIndex <= -1)) {
if (openBracketIndex > 0) {
propName = accessorText.substr(0, openBracketIndex);
accessorText = accessorText.substr(openBracketIndex);
propNameSource = ePropNameSource.beforeBracket;
// Check if getProp() is valid
var value = getProp(obj, context);
var getPropFuncInfo = parseGetPropFuncInfo(getProp, option);
var accessorText = getPropFuncInfo.accessorText;
var propIndex = 0;
var propValue = undefined;
while (accessorText) {
var openBracketIndex = accessorText.indexOf("[");
var closeBracketIndex = accessorText.indexOf("]");
var dotIndex = accessorText.indexOf(".");
var propName = "";
var propNameSource = ePropNameSource.none;
// if (dotIndex == 0) {
// accessorText = accessorText.substr(dotIndex + 1);
// continue;
// }
if (openBracketIndex > -1 && closeBracketIndex <= -1) {
throw new Error("Found open bracket but not close bracket.");
}
if (openBracketIndex <= -1 && closeBracketIndex > -1) {
throw new Error("Found close bracket but not open bracket.");
}
if (dotIndex > -1 && (dotIndex < openBracketIndex || openBracketIndex <= -1)) {
propName = accessorText.substr(0, dotIndex);
accessorText = accessorText.substr(dotIndex + 1);
propNameSource = ePropNameSource.beforeDot;
}
else if (openBracketIndex > -1 && (openBracketIndex < dotIndex || dotIndex <= -1)) {
if (openBracketIndex > 0) {
propName = accessorText.substr(0, openBracketIndex);
accessorText = accessorText.substr(openBracketIndex);
propNameSource = ePropNameSource.beforeBracket;
}
else {
propName = accessorText.substr(openBracketIndex + 1, closeBracketIndex - 1);
accessorText = accessorText.substr(closeBracketIndex + 1);
propNameSource = ePropNameSource.inBracket;
}
}
else {
propName = accessorText.substr(openBracketIndex + 1, closeBracketIndex - 1);
accessorText = accessorText.substr(closeBracketIndex + 1);
propNameSource = ePropNameSource.inBracket;
propName = accessorText;
accessorText = "";
propNameSource = ePropNameSource.last;
}
}
else {
propName = accessorText;
accessorText = "";
propNameSource = ePropNameSource.last;
}
propName = propName.trim();
if (propName == "") {
continue;
}
//console.log(propName);
if (propIndex <= 0) {
propValue = quickCopy(obj);
if (!accessorText) {
propValue = setProp(propValue);
propName = propName.trim();
if (propName == "") {
continue;
}
obj = propValue;
}
else {
var prevPropValue = propValue;
if (propNameSource == ePropNameSource.inBracket && isNaN(propName)) {
if (propName[0] == "#") {
var quotedPropName = getPropFuncInfo.quotedTextInfos[propName];
if (!quotedPropName) {
throw new Error("Cannot find quoted text for " + quotedPropName);
}
propName = eval(quotedPropName);
//console.log(propName);
if (propIndex <= 0) {
propValue = quickCopy(obj);
if (!accessorText) {
propValue = setProp(propValue);
}
else {
var statement = "'use strict';\n";
if (getPropFuncInfo.objParameterName) {
statement += "var " + getPropFuncInfo.objParameterName + " = arguments[1];\n";
obj = propValue;
}
else {
var prevPropValue = propValue;
if (propNameSource == ePropNameSource.inBracket && isNaN(propName)) {
if (propName[0] == "#") {
var quotedPropName = getPropFuncInfo.quotedTextInfos[propName];
if (!quotedPropName) {
throw new Error("Cannot find quoted text for " + quotedPropName);
}
propName = eval(quotedPropName);
}
if (getPropFuncInfo.cxtParameterName) {
statement += "var " + getPropFuncInfo.cxtParameterName + " = arguments[2];\n";
else {
var statement = "'use strict';\n";
if (getPropFuncInfo.objParameterName) {
statement += "var " + getPropFuncInfo.objParameterName + " = arguments[1];\n";
}
if (getPropFuncInfo.cxtParameterName) {
statement += "var " + getPropFuncInfo.cxtParameterName + " = arguments[2];\n";
}
statement += "" + propName;
propName = evalStatement(statement, obj, context);
}
statement += "" + propName;
propName = evalStatement(statement, obj, context);
}
propValue = propValue[propName];
propValue = quickCopy(propValue);
if (!accessorText) {
propValue = setProp(propValue);
}
prevPropValue[propName] = propValue;
}
propValue = propValue[propName];
propValue = quickCopy(propValue);
if (!accessorText) {
propValue = setProp(propValue);
}
prevPropValue[propName] = propValue;
//console.log(propValue);
propIndex++;
}
//console.log(propValue);
propIndex++;
}
if (deepFreeze && (option.freeze || option.freezeOutput)) {
deepFreeze(obj);
}
return obj;
}
var ePropNameSource;
(function (ePropNameSource) {
ePropNameSource[ePropNameSource["none"] = 0] = "none";
ePropNameSource[ePropNameSource["beforeDot"] = 1] = "beforeDot";
ePropNameSource[ePropNameSource["beforeBracket"] = 2] = "beforeBracket";
ePropNameSource[ePropNameSource["inBracket"] = 3] = "inBracket";
ePropNameSource[ePropNameSource["last"] = 4] = "last";
})(ePropNameSource || (ePropNameSource = {}));
function parseGetPropFuncInfo(func, option) {
var funcText = func.toString();
var matches = /\(([^\)]*)\)/.exec(funcText);
var objParameterName = undefined;
var cxtParameterName = undefined;
if (matches) {
var parametersText = matches[1];
var parameters = parametersText.split(",");
objParameterName = parameters[0];
cxtParameterName = parameters[1];
}
if (objParameterName) {
objParameterName = objParameterName.trim();
}
if (cxtParameterName) {
cxtParameterName = cxtParameterName.trim();
}
var bodyText = funcText.substring(funcText.indexOf("{") + 1, funcText.lastIndexOf("}"));
var accessorTextInfo = getAccessorTextInfo(bodyText, option);
return {
objParameterName: objParameterName,
cxtParameterName: cxtParameterName,
bodyText: bodyText,
accessorText: accessorTextInfo.accessorText,
quotedTextInfos: accessorTextInfo.quotedTextInfos,
};
}
function getAccessorTextInfo(bodyText, option) {
var returnIndex = bodyText.indexOf("return ");
if (!option.disableAllCheck && !option.disableHasReturnCheck) {
if (returnIndex <= -1) {
throw new Error("getProp() function has no 'return' keyword.");
if (deepFreeze && (option.freeze || option.freezeOutput)) {
deepFreeze(obj);
}
return obj;
}
if (!option.disableAllCheck && !option.disableExtraStatementCheck) {
var otherBodyText = bodyText.substr(0, returnIndex).trim();
if (otherBodyText != "") {
throw new Error("getProp() function has statements other than 'return': " + otherBodyText);
var ePropNameSource;
(function (ePropNameSource) {
ePropNameSource[ePropNameSource["none"] = 0] = "none";
ePropNameSource[ePropNameSource["beforeDot"] = 1] = "beforeDot";
ePropNameSource[ePropNameSource["beforeBracket"] = 2] = "beforeBracket";
ePropNameSource[ePropNameSource["inBracket"] = 3] = "inBracket";
ePropNameSource[ePropNameSource["last"] = 4] = "last";
})(ePropNameSource || (ePropNameSource = {}));
function parseGetPropFuncInfo(func, option) {
var funcText = func.toString();
var matches = /\(([^\)]*)\)/.exec(funcText);
var objParameterName = undefined;
var cxtParameterName = undefined;
if (matches) {
var parametersText = matches[1];
var parameters = parametersText.split(",");
objParameterName = parameters[0];
cxtParameterName = parameters[1];
}
if (objParameterName) {
objParameterName = objParameterName.trim();
}
if (cxtParameterName) {
cxtParameterName = cxtParameterName.trim();
}
var bodyText = funcText.substring(funcText.indexOf("{") + 1, funcText.lastIndexOf("}"));
var accessorTextInfo = getAccessorTextInfo(bodyText, option);
return {
objParameterName: objParameterName,
cxtParameterName: cxtParameterName,
bodyText: bodyText,
accessorText: accessorTextInfo.accessorText,
quotedTextInfos: accessorTextInfo.quotedTextInfos,
};
}
var accessorText = bodyText.substr(returnIndex + 7).trim();
if (accessorText[accessorText.length - 1] == ";") {
accessorText = accessorText.substring(0, accessorText.length - 1);
}
accessorText = accessorText.trim();
return parseTextInQuotes(accessorText, option);
}
function parseTextInQuotes(accessorText, option) {
var quotedTextInfos = {};
var index = 0;
while (true) {
var singleQuoteIndex = accessorText.indexOf("'");
var doubleQuoteIndex = accessorText.indexOf('"');
var varName = "#" + index++;
if (singleQuoteIndex <= -1 && doubleQuoteIndex <= -1)
break;
var matches = undefined;
var quoteIndex = void 0;
if (doubleQuoteIndex > -1 && (doubleQuoteIndex < singleQuoteIndex || singleQuoteIndex <= -1)) {
matches = /("[^"\\]*(?:\\.[^"\\]*)*")/.exec(accessorText);
quoteIndex = doubleQuoteIndex;
function getAccessorTextInfo(bodyText, option) {
var returnIndex = bodyText.indexOf("return ");
if (!option.disableAllCheck && !option.disableHasReturnCheck) {
if (returnIndex <= -1) {
throw new Error("getProp() function has no 'return' keyword.");
}
}
else if (singleQuoteIndex > -1 && (singleQuoteIndex < doubleQuoteIndex || doubleQuoteIndex <= -1)) {
matches = /('[^'\\]*(?:\\.[^'\\]*)*')/.exec(accessorText);
quoteIndex = singleQuoteIndex;
if (!option.disableAllCheck && !option.disableExtraStatementCheck) {
var otherBodyText = bodyText.substr(0, returnIndex).trim();
if (otherBodyText != "") {
throw new Error("getProp() function has statements other than 'return': " + otherBodyText);
}
}
if (matches) {
quotedTextInfos[varName] = matches[1];
accessorText =
accessorText.substr(0, quoteIndex) +
varName +
accessorText.substr(matches.index + matches[1].length);
var accessorText = bodyText.substr(returnIndex + 7).trim();
if (accessorText[accessorText.length - 1] == ";") {
accessorText = accessorText.substring(0, accessorText.length - 1);
}
else {
throw new Error("Invalid text in quotes: " + accessorText);
accessorText = accessorText.trim();
return parseTextInQuotes(accessorText, option);
}
function parseTextInQuotes(accessorText, option) {
var quotedTextInfos = {};
var index = 0;
while (true) {
var singleQuoteIndex = accessorText.indexOf("'");
var doubleQuoteIndex = accessorText.indexOf('"');
var varName = "#" + index++;
if (singleQuoteIndex <= -1 && doubleQuoteIndex <= -1)
break;
var matches = undefined;
var quoteIndex = void 0;
if (doubleQuoteIndex > -1 && (doubleQuoteIndex < singleQuoteIndex || singleQuoteIndex <= -1)) {
matches = /("[^"\\]*(?:\\.[^"\\]*)*")/.exec(accessorText);
quoteIndex = doubleQuoteIndex;
}
else if (singleQuoteIndex > -1 && (singleQuoteIndex < doubleQuoteIndex || doubleQuoteIndex <= -1)) {
matches = /('[^'\\]*(?:\\.[^'\\]*)*')/.exec(accessorText);
quoteIndex = singleQuoteIndex;
}
if (matches) {
quotedTextInfos[varName] = matches[1];
accessorText =
accessorText.substr(0, quoteIndex) +
varName +
accessorText.substr(matches.index + matches[1].length);
}
else {
throw new Error("Invalid text in quotes: " + accessorText);
}
}
return {
accessorText: accessorText,
quotedTextInfos: quotedTextInfos,
};
}
return {
accessorText: accessorText,
quotedTextInfos: quotedTextInfos,
};
}
function quickCopy(value) {
if (value != undefined && !(value instanceof Date)) {
if (value instanceof Array) {
return value.slice();
function quickCopy(value) {
if (value != undefined && !(value instanceof Date)) {
if (value instanceof Array) {
return value.slice();
}
else if (typeof (value) === "object") {
return extend({}, value);
}
}
else if (typeof (value) === "object") {
return extend({}, value);
return value;
}
function extend(destination) {
var sources = [];
for (var _i = 1; _i < arguments.length; _i++) {
sources[_i - 1] = arguments[_i];
}
}
return value;
}
function extend(destination) {
var sources = [];
for (var _i = 1; _i < arguments.length; _i++) {
sources[_i - 1] = arguments[_i];
}
for (var _a = 0, sources_1 = sources; _a < sources_1.length; _a++) {
var source = sources_1[_a];
for (var key in source) {
var value = source[key];
if (value !== undefined) {
destination[key] = value;
for (var _a = 0, sources_1 = sources; _a < sources_1.length; _a++) {
var source = sources_1[_a];
for (var key in source) {
if (!Object.prototype.hasOwnProperty.call(source, key)) {
continue;
}
var value = source[key];
if (value !== undefined) {
destination[key] = value;
}
}
}
return destination;
}
return destination;
}
function evalStatement() {
return eval(arguments[0]);
}
module.exports = iassign;
function evalStatement() {
return eval(arguments[0]);
}
// function isTextInQuote(text: string): boolean {
// let quoteMarks = ["'", '"'];
// for (let mark of quoteMarks) {
// if (text[0] == mark && text[text.length-1] == mark) {
// return true;
// }
// }
// return false;
// }
// function extractTextInQuote(text: string): string {
// let quoteMarks = ["'", '"'];
// for (let mark of quoteMarks) {
// if (text[0] == mark) {
// let regex = new RegExp(`^[${mark}]([^${mark}]*)[${mark}]$`);
// let match = regex.exec(text);
// if (match) {
// return match[1];
// }
// }
// }
// return undefined;
// }
return iassign;
});
//declare var iassign: IIassign;
//export = iassign;

@@ -1,11 +0,5 @@

"use strict";
"use strict"
//import deepFreeze = require("deep-freeze");
declare var define;
try {
var deepFreeze: DeepFreeze.DeepFreezeInterface = require("deep-freeze");
} catch (ex) {
console.warn("Cannot load deep-freeze module, however you can still use iassign() function.");
}
interface IIassignOption {

@@ -29,309 +23,342 @@ freeze: boolean; // Deep freeze both input and output

var iassign: IIassign = <any>_iassign;
// Immutable Assign
function _iassign<TObj, TProp, TContext>(
obj: TObj, // Object to set property, it will not be modified.
getProp: (obj: TObj, context: TContext) => TProp, // Function to get property to be updated. Must be pure function.
setProp: (prop: TProp) => TProp, // Function to set property.
context?: TContext, // (Optional) Context to be used in getProp().
option?: IIassignOption): TObj {
if (option) {
option = extend({}, iassign, option);
(function (root, factory) {
if (typeof module === 'object' && typeof module.exports === 'object') {
var v = factory(require, exports); if (v !== undefined) module.exports = v;
}
else {
option = iassign;
}
else if (typeof define === 'function' && define.amd) {
define(["require", "exports"], factory);
} else {
// Browser globals (root is window)
let require = (name) => {
if (name == "deep-freeze" && root.deepFreeze) {
return root.deepFreeze;
}
if (deepFreeze && (option.freeze || option.freezeInput)) {
deepFreeze(obj);
throw new Error("Unable to require: " + name);
}
root.iassign = factory(require, {});
}
})(this, function (require, exports) {
// Check if getProp() is valid
let value = getProp(obj, context);
//import deepFreeze = require("deep-freeze");
let getPropFuncInfo = parseGetPropFuncInfo(getProp, option);
let accessorText = getPropFuncInfo.accessorText;
try {
var deepFreeze: DeepFreeze.DeepFreezeInterface = require("deep-freeze");
} catch (ex) {
console.warn("Cannot load deep-freeze module, however you can still use iassign() function.");
}
let propIndex = 0;
let propValue = undefined;
var iassign: IIassign = <any>_iassign;
while (accessorText) {
let openBracketIndex = accessorText.indexOf("[");
let closeBracketIndex = accessorText.indexOf("]");
let dotIndex = accessorText.indexOf(".");
let propName = "";
let propNameSource = ePropNameSource.none;
// Immutable Assign
function _iassign<TObj, TProp, TContext>(
obj: TObj, // Object to set property, it will not be modified.
getProp: (obj: TObj, context: TContext) => TProp, // Function to get property to be updated. Must be pure function.
setProp: (prop: TProp) => TProp, // Function to set property.
context?: TContext, // (Optional) Context to be used in getProp().
option?: IIassignOption): TObj {
// if (dotIndex == 0) {
// accessorText = accessorText.substr(dotIndex + 1);
// continue;
// }
if (openBracketIndex > -1 && closeBracketIndex <= -1) {
throw new Error("Found open bracket but not close bracket.");
if (option) {
option = extend({}, iassign, option);
}
if (openBracketIndex <= -1 && closeBracketIndex > -1) {
throw new Error("Found close bracket but not open bracket.");
else {
option = iassign;
}
if (dotIndex > -1 && (dotIndex < openBracketIndex || openBracketIndex <= -1)) {
propName = accessorText.substr(0, dotIndex);
accessorText = accessorText.substr(dotIndex + 1);
propNameSource = ePropNameSource.beforeDot;
if (deepFreeze && (option.freeze || option.freezeInput)) {
deepFreeze(obj);
}
else if (openBracketIndex > -1 && (openBracketIndex < dotIndex || dotIndex <= -1)) {
if (openBracketIndex > 0) {
propName = accessorText.substr(0, openBracketIndex);
accessorText = accessorText.substr(openBracketIndex);
propNameSource = ePropNameSource.beforeBracket;
// Check if getProp() is valid
let value = getProp(obj, context);
let getPropFuncInfo = parseGetPropFuncInfo(getProp, option);
let accessorText = getPropFuncInfo.accessorText;
let propIndex = 0;
let propValue = undefined;
while (accessorText) {
let openBracketIndex = accessorText.indexOf("[");
let closeBracketIndex = accessorText.indexOf("]");
let dotIndex = accessorText.indexOf(".");
let propName = "";
let propNameSource = ePropNameSource.none;
// if (dotIndex == 0) {
// accessorText = accessorText.substr(dotIndex + 1);
// continue;
// }
if (openBracketIndex > -1 && closeBracketIndex <= -1) {
throw new Error("Found open bracket but not close bracket.");
}
if (openBracketIndex <= -1 && closeBracketIndex > -1) {
throw new Error("Found close bracket but not open bracket.");
}
if (dotIndex > -1 && (dotIndex < openBracketIndex || openBracketIndex <= -1)) {
propName = accessorText.substr(0, dotIndex);
accessorText = accessorText.substr(dotIndex + 1);
propNameSource = ePropNameSource.beforeDot;
}
else if (openBracketIndex > -1 && (openBracketIndex < dotIndex || dotIndex <= -1)) {
if (openBracketIndex > 0) {
propName = accessorText.substr(0, openBracketIndex);
accessorText = accessorText.substr(openBracketIndex);
propNameSource = ePropNameSource.beforeBracket;
}
else {
propName = accessorText.substr(openBracketIndex + 1, closeBracketIndex - 1);
accessorText = accessorText.substr(closeBracketIndex + 1);
propNameSource = ePropNameSource.inBracket;
}
}
else {
propName = accessorText.substr(openBracketIndex + 1, closeBracketIndex - 1);
accessorText = accessorText.substr(closeBracketIndex + 1);
propNameSource = ePropNameSource.inBracket;
propName = accessorText;
accessorText = "";
propNameSource = ePropNameSource.last;
}
}
else {
propName = accessorText;
accessorText = "";
propNameSource = ePropNameSource.last;
}
propName = propName.trim();
if (propName == "") {
continue;
}
propName = propName.trim();
if (propName == "") {
continue;
}
//console.log(propName);
//console.log(propName);
if (propIndex <= 0) {
propValue = quickCopy(obj);
if (propIndex <= 0) {
propValue = quickCopy(obj);
if (!accessorText) {
propValue = setProp(propValue);
if (!accessorText) {
propValue = setProp(propValue);
}
obj = propValue;
}
else {
let prevPropValue = propValue;
obj = propValue;
}
else {
let prevPropValue = propValue;
if (propNameSource == ePropNameSource.inBracket && isNaN(<any>propName)) {
if (propNameSource == ePropNameSource.inBracket && isNaN(<any>propName)) {
if (propName[0] == "#") {
let quotedPropName = getPropFuncInfo.quotedTextInfos[propName];
if (!quotedPropName) {
throw new Error("Cannot find quoted text for " + quotedPropName);
if (propName[0] == "#") {
let quotedPropName = getPropFuncInfo.quotedTextInfos[propName];
if (!quotedPropName) {
throw new Error("Cannot find quoted text for " + quotedPropName);
}
propName = eval(quotedPropName);
}
propName = eval(quotedPropName);
}
else {
let statement = `'use strict';\n`;
if (getPropFuncInfo.objParameterName) {
statement += `var ${getPropFuncInfo.objParameterName} = arguments[1];\n`
else {
let statement = `'use strict';\n`;
if (getPropFuncInfo.objParameterName) {
statement += `var ${getPropFuncInfo.objParameterName} = arguments[1];\n`
}
if (getPropFuncInfo.cxtParameterName) {
statement += `var ${getPropFuncInfo.cxtParameterName} = arguments[2];\n`
}
statement += `${propName}`;
propName = (<any>evalStatement)(statement, obj, context);
}
if (getPropFuncInfo.cxtParameterName) {
statement += `var ${getPropFuncInfo.cxtParameterName} = arguments[2];\n`
}
statement += `${propName}`;
propName = (<any>evalStatement)(statement, obj, context);
}
}
propValue = propValue[propName];
propValue = quickCopy(propValue)
propValue = propValue[propName];
propValue = quickCopy(propValue)
if (!accessorText) {
propValue = setProp(propValue);
if (!accessorText) {
propValue = setProp(propValue);
}
prevPropValue[propName] = propValue;
}
prevPropValue[propName] = propValue;
//console.log(propValue);
propIndex++;
}
//console.log(propValue);
if (deepFreeze && (option.freeze || option.freezeOutput)) {
deepFreeze(obj);
}
propIndex++;
return obj;
}
if (deepFreeze && (option.freeze || option.freezeOutput)) {
deepFreeze(obj);
enum ePropNameSource {
none,
beforeDot,
beforeBracket,
inBracket,
last,
}
return obj;
}
function parseGetPropFuncInfo(func: Function, option: IIassignOption) {
let funcText = func.toString();
enum ePropNameSource {
none,
beforeDot,
beforeBracket,
inBracket,
last,
}
let matches = /\(([^\)]*)\)/.exec(funcText);
var objParameterName = undefined;
let cxtParameterName = undefined;
if (matches) {
let parametersText = matches[1];
let parameters = parametersText.split(",");
objParameterName = parameters[0];
cxtParameterName = parameters[1];
}
function parseGetPropFuncInfo(func: Function, option: IIassignOption) {
let funcText = func.toString();
if (objParameterName) {
objParameterName = objParameterName.trim();
}
let matches = /\(([^\)]*)\)/.exec(funcText);
var objParameterName = undefined;
let cxtParameterName = undefined;
if (matches) {
let parametersText = matches[1];
let parameters = parametersText.split(",");
objParameterName = parameters[0];
cxtParameterName = parameters[1];
}
if (cxtParameterName) {
cxtParameterName = cxtParameterName.trim();
}
if (objParameterName) {
objParameterName = objParameterName.trim();
}
let bodyText = funcText.substring(funcText.indexOf("{") + 1, funcText.lastIndexOf("}"));
let accessorTextInfo = getAccessorTextInfo(bodyText, option);
if (cxtParameterName) {
cxtParameterName = cxtParameterName.trim();
return {
objParameterName: objParameterName,
cxtParameterName: cxtParameterName,
bodyText: bodyText,
accessorText: accessorTextInfo.accessorText,
quotedTextInfos: accessorTextInfo.quotedTextInfos,
}
}
let bodyText = funcText.substring(funcText.indexOf("{") + 1, funcText.lastIndexOf("}"));
let accessorTextInfo = getAccessorTextInfo(bodyText, option);
function getAccessorTextInfo(bodyText: string, option: IIassignOption) {
return {
objParameterName: objParameterName,
cxtParameterName: cxtParameterName,
bodyText: bodyText,
accessorText: accessorTextInfo.accessorText,
quotedTextInfos: accessorTextInfo.quotedTextInfos,
}
}
let returnIndex = bodyText.indexOf("return ");
function getAccessorTextInfo(bodyText: string, option: IIassignOption) {
if (!option.disableAllCheck && !option.disableHasReturnCheck) {
if (returnIndex <= -1) {
throw new Error("getProp() function has no 'return' keyword.");
}
}
let returnIndex = bodyText.indexOf("return ");
if (!option.disableAllCheck && !option.disableHasReturnCheck) {
if (returnIndex <= -1) {
throw new Error("getProp() function has no 'return' keyword.");
if (!option.disableAllCheck && !option.disableExtraStatementCheck) {
let otherBodyText = bodyText.substr(0, returnIndex).trim();
if (otherBodyText != "") {
throw new Error("getProp() function has statements other than 'return': " + otherBodyText);
}
}
}
if (!option.disableAllCheck && !option.disableExtraStatementCheck) {
let otherBodyText = bodyText.substr(0, returnIndex).trim();
if (otherBodyText != "") {
throw new Error("getProp() function has statements other than 'return': " + otherBodyText);
let accessorText = bodyText.substr(returnIndex + 7).trim();
if (accessorText[accessorText.length - 1] == ";") {
accessorText = accessorText.substring(0, accessorText.length - 1);
}
}
accessorText = accessorText.trim();
let accessorText = bodyText.substr(returnIndex + 7).trim();
if (accessorText[accessorText.length - 1] == ";") {
accessorText = accessorText.substring(0, accessorText.length - 1);
return parseTextInQuotes(accessorText, option);
}
accessorText = accessorText.trim();
return parseTextInQuotes(accessorText, option);
}
function parseTextInQuotes(accessorText, option: IIassignOption) {
let quotedTextInfos: { [key: string]: string } = {}
function parseTextInQuotes(accessorText, option: IIassignOption) {
let quotedTextInfos: { [key: string]: string } = {}
let index = 0;
while (true) {
let singleQuoteIndex = accessorText.indexOf("'");
let doubleQuoteIndex = accessorText.indexOf('"');
let varName = "#" + index++;
let index = 0;
while (true) {
let singleQuoteIndex = accessorText.indexOf("'");
let doubleQuoteIndex = accessorText.indexOf('"');
let varName = "#" + index++;
if (singleQuoteIndex <= -1 && doubleQuoteIndex <= -1)
break;
if (singleQuoteIndex <= -1 && doubleQuoteIndex <= -1)
break;
let matches: RegExpExecArray = undefined;
let quoteIndex: number;
let matches: RegExpExecArray = undefined;
let quoteIndex: number;
if (doubleQuoteIndex > -1 && (doubleQuoteIndex < singleQuoteIndex || singleQuoteIndex <= -1)) {
matches = /("[^"\\]*(?:\\.[^"\\]*)*")/.exec(accessorText);
quoteIndex = doubleQuoteIndex;
}
else if (singleQuoteIndex > -1 && (singleQuoteIndex < doubleQuoteIndex || doubleQuoteIndex <= -1)) {
matches = /('[^'\\]*(?:\\.[^'\\]*)*')/.exec(accessorText);
quoteIndex = singleQuoteIndex;
}
if (doubleQuoteIndex > -1 && (doubleQuoteIndex < singleQuoteIndex || singleQuoteIndex <= -1)) {
matches = /("[^"\\]*(?:\\.[^"\\]*)*")/.exec(accessorText);
quoteIndex = doubleQuoteIndex;
if (matches) {
quotedTextInfos[varName] = matches[1];
accessorText =
accessorText.substr(0, quoteIndex) +
varName +
accessorText.substr(matches.index + matches[1].length);
}
else {
throw new Error("Invalid text in quotes: " + accessorText);
}
}
else if (singleQuoteIndex > -1 && (singleQuoteIndex < doubleQuoteIndex || doubleQuoteIndex <= -1)) {
matches = /('[^'\\]*(?:\\.[^'\\]*)*')/.exec(accessorText);
quoteIndex = singleQuoteIndex;
}
if (matches) {
quotedTextInfos[varName] = matches[1];
accessorText =
accessorText.substr(0, quoteIndex) +
varName +
accessorText.substr(matches.index + matches[1].length);
}
else {
throw new Error("Invalid text in quotes: " + accessorText);
}
return {
accessorText,
quotedTextInfos,
};
}
return {
accessorText,
quotedTextInfos,
};
}
function quickCopy<T>(value: T): T {
function quickCopy<T>(value: T): T {
if (value != undefined && !(value instanceof Date)) {
if (value instanceof Array) {
return (<any>value).slice();
}
else if (typeof (value) === "object") {
return extend({}, value);
}
}
if (value != undefined && !(value instanceof Date)) {
if (value instanceof Array) {
return (<any>value).slice();
}
else if (typeof (value) === "object") {
return extend({}, value);
}
return value;
}
return value;
}
function extend(destination: any, ...sources) {
for (var source of sources) {
for (var key in source) {
let value = source[key];
if (value !== undefined) {
destination[key] = value;
function extend(destination: any, ...sources) {
for (var source of sources) {
for (var key in source) {
if (!Object.prototype.hasOwnProperty.call(source, key)) {
continue;
}
let value = source[key];
if (value !== undefined) {
destination[key] = value;
}
}
}
return destination;
}
return destination;
}
function evalStatement() {
return eval(arguments[0]);
}
function evalStatement() {
return eval(arguments[0]);
}
// function isTextInQuote(text: string): boolean {
// let quoteMarks = ["'", '"'];
// function isTextInQuote(text: string): boolean {
// let quoteMarks = ["'", '"'];
// for (let mark of quoteMarks) {
// if (text[0] == mark && text[text.length-1] == mark) {
// return true;
// }
// }
// for (let mark of quoteMarks) {
// if (text[0] == mark && text[text.length-1] == mark) {
// return true;
// }
// }
// return false;
// }
// return false;
// }
// function extractTextInQuote(text: string): string {
// let quoteMarks = ["'", '"'];
// function extractTextInQuote(text: string): string {
// let quoteMarks = ["'", '"'];
// for (let mark of quoteMarks) {
// if (text[0] == mark) {
// let regex = new RegExp(`^[${mark}]([^${mark}]*)[${mark}]$`);
// let match = regex.exec(text);
// if (match) {
// return match[1];
// }
// }
// }
// for (let mark of quoteMarks) {
// if (text[0] == mark) {
// let regex = new RegExp(`^[${mark}]([^${mark}]*)[${mark}]$`);
// let match = regex.exec(text);
// if (match) {
// return match[1];
// }
// }
// }
// return undefined;
// }
// return undefined;
// }
export = iassign;
return iassign;
});
//declare var iassign: IIassign;
//export = iassign;
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc