「解放されたスクリプトからコードを実行できません」エラーの原因

StackOverflow https://stackoverflow.com/questions/83132

  •  01-07-2019
  •  | 
  •  

質問

しばらく前に解決策を見つけたと思っていました(私の ブログ):

「解放されたスクリプトからコードを実行できません」という JavaScript (または JScript) エラーが表示された場合は、head 内のメタ タグをスクリプト タグの前に移動してみてください。

...しかし、最近のブログ コメントの 1 つによると、私が提案した修正はすべての人に効果があるわけではない可能性があります。これは StackOverflow コミュニティにオープンにするのに適していると思いました。

「解放されたスクリプトからコードを実行できません」というエラーの原因と解決策/回避策は何ですか?

役に立ちましたか?

解決

一部のタグの処理方法でバグ/問題が発生したか、メソッドを実行しようとしているリリースされたオブジェクトへの参照があるようです。

まず、どれかを移動します <meta> タグの前に <script> 提案されたタグ ここ その他多くの場所。

次に、ページ/セキュリティの問題について議論されているかどうかを確認します。 ここ.

他のヒント

存在しないウィンドウまたはフレームで作成された関数を呼び出すと、このエラーが発生します。

ウィンドウがまだ存在するかどうかが事前にわからない場合は、try/catch を実行してウィンドウを検出できます。

try
{
  f();
}
catch(e)
{
  if (e.number == -2146823277)
    // f is no longer available
    ...
}

