@o3co/ts.hocon 1.5.2 → 1.6.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/{config-BwjvKeZ5.d.cts → config-DCSLXkNY.d.cts} +11 -6
- package/dist/{config-BwjvKeZ5.d.ts → config-DCSLXkNY.d.ts} +11 -6
- package/dist/index.cjs +289 -183
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +289 -183
- package/dist/zod.cjs +289 -183
- package/dist/zod.d.cts +1 -1
- package/dist/zod.d.ts +1 -1
- package/dist/zod.js +289 -183
- package/package.json +1 -1
package/dist/zod.cjs
CHANGED
|
@@ -280,55 +280,6 @@ var NotResolvedError = class extends ConfigError {
|
|
|
280
280
|
}
|
|
281
281
|
};
|
|
282
282
|
|
|
283
|
-
// src/internal/resolver/types.ts
|
|
284
|
-
var separatorValues = /* @__PURE__ */ new WeakSet();
|
|
285
|
-
function isSubst(v) {
|
|
286
|
-
return v._kind === "subst-placeholder";
|
|
287
|
-
}
|
|
288
|
-
function isConcat(v) {
|
|
289
|
-
return v._kind === "concat-placeholder";
|
|
290
|
-
}
|
|
291
|
-
function isAppend(v) {
|
|
292
|
-
return v._kind === "append-placeholder";
|
|
293
|
-
}
|
|
294
|
-
function isResObj(v) {
|
|
295
|
-
return v._kind === "res-obj";
|
|
296
|
-
}
|
|
297
|
-
function makeResObj() {
|
|
298
|
-
return { _kind: "res-obj", fields: /* @__PURE__ */ new Map(), priorValues: /* @__PURE__ */ new Map() };
|
|
299
|
-
}
|
|
300
|
-
function mergeUnresolved(receiver, fallback) {
|
|
301
|
-
const result = makeResObj();
|
|
302
|
-
for (const [k, v] of fallback.fields) {
|
|
303
|
-
result.fields.set(k, v);
|
|
304
|
-
}
|
|
305
|
-
for (const [k, v] of fallback.priorValues) {
|
|
306
|
-
result.priorValues.set(k, v);
|
|
307
|
-
}
|
|
308
|
-
for (const [k, rv] of receiver.fields) {
|
|
309
|
-
const existing = result.fields.get(k);
|
|
310
|
-
if (existing !== void 0) {
|
|
311
|
-
const recPrior = receiver.priorValues.get(k);
|
|
312
|
-
if (recPrior !== void 0 && !isResObj(recPrior)) {
|
|
313
|
-
result.fields.set(k, rv);
|
|
314
|
-
continue;
|
|
315
|
-
}
|
|
316
|
-
if (isResObj(rv) && isResObj(existing)) {
|
|
317
|
-
result.fields.set(k, mergeUnresolved(rv, existing));
|
|
318
|
-
continue;
|
|
319
|
-
}
|
|
320
|
-
result.priorValues.set(k, existing);
|
|
321
|
-
}
|
|
322
|
-
result.fields.set(k, rv);
|
|
323
|
-
}
|
|
324
|
-
for (const [k, v] of receiver.priorValues) {
|
|
325
|
-
if (receiver.fields.has(k)) {
|
|
326
|
-
result.priorValues.set(k, v);
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
return result;
|
|
330
|
-
}
|
|
331
|
-
|
|
332
283
|
// src/internal/resolver/fold-self-ref.ts
|
|
333
284
|
function substFullKey(s) {
|
|
334
285
|
return stringSegmentsToKey(s.segments.map((seg) => seg.text));
|
|
@@ -342,11 +293,8 @@ function stringSegmentsToKey(segments) {
|
|
|
342
293
|
}).join(".");
|
|
343
294
|
}
|
|
344
295
|
function containsSelfRef(v, fullKey) {
|
|
345
|
-
if (isSubst(v)) return substFullKey(v) === fullKey;
|
|
296
|
+
if (isSubst(v)) return !v.knownAbsent && substFullKey(v) === fullKey;
|
|
346
297
|
if (isConcat(v)) return v.nodes.some((n) => containsSelfRef(n, fullKey));
|
|
347
|
-
if (isAppend(v)) {
|
|
348
|
-
return containsSelfRef(v.existing, fullKey) || containsSelfRef(v.elem, fullKey);
|
|
349
|
-
}
|
|
350
298
|
if (isResObj(v)) {
|
|
351
299
|
for (const f of v.fields.values()) {
|
|
352
300
|
if (containsSelfRef(f, fullKey)) return true;
|
|
@@ -377,19 +325,12 @@ function foldSelfRef(v, fullKey, replacement) {
|
|
|
377
325
|
col: v.col
|
|
378
326
|
};
|
|
379
327
|
}
|
|
380
|
-
if (isAppend(v)) {
|
|
381
|
-
return {
|
|
382
|
-
_kind: "append-placeholder",
|
|
383
|
-
existing: foldSelfRef(v.existing, fullKey, replacement),
|
|
384
|
-
elem: foldSelfRef(v.elem, fullKey, replacement)
|
|
385
|
-
};
|
|
386
|
-
}
|
|
387
328
|
if (isResObj(v)) {
|
|
388
329
|
const newFields = /* @__PURE__ */ new Map();
|
|
389
330
|
for (const [k, val] of v.fields) {
|
|
390
331
|
newFields.set(k, foldSelfRef(val, fullKey, replacement));
|
|
391
332
|
}
|
|
392
|
-
return { _kind: "res-obj", fields: newFields, priorValues: new Map(v.priorValues) };
|
|
333
|
+
return { _kind: "res-obj", fields: newFields, priorValues: new Map(v.priorValues), resetKeys: new Set(v.resetKeys) };
|
|
393
334
|
}
|
|
394
335
|
const hv = v;
|
|
395
336
|
if (hv.kind === "array") {
|
|
@@ -407,17 +348,106 @@ function foldSelfRef(v, fullKey, replacement) {
|
|
|
407
348
|
}
|
|
408
349
|
return v;
|
|
409
350
|
}
|
|
351
|
+
function foldKnownAbsentSelfRef(v, fullKey, replacement) {
|
|
352
|
+
if (isSubst(v)) {
|
|
353
|
+
return v.knownAbsent && substFullKey(v) === fullKey ? replacement : v;
|
|
354
|
+
}
|
|
355
|
+
if (isConcat(v)) {
|
|
356
|
+
return {
|
|
357
|
+
_kind: "concat-placeholder",
|
|
358
|
+
nodes: v.nodes.map((n) => foldKnownAbsentSelfRef(n, fullKey, replacement)),
|
|
359
|
+
line: v.line,
|
|
360
|
+
col: v.col
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
if (isResObj(v)) {
|
|
364
|
+
const newFields = /* @__PURE__ */ new Map();
|
|
365
|
+
for (const [k, val] of v.fields) {
|
|
366
|
+
newFields.set(k, foldKnownAbsentSelfRef(val, fullKey, replacement));
|
|
367
|
+
}
|
|
368
|
+
return { _kind: "res-obj", fields: newFields, priorValues: new Map(v.priorValues), resetKeys: new Set(v.resetKeys) };
|
|
369
|
+
}
|
|
370
|
+
const hv = v;
|
|
371
|
+
if (hv.kind === "array") {
|
|
372
|
+
return {
|
|
373
|
+
kind: "array",
|
|
374
|
+
items: hv.items.map((item) => foldKnownAbsentSelfRef(item, fullKey, replacement))
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
if (hv.kind === "object") {
|
|
378
|
+
const newFields = /* @__PURE__ */ new Map();
|
|
379
|
+
for (const [k, val] of hv.fields) {
|
|
380
|
+
newFields.set(k, foldKnownAbsentSelfRef(val, fullKey, replacement));
|
|
381
|
+
}
|
|
382
|
+
return { kind: "object", fields: newFields };
|
|
383
|
+
}
|
|
384
|
+
return v;
|
|
385
|
+
}
|
|
410
386
|
function foldOrSkipPrior(prior, fullKey, old) {
|
|
411
387
|
if (!containsSelfRef(prior, fullKey)) return cloneResolverValue(prior);
|
|
412
|
-
if (old === void 0) return
|
|
388
|
+
if (old === void 0) return foldOptionalSelfRefAbsent(prior, fullKey);
|
|
413
389
|
return foldSelfRef(prior, fullKey, old);
|
|
414
390
|
}
|
|
391
|
+
function foldOptionalSelfRefAbsent(v, fullKey) {
|
|
392
|
+
if (isSubst(v) && substFullKey(v) === fullKey) {
|
|
393
|
+
if (!v.optional) return void 0;
|
|
394
|
+
return {
|
|
395
|
+
_kind: "subst-placeholder",
|
|
396
|
+
segments: v.segments.map((seg) => ({ text: seg.text, line: seg.line, col: seg.col })),
|
|
397
|
+
optional: v.optional,
|
|
398
|
+
knownAbsent: true,
|
|
399
|
+
listSuffix: v.listSuffix,
|
|
400
|
+
line: v.line,
|
|
401
|
+
col: v.col,
|
|
402
|
+
prefixLen: v.prefixLen
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
if (isConcat(v)) {
|
|
406
|
+
const nodes = [];
|
|
407
|
+
for (const node of v.nodes) {
|
|
408
|
+
const folded = foldOptionalSelfRefAbsent(node, fullKey);
|
|
409
|
+
if (folded === void 0) return void 0;
|
|
410
|
+
nodes.push(folded);
|
|
411
|
+
}
|
|
412
|
+
return { _kind: "concat-placeholder", nodes, line: v.line, col: v.col };
|
|
413
|
+
}
|
|
414
|
+
if (isResObj(v)) {
|
|
415
|
+
const fields = /* @__PURE__ */ new Map();
|
|
416
|
+
for (const [key, value] of v.fields) {
|
|
417
|
+
const folded = foldOptionalSelfRefAbsent(value, fullKey);
|
|
418
|
+
if (folded === void 0) return void 0;
|
|
419
|
+
fields.set(key, folded);
|
|
420
|
+
}
|
|
421
|
+
return { _kind: "res-obj", fields, priorValues: new Map(v.priorValues), resetKeys: new Set(v.resetKeys) };
|
|
422
|
+
}
|
|
423
|
+
const hv = v;
|
|
424
|
+
if (hv.kind === "array") {
|
|
425
|
+
const items = [];
|
|
426
|
+
for (const item of hv.items) {
|
|
427
|
+
const folded = foldOptionalSelfRefAbsent(item, fullKey);
|
|
428
|
+
if (folded === void 0) return void 0;
|
|
429
|
+
items.push(folded);
|
|
430
|
+
}
|
|
431
|
+
return { kind: "array", items };
|
|
432
|
+
}
|
|
433
|
+
if (hv.kind === "object") {
|
|
434
|
+
const fields = /* @__PURE__ */ new Map();
|
|
435
|
+
for (const [key, value] of hv.fields) {
|
|
436
|
+
const folded = foldOptionalSelfRefAbsent(value, fullKey);
|
|
437
|
+
if (folded === void 0) return void 0;
|
|
438
|
+
fields.set(key, folded);
|
|
439
|
+
}
|
|
440
|
+
return { kind: "object", fields };
|
|
441
|
+
}
|
|
442
|
+
return cloneResolverValue(v);
|
|
443
|
+
}
|
|
415
444
|
function cloneResolverValue(v) {
|
|
416
445
|
if (isSubst(v)) {
|
|
417
446
|
return {
|
|
418
447
|
_kind: "subst-placeholder",
|
|
419
448
|
segments: v.segments.map((seg) => ({ text: seg.text, line: seg.line, col: seg.col })),
|
|
420
449
|
optional: v.optional,
|
|
450
|
+
knownAbsent: v.knownAbsent,
|
|
421
451
|
listSuffix: v.listSuffix,
|
|
422
452
|
line: v.line,
|
|
423
453
|
col: v.col,
|
|
@@ -437,14 +467,7 @@ function cloneResolverValue(v) {
|
|
|
437
467
|
for (const [k, val] of v.fields) newFields.set(k, cloneResolverValue(val));
|
|
438
468
|
const newPriors = /* @__PURE__ */ new Map();
|
|
439
469
|
for (const [k, val] of v.priorValues) newPriors.set(k, cloneResolverValue(val));
|
|
440
|
-
return { _kind: "res-obj", fields: newFields, priorValues: newPriors };
|
|
441
|
-
}
|
|
442
|
-
if (isAppend(v)) {
|
|
443
|
-
return {
|
|
444
|
-
_kind: "append-placeholder",
|
|
445
|
-
existing: cloneResolverValue(v.existing),
|
|
446
|
-
elem: cloneResolverValue(v.elem)
|
|
447
|
-
};
|
|
470
|
+
return { _kind: "res-obj", fields: newFields, priorValues: newPriors, resetKeys: new Set(v.resetKeys) };
|
|
448
471
|
}
|
|
449
472
|
const hv = v;
|
|
450
473
|
if (hv.kind === "array") {
|
|
@@ -479,14 +502,11 @@ function foldNestedSelfRefs(v, pathPrefix) {
|
|
|
479
502
|
}
|
|
480
503
|
newFields.set(k, finalVal);
|
|
481
504
|
}
|
|
482
|
-
return { _kind: "res-obj", fields: newFields, priorValues: new Map(v.priorValues) };
|
|
505
|
+
return { _kind: "res-obj", fields: newFields, priorValues: new Map(v.priorValues), resetKeys: new Set(v.resetKeys) };
|
|
483
506
|
}
|
|
484
507
|
function containsSubstByPath(v, target) {
|
|
485
|
-
if (isSubst(v)) return segmentsTextEqual(v.segments, target);
|
|
508
|
+
if (isSubst(v)) return !v.knownAbsent && segmentsTextEqual(v.segments, target);
|
|
486
509
|
if (isConcat(v)) return v.nodes.some((n) => containsSubstByPath(n, target));
|
|
487
|
-
if (isAppend(v)) {
|
|
488
|
-
return containsSubstByPath(v.existing, target) || containsSubstByPath(v.elem, target);
|
|
489
|
-
}
|
|
490
510
|
if (isResObj(v)) {
|
|
491
511
|
for (const f of v.fields.values()) {
|
|
492
512
|
if (containsSubstByPath(f, target)) return true;
|
|
@@ -515,6 +535,53 @@ function segmentsTextEqual(a, b) {
|
|
|
515
535
|
return true;
|
|
516
536
|
}
|
|
517
537
|
|
|
538
|
+
// src/internal/resolver/types.ts
|
|
539
|
+
var separatorValues = /* @__PURE__ */ new WeakSet();
|
|
540
|
+
function isSubst(v) {
|
|
541
|
+
return v._kind === "subst-placeholder";
|
|
542
|
+
}
|
|
543
|
+
function isConcat(v) {
|
|
544
|
+
return v._kind === "concat-placeholder";
|
|
545
|
+
}
|
|
546
|
+
function isResObj(v) {
|
|
547
|
+
return v._kind === "res-obj";
|
|
548
|
+
}
|
|
549
|
+
function makeResObj() {
|
|
550
|
+
return { _kind: "res-obj", fields: /* @__PURE__ */ new Map(), priorValues: /* @__PURE__ */ new Map(), resetKeys: /* @__PURE__ */ new Set() };
|
|
551
|
+
}
|
|
552
|
+
function mergeUnresolved(receiver, fallback) {
|
|
553
|
+
const result = makeResObj();
|
|
554
|
+
for (const [k, v] of fallback.fields) {
|
|
555
|
+
result.fields.set(k, v);
|
|
556
|
+
}
|
|
557
|
+
for (const [k, v] of fallback.priorValues) {
|
|
558
|
+
result.priorValues.set(k, v);
|
|
559
|
+
}
|
|
560
|
+
for (const [k, rv] of receiver.fields) {
|
|
561
|
+
const existing = result.fields.get(k);
|
|
562
|
+
if (existing !== void 0) {
|
|
563
|
+
const recPrior = receiver.priorValues.get(k);
|
|
564
|
+
if (recPrior !== void 0 && !isResObj(recPrior)) {
|
|
565
|
+
result.fields.set(k, rv);
|
|
566
|
+
continue;
|
|
567
|
+
}
|
|
568
|
+
if (isResObj(rv) && isResObj(existing)) {
|
|
569
|
+
result.fields.set(k, mergeUnresolved(rv, existing));
|
|
570
|
+
continue;
|
|
571
|
+
}
|
|
572
|
+
const foldedPrior = foldOrSkipPrior(existing, k, void 0);
|
|
573
|
+
if (foldedPrior !== void 0) result.priorValues.set(k, foldedPrior);
|
|
574
|
+
}
|
|
575
|
+
result.fields.set(k, rv);
|
|
576
|
+
}
|
|
577
|
+
for (const [k, v] of receiver.priorValues) {
|
|
578
|
+
if (receiver.fields.has(k)) {
|
|
579
|
+
result.priorValues.set(k, v);
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
return result;
|
|
583
|
+
}
|
|
584
|
+
|
|
518
585
|
// src/internal/resolver/utils.ts
|
|
519
586
|
function segmentsToKey(segments) {
|
|
520
587
|
return segments.map((s) => {
|
|
@@ -568,9 +635,19 @@ function deepMergeResObjInto(dst, src, pathPrefix = []) {
|
|
|
568
635
|
deepMergeResObjInto(dstVal, srcVal, childPrefix);
|
|
569
636
|
} else {
|
|
570
637
|
if (dstVal !== void 0) {
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
638
|
+
if (src.resetKeys.has(k)) {
|
|
639
|
+
dst.priorValues.delete(k);
|
|
640
|
+
} else {
|
|
641
|
+
const dstFolded = foldOrSkipPrior(dstVal, fullKey, dst.priorValues.get(k));
|
|
642
|
+
if (dstFolded !== void 0) {
|
|
643
|
+
const srcPrior = src.priorValues.get(k);
|
|
644
|
+
if (srcPrior !== void 0) {
|
|
645
|
+
dst.priorValues.set(k, foldKnownAbsentSelfRef(srcPrior, fullKey, dstFolded));
|
|
646
|
+
} else {
|
|
647
|
+
dst.priorValues.set(k, dstFolded);
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
}
|
|
574
651
|
}
|
|
575
652
|
dst.fields.set(k, srcVal);
|
|
576
653
|
}
|
|
@@ -580,6 +657,7 @@ function deepMergeResObjInto(dst, src, pathPrefix = []) {
|
|
|
580
657
|
dst.priorValues.set(k, srcPrior);
|
|
581
658
|
}
|
|
582
659
|
}
|
|
660
|
+
for (const k of src.resetKeys) dst.resetKeys.add(k);
|
|
583
661
|
}
|
|
584
662
|
function hoconValueToResObj(hv) {
|
|
585
663
|
const obj = makeResObj();
|
|
@@ -649,6 +727,11 @@ var Lexer = class {
|
|
|
649
727
|
this.line = 1;
|
|
650
728
|
this.col = 1;
|
|
651
729
|
this.hadSpace = false;
|
|
730
|
+
// Accumulates literal whitespace chars consumed between tokens. Reset on every
|
|
731
|
+
// token push. Used so the parser can preserve path-expression whitespace
|
|
732
|
+
// (xx.hocon#42, E13) — e.g. tab vs space adjacent to dots in key paths.
|
|
733
|
+
// Comment text is NOT accumulated; only the actual WS chars.
|
|
734
|
+
this.whitespaceBuffer = "";
|
|
652
735
|
this.tokens = [];
|
|
653
736
|
if (input.charCodeAt(0) === 65279) this.input = input.slice(1);
|
|
654
737
|
}
|
|
@@ -664,6 +747,7 @@ var Lexer = class {
|
|
|
664
747
|
continue;
|
|
665
748
|
}
|
|
666
749
|
if (isHoconWhitespace(ch)) {
|
|
750
|
+
this.whitespaceBuffer += ch;
|
|
667
751
|
this.advance();
|
|
668
752
|
this.hadSpace = true;
|
|
669
753
|
continue;
|
|
@@ -755,7 +839,7 @@ var Lexer = class {
|
|
|
755
839
|
}
|
|
756
840
|
throw new ParseError(`unexpected character: ${JSON.stringify(ch)}`, sl, sc);
|
|
757
841
|
}
|
|
758
|
-
this.tokens.push({ kind: "eof", value: "", line: this.line, col: this.col, isQuoted: false, precedingSpace: false });
|
|
842
|
+
this.tokens.push({ kind: "eof", value: "", line: this.line, col: this.col, isQuoted: false, precedingSpace: false, precedingWhitespace: "" });
|
|
759
843
|
return this.tokens;
|
|
760
844
|
}
|
|
761
845
|
peek(offset = 0) {
|
|
@@ -772,12 +856,14 @@ var Lexer = class {
|
|
|
772
856
|
return ch;
|
|
773
857
|
}
|
|
774
858
|
push(kind, value, l, c, isQuoted = false) {
|
|
775
|
-
this.tokens.push({ kind, value, line: l, col: c, isQuoted, precedingSpace: this.hadSpace });
|
|
859
|
+
this.tokens.push({ kind, value, line: l, col: c, isQuoted, precedingSpace: this.hadSpace, precedingWhitespace: this.whitespaceBuffer });
|
|
776
860
|
this.hadSpace = false;
|
|
861
|
+
this.whitespaceBuffer = "";
|
|
777
862
|
}
|
|
778
863
|
pushSubst(payload, value, l, c) {
|
|
779
|
-
this.tokens.push({ kind: "subst", value, line: l, col: c, isQuoted: false, precedingSpace: this.hadSpace, subst: payload });
|
|
864
|
+
this.tokens.push({ kind: "subst", value, line: l, col: c, isQuoted: false, precedingSpace: this.hadSpace, precedingWhitespace: this.whitespaceBuffer, subst: payload });
|
|
780
865
|
this.hadSpace = false;
|
|
866
|
+
this.whitespaceBuffer = "";
|
|
781
867
|
}
|
|
782
868
|
/**
|
|
783
869
|
* Read body of a quoted string. Opening `"` must already be consumed.
|
|
@@ -1023,7 +1109,7 @@ function isUnquotedContinue(ch, nextFn) {
|
|
|
1023
1109
|
}
|
|
1024
1110
|
|
|
1025
1111
|
// src/internal/parser/parser.ts
|
|
1026
|
-
var EOF_TOKEN = { kind: "eof", value: "", line: 0, col: 0, isQuoted: false, precedingSpace: false, subst: void 0 };
|
|
1112
|
+
var EOF_TOKEN = { kind: "eof", value: "", line: 0, col: 0, isQuoted: false, precedingSpace: false, precedingWhitespace: "", subst: void 0 };
|
|
1027
1113
|
var Parser = class {
|
|
1028
1114
|
constructor(tokens) {
|
|
1029
1115
|
this.tokens = tokens;
|
|
@@ -1136,13 +1222,17 @@ var Parser = class {
|
|
|
1136
1222
|
let trailingDot = false;
|
|
1137
1223
|
let firstWasQuoted = false;
|
|
1138
1224
|
let spaceConcat = false;
|
|
1225
|
+
let postDotPrefix = "";
|
|
1139
1226
|
while (true) {
|
|
1140
1227
|
const t = this.peek();
|
|
1141
1228
|
if (t.kind === "string") {
|
|
1142
1229
|
this.advance();
|
|
1143
1230
|
if (segments.length === 0) firstWasQuoted = true;
|
|
1144
1231
|
if (spaceConcat) {
|
|
1145
|
-
segments[segments.length - 1] = `${segments[segments.length - 1]}
|
|
1232
|
+
segments[segments.length - 1] = `${segments[segments.length - 1]}${t.precedingWhitespace}${t.value}`;
|
|
1233
|
+
} else if (postDotPrefix !== "") {
|
|
1234
|
+
segments.push(`${postDotPrefix}${t.value}`);
|
|
1235
|
+
postDotPrefix = "";
|
|
1146
1236
|
} else {
|
|
1147
1237
|
segments.push(t.value);
|
|
1148
1238
|
}
|
|
@@ -1152,24 +1242,23 @@ var Parser = class {
|
|
|
1152
1242
|
const raw = t.value.startsWith(".") && segments.length > 0 && !t.precedingSpace ? t.value.slice(1) : t.value;
|
|
1153
1243
|
const parts = raw.split(".");
|
|
1154
1244
|
const filtered = parts.filter((s) => s.length > 0);
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
const after = seg.length >= 2 ? JSON.stringify(seg[1]) : "EOF";
|
|
1158
|
-
throw new ParseError(
|
|
1159
|
-
`unquoted key segment cannot begin with '-' unless followed by a digit (got '-' then ${after} in ${JSON.stringify(seg)}, HOCON.md L270-276)`,
|
|
1160
|
-
t.line,
|
|
1161
|
-
t.col
|
|
1162
|
-
);
|
|
1163
|
-
}
|
|
1164
|
-
}
|
|
1165
|
-
if (spaceConcat && filtered.length > 0) {
|
|
1245
|
+
if (spaceConcat) {
|
|
1246
|
+
segments[segments.length - 1] = `${segments[segments.length - 1]}${t.precedingWhitespace}`;
|
|
1166
1247
|
if (raw.startsWith(".")) {
|
|
1167
1248
|
segments.push(...filtered);
|
|
1168
|
-
} else {
|
|
1249
|
+
} else if (filtered.length > 0) {
|
|
1169
1250
|
const [head, ...tail] = filtered;
|
|
1170
|
-
segments[segments.length - 1] = `${segments[segments.length - 1]}
|
|
1251
|
+
segments[segments.length - 1] = `${segments[segments.length - 1]}${head}`;
|
|
1171
1252
|
segments.push(...tail);
|
|
1172
1253
|
}
|
|
1254
|
+
} else if (postDotPrefix !== "" && raw.startsWith(".")) {
|
|
1255
|
+
segments.push(postDotPrefix);
|
|
1256
|
+
postDotPrefix = "";
|
|
1257
|
+
segments.push(...filtered);
|
|
1258
|
+
} else if (postDotPrefix !== "" && filtered.length > 0) {
|
|
1259
|
+
const [head, ...tail] = filtered;
|
|
1260
|
+
segments.push(`${postDotPrefix}${head}`, ...tail);
|
|
1261
|
+
postDotPrefix = "";
|
|
1173
1262
|
} else {
|
|
1174
1263
|
segments.push(...filtered);
|
|
1175
1264
|
}
|
|
@@ -1179,11 +1268,23 @@ var Parser = class {
|
|
|
1179
1268
|
break;
|
|
1180
1269
|
}
|
|
1181
1270
|
spaceConcat = false;
|
|
1182
|
-
if (trailingDot)
|
|
1271
|
+
if (trailingDot) {
|
|
1272
|
+
const next2 = this.peek();
|
|
1273
|
+
if ((next2.kind === "unquoted" || next2.kind === "string") && next2.precedingWhitespace.length > 0) {
|
|
1274
|
+
postDotPrefix = next2.precedingWhitespace;
|
|
1275
|
+
} else {
|
|
1276
|
+
postDotPrefix = "";
|
|
1277
|
+
}
|
|
1278
|
+
continue;
|
|
1279
|
+
}
|
|
1183
1280
|
const next = this.peek();
|
|
1184
1281
|
if (next.kind === "unquoted" && next.value === "." && !next.precedingSpace) {
|
|
1185
1282
|
this.advance();
|
|
1186
1283
|
trailingDot = true;
|
|
1284
|
+
const afterDot = this.peek();
|
|
1285
|
+
if ((afterDot.kind === "unquoted" || afterDot.kind === "string") && afterDot.precedingWhitespace.length > 0) {
|
|
1286
|
+
postDotPrefix = afterDot.precedingWhitespace;
|
|
1287
|
+
}
|
|
1187
1288
|
continue;
|
|
1188
1289
|
}
|
|
1189
1290
|
if (next.kind === "unquoted" && next.value.startsWith(".") && !next.precedingSpace) {
|
|
@@ -1196,6 +1297,14 @@ var Parser = class {
|
|
|
1196
1297
|
}
|
|
1197
1298
|
break;
|
|
1198
1299
|
}
|
|
1300
|
+
if (trailingDot) {
|
|
1301
|
+
const here = this.peek();
|
|
1302
|
+
throw new ParseError(
|
|
1303
|
+
`path has a trailing period '.' \u2014 empty key segment not allowed (HOCON.md path rules)`,
|
|
1304
|
+
here.line,
|
|
1305
|
+
here.col
|
|
1306
|
+
);
|
|
1307
|
+
}
|
|
1199
1308
|
return { segments, firstWasQuoted };
|
|
1200
1309
|
}
|
|
1201
1310
|
parseInclude() {
|
|
@@ -1368,7 +1477,8 @@ var Parser = class {
|
|
|
1368
1477
|
break;
|
|
1369
1478
|
}
|
|
1370
1479
|
if (hadSpace) {
|
|
1371
|
-
|
|
1480
|
+
const sep = t.precedingWhitespace.length > 0 ? t.precedingWhitespace : " ";
|
|
1481
|
+
parts.push({ kind: "scalar", raw: sep, valueType: "string", pos: { line: t.line, col: t.col }, _separator: true });
|
|
1372
1482
|
}
|
|
1373
1483
|
parts.push(node);
|
|
1374
1484
|
}
|
|
@@ -1804,35 +1914,19 @@ var StructureBuilder = class _StructureBuilder {
|
|
|
1804
1914
|
const childPrefix = [...pathPrefix, head];
|
|
1805
1915
|
const fullKey = stringSegmentsToKey(childPrefix);
|
|
1806
1916
|
if (field.append) {
|
|
1807
|
-
const
|
|
1808
|
-
|
|
1809
|
-
const folded = foldOrSkipPrior(existing2, fullKey, oldPrior);
|
|
1810
|
-
if (folded !== void 0) obj.priorValues.set(head, folded);
|
|
1811
|
-
obj.fields.set(head, {
|
|
1812
|
-
_kind: "append-placeholder",
|
|
1813
|
-
// Use the folded existing (self-ref-free) for the Append. When the
|
|
1814
|
-
// fold returned undefined (self-ref present but no old prior),
|
|
1815
|
-
// fall back to the original existing — resolveSubst will then
|
|
1816
|
-
// raise the "self-ref with no prior value" error at resolve time,
|
|
1817
|
-
// matching the pre-fix behaviour for that edge case.
|
|
1818
|
-
//
|
|
1819
|
-
// Clone `folded` again so the Append.existing and priorValues[head]
|
|
1820
|
-
// do not share the same Subst/Concat references — relativizeResObj
|
|
1821
|
-
// walks BOTH `fields` and `priorValues` and mutates Subst.segments
|
|
1822
|
-
// in place, so a shared reference would get its prefix applied
|
|
1823
|
-
// twice (resulting in e.g. `${outer.outer.base}` instead of
|
|
1824
|
-
// `${outer.base}`). Codex review on PR #131.
|
|
1825
|
-
existing: folded !== void 0 ? cloneResolverValue(folded) : existing2,
|
|
1826
|
-
elem: this.astToResolverValue(field.value, childPrefix)
|
|
1827
|
-
});
|
|
1917
|
+
const synthetic = this.desugarAppend(field, childPrefix);
|
|
1918
|
+
this.applyField(obj, synthetic, pathPrefix);
|
|
1828
1919
|
return;
|
|
1829
1920
|
}
|
|
1830
1921
|
const existing = obj.fields.get(head);
|
|
1831
1922
|
const newVal = this.astToResolverValue(field.value, childPrefix);
|
|
1923
|
+
if (!containsSelfRef(newVal, fullKey)) {
|
|
1924
|
+
obj.resetKeys.add(head);
|
|
1925
|
+
}
|
|
1832
1926
|
if (existing !== void 0) {
|
|
1833
|
-
const exFolded = foldNestedSelfRefs(existing, childPrefix);
|
|
1834
1927
|
const oldPrior = obj.priorValues.get(head);
|
|
1835
|
-
const
|
|
1928
|
+
const priorInput = isResObj(existing) ? foldNestedSelfRefs(existing, childPrefix) : existing;
|
|
1929
|
+
const prior = foldOrSkipPrior(priorInput, fullKey, oldPrior);
|
|
1836
1930
|
if (prior !== void 0) obj.priorValues.set(head, prior);
|
|
1837
1931
|
}
|
|
1838
1932
|
if (existing !== void 0 && isResObj(existing) && isResObj(newVal)) {
|
|
@@ -1870,23 +1964,19 @@ var StructureBuilder = class _StructureBuilder {
|
|
|
1870
1964
|
const childPrefix = [...pathPrefix, head];
|
|
1871
1965
|
const fullKey = stringSegmentsToKey(childPrefix);
|
|
1872
1966
|
if (field.append) {
|
|
1873
|
-
const
|
|
1874
|
-
|
|
1875
|
-
const folded = foldOrSkipPrior(existing2, fullKey, oldPrior);
|
|
1876
|
-
if (folded !== void 0) obj.priorValues.set(head, folded);
|
|
1877
|
-
obj.fields.set(head, {
|
|
1878
|
-
_kind: "append-placeholder",
|
|
1879
|
-
existing: folded !== void 0 ? cloneResolverValue(folded) : existing2,
|
|
1880
|
-
elem: await this.astToResolverValueAsync(field.value, childPrefix)
|
|
1881
|
-
});
|
|
1967
|
+
const synthetic = this.desugarAppend(field, childPrefix);
|
|
1968
|
+
await this.applyFieldAsync(obj, synthetic, pathPrefix);
|
|
1882
1969
|
return;
|
|
1883
1970
|
}
|
|
1884
1971
|
const existing = obj.fields.get(head);
|
|
1885
1972
|
const newVal = await this.astToResolverValueAsync(field.value, childPrefix);
|
|
1973
|
+
if (!containsSelfRef(newVal, fullKey)) {
|
|
1974
|
+
obj.resetKeys.add(head);
|
|
1975
|
+
}
|
|
1886
1976
|
if (existing !== void 0) {
|
|
1887
|
-
const exFolded = foldNestedSelfRefs(existing, childPrefix);
|
|
1888
1977
|
const oldPrior = obj.priorValues.get(head);
|
|
1889
|
-
const
|
|
1978
|
+
const priorInput = isResObj(existing) ? foldNestedSelfRefs(existing, childPrefix) : existing;
|
|
1979
|
+
const prior = foldOrSkipPrior(priorInput, fullKey, oldPrior);
|
|
1890
1980
|
if (prior !== void 0) obj.priorValues.set(head, prior);
|
|
1891
1981
|
}
|
|
1892
1982
|
if (existing !== void 0 && isResObj(existing) && isResObj(newVal)) {
|
|
@@ -1895,6 +1985,21 @@ var StructureBuilder = class _StructureBuilder {
|
|
|
1895
1985
|
}
|
|
1896
1986
|
obj.fields.set(head, newVal);
|
|
1897
1987
|
}
|
|
1988
|
+
/** Builds the `key = ${?fullkey} [value]` field that `key += value` desugars
|
|
1989
|
+
* to (S13b.2, HOCON.md L732). `childPrefix` is the field's fully-qualified
|
|
1990
|
+
* path (pathPrefix + key), so a nested `srv { items += x }` references
|
|
1991
|
+
* `${?srv.items}`; include relativization rewrites it under a mount prefix.
|
|
1992
|
+
* `field.key` is already single-segment here (multi-segment keys are split
|
|
1993
|
+
* into nested objects upstream). Returns a NEW AstField (append=false);
|
|
1994
|
+
* positions inherit from the original field so resolve-time errors (the
|
|
1995
|
+
* S13b.2 non-array check, now via the scalar+array concat) keep a location. */
|
|
1996
|
+
desugarAppend(field, childPrefix) {
|
|
1997
|
+
const segments = childPrefix.map((text) => ({ text, line: field.pos.line, col: field.pos.col }));
|
|
1998
|
+
const subst = { kind: "subst", segments, optional: true, listSuffix: false, pos: field.pos };
|
|
1999
|
+
const elemArray = { kind: "array", items: [field.value], pos: field.pos };
|
|
2000
|
+
const synthetic = { kind: "concat", nodes: [subst, elemArray], pos: field.pos };
|
|
2001
|
+
return { key: field.key, value: synthetic, append: false, pos: field.pos };
|
|
2002
|
+
}
|
|
1898
2003
|
astToResolverValue(ast, pathPrefix) {
|
|
1899
2004
|
switch (ast.kind) {
|
|
1900
2005
|
case "scalar": {
|
|
@@ -1909,7 +2014,7 @@ var StructureBuilder = class _StructureBuilder {
|
|
|
1909
2014
|
return inner;
|
|
1910
2015
|
}
|
|
1911
2016
|
case "subst":
|
|
1912
|
-
return { _kind: "subst-placeholder", segments: ast.segments, optional: ast.optional, listSuffix: ast.listSuffix, line: ast.pos.line, col: ast.pos.col, prefixLen: 0 };
|
|
2017
|
+
return { _kind: "subst-placeholder", segments: ast.segments, optional: ast.optional, knownAbsent: false, listSuffix: ast.listSuffix, line: ast.pos.line, col: ast.pos.col, prefixLen: 0 };
|
|
1913
2018
|
case "concat":
|
|
1914
2019
|
return { _kind: "concat-placeholder", nodes: ast.nodes.map((n) => this.astToResolverValue(n, pathPrefix)), line: ast.pos.line, col: ast.pos.col };
|
|
1915
2020
|
case "include":
|
|
@@ -1933,7 +2038,7 @@ var StructureBuilder = class _StructureBuilder {
|
|
|
1933
2038
|
case "object":
|
|
1934
2039
|
return await this.buildAsync(ast, pathPrefix);
|
|
1935
2040
|
case "subst":
|
|
1936
|
-
return { _kind: "subst-placeholder", segments: ast.segments, optional: ast.optional, listSuffix: ast.listSuffix, line: ast.pos.line, col: ast.pos.col, prefixLen: 0 };
|
|
2041
|
+
return { _kind: "subst-placeholder", segments: ast.segments, optional: ast.optional, knownAbsent: false, listSuffix: ast.listSuffix, line: ast.pos.line, col: ast.pos.col, prefixLen: 0 };
|
|
1937
2042
|
case "concat": {
|
|
1938
2043
|
const nodes = [];
|
|
1939
2044
|
for (const n of ast.nodes) {
|
|
@@ -1959,11 +2064,6 @@ var StructureBuilder = class _StructureBuilder {
|
|
|
1959
2064
|
}
|
|
1960
2065
|
return;
|
|
1961
2066
|
}
|
|
1962
|
-
if (isAppend(val)) {
|
|
1963
|
-
this.relativizeSubstPaths(val.existing, prefixSegments);
|
|
1964
|
-
this.relativizeSubstPaths(val.elem, prefixSegments);
|
|
1965
|
-
return;
|
|
1966
|
-
}
|
|
1967
2067
|
if (isResObj(val)) {
|
|
1968
2068
|
this.relativizeResObj(val, prefixSegments);
|
|
1969
2069
|
return;
|
|
@@ -2051,6 +2151,8 @@ var SubstitutionResolver = class {
|
|
|
2051
2151
|
const result = /* @__PURE__ */ new Map();
|
|
2052
2152
|
for (const [key, val] of obj.fields) {
|
|
2053
2153
|
this.resolvingFieldPath.push(key);
|
|
2154
|
+
const fullCacheKey = stringSegmentsToKey(this.resolvingFieldPath);
|
|
2155
|
+
this.cache.delete(fullCacheKey);
|
|
2054
2156
|
let resolved;
|
|
2055
2157
|
try {
|
|
2056
2158
|
resolved = this.resolveVal(val, obj);
|
|
@@ -2063,28 +2165,42 @@ var SubstitutionResolver = class {
|
|
|
2063
2165
|
if (prior !== void 0) {
|
|
2064
2166
|
const priorResolved = this.resolveVal(prior, obj);
|
|
2065
2167
|
if (priorResolved !== void 0 && priorResolved.kind === "object") {
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
priorResolved,
|
|
2070
|
-
resolved
|
|
2071
|
-
)
|
|
2168
|
+
const finalValue = deepMergeHoconValues(
|
|
2169
|
+
priorResolved,
|
|
2170
|
+
resolved
|
|
2072
2171
|
);
|
|
2172
|
+
result.set(key, finalValue);
|
|
2173
|
+
this.cache.set(fullCacheKey, finalValue);
|
|
2174
|
+
this.cacheDescendants(fullCacheKey, finalValue);
|
|
2073
2175
|
continue;
|
|
2074
2176
|
}
|
|
2075
2177
|
}
|
|
2076
2178
|
}
|
|
2077
2179
|
result.set(key, resolved);
|
|
2180
|
+
this.cache.set(fullCacheKey, resolved);
|
|
2181
|
+
this.cacheDescendants(fullCacheKey, resolved);
|
|
2078
2182
|
} else {
|
|
2079
2183
|
const prior = obj.priorValues.get(key);
|
|
2080
2184
|
if (prior !== void 0) {
|
|
2081
2185
|
const priorResolved = this.resolveVal(prior, obj);
|
|
2082
|
-
if (priorResolved !== void 0)
|
|
2186
|
+
if (priorResolved !== void 0) {
|
|
2187
|
+
result.set(key, priorResolved);
|
|
2188
|
+
this.cache.set(fullCacheKey, priorResolved);
|
|
2189
|
+
this.cacheDescendants(fullCacheKey, priorResolved);
|
|
2190
|
+
}
|
|
2083
2191
|
}
|
|
2084
2192
|
}
|
|
2085
2193
|
}
|
|
2086
2194
|
return { kind: "object", fields: result };
|
|
2087
2195
|
}
|
|
2196
|
+
cacheDescendants(prefix, value) {
|
|
2197
|
+
if (value.kind !== "object") return;
|
|
2198
|
+
for (const [key, child] of value.fields) {
|
|
2199
|
+
const childKey = `${prefix}.${stringSegmentsToKey([key])}`;
|
|
2200
|
+
this.cache.set(childKey, child);
|
|
2201
|
+
this.cacheDescendants(childKey, child);
|
|
2202
|
+
}
|
|
2203
|
+
}
|
|
2088
2204
|
resolveVal(v, scope) {
|
|
2089
2205
|
if (isSubst(v)) return this.resolveSubst(v, scope);
|
|
2090
2206
|
if (isConcat(v)) {
|
|
@@ -2096,7 +2212,6 @@ var SubstitutionResolver = class {
|
|
|
2096
2212
|
this.resolvingConcats.delete(v);
|
|
2097
2213
|
}
|
|
2098
2214
|
}
|
|
2099
|
-
if (isAppend(v)) return this.resolveAppend(v, scope);
|
|
2100
2215
|
if (isResObj(v)) return this.resolveResObj(v);
|
|
2101
2216
|
const hv = v;
|
|
2102
2217
|
if (hv.kind === "array") {
|
|
@@ -2110,6 +2225,7 @@ var SubstitutionResolver = class {
|
|
|
2110
2225
|
return hv;
|
|
2111
2226
|
}
|
|
2112
2227
|
resolveSubst(s, scope) {
|
|
2228
|
+
if (s.knownAbsent) return void 0;
|
|
2113
2229
|
const key = s.listSuffix ? `${segmentsToKey(s.segments)}[]` : segmentsToKey(s.segments);
|
|
2114
2230
|
if (this.cache.has(key)) return this.cache.get(key);
|
|
2115
2231
|
if (this.resolving.has(key)) {
|
|
@@ -2202,6 +2318,28 @@ var SubstitutionResolver = class {
|
|
|
2202
2318
|
if (result !== void 0) this.cache.set(key, result);
|
|
2203
2319
|
return result;
|
|
2204
2320
|
}
|
|
2321
|
+
if (s.prefixLen > 0 && s.segments.length > s.prefixLen) {
|
|
2322
|
+
const originalSegments = s.segments.slice(s.prefixLen);
|
|
2323
|
+
const fallbackFound = lookupPath(this.root, originalSegments);
|
|
2324
|
+
if (fallbackFound !== void 0) {
|
|
2325
|
+
let result = this.resolveVal(fallbackFound, scope);
|
|
2326
|
+
if (originalSegments.length === 1 && result !== void 0 && result.kind === "object") {
|
|
2327
|
+
const rootSeg = originalSegments[0]?.text ?? "";
|
|
2328
|
+
const prior = this.root.priorValues.get(rootSeg);
|
|
2329
|
+
if (prior !== void 0) {
|
|
2330
|
+
const priorResolved = this.resolveVal(prior, scope);
|
|
2331
|
+
if (priorResolved !== void 0 && priorResolved.kind === "object") {
|
|
2332
|
+
result = deepMergeHoconValues(
|
|
2333
|
+
priorResolved,
|
|
2334
|
+
result
|
|
2335
|
+
);
|
|
2336
|
+
}
|
|
2337
|
+
}
|
|
2338
|
+
}
|
|
2339
|
+
if (result !== void 0) this.cache.set(key, result);
|
|
2340
|
+
return result;
|
|
2341
|
+
}
|
|
2342
|
+
}
|
|
2205
2343
|
if (s.listSuffix && this.opts.useSystemEnvironment !== false) {
|
|
2206
2344
|
const result = this.resolveEnvList(s);
|
|
2207
2345
|
if (result !== void 0) {
|
|
@@ -2358,38 +2496,6 @@ var SubstitutionResolver = class {
|
|
|
2358
2496
|
}
|
|
2359
2497
|
return folded;
|
|
2360
2498
|
}
|
|
2361
|
-
resolveAppend(a, scope) {
|
|
2362
|
-
const existing = this.resolveVal(a.existing, scope) ?? { kind: "array", items: [] };
|
|
2363
|
-
if (this.opts.allowUnresolved && (isSubst(existing) || isConcat(existing) || isAppend(existing))) {
|
|
2364
|
-
return a;
|
|
2365
|
-
}
|
|
2366
|
-
const elem = this.resolveVal(a.elem, scope);
|
|
2367
|
-
let priorItems;
|
|
2368
|
-
if (existing.kind === "array") {
|
|
2369
|
-
priorItems = existing.items;
|
|
2370
|
-
} else if (existing.kind === "object") {
|
|
2371
|
-
const converted = numericObjectToArray(existing);
|
|
2372
|
-
if (converted === null) {
|
|
2373
|
-
throw new ResolveError(
|
|
2374
|
-
`'+=' on non-array value: prior value is object with non-numeric keys (spec L732)`,
|
|
2375
|
-
"",
|
|
2376
|
-
0,
|
|
2377
|
-
0
|
|
2378
|
-
);
|
|
2379
|
-
}
|
|
2380
|
-
priorItems = converted;
|
|
2381
|
-
} else {
|
|
2382
|
-
throw new ResolveError(
|
|
2383
|
-
`'+=' on non-array value: prior value is ${existing.kind} (spec L732)`,
|
|
2384
|
-
"",
|
|
2385
|
-
0,
|
|
2386
|
-
0
|
|
2387
|
-
);
|
|
2388
|
-
}
|
|
2389
|
-
const items = [...priorItems];
|
|
2390
|
-
if (elem !== void 0) items.push(elem);
|
|
2391
|
-
return { kind: "array", items };
|
|
2392
|
-
}
|
|
2393
2499
|
};
|
|
2394
2500
|
|
|
2395
2501
|
// src/internal/resolver/resolver.ts
|
|
@@ -2407,7 +2513,7 @@ function containsPlaceholders(tree) {
|
|
|
2407
2513
|
}
|
|
2408
2514
|
function valContainsPlaceholders(v) {
|
|
2409
2515
|
const rv = v;
|
|
2410
|
-
if (isSubst(rv) || isConcat(rv)
|
|
2516
|
+
if (isSubst(rv) || isConcat(rv)) return true;
|
|
2411
2517
|
if (isResObj(rv)) return containsPlaceholders(rv);
|
|
2412
2518
|
const hv = v;
|
|
2413
2519
|
if (hv?.kind === "array") {
|
|
@@ -2418,7 +2524,7 @@ function valContainsPlaceholders(v) {
|
|
|
2418
2524
|
function buildPartialHoconFromResObj(tree) {
|
|
2419
2525
|
const fields = /* @__PURE__ */ new Map();
|
|
2420
2526
|
for (const [k, v] of tree.fields) {
|
|
2421
|
-
if (!isSubst(v) && !isConcat(v)
|
|
2527
|
+
if (!isSubst(v) && !isConcat(v)) {
|
|
2422
2528
|
if (isResObj(v)) {
|
|
2423
2529
|
fields.set(k, buildPartialHoconFromResObj(v));
|
|
2424
2530
|
} else {
|
|
@@ -2807,7 +2913,7 @@ function hoconToJs(v) {
|
|
|
2807
2913
|
function resObjToKeyShape(tree) {
|
|
2808
2914
|
const fields = /* @__PURE__ */ new Map();
|
|
2809
2915
|
for (const [k, v] of tree.fields) {
|
|
2810
|
-
if (isSubst(v) || isConcat(v)
|
|
2916
|
+
if (isSubst(v) || isConcat(v)) {
|
|
2811
2917
|
fields.set(k, { kind: "scalar", raw: "", valueType: "null" });
|
|
2812
2918
|
} else if (isResObj(v)) {
|
|
2813
2919
|
fields.set(k, resObjToKeyShape(v));
|
|
@@ -2821,7 +2927,7 @@ function stripPlaceholderFields(v) {
|
|
|
2821
2927
|
const fields = /* @__PURE__ */ new Map();
|
|
2822
2928
|
let hadPlaceholders = false;
|
|
2823
2929
|
for (const [k, val] of v.fields) {
|
|
2824
|
-
if (val._kind === "subst-placeholder" || val._kind === "concat-placeholder"
|
|
2930
|
+
if (val._kind === "subst-placeholder" || val._kind === "concat-placeholder") {
|
|
2825
2931
|
hadPlaceholders = true;
|
|
2826
2932
|
} else if (val.kind === "object") {
|
|
2827
2933
|
const inner = stripPlaceholderFields(val);
|