2 * Copyright (C) 2011 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 copyrightdd
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.
31 WebInspector.HeapSnapshotRealWorker = function()
33 this._worker = new Worker("HeapSnapshotWorker.js");
34 this._worker.addEventListener("message", this._messageReceived.bind(this), false);
37 WebInspector.HeapSnapshotRealWorker.prototype = {
38 _messageReceived: function(event)
40 this.dispatchEventToListeners("message", event.data);
43 postMessage: function(message)
45 this._worker.postMessage(message);
50 this._worker.terminate();
54 WebInspector.HeapSnapshotRealWorker.prototype.__proto__ = WebInspector.Object.prototype;
56 WebInspector.HeapSnapshotFakeWorker = function()
58 this._dispatcher = new WebInspector.HeapSnapshotWorkerDispatcher(window, this._postMessageFromWorker.bind(this));
61 WebInspector.HeapSnapshotFakeWorker.prototype = {
62 postMessage: function(message)
67 this._dispatcher.dispatchMessage({data: message});
69 setTimeout(dispatch.bind(this), 0);
74 this._dispatcher = null;
77 _postMessageFromWorker: function(message)
81 this.dispatchEventToListeners("message", message);
83 setTimeout(send.bind(this), 0);
87 WebInspector.HeapSnapshotFakeWorker.prototype.__proto__ = WebInspector.Object.prototype;
89 WebInspector.HeapSnapshotWorker = function()
91 this._nextObjectId = 1;
94 this._previousCallbacks = [];
95 // There is no support for workers in Chromium DRT.
96 this._worker = typeof InspectorTest === "undefined" ? new WebInspector.HeapSnapshotRealWorker() : new WebInspector.HeapSnapshotFakeWorker();
97 this._worker.addEventListener("message", this._messageReceived.bind(this), false);
100 WebInspector.HeapSnapshotWorker.prototype = {
101 createObject: function(constructorName)
103 var proxyConstructorFunction = this._findFunction(constructorName + "Proxy");
104 var objectId = this._nextObjectId++;
105 var proxy = new proxyConstructorFunction(this, objectId);
106 this._postMessage({callId: this._nextCallId++, disposition: "create", objectId: objectId, methodName: constructorName});
112 this._worker.terminate();
114 clearInterval(this._interval);
117 disposeObject: function(objectId)
119 this._postMessage({callId: this._nextCallId++, disposition: "dispose", objectId: objectId});
122 callGetter: function(callback, objectId, getterName)
124 var callId = this._nextCallId++;
125 this._callbacks[callId] = callback;
126 this._postMessage({callId: callId, disposition: "getter", objectId: objectId, methodName: getterName});
129 callFactoryMethod: function(callback, objectId, methodName, proxyConstructorName)
131 var callId = this._nextCallId++;
132 var methodArguments = Array.prototype.slice.call(arguments, 4);
133 var newObjectId = this._nextObjectId++;
134 var proxyConstructorFunction = this._findFunction(proxyConstructorName);
136 function wrapCallback(remoteResult)
138 callback(remoteResult ? new proxyConstructorFunction(this, newObjectId) : null);
140 this._callbacks[callId] = wrapCallback.bind(this);
141 this._postMessage({callId: callId, disposition: "factory", objectId: objectId, methodName: methodName, methodArguments: methodArguments, newObjectId: newObjectId});
144 this._postMessage({callId: callId, disposition: "factory", objectId: objectId, methodName: methodName, methodArguments: methodArguments, newObjectId: newObjectId});
145 return new proxyConstructorFunction(this, newObjectId);
149 callMethod: function(callback, objectId, methodName)
151 var callId = this._nextCallId++;
152 var methodArguments = Array.prototype.slice.call(arguments, 3);
154 this._callbacks[callId] = callback;
155 this._postMessage({callId: callId, disposition: "method", objectId: objectId, methodName: methodName, methodArguments: methodArguments});
158 startCheckingForLongRunningCalls: function()
160 this._checkLongRunningCalls();
161 this._interval = setInterval(this._checkLongRunningCalls.bind(this), 300);
164 _checkLongRunningCalls: function()
166 for (var callId in this._previousCallbacks)
167 if (!(callId in this._callbacks))
168 delete this._previousCallbacks[callId];
169 var hasLongRunningCalls = false;
170 for (callId in this._previousCallbacks) {
171 hasLongRunningCalls = true;
174 this.dispatchEventToListeners("wait", hasLongRunningCalls);
175 for (callId in this._callbacks)
176 this._previousCallbacks[callId] = true;
179 _findFunction: function(name)
181 var path = name.split(".");
183 for (var i = 0; i < path.length; ++i)
184 result = result[path[i]];
188 _messageReceived: function(event)
190 var data = event.data;
191 if (!this._callbacks[data.callId])
193 var callback = this._callbacks[data.callId];
194 delete this._callbacks[data.callId];
195 callback(data.result);
198 _postMessage: function(message)
200 this._worker.postMessage(message);
204 WebInspector.HeapSnapshotWorker.prototype.__proto__ = WebInspector.Object.prototype;
206 WebInspector.HeapSnapshotProxyObject = function(worker, objectId)
208 this._worker = worker;
209 this._objectId = objectId;
212 WebInspector.HeapSnapshotProxyObject.prototype = {
213 _callWorker: function(workerMethodName, args)
215 args.splice(1, 0, this._objectId);
216 return this._worker[workerMethodName].apply(this._worker, args);
221 this._worker.disposeObject(this._objectId);
224 disposeWorker: function()
226 this._worker.dispose();
229 callFactoryMethod: function(callback, methodName, proxyConstructorName)
231 return this._callWorker("callFactoryMethod", Array.prototype.slice.call(arguments, 0));
234 callGetter: function(callback, getterName)
236 return this._callWorker("callGetter", Array.prototype.slice.call(arguments, 0));
239 callMethod: function(callback, methodName)
241 return this._callWorker("callMethod", Array.prototype.slice.call(arguments, 0));
249 WebInspector.HeapSnapshotLoaderProxy = function(worker, objectId)
251 WebInspector.HeapSnapshotProxyObject.call(this, worker, objectId);
252 this._loading = false;
253 this._loaded = false;
256 WebInspector.HeapSnapshotLoaderProxy.prototype = {
257 finishLoading: function(callback)
261 var loadCallbacks = this._onLoadCallbacks;
262 loadCallbacks.splice(0, 0, callback);
263 delete this._onLoadCallbacks;
264 this._loading = false;
266 function callLoadCallbacks(snapshotProxy)
268 for (var i = 0; i < loadCallbacks.length; ++i)
269 loadCallbacks[i](snapshotProxy);
271 function updateStaticData(snapshotProxy)
274 snapshotProxy.updateStaticData(callLoadCallbacks);
276 this.callFactoryMethod(updateStaticData.bind(this), "finishLoading", "WebInspector.HeapSnapshotProxy");
285 startLoading: function(callback)
287 if (!this._loading) {
288 this._onLoadCallbacks = [callback];
289 this._loading = true;
292 this._onLoadCallbacks.push(callback);
297 pushJSONChunk: function(chunk)
301 this.callMethod(null, "pushJSONChunk", chunk);
305 WebInspector.HeapSnapshotLoaderProxy.prototype.__proto__ = WebInspector.HeapSnapshotProxyObject.prototype;
307 WebInspector.HeapSnapshotProxy = function(worker, objectId)
309 WebInspector.HeapSnapshotProxyObject.call(this, worker, objectId);
312 WebInspector.HeapSnapshotProxy.prototype = {
313 aggregates: function(sortedIndexes, key, filter, callback)
315 this.callMethod(callback, "aggregates", sortedIndexes, key, filter);
318 createDiff: function(className)
320 return this.callFactoryMethod(null, "createDiff", "WebInspector.HeapSnapshotsDiffProxy", className);
323 createEdgesProvider: function(nodeIndex, filter)
325 return this.callFactoryMethod(null, "createEdgesProvider", "WebInspector.HeapSnapshotProviderProxy", nodeIndex, filter);
328 createNodesProvider: function(filter)
330 return this.callFactoryMethod(null, "createNodesProvider", "WebInspector.HeapSnapshotProviderProxy", filter);
333 createNodesProviderForClass: function(className, aggregatesKey)
335 return this.callFactoryMethod(null, "createNodesProviderForClass", "WebInspector.HeapSnapshotProviderProxy", className, aggregatesKey);
338 createNodesProviderForDominator: function(nodeIndex, filter)
340 return this.callFactoryMethod(null, "createNodesProviderForDominator", "WebInspector.HeapSnapshotProviderProxy", nodeIndex, filter);
343 createPathFinder: function(targetNodeIndex)
345 return this.callFactoryMethod(null, "createPathFinder", "WebInspector.HeapSnapshotPathFinderProxy", targetNodeIndex);
350 this.disposeWorker();
353 finishLoading: function()
360 return !!this._objectId;
365 return this._staticData.maxNodeId;
370 return this._staticData.nodeCount;
373 nodeFieldValuesByIndex: function(fieldName, indexes, callback)
375 this.callMethod(callback, "nodeFieldValuesByIndex", fieldName, indexes);
380 return this._staticData.nodeFlags;
383 pushBaseIds: function(snapshotId, className, nodeIds)
385 this.callMethod(null, "pushBaseIds", snapshotId, className, nodeIds);
390 return this._staticData.rootNodeIndex;
393 updateStaticData: function(callback)
395 function dataReceived(staticData)
397 this._staticData = staticData;
400 this.callMethod(dataReceived.bind(this), "updateStaticData");
403 startLoading: function(callback)
405 setTimeout(callback.bind(null, this), 0);
411 return this._staticData.totalSize;
416 return this._staticData.uid;
420 WebInspector.HeapSnapshotProxy.prototype.__proto__ = WebInspector.HeapSnapshotProxyObject.prototype;
422 WebInspector.HeapSnapshotProviderProxy = function(worker, objectId)
424 WebInspector.HeapSnapshotProxyObject.call(this, worker, objectId);
427 WebInspector.HeapSnapshotProviderProxy.prototype = {
428 isEmpty: function(callback)
430 this.callGetter(callback, "isEmpty");
433 serializeNextItems: function(count, callback)
435 this.callMethod(callback, "serializeNextItems", count);
438 sortAndRewind: function(comparator, callback)
440 this.callMethod(callback, "sortAndRewind", comparator);
444 WebInspector.HeapSnapshotProviderProxy.prototype.__proto__ = WebInspector.HeapSnapshotProxyObject.prototype;
446 WebInspector.HeapSnapshotPathFinderProxy = function(worker, objectId)
448 WebInspector.HeapSnapshotProxyObject.call(this, worker, objectId);
451 WebInspector.HeapSnapshotPathFinderProxy.prototype = {
452 findNext: function(callback)
454 this.callMethod(callback, "findNext");
457 updateRoots: function(filter)
459 this.callMethod(null, "updateRoots", filter);
463 WebInspector.HeapSnapshotPathFinderProxy.prototype.__proto__ = WebInspector.HeapSnapshotProxyObject.prototype;
465 WebInspector.HeapSnapshotsDiffProxy = function(worker, objectId)
467 WebInspector.HeapSnapshotProxyObject.call(this, worker, objectId);
470 WebInspector.HeapSnapshotsDiffProxy.prototype = {
471 calculate: function(callback)
473 this.callMethod(callback, "calculate");
476 pushBaseIds: function(baseIds)
478 this.callMethod(null, "pushBaseIds", baseIds);
481 pushBaseSelfSizes: function(baseSelfSizes)
483 this.callMethod(null, "pushBaseSelfSizes", baseSelfSizes);
487 WebInspector.HeapSnapshotsDiffProxy.prototype.__proto__ = WebInspector.HeapSnapshotProxyObject.prototype;