トップ回答者
XPSP3+IE8でwindow.open後に再読込みが発生しエラーとなる

質問
-
表題の件ですが、以下の現象について質問させてください。
[環境]
OS:Windows XP SP3 もしくは Windows Vista Business SP2
IE:8
[現象と発生手順]
メール末尾のサンプルスクリプト(現象発生部分を抜粋)を参照ください。
1.parent.htmlを開き「子画面を開く」ボタンを押下する
2.child.htmlが開き、「initchild」のダイアログが表示されるので、「OK」ボタンを押下する
3.再度「initchild」のダイアログが表示される
→なぜかchild.htmlが再ロードされてしまう
4.openerオブジェクトがnullのエラーが表示され停止する
[補足説明]
処理の内容としては、子ウィンドウから親ウィンドウのxmlノードにアクセスし、
clonenodeした途端に、子ウィンドウが再ロードされてしまいます。
[その他特記事項]
・IE7およびIE6では同現象が発生しません(エラーが発生しない)
・IE8においても以下のTabProcGrowthのレジストリ(新規ウィンドウを開く際、新しくプロセスを作らない)
をあてると発生しなくなります
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Main]
"TabProcGrowth"=dword:00000001
[質問]
IE8の動作に起因した問題と思い、本フォーラムに質問させていただきました。
原因および解決策についてご教授いただきたくお願いいたします。
[サンプルスクリプト]parent.html ------------------------------------------------ <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Expires" CONTENT="-1"/> <meta http-equiv="Content-Script-Type" content="text/javascript"/> <script type="text/javascript" src="parent.js" charset="UTF-8"></script> <title>親ウインドウ</title> </head> <body onload="initParent()"> <form id="form1" name="form1"> <input id="button1" name="button1" type="button" onClick="window.open('child.html', 'child', 'width=200,height=100,menubar=no,scrollbars=no,toolbar=no, top=200, left=100')" value="子画面を開く"> </form> </body> </html> ------------------------------------------------ child.html ------------------------------------------------ <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Expires" CONTENT="-1"/> <meta http-equiv="Content-Script-Type" content="text/javascript"/> <script type="text/javascript" src="child.js" charset="UTF-8"></script> <title>子ウインドウ</title> </head> <body onload="initchild()"> <form id="form2" name="form2"> <input id="button1" name="button1" type="button" value="孫画面を開く"> </form> </body> </html> ------------------------------------------------
parent.js ---------------------------------------------------------------- var AX_MSXML = "MSXML2.DOMDocument"; var g_xml; function initParent() { alert("initparent"); g_xml=new ActiveXObject(AX_MSXML); g_xml.async=false; g_xml.load("param.xml"); } ---------------------------------------------------------------- child.js ---------------------------------------------------------------- var AX_MSXML = "MSXML2.DOMDocument"; var g_childxml; function initchild() { alert("initchild"); g_childxml = new ActiveXObject(AX_MSXML); g_childxml.async=false; g_childxml.documentElement = opener.g_xml.documentElement.cloneNode( true ); var i; i = 100; //デバッガ停止用ステップ } ----------------------------------------------------------------
param.xml ------------------------------------------------------ <?xml version="1.0" encoding="UTF-8"?> <Param> <aaa>test1</aaa> <bbb>test2</bbb> </Param> ------------------------------------------------------
回答
-
先にも書いたように、文字列経由にすることで、うまくいきませんか?(XMLオブジェクトの生成元は子側で!)
この方法であれば、初期構築以降の操作も動作するはずなのですが。g_childxml.documentElement = opener.g_xml.documentElement.cloneNode( true );
↓
g_childxml.loadXML( opener.g_xml.xml);それでもダメなら、documentElementはかなり特殊な要素なはずで、そのCloneのみがダメなのであって、他の要素のClone&insertは動く可能性も少なくないと思っています。
色々試してみませんか?(すでに調査済みならすみません)
すべての返信
-
再現しませんでした(´・ω・`)
当方の環境は、XP SP3&IE8とWin7&IE8です。TabProcGrowthを設定していないことは確認しました。(親ウィンドウと子ウィンドウが別プロセスで動作していることも確認しています)(ネットワークはローカルイントラネットだったり、インターネットゾーン&保護モードだったり)
再現しないとは、3.再度「initchild」のダイアログが表示される→なぜかchild.htmlが再ロードされてしまう4.openerオブジェクトがnullのエラーが表示され停止するの両方ともになります。
nb2000さんの環境ではTabProcGrowthを設定した場合、3番、4番両方とも再現しなくなるということでしょうか?しかし、原因不明の再ロードが発生してしまうと、openerがnullになるのはどうしようもなさそうですね。
なので、再ロードが走る条件とタイミングを調査していきたい。「cloneNodeした途端」とは、opener.g_xml.documentElement.cloneNode( true );を変形してvar o = opener;o = o.g_xml;o = o.documentElement;o = o.cloneNode(ture); ←このメソッドを呼び出したタイミングで同期ブロックされて、このメソッドが完了する前にchild.htmlのinitchildが呼び出されopenerがnullとなった
と解釈しましたがよいでしょうか?
やはり、onloadイベント以外で(マウスクリックなど)上記のメソッドを呼び出したとしても再現するのでしょうか?実際のコードはjQueryの$()のタイミングだったりするとかありますか?少しだけ遅らせてみると動作が変わったりしませんかね?setTimeout(function(){g_childxml.documentElement = opener.g_xml.documentElement.cloneNode( true );
}, 1000);
質問ばかりですみません。 -
(´・ω・`)さん
返信どうもありがとうございます。
情報を提供いただける方に限って再現しなく残念です。
取り急ぎ、質問に回答させていただきます。
>nb2000さんの環境ではTabProcGrowthを設定した場合、3番、4番両方とも再現しなくなるということでしょうか?→そうです。TabProcGrowthを設定した場合は、3,4いずれも発生しません。
>←このメソッドを呼び出したタイミングで同期ブロックされて、このメソッドが完了する前にchild.htmlの initchildが呼び出されopener
>がnullとなった>と解釈しましたがよいでしょうか?→試してみたら違いました。(解析能力低く申し訳ありません)
上記までは、うまくいきました
次にg_childxml.documentElement にoを代入する時点でchild.htmlのinitchildが呼び出されopenerがnullとなりました。
>やはり、onloadイベント以外で(マウスクリックなど)上記のメソッドを呼び出したとしても再現するのでしょうか?→再現しました。ボタンのonclickイベントで試してみました。
>実際のコードはjQueryの$()のタイミングだったりするとかありますか?→ほとんど実際のコードに近いです。恥ずかしながら、jQueryなどのライブラリは使用しておりません。→1000msecと5000msecで試してみましたが、現象は変わりませんでした。
>少しだけ遅らせてみると動作が変わったりしませんかね?
-
再現しました(`・ω・´)
こちらでは、アクセス違反例外(0xc0000005)が発生しました。
(この部分はさっくり削って確認しちゃっていました。申し訳ないです。一番疑うべき箇所だったのに。。。)nb2000さんの環境ではクラッシュして自動回復か何かのために再ロードが行われたのでしょうかね。
WinDbgの出力は以下になりました。
(2508.2548): Access violation - code c0000005 (!!! second chance !!!) eax=068e3a68 ebx=06ae0120 ecx=068e3a68 edx=00000002 esi=068e3a68 edi=00000000 eip=5b7cb614 esp=0238d278 ebp=0238d284 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202 msxml3!Document::setRoot+0x13: 5b7cb614 f6430b1f test byte ptr [ebx+0Bh],1Fh ds:0023:06ae012b=?? STACK_TEXT: 0238d284 5b7dd793 06ae0120 0238d638 5b8509ac msxml3!Document::setRoot+0x13 0238d2dc 5b7dcac4 068e4700 057da3a4 0238d638 msxml3!DOMDocumentWrapper::putref_documentElement+0x92 0238d2f8 5b7bd847 068e4700 00000028 0238d324 msxml3!DOMDocumentWrapper::_invoke+0x90 0238d430 5b7bdb93 068e4700 00000000 00000028 msxml3!_dispatchImpl::InvokeHelper+0x109 0238d46c 5b7dd2c9 5b8509ac 068e4700 00000028 msxml3!_dispatchImpl::Invoke+0x5e
そんなことよりも回避策ですが、
子ウィンドウでXMLオブジェクトを作成させるのではなく、親ウィンドウで作成すればいけませんかね。こちらではいけているようです。parent.jsに追加 -------------------------------------------------------------- function getXMLObject(){ var xml = new ActiveXObject(AX_MSXML); xml.async = false; return xml; } ------------------------------------------------------------- child.js ---------------------------------------------------------------- // g_childxml = new ActiveXObject(AX_MSXML); // g_childxml.async=false; //これらをやめて g_childxml = opener.getXMLObject(); //親に作成させる。 // getXMLObject = opener.getXMLObject; //孫画面でさらに作成したい場合 ----------------------------------------------------------------
ただし、初期の構築はこれでよいとしてもその後のXML操作にオブジェクトを引数にしたい場合、
それらも親に作成させる必要があるかもしれません。そのほかには、XMLオブジェクトがよく分かっていませんが、オブジェクトツリー構築手段として、
オブジェクト経由がダメなようなので、
文字列経由にすると問題がなくなる可能性があるとも思っています。- 回答の候補に設定 山本春海 2010年6月4日 5:08
-
-
>1点教えてください。以下のように考える理由をは何でしょうか良い質問ですね(キリッ (と言って見る)。理由の1つ目は単純にこれまでの動作を見てそうだろうなと思っただけです。2つ目は「親に作成させる必要がある」というのはIEでは良くあることだと思っているからです。
nb2000さんのTabProcGrowthで再現しなくなったという書き込みと手元の再現内容からプロセス単位かそれに類する単位で管理している「何か」(例えばポインタとか)があり、本来想定していない操作により管理外ものもが取り込まれたんだと思いました。事実、親ウィンドウに生成させると動作するようになりました。エラーの事象についても不正なポインタ読み出しとなっておりいかにもな感じです。(ebx+0Bhって言うのはメンバ変数なのでは?そうだとしたらメソッドへの影響が大きいかなと。しかもDocumentオブジェクト。←この辺は勘違いなのであしからず)実は今回と同様の設計をしている場合(オブジェクトを丸ごと取り込む系)、同様の問題が他のActiveXコントロールにも言えると考えていますが、何かありますかね?
それとは別に、IEでは、関数がどのウィンドウで定義されたかによって、その関数内で生成されたオブジェクトの所属先が決まるというのは私にとってなじみ深い問題だったというのもあります。(例えば親と子で(true == true)がfalseになったり、子を閉じると子で生成したオブジェクトへのアクセスは親では不可となったり、.constructorが親子間で一致しなかったり、typeofが誤動作したり)このようにIEの場合組み込みオブジェクト(FunctionやNumberとか)は、windowオブジェクト単位で紐づいており、場合によって親に作成させる必要があるケースがありました。今回のものは、それがプロセス単位に変わっただけだと思いました。
というようなことを、もやっと考えてなんとなく方向付けのためのレスをしただけなので、別な何かを期待していたらすみません。 -
補足です。同一のコードでしたが、こちらの環境では以下となりました。
Win7 64bit&IE8 32bit →エラー: プロシージャの呼び出し、または引数が不正です。とエラー出力。
Win7 64bit&IE8 64bit →エラー: プロシージャの呼び出し、または引数が不正です。とエラー出力。Win7とVistaは同じような動きをすると思って未確認だったんですが、
どうやら異なっているようですね(少なくともnb2000さんの環境とは)。落ちる環境はWinXP SP3&IE8で確認していました。
他に確認された方いらっしゃいましたら教えてください。
-
先にも書いたように、文字列経由にすることで、うまくいきませんか?(XMLオブジェクトの生成元は子側で!)
この方法であれば、初期構築以降の操作も動作するはずなのですが。g_childxml.documentElement = opener.g_xml.documentElement.cloneNode( true );
↓
g_childxml.loadXML( opener.g_xml.xml);それでもダメなら、documentElementはかなり特殊な要素なはずで、そのCloneのみがダメなのであって、他の要素のClone&insertは動く可能性も少なくないと思っています。
色々試してみませんか?(すでに調査済みならすみません)