Starting with the Fancybrowser example, I wrote a little script player that
clicks through web forms and such, filling in fields, clicking NEXT etc.
Problem. I found that evaluateJavascript() failed on the first invocation on anything
more complicated than 'var x = "something";
In other words, any function definition, anything complex would not work.
Apparently the script evaluation engine gets left in some weird state. The only way
that I've found to clear it is to send the a bad javascript string 'syntax error;' to it.
It FAILS to run that simple javascript, but at least it clears it's state. And the next
script runs successfully, parsing complex files.
What's GOING ON HERE? I hate to send garbage to WebKit just to make it work.
Related
I've got some code that is occasionally exhibiting unexpected behavior that is hard to reproduce. I'm trying to see what is happening by running:
node --inspect client.js
It gives me a URL which I click, and then Chrome comes up with a console. Now I wait for the bad state to be encountered, and then I want to inspect the value of various variables in main.js (which are in term other objects I can dig into) in order to try to figure out what is going on.
However, I can't see any of my variables! I can see the global scope, but it has no variables from my code in it. How can I introspect the state of my program without having to think too far ahead, i.e. I could expose some variable to the global scope and hope that doesn't cause any side-effects, but then what if the issue is occurring somewhere I didn't think to expose? I want to set everything up and only have to run one time because this is a rather difficult problem to reproduce and may take a substantial amount of time, so once it gets into this state I have to be able to do everything I need to find the problem without losing the current program state.
Edit: Also to add, placing breakpoints is not necessarily helpful, because everything is event driven, and these is no guarantee I can trigger an event, or that it won't change the state in a way the interferes with trying to determine why the program is in a bad state, or that I can see the scope I need to look at from the scope where the event occurs.
Update: I tried adding a bit of code in my main module and then exporting all the top-level variables:
global.main=module
module.exports = {
var1:var1,
...
var99:var99
}
This part seemed to work ok, but I still don't have access the to internal state of objects. To accomplish this, I tried adding a debug function to each object which simply had a debugger statement to stop the debugger, like so:
function SomeOjbect(...) {
var me = this
...
me.debug = function() {
console.log("In debugger")
debugger
}
...
}
The theory being that at this point all the local variables closed to the object would be inspectable. However, when I hit the debug statement and get a breakpoint, the inspection tools completely ignore all my efforts to inspect variables in the object - in the console I get no output, just another prompt, while in the watch window after I type in the variable and hit enter it disappears completely, as if I never even tried to enter a new variable. This happens even if I mention the name of the variable in the code before hitting the debugger to try to prevent it from being optimized out, e.g. when I change the above code to this:
console.log("In debugger")
me;
debugger
I still am unable to inspect me. (It does, however, print me to the console if I replace me; with console.log(me)!)
Update: Actually, it appears that I'm able to do nothing at all in the breakpoint. If I enter console.log("Test") in the console, it doesn't output anything either. If I let the code continue running, the commands I entered into the console don't even show up in history, and in fact I no longer am able to enter any new commands at all, they all continue to be ignored, and sometimes in the source tab all source code vanishes and I pretty much have to shut down the running program and start over because the debugger becomes useless.
I have a function that will reload the current page after a period of time. I want this function to run automatically every time the page is reloaded (using the debugger).
function reloadPage() {
window.location.reload(false);
}
setInterval(reloadPage,3000)
The problem is that every time the page is reloaded, the code in the debugger will be cleaned and the function will not be called. How to fix this?
A very simple solution: Rather than putting the Javascript into the console, consider putting it in your application but disabling it when you're not debugging.
For example, you could have a GET parameter in your URL that, when present, triggers the function. A good explanation of how to retrieve a GET parameter in Javascript is at How to retrieve GET parameters from javascript?
An even simpler alternative would be to simply leave this code commented out, and comment it in when you want to debug. (This is not a good practice and I will scold you for it during code review, but it is a real thing that real people do, and it has the advantage of being easy and working.)
-
An alternative: You could detect when the console is open, and only run your code when the console is detected (though this would annoy power users like me who tend to always have developer tools open). It's not trivial to detect, but there's a library you can use: https://github.com/zswang/jdetects
I've set up a simple testbed for WatiN (ver 2.1) which reads:
var browser = new IE();
browser.GoTo("http://www.google.co.il"); // webpage doesn't matter really
browser.RunScript("alert(123)");
This works only if KB3025390 is not installed. Installing it breaks the above test with an UnAuthorizedAccessException which has HRESULT set to E_ACCESSDENIED. What gives? Is there any workaround?
Update: Using IWebBrowser2.Navigate2 along with "javascript:console.log(123)" type of scripts works however
it makes me feel uneasy using such a backchannel
the scripts run through this back-channel of .Navigate2() may only have a max length of about 2070 chars (give or take) otherwise they get forcibly truncated to this length leading to javascript errors upon attempting to run them
using .Navigate2(), even with the most trivial script, will clog the ready state of Internet Explorer for good in the sense that it will be set to READYSTATE_LOADING without any hope of getting rid of it. In simple terms this means that once you use this hack, you either have to perform every single subsequent operation in WatiN in a "dont-wait-for-webpage-to-load" fashion (GoToNoWait, ClickNoWait etc) lest your code freezes upon waiting for the browser to turn back to READYSTATE_COMPLETE (which will never come about ofcourse as already mentioned).
there appears to be a much broader issue here in the sense that I can't even access the properties of an IHtmlWindow2 object p.e. window.document throws an unauthorized exception again making it virtually impossible to transfer over to the C# world the return-values of the scripts I'm running (using Expando etc) for documents other than window.top.document (for the window.top.document window there is IWebBrowser2.Document which does the trick)
Update#2: The folks over at the selenium project have also noticed this issue:
https://code.google.com/p/selenium/issues/detail?id=8302
A bug report has been created as well:
https://connect.microsoft.com/IE/feedback/details/1062093/installation-of-kb3025390-breaks-out-of-process-javascript-execution-in-ie11
Update#3: IHTMLWindow2.setInterval and IHTMLWindow2.setTimeout also throw UnauthorizedAccess exceptions. These methods are not marked as deprecated in:
http://msdn.microsoft.com/ko-kr/library/windows/desktop/aa741505%28v=vs.85%29.aspx
yet they have wounded up suffering from the same cutbacks all the same.
Update#4: I gave the approach recommended in this post a shot:
https://stackoverflow.com/a/18546866/863651
In order to dynamically invoke the "eval" method of the IHTMLWindow2 object (or any other method really). Got the same "System.UnauthorizedAccessException" as above. So no joy here either.
Microsoft recommends using "eval" over "execscript" however after the above experiment I suspect that they are refering to accessing "eval" only from within the browser.
As far as I can tell thus far, when it comes to the full-fledged IE11+ using "eval" out-of-process (via COM) appears to have been completely prohibited along with any other function-invocation of the window object, the only exception being the back-channel of the .Navigate2() mentioned above.
It turns out Microsoft eventually backpedaled on its decision to kill off .execScript at COM-level. Just install the latest updates for Windows including kb3025390: One of the updates for IE that came after kb3025390 brings back .execScript functionality at COM-level
Note, however, that .execScript is not accessible through IE's javascript anymore. In that context it's gone for good.
fyi: this one is also not working
ieInstance.Document.Script.<methodNameString>(<commaSeperatedParameterString>)
try this worked for me at some places but not all places
ieObject.Navigate "javascript:<methodNameString>(<commaSeperatedParameterString>)", Null, "_parent"
or
ieObject.Navigate2 "javascript:"<methodNameString>(<commaSeperatedParameterString>)", Null, "_parent"
now trying to find out solution using eval
I have found a way around the problem of an update installing automatically. You can just create a simple batch file with following content.
{code}
#echo off
wusa /uninstall /kb:3025390/quiet /norestart
END
{code}
Then go to task scheduler, create a new task for this batch file to run every one hour or day as per your requirements. Add it as a system task so it runs in the background and does not affect the running automations.
I'm fairly new to casperjs (running on phantomjs) - I'm sure I'm probably missing a basic programming element here; looking to see if anyone has some insight. At the end of my script I call casper.exit(), which does exit the script and seemingly steps back into the current directory, however the current directory is not displayed in the command window.
I don't think it's related to the script itself and I can replicate with even the most basic scripts. Below is a screenshot of the outcome:
Where the yellow circle is after the .exit() call, and I would be expecting to see the cd (underlined in red)
I've tried using casper.die() with similar results.
Although it's not a big deal, it might be confusing to someone less familiar with casper/phantom and the script itself.. I guess I'm left with a few questions:
Is this expected behavior from how phantomjs/casperjs is built?
If not, is this a 'bad' thing? (affecting memory, stack, etc.)
Is there a way to return to the CD using casper/phantom or some other method in the script itself?
Bonus question.. is there a difference between using casper.die() and casper.exit()? I see that .die() logs a status message but other than that is there a preferred method to stop script execution or is it just syntactics, as in PHP ?
It is the normal behavior of the casperjs executable on windows. This has likely something to do with the python part of the executable since phantomjs does not have this behavior.
Another indicator is that when casperjs is run through phantomjs like described here, there is no such behavior and I get a normal prompt after exit.
I would say, this is a cosmetic problem that can throw you off when you first encounter it. This isn't really a problem.
Regarding the Bonus question: die can be seen as a fancier exit since it calls exit itself, but it is a more controlled way to exit casper. There is an optional message that is written to stout in red and an additional die event handler. die also sets the execution time of the script.
I am dealing with a complex legacy javascript code base, and it's difficult to figure out where to put breakpoint (I have to find the files, put a breakpoint in firebug etc).
Is there a way so that Firebug breaks on the first javascript execution that it encounters every time?
In other words, every time I click on something on the page, and if a javascript code is executed, I want Firebug to break on that line?
Of course I don't want Firebug to stop when it executes it's internal javascript.
Is this possible?
Yes, The latest build has a [pause] button for it.
You can read more about it here : http://getfirebug.com/doc/breakpoints/demo.html#suspend