fix(js): match Chromium data URL handling

This commit is contained in:
SGavrl committed 2026-07-30 21:40:13 +00:00
1 parent 0c4740a86a
commit f84120591e
2 files changed
+97 -31

No files matched your search

+42 -28
View File
@@ -164,35 +164,49 @@ let _fpSeed = 0;
let __dynScriptQueue = [];
let __dynScriptBusy = false;
function _decodeDataScriptUrl(url) {
let parsed;
try { parsed = new URL(url); }
catch(e) { throw new TypeError('Invalid dynamic script data URL'); }
const path = parsed.pathname;
const comma = path.indexOf(',');
if (comma < 0) throw new TypeError('Invalid dynamic script data URL');
const parts = path.slice(0, comma).split(';');
const mime = parts.shift().trim().toLowerCase();
const isJavaScript = mime === 'application/ecmascript' ||
mime === 'application/javascript' || mime === 'application/x-ecmascript' ||
mime === 'application/x-javascript' || mime === 'text/ecmascript' ||
mime === 'text/javascript' || /^text\/javascript1\.[0-5]$/.test(mime) ||
mime === 'text/jscript' || mime === 'text/livescript' ||
mime === 'text/x-ecmascript' || mime === 'text/x-javascript';
if (!isJavaScript) throw new TypeError('Unsupported dynamic script data URL MIME type');
let payload = path.slice(comma + 1);
try { payload = decodeURIComponent(payload); }
catch(e) { throw new TypeError('Invalid dynamic script data URL encoding'); }
const isBase64 = parts.some((part) => part.trim().toLowerCase() === 'base64');
if (!isBase64) return payload;
const clean = payload.replace(/[\r\n\s]/g, '');
if (!/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(clean)) {
throw new TypeError('Invalid dynamic script data URL base64');
const comma = url.indexOf(',');
if (!url.startsWith('data:') || comma < 5) {
throw new TypeError('Invalid dynamic script data URL');
}
return new TextDecoder().decode(_base64ToUint8Array(clean));
const meta = url.slice(5, comma);
const fragment = url.indexOf('#', comma + 1);
const payload = url.slice(comma + 1, fragment < 0 ? url.length : fragment);
if (meta.split(';').some(part => part.toLowerCase() === 'base64')) {
let encoded = payload.replace(/[\r\n\t\f ]/g, '');
const remainder = encoded.length % 4;
if (remainder === 1 || !/^[A-Za-z0-9+/]*={0,2}$/.test(encoded) || /=/.test(encoded.slice(0, -2))) {
throw new TypeError('Invalid dynamic script data URL base64');
}
if (remainder > 0) encoded += '='.repeat(4 - remainder);
if (!/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(encoded)) {
throw new TypeError('Invalid dynamic script data URL base64');
}
return new TextDecoder().decode(_base64ToUint8Array(encoded));
}
const bytes = [];
for (let i = 0; i < payload.length; i++) {
const code = payload.charCodeAt(i);
if (code === 0x25 && i + 2 < payload.length) {
const hi = _hexv(payload.charCodeAt(i + 1));
const lo = _hexv(payload.charCodeAt(i + 2));
if (hi >= 0 && lo >= 0) {
bytes.push(hi * 16 + lo);
i += 2;
continue;
}
}
if (code < 0x80) {
bytes.push(code);
} else {
const character = String.fromCodePoint(payload.codePointAt(i));
if (character.length === 2) i++;
const encoded = new TextEncoder().encode(character);
for (let j = 0; j < encoded.length; j++) bytes.push(encoded[j]);
}
}
return new TextDecoder().decode(new Uint8Array(bytes));
}
async function __processDynScriptQueue() {
if (__dynScriptBusy) return;