string comparison in Chrome changing mid-function - javascript

I am getting a totally bizarre issue in Chrome v. 33 that looks as if the string comparison operator is broken. It only occurs with the developer tools closed. I have the following function:
function TabSelected(data) {
var tab, was_design;
this.data = data;
tab = this.data.tab;
was_design = tab === 'design';
if (this.data.tab === 'design') {
this.tab = 1;
} else {
this.tab = 2;
console.log('was_design');
console.log(was_design);
console.log('is_design');
console.log(tab === 'design');
}
}
Which I call like so:
new TabSelected({
tab: 'design'
});
I have a setInterval running that runs this code every 50 ms. Most of the time, the if statement picks the first code path, so nothing gets logged to the console. However, after about ~8 seconds, it goes down the else code path. When I open the developer tools afterwards (since the bug doesn't happen when they're closed), I see the following log output:
was_design (index):96624
false (index):96625
is_design (index):96626
true (index):96627
I am... confused by this. I've also tried logging the contents of tab, which is in fact 'design', and logging this, which is a new TabSelected instance.
Am I losing my mind? Is Chrome losing it's mind?
UPDATE: I was able to reproduce it in a simplified setting: http://jsfiddle.net/WBpLG/24/. I'm pretty sure this is a bug with Chrome and I've filed an issue, see answer below.

