web-dev-qa-db-fra.com

Quelle est la cause de l'erreur "Impossible d'exécuter du code à partir d'un script libéré"

Je pensais avoir trouvé la solution il y a quelque temps (voir mon blog ):

Si vous rencontrez un jour l'erreur JavaScript (ou devrait-il s'agir de JScript) "Impossible d'exécuter du code à partir d'un script libéré", essayez de déplacer les balises méta dans la tête afin qu'elles soient avant les balises de script. 

... mais sur la base d'un des commentaires de blog les plus récents, le correctif que j'ai suggéré peut ne pas fonctionner pour tout le monde. J'ai pensé que ce serait un bon moyen de s'ouvrir à la communauté StackOverflow ....

Qu'est-ce qui cause l'erreur "Impossible d'exécuter du code à partir d'un script libéré" et quelles sont les solutions/solutions de contournement?

57
Tom Robinson

On dirait que vous avez rencontré un bogue ou un problème dans la façon dont certaines balises sont traitées ou que vous avez des références à des objets publiés sur lesquels vous essayez d’exécuter des méthodes.

Premièrement, je déplacerais les balises <meta> avant toutes les balises <script> comme suggéré ici et de nombreux autres endroits.

Ensuite, vérifiez si vous avez des problèmes de page/de sécurité discutés ici .

19
Joe Skora

Vous obtenez cette erreur lorsque vous appelez une fonction créée dans une fenêtre ou un cadre qui n'existe plus. 

Si vous ne savez pas à l'avance si la fenêtre existe toujours, vous pouvez essayer/attraper pour la détecter:

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

L'erreur est provoquée lorsque la fenêtre de script 'parent' est supprimée (c'est-à-dire: fermée) mais qu'une référence au script qui est toujours conservé (comme dans une autre fenêtre) est invoquée. Même si 'l'objet' est toujours vivant, le contexte dans lequel il veut s'exécuter ne l'est pas.

C'est un peu sale, mais cela fonctionne pour mon gadget Windows Sidebar:

Voici l’idée générale: La fenêtre "principale" configure une fonction qui évalue du code, ouais, c’est moche . Ensuite, un "enfant" peut appeler cette "fonction constructeur" (qui est/lié à la portée de la fenêtre principale /) et récupère une fonction qui est également liée à la fenêtre 'principale'. Un inconvénient évident est, bien sûr, que la fonction de "rebond" ne peut pas fermer sur la portée dans laquelle elle est apparemment définie dans ... de toute façon, assez de charabia:

Il s’agit en partie de pseudo-code, mais j’en utilise une variante sur un gadget de barre latérale Windows (je le répète sans cesse car les gadgets de barre latérale s’exécutent dans une "zone 0 non restreinte", ce qui peut considérablement changer le scénario.)


// 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

En variante, la fenêtre principale devrait pouvoir transmettre la fonction functionBuilder à la fenêtre enfant - tant que la fonction functionBuilder est définie dans le contexte de la fenêtre principale!

J'ai l'impression d'avoir utilisé trop de mots. YMMV.

18
user166390

Si vous essayez d'accéder à l'objet JS, le moyen le plus simple consiste à créer une copie:

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

J'espère que ça va aider.

8
Grzegorz Ciwoniuk

Voici un cas très spécifique dans lequel j'ai vu ce comportement. Il est reproductible pour moi dans IE6 et IE7.

Depuis un iframe:

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

Ensuite, après avoir rechargé l'iframe avec le nouveau contenu, dans la fenêtre contenant l'iframe:

window.mySpecialHandler();

Cet appel échoue avec "Impossible d'exécuter le code d'un script libéré" car mySpecialHandler a été défini dans un contexte (le DOM d'origine de l'iframe) qui n'existe plus. (Le rechargement de l'iframe a détruit ce contexte.)

