import { BaseElement } from "../../../shared/_base"; import './output-frame.less'; import { GetOutputFrameUrl } from "../../../shared/url-helpers"; import { GetNotificationBubbles } from "../../../shared/getdom"; import { postMessage } from "../../../shared/post-message"; export class OutputFrame extends BaseElement { public Iframe: HTMLIFrameElement | null = null; public CurrentIframeScriptRemoveResponseListener: Function | null = null; constructor() { super(); } onInit(): void { this.reset(); } onUpdate(): void { } reset(resetNotificationBubbles: boolean = true) { if (this.CurrentIframeScriptRemoveResponseListener != null) { this.CurrentIframeScriptRemoveResponseListener(); this.CurrentIframeScriptRemoveResponseListener = null; } if (this.Iframe && this.hasChild(this.Iframe)) { this.removeChild(this.Iframe); } this.Iframe = document.createElement("iframe"); this.Iframe.setAttribute("sandbox", "allow-pointer-lock allow-same-origin allow-scripts"); this.Iframe.src = GetOutputFrameUrl(); this.appendChild(this.Iframe); if (resetNotificationBubbles) { var bubbles = GetNotificationBubbles(); if (bubbles && bubbles.reset) { bubbles.reset(); } } } setError() { this.reset(); if (this.Iframe) { this.Iframe.src = GetOutputFrameUrl() + "execution-time-error.html"; } } preventInfiniteLoop(value: string) { return value.replace("while (true)", "while (false)"); } setScript(value: string) { this.reset(); this.onIframeLoaded(() => { this.CurrentIframeScriptRemoveResponseListener = postMessage(this.Iframe?.contentWindow, "script", value, (executeTimeInMs, exceedTimeInMs) => { if (executeTimeInMs === -1) { this.setError(); } else { var bubbles = GetNotificationBubbles(); bubbles.add("code executed in: " + executeTimeInMs + "ms", "info"); } }); }); } onIframeLoaded(fn: Function) { if (this.Iframe) { this.Iframe.onload = () => { fn(); } } else { this.waitFor(this.Iframe, () => { this.onIframeLoaded(fn); }); } } }