diff --git a/README.md b/README.md index 8b66d93..f5729df 100644 --- a/README.md +++ b/README.md @@ -411,8 +411,8 @@ 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. 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. +short, which returns `unsupported-node-shape` at the empty path, the code and path of markdown past +the length bound. Retry once any call that returns that; a repeat is a lasting refusal. ### Parsing @@ -445,7 +445,7 @@ The emitter raises these, and so does a parse, which asks the emitter how to spe | Code | Fires when | What you can do | | --- | --- | --- | | `unsupported-nesting-depth` | blocks, marks, an attribute's JSON or a carried node's JSON nest past 500 levels | keep the ADF and pass the document over, or show it read-only; flatten the input where you are the one who wrote it | -| `unsupported-node-shape` | parsing, in `losslessMarkdownToAdf`: markdown spells a node with an attribute, value, argument or body its type does not take, or without one it needs, wraps a directive mark around nothing or only hard breaks, writes as a directive a node or mark the lossless flavour spells as CommonMark, or one that, written out as plain CommonMark, would be longer than 536870888 characters, or puts a reserved directive out of place: `!adf:textBreak{}` parting nothing, `!adf:doc` anywhere but as the whole document. Emitting, in `adfToLosslessMarkdown`: a node not riding the carry that carries one mark type twice, a block or a non-text inline node holding `text`, or a leaf block or a non-text inline node holding `content`. Emitting, in `adfToPortableMarkdown`: a line or task list the portable writer cannot spell, a bug in this library. Emitting, in both writers: a document whose markdown would be longer than 536870888 characters, V8's longest string, on every engine; in `adfToPortableMarkdown`, also a document whose text alone is that long, edge whitespace included. In every call: a conversion that passes the longest string or array the JavaScript engine builds | fix what the message names; [`spec/flavour.md`](https://github.com/larvit/adf-codec/blob/main/spec/flavour.md) lists every type's attributes and body. For a portable line or task list, report it as a bug. Past 536870888 characters or the engine's limit, writing: set the document aside, keeping the ADF and passing it over or showing it read-only; reading: shorten the markdown, or nest its lists and quotes less deeply | +| `unsupported-node-shape` | parsing, in `losslessMarkdownToAdf`: markdown spells a node with an attribute, value, argument or body its type does not take, or without one it needs, wraps a directive mark around nothing or only hard breaks, writes as a directive a node or mark the lossless flavour spells as CommonMark, or one that, written out as plain CommonMark, would be longer than 536870888 characters, or puts a reserved directive out of place: `!adf:textBreak{}` parting nothing, `!adf:doc` anywhere but as the whole document. Emitting, in `adfToLosslessMarkdown`: a node not riding the carry that carries one mark type twice, a block or a non-text inline node holding `text`, or a leaf block or a non-text inline node holding `content`. Emitting, in `adfToPortableMarkdown`: a line or task list the portable writer cannot spell, a bug in this library. Emitting, in both writers: a document whose markdown would be longer than 536870888 characters, V8's longest string, on every engine; in `adfToPortableMarkdown`, also a document whose text alone is that long, edge whitespace included. In every call: a conversion that passes the longest string or array the JavaScript engine builds, or runs it short of memory | fix what the message names; [`spec/flavour.md`](https://github.com/larvit/adf-codec/blob/main/spec/flavour.md) lists every type's attributes and body. For a portable line or task list, report it as a bug. Past 536870888 characters or the engine's limit, retry once; if it repeats, writing: set the document aside, keeping the ADF and passing it over or showing it read-only; reading: shorten the markdown, or nest its lists and quotes less deeply | ## The guarantees diff --git a/src/markdown/length-bound.test.ts b/src/markdown/length-bound.test.ts index 2ce911f..f754d45 100644 --- a/src/markdown/length-bound.test.ts +++ b/src/markdown/length-bound.test.ts @@ -27,7 +27,7 @@ test('refuses a string past the bound as too long on every engine, and names any assert.deepEqual(withinEngineLimits(thrown('RangeError', 'Invalid string length')), tooLong()) assert.deepEqual(withinEngineLimits(thrown('InternalError', 'allocation size overflow')), tooLong()) assert.deepEqual(withinEngineLimits(thrown('RangeError', 'Out of memory')), { - error: { code: 'unsupported-node-shape', message: 'the conversion passed this JavaScript engine\'s longest string or array, or its heap (Out of memory)', path: [] }, + error: { code: 'unsupported-node-shape', message: 'the conversion passed this JavaScript engine\'s longest string or array, or ran it out of memory (Out of memory)', path: [] }, ok: false, }) assert.equal(withinEngineLimits(thrown('RangeError', 'Invalid array length')).ok, false) diff --git a/src/markdown/length-bound.ts b/src/markdown/length-bound.ts index 5d49ecd..be4f752 100644 --- a/src/markdown/length-bound.ts +++ b/src/markdown/length-bound.ts @@ -36,6 +36,6 @@ export function withinEngineLimits(convert: () => Result): Result { if (pastLongestString.includes(thrown)) return tooLong() // A stack overflow is a bug (docs/decisions.md §Nothing recurses unbounded), so it stays a throw. if (!pastEngineLimit.includes(thrown)) throw error - return failure('unsupported-node-shape', `the conversion passed this JavaScript engine's longest string or array, or its heap (${error.message})`, []) + return failure('unsupported-node-shape', `the conversion passed this JavaScript engine's longest string or array, or ran it out of memory (${error.message})`, []) } }