恢复覆盖的字符串原型

Reverting overridden String prototype

我的 javascript window 中有一个被覆盖的 String.prototype。

window.String.prototype.toUpperCase = ()=>{return "overridden"}

我有一个尚未被触及的 iframe window 的引用,我想用它来创建一个没有覆盖函数的新字符串:

console.log(iframe.contentWindow.String("newstring").toUpperCase());
// prints "overridden"

如何在没有覆盖函数的情况下创建新字符串?

对于重写 Array.prototype,使用新的 iframe 有效,但不适用于 String

console.log(iframe.contentWindow.Array(1,2,3).filter(a=>a));
// that works - prints - [1,2,3]

备注

我知道不应该这样做。我在问如何在另一个第 3 方库做到这一点的情况下修复它。

问题是iframe.contentWindow.String("newstring") 只是 returns 一个字符串,与 String("newstring")"newstring" 求值的原始字符串相同。当访问该字符串上的方法时,使用当前领域中的 String.prototype,其中有损坏的 toUpperCase.

您需要创建一个 实例 来获得一个 string object 继承自 iframe 的 String.prototype:

const stringObj = new iframe.contentWindow.String("newstring");
console.log(stringObj.toUpperCase());

但是,只恢复方法更容易:

String.prototype.toUpperCase = iframe.contentWindow.String.prototype.toUpperCase;
console.log("newstring".toUpperCase());

要恢复 JS 原生方法,您可以执行如下代码:

// Create dummy iframe to steal its fresh console object
const iframe = document.createElement('iframe');

// Add iframe to current window's scope in a hidden state
iframe.id = 'restoreiframe';
iframe.style.display = 'none';
iframe.name = 'restoreiframe_proxy'
document.body.insertAdjacentElement('beforeend', iframe);

// Reassign value of console to iframe's console
const proxyIframe = document.getElementsByName('restoreiframe_proxy')[0]; // document.getElementsByName

// restore document
document.getElementById = proxyIframe.contentDocument.getElementById;
document.getElementsByTagName = proxyIframe.contentDocument.getElementsByTagName;
document.getElementsByClassName = proxyIframe.contentDocument.getElementsByClassName;
document.querySelector = proxyIframe.contentDocument.querySelector;
document.querySelectorAll = proxyIframe.contentDocument.querySelectorAll;

// restore prototype
String.prototype.toUpperCase = proxyIframe.contentWindow.String.prototype.toUpperCase;

// remove proxy iframe
proxyIframe.remove();