Replace Javascript on-the-fly - javascript

this questions pops up again and again across the internet (even on SO), but I haven't found a satisfying solution to this problem:
How can we change/replace Javascript code in a running web application, without reloading the page?
Many people answer this with "you cannot, because it is impossible". Some experiments with IntelliJ IDEAs live edit plugin proves me that it is possible. But I don't want to be bound to an IDE for this feature. (Bonus: browser independent)
Here is what I tried:
add //# sourceURL=whatever.js to my dynamically loaded script
add folder to Chrome containing whatever.js
mapping the local whatever.js to the network whatever.js
changing code in either does not affect the web-page at all. In fact editing the network-side file results in a oddish "flashing" of the dev tools.
Please understand that I do not expect the changed JS to magically apply to the webpage once I change it, but I expect it to use the new code when the execution point is passed again.
Example:
Given a button that triggers 'alert(1);'
Change to 'alert(2);'
I expect the button to trigger 'alert(2);'
Having many dependencies and a huge script that is triggered pretty late in a workflow it is really a big problem for me to refresh the page, so I need to find a solution that works on-the-fly.

First of all: What you ask for is really tricky and you can find security problems if you allow this in your applications, anyway it is not impossible.
BUT if you want to achieve your example follow this steps:
Make a code snippet like this:
var message = "1"; // this must be a global variable!!!!
function showMessage() {
alert(message);
}
Given a button that triggers 'alert(1);'
Make button call a function ie: onclick='showMessage()'
Change to 'alert(2);'
I expect the button to trigger 'alert(2);'
Now it's easy, When you detect the event that implies to change the alert message to 2 you just need to change message value:
message = "2";
That's all.

Option 1: Livereload
I would say as long it's for develop reasons you can use livereload on your server.
Depends of your server type. I'm note big expert in apach, glassfish and other java's world stuff, but in world of JS (nodejs) this is a shorter way.
(link for npm-livereload)
Hack: You can handle static-files such as js, css with simple node.js server with built-in livereload.
Option 2: jRebel
I'm not sure about js but perhaps JRebel can handle this issue. Anyway it's a good addition to the develop process - at least it would make a java's "hot reload: for you.
Option 3: Monkey-patching
You can use monkey-patching techniques: Each function in js it's just a string, you can turn string -> function with new Function().
just like:
var foo = {
sum: function (a, b) {return a+b;}
}
//...
obj.sum = new Function(....) //Now you're replaced the original code
check this article about graceful way to do monkey-patching.
And small advertising of my lib for monkey-patching: monkey-punch
Option 4: Attach new tag
You can attach js files with:
var s = document.createElement("script");
s.type = "text/javascript";
s.src = "http://somedomain.com/somescript";
$("head").append(s);
You're also able to remove dom elements (scripts, styles) and attach new at anytime.

Related

Is it possible to make and run changes in javascript files using chrome developer tools or firebug without refreshing?

I am working an issue and problem is code is huge and deployed on some remote location and takes a lot of time to go through this process. Now, I know that in chrome developer tools we can open javascript files and modify/save them but problem is, changes are not reflected in application. for example, hello.js has something like this,
sayHello : function() {
// some existing code here.
}
now, developer tools allows to modify this file to look like,
sayHello : function() {
// some existing code here.
// additional code added at runtime.
}
but problem I am facing is, this additional code is not reflected when I execute
sayHello()
function again.
Note: I am not trying to load any new script here.
It's hard to say without some more input on your action, but could be that you are changing the source code (in the browser cache) and you expect the object already in memory to change as well? In case put a break point before the object is instantiated and change the code at that moment and see what happens.

Duplicate an HTML file (and its content) with a different name in Javascript

