跳至正文
LNN的博客!

JvavScript

JvavScript是我提出的一个基于JavaScript的深奥编程语言,是JavaScript的一个子集,也是JSFuck的一个超集。JvavScript代码符合JavaScript表达式的语法,然而只能使用有限的几种字符:

( ) [ ] < > + - ! , = ? : _ $

并且为了使代码稍简洁些,定义了几个常量:

const _ = alert, __ = prompt, $ = String.fromCharCode, $$ = this;

JSFuck基本混淆手法

JSFuck
"" +[]
false ![]
true !![]!+[]
0 +![]
1 +!![]+!+[]

Hello world

_($(
 +!+[]+[]+(+[])-(+!+[]+!+[]+!+[])+[]+(+!+[]+!+[]),
 +!+[]+[]+(+[])+(+!+[]),
 +!+[]+[]+(+[])+(+!+[]+[]+(+[])-(+!+[]+!+[])),
 +!+[]+[]+(+[])+(+!+[]+[]+(+[])-(+!+[]+!+[])),
 +!+[]+[]+(+!+[])+(+!+[]),
 +!+[]+!+[]+!+[]+!+[]+[]+(+!+[]+!+[]+!+[]+!+[]),
 +!+[]+!+[]+!+[]+[]+(+!+[]+!+[]),
 +!+[]+[]+(+!+[])+(+!+[]+[]+(+[])-!+[]),
 +!+[]+[]+(+!+[])+(+!+[]),
 +!+[]+[]+(+!+[])+(+!+[]+!+[]+!+[]+!+[]),
 +!+[]+[]+(+[])+(+!+[]+[]+(+[])-(+!+[]+!+[])),
 +!+[]+[]+(+[])+(+[]),
 +!+[]+!+[]+!+[]+[]+(+!+[]+!+[]+!+[])
))

运行以上代码会输出

Hello, world!

以上代码的实质:

alert(String.fromCharCode(
 1 + "" + 0 - (1 + true + true) + "" + (1 + true), // "72"
 1 + "" + 0 + 1, // "101"
 1 + "" + 0 + (1 + "" + 0 - (1 + true)), // "108"
 1 + "" + 0 + (1 + "" + 0 - (1 + true)), // "108"
 1 + "" + 1 + 1, // "111"
 1 + true + true + true + "" + (1 + true + true + true), // "44"
 1 + true + true + "" + (1 + true), // "32"
 1 + "" + 1 + (1 + "" + 0 - true), // "119"
 1 + "" + 1 + 1, // "111"
 1 + "" + 1 + (1 + true + true + true), // "114"
 1 + "" + 0 + (1 + "" + 0 - (1 + true)), // "108"
 1 + "" + 0 + 0, // "100"
 1 + true + true + "" + (1 + true + true) // "33"
))

brainfuck解释器

为了证明JvavScript不用太多地依赖JSFuck编码JavaScript源代码也能做到图灵完备,我写了一个brainfuck解释器:

