UNPKG

foop

Version:

interfaces that describe their intentions.

272 lines (210 loc) 20.3 kB
// --- // with a huge refactor to this, // with tons of safety // configuration like debugging on condition in certain places // stacktrace & sourcemap forcing on certain builds // this would provide a lovely debugging tool // --- var reStack = /(?:\n {4}at .*)+/; var errStack = function (err) { var stack = err instanceof Error ? err.stack : err; if (!stack) { return ''; } var match = stack.match(reStack); if (!match) { return ''; } return match[0].slice(1); }; // --- // https://github.com/ValYouW/njsTrace WRAPS ALL FN1? // https://github.com/scottnonnenberg/notate/blob/master/src/notate.js#L137 // https://github.com/Breeze/breeze.js.labs/blob/master/breeze.metadata-helper.js // https://github.com/v8/v8/wiki/Stack-Trace-API // https://github.com/sindresorhus/callsites var stacker = function () { var _ = Error.prepareStackTrace; Error.prepareStackTrace = function (_, stack) { return stack; }; var stack = new Error().stack.slice(1); Error.prepareStackTrace = _; return stack; }; // --- var stringify = function (x) { try { var str$1 = JSON.stringify(x, null, 2) return str$1 } catch (e) { var str = {} str.type = Object.prototype.toString.call(x) for (var prop in x) { str[prop] = stringify(x[prop]) } return stringify(x) } } var pretty = function (x) { return stringify(x).replace(/["\\[\]\,\']/g, ''); } // --- var weakCache = new WeakMap() var record = new WeakSet() var list = new Set() var cache = new Map() function debuggableStorage(x) { if (weakCache.has(x)) { weakCache.get(x).count += 1 } else { weakCache.set(x, x) } if (cache.has(x)) { cache.get(x).count += 1 } else { cache.set(x, x) } list.add(x) record.add(x) return debuggable } // --- function metadata() { var time = Date.now() var count = 0 return {time: time, count: count} } // --- function stackAt(index) { if ( index === void 0 ) index = 1; var stacks = stacker() var stack = stacks[index] var meta = {} // huge meta.thisArg = stack.getThis() meta.fn = stack.getFunction() // helpful meta.methodName = stack.getMethodName() meta.typeName = stack.getTypeName() meta.functionName = stack.getFunctionName() // file meta.fileName = stack.getFileName() meta.lineNumber = stack.getLineNumber() meta.columnNumber = stack.getColumnNumber() meta.origin = stack.getEvalOrigin() // bools var stackIs = { topLevel: stack.isToplevel(), constructor: stack.isConstructor(), native: stack.isNative(), } var topLevel = stackIs.topLevel; var constructor = stackIs.constructor; var native = stackIs.native; var methodName = meta.methodName; var functionName = meta.functionName; var thisArg = meta.thisArg; var fn = meta.fn; var fileName = meta.fileName; var lineNumber = meta.lineNumber; var columnNumber = meta.columnNumber; var origin = meta.origin; var called = {functionName: functionName, methodName: methodName, fileName: fileName, lineNumber: lineNumber} if (topLevel || constructor || native) { called.is = stackIs } if (origin != fileName) { called.origin = origin } if (called.thisArg === global) { called.thisArg = 'global' } return called } // could clone the data too function debuggable() { var stack = stackAt(2) var meta = metadata() var result = Object.assign({}, stack, {}, meta) result.args = arguments result.str = arguments.length !== 0 ? stringify(arguments) : '0 args' debuggableStorage(result) return result } debuggable.list = list debuggable.record = record debuggable.cache = cache debuggable.metadata = metadata debuggable.stackAt = stackAt // --- // where, pluck, evolve debuggable.values = function(cb) { var values = Array.from(debuggable.list.values()) // for entries // let index = 0 // const keys = Object.keys(where) // .reduce(function(reduced, value) { // reduced[index++] = next // return reduced // }, {}) if (cb) { return cb(values) } else { return values } } debuggable.where = function(where) { return debuggable.values().filter(where) } var queryable = [ 'functionName', 'methodName', 'fileName', 'lineNumber', 'count', 'args', 'str', 'time' ] // --- // filter, unique keys, index of the values with the uniq keys // debuggable.keys() // --- example --- // function gogo() { // debuggable(arguments) // } // class Go {} // Go.prototype.gogo = gogo // Go.prototype.zoomzoon = function() { // debuggable(arguments) // } // // gogo() // new Go().gogo() // new Go().gogo(1) // new Go().gogo(1) // new Go().zoomzoom('heyya') // ----- // functionName: 'gogo', // methodName: 'gogo', // fileName: '_play.js', // lineNumber: 189, // count: 0, // args: { '0': [Object] }, // str: '{\n "0": {\n "0": 1\n }\n}' } => { functionName: 'gogo', // const values = debuggable.values() // const R = require('ramda') // const propped = R.props(['functionName', 'methodName'], values) // const result = R.where(R.contains('zoomzoom'), propped) // console.log({result, propped}) // debuggable.cache.forEach(eh => console.log('list', eh)) // console.log(cache) // @example ramda filtering // const vals = Array.from(debuggable.values()) // const propped = vals.map(val => R.props(['functionName', 'methodName'], val)) // const funcLens = R.lensProp('functionName') // const funcWhere = R.where(funcLens, R.contains('zoomzoom')) // const funcSatisfies = R.where({ // functionName: R.equals('zoomzoom'), // }) // const evolved = vals.map(val => { // const lensed = R.view(funcLens, val) // const satisfies = funcSatisfies(val) // // console.log({lensed, satisfies, val}) // if (satisfies) return R.evolve({functionName: R.identity}, val) // else return false // }) // .filter(Boolean) // // .map(v => v[0] && v[1] ? R.fromPairs(v): v) // const result = R.where(R.contains('zoomzoom'), propped) // // console.log('eh', propped) // // console.log({result, propped, vals}) // console.log(evolved) module.exports = debuggable //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVidWdnYWJsZS5qcyIsInNvdXJjZXMiOlsiZGVidWdnYWJsZS5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyJcbi8vIC0tLVxuXG4vLyB3aXRoIGEgaHVnZSByZWZhY3RvciB0byB0aGlzLCBcbi8vIHdpdGggdG9ucyBvZiBzYWZldHlcbi8vIGNvbmZpZ3VyYXRpb24gbGlrZSBkZWJ1Z2dpbmcgb24gY29uZGl0aW9uIGluIGNlcnRhaW4gcGxhY2VzXG4vLyBzdGFja3RyYWNlICYgc291cmNlbWFwIGZvcmNpbmcgb24gY2VydGFpbiBidWlsZHNcbi8vIHRoaXMgd291bGQgcHJvdmlkZSBhIGxvdmVseSBkZWJ1Z2dpbmcgdG9vbFxuXG4vLyAtLS1cbmNvbnN0IHJlU3RhY2sgPSAvKD86XFxuIHs0fWF0IC4qKSsvO1xuY29uc3QgZXJyU3RhY2sgPSBlcnIgPT4ge1xuXHRjb25zdCBzdGFjayA9IGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLnN0YWNrIDogZXJyO1xuXG5cdGlmICghc3RhY2spIHtcblx0XHRyZXR1cm4gJyc7XG5cdH1cblxuXHRjb25zdCBtYXRjaCA9IHN0YWNrLm1hdGNoKHJlU3RhY2spO1xuXG5cdGlmICghbWF0Y2gpIHtcblx0XHRyZXR1cm4gJyc7XG5cdH1cblxuICByZXR1cm4gbWF0Y2hbMF0uc2xpY2UoMSk7XG59O1xuXG4vLyAtLS1cbi8vIGh0dHBzOi8vZ2l0aHViLmNvbS9WYWxZb3VXL25qc1RyYWNlIFdSQVBTIEFMTCBGTjE/XG4vLyBodHRwczovL2dpdGh1Yi5jb20vc2NvdHRub25uZW5iZXJnL25vdGF0ZS9ibG9iL21hc3Rlci9zcmMvbm90YXRlLmpzI0wxMzdcbi8vIGh0dHBzOi8vZ2l0aHViLmNvbS9CcmVlemUvYnJlZXplLmpzLmxhYnMvYmxvYi9tYXN0ZXIvYnJlZXplLm1ldGFkYXRhLWhlbHBlci5qc1xuLy8gaHR0cHM6Ly9naXRodWIuY29tL3Y4L3Y4L3dpa2kvU3RhY2stVHJhY2UtQVBJXG4vLyBodHRwczovL2dpdGh1Yi5jb20vc2luZHJlc29yaHVzL2NhbGxzaXRlc1xuY29uc3Qgc3RhY2tlciA9ICgpID0+IHtcblx0Y29uc3QgXyA9IEVycm9yLnByZXBhcmVTdGFja1RyYWNlO1xuXHRFcnJvci5wcmVwYXJlU3RhY2tUcmFjZSA9IChfLCBzdGFjaykgPT4gc3RhY2s7XG5cdGNvbnN0IHN0YWNrID0gbmV3IEVycm9yKCkuc3RhY2suc2xpY2UoMSk7XG5cdEVycm9yLnByZXBhcmVTdGFja1RyYWNlID0gXztcblx0cmV0dXJuIHN0YWNrO1xufTtcblxuLy8gLS0tXG52YXIgc3RyaW5naWZ5ID0geCA9PiB7XG4gIHRyeSB7XG4gICAgY29uc3Qgc3RyID0gSlNPTi5zdHJpbmdpZnkoeCwgbnVsbCwgMilcbiAgICByZXR1cm4gc3RyXG4gIH1cbiAgY2F0Y2ggKGUpIHtcbiAgICB2YXIgc3RyID0ge31cbiAgICBzdHIudHlwZSA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh4KVxuICAgIGZvciAodmFyIHByb3AgaW4geCkge1xuICAgICAgc3RyW3Byb3BdID0gc3RyaW5naWZ5KHhbcHJvcF0pXG4gICAgfVxuICAgIHJldHVybiBzdHJpbmdpZnkoeClcbiAgfVxufVxuXG52YXIgcHJldHR5ID0geCA9PiBzdHJpbmdpZnkoeCkucmVwbGFjZSgvW1wiXFxcXFtcXF1cXCxcXCddL2csICcnKVxuXG4vLyAtLS1cblxudmFyIHdlYWtDYWNoZSA9IG5ldyBXZWFrTWFwKClcbnZhciByZWNvcmQgPSBuZXcgV2Vha1NldCgpXG52YXIgbGlzdCA9IG5ldyBTZXQoKVxudmFyIGNhY2hlID0gbmV3IE1hcCgpXG5cbmZ1bmN0aW9uIGRlYnVnZ2FibGVTdG9yYWdlKHgpIHtcbiAgaWYgKHdlYWtDYWNoZS5oYXMoeCkpIHdlYWtDYWNoZS5nZXQoeCkuY291bnQgKz0gMSBcbiAgZWxzZSB3ZWFrQ2FjaGUuc2V0KHgsIHgpXG4gIFxuICBpZiAoY2FjaGUuaGFzKHgpKSBjYWNoZS5nZXQoeCkuY291bnQgKz0gMSBcbiAgZWxzZSBjYWNoZS5zZXQoeCwgeClcbiAgICBcbiAgbGlzdC5hZGQoeClcbiAgcmVjb3JkLmFkZCh4KVxuICByZXR1cm4gZGVidWdnYWJsZVxufVxuXG4vLyAtLS1cblxuZnVuY3Rpb24gbWV0YWRhdGEoKSB7XG4gIGNvbnN0IHRpbWUgPSBEYXRlLm5vdygpXG4gIGNvbnN0IGNvdW50ID0gMFxuICByZXR1cm4ge3RpbWUsIGNvdW50fVxufVxuXG4vLyAtLS1cblxuZnVuY3Rpb24gc3RhY2tBdChpbmRleCA9IDEpIHtcbiAgY29uc3Qgc3RhY2tzID0gc3RhY2tlcigpXG4gIGNvbnN0IHN0YWNrID0gc3RhY2tzW2luZGV4XVxuICBjb25zdCBtZXRhID0ge31cblxuICAvLyBodWdlXG4gIG1ldGEudGhpc0FyZyA9IHN0YWNrLmdldFRoaXMoKVxuICBtZXRhLmZuID0gc3RhY2suZ2V0RnVuY3Rpb24oKVxuXG4gIC8vIGhlbHBmdWxcbiAgbWV0YS5tZXRob2ROYW1lID0gc3RhY2suZ2V0TWV0aG9kTmFtZSgpXG4gIG1ldGEudHlwZU5hbWUgPSBzdGFjay5nZXRUeXBlTmFtZSgpXG4gIG1ldGEuZnVuY3Rpb25OYW1lID0gc3RhY2suZ2V0RnVuY3Rpb25OYW1lKClcbiAgXG4gIC8vIGZpbGVcbiAgbWV0YS5maWxlTmFtZSA9IHN0YWNrLmdldEZpbGVOYW1lKCkgXG4gIG1ldGEubGluZU51bWJlciA9IHN0YWNrLmdldExpbmVOdW1iZXIoKVxuICBtZXRhLmNvbHVtbk51bWJlciA9IHN0YWNrLmdldENvbHVtbk51bWJlcigpXG4gIG1ldGEub3JpZ2luID0gc3RhY2suZ2V0RXZhbE9yaWdpbigpXG5cbiAgLy8gYm9vbHNcbiAgY29uc3Qgc3RhY2tJcyA9IHtcbiAgICB0b3BMZXZlbDogc3RhY2suaXNUb3BsZXZlbCgpLFxuICAgIGNvbnN0cnVjdG9yOiBzdGFjay5pc0NvbnN0cnVjdG9yKCksXG4gICAgbmF0aXZlOiBzdGFjay5pc05hdGl2ZSgpLFxuICB9XG5cbiAgY29uc3Qge1xuICAgIHRvcExldmVsLCBcbiAgICBjb25zdHJ1Y3RvciwgXG4gICAgbmF0aXZlLFxuICB9ID0gc3RhY2tJc1xuICBjb25zdCB7XG4gICAgbWV0aG9kTmFtZSwgXG4gICAgZnVuY3Rpb25OYW1lLFxuICAgIHRoaXNBcmcsIFxuICAgIGZuLCBcbiAgICBmaWxlTmFtZSwgXG4gICAgbGluZU51bWJlciwgXG4gICAgY29sdW1uTnVtYmVyLCBcbiAgICBvcmlnaW4sXG4gIH0gPSBtZXRhXG5cbiAgbGV0IGNhbGxlZCA9IHtmdW5jdGlvbk5hbWUsIG1ldGhvZE5hbWUsIGZpbGVOYW1lLCBsaW5lTnVtYmVyfVxuXG4gIGlmICh0b3BMZXZlbCB8fCBjb25zdHJ1Y3RvciB8fCBuYXRpdmUpIHtcbiAgICBjYWxsZWQuaXMgPSBzdGFja0lzXG4gIH1cbiAgXG4gIGlmIChvcmlnaW4gIT0gZmlsZU5hbWUpIHtcbiAgICBjYWxsZWQub3JpZ2luID0gb3JpZ2luXG4gIH1cblxuICBpZiAoY2FsbGVkLnRoaXNBcmcgPT09IGdsb2JhbCkgY2FsbGVkLnRoaXNBcmcgPSAnZ2xvYmFsJ1xuXG4gIHJldHVybiBjYWxsZWRcbn1cblxuLy8gY291bGQgY2xvbmUgdGhlIGRhdGEgdG9vXG5mdW5jdGlvbiBkZWJ1Z2dhYmxlKCkge1xuICBjb25zdCBzdGFjayA9IHN0YWNrQXQoMilcbiAgY29uc3QgbWV0YSA9IG1ldGFkYXRhKClcbiAgY29uc3QgcmVzdWx0ID0gT2JqZWN0LmFzc2lnbih7fSwgc3RhY2ssIHt9LCBtZXRhKVxuICByZXN1bHQuYXJncyA9IGFyZ3VtZW50cyBcbiAgcmVzdWx0LnN0ciA9IGFyZ3VtZW50cy5sZW5ndGggIT09IDAgPyBzdHJpbmdpZnkoYXJndW1lbnRzKSA6ICcwIGFyZ3MnXG5cbiAgZGVidWdnYWJsZVN0b3JhZ2UocmVzdWx0KVxuXG4gIHJldHVybiByZXN1bHRcbn1cbmRlYnVnZ2FibGUubGlzdCA9IGxpc3RcbmRlYnVnZ2FibGUucmVjb3JkID0gcmVjb3JkXG5kZWJ1Z2dhYmxlLmNhY2hlID0gY2FjaGVcbmRlYnVnZ2FibGUubWV0YWRhdGEgPSBtZXRhZGF0YVxuZGVidWdnYWJsZS5zdGFja0F0ID0gc3RhY2tBdFxuXG4vLyAtLS1cblxuLy8gd2hlcmUsIHBsdWNrLCBldm9sdmVcbmRlYnVnZ2FibGUudmFsdWVzID0gZnVuY3Rpb24oY2IpIHtcbiAgY29uc3QgdmFsdWVzID0gQXJyYXkuZnJvbShkZWJ1Z2dhYmxlLmxpc3QudmFsdWVzKCkpXG5cbiAgLy8gZm9yIGVudHJpZXNcbiAgLy8gbGV0IGluZGV4ID0gMFxuICAvLyBjb25zdCBrZXlzID0gT2JqZWN0LmtleXMod2hlcmUpXG4gIC8vIC5yZWR1Y2UoZnVuY3Rpb24ocmVkdWNlZCwgdmFsdWUpIHtcbiAgLy8gICByZWR1Y2VkW2luZGV4KytdID0gbmV4dFxuICAvLyAgIHJldHVybiByZWR1Y2VkXG4gIC8vIH0sIHt9KVxuXG4gIGlmIChjYikgcmV0dXJuIGNiKHZhbHVlcylcbiAgZWxzZSByZXR1cm4gdmFsdWVzXG59XG5cbmRlYnVnZ2FibGUud2hlcmUgPSBmdW5jdGlvbih3aGVyZSkge1xuICByZXR1cm4gZGVidWdnYWJsZS52YWx1ZXMoKS5maWx0ZXIod2hlcmUpXG59XG5cbnZhciBxdWVyeWFibGUgPSBbXG4gICdmdW5jdGlvbk5hbWUnLFxuICAgJ21ldGhvZE5hbWUnLFxuICAgJ2ZpbGVOYW1lJyxcbiAgICdsaW5lTnVtYmVyJyxcbiAgICdjb3VudCcsXG4gICAnYXJncycsXG4gICAnc3RyJyxcbiAgICd0aW1lJ1xuICBdXG5cbi8vIC0tLVxuXG4vLyBmaWx0ZXIsIHVuaXF1ZSBrZXlzLCBpbmRleCBvZiB0aGUgdmFsdWVzIHdpdGggdGhlIHVuaXEga2V5c1xuLy8gZGVidWdnYWJsZS5rZXlzKClcblxuXG4vLyAtLS0gZXhhbXBsZSAtLS1cblxuLy8gZnVuY3Rpb24gZ29nbygpIHtcbi8vICAgZGVidWdnYWJsZShhcmd1bWVudHMpXG4vLyB9XG5cbi8vIGNsYXNzIEdvIHt9XG4vLyBHby5wcm90b3R5cGUuZ29nbyA9IGdvZ29cbi8vIEdvLnByb3RvdHlwZS56b29tem9vbiA9IGZ1bmN0aW9uKCkge1xuLy8gICBkZWJ1Z2dhYmxlKGFyZ3VtZW50cylcbi8vIH1cblxuLy8gLy8gZ29nbygpXG4vLyBuZXcgR28oKS5nb2dvKClcbi8vIG5ldyBHbygpLmdvZ28oMSlcbi8vIG5ldyBHbygpLmdvZ28oMSlcbi8vIG5ldyBHbygpLnpvb216b29tKCdoZXl5YScpXG5cbi8vIC0tLS0tXG5cbi8vIGZ1bmN0aW9uTmFtZTogJ2dvZ28nLFxuLy8gbWV0aG9kTmFtZTogJ2dvZ28nLFxuLy8gZmlsZU5hbWU6ICdfcGxheS5qcycsXG4vLyBsaW5lTnVtYmVyOiAxODksXG4vLyBjb3VudDogMCxcbi8vIGFyZ3M6IHsgJzAnOiBbT2JqZWN0XSB9LFxuLy8gc3RyOiAne1xcbiAgXCIwXCI6IHtcXG4gICAgXCIwXCI6IDFcXG4gIH1cXG59JyB9ID0+IHsgZnVuY3Rpb25OYW1lOiAnZ29nbycsXG5cbi8vIGNvbnN0IHZhbHVlcyA9IGRlYnVnZ2FibGUudmFsdWVzKClcbi8vIGNvbnN0IFIgPSByZXF1aXJlKCdyYW1kYScpXG4vLyBjb25zdCBwcm9wcGVkID0gUi5wcm9wcyhbJ2Z1bmN0aW9uTmFtZScsICdtZXRob2ROYW1lJ10sIHZhbHVlcylcbi8vIGNvbnN0IHJlc3VsdCA9IFIud2hlcmUoUi5jb250YWlucygnem9vbXpvb20nKSwgcHJvcHBlZClcblxuLy8gY29uc29sZS5sb2coe3Jlc3VsdCwgcHJvcHBlZH0pXG5cbi8vIGRlYnVnZ2FibGUuY2FjaGUuZm9yRWFjaChlaCA9PiBjb25zb2xlLmxvZygnbGlzdCcsIGVoKSlcbi8vIGNvbnNvbGUubG9nKGNhY2hlKVxuXG4vLyBAZXhhbXBsZSByYW1kYSBmaWx0ZXJpbmcgXG5cbi8vIGNvbnN0IHZhbHMgPSBBcnJheS5mcm9tKGRlYnVnZ2FibGUudmFsdWVzKCkpXG4vLyBjb25zdCBwcm9wcGVkID0gdmFscy5tYXAodmFsID0+IFIucHJvcHMoWydmdW5jdGlvbk5hbWUnLCAnbWV0aG9kTmFtZSddLCB2YWwpKVxuXG4vLyBjb25zdCBmdW5jTGVucyA9IFIubGVuc1Byb3AoJ2Z1bmN0aW9uTmFtZScpXG4vLyBjb25zdCBmdW5jV2hlcmUgPSBSLndoZXJlKGZ1bmNMZW5zLCBSLmNvbnRhaW5zKCd6b29tem9vbScpKVxuLy8gY29uc3QgZnVuY1NhdGlzZmllcyA9IFIud2hlcmUoe1xuLy8gICAgIGZ1bmN0aW9uTmFtZTogUi5lcXVhbHMoJ3pvb216b29tJyksXG4vLyAgIH0pXG5cbi8vIGNvbnN0IGV2b2x2ZWQgPSB2YWxzLm1hcCh2YWwgPT4ge1xuICBcbi8vICAgY29uc3QgbGVuc2VkID0gUi52aWV3KGZ1bmNMZW5zLCB2YWwpXG4vLyAgIGNvbnN0IHNhdGlzZmllcyA9IGZ1bmNTYXRpc2ZpZXModmFsKVxuICBcbi8vICAgLy8gY29uc29sZS5sb2coe2xlbnNlZCwgc2F0aXNmaWVzLCB2YWx9KVxuICBcbi8vICAgaWYgKHNhdGlzZmllcykgcmV0dXJuIFIuZXZvbHZlKHtmdW5jdGlvbk5hbWU6IFIuaWRlbnRpdHl9LCB2YWwpXG4vLyAgIGVsc2UgcmV0dXJuIGZhbHNlXG4vLyB9KVxuLy8gLmZpbHRlcihCb29sZWFuKVxuXG4vLyAvLyAubWFwKHYgPT4gdlswXSAmJiB2WzFdID8gUi5mcm9tUGFpcnModik6IHYpXG4vLyBjb25zdCByZXN1bHQgPSBSLndoZXJlKFIuY29udGFpbnMoJ3pvb216b29tJyksIHByb3BwZWQpXG5cbi8vIC8vIGNvbnNvbGUubG9nKCdlaCcsIHByb3BwZWQpXG5cbi8vIC8vIGNvbnNvbGUubG9nKHtyZXN1bHQsIHByb3BwZWQsIHZhbHN9KVxuLy8gY29uc29sZS5sb2coZXZvbHZlZClcblxubW9kdWxlLmV4cG9ydHMgPSBkZWJ1Z2dhYmxlIl0sIm5hbWVzIjpbImNvbnN0Iiwic3RyIiwibGV0Il0sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7OztBQVVBQSxHQUFLLENBQUMsT0FBTyxHQUFHLGtCQUFrQixDQUFDO0FBQ25DQSxHQUFLLENBQUMsUUFBUSxHQUFHLFVBQUEsR0FBRyxDQUFBLENBQUMsQUFBRztDQUN2QkEsR0FBSyxDQUFDLEtBQUss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