function decycle(object, callback) {
    // From: https://github.com/douglascrockford/JSON-js/blob/master/cycle.js
    // Contains additional logic to convert the following object types to string
    // so that they can properly be encoded using JSON.stringify:
    //  *Boolean
    //  *Date
    //  *File
    //  *Blob
    //  *Number
    //  *Regex
    // Make a deep copy of an object or array, assuring that there is at most
    // one instance of each object or array in the resulting structure. The
    // duplicate references (which might be forming cycles) are replaced with
    // an object of the form
    //      {$ref: PATH}
    // where the PATH is a JSONPath string that locates the first occurance.
    // So,
    //      var a = [];
    //      a[0] = a;
    //      return JSON.stringify(JSON.decycle(a));
    // produces the string '[{"$ref":"$"}]'.

    // JSONPath is used to locate the unique object. $ indicates the top level of
    // the object or array. [NUMBER] or [STRING] indicates a child member or
    // property.

    var objects = []; // Keep a reference to each unique object or array
    var paths = []; // Keep the path to each unique object or array
    var queuedObjects = [];
    var returnCallback = callback;
    var derezObj = void 0; // eslint-disable-line prefer-const

    /**
     * Check the queue to see if all objects have been processed.
     * if they have, call the callback with the converted object.
     */
    function checkForCompletion() {
        if (queuedObjects.length === 0) {
            returnCallback(derezObj);
        }
    }

    /**
     * Convert a blob to a data URL.
     * @param {Blob} blob to convert.
     * @param {String} path of blob in object being encoded.
     */
    function readBlobAsDataURL(blob, path) {
        var reader = new FileReader();
        reader.onloadend = function (loadedEvent) {
            var dataURL = loadedEvent.target.result;
            var blobtype = 'Blob';
            if (util.isFile(blob)) {
                // blobtype = 'File';
            }
            updateEncodedBlob(dataURL, path, blobtype);
        };
        reader.readAsDataURL(blob);
    }

    /**
     * Async handler to update a blob object to a data URL for encoding.
     * @param {String} dataURL
     * @param {String} path
     * @param {String} blobtype - file if the blob is a file; blob otherwise
     */
    function updateEncodedBlob(dataURL, path, blobtype) {
        var encoded = queuedObjects.indexOf(path);
        path = path.replace('$', 'derezObj');
        eval(path + '.$enc="' + dataURL + '"');
        eval(path + '.$type="' + blobtype + '"');
        queuedObjects.splice(encoded, 1);
        checkForCompletion();
    }

    function derez(value, path) {
        // The derez recurses through the object, producing the deep copy.

        var i = void 0,
            // The loop counter
        name = void 0,
            // Property name
        nu = void 0; // The new object or array

        // typeof null === 'object', so go on if this value is really an object but not
        // one of the weird builtin objects.

        var isObj = util.isObj(value);
        var valOfType = isObj && _typeof(value.valueOf());
        if (isObj && !['boolean', 'number', 'string'].includes(valOfType) && !util.isDate(value) && !util.isRegExp(value) && !util.isBlob(_w3cBlob2.default)) {
            // If the value is an object or array, look to see if we have already
            // encountered it. If so, return a $ref/path object. This is a hard way,
            // linear search that will get slower as the number of unique objects grows.

            for (i = 0; i < objects.length; i += 1) {
                if (objects[i] === value) {
                    return { $ref: paths[i] };
                }
            }

            // Otherwise, accumulate the unique value and its path.

            objects.push(value);
            paths.push(path);

            // If it is an array, replicate the array.

            if (Array.isArray(value)) {
                nu = [];
                for (i = 0; i < value.length; i += 1) {
                    nu[i] = derez(value[i], path + '[' + i + ']');
                }
            } else {
                // If it is an object, replicate the object.
                nu = {};
                for (name in value) {
                    if (Object.prototype.hasOwnProperty.call(value, name)) {
                        nu[name] = derez(value[name], path + '[' + JSON.stringify(name) + ']');
                    }
                }
            }

            return nu;
        } else if (util.isBlob(value)) {
            // Queue blob for conversion
            queuedObjects.push(path);
            readBlobAsDataURL(value, path);
        } else if (valOfType === 'boolean') {
            value = {
                '$type': 'Boolean',
                '$enc': value.toString()
            };
        } else if (util.isDate(value)) {
            value = {
                '$type': 'Date',
                '$enc': value.getTime()
            };
        } else if (valOfType === 'number') {
            value = {
                '$type': 'Number',
                '$enc': value.toString()
            };
        } else if (util.isRegExp(value)) {
            value = {
                '$type': 'RegExp',
                '$enc': value.toString()
            };
        } else if (typeof value === 'number') {
            value = {
                '$type': 'number',
                '$enc': value + '' // handles NaN, Infinity, Negative Infinity
            };
        } else if (value === undefined) {
            value = {
                '$type': 'undefined'
            };
        }
        return value;
    }
    derezObj = derez(object, '$');
    checkForCompletion();
}
/**
 * Implementation of the Structured Cloning Algorithm.  Supports the
 * following object types:
 * - Blob
 * - Boolean
 * - Date object
 * - File object (deserialized as Blob object).
 * - Number object
 * - RegExp object
 * - String object
 * This is accomplished by doing the following:
 * 1) Using the cycle/decycle functions from:
 *    https://github.com/douglascrockford/JSON-js/blob/master/cycle.js
 * 2) Serializing/deserializing objects to/from string that don't work with
 *    JSON.stringify and JSON.parse by using object specific logic (eg use
 *    the FileReader API to convert a Blob or File object to a data URL.
 * 3) JSON.stringify and JSON.parse do the final conversion to/from string.
 */
