yaml 3.0.0-0 → 3.0.0-2

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.
@@ -1,6 +1,5 @@
1
- import { t as __exportAll } from "./chunk-BYypO7fO.js";
2
- import { _ as Collection, b as Scalar, f as Alias, g as YAMLSeq, i as Document, p as Pair, t as Directives, u as YAMLMap, v as stringifyString, x as NodeBase } from "./directives-CG6n4xSM.js";
3
-
1
+ import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
+ import { S as Scalar, _ as YAMLMap, b as stringifyString, f as Pair, g as YAMLSeq, h as YAMLSet, i as Document, m as isNode, p as isCollection$1, t as Directives, u as Alias } from "./directives-DqP9ea45.js";
4
3
  //#region src/compose/resolve-block-scalar.ts
5
4
  function resolveBlockScalar(ctx, scalar, onError) {
6
5
  const start = scalar.offset;
@@ -79,9 +78,10 @@ function resolveBlockScalar(ctx, scalar, onError) {
79
78
  value += sep + indent.slice(trimIndent) + content;
80
79
  sep = "\n";
81
80
  prevMoreIndented = true;
82
- } else if (content === "") if (sep === "\n") value += "\n";
83
- else sep = "\n";
84
- else {
81
+ } else if (content === "") {
82
+ if (sep === "\n") value += "\n";
83
+ else sep = "\n";
84
+ } else {
85
85
  value += sep + content;
86
86
  sep = " ";
87
87
  prevMoreIndented = false;
@@ -147,6 +147,7 @@ function parseBlockScalarHeader({ offset, props }, strict, onError) {
147
147
  onError(token, "UNEXPECTED_TOKEN", token.message);
148
148
  length += token.source.length;
149
149
  break;
150
+ /* istanbul ignore next should not happen */
150
151
  default: {
151
152
  onError(token, "UNEXPECTED_TOKEN", `Unexpected token in block scalar header: ${token.type}`);
152
153
  const ts = token.source;
@@ -171,7 +172,6 @@ function splitLines(source) {
171
172
  for (let i = 1; i < split.length; i += 2) lines.push([split[i], split[i + 1]]);
172
173
  return lines;
173
174
  }
174
-
175
175
  //#endregion
176
176
  //#region src/compose/resolve-end.ts
177
177
  function resolveEnd(end, offset, reqSpace, onError) {
@@ -207,7 +207,6 @@ function resolveEnd(end, offset, reqSpace, onError) {
207
207
  offset
208
208
  };
209
209
  }
210
-
211
210
  //#endregion
212
211
  //#region src/compose/resolve-flow-scalar.ts
213
212
  function resolveFlowScalar(scalar, strict, onError) {
@@ -228,6 +227,7 @@ function resolveFlowScalar(scalar, strict, onError) {
228
227
  _type = Scalar.QUOTE_DOUBLE;
229
228
  value = doubleQuotedValue(source, _onError);
230
229
  break;
230
+ /* istanbul ignore next should not happen */
231
231
  default:
232
232
  onError(scalar, "UNEXPECTED_TOKEN", `Expected a flow scalar value, but found: ${type}`);
233
233
  return {
@@ -257,6 +257,7 @@ function resolveFlowScalar(scalar, strict, onError) {
257
257
  function plainValue(source, onError) {
258
258
  let badChar = "";
259
259
  switch (source[0]) {
260
+ /* istanbul ignore next should not happen */
260
261
  case " ":
261
262
  badChar = "a tab character";
262
263
  break;
@@ -271,9 +272,7 @@ function plainValue(source, onError) {
271
272
  badChar = `block scalar indicator ${source[0]}`;
272
273
  break;
273
274
  case "@":
274
- case "`":
275
- badChar = `reserved character ${source[0]}`;
276
- break;
275
+ case "`": badChar = `reserved character ${source[0]}`;
277
276
  }
278
277
  if (badChar) onError(0, "BAD_SCALAR_START", `Plain value cannot start with ${badChar}`);
279
278
  return foldLines(source);
@@ -282,41 +281,40 @@ function singleQuotedValue(source, onError) {
282
281
  if (source[source.length - 1] !== "'" || source.length === 1) onError(source.length, "MISSING_CHAR", "Missing closing 'quote");
283
282
  return foldLines(source.slice(1, -1)).replace(/''/g, "'");
284
283
  }
284
+ const CHAR_CR$1 = 13;
285
+ const CHAR_SPACE$1 = 32;
286
+ const CHAR_TAB$1 = 9;
285
287
  function foldLines(source) {
286
- /**
287
- * The negative lookbehind here and in the `re` RegExp is to
288
- * prevent causing a polynomial search time in certain cases.
289
- *
290
- * The try-catch is for Safari, which doesn't support this yet:
291
- * https://caniuse.com/js-regexp-lookbehind
292
- */
293
- let first, line;
294
- try {
295
- first = /* @__PURE__ */ new RegExp("(.*?)(?<![ ])[ ]*\r?\n", "sy");
296
- line = /* @__PURE__ */ new RegExp("[ ]*(.*?)(?:(?<![ ])[ ]*)?\r?\n", "sy");
297
- } catch {
298
- first = /(.*?)[ \t]*\r?\n/sy;
299
- line = /[ \t]*(.*?)[ \t]*\r?\n/sy;
300
- }
301
- let match = first.exec(source);
302
- if (!match) return source;
303
- let res = match[1];
288
+ let newLineIndex = source.indexOf("\n");
289
+ if (newLineIndex === -1) return source;
290
+ let end = newLineIndex;
291
+ let cc = source.charCodeAt(end - 1);
292
+ if (cc === CHAR_CR$1) cc = source.charCodeAt(--end - 1);
293
+ while (end > 0 && (cc === CHAR_SPACE$1 || cc === CHAR_TAB$1)) cc = source.charCodeAt(--end - 1);
294
+ let res = source.slice(0, end);
304
295
  let sep = " ";
305
- let pos = first.lastIndex;
306
- line.lastIndex = pos;
307
- while (match = line.exec(source)) {
308
- if (match[1] === "") if (sep === "\n") res += sep;
309
- else sep = "\n";
310
- else {
311
- res += sep + match[1];
296
+ let pos = newLineIndex + 1;
297
+ while ((newLineIndex = source.indexOf("\n", pos)) !== -1) {
298
+ let start = pos;
299
+ cc = source.charCodeAt(start);
300
+ while (start < newLineIndex && (cc === CHAR_SPACE$1 || cc === CHAR_TAB$1)) cc = source.charCodeAt(++start);
301
+ end = newLineIndex;
302
+ cc = source.charCodeAt(end - 1);
303
+ if (cc === CHAR_CR$1) cc = source.charCodeAt(--end - 1);
304
+ while (end > start && (cc === CHAR_SPACE$1 || cc === CHAR_TAB$1)) cc = source.charCodeAt(--end - 1);
305
+ if (start === end) {
306
+ if (sep === "\n") res += sep;
307
+ else sep = "\n";
308
+ } else {
309
+ res += sep + source.slice(start, end);
312
310
  sep = " ";
313
311
  }
314
- pos = line.lastIndex;
312
+ pos = newLineIndex + 1;
315
313
  }
316
- const last = /[ \t]*(.*)/sy;
317
- last.lastIndex = pos;
318
- match = last.exec(source);
319
- return res + sep + (match?.[1] ?? "");
314
+ let start = pos;
315
+ cc = source.charCodeAt(start);
316
+ while (start < source.length && (cc === CHAR_SPACE$1 || cc === CHAR_TAB$1)) cc = source.charCodeAt(++start);
317
+ return res + sep + source.slice(start);
320
318
  }
321
319
  function doubleQuotedValue(source, onError) {
322
320
  let res = "";
@@ -338,11 +336,7 @@ function doubleQuotedValue(source, onError) {
338
336
  next = source[++i + 1];
339
337
  while (next === " " || next === " ") next = source[++i + 1];
340
338
  } else if (next === "x" || next === "u" || next === "U") {
341
- const length = {
342
- x: 2,
343
- u: 4,
344
- U: 8
345
- }[next];
339
+ const length = next === "x" ? 2 : next === "u" ? 4 : 8;
346
340
  res += parseCharCode(source, i + 1, length, onError);
347
341
  i += length;
348
342
  } else {
@@ -402,14 +396,14 @@ const escapeCodes = {
402
396
  function parseCharCode(source, offset, length, onError) {
403
397
  const cc = source.substr(offset, length);
404
398
  const code = cc.length === length && /^[0-9a-fA-F]+$/.test(cc) ? parseInt(cc, 16) : NaN;
405
- if (isNaN(code)) {
399
+ try {
400
+ return String.fromCodePoint(code);
401
+ } catch {
406
402
  const raw = source.substr(offset - 2, length + 2);
407
403
  onError(offset - 2, "BAD_DQ_ESCAPE", `Invalid escape sequence ${raw}`);
408
404
  return raw;
409
405
  }
410
- return String.fromCodePoint(code);
411
406
  }
412
-
413
407
  //#endregion
414
408
  //#region src/errors.ts
415
409
  var YAMLError = class extends Error {
@@ -462,7 +456,6 @@ const prettifyError = (src, lc) => (error) => {
462
456
  error.message += `:\n\n${lineStr}\n${pointer}\n`;
463
457
  }
464
458
  };
465
-
466
459
  //#endregion
467
460
  //#region src/parse/cst-scalar.ts
468
461
  function resolveAsScalar(token, strict = true, onError) {
@@ -721,7 +714,6 @@ function setFlowScalarValue(token, source, type) {
721
714
  }
722
715
  }
723
716
  }
724
-
725
717
  //#endregion
726
718
  //#region src/parse/cst-stringify.ts
727
719
  /**
@@ -770,7 +762,6 @@ function stringifyItem({ start, key, sep, value }) {
770
762
  if (value) res += stringifyToken(value);
771
763
  return res;
772
764
  }
773
-
774
765
  //#endregion
775
766
  //#region src/parse/cst-visit.ts
776
767
  const BREAK = Symbol("break visit");
@@ -809,7 +800,7 @@ const visit = function visit(cst, visitor) {
809
800
  start: cst.start,
810
801
  value: cst.value
811
802
  };
812
- _visit(Object.freeze([]), cst, visitor);
803
+ _visit([], cst, visitor);
813
804
  };
814
805
  visit.BREAK = BREAK;
815
806
  visit.SKIP = SKIP;
@@ -837,7 +828,7 @@ function _visit(path, item, visitor) {
837
828
  const token = item[field];
838
829
  if (token && "items" in token) {
839
830
  for (let i = 0; i < token.items.length; ++i) {
840
- const ci = _visit(Object.freeze(path.concat([[field, i]])), token.items[i], visitor);
831
+ const ci = _visit([...path, [field, i]], token.items[i], visitor);
841
832
  if (typeof ci === "number") i = ci - 1;
842
833
  else if (ci === BREAK) return BREAK;
843
834
  else if (ci === REMOVE) {
@@ -850,14 +841,13 @@ function _visit(path, item, visitor) {
850
841
  }
851
842
  return typeof ctrl === "function" ? ctrl(item, path) : ctrl;
852
843
  }
853
-
854
844
  //#endregion
855
845
  //#region src/parse/cst.ts
856
846
  var cst_exports = /* @__PURE__ */ __exportAll({
857
- BOM: () => BOM,
858
- DOCUMENT: () => DOCUMENT,
859
- FLOW_END: () => FLOW_END,
860
- SCALAR: () => SCALAR,
847
+ BOM: () => "",
848
+ DOCUMENT: () => "",
849
+ FLOW_END: () => "",
850
+ SCALAR: () => "",
861
851
  createScalarToken: () => createScalarToken,
862
852
  isCollection: () => isCollection,
863
853
  isScalar: () => isScalar,
@@ -868,14 +858,6 @@ var cst_exports = /* @__PURE__ */ __exportAll({
868
858
  tokenType: () => tokenType,
869
859
  visit: () => visit
870
860
  });
871
- /** The byte order mark */
872
- const BOM = "";
873
- /** Start of doc-mode */
874
- const DOCUMENT = "";
875
- /** Unexpected end of flow-mode */
876
- const FLOW_END = "";
877
- /** Next token is a scalar value */
878
- const SCALAR = "";
879
861
  /** @returns `true` if `token` is a flow or block collection */
880
862
  const isCollection = (token) => !!token && "items" in token;
881
863
  /** @returns `true` if `token` is a flow or block scalar; not an alias */
@@ -884,20 +866,20 @@ const isScalar = (token) => !!token && (token.type === "scalar" || token.type ==
884
866
  /** Get a printable representation of a lexer token */
885
867
  function prettyToken(token) {
886
868
  switch (token) {
887
- case BOM: return "<BOM>";
888
- case DOCUMENT: return "<DOC>";
889
- case FLOW_END: return "<FLOW_END>";
890
- case SCALAR: return "<SCALAR>";
869
+ case "": return "<BOM>";
870
+ case "": return "<DOC>";
871
+ case "": return "<FLOW_END>";
872
+ case "": return "<SCALAR>";
891
873
  default: return JSON.stringify(token);
892
874
  }
893
875
  }
894
876
  /** Identify the type of a lexer token. May return `null` for unknown tokens. */
895
877
  function tokenType(source) {
896
878
  switch (source) {
897
- case BOM: return "byte-order-mark";
898
- case DOCUMENT: return "doc-mode";
899
- case FLOW_END: return "flow-error-end";
900
- case SCALAR: return "scalar";
879
+ case "": return "byte-order-mark";
880
+ case "": return "doc-mode";
881
+ case "": return "flow-error-end";
882
+ case "": return "scalar";
901
883
  case "---": return "doc-start";
902
884
  case "...": return "doc-end";
903
885
  case "":
@@ -927,7 +909,6 @@ function tokenType(source) {
927
909
  }
928
910
  return null;
929
911
  }
930
-
931
912
  //#endregion
932
913
  //#region src/parse/lexer.ts
933
914
  function isEmpty(ch) {
@@ -940,12 +921,26 @@ function isEmpty(ch) {
940
921
  default: return false;
941
922
  }
942
923
  }
943
- const flowIndicatorChars = /* @__PURE__ */ new Set(",[]{}");
924
+ const CHAR_TAB = 9;
925
+ const CHAR_LF = 10;
926
+ const CHAR_CR = 13;
927
+ const CHAR_SPACE = 32;
928
+ const CHAR_HASH = 35;
929
+ const CHAR_COLON = 58;
930
+ function isEmptyChar(ch) {
931
+ return Number.isNaN(ch) || ch === CHAR_SPACE || ch === CHAR_LF || ch === CHAR_CR || ch === CHAR_TAB;
932
+ }
933
+ const flowIndicatorCharCodes = /* @__PURE__ */ new Set([
934
+ 44,
935
+ 91,
936
+ 93,
937
+ 123,
938
+ 125
939
+ ]);
944
940
  const invalidAnchorChars = /* @__PURE__ */ new Set(" ,[]{}\n\r ");
945
941
  const isNotAnchorChar = (ch) => !ch || invalidAnchorChars.has(ch);
946
942
  const blockScalarHeader = /([|>][^\s#]*)([ \t]*)((?:.|\r(?!\n))*)$/my;
947
- const blockStart = /([-?:])(?=[ \n\r\t]|$)([ \t]*)/y;
948
- const directiveLine = /(%.*?)(?:([ \t]+)(#.*)?)?$/my;
943
+ const directiveLine = /(%(?:[^ \t\n\r]|[ \t](?![\n\r#]))*)([ \t]*)(#.*)?$/my;
949
944
  const docMarker = /[-.]{3}(?=[ \n\r\t]|$)(?:([ \t]+)(#.*)?)?/y;
950
945
  const emptyLineOrComment = /([ \t]*)(#.*)?$/my;
951
946
  const indicator = /(?:(&[^\s,[\]{}]*|!<[^\s>]*>?|!(?:[0-9a-z-#;/?:@&=+$_.!~*'()]|%[0-9a-f]{2})*)|([-?:])(?=[ \n\r\t]|$)|([-?:])(?=[,[\]{}]|$))([ \t]*)/iy;
@@ -968,7 +963,15 @@ function lex(source) {
968
963
  const lexer = new Lexer(source);
969
964
  const end = source.length;
970
965
  let state = "stream";
971
- while (lexer.pos < end) state = lexer[state]();
966
+ while (lexer.pos < end) switch (state) {
967
+ case "stream":
968
+ state = lexer.stream();
969
+ break;
970
+ case "document":
971
+ state = lexer.document();
972
+ break;
973
+ case "flow": state = lexer.flow();
974
+ }
972
975
  return lexer.tokens;
973
976
  }
974
977
  var Lexer = class {
@@ -995,23 +998,25 @@ var Lexer = class {
995
998
  this.source = source;
996
999
  }
997
1000
  charAt(n) {
998
- return this.source[this.pos + n];
1001
+ const i = this.pos + n;
1002
+ return i < this.source.length ? this.source[i] : void 0;
999
1003
  }
1000
1004
  continueScalar(offset) {
1001
1005
  if (this.indentNext > 0) {
1002
- let ch = this.source[offset];
1006
+ const len = this.source.length;
1003
1007
  let indent = 0;
1004
- while (ch === " ") ch = this.source[++indent + offset];
1005
- if (ch === "\r") {
1006
- if (this.source[indent + offset + 1] === "\n") return offset + indent + 1;
1008
+ while (offset + indent < len && this.source.charCodeAt(offset + indent) === CHAR_SPACE) ++indent;
1009
+ const cc = offset + indent < len ? this.source.charCodeAt(offset + indent) : NaN;
1010
+ if (cc === CHAR_CR) {
1011
+ if (this.source.charCodeAt(indent + offset + 1) === CHAR_LF) return offset + indent + 1;
1007
1012
  }
1008
- return ch === "\n" || indent >= this.indentNext ? offset + indent : -1;
1013
+ return cc === CHAR_LF || indent >= this.indentNext ? offset + indent : -1;
1009
1014
  }
1010
1015
  docMarker.lastIndex = offset;
1011
1016
  return docMarker.test(this.source) ? -1 : offset;
1012
1017
  }
1013
1018
  stream() {
1014
- if (this.charAt(0) === BOM) {
1019
+ if (this.charAt(0) === "") {
1015
1020
  this.count(1);
1016
1021
  return "stream";
1017
1022
  }
@@ -1036,7 +1041,7 @@ var Lexer = class {
1036
1041
  this.newline();
1037
1042
  return "stream";
1038
1043
  }
1039
- this.tokens.push(DOCUMENT);
1044
+ this.tokens.push("");
1040
1045
  return this.lineStart();
1041
1046
  }
1042
1047
  lineStart() {
@@ -1060,22 +1065,27 @@ var Lexer = class {
1060
1065
  }
1061
1066
  this.indentValue = this.spaces(false);
1062
1067
  if (this.indentNext > this.indentValue && !isEmpty(this.charAt(1))) this.indentNext = this.indentValue;
1063
- blockStart.lastIndex = this.pos;
1064
- let bsm;
1065
- while (bsm = blockStart.exec(this.source)) {
1066
- const [line, indicator, spaces] = bsm;
1067
- this.tokens.push(indicator);
1068
- if (spaces) this.tokens.push(spaces);
1069
- this.pos += line.length;
1068
+ while (true) {
1069
+ const ch = this.source[this.pos];
1070
+ if (ch !== "-" && ch !== "?" && ch !== ":") break;
1071
+ const next = this.source[this.pos + 1];
1072
+ if (next !== void 0 && next !== " " && next !== "\n" && next !== "\r" && next !== " ") break;
1073
+ this.tokens.push(ch);
1074
+ const start = this.pos;
1075
+ this.pos += 1;
1076
+ let sc = this.source.charCodeAt(this.pos);
1077
+ while (sc === CHAR_SPACE || sc === CHAR_TAB) sc = this.source.charCodeAt(++this.pos);
1078
+ if (this.pos > start + 1) this.tokens.push(this.source.slice(start + 1, this.pos));
1070
1079
  this.indentNext = this.indentValue + 1;
1071
- this.indentValue += line.length;
1080
+ this.indentValue += this.pos - start;
1072
1081
  }
1073
1082
  return "document";
1074
1083
  }
1075
1084
  document() {
1076
1085
  this.spaces(true);
1077
1086
  this.indicators();
1078
- switch (this.charAt(0)) {
1087
+ const ch = this.charAt(0);
1088
+ switch (ch) {
1079
1089
  case "#": this.toLineEnd();
1080
1090
  case "\n":
1081
1091
  case void 0:
@@ -1096,7 +1106,7 @@ var Lexer = class {
1096
1106
  return "document";
1097
1107
  case "\"":
1098
1108
  case "'":
1099
- this.quotedScalar();
1109
+ this.quotedScalar(ch);
1100
1110
  return "document";
1101
1111
  case "|":
1102
1112
  case ">":
@@ -1125,14 +1135,14 @@ var Lexer = class {
1125
1135
  let ch = this.charAt(0);
1126
1136
  if (indent !== -1 && indent < this.indentNext && ch !== "#" && !(indent === this.indentNext - 1 && this.flowLevel === 1 && (ch === "]" || ch === "}"))) {
1127
1137
  this.flowLevel = 0;
1128
- this.tokens.push(FLOW_END);
1138
+ this.tokens.push("");
1129
1139
  return this.lineStart();
1130
1140
  }
1131
1141
  if (indent === 0) {
1132
1142
  docMarker.lastIndex = this.pos;
1133
1143
  if (docMarker.test(this.source)) {
1134
1144
  this.flowLevel = 0;
1135
- this.tokens.push(FLOW_END);
1145
+ this.tokens.push("");
1136
1146
  return this.lineStart();
1137
1147
  }
1138
1148
  }
@@ -1167,7 +1177,7 @@ var Lexer = class {
1167
1177
  case "\"":
1168
1178
  case "'":
1169
1179
  this.flowKey = true;
1170
- this.quotedScalar();
1180
+ this.quotedScalar(ch);
1171
1181
  break;
1172
1182
  case ":":
1173
1183
  if (this.flowKey) {
@@ -1209,8 +1219,7 @@ var Lexer = class {
1209
1219
  }
1210
1220
  return hasIndicators;
1211
1221
  }
1212
- quotedScalar() {
1213
- const quote = this.charAt(0);
1222
+ quotedScalar(quote) {
1214
1223
  let end = this.source.indexOf(quote, this.pos + 1);
1215
1224
  if (quote === "'") while (end !== -1 && this.source[end + 1] === "'") end = this.source.indexOf("'", end + 2);
1216
1225
  else while (end !== -1) {
@@ -1246,16 +1255,16 @@ var Lexer = class {
1246
1255
  this.newline();
1247
1256
  let nl = this.pos - 1;
1248
1257
  let indent = 0;
1249
- let ch;
1250
- loop: for (let i = this.pos; ch = this.source[i]; ++i) switch (ch) {
1251
- case " ":
1258
+ let cc;
1259
+ loop: for (let i = this.pos; cc = this.source.charCodeAt(i); ++i) switch (cc) {
1260
+ case CHAR_SPACE:
1252
1261
  indent += 1;
1253
1262
  break;
1254
- case "\n":
1263
+ case CHAR_LF:
1255
1264
  nl = i;
1256
1265
  indent = 0;
1257
1266
  break;
1258
- case "\r": if (this.source[i + 1] === "\n") break;
1267
+ case CHAR_CR: if (this.source.charCodeAt(i + 1) === CHAR_LF) break;
1259
1268
  default: break loop;
1260
1269
  }
1261
1270
  if (indent >= this.indentNext) {
@@ -1269,50 +1278,56 @@ var Lexer = class {
1269
1278
  if (nl === -1) nl = this.source.length;
1270
1279
  }
1271
1280
  let i = nl + 1;
1272
- ch = this.source[i];
1273
- while (ch === " ") ch = this.source[++i];
1274
- if (ch === " ") {
1275
- while (ch === " " || ch === " " || ch === "\r" || ch === "\n") ch = this.source[++i];
1281
+ cc = this.source.charCodeAt(i);
1282
+ while (cc === CHAR_SPACE) cc = this.source.charCodeAt(++i);
1283
+ if (cc === CHAR_TAB) {
1284
+ while (cc === CHAR_TAB || cc === CHAR_SPACE || cc === CHAR_CR || cc === CHAR_LF) cc = this.source.charCodeAt(++i);
1276
1285
  nl = i - 1;
1277
1286
  } else if (!bsKeep) do {
1278
1287
  let i = nl - 1;
1279
- let ch = this.source[i];
1280
- if (ch === "\r") ch = this.source[--i];
1288
+ let cc = this.source.charCodeAt(i);
1289
+ if (cc === CHAR_CR) cc = this.source.charCodeAt(--i);
1281
1290
  const lastChar = i;
1282
- while (ch === " ") ch = this.source[--i];
1283
- if (ch === "\n" && i >= this.pos && i + 1 + indent > lastChar) nl = i;
1291
+ while (cc === CHAR_SPACE) cc = this.source.charCodeAt(--i);
1292
+ if (cc === CHAR_LF && i >= this.pos && i + 1 + indent > lastChar) nl = i;
1284
1293
  else break;
1285
1294
  } while (true);
1286
- this.tokens.push(SCALAR);
1295
+ this.tokens.push("");
1287
1296
  this.toIndex(nl + 1, true);
1288
1297
  }
1289
1298
  plainScalar() {
1290
1299
  const inFlow = this.flowLevel > 0;
1291
1300
  let end = this.pos - 1;
1292
1301
  let i = this.pos - 1;
1293
- let ch;
1294
- while (ch = this.source[++i]) if (ch === ":") {
1295
- const next = this.source[i + 1];
1296
- if (isEmpty(next) || inFlow && flowIndicatorChars.has(next)) break;
1297
- end = i;
1298
- } else if (isEmpty(ch)) {
1299
- let next = this.source[i + 1];
1300
- if (ch === "\r") if (next === "\n") {
1301
- i += 1;
1302
- ch = "\n";
1303
- next = this.source[i + 1];
1304
- } else end = i;
1305
- if (next === "#" || inFlow && flowIndicatorChars.has(next)) break;
1306
- if (ch === "\n") {
1307
- const cs = this.continueScalar(i + 1);
1308
- if (cs === -1) break;
1309
- i = Math.max(i, cs - 2);
1302
+ let cc;
1303
+ const len = this.source.length;
1304
+ while (++i < len) {
1305
+ cc = this.source.charCodeAt(i);
1306
+ if (cc === CHAR_COLON) {
1307
+ const next = i + 1 < len ? this.source.charCodeAt(i + 1) : NaN;
1308
+ if (isEmptyChar(next) || inFlow && flowIndicatorCharCodes.has(next)) break;
1309
+ end = i;
1310
+ } else if (isEmptyChar(cc)) {
1311
+ let next = i + 1 < len ? this.source.charCodeAt(i + 1) : NaN;
1312
+ if (cc === CHAR_CR) {
1313
+ if (next === CHAR_LF) {
1314
+ i += 1;
1315
+ cc = CHAR_LF;
1316
+ next = i + 1 < len ? this.source.charCodeAt(i + 1) : NaN;
1317
+ } else end = i;
1318
+ }
1319
+ if (next === CHAR_HASH || inFlow && flowIndicatorCharCodes.has(next)) break;
1320
+ if (cc === CHAR_LF) {
1321
+ const cs = this.continueScalar(i + 1);
1322
+ if (cs === -1) break;
1323
+ i = Math.max(i, cs - 2);
1324
+ }
1325
+ } else {
1326
+ if (inFlow && flowIndicatorCharCodes.has(cc)) break;
1327
+ end = i;
1310
1328
  }
1311
- } else {
1312
- if (inFlow && flowIndicatorChars.has(ch)) break;
1313
- end = i;
1314
1329
  }
1315
- this.tokens.push(SCALAR);
1330
+ this.tokens.push("");
1316
1331
  this.toIndex(end + 1, true);
1317
1332
  }
1318
1333
  count(n) {
@@ -1334,9 +1349,9 @@ var Lexer = class {
1334
1349
  }
1335
1350
  toLineEnd() {
1336
1351
  let i = this.pos;
1337
- let ch = this.source[i];
1338
- while (ch && ch !== "\n") ch = this.source[++i];
1339
- if (this.source[i - 1] === "\r") --i;
1352
+ let ch = this.source.charCodeAt(i);
1353
+ while (ch && ch !== CHAR_LF) ch = this.source.charCodeAt(++i);
1354
+ if (this.source.charCodeAt(i - 1) === CHAR_CR) --i;
1340
1355
  return this.toIndex(i, false);
1341
1356
  }
1342
1357
  newline() {
@@ -1346,11 +1361,13 @@ var Lexer = class {
1346
1361
  else return 0;
1347
1362
  }
1348
1363
  spaces(allowTabs) {
1349
- let i = this.pos - 1;
1350
- let ch;
1351
- do
1352
- ch = this.source[++i];
1353
- while (ch === " " || allowTabs && ch === " ");
1364
+ let i = this.pos;
1365
+ const len = this.source.length;
1366
+ while (i < len) {
1367
+ const cc = this.source.charCodeAt(i);
1368
+ if (cc !== CHAR_SPACE && !(allowTabs && cc === CHAR_TAB)) break;
1369
+ ++i;
1370
+ }
1354
1371
  const n = i - this.pos;
1355
1372
  if (n > 0) {
1356
1373
  const s = this.source.substr(this.pos, n);
@@ -1366,7 +1383,6 @@ var Lexer = class {
1366
1383
  return this.toIndex(i, false);
1367
1384
  }
1368
1385
  };
1369
-
1370
1386
  //#endregion
1371
1387
  //#region src/parse/parser.ts
1372
1388
  function includesToken(list, type) {
@@ -1401,6 +1417,7 @@ function getPrevProps(parent) {
1401
1417
  return it.sep ?? it.start;
1402
1418
  }
1403
1419
  case "block-seq": return parent.items[parent.items.length - 1].start;
1420
+ /* istanbul ignore next should not happen */
1404
1421
  default: return [];
1405
1422
  }
1406
1423
  }
@@ -1423,9 +1440,10 @@ function fixFlowSeqItems(fc) {
1423
1440
  for (const it of fc.items) if (it.sep && !it.value && !includesToken(it.start, "explicit-key-ind") && !includesToken(it.sep, "map-value-ind")) {
1424
1441
  if (it.key) it.value = it.key;
1425
1442
  delete it.key;
1426
- if (isFlowToken(it.value)) if (it.value.end) Array.prototype.push.apply(it.value.end, it.sep);
1427
- else it.value.end = it.sep;
1428
- else Array.prototype.push.apply(it.start, it.sep);
1443
+ if (isFlowToken(it.value)) {
1444
+ if (it.value.end) Array.prototype.push.apply(it.value.end, it.sep);
1445
+ else it.value.end = it.sep;
1446
+ } else Array.prototype.push.apply(it.start, it.sep);
1429
1447
  delete it.sep;
1430
1448
  }
1431
1449
  }
@@ -1624,11 +1642,10 @@ var Parser = class {
1624
1642
  return;
1625
1643
  } else if (it.sep) it.value = token;
1626
1644
  else {
1627
- Object.assign(it, {
1628
- key: token,
1629
- sep: []
1630
- });
1631
- this.onKeyLine = !it.explicitKey;
1645
+ const item = it;
1646
+ item.key = token;
1647
+ item.sep = [];
1648
+ this.onKeyLine = !item.explicitKey;
1632
1649
  return;
1633
1650
  }
1634
1651
  break;
@@ -1650,12 +1667,13 @@ var Parser = class {
1650
1667
  sep: []
1651
1668
  });
1652
1669
  else if (it.sep) it.value = token;
1653
- else Object.assign(it, {
1654
- key: token,
1655
- sep: []
1656
- });
1670
+ else {
1671
+ it.key = token;
1672
+ it.sep = [];
1673
+ }
1657
1674
  return;
1658
1675
  }
1676
+ /* istanbul ignore next should not happen */
1659
1677
  default:
1660
1678
  this.pop();
1661
1679
  this.pop(token);
@@ -1769,6 +1787,7 @@ var Parser = class {
1769
1787
  }
1770
1788
  this.pop();
1771
1789
  break;
1790
+ /* istanbul ignore next should not happen */
1772
1791
  default:
1773
1792
  this.pop();
1774
1793
  this.step();
@@ -1857,62 +1876,68 @@ var Parser = class {
1857
1876
  this.onKeyLine = true;
1858
1877
  return;
1859
1878
  case "map-value-ind":
1860
- if (it.explicitKey) if (!it.sep) if (includesToken(it.start, "newline")) Object.assign(it, {
1861
- key: null,
1862
- sep: [this.sourceToken]
1863
- });
1864
- else {
1865
- const start = getFirstKeyStartProps(it.start);
1866
- this.stack.push({
1867
- type: "block-map",
1868
- offset: this.offset,
1869
- indent: this.indent,
1870
- items: [{
1871
- start,
1872
- key: null,
1873
- sep: [this.sourceToken]
1874
- }]
1875
- });
1876
- }
1877
- else if (it.value) map.items.push({
1878
- start: [],
1879
- key: null,
1880
- sep: [this.sourceToken]
1881
- });
1882
- else if (includesToken(it.sep, "map-value-ind")) this.stack.push({
1883
- type: "block-map",
1884
- offset: this.offset,
1885
- indent: this.indent,
1886
- items: [{
1887
- start,
1879
+ if (it.explicitKey) {
1880
+ if (!it.sep) {
1881
+ if (includesToken(it.start, "newline")) {
1882
+ const item = it;
1883
+ item.key = null;
1884
+ item.sep = [this.sourceToken];
1885
+ } else {
1886
+ const start = getFirstKeyStartProps(it.start);
1887
+ this.stack.push({
1888
+ type: "block-map",
1889
+ offset: this.offset,
1890
+ indent: this.indent,
1891
+ items: [{
1892
+ start,
1893
+ key: null,
1894
+ sep: [this.sourceToken]
1895
+ }]
1896
+ });
1897
+ }
1898
+ } else if (it.value) map.items.push({
1899
+ start: [],
1888
1900
  key: null,
1889
1901
  sep: [this.sourceToken]
1890
- }]
1891
- });
1892
- else if (isFlowToken(it.key) && !includesToken(it.sep, "newline")) {
1893
- const start = getFirstKeyStartProps(it.start);
1894
- const key = it.key;
1895
- const sep = it.sep;
1896
- sep.push(this.sourceToken);
1897
- delete it.key;
1898
- delete it.sep;
1899
- this.stack.push({
1902
+ });
1903
+ else if (includesToken(it.sep, "map-value-ind")) this.stack.push({
1900
1904
  type: "block-map",
1901
1905
  offset: this.offset,
1902
1906
  indent: this.indent,
1903
1907
  items: [{
1904
1908
  start,
1905
- key,
1906
- sep
1909
+ key: null,
1910
+ sep: [this.sourceToken]
1907
1911
  }]
1908
1912
  });
1909
- } else if (start.length > 0) it.sep = it.sep.concat(start, this.sourceToken);
1910
- else it.sep.push(this.sourceToken);
1911
- else if (!it.sep) Object.assign(it, {
1912
- key: null,
1913
- sep: [this.sourceToken]
1914
- });
1915
- else if (it.value || atNextItem) map.items.push({
1913
+ else if (isFlowToken(it.key) && !includesToken(it.sep, "newline")) {
1914
+ const start = getFirstKeyStartProps(it.start);
1915
+ const key = it.key;
1916
+ const sep = it.sep;
1917
+ sep.push(this.sourceToken);
1918
+ delete it.key;
1919
+ delete it.sep;
1920
+ this.stack.push({
1921
+ type: "block-map",
1922
+ offset: this.offset,
1923
+ indent: this.indent,
1924
+ items: [{
1925
+ start,
1926
+ key,
1927
+ sep
1928
+ }]
1929
+ });
1930
+ } else if (start.length > 0) it.sep = [
1931
+ ...it.sep,
1932
+ ...start,
1933
+ this.sourceToken
1934
+ ];
1935
+ else it.sep.push(this.sourceToken);
1936
+ } else if (!it.sep) {
1937
+ const item = it;
1938
+ item.key = null;
1939
+ item.sep = [this.sourceToken];
1940
+ } else if (it.value || atNextItem) map.items.push({
1916
1941
  start,
1917
1942
  key: null,
1918
1943
  sep: [this.sourceToken]
@@ -1944,10 +1969,9 @@ var Parser = class {
1944
1969
  this.onKeyLine = true;
1945
1970
  } else if (it.sep) this.stack.push(fs);
1946
1971
  else {
1947
- Object.assign(it, {
1948
- key: fs,
1949
- sep: []
1950
- });
1972
+ const item = it;
1973
+ item.key = fs;
1974
+ item.sep = [];
1951
1975
  this.onKeyLine = true;
1952
1976
  }
1953
1977
  return;
@@ -1965,7 +1989,7 @@ var Parser = class {
1965
1989
  });
1966
1990
  return;
1967
1991
  }
1968
- } else if (atMapIndent) map.items.push({ start });
1992
+ } else if (atMapIndent && (it.sep || it.explicitKey || start.length > 0)) map.items.push({ start });
1969
1993
  this.stack.push(bv);
1970
1994
  return;
1971
1995
  }
@@ -2044,10 +2068,10 @@ var Parser = class {
2044
2068
  sep: [this.sourceToken]
2045
2069
  });
2046
2070
  else if (it.sep) it.sep.push(this.sourceToken);
2047
- else Object.assign(it, {
2048
- key: null,
2049
- sep: [this.sourceToken]
2050
- });
2071
+ else {
2072
+ it.key = null;
2073
+ it.sep = [this.sourceToken];
2074
+ }
2051
2075
  return;
2052
2076
  case "space":
2053
2077
  case "comment":
@@ -2069,10 +2093,10 @@ var Parser = class {
2069
2093
  sep: []
2070
2094
  });
2071
2095
  else if (it.sep) this.stack.push(fs);
2072
- else Object.assign(it, {
2073
- key: fs,
2074
- sep: []
2075
- });
2096
+ else {
2097
+ it.key = fs;
2098
+ it.sep = [];
2099
+ }
2076
2100
  return;
2077
2101
  }
2078
2102
  case "flow-map-end":
@@ -2217,7 +2241,6 @@ var Parser = class {
2217
2241
  }
2218
2242
  }
2219
2243
  };
2220
-
2221
2244
  //#endregion
2222
2245
  //#region src/compose/resolve-props.ts
2223
2246
  function resolveProps(tokens, { flow, indicator, next, offset, onError, parentIndent, startOnNewline }) {
@@ -2235,7 +2258,8 @@ function resolveProps(tokens, { flow, indicator, next, offset, onError, parentIn
2235
2258
  let comma = null;
2236
2259
  let found = null;
2237
2260
  let start = null;
2238
- for (const token of tokens) {
2261
+ let token;
2262
+ for (token of tokens) {
2239
2263
  if (reqSpace) {
2240
2264
  if (token.type !== "space" && token.type !== "newline" && token.type !== "comma") onError(token.offset, "MISSING_CHAR", "Tags and anchors must be separated from the next token by white space");
2241
2265
  reqSpace = false;
@@ -2305,8 +2329,7 @@ function resolveProps(tokens, { flow, indicator, next, offset, onError, parentIn
2305
2329
  hasSpace = false;
2306
2330
  }
2307
2331
  }
2308
- const last = tokens[tokens.length - 1];
2309
- const end = last ? last.offset + last.source.length : offset;
2332
+ const end = token ? token.offset + token.source.length : offset;
2310
2333
  if (reqSpace && next && next.type !== "space" && next.type !== "newline" && next.type !== "comma" && (next.type !== "scalar" || next.source !== "")) onError(next.offset, "MISSING_CHAR", "Tags and anchors must be separated from the next token by white space");
2311
2334
  if (tab && (atNewline && tab.indent <= parentIndent || next?.type === "block-map" || next?.type === "block-seq")) onError(tab, "TAB_AS_INDENT", "Tabs are not allowed as indentation");
2312
2335
  return {
@@ -2322,7 +2345,6 @@ function resolveProps(tokens, { flow, indicator, next, offset, onError, parentIn
2322
2345
  start: start ?? end
2323
2346
  };
2324
2347
  }
2325
-
2326
2348
  //#endregion
2327
2349
  //#region src/compose/util-contains-newline.ts
2328
2350
  function containsNewline(key) {
@@ -2349,7 +2371,6 @@ function containsNewline(key) {
2349
2371
  default: return true;
2350
2372
  }
2351
2373
  }
2352
-
2353
2374
  //#endregion
2354
2375
  //#region src/compose/util-flow-indent-check.ts
2355
2376
  function flowIndentCheck(indent, fc, onError) {
@@ -2358,21 +2379,11 @@ function flowIndentCheck(indent, fc, onError) {
2358
2379
  if (end.indent === indent && (end.source === "]" || end.source === "}") && containsNewline(fc)) onError(end, "BAD_INDENT", "Flow end indicator should be more indented than parent", true);
2359
2380
  }
2360
2381
  }
2361
-
2362
- //#endregion
2363
- //#region src/compose/util-map-includes.ts
2364
- function mapIncludes(ctx, items, search) {
2365
- const { uniqueKeys } = ctx.options;
2366
- if (uniqueKeys === false) return false;
2367
- const isEqual = typeof uniqueKeys === "function" ? uniqueKeys : (a, b) => a === b || a instanceof Scalar && b instanceof Scalar && a.value === b.value;
2368
- return items.some((pair) => isEqual(pair.key, search));
2369
- }
2370
-
2371
2382
  //#endregion
2372
2383
  //#region src/compose/resolve-block-map.ts
2373
2384
  const startColMsg = "All mapping items must start at the same column";
2374
2385
  function resolveBlockMap({ composeNode, composeEmptyNode }, ctx, bm, onError, tag) {
2375
- const map = new (tag?.nodeClass ?? YAMLMap)(ctx.schema);
2386
+ const map = new ((tag?.nodeClass) ?? YAMLMap)(ctx.schema);
2376
2387
  if (ctx.atRoot) ctx.atRoot = false;
2377
2388
  let offset = bm.offset;
2378
2389
  let commentEnd = null;
@@ -2394,8 +2405,10 @@ function resolveBlockMap({ composeNode, composeEmptyNode }, ctx, bm, onError, ta
2394
2405
  }
2395
2406
  if (!keyProps.anchor && !keyProps.tag && !sep) {
2396
2407
  commentEnd = keyProps.end;
2397
- if (keyProps.comment) if (map.comment) map.comment += "\n" + keyProps.comment;
2398
- else map.comment = keyProps.comment;
2408
+ if (keyProps.comment) {
2409
+ if (map.comment) map.comment += "\n" + keyProps.comment;
2410
+ else map.comment = keyProps.comment;
2411
+ }
2399
2412
  continue;
2400
2413
  }
2401
2414
  if (keyProps.newlineAfterProp || containsNewline(key)) onError(key ?? start[start.length - 1], "MULTILINE_IMPLICIT_KEY", "Implicit keys need to be on a single line");
@@ -2405,7 +2418,7 @@ function resolveBlockMap({ composeNode, composeEmptyNode }, ctx, bm, onError, ta
2405
2418
  const keyNode = key ? composeNode(ctx, key, keyProps, onError) : composeEmptyNode(ctx, keyStart, start, null, keyProps, onError);
2406
2419
  if (ctx.schema.compat) flowIndentCheck(bm.indent, key, onError);
2407
2420
  ctx.atKey = false;
2408
- if (mapIncludes(ctx, map.items, keyNode)) onError(keyStart, "DUPLICATE_KEY", "Map keys must be unique");
2421
+ if (map.has(keyNode)) onError(keyStart, "DUPLICATE_KEY", "Map keys must be unique");
2409
2422
  const valueProps = resolveProps(sep ?? [], {
2410
2423
  indicator: "map-value-ind",
2411
2424
  next: value,
@@ -2423,16 +2436,31 @@ function resolveBlockMap({ composeNode, composeEmptyNode }, ctx, bm, onError, ta
2423
2436
  const valueNode = value ? composeNode(ctx, value, valueProps, onError) : composeEmptyNode(ctx, offset, sep, null, valueProps, onError);
2424
2437
  if (ctx.schema.compat) flowIndentCheck(bm.indent, value, onError);
2425
2438
  offset = valueNode.range[2];
2426
- const pair = new Pair(keyNode, valueNode);
2427
- if (ctx.options.keepSourceTokens) pair.srcToken = collItem;
2428
- map.items.push(pair);
2439
+ if (map instanceof YAMLSet) {
2440
+ if (value || valueProps.anchor || valueProps.tag) onError(valueNode.range, "BAD_COLLECTION_TYPE", "Set items must not have non-empty values");
2441
+ if (valueProps.comment) {
2442
+ if (keyNode.comment) keyNode.comment += "\n" + valueProps.comment;
2443
+ else keyNode.comment = valueProps.comment;
2444
+ keyNode.range[2] = valueProps.end;
2445
+ }
2446
+ map.add(keyNode);
2447
+ } else {
2448
+ const pair = new Pair(keyNode, valueNode);
2449
+ if (ctx.options.keepSourceTokens) pair.srcToken = collItem;
2450
+ map.set(pair);
2451
+ }
2429
2452
  } else {
2430
2453
  if (implicitKey) onError(keyNode.range, "MISSING_CHAR", "Implicit map keys need to be followed by map values");
2431
- if (valueProps.comment) if (keyNode.comment) keyNode.comment += "\n" + valueProps.comment;
2432
- else keyNode.comment = valueProps.comment;
2433
- const pair = new Pair(keyNode);
2434
- if (ctx.options.keepSourceTokens) pair.srcToken = collItem;
2435
- map.items.push(pair);
2454
+ if (valueProps.comment) {
2455
+ if (keyNode.comment) keyNode.comment += "\n" + valueProps.comment;
2456
+ else keyNode.comment = valueProps.comment;
2457
+ }
2458
+ if (map instanceof YAMLSet) map.add(keyNode);
2459
+ else {
2460
+ const pair = new Pair(keyNode);
2461
+ if (ctx.options.keepSourceTokens) pair.srcToken = collItem;
2462
+ map.set(pair);
2463
+ }
2436
2464
  }
2437
2465
  }
2438
2466
  if (commentEnd && commentEnd < offset) onError(commentEnd, "IMPOSSIBLE", "Map comment with trailing content");
@@ -2443,11 +2471,10 @@ function resolveBlockMap({ composeNode, composeEmptyNode }, ctx, bm, onError, ta
2443
2471
  ];
2444
2472
  return map;
2445
2473
  }
2446
-
2447
2474
  //#endregion
2448
2475
  //#region src/compose/resolve-block-seq.ts
2449
2476
  function resolveBlockSeq({ composeNode, composeEmptyNode }, ctx, bs, onError, tag) {
2450
- const seq = new (tag?.nodeClass ?? YAMLSeq)(ctx.schema);
2477
+ const seq = new ((tag?.nodeClass) ?? YAMLSeq)(ctx.schema);
2451
2478
  if (ctx.atRoot) ctx.atRoot = false;
2452
2479
  if (ctx.atKey) ctx.atKey = false;
2453
2480
  let offset = bs.offset;
@@ -2461,17 +2488,20 @@ function resolveBlockSeq({ composeNode, composeEmptyNode }, ctx, bs, onError, ta
2461
2488
  parentIndent: bs.indent,
2462
2489
  startOnNewline: true
2463
2490
  });
2464
- if (!props.found) if (props.anchor || props.tag || value) if (value?.type === "block-seq") onError(props.end, "BAD_INDENT", "All sequence items must start at the same column");
2465
- else onError(offset, "MISSING_CHAR", "Sequence item without - indicator");
2466
- else {
2467
- commentEnd = props.end;
2468
- if (props.comment) seq.comment = props.comment;
2469
- continue;
2491
+ if (!props.found) {
2492
+ if (props.anchor || props.tag || value) {
2493
+ if (value?.type === "block-seq") onError(props.end, "BAD_INDENT", "All sequence items must start at the same column");
2494
+ else onError(offset, "MISSING_CHAR", "Sequence item without - indicator");
2495
+ } else {
2496
+ commentEnd = props.end;
2497
+ if (props.comment) seq.comment = props.comment;
2498
+ continue;
2499
+ }
2470
2500
  }
2471
2501
  const node = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end, start, null, props, onError);
2472
2502
  if (ctx.schema.compat) flowIndentCheck(bs.indent, value, onError);
2473
2503
  offset = node.range[2];
2474
- seq.items.push(node);
2504
+ seq._push(node);
2475
2505
  }
2476
2506
  seq.range = [
2477
2507
  bs.offset,
@@ -2480,7 +2510,6 @@ function resolveBlockSeq({ composeNode, composeEmptyNode }, ctx, bs, onError, ta
2480
2510
  ];
2481
2511
  return seq;
2482
2512
  }
2483
-
2484
2513
  //#endregion
2485
2514
  //#region src/compose/resolve-flow-collection.ts
2486
2515
  const blockMsg = "Block collections are not allowed within flow collections";
@@ -2488,7 +2517,9 @@ const isBlock = (token) => token && (token.type === "block-map" || token.type ==
2488
2517
  function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onError, tag) {
2489
2518
  const isMap = fc.start.source === "{";
2490
2519
  const fcName = isMap ? "flow map" : "flow sequence";
2491
- const coll = new (tag?.nodeClass ?? (isMap ? YAMLMap : YAMLSeq))(ctx.schema);
2520
+ let coll;
2521
+ if (tag?.nodeClass) coll = new tag.nodeClass(ctx.schema);
2522
+ else coll = isMap ? new YAMLMap(ctx.schema) : new YAMLSeq(ctx.schema);
2492
2523
  coll.flow = true;
2493
2524
  const atRoot = ctx.atRoot;
2494
2525
  if (atRoot) ctx.atRoot = false;
@@ -2510,8 +2541,10 @@ function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onErr
2510
2541
  if (!props.anchor && !props.tag && !sep && !value) {
2511
2542
  if (i === 0 && props.comma) onError(props.comma, "UNEXPECTED_TOKEN", `Unexpected , in ${fcName}`);
2512
2543
  else if (i < fc.items.length - 1) onError(props.start, "UNEXPECTED_TOKEN", `Unexpected empty item in ${fcName}`);
2513
- if (props.comment) if (coll.comment) coll.comment += "\n" + props.comment;
2514
- else coll.comment = props.comment;
2544
+ if (props.comment) {
2545
+ if (coll.comment) coll.comment += "\n" + props.comment;
2546
+ else coll.comment = props.comment;
2547
+ }
2515
2548
  offset = props.end;
2516
2549
  continue;
2517
2550
  }
@@ -2532,7 +2565,9 @@ function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onErr
2532
2565
  default: break loop;
2533
2566
  }
2534
2567
  if (prevItemComment) {
2535
- let prev = coll.items[coll.items.length - 1];
2568
+ let prev;
2569
+ if (Array.isArray(coll)) prev = coll[coll.length - 1];
2570
+ else for (const prev_ of coll.values.values()) prev = prev_;
2536
2571
  if (prev instanceof Pair) prev = prev.value ?? prev.key;
2537
2572
  if (prev.comment) prev.comment += "\n" + prevItemComment;
2538
2573
  else prev.comment = prevItemComment;
@@ -2542,7 +2577,7 @@ function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onErr
2542
2577
  }
2543
2578
  if (!isMap && !sep && !props.found) {
2544
2579
  const valueNode = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end, sep, null, props, onError);
2545
- coll.items.push(valueNode);
2580
+ coll._push(valueNode);
2546
2581
  offset = valueNode.range[2];
2547
2582
  if (isBlock(value)) onError(valueNode.range, "BLOCK_IN_FLOW", blockMsg);
2548
2583
  } else {
@@ -2571,30 +2606,35 @@ function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onErr
2571
2606
  }
2572
2607
  if (props.start < valueProps.found.offset - 1024) onError(valueProps.found, "KEY_OVER_1024_CHARS", "The : indicator must be at most 1024 chars after the start of an implicit flow sequence key");
2573
2608
  }
2574
- } else if (value) if ("source" in value && value.source?.[0] === ":") onError(value, "MISSING_CHAR", `Missing space after : in ${fcName}`);
2575
- else onError(valueProps.start, "MISSING_CHAR", `Missing , or : between ${fcName} items`);
2609
+ } else if (value) {
2610
+ if ("source" in value && value.source?.[0] === ":") onError(value, "MISSING_CHAR", `Missing space after : in ${fcName}`);
2611
+ else onError(valueProps.start, "MISSING_CHAR", `Missing , or : between ${fcName} items`);
2612
+ }
2576
2613
  const valueNode = value ? composeNode(ctx, value, valueProps, onError) : valueProps.found ? composeEmptyNode(ctx, valueProps.end, sep, null, valueProps, onError) : null;
2577
2614
  if (valueNode) {
2578
2615
  if (isBlock(value)) onError(valueNode.range, "BLOCK_IN_FLOW", blockMsg);
2579
- } else if (valueProps.comment) if (keyNode.comment) keyNode.comment += "\n" + valueProps.comment;
2580
- else keyNode.comment = valueProps.comment;
2616
+ } else if (valueProps.comment) {
2617
+ if (keyNode.comment) keyNode.comment += "\n" + valueProps.comment;
2618
+ else keyNode.comment = valueProps.comment;
2619
+ }
2581
2620
  const pair = new Pair(keyNode, valueNode);
2582
2621
  if (ctx.options.keepSourceTokens) pair.srcToken = collItem;
2583
2622
  if (isMap) {
2584
2623
  const map = coll;
2585
- if (mapIncludes(ctx, map.items, keyNode)) onError(keyStart, "DUPLICATE_KEY", "Map keys must be unique");
2586
- map.items.push(pair);
2624
+ if (map.has(keyNode)) onError(keyStart, "DUPLICATE_KEY", "Map keys must be unique");
2625
+ if (map instanceof YAMLSet) map.add(keyNode);
2626
+ else map.set(pair);
2587
2627
  } else {
2588
2628
  const map = new YAMLMap(ctx.schema);
2589
2629
  map.flow = true;
2590
- map.items.push(pair);
2630
+ map.set(pair);
2591
2631
  const endRange = (valueNode ?? keyNode).range;
2592
2632
  map.range = [
2593
2633
  keyNode.range[0],
2594
2634
  endRange[1],
2595
2635
  endRange[2]
2596
2636
  ];
2597
- coll.items.push(map);
2637
+ coll._push(map);
2598
2638
  }
2599
2639
  offset = valueNode ? valueNode.range[2] : valueProps.end;
2600
2640
  }
@@ -2611,8 +2651,10 @@ function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onErr
2611
2651
  }
2612
2652
  if (ee.length > 0) {
2613
2653
  const end = resolveEnd(ee, cePos, ctx.options.strict, onError);
2614
- if (end.comment) if (coll.comment) coll.comment += "\n" + end.comment;
2615
- else coll.comment = end.comment;
2654
+ if (end.comment) {
2655
+ if (coll.comment) coll.comment += "\n" + end.comment;
2656
+ else coll.comment = end.comment;
2657
+ }
2616
2658
  coll.range = [
2617
2659
  fc.offset,
2618
2660
  cePos,
@@ -2625,7 +2667,6 @@ function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onErr
2625
2667
  ];
2626
2668
  return coll;
2627
2669
  }
2628
-
2629
2670
  //#endregion
2630
2671
  //#region src/compose/compose-collection.ts
2631
2672
  function resolveCollection(CN, ctx, token, onError, tagName, tag) {
@@ -2662,13 +2703,12 @@ function composeCollection(CN, ctx, token, props, onError) {
2662
2703
  }
2663
2704
  const coll = resolveCollection(CN, ctx, token, onError, tagName, tag);
2664
2705
  const res = tag.resolve?.(coll, (msg) => onError(tagToken, "TAG_RESOLVE_FAILED", msg), ctx.options) ?? coll;
2665
- const node = res instanceof NodeBase ? res : new Scalar(res);
2706
+ const node = isNode(res) ? res : new Scalar(res);
2666
2707
  node.range = coll.range;
2667
2708
  node.tag = tagName;
2668
2709
  if (tag?.format) node.format = tag.format;
2669
2710
  return node;
2670
2711
  }
2671
-
2672
2712
  //#endregion
2673
2713
  //#region src/compose/compose-scalar.ts
2674
2714
  function composeScalar(ctx, token, tagToken, onError) {
@@ -2699,9 +2739,11 @@ function composeScalar(ctx, token, tagToken, onError) {
2699
2739
  function findScalarTagByName(schema, value, tagName, tagToken, onError) {
2700
2740
  if (tagName === "!") return schema.scalar;
2701
2741
  const matchWithTest = [];
2702
- for (const tag of schema.tags) if (!tag.collection && tag.tag === tagName) if (tag.default && tag.test) matchWithTest.push(tag);
2703
- else return tag;
2704
- for (const tag of matchWithTest) if (tag.test?.test(value)) return tag;
2742
+ for (const tag of schema.tags) if (!tag.collection && tag.tag === tagName) {
2743
+ if (tag.default && tag.test) matchWithTest.push(tag);
2744
+ else return tag;
2745
+ }
2746
+ for (const tag of matchWithTest) if (tag.test?.(value)) return tag;
2705
2747
  const kt = schema.knownTags[tagName];
2706
2748
  if (kt && !kt.collection) {
2707
2749
  schema.tags.push(Object.assign({}, kt, {
@@ -2713,15 +2755,20 @@ function findScalarTagByName(schema, value, tagName, tagToken, onError) {
2713
2755
  onError(tagToken, "TAG_RESOLVE_FAILED", `Unresolved tag: ${tagName}`, tagName !== "tag:yaml.org,2002:str");
2714
2756
  return schema.scalar;
2715
2757
  }
2758
+ const schemaTagsWithTest = /* @__PURE__ */ new WeakMap();
2716
2759
  function findScalarTagByTest({ atKey, directives, schema }, value, token, onError) {
2717
- const tag = schema.tags.find((tag) => (tag.default === true || atKey && tag.default === "key") && tag.test?.test(value)) || schema.scalar;
2760
+ let schemaTags = schemaTagsWithTest.get(schema);
2761
+ if (!schemaTags) {
2762
+ schemaTags = schema.tags.filter((t) => t.test !== void 0 && (t.default === true || t.default === "key"));
2763
+ schemaTagsWithTest.set(schema, schemaTags);
2764
+ }
2765
+ const tag = schemaTags.find((t) => (t.default === true || atKey && t.default === "key") && t.test?.(value)) ?? schema.scalar;
2718
2766
  if (schema.compat) {
2719
- const compat = schema.compat.find((tag) => tag.default && tag.test?.test(value)) ?? schema.scalar;
2767
+ const compat = schema.compat.find((tag) => tag.default && tag.test?.(value)) ?? schema.scalar;
2720
2768
  if (tag.tag !== compat.tag) onError(token, "TAG_RESOLVE_FAILED", `Value may be parsed as either ${directives.tagString(tag.tag)} or ${directives.tagString(compat.tag)}`, true);
2721
2769
  }
2722
2770
  return tag;
2723
2771
  }
2724
-
2725
2772
  //#endregion
2726
2773
  //#region src/compose/util-empty-scalar-position.ts
2727
2774
  function emptyScalarPosition(offset, before, pos) {
@@ -2746,7 +2793,6 @@ function emptyScalarPosition(offset, before, pos) {
2746
2793
  }
2747
2794
  return offset;
2748
2795
  }
2749
-
2750
2796
  //#endregion
2751
2797
  //#region src/compose/compose-node.ts
2752
2798
  const CN = {
@@ -2773,19 +2819,25 @@ function composeNode(ctx, token, props, onError) {
2773
2819
  case "block-map":
2774
2820
  case "block-seq":
2775
2821
  case "flow-collection":
2776
- node = composeCollection(CN, ctx, token, props, onError);
2777
- if (anchor) node.anchor = anchor.source.substring(1);
2822
+ try {
2823
+ node = composeCollection(CN, ctx, token, props, onError);
2824
+ if (anchor) node.anchor = anchor.source.substring(1);
2825
+ } catch (error) {
2826
+ onError(token, "RESOURCE_EXHAUSTION", error instanceof Error ? error.message : String(error));
2827
+ }
2778
2828
  break;
2779
2829
  default:
2780
2830
  onError(token, "UNEXPECTED_TOKEN", token.type === "error" ? token.message : `Unsupported token (type: ${token.type})`);
2781
- node = composeEmptyNode(ctx, token.offset, void 0, null, props, onError);
2782
2831
  isSrcToken = false;
2783
2832
  }
2833
+ node ??= composeEmptyNode(ctx, token.offset, void 0, null, props, onError);
2784
2834
  if (anchor && node.anchor === "") onError(anchor, "BAD_ALIAS", "Anchor cannot be an empty string");
2785
2835
  if (atKey && ctx.options.stringKeys && (!(node instanceof Scalar) || typeof node.value !== "string" || node.tag && node.tag !== "tag:yaml.org,2002:str")) onError(tag ?? token, "NON_STRING_KEY", "With stringKeys, all keys must be strings");
2786
2836
  if (spaceBefore) node.spaceBefore = true;
2787
- if (comment) if (token.type === "scalar" && token.source === "") node.comment = comment;
2788
- else node.commentBefore = comment;
2837
+ if (comment) {
2838
+ if (token.type === "scalar" && token.source === "") node.comment = comment;
2839
+ else node.commentBefore = comment;
2840
+ }
2789
2841
  if (ctx.options.keepSourceTokens && isSrcToken) node.srcToken = token;
2790
2842
  return node;
2791
2843
  }
@@ -2821,11 +2873,11 @@ function composeAlias({ options }, { offset, source, end }, onError) {
2821
2873
  if (re.comment) alias.comment = re.comment;
2822
2874
  return alias;
2823
2875
  }
2824
-
2825
2876
  //#endregion
2826
2877
  //#region src/compose/compose-doc.ts
2827
2878
  function composeDoc(options, directives, { offset, start, value, end }, onError) {
2828
- const doc = new Document(void 0, Object.assign({ _directives: directives }, options));
2879
+ const opts = Object.assign({ _directives: directives }, options);
2880
+ const doc = new Document(void 0, opts);
2829
2881
  const ctx = {
2830
2882
  atKey: false,
2831
2883
  atRoot: true,
@@ -2856,7 +2908,6 @@ function composeDoc(options, directives, { offset, start, value, end }, onError)
2856
2908
  ];
2857
2909
  return doc;
2858
2910
  }
2859
-
2860
2911
  //#endregion
2861
2912
  //#region src/compose/composer.ts
2862
2913
  function getErrorPos(src) {
@@ -2927,8 +2978,8 @@ var Composer = class {
2927
2978
  const dc = doc.value;
2928
2979
  if (afterDoc) doc.comment = doc.comment ? `${doc.comment}\n${comment}` : comment;
2929
2980
  else if (afterEmptyLine || doc.directives.docStart) doc.commentBefore = comment;
2930
- else if (dc instanceof Collection && !dc.flow && dc.items.length > 0) {
2931
- let it = dc.items[0];
2981
+ else if (isCollection$1(dc) && !dc.flow && dc.size > 0) {
2982
+ let it = Array.isArray(dc) ? dc[0] : dc.values.values().next().value;
2932
2983
  if (it instanceof Pair) it = it.key;
2933
2984
  const cb = it.commentBefore;
2934
2985
  it.commentBefore = cb ? `${comment}\n${cb}` : comment;
@@ -3037,7 +3088,8 @@ var Composer = class {
3037
3088
  this.docs.push(this.doc);
3038
3089
  this.doc = null;
3039
3090
  } else if (forceDoc) {
3040
- const doc = new Document(void 0, Object.assign({ _directives: this.directives }, this.options));
3091
+ const opts = Object.assign({ _directives: this.directives }, this.options);
3092
+ const doc = new Document(void 0, opts);
3041
3093
  if (this.atDirectives) this.onError(endOffset, "MISSING_CHAR", "Missing directives-end indicator line");
3042
3094
  doc.range = [
3043
3095
  0,
@@ -3050,7 +3102,6 @@ var Composer = class {
3050
3102
  return this.docs;
3051
3103
  }
3052
3104
  };
3053
-
3054
3105
  //#endregion
3055
3106
  //#region src/parse/line-counter.ts
3056
3107
  /**
@@ -3093,6 +3144,5 @@ var LineCounter = class {
3093
3144
  };
3094
3145
  };
3095
3146
  };
3096
-
3097
3147
  //#endregion
3098
- export { cst_exports as a, YAMLParseError as c, lex as i, YAMLWarning as l, Composer as n, prettyToken as o, Parser as r, YAMLError as s, LineCounter as t, prettifyError as u };
3148
+ export { cst_exports as a, YAMLParseError as c, lex as i, YAMLWarning as l, Composer as n, prettyToken as o, Parser as r, YAMLError as s, LineCounter as t, prettifyError as u };