• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2011 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 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
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
31WebInspector.HeapSnapshotProxy = function()
32{
33    this._snapshot = null;
34}
35
36WebInspector.HeapSnapshotProxy.prototype = {
37    _invokeGetter: function(getterName, callback)
38    {
39        function returnResult()
40        {
41            callback(this._snapshot[getterName]);
42        }
43        setTimeout(returnResult.bind(this), 0);
44    },
45
46    aggregates: function(withNodeIndexes, callback)
47    {
48        function returnResult()
49        {
50            callback(this._snapshot.aggregates(withNodeIndexes));
51        }
52        setTimeout(returnResult.bind(this), 0);
53    },
54
55    _extractEdgeData: function(edge)
56    {
57        return {name: edge.name, node: this._extractNodeData(edge.node), nodeIndex: edge.nodeIndex, type: edge.type};
58    },
59
60    _extractNodeData: function(node)
61    {
62        return {id: node.id, name: node.name, nodeIndex: node.nodeIndex, retainedSize: node.retainedSize, selfSize: node.selfSize, type: node.type};
63    },
64
65    createDiff: function(className)
66    {
67        return new WebInspector.HeapSnapshotsDiffProxy(new WebInspector.HeapSnapshotsDiff(this._snapshot, className));
68    },
69
70    createEdgesProvider: function(nodeIndex, filter)
71    {
72        function createProvider()
73        {
74            if (filter)
75                filter = filter.bind(this._snapshot);
76            return new WebInspector.HeapSnapshotEdgesProvider(this._snapshot, nodeIndex, filter);
77        }
78        return new WebInspector.HeapSnapshotProviderProxy(createProvider.bind(this), this._extractEdgeData.bind(this));
79    },
80
81    createNodesProvider: function(filter)
82    {
83        function createProvider()
84        {
85            if (filter)
86                filter = filter.bind(this._snapshot);
87            return new WebInspector.HeapSnapshotNodesProvider(this._snapshot, filter);
88        }
89        return new WebInspector.HeapSnapshotProviderProxy(createProvider.bind(this), this._extractNodeData.bind(this));
90    },
91
92    createPathFinder: function(targetNodeIndex)
93    {
94        return new WebInspector.HeapSnapshotPathFinderProxy(new WebInspector.HeapSnapshotPathFinder(this._snapshot, targetNodeIndex));
95    },
96
97    dispose: function()
98    {
99        this._snapshot.dispose();
100    },
101
102    finishLoading: function(callback)
103    {
104        if (this._snapshot || !this._isLoading)
105            return false;
106        function parse() {
107            var rawSnapshot = JSON.parse(this._json);
108            var loadCallbacks = this._onLoadCallbacks;
109            loadCallbacks.splice(0, 0, callback);
110            delete this._onLoadCallback;
111            delete this._json;
112            delete this._isLoading;
113            this._snapshot = new WebInspector.HeapSnapshot(rawSnapshot);
114            this._nodeCount = this._snapshot.nodeCount;
115            this._rootNodeIndex = this._snapshot._rootNodeIndex;
116            this._totalSize = this._snapshot.totalSize;
117            for (var i = 0; i < loadCallbacks.length; ++i)
118                loadCallbacks[i]();
119        }
120        setTimeout(parse.bind(this), 0);
121        return true;
122    },
123
124    get loaded()
125    {
126        return !!this._snapshot;
127    },
128
129    get nodeCount()
130    {
131        return this._nodeCount;
132    },
133
134    nodeFieldValuesByIndex: function(fieldName, indexes, callback)
135    {
136        function returnResult()
137        {
138            callback(this._snapshot.nodeFieldValuesByIndex(fieldName, indexes));
139        }
140        setTimeout(returnResult.bind(this), 0);
141    },
142
143    nodeIds: function(callback)
144    {
145        this._invokeGetter("nodeIds", callback);
146    },
147
148    pushJSONChunk: function(chunk)
149    {
150        if (this.loaded || !this._isLoading)
151            return;
152        this._json += chunk;
153    },
154
155    pushBaseIds: function(snapshotId, className, nodeIds)
156    {
157        this._snapshot.updateBaseNodeIds(snapshotId, className, nodeIds);
158    },
159
160    get rootNodeIndex()
161    {
162        return this._rootNodeIndex;
163    },
164
165    startLoading: function(callback)
166    {
167        if (this._snapshot) {
168            function asyncInvoke()
169            {
170                callback();
171            }
172            setTimeout(callback, 0);
173            return false;
174        } else if (this._isLoading) {
175            this._onLoadCallbacks.push(callback);
176            return false;
177        } else {
178            this._isLoading = true;
179            this._onLoadCallbacks = [callback];
180            this._json = "";
181            return true;
182        }
183    },
184
185    get totalSize()
186    {
187        return this._totalSize;
188    },
189
190    get uid()
191    {
192        return this._snapshot.uid;
193    }
194};
195
196WebInspector.HeapSnapshotProviderProxy = function(createProvider, extractData)
197{
198    this._provider = createProvider();
199    this._extractData = extractData;
200}
201
202WebInspector.HeapSnapshotProviderProxy.prototype = {
203    getNextItems: function(count, callback)
204    {
205        function returnResult()
206        {
207            var result = new Array(count);
208            for (var i = 0 ; i < count && this._provider.hasNext(); ++i, this._provider.next())
209                result[i] = this._extractData(this._provider.item);
210            result.length = i;
211            callback(result, this._provider.hasNext(), this._provider.length);
212        }
213        setTimeout(returnResult.bind(this), 0);
214    },
215
216    isEmpty: function(callback)
217    {
218        function returnResult()
219        {
220            callback(this._provider.isEmpty);
221        }
222        setTimeout(returnResult.bind(this), 0);
223    },
224
225    sortAndRewind: function(comparator, callback)
226    {
227        function returnResult()
228        {
229            var result = this._provider.sort(comparator);
230            if (result)
231                this._provider.first();
232            callback(result);
233        }
234        setTimeout(returnResult.bind(this), 0);
235    }
236};
237
238WebInspector.HeapSnapshotPathFinderProxy = function(pathFinder)
239{
240    this._pathFinder = pathFinder;
241}
242
243WebInspector.HeapSnapshotPathFinderProxy.prototype = {
244    findNext: function(callback)
245    {
246        function returnResult()
247        {
248            callback(this._pathFinder.findNext());
249        }
250        setTimeout(returnResult.bind(this), 0);
251    },
252
253    updateRoots: function(filter)
254    {
255        function asyncInvoke()
256        {
257            this._pathFinder.updateRoots(filter);
258        }
259        setTimeout(asyncInvoke.bind(this), 0);
260    }
261};
262
263WebInspector.HeapSnapshotsDiffProxy = function(diff)
264{
265    this._diff = diff;
266}
267
268WebInspector.HeapSnapshotsDiffProxy.prototype = {
269    calculate: function(callback)
270    {
271        function returnResult()
272        {
273            callback(this._diff.calculate());
274        }
275        setTimeout(returnResult.bind(this), 0);
276    },
277
278    pushBaseIds: function(baseSnapshotId, baseIds)
279    {
280        this._diff.baseIds = baseIds;
281    },
282
283    pushBaseSelfSizes: function(baseSelfSizes)
284    {
285        this._diff.baseSelfSizes = baseSelfSizes;
286    }
287};
288