このエラーは、スクリプトの「親」ウィンドウが破棄されるときに発生します (例:閉じられていますが、(別のウィンドウなどで) まだ保持されているスクリプトへの参照が呼び出されます。 「オブジェクト」はまだ生きていますが、それが実行しようとしているコンテキストは生きていません。

多少汚いですが、私の Windows サイドバー ガジェットでは機能します。

一般的な考え方は次のとおりです。「メイン」ウィンドウは、コードを評価する関数を設定します。そう、それは非常に見苦しいものです。次に、「子」はこの「ビルダー関数」(メイン ウィンドウのスコープにバインドされている) を呼び出し、同じく「メイン」ウィンドウにバインドされている関数を取得できます。もちろん、明らかな欠点は、「リバウンド」している関数が、定義されているように見えるスコープを超えて閉じることができないことです...とにかく、意味不明な話はこれくらいにして、

これは部分的に疑似コードですが、私は Windows サイドバー ガジェットでそのバリアントを使用しています (これを繰り返し言うのは、サイドバー ガジェットは「無制限のゾーン 0」で実行されるためです。これにより、シナリオが大きく変わる可能性がある、または変わらない可能性があります)。


// This has to be setup from the main window, not a child/etc!
mainWindow.functionBuilder = function (func, args) {
  // trim the name, if any
  var funcStr = ("" + func).replace(/^function\s+[^\s(]+\s*\(/, "function (")
  try {
    var rebuilt
    eval("rebuilt = (" + funcStr + ")")
    return rebuilt(args)
  } catch (e) {
    alert("oops! " + e.message)
  }
}

// then in the child, as an example
// as stated above, even though function (args) looks like it's 
// a closure in the child scope, IT IS NOT. There you go :)
var x = {blerg: 2}
functionInMainWindowContenxt = mainWindow.functionBuilder(function (args) {
  // in here args is in the bound scope -- have at the child objects! :-/
  function fn (blah) {
    return blah * args.blerg
  }
  return fn
}, x)

x.blerg = 7
functionInMainWindowContext(6) // -> 42 if I did my math right

バリエーションとして、メイン ウィンドウのコンテキストで functionBuilder 関数が定義されている限り、メイン ウィンドウは functionBuilder 関数を子ウィンドウに渡すことができる必要があります。

言葉を使いすぎたような気がします。YMMV。

JS オブジェクトにアクセスしようとしている場合、最も簡単な方法はコピーを作成することです。

var objectCopy = JSON.parse(JSON.stringify(object));

お役に立てれば幸いです。

このエラーは、子ウィンドウが開いていない親ウィンドウと通信しようとしたときに MSIE で発生する可能性があります。

(正確には、世界で最も役立つエラー メッセージ テキストではありません。)

これは、私がこの動作を確認した非常に具体的なケースです。IE6とIE7では再現可能です。

iframe 内から:

window.parent.mySpecialHandler = function() { ...work... }

次に、iframe を新しいコンテンツで再ロードした後、iframe を含むウィンドウで次のようにします。

window.mySpecialHandler();

mySpecialHandler が存在しないコンテキスト (iframe の元の DOM) で定義されているため、この呼び出しは「解放されたスクリプトからコードを実行できません」というエラーで失敗します。(iframe を再ロードすると、このコンテキストが破壊されました。)

ただし、親ウィンドウで「シリアル化可能な」値 (プリミティブ、関数を直接参照しないオブジェクト グラフ) を安全に設定できます。リモート ウィンドウに何らかの作業を指定するために別のウィンドウ (私の場合は iframe) が本当に必要な場合は、作業を String として渡し、受信側でそれを「評価」できます。これには注意してください。一般に、クリーンまたは安全な実装にはなりません。

IE9 以降、別のオブジェクト内の配列に格納されている Date オブジェクトに対して .getTime() を呼び出すと、このエラーが発生するようになりました。解決策は、Date メソッドを呼び出す前に、それが Date であることを確認することでした。

失敗: rowTime = wl.rowData[a][12].getTime()

合格: rowTime = new Date(wl.rowData[a][12]).getTime()

子フレーム内でトップレベルウィンドウに参照型を追加し、子ウィンドウがリロードされた後にそれにアクセスしようとしたときに、この問題が発生しました。

つまり

// set the value on first load
window.top.timestamp = new Date();

// after frame reloads, try to access the value
if(window.top.timestamp) // <--- Raises exception
...

プリミティブ型のみを使用することで問題を解決できました

// set the value on first load
window.top.timestamp = Number(new Date());

これは実際の答えではありませんが、これが正確に発生する場所の例です。

フレーム A とフレーム B があります (これは私のアイデアではありませんでしたが、我慢する必要があります)。フレーム A は決して変化せず、フレーム B は常に変化します。コードの変更をフレーム A に直接適用することはできないため、(ベンダーの指示に従って) JavaScript を実行できるのはフレーム B (変更を続ける正確なフレーム) のみです。

5 秒ごとに実行する必要がある JavaScript があるため、フレーム B の JavaScript は新しいスクリプト タグを作成し、フレーム B の先頭セクションに挿入します。setInterval は、この新しいスクリプト (挿入されたスクリプト) と、呼び出す関数に存在します。挿入された JavaScript は技術的にはフレーム A によってロードされますが (スクリプト タグが含まれているため)、フレーム B が変更されると、setInterval によって関数にアクセスできなくなります。

IE9 で、最終的に iFrame を開くページ内でこのエラーが発生しました。iFrame が開いていない限り、localStorage を使用できました。iFrame を開いて閉じると、このエラーのため localStorage を使用できなくなりました。これを修正するには、iFrame 内にある Javascript にこのコードを追加し、localStorage も使用する必要がありました。

if (window.parent) {
    localStorage = window.parent.localStorage;
}

ダイアログを開いているときに DHTMLX でこのエラーが発生しました。親 ID または現在のウィンドウ ID が見つかりません

        $(document).ready(function () {

            if (parent.dxWindowMngr == undefined) return;
            DhtmlxJS.GetCurrentWindow('wnManageConDlg').show();

});

ダイアログを開くときに正しい現在のウィンドウ ID または親ウィンドウ ID を送信していることを確認してください。

iframe の src を更新すると、そのエラーが発生します。

次のようにメインウィンドウ内の要素のイベント(私の場合はクリック)にアクセスすると、そのエラーが発生しました(メイン/最も外側のウィンドウを直接呼び出します)。

top.$("#settings").on("click",function(){
    $("#settings_modal").modal("show");
}); 

これを次のように変更したところ、正常に動作しました(iframeウィンドウの親の親を呼び出します)。

$('#settings', window.parent.parent.document).on("click",function(){                    
   $("#settings_modal").modal("show");      
});

モーダルを含む iframe も別の iframe 内にあります。

説明は以前の回答と非常に関連しています。私のシナリオを提供しようとしているだけです。これが他の人にも役立つことを願っています。

私たちが使っていたのは:

<script> window.document.writeln(table) </script>

, 、およびスクリプト内の他の関数を呼び出す onchange イベントは発生しますが、writeln は IE の HTML を完全にオーバーライドしますが、Chrome では動作が異なります。

それを次のように変更しました。

<script> window.document.body.innerHTML = table;</script> 

したがって、問題を修正したスクリプトは保持されました。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top