Jump to content

Recommended Posts

Posted

I have few JS polyfills saved, maybe one of them can help with Discord's 'are you human' Pop-up?


Posted

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.

Posted

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));

 

 

Posted
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;
  };
}

Posted

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. :worship:

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?

Posted

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.

Posted

Thanks ArcticFoxie,

With no Polyfills, it shows this (I hid some of the messages I thought were irrelevant):
IIOWs.png
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):
wwKUA.png
33h4v.png
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).

Posted
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?

Posted
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.

  • 3 weeks later...

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...