1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2008 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
53b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch(function() {
63ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch"use strict";
73ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// A more universal stringify that supports more types than JSON.
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Used by the d8 shell to output results.
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvar stringifyDepthLimit = 4;  // To avoid crashing on cyclic objects
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
12014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Hacky solution to circumvent forcing --allow-natives-syntax for d8
13014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochfunction isProxy(o) { return false };
14014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochfunction JSProxyGetTarget(proxy) { };
15014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochfunction JSProxyGetHandler(proxy) { };
16014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
17014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochtry {
18014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  isProxy = Function(['object'], 'return %_IsJSProxy(object)');
19014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  JSProxyGetTarget = Function(['proxy'],
20014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    'return %JSProxyGetTarget(proxy)');
21014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  JSProxyGetHandler = Function(['proxy'],
22014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    'return %JSProxyGetHandler(proxy)');
23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} catch(e) {};
24014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
25014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction Stringify(x, depth) {
27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (depth === undefined)
28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    depth = stringifyDepthLimit;
29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  else if (depth === 0)
30014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return "...";
31014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (isProxy(x)) {
32014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return StringifyProxy(x, depth);
33014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (typeof x) {
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case "undefined":
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return "undefined";
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case "boolean":
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case "number":
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case "function":
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return x.toString();
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case "string":
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return "\"" + x.toString() + "\"";
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case "symbol":
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return x.toString();
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case "object":
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (IS_NULL(x)) return "null";
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (x.constructor && x.constructor.name === "Array") {
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        var elems = [];
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        for (var i = 0; i < x.length; ++i) {
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          elems.push(
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            {}.hasOwnProperty.call(x, i) ? Stringify(x[i], depth - 1) : "");
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return "[" + elems.join(", ") + "]";
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      try {
56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        var string = String(x);
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (string && string !== "[object Object]") return string;
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } catch(e) {}
59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      var props = [];
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      var names = Object.getOwnPropertyNames(x);
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      names = names.concat(Object.getOwnPropertySymbols(x));
62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      for (var i in names) {
63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        var name = names[i];
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        var desc = Object.getOwnPropertyDescriptor(x, name);
65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (IS_UNDEFINED(desc)) continue;
66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (IS_SYMBOL(name)) name = "[" + Stringify(name) + "]";
67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if ("value" in desc) {
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          props.push(name + ": " + Stringify(desc.value, depth - 1));
69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (desc.get) {
71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          var getter = Stringify(desc.get);
72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          props.push("get " + name + getter.slice(getter.indexOf('(')));
73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (desc.set) {
75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          var setter = Stringify(desc.set);
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          props.push("set " + name + setter.slice(setter.indexOf('(')));
77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return "{" + props.join(", ") + "}";
80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    default:
81014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return "[crazy non-standard value]";
82014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
83014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
84014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
85014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochfunction StringifyProxy(proxy, depth) {
86014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  var proxy_type = typeof proxy;
87014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  var info_object = {
88014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    target: JSProxyGetTarget(proxy),
89014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    handler: JSProxyGetHandler(proxy)
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
91014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return '[' + proxy_type + ' Proxy ' + Stringify(info_object, depth-1) + ']';
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochreturn Stringify;
953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch})();
96