导致错误"无法从释放的脚本执行代码"的原因是什么

时间:2020-03-05 18:58:52  来源:igfitidea点击:

我以为我早就找到了解决方案(请参阅我的博客):

If you ever get the JavaScript (or should that be JScript) error "Can't execute code from a freed script" - try moving any meta tags in the head so that they're before your script tags.

...但是根据最近的博客评论之一,我建议的修复可能并不适合所有人。我认为这是向StackOverflow社区开放的好人...。

是什么原因导致错误"无法从释放的脚本中执行代码",解决方案/解决方法是什么?

解决方案

回答

当子窗口尝试与不再打开的父窗口进行通信时,MSIE中可能会发生此错误。

(不完全是世界上最有用的错误消息文本。)

回答

听起来我们在处理某些标签的方式上遇到了错误/问题,或者我们引用了要在其上执行方法的已发布对象。

首先,我将所有<meta>标签移到此处和许多其他地方建议的所有<script>标签之前。

然后检查是否有此处讨论的页面/安全问题。

回答

当我们调用在不再存在的窗口或者框架中创建的函数时,会出现此错误。

如果我们事先不知道该窗口是否仍然存在,则可以尝试/捕获以检测到该窗口:

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

回答

当脚本的"父"窗口被放置(即:关闭)但调用仍保留的脚本(例如在另一个窗口中)的引用时,会导致该错误。即使"对象"仍然存在,但它要执行的上下文却没有。

它有点脏,但是适用于我的Windows边栏小工具:

这是一般的想法:
"主"窗口设置了一个函数,该函数将评估一些代码,是的,这很丑陋。
然后,"子级"可以调用此"生成器函数"(/绑定到主窗口的范围/),并获得也绑定到"主"窗口的函数。当然,一个明显的缺点是,被"绑定"的函数无法关闭它似乎在...中定义的范围,无论如何,足够多的麻烦了:

这是部分伪代码,但是我在Windows Sidebar Gadget上使用了它的变体(我之所以这样说是因为Sidebar Gadgets在"不受限制的区域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。

回答

这是一个非常特殊的情况,在这种情况下,我已经看到了这种行为。对我来说,它在IE6和IE7中是可复制的。

在iframe中:

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

然后,在用新内容重新加载iframe之后,在包含iframe的窗口中:

window.mySpecialHandler();

此调用失败,并显示"无法从释放的脚本执行代码",因为mySpecialHandler是在不再存在的上下文(iframe的原始DOM)中定义的。 (重新加载iframe会破坏此上下文。)

但是,我们可以在父窗口中安全设置"可序列化"的值(基元,不直接引用函数的对象图)。如果我们确实需要一个单独的窗口(在我的情况下为iframe)来指定一些工作到远程窗口,则可以将工作作为String传递,并在接收器中"评估"它。对此要小心,它通常无法实现干净或者安全的实现。