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

immer

Package Overview
Dependencies
Maintainers
2
Versions
173
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

immer - npm Package Compare versions

Comparing version 4.0.2 to 5.0.0

22

dist/immer.d.ts

@@ -11,5 +11,3 @@ type Tail<T extends any[]> = ((...t: T) => any) extends ((

| Function
| Map<any, any>
| WeakMap<any, any>
| Set<any>
| WeakSet<any>

@@ -25,2 +23,6 @@ | Promise<any>

? T
: T extends Map<infer K, infer V>
? DraftMap<K, V>
: T extends Set<infer V>
? DraftSet<V>
: T extends object

@@ -30,5 +32,17 @@ ? {-readonly [K in keyof T]: Draft<T[K]>}

// Inline these in ts 3.7
interface DraftMap<K, V> extends Map<Draft<K>, Draft<V>> {}
// Inline these in ts 3.7
interface DraftSet<V> extends Set<Draft<V>> {}
/** Convert a mutable type into a readonly type */
export type Immutable<T> = T extends AtomicObject
? T
: T extends Map<infer K, infer V>
? // Ideally, but wait for TS 3.7: ? Omit<ImmutableMap<K, V>, "set" | "delete" | "clear">
ImmutableMap<K, V>
: T extends Set<infer V>
? // Ideally, but wait for TS 3.7: ? Omit<ImmutableSet<V>, "add" | "delete" | "clear">
ImmutableSet<V>
: T extends object

@@ -38,2 +52,6 @@ ? {readonly [K in keyof T]: Immutable<T[K]>}

interface ImmutableMap<K, V> extends Map<Immutable<K>, Immutable<V>> {}
interface ImmutableSet<V> extends Set<Immutable<V>> {}
export interface Patch {

@@ -40,0 +58,0 @@ op: "replace" | "remove" | "add"

@@ -14,3 +14,3 @@ 'use strict';

if (!value) { return false; }
return isPlainObject(value) || !!value[DRAFTABLE] || !!value.constructor[DRAFTABLE];
return isPlainObject(value) || !!value[DRAFTABLE] || !!value.constructor[DRAFTABLE] || isMap(value) || isSet(value);
}

@@ -28,12 +28,27 @@ function isPlainObject(value) {

} // We use Maps as `drafts` for Sets, not Objects
// See proxy.js
function assignSet(target, override) {
override.forEach(function (value) {
// When we add new drafts we have to remove their originals if present
var prev = original(value);
if (prev) { target.delete(prev); }
target.add(value);
});
return target;
} // We use Maps as `drafts` for Maps, not Objects
// See proxy.js
function assignMap(target, override) {
override.forEach(function (value, key) { return target.set(key, value); });
return target;
}
var assign = Object.assign || function assign(target, value) {
for (var key in value) {
if (has(value, key)) {
target[key] = value[key];
}
}
var assign = Object.assign || (function (target) {
var overrides = [], len = arguments.length - 1;
while ( len-- > 0 ) overrides[ len ] = arguments[ len + 1 ];
overrides.forEach(function (override) { return Object.keys(override).forEach(function (key) { return target[key] = override[key]; }); });
return target;
};
});
var ownKeys = typeof Reflect !== "undefined" && Reflect.ownKeys ? Reflect.ownKeys : typeof Object.getOwnPropertySymbols !== "undefined" ? function (obj) { return Object.getOwnPropertyNames(obj).concat(Object.getOwnPropertySymbols(obj)); } : Object.getOwnPropertyNames;

@@ -44,2 +59,4 @@ function shallowCopy(base, invokeGetters) {

if (Array.isArray(base)) { return base.slice(); }
if (isMap(base)) { return new Map(base); }
if (isSet(base)) { return new Set(base); }
var clone = Object.create(Object.getPrototypeOf(base));

@@ -74,7 +91,7 @@ ownKeys(base).forEach(function (key) {

}
function each(value, cb) {
if (Array.isArray(value)) {
for (var i = 0; i < value.length; i++) { cb(i, value[i], value); }
function each(obj, iter) {
if (Array.isArray(obj) || isMap(obj) || isSet(obj)) {
obj.forEach(function (entry, index) { return iter(index, entry, obj); });
} else {
ownKeys(value).forEach(function (key) { return cb(key, value[key], value); });
ownKeys(obj).forEach(function (key) { return iter(key, obj[key], obj); });
}

@@ -87,4 +104,7 @@ }

function has(thing, prop) {
return Object.prototype.hasOwnProperty.call(thing, prop);
return isMap(thing) ? thing.has(prop) : Object.prototype.hasOwnProperty.call(thing, prop);
}
function get(thing, prop) {
return isMap(thing) ? thing.get(prop) : thing[prop];
}
function is(x, y) {

@@ -98,5 +118,87 @@ // From: https://github.com/facebook/fbjs/blob/c69904a511b900266935168223063dd8772dfc40/packages/fbjs/src/core/shallowEqual.js

}
var hasSymbol = typeof Symbol !== "undefined";
var hasMap = typeof Map !== "undefined";
function isMap(target) {
return hasMap && target instanceof Map;
}
var hasSet = typeof Set !== "undefined";
function isSet(target) {
return hasSet && target instanceof Set;
}
function makeIterable(next) {
var obj;
var self;
return self = ( obj = {}, obj[Symbol.iterator] = function () { return self; }, obj.next = next, obj );
}
/** Map.prototype.values _-or-_ Map.prototype.entries */
function iterateMapValues(state, prop, receiver) {
var isEntries = prop !== "values";
return function () {
var iterator = latest(state)[Symbol.iterator]();
return makeIterable(function () {
var result = iterator.next();
if (!result.done) {
var ref = result.value;
var key = ref[0];
var value = receiver.get(key);
result.value = isEntries ? [key, value] : value;
}
return result;
});
};
}
function makeIterateSetValues(createProxy) {
function iterateSetValues(state, prop) {
var isEntries = prop === "entries";
return function () {
var iterator = latest(state)[Symbol.iterator]();
return makeIterable(function () {
var result = iterator.next();
if (!result.done) {
var value = wrapSetValue(state, result.value);
result.value = isEntries ? [value, value] : value;
}
return result;
});
};
}
function wrapSetValue(state, value) {
var key = original(value) || value;
var draft = state.drafts.get(key);
if (!draft) {
if (state.finalized || !isDraftable(value) || state.finalizing) {
return value;
}
draft = createProxy(value, state);
state.drafts.set(key, draft);
if (state.modified) {
state.copy.add(draft);
}
}
return draft;
}
return iterateSetValues;
}
function latest(state) {
return state.copy || state.base;
}
function clone(obj) {
if (!isDraftable(obj)) { return obj; }
if (Array.isArray(obj)) { return obj.map(clone); }
if (isMap(obj)) { return new Map(obj); }
if (isSet(obj)) { return new Set(obj); }
var cloned = Object.create(Object.getPrototypeOf(obj));

@@ -108,8 +210,21 @@

}
function deepFreeze(obj) {
function freeze(obj, deep) {
if ( deep === void 0 ) deep = false;
if (!isDraftable(obj) || isDraft(obj) || Object.isFrozen(obj)) { return; }
if (isSet(obj)) {
obj.add = obj.clear = obj.delete = dontMutateFrozenCollections;
} else if (isMap(obj)) {
obj.set = obj.clear = obj.delete = dontMutateFrozenCollections;
}
Object.freeze(obj);
if (Array.isArray(obj)) { obj.forEach(deepFreeze); }else { for (var key in obj) { deepFreeze(obj[key]); } }
if (deep) { each(obj, function (_, value) { return freeze(value, true); }); }
}
function dontMutateFrozenCollections() {
throw new Error("This object has been frozen and should not be mutated");
}
/** Each scope represents a `produce` call. */

@@ -156,5 +271,2 @@

// but share them all instead
var descriptors = {};
function willFinalize(scope, result, isReplaced) {

@@ -180,6 +292,14 @@ scope.drafts.forEach(function (draft) {

var draft = clonePotentialDraft(base);
each(draft, function (prop) {
proxyProperty(draft, prop, isArray || isEnumerable(base, prop));
}); // See "proxy.js" for property documentation.
if (isMap(base)) {
proxyMap(draft);
} else if (isSet(base)) {
proxySet(draft);
} else {
each(draft, function (prop) {
proxyProperty(draft, prop, isArray || isEnumerable(base, prop));
});
} // See "proxy.js" for property documentation.
var scope = parent ? parent.scope : ImmerScope.current;

@@ -192,6 +312,7 @@ var state = {

finalized: false,
assigned: {},
assigned: isMap(base) ? new Map() : {},
parent: parent,
base: base,
draft: draft,
drafts: isSet(base) ? new Map() : null,
copy: null,

@@ -211,3 +332,3 @@ revoke: revoke$1,

function source(state) {
function latest$1(state) {
return state.copy || state.base;

@@ -230,5 +351,5 @@ } // Access a property without creating an Immer draft.

function get(state, prop) {
function get$1(state, prop) {
assertUnrevoked(state);
var value = peek(source(state), prop);
var value = peek(latest$1(state), prop);
if (state.finalizing) { return value; } // Create a draft if the value is unmodified.

@@ -249,3 +370,3 @@

if (!state.modified) {
if (is(value, peek(source(state), prop))) { return; }
if (is(value, peek(latest$1(state), prop))) { return; }
markChanged(state);

@@ -280,4 +401,8 @@ prepareCopy(state);

return shallowCopy(base);
}
} // property descriptors are recycled to make sure we don't create a get and set closure per property,
// but share them all instead
var descriptors = {};
function proxyProperty(draft, prop, enumerable) {

@@ -293,4 +418,4 @@ var desc = descriptors[prop];

get: function get$1() {
return get(this[DRAFT_STATE], prop);
get: function get$1$1() {
return get$1(this[DRAFT_STATE], prop);
},

@@ -308,4 +433,170 @@

function proxyMap(target) {
Object.defineProperties(target, mapTraps);
if (hasSymbol) {
Object.defineProperty(target, Symbol.iterator, proxyMethod(iterateMapValues));
}
}
var mapTraps = finalizeTraps({
size: function (state) { return latest$1(state).size; },
has: function (state) { return function (key) { return latest$1(state).has(key); }; },
set: function (state) { return function (key, value) {
if (latest$1(state).get(key) !== value) {
prepareCopy(state);
markChanged(state);
state.assigned.set(key, true);
state.copy.set(key, value);
}
return state.draft;
}; },
delete: function (state) { return function (key) {
prepareCopy(state);
markChanged(state);
state.assigned.set(key, false);
state.copy.delete(key);
return false;
}; },
clear: function (state) { return function () {
if (!state.copy) {
prepareCopy(state);
}
markChanged(state);
state.assigned = new Map();
for (var i = 0, list = latest$1(state).keys(); i < list.length; i += 1) {
var key = list[i];
state.assigned.set(key, false);
}
return state.copy.clear();
}; },
forEach: function (state, key, reciever) { return function (cb) {
latest$1(state).forEach(function (value, key, map) {
cb(reciever.get(key), key, map);
});
}; },
get: function (state) { return function (key) {
var value = latest$1(state).get(key);
if (state.finalizing || state.finalized || !isDraftable(value)) {
return value;
}
if (value !== state.base.get(key)) {
return value;
}
var draft = createProxy(value, state);
prepareCopy(state);
state.copy.set(key, draft);
return draft;
}; },
keys: function (state) { return function () { return latest$1(state).keys(); }; },
values: iterateMapValues,
entries: iterateMapValues
});
function proxySet(target) {
Object.defineProperties(target, setTraps);
if (hasSymbol) {
Object.defineProperty(target, Symbol.iterator, proxyMethod(iterateSetValues));
}
}
var iterateSetValues = makeIterateSetValues(createProxy);
var setTraps = finalizeTraps({
size: function (state) {
return latest$1(state).size;
},
add: function (state) { return function (value) {
if (!latest$1(state).has(value)) {
markChanged(state);
if (!state.copy) {
prepareCopy(state);
}
state.copy.add(value);
}
return state.draft;
}; },
delete: function (state) { return function (value) {
markChanged(state);
if (!state.copy) {
prepareCopy(state);
}
return state.copy.delete(value);
}; },
has: function (state) { return function (key) {
return latest$1(state).has(key);
}; },
clear: function (state) { return function () {
markChanged(state);
if (!state.copy) {
prepareCopy(state);
}
return state.copy.clear();
}; },
keys: iterateSetValues,
entries: iterateSetValues,
values: iterateSetValues,
forEach: function (state) { return function (cb, thisArg) {
var iterator = iterateSetValues(state)();
var result = iterator.next();
while (!result.done) {
cb.call(thisArg, result.value, result.value, state.draft);
result = iterator.next();
}
}; }
});
function finalizeTraps(traps) {
return Object.keys(traps).reduce(function (acc, key) {
var builder = key === "size" ? proxyAttr : proxyMethod;
acc[key] = builder(traps[key], key);
return acc;
}, {});
}
function proxyAttr(fn) {
return {
get: function get() {
var state = this[DRAFT_STATE];
assertUnrevoked(state);
return fn(state);
}
};
}
function proxyMethod(trap, key) {
return {
get: function get() {
return function () {
var args = [], len = arguments.length;
while ( len-- ) args[ len ] = arguments[ len ];
var state = this[DRAFT_STATE];
assertUnrevoked(state);
return trap(state, key, state.draft).apply(void 0, args);
};
}
};
}
function assertUnrevoked(state) {
if (state.revoked === true) { throw new Error("Cannot use a proxy that has been revoked. Did you pass an object from inside an immer function to an async process? " + JSON.stringify(source(state))); }
if (state.revoked === true) { throw new Error("Cannot use a proxy that has been revoked. Did you pass an object from inside an immer function to an async process? " + JSON.stringify(latest$1(state))); }
} // This looks expensive, but only proxies are visited, and only objects without known changes are scanned.

@@ -325,3 +616,9 @@

if (hasArrayChanges(state)) { markChanged(state); }
} else if (hasObjectChanges(state)) { markChanged(state); }
} else if (isMap(state.base)) {
if (hasMapChanges(state)) { markChanged(state); }
} else if (isSet(state.base)) {
if (hasSetChanges(state)) { markChanged(state); }
} else if (hasObjectChanges(state)) {
markChanged(state);
}
}

@@ -423,2 +720,30 @@ }

function hasMapChanges(state) {
var base = state.base;
var draft = state.draft;
if (base.size !== draft.size) { return true; } // IE11 supports only forEach iteration
var hasChanges = false;
draft.forEach(function (value, key) {
if (!hasChanges) {
hasChanges = isDraftable(value) ? value.modified : value !== base.get(key);
}
});
return hasChanges;
}
function hasSetChanges(state) {
var base = state.base;
var draft = state.draft;
if (base.size !== draft.size) { return true; } // IE11 supports only forEach iteration
var hasChanges = false;
draft.forEach(function (value, key) {
if (!hasChanges) {
hasChanges = isDraftable(value) ? value.modified : !base.has(key);
}
});
return hasChanges;
}
function createHiddenProperty(target, prop, value) {

@@ -437,3 +762,11 @@ Object.defineProperty(target, prop, {

var obj$1, obj$1$1;
function willFinalize$1() {}
/**
* Returns a new draft of the `base` object.
*
* The second argument is the parent draft-state (used internally).
*/
function createProxy$1(base, parent) {

@@ -463,5 +796,21 @@ var scope = parent ? parent.scope : ImmerScope.current;

};
var ref = Array.isArray(base) ? // [state] is used for arrays, to make sure the proxy is array-ish and not violate invariants,
// although state itself is an object
Proxy.revocable([state], arrayTraps) : Proxy.revocable(state, objectTraps);
var target = state;
var traps = objectTraps;
if (Array.isArray(base)) {
target = [state];
traps = arrayTraps;
} // Map drafts must support object keys, so we use Map objects to track changes.
else if (isMap(base)) {
traps = mapTraps$1;
state.drafts = new Map();
state.assigned = new Map();
} // Set drafts use a Map object to track which of its values are drafted.
// And we don't need the "assigned" property, because Set objects have no keys.
else if (isSet(base)) {
traps = setTraps$1;
state.drafts = new Map();
}
var ref = Proxy.revocable(target, traps);
var revoke = ref.revoke;

@@ -474,17 +823,84 @@ var proxy = ref.proxy;

}
/**
* Object drafts
*/
var objectTraps = {
get: get$1,
get: function get(state, prop) {
if (prop === DRAFT_STATE) { return state; }
var drafts = state.drafts; // Check for existing draft in unmodified state.
has: function has(target, prop) {
return prop in source$1(target);
if (!state.modified && has(drafts, prop)) {
return drafts[prop];
}
var value = latest$2(state)[prop];
if (state.finalized || !isDraftable(value)) {
return value;
} // Check for existing draft in modified state.
if (state.modified) {
// Assigned values are never drafted. This catches any drafts we created, too.
if (value !== peek$1(state.base, prop)) { return value; } // Store drafts on the copy (when one exists).
drafts = state.copy;
}
return drafts[prop] = createProxy$1(value, state);
},
ownKeys: function ownKeys(target) {
return Reflect.ownKeys(source$1(target));
has: function has(state, prop) {
return prop in latest$2(state);
},
set: set$1,
deleteProperty: deleteProperty,
getOwnPropertyDescriptor: getOwnPropertyDescriptor,
ownKeys: function ownKeys(state) {
return Reflect.ownKeys(latest$2(state));
},
set: function set(state, prop, value) {
if (!state.modified) {
var baseValue = peek$1(state.base, prop); // Optimize based on value's truthiness. Truthy values are guaranteed to
// never be undefined, so we can avoid the `in` operator. Lastly, truthy
// values may be drafts, but falsy values are never drafts.
var isUnchanged = value ? is(baseValue, value) || value === state.drafts[prop] : is(baseValue, value) && prop in state.base;
if (isUnchanged) { return true; }
markChanged$1(state);
}
state.assigned[prop] = true;
state.copy[prop] = value;
return true;
},
deleteProperty: function deleteProperty(state, prop) {
// The `undefined` check is a fast path for pre-existing keys.
if (peek$1(state.base, prop) !== undefined || prop in state.base) {
state.assigned[prop] = false;
markChanged$1(state);
} else if (state.assigned[prop]) {
// if an originally not assigned property was deleted
delete state.assigned[prop];
}
if (state.copy) { delete state.copy[prop]; }
return true;
},
// Note: We never coerce `desc.value` into an Immer draft, because we can't make
// the same guarantee in ES5 mode.
getOwnPropertyDescriptor: function getOwnPropertyDescriptor(state, prop) {
var owner = latest$2(state);
var desc = Reflect.getOwnPropertyDescriptor(owner, prop);
if (desc) {
desc.writable = true;
desc.configurable = !Array.isArray(owner) || prop !== "length";
}
return desc;
},
defineProperty: function defineProperty() {

@@ -494,4 +910,4 @@ throw new Error("Object.defineProperty() cannot be used on an Immer draft"); // prettier-ignore

getPrototypeOf: function getPrototypeOf(target) {
return Object.getPrototypeOf(target.base);
getPrototypeOf: function getPrototypeOf(state) {
return Object.getPrototypeOf(state.base);
},

@@ -504,2 +920,6 @@

};
/**
* Array drafts
*/
var arrayTraps = {};

@@ -527,83 +947,100 @@ each(objectTraps, function (key, fn) {

return objectTraps.set.call(this, state[0], prop, value);
}; // returns the object we should be reading the current value from, which is base, until some change has been made
}; // Used by Map and Set drafts
function source$1(state) {
return state.copy || state.base;
} // Access a property without creating an Immer draft.
var reflectTraps = makeReflectTraps(["ownKeys", "has", "set", "deleteProperty", "defineProperty", "getOwnPropertyDescriptor", "preventExtensions", "isExtensible", "getPrototypeOf"]);
/**
* Map drafts
*/
var mapTraps$1 = makeTrapsForGetters(( obj$1 = {}, obj$1[DRAFT_STATE] = function (state) { return state; }, obj$1.size = function (state) { return latest$2(state).size; }, obj$1.has = function (state) { return function (key) { return latest$2(state).has(key); }; }, obj$1.set = function (state) { return function (key, value) {
var values = latest$2(state);
function peek$1(draft, prop) {
var state = draft[DRAFT_STATE];
var desc = Reflect.getOwnPropertyDescriptor(state ? source$1(state) : draft, prop);
return desc && desc.value;
}
if (!values.has(key) || values.get(key) !== value) {
markChanged$1(state);
state.assigned.set(key, true);
state.copy.set(key, value);
}
function get$1(state, prop) {
if (prop === DRAFT_STATE) { return state; }
var drafts = state.drafts; // Check for existing draft in unmodified state.
return state.draft;
}; }, obj$1.delete = function (state) { return function (key) {
if (latest$2(state).has(key)) {
markChanged$1(state);
state.assigned.set(key, false);
return state.copy.delete(key);
}
if (!state.modified && has(drafts, prop)) {
return drafts[prop];
}
return false;
}; }, obj$1.clear = function (state) { return function () {
markChanged$1(state);
state.assigned = new Map();
var value = source$1(state)[prop];
for (var i = 0, list = latest$2(state).keys(); i < list.length; i += 1) {
var key = list[i];
if (state.finalized || !isDraftable(value)) {
return value;
} // Check for existing draft in modified state.
state.assigned.set(key, false);
}
return state.copy.clear();
}; }, obj$1.forEach = function (state, _, receiver) { return function (cb, thisArg) { return latest$2(state).forEach(function (_, key, map) {
var value = receiver.get(key);
cb.call(thisArg, value, key, map);
}); }; }, obj$1.get = function (state) { return function (key) {
var drafts = state[state.modified ? "copy" : "drafts"];
if (state.modified) {
// Assigned values are never drafted. This catches any drafts we created, too.
if (value !== peek$1(state.base, prop)) { return value; } // Store drafts on the copy (when one exists).
if (drafts.has(key)) {
return drafts.get(key);
}
drafts = state.copy;
}
var value = latest$2(state).get(key);
return drafts[prop] = createProxy$1(value, state);
}
if (state.finalized || !isDraftable(value)) {
return value;
}
function set$1(state, prop, value) {
if (!state.modified) {
var baseValue = peek$1(state.base, prop); // Optimize based on value's truthiness. Truthy values are guaranteed to
// never be undefined, so we can avoid the `in` operator. Lastly, truthy
// values may be drafts, but falsy values are never drafts.
var draft = createProxy$1(value, state);
drafts.set(key, draft);
return draft;
}; }, obj$1.keys = function (state) { return function () { return latest$2(state).keys(); }; }, obj$1.values = iterateMapValues, obj$1.entries = iterateMapValues, obj$1[hasSymbol ? Symbol.iterator : "@@iterator"] = iterateMapValues, obj$1 ));
var iterateSetValues$1 = makeIterateSetValues(createProxy$1);
/**
* Set drafts
*/
var isUnchanged = value ? is(baseValue, value) || value === state.drafts[prop] : is(baseValue, value) && prop in state.base;
if (isUnchanged) { return true; }
markChanged$1(state);
}
var setTraps$1 = makeTrapsForGetters(( obj$1$1 = {}, obj$1$1[DRAFT_STATE] = function (state) { return state; }, obj$1$1.size = function (state) { return latest$2(state).size; }, obj$1$1.has = function (state) { return function (key) { return latest$2(state).has(key); }; }, obj$1$1.add = function (state) { return function (value) {
if (!latest$2(state).has(value)) {
markChanged$1(state);
state.copy.add(value);
}
state.assigned[prop] = true;
state.copy[prop] = value;
return true;
}
function deleteProperty(state, prop) {
// The `undefined` check is a fast path for pre-existing keys.
if (peek$1(state.base, prop) !== undefined || prop in state.base) {
state.assigned[prop] = false;
return state.draft;
}; }, obj$1$1.delete = function (state) { return function (value) {
markChanged$1(state);
} else if (state.assigned[prop]) {
// if an originally not assigned property was deleted
delete state.assigned[prop];
}
return state.copy.delete(value);
}; }, obj$1$1.clear = function (state) { return function () {
markChanged$1(state);
return state.copy.clear();
}; }, obj$1$1.forEach = function (state) { return function (cb, thisArg) {
var iterator = iterateSetValues$1(state)();
var result = iterator.next();
if (state.copy) { delete state.copy[prop]; }
return true;
} // Note: We never coerce `desc.value` into an Immer draft, because we can't make
// the same guarantee in ES5 mode.
while (!result.done) {
cb.call(thisArg, result.value, result.value, state.draft);
result = iterator.next();
}
}; }, obj$1$1.keys = iterateSetValues$1, obj$1$1.values = iterateSetValues$1, obj$1$1.entries = iterateSetValues$1, obj$1$1[hasSymbol ? Symbol.iterator : "@@iterator"] = iterateSetValues$1, obj$1$1 ));
/**
* Helpers
*/
// Retrieve the latest values of the draft.
function latest$2(state) {
return state.copy || state.base;
} // Access a property without creating an Immer draft.
function getOwnPropertyDescriptor(state, prop) {
var owner = source$1(state);
var desc = Reflect.getOwnPropertyDescriptor(owner, prop);
if (desc) {
desc.writable = true;
desc.configurable = !Array.isArray(owner) || prop !== "length";
}
return desc;
function peek$1(draft, prop) {
var state = draft[DRAFT_STATE];
var desc = Reflect.getOwnPropertyDescriptor(state ? latest$2(state) : draft, prop);
return desc && desc.value;
}

@@ -614,8 +1051,53 @@

state.modified = true;
state.copy = assign(shallowCopy(state.base), state.drafts);
state.drafts = null;
if (state.parent) { markChanged$1(state.parent); }
var base = state.base;
var drafts = state.drafts;
var parent = state.parent;
var copy = shallowCopy(base);
if (isSet(base)) {
// Note: The `drafts` property is preserved for Set objects, since
// we need to keep track of which values are drafted.
assignSet(copy, drafts);
} else {
// Merge nested drafts into the copy.
if (isMap(base)) { assignMap(copy, drafts); }else { assign(copy, drafts); }
state.drafts = null;
}
state.copy = copy;
if (parent) {
markChanged$1(parent);
}
}
}
/** Create traps that all use the `Reflect` API on the `latest(state)` */
function makeReflectTraps(names) {
return names.reduce(function (traps, name) {
traps[name] = function (state) {
var args = [], len = arguments.length - 1;
while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ];
return Reflect[name].apply(Reflect, [ latest$2(state) ].concat( args ));
};
return traps;
}, {});
}
function makeTrapsForGetters(getters) {
return Object.assign({}, reflectTraps, {
get: function get(state, prop, receiver) {
return getters.hasOwnProperty(prop) ? getters[prop](state, prop, receiver) : Reflect.get(state, prop, receiver);
},
setPrototypeOf: function setPrototypeOf(state) {
throw new Error("Object.setPrototypeOf() cannot be used on an Immer draft"); // prettier-ignore
}
});
}
var modernProxy = /*#__PURE__*/Object.freeze({

@@ -627,3 +1109,4 @@ willFinalize: willFinalize$1,

function generatePatches(state, basePath, patches, inversePatches) {
Array.isArray(state.base) ? generateArrayPatches(state, basePath, patches, inversePatches) : generateObjectPatches(state, basePath, patches, inversePatches);
var generatePatchesFn = Array.isArray(state.base) ? generateArrayPatches : isSet(state.base) ? generateSetPatches : generatePatchesFromAssigned;
generatePatchesFn(state, basePath, patches, inversePatches);
}

@@ -689,11 +1172,12 @@

}
}
} // This is used for both Map objects and normal objects.
function generateObjectPatches(state, basePath, patches, inversePatches) {
function generatePatchesFromAssigned(state, basePath, patches, inversePatches) {
var base = state.base;
var copy = state.copy;
each(state.assigned, function (key, assignedValue) {
var origValue = base[key];
var value = copy[key];
var op = !assignedValue ? "remove" : key in base ? "replace" : "add";
var origValue = get(base, key);
var value = get(copy, key);
var op = !assignedValue ? "remove" : has(base, key) ? "replace" : "add";
if (origValue === value && op === "replace") { return; }

@@ -724,2 +1208,50 @@ var path = basePath.concat(key);

function generateSetPatches(state, basePath, patches, inversePatches) {
var base = state.base;
var copy = state.copy;
var i = 0;
for (var i$1 = 0, list = base; i$1 < list.length; i$1 += 1) {
var value = list[i$1];
if (!copy.has(value)) {
var path = basePath.concat([i]);
patches.push({
op: "remove",
path: path,
value: value
});
inversePatches.unshift({
op: "add",
path: path,
value: value
});
}
i++;
}
i = 0;
for (var i$2 = 0, list$1 = copy; i$2 < list$1.length; i$2 += 1) {
var value$1 = list$1[i$2];
if (!base.has(value$1)) {
var path$1 = basePath.concat([i]);
patches.push({
op: "add",
path: path$1,
value: value$1
});
inversePatches.unshift({
op: "remove",
path: path$1,
value: value$1
});
}
i++;
}
}
var applyPatches = function (draft, patches) {

@@ -731,4 +1263,2 @@ for (var i$1 = 0, list = patches; i$1 < list.length; i$1 += 1) {

var op = patch.op;
var value = clone(patch.value); // used to clone patch to ensure original patch is not modified, see #411
if (!path.length) { throw new Error("Illegal state"); }

@@ -738,6 +1268,8 @@ var base = draft;

for (var i = 0; i < path.length - 1; i++) {
base = base[path[i]];
base = get(base, path[i]);
if (!base || typeof base !== "object") { throw new Error("Cannot apply patch, path doesn't resolve: " + path.join("/")); } // prettier-ignore
}
var value = clone(patch.value); // used to clone patch to ensure original patch is not modified, see #411
var key = path[path.length - 1];

@@ -747,13 +1279,10 @@

case "replace":
// if value is an object, then it's assigned by reference
// in the following add or remove ops, the value field inside the patch will also be modifyed
// so we use value from the cloned patch
base[key] = value;
break;
case "add":
if (Array.isArray(base)) {
// TODO: support "foo/-" paths for appending to an array
base.splice(key, 0, value);
if (isMap(base)) {
base.set(key, value);
} else if (isSet(base)) {
throw new Error('Sets cannot have "replace" patches.');
} else {
// if value is an object, then it's assigned by reference
// in the following add or remove ops, the value field inside the patch will also be modifyed
// so we use value from the cloned patch
base[key] = value;

@@ -764,11 +1293,14 @@ }

case "remove":
if (Array.isArray(base)) {
base.splice(key, 1);
} else {
delete base[key];
case "add":
if (isSet(base)) {
base.delete(patch.value);
}
Array.isArray(base) ? base.splice(key, 0, value) : isMap(base) ? base.set(key, value) : isSet(base) ? base.add(value) : base[key] = value;
break;
case "remove":
Array.isArray(base) ? base.splice(key, 1) : isMap(base) ? base.delete(key) : isSet(base) ? base.delete(patch.value) : delete base[key];
break;
default:

@@ -795,2 +1327,3 @@ throw new Error("Unsupported patch operation: " + op);

this.produce = this.produce.bind(this);
this.produceWithPatches = this.produceWithPatches.bind(this);
};

@@ -841,3 +1374,3 @@

if (result instanceof Promise) {
if (typeof Promise !== "undefined" && result instanceof Promise) {
return result.then(function (result) {

@@ -1018,13 +1551,13 @@ scope.usePatches(patchListener);

state.finalized = true;
this.finalizeTree(state.draft, path, scope);
this.finalizeTree(state.draft, path, scope); // We cannot really delete anything inside of a Set. We can only replace the whole Set.
if (this.onDelete) {
if (this.onDelete && !isSet(state.base)) {
// The `assigned` object is unreliable with ES5 drafts.
if (this.useProxies) {
var assigned = state.assigned;
for (var prop in assigned) {
if (!assigned[prop]) { this.onDelete(state, prop); }
}
each(assigned, function (prop, exists) {
if (!exists) { this$1.onDelete(state, prop); }
});
} else {
// TODO: Figure it out for Maps and Sets if we need to support ES5
var base = state.base;

@@ -1045,3 +1578,3 @@ var copy = state.copy;

if (this.autoFreeze && scope.canAutoFreeze) {
Object.freeze(state.copy);
freeze(state.copy, false);
}

@@ -1085,25 +1618,20 @@

var isDraftProp = !!state && parent === root;
var isSetMember = isSet(parent);
if (isDraft(value)) {
var path = isDraftProp && needPatches && !state.assigned[prop] ? rootPath.concat(prop) : null; // Drafts owned by `scope` are finalized here.
var path = isDraftProp && needPatches && !isSetMember && // Set objects are atomic since they have no keys.
!has(state.assigned, prop) // Skip deep patches for assigned keys.
? rootPath.concat(prop) : null; // Drafts owned by `scope` are finalized here.
value = this$1.finalize(value, path, scope); // Drafts from another scope must prevent auto-freezing.
value = this$1.finalize(value, path, scope);
replace(parent, prop, value); // Drafts from another scope must prevent auto-freezing.
if (isDraft(value)) {
scope.canAutoFreeze = false;
} // Preserve non-enumerable properties.
if (Array.isArray(parent) || isEnumerable(parent, prop)) {
parent[prop] = value;
} else {
Object.defineProperty(parent, prop, {
value: value
});
} // Unchanged drafts are never passed to the `onAssign` hook.
if (isDraftProp && value === state.base[prop]) { return; }
if (isDraftProp && value === get(state.base, prop)) { return; }
} // Unchanged draft properties are ignored.
else if (isDraftProp && is(value, state.base[prop])) {
else if (isDraftProp && is(value, get(state.base, prop))) {
return;

@@ -1116,3 +1644,3 @@ } // Search new objects for unfinalized drafts. Frozen objects should never contain drafts.

if (isDraftProp && this$1.onAssign) {
if (isDraftProp && this$1.onAssign && !isSetMember) {
this$1.onAssign(state, prop, value);

@@ -1130,6 +1658,25 @@ }

if (this.autoFreeze && !isDraft(value)) {
if (deep) { deepFreeze(value); }else { Object.freeze(value); }
freeze(value, deep);
}
};
function replace(parent, prop, value) {
if (isMap(parent)) {
parent.set(prop, value);
} else if (isSet(parent)) {
// In this case, the `prop` is actually a draft.
parent.delete(prop);
parent.add(value);
} else if (Array.isArray(parent) || isEnumerable(parent, prop)) {
// Preserve non-enumerable properties.
parent[prop] = value;
} else {
Object.defineProperty(parent, prop, {
value: value,
writable: true,
configurable: true
});
}
}
var immer = new Immer();

@@ -1136,0 +1683,0 @@ /**

@@ -10,3 +10,3 @@ var obj;

if (!value) { return false; }
return isPlainObject(value) || !!value[DRAFTABLE] || !!value.constructor[DRAFTABLE];
return isPlainObject(value) || !!value[DRAFTABLE] || !!value.constructor[DRAFTABLE] || isMap(value) || isSet(value);
}

@@ -24,12 +24,27 @@ function isPlainObject(value) {

} // We use Maps as `drafts` for Sets, not Objects
// See proxy.js
function assignSet(target, override) {
override.forEach(function (value) {
// When we add new drafts we have to remove their originals if present
var prev = original(value);
if (prev) { target.delete(prev); }
target.add(value);
});
return target;
} // We use Maps as `drafts` for Maps, not Objects
// See proxy.js
function assignMap(target, override) {
override.forEach(function (value, key) { return target.set(key, value); });
return target;
}
var assign = Object.assign || function assign(target, value) {
for (var key in value) {
if (has(value, key)) {
target[key] = value[key];
}
}
var assign = Object.assign || (function (target) {
var overrides = [], len = arguments.length - 1;
while ( len-- > 0 ) overrides[ len ] = arguments[ len + 1 ];
overrides.forEach(function (override) { return Object.keys(override).forEach(function (key) { return target[key] = override[key]; }); });
return target;
};
});
var ownKeys = typeof Reflect !== "undefined" && Reflect.ownKeys ? Reflect.ownKeys : typeof Object.getOwnPropertySymbols !== "undefined" ? function (obj) { return Object.getOwnPropertyNames(obj).concat(Object.getOwnPropertySymbols(obj)); } : Object.getOwnPropertyNames;

@@ -40,2 +55,4 @@ function shallowCopy(base, invokeGetters) {

if (Array.isArray(base)) { return base.slice(); }
if (isMap(base)) { return new Map(base); }
if (isSet(base)) { return new Set(base); }
var clone = Object.create(Object.getPrototypeOf(base));

@@ -70,7 +87,7 @@ ownKeys(base).forEach(function (key) {

}
function each(value, cb) {
if (Array.isArray(value)) {
for (var i = 0; i < value.length; i++) { cb(i, value[i], value); }
function each(obj, iter) {
if (Array.isArray(obj) || isMap(obj) || isSet(obj)) {
obj.forEach(function (entry, index) { return iter(index, entry, obj); });
} else {
ownKeys(value).forEach(function (key) { return cb(key, value[key], value); });
ownKeys(obj).forEach(function (key) { return iter(key, obj[key], obj); });
}

@@ -83,4 +100,7 @@ }

function has(thing, prop) {
return Object.prototype.hasOwnProperty.call(thing, prop);
return isMap(thing) ? thing.has(prop) : Object.prototype.hasOwnProperty.call(thing, prop);
}
function get(thing, prop) {
return isMap(thing) ? thing.get(prop) : thing[prop];
}
function is(x, y) {

@@ -94,5 +114,87 @@ // From: https://github.com/facebook/fbjs/blob/c69904a511b900266935168223063dd8772dfc40/packages/fbjs/src/core/shallowEqual.js

}
var hasSymbol = typeof Symbol !== "undefined";
var hasMap = typeof Map !== "undefined";
function isMap(target) {
return hasMap && target instanceof Map;
}
var hasSet = typeof Set !== "undefined";
function isSet(target) {
return hasSet && target instanceof Set;
}
function makeIterable(next) {
var obj;
var self;
return self = ( obj = {}, obj[Symbol.iterator] = function () { return self; }, obj.next = next, obj );
}
/** Map.prototype.values _-or-_ Map.prototype.entries */
function iterateMapValues(state, prop, receiver) {
var isEntries = prop !== "values";
return function () {
var iterator = latest(state)[Symbol.iterator]();
return makeIterable(function () {
var result = iterator.next();
if (!result.done) {
var ref = result.value;
var key = ref[0];
var value = receiver.get(key);
result.value = isEntries ? [key, value] : value;
}
return result;
});
};
}
function makeIterateSetValues(createProxy) {
function iterateSetValues(state, prop) {
var isEntries = prop === "entries";
return function () {
var iterator = latest(state)[Symbol.iterator]();
return makeIterable(function () {
var result = iterator.next();
if (!result.done) {
var value = wrapSetValue(state, result.value);
result.value = isEntries ? [value, value] : value;
}
return result;
});
};
}
function wrapSetValue(state, value) {
var key = original(value) || value;
var draft = state.drafts.get(key);
if (!draft) {
if (state.finalized || !isDraftable(value) || state.finalizing) {
return value;
}
draft = createProxy(value, state);
state.drafts.set(key, draft);
if (state.modified) {
state.copy.add(draft);
}
}
return draft;
}
return iterateSetValues;
}
function latest(state) {
return state.copy || state.base;
}
function clone(obj) {
if (!isDraftable(obj)) { return obj; }
if (Array.isArray(obj)) { return obj.map(clone); }
if (isMap(obj)) { return new Map(obj); }
if (isSet(obj)) { return new Set(obj); }
var cloned = Object.create(Object.getPrototypeOf(obj));

@@ -104,8 +206,21 @@

}
function deepFreeze(obj) {
function freeze(obj, deep) {
if ( deep === void 0 ) deep = false;
if (!isDraftable(obj) || isDraft(obj) || Object.isFrozen(obj)) { return; }
if (isSet(obj)) {
obj.add = obj.clear = obj.delete = dontMutateFrozenCollections;
} else if (isMap(obj)) {
obj.set = obj.clear = obj.delete = dontMutateFrozenCollections;
}
Object.freeze(obj);
if (Array.isArray(obj)) { obj.forEach(deepFreeze); }else { for (var key in obj) { deepFreeze(obj[key]); } }
if (deep) { each(obj, function (_, value) { return freeze(value, true); }); }
}
function dontMutateFrozenCollections() {
throw new Error("This object has been frozen and should not be mutated");
}
/** Each scope represents a `produce` call. */

@@ -152,5 +267,2 @@

// but share them all instead
var descriptors = {};
function willFinalize(scope, result, isReplaced) {

@@ -176,6 +288,14 @@ scope.drafts.forEach(function (draft) {

var draft = clonePotentialDraft(base);
each(draft, function (prop) {
proxyProperty(draft, prop, isArray || isEnumerable(base, prop));
}); // See "proxy.js" for property documentation.
if (isMap(base)) {
proxyMap(draft);
} else if (isSet(base)) {
proxySet(draft);
} else {
each(draft, function (prop) {
proxyProperty(draft, prop, isArray || isEnumerable(base, prop));
});
} // See "proxy.js" for property documentation.
var scope = parent ? parent.scope : ImmerScope.current;

@@ -188,6 +308,7 @@ var state = {

finalized: false,
assigned: {},
assigned: isMap(base) ? new Map() : {},
parent: parent,
base: base,
draft: draft,
drafts: isSet(base) ? new Map() : null,
copy: null,

@@ -207,3 +328,3 @@ revoke: revoke$1,

function source(state) {
function latest$1(state) {
return state.copy || state.base;

@@ -226,5 +347,5 @@ } // Access a property without creating an Immer draft.

function get(state, prop) {
function get$1(state, prop) {
assertUnrevoked(state);
var value = peek(source(state), prop);
var value = peek(latest$1(state), prop);
if (state.finalizing) { return value; } // Create a draft if the value is unmodified.

@@ -245,3 +366,3 @@

if (!state.modified) {
if (is(value, peek(source(state), prop))) { return; }
if (is(value, peek(latest$1(state), prop))) { return; }
markChanged(state);

@@ -276,4 +397,8 @@ prepareCopy(state);

return shallowCopy(base);
}
} // property descriptors are recycled to make sure we don't create a get and set closure per property,
// but share them all instead
var descriptors = {};
function proxyProperty(draft, prop, enumerable) {

@@ -289,4 +414,4 @@ var desc = descriptors[prop];

get: function get$1() {
return get(this[DRAFT_STATE], prop);
get: function get$1$1() {
return get$1(this[DRAFT_STATE], prop);
},

@@ -304,4 +429,170 @@

function proxyMap(target) {
Object.defineProperties(target, mapTraps);
if (hasSymbol) {
Object.defineProperty(target, Symbol.iterator, proxyMethod(iterateMapValues));
}
}
var mapTraps = finalizeTraps({
size: function (state) { return latest$1(state).size; },
has: function (state) { return function (key) { return latest$1(state).has(key); }; },
set: function (state) { return function (key, value) {
if (latest$1(state).get(key) !== value) {
prepareCopy(state);
markChanged(state);
state.assigned.set(key, true);
state.copy.set(key, value);
}
return state.draft;
}; },
delete: function (state) { return function (key) {
prepareCopy(state);
markChanged(state);
state.assigned.set(key, false);
state.copy.delete(key);
return false;
}; },
clear: function (state) { return function () {
if (!state.copy) {
prepareCopy(state);
}
markChanged(state);
state.assigned = new Map();
for (var i = 0, list = latest$1(state).keys(); i < list.length; i += 1) {
var key = list[i];
state.assigned.set(key, false);
}
return state.copy.clear();
}; },
forEach: function (state, key, reciever) { return function (cb) {
latest$1(state).forEach(function (value, key, map) {
cb(reciever.get(key), key, map);
});
}; },
get: function (state) { return function (key) {
var value = latest$1(state).get(key);
if (state.finalizing || state.finalized || !isDraftable(value)) {
return value;
}
if (value !== state.base.get(key)) {
return value;
}
var draft = createProxy(value, state);
prepareCopy(state);
state.copy.set(key, draft);
return draft;
}; },
keys: function (state) { return function () { return latest$1(state).keys(); }; },
values: iterateMapValues,
entries: iterateMapValues
});
function proxySet(target) {
Object.defineProperties(target, setTraps);
if (hasSymbol) {
Object.defineProperty(target, Symbol.iterator, proxyMethod(iterateSetValues));
}
}
var iterateSetValues = makeIterateSetValues(createProxy);
var setTraps = finalizeTraps({
size: function (state) {
return latest$1(state).size;
},
add: function (state) { return function (value) {
if (!latest$1(state).has(value)) {
markChanged(state);
if (!state.copy) {
prepareCopy(state);
}
state.copy.add(value);
}
return state.draft;
}; },
delete: function (state) { return function (value) {
markChanged(state);
if (!state.copy) {
prepareCopy(state);
}
return state.copy.delete(value);
}; },
has: function (state) { return function (key) {
return latest$1(state).has(key);
}; },
clear: function (state) { return function () {
markChanged(state);
if (!state.copy) {
prepareCopy(state);
}
return state.copy.clear();
}; },
keys: iterateSetValues,
entries: iterateSetValues,
values: iterateSetValues,
forEach: function (state) { return function (cb, thisArg) {
var iterator = iterateSetValues(state)();
var result = iterator.next();
while (!result.done) {
cb.call(thisArg, result.value, result.value, state.draft);
result = iterator.next();
}
}; }
});
function finalizeTraps(traps) {
return Object.keys(traps).reduce(function (acc, key) {
var builder = key === "size" ? proxyAttr : proxyMethod;
acc[key] = builder(traps[key], key);
return acc;
}, {});
}
function proxyAttr(fn) {
return {
get: function get() {
var state = this[DRAFT_STATE];
assertUnrevoked(state);
return fn(state);
}
};
}
function proxyMethod(trap, key) {
return {
get: function get() {
return function () {
var args = [], len = arguments.length;
while ( len-- ) args[ len ] = arguments[ len ];
var state = this[DRAFT_STATE];
assertUnrevoked(state);
return trap(state, key, state.draft).apply(void 0, args);
};
}
};
}
function assertUnrevoked(state) {
if (state.revoked === true) { throw new Error("Cannot use a proxy that has been revoked. Did you pass an object from inside an immer function to an async process? " + JSON.stringify(source(state))); }
if (state.revoked === true) { throw new Error("Cannot use a proxy that has been revoked. Did you pass an object from inside an immer function to an async process? " + JSON.stringify(latest$1(state))); }
} // This looks expensive, but only proxies are visited, and only objects without known changes are scanned.

@@ -321,3 +612,9 @@

if (hasArrayChanges(state)) { markChanged(state); }
} else if (hasObjectChanges(state)) { markChanged(state); }
} else if (isMap(state.base)) {
if (hasMapChanges(state)) { markChanged(state); }
} else if (isSet(state.base)) {
if (hasSetChanges(state)) { markChanged(state); }
} else if (hasObjectChanges(state)) {
markChanged(state);
}
}

@@ -419,2 +716,30 @@ }

function hasMapChanges(state) {
var base = state.base;
var draft = state.draft;
if (base.size !== draft.size) { return true; } // IE11 supports only forEach iteration
var hasChanges = false;
draft.forEach(function (value, key) {
if (!hasChanges) {
hasChanges = isDraftable(value) ? value.modified : value !== base.get(key);
}
});
return hasChanges;
}
function hasSetChanges(state) {
var base = state.base;
var draft = state.draft;
if (base.size !== draft.size) { return true; } // IE11 supports only forEach iteration
var hasChanges = false;
draft.forEach(function (value, key) {
if (!hasChanges) {
hasChanges = isDraftable(value) ? value.modified : !base.has(key);
}
});
return hasChanges;
}
function createHiddenProperty(target, prop, value) {

@@ -433,3 +758,11 @@ Object.defineProperty(target, prop, {

var obj$1, obj$1$1;
function willFinalize$1() {}
/**
* Returns a new draft of the `base` object.
*
* The second argument is the parent draft-state (used internally).
*/
function createProxy$1(base, parent) {

@@ -459,5 +792,21 @@ var scope = parent ? parent.scope : ImmerScope.current;

};
var ref = Array.isArray(base) ? // [state] is used for arrays, to make sure the proxy is array-ish and not violate invariants,
// although state itself is an object
Proxy.revocable([state], arrayTraps) : Proxy.revocable(state, objectTraps);
var target = state;
var traps = objectTraps;
if (Array.isArray(base)) {
target = [state];
traps = arrayTraps;
} // Map drafts must support object keys, so we use Map objects to track changes.
else if (isMap(base)) {
traps = mapTraps$1;
state.drafts = new Map();
state.assigned = new Map();
} // Set drafts use a Map object to track which of its values are drafted.
// And we don't need the "assigned" property, because Set objects have no keys.
else if (isSet(base)) {
traps = setTraps$1;
state.drafts = new Map();
}
var ref = Proxy.revocable(target, traps);
var revoke = ref.revoke;

@@ -470,17 +819,84 @@ var proxy = ref.proxy;

}
/**
* Object drafts
*/
var objectTraps = {
get: get$1,
get: function get(state, prop) {
if (prop === DRAFT_STATE) { return state; }
var drafts = state.drafts; // Check for existing draft in unmodified state.
has: function has(target, prop) {
return prop in source$1(target);
if (!state.modified && has(drafts, prop)) {
return drafts[prop];
}
var value = latest$2(state)[prop];
if (state.finalized || !isDraftable(value)) {
return value;
} // Check for existing draft in modified state.
if (state.modified) {
// Assigned values are never drafted. This catches any drafts we created, too.
if (value !== peek$1(state.base, prop)) { return value; } // Store drafts on the copy (when one exists).
drafts = state.copy;
}
return drafts[prop] = createProxy$1(value, state);
},
ownKeys: function ownKeys(target) {
return Reflect.ownKeys(source$1(target));
has: function has(state, prop) {
return prop in latest$2(state);
},
set: set$1,
deleteProperty: deleteProperty,
getOwnPropertyDescriptor: getOwnPropertyDescriptor,
ownKeys: function ownKeys(state) {
return Reflect.ownKeys(latest$2(state));
},
set: function set(state, prop, value) {
if (!state.modified) {
var baseValue = peek$1(state.base, prop); // Optimize based on value's truthiness. Truthy values are guaranteed to
// never be undefined, so we can avoid the `in` operator. Lastly, truthy
// values may be drafts, but falsy values are never drafts.
var isUnchanged = value ? is(baseValue, value) || value === state.drafts[prop] : is(baseValue, value) && prop in state.base;
if (isUnchanged) { return true; }
markChanged$1(state);
}
state.assigned[prop] = true;
state.copy[prop] = value;
return true;
},
deleteProperty: function deleteProperty(state, prop) {
// The `undefined` check is a fast path for pre-existing keys.
if (peek$1(state.base, prop) !== undefined || prop in state.base) {
state.assigned[prop] = false;
markChanged$1(state);
} else if (state.assigned[prop]) {
// if an originally not assigned property was deleted
delete state.assigned[prop];
}
if (state.copy) { delete state.copy[prop]; }
return true;
},
// Note: We never coerce `desc.value` into an Immer draft, because we can't make
// the same guarantee in ES5 mode.
getOwnPropertyDescriptor: function getOwnPropertyDescriptor(state, prop) {
var owner = latest$2(state);
var desc = Reflect.getOwnPropertyDescriptor(owner, prop);
if (desc) {
desc.writable = true;
desc.configurable = !Array.isArray(owner) || prop !== "length";
}
return desc;
},
defineProperty: function defineProperty() {

@@ -490,4 +906,4 @@ throw new Error("Object.defineProperty() cannot be used on an Immer draft"); // prettier-ignore

getPrototypeOf: function getPrototypeOf(target) {
return Object.getPrototypeOf(target.base);
getPrototypeOf: function getPrototypeOf(state) {
return Object.getPrototypeOf(state.base);
},

@@ -500,2 +916,6 @@

};
/**
* Array drafts
*/
var arrayTraps = {};

@@ -523,83 +943,100 @@ each(objectTraps, function (key, fn) {

return objectTraps.set.call(this, state[0], prop, value);
}; // returns the object we should be reading the current value from, which is base, until some change has been made
}; // Used by Map and Set drafts
function source$1(state) {
return state.copy || state.base;
} // Access a property without creating an Immer draft.
var reflectTraps = makeReflectTraps(["ownKeys", "has", "set", "deleteProperty", "defineProperty", "getOwnPropertyDescriptor", "preventExtensions", "isExtensible", "getPrototypeOf"]);
/**
* Map drafts
*/
var mapTraps$1 = makeTrapsForGetters(( obj$1 = {}, obj$1[DRAFT_STATE] = function (state) { return state; }, obj$1.size = function (state) { return latest$2(state).size; }, obj$1.has = function (state) { return function (key) { return latest$2(state).has(key); }; }, obj$1.set = function (state) { return function (key, value) {
var values = latest$2(state);
function peek$1(draft, prop) {
var state = draft[DRAFT_STATE];
var desc = Reflect.getOwnPropertyDescriptor(state ? source$1(state) : draft, prop);
return desc && desc.value;
}
if (!values.has(key) || values.get(key) !== value) {
markChanged$1(state);
state.assigned.set(key, true);
state.copy.set(key, value);
}
function get$1(state, prop) {
if (prop === DRAFT_STATE) { return state; }
var drafts = state.drafts; // Check for existing draft in unmodified state.
return state.draft;
}; }, obj$1.delete = function (state) { return function (key) {
if (latest$2(state).has(key)) {
markChanged$1(state);
state.assigned.set(key, false);
return state.copy.delete(key);
}
if (!state.modified && has(drafts, prop)) {
return drafts[prop];
}
return false;
}; }, obj$1.clear = function (state) { return function () {
markChanged$1(state);
state.assigned = new Map();
var value = source$1(state)[prop];
for (var i = 0, list = latest$2(state).keys(); i < list.length; i += 1) {
var key = list[i];
if (state.finalized || !isDraftable(value)) {
return value;
} // Check for existing draft in modified state.
state.assigned.set(key, false);
}
return state.copy.clear();
}; }, obj$1.forEach = function (state, _, receiver) { return function (cb, thisArg) { return latest$2(state).forEach(function (_, key, map) {
var value = receiver.get(key);
cb.call(thisArg, value, key, map);
}); }; }, obj$1.get = function (state) { return function (key) {
var drafts = state[state.modified ? "copy" : "drafts"];
if (state.modified) {
// Assigned values are never drafted. This catches any drafts we created, too.
if (value !== peek$1(state.base, prop)) { return value; } // Store drafts on the copy (when one exists).
if (drafts.has(key)) {
return drafts.get(key);
}
drafts = state.copy;
}
var value = latest$2(state).get(key);
return drafts[prop] = createProxy$1(value, state);
}
if (state.finalized || !isDraftable(value)) {
return value;
}
function set$1(state, prop, value) {
if (!state.modified) {
var baseValue = peek$1(state.base, prop); // Optimize based on value's truthiness. Truthy values are guaranteed to
// never be undefined, so we can avoid the `in` operator. Lastly, truthy
// values may be drafts, but falsy values are never drafts.
var draft = createProxy$1(value, state);
drafts.set(key, draft);
return draft;
}; }, obj$1.keys = function (state) { return function () { return latest$2(state).keys(); }; }, obj$1.values = iterateMapValues, obj$1.entries = iterateMapValues, obj$1[hasSymbol ? Symbol.iterator : "@@iterator"] = iterateMapValues, obj$1 ));
var iterateSetValues$1 = makeIterateSetValues(createProxy$1);
/**
* Set drafts
*/
var isUnchanged = value ? is(baseValue, value) || value === state.drafts[prop] : is(baseValue, value) && prop in state.base;
if (isUnchanged) { return true; }
markChanged$1(state);
}
var setTraps$1 = makeTrapsForGetters(( obj$1$1 = {}, obj$1$1[DRAFT_STATE] = function (state) { return state; }, obj$1$1.size = function (state) { return latest$2(state).size; }, obj$1$1.has = function (state) { return function (key) { return latest$2(state).has(key); }; }, obj$1$1.add = function (state) { return function (value) {
if (!latest$2(state).has(value)) {
markChanged$1(state);
state.copy.add(value);
}
state.assigned[prop] = true;
state.copy[prop] = value;
return true;
}
function deleteProperty(state, prop) {
// The `undefined` check is a fast path for pre-existing keys.
if (peek$1(state.base, prop) !== undefined || prop in state.base) {
state.assigned[prop] = false;
return state.draft;
}; }, obj$1$1.delete = function (state) { return function (value) {
markChanged$1(state);
} else if (state.assigned[prop]) {
// if an originally not assigned property was deleted
delete state.assigned[prop];
}
return state.copy.delete(value);
}; }, obj$1$1.clear = function (state) { return function () {
markChanged$1(state);
return state.copy.clear();
}; }, obj$1$1.forEach = function (state) { return function (cb, thisArg) {
var iterator = iterateSetValues$1(state)();
var result = iterator.next();
if (state.copy) { delete state.copy[prop]; }
return true;
} // Note: We never coerce `desc.value` into an Immer draft, because we can't make
// the same guarantee in ES5 mode.
while (!result.done) {
cb.call(thisArg, result.value, result.value, state.draft);
result = iterator.next();
}
}; }, obj$1$1.keys = iterateSetValues$1, obj$1$1.values = iterateSetValues$1, obj$1$1.entries = iterateSetValues$1, obj$1$1[hasSymbol ? Symbol.iterator : "@@iterator"] = iterateSetValues$1, obj$1$1 ));
/**
* Helpers
*/
// Retrieve the latest values of the draft.
function latest$2(state) {
return state.copy || state.base;
} // Access a property without creating an Immer draft.
function getOwnPropertyDescriptor(state, prop) {
var owner = source$1(state);
var desc = Reflect.getOwnPropertyDescriptor(owner, prop);
if (desc) {
desc.writable = true;
desc.configurable = !Array.isArray(owner) || prop !== "length";
}
return desc;
function peek$1(draft, prop) {
var state = draft[DRAFT_STATE];
var desc = Reflect.getOwnPropertyDescriptor(state ? latest$2(state) : draft, prop);
return desc && desc.value;
}

@@ -610,8 +1047,53 @@

state.modified = true;
state.copy = assign(shallowCopy(state.base), state.drafts);
state.drafts = null;
if (state.parent) { markChanged$1(state.parent); }
var base = state.base;
var drafts = state.drafts;
var parent = state.parent;
var copy = shallowCopy(base);
if (isSet(base)) {
// Note: The `drafts` property is preserved for Set objects, since
// we need to keep track of which values are drafted.
assignSet(copy, drafts);
} else {
// Merge nested drafts into the copy.
if (isMap(base)) { assignMap(copy, drafts); }else { assign(copy, drafts); }
state.drafts = null;
}
state.copy = copy;
if (parent) {
markChanged$1(parent);
}
}
}
/** Create traps that all use the `Reflect` API on the `latest(state)` */
function makeReflectTraps(names) {
return names.reduce(function (traps, name) {
traps[name] = function (state) {
var args = [], len = arguments.length - 1;
while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ];
return Reflect[name].apply(Reflect, [ latest$2(state) ].concat( args ));
};
return traps;
}, {});
}
function makeTrapsForGetters(getters) {
return Object.assign({}, reflectTraps, {
get: function get(state, prop, receiver) {
return getters.hasOwnProperty(prop) ? getters[prop](state, prop, receiver) : Reflect.get(state, prop, receiver);
},
setPrototypeOf: function setPrototypeOf(state) {
throw new Error("Object.setPrototypeOf() cannot be used on an Immer draft"); // prettier-ignore
}
});
}
var modernProxy = /*#__PURE__*/Object.freeze({

@@ -623,3 +1105,4 @@ willFinalize: willFinalize$1,

function generatePatches(state, basePath, patches, inversePatches) {
Array.isArray(state.base) ? generateArrayPatches(state, basePath, patches, inversePatches) : generateObjectPatches(state, basePath, patches, inversePatches);
var generatePatchesFn = Array.isArray(state.base) ? generateArrayPatches : isSet(state.base) ? generateSetPatches : generatePatchesFromAssigned;
generatePatchesFn(state, basePath, patches, inversePatches);
}

@@ -685,11 +1168,12 @@

}
}
} // This is used for both Map objects and normal objects.
function generateObjectPatches(state, basePath, patches, inversePatches) {
function generatePatchesFromAssigned(state, basePath, patches, inversePatches) {
var base = state.base;
var copy = state.copy;
each(state.assigned, function (key, assignedValue) {
var origValue = base[key];
var value = copy[key];
var op = !assignedValue ? "remove" : key in base ? "replace" : "add";
var origValue = get(base, key);
var value = get(copy, key);
var op = !assignedValue ? "remove" : has(base, key) ? "replace" : "add";
if (origValue === value && op === "replace") { return; }

@@ -720,2 +1204,50 @@ var path = basePath.concat(key);

function generateSetPatches(state, basePath, patches, inversePatches) {
var base = state.base;
var copy = state.copy;
var i = 0;
for (var i$1 = 0, list = base; i$1 < list.length; i$1 += 1) {
var value = list[i$1];
if (!copy.has(value)) {
var path = basePath.concat([i]);
patches.push({
op: "remove",
path: path,
value: value
});
inversePatches.unshift({
op: "add",
path: path,
value: value
});
}
i++;
}
i = 0;
for (var i$2 = 0, list$1 = copy; i$2 < list$1.length; i$2 += 1) {
var value$1 = list$1[i$2];
if (!base.has(value$1)) {
var path$1 = basePath.concat([i]);
patches.push({
op: "add",
path: path$1,
value: value$1
});
inversePatches.unshift({
op: "remove",
path: path$1,
value: value$1
});
}
i++;
}
}
var applyPatches = function (draft, patches) {

@@ -727,4 +1259,2 @@ for (var i$1 = 0, list = patches; i$1 < list.length; i$1 += 1) {

var op = patch.op;
var value = clone(patch.value); // used to clone patch to ensure original patch is not modified, see #411
if (!path.length) { throw new Error("Illegal state"); }

@@ -734,6 +1264,8 @@ var base = draft;

for (var i = 0; i < path.length - 1; i++) {
base = base[path[i]];
base = get(base, path[i]);
if (!base || typeof base !== "object") { throw new Error("Cannot apply patch, path doesn't resolve: " + path.join("/")); } // prettier-ignore
}
var value = clone(patch.value); // used to clone patch to ensure original patch is not modified, see #411
var key = path[path.length - 1];

@@ -743,13 +1275,10 @@

case "replace":
// if value is an object, then it's assigned by reference
// in the following add or remove ops, the value field inside the patch will also be modifyed
// so we use value from the cloned patch
base[key] = value;
break;
case "add":
if (Array.isArray(base)) {
// TODO: support "foo/-" paths for appending to an array
base.splice(key, 0, value);
if (isMap(base)) {
base.set(key, value);
} else if (isSet(base)) {
throw new Error('Sets cannot have "replace" patches.');
} else {
// if value is an object, then it's assigned by reference
// in the following add or remove ops, the value field inside the patch will also be modifyed
// so we use value from the cloned patch
base[key] = value;

@@ -760,11 +1289,14 @@ }

case "remove":
if (Array.isArray(base)) {
base.splice(key, 1);
} else {
delete base[key];
case "add":
if (isSet(base)) {
base.delete(patch.value);
}
Array.isArray(base) ? base.splice(key, 0, value) : isMap(base) ? base.set(key, value) : isSet(base) ? base.add(value) : base[key] = value;
break;
case "remove":
Array.isArray(base) ? base.splice(key, 1) : isMap(base) ? base.delete(key) : isSet(base) ? base.delete(patch.value) : delete base[key];
break;
default:

@@ -791,2 +1323,3 @@ throw new Error("Unsupported patch operation: " + op);

this.produce = this.produce.bind(this);
this.produceWithPatches = this.produceWithPatches.bind(this);
};

@@ -837,3 +1370,3 @@

if (result instanceof Promise) {
if (typeof Promise !== "undefined" && result instanceof Promise) {
return result.then(function (result) {

@@ -1014,13 +1547,13 @@ scope.usePatches(patchListener);

state.finalized = true;
this.finalizeTree(state.draft, path, scope);
this.finalizeTree(state.draft, path, scope); // We cannot really delete anything inside of a Set. We can only replace the whole Set.
if (this.onDelete) {
if (this.onDelete && !isSet(state.base)) {
// The `assigned` object is unreliable with ES5 drafts.
if (this.useProxies) {
var assigned = state.assigned;
for (var prop in assigned) {
if (!assigned[prop]) { this.onDelete(state, prop); }
}
each(assigned, function (prop, exists) {
if (!exists) { this$1.onDelete(state, prop); }
});
} else {
// TODO: Figure it out for Maps and Sets if we need to support ES5
var base = state.base;

@@ -1041,3 +1574,3 @@ var copy = state.copy;

if (this.autoFreeze && scope.canAutoFreeze) {
Object.freeze(state.copy);
freeze(state.copy, false);
}

@@ -1081,25 +1614,20 @@

var isDraftProp = !!state && parent === root;
var isSetMember = isSet(parent);
if (isDraft(value)) {
var path = isDraftProp && needPatches && !state.assigned[prop] ? rootPath.concat(prop) : null; // Drafts owned by `scope` are finalized here.
var path = isDraftProp && needPatches && !isSetMember && // Set objects are atomic since they have no keys.
!has(state.assigned, prop) // Skip deep patches for assigned keys.
? rootPath.concat(prop) : null; // Drafts owned by `scope` are finalized here.
value = this$1.finalize(value, path, scope); // Drafts from another scope must prevent auto-freezing.
value = this$1.finalize(value, path, scope);
replace(parent, prop, value); // Drafts from another scope must prevent auto-freezing.
if (isDraft(value)) {
scope.canAutoFreeze = false;
} // Preserve non-enumerable properties.
if (Array.isArray(parent) || isEnumerable(parent, prop)) {
parent[prop] = value;
} else {
Object.defineProperty(parent, prop, {
value: value
});
} // Unchanged drafts are never passed to the `onAssign` hook.
if (isDraftProp && value === state.base[prop]) { return; }
if (isDraftProp && value === get(state.base, prop)) { return; }
} // Unchanged draft properties are ignored.
else if (isDraftProp && is(value, state.base[prop])) {
else if (isDraftProp && is(value, get(state.base, prop))) {
return;

@@ -1112,3 +1640,3 @@ } // Search new objects for unfinalized drafts. Frozen objects should never contain drafts.

if (isDraftProp && this$1.onAssign) {
if (isDraftProp && this$1.onAssign && !isSetMember) {
this$1.onAssign(state, prop, value);

@@ -1126,6 +1654,25 @@ }

if (this.autoFreeze && !isDraft(value)) {
if (deep) { deepFreeze(value); }else { Object.freeze(value); }
freeze(value, deep);
}
};
function replace(parent, prop, value) {
if (isMap(parent)) {
parent.set(prop, value);
} else if (isSet(parent)) {
// In this case, the `prop` is actually a draft.
parent.delete(prop);
parent.add(value);
} else if (Array.isArray(parent) || isEnumerable(parent, prop)) {
// Preserve non-enumerable properties.
parent[prop] = value;
} else {
Object.defineProperty(parent, prop, {
value: value,
writable: true,
configurable: true
});
}
}
var immer = new Immer();

@@ -1132,0 +1679,0 @@ /**

2

dist/immer.umd.js

@@ -1,2 +0,2 @@

!function(e,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports):"function"==typeof define&&define.amd?define(["exports"],r):r((e=e||self).immer={})}(this,function(e){"use strict";var r,t="undefined"!=typeof Symbol?Symbol("immer-nothing"):((r={})["immer-nothing"]=!0,r),n="undefined"!=typeof Symbol&&Symbol.for?Symbol.for("immer-draftable"):"__$immer_draftable",o="undefined"!=typeof Symbol&&Symbol.for?Symbol.for("immer-state"):"__$immer_state";function i(e){return!!e&&!!e[o]}function a(e){return!!e&&(function(e){if(!e||"object"!=typeof e)return!1;if(Array.isArray(e))return!0;var r=Object.getPrototypeOf(e);return!r||r===Object.prototype}(e)||!!e[n]||!!e.constructor[n])}var f=Object.assign||function(e,r){for(var t in r)l(r,t)&&(e[t]=r[t]);return e},s="undefined"!=typeof Reflect&&Reflect.ownKeys?Reflect.ownKeys:void 0!==Object.getOwnPropertySymbols?function(e){return Object.getOwnPropertyNames(e).concat(Object.getOwnPropertySymbols(e))}:Object.getOwnPropertyNames;function c(e,r){if(void 0===r&&(r=!1),Array.isArray(e))return e.slice();var t=Object.create(Object.getPrototypeOf(e));return s(e).forEach(function(n){if(n!==o){var i=Object.getOwnPropertyDescriptor(e,n),a=i.value;if(i.get){if(!r)throw new Error("Immer drafts cannot have computed properties");a=i.get.call(e)}i.enumerable?t[n]=a:Object.defineProperty(t,n,{value:a,writable:!0,configurable:!0})}}),t}function u(e,r){if(Array.isArray(e))for(var t=0;t<e.length;t++)r(t,e[t],e);else s(e).forEach(function(t){return r(t,e[t],e)})}function p(e,r){var t=Object.getOwnPropertyDescriptor(e,r);return!!t&&t.enumerable}function l(e,r){return Object.prototype.hasOwnProperty.call(e,r)}function h(e,r){return e===r?0!==e||1/e==1/r:e!=e&&r!=r}function d(e){if(!a(e))return e;if(Array.isArray(e))return e.map(d);var r=Object.create(Object.getPrototypeOf(e));for(var t in e)r[t]=d(e[t]);return r}function y(e){if(a(e)&&!i(e)&&!Object.isFrozen(e))if(Object.freeze(e),Array.isArray(e))e.forEach(y);else for(var r in e)y(e[r])}var v=function(e){this.drafts=[],this.parent=e,this.canAutoFreeze=!0,this.patches=null};function b(e){e[o].revoke()}v.prototype.usePatches=function(e){e&&(this.patches=[],this.inversePatches=[],this.patchListener=e)},v.prototype.revoke=function(){this.leave(),this.drafts.forEach(b),this.drafts=null},v.prototype.leave=function(){this===v.current&&(v.current=this.parent)},v.current=null,v.enter=function(){return this.current=new v(this.current)};var g={};function m(e,r){var t=Array.isArray(e),n=A(e);u(n,function(r){!function(e,r,t){var n=g[r];n?n.enumerable=t:g[r]=n={configurable:!0,enumerable:t,get:function(){return function(e,r){E(e);var t=O(w(e),r);if(e.finalizing)return t;if(t===O(e.base,r)&&a(t))return j(e),e.copy[r]=m(t,e);return t}(this[o],r)},set:function(e){!function(e,r,t){if(E(e),e.assigned[r]=!0,!e.modified){if(h(t,O(w(e),r)))return;z(e),j(e)}e.copy[r]=t}(this[o],r,e)}};Object.defineProperty(e,r,n)}(n,r,t||p(e,r))});var i,f,s,c=r?r.scope:v.current;return i=n,f=o,s={scope:c,modified:!1,finalizing:!1,finalized:!1,assigned:{},parent:r,base:e,draft:n,copy:null,revoke:P,revoked:!1},Object.defineProperty(i,f,{value:s,enumerable:!1,writable:!0}),c.drafts.push(n),n}function P(){this.revoked=!0}function w(e){return e.copy||e.base}function O(e,r){var t=e[o];if(t&&!t.finalizing){t.finalizing=!0;var n=e[r];return t.finalizing=!1,n}return e[r]}function z(e){e.modified||(e.modified=!0,e.parent&&z(e.parent))}function j(e){e.copy||(e.copy=A(e.base))}function A(e){var r=e&&e[o];if(r){r.finalizing=!0;var t=c(r.draft,!0);return r.finalizing=!1,t}return c(e)}function E(e){if(!0===e.revoked)throw new Error("Cannot use a proxy that has been revoked. Did you pass an object from inside an immer function to an async process? "+JSON.stringify(w(e)))}function D(e){for(var r=e.length-1;r>=0;r--){var t=e[r][o];t.modified||(Array.isArray(t.base)?k(t)&&z(t):F(t)&&z(t))}}function F(e){for(var r=e.base,t=e.draft,n=Object.keys(t),i=n.length-1;i>=0;i--){var a=n[i],f=r[a];if(void 0===f&&!l(r,a))return!0;var s=t[a],c=s&&s[o];if(c?c.base!==f:!h(s,f))return!0}return n.length!==Object.keys(r).length}function k(e){var r=e.draft;if(r.length!==e.base.length)return!0;var t=Object.getOwnPropertyDescriptor(r,r.length-1);return!(!t||t.get)}var x=Object.freeze({willFinalize:function(e,r,t){e.drafts.forEach(function(e){e[o].finalizing=!0}),t?i(r)&&r[o].scope===e&&D(e.drafts):(e.patches&&function e(r){if(r&&"object"==typeof r){var t=r[o];if(t){var n=t.base,i=t.draft,a=t.assigned;if(Array.isArray(r)){if(k(t)){if(z(t),a.length=!0,i.length<n.length)for(var f=i.length;f<n.length;f++)a[f]=!1;else for(var s=n.length;s<i.length;s++)a[s]=!0;for(var c=0;c<i.length;c++)void 0===a[c]&&e(i[c])}}else Object.keys(i).forEach(function(r){void 0!==n[r]||l(n,r)?a[r]||e(i[r]):(a[r]=!0,z(t))}),Object.keys(n).forEach(function(e){void 0!==i[e]||l(i,e)||(a[e]=!1,z(t))})}}}(e.drafts[0]),D(e.drafts))},createProxy:m});function R(e,r){var t=r?r.scope:v.current,n={scope:t,modified:!1,finalized:!1,assigned:{},parent:r,base:e,draft:null,drafts:{},copy:null,revoke:null},o=Array.isArray(e)?Proxy.revocable([n],I):Proxy.revocable(n,S),i=o.revoke,a=o.proxy;return n.draft=a,n.revoke=i,t.drafts.push(a),a}var S={get:function(e,r){if(r===o)return e;var t=e.drafts;if(!e.modified&&l(t,r))return t[r];var n=N(e)[r];if(e.finalized||!a(n))return n;if(e.modified){if(n!==_(e.base,r))return n;t=e.copy}return t[r]=R(n,e)},has:function(e,r){return r in N(e)},ownKeys:function(e){return Reflect.ownKeys(N(e))},set:function(e,r,t){if(!e.modified){var n=_(e.base,r),o=t?h(n,t)||t===e.drafts[r]:h(n,t)&&r in e.base;if(o)return!0;T(e)}return e.assigned[r]=!0,e.copy[r]=t,!0},deleteProperty:function(e,r){void 0!==_(e.base,r)||r in e.base?(e.assigned[r]=!1,T(e)):e.assigned[r]&&delete e.assigned[r];e.copy&&delete e.copy[r];return!0},getOwnPropertyDescriptor:function(e,r){var t=N(e),n=Reflect.getOwnPropertyDescriptor(t,r);n&&(n.writable=!0,n.configurable=!Array.isArray(t)||"length"!==r);return n},defineProperty:function(){throw new Error("Object.defineProperty() cannot be used on an Immer draft")},getPrototypeOf:function(e){return Object.getPrototypeOf(e.base)},setPrototypeOf:function(){throw new Error("Object.setPrototypeOf() cannot be used on an Immer draft")}},I={};function N(e){return e.copy||e.base}function _(e,r){var t=e[o],n=Reflect.getOwnPropertyDescriptor(t?N(t):e,r);return n&&n.value}function T(e){e.modified||(e.modified=!0,e.copy=f(c(e.base),e.drafts),e.drafts=null,e.parent&&T(e.parent))}u(S,function(e,r){I[e]=function(){return arguments[0]=arguments[0][0],r.apply(this,arguments)}}),I.deleteProperty=function(e,r){if(isNaN(parseInt(r)))throw new Error("Immer only supports deleting array indices");return S.deleteProperty.call(this,e[0],r)},I.set=function(e,r,t){if("length"!==r&&isNaN(parseInt(r)))throw new Error("Immer only supports setting array indices and the 'length' property");return S.set.call(this,e[0],r,t)};var C=Object.freeze({willFinalize:function(){},createProxy:R});function U(e,r,t,n){Array.isArray(e.base)?function(e,r,t,n){var o,i,a=e.base,f=e.copy,s=e.assigned;f.length<a.length&&(a=(o=[f,a])[0],f=o[1],t=(i=[n,t])[0],n=i[1]);var c=f.length-a.length,u=0;for(;a[u]===f[u]&&u<a.length;)++u;var p=a.length;for(;p>u&&a[p-1]===f[p+c-1];)--p;for(var l=u;l<p;++l)if(s[l]&&f[l]!==a[l]){var h=r.concat([l]);t.push({op:"replace",path:h,value:f[l]}),n.push({op:"replace",path:h,value:a[l]})}for(var d=t.length,y=p+c-1;y>=p;--y){var v=r.concat([y]);t[d+y-p]={op:"add",path:v,value:f[y]},n.push({op:"remove",path:v})}}(e,r,t,n):function(e,r,t,n){var o=e.base,i=e.copy;u(e.assigned,function(e,a){var f=o[e],s=i[e],c=a?e in o?"replace":"add":"remove";if(f!==s||"replace"!==c){var u=r.concat(e);t.push("remove"===c?{op:c,path:u}:{op:c,path:u,value:s}),n.push("add"===c?{op:"remove",path:u}:"remove"===c?{op:"add",path:u,value:f}:{op:"replace",path:u,value:f})}})}(e,r,t,n)}var W=function(e,r){for(var t=0,n=r;t<n.length;t+=1){var o=n[t],i=o.path,a=o.op,f=d(o.value);if(!i.length)throw new Error("Illegal state");for(var s=e,c=0;c<i.length-1;c++)if(!(s=s[i[c]])||"object"!=typeof s)throw new Error("Cannot apply patch, path doesn't resolve: "+i.join("/"));var u=i[i.length-1];switch(a){case"replace":s[u]=f;break;case"add":Array.isArray(s)?s.splice(u,0,f):s[u]=f;break;case"remove":Array.isArray(s)?s.splice(u,1):delete s[u];break;default:throw new Error("Unsupported patch operation: "+a)}}return e};var K={useProxies:"undefined"!=typeof Proxy&&void 0!==Proxy.revocable&&"undefined"!=typeof Reflect,autoFreeze:"undefined"!=typeof process?"production"!==process.env.NODE_ENV:"verifyMinified"===function(){}.name,onAssign:null,onDelete:null,onCopy:null},M=function(e){f(this,K,e),this.setUseProxies(this.useProxies),this.produce=this.produce.bind(this)};M.prototype.produce=function(e,r,n){var o,i=this;if("function"==typeof e&&"function"!=typeof r){var f=r;r=e;var s=this;return function(e){var t=this;void 0===e&&(e=f);for(var n=[],o=arguments.length-1;o-- >0;)n[o]=arguments[o+1];return s.produce(e,function(e){return r.call.apply(r,[t,e].concat(n))})}}if("function"!=typeof r)throw new Error("The first or second argument to `produce` must be a function");if(void 0!==n&&"function"!=typeof n)throw new Error("The third argument to `produce` must be a function or undefined");if(a(e)){var c=v.enter(),u=this.createProxy(e),p=!0;try{o=r(u),p=!1}finally{p?c.revoke():c.leave()}return o instanceof Promise?o.then(function(e){return c.usePatches(n),i.processResult(e,c)},function(e){throw c.revoke(),e}):(c.usePatches(n),this.processResult(o,c))}if((o=r(e))!==t)return void 0===o&&(o=e),this.maybeFreeze(o,!0),o},M.prototype.produceWithPatches=function(e,r,t){var n,o,i=this;if("function"==typeof e)return function(r){for(var t=[],n=arguments.length-1;n-- >0;)t[n]=arguments[n+1];return i.produceWithPatches(r,function(r){return e.apply(void 0,[r].concat(t))})};if(t)throw new Error("A patch listener cannot be passed to produceWithPatches");return[this.produce(e,r,function(e,r){n=e,o=r}),n,o]},M.prototype.createDraft=function(e){if(!a(e))throw new Error("First argument to `createDraft` must be a plain object, an array, or an immerable object");var r=v.enter(),t=this.createProxy(e);return t[o].isManual=!0,r.leave(),t},M.prototype.finishDraft=function(e,r){var t=e&&e[o];if(!t||!t.isManual)throw new Error("First argument to `finishDraft` must be a draft returned by `createDraft`");if(t.finalized)throw new Error("The given draft is already finalized");var n=t.scope;return n.usePatches(r),this.processResult(void 0,n)},M.prototype.setAutoFreeze=function(e){this.autoFreeze=e},M.prototype.setUseProxies=function(e){this.useProxies=e,f(this,e?C:x)},M.prototype.applyPatches=function(e,r){var t;for(t=r.length-1;t>=0;t--){var n=r[t];if(0===n.path.length&&"replace"===n.op){e=n.value;break}}return i(e)?W(e,r):this.produce(e,function(e){return W(e,r.slice(t+1))})},M.prototype.processResult=function(e,r){var n=r.drafts[0],i=void 0!==e&&e!==n;if(this.willFinalize(r,e,i),i){if(n[o].modified)throw r.revoke(),new Error("An immer producer returned a new value *and* modified its draft. Either return a new value *or* modify the draft.");a(e)&&(e=this.finalize(e,null,r),this.maybeFreeze(e)),r.patches&&(r.patches.push({op:"replace",path:[],value:e}),r.inversePatches.push({op:"replace",path:[],value:n[o].base}))}else e=this.finalize(n,[],r);return r.revoke(),r.patches&&r.patchListener(r.patches,r.inversePatches),e!==t?e:void 0},M.prototype.finalize=function(e,r,t){var n=this,i=e[o];if(!i)return Object.isFrozen(e)?e:this.finalizeTree(e,null,t);if(i.scope!==t)return e;if(!i.modified)return this.maybeFreeze(i.base,!0),i.base;if(!i.finalized){if(i.finalized=!0,this.finalizeTree(i.draft,r,t),this.onDelete)if(this.useProxies){var a=i.assigned;for(var f in a)a[f]||this.onDelete(i,f)}else{var s=i.base,c=i.copy;u(s,function(e){l(c,e)||n.onDelete(i,e)})}this.onCopy&&this.onCopy(i),this.autoFreeze&&t.canAutoFreeze&&Object.freeze(i.copy),r&&t.patches&&U(i,r,t.patches,t.inversePatches)}return i.copy},M.prototype.finalizeTree=function(e,r,t){var n=this,f=e[o];f&&(this.useProxies||(f.copy=c(f.draft,!0)),e=f.copy);var s=!!r&&!!t.patches,l=function(o,c,d){if(c===d)throw Error("Immer forbids circular references");var y=!!f&&d===e;if(i(c)){var v=y&&s&&!f.assigned[o]?r.concat(o):null;if(i(c=n.finalize(c,v,t))&&(t.canAutoFreeze=!1),Array.isArray(d)||p(d,o)?d[o]=c:Object.defineProperty(d,o,{value:c}),y&&c===f.base[o])return}else{if(y&&h(c,f.base[o]))return;a(c)&&!Object.isFrozen(c)&&(u(c,l),n.maybeFreeze(c))}y&&n.onAssign&&n.onAssign(f,o,c)};return u(e,l),e},M.prototype.maybeFreeze=function(e,r){void 0===r&&(r=!1),this.autoFreeze&&!i(e)&&(r?y(e):Object.freeze(e))};var L=new M,$=L.produce,J=L.produceWithPatches.bind(L),V=L.setAutoFreeze.bind(L),q=L.setUseProxies.bind(L),B=L.applyPatches.bind(L),G=L.createDraft.bind(L),H=L.finishDraft.bind(L);e.Immer=M,e.applyPatches=B,e.createDraft=G,e.default=$,e.finishDraft=H,e.immerable=n,e.isDraft=i,e.isDraftable=a,e.nothing=t,e.original=function(e){if(e&&e[o])return e[o].base},e.produce=$,e.produceWithPatches=J,e.setAutoFreeze=V,e.setUseProxies=q,Object.defineProperty(e,"__esModule",{value:!0})});
!function(e,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports):"function"==typeof define&&define.amd?define(["exports"],r):r((e=e||self).immer={})}(this,function(e){"use strict";var r,t="undefined"!=typeof Symbol?Symbol("immer-nothing"):((r={})["immer-nothing"]=!0,r),n="undefined"!=typeof Symbol&&Symbol.for?Symbol.for("immer-draftable"):"__$immer_draftable",o="undefined"!=typeof Symbol&&Symbol.for?Symbol.for("immer-state"):"__$immer_state";function i(e){return!!e&&!!e[o]}function a(e){return!!e&&(function(e){if(!e||"object"!=typeof e)return!1;if(Array.isArray(e))return!0;var r=Object.getPrototypeOf(e);return!r||r===Object.prototype}(e)||!!e[n]||!!e.constructor[n]||g(e)||w(e))}function u(e){if(e&&e[o])return e[o].base}var f=Object.assign||function(e){for(var r=[],t=arguments.length-1;t-- >0;)r[t]=arguments[t+1];return r.forEach(function(r){return Object.keys(r).forEach(function(t){return e[t]=r[t]})}),e},c="undefined"!=typeof Reflect&&Reflect.ownKeys?Reflect.ownKeys:void 0!==Object.getOwnPropertySymbols?function(e){return Object.getOwnPropertyNames(e).concat(Object.getOwnPropertySymbols(e))}:Object.getOwnPropertyNames;function s(e,r){if(void 0===r&&(r=!1),Array.isArray(e))return e.slice();if(g(e))return new Map(e);if(w(e))return new Set(e);var t=Object.create(Object.getPrototypeOf(e));return c(e).forEach(function(n){if(n!==o){var i=Object.getOwnPropertyDescriptor(e,n),a=i.value;if(i.get){if(!r)throw new Error("Immer drafts cannot have computed properties");a=i.get.call(e)}i.enumerable?t[n]=a:Object.defineProperty(t,n,{value:a,writable:!0,configurable:!0})}}),t}function p(e,r){Array.isArray(e)||g(e)||w(e)?e.forEach(function(t,n){return r(n,t,e)}):c(e).forEach(function(t){return r(t,e[t],e)})}function l(e,r){var t=Object.getOwnPropertyDescriptor(e,r);return!!t&&t.enumerable}function d(e,r){return g(e)?e.has(r):Object.prototype.hasOwnProperty.call(e,r)}function h(e,r){return g(e)?e.get(r):e[r]}function y(e,r){return e===r?0!==e||1/e==1/r:e!=e&&r!=r}var v="undefined"!=typeof Symbol,b="undefined"!=typeof Map;function g(e){return b&&e instanceof Map}var m="undefined"!=typeof Set;function w(e){return m&&e instanceof Set}function P(e){var r,t;return(r={})[Symbol.iterator]=function(){return t},r.next=e,t=r}function O(e,r,t){var n="values"!==r;return function(){var r=j(e)[Symbol.iterator]();return P(function(){var e=r.next();if(!e.done){var o=e.value[0],i=t.get(o);e.value=n?[o,i]:i}return e})}}function z(e){return function(r,t){var n="entries"===t;return function(){var t=j(r)[Symbol.iterator]();return P(function(){var o=t.next();if(!o.done){var i=function(r,t){var n=u(t)||t,o=r.drafts.get(n);if(!o){if(r.finalized||!a(t)||r.finalizing)return t;o=e(t,r),r.drafts.set(n,o),r.modified&&r.copy.add(o)}return o}(r,o.value);o.value=n?[i,i]:i}return o})}}}function j(e){return e.copy||e.base}function E(e){if(!a(e))return e;if(Array.isArray(e))return e.map(E);if(g(e))return new Map(e);if(w(e))return new Set(e);var r=Object.create(Object.getPrototypeOf(e));for(var t in e)r[t]=E(e[t]);return r}function A(e,r){void 0===r&&(r=!1),!a(e)||i(e)||Object.isFrozen(e)||(w(e)?e.add=e.clear=e.delete=k:g(e)&&(e.set=e.clear=e.delete=k),Object.freeze(e),r&&p(e,function(e,r){return A(r,!0)}))}function k(){throw new Error("This object has been frozen and should not be mutated")}var x=function(e){this.drafts=[],this.parent=e,this.canAutoFreeze=!0,this.patches=null};function D(e){e[o].revoke()}function S(e,r){var t,n=Array.isArray(e),i=_(e);g(e)?(t=i,Object.defineProperties(t,W),v&&Object.defineProperty(t,Symbol.iterator,$(O))):w(e)?function(e){Object.defineProperties(e,K),v&&Object.defineProperty(e,Symbol.iterator,$(C))}(i):p(i,function(r){!function(e,r,t){var n=T[r];n?n.enumerable=t:T[r]=n={configurable:!0,enumerable:t,get:function(){return function(e,r){J(e);var t=R(M(e),r);if(e.finalizing)return t;if(t===R(e.base,r)&&a(t))return N(e),e.copy[r]=S(t,e);return t}(this[o],r)},set:function(e){!function(e,r,t){if(J(e),e.assigned[r]=!0,!e.modified){if(y(t,R(M(e),r)))return;I(e),N(e)}e.copy[r]=t}(this[o],r,e)}};Object.defineProperty(e,r,n)}(i,r,n||l(e,r))});var u=r?r.scope:x.current,f={scope:u,modified:!1,finalizing:!1,finalized:!1,assigned:g(e)?new Map:{},parent:r,base:e,draft:i,drafts:w(e)?new Map:null,copy:null,revoke:F,revoked:!1};return function(e,r,t){Object.defineProperty(e,r,{value:t,enumerable:!1,writable:!0})}(i,o,f),u.drafts.push(i),i}function F(){this.revoked=!0}function M(e){return e.copy||e.base}function R(e,r){var t=e[o];if(t&&!t.finalizing){t.finalizing=!0;var n=e[r];return t.finalizing=!1,n}return e[r]}function I(e){e.modified||(e.modified=!0,e.parent&&I(e.parent))}function N(e){e.copy||(e.copy=_(e.base))}function _(e){var r=e&&e[o];if(r){r.finalizing=!0;var t=s(r.draft,!0);return r.finalizing=!1,t}return s(e)}x.prototype.usePatches=function(e){e&&(this.patches=[],this.inversePatches=[],this.patchListener=e)},x.prototype.revoke=function(){this.leave(),this.drafts.forEach(D),this.drafts=null},x.prototype.leave=function(){this===x.current&&(x.current=this.parent)},x.current=null,x.enter=function(){return this.current=new x(this.current)};var T={};var W=U({size:function(e){return M(e).size},has:function(e){return function(r){return M(e).has(r)}},set:function(e){return function(r,t){return M(e).get(r)!==t&&(N(e),I(e),e.assigned.set(r,!0),e.copy.set(r,t)),e.draft}},delete:function(e){return function(r){return N(e),I(e),e.assigned.set(r,!1),e.copy.delete(r),!1}},clear:function(e){return function(){e.copy||N(e),I(e),e.assigned=new Map;for(var r=0,t=M(e).keys();r<t.length;r+=1){var n=t[r];e.assigned.set(n,!1)}return e.copy.clear()}},forEach:function(e,r,t){return function(r){M(e).forEach(function(e,n,o){r(t.get(n),n,o)})}},get:function(e){return function(r){var t=M(e).get(r);if(e.finalizing||e.finalized||!a(t))return t;if(t!==e.base.get(r))return t;var n=S(t,e);return N(e),e.copy.set(r,n),n}},keys:function(e){return function(){return M(e).keys()}},values:O,entries:O});var C=z(S),K=U({size:function(e){return M(e).size},add:function(e){return function(r){return M(e).has(r)||(I(e),e.copy||N(e),e.copy.add(r)),e.draft}},delete:function(e){return function(r){return I(e),e.copy||N(e),e.copy.delete(r)}},has:function(e){return function(r){return M(e).has(r)}},clear:function(e){return function(){return I(e),e.copy||N(e),e.copy.clear()}},keys:C,entries:C,values:C,forEach:function(e){return function(r,t){for(var n=C(e)(),o=n.next();!o.done;)r.call(t,o.value,o.value,e.draft),o=n.next()}}});function U(e){return Object.keys(e).reduce(function(r,t){var n="size"===t?L:$;return r[t]=n(e[t],t),r},{})}function L(e){return{get:function(){var r=this[o];return J(r),e(r)}}}function $(e,r){return{get:function(){return function(){for(var t=[],n=arguments.length;n--;)t[n]=arguments[n];var i=this[o];return J(i),e(i,r,i.draft).apply(void 0,t)}}}}function J(e){if(!0===e.revoked)throw new Error("Cannot use a proxy that has been revoked. Did you pass an object from inside an immer function to an async process? "+JSON.stringify(M(e)))}function V(e){for(var r=e.length-1;r>=0;r--){var t=e[r][o];t.modified||(Array.isArray(t.base)?B(t)&&I(t):g(t.base)?G(t)&&I(t):w(t.base)?H(t)&&I(t):q(t)&&I(t))}}function q(e){for(var r=e.base,t=e.draft,n=Object.keys(t),i=n.length-1;i>=0;i--){var a=n[i],u=r[a];if(void 0===u&&!d(r,a))return!0;var f=t[a],c=f&&f[o];if(c?c.base!==u:!y(f,u))return!0}return n.length!==Object.keys(r).length}function B(e){var r=e.draft;if(r.length!==e.base.length)return!0;var t=Object.getOwnPropertyDescriptor(r,r.length-1);return!(!t||t.get)}function G(e){var r=e.base,t=e.draft;if(r.size!==t.size)return!0;var n=!1;return t.forEach(function(e,t){n||(n=a(e)?e.modified:e!==r.get(t))}),n}function H(e){var r=e.base,t=e.draft;if(r.size!==t.size)return!0;var n=!1;return t.forEach(function(e,t){n||(n=a(e)?e.modified:!r.has(t))}),n}var Q,X,Y=Object.freeze({willFinalize:function(e,r,t){e.drafts.forEach(function(e){e[o].finalizing=!0}),t?i(r)&&r[o].scope===e&&V(e.drafts):(e.patches&&function e(r){if(r&&"object"==typeof r){var t=r[o];if(t){var n=t.base,i=t.draft,a=t.assigned;if(Array.isArray(r)){if(B(t)){if(I(t),a.length=!0,i.length<n.length)for(var u=i.length;u<n.length;u++)a[u]=!1;else for(var f=n.length;f<i.length;f++)a[f]=!0;for(var c=0;c<i.length;c++)void 0===a[c]&&e(i[c])}}else Object.keys(i).forEach(function(r){void 0!==n[r]||d(n,r)?a[r]||e(i[r]):(a[r]=!0,I(t))}),Object.keys(n).forEach(function(e){void 0!==i[e]||d(i,e)||(a[e]=!1,I(t))})}}}(e.drafts[0]),V(e.drafts))},createProxy:S});function Z(e,r){var t=r?r.scope:x.current,n={scope:t,modified:!1,finalized:!1,assigned:{},parent:r,base:e,draft:null,drafts:{},copy:null,revoke:null},o=n,i=ee;Array.isArray(e)?(o=[n],i=re):g(e)?(i=ne,n.drafts=new Map,n.assigned=new Map):w(e)&&(i=ie,n.drafts=new Map);var a=Proxy.revocable(o,i),u=a.revoke,f=a.proxy;return n.draft=f,n.revoke=u,t.drafts.push(f),f}var ee={get:function(e,r){if(r===o)return e;var t=e.drafts;if(!e.modified&&d(t,r))return t[r];var n=ae(e)[r];if(e.finalized||!a(n))return n;if(e.modified){if(n!==ue(e.base,r))return n;t=e.copy}return t[r]=Z(n,e)},has:function(e,r){return r in ae(e)},ownKeys:function(e){return Reflect.ownKeys(ae(e))},set:function(e,r,t){if(!e.modified){var n=ue(e.base,r);if(t?y(n,t)||t===e.drafts[r]:y(n,t)&&r in e.base)return!0;fe(e)}return e.assigned[r]=!0,e.copy[r]=t,!0},deleteProperty:function(e,r){return void 0!==ue(e.base,r)||r in e.base?(e.assigned[r]=!1,fe(e)):e.assigned[r]&&delete e.assigned[r],e.copy&&delete e.copy[r],!0},getOwnPropertyDescriptor:function(e,r){var t=ae(e),n=Reflect.getOwnPropertyDescriptor(t,r);return n&&(n.writable=!0,n.configurable=!Array.isArray(t)||"length"!==r),n},defineProperty:function(){throw new Error("Object.defineProperty() cannot be used on an Immer draft")},getPrototypeOf:function(e){return Object.getPrototypeOf(e.base)},setPrototypeOf:function(){throw new Error("Object.setPrototypeOf() cannot be used on an Immer draft")}},re={};p(ee,function(e,r){re[e]=function(){return arguments[0]=arguments[0][0],r.apply(this,arguments)}}),re.deleteProperty=function(e,r){if(isNaN(parseInt(r)))throw new Error("Immer only supports deleting array indices");return ee.deleteProperty.call(this,e[0],r)},re.set=function(e,r,t){if("length"!==r&&isNaN(parseInt(r)))throw new Error("Immer only supports setting array indices and the 'length' property");return ee.set.call(this,e[0],r,t)};var te=["ownKeys","has","set","deleteProperty","defineProperty","getOwnPropertyDescriptor","preventExtensions","isExtensible","getPrototypeOf"].reduce(function(e,r){return e[r]=function(e){for(var t=[],n=arguments.length-1;n-- >0;)t[n]=arguments[n+1];return Reflect[r].apply(Reflect,[ae(e)].concat(t))},e},{}),ne=ce(((Q={})[o]=function(e){return e},Q.size=function(e){return ae(e).size},Q.has=function(e){return function(r){return ae(e).has(r)}},Q.set=function(e){return function(r,t){var n=ae(e);return n.has(r)&&n.get(r)===t||(fe(e),e.assigned.set(r,!0),e.copy.set(r,t)),e.draft}},Q.delete=function(e){return function(r){return!!ae(e).has(r)&&(fe(e),e.assigned.set(r,!1),e.copy.delete(r))}},Q.clear=function(e){return function(){fe(e),e.assigned=new Map;for(var r=0,t=ae(e).keys();r<t.length;r+=1){var n=t[r];e.assigned.set(n,!1)}return e.copy.clear()}},Q.forEach=function(e,r,t){return function(r,n){return ae(e).forEach(function(e,o,i){var a=t.get(o);r.call(n,a,o,i)})}},Q.get=function(e){return function(r){var t=e[e.modified?"copy":"drafts"];if(t.has(r))return t.get(r);var n=ae(e).get(r);if(e.finalized||!a(n))return n;var o=Z(n,e);return t.set(r,o),o}},Q.keys=function(e){return function(){return ae(e).keys()}},Q.values=O,Q.entries=O,Q[v?Symbol.iterator:"@@iterator"]=O,Q)),oe=z(Z),ie=ce(((X={})[o]=function(e){return e},X.size=function(e){return ae(e).size},X.has=function(e){return function(r){return ae(e).has(r)}},X.add=function(e){return function(r){return ae(e).has(r)||(fe(e),e.copy.add(r)),e.draft}},X.delete=function(e){return function(r){return fe(e),e.copy.delete(r)}},X.clear=function(e){return function(){return fe(e),e.copy.clear()}},X.forEach=function(e){return function(r,t){for(var n=oe(e)(),o=n.next();!o.done;)r.call(t,o.value,o.value,e.draft),o=n.next()}},X.keys=oe,X.values=oe,X.entries=oe,X[v?Symbol.iterator:"@@iterator"]=oe,X));function ae(e){return e.copy||e.base}function ue(e,r){var t=e[o],n=Reflect.getOwnPropertyDescriptor(t?ae(t):e,r);return n&&n.value}function fe(e){if(!e.modified){e.modified=!0;var r=e.base,t=e.drafts,n=e.parent,o=s(r);w(r)?(i=o,t.forEach(function(e){var r=u(e);r&&i.delete(r),i.add(e)})):(g(r)?function(e,r){r.forEach(function(r,t){return e.set(t,r)})}(o,t):f(o,t),e.drafts=null),e.copy=o,n&&fe(n)}var i}function ce(e){return Object.assign({},te,{get:function(r,t,n){return e.hasOwnProperty(t)?e[t](r,t,n):Reflect.get(r,t,n)},setPrototypeOf:function(e){throw new Error("Object.setPrototypeOf() cannot be used on an Immer draft")}})}var se=Object.freeze({willFinalize:function(){},createProxy:Z});function pe(e,r,t,n){var o,i,a=e.base,u=e.copy,f=e.assigned;u.length<a.length&&(a=(o=[u,a])[0],u=o[1],t=(i=[n,t])[0],n=i[1]);for(var c=u.length-a.length,s=0;a[s]===u[s]&&s<a.length;)++s;for(var p=a.length;p>s&&a[p-1]===u[p+c-1];)--p;for(var l=s;l<p;++l)if(f[l]&&u[l]!==a[l]){var d=r.concat([l]);t.push({op:"replace",path:d,value:u[l]}),n.push({op:"replace",path:d,value:a[l]})}for(var h=t.length,y=p+c-1;y>=p;--y){var v=r.concat([y]);t[h+y-p]={op:"add",path:v,value:u[y]},n.push({op:"remove",path:v})}}function le(e,r,t,n){var o=e.base,i=e.copy;p(e.assigned,function(e,a){var u=h(o,e),f=h(i,e),c=a?d(o,e)?"replace":"add":"remove";if(u!==f||"replace"!==c){var s=r.concat(e);t.push("remove"===c?{op:c,path:s}:{op:c,path:s,value:f}),n.push("add"===c?{op:"remove",path:s}:"remove"===c?{op:"add",path:s,value:u}:{op:"replace",path:s,value:u})}})}function de(e,r,t,n){for(var o=e.base,i=e.copy,a=0,u=0,f=o;u<f.length;u+=1){var c=f[u];if(!i.has(c)){var s=r.concat([a]);t.push({op:"remove",path:s,value:c}),n.unshift({op:"add",path:s,value:c})}a++}a=0;for(var p=0,l=i;p<l.length;p+=1){var d=l[p];if(!o.has(d)){var h=r.concat([a]);t.push({op:"add",path:h,value:d}),n.unshift({op:"remove",path:h,value:d})}a++}}var he=function(e,r){for(var t=0,n=r;t<n.length;t+=1){var o=n[t],i=o.path,a=o.op;if(!i.length)throw new Error("Illegal state");for(var u=e,f=0;f<i.length-1;f++)if(!(u=h(u,i[f]))||"object"!=typeof u)throw new Error("Cannot apply patch, path doesn't resolve: "+i.join("/"));var c=E(o.value),s=i[i.length-1];switch(a){case"replace":if(g(u))u.set(s,c);else{if(w(u))throw new Error('Sets cannot have "replace" patches.');u[s]=c}break;case"add":w(u)&&u.delete(o.value),Array.isArray(u)?u.splice(s,0,c):g(u)?u.set(s,c):w(u)?u.add(c):u[s]=c;break;case"remove":Array.isArray(u)?u.splice(s,1):g(u)?u.delete(s):w(u)?u.delete(o.value):delete u[s];break;default:throw new Error("Unsupported patch operation: "+a)}}return e};var ye={useProxies:"undefined"!=typeof Proxy&&void 0!==Proxy.revocable&&"undefined"!=typeof Reflect,autoFreeze:"undefined"!=typeof process?"production"!==process.env.NODE_ENV:"verifyMinified"===function(){}.name,onAssign:null,onDelete:null,onCopy:null},ve=function(e){f(this,ye,e),this.setUseProxies(this.useProxies),this.produce=this.produce.bind(this),this.produceWithPatches=this.produceWithPatches.bind(this)};ve.prototype.produce=function(e,r,n){var o,i=this;if("function"==typeof e&&"function"!=typeof r){var u=r;r=e;var f=this;return function(e){var t=this;void 0===e&&(e=u);for(var n=[],o=arguments.length-1;o-- >0;)n[o]=arguments[o+1];return f.produce(e,function(e){return r.call.apply(r,[t,e].concat(n))})}}if("function"!=typeof r)throw new Error("The first or second argument to `produce` must be a function");if(void 0!==n&&"function"!=typeof n)throw new Error("The third argument to `produce` must be a function or undefined");if(a(e)){var c=x.enter(),s=this.createProxy(e),p=!0;try{o=r(s),p=!1}finally{p?c.revoke():c.leave()}return"undefined"!=typeof Promise&&o instanceof Promise?o.then(function(e){return c.usePatches(n),i.processResult(e,c)},function(e){throw c.revoke(),e}):(c.usePatches(n),this.processResult(o,c))}if((o=r(e))!==t)return void 0===o&&(o=e),this.maybeFreeze(o,!0),o},ve.prototype.produceWithPatches=function(e,r,t){var n,o,i=this;if("function"==typeof e)return function(r){for(var t=[],n=arguments.length-1;n-- >0;)t[n]=arguments[n+1];return i.produceWithPatches(r,function(r){return e.apply(void 0,[r].concat(t))})};if(t)throw new Error("A patch listener cannot be passed to produceWithPatches");return[this.produce(e,r,function(e,r){n=e,o=r}),n,o]},ve.prototype.createDraft=function(e){if(!a(e))throw new Error("First argument to `createDraft` must be a plain object, an array, or an immerable object");var r=x.enter(),t=this.createProxy(e);return t[o].isManual=!0,r.leave(),t},ve.prototype.finishDraft=function(e,r){var t=e&&e[o];if(!t||!t.isManual)throw new Error("First argument to `finishDraft` must be a draft returned by `createDraft`");if(t.finalized)throw new Error("The given draft is already finalized");var n=t.scope;return n.usePatches(r),this.processResult(void 0,n)},ve.prototype.setAutoFreeze=function(e){this.autoFreeze=e},ve.prototype.setUseProxies=function(e){this.useProxies=e,f(this,e?se:Y)},ve.prototype.applyPatches=function(e,r){var t;for(t=r.length-1;t>=0;t--){var n=r[t];if(0===n.path.length&&"replace"===n.op){e=n.value;break}}return i(e)?he(e,r):this.produce(e,function(e){return he(e,r.slice(t+1))})},ve.prototype.processResult=function(e,r){var n=r.drafts[0],i=void 0!==e&&e!==n;if(this.willFinalize(r,e,i),i){if(n[o].modified)throw r.revoke(),new Error("An immer producer returned a new value *and* modified its draft. Either return a new value *or* modify the draft.");a(e)&&(e=this.finalize(e,null,r),this.maybeFreeze(e)),r.patches&&(r.patches.push({op:"replace",path:[],value:e}),r.inversePatches.push({op:"replace",path:[],value:n[o].base}))}else e=this.finalize(n,[],r);return r.revoke(),r.patches&&r.patchListener(r.patches,r.inversePatches),e!==t?e:void 0},ve.prototype.finalize=function(e,r,t){var n=this,i=e[o];if(!i)return Object.isFrozen(e)?e:this.finalizeTree(e,null,t);if(i.scope!==t)return e;if(!i.modified)return this.maybeFreeze(i.base,!0),i.base;if(!i.finalized){if(i.finalized=!0,this.finalizeTree(i.draft,r,t),this.onDelete&&!w(i.base))if(this.useProxies){p(i.assigned,function(e,r){r||n.onDelete(i,e)})}else{var a=i.base,u=i.copy;p(a,function(e){d(u,e)||n.onDelete(i,e)})}this.onCopy&&this.onCopy(i),this.autoFreeze&&t.canAutoFreeze&&A(i.copy,!1),r&&t.patches&&function(e,r,t,n){(Array.isArray(e.base)?pe:w(e.base)?de:le)(e,r,t,n)}(i,r,t.patches,t.inversePatches)}return i.copy},ve.prototype.finalizeTree=function(e,r,t){var n=this,u=e[o];u&&(this.useProxies||(u.copy=s(u.draft,!0)),e=u.copy);var f=!!r&&!!t.patches,c=function(o,s,v){if(s===v)throw Error("Immer forbids circular references");var b=!!u&&v===e,m=w(v);if(i(s)){var P=b&&f&&!m&&!d(u.assigned,o)?r.concat(o):null;if(function(e,r,t){g(e)?e.set(r,t):w(e)?(e.delete(r),e.add(t)):Array.isArray(e)||l(e,r)?e[r]=t:Object.defineProperty(e,r,{value:t,writable:!0,configurable:!0})}(v,o,s=n.finalize(s,P,t)),i(s)&&(t.canAutoFreeze=!1),b&&s===h(u.base,o))return}else{if(b&&y(s,h(u.base,o)))return;a(s)&&!Object.isFrozen(s)&&(p(s,c),n.maybeFreeze(s))}b&&n.onAssign&&!m&&n.onAssign(u,o,s)};return p(e,c),e},ve.prototype.maybeFreeze=function(e,r){void 0===r&&(r=!1),this.autoFreeze&&!i(e)&&A(e,r)};var be=new ve,ge=be.produce,me=be.produceWithPatches.bind(be),we=be.setAutoFreeze.bind(be),Pe=be.setUseProxies.bind(be),Oe=be.applyPatches.bind(be),ze=be.createDraft.bind(be),je=be.finishDraft.bind(be);e.Immer=ve,e.applyPatches=Oe,e.createDraft=ze,e.default=ge,e.finishDraft=je,e.immerable=n,e.isDraft=i,e.isDraftable=a,e.nothing=t,e.original=u,e.produce=ge,e.produceWithPatches=me,e.setAutoFreeze=we,e.setUseProxies=Pe,Object.defineProperty(e,"__esModule",{value:!0})});
//# sourceMappingURL=immer.umd.js.map
{
"name": "immer",
"version": "4.0.2",
"description": "Create your next immutable state by mutating the current one",
"main": "dist/immer.js",
"umd:main": "dist/immer.umd.js",
"unpkg": "dist/immer.umd.js",
"jsdelivr": "dist/immer.umd.js",
"module": "dist/immer.module.js",
"jsnext:main": "dist/immer.module.js",
"react-native": "dist/immer.module.js",
"types": "./dist/immer.d.ts",
"scripts": {
"test": "jest",
"test:perf": "NODE_ENV=production yarn-or-npm build && cd __performance_tests__ && babel-node add-data.js && babel-node todo.js && babel-node incremental.js",
"test:flow": "yarn-or-npm flow check __tests__/flow",
"test:dts": "tsc -p __tests__/tsconfig.json --noEmit",
"watch": "jest --watch",
"coveralls": "jest --coverage && cat ./coverage/lcov.info | ./node_modules/.bin/coveralls && rm -rf ./coverage",
"build": "rimraf dist/ && yarn-or-npm bili && yarn-or-npm typed",
"typed": "cpx 'src/immer.{d.ts,js.flow}' dist -v",
"publish-docs": "cd website && GIT_USER=mweststrate USE_SSH=true yarn run publish-gh-pages",
"start": "cd website && yarn start"
},
"husky": {
"hooks": {
"pre-commit": "pretty-quick --staged"
}
},
"repository": {
"type": "git",
"url": "https://github.com/immerjs/immer.git"
},
"keywords": [
"immutable",
"mutable",
"copy-on-write"
],
"author": "Michel Weststrate",
"license": "MIT",
"bugs": {
"url": "https://github.com/immerjs/immer/issues"
},
"homepage": "https://github.com/immerjs/immer#readme",
"files": [
"dist",
"src"
],
"devDependencies": {
"@babel/cli": "^7.2.3",
"@babel/core": "^7.3.4",
"@babel/node": "^7.2.2",
"@babel/plugin-external-helpers": "^7.2.0",
"@babel/preset-env": "^7.3.4",
"@types/jest": "^24.0.11",
"babel-jest": "^24.4.0",
"babel-preset-modern-browsers": "^13.1.0",
"bili": "^4.7.0",
"coveralls": "^3.0.0",
"cpx": "^1.5.0",
"cross-env": "^5.1.3",
"deep-freeze": "^0.0.1",
"expect": "^24.7.1",
"flow-bin": "^0.68.0",
"husky": "^1.2.0",
"immutable": "^3.8.2",
"jest": "^24.7.1",
"lodash": "^4.17.4",
"lodash.clonedeep": "^4.5.0",
"prettier": "1.17.0",
"pretty-quick": "^1.8.0",
"regenerator-runtime": "^0.11.1",
"rimraf": "^2.6.2",
"seamless-immutable": "^7.1.3",
"spec.ts": "^1.1.0",
"typescript": "3.4.3",
"yarn-or-npm": "^2.0.4"
},
"jest": {
"moduleFileExtensions": [
"js"
],
"testURL": "http://localhost",
"transform": {
"\\.js$": "babel-jest"
}
}
"name": "immer",
"version": "5.0.0",
"description": "Create your next immutable state by mutating the current one",
"main": "dist/immer.js",
"umd:main": "dist/immer.umd.js",
"unpkg": "dist/immer.umd.js",
"jsdelivr": "dist/immer.umd.js",
"module": "dist/immer.module.js",
"jsnext:main": "dist/immer.module.js",
"react-native": "dist/immer.module.js",
"types": "./dist/immer.d.ts",
"scripts": {
"test": "jest",
"test:perf": "NODE_ENV=production yarn-or-npm build && cd __performance_tests__ && babel-node add-data.js && babel-node todo.js && babel-node incremental.js",
"test:flow": "yarn-or-npm flow check __tests__/flow",
"test:dts": "tsc -p __tests__/tsconfig.json --noEmit",
"watch": "jest --watch",
"coveralls": "jest --coverage && cat ./coverage/lcov.info | ./node_modules/.bin/coveralls && rm -rf ./coverage",
"build": "rimraf dist/ && yarn-or-npm bili && yarn-or-npm typed",
"typed": "cpx 'src/immer.{d.ts,js.flow}' dist -v",
"publish-docs": "cd website && GIT_USER=mweststrate USE_SSH=true yarn run publish-gh-pages",
"start": "cd website && yarn start"
},
"husky": {
"hooks": {
"pre-commit": "pretty-quick --staged"
}
},
"repository": {
"type": "git",
"url": "https://github.com/immerjs/immer.git"
},
"keywords": [
"immutable",
"mutable",
"copy-on-write"
],
"author": "Michel Weststrate",
"license": "MIT",
"bugs": {
"url": "https://github.com/immerjs/immer/issues"
},
"homepage": "https://github.com/immerjs/immer#readme",
"files": [
"dist",
"src"
],
"devDependencies": {
"@babel/cli": "^7.2.3",
"@babel/core": "^7.3.4",
"@babel/node": "^7.2.2",
"@babel/plugin-external-helpers": "^7.2.0",
"@babel/preset-env": "^7.3.4",
"@types/jest": "^24.0.11",
"babel-jest": "^24.4.0",
"babel-preset-modern-browsers": "^13.1.0",
"bili": "^4.7.0",
"coveralls": "^3.0.0",
"cpx": "^1.5.0",
"cross-env": "^5.1.3",
"deep-freeze": "^0.0.1",
"expect": "^24.7.1",
"flow-bin": "^0.68.0",
"husky": "^1.2.0",
"immutable": "^3.8.2",
"jest": "^24.7.1",
"lodash": "^4.17.4",
"lodash.clonedeep": "^4.5.0",
"prettier": "1.17.0",
"pretty-quick": "^1.8.0",
"regenerator-runtime": "^0.11.1",
"rimraf": "^2.6.2",
"seamless-immutable": "^7.1.3",
"spec.ts": "^1.1.0",
"typescript": "3.6.4",
"yarn-or-npm": "^2.0.4"
},
"jest": {
"moduleFileExtensions": [
"js"
],
"testURL": "http://localhost",
"transform": {
"\\.js$": "babel-jest"
}
}
}

@@ -23,3 +23,7 @@ export const NOTHING =

return (
isPlainObject(value) || !!value[DRAFTABLE] || !!value.constructor[DRAFTABLE]
isPlainObject(value) ||
!!value[DRAFTABLE] ||
!!value.constructor[DRAFTABLE] ||
isMap(value) ||
isSet(value)
)

@@ -42,12 +46,29 @@ }

// We use Maps as `drafts` for Sets, not Objects
// See proxy.js
export function assignSet(target, override) {
override.forEach(value => {
// When we add new drafts we have to remove their originals if present
const prev = original(value)
if (prev) target.delete(prev)
target.add(value)
})
return target
}
// We use Maps as `drafts` for Maps, not Objects
// See proxy.js
export function assignMap(target, override) {
override.forEach((value, key) => target.set(key, value))
return target
}
export const assign =
Object.assign ||
function assign(target, value) {
for (let key in value) {
if (has(value, key)) {
target[key] = value[key]
}
}
((target, ...overrides) => {
overrides.forEach(override =>
Object.keys(override).forEach(key => (target[key] = override[key]))
)
return target
}
})

@@ -66,2 +87,4 @@ export const ownKeys =

if (Array.isArray(base)) return base.slice()
if (isMap(base)) return new Map(base)
if (isSet(base)) return new Set(base)
const clone = Object.create(Object.getPrototypeOf(base))

@@ -93,7 +116,7 @@ ownKeys(base).forEach(key => {

export function each(value, cb) {
if (Array.isArray(value)) {
for (let i = 0; i < value.length; i++) cb(i, value[i], value)
export function each(obj, iter) {
if (Array.isArray(obj) || isMap(obj) || isSet(obj)) {
obj.forEach((entry, index) => iter(index, entry, obj))
} else {
ownKeys(value).forEach(key => cb(key, value[key], value))
ownKeys(obj).forEach(key => iter(key, obj[key], obj))
}

@@ -108,5 +131,11 @@ }

export function has(thing, prop) {
return Object.prototype.hasOwnProperty.call(thing, prop)
return isMap(thing)
? thing.has(prop)
: Object.prototype.hasOwnProperty.call(thing, prop)
}
export function get(thing, prop) {
return isMap(thing) ? thing.get(prop) : thing[prop]
}
export function is(x, y) {

@@ -121,5 +150,85 @@ // From: https://github.com/facebook/fbjs/blob/c69904a511b900266935168223063dd8772dfc40/packages/fbjs/src/core/shallowEqual.js

export const hasSymbol = typeof Symbol !== "undefined"
export const hasMap = typeof Map !== "undefined"
export function isMap(target) {
return hasMap && target instanceof Map
}
export const hasSet = typeof Set !== "undefined"
export function isSet(target) {
return hasSet && target instanceof Set
}
export function makeIterable(next) {
let self
return (self = {
[Symbol.iterator]: () => self,
next
})
}
/** Map.prototype.values _-or-_ Map.prototype.entries */
export function iterateMapValues(state, prop, receiver) {
const isEntries = prop !== "values"
return () => {
const iterator = latest(state)[Symbol.iterator]()
return makeIterable(() => {
const result = iterator.next()
if (!result.done) {
const [key] = result.value
const value = receiver.get(key)
result.value = isEntries ? [key, value] : value
}
return result
})
}
}
export function makeIterateSetValues(createProxy) {
function iterateSetValues(state, prop) {
const isEntries = prop === "entries"
return () => {
const iterator = latest(state)[Symbol.iterator]()
return makeIterable(() => {
const result = iterator.next()
if (!result.done) {
const value = wrapSetValue(state, result.value)
result.value = isEntries ? [value, value] : value
}
return result
})
}
}
function wrapSetValue(state, value) {
const key = original(value) || value
let draft = state.drafts.get(key)
if (!draft) {
if (state.finalized || !isDraftable(value) || state.finalizing) {
return value
}
draft = createProxy(value, state)
state.drafts.set(key, draft)
if (state.modified) {
state.copy.add(draft)
}
}
return draft
}
return iterateSetValues
}
function latest(state) {
return state.copy || state.base
}
export function clone(obj) {
if (!isDraftable(obj)) return obj
if (Array.isArray(obj)) return obj.map(clone)
if (isMap(obj)) return new Map(obj)
if (isSet(obj)) return new Set(obj)
const cloned = Object.create(Object.getPrototypeOf(obj))

@@ -130,7 +239,15 @@ for (const key in obj) cloned[key] = clone(obj[key])

export function deepFreeze(obj) {
export function freeze(obj, deep = false) {
if (!isDraftable(obj) || isDraft(obj) || Object.isFrozen(obj)) return
if (isSet(obj)) {
obj.add = obj.clear = obj.delete = dontMutateFrozenCollections
} else if (isMap(obj)) {
obj.set = obj.clear = obj.delete = dontMutateFrozenCollections
}
Object.freeze(obj)
if (Array.isArray(obj)) obj.forEach(deepFreeze)
else for (const key in obj) deepFreeze(obj[key])
if (deep) each(obj, (_, value) => freeze(value, true))
}
function dontMutateFrozenCollections() {
throw new Error("This object has been frozen and should not be mutated")
}

@@ -9,11 +9,13 @@ "use strict"

isEnumerable,
isMap,
isSet,
hasSymbol,
shallowCopy,
DRAFT_STATE
DRAFT_STATE,
iterateMapValues,
makeIterable,
makeIterateSetValues
} from "./common"
import {ImmerScope} from "./scope"
// property descriptors are recycled to make sure we don't create a get and set closure per property,
// but share them all instead
const descriptors = {}
export function willFinalize(scope, result, isReplaced) {

@@ -39,6 +41,13 @@ scope.drafts.forEach(draft => {

const draft = clonePotentialDraft(base)
each(draft, prop => {
proxyProperty(draft, prop, isArray || isEnumerable(base, prop))
})
if (isMap(base)) {
proxyMap(draft)
} else if (isSet(base)) {
proxySet(draft)
} else {
each(draft, prop => {
proxyProperty(draft, prop, isArray || isEnumerable(base, prop))
})
}
// See "proxy.js" for property documentation.

@@ -51,6 +60,7 @@ const scope = parent ? parent.scope : ImmerScope.current

finalized: false,
assigned: {},
assigned: isMap(base) ? new Map() : {},
parent,
base,
draft,
drafts: isSet(base) ? new Map() : null,
copy: null,

@@ -70,3 +80,3 @@ revoke,

function source(state) {
function latest(state) {
return state.copy || state.base

@@ -89,3 +99,3 @@ }

assertUnrevoked(state)
const value = peek(source(state), prop)
const value = peek(latest(state), prop)
if (state.finalizing) return value

@@ -104,3 +114,3 @@ // Create a draft if the value is unmodified.

if (!state.modified) {
if (is(value, peek(source(state), prop))) return
if (is(value, peek(latest(state), prop))) return
markChanged(state)

@@ -134,2 +144,6 @@ prepareCopy(state)

// property descriptors are recycled to make sure we don't create a get and set closure per property,
// but share them all instead
const descriptors = {}
function proxyProperty(draft, prop, enumerable) {

@@ -154,2 +168,157 @@ let desc = descriptors[prop]

function proxyMap(target) {
Object.defineProperties(target, mapTraps)
if (hasSymbol) {
Object.defineProperty(
target,
Symbol.iterator,
proxyMethod(iterateMapValues)
)
}
}
const mapTraps = finalizeTraps({
size: state => latest(state).size,
has: state => key => latest(state).has(key),
set: state => (key, value) => {
if (latest(state).get(key) !== value) {
prepareCopy(state)
markChanged(state)
state.assigned.set(key, true)
state.copy.set(key, value)
}
return state.draft
},
delete: state => key => {
prepareCopy(state)
markChanged(state)
state.assigned.set(key, false)
state.copy.delete(key)
return false
},
clear: state => () => {
if (!state.copy) {
prepareCopy(state)
}
markChanged(state)
state.assigned = new Map()
for (const key of latest(state).keys()) {
state.assigned.set(key, false)
}
return state.copy.clear()
},
forEach: (state, key, reciever) => cb => {
latest(state).forEach((value, key, map) => {
cb(reciever.get(key), key, map)
})
},
get: state => key => {
const value = latest(state).get(key)
if (state.finalizing || state.finalized || !isDraftable(value)) {
return value
}
if (value !== state.base.get(key)) {
return value
}
const draft = createProxy(value, state)
prepareCopy(state)
state.copy.set(key, draft)
return draft
},
keys: state => () => latest(state).keys(),
values: iterateMapValues,
entries: iterateMapValues
})
function proxySet(target) {
Object.defineProperties(target, setTraps)
if (hasSymbol) {
Object.defineProperty(
target,
Symbol.iterator,
proxyMethod(iterateSetValues)
)
}
}
const iterateSetValues = makeIterateSetValues(createProxy)
const setTraps = finalizeTraps({
size: state => {
return latest(state).size
},
add: state => value => {
if (!latest(state).has(value)) {
markChanged(state)
if (!state.copy) {
prepareCopy(state)
}
state.copy.add(value)
}
return state.draft
},
delete: state => value => {
markChanged(state)
if (!state.copy) {
prepareCopy(state)
}
return state.copy.delete(value)
},
has: state => key => {
return latest(state).has(key)
},
clear: state => () => {
markChanged(state)
if (!state.copy) {
prepareCopy(state)
}
return state.copy.clear()
},
keys: iterateSetValues,
entries: iterateSetValues,
values: iterateSetValues,
forEach: state => (cb, thisArg) => {
const iterator = iterateSetValues(state)()
let result = iterator.next()
while (!result.done) {
cb.call(thisArg, result.value, result.value, state.draft)
result = iterator.next()
}
}
})
function finalizeTraps(traps) {
return Object.keys(traps).reduce(function(acc, key) {
const builder = key === "size" ? proxyAttr : proxyMethod
acc[key] = builder(traps[key], key)
return acc
}, {})
}
function proxyAttr(fn) {
return {
get() {
const state = this[DRAFT_STATE]
assertUnrevoked(state)
return fn(state)
}
}
}
function proxyMethod(trap, key) {
return {
get() {
return function(...args) {
const state = this[DRAFT_STATE]
assertUnrevoked(state)
return trap(state, key, state.draft)(...args)
}
}
}
}
function assertUnrevoked(state) {

@@ -159,3 +328,3 @@ if (state.revoked === true)

"Cannot use a proxy that has been revoked. Did you pass an object from inside an immer function to an async process? " +
JSON.stringify(source(state))
JSON.stringify(latest(state))
)

@@ -175,3 +344,9 @@ }

if (hasArrayChanges(state)) markChanged(state)
} else if (hasObjectChanges(state)) markChanged(state)
} else if (isMap(state.base)) {
if (hasMapChanges(state)) markChanged(state)
} else if (isSet(state.base)) {
if (hasSetChanges(state)) markChanged(state)
} else if (hasObjectChanges(state)) {
markChanged(state)
}
}

@@ -267,2 +442,32 @@ }

function hasMapChanges(state) {
const {base, draft} = state
if (base.size !== draft.size) return true
// IE11 supports only forEach iteration
let hasChanges = false
draft.forEach(function(value, key) {
if (!hasChanges) {
hasChanges = isDraftable(value) ? value.modified : value !== base.get(key)
}
})
return hasChanges
}
function hasSetChanges(state) {
const {base, draft} = state
if (base.size !== draft.size) return true
// IE11 supports only forEach iteration
let hasChanges = false
draft.forEach(function(value, key) {
if (!hasChanges) {
hasChanges = isDraftable(value) ? value.modified : !base.has(key)
}
})
return hasChanges
}
function createHiddenProperty(target, prop, value) {

@@ -269,0 +474,0 @@ Object.defineProperty(target, prop, {

@@ -11,5 +11,3 @@ type Tail<T extends any[]> = ((...t: T) => any) extends ((

| Function
| Map<any, any>
| WeakMap<any, any>
| Set<any>
| WeakSet<any>

@@ -25,2 +23,6 @@ | Promise<any>

? T
: T extends Map<infer K, infer V>
? DraftMap<K, V>
: T extends Set<infer V>
? DraftSet<V>
: T extends object

@@ -30,5 +32,17 @@ ? {-readonly [K in keyof T]: Draft<T[K]>}

// Inline these in ts 3.7
interface DraftMap<K, V> extends Map<Draft<K>, Draft<V>> {}
// Inline these in ts 3.7
interface DraftSet<V> extends Set<Draft<V>> {}
/** Convert a mutable type into a readonly type */
export type Immutable<T> = T extends AtomicObject
? T
: T extends Map<infer K, infer V>
? // Ideally, but wait for TS 3.7: ? Omit<ImmutableMap<K, V>, "set" | "delete" | "clear">
ImmutableMap<K, V>
: T extends Set<infer V>
? // Ideally, but wait for TS 3.7: ? Omit<ImmutableSet<V>, "add" | "delete" | "clear">
ImmutableSet<V>
: T extends object

@@ -38,2 +52,6 @@ ? {readonly [K in keyof T]: Immutable<T[K]>}

interface ImmutableMap<K, V> extends Map<Immutable<K>, Immutable<V>> {}
interface ImmutableSet<V> extends Set<Immutable<V>> {}
export interface Patch {

@@ -40,0 +58,0 @@ op: "replace" | "remove" | "add"

@@ -10,2 +10,5 @@ import * as legacyProxy from "./es5"

isDraft,
isSet,
get,
isMap,
isDraftable,

@@ -16,3 +19,3 @@ isEnumerable,

NOTHING,
deepFreeze
freeze
} from "./common"

@@ -42,2 +45,3 @@ import {ImmerScope} from "./scope"

this.produce = this.produce.bind(this)
this.produceWithPatches = this.produceWithPatches.bind(this)
}

@@ -81,3 +85,3 @@ produce(base, recipe, patchListener) {

}
if (result instanceof Promise) {
if (typeof Promise !== "undefined" && result instanceof Promise) {
return result.then(

@@ -230,10 +234,12 @@ result => {

if (this.onDelete) {
// We cannot really delete anything inside of a Set. We can only replace the whole Set.
if (this.onDelete && !isSet(state.base)) {
// The `assigned` object is unreliable with ES5 drafts.
if (this.useProxies) {
const {assigned} = state
for (const prop in assigned) {
if (!assigned[prop]) this.onDelete(state, prop)
}
each(assigned, (prop, exists) => {
if (!exists) this.onDelete(state, prop)
})
} else {
// TODO: Figure it out for Maps and Sets if we need to support ES5
const {base, copy} = state

@@ -252,3 +258,3 @@ each(base, prop => {

if (this.autoFreeze && scope.canAutoFreeze) {
Object.freeze(state.copy)
freeze(state.copy, false)
}

@@ -284,6 +290,10 @@

const isDraftProp = !!state && parent === root
const isSetMember = isSet(parent)
if (isDraft(value)) {
const path =
isDraftProp && needPatches && !state.assigned[prop]
isDraftProp &&
needPatches &&
!isSetMember && // Set objects are atomic since they have no keys.
!has(state.assigned, prop) // Skip deep patches for assigned keys.
? rootPath.concat(prop)

@@ -294,2 +304,3 @@ : null

value = this.finalize(value, path, scope)
replace(parent, prop, value)

@@ -301,14 +312,7 @@ // Drafts from another scope must prevent auto-freezing.

// Preserve non-enumerable properties.
if (Array.isArray(parent) || isEnumerable(parent, prop)) {
parent[prop] = value
} else {
Object.defineProperty(parent, prop, {value})
}
// Unchanged drafts are never passed to the `onAssign` hook.
if (isDraftProp && value === state.base[prop]) return
if (isDraftProp && value === get(state.base, prop)) return
}
// Unchanged draft properties are ignored.
else if (isDraftProp && is(value, state.base[prop])) {
else if (isDraftProp && is(value, get(state.base, prop))) {
return

@@ -322,3 +326,3 @@ }

if (isDraftProp && this.onAssign) {
if (isDraftProp && this.onAssign && !isSetMember) {
this.onAssign(state, prop, value)

@@ -333,6 +337,24 @@ }

if (this.autoFreeze && !isDraft(value)) {
if (deep) deepFreeze(value)
else Object.freeze(value)
freeze(value, deep)
}
}
}
function replace(parent, prop, value) {
if (isMap(parent)) {
parent.set(prop, value)
} else if (isSet(parent)) {
// In this case, the `prop` is actually a draft.
parent.delete(prop)
parent.add(value)
} else if (Array.isArray(parent) || isEnumerable(parent, prop)) {
// Preserve non-enumerable properties.
parent[prop] = value
} else {
Object.defineProperty(parent, prop, {
value,
writable: true,
configurable: true
})
}
}

@@ -1,7 +0,11 @@

import {each, clone} from "./common"
import {get, each, isMap, isSet, has, clone} from "./common"
export function generatePatches(state, basePath, patches, inversePatches) {
Array.isArray(state.base)
? generateArrayPatches(state, basePath, patches, inversePatches)
: generateObjectPatches(state, basePath, patches, inversePatches)
const generatePatchesFn = Array.isArray(state.base)
? generateArrayPatches
: isSet(state.base)
? generateSetPatches
: generatePatchesFromAssigned
generatePatchesFn(state, basePath, patches, inversePatches)
}

@@ -66,8 +70,9 @@

function generateObjectPatches(state, basePath, patches, inversePatches) {
// This is used for both Map objects and normal objects.
function generatePatchesFromAssigned(state, basePath, patches, inversePatches) {
const {base, copy} = state
each(state.assigned, (key, assignedValue) => {
const origValue = base[key]
const value = copy[key]
const op = !assignedValue ? "remove" : key in base ? "replace" : "add"
const origValue = get(base, key)
const value = get(copy, key)
const op = !assignedValue ? "remove" : has(base, key) ? "replace" : "add"
if (origValue === value && op === "replace") return

@@ -86,6 +91,44 @@ const path = basePath.concat(key)

function generateSetPatches(state, basePath, patches, inversePatches) {
let {base, copy} = state
let i = 0
for (const value of base) {
if (!copy.has(value)) {
const path = basePath.concat([i])
patches.push({
op: "remove",
path,
value
})
inversePatches.unshift({
op: "add",
path,
value
})
}
i++
}
i = 0
for (const value of copy) {
if (!base.has(value)) {
const path = basePath.concat([i])
patches.push({
op: "add",
path,
value
})
inversePatches.unshift({
op: "remove",
path,
value
})
}
i++
}
}
export const applyPatches = (draft, patches) => {
for (const patch of patches) {
const {path, op} = patch
const value = clone(patch.value) // used to clone patch to ensure original patch is not modified, see #411

@@ -96,3 +139,3 @@ if (!path.length) throw new Error("Illegal state")

for (let i = 0; i < path.length - 1; i++) {
base = base[path[i]]
base = get(base, path[i])
if (!base || typeof base !== "object")

@@ -102,25 +145,40 @@ throw new Error("Cannot apply patch, path doesn't resolve: " + path.join("/")) // prettier-ignore

const value = clone(patch.value) // used to clone patch to ensure original patch is not modified, see #411
const key = path[path.length - 1]
switch (op) {
case "replace":
// if value is an object, then it's assigned by reference
// in the following add or remove ops, the value field inside the patch will also be modifyed
// so we use value from the cloned patch
base[key] = value
break
case "add":
if (Array.isArray(base)) {
// TODO: support "foo/-" paths for appending to an array
base.splice(key, 0, value)
if (isMap(base)) {
base.set(key, value)
} else if (isSet(base)) {
throw new Error('Sets cannot have "replace" patches.')
} else {
// if value is an object, then it's assigned by reference
// in the following add or remove ops, the value field inside the patch will also be modifyed
// so we use value from the cloned patch
base[key] = value
}
break
case "remove":
if (Array.isArray(base)) {
base.splice(key, 1)
} else {
delete base[key]
case "add":
if (isSet(base)) {
base.delete(patch.value)
}
Array.isArray(base)
? base.splice(key, 0, value)
: isMap(base)
? base.set(key, value)
: isSet(base)
? base.add(value)
: (base[key] = value)
break
case "remove":
Array.isArray(base)
? base.splice(key, 1)
: isMap(base)
? base.delete(key)
: isSet(base)
? base.delete(patch.value)
: delete base[key]
break
default:

@@ -127,0 +185,0 @@ throw new Error("Unsupported patch operation: " + op)

@@ -9,4 +9,13 @@ "use strict"

isDraft,
isMap,
isSet,
hasSymbol,
shallowCopy,
DRAFT_STATE
makeIterable,
DRAFT_STATE,
assignMap,
assignSet,
original,
iterateMapValues,
makeIterateSetValues
} from "./common"

@@ -18,2 +27,7 @@ import {ImmerScope} from "./scope"

/**
* Returns a new draft of the `base` object.
*
* The second argument is the parent draft-state (used internally).
*/
export function createProxy(base, parent) {

@@ -44,8 +58,23 @@ const scope = parent ? parent.scope : ImmerScope.current

const {revoke, proxy} = Array.isArray(base)
? // [state] is used for arrays, to make sure the proxy is array-ish and not violate invariants,
// although state itself is an object
Proxy.revocable([state], arrayTraps)
: Proxy.revocable(state, objectTraps)
let target = state
let traps = objectTraps
if (Array.isArray(base)) {
target = [state]
traps = arrayTraps
}
// Map drafts must support object keys, so we use Map objects to track changes.
else if (isMap(base)) {
traps = mapTraps
state.drafts = new Map()
state.assigned = new Map()
}
// Set drafts use a Map object to track which of its values are drafted.
// And we don't need the "assigned" property, because Set objects have no keys.
else if (isSet(base)) {
traps = setTraps
state.drafts = new Map()
}
const {revoke, proxy} = Proxy.revocable(target, traps)
state.draft = proxy

@@ -58,18 +87,81 @@ state.revoke = revoke

/**
* Object drafts
*/
const objectTraps = {
get,
has(target, prop) {
return prop in source(target)
get(state, prop) {
if (prop === DRAFT_STATE) return state
let {drafts} = state
// Check for existing draft in unmodified state.
if (!state.modified && has(drafts, prop)) {
return drafts[prop]
}
const value = latest(state)[prop]
if (state.finalized || !isDraftable(value)) {
return value
}
// Check for existing draft in modified state.
if (state.modified) {
// Assigned values are never drafted. This catches any drafts we created, too.
if (value !== peek(state.base, prop)) return value
// Store drafts on the copy (when one exists).
drafts = state.copy
}
return (drafts[prop] = createProxy(value, state))
},
ownKeys(target) {
return Reflect.ownKeys(source(target))
has(state, prop) {
return prop in latest(state)
},
set,
deleteProperty,
getOwnPropertyDescriptor,
ownKeys(state) {
return Reflect.ownKeys(latest(state))
},
set(state, prop, value) {
if (!state.modified) {
const baseValue = peek(state.base, prop)
// Optimize based on value's truthiness. Truthy values are guaranteed to
// never be undefined, so we can avoid the `in` operator. Lastly, truthy
// values may be drafts, but falsy values are never drafts.
const isUnchanged = value
? is(baseValue, value) || value === state.drafts[prop]
: is(baseValue, value) && prop in state.base
if (isUnchanged) return true
markChanged(state)
}
state.assigned[prop] = true
state.copy[prop] = value
return true
},
deleteProperty(state, prop) {
// The `undefined` check is a fast path for pre-existing keys.
if (peek(state.base, prop) !== undefined || prop in state.base) {
state.assigned[prop] = false
markChanged(state)
} else if (state.assigned[prop]) {
// if an originally not assigned property was deleted
delete state.assigned[prop]
}
if (state.copy) delete state.copy[prop]
return true
},
// Note: We never coerce `desc.value` into an Immer draft, because we can't make
// the same guarantee in ES5 mode.
getOwnPropertyDescriptor(state, prop) {
const owner = latest(state)
const desc = Reflect.getOwnPropertyDescriptor(owner, prop)
if (desc) {
desc.writable = true
desc.configurable = !Array.isArray(owner) || prop !== "length"
}
return desc
},
defineProperty() {
throw new Error("Object.defineProperty() cannot be used on an Immer draft") // prettier-ignore
},
getPrototypeOf(target) {
return Object.getPrototypeOf(target.base)
getPrototypeOf(state) {
return Object.getPrototypeOf(state.base)
},

@@ -81,2 +173,6 @@ setPrototypeOf() {

/**
* Array drafts
*/
const arrayTraps = {}

@@ -102,4 +198,118 @@ each(objectTraps, (key, fn) => {

// returns the object we should be reading the current value from, which is base, until some change has been made
function source(state) {
// Used by Map and Set drafts
const reflectTraps = makeReflectTraps([
"ownKeys",
"has",
"set",
"deleteProperty",
"defineProperty",
"getOwnPropertyDescriptor",
"preventExtensions",
"isExtensible",
"getPrototypeOf"
])
/**
* Map drafts
*/
const mapTraps = makeTrapsForGetters({
[DRAFT_STATE]: state => state,
size: state => latest(state).size,
has: state => key => latest(state).has(key),
set: state => (key, value) => {
const values = latest(state)
if (!values.has(key) || values.get(key) !== value) {
markChanged(state)
state.assigned.set(key, true)
state.copy.set(key, value)
}
return state.draft
},
delete: state => key => {
if (latest(state).has(key)) {
markChanged(state)
state.assigned.set(key, false)
return state.copy.delete(key)
}
return false
},
clear: state => () => {
markChanged(state)
state.assigned = new Map()
for (const key of latest(state).keys()) {
state.assigned.set(key, false)
}
return state.copy.clear()
},
forEach: (state, _, receiver) => (cb, thisArg) =>
latest(state).forEach((_, key, map) => {
const value = receiver.get(key)
cb.call(thisArg, value, key, map)
}),
get: state => key => {
const drafts = state[state.modified ? "copy" : "drafts"]
if (drafts.has(key)) {
return drafts.get(key)
}
const value = latest(state).get(key)
if (state.finalized || !isDraftable(value)) {
return value
}
const draft = createProxy(value, state)
drafts.set(key, draft)
return draft
},
keys: state => () => latest(state).keys(),
values: iterateMapValues,
entries: iterateMapValues,
[hasSymbol ? Symbol.iterator : "@@iterator"]: iterateMapValues
})
const iterateSetValues = makeIterateSetValues(createProxy)
/**
* Set drafts
*/
const setTraps = makeTrapsForGetters({
[DRAFT_STATE]: state => state,
size: state => latest(state).size,
has: state => key => latest(state).has(key),
add: state => value => {
if (!latest(state).has(value)) {
markChanged(state)
state.copy.add(value)
}
return state.draft
},
delete: state => value => {
markChanged(state)
return state.copy.delete(value)
},
clear: state => () => {
markChanged(state)
return state.copy.clear()
},
forEach: state => (cb, thisArg) => {
const iterator = iterateSetValues(state)()
let result = iterator.next()
while (!result.done) {
cb.call(thisArg, result.value, result.value, state.draft)
result = iterator.next()
}
},
keys: iterateSetValues,
values: iterateSetValues,
entries: iterateSetValues,
[hasSymbol ? Symbol.iterator : "@@iterator"]: iterateSetValues
})
/**
* Helpers
*/
// Retrieve the latest values of the draft.
function latest(state) {
return state.copy || state.base

@@ -112,3 +322,3 @@ }

const desc = Reflect.getOwnPropertyDescriptor(
state ? source(state) : draft,
state ? latest(state) : draft,
prop

@@ -119,76 +329,47 @@ )

function get(state, prop) {
if (prop === DRAFT_STATE) return state
let {drafts} = state
function markChanged(state) {
if (!state.modified) {
state.modified = true
// Check for existing draft in unmodified state.
if (!state.modified && has(drafts, prop)) {
return drafts[prop]
}
const {base, drafts, parent} = state
const copy = shallowCopy(base)
const value = source(state)[prop]
if (state.finalized || !isDraftable(value)) {
return value
}
if (isSet(base)) {
// Note: The `drafts` property is preserved for Set objects, since
// we need to keep track of which values are drafted.
assignSet(copy, drafts)
} else {
// Merge nested drafts into the copy.
if (isMap(base)) assignMap(copy, drafts)
else assign(copy, drafts)
state.drafts = null
}
// Check for existing draft in modified state.
if (state.modified) {
// Assigned values are never drafted. This catches any drafts we created, too.
if (value !== peek(state.base, prop)) return value
// Store drafts on the copy (when one exists).
drafts = state.copy
state.copy = copy
if (parent) {
markChanged(parent)
}
}
return (drafts[prop] = createProxy(value, state))
}
function set(state, prop, value) {
if (!state.modified) {
const baseValue = peek(state.base, prop)
// Optimize based on value's truthiness. Truthy values are guaranteed to
// never be undefined, so we can avoid the `in` operator. Lastly, truthy
// values may be drafts, but falsy values are never drafts.
const isUnchanged = value
? is(baseValue, value) || value === state.drafts[prop]
: is(baseValue, value) && prop in state.base
if (isUnchanged) return true
markChanged(state)
}
state.assigned[prop] = true
state.copy[prop] = value
return true
/** Create traps that all use the `Reflect` API on the `latest(state)` */
function makeReflectTraps(names) {
return names.reduce((traps, name) => {
traps[name] = (state, ...args) => Reflect[name](latest(state), ...args)
return traps
}, {})
}
function deleteProperty(state, prop) {
// The `undefined` check is a fast path for pre-existing keys.
if (peek(state.base, prop) !== undefined || prop in state.base) {
state.assigned[prop] = false
markChanged(state)
} else if (state.assigned[prop]) {
// if an originally not assigned property was deleted
delete state.assigned[prop]
function makeTrapsForGetters(getters) {
return {
...reflectTraps,
get(state, prop, receiver) {
return getters.hasOwnProperty(prop)
? getters[prop](state, prop, receiver)
: Reflect.get(state, prop, receiver)
},
setPrototypeOf(state) {
throw new Error("Object.setPrototypeOf() cannot be used on an Immer draft") // prettier-ignore
}
}
if (state.copy) delete state.copy[prop]
return true
}
// Note: We never coerce `desc.value` into an Immer draft, because we can't make
// the same guarantee in ES5 mode.
function getOwnPropertyDescriptor(state, prop) {
const owner = source(state)
const desc = Reflect.getOwnPropertyDescriptor(owner, prop)
if (desc) {
desc.writable = true
desc.configurable = !Array.isArray(owner) || prop !== "length"
}
return desc
}
function markChanged(state) {
if (!state.modified) {
state.modified = true
state.copy = assign(shallowCopy(state.base), state.drafts)
state.drafts = null
if (state.parent) markChanged(state.parent)
}
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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