javascript - 高速化 - peg js online




軽量のjavascriptからjavascriptのパーサー (4)

あなたがすべてのプログラムの状態にアクセスして復元したいと考えると、あなたの仕事は簡単ではないと思います。 問題の1つは、計算中にいつでもプログラムの状態を取得する必要があるかもしれないということです。 つまり、示されている例が正しくないことを意味します。 そのコードを実行する前に状態の種別を取得します(ただし、魔法を初期化する合計を事前計算し、元のJavaScriptのコードが実行される前には発生しません)。 私はあなたが実行中に任意の瞬間に状態をキャプチャしたいかもしれないと仮定します。

あなたの問題を述べたやり方は、JavaScriptでJavaScriptパーサーが必要なのでしょうか? 私はあなたがあなたの既存のJavaScriptコードJにそのようなJavaScriptパーサーを含め、あなたの結果のコードGを生成するために必要なことを想像していると仮定していると仮定していると仮定します。Jが起動すると、それを読み込む。 (私はGがJavaScriptのすべてを扱うことができれば、Gはかなり大きいと思います)JavaScriptイメージにはJ、大きなG、Sが含まれており、起動時に高価な操作(JからGへのフィード)を行います。

私があなたに役立つと思われるのは、オリジナルのJavaScriptコードJをオフラインで処理するツールGであり、実行のためにJに追加/置換できるプログラム状態/終了シリアル化コードS(その状態を保存して復元する)を生成します。 J + Sはクライアントに送信されますが、クライアントやGの実行は見られません。 これは、Sの生成をJのランタイム実行から切り離し、クライアントの実行時間とスペースを節約します。

この場合、そのようなコードの生成を最も簡単にするツールが必要です。 純粋なJavaScriptパーサーはスタートですが、十分ではありません。 どのファンクションコードがファンクションコールF(...)に接続されているかを知るためにシンボルテーブルのサポートが必要で、スコープ内のどの変数定義が変数Vへの代入やアクセスに対応しているかを確認する必要があります。 Jを使用して、プログラム状態をキャプチャできるアクセスポイントを挿入します。 いくつかの値がどこにあるかを調べるためにフロー分析が必要な場合があります。 JavaScriptでこのすべてを主張すると、ソリューションの範囲が狭くなります。

これらのタスクでは、 プログラム変換ツールが役立つ可能性があります。 このようなツールには、目的の言語のパーサが含まれており、プログラムを表すASTを構築し、識別子から定義のマップ(「シンボルテーブル」)を構築したり、アクセスポイントの挿入を表すASTを修正したり、ASTあなたのデモンストレーションの例を表現し、修正されたJと追加Sを含む有効なJavaScriptコードを再生成します。私が知っているすべてのプログラム変換システム(Wikipediaサイトのものすべてを含みます)ではJavaScriptで実装されていません。

私たちのDMSソフトウェアリエンジニアリングツールキットは、今説明したすべての機能を提供するプログラム変換システムです。 (はい、大きくて退屈な、実際のコンピュータ言語の複雑さに対応する必要があります)。 これには、AST向けの完全なJavaScriptパーサを含むJavaScriptフロントエンドと、修正または合成されたASTからJavaScriptコードを再生成するための機械が含まれています 。 (また、大きくて退屈な、良いものは、年長者+老人はまだひどいです)。 DMSが有用であれば、DMSはビルド制御とデータフロー分析をサポートします。

どのように私は軽量のJavaScriptをJavaScriptのパーサーに書くことになるだろう。 いくつかのコードスニペットを変換できる単純なもの。

私は基本的に関数の内部スコープオブジェクトを公開する必要があります。

だからこのようなもの

var outer = 42;
window.addEventListener('load', function() {
   var inner = 42;
   function magic() {
       var in_magic = inner + outer;
       console.log(in_magic);
   }
   magic();
}, false);

コンパイルする

__Scope__.set('outer', 42);
__Scope__.set('console', console);
window.addEventListener('load', constructScopeWrapper(__Scope__, function(__Scope__) {
    __Scope__.set('inner', 42);
    __Scope__.set('magic',constructScopeWrapper(__Scope__, function _magic(__Scope__) {
        __Scope__.set('in_magic', __Scope__.get('inner') + __Scope__.get('outer'));
        __Scope__.get('console').log(__Scope__.get('in_magic'));
    }));
    __Scope__.get('magic')();
}), false);

デモンストレーションの例

この背後にある動機は、関数とクローズの状態をシリアライズし、異なるマシン(クライアント、サーバー、複数のサーバー)間で同期を維持することです。 このために私は[[Scope]]表現が必要です

質問:

  1. 完全なJavaScript - >(わずかに異なる)JavaScriptコンパイラを記述しなくても、この種のコンパイラを実行できますか?
  2. どのように私はそのようなコンパイラを書くつもりですか?
  3. 既存のjs - > jsコンパイラを再利用できますか?

あなたの問題は、JS OpfuscatorsとJS Compressorで解決されているものと同じ問題のファミリーになること - JSを解析して同等のスクリプトに再フォーマットする必要があること、

ここ難読化に関する良い議論がありました。あなたの問題に対する可能な解決策は、FOSSのバージョンの1つの解析と生成の部分を活用することでした。

コールアウトの1つで、サンプルコードでは、設定/取得する変数のスコープを考慮していないため、最終的に解決しなければならない問題になります。

添加

クロージャ定義関数のスコープの問題がある場合、スコープを解決/保存して再インスタンス化するためにクロージャの外側のスコープ変数をインポート/エクスポートする必要があるため、静的解析問題としてこの問題を解決することはできません。 したがって、評価エンジン自体を掘り下げ、V8エンジンを入手し、インタープリタそのものをハックする必要があるかもしれません。これは、これがジェネリック・クロスのすべてのスクリプト・エンジンである必要はなく、それを結びつけることができると仮定していますあなたがコントロールする単一の実装にまで下がります。


単純なインターフェースで何かをしたいのなら、node-burritoを試すことができます: https://github.com/substack/node-burrito : https://github.com/substack/node-burrito

uglify-jsパーサーを使用してASTを生成し、ノードを再帰的に歩きます。 あなたがしなければならないことは、各ノードをテストする単一のコールバックを与えることだけです。 変更が必要なものを変更すると、結果のコードが出力されます。


私は変更する既存のパーサーを探してみようと思います。 おそらくあなたはJSLint / JSHintを適応させることができますか?





compiler-construction