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.20 to 1.0.21

34

deploy/iassign.d.ts

@@ -5,20 +5,38 @@

interface IIassignOption {
freeze: boolean; // Deep freeze both input and output
freezeInput: boolean; // Deep freeze input
freezeOutput: boolean; // Deep freeze output
disableAllCheck: boolean;
disableHasReturnCheck: boolean;
freeze?: boolean; // Deep freeze both input and output
freezeInput?: boolean; // Deep freeze input
freezeOutput?: boolean; // Deep freeze output
disableAllCheck?: boolean;
disableHasReturnCheck?: boolean;
// Disable validation for extra statements in the getProp() function,
// which is needed when running the coverage, e.g., istanbul.js does add
// instrument statements in our getProp() function, which can be safely ignored.
disableExtraStatementCheck: boolean;
disableExtraStatementCheck?: boolean;
}
type getPropFunc<TObj, TProp, TContext> = (obj: TObj, context: TContext) => TProp;
type setPropFunc<TProp> = (prop: TProp) => TProp;
interface IIassign extends IIassignOption {
// Intellisense for the TObj parameter in getProp will only work if we remove the auto added closing bracket of iassign,
// and manually add the closing bracket at last. i.e.,
//
// 1. Type iassign( in the editor
// 2. Most editor will auto complete with closing bracket, e.g., iassign()
// 3. If we continue to type without removing the closing bracket, e.g., iassign(nested, (n) => n.),
// editor such as VS Code will not show any intellisense for "n"
// 4. We must remove the closing bracket of iassign(), and intellisense will be shown for "n"
<TObj, TProp, TContext>(
obj: TObj,
getProp: (obj: TObj, context: TContext) => TProp,
setProp: (prop: TProp) => TProp,
getProp: getPropFunc<TObj, TProp, TContext>,
setProp: setPropFunc<TProp>,
context?: TContext,
option?: IIassignOption): TObj;
<TObj>(
obj: TObj,
setProp: setPropFunc<TObj>,
option?: IIassignOption): TObj;
}

@@ -25,0 +43,0 @@ }

@@ -32,6 +32,16 @@ "use strict";

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) {
getPropOrSetProp, // Function to get property to be updated. Must be pure function.
setPropOrOption, // Function to set property.
contextOrUndefined, // (Optional) Context to be used in getProp().
optionOrUndefined) {
var getProp = getPropOrSetProp;
var setProp = setPropOrOption;
var context = contextOrUndefined;
var option = optionOrUndefined;
if (typeof setPropOrOption !== "function") {
getProp = undefined;
setProp = getPropOrSetProp;
context = undefined;
option = setPropOrOption;
}
if (option) {

@@ -46,89 +56,95 @@ option = extend({}, iassign, option);

}
// 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;
if (!getProp) {
obj = quickCopy(obj);
obj = setProp(obj);
}
else {
// 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++;
}

@@ -135,0 +151,0 @@ if (deepFreeze && (option.freeze || option.freezeOutput)) {

@@ -13,2 +13,25 @@ // Karma configuration

// // }
// // sl_ie9: { // Deep freeze is not working
// // base: 'SauceLabs',
// // browserName: 'internet explorer',
// // platform: 'Windows 7',
// // version: '9'
// // },
// sl_ios_iphone: {
// base: 'SauceLabs',
// browserName: 'iphone',
// platform: 'iOS 10',
// },
// sl_android_chrome: { // Deep freeze is not working
// base: 'SauceLabs',
// browserName: 'android',
// platform: 'Android 4',
// version: "4.4"
// },
// sl_android_chrome: { // Deep freeze is not working
// base: 'SauceLabs',
// browserName: 'android',
// platform: 'Android 5',
// version: "5"
// }
// }

@@ -21,4 +44,10 @@

platform: 'Windows 10',
version: 'latest'
version: '11'
},
sl_ie10: {
base: 'SauceLabs',
browserName: 'internet explorer',
platform: 'Windows 8',
version: '10'
},
sl_edge: {

@@ -42,3 +71,3 @@ base: 'SauceLabs',

},
sl_mac_chrome: {

@@ -63,3 +92,3 @@ base: 'SauceLabs',

sl_ios_safari: {
sl_ios_10_iphone: {
base: 'SauceLabs',

@@ -69,2 +98,8 @@ browserName: 'iphone',

},
sl_android_5: {
base: 'SauceLabs',
browserName: 'android',
platform: 'Android 5',
varsion: "5"
},
}

@@ -151,4 +186,5 @@ config.set({

captureTimeout: 300000,
captureTimeout: 120000,
browserNoActivityTimeout: 300000,
retryLimit: 5,

@@ -155,0 +191,0 @@ // Concurrency level

{
"name": "immutable-assign",
"version": "1.0.20",
"version": "1.0.21",
"description": "Lightweight immutable helper that allows you to continue working with Plain JavaScript Objects",

@@ -5,0 +5,0 @@ "main": "src/iassign.js",

@@ -37,3 +37,6 @@ # immutable-assign (iassign.js)

```javascript
// Return a new POJO object with property updated.
// function overload 1:
function iassign<TObj, TProp, TContext>(

@@ -45,8 +48,15 @@ obj: TObj, // POJO object to be getting the property from, it will not be modified.

option?: IIassignOption): TObj; // (Optional) Options
// function overload 2: you can skip getProp() if you trying to update the root object, refer to example 1 and 2
function iassign<TObj>(
obj: TObj, // POJO object to be getting the property from, it will not be modified.
setProp: setPropFunc<TObj>, // Function to set the property.
option?: IIassignOption): TObj; // (Optional) Options
// Options, can be applied globally or individually
interface IIassignOption {
freeze: boolean; // Deep freeze both input and output
freezeInput: boolean; // Deep freeze input
freezeOutput: boolean; // Deep freeze output
freeze?: boolean; // Deep freeze both input and output
freezeInput?: boolean; // Deep freeze input
freezeOutput?: boolean; // Deep freeze output

@@ -56,3 +66,3 @@ // Disable validation for extra statements in the getProp() function,

// instrument statements in our getProp() function, which can be safely ignored.
disableExtraStatementCheck: boolean;
disableExtraStatementCheck?: boolean;
}

@@ -71,6 +81,5 @@ ```

// 1: Calling iassign() to update map1.b
// 1: Calling iassign() to update map1.b, using overload 2
var map2 = iassign(
map1,
function (m) { return m; },
function (m) { m.b = 50; return m; }

@@ -92,6 +101,5 @@ );

// 2.1: Calling iassign() to push items to list1
// 2.1: Calling iassign() to push items to list1, using overload 2
var list2 = iassign(
list1,
function (l) { return l; },
function (l) { l.push(3, 4, 5); return l; }

@@ -104,6 +112,5 @@ );

// 2.2: Calling iassign() to unshift item to list2
// 2.2: Calling iassign() to unshift item to list2, using overload 2
var list3 = iassign(
list2,
function (l) { return l; },
function (l) { l.unshift(0); return l; }

@@ -116,6 +123,5 @@ );

// 2.3, Calling iassign() to concat list1, list2 and list3
// 2.3, Calling iassign() to concat list1, list2 and list3, using overload 2
var list4 = iassign(
list1,
function (l) { return l; },
function (l) { return l.concat(list2, list3); }

@@ -128,6 +134,5 @@ );

// 2.4, Calling iassign() to concat sort list4
// 2.4, Calling iassign() to concat sort list4, using overload 2
var list5 = iassign(
list4,
function (l) { return l; },
function (l) { return l.sort(); }

@@ -349,3 +354,2 @@ );

##Constraints

@@ -358,2 +362,3 @@

* 1.0.21 - Added new function overload to skip getProp() if you trying to update the root object, refer to [example 1](#example-1-update-object) and [example 2](#example-2-update-listarray)
* 1.0.20 - Added Travis-CI, Coveralls (coverage) and SauceLabs (browsers' tests)

@@ -360,0 +365,0 @@ * 1.0.19 - Added TypeScript types to package.json

@@ -408,3 +408,140 @@ "use strict";

});
it("Example 1: update object", function () {
//var iassign = require("immutable-assign");
// Deep freeze both input and output, can be used in development to make sure they don't change.
iassign.freeze = true;
var map1 = { a: 1, b: 2, c: 3 };
// 1: Calling iassign() to update map1.b
var map2 = iassign(map1, function (m) { m.b = 50; return m; });
expect(map1).toEqual({ a: 1, b: 2, c: 3 });
expect(map2).toEqual({ a: 1, b: 50, c: 3 });
expect(map2).not.toBe(map1);
});
it("Example 1b: update object with option", function () {
//var iassign = require("immutable-assign");
// Deep freeze both input and output, can be used in development to make sure they don't change.
iassign.freeze = true;
var map1 = { a: 1, b: 2, c: 3 };
// 1: Calling iassign() to update map1.b
var map2 = iassign(map1, function (m) { m.b = 50; return m; });
expect(map1).toEqual({ a: 1, b: 2, c: 3 });
expect(map2).toEqual({ a: 1, b: 50, c: 3 });
expect(map2).not.toBe(map1);
expect(function () { map2.a = 3; }).toThrow();
var map3 = iassign(map2, function (m) { m.c = 60; return m; }, { freeze: false });
expect(map2).toEqual({ a: 1, b: 50, c: 3 });
expect(map3).toEqual({ a: 1, b: 50, c: 60 });
expect(map3).not.toBe(map2);
expect(function () { map3.a = 3; }).not.toThrow();
});
it("Example 1c: update object that pass undefined to getProp()", function () {
//var iassign = require("immutable-assign");
// Deep freeze both input and output, can be used in development to make sure they don't change.
iassign.freeze = true;
var map1 = { a: 1, b: 2, c: 3 };
// 1c: Calling iassign() to update map1.b
var map2 = iassign(map1, undefined, function (m) { m.b = 50; return m; });
expect(map1).toEqual({ a: 1, b: 2, c: 3 });
expect(map2).toEqual({ a: 1, b: 50, c: 3 });
expect(map2).not.toBe(map1);
});
it("Example 1d: update object with option that pass undefined to getProp()", function () {
//var iassign = require("immutable-assign");
// Deep freeze both input and output, can be used in development to make sure they don't change.
iassign.freeze = true;
var map1 = { a: 1, b: 2, c: 3 };
// 1: Calling iassign() to update map1.b
var map2 = iassign(map1, undefined, function (m) { m.b = 50; return m; });
expect(map1).toEqual({ a: 1, b: 2, c: 3 });
expect(map2).toEqual({ a: 1, b: 50, c: 3 });
expect(map2).not.toBe(map1);
expect(function () { map2.a = 3; }).toThrow();
var map3 = iassign(map2, undefined, function (m) { m.c = 60; return m; }, undefined, { freeze: false });
expect(map2).toEqual({ a: 1, b: 50, c: 3 });
expect(map3).toEqual({ a: 1, b: 50, c: 60 });
expect(map3).not.toBe(map2);
expect(function () { map3.a = 3; }).not.toThrow();
});
it("Example 2: update list/array", function () {
//var iassign = require("immutable-assign");
// Deep freeze both input and output, can be used in development to make sure they don't change.
iassign.freeze = true;
var list1 = [1, 2];
// 2.1: Calling iassign() to push items to list1
var list2 = iassign(list1, function (l) { l.push(3, 4, 5); return l; });
expect(list1).toEqual([1, 2]);
expect(list2).toEqual([1, 2, 3, 4, 5]);
expect(list2).not.toBe(list1);
// 2.2: Calling iassign() to unshift item to list2
var list3 = iassign(list2, function (l) { l.unshift(0); return l; });
expect(list2).toEqual([1, 2, 3, 4, 5]);
expect(list3).toEqual([0, 1, 2, 3, 4, 5]);
expect(list3).not.toBe(list2);
// 2.3, Calling iassign() to concat list1, list2 and list3
var list4 = iassign(list1, function (l) { return l.concat(list2, list3); });
expect(list1).toEqual([1, 2]);
expect(list2).toEqual([1, 2, 3, 4, 5]);
expect(list3).toEqual([0, 1, 2, 3, 4, 5]);
expect(list4).toEqual([1, 2, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5]);
expect(list4).not.toBe(list1);
expect(list4).not.toBe(list2);
expect(list4).not.toBe(list3);
// 2.4, Calling iassign() to concat sort list4
var list5 = iassign(list4, function (l) { return l.sort(); });
expect(list4).toEqual([1, 2, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5]);
expect(list5).toEqual([0, 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5]);
expect(list5).not.toBe(list4);
});
it("Example 2b: update list/array that pass undefined to getProp()", function () {
//var iassign = require("immutable-assign");
// Deep freeze both input and output, can be used in development to make sure they don't change.
iassign.freeze = true;
var list1 = [1, 2];
// 2.1: Calling iassign() to push items to list1
var list2 = iassign(list1, undefined, function (l) { l.push(3, 4, 5); return l; });
expect(list1).toEqual([1, 2]);
expect(list2).toEqual([1, 2, 3, 4, 5]);
expect(list2).not.toBe(list1);
// 2.2: Calling iassign() to unshift item to list2
var list3 = iassign(list2, undefined, function (l) { l.unshift(0); return l; });
expect(list2).toEqual([1, 2, 3, 4, 5]);
expect(list3).toEqual([0, 1, 2, 3, 4, 5]);
expect(list3).not.toBe(list2);
// 2.3, Calling iassign() to concat list1, list2 and list3
var list4 = iassign(list1, undefined, function (l) { return l.concat(list2, list3); });
expect(list1).toEqual([1, 2]);
expect(list2).toEqual([1, 2, 3, 4, 5]);
expect(list3).toEqual([0, 1, 2, 3, 4, 5]);
expect(list4).toEqual([1, 2, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5]);
expect(list4).not.toBe(list1);
expect(list4).not.toBe(list2);
expect(list4).not.toBe(list3);
// 2.4, Calling iassign() to concat sort list4
var list5 = iassign(list4, undefined, function (l) { return l.sort(); });
expect(list4).toEqual([1, 2, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5]);
expect(list5).toEqual([0, 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5]);
expect(list5).not.toBe(list4);
});
it("Example 3: update nested structures", function () {
//var iassign = require("immutable-assign");
// Deep freeze both input and output, can be used in development to make sure they don't change.
iassign.freeze = true;
var nested1 = { a: { b: { c: [3, 4, 5] } } };
// 3.1: Calling iassign() to assign d to nested1.a.b
var nested2 = iassign(nested1, function (n) { return n.a.b; }, function (b) { b.d = 6; return b; });
expect(nested1).toEqual({ a: { b: { c: [3, 4, 5] } } });
expect(nested2).toEqual({ a: { b: { c: [3, 4, 5], d: 6 } } });
expect(nested2).not.toBe(nested1);
// 3.2: Calling iassign() to increment nested2.a.b.d
var nested3 = iassign(nested2, function (n) { return n.a.b.d; }, function (d) { return d + 1; });
expect(nested2).toEqual({ a: { b: { c: [3, 4, 5], d: 6 } } });
expect(nested3).toEqual({ a: { b: { c: [3, 4, 5], d: 7 } } });
expect(nested3).not.toBe(nested2);
// 3.3: Calling iassign() to push item to nested3.a.b.c
var nested4 = iassign(nested3, function (n) { return n.a.b.c; }, function (c) { c.push(6); return c; });
expect(nested3).toEqual({ a: { b: { c: [3, 4, 5], d: 7 } } });
expect(nested4).toEqual({ a: { b: { c: [3, 4, 5, 6], d: 7 } } });
expect(nested4).not.toBe(nested3);
});
});
});

@@ -5,542 +5,815 @@

(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 browserRequire = (name) => {
if (name == "deep-freeze" && root.deepFreeze) {
return root.deepFreeze;
}
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 browserRequire = (name) => {
if (name == "deep-freeze" && root.deepFreeze) {
return root.deepFreeze;
}
if (name == "lodash" && root._) {
return root._;
}
if (name == "lodash" && root._) {
return root._;
}
if (name.indexOf("iassign") > -1 && root.iassign) {
return root.iassign;
}
if (name.indexOf("iassign") > -1 && root.iassign) {
return root.iassign;
}
throw new Error("Unable to require: " + name);
throw new Error("Unable to require: " + name);
}
factory(browserRequire, {});
}
factory(browserRequire, {});
}
})(this, function (require, exports) {
var iassign: IIassign = require("../src/iassign");
var deepFreeze: DeepFreeze.DeepFreezeInterface = require("deep-freeze");
var _: _.LoDashStatic = require("lodash");
var iassign: IIassign = require("../src/iassign");
var deepFreeze: DeepFreeze.DeepFreezeInterface = require("deep-freeze");
var _: _.LoDashStatic = require("lodash");
describe("Test", function () {
describe("Test", function () {
beforeEach(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);
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,
(o) => o.a.b.c[0][0],
(ci) => { ci.d++; return ci; }
);
var o2 = iassign(
o1,
(o) => o.a.b.c[0][0],
(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 }], [{ d: 31, e: 32 }]], c2: {} }, b2: {} }, a2: {} })
// 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 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(o2.a.b.c[2][0]).toBe(o1.a.b.c[2][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]);
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);
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,
(o) => o.a.b.c[1],
(c) => { c.push(<any>101); return c; }
);
var o2 = iassign(
o1,
(o) => o.a.b.c[1],
(c) => { c.push(<any>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 }], [{ d: 31, e: 32 }]], c2: {} }, b2: {} }, a2: {} })
// 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 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(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 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);
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; });
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);
});
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);
it("Access object", function () {
var o1 = { a: { b: { c: { d: 11, e: 12 } } } };
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, (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);
});
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);
it("Access primitive", 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[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]).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("Access date", function () {
var o1 = { a: { b: { c: { d: 11, e: 12, f: new Date() } } } };
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.f, (f) => { return new Date(2016, 1, 1) });
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.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.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);
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["1"]["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[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).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);
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["propB"].c["1"][0].d, (d) => { return d + 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.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);
});
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 () {
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);
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["p\\r\"o.p t[] e.s\'t'B"]["h\\e'llo w\'or\"ld"]["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.a[propBName][propCName][1][0].d).toBe(22);
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);
});
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);
});
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);
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);
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; });
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.a[propBName][propCName][propDName][propEName][1][0].d).toBe(22);
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);
});
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);
});
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);
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);
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; });
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; });
expect(o2.a[propBName][propCName][propDName][propEName][1][0].d).toBe(22);
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);
});
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);
});
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);
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 });
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(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("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);
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(() => {
iassign(o1, function (o) { return o.a.b.c; }, function (ci) { ci[0].push(<any>3); return ci; });
}).toThrowError(TypeError, /Cannot|Can't|writable|doesn't|support|readonly/i);
expect(() => {
iassign(o1, function (o) { return o.a.b.c; }, function (ci) { ci[0].push(<any>3); return ci; });
}).toThrowError(TypeError, /Cannot|Can't|writable|doesn't|support|readonly/i);
expect(() => {
iassign(o1, function (o) { return o.a.b.c[0]; }, function (ci) { ci[0].d++; return ci; });
}).toThrowError(TypeError, /Invalid|Cannot|read only|read-only|extensible|readonly/i);
expect(() => {
iassign(o1, function (o) { return o.a.b.c[0]; }, function (ci) { ci[0].d++; return ci; });
}).toThrowError(TypeError, /Invalid|Cannot|read only|read-only|extensible|readonly/i);
expect(() => {
iassign(o1, function (o) { return o.a.b.c[0]; }, function (ci) { (<any>ci[0]).g = 1; return ci; });
}).toThrowError(TypeError, /Invalid|add|extensible|readonly/i);
expect(() => {
iassign(o1, function (o) { return o.a.b.c[0]; }, function (ci) { (<any>ci[0]).g = 1; return ci; });
}).toThrowError(TypeError, /Invalid|add|extensible|readonly/i);
expect(() => {
iassign(o1, function (o) { return o.a.b.c; }, function (ci) { ci[0].pop(); return ci; });
}).toThrowError(TypeError, /extensible|Cannot|can't|support|unable/i);
});
expect(() => {
iassign(o1, function (o) { return o.a.b.c; }, function (ci) { ci[0].pop(); return ci; });
}).toThrowError(TypeError, /extensible|Cannot|can't|support|unable/i);
});
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("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
deepFreeze(o1); // Ensure o1 is not changed, for testing only
//
// 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); });
//
// 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 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({ a: { b: { c: [[{ d: 11, e: 12 }, { d: 13, e: 14 }], [{ d: 21, e: 22 }]] } }, a2: {} })
it("Update array using lodash 2", function () {
var o1 = { a: { b: { c: [1, 2, 3] } } };
expect(o2).toEqual({ a: { b: { c: [[{ d: 12, e: 12 }, { d: 14, e: 14 }], [{ d: 21, e: 22 }]] } }, a2: {} });
deepFreeze(o1); // Ensure o1 is not changed, for testing only
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]);
//
// 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.a.b.c[1][0]).toBe(o1.a.b.c[1][0]);
});
// expect o1 has not been changed
expect(o1).toEqual({ a: { b: { c: [1, 2, 3] } } })
it("Update array using lodash 2", function () {
var o1 = { a: { b: { c: [1, 2, 3] } } };
// expect o2.a.b.c has been updated.
expect(o2.a.b.c).toEqual([2, 3, 4]);
deepFreeze(o1); // Ensure o1 is not changed, for testing only
// 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);
});
//
// 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); }
);
it("Test root object is an array", function () {
var o1 = [[{ d: 11, e: 12 }, { d: 13, e: 14 }, { d: 21, e: 22 }]];
// expect o1 has not been changed
expect(o1).toEqual({ a: { b: { c: [1, 2, 3] } } })
deepFreeze(o1); // Ensure o1 is not changed, for testing only
// expect o2.a.b.c has been updated.
expect(o2.a.b.c).toEqual([2, 3, 4]);
//
// 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 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 o1 has not been changed
expect(o1).toEqual([[{ d: 11, e: 12 }, { d: 13, e: 14 }, { d: 21, e: 22 }]])
it("Test root object is an array", function () {
var o1 = [[{ 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 }]]);
deepFreeze(o1); // Ensure o1 is not changed, for testing only
// 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]);
//
// 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 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 }]])
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 o2.a.b.c has been updated.
expect(o2).toEqual([[{ d: 12, e: 12 }, { d: 14, e: 14 }, { d: 21, e: 22 }]]);
deepFreeze(o1); // Ensure o1 is not changed, for testing only
// 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]);
//
// 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 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 }])
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 o2.a.b.c has been updated.
expect(o2).toEqual([{ d: 12, e: 12 }, { d: 14, e: 14 }, { d: 21, e: 22 }]);
deepFreeze(o1); // Ensure o1 is not changed, for testing only
// 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]);
//
// 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 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([{ d: 11, e: 12 }, { d: 13, e: 14 }, { d: 21, e: 22 }])
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 o2.a.b.c has been updated.
expect(o2).toEqual([{ d: 12, e: 12 }, { d: 14, e: 14 }, { d: 21, e: 22 }]);
var o2 = iassign(
o1,
(o) => o,
(o) => { o.a = <any>{ b: 1 }; return o; }
);
// 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]);
//
// Jasmine Tests
//
// 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: 21, e: 22 }]], c2: {} }, b2: {} }, a2: {} });
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 o2 inner property has been updated.
expect(o2).toEqual({ a: { b: 1 }, a2: {} });
var o2 = iassign(
o1,
(o) => o,
(o) => { o.a = <any>{ b: 1 }; return o; }
);
// 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);
//
// Jasmine Tests
//
// expect object graph for unchanged property in o2 is still equal to (===) o1.
expect(o2.a2).toBe(o1.a2);
});
// expect o1 has not been changed
expect(o1).toEqual({ a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }]], c2: {} }, b2: {} }, 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 o2 inner property has been updated.
expect(o2).toEqual({ a: { b: 1 }, a2: {} });
expect(() => {
iassign(o1, function (o) { return o.a.b.c; }, function (ci) { ci[0].push(<any>3); return ci; });
}).toThrowError(TypeError, /Cannot|Can't|writable|doesn't|support|readonly/i);
// 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[0]; }, function (ci) { ci[0].d++; return ci; });
}).toThrowError(TypeError, /Invalid|Cannot|read only|read-only|extensible|readonly/i);
// expect object graph for unchanged property in o2 is still equal to (===) o1.
expect(o2.a2).toBe(o1.a2);
});
expect(() => {
iassign(o1, function (o) { return o.a.b.c[0]; }, function (ci) { (<any>ci[0]).g = 1; return ci; });
}).toThrowError(TypeError, /Invalid|add|extensible|readonly/i);
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(() => {
iassign(o1, function (o) { return o.a.b.c; }, function (ci) { ci[0].pop(); return ci; });
}).toThrowError(TypeError, /extensible|Cannot|can't|support|unable/i);
expect(() => {
iassign(o1, function (o) { return o.a.b.c; }, function (ci) { ci[0].push(<any>3); return ci; });
}).toThrowError(TypeError, /Cannot|Can't|writable|doesn't|support|readonly/i);
iassign.freezeInput = undefined;
});
expect(() => {
iassign(o1, function (o) { return o.a.b.c[0]; }, function (ci) { ci[0].d++; return ci; });
}).toThrowError(TypeError, /Invalid|Cannot|read only|read-only|extensible|readonly/i);
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[0]; }, function (ci) { (<any>ci[0]).g = 1; return ci; });
}).toThrowError(TypeError, /Invalid|add|extensible|readonly/i);
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; }, function (ci) { ci[0].pop(); return ci; });
}).toThrowError(TypeError, /extensible|Cannot|can't|support|unable/i);
// expect o1 has not been changed
expect(o1).toEqual({ a: { b: { c: [[{ d: 11, e: 12 }, { d: 13, e: 14 }, { d: 21, e: 22 }]] } } })
iassign.freezeInput = undefined;
});
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);
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).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]);
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(() => {
o2.a.b.c[0].push(<any>3);
}).toThrowError(TypeError, /Cannot|Can't|writable|doesn't|support|readonly/i);
expect(() => {
o2.a.b.c[0][0].d++;
}).toThrowError(TypeError, /Invalid|Cannot|read only|read-only|extensible|readonly/i);
expect(() => {
(<any>o2.a.b.c[0][0]).g = 1;
}).toThrowError(TypeError, /Invalid|add|extensible|readonly/i);
expect(() => {
o2.a.b.c[0].pop();
}).toThrowError(TypeError, /extensible|Cannot|can't|support|unable/i);
iassign.freezeOutput = undefined;
});
// expect o1 has not been changed
expect(o1).toEqual({ a: { b: { c: [[{ d: 11, e: 12 }, { d: 13, e: 14 }, { d: 21, e: 22 }]] } } })
it("Example 1: update object", function () {
//var iassign = require("immutable-assign");
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);
// Deep freeze both input and output, can be used in development to make sure they don't change.
iassign.freeze = true;
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]);
var map1 = { a: 1, b: 2, c: 3 };
expect(() => {
o2.a.b.c[0].push(<any>3);
}).toThrowError(TypeError, /Cannot|Can't|writable|doesn't|support|readonly/i);
expect(() => {
o2.a.b.c[0][0].d++;
}).toThrowError(TypeError, /Invalid|Cannot|read only|read-only|extensible|readonly/i);
// 1: Calling iassign() to update map1.b
var map2 = iassign(
map1,
(m) => { m.b = 50; return m; }
);
expect(() => {
(<any>o2.a.b.c[0][0]).g = 1;
}).toThrowError(TypeError, /Invalid|add|extensible|readonly/i);
expect(map1).toEqual({ a: 1, b: 2, c: 3 });
expect(map2).toEqual({ a: 1, b: 50, c: 3 });
expect(map2).not.toBe(map1);
});
expect(() => {
o2.a.b.c[0].pop();
}).toThrowError(TypeError, /extensible|Cannot|can't|support|unable/i);
it("Example 1b: update object with option", function () {
//var iassign = require("immutable-assign");
iassign.freezeOutput = undefined;
// Deep freeze both input and output, can be used in development to make sure they don't change.
iassign.freeze = true;
var map1 = { a: 1, b: 2, c: 3 };
// 1: Calling iassign() to update map1.b
var map2 = iassign(
map1,
(m) => { m.b = 50; return m; }
);
expect(map1).toEqual({ a: 1, b: 2, c: 3 });
expect(map2).toEqual({ a: 1, b: 50, c: 3 });
expect(map2).not.toBe(map1);
expect(() => { map2.a = 3; }).toThrow();
var map3 = iassign(
map2,
(m) => { m.c = 60; return m; },
{ freeze: false }
);
expect(map2).toEqual({ a: 1, b: 50, c: 3 });
expect(map3).toEqual({ a: 1, b: 50, c: 60 });
expect(map3).not.toBe(map2);
expect(() => { map3.a = 3; }).not.toThrow();
});
it("Example 1c: update object that pass undefined to getProp()", function () {
//var iassign = require("immutable-assign");
// Deep freeze both input and output, can be used in development to make sure they don't change.
iassign.freeze = true;
var map1 = { a: 1, b: 2, c: 3 };
// 1c: Calling iassign() to update map1.b
var map2 = iassign<any, { b: number }, any>(
map1,
undefined,
(m) => { m.b = 50; return m; }
);
expect(map1).toEqual({ a: 1, b: 2, c: 3 });
expect(map2).toEqual({ a: 1, b: 50, c: 3 });
expect(map2).not.toBe(map1);
});
it("Example 1d: update object with option that pass undefined to getProp()", function () {
//var iassign = require("immutable-assign");
// Deep freeze both input and output, can be used in development to make sure they don't change.
iassign.freeze = true;
var map1 = { a: 1, b: 2, c: 3 };
// 1: Calling iassign() to update map1.b
var map2 = iassign<any, {b: number}, any>(
map1,
undefined,
(m) => { m.b = 50; return m; }
);
expect(map1).toEqual({ a: 1, b: 2, c: 3 });
expect(map2).toEqual({ a: 1, b: 50, c: 3 });
expect(map2).not.toBe(map1);
expect(() => { map2.a = 3; }).toThrow();
var map3 = iassign<any, {c: number}, any>(
map2,
undefined,
(m) => { m.c = 60; return m; },
undefined,
{ freeze: false }
);
expect(map2).toEqual({ a: 1, b: 50, c: 3 });
expect(map3).toEqual({ a: 1, b: 50, c: 60 });
expect(map3).not.toBe(map2);
expect(() => { map3.a = 3; }).not.toThrow();
});
it("Example 2: update list/array", function () {
//var iassign = require("immutable-assign");
// Deep freeze both input and output, can be used in development to make sure they don't change.
iassign.freeze = true;
var list1 = [1, 2];
// 2.1: Calling iassign() to push items to list1
var list2 = iassign(
list1,
function (l) { l.push(3, 4, 5); return l; }
);
expect(list1).toEqual([1, 2]);
expect(list2).toEqual([1, 2, 3, 4, 5]);
expect(list2).not.toBe(list1);
// 2.2: Calling iassign() to unshift item to list2
var list3 = iassign(
list2,
function (l) { l.unshift(0); return l; }
);
expect(list2).toEqual([1, 2, 3, 4, 5]);
expect(list3).toEqual([0, 1, 2, 3, 4, 5]);
expect(list3).not.toBe(list2);
// 2.3, Calling iassign() to concat list1, list2 and list3
var list4 = iassign(
list1,
function (l) { return l.concat(list2, list3); }
);
expect(list1).toEqual([1, 2]);
expect(list2).toEqual([1, 2, 3, 4, 5]);
expect(list3).toEqual([0, 1, 2, 3, 4, 5]);
expect(list4).toEqual([1, 2, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5]);
expect(list4).not.toBe(list1);
expect(list4).not.toBe(list2);
expect(list4).not.toBe(list3);
// 2.4, Calling iassign() to concat sort list4
var list5 = iassign(
list4,
function (l) { return l.sort(); }
);
expect(list4).toEqual([1, 2, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5]);
expect(list5).toEqual([0, 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5]);
expect(list5).not.toBe(list4);
});
it("Example 2b: update list/array that pass undefined to getProp()", function () {
//var iassign = require("immutable-assign");
// Deep freeze both input and output, can be used in development to make sure they don't change.
iassign.freeze = true;
var list1 = [1, 2];
// 2.1: Calling iassign() to push items to list1
var list2 = iassign<any, number[], any>(
list1,
undefined,
function (l) { l.push(3, 4, 5); return l; }
);
expect(list1).toEqual([1, 2]);
expect(list2).toEqual([1, 2, 3, 4, 5]);
expect(list2).not.toBe(list1);
// 2.2: Calling iassign() to unshift item to list2
var list3 = iassign<any, number[], any>(
list2,
undefined,
function (l) { l.unshift(0); return l; }
);
expect(list2).toEqual([1, 2, 3, 4, 5]);
expect(list3).toEqual([0, 1, 2, 3, 4, 5]);
expect(list3).not.toBe(list2);
// 2.3, Calling iassign() to concat list1, list2 and list3
var list4 = iassign<any, number[], any>(
list1,
undefined,
function (l) { return l.concat(list2, list3); }
);
expect(list1).toEqual([1, 2]);
expect(list2).toEqual([1, 2, 3, 4, 5]);
expect(list3).toEqual([0, 1, 2, 3, 4, 5]);
expect(list4).toEqual([1, 2, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5]);
expect(list4).not.toBe(list1);
expect(list4).not.toBe(list2);
expect(list4).not.toBe(list3);
// 2.4, Calling iassign() to concat sort list4
var list5 = iassign<any, number[], any>(
list4,
undefined,
function (l) { return l.sort(); }
);
expect(list4).toEqual([1, 2, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5]);
expect(list5).toEqual([0, 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5]);
expect(list5).not.toBe(list4);
});
it("Example 3: update nested structures", function () {
//var iassign = require("immutable-assign");
// Deep freeze both input and output, can be used in development to make sure they don't change.
iassign.freeze = true;
var nested1 = { a: { b: { c: [3, 4, 5] } } };
// 3.1: Calling iassign() to assign d to nested1.a.b
var nested2 = iassign(
nested1,
function (n) { return n.a.b; },
function (b: any) { b.d = 6; return b; }
);
expect(nested1).toEqual({ a: { b: { c: [3, 4, 5] } } });
expect(nested2).toEqual({ a: { b: { c: [3, 4, 5], d: 6 } } });
expect(nested2).not.toBe(nested1);
// 3.2: Calling iassign() to increment nested2.a.b.d
var nested3 = iassign(
nested2,
function (n) { return (<any>n.a.b).d; },
function (d) { return d + 1; }
);
expect(nested2).toEqual({ a: { b: { c: [3, 4, 5], d: 6 } } });
expect(nested3).toEqual({ a: { b: { c: [3, 4, 5], d: 7 } } });
expect(nested3).not.toBe(nested2);
// 3.3: Calling iassign() to push item to nested3.a.b.c
var nested4 = iassign(
nested3,
function (n) { return n.a.b.c; },
function (c) { c.push(6); return c; }
);
expect(nested3).toEqual({ a: { b: { c: [3, 4, 5], d: 7 } } });
expect(nested4).toEqual({ a: { b: { c: [3, 4, 5, 6], d: 7 } } });
expect(nested4).not.toBe(nested3);
});
});
});
});

