diff --git a/packages/repl/src/lib/Output/ReplProxy.ts b/packages/repl/src/lib/Output/ReplProxy.ts index a42f28cd7..11a6adfc0 100644 --- a/packages/repl/src/lib/Output/ReplProxy.ts +++ b/packages/repl/src/lib/Output/ReplProxy.ts @@ -23,6 +23,8 @@ export default class ReplProxy { return this.handlers.on_error(event.data); case 'unhandledrejection': return this.handlers.on_unhandled_rejection(event.data); + case 'iframe_reload': + return this.handlers.on_iframe_reload(event.data); case 'console': if (event.data.command === 'info' && event.data.args[0]?.type === '__error') { const data = event.data.args[0]; diff --git a/packages/repl/src/lib/Output/Viewer.svelte b/packages/repl/src/lib/Output/Viewer.svelte index 53685b8f6..310024a01 100644 --- a/packages/repl/src/lib/Output/Viewer.svelte +++ b/packages/repl/src/lib/Output/Viewer.svelte @@ -77,6 +77,9 @@ error.message = 'Uncaught (in promise): ' + error.message; push_logs({ command: 'error', args: [error] }); }, + on_iframe_reload: () => { + ready = false; + }, on_console: (log) => { switch (log.command) { case 'clear': @@ -169,11 +172,65 @@ console.error(err); } } + window.__reset_custom_elements?.(); document.body.innerHTML = ''; window._svelteTransitionManager = null; } + if (!window.__reset_custom_elements) { + const registered = new Map(); + const define = CustomElementRegistry.prototype.define; + CustomElementRegistry.prototype.define = function(name, el, options) { + let ce = registered.get(name); + if (ce) { + if (ce.registered) { + // trigger error of re-registering + define.call(this, name, ce.el, options); + } + if (ce.options?.extends != options?.extends) { + parent.postMessage({ action: 'iframe_reload' }, '*'); + location.reload(); + } + ce.el = el; + ce.registered = true; + } else { + ce = { el, options, registered: true }; + registered.set(name, ce); + const Wrapper = class extends el { + connectedCallback() { + ce.el.prototype.connectedCallback?.apply(this, arguments); + } + disconnectedCallback() { + ce.el.prototype.disconnectedCallback?.apply(this, arguments); + } + adoptedCallback() { + ce.el.prototype.adoptedCallback?.apply(this, arguments); + } + }; + const DynamicWrapper = new Proxy(Wrapper, { + construct: function (_, args, newTarget) { + return Reflect.construct(ce.el, args, newTarget); + } + }); + try { + define.call(this, name, DynamicWrapper, options); + } catch (error) { + console.error(error); + throw new Error('Failed to define a custom element '+name); + } + } + }; + window.__reset_custom_elements = () => { + for (const ce of registered.values()) { + if (ce.registered) { + ce.el = HTMLElement; + ce.registered = false; + } + } + } + } + const __repl_exports = ${bundle.client?.code}; { const { mount, unmount, App, untrack } = __repl_exports; diff --git a/packages/repl/src/lib/Output/proxy.d.ts b/packages/repl/src/lib/Output/proxy.d.ts index b3f9fa8d1..87ea1ae97 100644 --- a/packages/repl/src/lib/Output/proxy.d.ts +++ b/packages/repl/src/lib/Output/proxy.d.ts @@ -1,4 +1,4 @@ export type Handlers = Record< - 'on_fetch_progress' | 'on_error' | 'on_unhandled_rejection' | 'on_console', + 'on_fetch_progress' | 'on_error' | 'on_unhandled_rejection' | 'on_iframe_reload' | 'on_console', (data: any) => void >; pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy