Сбросить / Перезагрузить IFrame JavaScript context - PullRequest
0 голосов
/ 12 января 2020

Я создаю интерактивный редактор кода, который состоит из текстового поля и элемента <iframe>. Всякий раз, когда пользователь вводит код в текстовое поле, содержимое IFrame записывается, а тег <script> внутри IFrame заполняется содержимым текстового поля кода, в результате чего введенный пользователем код запускается внутри IFrame. Каждый раз, когда пользователь печатает, IFrame должен быть сброшен / перезагружен, а документ снова записан с новым содержимым текстового поля в теге сценария IFrame, по сути, автоматически запуская любой код, который они печатают по мере его ввода.

Однако при этом я заметил, что конфликты пространства имен возникали как переменные, которые пользователь объявил бы в своем коде, которые будут сохраняться между обновлениями IFrame. Я исправил это, обернув вставленный код в IIFE, но затем заметил, что когда пользователь запустит al oop и затем дважды перезагрузит IFrame, будут запущены два цикла .

Очевидно, что JavaScript контекст IFrame не сбрасывается. Я попробовал ответы , приведенные здесь , включая перезагрузку IFrame с использованием .contentWindow.location.reload(), а также изменение источника IFrame с помощью .src = "about:blank", но они просто сбрасывают содержимое документа, а не контекст IFrame JavaScript, который в соответствии с этими ответами сохраняются, если IFrame находится в том же домене.

Вот фактический код, с которым я работаю (клонировать репозиторий -> Выполнить npm install -> Run npm run dev -> Open examples/Sandbox/index.html).

Вот минимальный воспроизводимый пример проблемы (основывается на существовании элемента IFrame с идентификатором frame):

const frame = document.getElementById("frame");
let i = 1;

function updateFrame() {
    frame.contentWindow.location.reload();

    frame.contentDocument.open();

    frame.contentDocument.write(`
        <html>
            <body>
                <script>
                    (function() {
                        let a = 0;

                        function print() {
                            console.log(${i++} + ": " + a++);

                            requestAnimationFrame(print);
                        }

                        print();
                    })();
                </script>
            </body>
        </html>
    `);

    frame.contentDocument.close();
}

updateFrame();
updateFrame();

См. На JSFiddle .

Обратите внимание, что updateFrame() вызывается дважды, что должно перезагрузить содержимое IFrame, оставляя только второй запущенный l oop, однако оба цикла print() одновременно печатаются на консоль, показывая, что контекст сохраняется во время перезагрузок.

Предполагаемое поведение состоит в том, что содержимое IFrame и контекст JavaScript Shoul будет полностью сброшен между перезагрузками. В этом примере, только 2: ... должен многократно печататься на консоли вместо 1: ... и 2: .... Как я могу перефразировать sh IFrame таким образом, чтобы его JavaScript контекст не сохранялся во время перезагрузок и по существу действует так же, как перезагрузка страницы вручную?

1 Ответ

1 голос
/ 12 января 2020

Создав IFrame, вы не можете редактировать его источник, чтобы запретить людям, использующим IFrames, вводить код в сайты для кражи информации и т. Д. c или создавать поддельные веб-сайты, в которых IFrames с вредоносным кодом включены в другие защищенные домены. .

Вам придется рендерить обновления из редактора через AJAX на бэкэнд, такой как PHP server или node.js, или полностью удалить элемент IFrame и создать новый с помощью

var if = document.createElement("IFRAME");
if.src = /* your code */
var container = document.getElementById("container");

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

container.innerHTML = "";
...