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](a1c0cbe604/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>
This commit is contained in:
parent
0b59bc944b
commit
0bf2cca5d7
2 changed files with 64 additions and 1 deletions
5
.changeset/big-elephants-drive.md
Normal file
5
.changeset/big-elephants-drive.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'@astrojs/svelte': patch
|
||||
---
|
||||
|
||||
Filter unknown `class` prop warnings
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue