diff --git a/.changeset/big-elephants-drive.md b/.changeset/big-elephants-drive.md new file mode 100644 index 000000000000..2d760f715ee2 --- /dev/null +++ b/.changeset/big-elephants-drive.md @@ -0,0 +1,5 @@ +--- +'@astrojs/svelte': patch +--- + +Filter unknown `class` prop warnings diff --git a/packages/integrations/svelte/client.js b/packages/integrations/svelte/client.js index 658ddb02f3d7..0d07ff2ba563 100644 --- a/packages/integrations/svelte/client.js +++ b/packages/integrations/svelte/client.js @@ -1,5 +1,8 @@ const noop = () => {}; +let originalConsoleWarning; +let consoleFilterRefs = 0; + export default (target) => { return (Component, props, slotted, { client }) => { if (!target.hasAttribute('ssr')) return; @@ -7,7 +10,10 @@ export default (target) => { for (const [key, value] of Object.entries(slotted)) { slots[key] = createSlotDefinition(key, value); } + try { + if (import.meta.env.DEV) useConsoleFilter(); + new Component({ target, props: { @@ -18,7 +24,10 @@ export default (target) => { hydrate: client !== 'only', $$inline: true, }); - } catch (e) {} + } catch (e) { + } finally { + if (import.meta.env.DEV) finishUsingConsoleFilter(); + } }; }; @@ -51,3 +60,52 @@ function createSlotDefinition(key, children) { noop, ]; } + +/** + * Reduces console noise by filtering known non-problematic warnings. + * + * Performs reference counting to allow parallel usage from async code. + * + * To stop filtering, please ensure that there always is a matching call + * to `finishUsingConsoleFilter` afterwards. + */ +function useConsoleFilter() { + consoleFilterRefs++; + + if (!originalConsoleWarning) { + originalConsoleWarning = console.warn; + try { + console.warn = filteredConsoleWarning; + } catch (error) { + // If we're unable to hook `console.warn`, just accept it + } + } +} + +/** + * Indicates that the filter installed by `useConsoleFilter` + * is no longer needed by the calling code. + */ +function finishUsingConsoleFilter() { + consoleFilterRefs--; + + // Note: Instead of reverting `console.warning` back to the original + // when the reference counter reaches 0, we leave our hook installed + // to prevent potential race conditions once `check` is made async +} + +/** + * Hook/wrapper function for the global `console.warning` function. + * + * Ignores known non-problematic errors while any code is using the console filter. + * Otherwise, simply forwards all arguments to the original function. + */ +function filteredConsoleWarning(msg, ...rest) { + if (consoleFilterRefs > 0 && typeof msg === 'string') { + // Astro passes a `class` prop to the Svelte component, which + // outputs the following warning, which we can safely filter out. + const isKnownSvelteError = msg.endsWith("was created with unknown prop 'class'"); + if (isKnownSvelteError) return; + } + originalConsoleWarning(msg, ...rest); +}