I need to identify the start and end of function definitions (blocks) in Javascript source code, using PHP. I don't need to parse the code, just literally know where the beginning and end of the Javascript code is if I've read it into a PHP string (using file_get_contents() for example, or some other way).
I need to only identify functions defined at the highest level within the global scope of the Javascript code, and also functions defined at that level for JQuery event callbacks, but I need to ignore more embedded functions in the code.
So, e.g.
function my_JS_func()
{
// some code
}
and
$('#button').onclick(click(function(e){
// some code
});
but I need to ignore the $.post callback function in here (but I would pick up func2 as a whole):
function func2()
{
$.post('myURL', {data: mydata}, function(data){
// ignore me
}
}
Obviously I need to identify the text: "function" (unless it's in a string literal for some reason) and I'm assuming I need to keep track of curly braces {} but otherwise, any ideas welcomed!
Many thanks for any suggestions! (Happy to use a PHP lib, 3rd party software or whatever)
Related
Is there a simple way to prevent $bind generation when passing around class member functions?
I have an object that takes in a function which will be called in an arbitrary interval. The object always binds itself as the 'this' binding before calling the function (this is done in the native side), therefore the call to $bind itself is unnecessary. However, I can't seem to find a simple way to prevent $bind from being emitted any time I grab a member function by value.
The only way I've found is to use __js__ with a string literal of the member function name, which I would rather avoid... Is there a typed way to do so? Or something a bit nicer? A way to still use haxe syntax w/ identifiers instead of a string literal?
Example:
private function onSpawn():Void
{
this.setAct( act ); // Will generate JS: this.setAct($bind(this,this.act));
// Id like to simply have it generate: this.setAct( this.act );
// Mitigated like this:
this.setAct( untyped __js__("this.act") );
}
private function act( dt:Float ):Void
{
...
}
Thank you.
You use macro to mask out the untyped expression, but this is quite dangerous.
Any reference to "this" will fail.
http://try-haxe.mrcdk.com/#70ee4
Btw, I think the compiler may be optimized to not generate $bind if the function code doesn't involve "this". You may want to raise an issue in the github repo about that.
I see sometimes js snippets that are using the $ in front of the argument ($argName).
function someName(arg) {
// some code
// using arg
}
function someName($arg) {
// some code
// using $arg
}
In this js example it works either way with or without the $ in front of the arguments. Can anyone explaine if it has any use?
The $ character is legal in JS identifiers, and is often used simply as a code convention to indicate that the passed parameter is already a jQuery object (as opposed to a native DOM element).
This serves as a reminder that it's not necessary to re-invoke the jQuery $(param) wrapper function on that parameter.
It's also used quite a lot in Angular JS code.
It's sometimes used to reference an object from another library , like JQuery or AngularJS , what you're talking about here looks like AngularJs's dependency injection to me
UPDATE
See this answer it might be useful
I'm working on a project that's essentially a templating domain-specific language. In my project, I accept lines of user input in the following form:
'{{index(1, 5)}}'
'{{firstName()}} X. {{lastName()}}'
'{{floating(-0.5, 0.5)}}'
'{{text(5, "words")}}'
Any command between double curly braces ({{ }}) has a corresponding Javascript method that should be called when that command is encountered. (For example, function index(min, max) {...} in the case of the first one).
I'm having a difficult time figuring out how to safely accept the input and call the appropriate function. I know that the way I'm doing it now isn't safe. I simply eval() anything between two sets of curly braces.
How can I parse these input strings such that I can flexibly match a function call between curly braces and execute that function with any parameters given, while still not blindly calling eval() with the code?
I've considered making a mapping (if command is index(), call function index() {}), but this doesn't seem very flexible; how do I collect and pass any parameters (e.g. {{index(2, 5)}}) if any are present?
This is written in Node.js.
This problem breaks down into:
Parsing the string
Evaluating the resulting function graph
Dispatching to each function (as part of #2 above)
Parsing the string
Unfortunately, with the requirements you have, parsing the {{...}} string is quite complex. You have at least these issues to deal with:
Functions can be nested {{function1(function2(), 2, 3)}}.
Strings can contain (escaped) quotes, and can contain commas, so even without requirement #1 above the trivial approach to finding the discrete arguments (splitting on a comma) won't work.
So...you need a proper parser. You could try to cobble one together ad hoc, but this is where parser generators come into the picture, like PEG.js or Jison (those are just examples, not necessarily recommendations — I did happen to notice one of the Jison examples is a JSON parser, which would be about half the battle). Writing a parser is out of scope for answering a question on SO I'm afraid. :-)
Evaluating the resulting function graph
Depending on what tool you use, your parser generator may handle this for you. (I'm pretty sure PEG.js and Jison both would, for instance.)
If not, then after parsing you'll presumably end up with an object graph of some sort, which gives you the functions and their arguments (which might be functions with arguments...which might be...).
functionA
1
"two"
functionB
"a"
functionC
42
functionD
27
functionA there has five arguments, the third of which is functionB with two arguments, and so on.
Your next task, then, is to evaluate those functions deepest first (and at the same depth, left-to-right) and replace them in the relevant arguments list with their result, so you'll need a depth-first traversal algorithm. By deepest first and left-to-right (top-to-bottom in the bullet list above) I mean that in the list above, you have to call functionC first, then functionB, then functionD, and finally functionA.
Dispatching to each function
Depending again on the tool you use, it may handle this bit too. Again I suspect PEG.js does, and I wouldn't be surprised if Jison did as well.
At the point where you're ready to call a function that (no longer) has function calls as arguments, you'll presumably have the function name and an array of arguments. Assuming you store your functions in a map:
var functions = {
index: function() { /* ... */ },
firstName: function() { /* ... */ },
// ...
};
...calling them is the easy bit:
functionResult = functions[functionName].apply(undefined, functionArguments);
I'm sorry not to be able to say "Just do X, and you're there," but it really isn't a trivial problem. I would throw tools at it, I wouldn't invent this wheel myself.
If possible do not evaluate the user input.
If you need to evaluate it, evaluate it in controlled scope and environment.
The last one means instead of using eval() use new Function() or specially designed libraries like https://github.com/dtao/lemming.js
See http://www.2ality.com/2014/01/eval.html for more information about eval vs new Function()
For more sophisticated approach try creating your own parser, check https://stackoverflow.com/a/2630085/481422
Search for comment // ECMAScript parser in https://github.com/douglascrockford/JSLint/blob/master/jslint.js
You could try something like this:
Assuming you have a function like this:
'{{floating(-0.5, 0.5)}}'
And all your actual functions are referenced in an object, like this:
var myFunctions = {
'index': function(){/* Do stuff */},
'firstName': function(){}
}
Then, this should work:
function parse(var input){
var temp = input.replace('{{','').replace(')}}','').split('('),
fn = temp[0];
arguments = temp[1].split(',');
myFunctions[fn].apply(this, arguments);
}
Please note that this only works for simple function calls that don't have functions nested as their arguments. It also passes all arguments as strings, instead of the types that may be intended (Numbers, booleans, etc).
If you want to handle more complex strings, you'll need to use a proper parser or template engine, as #T.J. Crowder suggested in the comments.
I have a "library" of objects that I want to load on the fly from a database. Each object comes with its own special functions that are called at specific times depending on the objects type. Ideally I'd like to be able to do this, although its been pointed out that this doesn't work:
library = {
"myObj" : {"name" : "myObj", "type" : "myType", "function" : function () { } } //, etc
}
The string "myObj" is passed around my program quite a bit, but I only have to access certain values of the object at a time, and in some circumstances there's a specific function that needs to be run. The problem is that I'm looking at hundreds, and eventually thousands, of potential objects that could exist with varying functions.
What is the "right" way to store a function to be called like this. I know that calling eval can be very unsafe during execution, enabling xss attacks and whatnot. I really want to avoid a massive switch statement or the bloated loading of additional functions. I'd also like the solution to be as concise as possible.
This can't be the first time this has come up. ;/
Thanks for your help.
Just use eval to recreate the function after loading it as a string. So if you deserialize an object myObj from JSON, and you have a property:
myObj = {
....
function: "function() { ... }"
}
you can very easily turn it to a real function:
eval("myObj.func = " + myObj.func);
http://jsfiddle.net/kceTr/
Oh - I am not sure if that was an edit or I missed it before - but re: eval.
Eval is a tool. You want to store a function in a database. It really doesn't make much difference if you have to "eval" to turn it into code, or there was some other magic way to do it: if someone can change the data in your DB, then they can change a function.
If you need to store a function, then eval is your tool. It's not "bad" by nature, it's bad because it's easy to misuse. Whether you use it well or not is up to you.
Remember anything running on the client is still just running on the client. There's nothing a malicious person could do with eval, that they couldn't do with the Chrome debugger a lot more easily. Anyone can always run any code they want on the client, it's up to your server to decide how to handle what it receives. There's nothing safe on the client in the first place...
Changing the prototype of the object is a half thought I have.
You've got your library like
library = {
"myObj" : {"name" : "myObj", "type" : "myType", "function" : function () { } } //, etc
}
You've got an object (let's call it theObj) that you know is a myObj (due to a string maybe? property?)
theObj.__proto__ = library["myObj"];
That way you can execute
theObj.function(...);
jsfiddle example (it's rough!). Also, be careful with proto, it's deprecated (1) (2)
As to serializing the functions, can you get them in using a script tag that points to something serverside that slurps them from the db and returns the js? Just include them inline as you render the page (in a script block)? Or, if all else fails, eval should work, as long as you know that the functions you've got stored in the database are clean and safe.
There is no right way to do this, because its not generally a good idea.
HOWEVER, if you want to do it anyways you can simply extend the prototype of Function with a .toJSON method.
Function.prototype.toJSON = function(){ return this.toString(); }
Then you can simply use JSON.stringify and functions will be serialized as strings.
Its generally a not good idea in most cases. There are very few circumstances where you want to do this and even then, there is probably a better way.
A better approach might be to serialize the object's properties when you "sleep" it, and "waking" the object by reattaching its properties to a new instance of the object with the appropriate methods defined.
what you are doing with it is just fine. However, if i were you, for readability and tidyness, i would rather have the function created outside and simply have it assigned to your object key.
You don't need eval here. Instead do it this way whenever you want access to the stored function -
library.myObj.function()
You do your best in parameterising your functions, so that you end up
with as little typologies as possible.
Store them on the server in individual JS files, then load the needed file dynamically, by name.
In the JSON, only store the name of the file that contains the function that you need. And, of course, you will be caching already loaded files, to go easy on the server.
Just my two cents.
You can only really serialise a whole file with require calls in it. If you do that, you can create a module, exports and module.exports, eval the file with a function surrounding it and snag the module.exports out of it.
It's not exactly secure, but for that you need to use something like VM2 and value-censorship (which I've been working on) to avoid them calling eval() and owning your machine or the entire network.
I have a gallery that I am trying to integrate in my site. I am replacing a and then I want to call the galleries function "function loadGal($)" so the gallery will be rebuilt. But I don't know what kind of parameter to send to it.
Before I changed it, it was called inside "jQuery(document).ready(function($) {"
I just tried to do something like this:
jQuery(document).ready(function($) {
loadGal($);
});
it works fine but I don't know what is the dollar...
The $ is just the name of the parameter. It is nothing special. $ is a valid character of variable names in JavaScript.
However it is often used by libraries such as jQuery or Prototype as it is probably the most characteristic one-letter variable (j or p don't stand out that much) (meaning it is easy to spot and easy to use as you only have to type one character).
The value passed to the ready handler, is the jQuery object (emphasis is mine):
When using another JavaScript library, we may wish to call $.noConflict() to avoid namespace difficulties. When this function is called, the $ shortcut is no longer available, forcing us to write jQuery each time we would normally write $. However, the handler passed to the .ready() method can take an argument, which is passed the global jQuery object. This means we can rename the object within the context of our .ready() handler without affecting other code
but you can name the parameter however you want. You could also write:
jQuery(document).ready(function(foobar) {
loadGal(foobar);
});
Update: And now that I understood the real question ;)
$ is the jQuery object, so you can write:
loadGal(jQuery);
But note that loadGal might not work if it has to work on the DOM elements and you call it outside the ready handler.