Javascript: How to use eval() safely [duplicate] - javascript

This question already has answers here:
When is JavaScript's eval() not evil?
(27 answers)
Closed 8 years ago.
I am building a little game and I've gotten to the point where I need to calculate data in the tips of abilities which is unique to each individual unit. So to do this I figured I'm gonna basically need a formula. I don't know if this is the way it's supposed to be done but here's what I've come up with
tip = 'Hurls a fire ball at your enemy, dealing [X] damage.';
formula = '5 * unit.magicPower * abilitylevel';
So for each unit's tool tip I use
tip.replace('[X]', eval(formula))
Which appears to work fine, but what I'm concerned about is the safety of this code. It hasn't been once or twice that I've seen people discouraging the use of it. Are there any potential issues that may occur with the way I'm using eval()?

As long as you control the input into eval, it's safe to use it. The concern comes in when you're using it to process input that you don't control. At that point, it becomes unsafe because it's a full JavaScript parser but people sometimes try to use it as just an expression evaluator (for instance, when parsing JSON from a source they don't control).
The other objection is that it's firing up a full JavaScript parser (and so in theory costly), but frankly unless you're doing this hundreds of thousands of times in a tight loop, it's not going to matter.

eval is very dangerous if any of the expression is supplied by the user. If you're constructing it entirely from built-in components, it's not very dangerous. However, there are still usually better ways of accomplishing it, such as calling closures.

The basic rule of thumb is to make sure that by default you pass your data/information through eval() only.
You can't stop someone with tools like Firebug if they want to mess with stuff obviously but that is what server-side validation is about.
Now if you're talking about server-side eval() then you really have to be careful. Unfortunately there are a lot of uncooperative people working on JavaScript and it's implementations in browsers so you'll be forced to use eval() in JavaScript, I've never had to use it in PHP.

Related

JavaScript Iterative Variable Filtering

Is there a tool that allows us to search for a javascript variable just like a memory editor does: through iterative filtering either by exact value or change?
(Sorry for the long intro, but it's the best way I found to describe my use case.)
When I was about 14 yrs old, I would use a memory editor to find, monitor, and edit variables in games.
This allowed me to understand a bit better how computers work but also allowed me to have fun, changing the variables of the games to whatever I liked (offline, of course ;) )
The program would show me all variables.
I would then reduce the list of variables by repeatedly filtering: either by searching for its exact value (if it was known) or by change (increase, decrease).
Now I find myself wanting to do the same for Javascript. I've searched for a while, and I've tried different things, including searching for the variables in the window variable in console (please keep in mind I'm not a javascript developer) or using the debug function (which works great if you know where the variable is) but I haven't found a similar solution.
Is it true that no tool exists like this?
There so many use-cases:
debugging: finding where that number with that weird value is;
fun: edit variables just for plain fun, in games, etc;
learning how to code: I learned how to program by "hacking" around, and I know I'm not the only one ;)
probably many others I can't think about.
Does anyone know anything like this?

Replacement of "-' with "_" using a loop in javascript

I have applied the same method to replace "-" with "_" in c++ and it is working properly but in javascript, it is not replacing at all.
function replace(str)
{
for(var i=0;i<str.length;i++)
{
if(str.charAt(i)=="-")
{
str.charAt(i) = "_";
}
}
return str;
}
It's simple enough in javascript, it's not really worth making a new function:
function replace(str){
return str.replace(/-/g, '_') // uses regular expression with 'g' flag for 'global'
}
console.log(replace("hello-this-is-a-string"))
This does not alter the original string, however, because strings in javascript are immutable.
If you are dead set on avoiding the builtin(maybe you want to do more complex processing), reduce() can be useful:
function replace(str){
return [...str].reduce((s, letter) => s += letter == '-' ? '_' : letter , '')
}
console.log(replace("hello-this-is-a-string"))
This is yet another case of "make sure you read the error message". In the case of
str.charAt(i) = "_";
the correct description of what happens is not "it is not replacing at all", as you would have it; it is "it generates a run-time JavaScript error", which in Chrome is worded as
Uncaught ReferenceError: Invalid left-hand side in assignment
In Firefox, it is
ReferenceError: invalid assignment left-hand side
That should have given you the clue you needed to track down your problem.
I repeat: read error messages closely. Then read them again, and again. In the great majority of cases, they tell you exactly what the problem is (if you only take the time to try to understand them), or at least point you in right direction.
Of course, reading the error message assumes you know how to view the error message. Do you? In most browsers, a development tools window is available--often via F12--which contains a "console", displaying error messages. If you don't know about devtools, or the console, then make sure you understand them before you write a single line of code.
Or, you could have simply searched on Stack Overflow, since (almost) all questions have already been asked there, especially those from newcomers. For example, I searched in Google for
can i use charat in javascript to replace a character in a string?
and the first result was How do I replace a character at a particular index in JavaScript?, which has over 400 upvotes, as does the first and accepted answer, which reads:
In JavaScript, strings are immutable, which means the best you can do is create a new string with the changed content, and assign the variable to point to it.
As you learn to program, or learn a new languages, you will inevitably run into things you don't know, or things that confuse you. What to do? Posting to Stack Overflow is almost always the worst alternative. After all, as you know, it's not a tutorial site, and it's not a help site, and it's not a forum. It's a Q&A site for interesting programming questions.
In the best case, you'll get snarky comments and answers which will ruin your day; in the worst case, you'll get down-voted, and close-voted, which is not just embarrassing, but may actually prevent you from asking questions in the future. Since you want to make sure you are able to ask questions when you really need to, you are best off taking much more time doing research, including Google and SO searches, on simple beginner questions before posting. Or find a forum which is designed to help new folks. Or ask the person next to you if there is one. Or run through one or more tutorials.
But why write it yourself at all?
However, unless you are working on this problem as a way of teaching yourself JavaScript, as a kind of training exercise, there is no reason to write it at all. It has already been written hundreds, or probably thousands, of times in the history of computing. And the overwhelming majority of those implementations are going to be better, faster, cleaner, less buggy, and more featureful than whatever you will write. So your job as a "programmer" is not to write something that converts dashes to underscores; it's to find and use something that does.
As the wise man said, today we don't write algorithms any more; we string together API calls. Our job is to find, and understand, the APIs to call.
Finding the API is not at all hard with Google. In this case, it could be helpful if you knew that strings with underscores are sometimes called "snake-cased", but even without knowing that you can find something on the first page of Google results with a query such as "javascript convert string to use underscores library".
The very first result, and the one you should take a look at, is underscore.string, a collection of string utilities written in the spirit of the versatile "underscore" library, and designed to be used with it. It provides an API called underscored. In addition to dealing with "dasherized" input (your case), it also handles other string/identifier formats such as "camelCase".
Even if you don't want to import this particular library and use it (which you probably should), you would be much better off stealing or cloning its code, which in simplified form is:
str
.replace(/([a-z\d])([A-Z]+)/g, '$1_$2')
.replace(/[-\s]+/g, '_')
This is not as complicated as it looks. The first part is to deal with camelCase input, so that "catsAndDogs" becomes "cats-and-dogs". the second line is what handles the dashes and spaces). Look closely--it replaces runs of multiple dashes with a single underscore. That could easily be something that you want to do too, depending on who is doing what with the transformed string downstream. That's a perfect example of something that someone else writing a professional-level library for this task has thought of that you might not when writing your home-grown solution.
Note that this well-regarded, finely-turned library does not use the split/join trick to do global replaces in strings, as another answer suggests. That approach went out of use almost a decade ago.
Besides saving yourself the trouble of writing it yourself, and ending up with better code, if you take time time to understand what it's doing, you will also end up knowing more about regular expressions.
You can easily replace complete string using .split() and .join().
function replace(str){
return str.split("-").join("_");
}
console.log(replace("hello-this-is-a-string"))

Why to cast all the values in an object to strings in Javascript?

Disclaimer: My experience is mainly development with statically typed languages, and even if I understand how dynamic types works, I'm not very familiar with the common practices, neither I'm very aware of the usual tips and tricks yet.
I recently started to work in a project where we use serverless and deploy some lambdas in AWS with javascript. After deep diving the existing code I found out a common practice that shocked me a bit:
When a lambda is invoked and it receives a JSON payload, there is an initial pre-processing, converting all the values in the object to strings.
const mapValues = require('lodash/mapValues')
const escape = require('validator/lib/escape')
...
const body = mapValues(requestBody, value => escape('' + value))
...
Then after that pre-processing, the real work begins (validation, processing, invoking other services, etc...)
My first thoughts this are:
Benefit: Helps to reduce the cognitive load of the possible different types, enabling to assume that everything will be always a string.
Downside: Extra complexity dealing with non-string values, such as numbers.
Q1: Are there any other benefits and pitfalls to using this approach?
Q2: Could this be considered a bad practice? If so, why? (facts, not opinions please)
Thanks in advance! :)
Interesting question. I suggest you to ask the author if they 're available. Here are some of my thoughts:
I argue having string values does not reduce but increase cognitive load, as you have to watch out to convert them when doing basic arithmetics. I am sure all of us have seen at least once 1+1 being 11.
Also, handling every data as strings is a so bad practice it even has its own mock name: stringly typed. This is the cookbook example of that.
The only valid reason I can possibly imagine is to prevent various injection attacks against the service. In some scenarios, if the user is allowed to send in arbitrary json, it is possible to make the service execute code paths that it would not do normally. (something whacky like {"__proto__":[],"length":1,"0":"foo"} coerects to "foo" but is typeof object, this could bypass some flawed validation logic. mongodb is also prone to some attacks alike). But even in this case, proper validation would be much better than converting every value to string.

