The usual way of adding Javascript to a page is by adding it to the document's <body> or <head> in either static HTML or something generated server-side.
I would like to generate dynamic Javascript, and add it to the document in a dynamic fashion; that is on-demand and during run-time. For example Javascript code transmitted over a WebSocket.
One option is to create a script element, add the string with script contents to the .text property, while finally adding the script to the document, like this:
var scriptContent = 'console.log("dynamic script");';
var s = document.createElement('script');
s.text = scriptContent;
document.body.appendChild(s);
This would work, but my concern is that the script is executed with the same URL/origin as the HTML document. Whereas, if it would be a separate file, invoked with the s.src parameter, it would show up under its own URL when looking at the browser console.
Why is this at all relevant? When using the browser console to debug and inspect, it usually tells you the name of the script and the line/column of the message printed to the console. For example, when opening the console, one might several console messages, with on the right side the origin and line/column information:
<domainname>:1:1
separate_js_file.js:14:20
This is the behavior that I desire because it makes it easy to distinguish what script has written something to the console. However, if adding Javascript dynamically to the page, it all gets 'advertised' under the main document, usually printed by the domainname, like domain.com:1:1.
What I would like is to change/pretend/masquerade the origin of the script, to pretend it was an external script. This way, not all lines printed to the console would be from origin domain.com:<line>:<column> but instead would be called specifically, like module1:<line>:<column>.
Is this at all possible?
I think you can append a source map at the end of the dynamic JS.
//# sourceURL=http://example.com/path/to/your/sourcemap.map
This works when using eval statements in Firefox and in with both injected script tags and evals in chrome. Might be a way to make Firefox understand it via script tags as well.
See https://developer.mozilla.org/en-US/docs/Tools/Debugger/How_to/Use_a_source_map for the details.
See also Can't see dynamically loaded code in Chrome Developer Tools 22 for some more details.
Related
Could the leiningen plug-in figwheel or boot's counterpart be used within arbitrary webpages? I'm thinking of it as an replacement of the browser's builtin developer console.
Here is a simple scenario of how I'd imagine this workflow:
You open an arbitrary website in the browser. Beside that, you have a browser repl inside a terminal window, which is provided by one of the tools mentioned above. (I guess they both use 'weasel' for this.)
Inside the terminal one could access the current state of the weppages' DOM.
E.g: (set! (.. js/window style backgroundColor) "green"))
I guess this should not be too problematic to archive. However, I faced the following problems:
Both tools do actually just inject a bunch of JavaScript into the users's HTML page. It's basically: The users's ClojureScript compiled to JavaScript plus additional implementation of the hot-reloading mechanism via websockets. The second is just omitted when the project comes into production.
My idea was to just inject the whole bundle to another page.
I used boot for the try.
After setting up the boot's ClojureScript REPL, I opened localhost:port in a browser. It's inital source looks like this:
<!doctype html>
<html>
<head>
<title>Hello, World!</title>
</head>
<body>
<script src="js/main.js"></script>
</body>
</html>
The after main.js has been executed on page-load, many (more than 100) further javaScript tags are injected to the page. My initial idea was to just open another page now, say duckduckgo.com, and inject that one script tag to it, augmented with an absolute path to localhost.
so, at the duckduckgo.com page, inside the developer console I did this:
tag = document.createElement("script");
tag.src = "http://localhost:3000/js/main.js";
document.body.appendChild(tag);
As expected the script gets injected, and this always leads to the immediate execution of its code. I was expecting that all the other script tags get injected now automatically. Finally the webSockets should be connected to the ClojureScript repl.
However, there's the following error in the browser console: A call to document.write() from an asynchronously-loaded external script was ignored.
Indeed, many of the further script tags have been injected. But not all of them. Effectively, the socket connection is not established.
So, it looks like some script tags are injected by the mechanism I used myself (via appendChild), others should be done by document.write("<script... The later causes the problem here.
Does anybody know a way to archive this?
Following problem:
I've given a file with HTML inside but also maybe some script code.
Now I want to edit the file so that no script gets executed when opening the file with a browser.
My question is: What do I have to do?
Which possibilities are there to place a script inside HTML to let it get executed? I know there is the script tag, you could also do it with an iframe but what else is possible?
I definitely want to prevent any kind of script execution. How can I achieve this?
Have a look at an established, well tested HTML filter library such as http://htmlpurifier.org/ which uses a whitelist to filter possibly malicious code. Don't rely on the filtered HTML documents being secure from any javascript though, time and time again browsers are updated and new ways to sneak in javascript are discovered.
I have already written a Hello World example extension. Now I am trying to write a Chrome extension to get a certain JavaScript variable's value, if it is declared.
So let's say there is a
var test = 'a';
in the source code. I would like to get that a value.
UPDATE: I do not have access to the "original" website's code, but I know that this variable is always there, and has a certain value, always different.
An alert would do. (Can I alert, from the extension's page?)
I saw that there are things like "permission" and "tabs" and I am not sure what might I be missing.
I tried to search, found something similar, but this example just doesn't do anything when I click on the link.
From a content script, you can't have access to a variable declared on the page.
Taken from the documentation:
Content scripts execute in a special environment called an isolated world. They have access to the DOM of the page they are injected into, but not to any JavaScript variables or functions created by the page.
The only way I see is to load the script source via XHR in the background page and parse it. Then you may use message passing if you want to send the result to your content script. Note that this solution won't work if the value of the variable has been changed by a subsequent script.
If you have control over that page you could put that value into a hidden HTML element on the page which your extension can then extract with a content script.
on the website:
var test a = 'a';
document.documentElement.dataset["a"] = a;
in the extension's content script:
var a = document.documentElement.dataset["a"];
Just make sure that the content script is executed after the script on the page (e.g. by adding "run_at": "document_end"in your manifest)
I* am using client-side JS to parse XML files and generate complex JS code to eval as a result. (Generating re-usable functions that are kicked off by a runtime.) However, I need to debug the code being generated, and would like to use Chrome's built-in breakpoints, stepping, watch windows, etc.
Is there an easier way to do this than:
Dump the generated JS string to the console and/or window.
Copy the JavaScript
(optional) Run the JS through a prettifier like JSBeautifier.
Paste the JS into a file that is loaded via <script src="..."> in another web page.
* actually, a friend of mine was doing this, not me
Instead of using eval, and instead of manually copy/pasting into a separate file, you can dynamically load the JS directly into the page that generated it by using a data uri on a dynamically-created <script> element. With this approach, Chrome's Developer Tools (and Firebug) allow you to pick the data-URI as a script, turn on the Pretty Print, set breakpoints, and away you go.
var js = createMyJSCodeString();
addCode(js); // Right now! Debuggable!
// Dynamically evaluate JavaScript-as-string in the browser
function addCode(js){
var e = document.createElement('script');
e.type = 'text/javascript';
e.src = 'data:text/javascript;charset=utf-8,'+escape(js);
document.body.appendChild(e);
}
Here I have asked a question pertaining to exceptions raised when dynamically loading scripts via XMLHttpRequest (in other words when executed via eval)
In a related question, I wanted to know whether loading scripts dynamically as such is considered bad practice to begin with. In my particular case I have an HTML Canvas element, and rather than load all possible shapes, I want to fetch them dynamically, without reloading the page, and execute them on return. The problem I am having there is that if the code associated with that shape is incorrect, the error message displayed is not very useful (indicates location of eval statement, not incorrect statement). Is there another way to dynamically fetch code from the server and execute it, while better informing the location of the exception when it occurs.
If you want to load a script use a <script> element. If you want to dynamically load a script, create the <script> element dynamically.
var script = document.createElement('SCRIPT');
script.src = "<url to load>";
document.getElementsByTagName("HEAD")[0].appendChild(script);
It's not guaranteed to be synchronous the way eval with synchronous XHR is, but ideally you'd structure your code to take advantage of asynchony.
Adding to Mike's answer, if you want good debugger support including a script tag is probably the way to go, since that is what debuggers are used to working on. The main differences from eval that you need to be aware of are:
Eval runs in the scope of where its called while included script tags run in the global scope.
Eval is synchronous while included tags run asynchronously. (You will need to use something like JSONP and dojo.io.script if you need to run code after the script tag finishes).
If the scripts are fixed you can also consider debugging them by including their script tags and deploying them as you see fit.