@@ -5,20 +5,38 @@

interface IIassignOption {
freeze: boolean; // Deep freeze both input and output
freezeInput: boolean; // Deep freeze input
freezeOutput: boolean; // Deep freeze output
disableAllCheck: boolean;
disableHasReturnCheck: boolean;
freeze?: boolean; // Deep freeze both input and output
freezeInput?: boolean; // Deep freeze input
freezeOutput?: boolean; // Deep freeze output
disableAllCheck?: boolean;
disableHasReturnCheck?: boolean;
// Disable validation for extra statements in the getProp() function,
// which is needed when running the coverage, e.g., istanbul.js does add
// instrument statements in our getProp() function, which can be safely ignored.
disableExtraStatementCheck: boolean;
disableExtraStatementCheck?: boolean;
}
type getPropFunc<TObj, TProp, TContext> = (obj: TObj, context: TContext) => TProp;
type setPropFunc<TProp> = (prop: TProp) => TProp;
interface IIassign extends IIassignOption {
// Intellisense for the TObj parameter in getProp will only work if we remove the auto added closing bracket of iassign,
// and manually add the closing bracket at last. i.e.,
//
// 1. Type iassign( in the editor
// 2. Most editor will auto complete with closing bracket, e.g., iassign()
// 3. If we continue to type without removing the closing bracket, e.g., iassign(nested, (n) => n.),
// editor such as VS Code will not show any intellisense for "n"
// 4. We must remove the closing bracket of iassign(), and intellisense will be shown for "n"
<TObj, TProp, TContext>(
obj: TObj,
getProp: (obj: TObj, context: TContext) => TProp,
setProp: (prop: TProp) => TProp,
getProp: getPropFunc<TObj, TProp, TContext>,
setProp: setPropFunc<TProp>,
context?: TContext,
option?: IIassignOption): TObj;
<TObj>(
obj: TObj,
setProp: setPropFunc<TObj>,
option?: IIassignOption): TObj;
}

