2 * Copyright (C) 2014 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 * @param {!Array.<!WebInspector.ModuleManager.ModuleDescriptor>} descriptors
35 WebInspector.ModuleManager = function(descriptors)
38 * @type {!Array.<!WebInspector.ModuleManager.Module>}
42 * @type {!Object.<string, !WebInspector.ModuleManager.Module>}
44 this._modulesMap = {};
46 * @type {!Array.<!WebInspector.ModuleManager.Extension>}
48 this._extensions = [];
51 * @type {!Object.<string, !function(new:Object)>}
53 this._cachedTypeClasses = {};
56 * @type {!Object.<string, !WebInspector.ModuleManager.ModuleDescriptor>}
58 this._descriptorsMap = {};
59 for (var i = 0; i < descriptors.length; ++i)
60 this._descriptorsMap[descriptors[i]["name"]] = descriptors[i];
63 WebInspector.ModuleManager.prototype = {
65 * @param {!Array.<string>} configuration
67 registerModules: function(configuration)
69 for (var i = 0; i < configuration.length; ++i)
70 this.registerModule(configuration[i]);
74 * @param {string} moduleName
76 registerModule: function(moduleName)
78 if (!this._descriptorsMap[moduleName]) {
79 var content = loadResource(moduleName + "/module.json");
81 throw new Error("Module is not defined: " + moduleName + " " + new Error().stack);
82 var module = /** @type {!WebInspector.ModuleManager.ModuleDescriptor} */ (self.eval("(" + content + ")"));
83 module["name"] = moduleName;
84 this._descriptorsMap[moduleName] = module;
86 var module = new WebInspector.ModuleManager.Module(this, this._descriptorsMap[moduleName]);
87 this._modules.push(module);
88 this._modulesMap[moduleName] = module;
92 * @param {string} moduleName
94 loadModule: function(moduleName)
96 this._modulesMap[moduleName]._load();
100 * @param {!WebInspector.ModuleManager.Extension} extension
101 * @param {?function(function(new:Object)):boolean} predicate
104 _checkExtensionApplicability: function(extension, predicate)
108 var contextTypes = /** @type {!Array.<string>|undefined} */ (extension.descriptor().contextTypes);
111 for (var i = 0; i < contextTypes.length; ++i) {
112 var contextType = this._resolve(contextTypes[i]);
113 var isMatching = !!contextType && predicate(contextType);
121 * @param {!WebInspector.ModuleManager.Extension} extension
122 * @param {?Object} context
125 isExtensionApplicableToContext: function(extension, context)
129 return this._checkExtensionApplicability(extension, isInstanceOf);
132 * @param {!Function} targetType
135 function isInstanceOf(targetType)
137 return context instanceof targetType;
142 * @param {!WebInspector.ModuleManager.Extension} extension
143 * @param {!Set.<!Function>=} currentContextTypes
146 isExtensionApplicableToContextTypes: function(extension, currentContextTypes)
148 if (!extension.descriptor().contextTypes)
151 return this._checkExtensionApplicability(extension, currentContextTypes ? isContextTypeKnown : null);
154 * @param {!Function} targetType
157 function isContextTypeKnown(targetType)
159 return currentContextTypes.contains(targetType);
164 * @param {string|!Function} type
165 * @param {?Object=} context
166 * @return {!Array.<!WebInspector.ModuleManager.Extension>}
168 extensions: function(type, context)
171 * @param {!WebInspector.ModuleManager.Extension} extension
174 function filter(extension)
176 if (extension._type !== type && extension._typeClass() !== type)
178 return !context || extension.isApplicable(context);
180 return this._extensions.filter(filter);
184 * @param {string|!Function} type
185 * @param {?Object=} context
186 * @return {?WebInspector.ModuleManager.Extension}
188 extension: function(type, context)
190 return this.extensions(type, context)[0] || null;
194 * @param {string|!Function} type
195 * @param {?Object=} context
196 * @return {!Array.<!Object>}
198 instances: function(type, context)
201 * @param {!WebInspector.ModuleManager.Extension} extension
204 function instantiate(extension)
206 return extension.instance();
208 return this.extensions(type, context).filter(instantiate).map(instantiate);
212 * @param {string|!Function} type
215 instance: function(type, context)
217 var extension = this.extension(type, context);
218 return extension ? extension.instance() : null;
222 * @param {string|!Function} type
223 * @param {string} nameProperty
224 * @param {string} orderProperty
225 * @return {function(string, string):number}
227 orderComparator: function(type, nameProperty, orderProperty)
229 var extensions = this.extensions(type);
230 var orderForName = {};
231 for (var i = 0; i < extensions.length; ++i) {
232 var descriptor = extensions[i].descriptor();
233 orderForName[descriptor[nameProperty]] = descriptor[orderProperty];
237 * @param {string} name1
238 * @param {string} name2
241 function result(name1, name2)
243 if (name1 in orderForName && name2 in orderForName)
244 return orderForName[name1] - orderForName[name2];
245 if (name1 in orderForName)
247 if (name2 in orderForName)
249 return name1.compareTo(name2);
255 * @return {?function(new:Object)}
257 _resolve: function(typeName)
259 if (!this._cachedTypeClasses[typeName]) {
260 var path = typeName.split(".");
262 for (var i = 0; object && (i < path.length); ++i)
263 object = object[path[i]];
265 this._cachedTypeClasses[typeName] = /** @type function(new:Object) */(object);
267 return this._cachedTypeClasses[typeName];
274 WebInspector.ModuleManager.ModuleDescriptor = function()
282 * @type {!Array.<!WebInspector.ModuleManager.ExtensionDescriptor>}
287 * @type {!Array.<!string>|undefined}
292 * @type {!Array.<string>}
300 WebInspector.ModuleManager.ExtensionDescriptor = function()
308 * @type {string|undefined}
313 * @type {!Array.<string>|undefined}
320 * @param {!WebInspector.ModuleManager} manager
321 * @param {!WebInspector.ModuleManager.ModuleDescriptor} descriptor
323 WebInspector.ModuleManager.Module = function(manager, descriptor)
325 this._manager = manager;
326 this._descriptor = descriptor;
327 this._name = descriptor.name;
328 var extensions = /** @type {?Array.<!WebInspector.ModuleManager.ExtensionDescriptor>}*/ (descriptor.extensions);
329 for (var i = 0; extensions && i < extensions.length; ++i)
330 this._manager._extensions.push(new WebInspector.ModuleManager.Extension(this, extensions[i]));
331 this._loaded = false;
334 WebInspector.ModuleManager.Module.prototype = {
348 if (this._isLoading) {
349 var oldStackTraceLimit = Error.stackTraceLimit;
350 Error.stackTraceLimit = 50;
351 console.assert(false, "Module " + this._name + " is loaded from itself: " + new Error().stack);
352 Error.stackTraceLimit = oldStackTraceLimit;
356 this._isLoading = true;
357 var dependencies = this._descriptor.dependencies;
358 for (var i = 0; dependencies && i < dependencies.length; ++i)
359 this._manager.loadModule(dependencies[i]);
360 var scripts = this._descriptor.scripts;
361 for (var i = 0; scripts && i < scripts.length; ++i)
362 loadScript(this._name + "/" + scripts[i]);
363 this._isLoading = false;
370 * @param {!WebInspector.ModuleManager.Module} module
371 * @param {!WebInspector.ModuleManager.ExtensionDescriptor} descriptor
373 WebInspector.ModuleManager.Extension = function(module, descriptor)
375 this._module = module;
376 this._descriptor = descriptor;
378 this._type = descriptor.type;
379 this._hasTypeClass = !!this._type.startsWith("@");
384 this._className = descriptor.className || null;
387 WebInspector.ModuleManager.Extension.prototype = {
391 descriptor: function()
393 return this._descriptor;
397 * @return {!WebInspector.ModuleManager.Module}
405 * @return {?function(new:Object)}
407 _typeClass: function()
409 if (!this._hasTypeClass)
411 return this._module._manager._resolve(this._type.substring(1));
415 * @param {?Object} context
418 isApplicable: function(context)
420 return this._module._manager.isExtensionApplicableToContext(this, context);
428 if (!this._className)
431 if (!this._instance) {
432 this._module._load();
434 var constructorFunction = window.eval(this._className);
435 if (!(constructorFunction instanceof Function))
438 this._instance = new constructorFunction();
440 return this._instance;
447 WebInspector.Renderer = function()
451 WebInspector.Renderer.prototype = {
453 * @param {!Object} object
456 render: function(object) {}
462 WebInspector.Revealer = function()
467 * @param {?Object} revealable
468 * @param {number=} lineNumber
470 WebInspector.Revealer.reveal = function(revealable, lineNumber)
474 var revealer = WebInspector.moduleManager.instance(WebInspector.Revealer, revealable);
476 revealer.reveal(revealable, lineNumber);
479 WebInspector.Revealer.prototype = {
481 * @param {!Object} object
483 reveal: function(object) {}
486 WebInspector.moduleManager = new WebInspector.ModuleManager(allDescriptors);