Is there any way to find out if a javascript object that was referenced somewhere in the code is still alive and in memory?
the reason i ask is that my code got really complicated and I added some "cleanup" functions that are supposed to clear some of the references but I'm not sure if they work as they should. Can I somehow get a list of variables that are still in use by the browser?
In chrome, press F12 to open the debugger, then do the following:
Click the [Timeline] tab
Click the [Record] button in the top-left; play around with your site, open a menu, load a page, etc, where you want to check the memory.
Whilst it's still recording, press the [garbage collector] and wait for a few seconds to let the buffer collect more data. Now press the [record] button again to stop the recording.
Once the recording has stopped, you will see a 'stair-step' of how memory was allocated onto the heap.
Importantly, you should see the lines return to zero after you hit the [garbage collection] button. If this doesn't happen, then you may have a memory-leak.
There are some very detailed videos from google advocates, explaining this debugger feature and is beyond the scope of this simplistic answer. This is just a pointer to a debugger feature you may want to use to test your code and find which objects are on the heap and if they're cleaned up as expected.
You can do further analysis of your objects with the [profiles] tab.
JavaScript is completely managed language and doesn't allow any kind of delete function.[delete keyword only deletes the properties but doesn't delete objects from memory]
Best bet to clean any object is to assign to null to give a hint to garbage collector still may not work in all scenarios.
Hope this helps
Related
I am a lowly operations employee without authorization to change the programs and permissions on my machine, and I would like to automate some highly repetitive data entry. I know there are a lot of programs that can do that, however, for the sake of this discussion we'll assume that I'm not allowed to have any of them and I can only script through the debug F12 menu in Chrome. I also probably don't understand half of these words as well as I should.
I have to run test cases on a third-party vendor's highly dynamic website, and I've already successfully written javascript which adds texts to elements in the DOM and presses the "next" button.
The problem is, upon .click()ing the "next" button, it takes time for the page to update, and the update creates new elements which weren't in the DOM when the script was initialized. I need to find a way to delay the execution of the script until the DOM contains all the elements I need to update.
As a really, really crude proof of concept I wrote the pre-filler for each page as a function, and I serially called each function at the end of the previous function, using setTimeout(nextfunct, 10000) to let the page update before executing the next line. (I was going to refine that by trying to create some kind of object listener instead of an arbitrary 10 second delay, but I wasn't even able to get that far.) This approach creates two errors.
1) The script seems to be checking whether the elements are on the DOM before the end of the setTimeout(), so it still gives me an error. If nextfunct is defined as
document.getElementById("doesntexistyet").value = "Fill Me";
console.log("nextfunct ran");
I will get the error message stating there is no element with the id "doesntexistyet" immediately, not after a delay of 10 seconds. The element on the next page will not update.
2) The DOM updating interrupts my script. In the above code, the console output will not ever appear in my console. If I comment out the missing element, so the function only prints a comment, it will still not appear in my console. However, if I comment out the code and I switch the setTimeout to 1ms, "nextfunct ran" will appear in my console, until the page updates, at which time the console will be deleted.
Are there ways around this which I can implement using only vanilla JS and a browser? I'm sure there's a keyword I can search for where someone has discussed this before, but it seems like the vast majority of JS autofilling discussions are oriented towards people designing code to be integrated into a website,
Thanks
I have a fairly good sized javascript (with react/redux but no jquery) codebase for a webapp I'm building, and I've noticed that when I repeatedly open and close a certain panel within the UI, the number of listeners according to Chrome's performance timeline keeps increasing.
The graph looks like this:
I have allowed the chrome's performance monitor run for a good minute or two with the page sitting idle (just after opening/closing the panel a bunch), hoping that perhaps the listeners will get garbage collected, but they are not. I've switched to other tabs during this process, also hoping that the listeners will get garbage collected when the tab is backgrounded, but they unfortunately are not.
I therefore suspect that some listeners are getting registered that are never unregistered.
This leads me to two main questions:
Does my hypothesis that listeners are getting added and never
unbound seems sensible, or is there more I could be doing to confirm
this suspicion?
Assuming my suspicion is correct, how can I best go
about tracking down the code where the event listener(s) is/are
being added? I have already tried the following:
Looked at the code that is responsible for opening the panel in question, seeing where it adds any listeners, and commenting out those portions to see if there's any change in the performance graph. There is not a change.
Overridden the addEventListener prototype like so:
var f = EventTarget.prototype.addEventListener;
EventTarget.prototype.addEventListener = function(type, fn, capture) {
this.f = f;
this.f(type, fn, capture);
console.trace("Added event listener on" + type);
}
Even after doing this, then commenting out all code portions that cause this console.trace to be executed (see #1) such that the console.trace is no longer printed upon open/close of the panel, I notice the same increase in listeners in the performance graph. Something else is causing the listeners to increase. I understand that there are other ways that listeners can be added, but it's not clear to me how to intercept all of those possibilities or cause them to be logged in Chrome's debugger in such a way that I can tell which code is responsible for adding them.
Edit:
- At the suggestion of cowbert in the comments, I took a look at this page:
https://developers.google.com/web/tools/chrome-devtools/console/events
I then made the following function:
function printListenerCount() {
var eles = document.getElementsByTagName("*");
var numListeners = 0;
for (idx in eles) { let listeners = getEventListeners(eles[idx]);
for(eIdx in listeners)
{
numListeners += listeners[eIdx].length;
}
console.log("ele", eles[idx], "listeners", getEventListeners(eles[idx]));
}
console.log("numListeners", numListeners)
}
I execute this function after having opened/closed the panel a bunch of times, but unfortunately the "numListeners" figure doesn't change.
If the numListeners figure changed, I would be able to diff the results before/after having open/closed the panel to discover which element
has the extra event listener registered to it, but unfortunately numListeners does not change.
There is also a monitorEvents() API described on https://developers.google.com/web/tools/chrome-devtools/console/events, but the function
call requires that you specify a DOM element that you wish to monitor. In this situation, I'm not sure which DOM element has the extra
listeners, so I'm not sure how the monitorEvents() call will really help me. I could attach it to all DOM elements, similar to how I've
written the printListenerCount function above, but I presume I'd run into a similar problem that I ran into with printListenerCount() --
for whatever reason, it's not accounting for the listener(s) in question.
Other notes:
This is a somewhat complicated reactjs (preact, technically) based application. Like most reactjs based apps, components get mounted/unmounted (inserted into and removed from the DOM) on the fly. I'm finding that this makes tracking down "stray event handler registrations" like this a bit tricky. So what I'm really hoping for is some general debugging advice about how to track down "Stray event handlers" in large/complex projects such as this. As a C programmer, I would open gdb and set a breakpoint on everything that can possibly cause the "listeners" number in the performance graph to increase. I'm not sure if there's an analog of that in the javascript world, and even if it there, I'm just not sure how to do it. Any advice would be much appreciated!
Thanks for your comments, everyone. I ended up figuring this out.
From my OP:
Does my hypothesis that listeners are getting added and never unbound seems sensible, or is there more I could be doing to confirm this suspicion?
It turns out that the answer to this question is: The hypothesis is not sensible. The listeners simply haven't had a chance to get garbage collected yet. It can take some more time than you might think.
Here's how I figured it out:
I failed to realize that while recording a performance timeline, it's possible to force a garbage collection by clicking on the trash can icon in the Performance tab (same tab used to start the timeline recording). By clicking this icon after repeated closings/openings of the UI panel, the extra listeners completely went away. The graph now looks like this, with the dips being moments where I clicked the trash icon:
Apparently, backgrounding the tab and waiting a couple of minutes like I mentioned in the OP is simply not enough time for garbage collection to occur on its own; It takes some more time than that.
I wasn't aware of the ability to manually collect garbage with the trash can icon when I wrote the OP... I strongly recommend using it before going on any wild goose chases hunting down what might at first look like a performance problem.
I am doing GUI automation of my website via Selenium (RobotFramework). The problem I am facing is:
When my automation script clicks on some element (button,link etc) which is supposed to perform some action, it dose nothing. This happening randomly. When we test is manually, it works all the time. One observation is, with slower machine/environment, this tends to happen more.
I suspect this is happening either due to some corresponding JS is not loaded yet or if there is any such thing called "action binding" with each elemetnt, has not happened.
Some question
- Is there a way to find out if all the JS calls are over?
- In case action binding happens, has it already bound or not.
Please share if you have any other solution.
do you know what is last to load on the page? This should be very easy to find out via Developer Tools in your browser of choice.
You can then easily use a Wait Until Keyword (there are many variations) to wait until that last item appears as you expect, then continue with your test. Setting the timeout length and interval will help control the overhead of time/performance.
Wait Until Element Is Visible id=finalElement 10 finalElement did not appear on the screen before timeout period
http://robotframework.org/Selenium2Library/Selenium2Library.html - please see the documentation for further examples and options in terms of keywords
I would like to debug a javascript file named somescript.js, to have an idea what it is used for and when. This file has lots of functions. Manually setting breakpoints in each function would be very tedious.
Is there a method in any browser to either:
Automatically set breakpoints at the beginning of every function in
somescript.js file, or
Tell the debugger to pause next time when it reaches any function in
somescript.js
I know there is a button "Pause on exceptions" but it results in stopping inside libraries (jquery). After pressing "Step out" many times it finally reaches a function in somescript.js - one function. I need to know what the rest of the functions are doing, but don't know when they are called.
I'm not aware of any capability to set a breakpoint at the start of every function in a module. I think what you will need to do is to study the code a bit and figure out what the main entry points are in the module or figure out which functions you most want to trace and understand and then set breakpoints in those specific functions.
One can often search for the installation of event handlers and figure out where various actions start, set breakpoints there and then step through them to learn how that particular action works.
Sometimes this is an iterative process too. As you step through some things, you learn enough about other good places to set breakpoints. Keep in mind that once you hit a breakpoint, you can also look at the call stack and see how you arrived there and perhaps set breakpoints further up the call chain for the next time you execute that function. Debugging/learning like this is a bit of an art. You find a place to start, trigger that breakpoint, learn some things that lead you to other breakpoints to set, learn some more and so on.
I am writing an application in JavaScript (with JQuery). The application has a lot of functionality that the user needs to access quickly and possibly at the same time (you could think of it as a game, even though it's not a game) so I've set it up to use the keyboard. I've got a prototype of the system working (in Chrome, at least), but there is a problem in that when I press, for example, Ctrl-T, it opens a new tab. I would like to use this as part of my application to, for example, toggle some setting. In general, I would like to disable the Ctrl-key functionality of the browser. This goes for Alt and Shift, too. In a different way, I would also like to disable the browser's usage of the Tab key. Basically, I want my application to have complete control over the keyboard while it's being used (if they want to navigate away, they will still be able to do so with the mouse). I will add the caveat that I don't care about some of the less-common keys (F1-F12, Windows/Mac-Command, Menu, anything right of the Enter key) because my application mainly targets laptops and many don't have those keys, so they won't be used.
My question is, how can I disable this browser functionality with JavaScript/JQuery/DOM?
I understand that taking over browser functionality in this way this sounds very authoritarian, but it's actually quite necessary. From the prototype and some target-audience test users (my family) everyone has agreed that this was a good idea.
I've also considered moving my application out of the browser and writing it in some application language (probably Java), but I want to find out if this kind of functionality is possible in JavaScript before making that kind of switch. This is prototyping time, though, so every idea is still up for consideration!
Basically, you return false at the right time. See this: How to create Ctrl+Key shortcuts in Javascript.
I should add and say sometimes this doesn't work - it's up to the browser to allow this.
Also, it is sometimes possible to change e.which to another key, but again, this wouldn't always work.