@@ -25,0 +43,0 @@ }

@@ -32,6 +32,16 @@ "use strict";

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) {
getPropOrSetProp, // Function to get property to be updated. Must be pure function.
setPropOrOption, // Function to set property.
contextOrUndefined, // (Optional) Context to be used in getProp().
optionOrUndefined) {
var getProp = getPropOrSetProp;
var setProp = setPropOrOption;
var context = contextOrUndefined;
var option = optionOrUndefined;
if (typeof setPropOrOption !== "function") {
getProp = undefined;
setProp = getPropOrSetProp;
context = undefined;
option = setPropOrOption;
}
if (option) {

@@ -46,89 +56,95 @@ option = extend({}, iassign, option);

}
// 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;
if (!getProp) {
obj = quickCopy(obj);
obj = setProp(obj);
}
else {
// 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++;
}

@@ -135,0 +151,0 @@ if (deepFreeze && (option.freeze || option.freezeOutput)) {

@@ -8,20 +8,38 @@ "use strict";

interface IIassignOption {
freeze: boolean; // Deep freeze both input and output
freezeInput: boolean; // Deep freeze input
freezeOutput: boolean; // Deep freeze output
disableAllCheck: boolean;
disableHasReturnCheck: boolean;
freeze?: boolean; // Deep freeze both input and output
freezeInput?: boolean; // Deep freeze input
freezeOutput?: boolean; // Deep freeze output
disableAllCheck?: boolean;
disableHasReturnCheck?: boolean;
// Disable validation for extra statements in the getProp() function,
// which is needed when running the coverage, e.g., istanbul.js does add
// instrument statements in our getProp() function, which can be safely ignored.
disableExtraStatementCheck: boolean;
disableExtraStatementCheck?: boolean;
}
type getPropFunc<TObj, TProp, TContext> = (obj: TObj, context: TContext) => TProp;
type setPropFunc<TProp> = (prop: TProp) => TProp;
interface IIassign extends IIassignOption {
// Intellisense for the TObj parameter in getProp will only work if we remove the auto added closing bracket of iassign,
// and manually add the closing bracket at last. i.e.,
//
// 1. Type iassign( in the editor
// 2. Most editor will auto complete with closing bracket, e.g., iassign()
// 3. If we continue to type without removing the closing bracket, e.g., iassign(nested, (n) => n.),
// editor such as VS Code will not show any intellisense for "n"
// 4. We must remove the closing bracket of iassign(), and intellisense will be shown for "n"
<TObj, TProp, TContext>(
obj: TObj,
getProp: (obj: TObj, context: TContext) => TProp,
setProp: (prop: TProp) => TProp,
getProp: getPropFunc<TObj, TProp, TContext>,
setProp: setPropFunc<TProp>,
context?: TContext,
option?: IIassignOption): TObj;
<TObj>(
obj: TObj,
setProp: setPropFunc<TObj>,
option?: IIassignOption): TObj;
}

@@ -60,8 +78,20 @@

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 {
obj: TObj, // Object to set property, it will not be modified.
getPropOrSetProp: getPropFunc<TObj, TProp, TContext> | setPropFunc<TProp>, // Function to get property to be updated. Must be pure function.
setPropOrOption: setPropFunc<TProp> | IIassignOption, // Function to set property.
contextOrUndefined?: TContext, // (Optional) Context to be used in getProp().
optionOrUndefined?: IIassignOption): TObj {
let getProp = <getPropFunc<TObj, TProp, TContext>>getPropOrSetProp;
let setProp = <setPropFunc<TProp>>setPropOrOption;
let context = contextOrUndefined;
let option = optionOrUndefined;
if (typeof setPropOrOption !== "function") {
getProp = undefined;
setProp = <setPropFunc<TProp>>getPropOrSetProp;
context = undefined;
option = <IIassignOption>setPropOrOption;
}
if (option) {

@@ -78,109 +108,115 @@ option = extend({}, iassign, option);

// Check if getProp() is valid
let value = getProp(obj, context);
if (!getProp) {
obj = quickCopy(obj);
obj = <any>setProp(<any>obj);
}
else {
// Check if getProp() is valid
let value = getProp(obj, context);
let getPropFuncInfo = parseGetPropFuncInfo(getProp, option);
let accessorText = getPropFuncInfo.accessorText;
let getPropFuncInfo = parseGetPropFuncInfo(getProp, option);
let accessorText = getPropFuncInfo.accessorText;
let propIndex = 0;
let propValue = undefined;
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;
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 (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 open bracket but not close bracket.");
}
if (openBracketIndex <= -1 && closeBracketIndex > -1) {
throw new Error("Found close bracket but not open 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 (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;
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);
propIndex++;
}

@@ -187,0 +223,0 @@

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