"해제된 스크립트에서 코드를 실행할 수 없습니다" 오류의 원인
-
01-07-2019 - |
문제
나는 얼마 전에 해결책을 찾았다고 생각했습니다. 블로그):
JavaScript(또는 JScript여야 함) 오류 "해제된 스크립트에서 코드를 실행할 수 없습니다"가 발생하는 경우 헤드에 있는 메타 태그를 스크립트 태그 앞에 오도록 이동해 보세요.
...하지만 가장 최근 블로그 댓글 중 하나에 따르면 제가 제안한 수정 사항이 모든 사람에게 적용되지 않을 수도 있습니다.나는 이것이 StackOverflow 커뮤니티에 공개하기에 좋은 것이라고 생각했습니다....
"해제된 스크립트에서 코드를 실행할 수 없습니다" 오류의 원인은 무엇이며 해결 방법은 무엇입니까?
다른 팁
더 이상 존재하지 않는 창이나 프레임에서 생성된 함수를 호출하면 이 오류가 발생합니다.
창이 여전히 존재하는지 미리 알 수 없는 경우 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)이 정말로 필요한 경우 해당 작업을 문자열로 전달하고 수신자에서 "평가"할 수 있습니다.일반적으로 깨끗하거나 안전한 구현이 불가능하므로 주의하세요.
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에 직접 적용할 수 없으므로 (공급업체의 지침에 따라) 계속 변경되는 정확한 프레임인 프레임 B에서만 JavaScript를 실행할 수 있습니다.
5초마다 실행해야 하는 JavaScript가 있으므로 프레임 B의 JavaScript는 새 스크립트 태그를 생성하고 프레임 B의 헤드 섹션에 삽입합니다.setInterval은 이 새 스크립트(주입된 스크립트)와 호출할 함수에 존재합니다.주입된 JavaScript가 기술적으로 프레임 A에 의해 로드되더라도(이제 스크립트 태그가 포함되어 있으므로) 프레임 B가 변경되면 해당 함수는 더 이상 setInterval을 통해 액세스할 수 없습니다.
결국 iFrame을 여는 페이지 내의 IE9에서 이 오류가 발생했습니다.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를 보내고 있는지 확인하세요.
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>
따라서 문제를 해결한 스크립트를 유지했습니다.