step-node-agent 3.26.0 → 3.26.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.
Files changed (48) hide show
  1. package/node_modules/cookie/index.js +117 -57
  2. package/node_modules/cookie/package.json +3 -3
  3. package/node_modules/express/History.md +5 -0
  4. package/node_modules/express/package.json +2 -2
  5. package/node_modules/yaml/README.md +17 -3
  6. package/node_modules/yaml/browser/dist/compose/compose-doc.js +1 -0
  7. package/node_modules/yaml/browser/dist/compose/compose-node.js +10 -0
  8. package/node_modules/yaml/browser/dist/compose/compose-scalar.js +14 -8
  9. package/node_modules/yaml/browser/dist/compose/resolve-block-map.js +2 -0
  10. package/node_modules/yaml/browser/dist/compose/resolve-block-seq.js +2 -0
  11. package/node_modules/yaml/browser/dist/compose/resolve-flow-collection.js +4 -0
  12. package/node_modules/yaml/browser/dist/compose/util-map-includes.js +1 -5
  13. package/node_modules/yaml/browser/dist/doc/Document.js +3 -2
  14. package/node_modules/yaml/browser/dist/nodes/addPairToJSMap.js +7 -49
  15. package/node_modules/yaml/browser/dist/public-api.js +3 -0
  16. package/node_modules/yaml/browser/dist/schema/Schema.js +1 -2
  17. package/node_modules/yaml/browser/dist/schema/tags.js +26 -13
  18. package/node_modules/yaml/browser/dist/schema/yaml-1.1/merge.js +64 -0
  19. package/node_modules/yaml/browser/dist/schema/yaml-1.1/schema.js +2 -0
  20. package/node_modules/yaml/browser/dist/stringify/stringify.js +6 -1
  21. package/node_modules/yaml/dist/compose/compose-doc.js +1 -0
  22. package/node_modules/yaml/dist/compose/compose-node.d.ts +1 -0
  23. package/node_modules/yaml/dist/compose/compose-node.js +10 -0
  24. package/node_modules/yaml/dist/compose/compose-scalar.js +13 -7
  25. package/node_modules/yaml/dist/compose/resolve-block-map.js +2 -0
  26. package/node_modules/yaml/dist/compose/resolve-block-seq.js +2 -0
  27. package/node_modules/yaml/dist/compose/resolve-flow-collection.js +4 -0
  28. package/node_modules/yaml/dist/compose/util-map-includes.js +1 -5
  29. package/node_modules/yaml/dist/doc/Document.js +3 -2
  30. package/node_modules/yaml/dist/errors.d.ts +1 -1
  31. package/node_modules/yaml/dist/nodes/Node.d.ts +7 -1
  32. package/node_modules/yaml/dist/nodes/addPairToJSMap.js +6 -48
  33. package/node_modules/yaml/dist/options.d.ts +6 -0
  34. package/node_modules/yaml/dist/parse/lexer.d.ts +1 -1
  35. package/node_modules/yaml/dist/parse/parser.d.ts +3 -3
  36. package/node_modules/yaml/dist/public-api.js +3 -0
  37. package/node_modules/yaml/dist/schema/Schema.d.ts +0 -1
  38. package/node_modules/yaml/dist/schema/Schema.js +1 -2
  39. package/node_modules/yaml/dist/schema/tags.d.ts +9 -1
  40. package/node_modules/yaml/dist/schema/tags.js +26 -13
  41. package/node_modules/yaml/dist/schema/types.d.ts +6 -4
  42. package/node_modules/yaml/dist/schema/yaml-1.1/merge.d.ts +9 -0
  43. package/node_modules/yaml/dist/schema/yaml-1.1/merge.js +68 -0
  44. package/node_modules/yaml/dist/schema/yaml-1.1/schema.js +2 -0
  45. package/node_modules/yaml/dist/stringify/stringify.js +6 -1
  46. package/node_modules/yaml/package.json +1 -1
  47. package/package.json +1 -1
  48. package/node_modules/cookie/HISTORY.md +0 -147
