Skip to content

Commit 64e6201

Browse files
Map javascript source maps
Signed-off-by: Aryan-SINGH-GIT <aryansingh12oct2005@gmail.com>
1 parent 92012d5 commit 64e6201

File tree

8 files changed

+187
-0
lines changed

8 files changed

+187
-0
lines changed

ruff_errors.txt

2.85 KB
Binary file not shown.

scanpipe/pipelines/deploy_to_develop.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ def steps(cls):
109109
cls.map_javascript_post_purldb_match,
110110
cls.map_javascript_path,
111111
cls.map_javascript_colocation,
112+
cls.map_javascript_source_map_sources,
112113
cls.map_thirdparty_npm_packages,
113114
cls.map_path,
114115
cls.flag_mapped_resources_archives_and_ignored_directories,
@@ -449,6 +450,11 @@ def map_javascript_colocation(self):
449450
"""Map JavaScript files based on neighborhood file mapping."""
450451
d2d.map_javascript_colocation(project=self.project, logger=self.log)
451452

453+
@optional_step("JavaScript")
454+
def map_javascript_source_map_sources(self):
455+
"""Map .map files by resolving listed sources against the from/ codebase."""
456+
d2d.map_javascript_source_map_sources(project=self.project, logger=self.log)
457+
452458
@optional_step("JavaScript")
453459
def map_thirdparty_npm_packages(self):
454460
"""Map thirdparty package using package.json metadata."""

scanpipe/pipes/d2d.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1297,6 +1297,79 @@ def _map_javascript_colocation_resource(
12971297
)
12981298

12991299

