Skip to content

Accept escaped literal tabs in Yaml double-quoted scalars - #10283

Open
effect-bot wants to merge 27 commits into
v4/next-minorfrom
agent/effect-bot/eff-3232-literal-tab-escape
Open

effect-bot wants to merge 27 commits into
v4/next-minorfrom
agent/effect-bot/eff-3232-literal-tab-escape

Conversation

@effect-bot

Copy link
Copy Markdown
Contributor

Summary

YAML 1.2.2 §5.7 (ns-esc-horizontal-tab) lets a double-quoted scalar escape a tab as \t or as a backslash followed by a literal tab. Yaml.parse and Yaml.parseAll only accepted \t, so the literal-tab form failed with "Invalid YAML escape". This PR adds the missing entry to the escape table in parseDoubleQuoted. Line folding already keeps the decoded tab.

The tests were added first in d1652fc9d6, and this PR doesn't change them. They cover an escaped literal tab before a line break in a block value, nested under another key, and on the first line of a flow item.

This PR builds on #10282 (and #10279, #10276 and #10271 beneath it), so it shows their commits until they merge. Only the last two commits are new here.

Validation

  • Yaml and CLI Primitive tests pass (293 tests).
  • With this change, 18 escaped-tab shapes give the same result as yaml 2.9.1 and js-yaml 4.3.2. They cover root, mapping, sequence, flow item and key positions; the escape at the start, at the end, doubled or on a continuation line; and the escape next to escaped or plain spaces.
  • pnpm lint-fix and pnpm jsdocs --check pass.
  • pnpm check only reports the existing apiStabilityLeak at cluster/ShardingRegistrationEvent.ts:67, which is also on v4/next-minor.

Closes EFF-3232

