Recently I have seen people talk about the using of macros in JavaScript. I have no idea what that means and after looking up documentation on MDN I came up without any answer. So that leads me to my question …
What are JavaScript macros?
How/why are they used?
Is it a form of meta-programming?
Answers with examples and example code would be appreciated greatly.
As has been posted in comments it's a macro system for javascript.
It's a way of defining text replacements in the "pre-processing phase". So you would define a macro and use it in your code, then run them both through sweet.js and the output would be code with text replacements.
example:
macro swap {
rule { ($a, $b) } => {
var tmp = $a;
$a = $b;
$b = tmp;
}
}
var a = 10;
var b = 20;
swap (a, b)
After running this through sweet.js we get the expanded code:
var a$1 = 10;
var b$2 = 20;
var tmp$3 = a$1;
a$1 = b$2;
b$2 = tmp$3;
I think the use case for this is more centered around frameworks and the likes. It's a more flexible way of saving lines of code than a function.
In JS, a function can basically either
Mathematically calculate something based off of it's inputs
Perform some kind of side effect on another variable within the scope of the function
But Macros are more flexible, it's like code that just takes in inputs and actually equates to text that can be compiled as regular code. It's a common feature in languages that prioritize code prettiness over code-traceability. A couple of notable examples are Ruby, Rust, and Elixir.
Here's an example of a ruby macro and what the equivalent code would look like in js.
In ruby you can do this to tell a class to have certain relationship methods in it's ORM
class Movie < ActiveRecord::Base
has_many :reviews
end
In this case, saying has_many :reviews dumps a bunch of methods onto the Movie class. So because of that line you can call movie.reviews.
In TypeORM right now you could do something like
class Movie {
#OneToMany(() => Review, review => review.movie)
reviews: Review[];
}
If macros made it into js, you could clean this up to look more like
class Movie {
oneToMany(Review, "reviews", "movie")
}
My guess is that this won't happen any time soon. IMO one of the things you lose with macros, is that it becomes less clear what your code actually does, I also have to imagine it would be a pretty big change for linters and type checkers. There's also other ways of dumping a bunch of functionality into an object or function.
For example in react hook form you can accomplish something similar using closures and spreading.
<input {...register("firstName")} placeholder="Bill" />
Related
To save me having to repeat a line of code (example a) in lots of different files - wherever I want to make use of a Java method, is it possible to move that line of code to the Karate-config.js so that I can make use of the methods attached to it? like in (example b)?
example a (line in feature file that I want to move to karate-config):
* def LdapUtils = Java.type('com.package.something.LdapUtils')
example b (in feature file):
* def newUser = LdapUtils.addNewUser()
* def userId = newUser.uid
Yes this is possible. You can find examples in our test-suites, for example this one: https://github.com/karatelabs/karate/tree/v1.2.1.RC1/karate-core/src/test/java/com/intuit/karate/core/parajava
Personally, I discourage too much of this, we've had problems with Java interop + JS, but the good news is it is mostly resolved. If you go down this path, please use 1.3.0.RC1 or RC2: https://github.com/karatelabs/karate/wiki/1.3.0-Upgrade-Guide
I have an idea for a game where people can type in some simple instructions for their character like player.goLeft() or player.attackInFront() and for that I have people type their code into a text box and then I parse it into eval(). This works well but it also allows people to change their own character object by typing things like player.health = Infinity; or something similar. I have a list of functions I want to allow people to use, but I am unsure how to restrict it to only use them.
I understand that the whole point of not letting people use eval is to avoid accidental cross-site scripting but I am unsure on how else to do this. If you have a suggestion please leave a comment about that.
I asked some people around on what to do and most suggested somehow changing scope(which is something I was not able to figure out) or to add some odd parameter to each function in my code that would be required to be a specific string to execute any function, but that seems hacky and since I am making the game in browser with p5js it would be easy to just inspect element and see what the password is.
basically every character has variable called "instruction" which is just a string of javascript. Then every frame of the game I execute it by doing eval(playerList[i].instruction);
tl;dr, how can I only allow specific function to be executed and not allow any others?
EDIT: I forgot to mention that I also am planning to provide player with information so that people can made code that would adapt to the situation. For example there will be parameter called vision that has vision.front and vision.left etc. These variables would just say if there is an enemy, wall, flower, etc around them in a grid. Some people suggested that I just replace some functions with key words but then it compromises the idea of using if statements and making it act differently.
EDIT 2: Sorry for lack of code in this post, but because of the way I am making it, half of the logic is written on server side and half of it works on client side. It will be a little large and to be completely honest I am not sure how readable my code is, still so far I am getting great help and I am very thankful for it. Thank you to everybody who is answering
Do NOT use eval() to execute arbitrary user input as code! There's no way to allow your code to run a function but prevent eval() from doing the same.
Instead, what you should do is make a map of commands the player can use, mapping them to functions. That way, you run the function based on the map lookup, but if it's not in the map, it can't be run. You can even allow arguments by splitting the string at spaces and spreading the array over the function parameters. Something like this:
const instructions = {
goLeft: player.goLeft.bind(player),
goRight: player.goRight.bind(player),
attackInFront: player.attackInFront.bind(player)
};
function processInstruction(instruction_string) {
const pieces = instruction_string.split(' ');
const command = pieces[0];
const args = pieces.slice(1);
if (instructions[command]) {
instructions[command](...args);
} else {
// Notify the user their command is not recognized.
}
};
With that, the player can enter things like goLeft 5 6 and it will call player.goLeft(5,6), but if they try to enter otherFunction 20 40 it will just say it's unrecognized, since otherFunction isn't in the map.
This issue sounds similar to the SQL Injection problem. I suggest you use a similar solution. Create an abstraction layer between the users input and your execution, similar to using parameters with stored procedures.
Let the users type keywords such as 'ATTACK FRONT', then pass that input to a function which parses the string, looks for keywords, then passes back 'player.attackInFront()' to be evaluated.
With this approach you simplify the syntax for the users, and limit the possible actions to those you allow.
I hope this isn't too vague. Good luck!
From your edit, it sounds like you're looking for an object-oriented approach to players. I'm not sure of your existing implementation needs, but it would look like this.
function Player() {
this.vision = {
left: '',
// and so on
}
}
Player.prototype.updateVisibilities = function() {
// to modify the values of this.visibility for each player
}
Player.prototype.moveLeft = function() {
}
Don't give the user an arbitrary interface (such as an input textfield that uses eval) to modify their attributes. Make a UI layer to control this logic. Things like buttons, inputs which explicitly run functions/methods that operate on the player. It shouldn't be up to the player as to what attributes they should have.
I have a Jupyter Notebook which is using the R programming language. I would like to call javascript functions within this R notebook.
I know there is a way to do this, because there are javascript based libraries that you can call from R, but I cannot find any examples of wrapping a javascript function, so it can be used by R.
Even an example of assigning javascript to a R variable and then calling that R variable would be helpful.
js::js_eval() can evaluate a string of JavaScript within R. From ?js::js_eval:
# Stateless evaluation
js_eval("(function() {return 'foo'})()")
For more complicated JavaScript operations, check out V8, which lets you keep a JavaScript instance for more than one line. From ?V8::v8:
# Create a new context
ctx <- v8();
# Evaluate some code
ctx$eval("var foo = 123")
ctx$eval("var bar = 456")
ctx$eval("foo+bar")
Ultimately it's going to get really frustrating for anything beyond little hacks, but it does work. You could likely source a whole script if you're clever, but I'm not sure it's worth it unless there's something that can absolutely only be done in JavaScript. Happy hacking!
I just wanted to add this answer in case anyone was interested in using javascript/html in Jupyter R. The following is a very basic example:
test="<input type=\"file\" id=\"myFile\"/>"
as.factor(test)
The as.factor() removes the quotes but you can basically just assigned javascript/html to an r variable and call that variable. For example:
test="<input type=\"file\" id=\"myFile\"/>"
test
So I found another way to do this by using the HTML function. Here is an example that will show and hide the code in a cell by clicking the text.
from IPython.core.display import HTML
HTML("""
<style>
// add your CSS styling here
</style>
<script>
var code_show=true; //true -> hide code at first
function code_toggle() {
$('div.prompt').hide(); // always hide prompt
if (code_show){
$('div.input').hide();
} else {
$('div.input').show();
}
code_show = !code_show
}
$( document ).ready(code_toggle);
</script>
<a href="javascript:code_toggle()"
style="text-decoration:none; background-color: none;color:black;">
<h1 align="center">Example</h1>
</a>
""")
i am facing the problem that i have to translate a larger html and javascript project into several languages. The html content was no problem, but the numerous javascript files are problematic, since i was a bit lazy during the development process. For instance, if i needed a message text, i just added it in the concerning position.
My approach now is, that i am using a build-in file search (Eclipse) for every occurrence of " and ', which i am getting line-wise. This would be extremely time consuming and errors are unavoidable.
Here are some examples that occur in the files:
var d = "Datum: " + d.getDate()+"."+(d.getMonth()+1)+"."+d.getFullYear();
showYesNoDialog("heading text","Are you sure?",function(){};
Sometimes i am mixing " and ', sometimes a string goes over several lines:
var list="";
list+='<li data-role="list-divider">';
list+='Text To Translate';
list+='</li>';
Things i don't want to get, are jquery selectors, e.g.:
$("input[name^=checkbox]").each(function () {};
Do you see any time saving method to get all of the strings that i would like to translate?
Regex? A java interpreter? Grep?
I know, that is a bit unusual question.
So any suggestion would be great.
Thanks in advance!
It is better to use some kind of the lexical scanner that converts the code into the tokens and then walk over the list of tokens (or syntax tree). There is a number of such tools (I even created one of them myself - here you can find some of the examples https://github.com/AlexAtNet/spelljs/blob/master/test/scan.js).
With it you can scan the JS file and just iterate over the tokens:
var scan = require('./..../scan.js');
scan(text).forEach(function (item) {
if (item.str) {
console.log(item);
}
});
Apparently the task I asked about earlier (JavaScript Automated Clicking) is impossible in JavaScript, or at the very least extremely difficult.
However, I have found the documentation on Selenium and how to use it extremely uninviting and difficult to understand.
Perhaps someone could help me translate this code to Selenium or, alternatively, help me with particular elements I'm having difficulty with.
function pausecomp(ms) {
ms = ms + new Date().getTime();
while (new Date() < ms){}
}
var itemlist, totalnumber, i;
itemlist = document.getElementsByClassName("image");
totalnumber = parseInt(document.getElementById("quickNavImage").childNodes[3].firstChild.firstChild.nodeValue.replace(/[0-9]* of /, ""));
for(i = 0; i < totalnumber; i = i + 1) {
console.log(i);
itemlist[i].childNodes[1].click();
pausecomp(3000);
}
Now, I know I can get elements by Class Name in Selenium, but how do I get specific child nodes?
Likewise, how do I use regex to cut out the total number of items that needs to be clicked? It is only available in text form.
And finally, how do I iterate in Selenium?
Please note, I have no available programming environments on these computers. So I cannot use Python, C#, etc. hooks unless they can be directly imported into the Selenium IDE itself. However, the documentation is difficult for me to understand, so I don't believe that is possible.
I figured it out. Please take a look at my previous linked post. I was being an idiot. I'll put the answer up there.