From 295e74275ef2292454cd0ddad8c5b550fa9b4536 Mon Sep 17 00:00:00 2001 From: "rossberg@chromium.org" Date: Mon, 18 Mar 2013 14:03:15 +0000 Subject: [PATCH] More useful result pretty printing for d8 For example: d8> ["hi", 5, [2,3],Object.prototype.toString, {get a() { return a}, b: 9, set a(x) {this.b=x}}, null, undefined] ["hi", 5, [2, 3], function toString() { [native code] }, {get a() { return a}, set a(x) {this.b=x}, b: 9}, null, undefined] Deactivated in test mode. R=yangguo@chromium.org BUG= Review URL: https://codereview.chromium.org/12653003 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13966 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/d8.cc | 26 +++++++++++++++++++------- src/d8.js | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 7 deletions(-) diff --git a/src/d8.cc b/src/d8.cc index eaebd900ef..00b23fb9b3 100644 --- a/src/d8.cc +++ b/src/d8.cc @@ -214,13 +214,25 @@ bool Shell::ExecuteString(Isolate* isolate, return false; } else { ASSERT(!try_catch.HasCaught()); - if (print_result && !result->IsUndefined()) { - // If all went well and the result wasn't undefined then print - // the returned value. - v8::String::Utf8Value str(result); - size_t count = fwrite(*str, sizeof(**str), str.length(), stdout); - (void) count; // Silence GCC-4.5.x "unused result" warning. - printf("\n"); + if (print_result) { + if (options.test_shell) { + if (!result->IsUndefined()) { + // If all went well and the result wasn't undefined then print + // the returned value. + v8::String::Utf8Value str(result); + fwrite(*str, sizeof(**str), str.length(), stdout); + printf("\n"); + } + } else { + Context::Scope context_scope(utility_context_); + Handle global = utility_context_->Global(); + Handle fun = global->Get(String::New("Stringify")); + Handle argv[1] = { result }; + Handle s = Handle::Cast(fun)->Call(global, 1, argv); + v8::String::Utf8Value str(s); + fwrite(*str, sizeof(**str), str.length(), stdout); + printf("\n"); + } } return true; } diff --git a/src/d8.js b/src/d8.js index 6a4ecb7330..1ff0ce8980 100644 --- a/src/d8.js +++ b/src/d8.js @@ -2194,3 +2194,59 @@ function SimpleArrayToJSON_(array) { json += ']'; return json; } + + +// A more universal stringify that supports more types than JSON. +// Used by the d8 shell to output results. +var stringifyDepthLimit = 4; // To avoid crashing on cyclic objects + +function Stringify(x, depth) { + if (depth === undefined) + depth = stringifyDepthLimit; + else if (depth === 0) + return "*"; + switch (typeof x) { + case "undefined": + return "undefined"; + case "boolean": + case "number": + case "function": + return x.toString(); + case "string": + return "\"" + x.toString() + "\""; + // TODO(rossberg): add symbol case + case "object": + if (x === null) return "null"; + if (x.constructor && x.constructor.name === "Array") { + var elems = []; + for (var i = 0; i < x.length; ++i) { + elems.push( + {}.hasOwnProperty.call(x, i) ? Stringify(x[i], depth - 1) : ""); + } + return "[" + elems.join(", ") + "]"; + } + try { + var string = String(x); + if (string && string !== "[object Object]") return string; + } catch(e) {} + var props = []; + for (var name in x) { + var desc = Object.getOwnPropertyDescriptor(x, name); + if (desc === void 0) continue; + if ("value" in desc) { + props.push(name + ": " + Stringify(desc.value, depth - 1)); + } + if ("get" in desc) { + var getter = desc.get.toString(); + props.push("get " + name + getter.slice(getter.indexOf('('))); + } + if ("set" in desc) { + var setter = desc.set.toString(); + props.push("set " + name + setter.slice(setter.indexOf('('))); + } + } + return "{" + props.join(", ") + "}"; + default: + return "[crazy non-standard shit]"; + } +}