2009-08-17 11 views
31

TL; DR:Array.prototypeおよびFunction.prototypeに組み込み関数を追加すると、IE8のネイティブJSONパーサーがJSONを解析する際にスタックオーバーフローを引き起こします。 JSON.parse()にリバーブ関数を渡した場合にのみ、配列が含まれます。IE8のネイティブJSON.parseのバグでスタックオーバーフローが発生する

これは質問から始まりましたが、自分のオリジナルの質問に答えましたので、私は質問します:このIE8バグの回避策は誰でも、修正するすべてのJSライブラリArray.prototypeとFunction.prototype?

オリジナル質問:

は、私は約13K JSONデータの解析する必要があります。データの構造は、ネストされた配列である単一の値を持つオブジェクトです。

{ 'value':[[ stuff ], [ more stuff], [ etc ]] } 

私はjson2.jsを使用しています。利用可能な場合は、ブラウザのネイティブJSON.parseを使用しています。リバース機能をJSON.parseに渡して、日付を適切に処理しています。 IE8がIE7エミュレーションモード(スクリプトベースのjson2.jsパーサーを使用するようになります)では、すべて正常に動作します。 IE8がIE8モード(ブラウザ固有のJSONパーサーを使用する)になると、「スタック領域外」というエラーが発生します。 FirefoxとChromeはもちろん、ブラウザ固有のJSONパーサーでうまく動作します。

これまでに絞り込んだことは、何もしないリバイバー関数をJSON.parseに渡すと、IE8のネイティブパーサーがスタックオーバーフローを取得することです。リバース機能を渡さないと、IE8のネイティブ・パーサーは正常に動作しますが、日付の解析は正しく行われません。

// no error: 
JSON.parse(stuff); 

// "out of stack space" error: 
JSON.parse(stuff, function(key, val) { return val; }); 

私は以下のデータまたはデータの少ないネスティングがエラーを避けることができるかどうかを確認するために、私のJSONデータを再生するために行くんだけど、誰もが前にこれを見ていた、または任意の他の提案した場合、私は思っていました回避策。 IE8の速度はまだ十分ですが、このバグのためにそのブラウザのネイティブJSONを無効にすることは残念です。

更新:別のJSONデータを使用すると、IE8のネイティブパーサーをリバース機能で使用すると「$ lineinfo is undefined」というjavascriptエラーが発生します。リバース機能を使用しないとエラーは発生しません。文字列 "$ lineinfo"は私のソースコードのどこにも表示されません。

更新2:実際、この問題はプロトタイプ1.6.0.3によって発生しているようです。プロトタイプライブラリに追加するまで、孤立したテストページで再現できませんでした。

UPDATE 3:

prototype.jsのは、IE8ネイティブJSONパーサーはこれです壊す理由:Array.prototypeをする任意の非組み込み関数を追加し、Function.prototypeはIE8ネイティブJSONパーサーを取得させますリバンバ関数をJSON.parse()に渡した場合にのみ、配列を含むJSONを解析する際にスタックオーバーフローが発生します。

Prototypeライブラリは、Array.prototypeとFunction.prototypeの両方に関数を追加しますが、これは同じことを行う他のライブラリにも等しく適用されます。 IE JSONパーサーのこのバグは、PrototypeとExtでは公開されていますが、jQueryでは公開されていません。私は他のフレームワークをテストしていません。

ここでは、完全に独立して問題を再現しています。 Function.prototype行またはArray.prototype行を削除するか、配列をJSON文字列から削除すると、「スタック領域外」エラーは発生しません。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 

<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
    <title></title> 
<script type="text/javascript"> 

Function.prototype.test1 = function() { }; 
Array.prototype.test2 = function() { }; 

window.onload = function() 
{ 
    alert(JSON.parse('{ "foo": [1,2,3] }', function(k,v) { return v; })); 
} 

</script> 
</head> 
<body> 

</body> 
</html> 
+3

JavaScriptチームは、これがJavaScriptエンジンの既知の問題であると報告しています。ありがとう。 – EricLaw

+0

私にお知らせいただきありがとうございます。 –

答えて

2

