@jarenjs/forms 0.86.0 → 0.89.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/README.md +2 -0
- package/dist/types/rules.d.ts +4 -2
- package/package.json +5 -5
- package/src/deps.js +7 -3
- package/src/rules.js +7 -4
package/README.md
CHANGED
|
@@ -451,6 +451,8 @@ paths in its query documents (plus its own location). That over-approximates
|
|
|
451
451
|
every read, and soundly: the only way into the document is such a path, and a
|
|
452
452
|
`$let`/`$for` variable can only hold what one of them produced.
|
|
453
453
|
|
|
454
|
+
Nested filters contribute their root reads too. Replacing the compiled rule set
|
|
455
|
+
invalidates the memo's results and template keys, even when the data is unchanged.
|
|
454
456
|
The memo diffs the previous document against the new one — reference-equal
|
|
455
457
|
subtrees are skipped whole, so an immutable edit costs O(change). A host that
|
|
456
458
|
already knows what it wrote can skip even that with `memo.touch(pointer)`,
|
package/dist/types/rules.d.ts
CHANGED
|
@@ -127,6 +127,7 @@ export declare function evaluateFormRules(compiled: CompiledRules, data: any, ca
|
|
|
127
127
|
export type RuleMemo = {
|
|
128
128
|
data: any;
|
|
129
129
|
catalog: any;
|
|
130
|
+
compiled?: CompiledRules | null;
|
|
130
131
|
results: Record<string, RuleResult> | null;
|
|
131
132
|
keys: string[][] | null;
|
|
132
133
|
/**
|
|
@@ -144,6 +145,7 @@ export type RuleMemo = {
|
|
|
144
145
|
* @typedef {object} RuleMemo
|
|
145
146
|
* @property {any} data
|
|
146
147
|
* @property {any} catalog
|
|
148
|
+
* @property {CompiledRules|null} [compiled]
|
|
147
149
|
* @property {Record<string, RuleResult>|null} results
|
|
148
150
|
* @property {string[][]|null} keys
|
|
149
151
|
* @property {string[]|null} touched - Pointers declared through
|
|
@@ -152,8 +154,8 @@ export type RuleMemo = {
|
|
|
152
154
|
*/
|
|
153
155
|
/**
|
|
154
156
|
* Create an empty rule memo. One per form session: it is bound to the
|
|
155
|
-
* document lineage
|
|
156
|
-
*
|
|
157
|
+
* document lineage and compiled rules it has seen. Switching compiled
|
|
158
|
+
* rules rebuilds the memo, including the keys written by item templates.
|
|
157
159
|
*
|
|
158
160
|
* `memo.touch(pointer)` declares a write before the next evaluation.
|
|
159
161
|
* It is an optimization AND a promise: the evaluation then trusts the
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jarenjs/forms",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.89.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.js",
|
|
7
7
|
"types": "./dist/types/index.d.ts",
|
|
@@ -47,9 +47,9 @@
|
|
|
47
47
|
"prepack": "npm run build:types"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@jarenjs/core": "^0.
|
|
51
|
-
"@jarenjs/formats": "^0.
|
|
52
|
-
"@jarenjs/json": "^0.
|
|
53
|
-
"@jarenjs/validate": "^0.
|
|
50
|
+
"@jarenjs/core": "^0.89.0",
|
|
51
|
+
"@jarenjs/formats": "^0.89.0",
|
|
52
|
+
"@jarenjs/json": "^0.89.0",
|
|
53
|
+
"@jarenjs/validate": "^0.89.0"
|
|
54
54
|
}
|
|
55
55
|
}
|
package/src/deps.js
CHANGED
|
@@ -137,7 +137,12 @@ function addPath(source, out) {
|
|
|
137
137
|
catch {
|
|
138
138
|
return; // a variable-rooted path, or not a path at all
|
|
139
139
|
}
|
|
140
|
-
|
|
140
|
+
collectPathQueries(ast, out);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** Visit every nested filter, including those on a relative query. */
|
|
144
|
+
function collectPathQueries(ast, out) {
|
|
145
|
+
if (ast.relative !== true) out.add(prefixOf(ast.segments));
|
|
141
146
|
for (const segment of ast.segments) {
|
|
142
147
|
for (const selector of segment.selectors) {
|
|
143
148
|
if (selector.kind === 'filter') collectFilterQueries(selector.expr, out);
|
|
@@ -168,8 +173,7 @@ function prefixOf(segments) {
|
|
|
168
173
|
function collectFilterQueries(node, out) {
|
|
169
174
|
if (node === null || typeof node !== 'object') return;
|
|
170
175
|
if (node.query !== undefined && Array.isArray(node.query.segments)) {
|
|
171
|
-
|
|
172
|
-
else collectFilterQueries(node.query, out);
|
|
176
|
+
collectPathQueries(node.query, out);
|
|
173
177
|
}
|
|
174
178
|
for (const key of ['operands', 'operand', 'left', 'right', 'args', 'expr']) {
|
|
175
179
|
const child = node[key];
|
package/src/rules.js
CHANGED
|
@@ -416,8 +416,8 @@ function expandItemRule(rule, data, node, partIndex, pointer, ext, results, cata
|
|
|
416
416
|
*/
|
|
417
417
|
export function evaluateFormRules(compiled, data, catalog = undefined, memo = undefined) {
|
|
418
418
|
const rules = compiled.rules;
|
|
419
|
-
//
|
|
420
|
-
const reuse = memo !== undefined && memo.results !== null && memo.catalog === catalog;
|
|
419
|
+
// A rule-set or catalog swap invalidates the entire result map and its keys.
|
|
420
|
+
const reuse = memo !== undefined && memo.results !== null && memo.catalog === catalog && memo.compiled === compiled;
|
|
421
421
|
// A declared write is taken at its word; otherwise the documents are
|
|
422
422
|
// diffed. Diffing is the honest default — it needs nothing from the
|
|
423
423
|
// caller — but it must scan the members of every container that
|
|
@@ -473,6 +473,7 @@ export function evaluateFormRules(compiled, data, catalog = undefined, memo = un
|
|
|
473
473
|
if (memo !== undefined) {
|
|
474
474
|
memo.data = data;
|
|
475
475
|
memo.catalog = catalog;
|
|
476
|
+
memo.compiled = compiled;
|
|
476
477
|
memo.results = results;
|
|
477
478
|
memo.keys = keys;
|
|
478
479
|
}
|
|
@@ -498,6 +499,7 @@ function evaluateRule(rule, data, ext, results, catalog, written) {
|
|
|
498
499
|
* @typedef {object} RuleMemo
|
|
499
500
|
* @property {any} data
|
|
500
501
|
* @property {any} catalog
|
|
502
|
+
* @property {CompiledRules|null} [compiled]
|
|
501
503
|
* @property {Record<string, RuleResult>|null} results
|
|
502
504
|
* @property {string[][]|null} keys
|
|
503
505
|
* @property {string[]|null} touched - Pointers declared through
|
|
@@ -507,8 +509,8 @@ function evaluateRule(rule, data, ext, results, catalog, written) {
|
|
|
507
509
|
|
|
508
510
|
/**
|
|
509
511
|
* Create an empty rule memo. One per form session: it is bound to the
|
|
510
|
-
* document lineage
|
|
511
|
-
*
|
|
512
|
+
* document lineage and compiled rules it has seen. Switching compiled
|
|
513
|
+
* rules rebuilds the memo, including the keys written by item templates.
|
|
512
514
|
*
|
|
513
515
|
* `memo.touch(pointer)` declares a write before the next evaluation.
|
|
514
516
|
* It is an optimization AND a promise: the evaluation then trusts the
|
|
@@ -526,6 +528,7 @@ export function createRuleMemo() {
|
|
|
526
528
|
const memo = {
|
|
527
529
|
data: undefined,
|
|
528
530
|
catalog: undefined,
|
|
531
|
+
compiled: null,
|
|
529
532
|
results: null,
|
|
530
533
|
keys: null,
|
|
531
534
|
touched: null,
|