mirror of
https://github.com/larvit/adf-codec.git
synced 2026-11-12 11:48:29 +01:00
Answer stability round 1: the escape flags flow through return values, and V8's failed typed-array allocation is refused as its memory running short
This commit is contained in:
@@ -410,9 +410,9 @@ typed on `ConvertError` takes both.
|
||||
|
||||
A call reports the first refusal in document order and stops, so a document with several surfaces
|
||||
them one per call. Every refusal is deterministic — there is no I/O anywhere — so a retry returns
|
||||
the identical error: fix the input, or set the document aside. On JavaScriptCore (Bun, Safari),
|
||||
retry once any call that returns `unsupported-node-shape` at the empty path: that engine reports a
|
||||
heap running short the same way as a string too long to build.
|
||||
the identical error: fix the input, or set the document aside. The exception is memory running
|
||||
short, which an engine may report as `unsupported-node-shape` at the empty path, and JavaScriptCore
|
||||
(Bun, Safari) reports the same way as a string too long to build: retry such a call once.
|
||||
|
||||
### Parsing
|
||||
|
||||
|
||||
@@ -95,8 +95,7 @@ function escape(segments: readonly InlineSegment[], container: LineContainer, cl
|
||||
const code = codes[index]
|
||||
return code === undefined ? undefined : escapingCodes[code]
|
||||
}
|
||||
const escaped = escapeClaims(scan, escapings, container, claims)
|
||||
escapeClosedRuns(scan, escapings, escaped)
|
||||
const escaped = escapeClosedRuns(scan, escapings, escapeClaims(scan, escapings, container, claims))
|
||||
const { output, placements } = backslashed(segments, scan, escaped)
|
||||
if (container === 'paragraph' && opensLinkDefinition(output)) {
|
||||
if (segments[0]?.nodes !== undefined) return { line: output, openingLinkAsDirective: true, unspellableRuns: [] }
|
||||
@@ -227,7 +226,7 @@ function claimsCharacter({ container, escapings, headingCloser, linkClose, scan
|
||||
|
||||
// CommonMark reads no escape inside a code span, so a backtick string left beside an escape still closes a span that an earlier bare run of its length opens.
|
||||
// The walk runs backwards and escapes only the run it just read, so every index it reads still holds the claims alone.
|
||||
function escapeClosedRuns(scan: string, escapings: Escapings, escaped: Uint8Array): void {
|
||||
function escapeClosedRuns(scan: string, escapings: Escapings, escaped: Uint8Array): Uint8Array {
|
||||
// The lengths of the backtick strings escapes leave: a bare run of one of these lengths would open a span one of them closes, so it is escaped too.
|
||||
const formed = new Set<number>()
|
||||
let end = scan.length - 1
|
||||
@@ -252,6 +251,7 @@ function escapeClosedRuns(scan: string, escapings: Escapings, escaped: Uint8Arra
|
||||
}
|
||||
end = start - 1
|
||||
}
|
||||
return escaped
|
||||
}
|
||||
|
||||
// One emphasis run, the innermost, or every highlight run the line cannot spell.
|
||||
|
||||
@@ -31,6 +31,7 @@ test('refuses a string past the bound as too long on every engine, and names any
|
||||
ok: false,
|
||||
})
|
||||
assert.equal(withinEngineLimits(thrown('RangeError', 'Invalid array length')).ok, false)
|
||||
assert.equal(withinEngineLimits(thrown('RangeError', 'Array buffer allocation failed')).ok, false)
|
||||
assert.deepEqual(
|
||||
withinEngineLimits(() => success('x')),
|
||||
{ ok: true, value: 'x' },
|
||||
|
||||
@@ -3,9 +3,9 @@ import { failure, success, type Result } from '../result.ts'
|
||||
// V8's longest string (docs/decisions.md §Markdown past V8's longest string is refused on every engine).
|
||||
export const longestMarkdown = 2 ** 29 - 24
|
||||
|
||||
// Measured on Firefox 155, Node 24 and Bun 1.4. SpiderMonkey's overflow and V8's string overflow both mean a string past longestMarkdown; the other two name an engine's own limit, and JavaScriptCore's also a heap running short.
|
||||
// Measured on Firefox 155, Node 24 and Bun 1.4. SpiderMonkey's overflow and V8's string overflow both mean a string past longestMarkdown; the others name an engine's own limit or its memory running short.
|
||||
const pastLongestString = ['InternalError: allocation size overflow', 'RangeError: Invalid string length']
|
||||
const pastEngineLimit = ['RangeError: Invalid array length', 'RangeError: Out of memory']
|
||||
const pastEngineLimit = ['RangeError: Array buffer allocation failed', 'RangeError: Invalid array length', 'RangeError: Out of memory']
|
||||
|
||||
export function tooLong<T>(): Result<T> {
|
||||
return failure('unsupported-node-shape', `the markdown for this document, or for a directive's plain CommonMark, would be longer than ${longestMarkdown} characters, the longest this library writes`, [])
|
||||
|
||||
Reference in New Issue
Block a user