1 <!DOCTYPE html> 2 <!-- 3 Copyright 2015 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 <link rel="import" href="/tracing/base/iteration_helpers.html"> 8 9 <script> 10 'use strict'; 11 12 tr.exportTo('pi', function() { 13 14 var FunctionRegistry = { 15 allFunctions_: [], 16 allFunctionsByName_: {}, 17 get allFunctions() { return this.allFunctions_; }, 18 get allFunctionsByName() { return this.allFunctionsByName_; } 19 }; 20 21 FunctionRegistry.getFunction = function(name) { 22 return this.allFunctionsByName_[name]; 23 }; 24 25 FunctionRegistry.register = function(func) { 26 if (func.name === '') 27 throw new Error('Registered functions must not be anonymous'); 28 if (this.allFunctionsByName[func.name] !== undefined) 29 throw new Error('Function named ' + func.name + 'is already registered.'); 30 this.allFunctionsByName[func.name] = func; 31 this.allFunctions.push(func); 32 }; 33 34 function ModuleToLoad(href, filename) { 35 if ((href !== undefined) ? (filename !== undefined) : 36 (filename === undefined)) { 37 throw new Error('ModuleToLoad must specify exactly one of href or ' + 38 'filename'); 39 } 40 this.href = href; 41 this.filename = filename; 42 } 43 44 ModuleToLoad.prototype = { 45 asDict: function() { 46 if (this.href !== undefined) 47 return {'href': this.href}; 48 return {'filename': this.filename}; 49 }, 50 51 toString: function() { 52 if (this.href !== undefined) 53 return 'ModuleToLoad(href="' + this.href + '")'; 54 return 'ModuleToLoad(filename="' + this.filename + '")'; 55 } 56 }; 57 58 ModuleToLoad.fromDict = function(moduleDict) { 59 return new ModuleToLoad(moduleDict.href, moduleDict.filename); 60 }; 61 62 function FunctionHandle(modulesToLoad, functionName, opt_options) { 63 if (!(modulesToLoad instanceof Array)) 64 throw new Error('modulesToLoad in FunctionHandle must be an array'); 65 if (typeof(functionName) !== 'string') 66 throw new Error('functionName in FunctionHandle must be a string'); 67 this.modulesToLoad = modulesToLoad; 68 this.functionName = functionName; 69 this.options_ = opt_options; 70 }; 71 72 FunctionHandle.prototype = { 73 get options() { 74 return this.options_; 75 }, 76 77 asDict: function() { 78 return { 79 'modules_to_load': this.modulesToLoad.map( 80 function(m) {return m.asDict();}), 81 'function_name': this.functionName, 82 'options': this.options_ 83 }; 84 }, 85 86 asUserFriendlyString: function() { 87 var parts = this.modulesToLoad.map(function(mtl) {return mtl.filename}); 88 parts.push(this.functionName); 89 parts.push(JSON.stringify(this.options_)); 90 return parts.join(','); 91 }, 92 93 hasHrefs: function() { 94 for (var module in this.modulesToLoad) { 95 if (this.modulesToLoad[module].href !== undefined) { 96 return true; 97 } 98 } 99 return false; 100 }, 101 102 load: function() { 103 if (this.hasHrefs()) { 104 var err = new Error( 105 'FunctionHandle named ' + this.functionName + 106 ' specifies hrefs, which cannot be loaded.'); 107 err.name = 'FunctionLoadingError'; 108 throw err; 109 } 110 111 for (var module in this.modulesToLoad) { 112 var filename = this.modulesToLoad[module].filename; 113 try { 114 HTMLImportsLoader.loadHTMLFile(filename); 115 } catch (err) { 116 err.name = 'FunctionLoadingError'; 117 throw err; 118 } 119 } 120 121 var func = FunctionRegistry.getFunction(this.functionName); 122 if (func === undefined) { 123 var err = new Error( 124 'No registered function named ' + this.functionName); 125 err.name = 'FunctionNotDefinedError'; 126 throw err; 127 } 128 129 return func; 130 }, 131 132 toString: function() { 133 var modulesToLoadStr = this.modulesToLoad.map(function(module) { 134 return module.toString(); 135 }); 136 return 'FunctionHandle(modulesToLoad=[' + modulesToLoadStr + '], ' + 137 'functionName="' + this.functionName + '", options="' + 138 JSON.stringify(this.options_) + '")'; 139 } 140 }; 141 142 FunctionHandle.loadFromFilename_ = function(filename) { 143 try { 144 var numFunctionsBefore = FunctionRegistry.allFunctions.length; 145 HTMLImportsLoader.loadHTMLFile(filename); 146 } catch (err) { 147 err.name = 'FunctionLoadingError'; 148 throw err; 149 } 150 151 // Verify a new function was registered. 152 var numFunctionsNow = FunctionRegistry.allFunctions.length; 153 if (numFunctionsNow !== (numFunctionsBefore + 1)) { 154 var err = new Error(filename + " didn't call FunctionRegistry.register"); 155 err.name = 'FunctionNotDefinedError'; 156 throw err; 157 } 158 159 return FunctionRegistry.allFunctions[numFunctionsNow - 1]; 160 }; 161 162 FunctionHandle.fromDict = function(handleDict) { 163 var options = handleDict.options; 164 if (handleDict.modules_to_load !== undefined) { 165 var modulesToLoad = handleDict.modules_to_load.map(function(module) { 166 return ModuleToLoad.fromDict(module); 167 }); 168 } 169 return new FunctionHandle(modulesToLoad, handleDict.function_name, options); 170 }; 171 172 return { 173 FunctionHandle: FunctionHandle, 174 ModuleToLoad: ModuleToLoad, 175 FunctionRegistry: FunctionRegistry 176 }; 177 }); 178 </script> 179