1/* 2 * Copyright 2017, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17function transform({obj, kind, name, children, timestamp, rect, bounds, highlight, rects_transform, chips, visible, flattened}) { 18 function call(fn, arg) { 19 return (typeof fn == 'function') ? fn(arg) : fn; 20 } 21 function handle_children(arg, transform) { 22 return [].concat(...arg.map((item) => { 23 var childrenFunc = item[0]; 24 var transformFunc = item[1]; 25 var childs = call(childrenFunc, obj); 26 if (childs) { 27 if (typeof childs.map != 'function'){ 28 throw 'Childs should be an array, but is: ' + (typeof childs) + '.' 29 } 30 return transform ? childs.map(transformFunc) : childs; 31 } else { 32 return []; 33 } 34 })); 35 } 36 function concat(arg, args, argsmap) { 37 var validArg = arg !== undefined && arg !== null; 38 39 if (Array.isArray(args)) { 40 if (validArg) { 41 return [arg].concat(...args.map(argsmap)); 42 } else { 43 return [].concat(...args.map(argsmap)); 44 } 45 } else if (validArg) { 46 return [arg]; 47 } else { 48 return undefined; 49 } 50 } 51 52 var transformed_children = handle_children(children, true /* transform */); 53 rects_transform = (rects_transform === undefined) ? (e) => e : rects_transform; 54 55 var kindResolved = call(kind, obj); 56 var nameResolved = call(name, obj); 57 var rectResolved = call(rect, obj); 58 59 var result = { 60 kind: kindResolved, 61 name: nameResolved, 62 children: transformed_children, 63 obj: obj, 64 timestamp: call(timestamp, obj), 65 skip: handle_children(children, false /* transform */), 66 bounds: call(bounds, obj) || transformed_children.map((e) => e.bounds).find((e) => true) || undefined, 67 rect: rectResolved, 68 rects: rects_transform(concat(rectResolved, transformed_children, (e) => e.rects)), 69 highlight: call(highlight, obj), 70 chips: call(chips, obj), 71 stableId: kindResolved + "|-|" + nameResolved, 72 visible: call(visible, obj), 73 childrenVisible: transformed_children.some((c) => { 74 return c.childrenVisible || c.visible 75 }), 76 flattened: call(flattened, obj), 77 }; 78 79 if (rectResolved) { 80 rectResolved.ref = result; 81 } 82 83 return Object.freeze(result); 84} 85 86 87function transform_json(obj, name, options) { 88 let {skip, formatter} = options; 89 90 var children = []; 91 var formatted = undefined; 92 93 if (skip && skip.includes(obj)) { 94 // skip 95 } else if ((formatted = formatter(obj))) { 96 children.push(transform_json(null, formatted, options)); 97 } else if (Array.isArray(obj)) { 98 obj.forEach((e, i) => { 99 children.push(transform_json(e, ""+i, options)); 100 }) 101 } else if (typeof obj == 'string') { 102 children.push(transform_json(null, obj, options)); 103 } else if (typeof obj == 'number' || typeof obj == 'boolean') { 104 children.push(transform_json(null, ""+obj, options)); 105 } else if (obj && typeof obj == 'object') { 106 Object.keys(obj).forEach((key) => { 107 children.push(transform_json(obj[key], key, options)); 108 }); 109 } 110 111 if (children.length == 1 && !children[0].combined) { 112 return Object.freeze({ 113 kind: "", 114 name: name + ": " + children[0].name, 115 children: children[0].children, 116 combined: true 117 }); 118 } 119 120 return Object.freeze({ 121 kind: "", 122 name: name, 123 children: children, 124 }); 125} 126 127function nanos_to_string(elapsedRealtimeNanos) { 128 var units = [ 129 [1000000, '(ns)'], 130 [1000, 'ms'], 131 [60, 's'], 132 [60, 'm'], 133 [24, 'h'], 134 [Infinity, 'd'], 135 ]; 136 137 var parts = [] 138 units.some(([div, str], i) => { 139 var part = (elapsedRealtimeNanos % div).toFixed() 140 if (!str.startsWith('(')) { 141 parts.push(part + str); 142 } 143 elapsedRealtimeNanos = Math.floor(elapsedRealtimeNanos / div); 144 return elapsedRealtimeNanos == 0; 145 }); 146 147 return parts.reverse().join(''); 148} 149 150 // Returns a UI element used highlight a visible entry. 151 function get_visible_chip() { 152 return {short: 'V', long: "visible", class: 'default'}; 153 } 154 155export {transform, transform_json, nanos_to_string, get_visible_chip}; 156