How can I debug evaled JavaScript within AngularJS? - javascript

I have some arbitrary javascript code that is run via the following method:
download it onto client browser via ajax call
pass resulting code string into javascript eval function.
Note: I cannot download/run the code by adding its file URL to a <script>'s src property because the code must run within a particular scope.
I would like to debug this code in Google Chrome. I am able to do this using plain Javascript, but not when I am using AngularJS. How can I fix this?
Example 1 (plain JS, I am given option to inspect code.js):
var codeToRun = ""
+"var a = 1;\n"
+"var b = 2;\n"
+"This line will fail\n"
+"//# sourceURL=code.js";
eval(codeToRun);
result: http://i.imgur.com/3LL9xi7.png
demo: https://jsfiddle.net/AlexLeung/mpjrwmbm/
Example 2 (AngularJS, I am not given option to inspect code.js):
var codeToRun = ""
+"var a = 1;\n"
+"var b = 2;\n"
+"This line will fail\n"
+"//# sourceURL=code.js";
angular.module("myApp", [])
.controller("myController", function($scope) {
eval(codeToRun);
});
result: http://i.imgur.com/x7lZcUf.png
demo: http://jsfiddle.net/oeoaep0o/

Use a named function rather than an anonymous function. For example:
var codeToRun = "var a = 1; console.log(a) //# sourceURL=foo.js";
function evaler()
{
eval(codeToRun);
}
angular.module("foo", []).run(evaler);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="foo"></div>
References
Named versus Anonymous Functions: Angular Style Guide
sourceURL and displayName in action: Eval and anonymous functions

Related

Lightswitch HTML global JS file to pass variable

