diff options
| author | 2023-08-15 18:31:01 -0400 | |
|---|---|---|
| committer | 2023-08-15 17:31:01 -0500 | |
| commit | 0bf2cca5d7fe1fb025feae00ab3c12ed80f9ea9a (patch) | |
| tree | 4d5023eb9af84f8388ef7e5a8c06a69b17d79eb9 | |
| 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-- | .changeset/big-elephants-drive.md | 5 | ||||
| -rw-r--r-- | packages/integrations/svelte/client.js | 60 | 
2 files changed, 64 insertions, 1 deletions
| diff --git a/.changeset/big-elephants-drive.md b/.changeset/big-elephants-drive.md new file mode 100644 index 000000000..2d760f715 --- /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 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); +} | 
