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, stableId}) { 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 var stableIdResolved = (stableId === undefined) ? 59 kindResolved + '|-|' + nameResolved : 60 call(stableId, obj); 61 62 var result = { 63 kind: kindResolved, 64 name: nameResolved, 65 children: transformed_children, 66 obj: obj, 67 timestamp: call(timestamp, obj), 68 skip: handle_children(children, false /* transform */), 69 bounds: call(bounds, obj) || transformed_children.map((e) => e.bounds).find((e) => true) || undefined, 70 rect: rectResolved, 71 rects: rects_transform(concat(rectResolved, transformed_children, (e) => e.rects)), 72 highlight: call(highlight, obj), 73 chips: call(chips, obj), 74 stableId: stableIdResolved, 75 visible: call(visible, obj), 76 childrenVisible: transformed_children.some((c) => { 77 return c.childrenVisible || c.visible 78 }), 79 flattened: call(flattened, obj), 80 }; 81 82 if (rectResolved) { 83 rectResolved.ref = result; 84 } 85 86 return Object.freeze(result); 87} 88 89 90function transform_json(obj, name, options) { 91 let {skip, formatter} = options; 92 93 var children = []; 94 var formatted = undefined; 95 96 if (skip && skip.includes(obj)) { 97 // skip 98 } else if ((formatted = formatter(obj))) { 99 children.push(transform_json(null, formatted, options)); 100 } else if (Array.isArray(obj)) { 101 obj.forEach((e, i) => { 102 children.push(transform_json(e, ""+i, options)); 103 }) 104 } else if (typeof obj == 'string') { 105 children.push(transform_json(null, obj, options)); 106 } else if (typeof obj == 'number' || typeof obj == 'boolean') { 107 children.push(transform_json(null, ""+obj, options)); 108 } else if (obj && typeof obj == 'object') { 109 Object.keys(obj).forEach((key) => { 110 children.push(transform_json(obj[key], key, options)); 111 }); 112 } 113 114 if (children.length == 1 && !children[0].combined) { 115 return Object.freeze({ 116 kind: "", 117 name: name + ": " + children[0].name, 118 children: children[0].children, 119 combined: true 120 }); 121 } 122 123 return Object.freeze({ 124 kind: "", 125 name: name, 126 children: children, 127 }); 128} 129 130function nanos_to_string(elapsedRealtimeNanos) { 131 var units = [ 132 [1000000, '(ns)'], 133 [1000, 'ms'], 134 [60, 's'], 135 [60, 'm'], 136 [24, 'h'], 137 [Infinity, 'd'], 138 ]; 139 140 var parts = [] 141 units.some(([div, str], i) => { 142 var part = (elapsedRealtimeNanos % div).toFixed() 143 if (!str.startsWith('(')) { 144 parts.push(part + str); 145 } 146 elapsedRealtimeNanos = Math.floor(elapsedRealtimeNanos / div); 147 return elapsedRealtimeNanos == 0; 148 }); 149 150 return parts.reverse().join(''); 151} 152 153 // Returns a UI element used highlight a visible entry. 154 function get_visible_chip() { 155 return {short: 'V', long: "visible", class: 'default'}; 156 } 157 158export {transform, transform_json, nanos_to_string, get_visible_chip}; 159