155

Recently a coworker showed this fragment of JavaScript code:

greet = "‮".toString.bind("hello world!")

If you paste this inside the Developer Console and execute it will print a "Hello, World!" message:

>> console.log(greet())
hello, world!

Another interesting thing I found is that if you paste the same greet code inside Node.js REPL it will automatically transpile it to a "readable" format.

How does this work? Why is this behaviour possible in a browser and why does Node.js automatically format it?

Igor F.
  • 2,649
  • 2
  • 31
  • 39
devaerial
  • 2,069
  • 3
  • 19
  • 33
  • 38
    Some sort of Unicode reverse bidi characters are involved in that. – deceze Jan 21 '20 at 09:00
  • 7
    It seems you have there right-to-left override symbol https://www.fileformat.info/info/unicode/char/202e/index.htm – Armen Stepanyan Jan 21 '20 at 09:01
  • 27
    You can see the text direction changes even in this page. Try to select the garbled code fragment. – Mindwin Remember Monica Jan 21 '20 at 21:25
  • 5
    Also note the syntax-highlighting in the snippet is correct (It doesn't show the `(` as part of the string - interestingly, that character is actually a `)` but the text-direction changes it!) – BlueRaja - Danny Pflughoeft Jan 21 '20 at 22:33
  • 1
    @BlueRaja-DannyPflughoeft I guess that actually makes sense - text highlight will go with the order of symbols and not the display order. It's still surprising when you look at it, though. – VLAZ Jan 22 '20 at 07:01
  • 13
    And this, dear friends, is why you should be very cautious when copy-pasting code from the Internet into your editor or console ... – Dubu Jan 22 '20 at 08:36
  • 4
    exactly the same, just in Java: [Why does this code, written backwards, print “Hello World!”](https://stackoverflow.com/q/43943699/995714) – phuclv Jan 22 '20 at 12:48
  • 1
    @Dubu: And even more cautious [opening e-mail attachments](https://krebsonsecurity.com/2011/09/right-to-left-override-aids-email-attacks/). – dan04 Jan 23 '20 at 00:11

2 Answers2

177

The actual code is:

greet = "...".toString.bind("hello world!")

Where the ... in the string literal are the bytes E2 80 AE, which is the right-to-left override Unicode character, which causes everything after it to be displayed in reverse. It's used for writing right-to-left languages like Arabic or Hebrew.

hex editors are your friend

deceze
  • 510,633
  • 85
  • 743
  • 889
  • 14
    Do these characters change the way my browser chooses to highlight on double click as well? when I try to double click OP's string it highlights the beginning quote, and end dot and end quote, nothing in between. Interesting. – Jordan.J.D Jan 21 '20 at 17:54
  • 11
    @Jordan.J.D yes, they should change selection appropriately in most software that handles RTL text properly. – Peteris Jan 21 '20 at 18:23
  • 46
    The RTL override is _not_ used for writing right-to-left languages. Those automatically render RTL. The bigger problem is shared characters like numbers. For those, the renderer has to _guess_ LTR vs RTL based on context. Developers insert the RTL override character to force the renderer to render neutral direction characters in the desired direction. – Mooing Duck Jan 21 '20 at 19:34
  • 2
    Note that if you need this character for BIDI text and are not deliberately trying to make your JS code look confusing, you'd write it as `\u202e`. – dan04 Jan 22 '20 at 04:37
  • 6
    @Moo It’s used *in the context of writing RTL languages in certain situations.* I didn’t want to go into too much detail as it’s irrelevant to this question. – deceze Jan 22 '20 at 04:57
  • Hold on... where is the `...` coming from? I don't see it in OPs code – Adelin Jan 23 '20 at 11:13
  • @Adelin It's an invisible character. Its only visible effect is the reversal of following characters. – deceze Jan 23 '20 at 11:17
76

You have hidden characters which reverse the text. Here you can see the raw characters: https://www.soscisurvey.de/tools/view-chars.php

enter image description here

feedy
  • 1,071
  • 5
  • 17
  • 30
    If I understand what you're saying, the basic answer is, this has nothing to do with Javascript whatsoever, and is just Unicode text rendering order, and the choice of using Javascript here is a red herring? – Jamin Grey Jan 21 '20 at 23:04
  • 4
    @JaminGrey apparently so. I suspect you can do the same in a Python or a Ruby REPL or many others. The only JavaScript trick here is the usage of `.bind` to create a bound function out of `toString`. This can easily be substituted with something like `"", console.log("hello world")` and you'd still get weird looking but executable code. – VLAZ Jan 22 '20 at 07:04
  • 1
    @JaminGrey Presumably, JavaScript was chosen because you can run its source code so easily. (Only needs a normal browser.) – knallfrosch Jan 22 '20 at 13:42
  • 2
    @JaminGrey I think it's more related to the Developer Console than to Javascript. Ruby and Python consoles simply display `"\u202E"` as an empty character and do not change the direction of the input, so `"hello world!"` is displayed as is, both in the input and output. Depending on your text editor, the script might be written right-to-left for the desired effect. Here's a [Ruby example](https://tio.run/##KypNqvz/P70oNbVEwVZB165a6VHDutSMnByF/PzynCLFFCW94tIkDX09fR11dU29dDBHQ08TiIAiMUYxhuqatdYFpSXFGmBD9DQ0Nf//BwA). – Eric Duminil Jan 22 '20 at 17:00