Debugging Web Workers in Safari Web Inspector - javascript

Chrome's Dev Tools are great for debugging web workers as I can "browse" into that JavaScript environment and set break points. Even the console works as expected.
On Safari, it is a completely different story. console.log from the web worker doesn't even print in the console. I see the worker script loaded and I put a break point on it, but it doesn't break. I don't even see the scripts that were loaded with importScripts.
How can I use Safari's Web Inspector to troubleshoot problems?
Not that I think it matters, but I'm using Safari 8.

Insert the debugger; code in your source
Usage: Insert it anywhere you want to add a breakpoint and when developer console is open automatically execution will pause at that line
var a = 50;
a = a + 5;
debugger; //--> execution is paused here
a = a - 5;
For more info see the Debugger Documentation on mozilla.org

In lieu of console.log, you can use postMessage. postMessage should allow you to send debug messages to the safari console.
Here is a great example on how to do that, I pasted the main idea below:
//
// In the Main thread
//
var worker = new Worker('/path/of/webworker/code.js')
worker.onmessage = function (e) {
var result = JSON.parse(e.data);
if(result.type == 'debug') {
console.log(result.msg);
} else if(result.type == 'response') {
// ... use result.answer ...
}
}
//
// In the WebWorker
//
function debug(msg) {
postMessage(JSON.stringify({type:'debug',msg:msg}));
}
onmessage = function (e) {
var inputData = e.data;
// work on input data
debug('Working OK');
// work some more
// ...
postMessage(JSON.stringify({type:'response', answer:42}));
};
If you don't want to play around with postMessage though, David Flanagan made a wrapper for it here that should allow you to at least do debugging with console.log

Related

How to get cpu usage of current tab from chrome

I am using the chrome extension api chrome.processes and chrome.tabs and have been trying to get the cpu usage of current tab only.
I looked at the chromium example code for reference but the purpose of its code is to display all information of all the processes on chrome but i only need the current tab"s information.
this is my code
var tid;
var cpu;
chrome.tabs.get(tabid, function(tabid) {
tid = tabid.id;
});
chrome.processes.onUpdatedWithMemory.addListener(
function(processes) {
for (pid in processes) {
if (processes[pid].id = tid) {
cpu = processes[pid].id.cpu;
return;
}
}
});
I didn't receive any error message but when I debug it, the value of tid is always undefined and the processes array is looping fine.

Execute JavaScript code to get the log from console using selenium webdriver or WatiN

(Sorry for being a bit descriptive)
I wanted to wait for a page to load completely but after searching on Google it seems that browsers react differently, when we try to use readyState or onLoad.
Also, for application I am working on, it seems that a particular log message ("TNP is ready") appears in console (chrome console or IE developer tool console), when the required page is loaded.
My plan is to execute a small JavaScript code on the browser, using Selenium WebDriver C# and WatiN C# (IE), to get this message from the console log.
Can this be done? Can I get the Last Log generated by console.log ?
Because when I execute the script it might happen that the message is already gone or yet to come. I need to fire it repeatedly.
Any suggestions?
This question, while not exactly a duplicate of In WatiN how to wait until postback is complete, is probably caused by the same thing.
The browser.WaitUntilComplete() method will wait for the page to finish loading, but if you have AJAX going on in the background as the page is loading then WaitUntilComplete won't do the trick.
From my research, there is no way to get log messages from the browser console unless you include some JavaScript to mirror the console and overwrite window.console and provide a mechanism for inspecting console messages.
(function(win) {
var console = win.console;
if (!console)
throw new Error("This browser does not support a debug console");
var mirror = {},
data = {};
var toString = Object.prototype.toString,
mirrorMethod = function(key) {
data[key] = [];
return function() {
data[key].push(arguments);
console[key].apply(console, arguments);
};
};
for (var key in console) {
if (toString.call(console[key]) == "[object Function]") {
mirror[key] = mirrorMethod(key);
}
}
win.console = mirror;
win.consoleMirror = {
getData: function(key) {
return data[key] || [];
}
};
}(this));
JSFiddle: http://jsfiddle.net/fyhLw0to/
And to use:
console.log("foo");
alert(consoleMirror.getData("log")[0][0]);
An alternative is to grab an element using WatiN that you need to interact with, and call WaitUntilExists:
var button = browser.Button("buttonIdThatDoesNotExistYet");
button.WaitUntilExists();
button.Click();
This way you don't have to hack the debug console, or hack XMLHttpRequest to infer when AJAX is done. Your tests will attempt to wait for elements to appear on the page before acting upon them. Test failures will be slower, but your tests should be more robust.