I know how this works in C#, however not so much in javascript so I am hoping it is similar.
With Javascript can I create say a master.js, with a variable (var defaultValue = "1234"), which I can reference in all other javascript files associated with the project?
so in terms of Lightswitch HTML, each screen has the ability to have a js file, and on the screen I want to be able to retrieve this defaultValue.
Can this be done?
If yes, how can I get this value onto the current screen?
so far I have created a main.js file, added this function:
function getDefaultValue(value) {
var value = "1234";
return value;
}
and declared the js file in the default.htm file:
<script type="text/javascript" src="Scripts/main.js"></script>
I know this is how i am using other JavaScript files like blob.js, lsWires.js etc...
using this method in by screen.js doesn't work so one of these stages is causing an error...
window.alert(main.getDefaultValue(value));
ideally i would like to use this defaultvalue for setting a value, i.e. var test = main.getDefaultValue(value)
This is certainly possible, and the script declaration you've used in your default.htm appears correct.
However, as the approach you've described creates a global getDefaultValue function (added to the global window object context) you wouldn't specify a main 'namespace' prefix like you would in c#.
Instead, rather than calling the function using main.getDefaultValue, you'd use the the following approach within your LightSwitch screens:
myapp.BrowseProducts.created = function (screen) {
window.alert(window.getDefaultValue("123")); // This will display 1234
// As window is a global object, its window prefix can be omitted e.g.
alert(getDefaultValue("123")); // This will display 1234
};
Or, if you want to define a global defaultValue variable in your main.js (probably the approach you're looking to implement) you would have the following code in your main.js file:
var defaultValue = "5678";
Then you'd access it as follows in your LightSwitch screens:
myapp.BrowseProducts.created = function (screen) {
alert(defaultValue); // This will display 5678
defaultValue = "Hello World";
alert(defaultValue); // This will now display Hello World
};
Also, if you'd like to organise your functions/properties in a main 'namespace', you could use the following type of approach in your main.js file: -
var main = (function (ns) {
ns.getDefaultValue = function (value) {
var value = "1234";
return value;
};
ns.defaultValue = "5678";
return ns;
})(main || {});
These would then be called as follows in your LightSwitch screens: -
myapp.BrowseProducts.created = function (screen) {
alert(main.getDefaultValue("123")); // This will display 1234
alert(main.defaultValue); // This will display 5678
main.defaultValue = "Hello World";
alert(main.defaultValue); // This will now display Hello World
};
This type of approach is covered in the following posts: -
How to span javascript namespace across multiple files?
JavaScript Module Pattern: In-Depth

how to get the returned value of a Javascript function executed at an HTML page

I am trying to develop a plugin to internet explorer browser using csharp and I try to inject a javascript to the loaded page.
To inject the javascript i used the following code. The code is injected and the alert is working fine.
but code given below should return the value of "msg" to output.
when i run this code i get null value for output. kindly help.
var output= HTMLDocument.parentWindow.execScript("msg()","JScript");
function msg(){
var msg = "This is sample";
alert(msg);
return msg;
}
According to this page:
https://msdn.microsoft.com/en-us/library/ie/ms536420%28v=vs.85%29.aspx
The execCode method returns some sort of null value. Use eval if you want the value of msg().
IE cannot eval functions (Presumably for security reasons).
The best workaround is to put the function in an array, like this:
var func = eval('[' + funcStr + ']')

Function undefined/null even with eval()

I need help and I do not understand what's going on.
I have a script get the list of files in a folder, and eval all the js files.
I inject some html, but when I use the html, it calls my function but it says a function (previously evaluated) isn't defined??
Edit: { Written in html, javascript, css, and vbs. In an HTA. }
I tried shifting the snippets around, but it still gives me the error. (and I cannot just copy and paste to the main file, its meant to be a plugin)
Code: (some not all)
var inject='<div id="console">\
<br><div id="consoletitle" class="dynDiv_moveParentDiv dynDiv_bodyLimit"><center>Console</center></div>\
<a id="consolekey"></a><a id="consolea"></a>\
<input type="text" id="consoleba" onkeydown="if(event.keyCode==13){ss(event);}">\
</div>';
plugins.innerHTML+=inject;
this part works just fine, and the html is injected
function ss(event){
var key=event.keycode;
alert(key);
}
but it says this code isn't eval'd (or isn't defined)
and both snippets are in the same file that is eval'd.
Error:
Line: 1
Char: 23
Error: The value of the property 'ss' is null or undefined, not a function object
Code: 0
URL:
Here is the code that loads and evals each file:
var fso=new ActiveXObject("Scripting.FileSystemObject");
This works fine.
function loadPlugins(){
var fs=new Enumerator(fso.GetFolder("./plugins/").Files);
for(;!fs.atEnd();fs.moveNext()){
var file=fso.OpenTextFile(fs.item(),1);
eval(file.readAll());
file.close();
}
}
Seems to be working too.
The code is evaluated in the scope of the loadPlugins function, so the functions defined in the evaluated code only exist in that scope.
You can write the function as a function expression and assign it to a global variable to make it exist in the global scope:
ss = function(event){
var key=event.keycode;
alert(key);
};
Note: The ss variable is implicitly created in the global scope. If you use var ss it will be a local variable that only exists inside the function scope.

Evaluate custom javascript method (CircularJSON) with Jade

I want to parse an object into client-side javascript through Jade. Normally this would work:
script var object = JSON.parse(#{JSON.stringify(object)});
but my object is circular and I need to do this
script var object = CircularJSON.parse(#{CircularJSON.stringify(object)});
but it throws the error
Cannot call method 'stringify' of undefined
which I guess is because Jade doesn't recognise my CircularJSON method.
Any way to make it?
It could be required and passed in the locals
response.render("index.jade", {CircularJSON : require('circular-json')});
Or it could be defined as a function in the scope of jade
- var CircularJSON = function(e,t){function l(e,t,o){var u=[],...//whole function
script var player = CircularJSON.parse('!{CircularJSON.stringify(player)}');

How do I pass argument to anonymous Javascript function?

I am writing a simple counter, and I would like to make installation of this counter very simple for users. One of the simplest counter code (for users who install it) I ever see was Google Analytics Code
So I would like to store main code in a file and user who will install my counter will need just to set websiteID like this:
<html><head><title></title></head><body>
<script type="text/javascript" src="http://counterhost.lan/tm.js">
var websiteId = 'XXXXX';
</script>
</body></html>
Here is my code:
<script type="text/javascript" src="http://counterhost.lan/tm.js">
var page = _gat.init('new');
</script>
and this is my JS file:
(function() {
var z = '_gat';
var aa = function init(data) { alert(data); alert(z);};
function na() {
return new z.aa();
}
na();
})();
I tried to understand Google Analytics javascript code but I failed to do this. Can anyone suggest how can I specify variable between tags and then read it in anonymous function which is located in a javascript file ?
Thanks.
In your example, websiteId is a global variable. So it is accessible everywhere including anonymous functions unless there is a local variable with the same name
<script> var websiteId = "something"; </script>
Later in the page or included js file...
(function() {
alert(websiteId); //this should work
})();
Can anyone suggest how can I specify variable between tags and then read it [...]
Not if your tag has both a SRC attribute and JS content.
<script type="text/javascript" src="http:/x.com/x.js"></script>
.. is different from,
<script type="text/javascript">
var x = 1;
</script>
One framework that optionally adds JS variables to SCRIPT tags is Dojo. So if you're using Dojo you can add variables to the global djConfig hash by writing,
<script type="text/javascript" src="mxclientsystem/dojo/dojo.js"
djConfig="
usePlainJson: true,
parseOnLoad: true
">
</script>
Dojo does this by running through the SCRIPT tags and evaluating the custom djConfig attribute.
This does not, however solve your problem.
You do really want two SCRIPT tags. One saying,
<script type="text/javascript">
var websiteId = '123456';
</script>
which will set a global variable websiteId and a second one,
<script type="text/javascript" src="http:/x.com/myreporter.js"></script>
which can load from anywhere and read out the websiteId variable and, I assume, report it back.
You can pass variables to an anonymous function like so:
(function(arg1, arg2, arg3) {
alert(arg1);
alert(arg2);
alert(arg3);
})("let's", "go", "redsox");
// will alert "let's", then "go", then "redsox" :)
I'm not entirely clear about what you're asking, but...
You can tag any HTML element with an id attribute, then use
document.getEntityById() to retrieve that specific element.
You can also give any HTML element user-defined attributes having names of your own choosing, then get and set them for that element within Javascript.
I think you've got a bit confused with how JS objects are called.
z is a String, '_gat'. You can't call aa() on it because a String has no member called aa. aa is a standalone function stored in a local variable. Even if you did call aa(), it doesn't return anything, so using the new operator on its results is meaningless. new can only be called on constructor-functions.
I guess you mean something like:
var _gat= function() {
// Private variable
//
var data= null;
// Object to put in window._gat
//
return {
// Set the private variable
//
init: function(d) {
data= d;
}
};
}();
Then calling _gat.init('foo') as in your second example would set the variable to website ID 'foo'. This works because the _gat object is the return {init: function() {...}} object defined inside the anonymous function, keeping a reference (a ‘closure’) on the hidden data variable.
If you specify a src attribute as part of a script element, any code within the script element tags themselves will not be executed. However, you can add this functionality with the following code. I got this technique from Crockford (I believe it was him), where he uses it in of his talks on the unrelated topic of rendering performance and asynchronously loading scripts into a page to that end.
JavaScript:
(function() {
// Using inner class example from bobince's answer
var _gat = (function() {
var data= null;
return {
init: function(d) {
console.info("Configuration data: ", d);
data = d;
}
}
})();
// Method 1: Extract configuration by ID (SEE FOOT NOTE)
var config = document.getElementById("my-counter-apps-unique-and-long-to-avoid-collision-id").innerHTML;
// Method 2: search all script tags for the script with the expected name
var scripts = document.getElementsByTagName("script");
for ( var i=0, l=scripts.length; i<l; ++i ) {
if ( scripts[i].src = "some-script.js" ) {
config = scripts[i].innerHTML;
break;
}
}
_gat.init( eval("(" +config+ ")") );
})();
HTML:
<script type="text/javascript" src="some-script.js" id="my-counter-apps-unique-and-long-to-avoid-collision-id">
{some: "foo", config: "bar", settings: 123}
</script>
Both methods have their draw backs:
Using a unique and non-colliding ID will make determining the proper script element more precise and faster; however, this is not valid HTML4/XHTML markup. In HTML5, you can define arbitrary attributes, so it wont be an issue at that time
This method is valid HTML markup; however, the simple comparison that I have shown can be easily broken if your url is subject to change (e.g.: http vs https) and a more robust comparison method may be in order
A note on eval
Both methods make use of eval. The typical mantra concerning this feature is that "eval is evil." However, that goes with say that using eval without knowing the dangers of eval is evil.
In this case, AFAIK, the data contained within the script tags is not subject to inject attack since the eval'ing script (the code shown) is executed as soon as that element is reached when parsing the HTML into the DOM. Scripts that may have been defined previously are unable to access the data contained within the counter's script tags as that node does not exist in the DOM tree at the point when they are executed.
It may be the case that a well timed setTimeout executed from a previously included script may be able to run at the time between the counter's script's inclusion and the time of the eval; however, this may or may not be the case, and if possible, may not be so consistently depending on CPU load, etc.
Moral of the story, if you're worried about it, include a non-eval'ing JSON parser and use that instead.

Categories