@exodus/bytes 1.12.0 → 1.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -29
- package/array.js +1 -1
- package/base32.js +1 -3
- package/base58.js +3 -3
- package/base58check.d.ts +2 -2
- package/base58check.js +6 -7
- package/base64.js +7 -6
- package/bech32.js +3 -3
- package/encoding-browser.browser.js +43 -17
- package/fallback/_utils.js +7 -122
- package/fallback/base32.js +3 -3
- package/fallback/base58check.js +3 -3
- package/fallback/base64.js +2 -3
- package/fallback/encoding.api.js +0 -43
- package/fallback/encoding.js +41 -2
- package/fallback/encoding.labels.js +20 -16
- package/fallback/hex.js +3 -4
- package/fallback/latin1.js +6 -25
- package/fallback/percent.js +1 -1
- package/fallback/platform.browser.js +31 -0
- package/fallback/platform.js +2 -0
- package/fallback/platform.native.js +122 -0
- package/fallback/single-byte.encodings.js +40 -49
- package/fallback/single-byte.js +4 -4
- package/fallback/utf16.js +70 -3
- package/fallback/utf8.auto.browser.js +2 -0
- package/fallback/utf8.auto.js +1 -0
- package/fallback/utf8.auto.native.js +1 -0
- package/fallback/utf8.js +25 -3
- package/hex.js +6 -8
- package/hex.node.js +2 -3
- package/multi-byte.js +2 -2
- package/multi-byte.node.js +3 -3
- package/package.json +28 -7
- package/single-byte.js +9 -9
- package/single-byte.node.js +8 -8
- package/utf16.browser.js +8 -0
- package/utf16.js +1 -90
- package/utf16.native.js +22 -0
- package/utf16.node.js +5 -20
- package/utf8.js +9 -28
- package/utf8.node.js +3 -4
- package/whatwg.js +6 -2
package/README.md
CHANGED
|
@@ -30,7 +30,7 @@ Tested in CI with [@exodus/test](https://github.com/ExodusMovement/test#exoduste
|
|
|
30
30
|
[](https://hermesengine.dev)
|
|
31
31
|
[](https://v8.dev/docs/d8)
|
|
32
32
|
[](https://docs.webkit.org/Deep%20Dive/JSC/JavaScriptCore.html)
|
|
33
|
-
[](https://spidermonkey.dev/)
|
|
33
|
+
[](https://spidermonkey.dev/)\
|
|
34
34
|
[](https://github.com/quickjs-ng/quickjs)
|
|
35
35
|
[](https://github.com/Moddable-OpenSource/moddable)
|
|
36
36
|
[](https://github.com/oracle/graaljs)
|
|
@@ -100,24 +100,47 @@ _These are only provided as a compatibility layer, prefer hardened APIs instead
|
|
|
100
100
|
|
|
101
101
|
### Lite version
|
|
102
102
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
import
|
|
106
|
-
|
|
107
|
-
|
|
103
|
+
Alternate exports exist that can help reduce bundle size, see comparison:
|
|
104
|
+
|
|
105
|
+
| import | size |
|
|
106
|
+
| - | - |
|
|
107
|
+
| [@exodus/bytes/encoding-browser.js](#exodusbytesencoding-browserjs-) | <sub></sub> |
|
|
108
|
+
| [@exodus/bytes/encoding-lite.js](#exodusbytesencoding-litejs-) | <sub></sub> |
|
|
109
|
+
| [@exodus/bytes/encoding.js](#exodusbytesencodingjs-) | <sub></sub> |
|
|
110
|
+
| `text-encoding` | <sub></sub> |
|
|
111
|
+
| `iconv-lite` | <sub></sub> |
|
|
112
|
+
| `whatwg-encoding` | <sub></sub> |
|
|
113
|
+
|
|
114
|
+
Libraries are advised to use single-purpose hardened `@exodus/bytes/utf8.js` / `@exodus/bytes/utf16.js` APIs for Unicode.
|
|
115
|
+
|
|
116
|
+
Applications (including React Native apps) are advised to load either `@exodus/bytes/encoding-lite.js` or `@exodus/bytes/encoding.js`
|
|
117
|
+
(depending on whether legacy multi-byte support is needed) and use that as a global polyfill.
|
|
108
118
|
|
|
109
|
-
|
|
110
|
-
from 90 KiB gzipped for `@exodus/bytes/encoding.js` to 10 KiB gzipped for `@exodus/bytes/encoding-lite.js`.\
|
|
111
|
-
(For comparison, `text-encoding` module is 190 KiB gzipped, and `iconv-lite` is 194 KiB gzipped):
|
|
119
|
+
#### `@exodus/bytes/encoding-lite.js`
|
|
112
120
|
|
|
113
|
-
|
|
114
|
-
|
|
121
|
+
If you don't need support for legacy multi-byte encodings.
|
|
122
|
+
|
|
123
|
+
Reduces the bundle size ~12x, while still keeping `utf-8`, `utf-16le`, `utf-16be` and all single-byte encodings specified by the spec.
|
|
124
|
+
The only difference is support for legacy multi-byte encodings.
|
|
115
125
|
|
|
116
126
|
See [the list of encodings](https://encoding.spec.whatwg.org/#names-and-labels).
|
|
117
127
|
|
|
128
|
+
This can be useful for example in React Native global TextDecoder polyfill,
|
|
129
|
+
if you are sure that you don't need legacy multi-byte encodings support.
|
|
130
|
+
|
|
131
|
+
#### `@exodus/bytes/encoding-browser.js`
|
|
132
|
+
|
|
133
|
+
Resolves to a tiny import in browser bundles, preferring native `TextDecoder` / `TextEncoder`.
|
|
134
|
+
|
|
135
|
+
For non-browsers (Node.js, React Native), loads a full implementation.
|
|
136
|
+
|
|
137
|
+
> [!NOTE]
|
|
138
|
+
> This is not the default behavior for `@exodus/bytes/encoding.js` because all major browser implementations have bugs,
|
|
139
|
+
> which `@exodus/bytes/encoding.js` fixes. Only use if you are ok with that.
|
|
140
|
+
|
|
118
141
|
## API
|
|
119
142
|
|
|
120
|
-
### @exodus/bytes/utf8.js
|
|
143
|
+
### @exodus/bytes/utf8.js <sub><sub>
|
|
121
144
|
|
|
122
145
|
UTF-8 encoding/decoding
|
|
123
146
|
|
|
@@ -183,7 +206,7 @@ Prefer using strict throwing methods for cryptography applications._
|
|
|
183
206
|
This is similar to `new TextDecoder('utf-8', { ignoreBOM: true }).decode(arr)`,
|
|
184
207
|
but works on all engines.
|
|
185
208
|
|
|
186
|
-
### @exodus/bytes/utf16.js
|
|
209
|
+
### @exodus/bytes/utf16.js <sub><sub>
|
|
187
210
|
|
|
188
211
|
UTF-16 encoding/decoding
|
|
189
212
|
|
|
@@ -233,7 +256,7 @@ Prefer using strict throwing methods for cryptography applications._
|
|
|
233
256
|
|
|
234
257
|
Throws on non-even byte length.
|
|
235
258
|
|
|
236
|
-
### @exodus/bytes/single-byte.js
|
|
259
|
+
### @exodus/bytes/single-byte.js <sub></sub>
|
|
237
260
|
|
|
238
261
|
Decode / encode the legacy single-byte encodings according to the
|
|
239
262
|
[Encoding standard](https://encoding.spec.whatwg.org/)
|
|
@@ -354,7 +377,7 @@ Same as:
|
|
|
354
377
|
const windows1252fromString = createSinglebyteEncoder('windows-1252', { mode: 'fatal' })
|
|
355
378
|
```
|
|
356
379
|
|
|
357
|
-
### @exodus/bytes/multi-byte.js
|
|
380
|
+
### @exodus/bytes/multi-byte.js <sub></sub>
|
|
358
381
|
|
|
359
382
|
Decode / encode the legacy multi-byte encodings according to the
|
|
360
383
|
[Encoding standard](https://encoding.spec.whatwg.org/)
|
|
@@ -396,7 +419,7 @@ Returns a function `encode(string)` that encodes a string to bytes.
|
|
|
396
419
|
In `'fatal'` mode (default), will throw on non well-formed strings or any codepoints which could
|
|
397
420
|
not be encoded in the target encoding.
|
|
398
421
|
|
|
399
|
-
### @exodus/bytes/bigint.js
|
|
422
|
+
### @exodus/bytes/bigint.js <sub></sub>
|
|
400
423
|
|
|
401
424
|
Convert between BigInt and Uint8Array
|
|
402
425
|
|
|
@@ -418,7 +441,7 @@ Convert a Uint8Array or Buffer to a BigInt
|
|
|
418
441
|
|
|
419
442
|
The bytes are interpreted as a big-endian unsigned integer.
|
|
420
443
|
|
|
421
|
-
### @exodus/bytes/hex.js
|
|
444
|
+
### @exodus/bytes/hex.js <sub></sub>
|
|
422
445
|
|
|
423
446
|
Implements Base16 from [RFC4648](https://datatracker.ietf.org/doc/html/rfc4648)
|
|
424
447
|
(no differences from [RFC3548](https://datatracker.ietf.org/doc/html/rfc4648)).
|
|
@@ -437,7 +460,7 @@ Unlike `Buffer.from()`, throws on invalid input
|
|
|
437
460
|
|
|
438
461
|
Encode a `Uint8Array` to a lowercase hex string
|
|
439
462
|
|
|
440
|
-
### @exodus/bytes/base64.js
|
|
463
|
+
### @exodus/bytes/base64.js <sub></sub>
|
|
441
464
|
|
|
442
465
|
Implements base64 and base64url from [RFC4648](https://datatracker.ietf.org/doc/html/rfc4648)
|
|
443
466
|
(no differences from [RFC3548](https://datatracker.ietf.org/doc/html/rfc4648)).
|
|
@@ -474,7 +497,7 @@ Encode a `Uint8Array` to a base64 string (RFC 4648)
|
|
|
474
497
|
|
|
475
498
|
Encode a `Uint8Array` to a base64url string (RFC 4648)
|
|
476
499
|
|
|
477
|
-
### @exodus/bytes/base32.js
|
|
500
|
+
### @exodus/bytes/base32.js <sub></sub>
|
|
478
501
|
|
|
479
502
|
Implements base32 and base32hex from [RFC4648](https://datatracker.ietf.org/doc/html/rfc4648)
|
|
480
503
|
(no differences from [RFC3548](https://datatracker.ietf.org/doc/html/rfc4648)).
|
|
@@ -504,7 +527,7 @@ Encode a `Uint8Array` to a base32 string (RFC 4648)
|
|
|
504
527
|
|
|
505
528
|
Encode a `Uint8Array` to a base32hex string (RFC 4648)
|
|
506
529
|
|
|
507
|
-
### @exodus/bytes/bech32.js
|
|
530
|
+
### @exodus/bytes/bech32.js <sub></sub>
|
|
508
531
|
|
|
509
532
|
Implements bech32 and bech32m from
|
|
510
533
|
[BIP-0173](https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki#specification)
|
|
@@ -538,7 +561,7 @@ Decode a bech32m string to bytes
|
|
|
538
561
|
|
|
539
562
|
Encode bytes to a bech32m string
|
|
540
563
|
|
|
541
|
-
### @exodus/bytes/base58.js
|
|
564
|
+
### @exodus/bytes/base58.js <sub></sub>
|
|
542
565
|
|
|
543
566
|
Implements [base58](https://www.ietf.org/archive/id/draft-msporny-base58-03.txt) encoding.
|
|
544
567
|
|
|
@@ -573,7 +596,7 @@ Encode a `Uint8Array` to a base58 string using XRP alphabet
|
|
|
573
596
|
|
|
574
597
|
Uses the XRP variant base58 alphabet
|
|
575
598
|
|
|
576
|
-
### @exodus/bytes/base58check.js
|
|
599
|
+
### @exodus/bytes/base58check.js <sub></sub>
|
|
577
600
|
|
|
578
601
|
Implements [base58check](https://en.bitcoin.it/wiki/Base58Check_encoding) encoding.
|
|
579
602
|
|
|
@@ -613,7 +636,7 @@ Uses double SHA-256 for checksum calculation
|
|
|
613
636
|
|
|
614
637
|
Create a base58check encoder/decoder with custom hash functions
|
|
615
638
|
|
|
616
|
-
### @exodus/bytes/wif.js
|
|
639
|
+
### @exodus/bytes/wif.js <sub></sub>
|
|
617
640
|
|
|
618
641
|
Wallet Import Format (WIF) encoding and decoding.
|
|
619
642
|
|
|
@@ -652,7 +675,7 @@ Encode WIF data to a WIF string
|
|
|
652
675
|
|
|
653
676
|
Encode WIF data to a WIF string (synchronous)
|
|
654
677
|
|
|
655
|
-
### @exodus/bytes/array.js
|
|
678
|
+
### @exodus/bytes/array.js <sub></sub>
|
|
656
679
|
|
|
657
680
|
TypedArray utils and conversions.
|
|
658
681
|
|
|
@@ -667,7 +690,7 @@ Create a view of a TypedArray in the specified format (`'uint8'` or `'buffer'`)
|
|
|
667
690
|
> [!IMPORTANT]
|
|
668
691
|
> Does not copy data, returns a view on the same underlying buffer
|
|
669
692
|
|
|
670
|
-
### @exodus/bytes/encoding.js
|
|
693
|
+
### @exodus/bytes/encoding.js <sub></sub>
|
|
671
694
|
|
|
672
695
|
Implements the [Encoding standard](https://encoding.spec.whatwg.org/):
|
|
673
696
|
[TextDecoder](https://encoding.spec.whatwg.org/#interface-textdecoder),
|
|
@@ -778,11 +801,11 @@ only expects lowercased encoding name:
|
|
|
778
801
|
new TextDecoder(getBOMEncoding(input) ?? fallbackEncoding).decode(input)
|
|
779
802
|
```
|
|
780
803
|
|
|
781
|
-
### @exodus/bytes/encoding-lite.js
|
|
804
|
+
### @exodus/bytes/encoding-lite.js <sub></sub>
|
|
782
805
|
|
|
783
806
|
The exact same exports as `@exodus/bytes/encoding.js` are also exported as
|
|
784
807
|
`@exodus/bytes/encoding-lite.js`, with the difference that the lite version does not load
|
|
785
|
-
multi-byte `TextDecoder` encodings by default to reduce bundle size
|
|
808
|
+
multi-byte `TextDecoder` encodings by default to reduce bundle size ~12x.
|
|
786
809
|
|
|
787
810
|
```js
|
|
788
811
|
import { TextDecoder, TextEncoder } from '@exodus/bytes/encoding-lite.js'
|
|
@@ -837,7 +860,7 @@ true
|
|
|
837
860
|
'%'
|
|
838
861
|
```
|
|
839
862
|
|
|
840
|
-
### @exodus/bytes/encoding-browser.js
|
|
863
|
+
### @exodus/bytes/encoding-browser.js <sub><sub>
|
|
841
864
|
|
|
842
865
|
Same as `@exodus/bytes/encoding.js`, but in browsers instead of polyfilling just uses whatever the
|
|
843
866
|
browser provides, drastically reducing the bundle size (to less than 2 KiB gzipped).
|
|
@@ -858,7 +881,7 @@ do not provide sufficiently complete / non-buggy `TextDecoder` APIs.
|
|
|
858
881
|
> but they are fixing them and the expected update window is short.\
|
|
859
882
|
> If you want to circumvent browser bugs, use full `@exodus/bytes/encoding.js` import.
|
|
860
883
|
|
|
861
|
-
### @exodus/bytes/whatwg.js
|
|
884
|
+
### @exodus/bytes/whatwg.js <sub></sub>
|
|
862
885
|
|
|
863
886
|
WHATWG helpers
|
|
864
887
|
|
package/array.js
CHANGED
package/base32.js
CHANGED
|
@@ -7,8 +7,6 @@ import * as js from './fallback/base32.js'
|
|
|
7
7
|
|
|
8
8
|
// 8 chars per 5 bytes
|
|
9
9
|
|
|
10
|
-
const { E_PADDING } = js
|
|
11
|
-
|
|
12
10
|
export const toBase32 = (arr, { padding = false } = {}) => js.toBase32(arr, false, padding)
|
|
13
11
|
export const toBase32hex = (arr, { padding = false } = {}) => js.toBase32(arr, true, padding)
|
|
14
12
|
|
|
@@ -30,7 +28,7 @@ function fromBase32common(str, isBase32Hex, padding, format, rest) {
|
|
|
30
28
|
if (rest !== null) assertEmptyRest(rest)
|
|
31
29
|
|
|
32
30
|
if (padding === true) {
|
|
33
|
-
if (str.length % 8 !== 0) throw new SyntaxError(E_PADDING)
|
|
31
|
+
if (str.length % 8 !== 0) throw new SyntaxError(js.E_PADDING)
|
|
34
32
|
} else if (padding === false) {
|
|
35
33
|
if (str.endsWith('=')) throw new SyntaxError('Did not expect padding in base32 input')
|
|
36
34
|
} else if (padding !== 'both') {
|
package/base58.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { typedView } from './array.js'
|
|
2
|
-
import {
|
|
3
|
-
import { nativeDecoder, nativeEncoder, isHermes
|
|
2
|
+
import { assertU8, E_STRING } from './fallback/_utils.js'
|
|
3
|
+
import { nativeDecoder, nativeEncoder, isHermes } from './fallback/platform.js'
|
|
4
4
|
import { encodeAscii, decodeAscii } from './fallback/latin1.js'
|
|
5
5
|
|
|
6
6
|
const alphabet58 = [...'123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz']
|
|
@@ -23,7 +23,7 @@ const E_CHAR = 'Invalid character in base58 input'
|
|
|
23
23
|
const shouldUseBigIntFrom = isHermes // faster only on Hermes, numbers path beats it on normal engines
|
|
24
24
|
|
|
25
25
|
function toBase58core(arr, alphabet, codes) {
|
|
26
|
-
|
|
26
|
+
assertU8(arr)
|
|
27
27
|
const length = arr.length
|
|
28
28
|
if (length === 0) return ''
|
|
29
29
|
|
package/base58check.d.ts
CHANGED
|
@@ -81,8 +81,8 @@ export interface Base58CheckSync extends Base58CheckAsync {
|
|
|
81
81
|
* @param hashAlgoSync - Optional sync hash function
|
|
82
82
|
* @returns Base58Check encoder/decoder instance
|
|
83
83
|
*/
|
|
84
|
-
export function makeBase58check(hashAlgo: HashFunction, hashAlgoSync
|
|
85
|
-
export function makeBase58check(hashAlgo: HashFunction): Base58CheckAsync;
|
|
84
|
+
export function makeBase58check(hashAlgo: HashFunction | HashFunctionSync, hashAlgoSync: HashFunctionSync): Base58CheckSync;
|
|
85
|
+
export function makeBase58check(hashAlgo: HashFunction | HashFunctionSync, hashAlgoSync?: undefined): Base58CheckAsync;
|
|
86
86
|
|
|
87
87
|
/**
|
|
88
88
|
* Encode bytes to base58check string asynchronously
|
package/base58check.js
CHANGED
|
@@ -8,12 +8,11 @@ import { makeBase58check } from './fallback/base58check.js'
|
|
|
8
8
|
|
|
9
9
|
const hash256sync = (x) => sha256(sha256(x))
|
|
10
10
|
const hash256 = hash256sync // See note at the top
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
|
|
12
|
+
const b58c = /* @__PURE__ */ makeBase58check(hash256, hash256sync)
|
|
13
|
+
export const toBase58check = /* @__PURE__ */ (() => b58c.encode)()
|
|
14
|
+
export const fromBase58check = /* @__PURE__ */ (() => b58c.decode)()
|
|
15
|
+
export const toBase58checkSync = /* @__PURE__ */ (() => b58c.encodeSync)()
|
|
16
|
+
export const fromBase58checkSync = /* @__PURE__ */ (() => b58c.decodeSync)()
|
|
17
17
|
|
|
18
18
|
export { makeBase58check } from './fallback/base58check.js'
|
|
19
|
-
export { toBase58check, fromBase58check, toBase58checkSync, fromBase58checkSync }
|
package/base64.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { assertEmptyRest } from './assert.js'
|
|
2
2
|
import { typedView } from './array.js'
|
|
3
|
-
import {
|
|
3
|
+
import { assertU8, E_STRING } from './fallback/_utils.js'
|
|
4
|
+
import { isHermes } from './fallback/platform.js'
|
|
4
5
|
import { decodeLatin1, encodeLatin1 } from './fallback/latin1.js'
|
|
5
6
|
import * as js from './fallback/base64.js'
|
|
6
7
|
|
|
@@ -34,10 +35,10 @@ function maybePad(res, padding) {
|
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
const toUrl = (x) => x.replaceAll('+', '-').replaceAll('/', '_')
|
|
37
|
-
const haveWeb = (x) =>
|
|
38
|
+
const haveWeb = (x) => web64 && x.toBase64 === web64
|
|
38
39
|
|
|
39
40
|
export function toBase64(x, { padding = true } = {}) {
|
|
40
|
-
|
|
41
|
+
assertU8(x)
|
|
41
42
|
if (haveWeb(x)) return padding ? x.toBase64() : x.toBase64({ omitPadding: !padding }) // Modern, optionless is slightly faster
|
|
42
43
|
if (haveNativeBuffer) return maybeUnpad(toBuffer(x).base64Slice(0, x.byteLength), padding) // Older Node.js
|
|
43
44
|
if (shouldUseBtoa) return maybeUnpad(btoa(decodeLatin1(x)), padding)
|
|
@@ -46,7 +47,7 @@ export function toBase64(x, { padding = true } = {}) {
|
|
|
46
47
|
|
|
47
48
|
// NOTE: base64url omits padding by default
|
|
48
49
|
export function toBase64url(x, { padding = false } = {}) {
|
|
49
|
-
|
|
50
|
+
assertU8(x)
|
|
50
51
|
if (haveWeb(x)) return x.toBase64({ alphabet: 'base64url', omitPadding: !padding }) // Modern
|
|
51
52
|
if (haveNativeBuffer) return maybePad(toBuffer(x).base64urlSlice(0, x.byteLength), padding) // Older Node.js
|
|
52
53
|
if (shouldUseBtoa) return maybeUnpad(toUrl(btoa(decodeLatin1(x))), padding)
|
|
@@ -111,7 +112,7 @@ function noWhitespaceSeen(str, arr) {
|
|
|
111
112
|
}
|
|
112
113
|
|
|
113
114
|
let fromBase64impl
|
|
114
|
-
if (
|
|
115
|
+
if (Uint8Array.fromBase64) {
|
|
115
116
|
// NOTICE: this is actually slower than our JS impl in older JavaScriptCore and (slightly) in SpiderMonkey, but faster on V8 and new JavaScriptCore
|
|
116
117
|
fromBase64impl = (str, isBase64url, padding) => {
|
|
117
118
|
const alphabet = isBase64url ? 'base64url' : 'base64'
|
package/bech32.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { nativeEncoder
|
|
1
|
+
import { assertU8, E_STRING } from './fallback/_utils.js'
|
|
2
|
+
import { nativeEncoder } from './fallback/platform.js'
|
|
3
3
|
import { decodeAscii, encodeAscii, encodeLatin1 } from './fallback/latin1.js'
|
|
4
4
|
|
|
5
5
|
const alphabet = [...'qpzry9x8gf2tvdw0s3jn54khce6mua7l']
|
|
@@ -109,7 +109,7 @@ function pPrefix(prefix) {
|
|
|
109
109
|
function toBech32enc(prefix, bytes, limit, encoding) {
|
|
110
110
|
if (typeof prefix !== 'string' || !prefix) throw new TypeError(E_PREFIX)
|
|
111
111
|
if (typeof limit !== 'number') throw new TypeError(E_SIZE)
|
|
112
|
-
|
|
112
|
+
assertU8(bytes)
|
|
113
113
|
const bytesLength = bytes.length
|
|
114
114
|
const wordsLength = Math.ceil((bytesLength * 8) / 5)
|
|
115
115
|
if (!(prefix.length + 7 + wordsLength <= limit)) throw new TypeError(E_SIZE)
|
|
@@ -1,10 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
fromSource,
|
|
3
|
-
getBOMEncoding,
|
|
4
|
-
normalizeEncoding,
|
|
5
|
-
E_ENCODING,
|
|
6
|
-
} from './fallback/encoding.api.js'
|
|
7
|
-
import labels from './fallback/encoding.labels.js'
|
|
1
|
+
import { getBOMEncoding } from './fallback/encoding.api.js'
|
|
8
2
|
|
|
9
3
|
// Lite-weight version which re-exports existing implementations on browsers,
|
|
10
4
|
// while still being aliased to the full impl in RN and Node.js
|
|
@@ -13,17 +7,49 @@ import labels from './fallback/encoding.labels.js'
|
|
|
13
7
|
|
|
14
8
|
const { TextDecoder, TextEncoder, TextDecoderStream, TextEncoderStream } = globalThis
|
|
15
9
|
|
|
16
|
-
export {
|
|
10
|
+
export { getBOMEncoding } from './fallback/encoding.api.js'
|
|
17
11
|
export { TextDecoder, TextEncoder, TextDecoderStream, TextEncoderStream }
|
|
18
12
|
|
|
19
|
-
|
|
13
|
+
export function normalizeEncoding(label) {
|
|
14
|
+
if (label === 'utf-8' || label === 'utf8' || label === 'UTF-8' || label === 'UTF8') return 'utf-8'
|
|
15
|
+
if (label === 'windows-1252' || label === 'ascii' || label === 'latin1') return 'windows-1252'
|
|
16
|
+
if (/[^\w\t\n\f\r .:-]/i.test(label)) return null
|
|
17
|
+
const l = `${label}`.trim().toLowerCase()
|
|
18
|
+
try {
|
|
19
|
+
return new TextDecoder(l).encoding
|
|
20
|
+
} catch {}
|
|
21
|
+
|
|
22
|
+
if (l === 'x-user-defined') return l
|
|
23
|
+
if (
|
|
24
|
+
l === 'replacement' ||
|
|
25
|
+
l === 'csiso2022kr' ||
|
|
26
|
+
l === 'hz-gb-2312' ||
|
|
27
|
+
l === 'iso-2022-cn' ||
|
|
28
|
+
l === 'iso-2022-cn-ext' ||
|
|
29
|
+
l === 'iso-2022-kr'
|
|
30
|
+
) {
|
|
31
|
+
return 'replacement'
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return null
|
|
35
|
+
}
|
|
36
|
+
|
|
20
37
|
export function legacyHookDecode(input, fallbackEncoding = 'utf-8') {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
38
|
+
const enc = getBOMEncoding(input) ?? normalizeEncoding(fallbackEncoding)
|
|
39
|
+
if (enc === 'replacement') return input.byteLength > 0 ? '\uFFFD' : ''
|
|
40
|
+
return new TextDecoder(enc).decode(input)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function labelToName(label) {
|
|
44
|
+
const enc = normalizeEncoding(label)
|
|
45
|
+
if (enc === 'utf-8') return 'UTF-8'
|
|
46
|
+
if (!enc) return enc
|
|
47
|
+
const p = enc.slice(0, 3)
|
|
48
|
+
if (p === 'utf' || p === 'iso' || p === 'koi' || p === 'euc' || p === 'ibm' || p === 'gbk') {
|
|
49
|
+
return enc.toUpperCase()
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (enc === 'big5') return 'Big5'
|
|
53
|
+
if (enc === 'shift_jis') return 'Shift_JIS'
|
|
54
|
+
return enc
|
|
29
55
|
}
|
package/fallback/_utils.js
CHANGED
|
@@ -1,131 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
const haveNativeBuffer = Buffer && !Buffer.TYPED_ARRAY_SUPPORT
|
|
3
|
-
export const nativeBuffer = haveNativeBuffer ? Buffer : null
|
|
4
|
-
export const isHermes = !!globalThis.HermesInternal
|
|
5
|
-
export const isDeno = !!globalThis.Deno
|
|
6
|
-
export const isLE = /* @__PURE__ */ (() => new Uint8Array(Uint16Array.of(258).buffer)[0] === 2)()
|
|
1
|
+
export * from './platform.js'
|
|
7
2
|
|
|
8
|
-
|
|
9
|
-
let isNative = (x) => x && (haveNativeBuffer || `${x}`.includes('[native code]'))
|
|
10
|
-
if (!haveNativeBuffer && isNative(() => {})) isNative = () => false // e.g. XS, we don't want false positives
|
|
11
|
-
|
|
12
|
-
export const nativeEncoder = isNative(TextEncoder) ? new TextEncoder() : null
|
|
13
|
-
export const nativeDecoder = isNative(TextDecoder)
|
|
14
|
-
? new TextDecoder('utf-8', { ignoreBOM: true })
|
|
15
|
-
: null
|
|
16
|
-
|
|
17
|
-
// Actually windows-1252, compatible with ascii and latin1 decoding
|
|
18
|
-
// Beware that on non-latin1, i.e. on windows-1252, this is broken in ~all Node.js versions released
|
|
19
|
-
// in 2025 due to a regression, so we call it Latin1 as it's usable only for that
|
|
20
|
-
const getNativeLatin1 = () => {
|
|
21
|
-
// Not all barebone engines with TextDecoder support something except utf-8, detect
|
|
22
|
-
if (nativeDecoder) {
|
|
23
|
-
try {
|
|
24
|
-
return new TextDecoder('latin1', { ignoreBOM: true })
|
|
25
|
-
} catch {}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return null
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export const nativeDecoderLatin1 = /* @__PURE__ */ getNativeLatin1()
|
|
32
|
-
|
|
33
|
-
// Block Firefox < 146 specifically from using native hex/base64, as it's very slow there
|
|
34
|
-
// Refs: https://bugzilla.mozilla.org/show_bug.cgi?id=1994067 (and linked issues), fixed in 146
|
|
35
|
-
// Before that, all versions of Firefox >= 133 are slow
|
|
36
|
-
// TODO: this could be removed when < 146 usage diminishes (note ESR)
|
|
37
|
-
// We do not worry about false-negatives here but worry about false-positives!
|
|
38
|
-
function shouldSkipBuiltins() {
|
|
39
|
-
const g = globalThis
|
|
40
|
-
// First, attempt to exclude as many things as we can using trivial checks, just in case, and to not hit ua
|
|
41
|
-
if (haveNativeBuffer || isHermes || !g.window || g.chrome || !g.navigator) return false
|
|
42
|
-
try {
|
|
43
|
-
// This was fixed specifically in Firefox 146. Other engines except Hermes (already returned) get this right
|
|
44
|
-
new WeakSet().add(Symbol()) // eslint-disable-line symbol-description
|
|
45
|
-
return false
|
|
46
|
-
} catch {
|
|
47
|
-
// In catch and not after in case if something too smart optimizes out code in try. False-negative is acceptable in that case
|
|
48
|
-
if (!('onmozfullscreenerror' in g)) return false // Firefox has it (might remove in the future, but we don't care)
|
|
49
|
-
return /firefox/i.test(g.navigator.userAgent || '') // as simple as we can
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/* c8 ignore next */
|
|
53
|
-
return false // eslint-disable-line no-unreachable
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export const skipWeb = /* @__PURE__ */ shouldSkipBuiltins()
|
|
57
|
-
|
|
58
|
-
function decodePartAddition(a, start, end, m) {
|
|
59
|
-
let o = ''
|
|
60
|
-
let i = start
|
|
61
|
-
for (const last3 = end - 3; i < last3; i += 4) {
|
|
62
|
-
const x0 = a[i]
|
|
63
|
-
const x1 = a[i + 1]
|
|
64
|
-
const x2 = a[i + 2]
|
|
65
|
-
const x3 = a[i + 3]
|
|
66
|
-
o += m[x0]
|
|
67
|
-
o += m[x1]
|
|
68
|
-
o += m[x2]
|
|
69
|
-
o += m[x3]
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
while (i < end) o += m[a[i++]]
|
|
73
|
-
return o
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Decoding with templates is faster on Hermes
|
|
77
|
-
function decodePartTemplates(a, start, end, m) {
|
|
78
|
-
let o = ''
|
|
79
|
-
let i = start
|
|
80
|
-
for (const last15 = end - 15; i < last15; i += 16) {
|
|
81
|
-
const x0 = a[i]
|
|
82
|
-
const x1 = a[i + 1]
|
|
83
|
-
const x2 = a[i + 2]
|
|
84
|
-
const x3 = a[i + 3]
|
|
85
|
-
const x4 = a[i + 4]
|
|
86
|
-
const x5 = a[i + 5]
|
|
87
|
-
const x6 = a[i + 6]
|
|
88
|
-
const x7 = a[i + 7]
|
|
89
|
-
const x8 = a[i + 8]
|
|
90
|
-
const x9 = a[i + 9]
|
|
91
|
-
const x10 = a[i + 10]
|
|
92
|
-
const x11 = a[i + 11]
|
|
93
|
-
const x12 = a[i + 12]
|
|
94
|
-
const x13 = a[i + 13]
|
|
95
|
-
const x14 = a[i + 14]
|
|
96
|
-
const x15 = a[i + 15]
|
|
97
|
-
o += `${m[x0]}${m[x1]}${m[x2]}${m[x3]}${m[x4]}${m[x5]}${m[x6]}${m[x7]}${m[x8]}${m[x9]}${m[x10]}${m[x11]}${m[x12]}${m[x13]}${m[x14]}${m[x15]}`
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
while (i < end) o += m[a[i++]]
|
|
101
|
-
return o
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
const decodePart = isHermes ? decodePartTemplates : decodePartAddition
|
|
105
|
-
export function decode2string(arr, start, end, m) {
|
|
106
|
-
if (end - start > 30_000) {
|
|
107
|
-
// Limit concatenation to avoid excessive GC
|
|
108
|
-
// Thresholds checked on Hermes for toHex
|
|
109
|
-
const concat = []
|
|
110
|
-
for (let i = start; i < end; ) {
|
|
111
|
-
const step = i + 500
|
|
112
|
-
const iNext = step > end ? end : step
|
|
113
|
-
concat.push(decodePart(arr, i, iNext, m))
|
|
114
|
-
i = iNext
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
const res = concat.join('')
|
|
118
|
-
concat.length = 0
|
|
119
|
-
return res
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
return decodePart(arr, start, end, m)
|
|
123
|
-
}
|
|
3
|
+
const Buffer = /* @__PURE__ */ (() => globalThis.Buffer)()
|
|
124
4
|
|
|
125
5
|
export function assert(condition, msg) {
|
|
126
6
|
if (!condition) throw new Error(msg)
|
|
127
7
|
}
|
|
128
8
|
|
|
9
|
+
export function assertU8(arg) {
|
|
10
|
+
if (!(arg instanceof Uint8Array)) throw new TypeError('Expected an Uint8Array')
|
|
11
|
+
}
|
|
12
|
+
|
|
129
13
|
// On arrays in heap (<= 64) it's cheaper to copy into a pooled buffer than lazy-create the ArrayBuffer storage
|
|
130
14
|
export const toBuf = (x) =>
|
|
131
15
|
x.byteLength <= 64 && x.BYTES_PER_ELEMENT === 1
|
|
@@ -133,3 +17,4 @@ export const toBuf = (x) =>
|
|
|
133
17
|
: Buffer.from(x.buffer, x.byteOffset, x.byteLength)
|
|
134
18
|
|
|
135
19
|
export const E_STRING = 'Input is not a string'
|
|
20
|
+
export const E_STRICT_UNICODE = 'Input is not well-formed Unicode'
|
package/fallback/base32.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { nativeEncoder, nativeDecoder, isHermes } from './
|
|
1
|
+
import { assertU8 } from './_utils.js'
|
|
2
|
+
import { nativeEncoder, nativeDecoder, isHermes } from './platform.js'
|
|
3
3
|
import { encodeAscii, decodeAscii } from './latin1.js'
|
|
4
4
|
|
|
5
5
|
// See https://datatracker.ietf.org/doc/html/rfc4648
|
|
@@ -18,7 +18,7 @@ const useTemplates = isHermes // Faster on Hermes and JSC, but we use it only on
|
|
|
18
18
|
|
|
19
19
|
// We construct output by concatenating chars, this seems to be fine enough on modern JS engines
|
|
20
20
|
export function toBase32(arr, isBase32Hex, padding) {
|
|
21
|
-
|
|
21
|
+
assertU8(arr)
|
|
22
22
|
const fullChunks = Math.floor(arr.length / 5)
|
|
23
23
|
const fullChunksBytes = fullChunks * 5
|
|
24
24
|
let o = ''
|
package/fallback/base58check.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { typedView } from '@exodus/bytes/array.js'
|
|
2
2
|
import { toBase58, fromBase58 } from '@exodus/bytes/base58.js'
|
|
3
|
-
import {
|
|
3
|
+
import { assertU8 } from './_utils.js'
|
|
4
4
|
|
|
5
5
|
const E_CHECKSUM = 'Invalid checksum'
|
|
6
6
|
|
|
@@ -28,7 +28,7 @@ function assertChecksum(c, r) {
|
|
|
28
28
|
export const makeBase58check = (hashAlgo, hashAlgoSync) => {
|
|
29
29
|
const apis = {
|
|
30
30
|
async encode(arr) {
|
|
31
|
-
|
|
31
|
+
assertU8(arr)
|
|
32
32
|
return encodeWithChecksum(arr, await hashAlgo(arr))
|
|
33
33
|
},
|
|
34
34
|
async decode(str, format = 'uint8') {
|
|
@@ -41,7 +41,7 @@ export const makeBase58check = (hashAlgo, hashAlgoSync) => {
|
|
|
41
41
|
return {
|
|
42
42
|
...apis,
|
|
43
43
|
encodeSync(arr) {
|
|
44
|
-
|
|
44
|
+
assertU8(arr)
|
|
45
45
|
return encodeWithChecksum(arr, hashAlgoSync(arr))
|
|
46
46
|
},
|
|
47
47
|
decodeSync(str, format = 'uint8') {
|
package/fallback/base64.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { nativeEncoder, nativeDecoder } from './_utils.js'
|
|
1
|
+
import { nativeEncoder, nativeDecoder } from './platform.js'
|
|
3
2
|
import { encodeAscii, decodeAscii } from './latin1.js'
|
|
4
3
|
|
|
5
4
|
// See https://datatracker.ietf.org/doc/html/rfc4648
|
|
@@ -15,8 +14,8 @@ export const E_LENGTH = 'Invalid base64 length'
|
|
|
15
14
|
export const E_LAST = 'Invalid last chunk'
|
|
16
15
|
|
|
17
16
|
// We construct output by concatenating chars, this seems to be fine enough on modern JS engines
|
|
17
|
+
// Expects a checked Uint8Array
|
|
18
18
|
export function toBase64(arr, isURL, padding) {
|
|
19
|
-
assertUint8(arr)
|
|
20
19
|
const fullChunks = (arr.length / 3) | 0
|
|
21
20
|
const fullChunksBytes = fullChunks * 3
|
|
22
21
|
let o = ''
|