1300+
def _map_javascript_source_map_resource(to_map, from_resources, from_resources_index):
1301+
"""Map a `.map` file by resolving its `sources` against the `from/` codebase."""
1302+
sources = js.get_map_sources(to_map)
1303+
if not sources:
1304+
return 0
1305+
1306+
matched_from_resources = []
1307+
for source_path in sources:
1308+
match = pathmap.find_paths(source_path, from_resources_index)
1309+
if not match:
1310+
to_map.update(status=flag.REQUIRES_REVIEW)
1311+
return 0
1312+
1313+
# Reject ambiguous matches where there are more candidate resources
1314+
# than the number of path segments actually matched.
1315+
if len(match.resource_ids) > match.matched_path_length:
1316+
to_map.update(status=flag.REQUIRES_REVIEW)
1317+
return 0
1318+
1319+
from_resource = from_resources.get(id=match.resource_ids[0])
1320+
matched_from_resources.append(from_resource)
1321+
1322+
# All sources resolved – create relations and mark the .map file as mapped.
1323+
for from_resource in matched_from_resources:
1324+
pipes.make_relation(
1325+
from_resource=from_resource,
1326+
to_resource=to_map,
1327+
map_type="js_source_map",
1328+
extra_data={"source_count": len(sources)},
1329+
)
1330+
1331+
to_map.update(status=flag.MAPPED)
1332+
return 1
1333+
1334+
1335+
def map_javascript_source_map_sources(project, logger=None):
1336+
"""Map .map files by resolving their sources against the from/ codebase."""
1337+
project_files = project.codebaseresources.files()
1338+
1339+
to_resources_dot_map = (
1340+
project_files.to_codebase()
1341+
.no_status()
1342+
.filter(extension=".map")
1343+
.exclude(name__startswith=".")
1344+
.exclude(path__contains="/node_modules/")
1345+
)
1346+
1347+
from_resources = project_files.from_codebase().exclude(path__contains="/test/")
1348+
resource_count = to_resources_dot_map.count()
1349+
1350+
if logger:
1351+
logger(
1352+
f"Mapping {resource_count:,d} .map source-map files by resolving their "
1353+
f"sources against the from/ codebase."
1354+
)
1355+
1356+
from_resources_index = pathmap.build_index(
1357+
from_resources.values_list("id", "path"), with_subpaths=True
1358+
)
1359+
1360+
resource_iterator = to_resources_dot_map.iterator(chunk_size=2000)
1361+
progress = LoopProgress(resource_count, logger)
1362+
map_count = 0
1363+
1364+
for to_map in progress.iter(resource_iterator):
1365+
map_count += _map_javascript_source_map_resource(
1366+
to_map, from_resources, from_resources_index
1367+
)
1368+
1369+
if logger:
1370+
logger(f"{map_count:,d} .map source-map files mapped")
1371+
1372+
13001373
def flag_processed_archives(project):
13011374
"""
13021375
Flag package archives as processed if they meet the following criteria:
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export function error() { }
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export function queue() { }

scanpipe/tests/data/d2d-javascript/to/bundle.js.map

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

scanpipe/tests/data/d2d-javascript/to/partial.js.map

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

scanpipe/tests/pipes/test_d2d.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2500,3 +2500,89 @@ def test_scanpipe_pipes_d2d_map_python_protobuf_files_no_py_files(self):
25002500
d2d.map_python_protobuf_files(self.project1)
25012501
relations = self.project1.codebaserelations.filter(map_type="protobuf_mapping")
25022502
self.assertEqual(0, relations.count())
2503+
2504+
def test_scanpipe_pipes_d2d_map_javascript_source_map_all_found(self):
2505+
"""
2506+
Test .map file with all sources present.
2507+
2508+
It creates relations and is flagged MAPPED.
2509+
"""
2510+
to_dir = self.project1.codebase_path / "to/dist"
2511+
to_dir.mkdir(parents=True)
2512+
copy_input(
2513+
self.data / "d2d-javascript" / "to" / "bundle.js.map",
2514+
to_dir,
2515+
)
2516+
2517+
from_dir = self.project1.codebase_path / "from/src"
2518+
from_dir.mkdir(parents=True)
2519+
copy_inputs(
2520+
[
2521+
self.data / "d2d-javascript" / "from" / "queue.ts",
2522+
self.data / "d2d-javascript" / "from" / "error.ts",
2523+
],
2524+
from_dir,
2525+
)
2526+
2527+
pipes.collect_and_create_codebase_resources(self.project1)
2528+
2529+
to_map = self.project1.codebaseresources.get(path="to/dist/bundle.js.map")
2530+
from_queue = self.project1.codebaseresources.get(path="from/src/queue.ts")
2531+
from_error = self.project1.codebaseresources.get(path="from/src/error.ts")
2532+
2533+
buffer = io.StringIO()
2534+
d2d.map_javascript_source_map_sources(self.project1, logger=buffer.write)
2535+
2536+
self.assertIn(
2537+
"Mapping 1 .map source-map files by resolving their sources",
2538+
buffer.getvalue(),
2539+
)
2540+
self.assertIn("1 .map source-map files mapped", buffer.getvalue())
2541+
2542+
to_map.refresh_from_db()
2543+
self.assertEqual(flag.MAPPED, to_map.status)
2544+
2545+
self.assertEqual(2, self.project1.codebaserelations.count())
2546+
relation_types = set(
2547+
self.project1.codebaserelations.values_list("map_type", flat=True)
2548+
)
2549+
self.assertEqual({"js_source_map"}, relation_types)
2550+
2551+
related_from_ids = set(
2552+
self.project1.codebaserelations.values_list("from_resource_id", flat=True)
2553+
)
2554+
self.assertIn(from_queue.id, related_from_ids)
2555+
self.assertIn(from_error.id, related_from_ids)
2556+
2557+
def test_scanpipe_pipes_d2d_map_javascript_source_map_partial(self):
2558+
"""
2559+
Test .map file with missing source.
2560+
2561+
It is flagged REQUIRES_REVIEW with no relations.
2562+
"""
2563+
to_dir = self.project1.codebase_path / "to/dist"
2564+
to_dir.mkdir(parents=True)
2565+
copy_input(
2566+
self.data / "d2d-javascript" / "to" / "partial.js.map",
2567+
to_dir,
2568+
)
2569+
2570+
from_dir = self.project1.codebase_path / "from/src"
2571+
from_dir.mkdir(parents=True)
2572+
copy_input(
2573+
self.data / "d2d-javascript" / "from" / "queue.ts",
2574+
from_dir,
2575+
)
2576+
2577+
pipes.collect_and_create_codebase_resources(self.project1)
2578+
2579+
to_map = self.project1.codebaseresources.get(path="to/dist/partial.js.map")
2580+
2581+
buffer = io.StringIO()
2582+
d2d.map_javascript_source_map_sources(self.project1, logger=buffer.write)
2583+
2584+
self.assertIn("0 .map source-map files mapped", buffer.getvalue())
2585+
2586+
to_map.refresh_from_db()
2587+
self.assertEqual(flag.REQUIRES_REVIEW, to_map.status)
2588+
self.assertEqual(0, self.project1.codebaserelations.count())

0 commit comments

Comments
 (0)