func (ctx ppctx) fields(obj *otto.Object) []string { var ( vals, methods []string seen = make(map[string]bool) ) add := func(k string) { if seen[k] || boringKeys[k] { return } seen[k] = true if v, _ := obj.Get(k); v.IsFunction() { methods = append(methods, k) } else { vals = append(vals, k) } } // add own properties ctx.doOwnProperties(obj.Value(), add) // add properties of the constructor if cp := constructorPrototype(obj); cp != nil { ctx.doOwnProperties(cp.Value(), add) } sort.Strings(vals) sort.Strings(methods) return append(vals, methods...) }
func constructorPrototype(obj *otto.Object) *otto.Object { if v, _ := obj.Get("constructor"); v.Object() != nil { if v, _ = v.Object().Get("prototype"); v.Object() != nil { return v.Object() } } return nil }
func (ctx ppctx) printObject(obj *otto.Object, level int, inArray bool) { switch obj.Class() { case "Array": lv, _ := obj.Get("length") len, _ := lv.ToInteger() if len == 0 { fmt.Printf("[]") return } if level > maxPrettyPrintLevel { fmt.Print("[...]") return } fmt.Print("[") for i := int64(0); i < len; i++ { el, err := obj.Get(strconv.FormatInt(i, 10)) if err == nil { ctx.printValue(el, level+1, true) } if i < len-1 { fmt.Printf(", ") } } fmt.Print("]") case "Object": // Print values from bignumber.js as regular numbers. if ctx.isBigNumber(obj) { numberColor.Print(toString(obj)) return } // Otherwise, print all fields indented, but stop if we're too deep. keys := ctx.fields(obj) if len(keys) == 0 { fmt.Print("{}") return } if level > maxPrettyPrintLevel { fmt.Print("{...}") return } fmt.Println("{") for i, k := range keys { v, _ := obj.Get(k) fmt.Printf("%s%s: ", ctx.indent(level+1), k) ctx.printValue(v, level+1, false) if i < len(keys)-1 { fmt.Printf(",") } fmt.Println() } if inArray { level-- } fmt.Printf("%s}", ctx.indent(level)) case "Function": // Use toString() to display the argument list if possible. if robj, err := obj.Call("toString"); err != nil { functionColor.Print("function()") } else { desc := strings.Trim(strings.Split(robj.String(), "{")[0], " \t\n") desc = strings.Replace(desc, " (", "(", 1) functionColor.Print(desc) } case "RegExp": stringColor.Print(toString(obj)) default: if v, _ := obj.Get("toString"); v.IsFunction() && level <= maxPrettyPrintLevel { s, _ := obj.Call("toString") fmt.Printf("<%s %s>", obj.Class(), s.String()) } else { fmt.Printf("<%s>", obj.Class()) } } }