microsoft/vscode-react-native

Public

mirrored from https://github.com/microsoft/vscode-react-nativeAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
bedf110fbb4cf82fb995f4cf2770e8339d5adbea

Branches

Tags

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

Clone

HTTPS

Download ZIP

src/debugger/scriptImporter.ts

109lines · modeblame

3fb37ad5unknown10 years ago1import fs = require("fs");
2import http = require("http");
bedf110funknown10 years ago3import {Log} from "../utils/commands/log";
3fb37ad5unknown10 years ago4import path = require("path");
5import Q = require("q");
6import request = require("request");
7import url = require("url");
8import vm = require("vm");
9
10interface ISourceMap {
11file: string;
12sources: string[];
13version: number;
14names: string[];
15mappings: string;
16sourceRoot?: string;
17sourcesContent?: string[];
18}
19
20export class ScriptImporter {
21private projectRootPath: string;
22private bundleFolderPath: string;
23
24constructor(projectRootPath: string) {
25this.projectRootPath = projectRootPath;
26// We put the source code inside the workspace, because VS Code doesn't seem to support source mapping if we don't do that
27this.bundleFolderPath = path.join(this.projectRootPath, ".vscode");
28}
29
30private fixSourceMap(sourceMapBody: string, generatedCodeFilePath: string): string {
31try {
32let sourceMap = <ISourceMap> JSON.parse(sourceMapBody);
33sourceMap.sources = sourceMap.sources.map(source => {
34// Make all paths relative to the location of the source map
35let relativeSourcePath = path.relative(this.bundleFolderPath, source);
36let sourceUrl = relativeSourcePath.replace(/\\/g, "/");
37return sourceUrl;
38});
39// fixedSourceMapBody.sourceRoot = "..";
40delete sourceMap.sourcesContent;
41sourceMap.sourceRoot = "";
42sourceMap.file = generatedCodeFilePath;
43return JSON.stringify(sourceMap);
44} catch (exception) {
45return sourceMapBody;
46}
47}
48
49public import(scriptUrl: string): Q.Promise<void> {
50
51// We'll get the source code, and store it locally to have a better debugging experience
52return this.request(scriptUrl).then(scriptBody => {
53// Extract sourceMappingURL from body
54let parsedUrl = url.parse(scriptUrl); // scriptUrl = "http://localhost:8081/index.ios.bundle?platform=ios&dev=true"
55let sourceMappingRelativeUrl = this.sourceMapRelativeUrl(scriptBody); // sourceMappingRelativeUrl = "/index.ios.map?platform=ios&dev=true"
56let sourceMappingUrl = parsedUrl.protocol + "//" + parsedUrl.host + sourceMappingRelativeUrl; // sourceMappingUrl = "http://localhost:8081/index.ios.map?platform=ios&dev=true"
57
58// We'll get the source map, and story it locally, so we can debug the original files instead of the bundle
59return this.request(sourceMappingUrl).then(sourceMapBody => {
60let sourceMappingRelativePath = url.parse(sourceMappingRelativeUrl).pathname.substr(1); // sourceMappingRelativePath = "index.ios.map?platform=ios&dev=true"
61let sourceMappingLocalPath = path.join(this.bundleFolderPath, sourceMappingRelativePath); // sourceMappingLocalPath = "$TMPDIR/index.ios.map?platform=ios&dev=true"
62let scriptFileRelativePath = path.basename(parsedUrl.pathname); // scriptFileRelativePath = "index.ios.bundle"
63this.writeTemporaryFileSync(sourceMappingLocalPath, this.fixSourceMap(sourceMapBody, scriptFileRelativePath));
64// Update the body with the new location of the source map on storage
65scriptBody = scriptBody.replace(/^\/\/# sourceMappingURL=(.*)$/m, "//# sourceMappingURL=" + sourceMappingRelativePath);
66}).then(() => { // TODO: Figure out how to handle the case that the source mapping fails.
67let scriptFilePath = path.join(this.bundleFolderPath, parsedUrl.pathname); // scriptFilePath = "$TMPDIR/index.ios.bundle"
68this.writeTemporaryFileSync(scriptFilePath, scriptBody);
69
70// The next line converts to any due to the incorrect typing on node.d.ts of vm.runInThisContext
71vm.runInThisContext(scriptBody, <any>{ filename: scriptFilePath });
bedf110funknown10 years ago72Log.logMessage("Imported script at " + scriptUrl + " locally stored on " + this.bundleFolderPath);
3fb37ad5unknown10 years ago73});
74});
75}
76
77private writeTemporaryFileSync(filename: string, data: string) {
78fs.writeFileSync(filename, data);
79this.scheduleTemporaryFileCleanUp(filename);
80}
81private scheduleTemporaryFileCleanUp(filename: string) {
82process.on("exit", function (){
83fs.unlinkSync(filename);
bedf110funknown10 years ago84Log.logMessage("Succesfully cleaned temporary file: " + filename);
3fb37ad5unknown10 years ago85});
86}
87
88private sourceMapRelativeUrl(body: any) {
89let match = body.match(/^\/\/# sourceMappingURL=(.*)$/m);
90// If match is null, the body doesn't contain the source map
91return match ? match[1] : null;
92}
93
94private request(uri: string): Q.Promise<any> {
95let result = Q.defer<any>();
96request(uri, function (error: any, response: http.IncomingMessage, body: any) {
97if (!error) {
98if (response.statusCode === 200) {
99result.resolve(body);
100} else {
101result.reject(body);
102}
103} else {
104result.reject(error);
105}
106});
107return result.promise;
108}
109}