- feat:
isomorphicDecode(),isomorphicEncode()in/encoding.js(in #68) - doc: deprecate
latin1toString()/latin1fromString()in favor ofisomorphicDecode()/isomorphicEncode()(see #55) - feat:
fromBase32crockford/toBase32crockfordin/base32.js - feat:
typedCopyBytes()in/array.js - feat: add
'arraybuffer'output format support in methods acceptingformatparameter (in #70) - feat:
'uint8'(default) output format now never returns pooledUint8Arrayinstances (see below)
This release brings support of native ArrayBuffer return format (under the name of format: 'arraybuffer').
Converting Uint8Array to ArrayBuffer downstream is non-trivial, and there is a lot of confusion in the ecosystem around those.
A simple access to .buffer is often seen and is incorrect -- code accepting Uint8Arrays that it didn't create should not assume that it did not receive for example a result of .subarray() (where .buffer size mismatches the view size), or a Node.js pooled Buffer instance (which are also Uint8Arrays).
That pattern (using .buffer and failing to check bounds) has been a source of numerous errors in ecosystem libraries.
To minimize the risks from such mistakes, this library now never returns Uint8Array instances (default format) that are not complete views of their underlying ArrayBuffer.
In other words, now the following are true for a returned Uint8Array instance u8:
u8.buffer.byteLength === u8.byteLengthu8.byteOffset === 0deepStrictEqual(new Uint8Array(u8.buffer), u8)
The affected parts (which previously returned non-complete views / subarrays) are:
- On multiple platforms:
fromBase58Check,createMultibyteEncoder,createSinglebyteEncoder - On Node.js import condition only (any Node.js version):
latin1fromString,utf8fromString,utf16fromString - On Node.js import condition with Node.js < 25:
fromHex,fromBase64
This comes at a reasonable performance cost (almost exclusively on Node.js import condition), but correctness/security comes first.
Note
This change doesn't affect TextEncoder, which is already governed by the Encoding Standard which demands non-pooled Uint8Arrays.
This also doesn't affect typedView() (from /array.js) which by definition is always a view of the same underlying ArrayBuffer data.
But now typedCopyBytes() is introduced.
Important
This change does not affect 'buffer' return format, which can still return pooled Buffer instances.
This is similar to the behavior of native Buffer.from / Buffer.alloc which are pooled.
Apart from making returned Uint8Array instances complete views, a dedicated ArrayBuffer return format is introduced to eliminate the need to use .buffer on the returned values in downstream code at all (as it's a bad pattern in general and tooling/lint will/should flag that).
Full Changelog: v1.14.1...v1.15.0