Make this change and the problem should go away:
if (this.data.tab === 'design') {
to
if (String(this.data.tab) === 'design') {
However, I can confirm that typeof this.data.tab === 'string' both before the if clause and during the else, so I think this is only a partial answer at best.
Alternatively, I can also clear the problem by adjusting NewElementButtonSectionOpened.prototype.previous_requirement on line 59440:
// Create a single instance of the requirement and store it in the closure.
var cachedReq = new TabSelected({ tab: 'design' });
// Now just return that one instance over and over again.
NewElementButtonSectionOpened.prototype.previous_requirement = function() {
// deleted line: return new TabSelected({ tab: 'design' });
return cachedReq;
};
While both of these solutions fix the problem on my machine, it is not clear to me why this works.
I am afraid to mention it, but at one point, I was also able to prevent the error from happening by adding a throw new Error("..."); line in your else block. In other words, changing something in the else block altered the behavior of the if check. My only clue here is that the length of the error message mattered. For a while there, I could clear the error or cause the error consistently by altering the length of an error message that would never be thrown. This is so bizarre that I must surely have been mistaken, and indeed, I can no longer replicate it.
However, this is an extremely large JavaScript file. Maybe there is something to that. Maybe it is just a ghost story. This problem is certainly quite creepy enough without it, but just in case somebody else sees something similar... You aren't alone.

I was able to create a simple reproduction case, so I've filed a bug with Chromium.
The necessary conditions seem to be: a setInterval or repeating setTimeout, an expensive computation in the body of the interval, a call to a new Object passing data that contains a string, and a string comparison.

Related

Why does this show in web console compiler and how to fix it and find the value

This This might sound out of of context but, does anyone know why this 2 is showing, anytime this happens I tends to have wrong data. Is there anyway to see the data that is shown there.
If someone is curious about the code, it is basically a recursive function.
(function postRow() {
if (state == "run") {
table.update(update_motor());
}
requestAnimationFrame(postRow);
// setTimeout(postRow, 20);
})();
The image shows the result I am talking about. The location that "2 appears.
The "2" means that it is a duplicate. You can turn it off in Chrome dev tools by going to Settings > Preferences > Console and uncheck Group similar I believe.
Edited:
Found a similar post, here is the correct answer

How .__defineGetter__ can be used to detect if the console in a browser is open

I have been reading through the source code here which detects when the console is open and if so plays an audio element.
I am confused by a couple of things.
Firstly, I cannot figure out how it detects that the console is open.
if( audioCheck === true || (window.Firebug && window.Firebug.chrome && window.Firebug.chrome.isInitialized)) {
play();
}
The lines below return undefined so it is audioCheck === true that triggers the play() function.
window.Firebug && window.Firebug.chrome && window.Firebug.chrome.isInitialized
It is the following line that sets audioCheck to true. I have done some research on __defineGetter__ but it remains unclear for me.
audioElement.__defineGetter__('id', function() {
audioCheck = true;
});
Can anyone explain what this does? I cannot figure it out after much research.
And finally what completely throws me is that if I remove this line the audio doesn't play:
console.log("Check the console: ", audioElement);
This is really strange as I would have though this should only log the info to the console, and not have any effect on whether or not the sound is played, but I guess this must tie back in with the __defineGetter__
There are a number of questions in here so any light that could be shed on these would be greatly appreciated.
I don't know of any sources to confirm this1, but most likely the behavior you are experiencing is an effect of what modern browsers' consoles usually do — if you issue console.log() and pass an HTML element as its argument, the console will attempt to display its details such as the ID. And the __defineGetter__ line ensures that when the browser accesses the ID, the fake getter function gets invoked (__defineGetter__() is just a non-standard way of setting — or replacing — a getter property on an object2). Quite smart, isn't it?
1Probably analysis of the source code of various browsers would be required to fully understand and validate the issue.
2Read more on getters at MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get (note that the standard way, as described therein, is to call Object.defineProperty()).

ExternalInterface return to AS3 not working consistently in IE

So, I'm having some trouble returning a value from an ExternalInterface call. I have a piece of code that looks like this:
var a:String = String(ExternalInterface.call("function() { var returnTest = 'test'; alert(returnTest); return returnTest;}"));
ExternalInterface.call("alert", a);
The first alert (in the anonymous function on line 1) is correct (obviously). However, the alert on line 2 is returning null 90% of the time in IE10. It works everytime in Firefox though.
To further explain the bit about working 90% of the time, it seems I can roll the dice again on whether or not it will work by adding or removing seemingly meaningless alerts. For example: let's say it's not working, I could add an alert and it will start working. Or, say it is working, I could add an alert for debugging, and it stops working, remove the alert, still doesn't work, add the alert back, and it starts working again. I know this isn't what's happening, but it's behaving as if a coin is flipped every time an alert is added or removed.
And this all only happens in IE, works perfectly every time in Firefox.
Thanks.
Edit:
The code I provided isn't the actual code that needs to work, but rather the code that I wrote to verify where the problem was. The actual situation is that there's a JavaScript property in the environment our Flash is running in that we need to know, but we don't have access to the HTML or JavaScript the SWF will be running in. The actual code I need to run looks more like this:
var pageNameFromJS:String = String(ExternalInterface.call("function() { var pageName = ServerObject.currentPage.name; alert(pageName); return pageName;}"));
ExternalInterface.call("alert", pageNameFromJS);
The alert in the first line is just to make sure that ServerObject.currentPage.name works, which it does. The alert in the second line is debug code that was added when we noticed that functions that require pageNameFromJS weren't working.
Really I dont know why you complicate things like this ;)
You can do it easier :
AS3 code:
ExternalInterface.addCallback("flash_function", flash_function);
function flash_function(from_js_param){
trace('param received from js : '+from_js_param)
}
ExternalInterface.call("js_function", to_js_param)
JS code:
function js_function(from_flash_param){
var to_flash_param = 'I received your '+from_flash_param;
(get_your_swf).flash_function(to_flash_param);
}

Bad idea to leave "console.log()" calls in your production JavaScript code?

I have a bunch of console.log() calls in my JavaScript.
Should I comment them out before I deploy to production?
I'd like to just leave them there, so I don't have to go to the trouble of re-adding the comments later on if I need to do any more debugging. Is this a bad idea?
It will cause Javascript errors, terminating the execution of the block of Javascript containing the error.
You could, however, define a dummy function that's a no-op when Firebug is not active:
if(typeof console === "undefined") {
console = { log: function() { } };
}
If you use any methods other than log, you would need to stub out those as well.
As others have already pointed it, leaving it in will cause errors in some browsers, but those errors can be worked around by putting in some stubs.
However, I would not only comment them out, but outright remove those lines. It just seems sloppy to do otherwise. Perhaps I'm being pedantic, but I don't think that "production" code should include "debug" code at all, even in commented form. If you leave comments in at all, those comments should describe what the code is doing, or the reasoning behind it--not blocks of disabled code. (Although, most comments should be removed automatically by your minification process. You are minimizing, right?)
Also, in several years of working with JavaScript, I can't recall ever coming back to a function and saying "Gee, I wish I'd left those console.logs in place here!" In general, when I am "done" with working on a function, and later have to come back to it, I'm coming back to fix some other problem. Whatever that new problem is, if the console.logs from a previous round of work could have been helpful, then I'd have spotted the problem the first time. In other words, if I come back to something, I'm not likely to need exactly the same debug information as I needed on previous occasions.
Just my two cents... Good luck!
Update after 13 years
I've changed my mind, and now agree with the comments that have accumulated on this answer over the years.
Some log messages provide long-term value to an application, even a client-side JavaScript application, and should be left in.
Other log messages are low-value noise and should be removed, or else they will drown out the high-value messages.
If you have a deployment script, you can use it to strip out the calls to console.log (and minify the file).
While you're at it, you can throw your JS through JSLint and log the violations for inspection (or prevent the deployment).
This is a great example of why you want to automate your deployment. If your process allows you to publish a js file with console.logs in it, at some point you will do it.
To my knowledge there is no shorter method of stubbing out console.log than the following 45 characters:
window.console||(console={log:function(){}});
That's the first of 3 different versions depending on which console methods you want to stub out all of them are tiny and all have been tested in IE6+ and modern browsers.
The other two versions cover varying other console methods. One covers the four basics and the other covers all known console methods for firebug and webkit. Again, in the tiniest file sizes possible.
That project is on github: https://github.com/andyet/ConsoleDummy.js
If you can think of any way to minimize the code further, contributions are welcomed.
-- EDIT -- May 16, 2012
I've since improved on this code. It's still tiny but adds the ability to turn the console output on and off: https://github.com/HenrikJoreteg/andlog
It was featured on The Changelog Show
You should at least create a dummy console.log if the object doesn't exist so your code won't throw errors on users' machines without firebug installed.
Another possibility would be to trigger logging only in 'debug mode', ie if a certain flag is set:
if(_debug) console.log('foo');
_debug && console.log('foo');
Hope it helps someone--I wrote a wrapper for it a while back, its slightly more flexible than the accepted solution.
Obviously, if you use other methods such as console.info etc, you can replicate the effect. when done with your staging environment, simply change the default C.debug to false for production and you won't have to change any other code / take lines out etc. Very easy to come back to and debug later on.
var C = {
// console wrapper
debug: true, // global debug on|off
quietDismiss: false, // may want to just drop, or alert instead
log: function() {
if (!C.debug) return false;
if (typeof console == 'object' && typeof console.log != "undefined") {
console.log.apply(this, arguments);
}
else {
if (!C.quietDismiss) {
var result = "";
for (var i = 0, l = arguments.length; i < l; i++)
result += arguments[i] + " ("+typeof arguments[i]+") ";
alert(result);
}
}
}
}; // end console wrapper.
// example data and object
var foo = "foo", bar = document.getElementById("divImage");
C.log(foo, bar);
// to surpress alerts on IE w/o a console:
C.quietDismiss = true;
C.log("this won't show if no console");
// to disable console completely everywhere:
C.debug = false;
C.log("this won't show ever");
this seems to work for me...
if (!window.console) {
window.console = {
log: function () {},
group: function () {},
error: function () {},
warn: function () {},
groupEnd: function () {}
};
}
Figured I would share a different perspective. Leaving this type of output visible to the outside world in a PCI application makes you non-compliant.
I agree that the console stub is a good approach. I've tried various console plugins, code snippets, including some fairly complex ones. They all had some problem in at least one browser, so I ended up going with something simple like below, which is an amalgamation of other snippets I've seen and some suggestions from the YUI team. It appears to function in IE8+, Firefox, Chrome and Safari (for Windows).
// To disable logging when posting a production release, just change this to false.
var debugMode = false;
// Support logging to console in all browsers even if the console is disabled.
var log = function (msg) {
debugMode && window.console && console.log ? console.log(msg) : null;
};
Note: It supports disabling logging to the console via a flag. Perhaps you could automate this via build scripts too. Alternatively, you could expose UI or some other mechanism to flip this flag at run time. You can get much more sophisticated of course, with logging levels, ajax submission of logs based on log threshold (e.g. all Error level statements are transmitted to the server for storage there etc.).
Many of these threads/questions around logging seem to think of log statements as debug code and not code instrumentation. Hence the desire to remove the log statements. Instrumentation is extremely useful when an application is in the wild and it's no longer as easy to attach a debugger or information is fed to you from a user or via support. You should never log anything sensitive, regardless of where it's been logged to so privacy/security should not be compromised. Once you think of the logging as instrumentation it now becomes production code and should be written to the same standard.
With applications using ever more complex javascript I think instrumentation is critical.
As other have mentions it will thrown an error in most browsers. In Firefox 4 it won't throw an error, the message is logged in the web developer console (new in Firefox 4).
One workaround to such mistakes that I really liked was de&&bug:
var de = true;
var bug = function() { console.log.apply(this, arguments); }
// within code
de&&bug(someObject);
A nice one-liner:
(!console) ? console.log=function(){} : console.log('Logging is supported.');
Yes, it's bad idea to let them running always in production.
What you can do is you can use console.debug which will console ONLY when the debugger is opened.
https://developer.mozilla.org/en-US/docs/Web/API/console/debug

What triggers "Object cannot be created in this context, Code: 9" in Firefox?

We see this occasionally in web apps on Firefox. What triggers it, and how do we prevent it? It seems to happen sporadically and the error message yields no useful information about line locations.
A quick google search yielded this:
http://blowery.org/2008/02/28/object-cannot-be-created-in-this-context-code-9/
...check your code to see if you’re
trying to grab a reference to the
computed style on a null reference.
It appears to be connected with the Dojo framework.
Edit: Ha. Sorry I gave you your own blog as an answer. I guess I don't completely understand what you're asking for. If you want to avoid the error, you could use object checking before running the applicable code.
function isValidObject(someObject)
{
return typeof someObject != null;
}
var obj1 = "Hello World";
if(isValidObject(obj1))
{
//This code will run
}
if(isValidObject(ob2))
{
//This code will not run
}
Hope that's helpful.

Categories

Resources