2017-01-22 21 views
3

JavaScriptファイルの内容を状態Aから状態BにAST変換するとします。AST変換に基づいてJavaScriptソースマップを生成するにはどうすればよいですか?

付随するソースマップを作成するにはどうすればよいですか?私はesprimaestravese(estraverse.replace)を使用してASTをトラバースしています(最初のASTに対応するソースマップがあります)、別のASTに変換します(ただし、結果のソースマップはありません)。

どうすればそのソースマップを入手できますか?

EDIT:AST変換を行うにはesprimaestraverseを使用しています。

module.exports = { 

    type: 'replace', // or traverse 

    enter(node, parent) { 

     if (
      node.type == 'ExpressionStatement' 
      && parent.type == 'Program' 
      && node.expression.type == 'CallExpression' 
      && node.expression.callee.name == 'module' 
     ) { 
      // rename `module` to `define` 
      node.expression.callee.name = 'define' 

      // The dependency object (the `{a:'./a', b:'./b'}` in `module({a:'./a', b:'./b'}, function(imports) {})`) will be... 
      const dependenciesObjectExpression = node.expression.arguments[0] 

      // ...converted into an array of paths (the `['./a', './b']` in `define(['./a', './b'], function(a,b) {})`), and... 
      const dependencyPathLiterals = 
       dependenciesObjectExpression.properties.map(prop => prop.value) 

      // ...the dependency names will be converted into parameters of the module body function (the `a,b` in `define(['./a', './b'], function(a,b) {})`). 
      const dependencyNameIdentifiers = 
       dependenciesObjectExpression.properties.map(prop => prop.key) 

      // set the new define call's arguments 
      node.expression.arguments[0] = { 
       type: 'ArrayExpression', 
       elements: dependencyPathLiterals, 
      } 
      node.expression.arguments[1].params = dependencyNameIdentifiers 

      return node 
     } 

     // if we see `imports.foo`, convert to `foo` 
     if (
      node.type == 'MemberExpression' 
      && node.object.type == 'Identifier' 
      && node.object.name == 'imports' 
     ) { 
      return { 
       type: 'Identifier', 
       name: node.property.name, 
      } 
     } 
    }, 

    leave(node, parent) { 
     // 
    } 

} 
+0

"sourcemap" とは何ですか? –

+0

... aha:定義されているソースマップ:https://www.html5rocks.com/en/tutorials/developertools/sourcemaps/ –

答えて

2

あなたが書き込むツリー変換ごとに、対応する変換をソースマップに書き込んでいます。

ツリー変換は基本的に任意であるため、対応するソース変換も任意です。同様に、複雑なツリー変換は、対応して複雑なソースマップ変換を引き起こす。

これを実装する1つの方法は、(これらが存在すると仮定して)ツリー変換操作のDeleteNode、ReplaceNode、ReplaceChildWithIdentifier、ReplaceChildWithLiteral、ReplaceChildWithOperatorを選択することです。これらの操作だけを使用すると、依然として任意のツリーを変更することができます。これらの操作を変更してソースマップを更新すると(各ソースマップはソースマップに非常に特化しています)、更新されたソースマップを「無料で」取得する必要があります。明らかに、これらのプリミティブを使用して実装されていない限り、他のツリー変更操作を使用することはできません。この目的のためのコミュニティで

カップルツール:

+0

こんにちはIra、この初期のお返事ありがとうございます。 AST変換がどのように見えるかを表示するために質問を更新しました。それに基づいた提案はありますか? – trusktr

+0

私はそのHTML5の記事を読んでいます!私は使いやすいツールがあることを期待していた... – trusktr

+0

私は提案したもののようなルーチンの呼び出しであなたのノードの更新を置き換える必要があります。最も基本的なツリー操作でタップするだけで、単純なトレースメカニズムを実装してソースマップを更新できますか?あなたが持っている(複雑な)呼び出しを使うならば、ソースマップの変更は非常に複雑になり、手作業でそれらをコーディングする必要があるでしょう。簡単なアウトはありません。 (「使いやすいツール」はすでにこれを実行していなければなりません; esprima内に既に組み込まれている使いやすいツールが必要ですが、それはすでに見つかりません)。 –

関連する問題