microsoft/vscode-react-native

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
caa0dc5eb84731caee69a4d06915c6a3856ec289

Branches

Tags

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

Clone

HTTPS

Download ZIP

src/debugger/sourceMapsCombinator.ts

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