exports.id = 5446;
exports.ids = [5446];
exports.modules = {

/***/ 473663:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

/**
 * LocalStorageLRU
 * Copyright 2022 SageMath, Inc.
 * Licensed under the Apache License, Version 2.0
 */
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.LocalStorageLRU = void 0;
var local_storage_lru_1 = __webpack_require__(757606);
Object.defineProperty(exports, "LocalStorageLRU", ({ enumerable: true, get: function () { return local_storage_lru_1.LocalStorageLRU; } }));


/***/ }),

/***/ 652381:
/***/ ((__unused_webpack_module, exports) => {

"use strict";

/**
 * LocalStorageLRU
 * Copyright 2022 SageMath, Inc.
 * Licensed under the Apache License, Version 2.0
 *
 * @jest-environment jsdom
 */
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.LocalStorageFallback = void 0;
// This backs the localStorage via a simple in-memory dictionary and it also has a limited size.
// It is used by @LocalStorageLRU, if fallback is true and the test if local storage is available fails.
class LocalStorageFallback {
    constructor(size = 1000) {
        this.data = {};
        this.size = size;
    }
    // number of elements in data
    get length() {
        return Object.keys(this.data).length;
    }
    // clear everything in data
    clear() {
        this.data = {};
    }
    getItem(key) {
        var _a;
        return (_a = this.data[key]) !== null && _a !== void 0 ? _a : null;
    }
    setItem(key, val) {
        if (this.length >= this.size) {
            throw new Error('storage full');
        }
        this.data[key] = val;
    }
    removeItem(key) {
        delete this.data[key];
    }
    key(index) {
        return Object.keys(this.data)[index];
    }
    keys() {
        return Object.keys(this.data);
    }
}
exports.LocalStorageFallback = LocalStorageFallback;


/***/ }),

/***/ 757606:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

/**
 * LocalStorageLRU
 * Copyright 2022 SageMath, Inc.
 * Licensed under the Apache License, Version 2.0
 */
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.LocalStorageLRU = void 0;
const local_storage_fallback_1 = __webpack_require__(652381);
// additionally, each one of them gets `typePrefixDelimiter` as a postfix,
// to further distinguish them from other (pure string) values.
const DEFAULT_TYPE_PREFIXES = {
    date: '\x00\x01date',
    bigint: '\x00\x02bigint',
    object: '\x00\x03object',
    int: '\x00\x04int',
    float: '\x00\x05float',
};
/**
 * Use an instance of this class to access localStorage – instead of using it directly.
 * You will no longer end up with random exceptions upon setting a key/value pair.
 * Instead, if there is a problem, it will remove a few entries and tries setting the value again.
 * Recently used entries won't be removed and you can also specify a function to filter potential candidates for deletion.
 *
 * **Important** do not use index accessors – use `get` and `set` instead.
 */
