I did notice a worrysome behaviour with node.js (v4.0.0).
I have an object with functions, something like this:
var local = {};
local.myMethod = function() {
console.log('here I am');
};
At a certain point in time I did comment out myMethod() for debugging purposes.
Some time later, I did call it again in my code, forgetting to remove comments from function definition:
...
var result = local.myMethod();
...
/*
local.myMethod = function() {
console.log('here I am');
};
*/
When running that code, I got no compile nor runtime error, so I got mad catching the silly problem...
What I ask is: Is this behaviour intended?
Should I use some pragma enforcing strictness, to avoid such problems?
UPDATE
Sorry, this code does not reproduce the problem, I did shrink it too much...
I'm quite sure on some condition the problem shows, however: I have a warning set just before the call to the undefined function... The warning prints, and then the code continues without a notice...
The undefined function is called inside an async.each() function, but I can't yet simplify my code enough to post it here... Keep trying...
Related
I don't know this is possible, but I have some special situations requiring it.
//Obj is a class with nothing.
Obj.prototype.v1 = function(){
//this is a normal statement.
//it could be something else
return 3;
}
//or it can be any way to declare a function:
var v1 = function(){return 3};
Obj.prototype.v2 = function(){
return this.v1()+2;
}
How to make it directly returns 3 here? It's like the function v1() is something like pseudocode this.return(3) for v2(), and certainly nothing can be reached after the first return.
If I'm generating the code dynamically and it has to be a return in the second function. (So it can easily get unexpected token for return (return 3).v2(), while trying to get the inside function to be called behaving like it's part of current function.)
Is there anyway to make this.v1() directly cause outside function v2() to return, for the first return it encounters? Preferably by focusing on modifying v1().
Is there anyway to make this.v1() directly cause outside function v2() to return, for the first return it encounters?
The idiomatic solution is to express this logic in v2. For example, you could cause v1 to modify a flag that decides what v2 does:
Obj.prototype.v1 = function(){
this.v1.continue = true; /* XXX: Continue? */
this.v1.continue = false; /* ... or not? */
return 3;
}
Obj.prototype.v2 = function(){
var ret_val = this.v1()+2;
if (!this.v1.continue) {
return;
}
/* XXX: Insert more code here */
}
We're talking about rather basic JavaScript here. Do you have a book?
Preferably by focusing on modifying v1().
I'm sure it's possible to circumvent the control of execution that v2 has when v1 returns in some situations, but that doesn't make it a good idea. Think about how difficult it'll become to debug this code!
For example, you could throw an error which v2 doesn't catch, and catch it further upstream. Such a hideous abuse of throw would be worse than the abuse of goto! Don't modify your code flow in such an unclear manner; it makes maintenance and debugging a nightmare!
To make debugging easier, I'm capturing all of the console logs in Chrome so that users who submit a feedback entry will also submit all of the logs to our server. When someone encounters a problem in production, I can first and foremost get them back to work so that I can then sit down and more thoroughly go through all of the logs to determine the root cause of whatever issue the user encountered in production.
The technique I use to capture the logs involves overriding console.log so that all text entered in the first argument gets stored in an array while simultaneously invoking the legacy function so that I can still see the logs in the console too.
The problem is when there's the occasional uncaught exception. These aren't included in the uploaded logs, so it's not always clear what caused the problem. So I tried overriding ReferenceError by writing a JavaScript function that takes a function as an argument, then returns a new function that does stuff with it, like storing data in a variable, and then invoking the legacy function as the last step:
function overrideException(legacyFn) {
/** arguments for original fn **/
return function() {
var args = [];
args[0] = arguments[0];
// pass in as arguments to original function and store result to
// prove we overrode the ReferenceError
output = ">> " + legacyFn.apply(this, args).stack;
return legacyFn.apply(this, arguments);
}
}
To test the overrideException function, I ran the following code on the console:
ReferenceError = overrideException(ReferenceError);
Afterwards, I tested the returned function, the new ReferenceError, by manually throwing a ReferenceError:
throw new ReferenceError("YES!! IT WORKS! HAHAHA!");
The resulting output on the console is:
ReferenceError: YES!! IT WORKS! HAHAHA!
And checking the global variable output from the overrideException function shows that it did indeed run:
output
">> ReferenceError: YES!! IT WORKS! HAHAHA!
at ReferenceError (<anonymous>)
at new <anonymous> (<anonymous>:18:35)
at <anonymous>:2:7
at Object.InjectedScript._evaluateOn (<anonymous>:562:39)
at Object.InjectedScript._evaluateAndWrap (<anonymous>:521:52)
at Object.InjectedScript.evaluate (<anonymous>:440:21)"
Now, here's where things start to fall apart. In our code, we're not going to know when an uncaught exception occurs, so I tested it by attempting to run a function that doesn't exist:
ttt();
Which results in:
ReferenceError: ttt is not defined
However, unlike the case where we explicitly throw an error, in this case, the function doesn't fire, and we're left with only the legacy functionality. The contents of the variable output is the same as in the first test.
So the question seems to be this: How do we override the ReferenceError functionality that the JavaScript engine uses to throw errors so that it's the same one we use when we throw a ReferenceError?
Keep in mind that my problem is limited only to Chrome at this time; I'm building a Chrome Packaged app.
I have done quite a bit of research for the same reason: I wanted to log errors and report them.
"Overriding" a native type (whether ReferenceError, String, or Array) is not possible.
Chrome binds these before any Javascript is run, so redefining window.ReferenceError has no effect.
You can extend ReferenceError with something like ReferenceError.prototype.extension = function() { return 0; }, or even override toString (for consistency, try it on the page, not the Dev Tools).
That doesn't help you much.
But not to worry....
(1) Use window.onerror to get file name, 1-indexed line number, and 0-indexed position of uncaught errors, as well as the error itself.
var errorData = [];
onerror = function(message, file, line, position, error) {
errorData.push({message:message, file:file, line:line, position:position, error:error});
};
See the fiddle for an example. Since the OP was Chrome-specific, this has only been tested to work in Chrome.
(2) Because of improvements to (1), this is no longer necessary, but I leave this second technique here for completeness, and since onerror is not guaranteed to work for all errors on all browsers. You will also sometimes see the following:
var errors = [];
function protectedFunction(f) {
return function() {
try {
f.apply(this, arguments);
} catch(e) {
errors.push(e);
throw e;
}
};
}
setTimeout = protectedFunction(setTimeout);
setInterval = protectedFunction(setInterval);
etc...
FYI, all this is very similar to what has been done in the Google Closure Compiler library, in goog.debug, created during Gmail development with the intent of doing exactly this. Of particular interest is goog.debug.ErrorHandler and goog.debug.ErrorReporter.
So I am I getting an error using tinyMCE but that isn't really the question here. I am trying to debug it using firebug and I am a little confused. I have a break point here.
This breakpoint gets hit when the page loads but then although the error says it is on line 564 I never see it get hit again (even though I can click save over and over and get the same error). Is that because of the way that function gets created? clearly JQuery is creating some sort of object literal with a bunch of functions as the value of the variables like
var functions = {
func1: function() {...},
func2: function() {...}
};
instead of saying
var myAwesomeFunction = function() { //do awesome };
I am not sure but if so how I can debug this?
Thanks
My code seems to bring about some kind of quantum duel state in chrome, invoking a universe where functions turn into undefined upon being pushed to an array... spooky
I'm building an array of functions using the following code, in order to callback chain them together using this function https://gist.github.com/3609831
console.log "creating stack"
ids = (id for id of #s3) # an array of integers
stack = [callback]
console.log stack
for ssid of #s3
new_func = ((cb) => #idb.load_s3(ssids.shift(),cb))
console.log new_func
stack.push new_func
console.log stack
console.log "stack done"
What's bizarre is that although it actually seems to work; all the function calls with the right arguments seem to be happening, it also get this in the console (with my formatting and comments)
> creating stack
# callback added to array correctly
> [function () { return _this.start(true); }]
# function generated correctly
> function (cb) { return _this.idb.load_s3(ssids.shift(), cb); }
# but the function doesn't get added to the array !!!!!!!
> [function () { return _this.start(true); }, undefined × 1]
> stack done
# and the undefined from the array can't be executed of course, verified my line number
> Uncaught TypeError: undefined is not a function
which seems to mean that although it worked... it also didn't work... because... the new_func turns into undefined upon being pushed to the array...
WTF???
Anyone got any clues as to what might be happening here?
I'm using chrome v21
...
EDIT: fyi the #idb.load_s3 function IS in scope and I know it's working because it loads data from indexedDB which doesn't load if any part of this is broken, (and because the callback does fire).
...
EDIT2: here's the javascript, nothing very different or odd about it, just harder to read
var id, ids, new_func, ssid, stack,
_this = this;
console.log("creating stack");
ids = (function() {
var _results;
_results = [];
for (id in this.s3) {
_results.push(id);
}
return _results;
}).call(this);
stack = [callback];
console.log(stack);
for (ssid in this.s3) {
new_func = (function(cb) {
return _this.idb.load_s3(ssids.shift(), cb);
});
console.log(new_func);
stack.push(new_func);
console.log(stack);
}
console.log("stack done");
...
EDIT 3: Just realised that part of the problem is because Chrome's console is presumably asynchronous so it seems the last item is popped off the stack (in code not shown here) AFTER the call to console.log but BEFORE console.log has actually output the array contents!!! So when I don't call the function (see referenced gist) to execute the stack then the rest seems to work fine.
HOWEVER this doesn't solve the mystery of the exception complaining about undefined not being a function (like it's trying to pop undefined from the array and execute it)... still weird!
...
EDIT #4:
load_s3 function is here: https://github.com/gnatters/neuroanatomist/blob/master/app/assets/jax/models/asset_loader.js.coffee.erb#L118
the real life version of the code being questioned here is in the same file in load_everything at #L145
I worked it out! There are two parts to the problem which look like the same thing. Firstly, as in edit 3, the array looks like it contains an undefined item in the place where the function was pushed. However this would seem to be a quirk (bug?) in chrome's asynchronous console, whereby the function is removed from the array in the time between the console.log call and the actual logging of the array.
The second part of the problem was also deceptive in appearance, and sorry I didn't think this was so important when asking the question. In the linked gist (which has now be revised) the function was trying to pop and execute an extra function from the array which of course amounts to trying to all undefined. Not an easy one to spot...
All is well. Thanks for playing ;)
I'm trying to create a javascript object that can call other methods within itself. However, I'm running into a weird problem that I just can't seem to figure out.
I have the following code
myObjectDef = function() {
this.init = function() {
//do some stuff
this.doSecondInit();
}
this.doSecondInit = function() {
//do some more stuff
}
}
myObject = new myObjectDef();
myObject.init();
I am getting an error that states "Message: Object doesn't support this property or method". And it ends at this.doSecondInit();. I can't quite figure out why it's doing this. My code runs great up to the call to the second method. How do I make this work?
There's an extra set of parenthesis here:
this.doSecondInit() = function() {
You can't assign to the result of a function call, let alone to the result of a function that doesn't even exist.
After your edit, your thing seems to work fine:
http://jsfiddle.net/nabVN/
You sure you didn't have the same typo in your actual code? Better start getting used to not putting that () after every function call, which is probably a bad habit carried over from languages where functions aren't values.