ここで大丈夫動作するようです:(インストール同じWindows上のInternet Explorerの複数のコピーを実行しようとしている?)問題が壊れInternet Explorer 8のいずれかがインストールされ

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html> 
<head> 
<title>Test</title> 
</head> 
<body> 
<pre> 
<script type="text/javascript"> 
document.writeln(''); 
var o = { 
    "firstName": "cyra", 
    "lastName": "richardson", 
    "address": { 
     "streetAddress": "1 Microsoft way", 
     "city": "Redmond", 
     "state": "WA", 
     "postalCode": 98052 
    }, 
    "phoneNumbers": [ 
     "425-777-7777", 
     "206-777-7777" 
    ] 
}; 
var s = JSON.stringify(o); 
document.writeln(s); 
var p = JSON.parse(s, function (key, val) { 
    if (typeof val === 'string') return val + '-reviver!'; 
    else return val; 
}); 
dump(p); 

function dump(o) { 
    for (var a in o) { 
     if (typeof o[a] === 'object') { 
      document.writeln(a + ':'); 
      dump(o[a]); 
     } else { 
      document.writeln(a + ' = ' + o[a]); 
     } 
    } 
} 
</script> 
</pre> 
</body> 
</html> 

かあなたの入力は悪いです。

Native JSON in IE8もお読みください。この特定の段落は、関心のあることがあります

オプション引数はポスト 変化を解析するために使用されるユーザー 定義関数である復活します。結果のオブジェクトまたは配列 は再帰的に横断され、復唱者 関数がすべてのメンバーに適用されます。 各メンバーの値は、復唱者によって返された の値に置き換えられます。 reviverがnullを返すと、オブジェクト のメンバーが削除されます。トラバーサルと 呼び戻しの呼び出しは ポストオーダーで行われます。そのとおり;すべてのオブジェクト はの後に '復活' です。そのメンバーはすべて '復活しました'です。

上記の段落では、私の復活祭の機能がどのように見えるのかを説明しています。テストコードでの私の最初の試みでした:このリバイバー関数はそのすべての子に適用された後、上記addressノードに適用されている場合

function (key, val) { 
    return val + '-reviver!'; 
} 

は明らかに、私は完全にaddressオブジェクトを破壊してきました。

もちろん、reviverのテストがあなたの質問に簡単に記述されている場合は、グローバル循環参照の一部が表示されている問題につながっている可能性は低いです。私はまだそれが壊れたInternet Explorerまたは悪いデータを指していると思う。

あなたはedit your questionと問題を示す実際のデータのサンプルを投稿できますので、ここで試すことができますか?

+0

ありがとう - それは何とかして、プロトタイプが原因です。 +1の徹底的な対応! –

3

私はこの質問をしばらくの間受け入れていないので、それを取り除くために、私は自分自身で答えるだろう。 Microsoftの

エリック法律は言う:

JavaScriptのチームは、これはJavaScriptエンジンの既知の問題であることを報告します。

5

ソリューションは、IE8にネイティブJSON.parseを削除し、JSONでそれを置き換えることです。

追加:json2.js LIBから解析

<script type="text/javascript"> 
if (jQuery.browser.msie && jQuery.browser.version.indexOf("8.") === 0) { 
    if (typeof JSON !== 'undefined') { 
     JSON.parse = null; 
    } 
} 
<script> 

...そして、次のとおりです

<script type="text/javascript" src="json2.js"></script> 

これは、独自のバージョン

// json2.js 
... 
if (typeof JSON.parse !== 'function') { 
    JSON.parse = function (text, reviver) { 
... 
とJSON.parseを置き換えるためにjson2トリガされます

その後、解析が再び機能するはずです。

この方法の1つの問題は、json2.js解析メソッドがネイティブの解析メソッドよりも遅いことです。

+0

私は同じ問題を抱えています。 IE8で動作するにはJSON.parserが必要です。私はあなたの推薦をした、それは私のために働いていない。他のブラウザでも動作します。何か案は? – user1471980

-2
eval(Ext.decode("{"foo":"bar"}")); 

IE 8でのオブジェクトに文字列を変換しています。

2

(静止IE9に存在する)は、この問題の拡張がある場合、ネイティブJSON.stringify関数がIEをクラッシュある:

  1. ラージオブジェクトグラフ
  2. オブジェクトグラフ参照jQueryの 'データオブジェクト。
  3. オブジェクトグラフは円形です。

クラッシュの原因となる特定の点は不明です。

このインスタンスの回避策は、stringify関数のreplacer関数を使用して特定のオブジェクトプロパティにnullを返し、オブジェクトグラフが横断されないようにすることでした。

関連する問題