您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
none
// ==UserScript== // @name lib:strict // @version 7 // @description none // @run-at document-start // @author rssaromeo // @license GPLv3 // @tag lib // @match *://*/* // @include * // @exclude /livereload.net\/files\/ffopen\/index.html$/ // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAMAAABiM0N1AAAAAXNSR0IB2cksfwAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAHJQTFRFAAAAEIijAo2yAI60BYyuF4WaFIifAY6zBI2wB4usGIaZEYigIoiZCIyrE4igG4iYD4mjEomhFoedCoqpDIqnDomlBYyvE4efEYmiDYqlA42xBoytD4mkCYqqGYSUFYidC4qoC4upAo6yCoupDYqmCYur4zowOQAAACZ0Uk5TAO////9vr////1+/D/+/L+/Pf/////+f3///////H4////////+5G91rAAACgUlEQVR4nM2Y22KjIBCGidg1264liZqDadK03X3/V2wNKHMC7MpF/xthHD5mgERAqZhWhfYqH6K+Qf2qNNf625hCoFj9/gblMUi5q5jLkXLCKudgyiRm0FMK82cWJp1fLbV5VmvJbCIc0GCYaFqqlDJgADdBjncqAXYobm1xh72aFMflbysteFfdy2Yi1XGOm5HGBzQ1dq7TzEoxjeNTjQZb7VA3e1c7+ImgasAgQ9+xusNVNZIo5xmOMgihIS2PbCQIiHEUdTvhxCcS/kPomfFI2zHy2PkWmA6aNatIJpKFJyekyy02xh5Y3DI9T4aOT6VhIUrsNTFp1pf79Z4SIIVDegl6IJO6cHiL/GimIZDhgTu/BlYWCQzHMl0zBWT/T3KAhtxOuUB9FtBrpsz0RV4xsjHmW+UCaffcSy/5viMGer0/6HdFNMZBq/vjJL38H9Dqx4Fuy0Em12DbZy+9pGtiDijbglwAehyj11n0tRD3WUBm+lwulE/8h4BuA+iWAQQnteg2Xm63WQLTpnMnpjdge0Mgu/GRPsV4xdjQ94Lfi624fabhDkfUqIKNrM64Q837v8yL0prasepCgrtvw1sJpoqanGEX7b5mQboNW8eawXaWXTMfMGxub472hzWzHSn6Sg2G9+6TAyRruE71s+zAzjWaknoyJCQzwxrghH2k5FDT4eqWunuNxyN9QCGcxVod5oADbYnIUkDTGZEf1xDJnSFteQ3KdsT8zYDMQXcHxsevcLH1TrsABzkNPyA/L7b0jg704viMMlpQI96WsHknCt/3YH0kOEo9zcGkwrFK39ck72rmoehmKqo2RKlilzSy/nJKEV45CT38myJp456fezktHjN5aeMAAAAASUVORK5CYII= // @grant none // @namespace https://greasyfork.org/users/1184528 // ==/UserScript== ;(() => { const a = loadlib("allfuncs") function testformat( obj, format, options = { allowextras: false, extrastype: undefined, allowconversions: false, logerror: true, allowunset: false, throwerror: true, insideextras: undefined, }, insideextras ) { if (options.extrastype) { if (a.gettype(options.extrastype, "string")) { options.extrastype = options.extrastype.split("|") } } if (options.allowunset) options.extrastype.push("none") var isvalid = true var unsets = [] if (insideextras) { for (var i = 0; i < Object.keys(obj).length; i++) { format.push(insideextras) } } format.find( ( { name, prop = name, type, inside, insideoptions = {}, value = [], insideextras, }, i ) => { prop ??= String(i) if (insideextras) inside ??= [] insideoptions = { ...options, ...insideoptions } var realvalue = obj[prop] if (a.gettype(type, "string")) { type = type.split("|") } if (options.allowunset) type.push("none") if (!a.gettype(realvalue, type)) { if (options.allowconversions) { if ( type.find((type) => { if (settype.test(realvalue, type)) { obj[prop] = settype(realvalue, type) return true } }) ) { return false } if (type.includes("any")) return false } if (!type.includes(obj[prop])) if (options.logerror) { if (!(prop in obj)) error( `the object is missing the property "${prop}". the property "${prop}" should have a type of "${type.join( "|" )}"` ) else error( `the value "${prop}" is of type "${a.gettype( obj[prop] )}" when it should be a type of "${type.join("|")}"` ) error("missing or invalid peram type", { prop, obj, type, }) } if (options.throwerror) throw new Error("missing or invalid peram type") isvalid = false return true } if (!(prop in obj)) unsets.push(prop) if (inside) { if ( !testformat( realvalue, inside, insideoptions, insideextras ) ) { if (options.logerror) error("invalid inside", { obj }) if (options.throwerror) throw new Error("invalid inside") isvalid = false return true } } } ) var objnames = [...Object.keys(obj), ...unsets] var formatnames = Object.values(format).map( (e, i) => e.name ?? String(i) ) var extras = objnames.filter( (prop) => !formatnames.includes(prop) ) if (!options.allowextras) { if (extras.length) { if (options.logerror) { error( `the object has the following extra properties: ${JSON.stringify( extras )}` ) error("extras found when allowextras is false", { obj, objnames, formatnames, }) } if (options.throwerror) throw new Error("extras found when allowextras is false") isvalid = false } } if (extras?.[0]?.name == "__extras") { var extras = extras[0] extras.shift() if (!testformat(obj.inside, obj.__extras, options)) { isvalid = false return true } } if (options.extrastype) { extras.find((prop) => { if (!a.gettype(obj[prop], options.extrastype)) { if (options.allowconversions) { if ( options.extrastype.find((type) => { if (settype.test(obj[prop], type)) { obj[prop] = settype(obj[prop], type) return true } }) ) { return false } if (options.extrastype.includes("any")) return false } isvalid = false return true } }) } return isvalid } function strictfunction(func, types, options = {}) { if (!!options === options) options = { allowconversions: options } return function (...args) { if ( !testformat((args = [...args]), types, { ...options, throwerror: true, logerror: true, }) ) throw new Error("error when calling function") return func.call(this, ...args) } } function setformat(obj, options = {}) { if (obj[Symbol.for("setformat")]) obj = { ...obj } return new Proxy(obj, { get(_obj, prop) { if (prop == Symbol.for("setformat")) return true if (prop == Symbol.for("options")) return options return Reflect.get(_obj, prop) }, }) } var entire_object function newtestformat( obj, format, tempoptions = { allowextras: false, extrasformat: {}, functionname: "no name given", // allowconversions: false, } ) { entire_object ??= obj var extrakeys = [] var options = { ...tempoptions, ...format[Symbol.for("options")] } for (var objkey of Object.keys(obj)) { if (!(objkey in format)) if (options.allowextras) extrakeys.push(objkey) else throw new Error( error("object has extra key", { function_name: options.functionname, extra_key: objkey, format, obj, entire_object, }) ) } for (var [formatkey, formatval] of Object.entries(format)) { checkformat(formatkey, formatval) } function checkformat(formatkey, formatval) { let currentcomparevalue = obj[formatkey] if (formatval[Symbol.for("condfunc")]) formatval = formatval(obj, entire_object) if (!a.gettype(obj, ["object", "array"])) throw new Error( error(`obj is not an object`, { function_name: options.functionname, object_is_instead: obj, trying_to_read_property: formatkey, entire_object, }) ) if (!(formatkey in obj)) if ( (formatval && formatval[Symbol.for("optional")]) || (formatval.type && formatval.type.includes("none")) || (formatval.type && formatval.type.includes("undefined")) || (formatval.value && formatval.value.includes(undefined)) ) return else { throw new Error( error(`obj is missing property`, { function_name: options.functionname, missing_property: formatkey, object: obj, entire_object, format: { ...format[formatkey] }, }) ) } if (!formatval[Symbol.for("setformat")]) { newtestformat(currentcomparevalue, formatval, tempoptions) } else { for (var [typekey, currentcheck] of Object.entries( formatval )) { // log({ obj, currentcomparevalue, typekey, currentcheck, formatval }) switch (typekey) { case "type": if ( a.gettype(currentcomparevalue, currentcheck) || currentcheck == "any" || currentcheck?.includes?.("any") ) break else throw new Error( error("type missmatch", { function_name: options.functionname, property: formatkey, object: obj, entire_object, current_value: currentcomparevalue, type_of_current_value: a.gettype(currentcomparevalue), type_should_be: currentcheck, }) ) case "value": if (currentcheck.includes(currentcomparevalue)) break else throw new Error( error("value missmatch", { format_key: formatkey, object: obj, entire_object, function_name: options.functionname, current_compare_value: currentcomparevalue, type_of_current_compare_value: a.gettype(currentcomparevalue), current_check: currentcheck, }) ) default: throw new Error( "invalid key in format", error({ function_name: options.functionname, object: obj, entire_object, type_key: typekey, format_val: formatval, }) ) } } } } for (var key of extrakeys) { if (!options.extrasformat) throw new Error( `options has allowextras options must also have extrasformat in function [${options.functionname}]` ) // log(options.extrasformat, options) checkformat(key, setformat(options.extrasformat), 1) } entire_object = undefined return true } loadlib("libloader").savelib("strict", { strictfunction, oldtestformat: testformat, setformat, optional: function (obj) { return new Proxy(obj, { get(_obj, prop) { if (prop == Symbol.for("optional")) return true return Reflect.get(_obj, prop) }, }) }, condfunc: function (func) { return new Proxy(func, { get(_obj, prop) { if (prop == Symbol.for("condfunc")) return true return Reflect.get(_obj, prop) }, }) }, testformat: newtestformat, }) })()