Intercept new downloads in Firefox Addon SDK

I have written a simple download manager for Windows and I would like to create an addon for Firefox that when enabled intercepts new downloads in Firefox and sends them to the download manager.
I have already done this for Google Chrome using:
chrome.downloads.onCreated.addListener(function(details) {
// stop the download
chrome.downloads.cancel(details.id, null);
}
The question is how can I achieve something similar using the Firefox add-on SDK.
I see there is a way of intercepting page loads to view the content / headers which might be helpful but then I won't know if the request will turn into a download or not.
Firefox add-on SDK: Get http response headers
I could perhaps look for a content type that is not text/html or check for a content disposition header but that could cause problems if I don't correctly handle all cases.
Is there no way of accessing the download manager using the JS SDK or some way of knowing when a download has been started / being started and stop it?
The http-on-examine-response observer that the linked question discusses is the wrong way to go. It concerns all requests not just downloads.
Instead use the Downloads.jsm to observe new downloads, then cancel them, and so on.
To load Downloads.jsm in the SDK use:
const {Cu} = require("chrome");
Cu.import("resource://gre/modules/Downloads.jsm");
Cu.import("resource://gre/modules/Task.jsm");
Then you can add your listener.
let view = {
onDownloadAdded: function(download) {
console.log("Added", download);
},
onDownloadChanged: function(download) {
console.log("Changed", download);
},
onDownloadRemoved: function(download) {
console.log("Removed", download);
}
};
Task.spawn(function() {
try {
let list = yield Downloads.getList(Downloads.ALL);
yield list.addView(view);
} catch (ex) {
console.error(ex);
}
});
The linked MDN docs have more information and samples.
Since your add-on is a restartless SDK add-on, you'll need to remove the listener again using .removeView on unload, or else there will be a memory leak.
Here's the JSM way.
Components.utils.import("resource://gre/modules/Downloads.jsm");
Components.utils.import("resource://gre/modules/Task.jsm");
Components.utils.import("resource://gre/modules/FileUtils.jsm");
var view = {
onDownloadChanged: function (download) {
console.log(download, 'Changed');
if (download.succeeded) {
var file = new FileUtils.File(this.target.path);
console.log('file', file);
}
}
};
var list;
Task.spawn(function () {
list = yield Downloads.getList(Downloads.ALL);
list.addView(view);
}).then(null, Components.utils.reportError);
Remember to removeView to stop listening. Can do this anywhere, like in shutdown function or whatever, doesn't have to be within that Task.spawn so list must be global var.
list.removeView(view); //to stop listening
Here's the old way, which seems to still work. Although I thought they said they're going to take out the old downloadManager:
var observerService = Components.classes["#mozilla.org/download-manager;1"].getService(Components.interfaces.nsIDownloadManager);
observerService.addListener({
onDownloadStateChange: function (state, dl) {
console.log('dl=', dl);
console.log('state=', state);
console.log('targetFile', dl.targetFile);
if (state == 7 && dl.targetFile.leafName.substr(-4) == ".txt") {
//guys just downloaded (succesfully) a .txt file
}
}
});
Heres a mozillazine with some more on this: http://forums.mozillazine.org/viewtopic.php?f=19&t=2792021

Running JS in a killable 'thread'; detecting and canceling long-running processes

Summary: How can I execute a JavaScript function, but then "execute" (kill) it if it does not finish with a timeframe (e.g. 2 seconds)?
Details
I'm writing a web application for interactively writing and testing PEG grammars. Unfortunately, the JavaScript library I'm using for parsing using a PEG has a 'bug' where certain poorly-written or unfinished grammars cause infinite execution (not even detected by some browsers). You can be happily typing along, working on your grammar, when suddenly the browser locks up and you lose all your hard work.
Right now my code is (very simplified):
grammarTextarea.onchange = generateParserAndThenParseInputAndThenUpdateThePage;
I'd like to change it to something like:
grammarTextarea.onchange = function(){
var result = runTimeLimited( generateParserAndThenParseInput, 2000 );
if (result) updateThePage();
};
I've considered using an iframe or other tab/window to execute the content, but even this messy solution is not guaranteed to work in the latest versions of major browsers. However, I'm happy to accept a solution that works only in latest versions of Safari, Chrome, and Firefox.
Web workers provide this capability—as long as the long-running function does not require access to the window or document or closures—albeit in a somewhat-cumbersome manner. Here's the solution I ended up with:
main.js
var worker, activeMsgs, userTypingTimeout, deathRowTimer;
killWorker(); // Also creates the first one
grammarTextarea.onchange = grammarTextarea.oninput = function(){
// Wait until the user has not typed for 500ms before parsing
clearTimeout(userTypingTimeout);
userTypingTimeout = setTimeout(askWorkerToParse,500);
}
function askWorkerToParse(){
worker.postMessage({action:'parseInput',input:grammarTextarea.value});
activeMsgs++; // Another message is in flight
clearTimeout(deathRowTimer); // Restart the timer
deathRowTimer = setTimeout(killWorker,2000); // It must finish quickly
};
function killWorker(){
if (worker) worker.terminate(); // This kills the thread
worker = new Worker('worker.js') // Create a new worker thread
activeMsgs = 0; // No messages are pending on this new one
worker.addEventListener('message',handleWorkerResponse,false);
}
function handleWorkerResponse(evt){
// If this is the last message, it responded in time: it gets to live.
if (--activeMsgs==0) clearTimeout(deathRowTimer);
// **Process the evt.data.results from the worker**
},false);
worker.js
importScripts('utils.js') // Each worker is a blank slate; must load libs
self.addEventListener('message',function(evt){
var data = evt.data;
switch(data.action){
case 'parseInput':
// Actually do the work (which sometimes goes bad and locks up)
var parseResults = parse(data.input);
// Send the results back to the main thread.
self.postMessage({kind:'parse-results',results:parseResults});
break;
}
},false);