ES8 - Why have padStart/padEnd methods?

Trying to understand the reasoning behind the support for these 2 methods in ES8. padEnd for example - this can be achieved either using concat, replace, repeat.
So is it just to have a cleaner way of achieving this because this could be a common use-case or this is more efficient than current alternatives?
Edit: It would help to know why a question is down voted - was the question too opinionated/broad to ask?
It's just for convenience. There are a huge amount of functions that could be done using other low level means - but when written poorly they result in bugs, or inefficient code. Everyone wins when the language adds support for something people often do.
To exaggerate your example - languages don't need for loops either. You can generally write the same sort of code with a while loop. People don't need ternaries - they can be done with a standard if statement. In both of the examples people would generally need to write more code to achieve the same effect - but why make the coder do that?
I would reverse the question - why do you think they shouldn't include padEnd?
I think your question is asking for usecases of padstart, padend functions, i.e what prompted for these to be included in ecmascript.
As pointed above, they are helper functions that let you achieve
more with less code.
Displaying tabular data in a monospaced font.
Adding a count or an ID to a file name or a URL: 'file 001.txt'.
Aligning console output: 'Test 001: ✓'.
Printing hexadecimal or binary numbers that have a fixed number of digits: '0x00FF'
You can read more about its usecase/applications here :
http://exploringjs.com/es2016-es2017/ch_string-padding.html
https://www.theregister.co.uk/2017/07/12/javascript_spec_straps_on_padding/

