Skip to content

Commit 03b9ba5

Browse files
committed
fix: clear BOM state on fatal errors after stream end
1 parent 69efd0c commit 03b9ba5

File tree

2 files changed

+21
-2
lines changed

2 files changed

+21
-2
lines changed

fallback/encoding.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,17 +110,19 @@ export class TextDecoder {
110110
u = u.subarray(bom)
111111
}
112112
}
113+
} else if (!stream && !this.ignoreBOM) {
114+
this.#canBOM = true
113115
}
114116

115117
if (!this.#decode) this.#decode = unicodeDecoder(this.encoding, !this.fatal)
116118
try {
117119
const res = (prefix ? this.#decode(prefix) : '') + this.#decode(u) + suffix
118120
if (res.length > 0 && stream) this.#canBOM = false
119-
120-
if (!stream) this.#canBOM = !this.ignoreBOM
121121
return res
122122
} catch (err) {
123123
this.#chunk = null // reset unfinished chunk on errors
124+
// The correct way per spec seems to be not destroying the decoder state (aka BOM here) in stream mode
125+
// See also multi-byte.js
124126
throw err
125127
}
126128

tests/encoding/mistakes.test.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -715,6 +715,23 @@ describe('Common implementation mistakes', () => {
715715
}
716716
})
717717

718+
test('utf-8 BOM handling', (t) => {
719+
// Firefox fails on this
720+
{
721+
const d = new TextDecoder('utf-8', { fatal: true })
722+
t.assert.strictEqual(d.decode(u(0xef, 0xbb, 0xbf), { stream: true }).length, 0) // BOM
723+
t.assert.throws(() => d.decode(u(0xff)))
724+
t.assert.strictEqual(d.decode(u(0xef, 0xbb, 0xbf)).length, 0)
725+
}
726+
727+
// Chrome and Node.js fail on this. Firefox, WebKit and Deno pass
728+
{
729+
const d = new TextDecoder('utf-8', { fatal: true })
730+
t.assert.throws(() => d.decode(u(0xef, 0xbb, 0xbf, 0xff), { stream: true }))
731+
t.assert.strictEqual(d.decode(u(0xef, 0xbb, 0xbf)).length, 1)
732+
}
733+
})
734+
718735
// https://github.com/facebook/hermes/pull/1855#issuecomment-3632349129
719736
for (const encoding of ['utf-16le', 'utf-16be']) {
720737
test(encoding, (t) => {

0 commit comments

Comments
 (0)