JSFuck (2012)
jsfuck.com
jsfuck.com
We wanted to obfuscate this bit of code, to make life just a little bit harder for reverse engineers. We made this huge function where we pretty much passed in all our application state, and it would run this JSFuck code, and spit out a token. We even made a few tweaks to the code so that you couldn't just reverse it back into JS with something like https://enkhee-osiris.github.io/Decoder-JSFuck/.
Performance was surprisingly alright, and it has never hit an environment where it couldn't execute. All in all, a fun few hours setting it up, and I haven't had to touch it since!
The effect of obfuscation is not what you expect. It seems like it moves the whole difficulty up, but it only moves up the floor. By doing so it tends to remove all the signals that would warn non-experts of security issues. Remove the obfuscation and then you have all the catastrophic security issues that have accumulated in there like treasures in an egyptian king's tomb https://zemnmez.medium.com/how-to-hack-the-uk-tax-system-i-g...
has a pretty good crack at obfuscator.io, too: https://closure-compiler.appspot.com/home#code%3D%252F%252F%...
That's the example from the site. "console.log('Hello world')" gets deobfuscated to "console[a(482)]("Hello World!");"
That does not look deobfuscated to me.
And, even if you don't, you can always call a(482)
I've been using the Google Closure compiler for many years with advanced and every time I look at the code output I'm like "there's no way in a 100 years I would be able to de-obfuscate back to my own code to a great extent". But I don't specialize in reverse engineering, so I might be missing something big.
I guess ultra-shortening the names into a,b,c,d,e, etc makes it superficially hard to understand what's going on but I agree on your point about abstract logic.
It's so good.
You make data private by not giving it to people you don't trust, or by encrypting it and not giving the key to people you don't trust.
Otherwise, all bets are off.
These applications run on the back end. Some of the API facing VMs have been attacked and so to be honest I've configured them so that if someone did get access to them, they wouldn't find much. Maybe just some API keys I can invalidate. Although I probably won't do it -- an obfuscator like this could be very handy here.
I think the problem with this thread is people think I am writing browser code, or code that is going to be shared on GitHub.
I am not.
Also I'm only half joking as I've indicated with the "/s" below.
Well thanks for chiming in about a completely unrelated topic from website javascript. My comment wasn't getting downvoted until your slapfight with oauea blew up.
"It does not depend on a browser, so you can even run it on Node.js."
Seems like the logical solution would be to restrict access to it then, rather than obfuscate it making it harder for yourself to maintain. But hey, you do you.
I also wouldn't obviously edit the obfuscated production code, so it wouldn't really be a problem.
Also, why do you mind me doing that?
https://enkhee-osiris.github.io/Decoder-JSFuck/> We even made a few tweaks to the code so that you couldn't just reverse it back into JS with something like https://enkhee-osiris.github.io/Decoder-JSFuck/.
We even made a few tweaks to the code so that you couldn't just reverse it back into JS
This is why a lot of us keep our tools private... an old tradition of the cracking scene going back decades to the 80s. Think of things like IDA/Hexrays and Ghidra, then realise the most prolific crackers had similar private tools they had written many years before those appeared.
How ironic, that you want to open up other peoples code but keep your own hidden.
Irony would be applying obfuscation or other DRM protection techniques to tools intended to de-obfuscate/reverse engineer which are then distributed/sold. This is fairly common in commercial reverse engineering solutions, although I don't think the irony of the cat and mouse game is lost on the authors in that case...
eJztVUESwyAIfAs3GJ60w/+/UZKiUUwzztT20OZiwgIbWJXAwARTmMAX02qRr0o9Vu02xRmwgKUPTzHv0weu8bGtZFhKyKSnTK0Z/parAJ/VI5WyXp7Uo/HYNc3qNchzKWBACnpCK3uj3N1Quvs6qCSJ4Gvah+++VT9/q3AlWLH5Pg3/cRqO94lR5SM5T6rDKSelDOUKC0+EzQ36l5N/zR7lDqti9Xjsj3U71f4AduQBlR9rUg==
This is my recipe for minification:
1. Apply a convention where all class properties and methods have to end with a trailing underscore (it's trivial to make an Eslint rule to enforce it)
2. Use 2 minification tools in following order: Closure Compiler (simple optimizations mode), then Terser for best output.
3. Configure Terser mangle.properties.regex: /_$/
4. If it's a desktop app, use Bytenode for Node.js processes (cannot be used for the renderer)
[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[ ]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[] ])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+ (!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+ !+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![ ]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![] +[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[ +!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!! []+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![ ]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[ ]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[])[+!+[]]+(![ ]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+(! []+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[]) [+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]+[+!+[]]+( !![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[ ])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]])()
What is the result of:
[]+[]
And I didn’t know the answer to that (I mean, who does that kind of fuckery in Javascript, you can’t sum arrays). I would have no chance with these Google level questions.I’d just Google it.
Having interviewed people myself, I think that's an overly broad question to ask in an interview and if the candidate starts answering it as asked, then you're not going to get a lot of signal from it.
Otherwise I thought the problems asked weren't that difficult, one was even directly taken from Cracking the Coding Interview - if only I had read that chapter ahead of the interview...
You're kidding, right?
Summing arrays calls `.toString()` on them, and two empty string gives you a new empty string.
[].toString() === ''
[] + []
=== '' + ''
=== ''
https://github.com/denysdovhan/wtfjs#adding-arrays[ ‘foo’, ‘bar ] + [ ‘baz’ ] would return ‘foo,barbaz’
You might have a service that yesterday returned a JSON payload:
{ tasks: 5, ... }
but today returns: { tasks: [{...}, ...], ...}
If you had an array of these objects and were trying to sum the count of tasks, now your code returns weird results. Knowing how the JS engine's type coercion works is then invaluable for figuring out the problem quickly.Yes, it's shitty code, and a change of API like that is shitty. But we don't always get to choose what code we're interfacing with, particularly when it comes to web services.
Questions that allow a person to show their skill and their thought process are much more revealing. They're much harder to fake and bluff your way through for poor candidates and they allow good candidates to show their skill. They require a bit more effort from the interviewer though because there isn't just one right answer and you have to sacrifice the idea that you get an ego boost by dunking on some poor candidate with your trick question.
An example of a question I used to ask when interviewing candidates who said they were good at unix: "Say I have a directory full of files called a, b, c, etc and I want to rename them all to a.bar, b.bar, c.bar etc how do I do that"? Then I would follow up with "Ok now I have a directory full of files called a.bar, b.bar, c.bar etc and I want to rename them back to a, b, c, how do I do that?".
Now if you know unix you know there are a bunch of ways to do this, there are a bunch of traps you can fall into, what if there are too many files for shell expansion, what if the file names contain spaces etc. It's not hard for someone skillful to come up with a few ways that deal with these issues and if they can talk through how they did it and why then any of them are fine.
Edit to add: There is a kernel of value here though, which is say you were debugging a thing where the result was an empty string and you thought "wow, that makes no sense", maybe you get to understanding what went wrong when you see that two arrays are getting type coerced or something.
In practice, unless you have some extremely pedantic, end to end testing, your first hint that something is going wrong is probably going to be malformed output. TypeScript won't catch this error because it doesn't do runtime checking, it trusts that type annotations are correct. It's very possible for code like this to pass through without causing any exceptions to throw. Indeed, JavaScript was originally designed to "keep on trucking" in this way, and that's why we have this degree of type coercion. So you're going to be working backwards from a result rather than forward from a source. If you already know how your code works and you see a weird result like that, knowing the type coercion gotchas can help you work backwards to understanding where the change occurred.
But in the former issue, I don't think the question on its own is bad for job interviews. How the question is used is what determines if it's good or bad. For example, it is a little unreasonable to expect people to know every single, little gotcha in JavaScript and the exact way in which they misbehave. But I do think it's reasonable to expect people to know that there are gotchas and that this is a common one. I'd accept as a valid answer, "I don't know the exact results, but I do know that this doesn't concatenate arrays and instead does something unexpected".
If you ask about how to uppercase a string, certain constructs like []+[], or whether camelCase or PascalCase is superior you will get the people who know the answers to those questions.
Does ayone know of any similar-calibre sequels or similar vids?
Edit: Wait, there is also the unary + which takes only one argument, but it also could be considered arithmetic.
alert(1);
here's how you do it :https://enkhee-osiris.github.io/Decoder-JSFuck/
The same script also featured both of these equally-amusing obfuscations:
JSFuck – esoteric JavaScript - https://news.ycombinator.com/item?id=9479834 - May 2015 (38 comments)
JSFuck – Write any JavaScript with 6 Characters: []()!+ - https://news.ycombinator.com/item?id=6379732 - Sept 2013 (71 comments)
JSFuck []()+ Use only 6 characters to write any JavaScript - https://news.ycombinator.com/item?id=4421848 - Aug 2012 (1 comment)
Dang has his own tool, but it’s handy when he hasn’t done the search yet.
(The 1st such link, at the very top, emulates previous days’ front page.)
I mean... http://aem1k.com/world speaks for itself.
JSFuck was included in his presentation back then and boy did it inspire me to do more JS. Here we are, a little under 7 years later, still in the JS world.
Brainfuck is an unrelated, separate programming language.
With this I was able to get the letter 'a' by starting with their initial definition `(false+"")[1]`, then continually substituting
(false+'')[1]
(![]+'')[1]
(![]+([]+[]))[1]
(![]+([]+[]))[+!(+[])]
All of the above lines when evaluated result in 'a'.
1. [] => An array object
2. []["flat"] => The built in flat function on the Array object
3. []["flat"]["constructor"] => The constructor of any JS function is the Function constructor, which can take JavaScript, as a string, as its sole parameter. Thus, to create a function that executes any CODE_AS_STRING:
4. []["flat"]["constructor"](CODE_AS_STRING) => gives you the Function object, and finally:
5. []["flat"]["constructor"](CODE_AS_STRING)() => executes it
Thus, all that's left is to encode the strings "flat", "constructor" and CODE_AS_STRING using the patterns described early in that file.
There are some tasks which lend themselves to the way the language is constructed, and can be done with few instructions.
Reversing a string, for example, is just ,[[<]<+>>[>],]<[.<] which is quite short compared to most "practical" programs in this language.
And a destructive y = y + x is just [->+<] (destructive because this also sets x to zero)
I'm always fascinated by these "minimum viable language projects", since I think they sort of get into a fundamental concept: what is computing exactly?
[1] https://www.jtolio.com/2017/03/whiteboard-problems-in-pure-l...
wow this is exactly what I wanted!
[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+!+[]]+(+[![]]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+(+(!+[]+!+[]+!+[]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([]+[])[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][[]]+[])[+!+[]]+(![]+[])[+!+[]]+((+[])[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]]](!+[]+!+[]+!+[]+[!+[]+!+[]])+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]])()([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+!+[]]+([]+[])[(![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]()[+!+[]+[!+[]+!+[]]]+((![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[+!+[]]+[!+[]+!+[]]+([][[]]+[])[+[]]+(+(+!+[]+[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]]+[+[]])+[])[+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+([][[]]+[])[!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]]+[+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]]+[+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]])[(![]+[])[!+[]+!+[]+!+[]]+(+(!+[]+!+[]+[+!+[]]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([]+[])[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][[]]+[])[+!+[]]+(![]+[])[+!+[]]+((+[])[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]]](!+[]+!+[]+!+[]+[+!+[]])[+!+[]]+(![]+[])[!+[]+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[+[]]]((!![]+[])[+[]])[([][(!![]+[])[!+[]+!+[]+!+[]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]]()+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([![]]+[][[]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]](([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+!+[]]+(![]+[+[]])[([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]]()[+!+[]+[+[]]]+![]+(![]+[+[]])[([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]]()[+!+[]+[+[]]])()[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[+[]])[([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]]()[+!+[]+[+[]]])+[])[+!+[]])+([]+[])[(![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]()[+!+[]+[!+[]+!+[]]])())
/s
(well done btw)
location="http://y2u.be/dQw4w9WgXcQAdding two arrays together isn’t the problem, it’s a perfectly obvious thing to do. Adding two arrays together and getting a new language out of it is bonkers.
Edit to add: I work in JS/TS almost exclusively. This isn’t a chip on my shoulder criticizing a language I’m not invested in.
Though I'd still argue that the presence of both `==`/`!=` and `===`/`!==` is somewhat more indicative of flexibility than awfulness.