Is metaprogramming possible in Javascript?

During my routine work, i happened to write the chained javascript function which is something like LINQ expression to query the JSON result.
var Result = from(obj1).as("x").where("x.id=5").groupby("x.status").having(count("x.status") > 5).select("x.status");
It works perfectly and give the expected result.
I was wondering this looks awesome if the code is written like this (in a more readable way)
var Result = from obj1 as x where x.status
groupby x.status having count(x.status) > 5
select x.status;
is there a way to achieve this??
Cheers
Ramesh Vel
No. JavaScript doesn't support this.
But this looks quite good too:
var Result = from(obj1)
.as("x")
.where("x.id=5")
.groupby("x.status")
.having(count("x.status") > 5)
.select("x.status");
Most people insist on trying to metaprogram from inside their favorite language. That doesn't work if the language doesn't support metaprogramming well; other answers have observed that JavaScript does not.
A way around this is to do metaprogramming from outside the language, using
program transformation tools. Such tools can parse source code, and carry out arbitrary transformations on it (that's what metaprogramming does anyway) and then spit the revised program.
If you have a general purpose program transformation system, that can parse arbitrary languages, you can then do metaprogramming on/with whatever language you like. See our DMS Software Reengineering Toolkit for such a tool, that has robust front ends for C, C++, Java, C#, COBOL, PHP, and ECMAScript and a number of other programming langauges, and has been used for metaprogramming on all of these.
In your case, you want to extend the JavaScript grammar with new syntax for SQL queries, and then transform them to plain JavaScript. (This is a lot like Intentional Programming)
DMS will easily let you build a JavaScript dialect with additional rules, and then you can use its program transformation capabilities to produce the equivalent standard Javascript.
Having said, that, I'm not a great fan of "custom syntax for every programmer on the planet" which is where Intentional Programming leads IMHO.
This is a good thing to do if there is a large community of users that would find this valuable. This idea may or may not be one of them; part of the problem is you don't get to find out without doing the experiment, and it might fail to gain enough social traction to matter.
although not quite what you wanted, it is possible to write parsers in javascript, and just parse the query (stored as strings) and then execute it. e.g.,using libraries like http://jscc.jmksf.com/ (no doubt there are others out there) it shouldnt be too hard to implement.
but what you have in the question looks great already, i m not sure why you'd want it to look the way you suggested.
Considering that this question is asked some years ago, I will try to add more to it based on the current technologies.
As of ECMAScript 6, metaprogramming is now supported in a sense via Symbol, Reflect and Proxy objects.
By searching on the web, I found a series of very interesting articles on the subject, written by Keith Kirkel:
Metaprogramming in ES6: Symbols and why they're awesome
In short, Symbols are new primitives that can be added inside an object (without practically being properties) and are very handy for passing metaprogramming properties to it among others. Symbols are all about changing the behavior of existing classes by modifying them (Reflection within implementation).
Metaprogramming in ES6: Part 2 - Reflect
In short, Reflect is effectively a collection of all of those “internal methods” that were available exclusively through the JavaScript engine internals, now exposed in one single, handy object. Its usage is analogous to the Reflection capabilities of Java and C#. They are used to discover very low level information about your code (Reflection through introspection).
Metaprogramming in ES6: Part 3 - Proxies
In short, Proxies are handler objects, responsible for wrapping objects and intercepting their behaviors through traps (Reflection through intercession).
Of course, these objects provide specific metaprogramming capabilities, much more restrictive compared to metaprogramming languages, but still can provide handy ways of basic metaprogramming, mainly through Reflection practices, in fact.
In the end, it is worth mentioning that there is some worth-noticing ongoing research work on staged metaprogramming in JavaScript.
Well, in your code sample:
var Result = from(obj1)
.as("x")
.where("x.id=5")
.groupby("x.status")
.having(count("x.status") > 5)
.select("x.status");
The only problem I see (other than select used as an identifier) is that you embed a predicate as a function argument. You'd have to make it a function instead:
.having(function(x){ return x.status > 5; })
JavaScript has closures and dynamic typing, so you can do some really nifty and elegant things in it. Just letting you know.
In pure JS no you can not. But with right preprocessor it is possible.
You can do something similar with sweet.js macros or (God forgive me) GPP.
Wat you want is to change the javascript parser into an SQL parser. It wasn't created to do that, the javascript syntax doesn't allow you to.
What you have is 90% like SQL (it maps straight onto it), and a 100% valid javascript, which is a great achievement. My answer to the question in the title is: YES, metaprogramming is possible, but NO it won't give you an SQL parser, since it's bound to use javascript grammar.
Maybe you want something like JSONPath if you've got JSON data. I found this at http://www.json.org/. Lots of other tools linked to from there if it's not exactly what you need.
(this is being worked on as well: http://docs.dojocampus.org/dojox/json/query)

Categories