we3fan Posted March 4 Posted March 4 I have few JS polyfills saved, maybe one of them can help with Discord's 'are you human' Pop-up?
NotHereToPlayGames Posted March 5 Author Posted March 5 Any luck? I do not have a Discord account so cannot 'Add Friend'. I'm always curious of growing lists of needed polyfills.
we3fan Posted March 5 Posted March 5 I have these JS polyfills saved: Array.at Change Array by Copy .toSorted findLast findLastIndex Object.fromEntries Object.hasOwn randomUUID String.at structuredClone Promise.withResolvers Which one of these might work to disable a 'are you human' Pop-up? If there are no suggested candidates to start with, I will have to try them all.
NotHereToPlayGames Posted March 5 Author Posted March 5 I'd start with all-of-the-below then watch the Javascript Console (Ctrl-Shift-J) for items in red to provide hints for where to go from there. // ==UserScript== // @name Inject Change Array by Copy All-in-One Polyfill [110] // @version 0.0.1 // @match *://*/* // @run-at document-start // @grant none // ==/UserScript== ((arrayPrototype, typedArrayPrototype) => { "use strict"; const typedArrayLength = Function.call.bind( Object.getOwnPropertyDescriptor(typedArrayPrototype, "length").get ); function toIntegerOrInfinity(arg) { let n = Number(arg); if (Number.isNaN(n) || n === 0) { return 0; } if (n === Number.POSITIVE_INFINITY) { return Number.POSITIVE_INFINITY; } if (n === Number.NEGATIVE_INFINITY) { return Number.NEGATIVE_INFINITY; } let i = Math.floor(Math.abs(n)); if (n < 0) { i = -i; } return i; } function toObject(val) { if (val === null || val === undefined) { throw new TypeError(`${val} is not an object`); } return Object(val); } function lengthOfArrayLike(arr) { if (!(typeof arr === "object" && arr !== null)) { throw new TypeError(); } let len = toIntegerOrInfinity(arr["length"]); if (!Number.isFinite(len)) { len = 0; } return Math.max(0, Math.min(len, Number.MAX_SAFE_INTEGER)); } /** @typedef {Int8Array|Uint8Array|Uint8ClampedArray|Int16Array|Uint16Array|Int32Array|Uint32Array|Float32Array|Float64Array|BigInt64Array|BigUint64Array} TypedArray */ /** * @param {unknown} v * @returns {TypedArray} */ function assertTypedArray(v) { typedArrayPrototype.keys.call(v); // @ts-expect-error return v; } /** * @param {TypedArray} arr * @returns {TypedArray[typeof Symbol.toStringTag]} */ function typedArrayNameInternalSlot(arr) { return Object.getOwnPropertyDescriptor(typedArrayPrototype, Symbol.toStringTag) .get.call(arr); } /** * @param {TypedArray} example * @param {number} length * @returns {TypedArray} */ function typedArrayCreate(example, length) { assertTypedArray(example); const arrayName = typedArrayNameInternalSlot(example); switch (arrayName) { case 'Int8Array': return new Int8Array(length); case 'Uint8Array': return new Uint8Array(length); case 'Uint8ClampedArray': return new Uint8ClampedArray(length); case 'Int16Array': return new Int16Array(length); case 'Uint16Array': return new Uint16Array(length); case 'Int32Array': return new Int32Array(length); case 'Uint32Array': return new Uint32Array(length); case 'Float32Array': return new Float32Array(length); case 'Float64Array': return new Float64Array(length); case 'BigInt64Array': return new BigInt64Array(length); case 'BigUint64Array': return new BigUint64Array(length); default: /** @type {never} */ const n = arrayName; throw new Error(`Unexpected TypedArray name ${n}`); } } /** * @param {TypedArray} example * @returns {boolean} */ function isBigIntArray(example) { assertTypedArray(example); const arrayName = typedArrayNameInternalSlot(example); switch (arrayName) { case 'BigInt64Array': case 'BigUint64Array': return true; } return false; } function transfer({ count, src, srcStart, srcStep = 1, target, targetStart, targetStep = srcStep }) { let from = srcStart; let to = targetStart; for (let i = 0; i < count; i++) { target[to] = src[from]; from += srcStep; to += targetStep; } } /** * @param {TypedArray} example * @param {unknown} value * @description convert `value` to bigint or number based on the the type of array * @returns {bigint | number} * @throws if one of the override methods throws. e.g. `@@toPrimitive`, `valueOf`, `toString` */ function typedArrayNumberConversion(example, value) { let asNumber; { if (isBigIntArray(example)) { asNumber = 0n; } else { asNumber = -0; // important to use `-0` and not `0` } // @ts-ignore : using `+=` to emulate ToBigInt or ToNumber asNumber += value; } return asNumber; } defineArrayMethods({ toReversed() { const o = toObject(this); const len = lengthOfArrayLike(o); const a = new Array(len); transfer({ src: o, srcStart: len - 1, srcStep: -1, target: a, targetStart: 0, targetStep: 1, count: len }); return a; }, }); defineTypedArrayMethods({ toReversed() { const o = assertTypedArray(this); const len = typedArrayLength(o); const a = typedArrayCreate(o, len); transfer({ src: o, srcStart: len - 1, srcStep: -1, target: a, targetStart: 0, targetStep: 1, count: len }); return a; }, }); defineArrayMethods({ toSorted(compareFn) { if (compareFn !== void 0 && typeof compareFn !== "function") { throw new TypeError(); } const o = toObject(this); const len = lengthOfArrayLike(o); const a = new Array(len);; transfer({ src: o, srcStart: 0, target: a, targetStart: 0, count: len }); arrayPrototype.sort.call(a, compareFn); return a; }, }); defineTypedArrayMethods({ toSorted(compareFn) { if (compareFn !== void 0 && typeof compareFn !== "function") { throw new TypeError(); } const o = assertTypedArray(this); const len = typedArrayLength(o); const a = typedArrayCreate(o, len); transfer({ src: o, srcStart: 0, target: a, targetStart: 0, count: len }); typedArrayPrototype.sort.call(a, compareFn); return a; }, }); function calculateSplice({ start, len, deleteCount, values, argsCount }) { const relativeStart = toIntegerOrInfinity(start); let actualStart; if (relativeStart === -Infinity) { actualStart = 0; } else if (relativeStart < 0) { actualStart = Math.max(len + relativeStart, 0); } else { actualStart = Math.min(relativeStart, len); } const insertCount = values.length; let actualDeleteCount; if (/* start is not present */ argsCount === 0) { actualDeleteCount = 0; } else if (/* deleteCount is not present */ argsCount === 1) { actualDeleteCount = len - actualStart; } else { const dc = toIntegerOrInfinity(deleteCount); actualDeleteCount = Math.max(0, Math.min(dc, len - actualStart)); } const newLen = len + insertCount - actualDeleteCount; return { actualStart, newLen, actualDeleteCount }; } function doSplice({ src, target, actualStart, actualDeleteCount, values, newLen }) { let i = 0; while (i < actualStart) { target = src; i++; } for (const E of values) { target = E; i++; } let r = actualStart + actualDeleteCount; while (i < newLen) { let fromValue = src[r]; target = fromValue; i++; r++; } } defineArrayMethods({ toSpliced(start, deleteCount, ...values) { const o = toObject(this); const len = lengthOfArrayLike(o); const { actualStart, actualDeleteCount, newLen } = calculateSplice({ start, deleteCount, len, values, argsCount: arguments.length }); if (newLen > Number.MAX_SAFE_INTEGER) { throw new TypeError(); } const a = new Array(newLen); doSplice({ src: o, target: a, actualStart, actualDeleteCount, values, newLen }); return a; } }); defineArrayMethods({ with(index, value) { const o = toObject(this); const len = lengthOfArrayLike(o); const relativeIndex = toIntegerOrInfinity(index); const actualIndex = relativeIndex < 0 ? len + relativeIndex : relativeIndex; if (actualIndex < 0 || actualIndex >= len) { throw new RangeError(); } const a = new Array(len); for (let k = 0; k < len; k++) { const v = k === actualIndex ? value : o[k]; a[k] = v; } return a; } }); defineTypedArrayMethods({ with(index, value) { const o = assertTypedArray(this); const len = typedArrayLength(o); const relativeIndex = toIntegerOrInfinity(index); const actualIndex = relativeIndex < 0 ? len + relativeIndex : relativeIndex; const asNumber = typedArrayNumberConversion(o, value); if (actualIndex < 0 || actualIndex >= len) { throw new RangeError(); } const a = typedArrayCreate(o, len); for (let k = 0; k < len; k++) { const v = k === actualIndex ? asNumber : o[k]; a[k] = v; } return a; } }); /** @type {(def: { [N in "with" | "toReversed" | "toSorted" | "toSpliced"]?: typeof Array.prototype[N] }) => void} */ function defineArrayMethods(def) { defineMethods(arrayPrototype, def).forEach(name => { if (name !== 'with') { // 'with' is already a keyword arrayPrototype[Symbol.unscopables][name] = true; } }); } /** @type {(def: { [N in "with" | "toReversed" | "toSorted"]?: (this: TypedArray, ...args: Parameters<Uint8Array[N]>) => TypedArray }) => void} */ function defineTypedArrayMethods(def) { defineMethods(typedArrayPrototype, def); } function defineMethods(obj, def) { return Object.entries(def).map(([name, method]) => { Object.defineProperty(obj, name, { value: method, enumerable: false, configurable: true, writable: true, }); return name; }); } })(Array.prototype, Object.getPrototypeOf(Int8Array.prototype)); // ==UserScript== // @name Inject Promise.withResolvers() Polyfill [119] // @version 0.0.1 // @match *://*/* // @run-at document-start // @grant none // ==/UserScript== Promise.withResolvers || (Promise.withResolvers = function withResolvers() { var a, b, c = new this(function (resolve, reject) { a = resolve; b = reject; }); return {resolve: a, reject: b, promise: c}; }); // ==UserScript== // @name Inject structuredClone() [major] Polyfill [98] // @version 0.0.1 // @match *://*/* // @run-at document-start // @grant none // ==/UserScript== 'use strict'; const VOID = -1; const PRIMITIVE = 0; const ARRAY = 1; const OBJECT = 2; const DATE = 3; const REGEXP = 4; const MAP = 5; const SET = 6; const ERROR = 7; const BIGINT = 8; // const SYMBOL = 9; const EMPTY = ''; const {toString} = {}; const {keys} = Object; const typeOf = value => { const type = typeof value; if (type !== 'object' || !value) return [PRIMITIVE, type]; const asString = toString.call(value).slice(8, -1); switch (asString) { case 'Array': return [ARRAY, EMPTY]; case 'Object': return [OBJECT, EMPTY]; case 'Date': return [DATE, EMPTY]; case 'RegExp': return [REGEXP, EMPTY]; case 'Map': return [MAP, EMPTY]; case 'Set': return [SET, EMPTY]; } if (asString.includes('Array')) return [ARRAY, asString]; if (asString.includes('Error')) return [ERROR, asString]; return [OBJECT, asString]; }; const shouldSkip = ([TYPE, type]) => ( TYPE === PRIMITIVE && (type === 'function' || type === 'symbol') ); const serializer = (strict, json, $, _) => { const as = (out, value) => { const index = _.push(out) - 1; $.set(value, index); return index; }; const pair = value => { if ($.has(value)) return $.get(value); let [TYPE, type] = typeOf(value); switch (TYPE) { case PRIMITIVE: { let entry = value; switch (type) { case 'bigint': TYPE = BIGINT; entry = value.toString(); break; case 'function': case 'symbol': if (strict) throw new TypeError('unable to serialize ' + type); entry = null; break; case 'undefined': return as([VOID], value); } return as([TYPE, entry], value); } case ARRAY: { if (type) return as([type, [...value]], value); const arr = []; const index = as([TYPE, arr], value); for (const entry of value) arr.push(pair(entry)); return index; } case OBJECT: { if (type) { switch (type) { case 'BigInt': return as([type, value.toString()], value); case 'Boolean': case 'Number': case 'String': return as([type, value.valueOf()], value); } } if (json && ('toJSON' in value)) return pair(value.toJSON()); const entries = []; const index = as([TYPE, entries], value); for (const key of keys(value)) { if (strict || !shouldSkip(typeOf(value[key]))) entries.push([pair(key), pair(value[key])]); } return index; } case DATE: return as([TYPE, value.toISOString()], value); case REGEXP: { const {source, flags} = value; return as([TYPE, {source, flags}], value); } case MAP: { const entries = []; const index = as([TYPE, entries], value); for (const [key, entry] of value) { if (strict || !(shouldSkip(typeOf(key)) || shouldSkip(typeOf(entry)))) entries.push([pair(key), pair(entry)]); } return index; } case SET: { const entries = []; const index = as([TYPE, entries], value); for (const entry of value) { if (strict || !shouldSkip(typeOf(entry))) entries.push(pair(entry)); } return index; } } const {message} = value; return as([TYPE, {name: type, message}], value); }; return pair; }; /** * @typedef {Array<string,any>} Record a type representation */ /** * Returns an array of serialized Records. * @param {any} value a serializable value. * @param {{json?: boolean, lossy?: boolean}?} options an object with a `lossy` or `json` property that, * if `true`, will not throw errors on incompatible types, and behave more * like JSON stringify would behave. Symbol and Function will be discarded. * @returns {Record[]} */ const serialize = (value, {json, lossy} = {}) => { const _ = []; return serializer(!(json || lossy), !!json, new Map, _)(value), _; }; const env = typeof self === 'object' ? self : globalThis; const deserializer = ($, _) => { const as = (out, index) => { $.set(index, out); return out; }; const unpair = index => { if ($.has(index)) return $.get(index); const [type, value] = _[index]; switch (type) { case PRIMITIVE: case VOID: return as(value, index); case ARRAY: { const arr = as([], index); for (const index of value) arr.push(unpair(index)); return arr; } case OBJECT: { const object = as({}, index); for (const [key, index] of value) object[unpair(key)] = unpair(index); return object; } case DATE: return as(new Date(value), index); case REGEXP: { const {source, flags} = value; return as(new RegExp(source, flags), index); } case MAP: { const map = as(new Map, index); for (const [key, index] of value) map.set(unpair(key), unpair(index)); return map; } case SET: { const set = as(new Set, index); for (const index of value) set.add(unpair(index)); return set; } case ERROR: { const {name, message} = value; return as(new env[name](message), index); } case BIGINT: return as(BigInt(value), index); case 'BigInt': return as(Object(BigInt(value)), index); } return as(new env[type](value), index); }; return unpair; }; /** * @typedef {Array<string,any>} Record a type representation */ /** * Returns a deserialized value from a serialized array of Records. * @param {Record[]} serialized a previously serialized value. * @returns {any} */ const deserialize = serialized => deserializer(new Map, serialized)(0); if (!("structuredClone" in env)) env.structuredClone = (any, options) => deserialize(serialize(any, options)); 2
NotHereToPlayGames Posted March 5 Author Posted March 5 7 hours ago, we3fan said: Change Array by Copy .toSorted You seem to be missing: 1) .toReversed 2) .toSpliced 3) .with The previous post "all-in-one" should cover all four. But these three as individual polyfills are below, in case you want them. // ==UserScript== // @name Inject Change Array by Copy .toReversed() Polyfill [110] // @version 0.0.1 // @match *://*/* // @run-at document-start // @grant none // ==/UserScript== if (!Array.prototype.toReversed) { Array.prototype.toReversed = function () { return this.slice().reverse(); }; } // ==UserScript== // @name Inject Change Array by Copy .toSpliced() Polyfill [110] // @version 0.0.1 // @match *://*/* // @run-at document-start // @grant none // ==/UserScript== if (!Array.prototype.toSpliced) { Array.prototype.toSpliced = function (start, deleteCount, ...items) { const copy = this.slice(); copy.splice(start, deleteCount, ...items); return copy; }; } // ==UserScript== // @name Inject Change Array by Copy .with() Polyfill [110] // @version 0.0.1 // @match *://*/* // @run-at document-start // @grant none // ==/UserScript== if (!Array.prototype.with) { Array.prototype.with = function (index, value) { const copy = this.slice(); copy[index] = value; return copy; }; } 1
obstinateXP Posted March 6 Posted March 6 I've just switched over to 360Chrome v13.5.1030 Redux after a trouble-free run with v13.5.1030 rebuild 6, for the last 3 years. Many thanks to NotHereToPlayGames for sharing his knowledge and efforts. Ironically, the problem that pushed me to upgrade was being unable to use the MSFN forum. I was hoping someone could tell me how to transfer my passwords from rebuild 6 to Redux?
we3fan Posted March 6 Posted March 6 Hi obstinateXP, 1. Optional: Make backup of rebuild 6 first, Application + User Data folders, backup 360Loader.exe + 360Loader.ini also just in case. 2. Copy rebuild 6 to new location, replace all contents from rebuild 6\Chrome\Application with Redux\Chrome\Application. 3. Replace 360Loader.exe from rebuild 6 with 360Loader.exe from Redux; replace 360Loader.ini also if you want or keep your old one from rebuild 6. 4. Rename rebuild 6 to Redux, done.
we3fan Posted March 6 Posted March 6 Thanks ArcticFoxie, With no Polyfills, it shows this (I hid some of the messages I thought were irrelevant): The last message "PUT https ... 9216 400" shows when I 'Add Friend' and when the 'are you human' Pop-up shows. With these 3 Polyfills (Change Array by Copy All-in-One + Promise.withResolvers + structuredClone major) active, it shows this (I hid some of the messages I thought were irrelevant): This time it didn't show the "PUT https ... 9216 400" message when I 'Added Friend' and when the 'are you human' Pop-up showed. I enabled chrome://flags/#enable-experimental-web-platform-features so: Change Array by Copy All-in-One + Promise.withResolvers + structuredClone major + chrome://flags/#enable-experimental-web-platform-features Enabled - but it still showed the 'are you human' Pop-up, so I Disabled chrome://flags/#enable-experimental-web-platform-features again (default).
NotHereToPlayGames Posted March 6 Author Posted March 6 It's gonna require someone with a Discord account to track down. Maybe it can be polyfilled. Maybe not. 2
we3fan Posted Saturday at 02:02 PM Posted Saturday at 02:02 PM On 3/6/2025 at 11:36 PM, NotHereToPlayGames said: It's gonna require someone with a Discord account to track down. The JS Console doesn't give us enough info?
obstinateXP Posted 20 hours ago Posted 20 hours ago On 3/7/2025 at 4:23 AM, we3fan said: Hi obstinateXP, 1. Optional: Make backup of rebuild 6 first, Application + User Data folders, backup 360Loader.exe + 360Loader.ini also just in case. 2. Copy rebuild 6 to new location, replace all contents from rebuild 6\Chrome\Application with Redux\Chrome\Application. 3. Replace 360Loader.exe from rebuild 6 with 360Loader.exe from Redux; replace 360Loader.ini also if you want or keep your old one from rebuild 6. 4. Rename rebuild 6 to Redux, done. Thanks, but unfortunately this doesn't really work for me. Using my old 'User Data' folder causes Redux to have the same problem as rebuild 6. I can see the home page of the forum, but I can't access any topics or threads. I just get a completely blank page if I try. I can't log in either. Redux without my 'User Data' folder swapped in, works fine. I'm using it to write this post.
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now