<commit_before>// ==========================================================================
// Plyr utils
// ==========================================================================

import loadjs from 'loadjs';
import support from './support';
import { providers } from './types';

const utils = {
    // Check variable types
    is: {
        object(input) {
            return this.getConstructor(input) === Object;
        },
        number(input) {
            return this.getConstructor(input) === Number && !Number.isNaN(input);
        },
        string(input) {
            return this.getConstructor(input) === String;
        },
        boolean(input) {
            return this.getConstructor(input) === Boolean;
        },
        function(input) {
            return this.getConstructor(input) === Function;
        },
        array(input) {
            return !this.nullOrUndefined(input) && Array.isArray(input);
        },
        weakMap(input) {
            return this.instanceof(input, WeakMap);
        },
        nodeList(input) {
            return this.instanceof(input, NodeList);
        },
        element(input) {
            return this.instanceof(input, Element);
        },
        textNode(input) {
            return this.getConstructor(input) === Text;
        },
        event(input) {
            return this.instanceof(input, Event);
        },
        cue(input) {
            return this.instanceof(input, TextTrackCue) || this.instanceof(input, VTTCue);
        },
        track(input) {
            return this.instanceof(input, TextTrack) || (!this.nullOrUndefined(input) && this.string(input.kind));
        },
        url(input) {
            return !this.nullOrUndefined(input) && /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-/]))?/.test(input);
        },
        nullOrUndefined(input) {
            return input === null || typeof input === 'undefined';
        },
        empty(input) {
            return (
                this.nullOrUndefined(input) ||
                ((this.string(input) || this.array(input) || this.nodeList(input)) && !input.length) ||
                (this.object(input) && !Object.keys(input).length)
            );
        },
        instanceof(input, constructor) {
            return Boolean(input && constructor && input instanceof constructor);
        },
        getConstructor(input) {
            return !this.nullOrUndefined(input) ? input.constructor : null;
        },
    },

    // Unfortunately, due to mixed support, UA sniffing is required
    getBrowser() {
        return {
            isIE: /* @cc_on!@ */ false || !!document.documentMode,
            isWebkit: 'WebkitAppearance' in document.documentElement.style && !/Edge/.test(navigator.userAgent),
            isIPhone: /(iPhone|iPod)/gi.test(navigator.platform),
            isIos: /(iPad|iPhone|iPod)/gi.test(navigator.platform),
        };
    },

    // Fetch wrapper
    // Using XHR to avoid issues with older browsers
    fetch(url, responseType = 'text') {
        return new Promise((resolve, reject) => {
            try {
                const request = new XMLHttpRequest();

                // Check for CORS support
                if (!('withCredentials' in request)) {
                    return;
                }

                request.addEventListener('load', () => {
                    if (responseType === 'text') {
                        try {
                            resolve(JSON.parse(request.responseText));
                        } catch (e) {
                            resolve(request.responseText);
                        }
                    } else {
                        resolve(request.response);
                    }
                });

                request.addEventListener('error', () => {
                    throw new Error(request.statusText);
                });

                request.open('GET', url, true);

                // Set the required response type
                request.responseType = responseType;

                request.send();
            } catch (e) {
                reject(e);
            }
        });
    },

    // Load an external script
    loadScript(url) {
        return new Promise((resolve, reject) => {
            loadjs(url, {
                success: resolve,
                error: reject,
            });
        });
    },

    // Load an external SVG sprite
    loadSprite(url, id) {
        if (!utils.is.string(url)) {
            return;
        }

        const prefix = 'cache-';
        const hasId = utils.is.string(id);
        let isCached = false;

        const exists = () => document.querySelectorAll(`#${id}`).length;

        function injectSprite(data) {
            // Check again incase of race condition
            if (hasId && exists()) {
                return;
            }<commit_msg>Add async method to utils for loading/checking images<commit_after>// ==========================================================================
// Plyr utils
// ==========================================================================

import loadjs from 'loadjs';
import support from './support';
import { providers } from './types';

const utils = {
    // Check variable types
    is: {
        object(input) {
            return this.getConstructor(input) === Object;
        },
        number(input) {
            return this.getConstructor(input) === Number && !Number.isNaN(input);
        },
        string(input) {
            return this.getConstructor(input) === String;
        },
        boolean(input) {
            return this.getConstructor(input) === Boolean;
        },
        function(input) {
            return this.getConstructor(input) === Function;
        },
        array(input) {
            return !this.nullOrUndefined(input) && Array.isArray(input);
        },
        weakMap(input) {
            return this.instanceof(input, WeakMap);
        },
        nodeList(input) {
            return this.instanceof(input, NodeList);
        },
        element(input) {
            return this.instanceof(input, Element);
        },
        textNode(input) {
            return this.getConstructor(input) === Text;
        },
        event(input) {
            return this.instanceof(input, Event);
        },
        cue(input) {
            return this.instanceof(input, TextTrackCue) || this.instanceof(input, VTTCue);
        },
        track(input) {
            return this.instanceof(input, TextTrack) || (!this.nullOrUndefined(input) && this.string(input.kind));
        },
        url(input) {
            return !this.nullOrUndefined(input) && /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-/]))?/.test(input);
        },
        nullOrUndefined(input) {
            return input === null || typeof input === 'undefined';
        },
        empty(input) {
            return (
                this.nullOrUndefined(input) ||
                ((this.string(input) || this.array(input) || this.nodeList(input)) && !input.length) ||
                (this.object(input) && !Object.keys(input).length)
            );
        },
        instanceof(input, constructor) {
            return Boolean(input && constructor && input instanceof constructor);
        },
        getConstructor(input) {
            return !this.nullOrUndefined(input) ? input.constructor : null;
        },
    },

    // Unfortunately, due to mixed support, UA sniffing is required
    getBrowser() {
        return {
            isIE: /* @cc_on!@ */ false || !!document.documentMode,
            isWebkit: 'WebkitAppearance' in document.documentElement.style && !/Edge/.test(navigator.userAgent),
            isIPhone: /(iPhone|iPod)/gi.test(navigator.platform),
            isIos: /(iPad|iPhone|iPod)/gi.test(navigator.platform),
        };
    },

    // Fetch wrapper
    // Using XHR to avoid issues with older browsers
    fetch(url, responseType = 'text') {
        return new Promise((resolve, reject) => {
            try {
                const request = new XMLHttpRequest();

                // Check for CORS support
                if (!('withCredentials' in request)) {
                    return;
                }

                request.addEventListener('load', () => {
                    if (responseType === 'text') {
                        try {
                            resolve(JSON.parse(request.responseText));
                        } catch (e) {
                            resolve(request.responseText);
                        }
                    } else {
                        resolve(request.response);
                    }
                });

                request.addEventListener('error', () => {
                    throw new Error(request.statusText);
                });

                request.open('GET', url, true);

                // Set the required response type
                request.responseType = responseType;

                request.send();
            } catch (e) {
                reject(e);
            }
        });
    },

    // Load image avoiding xhr/fetch CORS issues
    // Server status can't be obtained this way unfortunately, so this uses "naturalWidth" to determine if the image has loaded.
    // By default it checks if it is at least 1px, but you can add a second argument to change this.
    loadImage(src, minWidth = 1) {
        return new Promise((resolve, reject) => {
            const image = new Image();
            const handler = () => {
                delete image.onload;
                delete image.onerror;
                (image.naturalWidth >= minWidth ? resolve : reject)(image);
            };
            Object.assign(image, {onload: handler, onerror: handler, src});
        });
    },

    // Load an external script
    loadScript(url) {
        return new Promise((resolve, reject) => {
            loadjs(url, {
                success: resolve,
                error: reject,
            });
        });
    },

    // Load an external SVG sprite
    loadSprite(url, id) {
        if (!utils.is.string(url)) {
            return;
        }

        const prefix = 'cache-';
        const hasId = utils.is.string(id);
        let isCached = false;

        const exists = () => document.querySelectorAll(`#${id}`).length;

        function injectSprite(data) {
            // Check again incase of race condition
            if (hasId && exists()) {
                return;
            }
{'fraction_non_alphanumeric': 0.15797473164244324, 'fraction_numerical': 0.0009499382540134892, 'mean_word_length': 1.600148184736972, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 16, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6489966', 'n_tokens_mistral': 2751, 'n_tokens_neox': 2640, 'n_words': 565}