Skip to content

Quote a root block mapping key that reads as a document marker, #805 - #806

Open
MFA-G wants to merge 1 commit into
nodeca:masterfrom
MFA-G:fix/dump-root-key-document-marker
Open

MFA-G wants to merge 1 commit into
nodeca:masterfrom
MFA-G:fix/dump-root-key-document-marker

Conversation

@MFA-G

@MFA-G MFA-G commented Nov 3, 2026

Copy link
Copy Markdown

Summary

dump() wrote a root-level block mapping key that starts with --- or
... as a plain scalar at column 0, where those prefixes are document
boundary markers. The result either fails to reload or reloads with the key
silently changed:

dump({ '... x': 1 })   // "... x: 1\n"   -> load -> { x: 1 }
dump({ '--- x': 1 })   // "--- x: 1\n"   -> load throws

Cause

scalarLayout() derives shiftOfFirstLine from the scalar's level.
writeBlockMapping() passes level + 1 for a key, because the key scalar is
one level deeper in the AST, but writes the key on the mapping's own line. At
the document root the key really starts at column 0 while the layout reports
indent * 1 = 2, and canUsePlain() only applies the c-forbidden guard when
shiftOfFirstLine === 0. The guard therefore never fired for keys.

For a block-context key, report the mapping's indentation
(indent * (level - 1)) as the first-line shift. Flow keys keep the old
value: they always follow { or , and cannot start a line.

Result

dump({ '... x': 1 })                  // "'... x': 1\n"
dump({ '--- x': 1 })                  // "'--- x': 1\n"
dump({ a: { '... x': 1 } })           // "a:\n  ... x: 1\n"   (unchanged)
dump([{ '... x': 1 }])                // "- ... x: 1\n"       (unchanged)

Only content that is actually written at column 0 is quoted, so nested and
sequence-item keys stay plain. The diff-summary example from the report
(--- a/src/gateway/server.ts, ... 2 files omitted) now round-trips too.

Tests

Added quotes a root block mapping key that would read as a document marker
to test/core/units/dump-scalar-styles.test.mjs; it asserts the dumped text
and the reloaded value for --- x, ... x, ---, ..., indent: 4, and
that nested and sequence-item keys stay plain. The new test fails on the
current master and passes with the change.

npm test (lint, build, tsc --noEmit, yaml-test-suite, core tests):
1647 tests, 1634 pass, 0 fail, 13 skipped.

Fixes #805.

A block mapping key is written on its mapping's line, so `scalarLayout()`
saw it one level deeper than it really is and never applied the
c-forbidden guard. At the document root the key starts at column 0, so a
key beginning with `--- ` or `... ` was dumped unquoted: reloading either
failed (`--- x: 1`) or silently changed the key (`... x: 1` -> `x`).

Report the mapping's indentation as the key's first-line shift, and add a
regression test for root, nested and sequence-item keys, nodeca#805.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

dump(): block mapping keys starting with ... or --- are emitted unquoted and silently corrupt on reload

1 participant