@optique/core 1.0.0-dev.1901 → 1.0.0-dev.1970

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 (77) hide show
  1. package/dist/annotation-state.cjs +115 -60
  2. package/dist/annotation-state.d.cts +24 -0
  3. package/dist/annotation-state.d.ts +24 -0
  4. package/dist/annotation-state.js +114 -60
  5. package/dist/annotations.cjs +2 -267
  6. package/dist/annotations.d.cts +2 -152
  7. package/dist/annotations.d.ts +2 -152
  8. package/dist/annotations.js +2 -256
  9. package/dist/completion.d.cts +1 -1
  10. package/dist/completion.d.ts +1 -1
  11. package/dist/constructs.cjs +206 -238
  12. package/dist/constructs.d.cts +1 -1
  13. package/dist/constructs.d.ts +1 -1
  14. package/dist/constructs.js +96 -128
  15. package/dist/context.d.cts +1 -1
  16. package/dist/context.d.ts +1 -1
  17. package/dist/dependency-metadata.cjs +1 -1
  18. package/dist/dependency-metadata.d.cts +1 -1
  19. package/dist/dependency-metadata.d.ts +1 -1
  20. package/dist/dependency-metadata.js +1 -1
  21. package/dist/dependency-runtime.cjs +2 -2
  22. package/dist/dependency-runtime.js +2 -2
  23. package/dist/dependency.cjs +7 -1111
  24. package/dist/dependency.d.cts +2 -838
  25. package/dist/dependency.d.ts +2 -838
  26. package/dist/dependency.js +2 -1078
  27. package/dist/execution-context.cjs +56 -0
  28. package/dist/execution-context.js +53 -0
  29. package/dist/extension.cjs +87 -0
  30. package/dist/extension.d.cts +97 -0
  31. package/dist/extension.d.ts +97 -0
  32. package/dist/extension.js +76 -0
  33. package/dist/facade.cjs +19 -19
  34. package/dist/facade.d.cts +1 -1
  35. package/dist/facade.d.ts +1 -1
  36. package/dist/facade.js +19 -19
  37. package/dist/index.cjs +4 -41
  38. package/dist/index.d.cts +7 -7
  39. package/dist/index.d.ts +7 -7
  40. package/dist/index.js +5 -5
  41. package/dist/internal/annotations.cjs +316 -0
  42. package/dist/internal/annotations.d.cts +140 -0
  43. package/dist/internal/annotations.d.ts +140 -0
  44. package/dist/internal/annotations.js +306 -0
  45. package/dist/internal/dependency.cjs +984 -0
  46. package/dist/internal/dependency.d.cts +539 -0
  47. package/dist/internal/dependency.d.ts +539 -0
  48. package/dist/internal/dependency.js +964 -0
  49. package/dist/{mode-dispatch.cjs → internal/mode-dispatch.cjs} +1 -3
  50. package/dist/{mode-dispatch.d.cts → internal/mode-dispatch.d.cts} +3 -7
  51. package/dist/{mode-dispatch.d.ts → internal/mode-dispatch.d.ts} +3 -7
  52. package/dist/{mode-dispatch.js → internal/mode-dispatch.js} +1 -3
  53. package/dist/internal/parser.cjs +728 -0
  54. package/dist/internal/parser.d.cts +947 -0
  55. package/dist/internal/parser.d.ts +947 -0
  56. package/dist/internal/parser.js +711 -0
  57. package/dist/modifiers.cjs +108 -125
  58. package/dist/modifiers.d.cts +1 -1
  59. package/dist/modifiers.d.ts +1 -1
  60. package/dist/modifiers.js +92 -109
  61. package/dist/parser.cjs +11 -743
  62. package/dist/parser.d.cts +3 -991
  63. package/dist/parser.d.ts +3 -991
  64. package/dist/parser.js +2 -704
  65. package/dist/phase2-seed.cjs +4 -4
  66. package/dist/phase2-seed.js +4 -4
  67. package/dist/primitives.cjs +39 -74
  68. package/dist/primitives.d.cts +1 -1
  69. package/dist/primitives.d.ts +1 -1
  70. package/dist/primitives.js +26 -61
  71. package/dist/program.d.cts +1 -1
  72. package/dist/program.d.ts +1 -1
  73. package/dist/valueparser.cjs +23 -23
  74. package/dist/valueparser.d.cts +3 -3
  75. package/dist/valueparser.d.ts +3 -3
  76. package/dist/valueparser.js +23 -23
  77. package/package.json +9 -9
