platform.native.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  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. // We consider Node.js TextDecoder/TextEncoder native
  8. // Still needed in platform.native.js as this is re-exported to platform.js
  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. export const nativeEncoder = /* @__PURE__ */ (() =>
  12. isNative(globalThis.TextEncoder) ? new TextEncoder() : null)()
  13. export const nativeDecoder = /* @__PURE__ */ (() =>
  14. isNative(globalThis.TextDecoder) ? new TextDecoder('utf-8', { ignoreBOM: true }) : null)()
  15. // Actually windows-1252, compatible with ascii and latin1 decoding
  16. // Beware that on non-latin1, i.e. on windows-1252, this is broken in ~all Node.js versions released
  17. // in 2025 due to a regression, so we call it Latin1 as it's usable only for that
  18. export const nativeDecoderLatin1 = /* @__PURE__ */ (() => {
  19. // Not all barebone engines with TextDecoder support something except utf-8, detect
  20. if (nativeDecoder) {
  21. try {
  22. return new TextDecoder('latin1', { ignoreBOM: true })
  23. } catch {}
  24. }
  25. return null
  26. })()
  27. export function decodePartAddition(a, start, end, m) {
  28. let o = ''
  29. let i = start
  30. for (const last3 = end - 3; i < last3; i += 4) {
  31. const x0 = a[i]
  32. const x1 = a[i + 1]
  33. const x2 = a[i + 2]
  34. const x3 = a[i + 3]
  35. o += m[x0]
  36. o += m[x1]
  37. o += m[x2]
  38. o += m[x3]
  39. }
  40. while (i < end) o += m[a[i++]]
  41. return o
  42. }
  43. // Decoding with templates is faster on Hermes
  44. export function decodePartTemplates(a, start, end, m) {
  45. let o = ''
  46. let i = start
  47. for (const last15 = end - 15; i < last15; i += 16) {
  48. const x0 = a[i]
  49. const x1 = a[i + 1]
  50. const x2 = a[i + 2]
  51. const x3 = a[i + 3]
  52. const x4 = a[i + 4]
  53. const x5 = a[i + 5]
  54. const x6 = a[i + 6]
  55. const x7 = a[i + 7]
  56. const x8 = a[i + 8]
  57. const x9 = a[i + 9]
  58. const x10 = a[i + 10]
  59. const x11 = a[i + 11]
  60. const x12 = a[i + 12]
  61. const x13 = a[i + 13]
  62. const x14 = a[i + 14]
  63. const x15 = a[i + 15]
  64. 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]}`
  65. }
  66. while (i < end) o += m[a[i++]]
  67. return o
  68. }
  69. const decodePart = isHermes ? decodePartTemplates : decodePartAddition
  70. export function decode2string(arr, start, end, m) {
  71. if (end - start > 30_000) {
  72. // Limit concatenation to avoid excessive GC
  73. // Thresholds checked on Hermes for toHex
  74. const concat = []
  75. for (let i = start; i < end; ) {
  76. const step = i + 500
  77. const iNext = step > end ? end : step
  78. concat.push(decodePart(arr, i, iNext, m))
  79. i = iNext
  80. }
  81. const res = concat.join('')
  82. concat.length = 0
  83. return res
  84. }
  85. return decodePart(arr, start, end, m)
  86. }
  87. /* eslint-disable @exodus/mutable/no-param-reassign-prop-only */
  88. function encodeCharcodesHermes(str, arr) {
  89. const length = str.length
  90. if (length > 64) {
  91. const at = str.charCodeAt.bind(str) // faster on strings from ~64 chars on Hermes, but can be 10x slower on e.g. JSC
  92. for (let i = 0; i < length; i++) arr[i] = at(i)
  93. } else {
  94. for (let i = 0; i < length; i++) arr[i] = str.charCodeAt(i)
  95. }
  96. return arr
  97. }
  98. export function encodeCharcodesPure(str, arr) {
  99. const length = str.length
  100. // Can be optimized with unrolling, but this is not used on non-Hermes atm
  101. for (let i = 0; i < length; i++) arr[i] = str.charCodeAt(i)
  102. return arr
  103. }
  104. /* eslint-enable @exodus/mutable/no-param-reassign-prop-only */
  105. export const encodeCharcodes = isHermes ? encodeCharcodesHermes : encodeCharcodesPure