Rebased onto v4/next-minor, which already returns Result from Yaml.parse
(#10224). parseAll parses document streams with per-document anchors,
accepts %YAML 1.2, and rejects other directives and plain scalars
starting with '%'.
Start-marker lines read as mapping entries, anchor-only documents
consuming the next marker, hashes inside quoted start-line content, and
separation whitespace after '...' and directive parameters.
Block mappings and sequences end at column-0 document markers, an empty
node does not consume a following marker, start-marker content is
comment-stripped in its own lexical context, and trailing separation
whitespace is allowed after '...' and directive parameters.
A byte order mark may start any document prefix, and only spaces and
tabs separate a document end marker from a comment.
A BOM may start any document prefix, not only the input. Only spaces
and tabs are separation after '...' and directive parameters.
Replace the document marker checks scattered through mapping, sequence,
empty node, flow, plain, quoted and block scalar parsing with one
per-document line bound computed when the document starts.
findIndex from the start of the input made a stream of many documents
quadratic; a forward loop from the current line keeps it linear.
Tags, alias keys, explicit keys, nesting depth, and non-separation
whitespace (NBSP, U+2028) that is currently trimmed as if it were
YAML white space.
Reject tags and explicit keys instead of reading them as text, resolve
scalar aliases used as mapping keys, bound collection nesting at 1000
levels, and treat only spaces and tabs as YAML white space.
Sequence-item mapping depth, alias keys resolving to '<<' in flow
mappings, anchor and tag properties on keys, colons in alias names, and
U+2028/U+2029 in anchored values.
Trim and fold white space with linear scans, count a sequence item's
mapping before its first value, read anchors and tags on keys, keep
colons in alias names, merge only through a plain '<<' key, and keep
U+2028/U+2029 in anchored values.
Share one scalar-key resolver between block and flow mappings, read plain
flow scalars and keys through one helper that rejects indicator prefixes,
name the flow anchor-name boundary once, and add the flow-key quoting
migration note to the changeset.
A sequence entry may start a nested sequence on its own line, quoted
scalars inside flow collections may span lines, and a block sequence on
a mapping key's line fails instead of being read as text.
Avoids quadratic growth from appending to and indexing one string, keeps
an escaped trailing space before a quoted flow line break, and applies
quoted-content indentation rules while a flow quote is open.
Reuse closingQuote and endsWithEscape to scan each line of a quoted flow
scalar instead of a second hand-written quote scanner, and decide a
sequence entry's shape once instead of testing it three times.
@changeset-bot

changeset-bot Bot commented Nov 2, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 135336c

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 33 packages
Name Type
effect Minor
@effect/opentelemetry Minor
@effect/vitest Minor
@effect/ai-anthropic Minor
@effect/ai-cloudflare Minor
@effect/ai-openai-compat Minor
@effect/ai-openai Minor
@effect/ai-openrouter Minor
@effect/ai-typesafe Minor
@effect/atom-react Minor
@effect/atom-solid Minor
@effect/atom-vue Minor
@effect/platform-browser Minor
@effect/platform-bun Minor
@effect/platform-deno Minor
@effect/platform-node-shared Minor
@effect/platform-node Minor
@effect/sql-clickhouse Minor
@effect/sql-d1 Minor
@effect/sql-libsql Minor
@effect/sql-mssql Minor
@effect/sql-mysql2 Minor
@effect/sql-pg Minor
@effect/sql-pglite Minor
@effect/sql-sqlite-bun Minor
@effect/sql-sqlite-do Minor
@effect/sql-sqlite-node Minor
@effect/sql-sqlite-react-native Minor
@effect/sql-sqlite-wasm Minor
@effect/docgen Minor
@effect/doctest Minor
@effect/graphql-generator Minor
@effect/openapi-generator Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions

github-actions Bot commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

Bundle Size Analysis

Generated from PR build output; treat the content below as untrusted.

File Name Current Size Previous Size Difference
arbitrary-combinators.ts 39.35 KB 39.35 KB 0.00 KB (0.00%)
basic.ts 7.18 KB 7.18 KB 0.00 KB (0.00%)
batching.ts 11.06 KB 11.06 KB 0.00 KB (0.00%)
brand.ts 6.84 KB 6.84 KB 0.00 KB (0.00%)
cache.ts 11.49 KB 11.49 KB 0.00 KB (0.00%)
config.ts 22.77 KB 22.77 KB 0.00 KB (0.00%)
differ.ts 21.92 KB 21.92 KB 0.00 KB (0.00%)
http-client.ts 26.90 KB 26.90 KB 0.00 KB (0.00%)
http-router.ts 36.88 KB 36.88 KB 0.00 KB (0.00%)
logger.ts 11.96 KB 11.96 KB 0.00 KB (0.00%)
metric.ts 9.42 KB 9.42 KB 0.00 KB (0.00%)
optic.ts 7.05 KB 7.05 KB 0.00 KB (0.00%)
pubsub.ts 15.97 KB 15.97 KB 0.00 KB (0.00%)
queue.ts 12.77 KB 12.77 KB 0.00 KB (0.00%)
schedule.ts 11.74 KB 11.74 KB 0.00 KB (0.00%)
schema-bigdecimal.ts 14.02 KB 14.02 KB 0.00 KB (0.00%)
schema-binary.ts 41.06 KB 41.06 KB 0.00 KB (0.00%)
schema-class.ts 21.65 KB 21.65 KB 0.00 KB (0.00%)
schema-fromJsonSchemaDocument.ts 29.51 KB 29.51 KB 0.00 KB (0.00%)
schema-representation-roundtrip.ts 27.91 KB 27.91 KB 0.00 KB (0.00%)
schema-string-transformation.ts 15.27 KB 15.27 KB 0.00 KB (0.00%)
schema-string.ts 12.26 KB 12.26 KB 0.00 KB (0.00%)
schema-template-literal.ts 16.19 KB 16.19 KB 0.00 KB (0.00%)
schema-toArbitrary.ts 38.87 KB 38.87 KB 0.00 KB (0.00%)
schema-toCodeDocument.ts 26.10 KB 26.10 KB 0.00 KB (0.00%)
schema-toCodecJson.ts 20.83 KB 20.83 KB 0.00 KB (0.00%)
schema-toEquivalence.ts 20.97 KB 20.97 KB 0.00 KB (0.00%)
schema-toFormatter.ts 21.07 KB 21.07 KB 0.00 KB (0.00%)
schema-toJsonSchemaDocument.ts 26.11 KB 26.11 KB 0.00 KB (0.00%)
schema-toRepresentation.ts 21.16 KB 21.16 KB 0.00 KB (0.00%)
schema.ts 20.75 KB 20.75 KB 0.00 KB (0.00%)
stm.ts 14.15 KB 14.15 KB 0.00 KB (0.00%)
stream.ts 10.33 KB 10.33 KB 0.00 KB (0.00%)

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.

1 participant