1 <!DOCTYPE html> 2 <!-- 3 Copyright (c) 2014 The Chromium Authors. All rights reserved. 4 Use of this source code is governed by a BSD-style license that can be 5 found in the LICENSE file. 6 --> 7 8 <script> 9 'use strict'; 10 11 /** 12 * The global object. 13 * @type {!Object} 14 * @const 15 */ 16 var global = this; 17 18 /** Platform, package, object property, and Event support. */ 19 this.tr = (function() { 20 if (global.tr) { 21 console.warn('Base was multiply initialized. First init wins.'); 22 return global.tr; 23 } 24 25 /** 26 * Builds an object structure for the provided namespace path, 27 * ensuring that names that already exist are not overwritten. For 28 * example: 29 * 'a.b.c' -> a = {};a.b={};a.b.c={}; 30 * @param {string} name Name of the object that this file defines. 31 * @private 32 */ 33 function exportPath(name) { 34 var parts = name.split('.'); 35 var cur = global; 36 37 for (var part; parts.length && (part = parts.shift());) { 38 if (part in cur) { 39 cur = cur[part]; 40 } else { 41 cur = cur[part] = {}; 42 } 43 } 44 return cur; 45 }; 46 47 function isExported(name) { 48 var parts = name.split('.'); 49 var cur = global; 50 51 for (var part; parts.length && (part = parts.shift());) { 52 if (part in cur) { 53 cur = cur[part]; 54 } else { 55 return false; 56 } 57 } 58 return true; 59 } 60 61 function isDefined(name) { 62 var parts = name.split('.'); 63 64 var curObject = global; 65 66 for (var i = 0; i < parts.length; i++) { 67 var partName = parts[i]; 68 var nextObject = curObject[partName]; 69 if (nextObject === undefined) 70 return false; 71 curObject = nextObject; 72 } 73 return true; 74 } 75 76 var panicElement = undefined; 77 var rawPanicMessages = []; 78 function showPanicElementIfNeeded() { 79 if (panicElement) 80 return; 81 82 var panicOverlay = document.createElement('div'); 83 panicOverlay.style.backgroundColor = 'white'; 84 panicOverlay.style.border = '3px solid red'; 85 panicOverlay.style.boxSizing = 'border-box'; 86 panicOverlay.style.color = 'black'; 87 panicOverlay.style.display = '-webkit-flex'; 88 panicOverlay.style.height = '100%'; 89 panicOverlay.style.left = 0; 90 panicOverlay.style.padding = '8px'; 91 panicOverlay.style.position = 'fixed'; 92 panicOverlay.style.top = 0; 93 panicOverlay.style.webkitFlexDirection = 'column'; 94 panicOverlay.style.width = '100%'; 95 96 panicElement = document.createElement('div'); 97 panicElement.style.webkitFlex = '1 1 auto'; 98 panicElement.style.overflow = 'auto'; 99 panicOverlay.appendChild(panicElement); 100 101 if (!document.body) { 102 setTimeout(function() { 103 document.body.appendChild(panicOverlay); 104 }, 150); 105 } else { 106 document.body.appendChild(panicOverlay); 107 } 108 } 109 110 function showPanic(panicTitle, panicDetails) { 111 if (tr.isHeadless) { 112 if (panicDetails instanceof Error) 113 throw panicDetails; 114 throw new Error('Panic: ' + panicTitle + ':\n' + panicDetails); 115 } 116 117 if (panicDetails instanceof Error) 118 panicDetails = panicDetails.stack; 119 120 showPanicElementIfNeeded(); 121 var panicMessageEl = document.createElement('div'); 122 panicMessageEl.innerHTML = 123 '' + 124 ''; 125 panicMessageEl.querySelector('#message').textContent = panicTitle; 126 panicMessageEl.querySelector('#details').textContent = panicDetails; 127 panicElement.appendChild(panicMessageEl); 128 129 rawPanicMessages.push({ 130 title: panicTitle, 131 details: panicDetails 132 }); 133 } 134 135 function hasPanic() { 136 return rawPanicMessages.length !== 0; 137 } 138 function getPanicText() { 139 return rawPanicMessages.map(function(msg) { 140 return msg.title; 141 }).join(', '); 142 } 143 144 function exportTo(namespace, fn) { 145 var obj = exportPath(namespace); 146 var exports = fn(); 147 148 for (var propertyName in exports) { 149 // Maybe we should check the prototype chain here? The current usage 150 // pattern is always using an object literal so we only care about own 151 // properties. 152 var propertyDescriptor = Object.getOwnPropertyDescriptor(exports, 153 propertyName); 154 if (propertyDescriptor) 155 Object.defineProperty(obj, propertyName, propertyDescriptor); 156 } 157 }; 158 159 /** 160 * Initialization which must be deferred until run-time. 161 */ 162 function initialize() { 163 if (global.version && global.version()) { 164 tr.isD8 = true; 165 } else if (global.process && global.process.versions.node) { 166 tr.isNode = true; 167 } else { 168 tr.isD8 = false; 169 tr.isNode = false; 170 tr.doc = document; 171 172 tr.isMac = /Mac/.test(navigator.platform); 173 tr.isWindows = /Win/.test(navigator.platform); 174 tr.isChromeOS = /CrOS/.test(navigator.userAgent); 175 tr.isLinux = /Linux/.test(navigator.userAgent); 176 } 177 tr.isHeadless = tr.isD8 || tr.isNode; 178 } 179 180 return { 181 initialize: initialize, 182 183 exportTo: exportTo, 184 isExported: isExported, 185 isDefined: isDefined, 186 187 showPanic: showPanic, 188 hasPanic: hasPanic, 189 getPanicText: getPanicText 190 }; 191 })(); 192 193 tr.initialize(); 194 </script> 195