@@ -1,5 +1,5 @@
1
- import { annotationKey, getAnnotations, inheritAnnotations, injectAnnotations, isInjectedAnnotationWrapper, unwrapInjectedAnnotationWrapper } from "./annotations.js";
2
- import { inheritParentAnnotationsKey } from "./parser.js";
1
+ import { annotationKey, getAnnotations, inheritAnnotations, injectAnnotations, isInjectedAnnotationWrapper, unwrapInjectedAnnotationWrapper } from "./internal/annotations.js";
2
+ import { inheritParentAnnotationsKey } from "./internal/parser.js";
3
3
 
4
4
  //#region src/annotation-state.ts
5
5
  /**
@@ -11,6 +11,7 @@ import { inheritParentAnnotationsKey } from "./parser.js";
11
11
  * @internal
12
12
  */
13
13
  const annotationViewTargets = /* @__PURE__ */ new WeakMap();
14
+ const delegatedAnnotationCloneTargets = /* @__PURE__ */ new WeakMap();
14
15
  /**
15
16
  * Unwraps an annotation-view proxy to its original target object.
16
17
  *
@@ -23,14 +24,18 @@ function unwrapAnnotationView(value) {
23
24
  if (value == null || typeof value !== "object") return value;
24
25
  return annotationViewTargets.get(value) ?? value;
25
26
  }
27
+ function unwrapDelegatedAnnotationClone(value) {
28
+ if (value == null || typeof value !== "object") return value;
29
+ return delegatedAnnotationCloneTargets.get(value) ?? value;
30
+ }
26
31
  /**
27
- * Creates a proxy that exposes annotations without changing the target shape.
32
+ * Creates an annotation-aware proxy without changing the target shape.
28
33
  *
29
34
  * @param state The object state to expose through an annotation-aware view.
30
35
  * @param annotations The annotations to surface through the proxy.
31
36
  * @returns A proxy over the unwrapped target object that reports the supplied
32
37
  * annotations while preserving the target's structural behavior.
33
- * @internal
38
+ * @since 1.0.0
34
39
  */
