convert.js 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. exports.v8LocationToInspectorLocation = function(v8loc) {
  2. return {
  3. scriptId: v8loc.script_id.toString(),
  4. lineNumber: v8loc.line,
  5. columnNumber: v8loc.column
  6. };
  7. };
  8. // Conversions between v8 file paths and node-inspector urls
  9. // Kind Path Url
  10. // UNIX /dir/app.js file:///dir/app.js
  11. // Windows c:\dir\app.js file:///C:/dir/app.js
  12. // UNC \\SHARE\app.js file://SHARE/app.js
  13. exports.v8NameToInspectorUrl = function(v8name) {
  14. if (!v8name || v8name === 'repl') {
  15. // Call to `evaluate` from user-land creates a new script with undefined URL.
  16. // REPL has null main script file and calls `evaluate` with `repl`
  17. // as the file name.
  18. //
  19. // When we send an empty string as URL, front-end opens the source
  20. // as VM-only script (named "[VM] {script-id}").
  21. //
  22. // The empty name of the main script file is displayed as "(program)".
  23. return '';
  24. }
  25. if (/^\//.test(v8name)) {
  26. return 'file://' + v8name;
  27. } else if (/^[a-zA-Z]:\\/.test(v8name)) {
  28. return 'file:///' + v8name.replace(/\\/g, '/');
  29. } else if (/^\\\\/.test(v8name)) {
  30. return 'file://' + v8name.substring(2).replace(/\\/g, '/');
  31. }
  32. return v8name;
  33. };
  34. exports.inspectorUrlToV8Name = function(url) {
  35. var path = url.replace(/^file:\/\//, '');
  36. if (/^\/[a-zA-Z]:\//.test(path))
  37. return path.substring(1).replace(/\//g, '\\'); // Windows disk path
  38. if (/^\//.test(path))
  39. return path; // UNIX-style
  40. if (/^file:\/\//.test(url))
  41. return '\\\\' + path.replace(/\//g, '\\'); // Windows UNC path
  42. return url;
  43. };
  44. exports.v8ScopeTypeToString = function(v8ScopeType) {
  45. switch (v8ScopeType) {
  46. case 0:
  47. return 'global';
  48. case 1:
  49. return 'local';
  50. case 2:
  51. return 'with';
  52. case 3:
  53. return 'closure';
  54. case 4:
  55. return 'catch';
  56. default:
  57. return 'unknown';
  58. }
  59. };
  60. exports.v8RefToInspectorObject = function(ref) {
  61. var desc = '',
  62. type = ref.type,
  63. subtype,
  64. size,
  65. name,
  66. objectId,
  67. inspectorResult;
  68. switch (type) {
  69. case 'object':
  70. name = /#<(\w+)>/.exec(ref.text);
  71. if (name && name.length > 1) {
  72. desc = name[1];
  73. if (desc === 'Array' || desc === 'Buffer') {
  74. size = ref.properties.filter(function(p) { return /^\d+$/.test(p.name);}).length;
  75. desc += '[' + size + ']';
  76. subtype = 'array';
  77. }
  78. } else if (ref.className === 'Date') {
  79. desc = new Date(ref.value || NaN).toString();
  80. subtype = 'date';
  81. } else {
  82. desc = ref.className || 'Object';
  83. }
  84. break;
  85. case 'regexp':
  86. type = 'object';
  87. subtype = 'regexp';
  88. desc = ref.text || '';
  89. /*
  90. We need to collect RegExp flags and append they to description,
  91. or open issue in NodeJS same as 'RegExp text serialized without flags'
  92. */
  93. break;
  94. case 'function':
  95. desc = ref.text || 'function()';
  96. break;
  97. case 'error':
  98. type = 'object';
  99. desc = ref.text || 'Error';
  100. break;
  101. default:
  102. desc = ref.text || '';
  103. break;
  104. }
  105. if (desc.length > 100) {
  106. desc = desc.substring(0, 100) + '\u2026';
  107. }
  108. objectId = ref.handle;
  109. if (objectId === undefined)
  110. objectId = ref.ref;
  111. inspectorResult = {
  112. type: type,
  113. subtype: subtype,
  114. objectId: String(objectId),
  115. className: ref.className,
  116. description: desc
  117. };
  118. return inspectorResult;
  119. };
  120. exports.v8ObjectToInspectorProperties = function(obj, refs, options) {
  121. var proto = obj.protoObject,
  122. props = obj.properties || [],
  123. ownProperties = options.ownProperties,
  124. accessorPropertiesOnly = options.accessorPropertiesOnly;
  125. props = props.map(function(prop) {
  126. var ref = refs[prop.ref];
  127. var inspectorProperty = {
  128. name: String(prop.name),
  129. writable: !(prop.attributes & 1 << 0),
  130. enumerable: !(prop.attributes & 1 << 1),
  131. configurable: !(prop.attributes & 1 << 2),
  132. value: exports.v8ResultToInspectorResult(ref)
  133. };
  134. return inspectorProperty;
  135. });
  136. if (ownProperties && proto) {
  137. proto = refs[proto.ref];
  138. if (proto.type !== 'undefined') {
  139. props.push({
  140. name: '__proto__',
  141. value: exports.v8RefToInspectorObject(proto),
  142. writable: true,
  143. configurable: true,
  144. enumerable: false,
  145. isOwn: true
  146. });
  147. }
  148. }
  149. props = props.filter(function(prop) {
  150. /*
  151. Node.js does not return get/set property descriptors now (v0.11.11),
  152. therefore we can't fully implement 'accessorPropertiesOnly'.
  153. See https://github.com/joyent/node/issues/7139
  154. */
  155. var isAccessorProperty = ('get' in prop || 'set' in prop);
  156. return accessorPropertiesOnly ? isAccessorProperty : !isAccessorProperty;
  157. });
  158. return props;
  159. };
  160. exports.v8ErrorToInspectorError = function(message) {
  161. var nameMatch = /^([^:]+):/.exec(message);
  162. return {
  163. type: 'object',
  164. objectId: 'ERROR',
  165. className: nameMatch ? nameMatch[1] : 'Error',
  166. description: message
  167. };
  168. };
  169. exports.v8ResultToInspectorResult = function(result) {
  170. var subtype,
  171. inspectorResult;
  172. if (['object', 'function', 'regexp', 'error'].indexOf(result.type) > -1) {
  173. return exports.v8RefToInspectorObject(result);
  174. }
  175. if (result.type == 'null') {
  176. // workaround for the problem with front-end's setVariableValue
  177. // implementation not preserving null type
  178. result.value = null;
  179. subtype = 'null';
  180. }
  181. inspectorResult = {
  182. type: result.type,
  183. subtype: subtype,
  184. value: result.value,
  185. description: String(result.value)
  186. };
  187. return inspectorResult;
  188. };
  189. exports.inspectorValueToV8Value = function(value) {
  190. if (value.value === undefined && value.objectId === undefined)
  191. return { type: 'undefined' };
  192. if (value.objectId) {
  193. return { handle: Number(value.objectId) };
  194. }
  195. return value;
  196. };
  197. exports.v8FunctionLookupToFunctionDetails = function(handleData) {
  198. return {
  199. details: {
  200. location: {
  201. scriptId: String(handleData.scriptId),
  202. lineNumber: handleData.line,
  203. columnNumber: handleData.column
  204. },
  205. name: handleData.name || handleData.inferredName,
  206. // There is a list of scope ids in responseBody.scopes, but not scope
  207. // details :( // We need to issue `scopes` request to fetch scopes
  208. // details, but we don't have frame number where the function was defined.
  209. // Let's leave the scopeChain empty for now.
  210. scopeChain: []
  211. }
  212. };
  213. };
  214. exports.v8ScriptIdToInspectorId = function(scriptId) {
  215. return String(scriptId);
  216. };
  217. exports.inspectorScriptIdToV8Id = function(scriptId) {
  218. return Number(scriptId);
  219. };