Skip to content

Commit d70e500

Browse files
smnandrenicolas-grekas
authored andcommitted
[AssetMapper] Fix JavaScript compiler load imports from JS strings
1 parent 0294563 commit d70e500

File tree

2 files changed

+65
-2
lines changed

2 files changed

+65
-2
lines changed

src/Symfony/Component/AssetMapper/Compiler/JavaScriptImportPathCompiler.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@
2727
*/
2828
final class JavaScriptImportPathCompiler implements AssetCompilerInterface
2929
{
30-
// https://regex101.com/r/fquriB/1
31-
private const IMPORT_PATTERN = '/(?:import\s*(?:(?:\*\s*as\s+\w+|[\w\s{},*]+)\s*from\s*)?|\bimport\()\s*[\'"`](\.\/[^\'"`]+|(\.\.\/)*[^\'"`]+)[\'"`]\s*[;\)]?/m';
30+
// https://regex101.com/r/qFoeoR/1
31+
private const IMPORT_PATTERN = '/(?:\'(?:[^\'\\\\]|\\\\.)*\'|"(?:[^"\\\\]|\\\\.)*")|(?:import\s*(?:(?:\*\s*as\s+\w+|[\w\s{},*]+)\s*from\s*)?|\bimport\()\s*[\'"`](\.\/[^\'"`]+|(\.\.\/)*[^\'"`]+)[\'"`]\s*[;\)]?/m';
3232

3333
public function __construct(
3434
private readonly ImportMapConfigReader $importMapConfigReader,
@@ -42,6 +42,11 @@ public function compile(string $content, MappedAsset $asset, AssetMapperInterfac
4242
return preg_replace_callback(self::IMPORT_PATTERN, function ($matches) use ($asset, $assetMapper, $content) {
4343
$fullImportString = $matches[0][0];
4444

45+
// Ignore enquoted strings (e.g. console.log("import 'foo';")
46+
if (!isset($matches[1][0])) {
47+
return $fullImportString;
48+
}
49+
4550
if ($this->isCommentedOut($matches[0][1], $content)) {
4651
return $fullImportString;
4752
}

src/Symfony/Component/AssetMapper/Tests/Compiler/JavaScriptImportPathCompilerTest.php

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ public function testCompileFindsCorrectImports(string $input, array $expectedJav
6767
->method('getAssetFromSourcePath')
6868
->willReturnCallback(function ($path) {
6969
return match ($path) {
70+
'/project/assets/foo.js' => new MappedAsset('foo.js', '/can/be/anything.js', publicPathWithoutDigest: '/assets/foo.js'),
7071
'/project/assets/other.js' => new MappedAsset('other.js', '/can/be/anything.js', publicPathWithoutDigest: '/assets/other.js'),
7172
'/project/assets/subdir/foo.js' => new MappedAsset('subdir/foo.js', '/can/be/anything.js', publicPathWithoutDigest: '/assets/subdir/foo.js'),
7273
'/project/assets/styles.css' => new MappedAsset('styles.css', '/can/be/anything.js', publicPathWithoutDigest: '/assets/styles.css'),
@@ -269,6 +270,63 @@ public static function provideCompileTests(): iterable
269270
'expectedJavaScriptImports' => ['/assets/other.js' => ['lazy' => true, 'asset' => 'other.js', 'add' => true]],
270271
];
271272

273+
yield 'import_in_double_quoted_string_is_ignored' => [
274+
'input' => <<<EOF
275+
const fun;
276+
console.log("import('./foo.js')");
277+
EOF
278+
,
279+
'expectedJavaScriptImports' => [],
280+
];
281+
282+
yield 'import_in_double_quoted_string_with_escaped_quote_is_ignored' => [
283+
'input' => <<<EOF
284+
const fun;
285+
console.log(" foo \" import('./foo.js')");
286+
EOF
287+
,
288+
'expectedJavaScriptImports' => [],
289+
];
290+
291+
yield 'import_in_single_quoted_string_is_ignored' => [
292+
'input' => <<<EOF
293+
const fun;
294+
console.log('import("./foo.js")');
295+
EOF
296+
,
297+
'expectedJavaScriptImports' => [],
298+
];
299+
300+
yield 'import_after_a_string_is_parsed' => [
301+
'input' => <<<EOF
302+
const fun;
303+
console.log("import('./other.js')"); import("./foo.js");
304+
EOF
305+
,
306+
'expectedJavaScriptImports' => ['/assets/foo.js' => ['lazy' => true, 'asset' => 'foo.js', 'add' => true]],
307+
];
308+
309+
yield 'import_before_a_string_is_parsed' => [
310+
'input' => <<<EOF
311+
const fun;
312+
import("./other.js"); console.log("import('./foo.js')");
313+
EOF
314+
,
315+
'expectedJavaScriptImports' => ['/assets/other.js' => ['lazy' => true, 'asset' => 'other.js', 'add' => true]],
316+
];
317+
318+
yield 'import_before_and_after_a_string_is_parsed' => [
319+
'input' => <<<EOF
320+
const fun;
321+
import("./other.js"); console.log("import('./foo.js')"); import("./subdir/foo.js");
322+
EOF
323+
,
324+
'expectedJavaScriptImports' => [
325+
'/assets/other.js' => ['lazy' => true, 'asset' => 'other.js', 'add' => true],
326+
'/assets/subdir/foo.js' => ['lazy' => true, 'asset' => 'subdir/foo.js', 'add' => true],
327+
],
328+
];
329+
272330
yield 'bare_import_not_in_importmap' => [
273331
'input' => 'import "some_module";',
274332
'expectedJavaScriptImports' => [],

0 commit comments

Comments
 (0)
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