diff options
author | 2023-08-15 18:31:01 -0400 | |
---|---|---|
committer | 2023-08-15 17:31:01 -0500 | |
commit | 0bf2cca5d7fe1fb025feae00ab3c12ed80f9ea9a (patch) | |
tree | 4d5023eb9af84f8388ef7e5a8c06a69b17d79eb9 /packages/integrations/svelte/client.js | |
parent | 0b59bc944b18913bd985f01b514e7416aa167324 (diff) | |
download | astro-0bf2cca5d7fe1fb025feae00ab3c12ed80f9ea9a.tar.gz astro-0bf2cca5d7fe1fb025feae00ab3c12ed80f9ea9a.tar.zst astro-0bf2cca5d7fe1fb025feae00ab3c12ed80f9ea9a.zip |
Filter out Svelte's unknown class prop console warnings (#7291)
* Filter out Svelte's unexpected class prop console warnings
Astro's hydration code passes a `class` prop to Svelte components, inducing Svelte to log a warning about an unknown prop. Preempting this by exporting a `class` prop from the Svelte component isn't a viable workaround since `class` is a reserved identifier in JS.
This PR implements the console-filtering workaround suggested by @HiDeoo in #5665, borrowing the `useConsoleFilter` approach from the [preact integration](https://github.com/withastro/astro/blob/a1c0cbe604c9f91cdc421b5606aab574999eba01/packages/integrations/preact/src/server.ts#L72-L94).
It would probably be better to generalize console filtering so it could be shared across multiple integrations.
Ideally there would be a way to handle this in Svelte, but as was pointed out in the issue thread even they resort to [similar cringe-inducing hackery](https://github.com/sveltejs/kit/blob/master/packages/kit/src/runtime/client/client.js#L1974-L1996) in sveltekit.
* Only filter Svelte console warnings in dev builds
* Add changeset
* Fix lint error.
---------
Co-authored-by: bluwy <bjornlu.dev@gmail.com>
Co-authored-by: Nate Moore <natemoo-re@users.noreply.github.com>
Diffstat (limited to '')
-rw-r--r-- | packages/integrations/svelte/client.js | 60 |
1 files changed, 59 insertions, 1 deletions
diff --git a/packages/integrations/svelte/client.js b/packages/integrations/svelte/client.js index 658ddb02f..0d07ff2ba 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); +} |