在 Edge 和 IE 上修补 document.write

Patching document.write on Edge and IE

这是 document.write 的一个简单猴子补丁,它适用于除 MS Edge 和 IE 之外的所有主流浏览器。

<!DOCTYPE html>
<html>
    <head>
    </head>
    <body>
        <iframe id="first" width="300" height="250"></iframe>
        <script>
            var ifr = document.getElementById('first');
            var doc = ifr.contentWindow.document;

            console.log('Before patching:', doc.write);

            (function(doc) {
                var originalWrite = doc.write;
                doc.write = function() {
                    console.log('Patched');
                    return originalWrite.apply(doc, arguments);
                };
            })(doc);

            console.log('After patching:', doc.write);

            doc.write('<iframe id="second" width="300" height="250"></iframe>');

            console.log('After writing:', doc.write);
        </script>
    </body>
</html>

预期行为:doc.write写入后应与修补后相同

实际行为:doc.write 未定义

不工作:Edge 18,IE 11

工作:Chrome、Firefox、Opera、Safari

要重现的片段: https://jsbin.com/qutaxixeku/edit?html,console

有什么解决方法吗?

2019-11-19更新:

跟着余舟的回答。如果我完全删除修补逻辑并在写入后记录 doc,Microsoft Edge 也会在 HTMLDocumentPrototype 中显示 <Permission denied> 错误。但是如果我在它之后立即登录 doc.write,Microsoft Edge 将显示 function write() { [native code] }

此外,如果我尝试在不打补丁的情况下多次写入 iframe,它将在 Edge 上正常工作:

doc.write('<div>One</div>');
doc.write('<div>Two</div>');
doc.write('<div>Three</div>');

Snippet

如果你在写入后登录doc,你会发现Microsoft Edge(EdgeHTML)会在HTMLDocumentPrototype中显示<Permission denied>错误:

结果在IE中是一样的。从document.write()the documentation,我们可以看到这个注释:

Note: In Edge only, calling document.write more than once in an <iframe> causes the error SCRIPT70: Permission denied.

您不能在 IE 和 Edge 的 <iframe> 中多次调用写入函数。如果您在其他元素中调用该函数,则它不会是 undefined:

var doc = document;
console.log('Before patching:', doc.write);

var originalWrite = doc.write;
doc.write = function() {
  console.log('Patched');
  return originalWrite.apply(doc, arguments);
};

console.log('After patching:', doc.write);

doc.write('<iframe id="second" width="300" height="250"></iframe>');

console.log('After writing:', doc.write);
<p></p>

应该是Edge和IE11的设计问题。我不建议在 Edge 的 iframe 中多次调用 document.write,即使它使用本机 document.write 方法也是如此。 Return 对于你的问题,如果你多次写入 iframe 在你修补 之后,Edge 只显示一个对象:

<!DOCTYPE html>
<html>
    <head>
    </head>
    <body>
        <iframe id="first" width="300" height="250"></iframe>
        <script>
            var ifr = document.getElementById('first');
            var doc = ifr.contentWindow.document;

            console.log('Before patching:', doc.write);
   
            (function(doc) {
                var originalWrite = doc.write;
                doc.write = function() {
                    console.log('Patched');
                    return originalWrite.apply(doc, arguments);
                };
            })(doc); 

            console.log('After patching:', doc.write);

            //doc.write('<iframe id="second" width="300" height="250"></iframe>');
   doc.write('<div>One</div>');
   doc.write('<div>Two</div>');
   doc.write('<div>Three</div>');

            console.log('After writing:', doc.write);
        </script>
    </body>
</html>

我们已将此问题报告给 Microsoft Edge 团队,但我们不确定它是否会在可预见的时间内得到修复,因为即将推出带有 Chromium 的新 Edge。