@@ -23,14 +23,66 @@ exports.serialize = serialize;
23
23
  var __toString = Object.prototype.toString
24
24
 
25
25
  /**
26
- * RegExp to match field-content in RFC 7230 sec 3.2
26
+ * RegExp to match cookie-name in RFC 6265 sec 4.1.1
27
+ * This refers out to the obsoleted definition of token in RFC 2616 sec 2.2
28
+ * which has been replaced by the token definition in RFC 7230 appendix B.
27
29
  *
28
- * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
29
- * field-vchar = VCHAR / obs-text
30
- * obs-text = %x80-FF
30
+ * cookie-name = token
31
+ * token = 1*tchar
32
+ * tchar = "!" / "#" / "$" / "%" / "&" / "'" /
33
+ * "*" / "+" / "-" / "." / "^" / "_" /
34
+ * "`" / "|" / "~" / DIGIT / ALPHA
31
35
  */
32
36
 
33
- var fieldContentRegExp = /^[\u0009\u0020-\u007e\u0080-\u00ff]+$/;
37
+ var cookieNameRegExp = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
38
+
39
+ /**
40
+ * RegExp to match cookie-value in RFC 6265 sec 4.1.1
41
+ *
42
+ * cookie-value = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE )
43
+ * cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
44
+ * ; US-ASCII characters excluding CTLs,
45
+ * ; whitespace DQUOTE, comma, semicolon,
46
+ * ; and backslash
47
+ */
48
+
49
+ var cookieValueRegExp = /^("?)[\u0021\u0023-\u002B\u002D-\u003A\u003C-\u005B\u005D-\u007E]*\1$/;
50
+
51
+ /**
52
+ * RegExp to match domain-value in RFC 6265 sec 4.1.1
53
+ *
54
+ * domain-value = <subdomain>
55
+ * ; defined in [RFC1034], Section 3.5, as
56
+ * ; enhanced by [RFC1123], Section 2.1
57
+ * <subdomain> = <label> | <subdomain> "." <label>
58
+ * <label> = <let-dig> [ [ <ldh-str> ] <let-dig> ]
59
+ * Labels must be 63 characters or less.
60
+ * 'let-dig' not 'letter' in the first char, per RFC1123
61
+ * <ldh-str> = <let-dig-hyp> | <let-dig-hyp> <ldh-str>
62
+ * <let-dig-hyp> = <let-dig> | "-"
63
+ * <let-dig> = <letter> | <digit>
64
+ * <letter> = any one of the 52 alphabetic characters A through Z in
65
+ * upper case and a through z in lower case
66
+ * <digit> = any one of the ten digits 0 through 9
67
+ *
68
+ * Keep support for leading dot: https://github.com/jshttp/cookie/issues/173
69
+ *
70
+ * > (Note that a leading %x2E ("."), if present, is ignored even though that
71
+ * character is not permitted, but a trailing %x2E ("."), if present, will
72
+ * cause the user agent to ignore the attribute.)
73
+ */
74
+
75
+ var domainValueRegExp = /^([.]?[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)([.][a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)*$/i;
76
+
77
+ /**
78
+ * RegExp to match path-value in RFC 6265 sec 4.1.1
79
+ *
80
+ * path-value = <any CHAR except CTLs or ";">
81
+ * CHAR = %x01-7F
82
+ * ; defined in RFC 5234 appendix B.1
83
+ */
84
+
85
+ var pathValueRegExp = /^[\u0020-\u003A\u003D-\u007E]*$/;
34
86
 
35
87
  /**
36
88
  * Parse a cookie header.
@@ -39,107 +91,128 @@ var fieldContentRegExp = /^[\u0009\u0020-\u007e\u0080-\u00ff]+$/;
39
91
  * The object has the various cookies as keys(names) => values
40
92
  *
41
93
  * @param {string} str
42
- * @param {object} [options]
94
+ * @param {object} [opt]
43
95
  * @return {object}
44
96
  * @public
45
97
  */
46
98
 
47
- function parse(str, options) {
99
+ function parse(str, opt) {
48
100
  if (typeof str !== 'string') {
49
101
  throw new TypeError('argument str must be a string');
50
102
  }
51
103
 
52
- var obj = {}
53
- var opt = options || {};
54
- var dec = opt.decode || decode;
104
+ var obj = {};
105
+ var len = str.length;
106
+ // RFC 6265 sec 4.1.1, RFC 2616 2.2 defines a cookie name consists of one char minimum, plus '='.
107
+ if (len < 2) return obj;
55
108
 
56
- var index = 0
57
- while (index < str.length) {
58
- var eqIdx = str.indexOf('=', index)
109
+ var dec = (opt && opt.decode) || decode;
110
+ var index = 0;
111
+ var eqIdx = 0;
112
+ var endIdx = 0;
59
113
 
60
- // no more cookie pairs
61
- if (eqIdx === -1) {
62
- break
63
- }
114
+ do {
115
+ eqIdx = str.indexOf('=', index);
116
+ if (eqIdx === -1) break; // No more cookie pairs.
64
117
 
65
- var endIdx = str.indexOf(';', index)
118
+ endIdx = str.indexOf(';', index);
66
119
 
67
120
  if (endIdx === -1) {
68
- endIdx = str.length
69
- } else if (endIdx < eqIdx) {
121
+ endIdx = len;
122
+ } else if (eqIdx > endIdx) {
70
123
  // backtrack on prior semicolon
71
- index = str.lastIndexOf(';', eqIdx - 1) + 1
72
- continue
124
+ index = str.lastIndexOf(';', eqIdx - 1) + 1;
125
+ continue;
73
126
  }
74
127
 
75
- var key = str.slice(index, eqIdx).trim()
128
+ var keyStartIdx = startIndex(str, index, eqIdx);
129
+ var keyEndIdx = endIndex(str, eqIdx, keyStartIdx);
130
+ var key = str.slice(keyStartIdx, keyEndIdx);
76
131
 
77
132
  // only assign once
78
- if (undefined === obj[key]) {
79
- var val = str.slice(eqIdx + 1, endIdx).trim()
133
+ if (!obj.hasOwnProperty(key)) {
134
+ var valStartIdx = startIndex(str, eqIdx + 1, endIdx);
135
+ var valEndIdx = endIndex(str, endIdx, valStartIdx);
80
136
 
81
- // quoted values
82
- if (val.charCodeAt(0) === 0x22) {
83
- val = val.slice(1, -1)
137
+ if (str.charCodeAt(valStartIdx) === 0x22 /* " */ && str.charCodeAt(valEndIdx - 1) === 0x22 /* " */) {
138
+ valStartIdx++;
139
+ valEndIdx--;
84
140
  }
85
141
 
142
+ var val = str.slice(valStartIdx, valEndIdx);
86
143
  obj[key] = tryDecode(val, dec);
87
144
  }
88
145
 
89
146
  index = endIdx + 1
90
- }
147
+ } while (index < len);
91
148
 
92
149
  return obj;
93
150
  }
94
151
 
152
+ function startIndex(str, index, max) {
153
+ do {
154
+ var code = str.charCodeAt(index);
155
+ if (code !== 0x20 /* */ && code !== 0x09 /* \t */) return index;
156
+ } while (++index < max);
157
+ return max;
158
+ }
159
+
160
+ function endIndex(str, index, min) {
161
+ while (index > min) {
162
+ var code = str.charCodeAt(--index);
163
+ if (code !== 0x20 /* */ && code !== 0x09 /* \t */) return index + 1;
164
+ }
165
+ return min;
166
+ }
167
+
95
168
  /**
96
169
  * Serialize data into a cookie header.
97
170
  *
98
- * Serialize the a name value pair into a cookie string suitable for
99
- * http headers. An optional options object specified cookie parameters.
171
+ * Serialize a name value pair into a cookie string suitable for
172
+ * http headers. An optional options object specifies cookie parameters.
100
173
  *
101
174
  * serialize('foo', 'bar', { httpOnly: true })
102
175
  * => "foo=bar; httpOnly"
103
176
  *
104
177
  * @param {string} name
105
178
  * @param {string} val
106
- * @param {object} [options]
179
+ * @param {object} [opt]
107
180
  * @return {string}
108
181
  * @public
109
182
  */
110
183
 
111
- function serialize(name, val, options) {
112
- var opt = options || {};
113
- var enc = opt.encode || encode;
184
+ function serialize(name, val, opt) {
185
+ var enc = (opt && opt.encode) || encodeURIComponent;
114
186
 
115
187
  if (typeof enc !== 'function') {
116
188
  throw new TypeError('option encode is invalid');
117
189
  }
118
190
 
119
- if (!fieldContentRegExp.test(name)) {
191
+ if (!cookieNameRegExp.test(name)) {
120
192
  throw new TypeError('argument name is invalid');
121
193
  }
122
194
 
123
195
  var value = enc(val);
124
196
 
125
- if (value && !fieldContentRegExp.test(value)) {
197
+ if (!cookieValueRegExp.test(value)) {
126
198
  throw new TypeError('argument val is invalid');
127
199
  }
128
200
 
129
201
  var str = name + '=' + value;
202
+ if (!opt) return str;
130
203
 
131
204
  if (null != opt.maxAge) {
132
- var maxAge = opt.maxAge - 0;
205
+ var maxAge = Math.floor(opt.maxAge);
133
206
 
134
- if (isNaN(maxAge) || !isFinite(maxAge)) {
207
+ if (!isFinite(maxAge)) {
135
208
  throw new TypeError('option maxAge is invalid')
136
209
  }
137
210
 
138
- str += '; Max-Age=' + Math.floor(maxAge);
211
+ str += '; Max-Age=' + maxAge;
139
212
  }
140
213
 
141
214
  if (opt.domain) {
142
- if (!fieldContentRegExp.test(opt.domain)) {
215
+ if (!domainValueRegExp.test(opt.domain)) {
143
216
  throw new TypeError('option domain is invalid');
144
217
  }
145
218
 
@@ -147,7 +220,7 @@ function serialize(name, val, options) {
147
220
  }
148
221
 
149
222
  if (opt.path) {
150
- if (!fieldContentRegExp.test(opt.path)) {
223
+ if (!pathValueRegExp.test(opt.path)) {
151
224
  throw new TypeError('option path is invalid');
152
225
  }
153
226
 
@@ -178,8 +251,7 @@ function serialize(name, val, options) {
178
251
 
179
252
  if (opt.priority) {
180
253
  var priority = typeof opt.priority === 'string'
181
- ? opt.priority.toLowerCase()
182
- : opt.priority
254
+ ? opt.priority.toLowerCase() : opt.priority;
183
255
 
184
256
  switch (priority) {
185
257
  case 'low':
@@ -234,17 +306,6 @@ function decode (str) {
234
306
  : str
235
307
  }
236
308
 
237
- /**
238
- * URL-encode value.
239
- *
240
- * @param {string} val
241
- * @returns {string}
242
- */
243
-
244
- function encode (val) {
245
- return encodeURIComponent(val)
246
- }
247
-
248
309
  /**
249
310
  * Determine if value is a Date.
250
311
  *
@@ -253,8 +314,7 @@ function encode (val) {
253
314
  */
254
315
 
255
316
  function isDate (val) {
256
- return __toString.call(val) === '[object Date]' ||
257
- val instanceof Date
317
+ return __toString.call(val) === '[object Date]';
258
318
  }
259
319
 
260
320
  /**
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "cookie",
3
3
  "description": "HTTP server cookie parsing and serialization",
4
- "version": "0.6.0",
4
+ "version": "0.7.1",
5
5
  "author": "Roman Shtylman <shtylman@gmail.com>",
6
6
  "contributors": [
7
7
  "Douglas Christopher Wilson <doug@somethingdoug.com>"
@@ -29,6 +29,7 @@
29
29
  "SECURITY.md",
30
30
  "index.js"
31
31
  ],
32
+ "main": "index.js",
32
33
  "engines": {
33
34
  "node": ">= 0.6"
34
35
  },
@@ -38,7 +39,6 @@
38
39
  "test": "mocha --reporter spec --bail --check-leaks test/",
39
40
  "test-ci": "nyc --reporter=lcov --reporter=text npm test",
40
41
  "test-cov": "nyc --reporter=html --reporter=text npm test",
41
- "update-bench": "node scripts/update-benchmark.js",
42
- "version": "node scripts/version-history.js && git add HISTORY.md"
42
+ "update-bench": "node scripts/update-benchmark.js"
43
43
  }
44
44
  }
@@ -1,3 +1,8 @@
1
+ 4.21.1 / 2024-10-08
2
+ ==========
3
+
4
+ * Backported a fix for [CVE-2024-47764](https://nvd.nist.gov/vuln/detail/CVE-2024-47764)
5
+
1
6
  4.21.0 / 2024-09-11
2
7
  ==========
3
8
 
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "express",
3
3
  "description": "Fast, unopinionated, minimalist web framework",
4
- "version": "4.21.0",
4
+ "version": "4.21.1",
5
5
  "author": "TJ Holowaychuk <tj@vision-media.ca>",
6
6
  "contributors": [
7
7
  "Aaron Heckmann <aaron.heckmann+github@gmail.com>",
@@ -33,7 +33,7 @@
33
33
  "body-parser": "1.20.3",
34
34
  "content-disposition": "0.5.4",
35
35
  "content-type": "~1.0.4",
36
- "cookie": "0.6.0",
36
+ "cookie": "0.7.1",
37
37
  "cookie-signature": "1.0.6",
38
38
  "debug": "2.6.9",
39
39
  "depd": "2.0.0",
@@ -30,9 +30,23 @@ npm install yaml
30
30
 
31
31
  The development and maintenance of this library is [sponsored](https://github.com/sponsors/eemeli) by:
32
32
 
33
- <a href="https://www.scipress.io/">
34
- <img width=150 src="https://eemeli.org/yaml/images/scipress.svg" alt="Scipress" />
35
- </a>
33
+ <p align="center" width="100%">
34
+ <a href="https://www.scipress.io/"
35
+ ><img
36
+ width="150"
37
+ align="top"
38
+ src="https://eemeli.org/yaml/images/scipress.svg"
39
+ alt="Scipress"
40
+ /></a>
41
+ &nbsp; &nbsp;
42
+ <a href="https://manifest.build/"
43
+ ><img
44
+ width="150"
45
+ align="top"
46
+ src="https://eemeli.org/yaml/images/manifest.svg"
47
+ alt="Manifest"
48
+ /></a>
49
+ </p>
36
50
 
37
51
  ## API Overview
38
52
 
@@ -7,6 +7,7 @@ function composeDoc(options, directives, { offset, start, value, end }, onError)
7
7
  const opts = Object.assign({ _directives: directives }, options);
8
8
  const doc = new Document(undefined, opts);
9
9
  const ctx = {
10
+ atKey: false,
10
11
  atRoot: true,
11
12
  directives: doc.directives,
12
13
  options: doc.options,
@@ -1,4 +1,5 @@
1
1
  import { Alias } from '../nodes/Alias.js';
2
+ import { isScalar } from '../nodes/identity.js';
2
3
  import { composeCollection } from './compose-collection.js';
3
4
  import { composeScalar } from './compose-scalar.js';
4
5
  import { resolveEnd } from './resolve-end.js';
@@ -6,6 +7,7 @@ import { emptyScalarPosition } from './util-empty-scalar-position.js';
6
7
 
7
8
  const CN = { composeNode, composeEmptyNode };
8
9
  function composeNode(ctx, token, props, onError) {
10
+ const atKey = ctx.atKey;
9
11
  const { spaceBefore, comment, anchor, tag } = props;
10
12
  let node;
11
13
  let isSrcToken = true;
@@ -41,6 +43,14 @@ function composeNode(ctx, token, props, onError) {
41
43
  }
42
44
  if (anchor && node.anchor === '')
43
45
  onError(anchor, 'BAD_ALIAS', 'Anchor cannot be an empty string');
46
+ if (atKey &&
47
+ ctx.options.stringKeys &&
48
+ (!isScalar(node) ||
49
+ typeof node.value !== 'string' ||
50
+ (node.tag && node.tag !== 'tag:yaml.org,2002:str'))) {
51
+ const msg = 'With stringKeys, all keys must be strings';
52
+ onError(tag ?? token, 'NON_STRING_KEY', msg);
53
+ }
44
54
  if (spaceBefore)
45
55
  node.spaceBefore = true;
46
56
  if (comment) {
@@ -1,4 +1,4 @@
1
- import { SCALAR, isScalar } from '../nodes/identity.js';
1
+ import { isScalar, SCALAR } from '../nodes/identity.js';
2
2
  import { Scalar } from '../nodes/Scalar.js';
3
3
  import { resolveBlockScalar } from './resolve-block-scalar.js';
4
4
  import { resolveFlowScalar } from './resolve-flow-scalar.js';
@@ -10,11 +10,16 @@ function composeScalar(ctx, token, tagToken, onError) {
10
10
  const tagName = tagToken
11
11
  ? ctx.directives.tagName(tagToken.source, msg => onError(tagToken, 'TAG_RESOLVE_FAILED', msg))
12
12
  : null;
13
- const tag = tagToken && tagName
14
- ? findScalarTagByName(ctx.schema, value, tagName, tagToken, onError)
15
- : token.type === 'scalar'
16
- ? findScalarTagByTest(ctx, value, token, onError)
17
- : ctx.schema[SCALAR];
13
+ let tag;
14
+ if (ctx.options.stringKeys && ctx.atKey) {
15
+ tag = ctx.schema[SCALAR];
16
+ }
17
+ else if (tagName)
18
+ tag = findScalarTagByName(ctx.schema, value, tagName, tagToken, onError);
19
+ else if (token.type === 'scalar')
20
+ tag = findScalarTagByTest(ctx, value, token, onError);
21
+ else
22
+ tag = ctx.schema[SCALAR];
18
23
  let scalar;
19
24
  try {
20
25
  const res = tag.resolve(value, msg => onError(tagToken ?? token, 'TAG_RESOLVE_FAILED', msg), ctx.options);
@@ -62,8 +67,9 @@ function findScalarTagByName(schema, value, tagName, tagToken, onError) {
62
67
  onError(tagToken, 'TAG_RESOLVE_FAILED', `Unresolved tag: ${tagName}`, tagName !== 'tag:yaml.org,2002:str');
63
68
  return schema[SCALAR];
64
69
  }
65
- function findScalarTagByTest({ directives, schema }, value, token, onError) {
66
- const tag = schema.tags.find(tag => tag.default && tag.test?.test(value)) || schema[SCALAR];
70
+ function findScalarTagByTest({ atKey, directives, schema }, value, token, onError) {
71
+ const tag = schema.tags.find(tag => (tag.default === true || (atKey && tag.default === 'key')) &&
72
+ tag.test?.test(value)) || schema[SCALAR];
67
73
  if (schema.compat) {
68
74
  const compat = schema.compat.find(tag => tag.default && tag.test?.test(value)) ??
69
75
  schema[SCALAR];
@@ -50,12 +50,14 @@ function resolveBlockMap({ composeNode, composeEmptyNode }, ctx, bm, onError, ta
50
50
  onError(offset, 'BAD_INDENT', startColMsg);
51
51
  }
52
52
  // key value
53
+ ctx.atKey = true;
53
54
  const keyStart = keyProps.end;
54
55
  const keyNode = key
55
56
  ? composeNode(ctx, key, keyProps, onError)
56
57
  : composeEmptyNode(ctx, keyStart, start, null, keyProps, onError);
57
58
  if (ctx.schema.compat)
58
59
  flowIndentCheck(bm.indent, key, onError);
60
+ ctx.atKey = false;
59
61
  if (mapIncludes(ctx, map.items, keyNode))
60
62
  onError(keyStart, 'DUPLICATE_KEY', 'Map keys must be unique');
61
63
  // value properties
@@ -7,6 +7,8 @@ function resolveBlockSeq({ composeNode, composeEmptyNode }, ctx, bs, onError, ta
7
7
  const seq = new NodeClass(ctx.schema);
8
8
  if (ctx.atRoot)
9
9
  ctx.atRoot = false;
10
+ if (ctx.atKey)
11
+ ctx.atKey = false;
10
12
  let offset = bs.offset;
11
13
  let commentEnd = null;
12
14
  for (const { start, value } of bs.items) {
@@ -18,6 +18,8 @@ function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onErr
18
18
  const atRoot = ctx.atRoot;
19
19
  if (atRoot)
20
20
  ctx.atRoot = false;
21
+ if (ctx.atKey)
22
+ ctx.atKey = false;
21
23
  let offset = fc.offset + fc.start.source.length;
22
24
  for (let i = 0; i < fc.items.length; ++i) {
23
25
  const collItem = fc.items[i];
@@ -97,12 +99,14 @@ function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onErr
97
99
  else {
98
100
  // item is a key+value pair
99
101
  // key value
102
+ ctx.atKey = true;
100
103
  const keyStart = props.end;
101
104
  const keyNode = key
102
105
  ? composeNode(ctx, key, props, onError)
103
106
  : composeEmptyNode(ctx, keyStart, start, null, props, onError);
104
107
  if (isBlock(key))
105
108
  onError(keyNode.range, 'BLOCK_IN_FLOW', blockMsg);
109
+ ctx.atKey = false;
106
110
  // value properties
107
111
  const valueProps = resolveProps(sep ?? [], {
108
112
  flow: fcName,
@@ -6,11 +6,7 @@ function mapIncludes(ctx, items, search) {
6
6
  return false;
7
7
  const isEqual = typeof uniqueKeys === 'function'
8
8
  ? uniqueKeys
9
- : (a, b) => a === b ||
10
- (isScalar(a) &&
11
- isScalar(b) &&
12
- a.value === b.value &&
13
- !(a.value === '<<' && ctx.schema.merge));
9
+ : (a, b) => a === b || (isScalar(a) && isScalar(b) && a.value === b.value);
14
10
  return items.some(pair => isEqual(pair.key, search));
15
11
  }
16
12
 
@@ -35,6 +35,7 @@ class Document {
35
35
  logLevel: 'warn',
36
36
  prettyErrors: true,
37
37
  strict: true,
38
+ stringKeys: false,
38
39
  uniqueKeys: true,
39
40
  version: '1.2'
40
41
  }, options);
@@ -258,7 +259,7 @@ class Document {
258
259
  this.directives.yaml.version = '1.1';
259
260
  else
260
261
  this.directives = new Directives({ version: '1.1' });
261
- opt = { merge: true, resolveKnownTags: false, schema: 'yaml-1.1' };
262
+ opt = { resolveKnownTags: false, schema: 'yaml-1.1' };
262
263
  break;
263
264
  case '1.2':
264
265
  case 'next':
@@ -266,7 +267,7 @@ class Document {
266
267
  this.directives.yaml.version = version;
267
268
  else
268
269
  this.directives = new Directives({ version });
269
- opt = { merge: false, resolveKnownTags: true, schema: 'core' };
270
+ opt = { resolveKnownTags: true, schema: 'core' };
270
271
  break;
271
272
  case null:
272
273
  if (this.directives)
@@ -1,22 +1,15 @@
1
1
  import { warn } from '../log.js';
2
+ import { isMergeKey, addMergeToJSMap } from '../schema/yaml-1.1/merge.js';
2
3
  import { createStringifyContext } from '../stringify/stringify.js';
3
- import { isAlias, isSeq, isScalar, isMap, isNode } from './identity.js';
4
- import { Scalar } from './Scalar.js';
4
+ import { isNode } from './identity.js';
5
5
  import { toJS } from './toJS.js';
6
6
 
7
- const MERGE_KEY = '<<';
8
7
  function addPairToJSMap(ctx, map, { key, value }) {
9
- if (ctx?.doc.schema.merge && isMergeKey(key)) {
10
- value = isAlias(value) ? value.resolve(ctx.doc) : value;
11
- if (isSeq(value))
12
- for (const it of value.items)
13
- mergeToJSMap(ctx, map, it);
14
- else if (Array.isArray(value))
15
- for (const it of value)
16
- mergeToJSMap(ctx, map, it);
17
- else
18
- mergeToJSMap(ctx, map, value);
19
- }
8
+ if (isNode(key) && key.addToJSMap)
9
+ key.addToJSMap(ctx, map, value);
10
+ // TODO: Should drop this special case for bare << handling
11
+ else if (isMergeKey(ctx, key))
12
+ addMergeToJSMap(ctx, map, value);
20
13
  else {
21
14
  const jsKey = toJS(key, '', ctx);
22
15
  if (map instanceof Map) {
@@ -41,41 +34,6 @@ function addPairToJSMap(ctx, map, { key, value }) {
41
34
  }
42
35
  return map;
43
36
  }
44
- const isMergeKey = (key) => key === MERGE_KEY ||
45
- (isScalar(key) &&
46
- key.value === MERGE_KEY &&
47
- (!key.type || key.type === Scalar.PLAIN));
48
- // If the value associated with a merge key is a single mapping node, each of
49
- // its key/value pairs is inserted into the current mapping, unless the key
50
- // already exists in it. If the value associated with the merge key is a
51
- // sequence, then this sequence is expected to contain mapping nodes and each
52
- // of these nodes is merged in turn according to its order in the sequence.
53
- // Keys in mapping nodes earlier in the sequence override keys specified in
54
- // later mapping nodes. -- http://yaml.org/type/merge.html
55
- function mergeToJSMap(ctx, map, value) {
56
- const source = ctx && isAlias(value) ? value.resolve(ctx.doc) : value;
57
- if (!isMap(source))
58
- throw new Error('Merge sources must be maps or map aliases');
59
- const srcMap = source.toJSON(null, ctx, Map);
60
- for (const [key, value] of srcMap) {
61
- if (map instanceof Map) {
62
- if (!map.has(key))
63
- map.set(key, value);
64
- }
65
- else if (map instanceof Set) {
66
- map.add(key);
67
- }
68
- else if (!Object.prototype.hasOwnProperty.call(map, key)) {
69
- Object.defineProperty(map, key, {
70
- value,
71
- writable: true,
72
- enumerable: true,
73
- configurable: true
74
- });
75
- }
76
- }
77
- return map;
78
- }
79
37
  function stringifyKey(key, jsKey, ctx) {
80
38
  if (jsKey === null)
81
39
  return '';
@@ -2,6 +2,7 @@ import { Composer } from './compose/composer.js';
2
2
  import { Document } from './doc/Document.js';
3
3
  import { prettifyError, YAMLParseError } from './errors.js';
4
4
  import { warn } from './log.js';
5
+ import { isDocument } from './nodes/identity.js';
5
6
  import { LineCounter } from './parse/line-counter.js';
6
7
  import { Parser } from './parse/parser.js';
7
8
 
@@ -93,6 +94,8 @@ function stringify(value, replacer, options) {
93
94
  if (!keepUndefined)
94
95
  return undefined;
95
96
  }
97
+ if (isDocument(value) && !_replacer)
98
+ return value.toString(options);
96
99
  return new Document(value, _replacer, options).toString(options);
97
100
  }
98
101
 
@@ -12,10 +12,9 @@ class Schema {
12
12
  : compat
13
13
  ? getTags(null, compat)
14
14
  : null;
15
- this.merge = !!merge;
16
15
  this.name = (typeof schema === 'string' && schema) || 'core';
17
16
  this.knownTags = resolveKnownTags ? coreKnownTags : {};
18
- this.tags = getTags(customTags, this.name);
17
+ this.tags = getTags(customTags, this.name, merge);
19
18
  this.toStringOptions = toStringDefaults ?? null;
20
19
  Object.defineProperty(this, MAP, { value: map });
21
20
  Object.defineProperty(this, SCALAR, { value: string });