Coder en JavaScript avec seulement six caractères
Un tutoriel de Sylvain Pollet-Villard
Le 2013-07-08 08:35:04, par vermine, Expert éminent sénior
Sylvain Pollet-Villard s'ennuyait sûrement le jour où il eut l'idée saugrenue de coder du JavaScript avec le moins de caractères possibles. Et pourtant, il l'a fait ! Il nous explique les différentes étapes de sa démarche qui aboutit à la rédaction d'un compilateur.
N'hésitez pas à lui faire part de vos commentaires et remarques sur cette drôle de machinerie barbare.
-
OPiMembre actifPour Python cela me semble impossible, cela ne peut se faire qu'avec des langages à typage faible.
J'ai généré automatiquement les codes bien parenthésés d'une certaine longueur qui sont évaluées correctement.
Code : +!![]
Code : +!+[]
Code : 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22object 6 [[[]]] object 4 [[]] object 2 [] undefined undefined 6 [][[]] string 5 []+[] string false 6 []+![] object 0 5 [+[]] object false 5 [![]] object true 6 [!+[]] object true 6 [!![]] number 0 5 +[[]] number 0 3 +[] string 0 6 +[]+[] number NaN 6 +[![]] number 1 5 +!+[] number 1 5 +!![] boolean false 5 ![[]] boolean false 3 ![] string false 6 ![]+[] boolean true 6 !+[[]] boolean true 4 !+[] boolean true 4 !![]
Code : 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125var CHARS = ['[', ']', '+', '!', '(', ')']; /* changer ce tableau pour utiliser d'autres caractères */ var NB_CHARS = CHARS.length; var BALANCED_CHARS = {}; var CLOSE_CHARS = []; if ( CHARS.indexOf('[') >= 0 ) { BALANCED_CHARS['['] = ']'; CLOSE_CHARS.push(']'); } if ( CHARS.indexOf('(') >= 0 ) { BALANCED_CHARS['('] = ')'; CLOSE_CHARS.push(')'); } if ( CHARS.indexOf('{') >= 0 ) { BALANCED_CHARS['{'] = '}'; CLOSE_CHARS.push('}'); } var results = {}; /* Renvoie true si s est bien parenthésée, false sinon. */ function balanced(s) { 'use strict'; var s_LENGTH = s.length; var stack = []; var i; var c; for (i = 0; i < s_LENGTH; i++) { c = s[i]; if ( c in BALANCED_CHARS ) { stack.push(c); } else if ( CLOSE_CHARS.indexOf(c) >= 0 ) { if ( BALANCED_CHARS[stack.pop()] !== c ) { return false; } } } return (stack.length === 0); } /* Parcourt récursivement les chaînes jusqu'à une longueur num, tente de les évaluer et affiche les résultats non encore rencontrés ou déjà rencontrés mais au moins aussi long. */ function build_and_try_string(s, num) { 'use strict'; if ( num > 0 ) { var i; var c; for (i = 0; i < NB_CHARS; i++) { c = CHARS[i]; try_string(s + c); build_and_try_string(s + c, num - 1); } } } /* Affiche s */ function display(s) { try { // dans un navigateur document.write(s + '\n'); } catch ( err ) { // avec Rhino print(s); } } /* Tente d'évaluer s. Si l'évaluation s'est bien passée et que le résultat n'a pas encore été obtenu ou a déjà été obtenu avec une chaîne au moins aussi longue, alors affiche le résultat. BORD: ajoute l'éventuel élément affiché à results */ function try_string(s) { 'use strict'; if ( balanced(s) ) { var v; try { v = eval(s); } catch ( err ) { return; } var k = [typeof v, v]; if ( !(k in results) || (s.length <= results[k]) ) { results[k] = s.length; display((typeof v) + '\t' + v + '\t' + s.length + '\t' + s); } } } /* Main */ build_and_try_string('', 6);
le 10/07/2013 à 11:15 -
KaamoMembre éméritePour information, voici le sujet de la réflexion.
Sylvain, as-tu pu échanger avec le créateur de JSFuck ?le 08/07/2013 à 10:08 -
anykeyhMembre confirméBravo bon boulot!
En plus de la considération ludique, je trouve que c'est très instructif ce genre d'exploit!le 09/07/2013 à 11:35 -
SylvainPVRédacteur/ModérateurGood news everyone !
Je vous disais dans cet article publié il y a presque trois ans qu'il serait peut-être possible de descendre à 5 caractères. Une nouvelle piste est apparue avec la norme ECMAScript 6 et la fonction Array.prototype.find ! En effet, nous disposons de toutes les lettres de "find" grâce à undefined.
Cela permet donc de récupérer une fonction sans avoir besoin du caractère "!".Code : 1
2Array.prototype.find === [][[[]+[][+[]]][+[]][++[++[++[++[[]][+[]]][+[]]][+[]]][+[]]]+[[]+[][+[]]][+[]][++[++[++[++[++[[]][+[]]][+[]]][+[]]][+[]]][+[]]]+[[]+[][+[]]][+[]][++[[]][+[]]]+[[]+[][+[]]][+[]][++[++[[]][+[]]][+[]]]]
C'est un gros bond en avant, mais je n'ai pas réussi pour le moment à aller plus loin avec les 3 caractères +[]. En effet, les lettres C O V ne nous débloquent pas vraiment. Les seules nouvelles fonctions accessibles grâce à ces lettres sont #String.concat ou #Array.concat.
Pour aller plus loin, la piste la plus sérieuse serait de réussir à obtenir la valeur null, ce qui nous donnerait la lettre L puis la fonction #Function.call. A partir de là, tout est possibleMais aucune fonction accessible dans la norme ECMAScript actuelle ne nous renvoie null le 02/06/2016 à 0:16 -
SylvainPVRédacteur/ModérateurJe lui ai lâché un message sur le github du projet, mais pas de réponse pour le moment
Si on voulait vraiment pousser la réflexion jusqu'au bout, il faudrait travailler l'optimisation de toute la table de caractères, puis comparer la taille du code généré avec ou sans l'usage de String.fromCharCode
Mais je crois que ça dépasse le seuil d'intérêt que l'on puisse légitimement prêter à ce problèmele 08/07/2013 à 13:39 -
rambcMembre chevronnéTrès rigolo !!!
Existe-t-il un équivalent pour le langage Python ou est-ce propre à JS ?le 09/07/2013 à 20:01 -
SylvainPVRédacteur/ModérateurJe ne connais pas assez bien le Python pour répondre, mais je suis sûr que d'autres s'amuseraient beaucoup à faire la même chose sur d'autres langages
Envoyé par Quentin de Serres-Justiniac
Le code généré est largement plus long que l'original, comme tu as pu le constater si tu as essayé le compilateur. Eventuellement on pourrait s'y intéresser à des fins d'obfuscation de code extrême, mais je ne pense pas que ce soit la meilleure approche.le 10/07/2013 à 9:20 -
elias551Membre du Cluble 10/07/2013 à 17:06
-
SylvainPVRédacteur/ModérateurVoici une présentation en anglais parcourant de manière plus synthétique tout le cheminement pour arriver au compilateur:
http://slides.com/sylvainpv/xchars-js/
Le compilateur a également été mis à jour pour fonctionner avec Chrome, Firefox et Edge dans leurs dernières versions.
Dernière chose, une démonstration du 1K chess de Óscar Toledo G.convertie via 6chars.js est jouable ici : http://syllab.fr/projets/experiments/sixcharsjs/nanochess.html
Regardez la sourcele 05/06/2016 à 22:02