help with Firefox extension in multiple windows

I'm writing a Firefox extension that creates a socket server which will output the active tab's URL when a client makes a connection to it. I have the following code in my javascript file:
var serverSocket;
function startServer()
{
var listener =
{
onSocketAccepted : function(socket, transport)
{
try {
var outputString = gBrowser.currentURI.spec + "\n";
var stream = transport.openOutputStream(0,0,0);
stream.write(outputString,outputString.length);
stream.close();
} catch(ex2){ dump("::"+ex2); }
},
onStopListening : function(socket, status){}
};
try {
serverSocket = Components.classes["#mozilla.org/network/server-socket;1"]
.createInstance(Components.interfaces.nsIServerSocket);
serverSocket.init(7055,true,-1);
serverSocket.asyncListen(listener);
} catch(ex){ dump(ex); }
document.getElementById("status").value = "Started";
}
function stopServer ()
{
if (serverSocket)
serverSocket.close();
}
window.addEventListener("load", function() { startServer(); }, false);
window.addEventListener("unload", function() { stopServer(); }, false);
As it is, it works for multiple tabs in a single window. If I open multiple windows, it ignores the additional windows. I think it is creating a server socket for each window, but since they are using the same port, the additional sockets fail to initialize. I need it to create a server socket when the browser launches and continue running when I close the windows (Mac OS X). As it is, when I close a window but Firefox remains running, the socket closes and I have to restart firefox to get it up an running. How do I go about that?
Firefox extension overlays bind to window objects. One way around this is to create an XPCOM component or find one that someone else already created to allow you to build functionality without binding it to the window objects.
Of course, section #2 below on Observer Notifications may be helpful as well.
Possible workaround: #1
Instead of calling "startServer()" each time a window is opened, you could have a flag called windowCount that you could increment each time you open a new window. If windowCount is greater than 0, don't call startServer().
As windows close, you could decrement the count. Once it hits 0, stop the server.
Here is information from the Mozilla forums on this problem:
http://forums.mozillazine.org/viewtopic.php?f=19&t=2030279
Possible workaround #2:
With that said, I've also found documentation for Observer Notifications, which may be helpful as there is a section on Application Startup and Shutdown:
https://developer.mozilla.org/en/Observer_Notifications
UPDATE:
Here are some resources on creating XPCOM components in JavaScript and in C++:
https://developer.mozilla.org/en/how_to_build_an_xpcom_component_in_javascript
http://www.codeproject.com/KB/miscctrl/XPCOM_Creation.aspx
https://developer.mozilla.org/en/creating_xpcom_components
You probably want to:
Move your code into a JavaScript component
Register your component as a profile-after-change observer
Whenever someone makes a connection to your socket, find the active window and return its URL.
Use something like
var wm = Components.classes["#mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator);
var win = wm.getMostRecentWindow("navigator:browser");
var spec = win ? win.getBrowser().currentURI.spec : "";
var outputString = spec + "\n";
etc.

Categories

Resources