Как сбросить сломанный JavaScript объект массива из нового iframe? - PullRequest
2 голосов
/ 02 августа 2020

У меня есть сценарий, который запускается на сайте, и я не могу рассчитывать, что его объект window.Array не будет отменен. (Он мог быть изменен другим скриптом, который был загружен ранее).

Я создаю новый iframe и хочу вернуть объект window.Array обратно в прототип собственного массива

    // let's assume Array.prototype.filter function was changed by another script
    Array.prototype.filter = ()=>{return "haha!"}

    console.log('test overridden: ', new Array(1,2,3).filter(x=>x));
    console.log('test overridden literal:', [1,2,3].filter(x=>x));

    // prints test overridden: haha
    // prints test overridden literal: haha

    // get new window with native code from iframe
    var iframe = null;
    (iframe = document.createElement('iframe')).name = 'native_function';
    document.body.appendChild(iframe);
    var native = window.frames['native_function'];

    // here I am trying to set my broken Array to a new fresh copy
    Object.setPrototypeOf(Array, native.Array.prototype);

    console.log('test restored filter: ', new Array(1,2,3).filter(x=>x));
    console.log('test restored literal array filter', [1,2,3].filter(x=>x));

 
    // prints test restored filter: haha
    // prints test restored literal array filter: haha

    // It didn't work.

Как я могу восстановить свой window.Array в native.window.Array?

Примечание Я хочу восстановить весь объект Array в исходный массив в окне iframe. Не только функция фильтра, которую я только что использовал в качестве примера.

1 Ответ

1 голос
/ 02 августа 2020

Я хочу восстановить весь объект Array в исходный массив в окне iframe

Вы не можете перезаписать прототип встроенного массива, который используется при создании массивов из литералов, поэтому вместо этого вам нужно чтобы перезаписать методы на этом.

const iframe = document.body.appendChild(document.createElement("iframe"));
const iframeArray = iframe.contentWindow.Array;
document.body.removeChild(iframe);

const nativeArrayProto = Object.getPrototypeOf([]);
for (const p of ["constructor", "filter", "map", "slice", /* … */])
    nativeArrayProto[p] = iframeArray.prototype[p];
Array = nativeArrayProto.constructor;
Array.prototype = nativeArrayProto;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...