5

私は過去数日間、基本的なライブ評価のjavascript開発環境(私はそれをWEPLと呼んでいます)を構築してきましたが、エラーメッセージを行番号に関連付けることができれば素晴らしいと思いました。残念ながら、eval()は、これを行うための優れた方法を提供していません。

私がこれまでに思いついた解決策は、eval()の前にソースを変換して、eval()のラッパーへのネストされた呼び出しのセットになるようにすることです。これは、evalの前にいくつかの情報を記録し、evalが成功するかどうかを確認します。次に、その情報を使用して、より有用なトラブルシューティング情報をユーザーに出力します。

私の質問は、なぜこれが悪い考えなのかということです。これがうまく機能することを確認するには、どのような問題を解決する必要がありますか?

これを具体的にするために、私が意味する一種の変換の例。

これ

if (cond) {
  return foo + bar;
}
else {
  return baz + quux;
}

これになります

if (myEval('cond')) {
  return myEval("myEval(\"foo\") + myEval(\"bar\")");
else {
  return myEval("myEval(\"baz\") + myEval(\"quux\")");
}

私は明らかに最高レベルをラップしませんでしたが、プログラムバージョンはラップしました。

4

2 に答える 2

3

リモートで複雑なスクリプトでも受け入れたい場合、これは機能しません。いくつかの潜在的な問題:

範囲

var i = 1; // global scope
!function() {
    var i = 2; // function scope
}();
alert(i); // 1

対。

myEval('var i = 1;'); // global scope
myEval('!function() {
    myEval(\'var i = 2;\'); // eval has global scope, always
}();');
myEval('alert(i);'); // 2

クロージャ

!function() {
    var i = 1; // local to outer function
    !function() { // inherits context from outer function
        alert(i); // 1
    }();
}();

対。

myEval('!function() {
    myEval(\'var i = 1;\'); // local to outer function
    myEval(\'!function() { // eval has global scope; myEval inherits from wherever it was defined
        myEval(\\\'alert(i);\\\'); // undefined
    }();\');
}();');

これ

var obj = {
    n: 1,
    f: function() {
        return this.n; // this is the object f is called from
    }
}
alert(obj.f()); // 1

対。

myEval('var obj = {
    n: myEval(\'1\'),
    f: myEval(\'function() {
           return myEval(\\\'this.n\\\'); // this is always the window in eval
       }')
}');
myEval('alert(obj.f());'); // undefined

クリープを逃れる

すべての引用符をエスケープする必要があり、エスケープ記号もエスケープする必要があります。オブジェクト、クロージャ、内部関数などがたくさんあるコードでは、これによりエスケープ記号が管理できなくなります。

!function() {
    $(function() {
        $('#foo').click(function() {
            setTimeout(function() {
                $.post('/', function(res) {
                     log(res);
                });
            }, 1000);
        });
    });
}();

(これは特に工夫された、または複雑な例ではないことに注意してください。特定のイベントでコールバックが発生する、委任されたアクションのみが含まれます)

myEval('!function() {
    myEval(\'$(myEval(\\\'function() {
        myEval(\\\\\\\'$(\\\\\\\'#foo\\\\\\\').click(myEval(\\\\\\\\\\\\\\\'function() {
            myEval(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'setTimeout(myEval(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'function() {
                myEval(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'$.post('/', myEval(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'function(res) {
                     myEval(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'log(res);\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\');
                }\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'));\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\');
            }\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'), 1000);\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\');
        }\\\\\\\\\\\\\\\'));\\\\\\\');
    }\\\'));\');
}();');

あなたはおそらく私が何をしているのかを見ることができます。

于 2012-09-16T20:39:02.563 に答える
2

IEの拡張機能で作業するときは、同様のことをしなければなりませんでした。最終的に「lineNumber」というグローバル変数を作成し、コードを次のように変換しました。

lineNumber = 1; if (cond) {
  lineNumber = 2; return foo + bar;
}
else {
  lineNumber = 5; return baz + quux;
}

もちろん、すべてのブロックを中かっこで囲み、コーディングを単純にして、貧弱なラメパーサーを混乱させないようにする必要がありましたが、それでうまくいきました。

于 2012-09-14T20:48:53.587 に答える