I'm having a JavaScript debugging question. I would like to know, how it would be possible to find out in which file/line a new script is loaded and called. My website has several scripts which are appended via document.write(), and I would like to find a way to find the function call in all attached scripts of the website.
I would prefer either Firebug or Chrome Dev tools.
Thanks!
Neither Firebug nor the Firefox or the Chrome DevTools currently allow to debug code inserted via document.write(). I created bug 1122222 for the Firefox DevTools and issue 449269 for the Chrome DevTools requesting to be able to debug such scripts. As upcoming Firebug versions will be based on the Firefox DevTools, it will offer this feature once the Firefox bug is fixed, so there's no need to create a separate issue for it.
Until the above bugs are fixed you need to use another method to inject your script in order to be able to debug it within the browser.
Method 1: using eval()
You can use the eval() function to evaluate arbitrary code dynamically. Note that the eval() only evaluates JavaScript code, it must not be surrounded by any HTML.
Example:
eval("console.log('Hi!')");
Method 2: injecting a <script> tag
You can add a <script> tag to the page and then add contents to it.
Example:
var script = document.createElement("script");
script.textContent = "console.log('Hi!');";
document.body.appendChild(script);
Method 3: using new Function()
You can create a new function via the Function constructor.
Example:
(new Function("console.log('Hi!');"))();
Note that JavaScript won't be executed using innerHTML or insertAdjacentHTML() due to security reasons.
Related
I have developed a JS library that renders layouts (similar to layout rendering as in Razor View Engine in ASP.Net MVC). In order to display the final result, I replace the whole document by calling the document.write(...) function. For example:
document.open()
document.write(renderedLayout)
document.close()
I'm using this methods because I need all scripts whether defined by the developer or acquired from an external resource to be run and evaluated right after the content is replaced. That said, replacing the inner HTML of the html node will fail.
The methods I described works in Opera, Chrome, and Firefox but when I try to test it under IE and Edge, it fails and the browser does not showing anything once the write method is called.
My test shows that, all console outputs are received just before write is called and after that everything disappears.
Even though some may suggest that it could be a security measure in IE or Edge which might be solved by changing their configs, I would like to know how I can solve it using pure JavaScript so that my solution could be used in all major browsers.
I have traced and tested my code carefully, and I'm 100% sure the block of code I attached in the question is causing the blocking.
document.write writes to the document stream, calling document.write on a closed (loaded) document automatically calls document.open, which will clear the document.
removing document.open() and document.close() might help.
Next time when you are confused if your function written works on browser,
Open console(use ctrl+i or F12) - In Console place your Javascript code.
Here is the reference for you : https://developer.mozilla.org/en-US/docs/Web/API/Document/write
I am making Google Chrome Extension which gets the text from ACE Editor. But as soon as I create ACE object, formatting is lost and I am not able to get the Java code with indentation. The result also contains many unwanted characters.
I have used following code.
var editor = ace.edit('editor');
var code = editor.getValue();
Before my code is executed
After my code is executed
But when I run same code from developer console, it works fine.
Please suggest what is wrong or any other way to get full code with formatting using DOM element?
This happens because code in chrome extension doesn't have access to the code running in the page.
When you call ace.edit on existing editor env property of the element and creates a new editor instead.
As a workaround you can create a content script which will run in the page context, and communicate with the rest of extensions using events or postMessage. See https://stackoverflow.com/a/13292994/1743328 for more details
I'm doing quite a bit of work in the developer tools, and like to use jQuery in the console to run code snippets. To inject jQuery into the page (and the console), I'm pasting this into the devtools console:
var j = document.createElement('script'); j.src = "//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"; document.getElementsByTagName('head')[0].appendChild(j);
Is there a way to inject jQuery automatically into the developer tools console? Ideally, without affecting window.$ or window.jQuery for the current page.
The Developer Toolbar has an inject command that will allow you to inject a script into the current page a bit more easily. It supports commonly used libraries like jQuery and underscore. For more, see the docs I linked to.
If you wanted to always do this, you could create an add-on similar to dotjs - the main difference is that you would need to expose the jQuery object into the page's actual DOM, a content script isn't good enough. You should probably also always try to detect an existing jQuery? I'm not quite sure what you mean by 'without affecting window.$ or window.jQuery for the current page' - the current scope of the console by default is the current page. This is only different if you are debugging and are stopped at a breakpoint inside some other scope.
You can copy/paste the below code into the console and jQuery will be available to you in DevTools
var jq = document.createElement('script');
jq.src = "https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js";
document.getElementsByTagName('head')[0].appendChild(jq);
// ... You might need to also run
jQuery.noConflict();
You might immediately see an error: Uncaught ReferenceError: jQuery is not defined. Ignore it - DevTools is pulling your leg. (Google's weak attempt at humor, maybe...)
Then, in DevTools console, test it:
$('div').length; //press Enter
If you get an error, try it this way:
jQuery('div').length
Hopefully, the first will work - but sometimes you'll need to use the second method.
I am creating a Firefox extension, and one feature of it that I would like is the ability for the user to inject a script or stylesheet into a specific website, rather like Greasemonkey (except that this will only be for one site). I am adding some functions for the scripts to make use of, which I intended to add from the Content Script into the main (unsafe) window. On the MDN blog, it says that they have made changes to how it should be implemented, so I have based my code on the new implementation as advised in the post, so this is what I have:
var $jq = jQuery.noConflict();//Yes, I am also injecting jQuery at the same time
console.log("created jquery object"); //This works
exportFunction($jq, unsafeWindow, {defineAs: "$jq"});
console.log("This will never be called");
But execution of the script just stops, and in the console it prints Message: TypeError: window is null.
I am testing in Firefox 28 predominantly (I can't seem to get Firefox for Ubuntu to update beyond that right now, and a whole load of issues are forcing me to use Ubuntu in a VM for this), but in Nightly 31a1 (Win7) nothing is ever injected, including a hardcoded style (that works on FF28) so I will have to figure that out at some point. (The PageMod code is here:
var lttWorker = sdk.pageMod.PageMod({
include:["*"],
/*contentScriptFile: [sdk.data.url("jquery.large.js"), sdk.data.url("scripts/bootstrapper.js")],
contentScriptWhen: "ready",*/ //This is commented to test whether it was an issue with the script. It's not.
contentStyle: "#header_bar{background-color:green;}", //This is injected in FF28 but not 31
attachTo: ["existing", "top"],
onAttach: function(){desktopNotifications({title:"attached content worker", text:"The content worker has been successfully attached"})} //This is called in FF28 but not 31
});
lttWorker.on("error", function(){callError("pageWorker failed");}); //This never gets called. Ever.
if anybody is interested)
EDIT: I have now tried it on Firefox 30b and there are still a load of issues, although they seem to be slightly different to both FF28 and 31...
First of all: These new functions are supported in Firefox 30 and later. See #canuckistani answer.
The exportFunction API is way too limited to actually inject something like jQuery with all the complex objects being or containing DOM nodes. That simply won't fly with the structured-clone algorithm that is applied to arguments.
The API is meant as a way for add-ons to communicate with pages bi-directionally, and not to inject complex libraries.
Your best bet is actually creating a script tag using the DOM APIs and putting jQuery there.
I have an ASP.NET MVC project that uses some simple AJAX functionality through jQuery's $.get method like so:
$.get(myUrl, null, function(result) {
$('#myselector').html(result);
});
The amount of content is relatively low here -- usually a single div with a short blurb of text. Sometimes, however, I am also injecting some javascript into the page. At some point when I dynamically include script into content that was itself dynamically added to the page, the script still runs, but it ceases to be available to the debugger. In VS2008, any breakpoints are ignored, and when I use the "debugger" statement, I get a messagebox saying that "no source code is available at this location." This fails both for the VS2008 debugger and the Firebug debugger in Firefox. I have tried both including the script inline in my dynamic content and also referencing a separate js file from this dynamic content -- both ways seemed to result in script that's unavailable to the debugger.
So, my question is twofold:
Is there any way to help the debugger recognize the existence of this script?
If not, what's the best way to include scripts that are used infrequently and in dynamically generated content in a way that is accessible to the debuggers?
I can not comment yet, but I can maybe help answer. As qwerty said, firefox console can be the way to go. I'd recommend going full bar and getting firebug. It hasn't ever missed code in my 3 years using it.
You could also change the way the injected javascript is added and see if that effects the debugger you're using. (I take it you're using Microsoft's IDE?).
In any case, I find the best way to inject javascript for IE is to put it as an appendChild in the head. In the case that isn't viable, the eval function (I hate using it as much as you do) can be used. Here is my AJAX IE fixer code I use. I use it for safari too since it has similar behavior. If you need that too just change the browser condition check (document.all for IE, Safari is navigator.userAgent.toLowerCase() == 'safari';).
function execajaxscripts(obj){
if(document.all){
var scripts = obj.getElementsByTagName('script');
for(var i=0; i<scripts.length; i++){
eval(scripts[i].innerHTML);
}
}
}
I've never used jquery, I preferred prototype then dojo but... I take it that it would look something like this:
$.get(myUrl, null, function(result) {
$('#myselector').html(result);
execajaxscripts(result);
});
The one problem is, eval debug errors may not be caught since it creates another instance of the interpreter. But it is worth trying.. and otherwise. Use a different debugger :D
This might be a long shot, but I don't have access to IE right now to test.
Try naming the anonymous function, e.g.:
$.get(myUrl, null, function anon_temp1(result) {
$('#myselector').html(result);
});
I'm surprised firebug is not catching the 'debugger' statement. I've never had any problems no matter how complicated the JS including method was
If this is javascript embedded within dynmically generated HTML, I can see where that might be a problem since the debugger would not see it in the initial load. I am surprised that you could put it into a seperate .js file and the debugger still failed to see the function.
It seems you could define a function in a seperate static file, nominally "get_and_show" (or whatever, possibly nested in a namespace of sorts) with a parameter of myUrl, and then call the function from the HTML. Why won't that trip the breakpoint (did you try something like this -- the question is unclear as to whether the reference to the .js in the dynamic HTML was just a func call, or the actual script/load reference as well)? Be sure to first load the external script file from a "hard coded" reference in the HTML file? (view source on roboprogs.com/index.html -- loads .js files, then runs a text insertion func)
We use firebug for debug javascript, profile requests, throw logs, etc.
You can download from http://getfirebug.com/
If firebug don't show your javascript source, post some url to test your example case.
I hope I've been of any help!
If you add // # sourceURL=foo.js to the end of the script that you're injecting then it should show up in the list of scripts in firebug and webkit inspector.
jQuery could be patched to do this automatically, but the ticket was rejected.
Here's a related question: Is possible to debug dynamic loading JavaScript by some debugger like WebKit, FireBug or IE8 Developer Tool?