<commit_before>namespace pxsim {
    export interface SimulatorDriverOptions {
        revealElement?: (el: HTMLElement) => void;
        removeElement?: (el: HTMLElement, onComplete?: () => void) => void;
        unhideElement?: (el: HTMLElement) => void;
        onDebuggerWarning?: (wrn: DebuggerWarningMessage) => void;
        onDebuggerBreakpoint?: (brk: DebuggerBreakpointMessage) => void;
        onTraceMessage?: (msg: TraceMessage) => void;
        onDebuggerResume?: () => void;
        onStateChanged?: (state: SimulatorState) => void;
        onSimulatorCommand?: (msg: pxsim.SimulatorCommandMessage) => void;
        onTopLevelCodeEnd?: () => void;
        simUrl?: string;
        stoppedClass?: string;
    }

    export enum SimulatorState {
        Unloaded,
        Stopped,
        Running,
        Paused
    }

    export enum SimulatorDebuggerCommand {
        StepInto,
        StepOver,
        StepOut,
        Resume,
        Pause
    }

    export interface SimulatorRunOptions {
        debug?: boolean;
        boardDefinition?: pxsim.BoardDefinition;
        parts?: string[];
        fnArgs?: any;
        aspectRatio?: number;
        partDefinitions?: pxsim.Map<PartDefinition>;
        mute?: boolean;
        highContrast?: boolean;
        light?: boolean;
        cdnUrl?: string;
        localizedStrings?: pxsim.Map<string>;
        refCountingDebug?: boolean;
        version?: string;
    }

    export interface HwDebugger {
        postMessage: (msg: pxsim.SimulatorMessage) => void;
    }

    export class SimulatorDriver {
        private themes = ["blue", "red", "green", "yellow"];
        private runId = '';
        private nextFrameId = 0;
        private frameCounter = 0;
        private currentRuntime: pxsim.SimulatorRunMessage;
        private listener: (ev: MessageEvent) => void;
        private traceInterval = 0;
        public runOptions: SimulatorRunOptions = {};
        public state = SimulatorState.Unloaded;
        public hwdbg: HwDebugger;

        constructor(public container: HTMLElement, public options: SimulatorDriverOptions = {}) {
        }

        public setHwDebugger(hw: HwDebugger) {
            if (hw) {
                // TODO set some visual on the simulator frame
                // in future the simulator frame could reflect changes in the hardware
                this.hwdbg = hw
                this.setState(SimulatorState.Running)
                this.container.style.opacity = "0.3"
            } else {
                delete this.container.style.opacity
                this.hwdbg = null
                this.setState(SimulatorState.Running)
                this.stop()
            }
        }

        public handleHwDebuggerMsg(msg: pxsim.SimulatorMessage) {
            if (!this.hwdbg) return
            this.handleMessage(msg)
        }

        public setThemes(themes: string[]) {
            U.assert(themes && themes.length > 0)
            this.themes = themes;
        }

        private setState(state: SimulatorState) {
            if (this.state != state) {
                this.state = state;
                this.freeze(this.state == SimulatorState.Paused); // don't allow interaction when pause
                if (this.options.onStateChanged)
                    this.options.onStateChanged(this.state);
            }
        }

        private freeze(value: boolean) {
            const cls = "pause-overlay";
            if (!value) {
                pxsim.util.toArray(this.container.querySelectorAll(`div.simframe div.${cls}`))
                    .forEach(overlay => overlay.parentElement.removeChild(overlay));
            } else {
                pxsim.util.toArray(this.container.querySelectorAll("div.simframe"))
                    .forEach(frame => {
                        if (frame.querySelector(`div.${cls}`))
                            return;
                        const div = document.createElement("div");
                        div.className = cls;
                        div.onclick = (ev) => {
                            ev.preventDefault();
                            return false;
                        };
                        frame.appendChild(div);
                    })
            }
        }

        public postMessage(msg: pxsim.SimulatorMessage, source?: Window) {
            if (this.hwdbg) {
                this.hwdbg.postMessage(msg)
                return
            }
            // dispatch to all iframe besides self
            let frames = this.container.getElementsByTagName("iframe");
            if (source && (msg.type === 'eventbus' || msg.type == 'radiopacket' || msg.type == 'irpacket')) {
                if (frames.length < 2) {
                    this.container.appendChild(this.createFrame());
                    frames = this.container.getElementsByTagName("iframe");
                } else if (frames[1].dataset['runid'] != this.runId) {
                    this.startFrame(frames[1]);
                }
            }

            for (let i = 0; i < frames.length; ++i) {
                let frame = frames[i] as HTMLIFrameElement
                if (source && frame.contentWindow == source) continue;

                frame.contentWindow.postMessage(msg, "*");
            }
        }

        private createFrame(light?: boolean): HTMLDivElement {
            const wrapper = document.createElement("div") as HTMLDivElement;
            wrapper.className = 'simframe';

            const frame = document.createElement('iframe') as HTMLIFrameElement;
            frame.id = 'sim-frame-' + this.nextId()
            frame.allowFullscreen = true;
            frame.setAttribute('allow', 'autoplay; fullscreen');
            frame.setAttribute('sandbox', 'allow-same-origin allow-scripts');
            (frame.sandbox as any).value = "allow-scripts allow-same-origin"
            let simUrl = this.options.simUrl || ((window as any).pxtConfig || {}).simUrl || "/sim/simulator.html"
            frame.className = 'no-select'
            if (this.runOptions.aspectRatio)
                wrapper.style.paddingBottom = (100 / this.runOptions.aspectRatio) + "%";
            frame.src = simUrl + '#' + frame.id;
            frame.frameBorder = "0";
            frame.dataset['runid'] = this.runId;

            wrapper.appendChild(frame);

            return wrapper;
        }

        public stop(unload = false) {
            this.clearDebugger();
            this.postMessage({ type: 'stop' });
            this.setState(SimulatorState.Stopped);
            if (unload) this.unload();
            else {
                let frames = this.container.getElementsByTagName("iframe");
                for (let i = 0; i < frames.length; ++i) {<commit_msg>Remove redundant allow fullscreen in sim driver (#4347)<commit_after>namespace pxsim {
    export interface SimulatorDriverOptions {
        revealElement?: (el: HTMLElement) => void;
        removeElement?: (el: HTMLElement, onComplete?: () => void) => void;
        unhideElement?: (el: HTMLElement) => void;
        onDebuggerWarning?: (wrn: DebuggerWarningMessage) => void;
        onDebuggerBreakpoint?: (brk: DebuggerBreakpointMessage) => void;
        onTraceMessage?: (msg: TraceMessage) => void;
        onDebuggerResume?: () => void;
        onStateChanged?: (state: SimulatorState) => void;
        onSimulatorCommand?: (msg: pxsim.SimulatorCommandMessage) => void;
        onTopLevelCodeEnd?: () => void;
        simUrl?: string;
        stoppedClass?: string;
    }

    export enum SimulatorState {
        Unloaded,
        Stopped,
        Running,
        Paused
    }

    export enum SimulatorDebuggerCommand {
        StepInto,
        StepOver,
        StepOut,
        Resume,
        Pause
    }

    export interface SimulatorRunOptions {
        debug?: boolean;
        boardDefinition?: pxsim.BoardDefinition;
        parts?: string[];
        fnArgs?: any;
        aspectRatio?: number;
        partDefinitions?: pxsim.Map<PartDefinition>;
        mute?: boolean;
        highContrast?: boolean;
        light?: boolean;
        cdnUrl?: string;
        localizedStrings?: pxsim.Map<string>;
        refCountingDebug?: boolean;
        version?: string;
    }

    export interface HwDebugger {
        postMessage: (msg: pxsim.SimulatorMessage) => void;
    }

    export class SimulatorDriver {
        private themes = ["blue", "red", "green", "yellow"];
        private runId = '';
        private nextFrameId = 0;
        private frameCounter = 0;
        private currentRuntime: pxsim.SimulatorRunMessage;
        private listener: (ev: MessageEvent) => void;
        private traceInterval = 0;
        public runOptions: SimulatorRunOptions = {};
        public state = SimulatorState.Unloaded;
        public hwdbg: HwDebugger;

        constructor(public container: HTMLElement, public options: SimulatorDriverOptions = {}) {
        }

        public setHwDebugger(hw: HwDebugger) {
            if (hw) {
                // TODO set some visual on the simulator frame
                // in future the simulator frame could reflect changes in the hardware
                this.hwdbg = hw
                this.setState(SimulatorState.Running)
                this.container.style.opacity = "0.3"
            } else {
                delete this.container.style.opacity
                this.hwdbg = null
                this.setState(SimulatorState.Running)
                this.stop()
            }
        }

        public handleHwDebuggerMsg(msg: pxsim.SimulatorMessage) {
            if (!this.hwdbg) return
            this.handleMessage(msg)
        }

        public setThemes(themes: string[]) {
            U.assert(themes && themes.length > 0)
            this.themes = themes;
        }

        private setState(state: SimulatorState) {
            if (this.state != state) {
                this.state = state;
                this.freeze(this.state == SimulatorState.Paused); // don't allow interaction when pause
                if (this.options.onStateChanged)
                    this.options.onStateChanged(this.state);
            }
        }

        private freeze(value: boolean) {
            const cls = "pause-overlay";
            if (!value) {
                pxsim.util.toArray(this.container.querySelectorAll(`div.simframe div.${cls}`))
                    .forEach(overlay => overlay.parentElement.removeChild(overlay));
            } else {
                pxsim.util.toArray(this.container.querySelectorAll("div.simframe"))
                    .forEach(frame => {
                        if (frame.querySelector(`div.${cls}`))
                            return;
                        const div = document.createElement("div");
                        div.className = cls;
                        div.onclick = (ev) => {
                            ev.preventDefault();
                            return false;
                        };
                        frame.appendChild(div);
                    })
            }
        }

        public postMessage(msg: pxsim.SimulatorMessage, source?: Window) {
            if (this.hwdbg) {
                this.hwdbg.postMessage(msg)
                return
            }
            // dispatch to all iframe besides self
            let frames = this.container.getElementsByTagName("iframe");
            if (source && (msg.type === 'eventbus' || msg.type == 'radiopacket' || msg.type == 'irpacket')) {
                if (frames.length < 2) {
                    this.container.appendChild(this.createFrame());
                    frames = this.container.getElementsByTagName("iframe");
                } else if (frames[1].dataset['runid'] != this.runId) {
                    this.startFrame(frames[1]);
                }
            }

            for (let i = 0; i < frames.length; ++i) {
                let frame = frames[i] as HTMLIFrameElement
                if (source && frame.contentWindow == source) continue;

                frame.contentWindow.postMessage(msg, "*");
            }
        }

        private createFrame(light?: boolean): HTMLDivElement {
            const wrapper = document.createElement("div") as HTMLDivElement;
            wrapper.className = 'simframe';

            const frame = document.createElement('iframe') as HTMLIFrameElement;
            frame.id = 'sim-frame-' + this.nextId()
            frame.allowFullscreen = true;
            frame.setAttribute('allow', 'autoplay');
            frame.setAttribute('sandbox', 'allow-same-origin allow-scripts');
            (frame.sandbox as any).value = "allow-scripts allow-same-origin"
            let simUrl = this.options.simUrl || ((window as any).pxtConfig || {}).simUrl || "/sim/simulator.html"
            frame.className = 'no-select'
            if (this.runOptions.aspectRatio)
                wrapper.style.paddingBottom = (100 / this.runOptions.aspectRatio) + "%";
            frame.src = simUrl + '#' + frame.id;
            frame.frameBorder = "0";
            frame.dataset['runid'] = this.runId;

            wrapper.appendChild(frame);

            return wrapper;
        }

        public stop(unload = false) {
            this.clearDebugger();
            this.postMessage({ type: 'stop' });
            this.setState(SimulatorState.Stopped);
            if (unload) this.unload();
            else {
                let frames = this.container.getElementsByTagName("iframe");
                for (let i = 0; i < frames.length; ++i) {
{'fraction_non_alphanumeric': 0.11109465264405273, 'fraction_numerical': 0.002518145459931862, 'mean_word_length': 1.7119903595099417, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4781418', 'n_tokens_mistral': 3544, 'n_tokens_neox': 3445, 'n_words': 752}