35
40
  function withAnnotationView(state, annotations) {
36
41
  const target = unwrapAnnotationView(state);
@@ -59,61 +64,90 @@ function normalizeInjectedAnnotationState(state) {
59
64
  return unwrapInjectedAnnotationWrapper(state);
60
65
  }
61
66
  function isNonPlainDelegatedObject(state) {
62
- if (Array.isArray(state) || state instanceof Date || state instanceof Map || state instanceof Set || state instanceof RegExp) return false;
63
67
  const proto = Object.getPrototypeOf(state);
68
+ if (proto === Array.prototype || proto === Date.prototype || proto === Map.prototype || proto === Set.prototype || proto === RegExp.prototype) return false;
64
69
  return proto !== Object.prototype && proto !== null;
65
70
  }
71
+ function inheritDelegatedAnnotations(parentState, childState) {
72
+ const target = normalizeDelegatedAnnotationState(childState);
73
+ const delegatedState = inheritAnnotations(parentState, target);
74
+ if (delegatedState !== target) delegatedAnnotationCloneTargets.set(delegatedState, target);
75
+ return delegatedState;
76
+ }
66
77
  /**
67
78
  * Removes Optique's internal annotation carriers from a delegated state.
68
79
  *
69
- * This unwraps both primitive-state annotation wrappers and annotation-view
70
- * proxies used for non-plain object states.
80
+ * This unwraps primitive-state annotation wrappers, tracked delegated clones,
81
+ * and annotation-view proxies used for object states.
71
82
  *
72
83
  * @param state The delegated state to normalize.
73
84
  * @returns The original underlying state value.
74
85
  * @internal
75
86
  */
76
87
  function normalizeDelegatedAnnotationState(state) {
77
- return normalizeInjectedAnnotationState(unwrapAnnotationView(state));
88
+ return normalizeInjectedAnnotationState(unwrapDelegatedAnnotationClone(unwrapAnnotationView(state)));
78
89
  }
79
90
  /**
80
91
  * Returns whether the given state uses an internal delegated annotation carrier.
81
92
  *
82
93
  * @param state The candidate state to inspect.
83
- * @returns `true` when the state is an injected primitive wrapper or an
84
- * annotation-view proxy.
94
+ * @returns `true` when the state is an injected primitive wrapper, a tracked
95
+ * delegated clone, or an annotation-view proxy.
85
96
  * @internal
86
97
  */
87
98
  function hasDelegatedAnnotationCarrier(state) {
88
- return state != null && typeof state === "object" && (isInjectedAnnotationWrapper(state) || annotationViewTargets.has(state));
99
+ return state != null && typeof state === "object" && (isInjectedAnnotationWrapper(state) || delegatedAnnotationCloneTargets.has(state) || annotationViewTargets.has(state));
100
+ }
101
+ function getOrCreateNestedNormalizationClone(entry) {
102
+ entry.clone ??= entry.createClone();
103
+ return entry.clone;
89
104
  }
90
- function isPendingNestedNormalizationAlias(originalValue, normalizedValue, seen) {
91
- if (originalValue == null || typeof originalValue !== "object") return false;
105
+ function getPendingNestedNormalizationEntry(originalValue, normalizedValue, seen) {
106
+ if (originalValue == null || typeof originalValue !== "object") return void 0;
92
107
  const entry = seen.get(originalValue);
93
- return entry != null && !entry.finalized && entry.clone === normalizedValue;
108
+ return entry != null && entry.clone != null && entry.clone === normalizedValue && (!entry.finalized || entry.preferCloneOnRead) ? entry : void 0;
94
109
  }
95
110
  function createPendingNestedNormalizationClone(source) {
96
- return Array.isArray(source) ? [] : Object.create(Object.getPrototypeOf(source));
111
+ if (!Array.isArray(source)) return Object.create(Object.getPrototypeOf(source));
112
+ if (Object.getPrototypeOf(source) === Array.prototype) return [];
113
+ try {
114
+ return source.slice(0, 0);
115
+ } catch {
116
+ return [];
117
+ }
118
+ }
119
+ function createPendingNestedNormalizationCollectionClone(source) {
120
+ const proto = Object.getPrototypeOf(source);
121
+ if (source instanceof Map && proto === Map.prototype) return /* @__PURE__ */ new Map();
122
+ if (source instanceof Set && proto === Set.prototype) return /* @__PURE__ */ new Set();
123
+ const Constructor = source.constructor;
124
+ if (typeof Constructor === "function") try {
125
+ return new Constructor();
126
+ } catch {}
127
+ return source instanceof Map ? /* @__PURE__ */ new Map() : /* @__PURE__ */ new Set();
97
128
  }
98
- function normalizeNestedDelegatedStructuredState(source, seen) {
99
- const clone = createPendingNestedNormalizationClone(source);
129
+ function normalizeNestedDelegatedStructuredState(source, seen, preferPendingClone) {
100
130
  const entry = {
101
- clone,
131
+ clone: void 0,
132
+ createClone: () => createPendingNestedNormalizationClone(source),
102
133
  finalized: false,
103
- result: clone
134
+ result: source,
135
+ preferCloneOnRead: false
104
136
  };
105
137
  seen.set(source, entry);
106
138
  const overrides = /* @__PURE__ */ new Map();
107
139
  let changed = false;
140
+ let hasPendingAliasOverride = false;
108
141
  for (const key of Reflect.ownKeys(source)) {
109
142
  const descriptor = Object.getOwnPropertyDescriptor(source, key);
110
143
  if (descriptor == null || !("value" in descriptor)) continue;
111
- const nextValue = normalizeNestedDelegatedAnnotationState(descriptor.value, seen);
144
+ const nextValue = normalizeNestedDelegatedAnnotationState(descriptor.value, seen, true);
112
145
  if (nextValue === descriptor.value) continue;
113
146
  overrides.set(key, nextValue);
114
- if (!isPendingNestedNormalizationAlias(descriptor.value, nextValue, seen)) changed = true;
147
+ if (getPendingNestedNormalizationEntry(descriptor.value, nextValue, seen) == null) changed = true;
148
+ else hasPendingAliasOverride = true;
115
149
  }
116
- if (!changed) {
150
+ if (!changed && !hasPendingAliasOverride) {
117
151
  entry.finalized = true;
118
152
  entry.result = source;
119
153
  return source;
@@ -127,41 +161,50 @@ function normalizeNestedDelegatedStructuredState(source, seen) {
127
161
  value: nextValue
128
162
  };
129
163
  }
164
+ const clone = getOrCreateNestedNormalizationClone(entry);
130
165
  Object.defineProperties(clone, descriptors);
131
166
  entry.finalized = true;
132
- entry.result = clone;
133
- return clone;
167
+ entry.preferCloneOnRead = !changed && hasPendingAliasOverride;
168
+ entry.result = changed ? clone : source;
169
+ return changed || preferPendingClone ? clone : source;
134
170
  }
135
- function normalizeNestedDelegatedMapState(source, seen) {
136
- const clone = /* @__PURE__ */ new Map();
171
+ function normalizeNestedDelegatedMapState(source, seen, preferPendingClone) {
137
172
  const entry = {
138
- clone,
173
+ clone: void 0,
174
+ createClone: () => createPendingNestedNormalizationCollectionClone(source),
139
175
  finalized: false,
140
- result: clone
176
+ result: source,
177
+ preferCloneOnRead: false
141
178
  };
142
179
  seen.set(source, entry);
143
180
  const normalizedEntries = [];
144
181
  const overrides = /* @__PURE__ */ new Map();
145
182
  let changed = false;
183
+ let hasPendingAliasOverride = false;
146
184
  for (const [key, value] of source) {
147
- const nextKey = normalizeNestedDelegatedAnnotationState(key, seen);
148
- const nextValue = normalizeNestedDelegatedAnnotationState(value, seen);
185
+ const nextKey = normalizeNestedDelegatedAnnotationState(key, seen, true);
186
+ const nextValue = normalizeNestedDelegatedAnnotationState(value, seen, true);
149
187
  normalizedEntries.push([nextKey, nextValue]);
150
- if (!isPendingNestedNormalizationAlias(key, nextKey, seen) && nextKey !== key || !isPendingNestedNormalizationAlias(value, nextValue, seen) && nextValue !== value) changed = true;
188
+ if (nextKey !== key) if (getPendingNestedNormalizationEntry(key, nextKey, seen) == null) changed = true;
189
+ else hasPendingAliasOverride = true;
190
+ if (nextValue !== value) if (getPendingNestedNormalizationEntry(value, nextValue, seen) == null) changed = true;
191
+ else hasPendingAliasOverride = true;
151
192
  }
152
193
  for (const key of Reflect.ownKeys(source)) {
153
194
  const descriptor = Object.getOwnPropertyDescriptor(source, key);
154
195
  if (descriptor == null || !("value" in descriptor)) continue;
155
- const nextValue = normalizeNestedDelegatedAnnotationState(descriptor.value, seen);
196
+ const nextValue = normalizeNestedDelegatedAnnotationState(descriptor.value, seen, true);
156
197
  if (nextValue === descriptor.value) continue;
157
198
  overrides.set(key, nextValue);
158
- if (!isPendingNestedNormalizationAlias(descriptor.value, nextValue, seen)) changed = true;
199
+ if (getPendingNestedNormalizationEntry(descriptor.value, nextValue, seen) == null) changed = true;
200
+ else hasPendingAliasOverride = true;
159
201
  }
160
- if (!changed) {
202
+ if (!changed && !hasPendingAliasOverride) {
161
203
  entry.finalized = true;
162
204
  entry.result = source;
163
205
  return source;
164
206
  }
207
+ const clone = getOrCreateNestedNormalizationClone(entry);
165
208
  for (const [key, value] of normalizedEntries) clone.set(key, value);
166
209
  const descriptors = Object.getOwnPropertyDescriptors(source);
167
210
  for (const [key, nextValue] of overrides) {
@@ -174,38 +217,45 @@ function normalizeNestedDelegatedMapState(source, seen) {
174
217
  }
175
218
  Object.defineProperties(clone, descriptors);
176
219
  entry.finalized = true;
177
- entry.result = clone;
178
- return clone;
220
+ entry.preferCloneOnRead = !changed && hasPendingAliasOverride;
221
+ entry.result = changed ? clone : source;
222
+ return changed || preferPendingClone ? clone : source;
179
223
  }
180
- function normalizeNestedDelegatedSetState(source, seen) {
181
- const clone = /* @__PURE__ */ new Set();
224
+ function normalizeNestedDelegatedSetState(source, seen, preferPendingClone) {
182
225
  const entry = {
183
- clone,
226
+ clone: void 0,
227
+ createClone: () => createPendingNestedNormalizationCollectionClone(source),
184
228
  finalized: false,
185
- result: clone
229
+ result: source,
230
+ preferCloneOnRead: false
186
231
  };
187
232
  seen.set(source, entry);
188
233
  const normalizedValues = [];
189
234
  const overrides = /* @__PURE__ */ new Map();
190
235
  let changed = false;
236
+ let hasPendingAliasOverride = false;
191
237
  for (const value of source) {
192
- const nextValue = normalizeNestedDelegatedAnnotationState(value, seen);
238
+ const nextValue = normalizeNestedDelegatedAnnotationState(value, seen, true);
193
239
  normalizedValues.push(nextValue);
194
- if (nextValue !== value && !isPendingNestedNormalizationAlias(value, nextValue, seen)) changed = true;
240
+ if (nextValue === value) continue;
241
+ if (getPendingNestedNormalizationEntry(value, nextValue, seen) == null) changed = true;
242
+ else hasPendingAliasOverride = true;
195
243
  }
196
244
  for (const key of Reflect.ownKeys(source)) {
197
245
  const descriptor = Object.getOwnPropertyDescriptor(source, key);
198
246
  if (descriptor == null || !("value" in descriptor)) continue;
199
- const nextValue = normalizeNestedDelegatedAnnotationState(descriptor.value, seen);
247
+ const nextValue = normalizeNestedDelegatedAnnotationState(descriptor.value, seen, true);
200
248
  if (nextValue === descriptor.value) continue;
201
249
  overrides.set(key, nextValue);
202
- if (!isPendingNestedNormalizationAlias(descriptor.value, nextValue, seen)) changed = true;
250
+ if (getPendingNestedNormalizationEntry(descriptor.value, nextValue, seen) == null) changed = true;
251
+ else hasPendingAliasOverride = true;
203
252
  }
204
- if (!changed) {
253
+ if (!changed && !hasPendingAliasOverride) {
205
254
  entry.finalized = true;
206
255
  entry.result = source;
207
256
  return source;
208
257
  }
258
+ const clone = getOrCreateNestedNormalizationClone(entry);
209
259
  for (const value of normalizedValues) clone.add(value);
210
260
  const descriptors = Object.getOwnPropertyDescriptors(source);
211
261
  for (const [key, nextValue] of overrides) {
@@ -218,8 +268,9 @@ function normalizeNestedDelegatedSetState(source, seen) {
218
268
  }
219
269
  Object.defineProperties(clone, descriptors);
220
270
  entry.finalized = true;
221
- entry.result = clone;
222
- return clone;
271
+ entry.preferCloneOnRead = !changed && hasPendingAliasOverride;
272
+ entry.result = changed ? clone : source;
273
+ return changed || preferPendingClone ? clone : source;
223
274
  }
224
275
  /**
225
276
  * Recursively removes delegated annotation carriers from plain-object, array,
@@ -237,27 +288,30 @@ function normalizeNestedDelegatedSetState(source, seen) {
237
288
  * normalized clone with delegated carriers removed.
238
289
  * @internal
239
290
  */
240
- function normalizeNestedDelegatedAnnotationState(value, seen = /* @__PURE__ */ new WeakMap()) {
291
+ function normalizeNestedDelegatedAnnotationState(value, seen = /* @__PURE__ */ new WeakMap(), preferPendingClone = false) {
241
292
  const normalized = normalizeDelegatedAnnotationState(value);
242
293
  if (normalized == null || typeof normalized !== "object") return normalized;
243
294
  const source = normalized;
244
295
  const existing = seen.get(source);
245
- if (existing != null) return existing.finalized ? existing.result : existing.clone;
246
- if (Array.isArray(source)) return normalizeNestedDelegatedStructuredState(source, seen);
247
- if (source instanceof Map) return normalizeNestedDelegatedMapState(source, seen);
248
- if (source instanceof Set) return normalizeNestedDelegatedSetState(source, seen);
296
+ if (existing != null) {
297
+ if (!existing.finalized) return getOrCreateNestedNormalizationClone(existing);
298
+ return preferPendingClone && existing.preferCloneOnRead ? getOrCreateNestedNormalizationClone(existing) : existing.result;
299
+ }
300
+ if (Array.isArray(source)) return normalizeNestedDelegatedStructuredState(source, seen, preferPendingClone);
301
+ if (source instanceof Map) return normalizeNestedDelegatedMapState(source, seen, preferPendingClone);
302
+ if (source instanceof Set) return normalizeNestedDelegatedSetState(source, seen, preferPendingClone);
249
303
  const proto = Object.getPrototypeOf(source);
250
304
  if (proto !== Object.prototype && proto !== null) return normalized;
251
- return normalizeNestedDelegatedStructuredState(source, seen);
305
+ return normalizeNestedDelegatedStructuredState(source, seen, preferPendingClone);
252
306
  }
253
307
  /**
254
308
  * Creates a short-lived delegated state that exposes the parent's annotations
255
309
  * regardless of the child state's runtime shape.
256
310
  *
257
- * Primitive and nullish states use `injectAnnotations()`, plain objects and
258
- * built-ins use `inheritAnnotations()`, and non-plain objects use an
259
- * annotation-view proxy so class invariants such as private fields remain
260
- * intact.
311
+ * Primitive and nullish states use `injectAnnotations()`, clone-based object
312
+ * delegation is tracked so it can be normalized back out later, and non-plain
313
+ * objects use an annotation-view proxy so class invariants such as private
314
+ * fields remain intact.
261
315
  *
262
316
  * @param parentState The state carrying the annotations to delegate.
263
317
  * @param childState The child state that should observe those annotations.
@@ -268,10 +322,10 @@ function getDelegatedAnnotationState(parentState, childState) {
268
322
  const annotations = getAnnotations(parentState);
269
323
  if (annotations === void 0) return childState;
270
324
  if (isInjectedAnnotationWrapper(childState)) return injectAnnotations(normalizeInjectedAnnotationState(childState), annotations);
271
- if (getAnnotations(childState) === annotations) return childState;
272
325
  if (childState == null || typeof childState !== "object") return injectAnnotations(childState, annotations);
326
+ if (getAnnotations(childState) === annotations && (delegatedAnnotationCloneTargets.has(childState) || annotationViewTargets.has(childState))) return childState;
273
327
  if (isNonPlainDelegatedObject(childState)) return withAnnotationView(childState, annotations);
274
- return inheritAnnotations(parentState, childState);
328
+ return inheritDelegatedAnnotations(parentState, childState);
275
329
  }
276
330
  /**
277
331
  * Returns whether a state is still at the initial sentinel after normalizing
@@ -357,4 +411,4 @@ function reconcileObjectChildState(parentState, childState) {
357
411
  }
358
412
 
359
413
  //#endregion
360
- export { annotationViewTargets, getDelegatedAnnotationState, getWrappedChildParseState, getWrappedChildState, hasDelegatedAnnotationCarrier, isAnnotationWrappedInitialState, normalizeDelegatedAnnotationState, normalizeInjectedAnnotationState, normalizeNestedDelegatedAnnotationState, reconcileObjectChildState, unwrapAnnotationView };
414
+ export { annotationViewTargets, getDelegatedAnnotationState, getWrappedChildParseState, getWrappedChildState, hasDelegatedAnnotationCarrier, isAnnotationWrappedInitialState, normalizeDelegatedAnnotationState, normalizeInjectedAnnotationState, normalizeNestedDelegatedAnnotationState, reconcileObjectChildState, unwrapAnnotationView, withAnnotationView };
@@ -1,268 +1,3 @@
1
+ const require_annotations = require('./internal/annotations.cjs');
1
2
 
2
- //#region src/annotations.ts
3
- /**
4
- * Runtime context extension system for Optique parsers.
5
- *
6
- * This module provides the annotations system that allows external runtime data
7
- * to be passed to parsers during the parsing session. This enables use cases like
8
- * config file fallbacks, environment-based validation, and shared context.
9
- *
10
- * @module
11
- * @since 0.10.0
12
- */
13
- /**
14
- * Annotation key symbol for storing data in parser state.
15
- * @since 0.10.0
16
- */
17
- const annotationKey = Symbol.for("@optique/core/parser/annotation");
18
- /**
19
- * Internal marker attached during the first pass of `runWith()` so wrappers
20
- * with side effects can defer work until two-pass contexts have resolved.
21
- *
22
- * @internal
23
- */
24
- const firstPassAnnotationKey = Symbol.for("@optique/core/parser/firstPass");
25
- /**
26
- * Internal key for preserving primitive parser state values when annotations
27
- * are injected into non-object states.
28
- * @internal
29
- */
30
- const annotationStateValueKey = Symbol.for("@optique/core/parser/annotationStateValue");
31
- /**
32
- * Internal marker key that indicates annotation wrapping was injected by
33
- * Optique internals for non-object states.
34
- * @internal
35
- */
36
- const annotationWrapperKey = Symbol.for("@optique/core/parser/annotationWrapper");
37
- /**
38
- * Internal symbol keys that define Optique's primitive-state annotation
39
- * wrapper shape.
40
- * @internal
41
- */
42
- const annotationWrapperKeys = new Set([
43
- annotationKey,
44
- annotationStateValueKey,
45
- annotationWrapperKey
46
- ]);
47
- const injectedAnnotationWrappers = /* @__PURE__ */ new WeakSet();
48
- /**
49
- * Extracts annotations from parser state.
50
- *
51
- * @param state Parser state that may contain annotations
52
- * @returns Annotations object or undefined if no annotations are present
53
- * @since 0.10.0
54
- *
55
- * @example
56
- * ```typescript
57
- * const annotations = getAnnotations(state);
58
- * const myData = annotations?.[myDataKey];
59
- * ```
60
- */
61
- function getAnnotations(state) {
62
- if (state == null || typeof state !== "object") return void 0;
63
- const stateObj = state;
64
- const annotations = stateObj[annotationKey];
65
- if (annotations != null && typeof annotations === "object") return annotations;
66
- return void 0;
67
- }
68
- /**
69
- * Reattaches annotations to a freshly created array state.
70
- *
71
- * Array spread copies elements but drops symbol properties, so parsers that
72
- * rebuild array states need to copy annotations back explicitly.
73
- *
74
- * @param source The original state that may carry annotations.
75
- * @param target The freshly created array state.
76
- * @returns The target array, with annotations copied when available.
77
- * @internal
78
- */
79
- function annotateFreshArray(source, target) {
80
- const annotations = getAnnotations(source);
81
- if (annotations === void 0) return target;
82
- const annotated = target;
83
- annotated[annotationKey] = annotations;
84
- return annotated;
85
- }
86
- /**
87
- * Propagates annotations from one parser state to another.
88
- *
89
- * This is mainly used by parsers that rebuild array states with spread syntax.
90
- * Array spread copies elements but drops custom symbol properties, so we need
91
- * to reattach annotations explicitly when present.
92
- *
93
- * @param source The original state that may carry annotations.
94
- * @param target The new state to receive annotations.
95
- * @returns The target state, with annotations copied when available.
96
- * @internal
97
- */
98
- function inheritAnnotations(source, target) {
99
- const annotations = getAnnotations(source);
100
- if (annotations === void 0) return target;
101
- if (target == null || typeof target !== "object") return injectAnnotations(target, annotations);
102
- if (isInjectedAnnotationWrapper(target)) return injectAnnotations(target, annotations);
103
- if (Array.isArray(target)) {
104
- const cloned$1 = [...target];
105
- cloned$1[annotationKey] = annotations;
106
- return cloned$1;
107
- }
108
- if (target instanceof Date) {
109
- const cloned$1 = new Date(target.getTime());
110
- cloned$1[annotationKey] = annotations;
111
- return cloned$1;
112
- }
113
- if (target instanceof Map) {
114
- const cloned$1 = new Map(target);
115
- cloned$1[annotationKey] = annotations;
116
- return cloned$1;
117
- }
118
- if (target instanceof Set) {
119
- const cloned$1 = new Set(target);
120
- cloned$1[annotationKey] = annotations;
121
- return cloned$1;
122
- }
123
- if (target instanceof RegExp) {
124
- const cloned$1 = new RegExp(target);
125
- cloned$1[annotationKey] = annotations;
126
- return cloned$1;
127
- }
128
- if (Object.getPrototypeOf(target) !== Object.prototype && Object.getPrototypeOf(target) !== null) return target;
129
- const cloned = Object.create(Object.getPrototypeOf(target), Object.getOwnPropertyDescriptors(target));
130
- cloned[annotationKey] = annotations;
131
- return cloned;
132
- }
133
- /**
134
- * Returns whether an annotations record carries at least one own symbol key.
135
- *
136
- * An annotations object with no own symbol keys is treated as a no-op by the
137
- * injection pipeline: it should behave identically to omitting the
138
- * `annotations` option entirely. `null` and `undefined` are accepted for
139
- * call-site convenience and always return `false`.
140
- *
141
- * @param annotations The annotations record to check.
142
- * @returns `true` when the record has at least one own symbol key.
143
- * @internal
144
- */
145
- function hasMeaningfulAnnotations(annotations) {
146
- return annotations != null && Object.getOwnPropertySymbols(annotations).length > 0;
147
- }
148
- /**
149
- * Injects annotations into parser state while preserving state shape.
150
- *
151
- * - Primitive, null, and undefined states are wrapped with internal metadata.
152
- * - Array states are cloned and annotated without mutating the original.
153
- * - Plain object states are shallow-cloned with annotations attached.
154
- * - Built-in object states (Date/Map/Set/RegExp) are cloned by constructor.
155
- * - Other non-plain object states are cloned via prototype/descriptors.
156
- * - If the `annotations` record has no own symbol keys, the state is
157
- * returned unchanged; an empty annotations object is a no-op.
158
- *
159
- * @param state The parser state to annotate.
160
- * @param annotations The annotations to inject.
161
- * @returns Annotated state.
162
- * @internal
163
- */
164
- function injectAnnotations(state, annotations) {
165
- if (!hasMeaningfulAnnotations(annotations)) return state;
166
- if (state == null || typeof state !== "object") {
167
- const wrapper = {};
168
- Object.defineProperties(wrapper, {
169
- [annotationKey]: {
170
- value: annotations,
171
- enumerable: true,
172
- writable: true,
173
- configurable: true
174
- },
175
- [annotationStateValueKey]: {
176
- value: state,
177
- enumerable: false,
178
- writable: true,
179
- configurable: true
180
- },
181
- [annotationWrapperKey]: {
182
- value: true,
183
- enumerable: false,
184
- writable: true,
185
- configurable: true
186
- }
187
- });
188
- injectedAnnotationWrappers.add(wrapper);
189
- return wrapper;
190
- }
191
- if (Array.isArray(state)) {
192
- const cloned$1 = [...state];
193
- cloned$1[annotationKey] = annotations;
194
- return cloned$1;
195
- }
196
- if (isInjectedAnnotationWrapper(state)) {
197
- state[annotationKey] = annotations;
198
- return state;
199
- }
200
- if (state instanceof Date) {
201
- const cloned$1 = new Date(state.getTime());
202
- cloned$1[annotationKey] = annotations;
203
- return cloned$1;
204
- }
205
- if (state instanceof Map) {
206
- const cloned$1 = new Map(state);
207
- cloned$1[annotationKey] = annotations;
208
- return cloned$1;
209
- }
210
- if (state instanceof Set) {
211
- const cloned$1 = new Set(state);
212
- cloned$1[annotationKey] = annotations;
213
- return cloned$1;
214
- }
215
- if (state instanceof RegExp) {
216
- const cloned$1 = new RegExp(state);
217
- cloned$1[annotationKey] = annotations;
218
- return cloned$1;
219
- }
220
- const proto = Object.getPrototypeOf(state);
221
- if (proto === Object.prototype || proto === null) return {
222
- ...state,
223
- [annotationKey]: annotations
224
- };
225
- const cloned = Object.create(proto, Object.getOwnPropertyDescriptors(state));
226
- cloned[annotationKey] = annotations;
227
- return cloned;
228
- }
229
- /**
230
- * Unwraps a primitive-state annotation wrapper injected by Optique internals.
231
- *
232
- * @param value Value to potentially unwrap.
233
- * @returns The unwrapped primitive value when the input is an injected wrapper;
234
- * otherwise the original value.
235
- * @internal
236
- */
237
- function unwrapInjectedAnnotationWrapper(value) {
238
- if (value == null || typeof value !== "object") return value;
239
- const valueRecord = value;
240
- if (valueRecord[annotationWrapperKey] !== true) return value;
241
- const ownKeys = Reflect.ownKeys(valueRecord);
242
- if (ownKeys.length === 3 && ownKeys.every((key) => annotationWrapperKeys.has(key)) && isInjectedAnnotationWrapper(value)) return valueRecord[annotationStateValueKey];
243
- return value;
244
- }
245
- /**
246
- * Returns whether the given value is an internal primitive-state annotation
247
- * wrapper that was injected by Optique.
248
- *
249
- * @param value Value to check.
250
- * @returns `true` if the value is an injected internal wrapper.
251
- * @internal
252
- */
253
- function isInjectedAnnotationWrapper(value) {
254
- return value != null && typeof value === "object" && injectedAnnotationWrappers.has(value);
255
- }
256
-
257
- //#endregion
258
- exports.annotateFreshArray = annotateFreshArray;
259
- exports.annotationKey = annotationKey;
260
- exports.annotationStateValueKey = annotationStateValueKey;
261
- exports.annotationWrapperKey = annotationWrapperKey;
262
- exports.firstPassAnnotationKey = firstPassAnnotationKey;
263
- exports.getAnnotations = getAnnotations;
264
- exports.hasMeaningfulAnnotations = hasMeaningfulAnnotations;
265
- exports.inheritAnnotations = inheritAnnotations;
266
- exports.injectAnnotations = injectAnnotations;
267
- exports.isInjectedAnnotationWrapper = isInjectedAnnotationWrapper;
268
- exports.unwrapInjectedAnnotationWrapper = unwrapInjectedAnnotationWrapper;
3
+ exports.getAnnotations = require_annotations.getAnnotations;