This commit is contained in:
nuno maduro
2026-04-23 17:32:27 -07:00
parent 3d3c5d41ac
commit b46f051550
2 changed files with 35 additions and 1 deletions

View File

@ -60,6 +60,12 @@ final class ContentHash
return self::hashPhpContent($raw); return self::hashPhpContent($raw);
} }
foreach (['.vue', '.tsx', '.jsx', '.svelte', '.ts', '.js', '.mjs', '.cjs', '.mts'] as $extension) {
if (str_ends_with($lower, $extension)) {
return self::hashJsContent($raw);
}
}
return hash('xxh128', $raw); return hash('xxh128', $raw);
} }
@ -115,4 +121,24 @@ final class ContentHash
return hash('xxh128', trim($stripped)); return hash('xxh128', trim($stripped));
} }
/**
* Conservative JS/TS/Vue/Svelte normaliser. Strips `//` line
* comments and `/* … *\/` block comments that appear on their own
* lines (including leading indentation), then collapses
* whitespace. Deliberately leaves trailing comments after code
* alone — a string literal like `'http://foo'` would be unsafe to
* split on `//` without a full lexer. The direction of error is
* over-detection (we may not strip a trailing comment that's
* purely cosmetic), never under-detection. Blank lines and
* indentation changes are erased regardless.
*/
private static function hashJsContent(string $raw): string
{
$stripped = preg_replace('/^\s*\/\/[^\n]*$/m', '', $raw) ?? $raw;
$stripped = preg_replace('/^\s*\/\*.*?\*\/\s*$/sm', '', $stripped) ?? $stripped;
$stripped = preg_replace('/\s+/', ' ', $stripped) ?? $stripped;
return hash('xxh128', trim($stripped));
}
} }

View File

@ -52,7 +52,15 @@ final readonly class Fingerprint
// the PHP fallback) so shared components / layouts / // the PHP fallback) so shared components / layouts /
// composables invalidate the specific pages they're used // composables invalidate the specific pages they're used
// by, not every browser test. // by, not every browser test.
private const int SCHEMA_VERSION = 8; // v9: `ContentHash` now normalises JS/TS/Vue/Svelte comments +
// whitespace. Old graphs' run-tree hashes for those files
// were raw-byte; mixing formats would flag every JS file as
// changed on first run.
// v10: `vite.config.*` hashed into the structural bucket. A
// Vite config change reshapes the module dependency graph
// that `JsModuleGraph` records; without a graph rebuild
// the stored `$jsFileToComponents` map silently goes stale.
private const int SCHEMA_VERSION = 10;
/** /**
* @return array{ * @return array{