Hieroglyphy: Taking JavaScript Type Coercion to its Illogical Conclusion
Table of Contents
- But Why?
- Pulling Ourselves Up By Our Bootstraps
- Pulling Some Strings
- What Have We Achieved So Far?
- Extracting Characters From Keywords
- Tricks With Big Numbers
- So Where Are We Now?
- Tricks With Functions
Introduction
The functionality described in this blog is neither new nor is it unique. In this case, it is an extensive rewrite and optimisation of the original Hieroglyphy by Patricio Palladino.
Here is my version of Hieroglyphy.
Other variations of this style of app exist that use a minimal alphabet, but in this particular case, a close-to-minimal alphabet has been chosen.
WARNING
I can think of no practical reason why you would ever want to use this library in a real life situation…🤪
But that said, the process by which it works is interesting if you really want to understand the inner workings of JavaScript’s type coercion behaviour
Overview
There has been some investigation into encoding the source code of a JavaScript program such that it uses a reduced alphabet, but remains syntactically valid and executable.
The object of the exercise here is not to create a program that remains human readable, but one that can be eval
ed and executed.
For example:
$ node
Welcome to Node.js v16.12.0.
Type ".help" for more information.
> eval('(+((+!![]+[])+(!![]+!![]+!![]+!![]+!![]+!![]+!![]+[])))[(!![]+[])[+[]]+([]+{})[+!![]]+([]+([]+{})[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[!![]+!![]+!![]+!![]+!![]]+([][+[]]+[])[+!![]]+([]+([]+{})[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[+((+!![]+[])+(!![]+!![]+!![]+!![]+[]))]](+((!![]+!![]+!![]+[])+(!![]+!![]+!![]+!![]+!![]+!![]+[])))+(!![]+[])[!![]+!![]+!![]]+(![]+[])[!![]+!![]]+(![]+[])[!![]+!![]]+([]+{})[+!![]]')
'hello'
>
Room from improvement
This library is just a proof of concept; there is plenty of room for improvement:
- Ensure that all characters have been encoded using the shortest possible representation
- Allow some flexibility in the alphabet size to account for different target runtime environments
- Knowing the specific runtime would allow us to take advantage of features unique to that environment, which in turn, may yield shorter character encodings