How to get javascript variables in a debugger when using webpack - javascript

I am developing a react application with the bundler Webpack.
I would like to debug this application with a browser console (here i use chrome).
I have used source-maps and equivalent in my webpack config:
devtool = 'inline-source-map';
Now errors are displayed with the exact line of the original file.
The problem is that i want to access to live variables with the console.
So far I found two ways to display them:
1- Add a library in webpack.config.js
output: {
library: "lib"
},
export variable in the code export var foo = 34; and finally inside the browser console use lib.foo.
2- use breakpoint and access to variable set in the file
Is there another solution to access live variables?
Thanks

There are other solutions, but that means defining global variables and that should be avoided as it can have side effects in the code you're trying to debug, so you might run into problems that are not identical with and without exposing the variables, which makes your debugging experience very frustrating.
Using breakpoints is the best you can do for debugging purposes. The browser debuggers, especially the Chrome devtools, are extremely powerful and it's absolutely worth spending some time to get familiar with them.
Because pausing the app at every breakpoint you set for getting to a certain point can be tedious, you can use conditional breakpoints. One way is to use the debugger statement in your code, in that case you can guard it by any JavaScript you like, for instance this will only pause when the input to the function is 5:
function debug(input) {
if (input === 5) {
debugger;
}
// Other code
}
Another way is to add conditional breakpoints in the Chrome devtools. As you've configure source maps, you can set the breakpoints in the original source under Sources > top > webpack:// > .
To set a conditional breakpoint you simply right-click a line and choose Add conditional breakpoint... and enter the condition, e.g. input === 5. You can also Edit breakpoint... to change or add a condition to an existing breakpoint. For more information about breakpoints in Chrome see Pause Your Code With Breakpoints.
In the Sources tab you can also right click anywhere and Add folder to workspace so you can edit the sources directly and save the changes to disk (in older versions of Chrome it's a bit more complicated to add a folder to the workspace). To let Chrome know that the source maps of webpack correspond to your workspace, you can right-click any webpack source map and select Map to File System Resource... and you simply choose the correct file of the workspace. After that, all the sources of webpack should automatically be mapped to the correct files. Now you can set the breakpoints there and when you change something and save it (Ctrl + S or Cmd + S), webpack will recompile it. See also Set Up Persistence with DevTools Workspaces.
Sometimes setting a breakpoint might be too much effort for only getting values of variables. With just console.log you probably end up with a lot of different messages. To make it easier to find the messages you need, you can use console.group which lets you put messages inside a group, that can be expanded and collapsed. The groups can also be nested. Use console.groupCollapsed if you want the group to be collapsed initially.

Related

Breakpoints in WebStorm not hitting for JavaScript debugging

I have the following configuration setup in WebStorm:
When I click debug, it launches Chrome fine and navigates to the page, but my breakpoints never get hit. It's connected somehow though because I see all of the console.log() output in WebStorm.
I'm trying to navigate to the URL specified in the screenshot and have breakpoints in main.js get hit, but it doesn't work as expected (see: at all). I'm not exactly sure what I'm missing. I've tried setting a remote URL for the specific main.js file in the Remote URLs section, but that didn't help either.
For reference I run the application via bra run and npm run watch.
Quick Update
So I've been able to actually get a breakpoint to hit, but it's in a different file (in a different path):
../public/app/core/routes/dashboard_loaders.ts allows me to stop at breakpoints, but ../public/dashboards doesn't.
When I navigate to http://localhost:3000/dashboard/script/main.js?orgId=1, it hits the route:
.when('/dashboard/:type/:slug', {
templateUrl: 'public/app/partials/dashboard.html',
controller : 'LoadDashboardCtrl',
reloadOnSearch: false,
pageClass: 'page-dashboard',
})
Which ultimately does load the file ../public/dashboards/multi.js -- but no breakpoints are hit.
Further Updates
It looks like the script is served via the following command (in ../public/app/features/dashboard/dashboardLoaderSrv.js):
/*jshint -W054 */
var script_func = new Function('ARGS','kbn','dateMath','_','moment','window','document','$','jQuery', 'services', result.data);
var script_result = script_func($routeParams, kbn, dateMath, _ , moment, window, document, $, $, services);
Where $routeParams are type:script and slug:main.js - If I step into this function, I get an anonymous(?) file that's identical to my actual main.js file, but the name is like 43550 instead of main.js -- I think this is boiling down to a fundamental lack of knowledge in how JavaScript handles something on my part. :)
Edit: I found this issue for using webstorm with grafana (second edit) looks like this is you.
I think what he linked solves it with declaring a sourceUrl then your file isn't "anonymous" or rather dynamic.
//# sourceURL=filename.js
I.E
//# sourceURL=main.js
Reference How to debug dynamically loaded JavaScript (with jQuery) in the browser's debugger itself?
Here is the documentation and video on debugging in webstorm to make sure everything is setup properly. (I.E My default setting were to debug my index file instead of my project). Make sure you have their Chrome extension or Firefox Extension
General JS Debugging in Webstorm
Debugging for Chrome in Webstorm
Debugging for Firefox in Webstorm
Debugging Node.JS in Webstorm

selenium + chrome.fileSystem.chooseEntry = invalid calling page error

I am writing a Selenium script to test a Chrome app that uses the Chrome.fileSystem.chooseEntry API to select a directory. When I do this manually, it works fine. But when I do this in a Selenium script, I get back this error:
Unchecked runtime.lastError while running fileSystem.chooseEntry: Invalid calling page. This function can't be called from a background page.
Any ideas on how to make Selenium and chooseEntry play nicely together?
I updated to the latest Chromedriver, but still no luck. I also looked at ChromeOptions, but didn't see anything that looked like it would be helpful. The interwebs doesn't seem to have much to say about Selenium and chooseEntry. I'm on version 51 of Chrome.
I'm down to thinking I'll need a special javascript entry point to set the path values for testing instead of using chooseEntry. But I would strongly prefer to not have a separate code execution path for my tests. Anybody have a cleaner solution?
EDIT: per commenter's request, here's the offending code:
chrome.fileSystem.chooseEntry({type:'openDirectory'},function(entry) {
chrome.fileSystem.getWritableEntry(entry,function(writeable_entry) {
console.log("got writeable entry");
});
}, function(e) { errorHandler(e); });
EDIT #2: I've gone with the special javascript entry point hack. In manual mode -- i.e., not running under Selenium -- I run code that executes chooseEntry, and then use the retainEntry API to get the entry id. I added an entry point in my javascript to take an entry id and call the restoreEntry API to turn it back into an entry. I also modified my code so if this entry object is set, then use that as the file instead of calling chooseEntry. Lastly, I modified my Selenium script to call the restoreEntry entry point before running the rest of the script.
This is not ideal, since now my test code execution path is somewhat different from my actual live-human-being-at-the-controls code execution path. But at least it lets me use Selenium scripts now. Of course, if anyone can think of a non-horrible way to solve this solution, I'd love to hear about it.
EDIT #3: Per #Xan's comment, corrected my terminology from "extension" to "Chrome App."
I can only offer this horrible hack. For Chrome Apps under OSX I created folder favorites and use Robot keyPress to navigate and select the 'favorite' folders needed for the App. The only possible redeeming factor is that it does mirror a valid/possible actual human interaction with the file interface.
private void selectOSXFolderFavorite(int favorite) {
// With an OSX file folder dialog open, Shift-Tab to favorites list
robot.keyPress(KeyEvent.VK_SHIFT);
robot.keyPress(KeyEvent.VK_TAB);
robot.keyRelease(KeyEvent.VK_TAB);
robot.keyRelease(KeyEvent.VK_SHIFT);
// move to the top of favorites list
int i = 40;
while (i-- > 0) {
robot.keyPress(KeyEvent.VK_UP);
robot.keyRelease(KeyEvent.VK_UP);
}
while (favorite-- > 0) {
robot.keyPress(KeyEvent.VK_DOWN);
robot.keyRelease(KeyEvent.VK_DOWN);
}
// Send an enter key to Select the selected folder
robot.keyPress(KeyEvent.VK_ENTER);
robot.keyRelease(KeyEvent.VK_ENTER);
}

How do I change the underlying Phantomjs object settings using Chutzpah?

We have some QUnit javascript tests running in Visual Studio using the Chutzpah test adapter. Everything was working fine until we changed our api (the one being tested by the js files) recently, and added some validations over the UserAgent http header. When I tried to update the tests to change/mock the user agent I realized it was not directly possible even by overriding the default browser property.
After a few days of scavenging, I finally found what exactly is happening. Chutzpah is creating a phantomjs page object for the test files to run on. This is being done on a base javascript file (chutzpahRunner.js) located at the Chutzpah adapter installation path. These are the last lines on the file, that effectively start the tests:
...
// Allows local files to make ajax calls to remote urls
page.settings.localToRemoteUrlAccessEnabled = true; //(default false)
// Stops all security (for example you can access content in other domain IFrames)
page.settings.webSecurityEnabled = false; //(default true)
page.open(testFile, pageOpenHandler);
...
Phatomjs supports changing the user agent header by specifying it in the page settings object. If I edit this chutzpahRunner.js file in my machine, and manually set the user agent there, like this:
page.settings.userAgent = "MyCustomUserAgent";
My tests start to work again. The problem is that this is not in the project itself, and thus cannot be shared with the rest of the team.
Is it possible to change the properties of the phantomjs objects created by Chutzpah to run the tests? I'd like to either change them from inside my own tests, or from another script file I could embed on the pipeline.
Without a code change in Chutzpah it is not possible to set those properties on the PhantomJS object. Please file an issue at https://github.com/mmanela/chutzpah asking for this functionality and then fork/patch Chutzpah to add it (or wait for a developer on the project to hopefully get to this).
Update:
I pushed a fix for this issue. Once this is released you can use the following in a Chutzpah.json file:
{
"userAgent": "myUserAgent"
}

Out of range error in firebug console

I am trying to debug ext-all-debug-w-comments.js file. The file is pretty big and when the error occurs, it says "TypeError: all.item(...) is null (151559 out of range 149122)"
Basically the error occurs at line number 151559 but only 149122 files are shown in firebug. Since all the lines are not loaded I cannot debug in firebug.
Please see below image for more information
What should option I have here?
Thank you
Is there a browser specific issue involved?
If not, you could use Chrome, it can handle bigger scripts compared to Firefox.
Use ext-dev.js instead. The ext-all- files are compiled versions with all classes available in Ext JS; ext-dev.js will load every class you use in a separate file. Slows down the app loading considerably so it's only suitable for debugging, but it also makes Ext JS a lot easier to debug.
In order to use ext-dev.js you'll need to set the paths to Ext JS and your custom classes using Ext.Loader.setPath, before the first classes are required -- at the top of your app.js would probably be the best place.
Another (better) way to manage dependencies is to use Sencha Cmd.

Meteor cannot read property 'click' of undefined

I'm having an issue where in production only (not development) I get hundreds of cannot read property 'click' of undefined with 3-30 on each click, and a few cannot read property 'submit' of undefined. This very well may not be an issue with Meteor but with my code, so I'm just looking for any ideas why this may be happening or how I can debug it. All my events are either in Template.events or Template.rendered. It happens on every page and no matter where I click.
There are a couple of things that can cause this.
The first is that in production mode latency is a lot higher. So if you've automatically assumed that when a template is rendered the data is ready you could get all sorts of undefined as the object's are null for a very short time when meteor initally loads.
You could check your code to see if you've used any findOne or find. You need to ensure that the result of your query is properly handled in the case that there aren't any results, for that initial load. i.e
var data = myCollection.findOne(...);
if(data) {
....
}
or
var data = myCollection.find(...);
if(data.count()>0) {
....
}
The other thing that might cause it are atmosphere packages that you're using that might not be mapped correctly.
To check this have a look at your network tab in the chrome inspector:
Look through for files whos extensions don't match their content (js & css files).
If a file is a .js file it might have HTML content (Meteor doesn't serve up 404 errors, instead giving them html whichever path is called, so no explicit errors are given).
If this is the case figure out which file it is and map it correctly. (You might be calling click to a plugin that didn't load correctly). In production mode files are minified and the package paths change so this might also be it.

Categories