From 63b9635d308f7bc82819d78a2e2645a5be4a898c Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Thu, 10 Aug 2023 10:46:07 -0400 Subject: [PATCH] [AssetMapper] Fixing bug where a circular exception could be thrown while making error message --- .../Compiler/JavaScriptImportPathCompiler.php | 9 +++++-- .../Exception/CircularAssetsException.php | 19 ++++++++++++++ .../Factory/MappedAssetFactory.php | 3 ++- .../JavaScriptImportPathCompilerTest.php | 26 +++++++++++++++++++ 4 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 src/Symfony/Component/AssetMapper/Exception/CircularAssetsException.php diff --git a/src/Symfony/Component/AssetMapper/Compiler/JavaScriptImportPathCompiler.php b/src/Symfony/Component/AssetMapper/Compiler/JavaScriptImportPathCompiler.php index 8ca018f0f13c4..5d011f9edc39a 100644 --- a/src/Symfony/Component/AssetMapper/Compiler/JavaScriptImportPathCompiler.php +++ b/src/Symfony/Component/AssetMapper/Compiler/JavaScriptImportPathCompiler.php @@ -15,6 +15,7 @@ use Psr\Log\NullLogger; use Symfony\Component\AssetMapper\AssetDependency; use Symfony\Component\AssetMapper\AssetMapperInterface; +use Symfony\Component\AssetMapper\Exception\CircularAssetsException; use Symfony\Component\AssetMapper\Exception\RuntimeException; use Symfony\Component\AssetMapper\MappedAsset; @@ -57,8 +58,12 @@ public function compile(string $content, MappedAsset $asset, AssetMapperInterfac if (!$dependentAsset) { $message = sprintf('Unable to find asset "%s" imported from "%s".', $matches[1], $asset->sourcePath); - if (null !== $assetMapper->getAsset(sprintf('%s.js', $resolvedPath))) { - $message .= sprintf(' Try adding ".js" to the end of the import - i.e. "%s.js".', $matches[1]); + try { + if (null !== $assetMapper->getAsset(sprintf('%s.js', $resolvedPath))) { + $message .= sprintf(' Try adding ".js" to the end of the import - i.e. "%s.js".', $matches[1]); + } + } catch (CircularAssetsException $e) { + // avoid circular error if there is self-referencing import comments } $this->handleMissingImport($message); diff --git a/src/Symfony/Component/AssetMapper/Exception/CircularAssetsException.php b/src/Symfony/Component/AssetMapper/Exception/CircularAssetsException.php new file mode 100644 index 0000000000000..da412e63123ee --- /dev/null +++ b/src/Symfony/Component/AssetMapper/Exception/CircularAssetsException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\AssetMapper\Exception; + +/** + * Thrown when a circular reference is detected while creating an asset. + */ +class CircularAssetsException extends RuntimeException +{ +} diff --git a/src/Symfony/Component/AssetMapper/Factory/MappedAssetFactory.php b/src/Symfony/Component/AssetMapper/Factory/MappedAssetFactory.php index b6fdb3debaa2d..4c19ab7677d51 100644 --- a/src/Symfony/Component/AssetMapper/Factory/MappedAssetFactory.php +++ b/src/Symfony/Component/AssetMapper/Factory/MappedAssetFactory.php @@ -12,6 +12,7 @@ namespace Symfony\Component\AssetMapper\Factory; use Symfony\Component\AssetMapper\AssetMapperCompiler; +use Symfony\Component\AssetMapper\Exception\CircularAssetsException; use Symfony\Component\AssetMapper\Exception\RuntimeException; use Symfony\Component\AssetMapper\MappedAsset; use Symfony\Component\AssetMapper\Path\PublicAssetsPathResolverInterface; @@ -36,7 +37,7 @@ public function __construct( public function createMappedAsset(string $logicalPath, string $sourcePath): ?MappedAsset { if (\in_array($logicalPath, $this->assetsBeingCreated, true)) { - throw new RuntimeException(sprintf('Circular reference detected while creating asset for "%s": "%s".', $logicalPath, implode(' -> ', $this->assetsBeingCreated).' -> '.$logicalPath)); + throw new CircularAssetsException(sprintf('Circular reference detected while creating asset for "%s": "%s".', $logicalPath, implode(' -> ', $this->assetsBeingCreated).' -> '.$logicalPath)); } if (!isset($this->assetsCache[$logicalPath])) { diff --git a/src/Symfony/Component/AssetMapper/Tests/Compiler/JavaScriptImportPathCompilerTest.php b/src/Symfony/Component/AssetMapper/Tests/Compiler/JavaScriptImportPathCompilerTest.php index 4c04a70ba78b4..cf290e5ef0c90 100644 --- a/src/Symfony/Component/AssetMapper/Tests/Compiler/JavaScriptImportPathCompilerTest.php +++ b/src/Symfony/Component/AssetMapper/Tests/Compiler/JavaScriptImportPathCompilerTest.php @@ -16,6 +16,7 @@ use Symfony\Component\AssetMapper\AssetMapperInterface; use Symfony\Component\AssetMapper\Compiler\AssetCompilerInterface; use Symfony\Component\AssetMapper\Compiler\JavaScriptImportPathCompiler; +use Symfony\Component\AssetMapper\Exception\CircularAssetsException; use Symfony\Component\AssetMapper\Exception\RuntimeException; use Symfony\Component\AssetMapper\MappedAsset; @@ -277,6 +278,31 @@ public static function provideMissingImportModeTests(): iterable ]; } + public function testErrorMessageAvoidsCircularException() + { + $assetMapper = $this->createMock(AssetMapperInterface::class); + $assetMapper->expects($this->any()) + ->method('getAsset') + ->willReturnCallback(function ($logicalPath) { + if ('htmx' === $logicalPath) { + return null; + } + + if ('htmx.js' === $logicalPath) { + throw new CircularAssetsException(); + } + }); + + $asset = new MappedAsset('htmx.js', '/path/to/app.js'); + $compiler = new JavaScriptImportPathCompiler(); + $content = '//** @type {import("./htmx").HtmxApi} */'; + $compiled = $compiler->compile($content, $asset, $assetMapper); + // To form a good exception message, the compiler will check for the + // htmx.js asset, which will throw a CircularAssetsException. This + // should not be caught. + $this->assertSame($content, $compiled); + } + private function createAssetMapper(): AssetMapperInterface { $assetMapper = $this->createMock(AssetMapperInterface::class); pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy