Skip to content

Commit e198e05

Browse files
committed
fix: support cross-context Uint8Array in TextEncoder#encodeInto
1 parent 3ef9b62 commit e198e05

File tree

2 files changed

+22
-2
lines changed

2 files changed

+22
-2
lines changed

fallback/encoding.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ export function normalizeEncoding(label) {
4747

4848
const define = (obj, key, value) => Object.defineProperty(obj, key, { value, writable: false })
4949

50+
// TODO: make this more strict against Symbol.toStringTag
51+
// Is not very significant though, anything faking Symbol.toStringTag could as well override
52+
// prototypes, which is not something we protect against
53+
5054
function isAnyArrayBuffer(x) {
5155
if (x instanceof ArrayBuffer) return true
5256
if (globalThis.SharedArrayBuffer && x instanceof SharedArrayBuffer) return true
@@ -55,6 +59,12 @@ function isAnyArrayBuffer(x) {
5559
return s === '[object ArrayBuffer]' || s === '[object SharedArrayBuffer]'
5660
}
5761

62+
function isAnyUint8Array(x) {
63+
if (x instanceof Uint8Array) return true
64+
if (!x || !ArrayBuffer.isView(x) || x.BYTES_PER_ELEMENT !== 1) return false
65+
return Object.prototype.toString.call(x) === '[object Uint8Array]'
66+
}
67+
5868
const fromSource = (x) => {
5969
if (x instanceof Uint8Array) return x
6070
if (ArrayBuffer.isView(x)) return new Uint8Array(x.buffer, x.byteOffset, x.byteLength)
@@ -217,7 +227,7 @@ export class TextEncoder {
217227

218228
encodeInto(str, target) {
219229
if (typeof str !== 'string') str = `${str}`
220-
if (!(target instanceof Uint8Array)) throw new TypeError('Target must be an Uint8Array')
230+
if (!isAnyUint8Array(target)) throw new TypeError('Target must be an Uint8Array')
221231
if (target.buffer.detached) return { read: 0, written: 0 } // Until https://github.com/whatwg/encoding/issues/324 is resolved
222232

223233
const tlen = target.length

tests/encoding/cross-context.test.cjs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,23 @@ describe('vm', { skip: !vm }, () => {
1313
const u = Uint8Array.of(0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0xe2, 0x88, 0x80)
1414
const ctx = { TextDecoder, TextEncoder }
1515

16-
test('TextEncoder', (t) => {
16+
test('TextEncoder.encode', (t) => {
1717
const outer = new TextEncoder().encode(string)
1818
const inner = vm.runInNewContext(`new TextEncoder().encode(${JSON.stringify(string)})`, ctx)
1919
t.assert.deepStrictEqual(outer, u)
2020
t.assert.deepStrictEqual(inner, u)
2121
})
2222

23+
test('TextEncoder.encodeInto', (t) => {
24+
const res = vm.runInNewContext(
25+
`ua = new Uint8Array(25); [new TextEncoder().encodeInto(${JSON.stringify(string)}, ua), ua]`,
26+
ctx
27+
)
28+
t.assert.deepStrictEqual(res[0], { read: 8, written: 10 })
29+
t.assert.deepEqual(res[1].subarray(0, 10), u)
30+
t.assert.deepEqual(res[1].subarray(10), new Uint8Array(15))
31+
})
32+
2333
test('TextDecoder + Uint8Array', (t) => {
2434
const outer = new TextDecoder().decode(u)
2535
const inner = vm.runInNewContext(`new TextDecoder().decode(Uint8Array.of(${u.join(',')}))`, ctx)

0 commit comments

Comments
 (0)