@optique/core 1.0.0-dev.921 → 1.0.1
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/dist/annotation-state.cjs +425 -0
- package/dist/annotation-state.d.cts +24 -0
- package/dist/annotation-state.d.ts +24 -0
- package/dist/annotation-state.js +414 -0
- package/dist/annotations.cjs +2 -248
- package/dist/annotations.d.cts +2 -137
- package/dist/annotations.d.ts +2 -137
- package/dist/annotations.js +2 -238
- package/dist/completion.cjs +611 -100
- package/dist/completion.d.cts +1 -1
- package/dist/completion.d.ts +1 -1
- package/dist/completion.js +611 -100
- package/dist/constructs.cjs +3338 -827
- package/dist/constructs.d.cts +48 -7
- package/dist/constructs.d.ts +48 -7
- package/dist/constructs.js +3338 -827
- package/dist/context.cjs +0 -23
- package/dist/context.d.cts +119 -53
- package/dist/context.d.ts +119 -53
- package/dist/context.js +0 -22
- package/dist/dependency-metadata.cjs +139 -0
- package/dist/dependency-metadata.d.cts +112 -0
- package/dist/dependency-metadata.d.ts +112 -0
- package/dist/dependency-metadata.js +138 -0
- package/dist/dependency-runtime.cjs +698 -0
- package/dist/dependency-runtime.d.cts +149 -0
- package/dist/dependency-runtime.d.ts +149 -0
- package/dist/dependency-runtime.js +687 -0
- package/dist/dependency.cjs +7 -928
- package/dist/dependency.d.cts +2 -794
- package/dist/dependency.d.ts +2 -794
- package/dist/dependency.js +2 -899
- package/dist/displaywidth.cjs +44 -0
- package/dist/displaywidth.js +43 -0
- package/dist/doc.cjs +285 -23
- package/dist/doc.d.cts +57 -2
- package/dist/doc.d.ts +57 -2
- package/dist/doc.js +283 -25
- package/dist/execution-context.cjs +56 -0
- package/dist/execution-context.js +53 -0
- package/dist/extension.cjs +87 -0
- package/dist/extension.d.cts +97 -0
- package/dist/extension.d.ts +97 -0
- package/dist/extension.js +76 -0
- package/dist/facade.cjs +718 -525
- package/dist/facade.d.cts +59 -15
- package/dist/facade.d.ts +59 -15
- package/dist/facade.js +718 -525
- package/dist/index.cjs +14 -29
- package/dist/index.d.cts +10 -10
- package/dist/index.d.ts +10 -10
- package/dist/index.js +7 -7
- package/dist/input-trace.cjs +56 -0
- package/dist/input-trace.d.cts +77 -0
- package/dist/input-trace.d.ts +77 -0
- package/dist/input-trace.js +55 -0
- package/dist/internal/annotations.cjs +316 -0
- package/dist/internal/annotations.d.cts +140 -0
- package/dist/internal/annotations.d.ts +140 -0
- package/dist/internal/annotations.js +306 -0
- package/dist/internal/dependency.cjs +984 -0
- package/dist/internal/dependency.d.cts +539 -0
- package/dist/internal/dependency.d.ts +539 -0
- package/dist/internal/dependency.js +964 -0
- package/dist/{mode-dispatch.cjs → internal/mode-dispatch.cjs} +1 -3
- package/dist/{mode-dispatch.d.cts → internal/mode-dispatch.d.cts} +3 -7
- package/dist/{mode-dispatch.d.ts → internal/mode-dispatch.d.ts} +3 -7
- package/dist/{mode-dispatch.js → internal/mode-dispatch.js} +1 -3
- package/dist/internal/parser.cjs +728 -0
- package/dist/internal/parser.d.cts +947 -0
- package/dist/internal/parser.d.ts +947 -0
- package/dist/internal/parser.js +711 -0
- package/dist/message.cjs +84 -26
- package/dist/message.d.cts +49 -9
- package/dist/message.d.ts +49 -9
- package/dist/message.js +84 -27
- package/dist/modifiers.cjs +1023 -240
- package/dist/modifiers.d.cts +42 -1
- package/dist/modifiers.d.ts +42 -1
- package/dist/modifiers.js +1023 -240
- package/dist/parser.cjs +11 -463
- package/dist/parser.d.cts +3 -537
- package/dist/parser.d.ts +3 -537
- package/dist/parser.js +2 -433
- package/dist/phase2-seed.cjs +59 -0
- package/dist/phase2-seed.js +56 -0
- package/dist/primitives.cjs +557 -208
- package/dist/primitives.d.cts +10 -14
- package/dist/primitives.d.ts +10 -14
- package/dist/primitives.js +557 -208
- package/dist/program.cjs +5 -1
- package/dist/program.d.cts +5 -3
- package/dist/program.d.ts +5 -3
- package/dist/program.js +6 -1
- package/dist/suggestion.cjs +22 -8
- package/dist/suggestion.js +22 -8
- package/dist/usage-internals.cjs +3 -2
- package/dist/usage-internals.js +4 -2
- package/dist/usage.cjs +195 -40
- package/dist/usage.d.cts +92 -11
- package/dist/usage.d.ts +92 -11
- package/dist/usage.js +194 -41
- package/dist/validate.cjs +170 -0
- package/dist/validate.js +164 -0
- package/dist/valueparser.cjs +1270 -187
- package/dist/valueparser.d.cts +320 -14
- package/dist/valueparser.d.ts +320 -14
- package/dist/valueparser.js +1269 -188
- package/package.json +9 -9
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
import { annotationKey, getAnnotations, inheritAnnotations, injectAnnotations, isInjectedAnnotationWrapper, unwrapInjectedAnnotationWrapper } from "./internal/annotations.js";
|
|
2
|
+
import { inheritParentAnnotationsKey } from "./internal/parser.js";
|
|
3
|
+
|
|
4
|
+
//#region src/annotation-state.ts
|
|
5
|
+
/**
|
|
6
|
+
* Shared targets for annotation-view proxies.
|
|
7
|
+
*
|
|
8
|
+
* Maps a proxy returned by {@link withAnnotationView} back to its original
|
|
9
|
+
* target object.
|
|
10
|
+
*
|
|
11
|
+
* @internal
|
|
12
|
+
*/
|
|
13
|
+
const annotationViewTargets = /* @__PURE__ */ new WeakMap();
|
|
14
|
+
const delegatedAnnotationCloneTargets = /* @__PURE__ */ new WeakMap();
|
|
15
|
+
/**
|
|
16
|
+
* Unwraps an annotation-view proxy to its original target object.
|
|
17
|
+
*
|
|
18
|
+
* @param value The candidate value that may be an annotation-view proxy.
|
|
19
|
+
* @returns The original target object when the input is a tracked
|
|
20
|
+
* annotation-view proxy; otherwise the input value unchanged.
|
|
21
|
+
* @internal
|
|
22
|
+
*/
|
|
23
|
+
function unwrapAnnotationView(value) {
|
|
24
|
+
if (value == null || typeof value !== "object") return value;
|
|
25
|
+
return annotationViewTargets.get(value) ?? value;
|
|
26
|
+
}
|
|
27
|
+
function unwrapDelegatedAnnotationClone(value) {
|
|
28
|
+
if (value == null || typeof value !== "object") return value;
|
|
29
|
+
return delegatedAnnotationCloneTargets.get(value) ?? value;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Creates an annotation-aware proxy without changing the target shape.
|
|
33
|
+
*
|
|
34
|
+
* @param state The object state to expose through an annotation-aware view.
|
|
35
|
+
* @param annotations The annotations to surface through the proxy.
|
|
36
|
+
* @returns A proxy over the unwrapped target object that reports the supplied
|
|
37
|
+
* annotations while preserving the target's structural behavior.
|
|
38
|
+
* @since 1.0.0
|
|
39
|
+
*/
|
|
40
|
+
function withAnnotationView(state, annotations) {
|
|
41
|
+
const target = unwrapAnnotationView(state);
|
|
42
|
+
const view = new Proxy(target, {
|
|
43
|
+
get(target$1, key) {
|
|
44
|
+
if (key === annotationKey) return annotations;
|
|
45
|
+
const value = Reflect.get(target$1, key, target$1);
|
|
46
|
+
return typeof value === "function" ? value.bind(target$1) : value;
|
|
47
|
+
},
|
|
48
|
+
has(target$1, key) {
|
|
49
|
+
return key === annotationKey || Reflect.has(target$1, key);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
annotationViewTargets.set(view, target);
|
|
53
|
+
return view;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Removes Optique's internal primitive-state annotation wrapper when present.
|
|
57
|
+
*
|
|
58
|
+
* @param state The parser state to normalize.
|
|
59
|
+
* @returns The wrapped primitive sentinel when the input is an injected
|
|
60
|
+
* annotation wrapper; otherwise the original input unchanged.
|
|
61
|
+
* @internal
|
|
62
|
+
*/
|
|
63
|
+
function normalizeInjectedAnnotationState(state) {
|
|
64
|
+
return unwrapInjectedAnnotationWrapper(state);
|
|
65
|
+
}
|
|
66
|
+
function isNonPlainDelegatedObject(state) {
|
|
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;
|
|
69
|
+
return proto !== Object.prototype && proto !== null;
|
|
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
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Removes Optique's internal annotation carriers from a delegated state.
|
|
79
|
+
*
|
|
80
|
+
* This unwraps primitive-state annotation wrappers, tracked delegated clones,
|
|
81
|
+
* and annotation-view proxies used for object states.
|
|
82
|
+
*
|
|
83
|
+
* @param state The delegated state to normalize.
|
|
84
|
+
* @returns The original underlying state value.
|
|
85
|
+
* @internal
|
|
86
|
+
*/
|
|
87
|
+
function normalizeDelegatedAnnotationState(state) {
|
|
88
|
+
return normalizeInjectedAnnotationState(unwrapDelegatedAnnotationClone(unwrapAnnotationView(state)));
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Returns whether the given state uses an internal delegated annotation carrier.
|
|
92
|
+
*
|
|
93
|
+
* @param state The candidate state to inspect.
|
|
94
|
+
* @returns `true` when the state is an injected primitive wrapper, a tracked
|
|
95
|
+
* delegated clone, or an annotation-view proxy.
|
|
96
|
+
* @internal
|
|
97
|
+
*/
|
|
98
|
+
function hasDelegatedAnnotationCarrier(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;
|
|
104
|
+
}
|
|
105
|
+
function getPendingNestedNormalizationEntry(originalValue, normalizedValue, seen) {
|
|
106
|
+
if (originalValue == null || typeof originalValue !== "object") return void 0;
|
|
107
|
+
const entry = seen.get(originalValue);
|
|
108
|
+
return entry != null && entry.clone != null && entry.clone === normalizedValue && (!entry.finalized || entry.preferCloneOnRead) ? entry : void 0;
|
|
109
|
+
}
|
|
110
|
+
function createPendingNestedNormalizationClone(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();
|
|
128
|
+
}
|
|
129
|
+
function normalizeNestedDelegatedStructuredState(source, seen, preferPendingClone) {
|
|
130
|
+
const entry = {
|
|
131
|
+
clone: void 0,
|
|
132
|
+
createClone: () => createPendingNestedNormalizationClone(source),
|
|
133
|
+
finalized: false,
|
|
134
|
+
result: source,
|
|
135
|
+
preferCloneOnRead: false
|
|
136
|
+
};
|
|
137
|
+
seen.set(source, entry);
|
|
138
|
+
const overrides = /* @__PURE__ */ new Map();
|
|
139
|
+
let changed = false;
|
|
140
|
+
let hasPendingAliasOverride = false;
|
|
141
|
+
for (const key of Reflect.ownKeys(source)) {
|
|
142
|
+
const descriptor = Object.getOwnPropertyDescriptor(source, key);
|
|
143
|
+
if (descriptor == null || !("value" in descriptor)) continue;
|
|
144
|
+
const nextValue = normalizeNestedDelegatedAnnotationState(descriptor.value, seen, true);
|
|
145
|
+
if (nextValue === descriptor.value) continue;
|
|
146
|
+
overrides.set(key, nextValue);
|
|
147
|
+
if (getPendingNestedNormalizationEntry(descriptor.value, nextValue, seen) == null) changed = true;
|
|
148
|
+
else hasPendingAliasOverride = true;
|
|
149
|
+
}
|
|
150
|
+
if (!changed && !hasPendingAliasOverride) {
|
|
151
|
+
entry.finalized = true;
|
|
152
|
+
entry.result = source;
|
|
153
|
+
return source;
|
|
154
|
+
}
|
|
155
|
+
const descriptors = Object.getOwnPropertyDescriptors(source);
|
|
156
|
+
for (const [key, nextValue] of overrides) {
|
|
157
|
+
const descriptor = descriptors[key];
|
|
158
|
+
if (descriptor == null || !("value" in descriptor)) continue;
|
|
159
|
+
descriptors[key] = {
|
|
160
|
+
...descriptor,
|
|
161
|
+
value: nextValue
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
const clone = getOrCreateNestedNormalizationClone(entry);
|
|
165
|
+
Object.defineProperties(clone, descriptors);
|
|
166
|
+
entry.finalized = true;
|
|
167
|
+
entry.preferCloneOnRead = !changed && hasPendingAliasOverride;
|
|
168
|
+
entry.result = changed ? clone : source;
|
|
169
|
+
return changed || preferPendingClone ? clone : source;
|
|
170
|
+
}
|
|
171
|
+
function normalizeNestedDelegatedMapState(source, seen, preferPendingClone) {
|
|
172
|
+
const entry = {
|
|
173
|
+
clone: void 0,
|
|
174
|
+
createClone: () => createPendingNestedNormalizationCollectionClone(source),
|
|
175
|
+
finalized: false,
|
|
176
|
+
result: source,
|
|
177
|
+
preferCloneOnRead: false
|
|
178
|
+
};
|
|
179
|
+
seen.set(source, entry);
|
|
180
|
+
const normalizedEntries = [];
|
|
181
|
+
const overrides = /* @__PURE__ */ new Map();
|
|
182
|
+
let changed = false;
|
|
183
|
+
let hasPendingAliasOverride = false;
|
|
184
|
+
for (const [key, value] of source) {
|
|
185
|
+
const nextKey = normalizeNestedDelegatedAnnotationState(key, seen, true);
|
|
186
|
+
const nextValue = normalizeNestedDelegatedAnnotationState(value, seen, true);
|
|
187
|
+
normalizedEntries.push([nextKey, nextValue]);
|
|
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;
|
|
192
|
+
}
|
|
193
|
+
for (const key of Reflect.ownKeys(source)) {
|
|
194
|
+
const descriptor = Object.getOwnPropertyDescriptor(source, key);
|
|
195
|
+
if (descriptor == null || !("value" in descriptor)) continue;
|
|
196
|
+
const nextValue = normalizeNestedDelegatedAnnotationState(descriptor.value, seen, true);
|
|
197
|
+
if (nextValue === descriptor.value) continue;
|
|
198
|
+
overrides.set(key, nextValue);
|
|
199
|
+
if (getPendingNestedNormalizationEntry(descriptor.value, nextValue, seen) == null) changed = true;
|
|
200
|
+
else hasPendingAliasOverride = true;
|
|
201
|
+
}
|
|
202
|
+
if (!changed && !hasPendingAliasOverride) {
|
|
203
|
+
entry.finalized = true;
|
|
204
|
+
entry.result = source;
|
|
205
|
+
return source;
|
|
206
|
+
}
|
|
207
|
+
const clone = getOrCreateNestedNormalizationClone(entry);
|
|
208
|
+
for (const [key, value] of normalizedEntries) clone.set(key, value);
|
|
209
|
+
const descriptors = Object.getOwnPropertyDescriptors(source);
|
|
210
|
+
for (const [key, nextValue] of overrides) {
|
|
211
|
+
const descriptor = descriptors[key];
|
|
212
|
+
if (descriptor == null || !("value" in descriptor)) continue;
|
|
213
|
+
descriptors[key] = {
|
|
214
|
+
...descriptor,
|
|
215
|
+
value: nextValue
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
Object.defineProperties(clone, descriptors);
|
|
219
|
+
entry.finalized = true;
|
|
220
|
+
entry.preferCloneOnRead = !changed && hasPendingAliasOverride;
|
|
221
|
+
entry.result = changed ? clone : source;
|
|
222
|
+
return changed || preferPendingClone ? clone : source;
|
|
223
|
+
}
|
|
224
|
+
function normalizeNestedDelegatedSetState(source, seen, preferPendingClone) {
|
|
225
|
+
const entry = {
|
|
226
|
+
clone: void 0,
|
|
227
|
+
createClone: () => createPendingNestedNormalizationCollectionClone(source),
|
|
228
|
+
finalized: false,
|
|
229
|
+
result: source,
|
|
230
|
+
preferCloneOnRead: false
|
|
231
|
+
};
|
|
232
|
+
seen.set(source, entry);
|
|
233
|
+
const normalizedValues = [];
|
|
234
|
+
const overrides = /* @__PURE__ */ new Map();
|
|
235
|
+
let changed = false;
|
|
236
|
+
let hasPendingAliasOverride = false;
|
|
237
|
+
for (const value of source) {
|
|
238
|
+
const nextValue = normalizeNestedDelegatedAnnotationState(value, seen, true);
|
|
239
|
+
normalizedValues.push(nextValue);
|
|
240
|
+
if (nextValue === value) continue;
|
|
241
|
+
if (getPendingNestedNormalizationEntry(value, nextValue, seen) == null) changed = true;
|
|
242
|
+
else hasPendingAliasOverride = true;
|
|
243
|
+
}
|
|
244
|
+
for (const key of Reflect.ownKeys(source)) {
|
|
245
|
+
const descriptor = Object.getOwnPropertyDescriptor(source, key);
|
|
246
|
+
if (descriptor == null || !("value" in descriptor)) continue;
|
|
247
|
+
const nextValue = normalizeNestedDelegatedAnnotationState(descriptor.value, seen, true);
|
|
248
|
+
if (nextValue === descriptor.value) continue;
|
|
249
|
+
overrides.set(key, nextValue);
|
|
250
|
+
if (getPendingNestedNormalizationEntry(descriptor.value, nextValue, seen) == null) changed = true;
|
|
251
|
+
else hasPendingAliasOverride = true;
|
|
252
|
+
}
|
|
253
|
+
if (!changed && !hasPendingAliasOverride) {
|
|
254
|
+
entry.finalized = true;
|
|
255
|
+
entry.result = source;
|
|
256
|
+
return source;
|
|
257
|
+
}
|
|
258
|
+
const clone = getOrCreateNestedNormalizationClone(entry);
|
|
259
|
+
for (const value of normalizedValues) clone.add(value);
|
|
260
|
+
const descriptors = Object.getOwnPropertyDescriptors(source);
|
|
261
|
+
for (const [key, nextValue] of overrides) {
|
|
262
|
+
const descriptor = descriptors[key];
|
|
263
|
+
if (descriptor == null || !("value" in descriptor)) continue;
|
|
264
|
+
descriptors[key] = {
|
|
265
|
+
...descriptor,
|
|
266
|
+
value: nextValue
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
Object.defineProperties(clone, descriptors);
|
|
270
|
+
entry.finalized = true;
|
|
271
|
+
entry.preferCloneOnRead = !changed && hasPendingAliasOverride;
|
|
272
|
+
entry.result = changed ? clone : source;
|
|
273
|
+
return changed || preferPendingClone ? clone : source;
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Recursively removes delegated annotation carriers from plain-object, array,
|
|
277
|
+
* and built-in collection structures.
|
|
278
|
+
*
|
|
279
|
+
* Nested plain objects, arrays, Maps, and Sets are shallow-cloned only when a
|
|
280
|
+
* delegated carrier is found below them. Other non-plain objects are unwrapped
|
|
281
|
+
* at the top level and then preserved as-is to avoid mutating or reconstructing
|
|
282
|
+
* class instances.
|
|
283
|
+
*
|
|
284
|
+
* @param value The candidate value to normalize.
|
|
285
|
+
* @param seen Tracks already-normalized objects so cyclic values keep their
|
|
286
|
+
* shape.
|
|
287
|
+
* @returns The original value when no delegated carriers are present, or a
|
|
288
|
+
* normalized clone with delegated carriers removed.
|
|
289
|
+
* @internal
|
|
290
|
+
*/
|
|
291
|
+
function normalizeNestedDelegatedAnnotationState(value, seen = /* @__PURE__ */ new WeakMap(), preferPendingClone = false) {
|
|
292
|
+
const normalized = normalizeDelegatedAnnotationState(value);
|
|
293
|
+
if (normalized == null || typeof normalized !== "object") return normalized;
|
|
294
|
+
const source = normalized;
|
|
295
|
+
const existing = seen.get(source);
|
|
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);
|
|
303
|
+
const proto = Object.getPrototypeOf(source);
|
|
304
|
+
if (proto !== Object.prototype && proto !== null) return normalized;
|
|
305
|
+
return normalizeNestedDelegatedStructuredState(source, seen, preferPendingClone);
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Creates a short-lived delegated state that exposes the parent's annotations
|
|
309
|
+
* regardless of the child state's runtime shape.
|
|
310
|
+
*
|
|
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.
|
|
315
|
+
*
|
|
316
|
+
* @param parentState The state carrying the annotations to delegate.
|
|
317
|
+
* @param childState The child state that should observe those annotations.
|
|
318
|
+
* @returns A delegated child state that exposes the parent's annotations.
|
|
319
|
+
* @internal
|
|
320
|
+
*/
|
|
321
|
+
function getDelegatedAnnotationState(parentState, childState) {
|
|
322
|
+
const annotations = getAnnotations(parentState);
|
|
323
|
+
if (annotations === void 0) return childState;
|
|
324
|
+
if (isInjectedAnnotationWrapper(childState)) return injectAnnotations(normalizeInjectedAnnotationState(childState), annotations);
|
|
325
|
+
if (childState == null || typeof childState !== "object") return injectAnnotations(childState, annotations);
|
|
326
|
+
if (getAnnotations(childState) === annotations && (delegatedAnnotationCloneTargets.has(childState) || annotationViewTargets.has(childState))) return childState;
|
|
327
|
+
if (isNonPlainDelegatedObject(childState)) return withAnnotationView(childState, annotations);
|
|
328
|
+
return inheritDelegatedAnnotations(parentState, childState);
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Returns whether a state is still at the initial sentinel after normalizing
|
|
332
|
+
* Optique's injected annotation wrapper.
|
|
333
|
+
*
|
|
334
|
+
* This treats plain `undefined` and annotation-wrapped `undefined` the same.
|
|
335
|
+
*
|
|
336
|
+
* @param state The parser state to inspect.
|
|
337
|
+
* @returns `true` when the normalized state is still `undefined`;
|
|
338
|
+
* otherwise `false`.
|
|
339
|
+
* @internal
|
|
340
|
+
*/
|
|
341
|
+
function isAnnotationWrappedInitialState(state) {
|
|
342
|
+
return normalizeInjectedAnnotationState(state) === void 0;
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Propagates parent annotations into a child parse state when the child parser
|
|
346
|
+
* explicitly opts into parent annotation inheritance.
|
|
347
|
+
*
|
|
348
|
+
* @param parentState The parent parser state that may carry annotations.
|
|
349
|
+
* @param childState The child parse state that may receive inherited
|
|
350
|
+
* annotations.
|
|
351
|
+
* @param parser The child parser whose inheritance marker controls whether
|
|
352
|
+
* wrapper injection is allowed.
|
|
353
|
+
* @returns The original child state when no injection is needed or possible,
|
|
354
|
+
* or an annotation-injected child state that preserves the original
|
|
355
|
+
* sentinel or object shape when inheritance applies.
|
|
356
|
+
* @internal
|
|
357
|
+
*/
|
|
358
|
+
function getWrappedChildParseState(parentState, childState, parser) {
|
|
359
|
+
const annotations = getAnnotations(parentState);
|
|
360
|
+
const shouldInheritAnnotations = Reflect.get(parser, inheritParentAnnotationsKey) === true;
|
|
361
|
+
if (childState == null) {
|
|
362
|
+
if (annotations !== void 0 && shouldInheritAnnotations) return injectAnnotations(childState, annotations);
|
|
363
|
+
return childState;
|
|
364
|
+
}
|
|
365
|
+
if (annotations === void 0 || typeof childState !== "object" || getAnnotations(childState) === annotations || !shouldInheritAnnotations) return childState;
|
|
366
|
+
const injectedState = injectAnnotations(childState, annotations);
|
|
367
|
+
return getAnnotations(injectedState) === annotations ? injectedState : childState;
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Propagates parent annotations into a child state while preserving the child
|
|
371
|
+
* state's shape for parsers that do not opt into full wrapper injection.
|
|
372
|
+
*
|
|
373
|
+
* @param parentState The parent parser state that may carry annotations.
|
|
374
|
+
* @param childState The child state that may receive inherited annotations.
|
|
375
|
+
* @param parser The child parser whose inheritance marker controls whether
|
|
376
|
+
* full wrapper injection is allowed.
|
|
377
|
+
* @returns The original child state when no wrapping is needed, an
|
|
378
|
+
* annotation-injected child state when inheritance applies, or an
|
|
379
|
+
* annotation-view proxy that preserves the child's object shape.
|
|
380
|
+
* @internal
|
|
381
|
+
*/
|
|
382
|
+
function getWrappedChildState(parentState, childState, parser) {
|
|
383
|
+
const annotations = getAnnotations(parentState);
|
|
384
|
+
const shouldInheritAnnotations = Reflect.get(parser, inheritParentAnnotationsKey) === true;
|
|
385
|
+
if (childState == null) {
|
|
386
|
+
if (annotations !== void 0 && shouldInheritAnnotations) return injectAnnotations(childState, annotations);
|
|
387
|
+
return childState;
|
|
388
|
+
}
|
|
389
|
+
if (annotations === void 0 || typeof childState !== "object" || getAnnotations(childState) === annotations) return childState;
|
|
390
|
+
if (shouldInheritAnnotations) {
|
|
391
|
+
const injectedState = injectAnnotations(childState, annotations);
|
|
392
|
+
if (getAnnotations(injectedState) === annotations) return injectedState;
|
|
393
|
+
}
|
|
394
|
+
return withAnnotationView(childState, annotations);
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Reconciles object-owned child state with parent annotations using the same
|
|
398
|
+
* shared object-state inheritance rule across parser families.
|
|
399
|
+
*
|
|
400
|
+
* @param parentState The parent parser state that may carry annotations.
|
|
401
|
+
* @param childState The object-owned child state to reconcile.
|
|
402
|
+
* @returns The original child state when no reconciliation is needed, or a
|
|
403
|
+
* child state with inherited annotations when the object state should
|
|
404
|
+
* carry the parent's annotations.
|
|
405
|
+
* @internal
|
|
406
|
+
*/
|
|
407
|
+
function reconcileObjectChildState(parentState, childState) {
|
|
408
|
+
const annotations = getAnnotations(parentState);
|
|
409
|
+
if (annotations === void 0 || childState == null || typeof childState !== "object" || getAnnotations(childState) === annotations) return childState;
|
|
410
|
+
return inheritAnnotations(parentState, childState);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
//#endregion
|
|
414
|
+
export { annotationViewTargets, getDelegatedAnnotationState, getWrappedChildParseState, getWrappedChildState, hasDelegatedAnnotationCarrier, isAnnotationWrappedInitialState, normalizeDelegatedAnnotationState, normalizeInjectedAnnotationState, normalizeNestedDelegatedAnnotationState, reconcileObjectChildState, unwrapAnnotationView, withAnnotationView };
|
package/dist/annotations.cjs
CHANGED
|
@@ -1,249 +1,3 @@
|
|
|
1
|
+
const require_annotations = require('./internal/annotations.cjs');
|
|
1
2
|
|
|
2
|
-
|
|
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 dynamic 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
|
-
* Injects annotations into parser state while preserving state shape.
|
|
135
|
-
*
|
|
136
|
-
* - Primitive, null, and undefined states are wrapped with internal metadata.
|
|
137
|
-
* - Array states are cloned and annotated without mutating the original.
|
|
138
|
-
* - Plain object states are shallow-cloned with annotations attached.
|
|
139
|
-
* - Built-in object states (Date/Map/Set/RegExp) are cloned by constructor.
|
|
140
|
-
* - Other non-plain object states are cloned via prototype/descriptors.
|
|
141
|
-
*
|
|
142
|
-
* @param state The parser state to annotate.
|
|
143
|
-
* @param annotations The annotations to inject.
|
|
144
|
-
* @returns Annotated state.
|
|
145
|
-
* @internal
|
|
146
|
-
*/
|
|
147
|
-
function injectAnnotations(state, annotations) {
|
|
148
|
-
if (state == null || typeof state !== "object") {
|
|
149
|
-
const wrapper = {};
|
|
150
|
-
Object.defineProperties(wrapper, {
|
|
151
|
-
[annotationKey]: {
|
|
152
|
-
value: annotations,
|
|
153
|
-
enumerable: true,
|
|
154
|
-
writable: true,
|
|
155
|
-
configurable: true
|
|
156
|
-
},
|
|
157
|
-
[annotationStateValueKey]: {
|
|
158
|
-
value: state,
|
|
159
|
-
enumerable: false,
|
|
160
|
-
writable: true,
|
|
161
|
-
configurable: true
|
|
162
|
-
},
|
|
163
|
-
[annotationWrapperKey]: {
|
|
164
|
-
value: true,
|
|
165
|
-
enumerable: false,
|
|
166
|
-
writable: true,
|
|
167
|
-
configurable: true
|
|
168
|
-
}
|
|
169
|
-
});
|
|
170
|
-
injectedAnnotationWrappers.add(wrapper);
|
|
171
|
-
return wrapper;
|
|
172
|
-
}
|
|
173
|
-
if (Array.isArray(state)) {
|
|
174
|
-
const cloned$1 = [...state];
|
|
175
|
-
cloned$1[annotationKey] = annotations;
|
|
176
|
-
return cloned$1;
|
|
177
|
-
}
|
|
178
|
-
if (isInjectedAnnotationWrapper(state)) {
|
|
179
|
-
state[annotationKey] = annotations;
|
|
180
|
-
return state;
|
|
181
|
-
}
|
|
182
|
-
if (state instanceof Date) {
|
|
183
|
-
const cloned$1 = new Date(state.getTime());
|
|
184
|
-
cloned$1[annotationKey] = annotations;
|
|
185
|
-
return cloned$1;
|
|
186
|
-
}
|
|
187
|
-
if (state instanceof Map) {
|
|
188
|
-
const cloned$1 = new Map(state);
|
|
189
|
-
cloned$1[annotationKey] = annotations;
|
|
190
|
-
return cloned$1;
|
|
191
|
-
}
|
|
192
|
-
if (state instanceof Set) {
|
|
193
|
-
const cloned$1 = new Set(state);
|
|
194
|
-
cloned$1[annotationKey] = annotations;
|
|
195
|
-
return cloned$1;
|
|
196
|
-
}
|
|
197
|
-
if (state instanceof RegExp) {
|
|
198
|
-
const cloned$1 = new RegExp(state);
|
|
199
|
-
cloned$1[annotationKey] = annotations;
|
|
200
|
-
return cloned$1;
|
|
201
|
-
}
|
|
202
|
-
const proto = Object.getPrototypeOf(state);
|
|
203
|
-
if (proto === Object.prototype || proto === null) return {
|
|
204
|
-
...state,
|
|
205
|
-
[annotationKey]: annotations
|
|
206
|
-
};
|
|
207
|
-
const cloned = Object.create(proto, Object.getOwnPropertyDescriptors(state));
|
|
208
|
-
cloned[annotationKey] = annotations;
|
|
209
|
-
return cloned;
|
|
210
|
-
}
|
|
211
|
-
/**
|
|
212
|
-
* Unwraps a primitive-state annotation wrapper injected by Optique internals.
|
|
213
|
-
*
|
|
214
|
-
* @param value Value to potentially unwrap.
|
|
215
|
-
* @returns The unwrapped primitive value when the input is an injected wrapper;
|
|
216
|
-
* otherwise the original value.
|
|
217
|
-
* @internal
|
|
218
|
-
*/
|
|
219
|
-
function unwrapInjectedAnnotationWrapper(value) {
|
|
220
|
-
if (value == null || typeof value !== "object") return value;
|
|
221
|
-
const valueRecord = value;
|
|
222
|
-
if (valueRecord[annotationWrapperKey] !== true) return value;
|
|
223
|
-
const ownKeys = Reflect.ownKeys(valueRecord);
|
|
224
|
-
if (ownKeys.length === 3 && ownKeys.every((key) => annotationWrapperKeys.has(key)) && isInjectedAnnotationWrapper(value)) return valueRecord[annotationStateValueKey];
|
|
225
|
-
return value;
|
|
226
|
-
}
|
|
227
|
-
/**
|
|
228
|
-
* Returns whether the given value is an internal primitive-state annotation
|
|
229
|
-
* wrapper that was injected by Optique.
|
|
230
|
-
*
|
|
231
|
-
* @param value Value to check.
|
|
232
|
-
* @returns `true` if the value is an injected internal wrapper.
|
|
233
|
-
* @internal
|
|
234
|
-
*/
|
|
235
|
-
function isInjectedAnnotationWrapper(value) {
|
|
236
|
-
return value != null && typeof value === "object" && injectedAnnotationWrappers.has(value);
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
//#endregion
|
|
240
|
-
exports.annotateFreshArray = annotateFreshArray;
|
|
241
|
-
exports.annotationKey = annotationKey;
|
|
242
|
-
exports.annotationStateValueKey = annotationStateValueKey;
|
|
243
|
-
exports.annotationWrapperKey = annotationWrapperKey;
|
|
244
|
-
exports.firstPassAnnotationKey = firstPassAnnotationKey;
|
|
245
|
-
exports.getAnnotations = getAnnotations;
|
|
246
|
-
exports.inheritAnnotations = inheritAnnotations;
|
|
247
|
-
exports.injectAnnotations = injectAnnotations;
|
|
248
|
-
exports.isInjectedAnnotationWrapper = isInjectedAnnotationWrapper;
|
|
249
|
-
exports.unwrapInjectedAnnotationWrapper = unwrapInjectedAnnotationWrapper;
|
|
3
|
+
exports.getAnnotations = require_annotations.getAnnotations;
|