react-deepwatch 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/Util.d.ts +66 -0
- package/Util.d.ts.map +1 -0
- package/Util.js +178 -0
- package/Util.js.map +1 -0
- package/Util.ts +190 -0
- package/dist/mjs/Util.d.ts +66 -0
- package/dist/mjs/Util.d.ts.map +1 -0
- package/dist/mjs/Util.js +164 -0
- package/dist/mjs/Util.js.map +1 -0
- package/dist/mjs/index.d.ts +218 -0
- package/dist/mjs/index.d.ts.map +1 -0
- package/dist/mjs/index.js +821 -0
- package/dist/mjs/index.js.map +1 -0
- package/dist/mjs/preserve.d.ts +72 -0
- package/dist/mjs/preserve.d.ts.map +1 -0
- package/dist/mjs/preserve.js +374 -0
- package/dist/mjs/preserve.js.map +1 -0
- package/index.d.ts +218 -0
- package/index.d.ts.map +1 -0
- package/index.js +830 -0
- package/index.js.map +1 -0
- package/index.ts +1237 -0
- package/index_esm.mjs +6 -0
- package/mechanics.md +47 -0
- package/package.json +59 -0
- package/preserve.d.ts +72 -0
- package/preserve.d.ts.map +1 -0
- package/preserve.js +385 -0
- package/preserve.js.map +1 -0
- package/preserve.ts +492 -0
- package/readme.md +109 -0
package/index_esm.mjs
ADDED
package/mechanics.md
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Deeper explaining the mechanics
|
|
2
|
+
## Re-rendering
|
|
3
|
+
- A watchedComponents is re-rendered **by React from the outside**, only when shallow properties change. It uses React's [memo](https://react.dev/reference/react/memo) therefore. See the `WatchedComponentOptions#memo` flag.
|
|
4
|
+
- A watchedComponents re-renders it's self when a property, that is actually "read" inside the render function (=component function), later changes. This is from these (root) sources:
|
|
5
|
+
- the `props`
|
|
6
|
+
- the `useWatchedState`
|
|
7
|
+
- a `watched(useContext(...))`
|
|
8
|
+
- a `watched` external / global object
|
|
9
|
+
- the result of a `load(...)` statement
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
So, what is a "read"? tl;dr: Just everything anywhere that reads from the above mentioned:
|
|
13
|
+
````javascript
|
|
14
|
+
//# Directly:
|
|
15
|
+
{props.myProp} // this is a read (outputting in jsx)
|
|
16
|
+
console.log(props.myProp) // this is a read
|
|
17
|
+
props.myProp // this is a (useless) read
|
|
18
|
+
|
|
19
|
+
//# Reads from inside other code (or libraries) are recorded too ;):
|
|
20
|
+
function myFunc(props) {
|
|
21
|
+
return props.myModel.users; // this is two reads.
|
|
22
|
+
}
|
|
23
|
+
myFunc(props); // this is not a read it's self.
|
|
24
|
+
|
|
25
|
+
//# Getters / setters are treated as whitebox. Just like functions:
|
|
26
|
+
const myState = useWatchedState({
|
|
27
|
+
get logonUser() {
|
|
28
|
+
return this._logonUser; // this is a read
|
|
29
|
+
}
|
|
30
|
+
})
|
|
31
|
+
myState.logonUser; // this is not a read it's self.
|
|
32
|
+
|
|
33
|
+
//# Reads are also recorded on Sets, Maps and Arrays:
|
|
34
|
+
const myStateWithSet = useWatchedState(new Set(["a","b"]))
|
|
35
|
+
myStateWithSet.has("c"); // This is a read and a re-render will be triggerd if someone does myStateWithSet.add("c") later
|
|
36
|
+
````
|
|
37
|
+
|
|
38
|
+
Change tracking works also (by default), if these properties are changed externally / from the outside / not through the proxy-facade that you see in the render function. See `WatchedComponentOptions#watchOutside`.
|
|
39
|
+
_Thanks to the mothers and fathers of Ecmascript to make all this possible through fancy proxy tricks ;)_
|
|
40
|
+
- _Besides that, re-renders can be made for operational purposes: to display the state change of a load or to serve the isLoading() and loadFailed() probing functions, etc..._
|
|
41
|
+
|
|
42
|
+
## Re-loading
|
|
43
|
+
The `loaderFn` from inside the `load(...)` statements is re-executed, when:
|
|
44
|
+
- A property, that is read immediately in the `loaderFn`, later changes. _Immediately = in the same sync block / not after an awaited i/o operation._
|
|
45
|
+
- The precondition changes: Meaning, those reads that were done **before** the `load(...)` statement, their value later changes.
|
|
46
|
+
|
|
47
|
+
For this to work, your component function must be pure / deterministic against all watched sources (listed [above](#re-rendering)), meaning: **Your component function must not use any non-watched source!**
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "react-deepwatch",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"react",
|
|
7
|
+
"proxy"
|
|
8
|
+
],
|
|
9
|
+
"author": "Boris Gingold <bogeee@bogitech.de>",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/bogeeee/react-deepwatch.git",
|
|
13
|
+
"directory": "react-deepwatch"
|
|
14
|
+
},
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"main": "index.js",
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"browser": "./dist/mjs/index.js",
|
|
20
|
+
"default": "./index.js"
|
|
21
|
+
},
|
|
22
|
+
"./develop": {
|
|
23
|
+
"browser": "./index.ts"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"scripts": {
|
|
27
|
+
"dev:playground.ts": "tsx devPlayground.ts",
|
|
28
|
+
"dev:generateEsRuntimeBehaviourCheckerCode": "tsx dev_generateEsRuntimeBehaviourCheckerCode.ts",
|
|
29
|
+
"clean": "tsc --build --clean && rimraf dist LICENSE readme.md",
|
|
30
|
+
"build": "tsc --build --force && tsc -module ES6 --outDir dist/mjs",
|
|
31
|
+
"test": "npm run clean && vitest --clearScreen --hideSkippedTests --poolOptions.threads.singleThread",
|
|
32
|
+
"test_specific": "npm run clean && vitest --clearScreen --hideSkippedTests --poolOptions.threads.singleThread --testNamePattern \"Arrays with Object.keys with .*push.* With writes from outside\"",
|
|
33
|
+
"test:web:prepare": "npm install --prefix ../tests/web dev --ignore-scripts",
|
|
34
|
+
"test:web": "npm run clean && npm run --prefix ../tests/web dev",
|
|
35
|
+
"prepublish": "npm run clean && npm run build && ncp ../LICENSE ./LICENSE && ncp ../readme.md ./readme.md",
|
|
36
|
+
"publish:npmlogin": "npm login",
|
|
37
|
+
"publish:publish": "npm run prepublish && npm publish"
|
|
38
|
+
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"@types/underscore": "^1.11.4",
|
|
42
|
+
"@types/node": "^20.12.7",
|
|
43
|
+
"underscore": "^1.13.3",
|
|
44
|
+
"react": "^18.3.1",
|
|
45
|
+
"@types/react": "^18.3.11",
|
|
46
|
+
"react-error-boundary": "^4.x",
|
|
47
|
+
"clone": "^2.1.2",
|
|
48
|
+
"@types/clone": "^2.1.4",
|
|
49
|
+
"proxy-facades": "^1.0.0"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"tsx": "^4.7.0",
|
|
53
|
+
"@vitest/ui": "^1.5.1",
|
|
54
|
+
"rimraf": "=5.0.5",
|
|
55
|
+
"ncp": "=2.0.0",
|
|
56
|
+
"typescript": "^5.4.5",
|
|
57
|
+
"vitest": "^1.5.0"
|
|
58
|
+
}
|
|
59
|
+
}
|
package/preserve.d.ts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
export type PreserveDiagnosis = {
|
|
2
|
+
fromLoad?: boolean;
|
|
3
|
+
callStack?: Error;
|
|
4
|
+
};
|
|
5
|
+
export type PreserveOptions = {
|
|
6
|
+
/**
|
|
7
|
+
* Invalidates those objects under newObj that have become obsolete, by installing a proxy on them that throws an a Error when trying to use them. This makes sure, your code does not accidentally use them.
|
|
8
|
+
* <p>Default: true</p>
|
|
9
|
+
*/
|
|
10
|
+
destroyObsolete?: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Ignores the "id" property and only uses the "key" property when re-identifying objects
|
|
13
|
+
* <p>Default: false</p>
|
|
14
|
+
*/
|
|
15
|
+
ignoresIds?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Ignores the "key" property and only uses the "id" property when re-identifying objects
|
|
18
|
+
* <p>Default: false</p>
|
|
19
|
+
*/
|
|
20
|
+
ignoresKeys?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Threats an object that was preserved and reoccurs on a completely differnt place (not the same parent) as the same = re-uses that instance.
|
|
23
|
+
* <p>Default: false</p>
|
|
24
|
+
* <p>Disabled by default because too much magic / behaviour flipping depending indirectly related data.</p>
|
|
25
|
+
*/
|
|
26
|
+
preserveCircular?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Only for normalizeList(s) function
|
|
29
|
+
*/
|
|
30
|
+
normalize_ignoreDifferent?: boolean;
|
|
31
|
+
};
|
|
32
|
+
declare class PreserveCall {
|
|
33
|
+
options: PreserveOptions;
|
|
34
|
+
/**
|
|
35
|
+
* preserved/old -> new (obsolete) object
|
|
36
|
+
*/
|
|
37
|
+
mergedToNew: Map<object, object>;
|
|
38
|
+
/**
|
|
39
|
+
* new (obsolete) object -> preserved/old object
|
|
40
|
+
*/
|
|
41
|
+
newToPreserved: Map<object, object>;
|
|
42
|
+
possiblyObsoleteObjects: Set<object>;
|
|
43
|
+
usedObjects: WeakSet<object>;
|
|
44
|
+
/**
|
|
45
|
+
*
|
|
46
|
+
* @param value
|
|
47
|
+
*/
|
|
48
|
+
markUsed(value: unknown): void;
|
|
49
|
+
diagnosis?: PreserveDiagnosis;
|
|
50
|
+
constructor(options: PreserveOptions, diagnosis?: PreserveDiagnosis);
|
|
51
|
+
}
|
|
52
|
+
export declare function preserve<T>(oldValue: T, newValue: T, options?: PreserveOptions): T;
|
|
53
|
+
export declare function _preserve<T>(oldValue: T, newValue: T, options: PreserveOptions, diagnosis?: PreserveDiagnosis): T;
|
|
54
|
+
export declare function preserve_inner<T>(oldValue: T, newValue: T, call: PreserveCall, diagnosis_path: string): T;
|
|
55
|
+
export declare function diagnisis_shortenValue(evil_value: any): string;
|
|
56
|
+
/**
|
|
57
|
+
*
|
|
58
|
+
* Scans root deeply for Arrays and for each found array, it call normalizeList, which squeezes the items with the same id/key into one object instance.
|
|
59
|
+
* @see normalizeList
|
|
60
|
+
* @param root
|
|
61
|
+
* @param options
|
|
62
|
+
*/
|
|
63
|
+
export declare function normalizeLists<T extends object>(root: T, options?: PreserveOptions): T;
|
|
64
|
+
/**
|
|
65
|
+
* Squeezes the items with the same id/key into one object instance.
|
|
66
|
+
* @param list
|
|
67
|
+
* @param options
|
|
68
|
+
* @param diagnosis_path internal
|
|
69
|
+
*/
|
|
70
|
+
export declare function normalizeList<T extends unknown[]>(list: T, options?: PreserveOptions, diagnosis_path?: string): T;
|
|
71
|
+
export {};
|
|
72
|
+
//# sourceMappingURL=preserve.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preserve.d.ts","sourceRoot":"","sources":["preserve.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,iBAAiB,GAAG;IAC5B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,KAAK,CAAC;CACrB,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC1B;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAE1B;;OAEG;IACH,yBAAyB,CAAC,EAAE,OAAO,CAAA;CACtC,CAAA;AAED,cAAM,YAAY;IACd,OAAO,EAAE,eAAe,CAAC;IACzB;;OAEG;IACH,WAAW,sBAA4B;IAEvC;;OAEG;IACH,cAAc,sBAA4B;IAE1C,uBAAuB,cAAqB;IAE5C,WAAW,kBAAyB;IAEpC;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,OAAO;IAMvB,SAAS,CAAC,EAAE,iBAAiB,CAAA;gBAEjB,OAAO,EAAE,eAAe,EAAE,SAAS,CAAC,EAAE,iBAAiB;CAItE;AA8FD,wBAAgB,QAAQ,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,GAAE,eAAoB,GAAG,CAAC,CAEtF;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,eAAe,EAAE,SAAS,CAAC,EAAE,iBAAiB,GAAG,CAAC,CAoBjH;AAGD,wBAAgB,cAAc,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,GAAG,CAAC,CAuEzG;AAmFD,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,GAAG,GAAI,MAAM,CAqE/D;AA6BD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,GAAE,eAAoB,KAOtF;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,GAAE,eAAoB,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,CAAC,CAoBrH"}
|
package/preserve.js
ADDED
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.preserve = preserve;
|
|
7
|
+
exports._preserve = _preserve;
|
|
8
|
+
exports.preserve_inner = preserve_inner;
|
|
9
|
+
exports.diagnisis_shortenValue = diagnisis_shortenValue;
|
|
10
|
+
exports.normalizeLists = normalizeLists;
|
|
11
|
+
exports.normalizeList = normalizeList;
|
|
12
|
+
const Util_1 = require("./Util");
|
|
13
|
+
const underscore_1 = __importDefault(require("underscore"));
|
|
14
|
+
const proxy_facades_1 = require("proxy-facades");
|
|
15
|
+
const normalizeListsHint = `Hint: When this is fetched server data and having duplicate items in a list is intentional, you can pre-process it with the normalizeLists function first. See: import {normalizeLists, normalizeList} from "react-deepwatch"`;
|
|
16
|
+
class PreserveCall {
|
|
17
|
+
/**
|
|
18
|
+
*
|
|
19
|
+
* @param value
|
|
20
|
+
*/
|
|
21
|
+
markUsed(value) {
|
|
22
|
+
if (value !== null && typeof value === "object") {
|
|
23
|
+
this.usedObjects.add(value);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
constructor(options, diagnosis) {
|
|
27
|
+
/**
|
|
28
|
+
* preserved/old -> new (obsolete) object
|
|
29
|
+
*/
|
|
30
|
+
this.mergedToNew = new Map();
|
|
31
|
+
/**
|
|
32
|
+
* new (obsolete) object -> preserved/old object
|
|
33
|
+
*/
|
|
34
|
+
this.newToPreserved = new Map();
|
|
35
|
+
this.possiblyObsoleteObjects = new Set();
|
|
36
|
+
this.usedObjects = new WeakSet();
|
|
37
|
+
this.options = options;
|
|
38
|
+
this.diagnosis = diagnosis;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Registry for objects in the **same** Array / Set / Map
|
|
43
|
+
*/
|
|
44
|
+
class ObjRegistry {
|
|
45
|
+
constructor(preserveOptions) {
|
|
46
|
+
this.objectsById = new Map();
|
|
47
|
+
this.objectsByKey = new Map();
|
|
48
|
+
this.objectsByIdAndKey = new Map();
|
|
49
|
+
this.preserveOptions = preserveOptions;
|
|
50
|
+
}
|
|
51
|
+
getIdAndKey(obj, diagnosis_path) {
|
|
52
|
+
const diagnosis_getErrorDiag = () => `Trying to reidentify the object ${diagnisis_shortenValue(obj)} during a 'preserve' operation. Path: ${diagnosis_path}`;
|
|
53
|
+
const result = {};
|
|
54
|
+
for (const mode of [{ propName: "id", map: this.objectsById, diag_other: this.objectsByKey }, { propName: "key", map: this.objectsByKey, diag_other: this.objectsById }]) {
|
|
55
|
+
const throwInconsistent = (map) => { throw new PreserveError(`Objects must be consistent in either having an id or a key or both set, but found: ${diagnisis_shortenValue(obj)} and ${diagnisis_shortenValue(map.values().next().value)}. Path: ${diagnosis_path}`); };
|
|
56
|
+
//@ts-ignore
|
|
57
|
+
const value = obj[mode.propName];
|
|
58
|
+
if (value === undefined || value === null) {
|
|
59
|
+
if (mode.map.size > 0) {
|
|
60
|
+
throwInconsistent(mode.map);
|
|
61
|
+
}
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
if (!(typeof value === "number" || typeof value === "string")) {
|
|
65
|
+
throw new PreserveError(`${mode.propName} must be a number or a string. ${diagnosis_getErrorDiag()}`);
|
|
66
|
+
}
|
|
67
|
+
// safety check:
|
|
68
|
+
if (mode.map.size == 0 && mode.diag_other.size > 0) {
|
|
69
|
+
throwInconsistent(mode.diag_other);
|
|
70
|
+
}
|
|
71
|
+
//@ts-ignore
|
|
72
|
+
result[mode.propName] = value;
|
|
73
|
+
}
|
|
74
|
+
if (result.id === undefined && result.key === undefined) {
|
|
75
|
+
throw new PreserveError(`Object has no id or key set. ${diagnosis_getErrorDiag()}. Please specify 'id' or 'key' property or both on your data objects when using them in an Array/Set/Map`);
|
|
76
|
+
}
|
|
77
|
+
return result;
|
|
78
|
+
}
|
|
79
|
+
register(value, diagnosis_path) {
|
|
80
|
+
if (value === null || typeof value !== "object") { // not an object
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
let idAndKey = this.getIdAndKey(value, diagnosis_path);
|
|
84
|
+
const idAndKeyString = this.idAndKeyToString(idAndKey);
|
|
85
|
+
const existing = this.objectsByIdAndKey.get(idAndKeyString);
|
|
86
|
+
if (existing !== undefined && existing !== value) {
|
|
87
|
+
throw new PreserveError(`Multiple items in an array have the same id+key: ${diagnisis_shortenValue(idAndKey)}. Path: ${diagnosis_path}.\n${normalizeListsHint}`);
|
|
88
|
+
}
|
|
89
|
+
// Add to maps:
|
|
90
|
+
this.objectsByIdAndKey.set(idAndKeyString, value);
|
|
91
|
+
if (idAndKey.id !== undefined) {
|
|
92
|
+
this.objectsById.set(idAndKey.id, value);
|
|
93
|
+
}
|
|
94
|
+
if (idAndKey.key !== undefined) {
|
|
95
|
+
this.objectsByKey.set(idAndKey.key, value);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
get(value, diagnosis_path) {
|
|
99
|
+
return this.objectsByIdAndKey.get(this.idAndKeyToString(this.getIdAndKey(value, diagnosis_path)));
|
|
100
|
+
}
|
|
101
|
+
getPreserved(newValue, call, diagnosis_path) {
|
|
102
|
+
if (newValue === undefined || newValue === null || typeof newValue !== "object") { // newValue is no object ?
|
|
103
|
+
return newValue;
|
|
104
|
+
}
|
|
105
|
+
const existing = this.get(newValue, diagnosis_path);
|
|
106
|
+
return preserve_inner(existing, newValue, call, diagnosis_path);
|
|
107
|
+
}
|
|
108
|
+
idAndKeyToString(ik) {
|
|
109
|
+
return `${ik.id}_${ik.key}`;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
function preserve(oldValue, newValue, options = {}) {
|
|
113
|
+
return _preserve(oldValue, newValue, options);
|
|
114
|
+
}
|
|
115
|
+
function _preserve(oldValue, newValue, options, diagnosis) {
|
|
116
|
+
let call = new PreserveCall(options, diagnosis);
|
|
117
|
+
let result = preserve_inner(oldValue, newValue, call, "<root>");
|
|
118
|
+
// Invalidate obsolete objects
|
|
119
|
+
if (options.destroyObsolete !== false && call.possiblyObsoleteObjects.size > 0) {
|
|
120
|
+
const obsoleteCause = (diagnosis === null || diagnosis === void 0 ? void 0 : diagnosis.callStack) || new Error("Preserve was called");
|
|
121
|
+
call.possiblyObsoleteObjects.forEach(obj => {
|
|
122
|
+
if (call.usedObjects.has(obj)) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
try {
|
|
126
|
+
(0, proxy_facades_1.invalidateObject)(obj, "This object is obsolete. Another object is used in its place (which has all values copied to it =preserved), to keep constant object identities across data fetches. See cause. You can disable invalidation via the PreserveOptions#destroyObsolete flag.", obsoleteCause);
|
|
127
|
+
}
|
|
128
|
+
catch (e) {
|
|
129
|
+
throw new Error("Error during invalidation. You should disable invalidation via the PreserveOptions#destroyObsolete flag", { cause: e });
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
return result;
|
|
134
|
+
}
|
|
135
|
+
function preserve_inner(oldValue, newValue, call, diagnosis_path) {
|
|
136
|
+
const inner = () => {
|
|
137
|
+
if (newValue === null || typeof newValue !== "object") {
|
|
138
|
+
return newValue;
|
|
139
|
+
}
|
|
140
|
+
if (call.options.preserveCircular) {
|
|
141
|
+
const preserved = call.newToPreserved.get(newValue);
|
|
142
|
+
if (preserved !== undefined) {
|
|
143
|
+
return preserved;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (!mergeable(oldValue, newValue)) {
|
|
147
|
+
return newValue;
|
|
148
|
+
}
|
|
149
|
+
// Narrow types:
|
|
150
|
+
if (oldValue === null || typeof oldValue !== "object" || newValue === null || typeof newValue !== "object") {
|
|
151
|
+
return newValue;
|
|
152
|
+
}
|
|
153
|
+
if (call.mergedToNew.has(oldValue)) { // Already merged or currently merging?
|
|
154
|
+
// Safety check:
|
|
155
|
+
if (call.mergedToNew.get(oldValue) !== newValue) {
|
|
156
|
+
throw new PreserveError(`Cannot replace object ${diagnisis_shortenValue(oldValue)} into ${diagnisis_shortenValue(newValue)} in: ${diagnosis_path}. It has already been replaced by another object: ${diagnisis_shortenValue(call.mergedToNew.get(oldValue))}. Please make your objects have a proper id or key and are not used in multiple places where these can be mistaken.\n${normalizeListsHint}`);
|
|
157
|
+
}
|
|
158
|
+
return oldValue;
|
|
159
|
+
}
|
|
160
|
+
// *** Merge: ****
|
|
161
|
+
call.mergedToNew.set(oldValue, newValue);
|
|
162
|
+
call.newToPreserved.set(newValue, oldValue);
|
|
163
|
+
if (Array.isArray(oldValue)) {
|
|
164
|
+
return preserve_array(oldValue, newValue, call, diagnosis_path);
|
|
165
|
+
}
|
|
166
|
+
else if (oldValue instanceof Set) {
|
|
167
|
+
return preserve_set(oldValue, newValue, call, diagnosis_path);
|
|
168
|
+
}
|
|
169
|
+
else if (oldValue instanceof Map) {
|
|
170
|
+
return preserve_map(oldValue, newValue, call, diagnosis_path);
|
|
171
|
+
}
|
|
172
|
+
else { // Plain objects (or class instances) ?
|
|
173
|
+
// ** merge objects **
|
|
174
|
+
// add new values:
|
|
175
|
+
for (const key of [...Object.getOwnPropertyNames(newValue), ...Object.getOwnPropertySymbols(newValue)]) { // iterate own keys of newValue
|
|
176
|
+
//@ts-ignore
|
|
177
|
+
oldValue[key] = preserve_inner(oldValue[key], newValue[key], call, diagnosis_path + diagnosis_jsonPath(key));
|
|
178
|
+
}
|
|
179
|
+
// remove keys not in newValue:
|
|
180
|
+
for (const key of [...Object.getOwnPropertyNames(oldValue), ...Object.getOwnPropertySymbols(oldValue)]) { // iterate own keys of oldValue
|
|
181
|
+
//@ts-ignore
|
|
182
|
+
if (Object.getOwnPropertyDescriptor(newValue, key) === undefined && newValue[key] === undefined) {
|
|
183
|
+
//@ts-ignore
|
|
184
|
+
(0, proxy_facades_1.deleteProperty)(oldValue, key);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return oldValue;
|
|
189
|
+
};
|
|
190
|
+
const result = inner();
|
|
191
|
+
if (result !== newValue) { // old was preserved
|
|
192
|
+
call.possiblyObsoleteObjects.add(newValue);
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
call.markUsed(newValue);
|
|
196
|
+
}
|
|
197
|
+
return result;
|
|
198
|
+
}
|
|
199
|
+
function preserve_array(oldArray, newArray, call, diagnosis_path) {
|
|
200
|
+
const oldObjectRegistry = new ObjRegistry(call.options);
|
|
201
|
+
oldArray.forEach((v, i) => oldObjectRegistry.register(v, `${diagnosis_path}[${i}]`));
|
|
202
|
+
const indicesInNewArray = new Set();
|
|
203
|
+
for (let i in newArray) {
|
|
204
|
+
indicesInNewArray.add(i);
|
|
205
|
+
const newValue = newArray[i];
|
|
206
|
+
oldArray[i] = oldObjectRegistry.getPreserved(newValue, call, `${diagnosis_path}[${i}]`);
|
|
207
|
+
}
|
|
208
|
+
for (let i in oldArray) {
|
|
209
|
+
if (!indicesInNewArray.has(i)) {
|
|
210
|
+
(0, proxy_facades_1.deleteProperty)(oldArray, i); // This properly deletes the key as well, so a for...in iteration works consitent. Still it does not decrease oldArray.length
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
// Fix oldArray.length:
|
|
214
|
+
while (oldArray.length > newArray.length) {
|
|
215
|
+
oldArray.pop();
|
|
216
|
+
}
|
|
217
|
+
return oldArray;
|
|
218
|
+
}
|
|
219
|
+
function preserve_set(oldSet, newSet, call, diagnosis_path) {
|
|
220
|
+
// Register old ids/keys:
|
|
221
|
+
const oldValuesRegistry = new ObjRegistry(call.options);
|
|
222
|
+
for (const value of oldSet.values()) {
|
|
223
|
+
oldValuesRegistry.register(value, `${diagnosis_path}`);
|
|
224
|
+
}
|
|
225
|
+
oldSet.clear();
|
|
226
|
+
for (const newValue of newSet.values()) {
|
|
227
|
+
oldSet.add(oldValuesRegistry.getPreserved(newValue, call, diagnosis_path));
|
|
228
|
+
}
|
|
229
|
+
return oldSet;
|
|
230
|
+
}
|
|
231
|
+
function preserve_map(oldMap, newMap, call, diagnosis_path) {
|
|
232
|
+
// Register old ids/keys:
|
|
233
|
+
const oldKeysRegistry = new ObjRegistry(call.options);
|
|
234
|
+
for (const key of oldMap.keys()) {
|
|
235
|
+
oldKeysRegistry.register(key, `${diagnosis_path}`);
|
|
236
|
+
}
|
|
237
|
+
const oldValuesRegistry = new ObjRegistry(call.options);
|
|
238
|
+
for (const value of oldMap.values()) {
|
|
239
|
+
oldValuesRegistry.register(value, `${diagnosis_path}`);
|
|
240
|
+
}
|
|
241
|
+
oldMap.clear();
|
|
242
|
+
for (let newKey of newMap.keys()) {
|
|
243
|
+
let newValue = newMap.get(newKey);
|
|
244
|
+
oldMap.set(oldKeysRegistry.getPreserved(newKey, call, diagnosis_path), oldValuesRegistry.getPreserved(newValue, call, `${diagnosis_path}[${diagnisis_shortenValue(newKey)}]`));
|
|
245
|
+
}
|
|
246
|
+
return oldMap;
|
|
247
|
+
}
|
|
248
|
+
function isSameObjectType(a, b) {
|
|
249
|
+
return Object.getPrototypeOf(a) === Object.getPrototypeOf(b) || a.constructor === b.constructor;
|
|
250
|
+
}
|
|
251
|
+
function diagnosis_jsonPath(key) {
|
|
252
|
+
if (!Number.isNaN(Number(key))) {
|
|
253
|
+
return `[${key}]`;
|
|
254
|
+
}
|
|
255
|
+
return `.${key}`;
|
|
256
|
+
}
|
|
257
|
+
class PreserveError extends Error {
|
|
258
|
+
}
|
|
259
|
+
function diagnisis_shortenValue(evil_value) {
|
|
260
|
+
var _a, _b, _c;
|
|
261
|
+
if (evil_value === undefined) {
|
|
262
|
+
return "undefined";
|
|
263
|
+
}
|
|
264
|
+
if (evil_value === null) {
|
|
265
|
+
return "null";
|
|
266
|
+
}
|
|
267
|
+
let objPrefix = "";
|
|
268
|
+
if (typeof evil_value == "object" && ((_a = evil_value.constructor) === null || _a === void 0 ? void 0 : _a.name) && ((_b = evil_value.constructor) === null || _b === void 0 ? void 0 : _b.name) !== "Object") {
|
|
269
|
+
objPrefix = `class ${(_c = evil_value.constructor) === null || _c === void 0 ? void 0 : _c.name} `;
|
|
270
|
+
}
|
|
271
|
+
function shorten(value) {
|
|
272
|
+
const MAX = 50;
|
|
273
|
+
if (value.length > MAX) {
|
|
274
|
+
return value.substring(0, MAX) + "...";
|
|
275
|
+
}
|
|
276
|
+
return value;
|
|
277
|
+
}
|
|
278
|
+
try {
|
|
279
|
+
return shorten(objPrefix + betterJsonStringify(evil_value));
|
|
280
|
+
}
|
|
281
|
+
catch (e) {
|
|
282
|
+
}
|
|
283
|
+
if (typeof evil_value == "string") {
|
|
284
|
+
return shorten(evil_value);
|
|
285
|
+
}
|
|
286
|
+
else if (typeof evil_value == "object") {
|
|
287
|
+
return `${objPrefix}{...}`;
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
290
|
+
return "unknown";
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Like JSON.stringify, but support for some additional types.
|
|
294
|
+
*
|
|
295
|
+
* @param value
|
|
296
|
+
*/
|
|
297
|
+
function betterJsonStringify(value) {
|
|
298
|
+
return JSON.stringify(value, (key, val) => {
|
|
299
|
+
if (val === undefined) {
|
|
300
|
+
return "undefined";
|
|
301
|
+
}
|
|
302
|
+
else if (typeof val === 'number' && isNaN(val)) {
|
|
303
|
+
return "NaN";
|
|
304
|
+
}
|
|
305
|
+
else if (val !== null && JSON.stringify(val) === "null") {
|
|
306
|
+
return "-unknown type-";
|
|
307
|
+
}
|
|
308
|
+
else if (val instanceof Set) {
|
|
309
|
+
return "-Set(...)-";
|
|
310
|
+
}
|
|
311
|
+
else if (val instanceof Map) {
|
|
312
|
+
return "-Map(...)-";
|
|
313
|
+
}
|
|
314
|
+
else if (val instanceof RegExp) {
|
|
315
|
+
return "-Regexp(...)-";
|
|
316
|
+
}
|
|
317
|
+
return val;
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
function mergeable(oldValue, newValue) {
|
|
322
|
+
// Return if both are not compatible objects:
|
|
323
|
+
if (oldValue === undefined || oldValue === null || typeof oldValue !== "object") { // oldValue is no object ?
|
|
324
|
+
return false;
|
|
325
|
+
}
|
|
326
|
+
if (newValue === undefined || newValue === null || typeof newValue !== "object") { // new is no object ?
|
|
327
|
+
return false;
|
|
328
|
+
}
|
|
329
|
+
if (!isSameObjectType(oldValue, newValue)) {
|
|
330
|
+
return false;
|
|
331
|
+
}
|
|
332
|
+
if (oldValue === newValue) {
|
|
333
|
+
return false; // nothing to do
|
|
334
|
+
}
|
|
335
|
+
if (newValue instanceof WeakSet) {
|
|
336
|
+
return false; // Merging unsupported
|
|
337
|
+
}
|
|
338
|
+
else if (newValue instanceof WeakMap) {
|
|
339
|
+
return false; // Merging unsupported
|
|
340
|
+
}
|
|
341
|
+
return true;
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
*
|
|
345
|
+
* Scans root deeply for Arrays and for each found array, it call normalizeList, which squeezes the items with the same id/key into one object instance.
|
|
346
|
+
* @see normalizeList
|
|
347
|
+
* @param root
|
|
348
|
+
* @param options
|
|
349
|
+
*/
|
|
350
|
+
function normalizeLists(root, options = {}) {
|
|
351
|
+
return (0, Util_1.visitReplace)(root, (value, visitChilds, context) => {
|
|
352
|
+
if (Array.isArray(value)) {
|
|
353
|
+
normalizeList(value, options, context.diagnosis_path);
|
|
354
|
+
}
|
|
355
|
+
return visitChilds(value, context);
|
|
356
|
+
}, "onError");
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Squeezes the items with the same id/key into one object instance.
|
|
360
|
+
* @param list
|
|
361
|
+
* @param options
|
|
362
|
+
* @param diagnosis_path internal
|
|
363
|
+
*/
|
|
364
|
+
function normalizeList(list, options = {}, diagnosis_path) {
|
|
365
|
+
const objRegistry = new ObjRegistry(options);
|
|
366
|
+
for (let i in list) {
|
|
367
|
+
const value = list[i];
|
|
368
|
+
if (value === null || typeof value !== "object") { // value is no object ?
|
|
369
|
+
continue;
|
|
370
|
+
}
|
|
371
|
+
let existing = objRegistry.get(value, diagnosis_path || "<list>");
|
|
372
|
+
if (existing !== undefined) {
|
|
373
|
+
// Safety check:
|
|
374
|
+
if (!options.normalize_ignoreDifferent && !underscore_1.default.isEqual(existing, value)) {
|
|
375
|
+
throw new Error(`Array-items at indexes ${list.findIndex(v => v === existing)} and ${i} have the same id/key but different content: ${diagnisis_shortenValue(existing)} vs. ${diagnisis_shortenValue(value)} Path: ${diagnosis_path}. You can set the normalize_ignoreDifferent option to ignore this.`);
|
|
376
|
+
}
|
|
377
|
+
//@ts-ignore
|
|
378
|
+
list[i] = existing;
|
|
379
|
+
continue;
|
|
380
|
+
}
|
|
381
|
+
objRegistry.register(value, diagnosis_path || "<list>");
|
|
382
|
+
}
|
|
383
|
+
return list;
|
|
384
|
+
}
|
|
385
|
+
//# sourceMappingURL=preserve.js.map
|
package/preserve.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preserve.js","sourceRoot":"","sources":["preserve.ts"],"names":[],"mappings":"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"}
|