UNPKG

chrome-unmirror

Version:

Transform mirror objects from a remote Chrome debugger into local values

152 lines (122 loc) 4.18 kB
'use strict'; var ERROR_CONSTRUCTORS = { 'Error': Error, 'EvalError': EvalError, 'InternalError': Error, 'RangeError': RangeError, 'ReferenceError': ReferenceError, 'SyntaxError': SyntaxError, 'TypeError': TypeError, 'URIError': URIError }; var classes = {}; function unmirror(remoteObj) { var type = remoteObj.type; var subtype = remoteObj.subtype; var className = remoteObj.className; var value = remoteObj.value; var preview = remoteObj.preview; var description = remoteObj.description; var props = preview && preview.properties || []; if (type === 'string') return value; if (type === 'function') return function () {}; if (type === 'undefined') return undefined; if (type === 'boolean') return value === 'true' || value === true; if (type === 'symbol') { if (typeof Symbol === 'undefined') return; var match = (description || '').match(/Symbol\((.*)\)/); return Symbol(match && match[1] || undefined); } if (type === 'number') { // If message came from Console domain if (typeof value === 'number') return value; switch (value) { case 'NaN': return NaN; case '-Infinity': return -Infinity; case 'Infinity': return Infinity; case '-0': return -0; default: return maybeJSON(value); } } if (subtype === 'null') return null; if (subtype === 'date') return new Date(description); if (subtype === 'node') return className; if (subtype === 'regexp') { var source = undefined, lastIndex = undefined, flags = ''; // If message came from Runtime or Debugger domain props.forEach(function (prop) { if (prop.name === 'source') source = prop.value; if (prop.name === 'global' && unmirror(prop)) flags += 'g'; if (prop.name === 'ignoreCase' && unmirror(prop)) flags += 'i'; if (prop.name === 'multiline' && unmirror(prop)) flags += 'm'; if (prop.name === 'lastIndex') lastIndex = unmirror(prop); }); // If message came from Console domain if (source === undefined) { var i = description.lastIndexOf(description[0]); source = description.slice(1, i); flags = description.slice(i + 1); } var re = new RegExp(source, flags); re.lastIndex = lastIndex; return re; } if (subtype === 'error') { var _ret = (function () { var Constructor = ERROR_CONSTRUCTORS[className] || Error; var lines = (description || '').split('\n'), msg = lines[0]; if (className && msg.slice(0, className.length) === className) { msg = msg.slice(className.length + 1).trim(); } var stack = lines.slice(1).join('\n'), err = new Constructor(msg); if (stack) Object.defineProperty(err, 'stack', { enumerable: false, value: stack }); props.forEach(function (p) { Object.defineProperty(err, p.name, { enumerable: false, value: unmirror(p) }); }); return { v: err }; })(); if (typeof _ret === 'object') return _ret.v; } // Mirror objects for Maps and Sets do not include elements, // you'll need to fetch them through the Runtime domain. A // module for that (also to unmirror lossy previews) is in the works. if (subtype === 'map') return typeof Map !== 'undefined' ? new Map() : undefined; if (subtype === 'set') return typeof Set !== 'undefined' ? new Set() : undefined; if (subtype === 'array') return props.map(unmirror); var o = typeof value === 'object' ? value : makeInstance(className); props.forEach(function (prop) { return o[prop.name] = unmirror(prop); }); return o; } function maybeJSON(value, notSetValue) { if (value === undefined) return notSetValue; try { return JSON.parse(value); } catch (_) { return value; } } function makeInstance(className) { if (!className || className === 'Object') return {}; if (!classes[className]) { var namedFunction = new Function('return function ' + className + '() {}'); classes[className] = namedFunction(); } return new classes[className](); } module.exports = unmirror;