I have an HTML file with some Javascript and css applied on.
I would like to duplicate that file, make like file1.html, file2.html, file3.html,...
All of that using Javascript, Jquery or something like that !
The idea is to create a different page (from that kind of template) that will be printed afterwards with different data in it (from a XML file).
I hope it is possible !
Feel free to ask more precision if you want !
Thank you all by advance
Note: I do not want to copy the content only but the entire file.
Edit: I Know I should use server-side language, I just don't have the option ):
There are a couple ways you could go about implementing something similar to what you are describing. Which implementation you should use would depend on exactly what your goals are.
First of all, I would recommend some sort of template system such as VueJS, AngularJS or React. However, given that you say you don't have the option of using a server side language, I suspect you won't have the option to implement one of these systems.
My next suggestion, would be to build your own 'templating system'. A simple implementation that may suit your needs could be something mirroring the following:
In your primary file (root file) which you want to route or copy the other files through to, you could use JS to include the correct HTML files. For example, you could have JS conditionally load a file depending on certain circumstances by putting something like the following after a conditional statement:
Note that while doing this could optimize your server's data usage (as it would only serve required files and not everything all the time), it would also probably increase loading times. Your site would need to wait for the additional HTTP request to come through and for whatever requested content to load & render on the client. While this sounds very slow it has the potential of not being that bad if you don't have too many discrete requests, and none of your code is unusually large or computationally expensive.
If using vanilla JS, the following snippet will illustrate the above:
In a script that comes loaded with your routing file:
function read(text) {
var xhr=new XMLHttpRequest;
xhr.open('GET',text);
xhr.onload=show;
xhr.send();
}
function show() {
var text = this.response;
document.body.innerHTML = text;//you can replace document.body with whatever element you want to wrap your imported HTML
}
read(path/to/file/on/server);
Note a couple of things about the above code. If you are testing on your computer (ie opening your html file on a browser, with a path like file://__) without a local server, you will get some sort of cross origin request error when trying to make an XML request. To bypass this error, either test your code on an actual server (not ideal constantly pushing code, I know) or, preferably, set up a local testing server. If this is something you would want to explore, its not that difficult to do, let me know and I'd be happy to walk you through the process.
Alternately, you could implement the above loading system with jQuery and the .load() function. http://api.jquery.com/load/
If none of the above solutions work for you, let me know more specifically what it is that you need, and I'll be happy to give a more useful/ relevant answer!

Calling an overridden and frozen function

I'm building a security framework which injects a javascript file which will always be executed first, and blocks some functions to be executed.
The developers will make their own webapps and the script will make sure that some functionalities cannot be called.
Let's suppose the "blocking" script is like this:
window.alert = function(){Object.freeze(this)}
Is there any way for an application to circumvent this block, without using iframes/external files?
delete(window.alert) doesn't work in this scenario.
not if you can't stop that script running first, otherwise you could asign the original alert to something else:
var oldAlert = window.alert;
window.alert = function(){Object.freeze(this)}
How/why are you using alert? if its for debugging you'd be better off using console.log. if you are using it to notify users then maybe a dedicated modal would be the better option
Based on your updated question, it depends how your framework is loaded.
Lets say you provide the script to the developer to use, in that case they could very easily alter what your script does. if the code is running on in a env that isn't yours then you can assume it's not secure. browser plugins can block scripts, there would bypass any security based in a javascript file.
based on the work of #Abdennour TOUMI on this post : Opposite of Object.freeze or Object.seal in JavaScript, you can do something like that :
window.alert = function(){Object.freeze(this)} ;
Object.unfreezeAlert=function(){
return window.prompt;
}
window.alert = Object.unfreezeAlert(window.alert);
alert ('test4');
http://jsfiddle.net/scraaappy/pxv51zqg/
You need to set the alert property on Window.prototype, not on window. Otherwise:
Window.prototype.alert.call(window, 'This works.');

How can I execute code that a user inputs into my ACE editor on my page

I am using ACE Editor as my text editor on my page and the user will type in it code.
I am looking to execute code that has been entered by the user on or in the browser if possible. How do I get the input from the editor and utilize the Browsers V8 JavaScript compiler with it?
I am then going to try to run it on a Node.js but first I have to learn Node :).
It's relatively simple to grab some user entered code and run it, with JavaScript. Essentially, you'll grab the code from ACE:
var code = editor.getValue();
Then use javascript to run it. At the simplest level you can just do:
eval(code);
However, you probably don't want to use eval(). Instead you might do something like:
// grabbed from https://stackoverflow.com/questions/6432984/adding-script-element-to-the-dom-and-have-the-javascript-run
var script = document.createElement('script');
try {
script.appendChild(document.createTextNode(code));
document.body.appendChild(script);
} catch (e) {
script.text = code;
document.body.appendChild(script);
}
This will work. However, it will still cause some problems, as then, the user code could affect your environment. In this scenario, it may not be terrible from a security perspective (unless the user can share their code), but it would be confusing. For that reason, you'll want to sandbox your code.
This answer explains sandboxing client side javascript, using window.postMessage, you could send javascript to the sandboxed iframe and have it be evaluated there.
If you wish to bring this server-side and execute Node code, you'll need to do sandboxing differently. On a server, sandboxing is much more of a concern, as the user gets to do a lot more with Javascript and could maliciously interact with your server. Luckily, there are a few sandboxes for Node that should help.
Getting code is the easy part just do code = editor.getValue()
Simply utilizing V8 compiler is easy too, create iframe and do
try {
var result = iframeWindow.eval(code)
} catch(e) {
// report error...
}
but this won't be very useful since it will be very easy to create infinite loops and break the page.
You can have a look at https://github.com/jsbin/jsbin/blob/master/public/js/runner/loop-protect.js#L7 to resolve loop problem.