class LocalStorageLRU {
    constructor(props) {
        var _a, _b, _c, _d, _e, _f, _g;
        this.maxSize = (_a = props === null || props === void 0 ? void 0 : props.maxSize) !== null && _a !== void 0 ? _a : 64;
        this.isCandidate = props === null || props === void 0 ? void 0 : props.isCandidate;
        this.recentKey = (_b = props === null || props === void 0 ? void 0 : props.recentKey) !== null && _b !== void 0 ? _b : '__recent';
        this.delimiter = (_c = props === null || props === void 0 ? void 0 : props.delimiter) !== null && _c !== void 0 ? _c : '\0';
        this.serializer = (_d = props === null || props === void 0 ? void 0 : props.serializer) !== null && _d !== void 0 ? _d : JSON.stringify;
        this.deserializer = (_e = props === null || props === void 0 ? void 0 : props.deserializer) !== null && _e !== void 0 ? _e : JSON.parse;
        this.parseExistingJSON = (_f = props === null || props === void 0 ? void 0 : props.parseExistingJSON) !== null && _f !== void 0 ? _f : false;
        this.typePrefixDelimiter = (_g = props === null || props === void 0 ? void 0 : props.typePrefixDelimiter) !== null && _g !== void 0 ? _g : '\0';
        this.typePrefixes = this.preparePrefixes(props === null || props === void 0 ? void 0 : props.typePrefixes);
        this.checkPrefixes();
        this.ls = this.initLocalStorage(props);
    }
    initLocalStorage(props) {
        const { fallback = false, localStorage } = props !== null && props !== void 0 ? props : {};
        let lsProposed;
        try {
            lsProposed = localStorage !== null && localStorage !== void 0 ? localStorage : window === null || window === void 0 ? void 0 : window.localStorage;
        }
        catch (_a) { }
        if (lsProposed != null) {
            if (fallback && !LocalStorageLRU.testLocalStorage(lsProposed)) {
                return new local_storage_fallback_1.LocalStorageFallback(1000);
            }
            return lsProposed;
        }
        else {
            return new local_storage_fallback_1.LocalStorageFallback(1000);
        }
    }
    preparePrefixes(typePrefixes) {
        var _a, _b, _c, _d, _e;
        const delim = this.typePrefixDelimiter;
        return {
            date: `${(_a = typePrefixes === null || typePrefixes === void 0 ? void 0 : typePrefixes.date) !== null && _a !== void 0 ? _a : DEFAULT_TYPE_PREFIXES.date}${delim}`,
            bigint: `${(_b = typePrefixes === null || typePrefixes === void 0 ? void 0 : typePrefixes.bigint) !== null && _b !== void 0 ? _b : DEFAULT_TYPE_PREFIXES.bigint}${delim}`,
            object: `${(_c = typePrefixes === null || typePrefixes === void 0 ? void 0 : typePrefixes.object) !== null && _c !== void 0 ? _c : DEFAULT_TYPE_PREFIXES.object}${delim}`,
            int: `${(_d = typePrefixes === null || typePrefixes === void 0 ? void 0 : typePrefixes.int) !== null && _d !== void 0 ? _d : DEFAULT_TYPE_PREFIXES.int}${delim}`,
            float: `${(_e = typePrefixes === null || typePrefixes === void 0 ? void 0 : typePrefixes.float) !== null && _e !== void 0 ? _e : DEFAULT_TYPE_PREFIXES.float}${delim}`,
        };
    }
    checkPrefixes() {
        // during init, we check that all values of typePrefixes are unique
        const prefixes = Object.values(this.typePrefixes);
        const uniqueValues = new Set(prefixes);
        if (prefixes.length !== uniqueValues.size) {
            throw new Error('all type prefixes must be distinct');
        }
    }
    /**
     * the number of recent keys tracked
     */
    getMaxSize() {
        return this.maxSize;
    }
    /**
     * specific types are serialized with a prefix, while plain strings are stored as they are.
     */
    serialize(val) {
        if (typeof val === 'string') {
            return val;
        }
        else if (Number.isInteger(val)) {
            return `${this.typePrefixes.int}${val}`;
        }
        else if (typeof val === 'number') {
            return `${this.typePrefixes.float}${val}`;
        }
        else if (val instanceof Date) {
            return `${this.typePrefixes.date}${val.valueOf()}`;
        }
        else if (typeof val === 'bigint') {
            return `${this.typePrefixes.bigint}${val.toString()}`;
        }
        else if (val === undefined) {
            return `${this.typePrefixes.object}${this.serializer(null)}`;
        }
        return `${this.typePrefixes.object}${this.serializer(val)}`;
    }
    /**
     * Each value in localStorage is a string. For specific prefixes,
     * this deserializes the value. As a fallback, it optionally tries
     * to use JSON.parse. If everything fails, the plain string value is returned.
     */
    deserialize(ser) {
        if (ser === null) {
            return null;
        }
        try {
            if (ser.startsWith(this.typePrefixes.object)) {
                const s = ser.slice(this.typePrefixes.object.length);
                try {
                    return this.deserializer(s);
                }
                catch (_a) {
                    return s;
                }
            }
            else if (ser.startsWith(this.typePrefixes.int)) {
                const s = ser.slice(this.typePrefixes.int.length);
                try {
                    return parseInt(s, 10);
                }
                catch (_b) {
                    return s;
                }
            }
            else if (ser.startsWith(this.typePrefixes.float)) {
                const s = ser.slice(this.typePrefixes.float.length);
                try {
                    return parseFloat(s);
                }
                catch (_c) {
                    return s;
                }
            }
            else if (ser.startsWith(this.typePrefixes.date)) {
                const tsStr = ser.slice(this.typePrefixes.date.length);
                try {
                    return new Date(parseInt(tsStr, 10));
                }
                catch (_d) {
                    return tsStr; // we return the string if we can't parse it
                }
            }
            else if (ser.startsWith(this.typePrefixes.bigint)) {
                const s = ser.slice(this.typePrefixes.bigint.length);
                try {
                    return BigInt(s);
                }
                catch (_e) {
                    return s;
                }
            }
        }
        catch (_f) { }
        // optionally, it tries to parse existing JSON values – they'll be stored with a prefix when saved again
        if (this.parseExistingJSON) {
            try {
                if (this.deserialize !== JSON.parse) {
                    return this.deserialize(ser);
                }
            }
            catch (_g) { }
            try {
                return JSON.parse(ser);
            }
            catch (_h) { }
        }
        // most likely a plain string
        return ser;
    }
    /**
     * Wrapper around localStorage, so we can safely touch it without raising an
     * exception if it is banned (like in some browser modes) or doesn't exist.
     */
    set(key, val) {
        if (key === this.recentKey) {
            throw new Error(`localStorage: Key "${this.recentKey}" is reserved.`);
        }
        if (key.indexOf(this.delimiter) !== -1) {
            throw new Error(`localStorage: Cannot use "${this.delimiter}" as a character in a key`);
        }
        const valSer = this.serialize(val);
        // we have to record the usage of the key first!
        // otherwise, setting it first and then updating the list of recent keys
        // could delete that very key upon updating the list of recently used keys.
        this.recordUsage(key);
        try {
            this.ls.setItem(key, valSer);
        }
        catch (e) {
            console.log('set error', e);
            if (!this.trim(key, valSer)) {
                console.warn(`localStorage: set error -- ${e}`);
            }
        }
    }
    get(key) {
        try {
            const v = this.ls.getItem(key);
            this.recordUsage(key);
            return this.deserialize(v);
        }
        catch (e) {
            console.warn(`localStorage: get error -- ${e}`);
            return null;
        }
    }
    has(key) {
        // we don't call this.get, because we don't want to record the usage
        return this.ls.getItem(key) != null;
    }
    /**
     * Keys of last recently used entries. The most recent one comes first!
     */
    getRecent() {
        var _a, _b;
        try {
            return (_b = (_a = this.ls.getItem(this.recentKey)) === null || _a === void 0 ? void 0 : _a.split(this.delimiter)) !== null && _b !== void 0 ? _b : [];
        }
        catch (_c) {
            return [];
        }
    }
    getRecentKey() {
        return this.recentKey;
    }
    /**
     * avoid trimming more useful entries, we keep an array of recently modified keys
     */
    recordUsage(key) {
        try {
            let keys = this.getRecent();
            // first, only keep most recent entries, and leave one slot for the new one
            keys = keys.slice(0, this.maxSize - 1);
            // if the key already exists, remove it
            keys = keys.filter((el) => el !== key);
            // finally, insert the current key at the beginning
            keys.unshift(key);
            const nextRecentUsage = keys.join(this.delimiter);
            try {
                this.ls.setItem(this.recentKey, nextRecentUsage);
            }
            catch (_a) {
                this.trim(this.recentKey, nextRecentUsage);
            }
        }
        catch (e) {
            console.warn(`localStorage: unable to record usage of '${key}' -- ${e}`);
        }
    }
    /**
     * remove a key from the recently used list
     */
    deleteUsage(key) {
        try {
            let keys = this.getRecent();
            // we only keep those keys, which are different from the one we removed
            keys = keys.filter((el) => el !== key);
            this.ls.setItem(this.recentKey, keys.join(this.delimiter));
        }
        catch (e) {
            console.warn(`localStorage: unable to delete usage of '${key}' -- ${e}`);
        }
    }
    /**
     * Trim the local storage in case it is too big.
     * In case there is an error upon storing a value, we assume we hit the quota limit.
     * Try a couple of times to delete some entries and saving the key/value pair.
     */
    trim(key, val) {
        // we try up to 10 times to remove a couple of key/values
        for (let i = 0; i < 10; i++) {
            this.trimOldEntries();
            try {
                this.ls.setItem(key, val);
                // no error means we were able to set the value
                // console.info(`localStorage: trimming a few entries worked`);
                return true;
            }
            catch (e) { }
        }
        console.warn(`localStorage: trimming did not help`);
        return false;
    }
    // delete a few keys (not recently used and only of a specific type).
    trimOldEntries() {
        if (this.size() === 0)
            return;
        // delete a maximum of 10 entries
        let num = Math.min(this.size(), 10);
        const keys = this.keys();
        // only get recent once, more efficient
        const recent = this.getRecent();
        // attempt deleting those entries up to 20 times
        for (let i = 0; i < 20; i++) {
            const candidate = keys[Math.floor(Math.random() * keys.length)];
            if (candidate === this.recentKey)
                continue;
            if (recent.includes(candidate))
                continue;
            if (this.isCandidate != null && !this.isCandidate(candidate, recent))
                continue;
            // do not call this.delete, could cause a recursion
            try {
                this.ls.removeItem(candidate);
            }
            catch (e) {
                console.warn(`localStorage: trimming/delete does not work`);
                return;
            }
            num -= 1;
            if (num <= 0)
                return;
            if (this.size() === 0)
                return;
        }
    }
    /**
     * Return all keys in local storage, optionally sorted.
     *
     * @param {boolean} [sorted=false]
     * @return {string[]}
     */
    keys(sorted = false) {
        const keys = this.ls instanceof local_storage_fallback_1.LocalStorageFallback ? this.ls.keys() : Object.keys(this.ls);
        const filteredKeys = keys.filter((el) => el !== this.recentKey);
        if (sorted)
            filteredKeys.sort();
        return filteredKeys;
    }
    /**
     * Deletes key from local storage
     *
     * Throws an error only if you try to delete the reserved key to record recent entries.
     */
    delete(key) {
        if (key === this.recentKey) {
            throw new Error(`localStorage: Key "${this.recentKey}" is reserved.`);
        }
        try {
            this.deleteUsage(key);
            this.ls.removeItem(key);
        }
        catch (e) {
            console.warn(`localStorage: delete error -- ${e}`);
        }
    }
    /**
     * Returns true, if we can store something in local storage at all.
     */
    localStorageIsAvailable() {
        return LocalStorageLRU.testLocalStorage(this.ls);
    }
    /**
     * Returns true, if we can store something in local storage at all.
     * This is used for testing and during initialization.
     *
     * @static
     * @param {Storage} ls
     */
    static testLocalStorage(ls) {
        try {
            const TEST = '__test__';
            const timestamp = `${Date.now()}`;
            ls.setItem(TEST, timestamp);
            if (ls.getItem(TEST) !== timestamp) {
                throw new Error('localStorage: test failed');
            }
            ls.removeItem(TEST);
            return true;
        }
        catch (e) {
            return false;
        }
    }
    /**
     * number of items stored in the local storage – not counting the "recent key" itself
     */
    size() {
        try {
            const v = this.ls.length;
            if (this.has(this.recentKey)) {
                return v - 1;
            }
            else {
                return v;
            }
        }
        catch (e) {
            return 0;
        }
    }
    /**
     * calls `localStorage.clear()` and returns true if it worked – otherwise false.
     */
    clear() {
        try {
            this.ls.clear();
            return true;
        }
        catch (e) {
            console.warn(`localStorage: clear error -- ${e}`);
            return false;
        }
    }
    getLocalStorage() {
        return this.ls;
    }
    /** Delete all keys with the given prefix */
    deletePrefix(prefix) {
        for (let i = 0; i < this.ls.length; i++) {
            const key = this.ls.key(i);
            if (key == null)
                continue;
            if (key.startsWith(prefix) && key !== this.recentKey) {
                this.delete(key);
            }
        }
    }
    /**
     * Usage:
     *
     * ```ts
     * const entries: [string, any][] = [];
     * for (const [k, v] of storage) {
     *    entries.push([k, v]);
     * }
     * entries; // equals: [[ 'key1', '1' ], [ 'key2', '2' ], ... ]
     * ```
     *
     * @returns iterator over key/value pairs
     */
    *[Symbol.iterator]() {
        for (const k of this.keys()) {
            if (k === this.recentKey)
                continue;
            if (k == null)
                continue;
            const v = this.get(k);
            if (v == null)
                continue;
            yield [k, v];
        }
    }
}
exports.LocalStorageLRU = LocalStorageLRU;


/***/ }),

/***/ 304298:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

module.exports = __webpack_require__(920699)


/***/ })

};
;