microsoft/vscode-react-native

Public

mirrored fromhttps://github.com/microsoft/vscode-react-nativeAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
fix-mocha-this-typing

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

src/debugger/sourceMapsCombinator.ts

134lines · modecode

1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for details.
3
4// eslint-disable-next-line @typescript-eslint/triple-slash-reference
5/// <reference path="./../typings/debugger/sourceMapsCombinator.d.ts" />
6
7import * as fs from "fs";
8import * as path from "path";
9import {
10 SourceMapConsumer,
11 RawSourceMap,
12 SourceMapGenerator,
13 MappingItem,
14 Mapping,
15 Position,
16 NullableMappedPosition,
17} from "source-map";
18import * as sourceMapResolve from "source-map-resolve";
19
20const DISK_LETTER_RE = /^(?:[a-z]{2,}:\/{3})?[a-z]:/i;
21
22export class SourceMapsCombinator {
23 public convert(rawBundleSourcemap: RawSourceMap): RawSourceMap {
24 // Find user files from bundle files list
25 const consumers: { [key: string]: SourceMapConsumer } = rawBundleSourcemap.sources.reduce(
26 (result: { [key: string]: SourceMapConsumer }, file) => {
27 // Skip files inside node_modules
28 if (file.includes("node_modules")) return result;
29
30 try {
31 const consumer: SourceMapConsumer | null = this.getSourceMapConsumerFrom(file);
32 if (consumer) result[file] = consumer;
33 } finally {
34 return result;
35 }
36 },
37 {},
38 );
39
40 if (Object.keys(consumers).length === 0) {
41 // Sourcemaps not found, so return original bundle sourcemap
42 return rawBundleSourcemap;
43 }
44
45 const generator = new SourceMapGenerator();
46 const bundleConsumer = new SourceMapConsumer(rawBundleSourcemap);
47
48 bundleConsumer.eachMapping((item: MappingItem) => {
49 if (item.source === null) {
50 // Some mappings in react native bundle have no sources
51 return;
52 }
53
54 // Copy mappings
55 const mapping: Mapping = {
56 generated: { line: item.generatedLine, column: item.generatedColumn },
57 original: { line: item.originalLine, column: item.originalColumn },
58 source: item.source,
59 name: item.name,
60 };
61
62 if (consumers[item.source]) {
63 const jsPosition: Position = {
64 line: item.originalLine,
65 column: item.originalColumn,
66 };
67 const tsPosition: NullableMappedPosition =
68 consumers[item.source].originalPositionFor(jsPosition);
69
70 if (tsPosition.source === null) {
71 // Some positions from react native generated bundle can not translate to TS source positions
72 // skip them
73 return;
74 }
75
76 // Resolve TS source path to absolute because it might be relative to generated JS
77 // (this depends on whether "sourceRoot" option is specified in tsconfig.json)
78 if (!tsPosition.source.match(DISK_LETTER_RE)) {
79 // This check for Windows tests which were run on MacOs
80 tsPosition.source = path.resolve(
81 <string>rawBundleSourcemap.sourceRoot,
82 path.dirname(item.source),
83 tsPosition.source,
84 );
85 }
86
87 // Update mapping w/ mapped position values
88 mapping.source = tsPosition.source;
89 mapping.name = tsPosition.name || mapping.name;
90 if (tsPosition.line !== null && tsPosition.column !== null) {
91 mapping.original = { line: tsPosition.line, column: tsPosition.column };
92 }
93 }
94
95 try {
96 generator.addMapping(mapping);
97 } catch (err) {}
98 });
99
100 return generator.toJSON();
101 }
102
103 private getSourceMapConsumerFrom(generatedFile: string): SourceMapConsumer | null {
104 const code = fs.readFileSync(generatedFile);
105
106 const consumer = this.readSourcemap(generatedFile, code.toString());
107 return consumer;
108 }
109
110 private readSourcemap(file: string, code: string): SourceMapConsumer | null {
111 const result = sourceMapResolve.resolveSync(
112 code,
113 file,
114 readFileSync.bind(null, getDiskLetter(file)),
115 );
116 if (result === null) {
117 return null;
118 }
119 return new SourceMapConsumer(result.map);
120 }
121}
122
123// Hack for source-map-resolve and cutted disk letter
124// https://github.com/lydell/source-map-resolve/issues/9
125function readFileSync(diskLetter: string, filePath: string) {
126 return filePath.match(DISK_LETTER_RE)
127 ? fs.readFileSync(filePath)
128 : fs.readFileSync(`${diskLetter}${filePath}`);
129}
130
131function getDiskLetter(filePath: string): string {
132 const matched = filePath.match(DISK_LETTER_RE);
133 return matched ? matched[0] : "";
134}
135