Skip to content

Commit fac667d

Browse files
committed
fix: decoding detached returns empty data
1 parent 8c57f36 commit fac667d

2 files changed

Lines changed: 32 additions & 1 deletion

File tree

fallback/encoding.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,16 @@ function isAnyUint8Array(x) {
6868
const fromSource = (x) => {
6969
if (x instanceof Uint8Array) return x
7070
if (ArrayBuffer.isView(x)) return new Uint8Array(x.buffer, x.byteOffset, x.byteLength)
71-
if (isAnyArrayBuffer(x)) return new Uint8Array(x)
71+
if (isAnyArrayBuffer(x)) {
72+
if ('detached' in x) return x.detached === true ? new Uint8Array() : new Uint8Array(x)
73+
// Old engines without .detached, try-catch
74+
try {
75+
return new Uint8Array(x)
76+
} catch {
77+
return new Uint8Array()
78+
}
79+
}
80+
7281
throw new TypeError('Argument must be a SharedArrayBuffer, ArrayBuffer or ArrayBufferView')
7382
}
7483

tests/encoding/mistakes.test.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -811,4 +811,26 @@ describe('Common implementation mistakes', () => {
811811
t.assert.strictEqual(new TextDecoder('UTF-8'.toLowerCase()).encoding, 'utf-8') // Do not remove .toLowerCase() from test
812812
})
813813
})
814+
815+
// text-encoding is wrong, naive whatwg-encoding usage fails too
816+
// https://webidl.spec.whatwg.org/#dfn-get-buffer-source-copy
817+
// 7. If IsDetachedBuffer(jsArrayBuffer) is true, then return the empty byte sequence.
818+
test('decoding detached returns empty data', { skip: !globalThis.MessageChannel }, (t) => {
819+
for (const fatal of [false, true]) {
820+
const decoder = new TextDecoder('utf-8', { fatal })
821+
const a = new ArrayBuffer(2)
822+
const b = new Uint8Array(a)
823+
b[0] = 0x24
824+
b[1] = 0x25
825+
t.assert.strictEqual(decoder.decode(a), '$%')
826+
t.assert.strictEqual(decoder.decode(b), '$%')
827+
// second time
828+
t.assert.strictEqual(decoder.decode(a), '$%')
829+
t.assert.strictEqual(decoder.decode(b), '$%')
830+
new MessageChannel().port1.postMessage(a, [a])
831+
// but not anymore
832+
t.assert.strictEqual(decoder.decode(a), '')
833+
t.assert.strictEqual(decoder.decode(b), '')
834+
}
835+
})
814836
})

0 commit comments

Comments
 (0)