UNPKG

@sprucelabs/jest-json-reporter

Version:

Stream Jest results to stdout in JSON for ingestion by parent processes.

146 lines (141 loc) 6.11 kB
"use strict"; /* Cycle.js 2018-05-15 Public Domain. NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. This code should be minified before deployment. See http://javascript.crockford.com/jsmin.html USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO NOT CONTROL. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.retrocycle = exports.cycle = void 0; // The file uses the WeakMap feature of ES6. /*jslint eval */ /*property $ref, decycle, forEach, get, indexOf, isArray, keys, length, push, retrocycle, set, stringify, test */ const cycle = function (object, replacer) { 'use strict'; // 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":"$"}]'. // If a replacer function is provided, then it will be called for each value. // A replacer function receives a value and returns a replacement value. // JSONPath is used to locate the unique object. $ indicates the top level of // the object or array. [NUMBER] or [STRING] indicates a child element or // property. let objects = new WeakMap(); // object to path mappings return (function derez(value, path) { // The derez function recurses through the object, producing the deep copy. let oldPath; // The path of an earlier occurance of value let nu; // The new object or array // If a replacer function was provided, then call it to get a replacement value. if (replacer !== undefined) { value = replacer(value); } // typeof null === "object", so go on if this value is really an object but not // one of the weird builtin objects. if (typeof value === 'object' && value !== null && !(value instanceof Boolean) && !(value instanceof Date) && !(value instanceof Number) && !(value instanceof RegExp) && !(value instanceof String)) { // 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 uses an // ES6 WeakMap. oldPath = objects.get(value); if (oldPath !== undefined) { return { $ref: oldPath }; } // Otherwise, accumulate the unique value and its path. objects.set(value, path); // If it is an array, replicate the array. if (Array.isArray(value)) { nu = []; value.forEach(function (element, i) { nu[i] = derez(element, path + '[' + i + ']'); }); } else { // If it is an object, replicate the object. nu = {}; Object.keys(value).forEach(function (name) { nu[name] = derez(value[name], path + '[' + JSON.stringify(name) + ']'); }); } return nu; } return value; })(object, '$'); }; exports.cycle = cycle; const retrocycle = function ($) { 'use strict'; // Restore an object that was reduced by decycle. Members whose values are // objects of the form // {$ref: PATH} // are replaced with references to the value found by the PATH. This will // restore cycles. The object will be mutated. // The eval function is used to locate the values described by a PATH. The // root object is kept in a $ variable. A regular expression is used to // assure that the PATH is extremely well formed. The regexp contains nested // * quantifiers. That has been known to have extremely bad performance // problems on some browsers for very long strings. A PATH is expected to be // reasonably short. A PATH is allowed to belong to a very restricted subset of // Goessner's JSONPath. // So, // var s = '[{"$ref":"$"}]'; // return JSON.retrocycle(JSON.parse(s)); // produces an array containing a single element which is the array itself. let px = /^\$(?:\[(?:\d+|"(?:[^\\"\u0000-\u001f]|\\(?:[\\"\/bfnrt]|u[0-9a-zA-Z]{4}))*")\])*$/; (function rez(value) { // The rez function walks recursively through the object looking for $ref // properties. When it finds one that has a value that is a path, then it // replaces the $ref object with a reference to the value that is found by // the path. if (value && typeof value === 'object') { if (Array.isArray(value)) { value.forEach(function (element, i) { if (typeof element === 'object' && element !== null) { let path = element.$ref; if (typeof path === 'string' && px.test(path)) { value[i] = eval(path); } else { rez(element); } } }); } else { Object.keys(value).forEach(function (name) { let item = value[name]; if (typeof item === 'object' && item !== null) { let path = item.$ref; if (typeof path === 'string' && px.test(path)) { value[name] = eval(path); } else { rez(item); } } }); } } })($); return $; }; exports.retrocycle = retrocycle;