@astrale-os/kernel-dsl 0.2.0-beta.36 → 0.2.0-beta.38

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.
Files changed (58) hide show
  1. package/dist/v1/builder/core/authoring.d.ts +7 -2
  2. package/dist/v1/builder/lowering/schema/context.d.ts +9 -4
  3. package/dist/v1/builder/lowering/schema/context.js +20 -20
  4. package/dist/v1/builder/policy/authoring.d.ts +6 -6
  5. package/dist/v1/builder/policy/authoring.js +3 -1
  6. package/dist/v1/compiled/admission/accept.js +97 -18
  7. package/dist/v1/compiled/admission/semantics.js +77 -24
  8. package/dist/v1/compiled/compiler/compile.js +23 -7
  9. package/dist/v1/compiled/loader/load.d.ts +11 -2
  10. package/dist/v1/compiled/loader/load.js +4 -1
  11. package/dist/v1/compiled/model/schema.d.ts +5 -4
  12. package/dist/v1/domain/create.js +17 -9
  13. package/dist/v1/index.d.ts +1 -1
  14. package/dist/v1/language/class/property-values.js +5 -2
  15. package/dist/v1/language/core/model/core.d.ts +7 -1
  16. package/dist/v1/language/core/resolved.d.ts +6 -2
  17. package/dist/v1/language/index.d.ts +1 -1
  18. package/dist/v1/language/index.js +1 -1
  19. package/dist/v1/language/policy/index.d.ts +1 -1
  20. package/dist/v1/language/policy/index.js +1 -1
  21. package/dist/v1/language/policy/model/policy.d.ts +1 -0
  22. package/dist/v1/language/policy/model/policy.js +17 -0
  23. package/dist/v1/language/value/compile/fields.d.ts +1 -1
  24. package/dist/v1/language/value/compile/load.d.ts +4 -2
  25. package/dist/v1/language/value/compile/load.js +22 -1
  26. package/dist/v1/language/value/compile/model.d.ts +16 -1
  27. package/dist/v1/language/value/evaluate/assertions.d.ts +2 -0
  28. package/dist/v1/language/value/evaluate/assertions.js +13 -0
  29. package/dist/v1/language/value/evaluate/evaluator.js +12 -7
  30. package/dist/v1/language/value/evaluate/preparation.d.ts +10 -1
  31. package/dist/v1/language/value/evaluate/preparation.js +17 -26
  32. package/dist/v1/language/value/evaluate/program.js +1 -1
  33. package/dist/v1/language/value/evaluate/validate.d.ts +6 -2
  34. package/dist/v1/language/value/evaluate/validate.js +18 -11
  35. package/dist/v1/language/value/ordering.d.ts +2 -0
  36. package/dist/v1/language/value/ordering.js +4 -8
  37. package/dist/v1/language/value/profile/json.validate.js +1 -1
  38. package/dist/v1/language/value/regexp/compile.d.ts +3 -3
  39. package/dist/v1/language/value/regexp/compile.js +56 -11
  40. package/dist/v1/language/value/regexp/matcher.d.ts +3 -3
  41. package/dist/v1/language/value/regexp/matcher.js +75 -3
  42. package/dist/v1/schema/compatibility/footprint.js +6 -5
  43. package/dist/v1/schema/normalization/domain.js +15 -1
  44. package/dist/v1/schema/resolution/domain.js +17 -10
  45. package/dist/v1/schema/resolution/origins.d.ts +3 -0
  46. package/dist/v1/schema/resolution/origins.js +12 -4
  47. package/dist/v1/schema/validation/core.js +78 -26
  48. package/dist/v1/schema/validation/domain.structure.js +7 -2
  49. package/dist/value/accept.d.ts +9 -0
  50. package/dist/value/accept.js +78 -5
  51. package/dist/value/canonical.js +2 -2
  52. package/dist/value/immutable.optimization.d.ts +12 -0
  53. package/dist/value/immutable.optimization.js +28 -0
  54. package/dist/value/index.d.ts +1 -1
  55. package/dist/value/index.js +1 -1
  56. package/dist/value/unicode.d.ts +1 -1
  57. package/dist/value/unicode.js +1 -0
  58. package/package.json +1 -1
