blob: ce48ebf1411251a3ea2e688c22241590c221b87b [file] [log] [blame]
/*
* Copyright (C) 2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
importScripts(...[
"HeapSnapshot.js"
]);
HeapSnapshotWorker = class HeapSnapshotWorker
{
constructor()
{
this._nextObjectId = 1;
this._objects = new Map;
this._snapshots = [];
self.addEventListener("message", this._handleMessage.bind(this));
}
// Actions
clearSnapshots()
{
this._objects.clear();
this._snapshots = [];
}
createSnapshot(snapshotString, title, imported)
{
let objectId = this._nextObjectId++;
let snapshot = new HeapSnapshot(objectId, snapshotString, title, imported);
this._objects.set(objectId, snapshot);
if (!imported) {
this._snapshots.push(snapshot);
if (this._snapshots.length > 1) {
setTimeout(() => {
let collectionData = snapshot.updateDeadNodesAndGatherCollectionData(this._snapshots);
if (!collectionData || !collectionData.affectedSnapshots.length)
return;
this.sendEvent("HeapSnapshot.CollectionEvent", collectionData);
}, 0);
}
}
return {objectId, snapshot: snapshot.serialize()};
}
createSnapshotDiff(objectId1, objectId2)
{
let snapshot1 = this._objects.get(objectId1);
let snapshot2 = this._objects.get(objectId2);
console.assert(snapshot1 instanceof HeapSnapshot);
console.assert(snapshot2 instanceof HeapSnapshot);
let objectId = this._nextObjectId++;
let snapshotDiff = new HeapSnapshotDiff(objectId, snapshot1, snapshot2);
this._objects.set(objectId, snapshotDiff);
return {objectId, snapshotDiff: snapshotDiff.serialize()};
}
// Public
sendEvent(eventName, eventData)
{
self.postMessage({eventName, eventData});
}
// Private
_handleMessage(event)
{
let data = event.data;
// Action.
if (data.actionName) {
let result = this[data.actionName](...data.actionArguments);
self.postMessage({callId: data.callId, result});
return;
}
// Method.
if (data.methodName) {
console.assert(data.objectId, "Must have an objectId to call the method on");
let object = this._objects.get(data.objectId);
if (!object)
self.postMessage({callId: data.callId, error: "No such object."});
else {
let result = object[data.methodName](...data.methodArguments);
self.postMessage({callId: data.callId, result});
}
return;
}
console.error("Unexpected HeapSnapshotWorker message", data);
}
};
self.heapSnapshotWorker = new HeapSnapshotWorker;