Implementation of the Structured Cloning Algorithm.  Supports the
following object types:
- Blob
- Boolean
- Date object
- File object (deserialized as Blob object).
Implementation of the Structured Cloning Algorithm . Supports the following object types : - Blob - Boolean - Date object - File object ( deserialized as Blob object ) .
function decycle(object, callback) {
    var objects = []; 
    var paths = []; 
    var queuedObjects = [];
    var returnCallback = callback;
    var derezObj = void 0; 
    function checkForCompletion() {
        if (queuedObjects.length === 0) {
            returnCallback(derezObj);
        }
    }
    function readBlobAsDataURL(blob, path) {
        var reader = new FileReader();
        reader.onloadend = function (loadedEvent) {
            var dataURL = loadedEvent.target.result;
            var blobtype = 'Blob';
            if (util.isFile(blob)) {
            }
            updateEncodedBlob(dataURL, path, blobtype);
        };
        reader.readAsDataURL(blob);
    }
    function updateEncodedBlob(dataURL, path, blobtype) {
        var encoded = queuedObjects.indexOf(path);
        path = path.replace('$', 'derezObj');
        eval(path + '.$enc="' + dataURL + '"');
        eval(path + '.$type="' + blobtype + '"');
        queuedObjects.splice(encoded, 1);
        checkForCompletion();
    }
    function derez(value, path) {
        var i = void 0,
        name = void 0,
        nu = void 0; 
        var isObj = util.isObj(value);
        var valOfType = isObj && _typeof(value.valueOf());
        if (isObj && !['boolean', 'number', 'string'].includes(valOfType) && !util.isDate(value) && !util.isRegExp(value) && !util.isBlob(_w3cBlob2.default)) {
            for (i = 0; i < objects.length; i += 1) {
                if (objects[i] === value) {
                    return { $ref: paths[i] };
                }
            }
            objects.push(value);
            paths.push(path);
            if (Array.isArray(value)) {
                nu = [];
                for (i = 0; i < value.length; i += 1) {
                    nu[i] = derez(value[i], path + '[' + i + ']');
                }
            } else {
                nu = {};
                for (name in value) {
                    if (Object.prototype.hasOwnProperty.call(value, name)) {
                        nu[name] = derez(value[name], path + '[' + JSON.stringify(name) + ']');
                    }
                }
            }
            return nu;
        } else if (util.isBlob(value)) {
            queuedObjects.push(path);
            readBlobAsDataURL(value, path);
        } else if (valOfType === 'boolean') {
            value = {
                '$type': 'Boolean',
                '$enc': value.toString()
            };
        } else if (util.isDate(value)) {
            value = {
                '$type': 'Date',
                '$enc': value.getTime()
            };
        } else if (valOfType === 'number') {
            value = {
                '$type': 'Number',
                '$enc': value.toString()
            };
        } else if (util.isRegExp(value)) {
            value = {
                '$type': 'RegExp',
                '$enc': value.toString()
            };
        } else if (typeof value === 'number') {
            value = {
                '$type': 'number',
                '$enc': value + '' 
            };
        } else if (value === undefined) {
            value = {
                '$type': 'undefined'
            };
        }
        return value;
    }
    derezObj = derez(object, '$');
    checkForCompletion();
}
function decycle ( object , callback ) { var objects = [ ] ; var paths = [ ] ; var queuedObjects = [ ] ; var returnCallback = callback ; var derezObj = void 0 ; function checkForCompletion ( ) { if ( queuedObjects . length === 0 ) { returnCallback ( derezObj ) ; } } function readBlobAsDataURL ( blob , path ) { var reader = new FileReader ( ) ; reader . onloadend = function ( loadedEvent ) { var dataURL = loadedEvent . target . result ; var blobtype = 'Blob' ; if ( util . isFile ( blob ) ) { } updateEncodedBlob ( dataURL , path , blobtype ) ; } ; reader . readAsDataURL ( blob ) ; } function updateEncodedBlob ( dataURL , path , blobtype ) { var encoded = queuedObjects . indexOf ( path ) ; path = path . replace ( '$' , 'derezObj' ) ; eval ( path + '.$enc="' + dataURL + '"' ) ; eval ( path + '.$type="' + blobtype + '"' ) ; queuedObjects . splice ( encoded , 1 ) ; checkForCompletion ( ) ; } function derez ( value , path ) { var i = void 0 , name = void 0 , nu = void 0 ; var isObj = util . isObj ( value ) ; var valOfType = isObj && _typeof ( value . valueOf ( ) ) ; if ( isObj && ! [ 'boolean' , 'number' , 'string' ] . includes ( valOfType ) && ! util . isDate ( value ) && ! util . isRegExp ( value ) && ! util . isBlob ( _w3cBlob2 . default ) ) { for ( i = 0 ; i < objects . length ; i += 1 ) { if ( objects [ i ] === value ) { return { $ref : paths [ i ] } ; } } objects . push ( value ) ; paths . push ( path ) ; if ( Array . isArray ( value ) ) { nu = [ ] ; for ( i = 0 ; i < value . length ; i += 1 ) { nu [ i ] = derez ( value [ i ] , path + '[' + i + ']' ) ; } } else { nu = { } ; for ( name in value ) { if ( Object . prototype . hasOwnProperty . call ( value , name ) ) { nu [ name ] = derez ( value [ name ] , path + '[' + JSON . stringify ( name ) + ']' ) ; } } } return nu ; } else if ( util . isBlob ( value ) ) { queuedObjects . push ( path ) ; readBlobAsDataURL ( value , path ) ; } else if ( valOfType === 'boolean' ) { value = { '$type' : 'Boolean' , '$enc' : value . toString ( ) } ; } else if ( util . isDate ( value ) ) { value = { '$type' : 'Date' , '$enc' : value . getTime ( ) } ; } else if ( valOfType === 'number' ) { value = { '$type' : 'Number' , '$enc' : value . toString ( ) } ; } else if ( util . isRegExp ( value ) ) { value = { '$type' : 'RegExp' , '$enc' : value . toString ( ) } ; } else if ( typeof value === 'number' ) { value = { '$type' : 'number' , '$enc' : value + '' } ; } else if ( value === undefined ) { value = { '$type' : 'undefined' } ; } return value ; } derezObj = derez ( object , '$' ) ; checkForCompletion ( ) ; }
Implementation of the Structured Cloning Algorithm.
Implementation of the Structured Cloning Algorithm .
// From: https://github.com/douglascrockford/JSON-js/blob/master/cycle.js // Contains additional logic to convert the following object types to string // so that they can properly be encoded using JSON.stringify: //  *Boolean //  *Date //  *File //  *Blob //  *Number //  *Regex // Make a deep copy of an object or array, assuring that there is at most // one instance of each object or array in the resulting structure. The // duplicate references (which might be forming cycles) are replaced with // an object of the form //      {$ref: PATH} // where the PATH is a JSONPath string that locates the first occurance. // So, //      var a = []; //      a[0] = a; //      return JSON.stringify(JSON.decycle(a)); // produces the string '[{"$ref":"$"}]'. // JSONPath is used to locate the unique object. $ indicates the top level of // the object or array. [NUMBER] or [STRING] indicates a child member or // property. // Keep a reference to each unique object or array // Keep the path to each unique object or array // eslint-disable-line prefer-const /**
     * Check the queue to see if all objects have been processed.
     * if they have, call the callback with the converted object.
     */ /**
     * Convert a blob to a data URL.
     * @param {Blob} blob to convert.
     * @param {String} path of blob in object being encoded.
     */ // blobtype = 'File'; /**
     * Async handler to update a blob object to a data URL for encoding.
     * @param {String} dataURL
     * @param {String} path
     * @param {String} blobtype - file if the blob is a file; blob otherwise
     */ // The derez recurses through the object, producing the deep copy. // The loop counter // Property name // The new object or array // typeof null === 'object', so go on if this value is really an object but not // one of the weird builtin objects. // If the value is an object or array, look to see if we have already // encountered it. If so, return a $ref/path object. This is a hard way, // linear search that will get slower as the number of unique objects grows. // Otherwise, accumulate the unique value and its path. // If it is an array, replicate the array. // If it is an object, replicate the object. // Queue blob for conversion // handles NaN, Infinity, Negative Infinity