yaml 2.9.0 → 2.9.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.
@@ -64,46 +64,47 @@ function plainValue(source, onError) {
64
64
  }
65
65
  if (badChar)
66
66
  onError(0, 'BAD_SCALAR_START', `Plain value cannot start with ${badChar}`);
67
- return foldLines(source);
67
+ return unfoldLines(source);
68
68
  }
69
69
  function singleQuotedValue(source, onError) {
70
70
  if (source[source.length - 1] !== "'" || source.length === 1)
71
71
  onError(source.length, 'MISSING_CHAR', "Missing closing 'quote");
72
- return foldLines(source.slice(1, -1)).replace(/''/g, "'");
72
+ return unfoldLines(source.slice(1, -1)).replace(/''/g, "'");
73
73
  }
74
- function foldLines(source) {
74
+ function unfoldLines(source) {
75
+ const line = /(.*?)\r?\n/sy;
76
+ let match = line.exec(source);
77
+ if (!match)
78
+ return source;
75
79
  /**
76
- * The negative lookbehind here and in the `re` RegExp is to
80
+ * The negative lookbehinds in these RegExps are to
77
81
  * prevent causing a polynomial search time in certain cases.
78
82
  *
79
- * The try-catch is for Safari, which doesn't support this yet:
83
+ * The try-catch is for Safari < 16.4 and other old browsers:
80
84
  * https://caniuse.com/js-regexp-lookbehind
81
85
  */
82
- let first, line;
86
+ let trimEnd, trimBoth;
83
87
  try {
84
- first = new RegExp('(.*?)(?<![ \t])[ \t]*\r?\n', 'sy');
85
- line = new RegExp('[ \t]*(.*?)(?:(?<![ \t])[ \t]*)?\r?\n', 'sy');
88
+ trimEnd = new RegExp('(?<![ \t])[ \t]+$');
89
+ trimBoth = new RegExp('^[ \t]+|(?<![ \t])[ \t]+$', 'g');
86
90
  }
87
91
  catch {
88
- first = /(.*?)[ \t]*\r?\n/sy;
89
- line = /[ \t]*(.*?)[ \t]*\r?\n/sy;
92
+ trimEnd = /[ \t]+$/;
93
+ trimBoth = /^[ \t]+|[ \t]+$/g;
90
94
  }
91
- let match = first.exec(source);
92
- if (!match)
93
- return source;
94
- let res = match[1];
95
+ let res = match[1].replace(trimEnd, '');
95
96
  let sep = ' ';
96
- let pos = first.lastIndex;
97
- line.lastIndex = pos;
97
+ let pos = line.lastIndex;
98
98
  while ((match = line.exec(source))) {
99
- if (match[1] === '') {
99
+ const lm = match[1].replace(trimBoth, '');
100
+ if (lm === '') {
100
101
  if (sep === '\n')
101
102
  res += sep;
102
103
  else
103
104
  sep = '\n';
104
105
  }
105
106
  else {
106
- res += sep + match[1];
107
+ res += sep + lm;
107
108
  sep = ' ';
108
109
  }
109
110
  pos = line.lastIndex;
@@ -43,38 +43,40 @@ class Alias extends NodeBase {
43
43
  if (node.anchor === this.source)
44
44
  found = node;
45
45
  }
46
+ if (found && ctx) {
47
+ const { anchors, doc, maxAliasCount } = ctx;
48
+ let data = anchors.get(found);
49
+ if (!data) {
50
+ // Resolve anchors for Node.prototype.toJS()
51
+ toJS(found, null, ctx);
52
+ data = anchors.get(found);
53
+ }
54
+ /* istanbul ignore if */
55
+ if (data?.res === undefined) {
56
+ const msg = 'This should not happen: Alias anchor was not resolved?';
57
+ throw new ReferenceError(msg);
58
+ }
59
+ if (maxAliasCount >= 0) {
60
+ data.count += 1;
61
+ if (data.aliasCount === 0)
62
+ data.aliasCount = getAliasCount(doc, found, anchors);
63
+ if (data.count * data.aliasCount > maxAliasCount) {
64
+ const msg = 'Excessive alias count indicates a resource exhaustion attack';
65
+ throw new ReferenceError(msg);
66
+ }
67
+ }
68
+ }
46
69
  return found;
47
70
  }
48
71
  toJSON(_arg, ctx) {
49
72
  if (!ctx)
50
73
  return { source: this.source };
51
- const { anchors, doc, maxAliasCount } = ctx;
52
- const source = this.resolve(doc, ctx);
74
+ const source = this.resolve(ctx.doc, ctx);
53
75
  if (!source) {
54
76
  const msg = `Unresolved alias (the anchor must be set before the alias): ${this.source}`;
55
77
  throw new ReferenceError(msg);
56
78
  }
57
- let data = anchors.get(source);
58
- if (!data) {
59
- // Resolve anchors for Node.prototype.toJS()
60
- toJS(source, null, ctx);
61
- data = anchors.get(source);
62
- }
63
- /* istanbul ignore if */
64
- if (data?.res === undefined) {
65
- const msg = 'This should not happen: Alias anchor was not resolved?';
66
- throw new ReferenceError(msg);
67
- }
68
- if (maxAliasCount >= 0) {
69
- data.count += 1;
70
- if (data.aliasCount === 0)
71
- data.aliasCount = getAliasCount(doc, source, anchors);
72
- if (data.count * data.aliasCount > maxAliasCount) {
73
- const msg = 'Excessive alias count indicates a resource exhaustion attack';
74
- throw new ReferenceError(msg);
75
- }
76
- }
77
- return data.res;
79
+ return ctx.anchors.get(source).res;
78
80
  }
79
81
  toString(ctx, _onComment, _onChompKeep) {
80
82
  const src = `*${this.source}`;
@@ -66,46 +66,47 @@ function plainValue(source, onError) {
66
66
  }
67
67
  if (badChar)
68
68
  onError(0, 'BAD_SCALAR_START', `Plain value cannot start with ${badChar}`);
69
- return foldLines(source);
69
+ return unfoldLines(source);
70
70
  }
71
71
  function singleQuotedValue(source, onError) {
72
72
  if (source[source.length - 1] !== "'" || source.length === 1)
73
73
  onError(source.length, 'MISSING_CHAR', "Missing closing 'quote");
74
- return foldLines(source.slice(1, -1)).replace(/''/g, "'");
74
+ return unfoldLines(source.slice(1, -1)).replace(/''/g, "'");
75
75
  }
76
- function foldLines(source) {
76
+ function unfoldLines(source) {
77
+ const line = /(.*?)\r?\n/sy;
78
+ let match = line.exec(source);
79
+ if (!match)
80
+ return source;
77
81
  /**
78
- * The negative lookbehind here and in the `re` RegExp is to
82
+ * The negative lookbehinds in these RegExps are to
79
83
  * prevent causing a polynomial search time in certain cases.
80
84
  *
81
- * The try-catch is for Safari, which doesn't support this yet:
85
+ * The try-catch is for Safari < 16.4 and other old browsers:
82
86
  * https://caniuse.com/js-regexp-lookbehind
83
87
  */
84
- let first, line;
88
+ let trimEnd, trimBoth;
85
89
  try {
86
- first = new RegExp('(.*?)(?<![ \t])[ \t]*\r?\n', 'sy');
87
- line = new RegExp('[ \t]*(.*?)(?:(?<![ \t])[ \t]*)?\r?\n', 'sy');
90
+ trimEnd = new RegExp('(?<![ \t])[ \t]+$');
91
+ trimBoth = new RegExp('^[ \t]+|(?<![ \t])[ \t]+$', 'g');
88
92
  }
89
93
  catch {
90
- first = /(.*?)[ \t]*\r?\n/sy;
91
- line = /[ \t]*(.*?)[ \t]*\r?\n/sy;
94
+ trimEnd = /[ \t]+$/;
95
+ trimBoth = /^[ \t]+|[ \t]+$/g;
92
96
  }
93
- let match = first.exec(source);
94
- if (!match)
95
- return source;
96
- let res = match[1];
97
+ let res = match[1].replace(trimEnd, '');
97
98
  let sep = ' ';
98
- let pos = first.lastIndex;
99
- line.lastIndex = pos;
99
+ let pos = line.lastIndex;
100
100
  while ((match = line.exec(source))) {
101
- if (match[1] === '') {
101
+ const lm = match[1].replace(trimBoth, '');
102
+ if (lm === '') {
102
103
  if (sep === '\n')
103
104
  res += sep;
104
105
  else
105
106
  sep = '\n';
106
107
  }
107
108
  else {
108
- res += sep + match[1];
109
+ res += sep + lm;
109
110
  sep = ' ';
110
111
  }
111
112
  pos = line.lastIndex;
@@ -45,38 +45,40 @@ class Alias extends Node.NodeBase {
45
45
  if (node.anchor === this.source)
46
46
  found = node;
47
47
  }
48
+ if (found && ctx) {
49
+ const { anchors, doc, maxAliasCount } = ctx;
50
+ let data = anchors.get(found);
51
+ if (!data) {
52
+ // Resolve anchors for Node.prototype.toJS()
53
+ toJS.toJS(found, null, ctx);
54
+ data = anchors.get(found);
55
+ }
56
+ /* istanbul ignore if */
57
+ if (data?.res === undefined) {
58
+ const msg = 'This should not happen: Alias anchor was not resolved?';
59
+ throw new ReferenceError(msg);
60
+ }
61
+ if (maxAliasCount >= 0) {
62
+ data.count += 1;
63
+ if (data.aliasCount === 0)
64
+ data.aliasCount = getAliasCount(doc, found, anchors);
65
+ if (data.count * data.aliasCount > maxAliasCount) {
66
+ const msg = 'Excessive alias count indicates a resource exhaustion attack';
67
+ throw new ReferenceError(msg);
68
+ }
69
+ }
70
+ }
48
71
  return found;
49
72
  }
50
73
  toJSON(_arg, ctx) {
51
74
  if (!ctx)
52
75
  return { source: this.source };
53
- const { anchors, doc, maxAliasCount } = ctx;
54
- const source = this.resolve(doc, ctx);
76
+ const source = this.resolve(ctx.doc, ctx);
55
77
  if (!source) {
56
78
  const msg = `Unresolved alias (the anchor must be set before the alias): ${this.source}`;
57
79
  throw new ReferenceError(msg);
58
80
  }
59
- let data = anchors.get(source);
60
- if (!data) {
61
- // Resolve anchors for Node.prototype.toJS()
62
- toJS.toJS(source, null, ctx);
63
- data = anchors.get(source);
64
- }
65
- /* istanbul ignore if */
66
- if (data?.res === undefined) {
67
- const msg = 'This should not happen: Alias anchor was not resolved?';
68
- throw new ReferenceError(msg);
69
- }
70
- if (maxAliasCount >= 0) {
71
- data.count += 1;
72
- if (data.aliasCount === 0)
73
- data.aliasCount = getAliasCount(doc, source, anchors);
74
- if (data.count * data.aliasCount > maxAliasCount) {
75
- const msg = 'Excessive alias count indicates a resource exhaustion attack';
76
- throw new ReferenceError(msg);
77
- }
78
- }
79
- return data.res;
81
+ return ctx.anchors.get(source).res;
80
82
  }
81
83
  toString(ctx, _onComment, _onChompKeep) {
82
84
  const src = `*${this.source}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yaml",
3
- "version": "2.9.0",
3
+ "version": "2.9.1",
4
4
  "license": "ISC",
5
5
  "author": "Eemeli Aro <eemeli@gmail.com>",
6
6
  "funding": "https://github.com/sponsors/eemeli",