Skip to content

Commit b91b92c

Browse files
committed
refactor: move js decode api impl to fallback/utf16.js
1 parent 6754f84 commit b91b92c

File tree

2 files changed

+42
-51
lines changed

2 files changed

+42
-51
lines changed

fallback/utf16.js

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { decodeUCS2, encodeCharcodes } from './latin1.js'
2-
import { isLE, E_STRING, E_STRICT_UNICODE } from './_utils.js'
2+
import { nativeDecoder, isLE, E_STRING, E_STRICT_UNICODE } from './_utils.js'
33

44
export const E_STRICT = 'Input is not well-formed utf16'
55
const { TextDecoder } = globalThis
@@ -28,6 +28,12 @@ export function encodeApi(str, loose, format) {
2828
return format === 'uint16' ? u16 : new Uint8Array(u16.buffer, u16.byteOffset, u16.byteLength)
2929
}
3030

31+
const ignoreBOM = true
32+
const decFatalLE = nativeDecoder ? new TextDecoder('utf-16le', { ignoreBOM, fatal: true }) : null
33+
const decLooseLE = nativeDecoder ? new TextDecoder('utf-16le', { ignoreBOM }) : null
34+
const decFatalBE = nativeDecoder ? new TextDecoder('utf-16be', { ignoreBOM, fatal: true }) : null
35+
const decLooseBE = nativeDecoder ? new TextDecoder('utf-16be', { ignoreBOM }) : null
36+
3137
export function decodeApiDecoders(input, loose, format) {
3238
if (format === 'uint16') {
3339
if (!(input instanceof Uint16Array)) throw new TypeError('Expected an Uint16Array')
@@ -38,8 +44,36 @@ export function decodeApiDecoders(input, loose, format) {
3844
throw new TypeError('Unknown format')
3945
}
4046

41-
const encoding = format === 'uint8-le' || (format === 'uint16' && isLE) ? 'utf-16le' : 'utf-16be'
42-
return new TextDecoder(encoding, { ignoreBOM: true, fatal: !loose }).decode(input)
47+
const le = format === 'uint8-le' || (format === 'uint16' && isLE)
48+
return (le ? (loose ? decLooseLE : decFatalLE) : loose ? decLooseBE : decFatalBE).decode(input)
49+
}
50+
51+
export function decodeApiJS(input, loose, format) {
52+
let u16
53+
switch (format) {
54+
case 'uint16':
55+
if (!(input instanceof Uint16Array)) throw new TypeError('Expected an Uint16Array')
56+
u16 = input
57+
break
58+
case 'uint8-le':
59+
if (!(input instanceof Uint8Array)) throw new TypeError('Expected an Uint8Array')
60+
if (input.byteLength % 2 !== 0) throw new TypeError('Expected even number of bytes')
61+
u16 = to16input(input, true)
62+
break
63+
case 'uint8-be':
64+
if (!(input instanceof Uint8Array)) throw new TypeError('Expected an Uint8Array')
65+
if (input.byteLength % 2 !== 0) throw new TypeError('Expected even number of bytes')
66+
u16 = to16input(input, false)
67+
break
68+
default:
69+
throw new TypeError('Unknown format')
70+
}
71+
72+
const str = decode(u16, loose, (!loose && isWellFormedStr) || (loose && isWellFormedStr))
73+
if (!loose && isWellFormedStr && !isWellFormedStr.call(str)) throw new TypeError(E_STRICT)
74+
if (loose && isWellFormedStr) return isWellFormedStr.call(str)
75+
76+
return str
4377
}
4478

4579
export function to16input(u8, le) {

utf16.native.js

Lines changed: 5 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import * as js from './fallback/utf16.js'
2-
import { nativeDecoder, isLE } from './fallback/_utils.js'
1+
import { encodeApi, decodeApiDecoders, decodeApiJS } from './fallback/utf16.js'
2+
import { nativeDecoder } from './fallback/_utils.js'
33

44
function checkDecoders() {
55
// Not all barebone engines with TextDecoder support something except utf-8
@@ -14,52 +14,9 @@ function checkDecoders() {
1414
return false
1515
}
1616

17-
const canDecoders = checkDecoders()
18-
const ignoreBOM = true
19-
const decoderFatalLE = canDecoders ? new TextDecoder('utf-16le', { ignoreBOM, fatal: true }) : null
20-
const decoderLooseLE = canDecoders ? new TextDecoder('utf-16le', { ignoreBOM }) : null
21-
const decoderFatalBE = canDecoders ? new TextDecoder('utf-16be', { ignoreBOM, fatal: true }) : null
22-
const decoderLooseBE = canDecoders ? new TextDecoder('utf-16be', { ignoreBOM }) : null
23-
const decoderFatal16 = isLE ? decoderFatalLE : decoderFatalBE
24-
const decoderLoose16 = isLE ? decoderLooseLE : decoderLooseBE
25-
const { isWellFormed, toWellFormed } = String.prototype
17+
const decode = checkDecoders() ? decodeApiDecoders : decodeApiJS
2618

27-
const { E_STRICT } = js
28-
29-
// Unlike utf8, operates on Uint16Arrays by default
30-
31-
function decode(input, loose = false, format = 'uint16') {
32-
let u16
33-
switch (format) {
34-
case 'uint16':
35-
if (!(input instanceof Uint16Array)) throw new TypeError('Expected an Uint16Array')
36-
if (canDecoders) return loose ? decoderLoose16.decode(input) : decoderFatal16.decode(input)
37-
u16 = input
38-
break
39-
case 'uint8-le':
40-
if (!(input instanceof Uint8Array)) throw new TypeError('Expected an Uint8Array')
41-
if (input.byteLength % 2 !== 0) throw new TypeError('Expected even number of bytes')
42-
if (canDecoders) return loose ? decoderLooseLE.decode(input) : decoderFatalLE.decode(input)
43-
u16 = js.to16input(input, true)
44-
break
45-
case 'uint8-be':
46-
if (!(input instanceof Uint8Array)) throw new TypeError('Expected an Uint8Array')
47-
if (input.byteLength % 2 !== 0) throw new TypeError('Expected even number of bytes')
48-
if (canDecoders) return loose ? decoderLooseBE.decode(input) : decoderFatalBE.decode(input)
49-
u16 = js.to16input(input, false)
50-
break
51-
default:
52-
throw new TypeError('Unknown format')
53-
}
54-
55-
const str = js.decode(u16, loose, (!loose && isWellFormed) || (loose && toWellFormed))
56-
if (!loose && isWellFormed && !isWellFormed.call(str)) throw new TypeError(E_STRICT)
57-
if (loose && toWellFormed) return toWellFormed.call(str)
58-
59-
return str
60-
}
61-
62-
export const utf16fromString = (str, format = 'uint16') => js.encodeApi(str, false, format)
63-
export const utf16fromStringLoose = (str, format = 'uint16') => js.encodeApi(str, true, format)
19+
export const utf16fromString = (str, format = 'uint16') => encodeApi(str, false, format)
20+
export const utf16fromStringLoose = (str, format = 'uint16') => encodeApi(str, true, format)
6421
export const utf16toString = (arr, format = 'uint16') => decode(arr, false, format)
6522
export const utf16toStringLoose = (arr, format = 'uint16') => decode(arr, true, format)

0 commit comments

Comments
 (0)