|
1 | | -const { Buffer } = globalThis |
2 | | -const haveNativeBuffer = Buffer && !Buffer.TYPED_ARRAY_SUPPORT |
3 | | -export const nativeBuffer = haveNativeBuffer ? Buffer : null |
4 | | -export const isHermes = /* @__PURE__ */ (() => !!globalThis.HermesInternal)() |
5 | | -export const isDeno = /* @__PURE__ */ (() => !!globalThis.Deno)() |
6 | | -export const isLE = /* @__PURE__ */ (() => new Uint8Array(Uint16Array.of(258).buffer)[0] === 2)() |
7 | | - |
8 | | -// We consider Node.js TextDecoder/TextEncoder native |
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 = /* @__PURE__ */ (() => |
13 | | - isNative(globalThis.TextEncoder) ? new TextEncoder() : null)() |
14 | | -export const nativeDecoder = /* @__PURE__ */ (() => |
15 | | - isNative(globalThis.TextDecoder) ? new TextDecoder('utf-8', { ignoreBOM: true }) : 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 | | -export const nativeDecoderLatin1 = /* @__PURE__ */ (() => { |
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 | | -// Block Firefox < 146 specifically from using native hex/base64, as it's very slow there |
32 | | -// Refs: https://bugzilla.mozilla.org/show_bug.cgi?id=1994067 (and linked issues), fixed in 146 |
33 | | -// Before that, all versions of Firefox >= 133 are slow |
34 | | -// TODO: this could be removed when < 146 usage diminishes (note ESR) |
35 | | -// We do not worry about false-negatives here but worry about false-positives! |
36 | | -function shouldSkipBuiltins() { |
37 | | - const g = globalThis |
38 | | - // First, attempt to exclude as many things as we can using trivial checks, just in case, and to not hit ua |
39 | | - if (haveNativeBuffer || isHermes || !g.window || g.chrome || !g.navigator) return false |
40 | | - try { |
41 | | - // This was fixed specifically in Firefox 146. Other engines except Hermes (already returned) get this right |
42 | | - new WeakSet().add(Symbol()) // eslint-disable-line symbol-description |
43 | | - return false |
44 | | - } catch { |
45 | | - // In catch and not after in case if something too smart optimizes out code in try. False-negative is acceptable in that case |
46 | | - if (!('onmozfullscreenerror' in g)) return false // Firefox has it (might remove in the future, but we don't care) |
47 | | - return /firefox/i.test(g.navigator.userAgent || '') // as simple as we can |
48 | | - } |
49 | | - |
50 | | - /* c8 ignore next */ |
51 | | - return false // eslint-disable-line no-unreachable |
52 | | -} |
53 | | - |
54 | | -export const skipWeb = /* @__PURE__ */ shouldSkipBuiltins() |
55 | | - |
56 | | -function decodePartAddition(a, start, end, m) { |
57 | | - let o = '' |
58 | | - let i = start |
59 | | - for (const last3 = end - 3; i < last3; i += 4) { |
60 | | - const x0 = a[i] |
61 | | - const x1 = a[i + 1] |
62 | | - const x2 = a[i + 2] |
63 | | - const x3 = a[i + 3] |
64 | | - o += m[x0] |
65 | | - o += m[x1] |
66 | | - o += m[x2] |
67 | | - o += m[x3] |
68 | | - } |
69 | | - |
70 | | - while (i < end) o += m[a[i++]] |
71 | | - return o |
72 | | -} |
73 | | - |
74 | | -// Decoding with templates is faster on Hermes |
75 | | -function decodePartTemplates(a, start, end, m) { |
76 | | - let o = '' |
77 | | - let i = start |
78 | | - for (const last15 = end - 15; i < last15; i += 16) { |
79 | | - const x0 = a[i] |
80 | | - const x1 = a[i + 1] |
81 | | - const x2 = a[i + 2] |
82 | | - const x3 = a[i + 3] |
83 | | - const x4 = a[i + 4] |
84 | | - const x5 = a[i + 5] |
85 | | - const x6 = a[i + 6] |
86 | | - const x7 = a[i + 7] |
87 | | - const x8 = a[i + 8] |
88 | | - const x9 = a[i + 9] |
89 | | - const x10 = a[i + 10] |
90 | | - const x11 = a[i + 11] |
91 | | - const x12 = a[i + 12] |
92 | | - const x13 = a[i + 13] |
93 | | - const x14 = a[i + 14] |
94 | | - const x15 = a[i + 15] |
95 | | - 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]}` |
96 | | - } |
97 | | - |
98 | | - while (i < end) o += m[a[i++]] |
99 | | - return o |
100 | | -} |
101 | | - |
102 | | -const decodePart = isHermes ? decodePartTemplates : decodePartAddition |
103 | | -export function decode2string(arr, start, end, m) { |
104 | | - if (end - start > 30_000) { |
105 | | - // Limit concatenation to avoid excessive GC |
106 | | - // Thresholds checked on Hermes for toHex |
107 | | - const concat = [] |
108 | | - for (let i = start; i < end; ) { |
109 | | - const step = i + 500 |
110 | | - const iNext = step > end ? end : step |
111 | | - concat.push(decodePart(arr, i, iNext, m)) |
112 | | - i = iNext |
113 | | - } |
114 | | - |
115 | | - const res = concat.join('') |
116 | | - concat.length = 0 |
117 | | - return res |
118 | | - } |
119 | | - |
120 | | - return decodePart(arr, start, end, m) |
121 | | -} |
| 1 | +// it's safe even if bundler does not follow browser resolution for browser and skipWeb misdetects |
| 2 | +export * from './platform.native.js' |
0 commit comments