@optique/core 1.0.0-dev.1890 → 1.0.0-dev.1893

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.
@@ -58,6 +58,121 @@ function withAnnotationView(state, annotations) {
58
58
  function normalizeInjectedAnnotationState(state) {
59
59
  return require_annotations.unwrapInjectedAnnotationWrapper(state);
60
60
  }
61
+ function isNonPlainDelegatedObject(state) {
62
+ if (Array.isArray(state) || state instanceof Date || state instanceof Map || state instanceof Set || state instanceof RegExp) return false;
63
+ const proto = Object.getPrototypeOf(state);
64
+ return proto !== Object.prototype && proto !== null;
65
+ }
66
+ /**
67
+ * Removes Optique's internal annotation carriers from a delegated state.
68
+ *
69
+ * This unwraps both primitive-state annotation wrappers and annotation-view
70
+ * proxies used for non-plain object states.
71
+ *
72
+ * @param state The delegated state to normalize.
73
+ * @returns The original underlying state value.
74
+ * @internal
75
+ */
76
+ function normalizeDelegatedAnnotationState(state) {
77
+ return normalizeInjectedAnnotationState(unwrapAnnotationView(state));
78
+ }
79
+ /**
80
+ * Returns whether the given state uses an internal delegated annotation carrier.
81
+ *
82
+ * @param state The candidate state to inspect.
83
+ * @returns `true` when the state is an injected primitive wrapper or an
84
+ * annotation-view proxy.
85
+ * @internal
86
+ */
87
+ function hasDelegatedAnnotationCarrier(state) {
88
+ return state != null && typeof state === "object" && (require_annotations.isInjectedAnnotationWrapper(state) || annotationViewTargets.has(state));
89
+ }
90
+ /**
91
+ * Recursively removes delegated annotation carriers from plain-object and array
92
+ * structures.
93
+ *
94
+ * Nested plain objects and arrays are shallow-cloned only when a delegated
95
+ * carrier is found below them. Non-plain objects are unwrapped at the top
96
+ * level and then preserved as-is to avoid mutating or reconstructing class
97
+ * instances.
98
+ *
99
+ * @param value The candidate value to normalize.
100
+ * @param seen Tracks already-normalized objects so cyclic values keep their
101
+ * shape.
102
+ * @returns The original value when no delegated carriers are present, or a
103
+ * normalized clone with delegated carriers removed.
104
+ * @internal
105
+ */
106
+ function normalizeNestedDelegatedAnnotationState(value, seen = /* @__PURE__ */ new WeakMap()) {
107
+ const normalized = normalizeDelegatedAnnotationState(value);
108
+ if (normalized == null || typeof normalized !== "object") return normalized;
109
+ const source = normalized;
110
+ if (seen.has(source)) return seen.get(source);
111
+ if (Array.isArray(source)) {
112
+ let changed$1 = false;
113
+ const clone$1 = [...source];
114
+ seen.set(source, clone$1);
115
+ for (let i = 0; i < source.length; i++) {
116
+ const nextValue = normalizeNestedDelegatedAnnotationState(source[i], seen);
117
+ if (nextValue !== source[i]) {
118
+ clone$1[i] = nextValue;
119
+ changed$1 = true;
120
+ }
121
+ }
122
+ if (!changed$1) {
123
+ seen.set(source, source);
124
+ return source;
125
+ }
126
+ return clone$1;
127
+ }
128
+ const proto = Object.getPrototypeOf(source);
129
+ if (proto !== Object.prototype && proto !== null) return normalized;
130
+ const descriptors = Object.getOwnPropertyDescriptors(source);
131
+ let changed = false;
132
+ const clone = Object.create(proto);
133
+ seen.set(source, clone);
134
+ for (const key of Reflect.ownKeys(descriptors)) {
135
+ const descriptor = descriptors[key];
136
+ if (descriptor != null && "value" in descriptor) {
137
+ const nextValue = normalizeNestedDelegatedAnnotationState(descriptor.value, seen);
138
+ if (nextValue !== descriptor.value) {
139
+ descriptors[key] = {
140
+ ...descriptor,
141
+ value: nextValue
142
+ };
143
+ changed = true;
144
+ }
145
+ }
146
+ }
147
+ if (!changed) {
148
+ seen.set(source, source);
149
+ return source;
150
+ }
151
+ Object.defineProperties(clone, descriptors);
152
+ return clone;
153
+ }
154
+ /**
155
+ * Creates a short-lived delegated state that exposes the parent's annotations
156
+ * regardless of the child state's runtime shape.
157
+ *
158
+ * Primitive and nullish states use `injectAnnotations()`, plain objects and
159
+ * built-ins use `inheritAnnotations()`, and non-plain objects use an
160
+ * annotation-view proxy so class invariants such as private fields remain
161
+ * intact.
162
+ *
163
+ * @param parentState The state carrying the annotations to delegate.
164
+ * @param childState The child state that should observe those annotations.
165
+ * @returns A delegated child state that exposes the parent's annotations.
166
+ * @internal
167
+ */
168
+ function getDelegatedAnnotationState(parentState, childState) {
169
+ const annotations = require_annotations.getAnnotations(parentState);
170
+ if (annotations === void 0 || require_annotations.getAnnotations(childState) === annotations) return childState;
171
+ if (childState == null || typeof childState !== "object") return require_annotations.injectAnnotations(childState, annotations);
172
+ if (require_annotations.isInjectedAnnotationWrapper(childState)) return require_annotations.injectAnnotations(normalizeInjectedAnnotationState(childState), annotations);
173
+ if (isNonPlainDelegatedObject(childState)) return withAnnotationView(childState, annotations);
174
+ return require_annotations.inheritAnnotations(parentState, childState);
175
+ }
61
176
  /**
62
177
  * Returns whether a state is still at the initial sentinel after normalizing
63
178
  * Optique's injected annotation wrapper.
@@ -143,9 +258,13 @@ function reconcileObjectChildState(parentState, childState) {
143
258
 
144
259
  //#endregion
145
260
  exports.annotationViewTargets = annotationViewTargets;
261
+ exports.getDelegatedAnnotationState = getDelegatedAnnotationState;
146
262
  exports.getWrappedChildParseState = getWrappedChildParseState;
147
263
  exports.getWrappedChildState = getWrappedChildState;
264
+ exports.hasDelegatedAnnotationCarrier = hasDelegatedAnnotationCarrier;
148
265
  exports.isAnnotationWrappedInitialState = isAnnotationWrappedInitialState;
266
+ exports.normalizeDelegatedAnnotationState = normalizeDelegatedAnnotationState;
149
267
  exports.normalizeInjectedAnnotationState = normalizeInjectedAnnotationState;
268
+ exports.normalizeNestedDelegatedAnnotationState = normalizeNestedDelegatedAnnotationState;
150
269
  exports.reconcileObjectChildState = reconcileObjectChildState;
151
270
  exports.unwrapAnnotationView = unwrapAnnotationView;
@@ -1,4 +1,4 @@
1
- import { annotationKey, getAnnotations, inheritAnnotations, injectAnnotations, unwrapInjectedAnnotationWrapper } from "./annotations.js";
1
+ import { annotationKey, getAnnotations, inheritAnnotations, injectAnnotations, isInjectedAnnotationWrapper, unwrapInjectedAnnotationWrapper } from "./annotations.js";
2
2
  import { inheritParentAnnotationsKey } from "./parser.js";
3
3
 
4
4
  //#region src/annotation-state.ts
@@ -58,6 +58,121 @@ function withAnnotationView(state, annotations) {
58
58
  function normalizeInjectedAnnotationState(state) {
59
59
  return unwrapInjectedAnnotationWrapper(state);
60
60
  }
61
+ function isNonPlainDelegatedObject(state) {
62
+ if (Array.isArray(state) || state instanceof Date || state instanceof Map || state instanceof Set || state instanceof RegExp) return false;
63
+ const proto = Object.getPrototypeOf(state);
64
+ return proto !== Object.prototype && proto !== null;
65
+ }
66
+ /**
67
+ * Removes Optique's internal annotation carriers from a delegated state.
68
+ *
69
+ * This unwraps both primitive-state annotation wrappers and annotation-view
70
+ * proxies used for non-plain object states.
71
+ *
72
+ * @param state The delegated state to normalize.
73
+ * @returns The original underlying state value.
74
+ * @internal
75
+ */
76
+ function normalizeDelegatedAnnotationState(state) {
77
+ return normalizeInjectedAnnotationState(unwrapAnnotationView(state));
78
+ }
79
+ /**
80
+ * Returns whether the given state uses an internal delegated annotation carrier.
81
+ *
82
+ * @param state The candidate state to inspect.
83
+ * @returns `true` when the state is an injected primitive wrapper or an
84
+ * annotation-view proxy.
85
+ * @internal
86
+ */
87
+ function hasDelegatedAnnotationCarrier(state) {
88
+ return state != null && typeof state === "object" && (isInjectedAnnotationWrapper(state) || annotationViewTargets.has(state));
89
+ }
90
+ /**
91
+ * Recursively removes delegated annotation carriers from plain-object and array
92
+ * structures.
93
+ *
94
+ * Nested plain objects and arrays are shallow-cloned only when a delegated
95
+ * carrier is found below them. Non-plain objects are unwrapped at the top
96
+ * level and then preserved as-is to avoid mutating or reconstructing class
97
+ * instances.
98
+ *
99
+ * @param value The candidate value to normalize.
100
+ * @param seen Tracks already-normalized objects so cyclic values keep their
101
+ * shape.
102
+ * @returns The original value when no delegated carriers are present, or a
103
+ * normalized clone with delegated carriers removed.
104
+ * @internal
105
+ */
106
+ function normalizeNestedDelegatedAnnotationState(value, seen = /* @__PURE__ */ new WeakMap()) {
107
+ const normalized = normalizeDelegatedAnnotationState(value);
108
+ if (normalized == null || typeof normalized !== "object") return normalized;
109
+ const source = normalized;
110
+ if (seen.has(source)) return seen.get(source);
111
+ if (Array.isArray(source)) {
112
+ let changed$1 = false;
113
+ const clone$1 = [...source];
114
+ seen.set(source, clone$1);
115
+ for (let i = 0; i < source.length; i++) {
116
+ const nextValue = normalizeNestedDelegatedAnnotationState(source[i], seen);
117
+ if (nextValue !== source[i]) {
118
+ clone$1[i] = nextValue;
119
+ changed$1 = true;
120
+ }
121
+ }
122
+ if (!changed$1) {
123
+ seen.set(source, source);
124
+ return source;
125
+ }
126
+ return clone$1;
127
+ }
128
+ const proto = Object.getPrototypeOf(source);
129
+ if (proto !== Object.prototype && proto !== null) return normalized;
130
+ const descriptors = Object.getOwnPropertyDescriptors(source);
131
+ let changed = false;
132
+ const clone = Object.create(proto);
133
+ seen.set(source, clone);
134
+ for (const key of Reflect.ownKeys(descriptors)) {
135
+ const descriptor = descriptors[key];
136
+ if (descriptor != null && "value" in descriptor) {
137
+ const nextValue = normalizeNestedDelegatedAnnotationState(descriptor.value, seen);
138
+ if (nextValue !== descriptor.value) {
139
+ descriptors[key] = {
140
+ ...descriptor,
141
+ value: nextValue
142
+ };
143
+ changed = true;
144
+ }
145
+ }
146
+ }
147
+ if (!changed) {
148
+ seen.set(source, source);
149
+ return source;
150
+ }
151
+ Object.defineProperties(clone, descriptors);
152
+ return clone;
153
+ }
154
+ /**
155
+ * Creates a short-lived delegated state that exposes the parent's annotations
156
+ * regardless of the child state's runtime shape.
157
+ *
158
+ * Primitive and nullish states use `injectAnnotations()`, plain objects and
159
+ * built-ins use `inheritAnnotations()`, and non-plain objects use an
160
+ * annotation-view proxy so class invariants such as private fields remain
161
+ * intact.
162
+ *
163
+ * @param parentState The state carrying the annotations to delegate.
164
+ * @param childState The child state that should observe those annotations.
165
+ * @returns A delegated child state that exposes the parent's annotations.
166
+ * @internal
167
+ */
168
+ function getDelegatedAnnotationState(parentState, childState) {
169
+ const annotations = getAnnotations(parentState);
170
+ if (annotations === void 0 || getAnnotations(childState) === annotations) return childState;
171
+ if (childState == null || typeof childState !== "object") return injectAnnotations(childState, annotations);
172
+ if (isInjectedAnnotationWrapper(childState)) return injectAnnotations(normalizeInjectedAnnotationState(childState), annotations);
173
+ if (isNonPlainDelegatedObject(childState)) return withAnnotationView(childState, annotations);
174
+ return inheritAnnotations(parentState, childState);
175
+ }
61
176
  /**
62
177
  * Returns whether a state is still at the initial sentinel after normalizing
63
178
  * Optique's injected annotation wrapper.
@@ -142,4 +257,4 @@ function reconcileObjectChildState(parentState, childState) {
142
257
  }
143
258
 
144
259
  //#endregion
145
- export { annotationViewTargets, getWrappedChildParseState, getWrappedChildState, isAnnotationWrappedInitialState, normalizeInjectedAnnotationState, reconcileObjectChildState, unwrapAnnotationView };
260
+ export { annotationViewTargets, getDelegatedAnnotationState, getWrappedChildParseState, getWrappedChildState, hasDelegatedAnnotationCarrier, isAnnotationWrappedInitialState, normalizeDelegatedAnnotationState, normalizeInjectedAnnotationState, normalizeNestedDelegatedAnnotationState, reconcileObjectChildState, unwrapAnnotationView };
@@ -4,6 +4,7 @@ const require_mode_dispatch = require('./mode-dispatch.cjs');
4
4
  const require_dependency_metadata = require('./dependency-metadata.cjs');
5
5
  const require_phase2_seed = require('./phase2-seed.cjs');
6
6
  const require_parser = require('./parser.cjs');
7
+ const require_annotation_state = require('./annotation-state.cjs');
7
8
 
8
9
  //#region src/modifiers.ts
9
10
  function withChildExecPath(exec, segment) {
@@ -81,9 +82,77 @@ function unwrapMultipleItemState(state) {
81
82
  function isPromiseLike(value) {
82
83
  return value != null && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function";
83
84
  }
85
+ function normalizeOptionalLikeCompleteResult(result) {
86
+ return result.success ? {
87
+ ...result,
88
+ value: require_annotation_state.normalizeNestedDelegatedAnnotationState(result.value)
89
+ } : result;
90
+ }
91
+ function completeOptionalLikeSync(parser, state, exec) {
92
+ const hasCarrier = require_annotation_state.hasDelegatedAnnotationCarrier(state);
93
+ try {
94
+ return normalizeOptionalLikeCompleteResult(parser.complete(state, exec));
95
+ } catch (error) {
96
+ if (!hasCarrier) throw error;
97
+ const fallbackState = require_annotation_state.normalizeDelegatedAnnotationState(state);
98
+ return normalizeOptionalLikeCompleteResult(parser.complete(fallbackState, exec));
99
+ }
100
+ }
101
+ async function completeOptionalLikeAsync(parser, state, exec) {
102
+ const hasCarrier = require_annotation_state.hasDelegatedAnnotationCarrier(state);
103
+ try {
104
+ return normalizeOptionalLikeCompleteResult(await parser.complete(state, exec));
105
+ } catch (error) {
106
+ if (!hasCarrier) throw error;
107
+ const fallbackState = require_annotation_state.normalizeDelegatedAnnotationState(state);
108
+ return normalizeOptionalLikeCompleteResult(await parser.complete(fallbackState, exec));
109
+ }
110
+ }
111
+ function normalizeOptionalLikePhase2Seed(seed) {
112
+ return seed == null ? null : {
113
+ ...seed,
114
+ value: require_annotation_state.normalizeNestedDelegatedAnnotationState(seed.value)
115
+ };
116
+ }
84
117
  function extractOptionalLikePhase2Seed(parser, state, exec) {
85
118
  if (!Array.isArray(state) && !(state != null && typeof state === "object")) return require_mode_dispatch.wrapForMode(parser.$mode, null);
86
- return require_phase2_seed.completeOrExtractPhase2Seed(parser, normalizeOptionalLikeInnerState(state, parser.initialState, parser), exec);
119
+ const innerState = normalizeOptionalLikeInnerState(state, parser.initialState, parser);
120
+ const hasCarrier = require_annotation_state.hasDelegatedAnnotationCarrier(innerState);
121
+ return require_mode_dispatch.dispatchByMode(parser.$mode, () => {
122
+ try {
123
+ const result = parser.complete(innerState, exec);
124
+ if (result.success) return normalizeOptionalLikePhase2Seed(require_phase2_seed.phase2SeedFromValueResult(result));
125
+ const seed = require_phase2_seed.extractPhase2Seed(parser, innerState, exec);
126
+ if (seed == null && hasCarrier) {
127
+ const fallbackState = require_annotation_state.normalizeDelegatedAnnotationState(innerState);
128
+ return normalizeOptionalLikePhase2Seed(require_phase2_seed.extractPhase2Seed(parser, fallbackState, exec));
129
+ }
130
+ return normalizeOptionalLikePhase2Seed(seed);
131
+ } catch (error) {
132
+ if (!hasCarrier) throw error;
133
+ const fallbackState = require_annotation_state.normalizeDelegatedAnnotationState(innerState);
134
+ const result = parser.complete(fallbackState, exec);
135
+ if (result.success) return normalizeOptionalLikePhase2Seed(require_phase2_seed.phase2SeedFromValueResult(result));
136
+ return normalizeOptionalLikePhase2Seed(require_phase2_seed.extractPhase2Seed(parser, fallbackState, exec));
137
+ }
138
+ }, async () => {
139
+ try {
140
+ const result = await parser.complete(innerState, exec);
141
+ if (result.success) return normalizeOptionalLikePhase2Seed(require_phase2_seed.phase2SeedFromValueResult(result));
142
+ const seed = await require_phase2_seed.extractPhase2Seed(parser, innerState, exec);
143
+ if (seed == null && hasCarrier) {
144
+ const fallbackState = require_annotation_state.normalizeDelegatedAnnotationState(innerState);
145
+ return normalizeOptionalLikePhase2Seed(await require_phase2_seed.extractPhase2Seed(parser, fallbackState, exec));
146
+ }
147
+ return normalizeOptionalLikePhase2Seed(seed);
148
+ } catch (error) {
149
+ if (!hasCarrier) throw error;
150
+ const fallbackState = require_annotation_state.normalizeDelegatedAnnotationState(innerState);
151
+ const result = await parser.complete(fallbackState, exec);
152
+ if (result.success) return normalizeOptionalLikePhase2Seed(require_phase2_seed.phase2SeedFromValueResult(result));
153
+ return normalizeOptionalLikePhase2Seed(await require_phase2_seed.extractPhase2Seed(parser, fallbackState, exec));
154
+ }
155
+ });
87
156
  }
88
157
  /**
89
158
  * Computes the inner state to pass through to the wrapped parser inside
@@ -182,7 +251,15 @@ function processOptionalStyleResult(result, innerState, context) {
182
251
  */
183
252
  function adaptShouldDeferCompletion(innerCheck, parser) {
184
253
  return (state, exec) => {
185
- if (Array.isArray(state) || state != null && typeof state === "object") return innerCheck(normalizeOptionalLikeInnerState(state, parser.initialState, parser), exec);
254
+ if (Array.isArray(state) || state != null && typeof state === "object") {
255
+ const innerState = normalizeOptionalLikeInnerState(state, parser.initialState, parser);
256
+ try {
257
+ return innerCheck(innerState, exec);
258
+ } catch (error) {
259
+ if (!require_annotation_state.hasDelegatedAnnotationCarrier(innerState)) throw error;
260
+ return innerCheck(require_annotation_state.normalizeDelegatedAnnotationState(innerState), exec);
261
+ }
262
+ }
186
263
  return false;
187
264
  };
188
265
  }
@@ -192,9 +269,9 @@ function isAnnotationOnlyObjectState(state) {
192
269
  return require_annotations.getAnnotations(state) != null && keys.length === 1 && keys[0] === require_annotations.annotationKey;
193
270
  }
194
271
  function normalizeOptionalLikeInnerState(state, initialState, parser) {
195
- if (Array.isArray(state)) return require_annotations.getAnnotations(state) != null && state[0] != null && typeof state[0] === "object" ? require_annotations.inheritAnnotations(state, state[0]) : state[0];
272
+ if (Array.isArray(state)) return require_annotation_state.getDelegatedAnnotationState(state, state[0]);
196
273
  if (isAnnotationOnlyObjectState(state)) {
197
- if (parser != null && (parser.dependencyMetadata?.source != null || typeof parser.shouldDeferCompletion === "function")) return require_annotations.inheritAnnotations(state, initialState);
274
+ if (parser != null && (parser.dependencyMetadata?.source != null || typeof parser.shouldDeferCompletion === "function")) return require_annotation_state.getDelegatedAnnotationState(state, initialState);
198
275
  return initialState;
199
276
  }
200
277
  if (state != null && typeof state === "object") return state;
@@ -266,7 +343,7 @@ function optional(parser) {
266
343
  complete(state, exec) {
267
344
  if (!Array.isArray(state)) {
268
345
  const delegateToInner = (resolvedInnerState) => {
269
- const innerResult = require_mode_dispatch.dispatchByMode(parser.$mode, () => syncParser.complete(resolvedInnerState, exec), async () => await parser.complete(resolvedInnerState, exec));
346
+ const innerResult = require_mode_dispatch.dispatchByMode(parser.$mode, () => completeOptionalLikeSync(syncParser, resolvedInnerState, exec), async () => await completeOptionalLikeAsync(parser, resolvedInnerState, exec));
270
347
  return require_mode_dispatch.mapModeValue(parser.$mode, innerResult, (result) => result.success ? result : {
271
348
  success: true,
272
349
  value: void 0
@@ -279,7 +356,7 @@ function optional(parser) {
279
356
  const sourceMetadata = parser.dependencyMetadata?.source;
280
357
  if (sourceMetadata?.preservesSourceValue !== false && sourceMetadata?.getMissingSourceValue != null) {
281
358
  const delegatedState = normalizeOptionalLikeInnerState(state, parser.initialState, parser);
282
- return require_mode_dispatch.dispatchByMode(parser.$mode, () => syncParser.complete(delegatedState, exec), async () => await parser.complete(delegatedState, exec));
359
+ return require_mode_dispatch.dispatchByMode(parser.$mode, () => completeOptionalLikeSync(syncParser, delegatedState, exec), async () => await completeOptionalLikeAsync(parser, delegatedState, exec));
283
360
  }
284
361
  if (parser[require_parser.unmatchedNonCliDependencySourceStateMarker] === true && state != null && typeof state === "object") {
285
362
  const innerState = normalizeOptionalLikeInnerState(state, parser.initialState, parser);
@@ -291,7 +368,7 @@ function optional(parser) {
291
368
  };
292
369
  }
293
370
  const innerElement = normalizeOptionalLikeInnerState(state, parser.initialState, parser);
294
- return require_mode_dispatch.dispatchByMode(parser.$mode, () => syncParser.complete(innerElement, exec), async () => await parser.complete(innerElement, exec));
371
+ return require_mode_dispatch.dispatchByMode(parser.$mode, () => completeOptionalLikeSync(syncParser, innerElement, exec), async () => await completeOptionalLikeAsync(parser, innerElement, exec));
295
372
  },
296
373
  suggest(context, prefix) {
297
374
  return require_mode_dispatch.dispatchIterableByMode(parser.$mode, () => suggestSync(context, prefix), () => suggestAsync(context, prefix));
@@ -442,12 +519,12 @@ function withDefault(parser, defaultValue, options) {
442
519
  if (!Array.isArray(state)) {
443
520
  if (typeof parser.shouldDeferCompletion === "function" && state != null && typeof state === "object") {
444
521
  const innerState = normalizeOptionalLikeInnerState(state, parser.initialState, parser);
445
- const innerResult = require_mode_dispatch.dispatchByMode(parser.$mode, () => syncParser.complete(innerState, exec), async () => await parser.complete(innerState, exec));
522
+ const innerResult = require_mode_dispatch.dispatchByMode(parser.$mode, () => completeOptionalLikeSync(syncParser, innerState, exec), async () => await completeOptionalLikeAsync(parser, innerState, exec));
446
523
  return innerResult;
447
524
  }
448
525
  if (parser[require_parser.unmatchedNonCliDependencySourceStateMarker] === true && state != null && typeof state === "object") {
449
526
  const innerState = normalizeOptionalLikeInnerState(state, parser.initialState, parser);
450
- const innerResult = require_mode_dispatch.dispatchByMode(parser.$mode, () => syncParser.complete(innerState, exec), async () => await parser.complete(innerState, exec));
527
+ const innerResult = require_mode_dispatch.dispatchByMode(parser.$mode, () => completeOptionalLikeSync(syncParser, innerState, exec), async () => await completeOptionalLikeAsync(parser, innerState, exec));
451
528
  const handleInnerResult = (result) => {
452
529
  if (result.success && result.value !== void 0) return result;
453
530
  try {
@@ -478,7 +555,7 @@ function withDefault(parser, defaultValue, options) {
478
555
  }
479
556
  }
480
557
  const innerElement = normalizeOptionalLikeInnerState(state, parser.initialState, parser);
481
- return require_mode_dispatch.dispatchByMode(parser.$mode, () => syncParser.complete(innerElement, exec), async () => await parser.complete(innerElement, exec));
558
+ return require_mode_dispatch.dispatchByMode(parser.$mode, () => completeOptionalLikeSync(syncParser, innerElement, exec), async () => await completeOptionalLikeAsync(parser, innerElement, exec));
482
559
  },
483
560
  suggest(context, prefix) {
484
561
  return require_mode_dispatch.dispatchIterableByMode(parser.$mode, () => suggestSync(context, prefix), () => suggestAsync(context, prefix));
package/dist/modifiers.js CHANGED
@@ -2,8 +2,9 @@ import { annotateFreshArray, annotationKey, getAnnotations, inheritAnnotations,
2
2
  import { formatMessage, message, text } from "./message.js";
3
3
  import { dispatchByMode, dispatchIterableByMode, mapModeValue, wrapForMode } from "./mode-dispatch.js";
4
4
  import { composeDependencyMetadata } from "./dependency-metadata.js";
5
- import { completeOrExtractPhase2Seed, extractPhase2Seed, extractPhase2SeedKey } from "./phase2-seed.js";
5
+ import { completeOrExtractPhase2Seed, extractPhase2Seed, extractPhase2SeedKey, phase2SeedFromValueResult } from "./phase2-seed.js";
6
6
  import { defineInheritedAnnotationParser, defineSourceBindingOnlyAnnotationCompletionParser, unmatchedNonCliDependencySourceStateMarker } from "./parser.js";
7
+ import { getDelegatedAnnotationState, hasDelegatedAnnotationCarrier, normalizeDelegatedAnnotationState, normalizeNestedDelegatedAnnotationState } from "./annotation-state.js";
7
8
 
8
9
  //#region src/modifiers.ts
9
10
  function withChildExecPath(exec, segment) {
@@ -81,9 +82,77 @@ function unwrapMultipleItemState(state) {
81
82
  function isPromiseLike(value) {
82
83
  return value != null && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function";
83
84
  }
85
+ function normalizeOptionalLikeCompleteResult(result) {
86
+ return result.success ? {
87
+ ...result,
88
+ value: normalizeNestedDelegatedAnnotationState(result.value)
89
+ } : result;
90
+ }
91
+ function completeOptionalLikeSync(parser, state, exec) {
92
+ const hasCarrier = hasDelegatedAnnotationCarrier(state);
93
+ try {
94
+ return normalizeOptionalLikeCompleteResult(parser.complete(state, exec));
95
+ } catch (error) {
96
+ if (!hasCarrier) throw error;
97
+ const fallbackState = normalizeDelegatedAnnotationState(state);
98
+ return normalizeOptionalLikeCompleteResult(parser.complete(fallbackState, exec));
99
+ }
100
+ }
101
+ async function completeOptionalLikeAsync(parser, state, exec) {
102
+ const hasCarrier = hasDelegatedAnnotationCarrier(state);
103
+ try {
104
+ return normalizeOptionalLikeCompleteResult(await parser.complete(state, exec));
105
+ } catch (error) {
106
+ if (!hasCarrier) throw error;
107
+ const fallbackState = normalizeDelegatedAnnotationState(state);
108
+ return normalizeOptionalLikeCompleteResult(await parser.complete(fallbackState, exec));
109
+ }
110
+ }
111
+ function normalizeOptionalLikePhase2Seed(seed) {
112
+ return seed == null ? null : {
113
+ ...seed,
114
+ value: normalizeNestedDelegatedAnnotationState(seed.value)
115
+ };
116
+ }
84
117
  function extractOptionalLikePhase2Seed(parser, state, exec) {
85
118
  if (!Array.isArray(state) && !(state != null && typeof state === "object")) return wrapForMode(parser.$mode, null);
86
- return completeOrExtractPhase2Seed(parser, normalizeOptionalLikeInnerState(state, parser.initialState, parser), exec);
119
+ const innerState = normalizeOptionalLikeInnerState(state, parser.initialState, parser);
120
+ const hasCarrier = hasDelegatedAnnotationCarrier(innerState);
121
+ return dispatchByMode(parser.$mode, () => {
122
+ try {
123
+ const result = parser.complete(innerState, exec);
124
+ if (result.success) return normalizeOptionalLikePhase2Seed(phase2SeedFromValueResult(result));
125
+ const seed = extractPhase2Seed(parser, innerState, exec);
126
+ if (seed == null && hasCarrier) {
127
+ const fallbackState = normalizeDelegatedAnnotationState(innerState);
128
+ return normalizeOptionalLikePhase2Seed(extractPhase2Seed(parser, fallbackState, exec));
129
+ }
130
+ return normalizeOptionalLikePhase2Seed(seed);
131
+ } catch (error) {
132
+ if (!hasCarrier) throw error;
133
+ const fallbackState = normalizeDelegatedAnnotationState(innerState);
134
+ const result = parser.complete(fallbackState, exec);
135
+ if (result.success) return normalizeOptionalLikePhase2Seed(phase2SeedFromValueResult(result));
136
+ return normalizeOptionalLikePhase2Seed(extractPhase2Seed(parser, fallbackState, exec));
137
+ }
138
+ }, async () => {
139
+ try {
140
+ const result = await parser.complete(innerState, exec);
141
+ if (result.success) return normalizeOptionalLikePhase2Seed(phase2SeedFromValueResult(result));
142
+ const seed = await extractPhase2Seed(parser, innerState, exec);
143
+ if (seed == null && hasCarrier) {
144
+ const fallbackState = normalizeDelegatedAnnotationState(innerState);
145
+ return normalizeOptionalLikePhase2Seed(await extractPhase2Seed(parser, fallbackState, exec));
146
+ }
147
+ return normalizeOptionalLikePhase2Seed(seed);
148
+ } catch (error) {
149
+ if (!hasCarrier) throw error;
150
+ const fallbackState = normalizeDelegatedAnnotationState(innerState);
151
+ const result = await parser.complete(fallbackState, exec);
152
+ if (result.success) return normalizeOptionalLikePhase2Seed(phase2SeedFromValueResult(result));
153
+ return normalizeOptionalLikePhase2Seed(await extractPhase2Seed(parser, fallbackState, exec));
154
+ }
155
+ });
87
156
  }
88
157
  /**
89
158
  * Computes the inner state to pass through to the wrapped parser inside
@@ -182,7 +251,15 @@ function processOptionalStyleResult(result, innerState, context) {
182
251
  */
183
252
  function adaptShouldDeferCompletion(innerCheck, parser) {
184
253
  return (state, exec) => {
185
- if (Array.isArray(state) || state != null && typeof state === "object") return innerCheck(normalizeOptionalLikeInnerState(state, parser.initialState, parser), exec);
254
+ if (Array.isArray(state) || state != null && typeof state === "object") {
255
+ const innerState = normalizeOptionalLikeInnerState(state, parser.initialState, parser);
256
+ try {
257
+ return innerCheck(innerState, exec);
258
+ } catch (error) {
259
+ if (!hasDelegatedAnnotationCarrier(innerState)) throw error;
260
+ return innerCheck(normalizeDelegatedAnnotationState(innerState), exec);
261
+ }
262
+ }
186
263
  return false;
187
264
  };
188
265
  }
@@ -192,9 +269,9 @@ function isAnnotationOnlyObjectState(state) {
192
269
  return getAnnotations(state) != null && keys.length === 1 && keys[0] === annotationKey;
193
270
  }
194
271
  function normalizeOptionalLikeInnerState(state, initialState, parser) {
195
- if (Array.isArray(state)) return getAnnotations(state) != null && state[0] != null && typeof state[0] === "object" ? inheritAnnotations(state, state[0]) : state[0];
272
+ if (Array.isArray(state)) return getDelegatedAnnotationState(state, state[0]);
196
273
  if (isAnnotationOnlyObjectState(state)) {
197
- if (parser != null && (parser.dependencyMetadata?.source != null || typeof parser.shouldDeferCompletion === "function")) return inheritAnnotations(state, initialState);
274
+ if (parser != null && (parser.dependencyMetadata?.source != null || typeof parser.shouldDeferCompletion === "function")) return getDelegatedAnnotationState(state, initialState);
198
275
  return initialState;
199
276
  }
200
277
  if (state != null && typeof state === "object") return state;
@@ -266,7 +343,7 @@ function optional(parser) {
266
343
  complete(state, exec) {
267
344
  if (!Array.isArray(state)) {
268
345
  const delegateToInner = (resolvedInnerState) => {
269
- const innerResult = dispatchByMode(parser.$mode, () => syncParser.complete(resolvedInnerState, exec), async () => await parser.complete(resolvedInnerState, exec));
346
+ const innerResult = dispatchByMode(parser.$mode, () => completeOptionalLikeSync(syncParser, resolvedInnerState, exec), async () => await completeOptionalLikeAsync(parser, resolvedInnerState, exec));
270
347
  return mapModeValue(parser.$mode, innerResult, (result) => result.success ? result : {
271
348
  success: true,
272
349
  value: void 0
@@ -279,7 +356,7 @@ function optional(parser) {
279
356
  const sourceMetadata = parser.dependencyMetadata?.source;
280
357
  if (sourceMetadata?.preservesSourceValue !== false && sourceMetadata?.getMissingSourceValue != null) {
281
358
  const delegatedState = normalizeOptionalLikeInnerState(state, parser.initialState, parser);
282
- return dispatchByMode(parser.$mode, () => syncParser.complete(delegatedState, exec), async () => await parser.complete(delegatedState, exec));
359
+ return dispatchByMode(parser.$mode, () => completeOptionalLikeSync(syncParser, delegatedState, exec), async () => await completeOptionalLikeAsync(parser, delegatedState, exec));
283
360
  }
284
361
  if (parser[unmatchedNonCliDependencySourceStateMarker] === true && state != null && typeof state === "object") {
285
362
  const innerState = normalizeOptionalLikeInnerState(state, parser.initialState, parser);
@@ -291,7 +368,7 @@ function optional(parser) {
291
368
  };
292
369
  }
293
370
  const innerElement = normalizeOptionalLikeInnerState(state, parser.initialState, parser);
294
- return dispatchByMode(parser.$mode, () => syncParser.complete(innerElement, exec), async () => await parser.complete(innerElement, exec));
371
+ return dispatchByMode(parser.$mode, () => completeOptionalLikeSync(syncParser, innerElement, exec), async () => await completeOptionalLikeAsync(parser, innerElement, exec));
295
372
  },
296
373
  suggest(context, prefix) {
297
374
  return dispatchIterableByMode(parser.$mode, () => suggestSync(context, prefix), () => suggestAsync(context, prefix));
@@ -442,12 +519,12 @@ function withDefault(parser, defaultValue, options) {
442
519
  if (!Array.isArray(state)) {
443
520
  if (typeof parser.shouldDeferCompletion === "function" && state != null && typeof state === "object") {
444
521
  const innerState = normalizeOptionalLikeInnerState(state, parser.initialState, parser);
445
- const innerResult = dispatchByMode(parser.$mode, () => syncParser.complete(innerState, exec), async () => await parser.complete(innerState, exec));
522
+ const innerResult = dispatchByMode(parser.$mode, () => completeOptionalLikeSync(syncParser, innerState, exec), async () => await completeOptionalLikeAsync(parser, innerState, exec));
446
523
  return innerResult;
447
524
  }
448
525
  if (parser[unmatchedNonCliDependencySourceStateMarker] === true && state != null && typeof state === "object") {
449
526
  const innerState = normalizeOptionalLikeInnerState(state, parser.initialState, parser);
450
- const innerResult = dispatchByMode(parser.$mode, () => syncParser.complete(innerState, exec), async () => await parser.complete(innerState, exec));
527
+ const innerResult = dispatchByMode(parser.$mode, () => completeOptionalLikeSync(syncParser, innerState, exec), async () => await completeOptionalLikeAsync(parser, innerState, exec));
451
528
  const handleInnerResult = (result) => {
452
529
  if (result.success && result.value !== void 0) return result;
453
530
  try {
@@ -478,7 +555,7 @@ function withDefault(parser, defaultValue, options) {
478
555
  }
479
556
  }
480
557
  const innerElement = normalizeOptionalLikeInnerState(state, parser.initialState, parser);
481
- return dispatchByMode(parser.$mode, () => syncParser.complete(innerElement, exec), async () => await parser.complete(innerElement, exec));
558
+ return dispatchByMode(parser.$mode, () => completeOptionalLikeSync(syncParser, innerElement, exec), async () => await completeOptionalLikeAsync(parser, innerElement, exec));
482
559
  },
483
560
  suggest(context, prefix) {
484
561
  return dispatchIterableByMode(parser.$mode, () => suggestSync(context, prefix), () => suggestAsync(context, prefix));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optique/core",
3
- "version": "1.0.0-dev.1890+0291e3fc",
3
+ "version": "1.0.0-dev.1893+e1c35f1a",
4
4
  "description": "Type-safe combinatorial command-line interface parser",
5
5
  "keywords": [
6
6
  "CLI",