Home | History | Annotate | Download | only in src
      1 // Copyright 2008 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 (function() {
      6 "use strict";
      7 
      8 // A more universal stringify that supports more types than JSON.
      9 // Used by the d8 shell to output results.
     10 var stringifyDepthLimit = 4;  // To avoid crashing on cyclic objects
     11 
     12 // Hacky solution to circumvent forcing --allow-natives-syntax for d8
     13 function isProxy(o) { return false };
     14 function JSProxyGetTarget(proxy) { };
     15 function JSProxyGetHandler(proxy) { };
     16 
     17 try {
     18   isProxy = Function(['object'], 'return %_IsJSProxy(object)');
     19   JSProxyGetTarget = Function(['proxy'],
     20     'return %JSProxyGetTarget(proxy)');
     21   JSProxyGetHandler = Function(['proxy'],
     22     'return %JSProxyGetHandler(proxy)');
     23 } catch(e) {};
     24 
     25 
     26 function Stringify(x, depth) {
     27   if (depth === undefined)
     28     depth = stringifyDepthLimit;
     29   else if (depth === 0)
     30     return "...";
     31   if (isProxy(x)) {
     32     return StringifyProxy(x, depth);
     33   }
     34   switch (typeof x) {
     35     case "undefined":
     36       return "undefined";
     37     case "boolean":
     38     case "number":
     39     case "function":
     40       return x.toString();
     41     case "string":
     42       return "\"" + x.toString() + "\"";
     43     case "symbol":
     44       return x.toString();
     45     case "object":
     46       if (IS_NULL(x)) return "null";
     47       if (x.constructor && x.constructor.name === "Array") {
     48         var elems = [];
     49         for (var i = 0; i < x.length; ++i) {
     50           elems.push(
     51             {}.hasOwnProperty.call(x, i) ? Stringify(x[i], depth - 1) : "");
     52         }
     53         return "[" + elems.join(", ") + "]";
     54       }
     55       try {
     56         var string = String(x);
     57         if (string && string !== "[object Object]") return string;
     58       } catch(e) {}
     59       var props = [];
     60       var names = Object.getOwnPropertyNames(x);
     61       names = names.concat(Object.getOwnPropertySymbols(x));
     62       for (var i in names) {
     63         var name = names[i];
     64         var desc = Object.getOwnPropertyDescriptor(x, name);
     65         if (IS_UNDEFINED(desc)) continue;
     66         if (IS_SYMBOL(name)) name = "[" + Stringify(name) + "]";
     67         if ("value" in desc) {
     68           props.push(name + ": " + Stringify(desc.value, depth - 1));
     69         }
     70         if (desc.get) {
     71           var getter = Stringify(desc.get);
     72           props.push("get " + name + getter.slice(getter.indexOf('(')));
     73         }
     74         if (desc.set) {
     75           var setter = Stringify(desc.set);
     76           props.push("set " + name + setter.slice(setter.indexOf('(')));
     77         }
     78       }
     79       return "{" + props.join(", ") + "}";
     80     default:
     81       return "[crazy non-standard value]";
     82   }
     83 }
     84 
     85 function StringifyProxy(proxy, depth) {
     86   var proxy_type = typeof proxy;
     87   var info_object = {
     88     target: JSProxyGetTarget(proxy),
     89     handler: JSProxyGetHandler(proxy)
     90   }
     91   return '[' + proxy_type + ' Proxy ' + Stringify(info_object, depth-1) + ']';
     92 }
     93 
     94 return Stringify;
     95 })();
     96