@@ -1,4 +1,5 @@
1
1
  import { BoundaryError } from './error.js';
2
+ import { includeSnapshot, retainImmutableSnapshot, reusableSnapshot, } from './immutable.optimization.js';
2
3
  import { limitsFor } from './limits.js';
3
4
  import { assertHostString } from './unicode.js';
4
5
  /**
@@ -7,9 +8,45 @@ import { assertHostString } from './unicode.js';
7
8
  * Every source property is obtained from one descriptor snapshot. Accessors are never invoked.
8
9
  */
9
10
  export function accept(input, options) {
10
- const state = { active: new WeakSet(), limits: limitsFor(options), members: 0 };
11
+ return snapshot(input, options, 'copy');
12
+ }
13
+ /** Admit unknown data into a deeply immutable snapshot; owned subtrees may be shared. */
14
+ export function acceptImmutable(input, options) {
15
+ const captured = { propertyRoots: false };
16
+ const value = snapshot(input, options, 'immutable', captured);
17
+ if (value !== null && typeof value === 'object') {
18
+ retainImmutableSnapshot(value, captured.summary);
19
+ }
20
+ return value;
21
+ }
22
+ /** Admit a read-only snapshot, sharing owned immutable subtrees without freezing new wrappers. */
23
+ export function acceptForRead(input, options) {
24
+ return snapshot(input, options, 'read');
25
+ }
26
+ /**
27
+ * Private PropertyValues owner seam. Retain immediate recursive values, not the enclosing
28
+ * dictionary: its canonical coordinates are re-admitted by the Property owner on every use.
29
+ */
30
+ export function acceptPropertyRoot(input) {
31
+ return snapshot(input, undefined, 'immutable', { propertyRoots: true });
32
+ }
33
+ function snapshot(input, options, mode, captured) {
34
+ const state = {
35
+ active: new WeakSet(),
36
+ limits: limitsFor(options),
37
+ members: 0,
38
+ mode,
39
+ summary: mode === 'immutable' && !captured?.propertyRoots
40
+ ? { members: 0, depth: 0, stringBytes: 0 }
41
+ : undefined,
42
+ summaryDepth: 0,
43
+ propertyRoots: captured?.propertyRoots ?? false,
44
+ };
11
45
  try {
12
- return admit(input, '', 0, state);
46
+ const value = admit(input, '', 0, state);
47
+ if (captured !== undefined)
48
+ captured.summary = state.summary;
49
+ return value;
13
50
  }
14
51
  catch (error) {
15
52
  if (error instanceof BoundaryError)
@@ -30,12 +67,20 @@ function admit(input, pointer, depth, state) {
30
67
  return input;
31
68
  }
32
69
  if (typeof input === 'string') {
33
- assertHostString(input, pointer, state.limits.maxStringBytes);
70
+ admitString(input, pointer, state);
34
71
  return input;
35
72
  }
36
73
  if (typeof input !== 'object') {
37
74
  throw new BoundaryError('VALUE_TYPE', 'Expected a portable value', pointer);
38
75
  }
76
+ if (state.mode !== 'copy' && !(state.propertyRoots && depth === 0)) {
77
+ const summary = reusableSnapshot(input, state.limits, depth, state.members);
78
+ if (summary !== undefined) {
79
+ state.members += summary.members;
80
+ includeSnapshot(state.summary, summary, depth - state.summaryDepth);
81
+ return input;
82
+ }
83
+ }
39
84
  if (state.active.has(input)) {
40
85
  throw new BoundaryError('VALUE_CYCLE', 'Cyclic object graphs are not portable values', pointer);
41
86
  }
@@ -43,13 +88,33 @@ function admit(input, pointer, depth, state) {
43
88
  throw new BoundaryError('VALUE_LIMIT', `Container depth exceeds the ${state.limits.maxDepth}-level limit`, pointer);
44
89
  }
45
90
  state.active.add(input);
91
+ const parent = state.summary;
92
+ const parentDepth = state.summaryDepth;
93
+ const propertyRoot = state.mode === 'immutable' && state.propertyRoots && depth === 1;
94
+ if (propertyRoot) {
95
+ state.summary = { members: 0, depth: 0, stringBytes: 0 };
96
+ state.summaryDepth = depth;
97
+ }
98
+ if (state.summary !== undefined) {
99
+ state.summary.depth = Math.max(state.summary.depth, depth + 1 - state.summaryDepth);
100
+ }
46
101
  try {
47
- return reflect(() => Array.isArray(input), pointer, 'Cannot inspect the host value brand')
102
+ const output = reflect(() => Array.isArray(input), pointer, 'Cannot inspect the host value brand')
48
103
  ? admitArray(input, pointer, depth + 1, state)
49
104
  : admitObject(input, pointer, depth + 1, state);
105
+ if (state.mode === 'immutable') {
106
+ Object.freeze(output);
107
+ if (propertyRoot) {
108
+ retainImmutableSnapshot(output, state.summary);
109
+ includeSnapshot(parent, state.summary, depth - parentDepth);
110
+ }
111
+ }
112
+ return output;
50
113
  }
51
114
  finally {
52
115
  state.active.delete(input);
116
+ state.summary = parent;
117
+ state.summaryDepth = parentDepth;
53
118
  }
54
119
  }
55
120
  function admitArray(input, pointer, depth, state) {
@@ -92,7 +157,7 @@ function admitObject(input, pointer, depth, state) {
92
157
  throw new BoundaryError('VALUE_OBJECT', 'Portable Objects cannot have symbol members', pointer);
93
158
  }
94
159
  const memberPointer = child(pointer, key);
95
- assertHostString(key, memberPointer, state.limits.maxStringBytes);
160
+ admitString(key, memberPointer, state);
96
161
  const descriptor = ownDescriptor(descriptors, key);
97
162
  if (descriptor === undefined || !descriptor.enumerable || !('value' in descriptor)) {
98
163
  throw new BoundaryError('VALUE_OBJECT', 'Object members must be enumerable data properties', memberPointer);
@@ -115,10 +180,18 @@ function ownDescriptor(descriptors, name) {
115
180
  }
116
181
  function addMembers(state, count, pointer) {
117
182
  state.members += count;
183
+ if (state.summary !== undefined)
184
+ state.summary.members += count;
118
185
  if (state.members > state.limits.maxMembers) {
119
186
  throw new BoundaryError('VALUE_LIMIT', `Value exceeds the ${state.limits.maxMembers}-member limit`, pointer);
120
187
  }
121
188
  }
189
+ function admitString(value, pointer, state) {
190
+ const bytes = assertHostString(value, pointer, state.limits.maxStringBytes);
191
+ if (state.summary !== undefined) {
192
+ state.summary.stringBytes = Math.max(state.summary.stringBytes, bytes);
193
+ }
194
+ }
122
195
  function reflect(operation, pointer, message) {
123
196
  try {
124
197
  return operation();
@@ -1,4 +1,4 @@
1
- import { accept } from './accept.js';
1
+ import { acceptForRead } from './accept.js';
2
2
  import { BoundaryError } from './error.js';
3
3
  import { defaultLimits, limitsFor } from './limits.js';
4
4
  import { utf8Length } from './unicode.js';
@@ -6,7 +6,7 @@ const encoder = new TextEncoder();
6
6
  /** RFC 8785 canonical JSON for one admitted portable snapshot. */
7
7
  export function serialize(input, options) {
8
8
  const limits = limitsFor(options);
9
- return serializeSnapshot(accept(input, options), limits.maxBytes);
9
+ return serializeSnapshot(acceptForRead(input, options), limits.maxBytes);
10
10
  }
11
11
  /** Serialize a trusted portable value whose default structural admission proof is still valid. */
12
12
  export function serializeAdmitted(input) {
@@ -0,0 +1,12 @@
1
+ import type { Limits } from './limits.js';
2
+ export interface SnapshotSummary {
3
+ members: number;
4
+ depth: number;
5
+ stringBytes: number;
6
+ }
7
+ export declare function isImmutableSnapshot(value: object): boolean;
8
+ /** Called only after admission has constructed and deeply frozen this container. */
9
+ export declare function retainImmutableSnapshot(value: object, summary: SnapshotSummary): void;
10
+ export declare function includeSnapshot(parent: SnapshotSummary | undefined, child: SnapshotSummary, depth: number): void;
11
+ /** A failed fit must use normal admission, preserving its exact error pointer. */
12
+ export declare function reusableSnapshot(value: object, limits: Limits, depth: number, members: number): SnapshotSummary | undefined;
@@ -0,0 +1,28 @@
1
+ // Only admission-owned, deeply immutable snapshots enter this table. A frozen
2
+ // caller object is not a proof. Weak identity ownership retains no caller data.
3
+ const snapshots = new WeakMap();
4
+ export function isImmutableSnapshot(value) {
5
+ return snapshots.has(value);
6
+ }
7
+ /** Called only after admission has constructed and deeply frozen this container. */
8
+ export function retainImmutableSnapshot(value, summary) {
9
+ if (!snapshots.has(value))
10
+ snapshots.set(value, summary);
11
+ }
12
+ export function includeSnapshot(parent, child, depth) {
13
+ if (parent === undefined)
14
+ return;
15
+ parent.members += child.members;
16
+ parent.depth = Math.max(parent.depth, depth + child.depth);
17
+ parent.stringBytes = Math.max(parent.stringBytes, child.stringBytes);
18
+ }
19
+ /** A failed fit must use normal admission, preserving its exact error pointer. */
20
+ export function reusableSnapshot(value, limits, depth, members) {
21
+ const summary = snapshots.get(value);
22
+ if (summary === undefined ||
23
+ summary.members > limits.maxMembers - members ||
24
+ summary.depth > limits.maxDepth - depth ||
25
+ summary.stringBytes > limits.maxStringBytes)
26
+ return undefined;
27
+ return summary;
28
+ }
@@ -1,5 +1,5 @@
1
1
  /** Portable values shared by the DSL and kernel contracts. */
2
- export { accept } from './accept.js';
2
+ export { accept, acceptForRead, acceptImmutable } from './accept.js';
3
3
  export { equal } from './equal.js';
4
4
  export { BoundaryError, DecodeError } from './error.js';
5
5
  export type { BoundaryErrorCode, DecodeErrorCode } from './error.js';
@@ -1,5 +1,5 @@
1
1
  /** Portable values shared by the DSL and kernel contracts. */
2
- export { accept } from './accept.js';
2
+ export { accept, acceptForRead, acceptImmutable } from './accept.js';
3
3
  export { equal } from './equal.js';
4
4
  export { BoundaryError, DecodeError } from './error.js';
5
5
  export { defaultLimits } from './limits.js';
@@ -1,4 +1,4 @@
1
1
  export declare function utf8Length(value: string, max?: number): number;
2
- export declare function assertHostString(value: string, pointer: string, maxBytes: number): void;
2
+ export declare function assertHostString(value: string, pointer: string, maxBytes: number): number;
3
3
  export declare function assertDecodedString(value: string, offset: number, maxBytes: number): void;
4
4
  export declare function assertSourceString(value: string, maxBytes: number): void;
@@ -34,6 +34,7 @@ export function assertHostString(value, pointer, maxBytes) {
34
34
  if (length > maxBytes) {
35
35
  throw new BoundaryError('VALUE_LIMIT', `String exceeds the ${maxBytes}-byte UTF-8 limit`, pointer);
36
36
  }
37
+ return length;
37
38
  }
38
39
  export function assertDecodedString(value, offset, maxBytes) {
39
40
  if (value.includes('\u0000')) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astrale-os/kernel-dsl",
3
- "version": "0.2.0-beta.36",
3
+ "version": "0.2.0-beta.38",
4
4
  "description": "Astrale Kernel DSL - Schema authoring, inference, and IR serialization",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {