close icon
JavaScript

Stranger Scripts

This is a story of the odd and the strange. A story involving dimensions, monsters, and JavaScript

October 27, 2022

It is 1995, in a small US town. A group of friends is playing Dungeons & Dragons. When they see that Demogorgon enters the game, Brendan casts Fireball. He rolls the die, but it goes missing on the floor. They keep playing.

After the game ends, Brendan rides his bike through the woods, passing by the Netscape Communications Corporation. Then he sees something weird in front of him. He loses his balance, falls down a steep hill, and crashes.

The boy runs home. He's shivering as he looks back, ensuring that thing doesn't follow him. He arrives home only to find out no one is there. He tries to call his parents, but he can't get through.

Something unlocks the door. Brendan runs out to the backyard when he sees the thing. A light glows brightly and then fades, revealing no one is there anymore.

After ten days of searching, Brendan Eich reappears in the forest, but he is not alone. A yellow and mysterious creature is with him, with odd characteristics but a powerful presence.

JavaScript

It is too late for the world. JavaScript is out!

The Weirdo on Maple Street

Joey, Andrea, and Juan are wandering in the woods when they encounter JavaScript. They freeze as the programming language tries to communicate with them but can't figure out what it's trying to say.

With the help of an interpreter, they managed to capture the strange language, but what does it all mean?

In front of them lay the script

([![]] + [][[]])[+!+[] + [+[]]] + 
([![]] + [][[]])[+!+[] + [+!+[]+!+[]]]
+ " " +
(![] + [])[+[]] +
(![] + [])[+!+[]] +
([![]] + [][[]])[+!+[] + [+[]]] +
(![] + [])[!+[] + !+[]] + 
(![] + [])[+!+[]+!+[]+!+[]]

After some thought, the team got to work on the problem. They split it up into smaller chunks and worked it out.

First let's take a look at ([![]] + [][[]]) which is repeated throughout the snippet.

Breaking it down, even more, we get:

[![]] and we know that ![] is false, so we have [false] as a result.

Next, [][[]] looks confusing, but looking into more details, it follows this pattern: array[index] where array = [] and index = [], and accessing an empty array at any position, will return undefined, even if that position happens to be another array.

Putting this part of the script back together, we get:

([![]] + [][[]]) === [false] + undefined &&
[false] + undefined === 'falseundefined'

And so they replaced

'falseundefined'[+!+[] + [+[]]] + 
'falseundefined'[+!+[] + [+!+[]+!+[]]]
+ " " +
(![] + [])[+[]] +
(![] + [])[+!+[]] +
'falseundefined'[+!+[] + [+[]]] +
(![] + [])[!+[] + !+[]] + 
(![] + [])[+!+[]+!+[]+!+[]]

But then:

(![] + []) === 'false'

and

'falseundefined'[+!+[] + [+[]]] + 
'falseundefined'[+!+[] + [+!+[]+!+[]]]
+ " " +
'false'[+[]] +
'false'[+!+[]] +
'falseundefined'[+!+[] + [+[]]] +
'false'[!+[] + !+[]] + 
'false'[+!+[]+!+[]+!+[]]

Now we understand more. Using this strange language, we could decode strings. Since JavaScript allows us to access any character in a string by asking for its position, each particular line seems to be capturing a unique character on each string.

We have the strings, but we need a way to build up indexes; fortunately, there are a few tricks we can use.

For starters, thanks to Math in JavaScript, we know that +true === 1 and that +false === 0, why? the + sign at the beginning tells JavaScript to cast the boolean value to its numeric form.

Once we have those numbers, we can make any combination. For example, 2 can be written as +true+true, but what if we want something in the two digits order? It will take a long of those... Or we can use a different technique.

number1+[number2] === "numbernumber2", this happens because the sum now acts as a concatenate and converts each side of the + sign into a string. This is done by design, as JavaScript can't add an array to an integer.

Finally, we can use this little array to bool conversion table to get our numbers:

+[] -> +false -> 0
!+[] -> !false -> true
+!+[] -> +true -> 1

Now that we can form single and two-digit numbers, we can easily convert all the indexes into numbers or strings and form our final answer:

'falseundefined'['10'] + 
'falseundefined'['12']
+ " " +
'false'[0] +
'false'[1] +
'falseundefined'['10'] +
'false'[2] + 
'false'[3]

