Skip to content

Commit

Permalink
Do not Retain Canvas/Context in extension to prevent memory leaks Fixed
Browse files Browse the repository at this point in the history
  • Loading branch information
sebavan committed Apr 13, 2018
1 parent df6d437 commit b5eb0aa
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 43 deletions.
5 changes: 3 additions & 2 deletions documentation/changeLogs.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
## Change Log
Please, find below the per release summary of the contribution added to the project per version. Each of the listed versions is having its corresponding tag in the repo.

## v0.9.4 Textures (I will do it... someday)
In progress
## v0.9.4 Memory Leak Fix
This release is fixing a memory leak intriduced through the 0.9.3 version in the extension:
- [Do not Retain Canvas/Context in extension to prevent memory leaks](https://github.com/BabylonJS/Spector.js/issues/87)

## v0.9.3 Fixes
This release is meant to address the few bugs found during a bug bash session:
Expand Down
20 changes: 14 additions & 6 deletions extensions/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,16 @@ var currentTabId = null;
var refreshCanvases = function() {
var popup = window.browser.extension.getViews({ type: "popup" })[0];
if (popup != null) {
var canvasesToSend = [];
var canvasesToSend = { canvases: [], captureOffScreen: false };
window.browser.tabs.query({ active: true, currentWindow: true }, function(tabs) {
for (var tabId in tabInfo) {
if (tabId == tabs[0].id) {
for (var frameId in tabInfo[tabId]) {
var infos = tabInfo[tabId][frameId];
for (var i = 0; i < infos.length; i++) {
var info = infos[i];
canvasesToSend.push({
canvasesToSend.captureOffScreen = infos.captureOffScreen;
for (var i = 0; i < infos.canvases.length; i++) {
var info = infos.canvases[i];
canvasesToSend.canvases.push({
id: info.id,
width: info.width,
height: info.height,
Expand Down Expand Up @@ -85,7 +86,7 @@ listenForMessage(function(request, sender, sendResponse) {
else if (request.refreshCanvases) {
window.browser.tabs.query({ active: true, currentWindow: true }, function(tabs) {
tabInfo = {}
sendMessage({ action: "requestCanvases", offScreen: request.offScreen });
sendMessage({ action: "requestCanvases" });

setTimeout(function() { refreshCanvases(); }, 500);
setTimeout(function() { refreshCanvases(); }, 2000);
Expand All @@ -105,7 +106,7 @@ listenForMessage(function(request, sender, sendResponse) {
tabInfo[tabId] = { };
}

tabInfo[tabId][frameId] = request.canvases;
tabInfo[tabId][frameId] = { canvases: request.canvases, captureOffScreen: request.captureOffScreen };
}
else if (request.errorString) {
// Close the wait message and may display an error.
Expand Down Expand Up @@ -140,6 +141,13 @@ listenForMessage(function(request, sender, sendResponse) {
popup.captureComplete();
}
}
else if (request.pageReload) {
// Display the fps of the selected frame.
var popup = window.browser.extension.getViews({ type: "popup" })[0];
if (popup != null && popup.refreshCanvases) {
popup.refreshCanvases();
}
}

// Return the frameid for reference.
sendResponse({ frameId: frameId });
Expand Down
110 changes: 83 additions & 27 deletions extensions/contentScript.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ var spectorCaptureOnLoadKey = "SPECTOR_CAPTUREONLOAD";
var spectorCaptureOnLoadCommandCountKey = "SPECTOR_CAPTUREONLOAD_COMMANDCOUNT";
var spectorCaptureOnLoadTransientKey = "SPECTOR_CAPTUREONLOAD_TRANSIENT";
var spectorCaptureOnLoadQuickCaptureKey = "SPECTOR_CAPTUREONLOAD_QUICKCAPTURE";
var captureOffScreenKey = "SPECTOR_CAPTUREOFFSCREEN";
var spectorCommunicationElementId = "SPECTOR_COMMUNICATION";
var spectorCommunicationQuickCaptureElementId = "SPECTOR_COMMUNICATION_QUICKCAPTURE";
var spectorCommunicationRebuildProgramElementId = "SPECTOR_COMMUNICATION_REBUILDPROGRAM";
Expand All @@ -86,6 +87,7 @@ var captureOnLoad = false;
var captureOnLoadTransient = false;
var captureOnLoadQuickCapture = false;
var captureOnLoadCommandCount = 500;
var captureOffScreen = false;

if (sessionStorage.getItem(spectorCaptureOnLoadKey) === "true") {
sessionStorage.setItem(spectorCaptureOnLoadKey, "false");
Expand All @@ -96,9 +98,12 @@ if (sessionStorage.getItem(spectorCaptureOnLoadKey) === "true") {
captureOnLoadCommandCount = parseInt(sessionStorage.getItem(spectorCaptureOnLoadCommandCountKey));
}

captureOffScreen = (sessionStorage.getItem(captureOffScreenKey) === "true");

var canvasGetContextDetection = `
var spector;
var captureOnLoad = ${captureOnLoad ? "true" : "false"};
var captureOffScreen = ${captureOffScreen ? "true" : "false"};
window.__SPECTOR_Canvases = [];
(function() {
Expand Down Expand Up @@ -131,15 +136,17 @@ var canvasGetContextDetection = `
var myEvent = new CustomEvent("SpectorWebGLCanvasAvailableEvent");
document.dispatchEvent(myEvent);
var found = false;
for (var i = 0; i < window.__SPECTOR_Canvases.length; i++) {
if (window.__SPECTOR_Canvases[i] === this) {
found = true;
break;
if (captureOffScreen) {
var found = false;
for (var i = 0; i < window.__SPECTOR_Canvases.length; i++) {
if (window.__SPECTOR_Canvases[i] === this) {
found = true;
break;
}
}
if (!found) {
window.__SPECTOR_Canvases.push(this);
}
}
if (!found) {
window.__SPECTOR_Canvases.push(this);
}
if (captureOnLoad) {
Expand All @@ -157,7 +164,6 @@ var canvasGetContextDetection = `
insertTextScript(canvasGetContextDetection);

var frameId = null;
var offScreen = false;

// In case the spector injection has been requested, inject the library in the page.
if (sessionStorage.getItem(spectorLoadedKey)) {
Expand Down Expand Up @@ -185,7 +191,12 @@ if (sessionStorage.getItem(spectorLoadedKey)) {
document.addEventListener("SpectorRequestCaptureEvent", function(e) {
var canvasIndex = document.getElementById('${spectorCommunicationElementId}').value;
var canvas = window.__SPECTOR_Canvases[canvasIndex];
var canvas = null;
if (${captureOffScreen}) {
canvas = window.__SPECTOR_Canvases[canvasIndex];
} else {
canvas = document.body.querySelectorAll("canvas")[canvasIndex];
}
var quickCapture = (document.getElementById('${spectorCommunicationQuickCaptureElementId}').value === "true");
spector.captureCanvas(canvas, 0, quickCapture);
});
Expand Down Expand Up @@ -218,8 +229,7 @@ if (sessionStorage.getItem(spectorLoadedKey)) {
id: canvas.id,
width: canvas.width,
height: canvas.height,
ref: i,
offScreen: !document.body.contains(canvas)
ref: i
});
}
var myEvent = new CustomEvent("SpectorOnCanvasListEvent", {
Expand Down Expand Up @@ -320,18 +330,16 @@ if (sessionStorage.getItem(spectorLoadedKey)) {
var uiInformation = [];
for (var i = 0; i < canvasList.length; i++) {
var canvasInformation = canvasList[i];
if (canvasInformation.offScreen === offScreen) {
uiInformation.push({
id: canvasInformation.id,
width: canvasInformation.width,
height: canvasInformation.height,
ref: canvasInformation.ref
});
}
uiInformation.push({
id: canvasInformation.id,
width: canvasInformation.width,
height: canvasInformation.height,
ref: canvasInformation.ref
});
}

// Inform the extension that canvases are present (2 means injection has been done, 1 means ready to inject)
sendMessage({ canvases: uiInformation }, function (response) {
sendMessage({ canvases: uiInformation, captureOffScreen: true }, function (response) {
frameId = response.frameId;
});
});
Expand All @@ -345,10 +353,43 @@ else {
}, false);
}

var getCanvases = function(offScreenParam) {
offScreen = !!offScreenParam;
var myEvent = new CustomEvent("SpectorRequestCanvasListEvent");
document.dispatchEvent(myEvent);
var refreshCanvases = function() {
if (captureOffScreen) {
// List is retrieved from all the ever created canvases.
var myEvent = new CustomEvent("SpectorRequestCanvasListEvent");
document.dispatchEvent(myEvent);
}
else {
if (document.body) {
var canvasElements = document.body.querySelectorAll("canvas");
if (canvasElements.length > 0) {

var canvasesInformation = [];
for (var i = 0; i < canvasElements.length; i++) {
var canvas = canvasElements[i];
var context = null;
try {
context = canvas.getContext(canvas.getAttribute(spectorContextTypeKey));
}
catch (e) {
// Do Nothing.
}

if (context) {
canvasesInformation.push({
id: canvas.id,
width: canvas.width,
height: canvas.height,
ref: i
});
}
}
sendMessage({ canvases: canvasesInformation, captureOffScreen: false }, function (response) {
frameId = response.frameId;
});
}
}
}
}

// Check for existing canvas a bit after the end of the loading.
Expand All @@ -358,6 +399,13 @@ document.addEventListener("DOMContentLoaded", function () {
sendMessage({ present: 2 }, function (response) {
frameId = response.frameId;
});

// Refresh the canvas list.
setTimeout(function () {
sendMessage({ pageReload: true }, function (response) {
frameId = response.frameId;
});
}, 500);
}
});

Expand All @@ -378,6 +426,14 @@ listenForMessage(function (message) {
}
}

// Set offscreen canvas mode.
if (action === "changeOffScreen") {
sessionStorage.setItem(captureOffScreenKey, message.captureOffScreen ? "true" : "false");
// Delay for all frames.
setTimeout(function () { window.location.reload(); }, 50);
return;
}

// We need to reload to inject the capture loading sequence.
if (action === "captureOnLoad") {
var transient = message.transient;
Expand All @@ -403,8 +459,8 @@ listenForMessage(function (message) {

// Let s refresh the canvases list.
if (action === "requestCanvases") {
setTimeout(function () { getCanvases(message.offScreen); }, 0);
setTimeout(function () { getCanvases(message.offScreen); }, 1000);
setTimeout(function () { refreshCanvases(); }, 0);
setTimeout(function () { refreshCanvases(); }, 1000);
return;
}

Expand Down
20 changes: 14 additions & 6 deletions extensions/popup.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ function sendMessage(message) {
//_____________________________________________________________________________________

var ui = null;
var offScreenInput = null;

// Display the capture UI.
window.addEventListener("DOMContentLoaded", function() {
Expand All @@ -31,7 +32,7 @@ window.addEventListener("DOMContentLoaded", function() {
var captureOnLoadCountInput = document.getElementById("captureOnLoadCount");
var captureOnLoadTransientInput = document.getElementById("captureOnLoadTransient");
var quickCaptureInput = document.getElementById("quickCapture");
var offScreenInput = document.getElementById("offScreen");
offScreenInput = document.getElementById("offScreen");

captureOnLoadElement.addEventListener("click", (e) => {
var transient = captureOnLoadTransientInput.checked;
Expand All @@ -44,15 +45,22 @@ window.addEventListener("DOMContentLoaded", function() {
return false;
});

offScreenInput.onchange = function() {
refreshCanvases();
offScreenInput.onchange = () => {
this.changeOffScreenStatus(offScreenInput.checked);
};

initUI();
refreshCanvases();
playAll();
});

var changeOffScreenStatus = function(offScreen) {
sendMessage({
action: "changeOffScreen",
captureOffScreen : offScreen,
});
}

var captureonLoad = function(commandCount, transient, quickCapture) {
sendMessage({
action: "captureOnLoad",
Expand Down Expand Up @@ -125,12 +133,12 @@ var initUI = function() {
}

var refreshCanvases = function() {
var offScreenInput = document.getElementById("offScreen");
window.browser.runtime.sendMessage({ refreshCanvases: true, offScreen: offScreenInput.checked }, function(response) { });
window.browser.runtime.sendMessage({ refreshCanvases: true }, function(response) { });
}

var updateCanvasesListInformation = function (canvasesToSend) {
ui.updateCanvasesListInformation(canvasesToSend);
ui.updateCanvasesListInformation(canvasesToSend.canvases);
offScreenInput.checked = canvasesToSend.captureOffScreen;
}

var refreshFps = function(fps, frameId, tabId) {
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "spectorjs",
"version": "0.9.3",
"version": "0.9.4",
"description": "Explore and Troubleshoot your WebGL scenes easily.",
"keywords": [
"webgl",
Expand Down

0 comments on commit b5eb0aa

Please sign in to comment.