Vous pouvez cependant définir en toute sécurité des valeurs "sérialisables" (primitives, graphes d'objets ne référençant pas directement les fonctions) dans la fenêtre parente. Si vous avez vraiment besoin d'une fenêtre séparée (dans mon cas, une iframe) pour spécifier un travail à une fenêtre distante, vous pouvez transmettre le travail en tant que chaîne et le "valider" dans le récepteur. Attention, cela ne permet généralement pas une implémentation propre ou sécurisée.

6
aaron

Depuis IE9, nous avons commencé à recevoir cette erreur lorsque nous avons appelé .getTime () sur un objet Date stocké dans un tableau dans un autre objet. La solution a été de s'assurer qu'il s'agissait bien d'une date avant d'appeler les méthodes Date:

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

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

5
Tom

Cette erreur peut se produire dans MSIE lorsqu'une fenêtre enfant tente de communiquer avec une fenêtre parent qui n'est plus ouverte.

(Ce n'est pas le texte du message d'erreur le plus utile au monde.)

3
pcorcoran

J'ai rencontré ce problème lorsque, à l'intérieur d'un cadre enfant, j'ai ajouté un type de référence à la fenêtre de niveau supérieur et tenté d'y accéder après le rechargement de la fenêtre enfant.

c'est à dire.

// 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
...

J'ai pu résoudre le problème en utilisant uniquement des types primitifs

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

Ce n'est pas vraiment une réponse, mais plutôt un exemple où cela se produit précisément.

Nous avons les cadres A et B (ce n’était pas mon idée, mais je dois vivre avec). L'image A ne change jamais, l'image B change constamment. Nous ne pouvons pas appliquer les modifications de code directement dans le cadre A; par conséquent (conformément aux instructions du fournisseur), nous ne pouvons exécuter JavaScript que dans le cadre B - le cadre exact qui ne cesse de changer.

Nous avons un morceau de JavaScript qui doit être exécuté toutes les 5 secondes. Le JavaScript de l’image B crée donc une nouvelle balise de script et s’insère dans la section d’en-tête de l’image B. ainsi que la fonction à appeler. Même si le JavaScript injecté est techniquement chargé par l'image A (puisqu'il contient maintenant la balise de script), une fois l'image B modifiée, la fonction n'est plus accessible par setInterval.

1
Nathan Crause

J'ai eu cette erreur dans IE9 dans une page qui ouvre finalement un iFrame. Tant que l'iFrame n'était pas ouvert, je pouvais utiliser localStorage. Une fois l'iFrame ouvert et fermé, je ne pouvais plus utiliser le stockage local à cause de cette erreur. Pour résoudre ce problème, j'ai dû ajouter ce code dans le code Javascript qui se trouvait à l'intérieur de l'iFrame et qui utilisait également le stockage local.

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

Lors de la mise à jour du code src d'iframe, j'obtiens cette erreur.

Vous avez cette erreur en accédant à un événement (cliquez dans mon cas) d'un élément de la fenêtre principale comme ceci (appelant directement la fenêtre principale/la plus à l'extérieur): 

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

Je viens de le changer comme ça et ça fonctionne bien (appeler le parent du parent de la fenêtre iframe):

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

Mon iframe contenant le modal se trouve également dans une autre iframe.

0
Chan

Les explications sont très pertinentes dans les réponses précédentes. J'essaie juste de fournir mon scénario. J'espère que cela peut aider les autres.

nous utilisions:

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

, et en appelant d’autres fonctions dans le script sur les événements onchange, mais Writeln remplace complètement le code HTML dans IE, qui présente un comportement différent en chrome.

nous l'avons changé pour:

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

Ainsi conservé le script qui corrige le problème.

0
pavan kumar

a obtenu cette erreur dans DHTMLX lors de l'ouverture d'un dialogue et d'un identifiant parent ou d'un identifiant de fenêtre actuel non trouvé 

        $(document).ready(function () {

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

});

Assurez-vous simplement que vous envoyez le bon identifiant de fenêtre curr/parent tout en ouvrant un dialogue.

0
panky sharma