Now, we have to count.

i
e
" "
f
a
i
l
s

That's it! He is trying to say, "ie fails"!

Holly, Jolly, and The Body

Carla, Brendan's mom, is sure that he is trying to communicate with her through the lights of her house. Carla is determined to find out, so she elaborates on a simple math test.

"Brendan, can you hear me?" she asks. If you can hear me, tell me, what is 1 + 1, and the lights go on and off two times.

For the second test, 3 + 1, the lights go on and off four times.

Is this a coincidence? She is, by now, freaking out.

"3" - 1, and the lights go twice.

It has to be him! One more to be sure

"3" + 1, but the lights start a different show this time. They go on and off for a while. When they stopped, she had counted "31".

Maybe I am a mess; maybe I'm crazy, she concluded. What kind of math is that?

She doesn't know JavaScript, or she would have understood. The lights were correct, according to JavaScript, of course.

If the same happens to you, remember, in JavaScript.

Number + Number -> addition
Boolean + Number -> addition
Boolean + Boolean -> addition
Number + String -> concatenation
String + Boolean -> concatenation
String + String -> concatenation

For example:

3 - 1 // -> 2
 3 + 1 // -> 4
'3' - 1 // -> 2
'3' + 1 // -> '31'

'' + '' // -> ''
[] + [] // -> ''
{} + [] // -> 0
[] + {} // -> '[object Object]'
{} + {} // -> '[object Object][object Object]'

'222' - -'111' // -> 333

[4] * [4] // -> 16
[] * [] // -> 0
[4, 4] * [4, 4] // NaN

The Flea and the Acrobat

Tony, the local chief of police, who starts to believe in Carla's story, decides to break into the Netscape Communications Corporation, looking to learn more about JavaScript.

Juan, Andrea, and Joey, who had a conversation with Brendan, believe that JavaScript came from an alternate dimension, the "Upside Down".

In this dimension, there are special considerations, he adds. For example,

Math.min() > Math.max(); // -> true
Math.min() < Math.max(); // -> false

Intuitively it is strange, but in the JavaScript dimension, it makes sense, as

Math.min(); // -> Infinity
Math.max(); // -> -Infinity
Infinity > -Infinity; // -> true

But why does Math.min() === Infinity? Math.min takes arguments, tries to convert each one to a number, and then it returns the smallest of them. If you don't provide any arguments, the result is Infinity.

And the opposite thing happens to Math.max.

Meanwhile, Tony had an encounter.

The Monster and The Upside Down

Deep in the lab, where the shadows cover the rooms, Tony feels there's something around. He calls in for backup. On the other side, Greg and Dan are on their way.

Juan, Andrea, and Joey know that the only way to conquer JavaScript is to enter into its dimension, so they fire up a terminal and open the portal. They all jump inside.

In the lab, another portal opens. Tony, who already met with Greg and Dan, gets inside, and the portal collapses right after.

From the shadows, a strange passage appears. It contains a challenge, "solve me, and I'll let you go!"

['1', '7', '11'].map(parseInt);

Intuitively, the group tries to guess the first answer, [1, 7, 11], but Juan, Andrea, and Joey stop them before they can input it.

In this place, not all things are what they look like, so we must treat arguments very carefully, mentioned Juan.

Carla, who found her way to the "Upside Down", provided some more insights into the problem.

The function parseInt expects two parameters, a string and the radix. The latter is an integer between 2 and 36, representing the base in mathematical numeral systems.

So the map function could be providing more than one argument, so more than just the string to the parseInt function, added Joey.

Breaking it down, the team formed the following statement:

['1', '7', '11'].map((currentValue, index, array) => parseInt(currentValue, index, array));

The index from the map function is passed to the parseInt function as the radix, and thus, the resulting value would be different from the expected.

So the team calculates each value:

parseInt('1', 0) // 1
parseInt('7', 1) // NaN
parseInt('11', 2) // 3

So the final result is [1, NaN, 3].

As they type it in, the dimension starts shaking, and a new portal opens up.

They all rush out. "We are safe. We are back home", they rejoiced.

But that thing is still out there. Let's get it - Tony.

The team prepares for battle...

To be continued.


I hope you enjoyed this little informative parody of Stranger Things, our treat for this Halloween.

  • Twitter icon
  • LinkedIn icon
  • Faceboook icon