Greasy Fork

Greasy Fork is available in English.

Picarto Polyfills for older browsers like FF52

Restore some compatibility between Picarto and older browsers (like FF 52) -- StevenRoy

当前为 2024-10-19 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name        Picarto Polyfills for older browsers like FF52
// @namespace   http://michrev.com/
// @description Restore some compatibility between Picarto and older browsers (like FF 52) -- StevenRoy
// @include     https://www.picarto.tv/*
// @include     https://picarto.tv/*
// @include     https://www.picarto.tv
// @include     https://picarto.tv
// @version     2.001
// @run-at document-start
// @grant       GM_xmlhttpRequest
// ==/UserScript==
"use strict";

//     _____________  __    __
//    / ___________/ /  \,-' /
//   / /__    ___   / /\,-/ /
//   \___ \  / __\ / /   / /
//______/ / / /   / /   / /
//_______/ /_/   /_/   /_/



// This is what "spread syntax" in object literals looks like:
// {...r, r:e, g:t, b:n}
// { ...methods, r, g, b }
// But because that feature doesn't exist in the latest FF for 32-bit Windows, it needs to be converted.
// (It didn't exist until 2018 and every major browser stopped updating long before then. Screw them.)

// These examples become:
// Object.assign({},r,{r:e, g:t, b:n})
// Object.assign({},methods,{ r, g, b })

// There's a similar feature for arrays but -that- is already supported! Go figure.

function grabscript(url){
	console.log("Fetching:",url);
	var response=GM_xmlhttpRequest({
		method: "GET",
		url: url,
		synchronous: true // Imagine trying to make this script without this feature.
	});
	if (!response.responseText) { throw("Something stupid happened while trying to load:",url,response); }
	console.log('Script fetched, length:'+response.responseText.length);
	return response.responseText;
}

// This adds (actually re-adds) a script to the current page so it can run.
function addScript(text) {
	var newScript = document.createElement('script');
	newScript.type = "text/javascript";
	newScript.textContent = text;
	var head = document.getElementsByTagName('head')[0];
//	console.log("We're adding the thing, length:",text.length);
	head.appendChild(newScript);
//	console.log('We added the thing, length:',text.length);
	return newScript;
}

unsafeWindow.String.prototype.trimStart=unsafeWindow.String.prototype.trimLeft;
unsafeWindow.String.prototype.trimEnd=unsafeWindow.String.prototype.trimRight;
unsafeWindow.URL.canParse=exportFunction(function canParse(url) {
    var base = arguments.length < 2 || arguments[1] === undefined ? undefined : arguments[1];
    try {
      return !!new URL(url, base);
    } catch (error) {
      return false;
    }
  },unsafeWindow);


// So, here's the deal:

// On other pages, I could just use beforescriptexecute to intercept problem scripts,
// fix the syntax error with a single responseText.replace(), then re-add it.

// In this case, the script I need to intercept isn't loaded like a script!
// When something is loaded using the Worker object, beforescriptexecute does NOTHING!

// So I tried to edit the Worker constructor, using ES6 subclasses and exportFunction
// to create a version of the object that could load, edit and inject the fixed code. That was hard...

// I came so dang close to that actually working, too, but started running into
// Error: Permission denied to access property "addEventListener"
// ...Seems pages can't access Worker objects loaded from blobs created in userscripts
// because of some "same-origin security" bull.
// I spent so many frustrating hours trying to find a way around that...

// Finally I decided, I had to try a different approach, and I got creative:

window.addEventListener('beforescriptexecute', function(e) {
	var src = e.target.src;
	console.log("Checking script:"+(src?src:"(unknown)"));
	if (src && src.search(/\/static\/js\/1\.[0-9a-f]+\.chunk\.js/) != -1) { // static/js/1.b2dade89.chunk.js
		console.log('Intercepted probable chat script'); // This is the script that loads the Worker
		var onl=e.target.onload; // There's a callback when the script loads. We gotta keep the callback when we replace the script!
//		console.log('onload:',onl);
		e.target.onload=e.target.onerror=null; // Prevent the onerror handler when we cancel this.
		e.preventDefault();
		e.stopPropagation();
		var scr=grabscript(src); // load the script so we can edit it...
		// Original code: _=new Worker("/chatworker.min.js?ver=".concat(m.l)),
console.log('grabbed, adding');
		scr=addScript("window.AAA=1;console.log('Running edited script');\n"+scr.replace(/new Worker/g,"editedWorker")+"\n\n"+
// And now that script has the function that does the loading, editing, and fixing of the other script...
		'function editedWorker(n){console.log("Fetching worker: "+n);var d=new XMLHttpRequest(); d.open("GET","https://picarto.tv"+n,false); d.send(null);'+
'console.log("Fetch status:"+d.status);'+
			'd=d.responseText.replace(/\\{\\.\\.\\.([^,}]+)(?:,([^}]+))?\\}/g,(m,p1,p2)=>{return "Object.assign({},"+p1+(p2? ",{"+p2+"}" :"")+")";})'+
			'.replace(/importScripts\\("([a-z.]+)"\\)[,;]/g,(m,p1)=>{'+
				'return \'importScripts("https://picarto.tv/\'+p1+\'");\'; // absolute paths required here for some stupid reason\n'+
			'});'+

			'return new Worker(URL.createObjectURL(new Blob(["console.log(\'Fixed worker running - SrM was here\');\\n"+d ])));'+
		'}');
console.log('added');
		if (window.AAA) { onl(); } else { scr.onload=scr.onerror=onl; } // New script, same callback
	}
});