github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/internal/jsre/pretty.go (about) 1 2 //此源码被清华学神尹成大魔王专业翻译分析并修改 3 //尹成QQ77025077 4 //尹成微信18510341407 5 //尹成所在QQ群721929980 6 //尹成邮箱 yinc13@mails.tsinghua.edu.cn 7 //尹成毕业于清华大学,微软区块链领域全球最有价值专家 8 //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620 9 //版权所有2016 Go Ethereum作者 10 //此文件是Go以太坊库的一部分。 11 // 12 //Go-Ethereum库是免费软件:您可以重新分发它和/或修改 13 //根据GNU发布的较低通用公共许可证的条款 14 //自由软件基金会,或者许可证的第3版,或者 15 //(由您选择)任何更高版本。 16 // 17 //Go以太坊图书馆的发行目的是希望它会有用, 18 //但没有任何保证;甚至没有 19 //适销性或特定用途的适用性。见 20 //GNU较低的通用公共许可证,了解更多详细信息。 21 // 22 //你应该收到一份GNU较低级别的公共许可证副本 23 //以及Go以太坊图书馆。如果没有,请参见<http://www.gnu.org/licenses/>。 24 25 package jsre 26 27 import ( 28 "fmt" 29 "io" 30 "sort" 31 "strconv" 32 "strings" 33 34 "github.com/fatih/color" 35 "github.com/robertkrimen/otto" 36 ) 37 38 const ( 39 maxPrettyPrintLevel = 3 40 indentString = " " 41 ) 42 43 var ( 44 FunctionColor = color.New(color.FgMagenta).SprintfFunc() 45 SpecialColor = color.New(color.Bold).SprintfFunc() 46 NumberColor = color.New(color.FgRed).SprintfFunc() 47 StringColor = color.New(color.FgGreen).SprintfFunc() 48 ErrorColor = color.New(color.FgHiRed).SprintfFunc() 49 ) 50 51 //打印对象时隐藏这些字段。 52 var boringKeys = map[string]bool{ 53 "valueOf": true, 54 "toString": true, 55 "toLocaleString": true, 56 "hasOwnProperty": true, 57 "isPrototypeOf": true, 58 "propertyIsEnumerable": true, 59 "constructor": true, 60 } 61 62 //预打印将值写入标准输出。 63 func prettyPrint(vm *otto.Otto, value otto.Value, w io.Writer) { 64 ppctx{vm: vm, w: w}.printValue(value, 0, false) 65 } 66 67 //PrettyError将错误写入标准输出。 68 func prettyError(vm *otto.Otto, err error, w io.Writer) { 69 failure := err.Error() 70 if ottoErr, ok := err.(*otto.Error); ok { 71 failure = ottoErr.String() 72 } 73 fmt.Fprint(w, ErrorColor("%s", failure)) 74 } 75 76 func (re *JSRE) prettyPrintJS(call otto.FunctionCall) otto.Value { 77 for _, v := range call.ArgumentList { 78 prettyPrint(call.Otto, v, re.output) 79 fmt.Fprintln(re.output) 80 } 81 return otto.UndefinedValue() 82 } 83 84 type ppctx struct { 85 vm *otto.Otto 86 w io.Writer 87 } 88 89 func (ctx ppctx) indent(level int) string { 90 return strings.Repeat(indentString, level) 91 } 92 93 func (ctx ppctx) printValue(v otto.Value, level int, inArray bool) { 94 switch { 95 case v.IsObject(): 96 ctx.printObject(v.Object(), level, inArray) 97 case v.IsNull(): 98 fmt.Fprint(ctx.w, SpecialColor("null")) 99 case v.IsUndefined(): 100 fmt.Fprint(ctx.w, SpecialColor("undefined")) 101 case v.IsString(): 102 s, _ := v.ToString() 103 fmt.Fprint(ctx.w, StringColor("%q", s)) 104 case v.IsBoolean(): 105 b, _ := v.ToBoolean() 106 fmt.Fprint(ctx.w, SpecialColor("%t", b)) 107 case v.IsNaN(): 108 fmt.Fprint(ctx.w, NumberColor("NaN")) 109 case v.IsNumber(): 110 s, _ := v.ToString() 111 fmt.Fprint(ctx.w, NumberColor("%s", s)) 112 default: 113 fmt.Fprint(ctx.w, "<unprintable>") 114 } 115 } 116 117 func (ctx ppctx) printObject(obj *otto.Object, level int, inArray bool) { 118 switch obj.Class() { 119 case "Array", "GoArray": 120 lv, _ := obj.Get("length") 121 len, _ := lv.ToInteger() 122 if len == 0 { 123 fmt.Fprintf(ctx.w, "[]") 124 return 125 } 126 if level > maxPrettyPrintLevel { 127 fmt.Fprint(ctx.w, "[...]") 128 return 129 } 130 fmt.Fprint(ctx.w, "[") 131 for i := int64(0); i < len; i++ { 132 el, err := obj.Get(strconv.FormatInt(i, 10)) 133 if err == nil { 134 ctx.printValue(el, level+1, true) 135 } 136 if i < len-1 { 137 fmt.Fprintf(ctx.w, ", ") 138 } 139 } 140 fmt.Fprint(ctx.w, "]") 141 142 case "Object": 143 //将bignumber.js中的值打印为常规数字。 144 if ctx.isBigNumber(obj) { 145 fmt.Fprint(ctx.w, NumberColor("%s", toString(obj))) 146 return 147 } 148 //否则,打印所有缩进的字段,但如果太深则停止。 149 keys := ctx.fields(obj) 150 if len(keys) == 0 { 151 fmt.Fprint(ctx.w, "{}") 152 return 153 } 154 if level > maxPrettyPrintLevel { 155 fmt.Fprint(ctx.w, "{...}") 156 return 157 } 158 fmt.Fprintln(ctx.w, "{") 159 for i, k := range keys { 160 v, _ := obj.Get(k) 161 fmt.Fprintf(ctx.w, "%s%s: ", ctx.indent(level+1), k) 162 ctx.printValue(v, level+1, false) 163 if i < len(keys)-1 { 164 fmt.Fprintf(ctx.w, ",") 165 } 166 fmt.Fprintln(ctx.w) 167 } 168 if inArray { 169 level-- 170 } 171 fmt.Fprintf(ctx.w, "%s}", ctx.indent(level)) 172 173 case "Function": 174 //如果可能,使用ToString()显示参数列表。 175 if robj, err := obj.Call("toString"); err != nil { 176 fmt.Fprint(ctx.w, FunctionColor("function()")) 177 } else { 178 desc := strings.Trim(strings.Split(robj.String(), "{")[0], " \t\n") 179 desc = strings.Replace(desc, " (", "(", 1) 180 fmt.Fprint(ctx.w, FunctionColor("%s", desc)) 181 } 182 183 case "RegExp": 184 fmt.Fprint(ctx.w, StringColor("%s", toString(obj))) 185 186 default: 187 if v, _ := obj.Get("toString"); v.IsFunction() && level <= maxPrettyPrintLevel { 188 s, _ := obj.Call("toString") 189 fmt.Fprintf(ctx.w, "<%s %s>", obj.Class(), s.String()) 190 } else { 191 fmt.Fprintf(ctx.w, "<%s>", obj.Class()) 192 } 193 } 194 } 195 196 func (ctx ppctx) fields(obj *otto.Object) []string { 197 var ( 198 vals, methods []string 199 seen = make(map[string]bool) 200 ) 201 add := func(k string) { 202 if seen[k] || boringKeys[k] || strings.HasPrefix(k, "_") { 203 return 204 } 205 seen[k] = true 206 if v, _ := obj.Get(k); v.IsFunction() { 207 methods = append(methods, k) 208 } else { 209 vals = append(vals, k) 210 } 211 } 212 iterOwnAndConstructorKeys(ctx.vm, obj, add) 213 sort.Strings(vals) 214 sort.Strings(methods) 215 return append(vals, methods...) 216 } 217 218 func iterOwnAndConstructorKeys(vm *otto.Otto, obj *otto.Object, f func(string)) { 219 seen := make(map[string]bool) 220 iterOwnKeys(vm, obj, func(prop string) { 221 seen[prop] = true 222 f(prop) 223 }) 224 if cp := constructorPrototype(obj); cp != nil { 225 iterOwnKeys(vm, cp, func(prop string) { 226 if !seen[prop] { 227 f(prop) 228 } 229 }) 230 } 231 } 232 233 func iterOwnKeys(vm *otto.Otto, obj *otto.Object, f func(string)) { 234 Object, _ := vm.Object("Object") 235 rv, _ := Object.Call("getOwnPropertyNames", obj.Value()) 236 gv, _ := rv.Export() 237 switch gv := gv.(type) { 238 case []interface{}: 239 for _, v := range gv { 240 f(v.(string)) 241 } 242 case []string: 243 for _, v := range gv { 244 f(v) 245 } 246 default: 247 panic(fmt.Errorf("Object.getOwnPropertyNames returned unexpected type %T", gv)) 248 } 249 } 250 251 func (ctx ppctx) isBigNumber(v *otto.Object) bool { 252 //使用自定义构造函数处理数字。 253 if v, _ := v.Get("constructor"); v.Object() != nil { 254 if strings.HasPrefix(toString(v.Object()), "function BigNumber") { 255 return true 256 } 257 } 258 //处理默认构造函数。 259 BigNumber, _ := ctx.vm.Object("BigNumber.prototype") 260 if BigNumber == nil { 261 return false 262 } 263 bv, _ := BigNumber.Call("isPrototypeOf", v) 264 b, _ := bv.ToBoolean() 265 return b 266 } 267 268 func toString(obj *otto.Object) string { 269 s, _ := obj.Call("toString") 270 return s.String() 271 } 272 273 func constructorPrototype(obj *otto.Object) *otto.Object { 274 if v, _ := obj.Get("constructor"); v.Object() != nil { 275 if v, _ = v.Object().Get("prototype"); v.Object() != nil { 276 return v.Object() 277 } 278 } 279 return nil 280 }