149 lines
4.2 KiB
JavaScript
149 lines
4.2 KiB
JavaScript
/** TextEncoder/TextDecoder when missing on globalThis (Bare/Pear guest eval). */
|
|
|
|
/**
|
|
* @param {Uint8Array} bytes
|
|
*/
|
|
function bareAgentUtf8Decode(bytes) {
|
|
let out = ''
|
|
let i = 0
|
|
const len = bytes.length
|
|
while (i < len) {
|
|
const b0 = bytes[i++]
|
|
if (b0 < 0x80) {
|
|
out += String.fromCharCode(b0)
|
|
continue
|
|
}
|
|
if ((b0 & 0xe0) === 0xc0) {
|
|
if (i >= len || (bytes[i] & 0xc0) !== 0x80) {
|
|
out += '\ufffd'
|
|
continue
|
|
}
|
|
const b1 = bytes[i++]
|
|
const cp = ((b0 & 0x1f) << 6) | (b1 & 0x3f)
|
|
if (cp < 0x80) out += '\ufffd'
|
|
else out += String.fromCharCode(cp)
|
|
continue
|
|
}
|
|
if ((b0 & 0xf0) === 0xe0) {
|
|
if (i + 1 >= len || (bytes[i] & 0xc0) !== 0x80 || (bytes[i + 1] & 0xc0) !== 0x80) {
|
|
out += '\ufffd'
|
|
continue
|
|
}
|
|
const b1 = bytes[i++]
|
|
const b2 = bytes[i++]
|
|
let cp = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f)
|
|
if (cp < 0x800 || (cp >= 0xd800 && cp <= 0xdfff)) out += '\ufffd'
|
|
else out += String.fromCharCode(cp)
|
|
continue
|
|
}
|
|
if ((b0 & 0xf8) === 0xf0) {
|
|
if (
|
|
i + 2 >= len ||
|
|
(bytes[i] & 0xc0) !== 0x80 ||
|
|
(bytes[i + 1] & 0xc0) !== 0x80 ||
|
|
(bytes[i + 2] & 0xc0) !== 0x80
|
|
) {
|
|
out += '\ufffd'
|
|
continue
|
|
}
|
|
const b1 = bytes[i++]
|
|
const b2 = bytes[i++]
|
|
const b3 = bytes[i++]
|
|
let cp =
|
|
((b0 & 0x07) << 18) |
|
|
((b1 & 0x3f) << 12) |
|
|
((b2 & 0x3f) << 6) |
|
|
(b3 & 0x3f)
|
|
if (cp < 0x10000 || cp > 0x10ffff) out += '\ufffd'
|
|
else {
|
|
cp -= 0x10000
|
|
out += String.fromCharCode(0xd800 + (cp >> 10), 0xdc00 + (cp & 0x3ff))
|
|
}
|
|
continue
|
|
}
|
|
out += '\ufffd'
|
|
}
|
|
return out
|
|
}
|
|
|
|
/**
|
|
* @param {string} str
|
|
*/
|
|
function bareAgentUtf8Encode(str) {
|
|
const out = []
|
|
for (let i = 0; i < str.length; i++) {
|
|
let c = str.charCodeAt(i)
|
|
if (c < 0x80) {
|
|
out.push(c)
|
|
} else if (c < 0x800) {
|
|
out.push(0xc0 | (c >> 6), 0x80 | (c & 0x3f))
|
|
} else if (c >= 0xd800 && c <= 0xdbff && i + 1 < str.length) {
|
|
const c2 = str.charCodeAt(i + 1)
|
|
if ((c2 & 0xfc00) === 0xdc00) {
|
|
i++
|
|
const cp = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff)
|
|
out.push(
|
|
0xf0 | (cp >> 18),
|
|
0x80 | ((cp >> 12) & 0x3f),
|
|
0x80 | ((cp >> 6) & 0x3f),
|
|
0x80 | (cp & 0x3f)
|
|
)
|
|
} else {
|
|
out.push(0xe0 | (c >> 12), 0x80 | ((c >> 6) & 0x3f), 0x80 | (c & 0x3f))
|
|
}
|
|
} else if (c < 0xd800 || c >= 0xe000) {
|
|
out.push(0xe0 | (c >> 12), 0x80 | ((c >> 6) & 0x3f), 0x80 | (c & 0x3f))
|
|
}
|
|
}
|
|
return new Uint8Array(out)
|
|
}
|
|
|
|
function bareAgentEnsureTextCodecPolyfill() {
|
|
const g =
|
|
typeof globalThis !== 'undefined'
|
|
? globalThis
|
|
: typeof global !== 'undefined'
|
|
? global
|
|
: typeof self !== 'undefined'
|
|
? self
|
|
: /** @type {Record<string, unknown>} */ ({})
|
|
|
|
if (typeof g.TextDecoder !== 'function') {
|
|
function BareTextDecoder() {
|
|
/** @type {'utf-8'} */
|
|
this.encoding = 'utf-8'
|
|
}
|
|
BareTextDecoder.prototype.decode = function (input, options) {
|
|
let u8
|
|
if (input instanceof Uint8Array) u8 = input
|
|
else if (typeof ArrayBuffer !== 'undefined' && input instanceof ArrayBuffer)
|
|
u8 = new Uint8Array(input)
|
|
else if (input != null && typeof input === 'object' && 'length' in input) {
|
|
u8 = new Uint8Array(/** @type {ArrayLike<number>} */ (input))
|
|
} else if (input == null || input === undefined) {
|
|
return ''
|
|
} else {
|
|
return ''
|
|
}
|
|
const stream = !!(options && options.stream)
|
|
void stream
|
|
return bareAgentUtf8Decode(u8)
|
|
}
|
|
if (typeof globalThis !== 'undefined') globalThis.TextDecoder = BareTextDecoder
|
|
else g.TextDecoder = BareTextDecoder
|
|
}
|
|
|
|
if (typeof g.TextEncoder !== 'function') {
|
|
function BareTextEncoder() {
|
|
this.encoding = 'utf-8'
|
|
}
|
|
BareTextEncoder.prototype.encode = function (input) {
|
|
return bareAgentUtf8Encode(String(input == null ? '' : input))
|
|
}
|
|
if (typeof globalThis !== 'undefined') globalThis.TextEncoder = BareTextEncoder
|
|
else g.TextEncoder = BareTextEncoder
|
|
}
|
|
}
|
|
|
|
bareAgentEnsureTextCodecPolyfill()
|