I have just spent far too long trying to find a problem with the code below.
In turned out that because of the context that addRoute was called in, keys() was not returning the keys of the results object. To fix this I had to use Object.keys() despite it working without a problem in the JavaScript console (which I later realised was because of the context).
My question is, why didn't this show in my JavaScript console? It took me quite a while to realise (I have cropped the full code, the actual function is a lot bigger).
Wrong, but no error in the console:
Map.prototype.addRoute = function (results) {
var sectionsIDs = keys(results);
}
Correct
Map.prototype.addRoute = function (results) {
var sectionsIDs = Object.keys(results);
}
Your first function uses the keys console API function.
That "Command Line API Reference" page includes the warning:
Note: This API is only available from within the console itself. You cannot access the Command Line API from scripts on the page.
Thus, it is by design that the keys function only exists for code run directly on the console.
Chrome gives you a small hint about the keys function being a console-only function if you view it in the console:
> keys
function keys(object) { [Command Line API] }
Related
I have some automated tests written in TruClient scripts and I want to verify what was printed in the application JS console.
Is there any way to access that from the javascript?
Like console.getText() type of thing?
I want to verify that some information appeared in the console.
For instance, how can I do this?
console.log("Hi");
//Now I want to check if it was printed correctly in the browser
if(console.getText() == "Hi")
{
//then test passed
}
I am needing this because we are architecting new browsers.
You might be able to intercept calls to console by redefining them:
// Save original console methods
var originalConsole = {
log: console.log,
warn: console.warn,
error: console.error
}
var consoleHistory = [];
console.log = function() {
// Save inputs given to console.log()
consoleHistory.push(arguments);
// Make call to original console
originalConsole.log.apply(window.console, arguments);
}
// Repeat for warn and error, if needed.
Eloquent JavaScript uses this technique to display errors when evaluating JS in its code sandbox.
I have two similar functions, but one works and the other not
function notWorking(el) {
return getEventListeners(el);
}
notWorking(document);
// result --> Uncaught ReferenceError: getEventListeners is not defined
working = function(el) {
return getEventListeners(el);
}
working(document);
// result --> Object {keyup: Array[1], …}
Why is getEventListeners working inside the second function and not inside the first?
Firstly to all those question comments, getEventListeners is not custom method, it is the console api provided by browser.
getEventListeners(object)
getEventListeners(object) returns the event listeners registered on
the specified object.
I executed the code which you have provided in the question. It just works fine in Firefox, check the attached snapshot
I executed the same in Chrome browser
But this is not expected. As it is valid and also Firefox is doing right, the same should have been worked in chrome. I checked all the answers in var functionName = function() {} vs function functionName() {} and all other resources. It explains the scope/visibility of function declaration and function expression. But here the problem is visibility of getEventListeners function not function-working or function-notWorking.
So I think this must be defect in Chrome or the method getEventListerners should not be used in script, it is only for debugging purpose as specified in Command Line API Reference.
Note : This API is only available from within the console itself. You
cannot access the Command Line API from scripts on the page.
More information
getEventListeners.toString()
> "function getEventListeners(node) { [Command Line API] }"
this.getEventListeners
> undefined //function is not accessible via window object
// where as
this.setTimeout
> setTimeout() { [native code] }
function Notify(header,content,image){
var note = webkitNotifications.createNotification(image||"",header,content);
note.show();
return note;}
var extensions = ["pbjhaapnigfhipfahcfkeakpcgkmnklc"];
function CheckReload(){
for(var CN=0;CN<extensions.length;CN++){
var id = extensions[CN];
var ex = chrome.management.get(id);
console.log("Checking",ex,"-",id);
if(!ex.enabled){
Notify("Extension reloaded!",ex.name+" was found crashed, and reloaded!");
chrome.management.setEnabled(id,true);
}
}
}
setInterval(CheckReload,1000);
Ok, so what I was expecting was for this to check the extensions in the "extensions" array, and if they weren't enabled it would create a notification saying that it wasn't, and then enable it.
However, chrome.management.get(id) seems to be returning undefined.
I expected an output like:
Checking Object - [id]
Instead, what I got was:
Checking undefined - pbjhaapnigfhipfahcfkeakpcgkmnklc
Uncaught TypeError: Cannot read property 'enabled' of undefined
How can I fix this?
Most of the methods provided by chrome don't return a value, instead they take a callback function as a parameter, and call that function with the wanted result.
You should replace your code by
chrome.management.get(id, function(ex) {
console.log("Checking",ex,"-",id);
if(!ex.enabled){
Notify("Extension reloaded!",ex.name+" was found crashed, and reloaded!");
chrome.management.setEnabled(id,true);
}
});
See http://developer.chrome.com/extensions/management.html#method-get for details.
If you are running your code from an extensions, make sure that your extension have permissions to management.
I prototyped Function so that it has a getBody function:
Function.prototype.getBody = function() {
// Get content between first { and last }
var m = this.toString().match(/\{([\s\S]*)\}/m)[1];
// Strip comments
return m.replace(/^\s*\/\/.*$/mg,'');
};
See here for more info.
I tried to test it this way:
console.log(console.log.getBody.getBody());
but received an error: TypeError: console.log.getBody is undefined.
I figured out that maybe this happens because console.log was defined before I actually prototyped Function so I created an empty function x right before the prototyping and tried to call
console.log(x.getBody.getBody());
which worked without a problem. Checking the type of console.log with typeof console.log results in "function". Here's a CodePen to try it out. All of this wasn't really a surprise since it's what I expected except of console.log.getBody to be undefined.
So why does prototyping Function not affect console.log? I'm using Firefox 18.0.1 with Firebug 1.11.1.
This seems to be an issue with Firebug not with Firefox per se. My guess is that Function in Firebug lives in a different scope then Function in your page. (since unlike the other browsers Firebug is an extension , not a built in browser tool)
In fact if instead of Firebug you use the built in Firefox console (Ctrl+Shift+K), your code works perfectly fine.
More information about Firebug internals can be found here
http://getfirebug.com/wiki/index.php/Firebug_Internals
This excerpt may be interesting
When Firebug is detached from Firefox, open in a new or separate
window, the new window has its own scope. In that scope, a few Firebug
script tags compile to create a connection back to the original
browser.xul window. Most important, chrome.js is unique to each top
level window, but the Firebug object used by the detached window is
the object of the parent browser.xul.
I saw many posts how to replace the JS console functions by others but no one leaves it intact for Firebug.
When I replace any of them, it calls my custom function but it reports the message from the very same place the new function comes from.
The goal here is to receive any of those console messages and display them somewhere else whilst I still can jump to the callee in the Firebug console.
Is this possible at all ?
Update :
for instance (PSEUDO) :
//keep the old one
var oriFn=console.error;
console.error=function(){
someOtherFunc(arguments);//send to server for instance
oriFn(arguments);
}
Now somewhere else I'd like to call as usual console.error('bla'); In the Firebug console, it prints my message but shows a link to the replacement code above. I want in the Firebug console the link to the callee's parent function and that's it.
Use a function pointer. Given foo.js:
function foo()
{
console.error = console.log; //Reassign console.error
location.hash = document.title; //Do something
console.error("Not the mama"); //Outputs line foo.js:5
}
References
How to de-anonymize your anonymous functions
JavaScript Wikibook: Anonymous Functions
JavaScript Anonymous Functions
Javascript function declarations vs function operators