_((($_,_$$,__$)=>$_($_,_$$,+[],__$,+[],[]+[],[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+!+[]]+(+[![]]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+(+(!+[]+!+[]+!+[]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([]+[])[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][[]]+[])[+!+[]]+(![]+[])[+!+[]]+((+[])[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]]](!+[]+!+[]+!+[]+[!+[]+!+[]])+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]])()(([][[]]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(+(!+[]+!+[]+!+[]+[!+[]+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([]+[])[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][[]]+[])[+!+[]]+(![]+[])[+!+[]]+((+[])[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]]](!+[]+!+[]+!+[]+[!+[]+!+[]+!+[]])+(+[![]]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+!+[]]]+(+(+!+[]+(!+[]+[])[!+[]+!+[]+!+[]]+[+!+[]]+[+[]]+[+[]]+[+[]])+[])[+[]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(+[]+[][([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]+(!![]+[])[+!+[]]+(![]+[])[+!+[]]+(+[![]]+[+(+!+[]+(!+[]+[])[!+[]+!+[]+!+[]]+[+!+[]]+[+[]]+[+[]]+[+[]])])[+!+[]+[+[]]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[+!+[]+[!+[]+!+[]+!+[]]]+[!+[]+!+[]+!+[]]+[+[]]+[+[]]+[+[]]+[+[]]+([+[]]+![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[!+[]+!+[]+[+[]]]),+[]))(($_,_$$,_$$_,__$,__$_,$$_,$__,$__$)=>(
 _$$[_$$_]?
  _$$[_$$_]==([]+[])[([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]]()[+[]]?
   $_($_,_$$,_$$_+!![],__$,__$_,$$_,$__,$__$?$__$-!![]:!![]+!![]+!![]+[]+(+[])+(+[])+(+[])+(+[])-!![])
  :_$$[_$$_]==([]+[])[([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]]()[!+[]+!+[]]?
   $_($_,_$$,_$$_+!![],__$,__$_,$$_,$__,$__$==!![]+!![]+!![]+[]+(+[])+(+[])+(+[])+(+[])-!![]?+[]:$__$+!![])
  :(
   _$$[_$$_]==(+((+(+!+[]+[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]]+[+[]])+[])[+!+[]]+[+[]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[+!+[]]])+[])[!+[]+!+[]]?
    ($__[$__$]--,[])
   :_$$[_$$_]==(+(+!+[]+(!+[]+[])[!+[]+!+[]+!+[]]+[+!+[]]+[+[]]+[+[]])+[])[!+[]+!+[]]?
    ($__[$__$]++,[])
   :_$$[_$$_]==(+(+!+[]+[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]]+[+[]])+[])[+!+[]]?
    ($$_+=$($__[$__$]),[])
   :_$$[_$$_]==[[]][([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]([[]])+[]?
    ($__[$__$]=__$[__$_]?__$[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(+(+!+[]+[+[]]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([]+[])[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][[]]+[])[+!+[]]+(![]+[])[+!+[]]+((+[])[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]]](!+[]+!+[]+[+!+[]])[+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+!+[]]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+!+[]]+(+[![]]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(+(!+[]+!+[]+[+!+[]]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([]+[])[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][[]]+[])[+!+[]]+(![]+[])[+!+[]]+((+[])[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]]](!+[]+!+[]+!+[]+[+!+[]])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]])()(([]+[])[([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]]())[!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(+[]+[][([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+[]]](__$_++):-!![],[])
   :[][[]]
  )?
   $_($_,_$$,_$$_+!![],__$,__$_,$$_,$__,$__$)
  :_$$[_$$_]==([][(!![]+[])[!+[]+!+[]+!+[]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]]()+[])[+[]]?
   $_($_,_$$,$__[$__$]?_$$_+!![]:(($_$,_$$,_$$_)=>$_$($_$,_$$,_$$_,+[]))(($_$,_$$,_$$_,_$)=>(
    _$$[_$$_]?
     _$$[_$$_]==([][(!![]+[])[!+[]+!+[]+!+[]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]]()+[])[+[]]?
      $_$($_$,_$$,_$$_+!![],_$+!![])
     :_$$[_$$_]==([][(!![]+[])[!+[]+!+[]+!+[]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]]()+[])[!+[]+!+[]+[!+[]+!+[]]]?
      _$?$_$($_$,_$$,_$$_+!![],_$-!![]):_$$_+!![]
     :$_$($_$,_$$,_$$_+!![],_$)
    :_$$_
   ),_$$,_$$_+!![]),__$,__$_,$$_,$__,$__$)
  :_$$[_$$_]==([][(!![]+[])[!+[]+!+[]+!+[]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]]()+[])[!+[]+!+[]+[!+[]+!+[]]]?
   $_($_,_$$,$__[$__$]?(($_$,_$$,_$$_)=>$_$($_$,_$$,_$$_,+[]))(($_$,_$$,_$$_,_$)=>(
    _$$[_$$_]?
     _$$[_$$_]==([][(!![]+[])[!+[]+!+[]+!+[]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]]()+[])[!+[]+!+[]+[!+[]+!+[]]]?
      $_$($_$,_$$,_$$_-!![],_$+!![])
     :_$$[_$$_]==([][(!![]+[])[!+[]+!+[]+!+[]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]]()+[])[+[]]?
      _$?$_$($_$,_$$,_$$_-!![],_$-!![]):_$$_+!![]
     :$_$($_$,_$$,_$$_-!![],_$)
    :+[]
   ),_$$,_$$_-!![]):_$$_+!![],__$,__$_,$$_,$__,$__$)
  :$_($_,_$$,_$$_+!![],__$,__$_,$$_,$__,$__$)
 :$$_
),__(([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]),__(([![]]+[][[]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(+(!+[]+!+[]+[+!+[]]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([]+[])[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][[]]+[])[+!+[]]+(![]+[])[+!+[]]+((+[])[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]]](!+[]+!+[]+!+[]+[+!+[]])[+!+[]]+([][[]]+[])[+[]]+(!![]+[])[+[]])))

由于用递归代替循环,所以太过复杂的brainfuck代码可能会无法执行,比如目前最短的Hello world:

+[-->-[>>+>-----<<]<--<---]>-.>>>+.>>..+++[.>]<<<<.+++.------.<<-.>>>>+.

它在我的浏览器上会报错(递归次数过多)。不过,这个Hello world在我的浏览器上可以运行:

++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.

代码中时常出现的大段只由 ()+[]! 组成的部分,是用JSFuck编码的字符串。(还有一个表达式 new Int8Array(30000) 也是用JSFuck编码的。)

未经混淆的JavaScript源代码:

alert(((func, code, input) => func(func, code, 0, input, 0, "", new Int8Array(30000), 0))((func, code, codePointer, input, inputPointer, output, memory, memoryPointer) => (
 code[codePointer] ?
  code[codePointer] == "<" ?
   func(func, code, codePointer + 1, input, inputPointer, output, memory, memoryPointer ? memoryPointer - 1 : 29999)
  : code[codePointer] == ">" ?
   func(func, code, codePointer + 1, input, inputPointer, output, memory, memoryPointer==29999 ? 0 : memoryPointer + 1)
  : (
   code[codePointer] == "-" ?
    (memory[memoryPointer]--, 1)
   : code[codePointer] == "+" ?
    (memory[memoryPointer]++, 1)
   : code[codePointer] == "." ?
    (output += String.fromCharCode(memory[memoryPointer]), 1)
   : code[codePointer] == ", " ?
    (memory[memoryPointer] = input[inputPointer] ? input.charCodeAt(inputPointer++) : -1, 1)
   : undefined
  ) ?
   func(func, code, codePointer + 1, input, inputPointer, output, memory, memoryPointer)
  : code[codePointer] == "[" ?
   func(func, code, memory[memoryPointer] ? codePointer + 1 : ((func2, code, codePointer) => func2(func2, code, codePointer, 0))((func2, code, codePointer, count) => (
    code[codePointer] ?
     code[codePointer] == "[" ?
      func2(func2, code, codePointer + 1, count + 1)
     : code[codePointer] == "]" ?
      count ? func2(func2, code, codePointer + 1, count-1) : codePointer + 1
     : func2(func2, code, codePointer + 1, count)
    : codePointer
   ), code, codePointer + 1), input, inputPointer, output, memory, memoryPointer)
  : code[codePointer] == "]" ?
   func(func, code, memory[memoryPointer] ? ((func2, code, codePointer) => func2(func2, code, codePointer, 0))((func2, code, codePointer, count) => (
    code[codePointer] ?
     code[codePointer] == "]" ?
      func2(func2, code, codePointer-1, count + 1)
     : code[codePointer] == "[" ?
      count ? func2(func2, code, codePointer-1, count-1) : codePointer + 1
     : func2(func2, code, codePointer-1, count)
    : 0
   ), code, codePointer - 1) : codePointer + 1, input, inputPointer, output, memory, memoryPointer)
  : func(func, code, codePointer + 1, input, inputPointer, output, memory, memoryPointer)
 : output
), prompt("code"), prompt("input")))

2022-12-04 更新(写于 2022-11-13)

前几天翻看本页时,发现上述 brainf 解释器代码中用 JSFuck 编码的部分太长,可以大幅优化。如表达式 new Int8Array(30000) 被表示为 Function("return eval")()("new Int8Array(30000)"),其中 Function 构造函数来自 []["flat"]["constructor"],且完全没有使用 JvavScript 中定义的常量;应当使用 $$["eval"]("new Int8Array(30000)") 代替。

随后我萌生了一个想法,即编写一个程序来找出用尽可能短的 JvavScript 表达式来获得任意的双精度浮点数或字符串值的方法。

JvavScript 中存在比 [] 更短的真值($_),而且允许减号,因此很多基本值的编码结果会比 JSFuck 更短:

JSFuck JvavScript
false ![] !_
true !+[] !!_
1 +!+[] +!!_
"10" +!+[]+[+[]] [+!!_]+-[]
7 !+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[] [+!!_]+-[]-!!_-!!_-!!_

语法比 JSFuck 更丰富的代价是,要找到最佳的编码方案变得极为困难。用 "10" 减去 3 个 true(22 字节)要比 7 个 true 相加(27 字节)短许多,这一点尚且比较容易确定;若是数字稍大一些,恐怕情况会变得极其复杂。譬如编码数字 179:

方案 JvavScript 长度 (字节)
+("1" + "7" + "9") +(+!!_+[[+!!_]+-[]-!!_-!!_-!!_]+[[+!!_]+-[]-!!_]) 49
+("17" + "9") +([!!_+!!_]+-[]-!!_-!!_-!!_+[[+!!_]+-[]-!!_]) 45
200 - 21 [!!_+!!_]+-[]+-[]-(!!_+!!_+[+!!_]) 34
180 - 1 +!!_+[[+!!_]+-[]-!!_-!!_]+-[]-!!_ 33

本着知难而进的精神,我成功写出了一个懂得减法的数字编码程序(源代码),可以编码任意双精度浮点数,只是在特定情况下长度可能并不是最优。

正当我信心满满朝着字符串进军时,未曾设想的情况出现了。一部分字符除了可以通过字符编码获得外,还可以通过其他方式获得(如 (false + [])[0] 返回 "f"),我称之为“简单编码”。在众多选择的排列组合中找到最短方案不是一件容易的事。有的字符如果单独出现,用简单编码更短;但如果夹在两个字符编码之间,则不如也用字符编码,这样就可以省去一套函数名、函数调用的括号和两个加号 )+ +$(,只在两边用逗号分隔。下面的图示展示了编码字符串 "Hello" 的多种可行思路:

流程图中有上下两条主干线,上方是简单编码,下方是字符编码。每个编码字符开始前都有一条路可以从简单编码模式经过“$(”进入字符编码模式,每个字符后也有一条路可以从字符编码模式经过“)”回到简单编码模式。相邻的两个简单编码之间用“+”连接,相邻的字符编码之间则是“,”。起点和终点都在简单编码线上。第一个字符为大写字母 H,只能走字符编码线,途径数字 72;小写字母 e 可以选择简单编码“(true+[])[3]”或字符编码 101;两个小写字母 l 分别可以选择简单编码“(false+[])[2]”或字符编码 108;最后小写字母 o 可以选择简单编码“($$+[])[1]”或字符编码 111。

另外,当字符串恰好包含一些简单值(如 false)的字符串形式时也可以将简单值整个嵌入进去;数字还可以通过减法获得。要想找出最短的编码方式,就需要在类似上图甚至更复杂的路线图中找出最佳的路线,我判断这对于编码一个字符串来说要求过高了。因此最后我决定采取最通用的方法,只使用 String.fromCharCode() 来获得字符串。


回到 brainf 解释器的问题上。为了体现 JvavScript 不需要 eval()Function() 也能活得好好的(草),我们使用反射(en)来调用构造函数 Int8Array

$$["Reflect"]["construct"]($$["Int8Array"], [30000])

代码中还用到了几个字符串,它们也可以使用字符编码来获得。下面是修改后的代码。

_((($_,_$$,__$)=>$_($_,_$$,+[],__$,+[],[]+[],$$[$([+!!_]+-[]-!!_-!!_+[!!_+!!_],[+!!_]+-[]+(+!!_),[+!!_]+-[]+(!!_+!!_),+!!_+[+!!_]+-[]-!!_-!!_,[+!!_]+-[]+(+!!_),[+!!_]+-[]+-[]-!!_,+!!_+[+!!_]+(!!_+!!_+!!_+!!_+!!_+!!_))][$([+!!_]+-[]+-[]-!!_,+!!_+[+!!_]+(+!!_),+!!_+[+!!_]+-[],+!!_+[+!!_]+(!!_+!!_+!!_+!!_+!!_),+!!_+[+!!_]+(!!_+!!_+!!_+!!_+!!_+!!_),+!!_+[+!!_]+(!!_+!!_+!!_+!!_),+!!_+[!!_+!!_]+-[]-!!_-!!_-!!_,[+!!_]+-[]+-[]-!!_,+!!_+[+!!_]+(!!_+!!_+!!_+!!_+!!_+!!_))]($$[$([+!!_]+-[]-!!_-!!_-!!_+[!!_+!!_+!!_],+!!_+[+!!_]+-[],+!!_+[+!!_]+(!!_+!!_+!!_+!!_+!!_+!!_),!!_+!!_+!!_+!!_+!!_+[!!_+!!_+!!_+!!_+!!_+!!_],!!_+!!_+!!_+!!_+!!_+!!_+[!!_+!!_+!!_+!!_+!!_],+!!_+[+!!_]+(!!_+!!_+!!_+!!_),+!!_+[+!!_]+(!!_+!!_+!!_+!!_),[+!!_]+-[]+-[]-!!_-!!_-!!_,+!!_+[!!_+!!_]+(+!!_))],[[!!_+!!_+!!_]+-[]+-[]+-[]+-[]]),+[]))(($_,_$$,_$$_,__$,__$_,$$_,$__,$__$)=>(
 _$$[_$$_]?
  _$$[_$$_]==$([!!_+!!_+!!_+!!_+!!_+!!_]+-[])?
   $_($_,_$$,_$$_+!!_,__$,__$_,$$_,$__,$__$?$__$-!!_:[!!_+!!_+!!_]+-[]+-[]+-[]+-[]-!!_)
  :_$$[_$$_]==$(!!_+!!_+!!_+!!_+!!_+!!_+[!!_+!!_])?
   $_($_,_$$,_$$_+!![],__$,__$_,$$_,$__,$__$==[!!_+!!_+!!_]+-[]+-[]+-[]+-[]-!!_?+[]:$__$+!!_)
  :(
   _$$[_$$_]==(-!!_+[])[+[]]?
    ($__[$__$]--,!!_)
   :_$$[_$$_]==$(!!_+!!_+!!_+!!_+[!!_+!!_+!!_])?
    ($__[$__$]++,!!_)
   :_$$[_$$_]==$(!!_+!!_+!!_+!!_+[!!_+!!_+!!_+!!_+!!_+!!_])?
    ($$_+=$($__[$__$]),!!_)
   :_$$[_$$_]==$(!!_+!!_+!!_+!!_+[!!_+!!_+!!_+!!_])?
    ($__[$__$]=__$[__$_]?__$[$([+!!_]+-[]+-[]-!!_,[+!!_]+-[]+(!!_+!!_+!!_+!!_),[+!!_]+-[]+-[]-!!_-!!_-!!_,+!!_+[+!!_]+(!!_+!!_+!!_+!!_),[+!!_]+-[]+-[]-(!!_+!!_+!!_+[!!_+!!_+!!_]),+!!_+[+!!_]+(+!!_),[+!!_]+-[]+-[],[+!!_]+-[]+(+!!_),!!_+!!_+!!_+!!_+!!_+!!_+[!!_+!!_+!!_+!!_+!!_],+!!_+[+!!_]+(!!_+!!_+!!_+!!_+!!_+!!_))](__$_++):-!!_,!!_)
   :!_
  )?
   $_($_,_$$,_$$_+!!_,__$,__$_,$$_,$__,$__$)
  :_$$[_$$_]==$([+!!_]+-[]-!!_+[+!!_])?
   $_($_,_$$,$__[$__$]?_$$_+!!_:(($_$,_$$,_$$_)=>$_$($_$,_$$,_$$_,+[]))(($_$,_$$,_$$_,_$)=>(
    _$$[_$$_]?
     _$$[_$$_]==$([+!!_]+-[]-!!_+[+!!_])?
      $_$($_$,_$$,_$$_+!![],_$+!!_)
     :_$$[_$$_]==$([+!!_]+-[]-!!_+[!!_+!!_+!!_])?
      _$?$_$($_$,_$$,_$$_+!!_,_$-!!_):_$$_+!!_
     :$_$($_$,_$$,_$$_+!!_,_$)
    :_$$_
   ),_$$,_$$_+!!_),__$,__$_,$$_,$__,$__$)
  :_$$[_$$_]==$([+!!_]+-[]-!!_+[!!_+!!_+!!_])?
   $_($_,_$$,$__[$__$]?(($_$,_$$,_$$_)=>$_$($_$,_$$,_$$_,+[]))(($_$,_$$,_$$_,_$)=>(
    _$$[_$$_]?
     _$$[_$$_]==$([+!!_]+-[]-!!_+[!!_+!!_+!!_])?
      $_$($_$,_$$,_$$_-!!_,_$+!!_)
     :_$$[_$$_]==$([+!!_]+-[]-!!_+[+!!_])?
      _$?$_$($_$,_$$,_$$_-!![],_$-!!_):_$$_+!!_
     :$_$($_$,_$$,_$$_-!!_,_$)
    :+[]
   ),_$$,_$$_-!!_):_$$_+!!_,__$,__$_,$$_,$__,$__$)
  :$_($_,_$$,_$$_+!!_,__$,__$_,$$_,$__,$__$)
 :$$_
),__($([+!!_]+-[]+-[]-!!_,+!!_+[+!!_]+(+!!_),[+!!_]+-[]+-[],[+!!_]+-[]+(+!!_))),__($([+!!_]+-[]+(!!_+!!_+!!_+!!_+!!_),+!!_+[+!!_]+-[],+!!_+[+!!_]+(!!_+!!_),+!!_+[!!_+!!_]+-[]-!!_-!!_-!!_,+!!_+[+!!_]+(!!_+!!_+!!_+!!_+!!_+!!_)))))

以上 brainf 实现中,EOF 后再读取输入会返回 -1。若要让 EOF 不改变当前单元格值可将这行代码

    ($__[$__$]=__$[__$_]?__$[$([+!!_]+-[]+-[]-!!_,[+!!_]+-[]+(!!_+!!_+!!_+!!_),[+!!_]+-[]+-[]-!!_-!!_-!!_,+!!_+[+!!_]+(!!_+!!_+!!_+!!_),[+!!_]+-[]+-[]-(!!_+!!_+!!_+[!!_+!!_+!!_]),+!!_+[+!!_]+(+!!_),[+!!_]+-[]+-[],[+!!_]+-[]+(+!!_),!!_+!!_+!!_+!!_+!!_+!!_+[!!_+!!_+!!_+!!_+!!_],+!!_+[+!!_]+(!!_+!!_+!!_+!!_+!!_+!!_))](__$_++):-!!_,!!_)

替换为

    (__$[__$_]?($__[$__$]=__$[$([+!!_]+-[]+-[]-!!_,[+!!_]+-[]+(!!_+!!_+!!_+!!_),[+!!_]+-[]+-[]-!!_-!!_-!!_,+!!_+[+!!_]+(!!_+!!_+!!_+!!_),[+!!_]+-[]+-[]-(!!_+!!_+!!_+[!!_+!!_+!!_]),+!!_+[+!!_]+(+!!_),[+!!_]+-[]+-[],[+!!_]+-[]+(+!!_),!!_+!!_+!!_+!!_+!!_+!!_+[!!_+!!_+!!_+!!_+!!_],+!!_+[+!!_]+(!!_+!!_+!!_+!!_+!!_+!!_))](__$_++)):_,!!_)

或者若需要 EOF 返回 0,可将前者中的“:-!!_”改为“:+[]”。

若要在运行完成后输出整个内存纸带中的值,可将倒数第二行“:$$_”替换为“:(_($__),$$_)”。


尽管修改后的 brainf 解释器代码更短了,但调用堆栈溢出的问题还没有解决,稍微长一点的循环就会让解释器报错。这一点理论上应该可以优化,但是我懒得弄了。就这样吧。

顺带补充一下对于四个预定义常量的规定,之前的说明并不够清楚。

  • _ 函数接受一个参数,默认值为空字符串,将该参数的内容以字符串形式输出。输出到终端时,末尾应添加换行符。返回 undefined
  • __ 函数接受两个参数 messagedefaultValue。若 message 不为 undefined 则仿照 _ 函数的方法输出 message,然后要求一行输入,若 defaultValue 不为 undefined,则以其字符串形式作为输入框的初始内容。返回一个字符串,不包含末尾的换行符(如果有),但如果用户取消输入或 EOF,则应返回 null
  • $ 函数在被调用时的行为必须与 String.fromCharCode() 相同。
  • $$ 对象必须是当前环境下的全局作用域。

对于这四个函数或对象转换成字符串的结果不再做要求。对这些常量赋值的效果是未定义的,因此它们可以实际上不是常量。

另外,JvavScript 并没有允许代码包含空白字符,但一般为了可读性(大嘘)还是需要使用一定的换行和缩进。现规定空白字符只能在不影响语法的情况下使用,即删去所有空白后代码的含义必须与原来一致。如“[-!!_]+ +!!_”是不允许的,因为删去空格后两个加号会变成一个递增操作符,导致语法错误;需要改成“-!!_+[+!!_]”。这也意味着不可以用换行来代替分号。

一个按照上述规定运行 JvavScript 代码的函数:

function executeJvavScript(code) {
  var match = code.match(/[^()[\]<>+\-!,=?:_$\s]/)
  if (match)
    throw new SyntaxError(`Code contains invalid character ‘${match[0]}’`)
  code = code.replace(/\s+/g, "")
  var fun = new Function("_", "__", "$", "$$", code)
  fun(alert, prompt, String.fromCharCode, self)
}

评论区

加载基于 GitHub issues 的 utteranc.es 评论区组件……