Validating JavaScript

I load lot of JavaScript From My DB for validation and for Costume Validation which can be Uploaded through My Customer so i want to validate whether the given Javscript is valid or Not While Rendering it on my page i am using MVC 3.0 razer view engine
Please help me finding a way fix it
Thanks
Ashies
Your task is simply not recommended. Render JavaScript code directly from the database is dangerous because you are leaving the doors wide open to XSS attacks.
However, yes, you can validate JSCode normally with JSLint.
There is a plugin for visual studio, and of course there might be a way to use the functionality packed in the JSLint DLL so you can check your JavaScript.
This two posts might put you in the "right" direction. (I still have to say that rendering user entered JS code is fundamentally wrong)
http://www.codeproject.com/Articles/21438/JSLint-VS-JavaScript-Verifier-for-Visual-Studio
http://blog.outsharked.com/2011/08/sharplinter-command-line-tool-for.html
I assume that you are working with Visual Studio 2010/2012.
As Adrian Salazar said:
Your task is simply not recommended. Render JavaScript code directly from the database is dangerous because you are leaving the doors wide open to XSS attacks.
That being said I would highly recommend rethinking your current design. If you're planning on doing so, you should have a look at Web Essentials which is a plugin available from NuGet. This has JSHint integrated which will check your Javascript after saving a file or on building your application within Visual Studio.
Also downloadable as installer:
http://visualstudiogallery.msdn.microsoft.com/6ed4c78f-a23e-49ad-b5fd-369af0c2107f
or for 2012:
http://visualstudiogallery.msdn.microsoft.com/07d54d12-7133-4e15-becb-6f451ea3bea6
Javascript syntax checking is tricky because there is so much scope for generating silent run-time errors based on how primitive are handled (for example).
There are verifiers like JSLint available and you can build your own techniques for verification.
I use the following structure for javasript files (using jquery) setting a class ("scriptVerified") on the body tag if the script completely runs - which can quickly tell you if the script looks syntactically OK. But event handlers can still go wrong when the event is fired.
#AdiranSalazar's security warning is worth listening to.
$(document).ready(function () {
pageScript.Init();
});
var pageScript =
{
Init: function()
{
pageScript.CleanUp();
pageScript.RegisterHandlers();
pageScript.Start();
pageScript.Final();
},
CleanUp: function()
{
//put page cleanup stuff in here
},
RegisterHandlers: function()
{
//register event handlers in here
},
Start: function()
{
//put page js code in here
},
Final: function () {
$("body").addClass("scriptVerified"); //add class to body to say this has run
}
};

Categories

Resources