Home | History | Annotate | Download | only in base
      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