// Copyright 2020 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Helpers for printing in correctness fuzzing. // Global helper functions for printing. var __prettyPrint; var __prettyPrintExtra; // Track caught exceptions. var __caught = 0; // Track a hash of all printed values - printing is cut off after a // certain size. var __hash = 0; (function() { const charCodeAt = String.prototype.charCodeAt; const join = Array.prototype.join; const map = Array.prototype.map; const substring = String.prototype.substring; const toString = Object.prototype.toString; // Same as in mjsunit.js. const classOf = function(object) { // Argument must not be null or undefined. const string = toString.call(object); // String has format [object ]. return substring.call(string, 8, string.length - 1); }; // For standard cases use original prettyPrinted from mjsunit. const origPrettyPrinted = prettyPrinted; // Override prettyPrinted with a version that also recusively prints objects // and arrays with a depth of 4. We don't track circles, but we'd cut off // after a depth of 4 if there are any. prettyPrinted = function prettyPrinted(value, depth=4) { if (depth <= 0) { return "..."; } switch (typeof value) { case "object": if (value === null) return "null"; switch (classOf(value)) { case "Array": return prettyPrintedArray(value, depth); case "Object": return prettyPrintedObject(value, depth); } } // Fall through to original version for all other types. return origPrettyPrinted(value); } // Helper for pretty array with depth. function prettyPrintedArray(array, depth) { const result = map.call(array, (value, index, array) => { if (value === undefined && !(index in array)) return ""; return prettyPrinted(value, depth - 1); }); return `[${join.call(result, ", ")}]`; } // Helper for pretty objects with depth. function prettyPrintedObject(object, depth) { const keys = Object.keys(object); const prettyValues = map.call(keys, (key) => { return `${key}: ${prettyPrinted(object[key], depth - 1)}`; }); const content = join.call(prettyValues, ", "); return `${object.constructor.name || "Object"}{${content}}`; } // Helper for calculating a hash code of a string. function hashCode(str) { let hash = 0; if (str.length == 0) { return hash; } for (let i = 0; i < str.length; i++) { const char = charCodeAt.call(str, i); hash = ((hash << 5) - hash) + char; hash = hash & hash; } return hash; } // Upper limit for calling extra printing. When reached, hashes of // strings are tracked and printed instead. let maxExtraPrinting = 100; // Helper for pretty printing. __prettyPrint = function(value, extra=false) { let str = prettyPrinted(value); // Change __hash with the contents of the full string to // keep track of differences also when we don't print. const hash = hashCode(str); __hash = hashCode(hash + __hash.toString()); if (extra && maxExtraPrinting-- <= 0) { return; } // Cut off long strings to prevent overloading I/O. We still track // the hash of the full string. if (str.length > 64) { const head = substring.call(str, 0, 54); const tail = substring.call(str, str.length - 10, str.length - 1); str = `${head}[...]${tail}`; } print(str); }; __prettyPrintExtra = function (value) { __prettyPrint(value, true); } })();