Acorn-cspのできた流れ
RReverser/acorn-csp についての話
- Not working for web workers · Issue #90 · marijnh/acorn
- acornが
new Function
を使うので、CodeMirror経由でacorn使ってる人等がひっかかる - Chrome Appとかも同じ問題
- @RReverserさんがAST変換をしたCSP対応バージョンを作る - Not working for web workers · Issue #90 · marijnh/acorn
RReverser/acorn-csp は recastを使ってAST変換をしてる。
アプローチ
new Function
はmakePredicate
という関数のみで使ってるので、
これを置き換えた関数に一度書き換えてる。
acorn/acorn.js at a246bf83d00f6888268997dbf55533bb33e66bd3 · marijnh/acorn
'function makePredicate(words) {' + ' var generatedFn = _makePredicate(words);' + ' makePredicateCache[words] = generatedFn.toString();' + ' return generatedFn;' + '}'
書き換えた関数は、オリジナルのmakePredicate
の実行結果をキャッシュにいれていくだけ。
(元コード見てないけど、多分これでnew Function
によって展開されたものを回収してそう)
書き換えたものをnodeのvmモジュールを使って、 evalを展開した中身を回収してる。
var makePredicateCache = {}; // makePredicateCache[words] に値をnew Functionの結果を入れていってる vm.runInNewContext( recast.prettyPrint(ast).code, {makePredicateCache: makePredicateCache} );
最後、展開した中身をもう一度AST変換して、最初に書き換えていたmakePredicate
が、
先ほど作った展開済みの値を返すように書き換えてる。
properties: Object.keys(makePredicateCache).map(function (key) { var fnNode = esprima.parse('(' + this[key] + ')').body[0].expression; fnNode.id = null; return { type: 'Property', kind: 'init', key: {type: 'Literal', value: key}, value: fnNode }; }, makePredicateCache)
vmモジュールを使ってインライン展開チックな事やってるのが面白い