Upstream version 7.35.144.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / devtools / front_end / ModuleManager.js
1 /*
2  * Copyright (C) 2014 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
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
13  * distribution.
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.
17  *
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.
29  */
30
31 /**
32  * @constructor
33  * @param {!Array.<!WebInspector.ModuleManager.ModuleDescriptor>} descriptors
34  */
35 WebInspector.ModuleManager = function(descriptors)
36 {
37     /**
38      * @type {!Array.<!WebInspector.ModuleManager.Module>}
39      */
40     this._modules = [];
41     /**
42      * @type {!Object.<string, !WebInspector.ModuleManager.Module>}
43      */
44     this._modulesMap = {};
45     /**
46      * @type {!Array.<!WebInspector.ModuleManager.Extension>}
47      */
48     this._extensions = [];
49
50     /**
51      * @type {!Object.<string, !function(new:Object)>}
52      */
53     this._cachedTypeClasses = {};
54
55     /**
56      * @type {!Object.<string, !WebInspector.ModuleManager.ModuleDescriptor>}
57      */
58     this._descriptorsMap = {};
59     for (var i = 0; i < descriptors.length; ++i)
60         this._descriptorsMap[descriptors[i]["name"]] = descriptors[i];
61 }
62
63 WebInspector.ModuleManager.prototype = {
64     /**
65      * @param {!Array.<string>} configuration
66      */
67     registerModules: function(configuration)
68     {
69         for (var i = 0; i < configuration.length; ++i)
70             this.registerModule(configuration[i]);
71     },
72
73     /**
74      * @param {string} moduleName
75      */
76     registerModule: function(moduleName)
77     {
78         if (!this._descriptorsMap[moduleName])
79             throw new Error("Module is not defined: " + moduleName + " " + new Error().stack);
80         var module = new WebInspector.ModuleManager.Module(this, this._descriptorsMap[moduleName]);
81         this._modules.push(module);
82         this._modulesMap[moduleName] = module;
83     },
84
85     /**
86      * @param {string} moduleName
87      */
88     loadModule: function(moduleName)
89     {
90         this._modulesMap[moduleName]._load();
91     },
92
93     /**
94      * @param {string|!Function} type
95      * @param {?Object=} context
96      * @return {!Array.<!WebInspector.ModuleManager.Extension>}
97      */
98     extensions: function(type, context)
99     {
100         /**
101          * @param {!WebInspector.ModuleManager.Extension} extension
102          * @return {boolean}
103          */
104         function filter(extension)
105         {
106             if (extension._type !== type && extension._typeClass() !== type)
107                 return false;
108             return !context || extension.isApplicable(context);
109         }
110         return this._extensions.filter(filter);
111     },
112
113     /**
114      * @param {string|!Function} type
115      * @param {?Object=} context
116      * @return {?WebInspector.ModuleManager.Extension}
117      */
118     extension: function(type, context)
119     {
120         return this.extensions(type, context)[0] || null;
121     },
122
123     /**
124      * @param {string|!Function} type
125      * @param {?Object=} context
126      * @return {!Array.<!Object>}
127      */
128     instances: function(type, context)
129     {
130         /**
131          * @param {!WebInspector.ModuleManager.Extension} extension
132          * @return {?Object}
133          */
134         function instantiate(extension)
135         {
136             return extension.instance();
137         }
138         return this.extensions(type, context).filter(instantiate).map(instantiate);
139     },
140
141     /**
142      * @param {string|!Function} type
143      * @return {?Object}
144      */
145     instance: function(type, context)
146     {
147         var extension = this.extension(type, context);
148         return extension ? extension.instance() : null;
149     },
150
151     /**
152      * @param {string|!Function} type
153      * @param {string} nameProperty
154      * @param {string} orderProperty
155      * @return {function(string, string):number}
156      */
157     orderComparator: function(type, nameProperty, orderProperty)
158     {
159         var extensions = this.extensions(type);
160         var orderForName = {};
161         for (var i = 0; i < extensions.length; ++i) {
162             var descriptor = extensions[i].descriptor();
163             orderForName[descriptor[nameProperty]] = descriptor[orderProperty];
164         }
165
166         /**
167          * @param {string} name1
168          * @param {string} name2
169          * @return {number}
170          */
171         function result(name1, name2)
172         {
173             if (name1 in orderForName && name2 in orderForName)
174                 return orderForName[name1] - orderForName[name2];
175             if (name1 in orderForName)
176                 return -1;
177             if (name2 in orderForName)
178                 return 1;
179             return name1.compareTo(name2);
180         }
181         return result;
182     },
183
184     /**
185      * @return {?function(new:Object)}
186      */
187     resolve: function(typeName)
188     {
189         if (!this._cachedTypeClasses[typeName]) {
190             try {
191                 this._cachedTypeClasses[typeName] = /** @type function(new:Object) */ (window.eval(typeName.substring(1)));
192             } catch (e) {
193             }
194         }
195         return this._cachedTypeClasses[typeName];
196     }
197
198 }
199
200 /**
201  * @constructor
202  */
203 WebInspector.ModuleManager.ModuleDescriptor = function()
204 {
205     /**
206      * @type {string}
207      */
208     this.name;
209
210     /**
211      * @type {!Array.<!WebInspector.ModuleManager.ExtensionDescriptor>}
212      */
213     this.extensions;
214
215     /**
216      * @type {!Array.<string>}
217      */
218     this.scripts;
219 }
220
221 /**
222  * @constructor
223  */
224 WebInspector.ModuleManager.ExtensionDescriptor = function()
225 {
226     /**
227      * @type {string}
228      */
229     this.type;
230
231     /**
232      * @type {string|undefined}
233      */
234     this.className;
235
236     /**
237      * @type {!Array.<string>|undefined}
238      */
239     this.contextTypes;
240 }
241
242 /**
243  * @constructor
244  * @param {!WebInspector.ModuleManager} manager
245  * @param {!WebInspector.ModuleManager.ModuleDescriptor} descriptor
246  */
247 WebInspector.ModuleManager.Module = function(manager, descriptor)
248 {
249     this._manager = manager;
250     this._descriptor = descriptor;
251     this._name = descriptor.name;
252     var extensions = /** @type {?Array.<!WebInspector.ModuleManager.ExtensionDescriptor>}*/ (descriptor.extensions);
253     for (var i = 0; extensions && i < extensions.length; ++i)
254         this._manager._extensions.push(new WebInspector.ModuleManager.Extension(this, extensions[i]));
255     this._loaded = false;
256 }
257
258 WebInspector.ModuleManager.Module.prototype = {
259     /**
260      * @return {string}
261      */
262     name: function()
263     {
264         return this._name;
265     },
266
267     _load: function()
268     {
269         if (this._loaded)
270             return;
271
272         if (this._isLoading) {
273             var oldStackTraceLimit = Error.stackTraceLimit;
274             Error.stackTraceLimit = 50;
275             console.assert(false, "Module " + this._name + " is loaded from itself: " + new Error().stack);
276             Error.stackTraceLimit = oldStackTraceLimit;
277             return;
278         }
279
280         this._isLoading = true;
281         var scripts = this._descriptor.scripts;
282         for (var i = 0; scripts && i < scripts.length; ++i)
283             loadScript(scripts[i]);
284         this._isLoading = false;
285         this._loaded = true;
286     }
287 }
288
289 /**
290  * @constructor
291  * @param {!WebInspector.ModuleManager.Module} module
292  * @param {!WebInspector.ModuleManager.ExtensionDescriptor} descriptor
293  */
294 WebInspector.ModuleManager.Extension = function(module, descriptor)
295 {
296     this._module = module;
297     this._descriptor = descriptor;
298
299     this._type = descriptor.type;
300     this._hasTypeClass = !!this._type.startsWith("@");
301
302     /**
303      * @type {?string}
304      */
305     this._className = descriptor.className || null;
306 }
307
308 WebInspector.ModuleManager.Extension.prototype = {
309     /**
310      * @return {!Object}
311      */
312     descriptor: function()
313     {
314         return this._descriptor;
315     },
316
317     /**
318      * @return {!WebInspector.ModuleManager.Module}
319      */
320     module: function()
321     {
322         return this._module;
323     },
324
325     /**
326      * @return {?function(new:Object)}
327      */
328     _typeClass: function()
329     {
330         if (!this._hasTypeClass)
331             return null;
332         return this._module._manager.resolve(this._type);
333     },
334
335     /**
336      * @param {?Object} context
337      * @return {boolean}
338      */
339     isApplicable: function(context)
340     {
341         var contextTypes = /** @type {!Array.<string>|undefined} */ (this._descriptor.contextTypes);
342         if (!contextTypes)
343             return true;
344         for (var i = 0; i < contextTypes.length; ++i) {
345             var contextType = /** @type {!Function} */ (window.eval(contextTypes[i]));
346             if (context instanceof contextType)
347                 return true;
348         }
349         return false;
350     },
351
352     /**
353      * @return {?Object}
354      */
355     instance: function()
356     {
357         if (!this._className)
358             return null;
359
360         if (!this._instance) {
361             this._module._load();
362
363             var constructorFunction = window.eval(this._className);
364             if (!(constructorFunction instanceof Function))
365                 return null;
366
367             this._instance = new constructorFunction();
368         }
369         return this._instance;
370     }
371 }
372
373 /**
374  * @interface
375  */
376 WebInspector.Renderer = function()
377 {
378 }
379
380 WebInspector.Renderer.prototype = {
381     /**
382      * @param {!Object} object
383      * @return {?Element}
384      */
385     render: function(object) {}
386 }
387
388 /**
389  * @interface
390  */
391 WebInspector.Revealer = function()
392 {
393 }
394
395 /**
396  * @param {?Object} revealable
397  * @param {number=} lineNumber
398  */
399 WebInspector.Revealer.reveal = function(revealable, lineNumber)
400 {
401     if (!revealable)
402         return;
403     var revealer = WebInspector.moduleManager.instance(WebInspector.Revealer, revealable);
404     if (revealer)
405         revealer.reveal(revealable, lineNumber);
406 }
407
408 WebInspector.Revealer.prototype = {
409     /**
410      * @param {!Object} object
411      */
412     reveal: function(object) {}
413 }
414
415 /**
416  * @interface
417  */
418 WebInspector.ActionDelegate = function()
419 {
420 }
421
422 WebInspector.ActionDelegate.prototype = {
423     /**
424      * @param {!Event} event
425      * @return {boolean}
426      */
427     handleAction: function(event) {}
428 }
429
430 WebInspector.moduleManager = new WebInspector.ModuleManager(allDescriptors);