microsoft/vscode-react-native

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
678db279088f7b3fd6c7888d37be778e758ff688

Branches

Tags

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

Clone

HTTPS

Download ZIP

src/debugger/scriptImporter.ts

110lines · 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
4import {FileSystem} from "../common/node/fileSystem";
5import {Log} from "../common/log/log";
6import {LogLevel} from "../common/log/logHelper";
7import {Packager} from "../common/packager";
8import path = require("path");
9import Q = require("q");
10import {Request} from "../common/node/request";
11import {SourceMapUtil} from "./sourceMap";
12import url = require("url");
13
14export interface DownloadedScript {
15 contents: string;
16 filepath: string;
17}
18
19interface IStrictUrl extends url.Url {
20 pathname: string;
21 href: string;
22}
23
24export class ScriptImporter {
25 public static DEBUGGER_WORKER_FILE_BASENAME = "debuggerWorker";
26 public static DEBUGGER_WORKER_FILENAME = ScriptImporter.DEBUGGER_WORKER_FILE_BASENAME + ".js";
27 private packagerPort: number;
28 private sourcesStoragePath: string;
29 private sourceMapUtil: SourceMapUtil;
30
31 constructor(packagerPort: number, sourcesStoragePath: string) {
32 this.packagerPort = packagerPort;
33 this.sourcesStoragePath = sourcesStoragePath;
34 this.sourceMapUtil = new SourceMapUtil();
35 }
36
37 public downloadAppScript(scriptUrlString: string): Q.Promise<DownloadedScript> {
38 const parsedScriptUrl = url.parse(scriptUrlString);
39 const overriddenScriptUrlString = (parsedScriptUrl.hostname === "localhost") ? this.overridePackagerPort(scriptUrlString) : scriptUrlString;
40 // We'll get the source code, and store it locally to have a better debugging experience
41 return Request.request(overriddenScriptUrlString, true).then(scriptBody => {
42 // Extract sourceMappingURL from body
43 let scriptUrl = <IStrictUrl>url.parse(overriddenScriptUrlString); // scriptUrl = "http://localhost:8081/index.ios.bundle?platform=ios&dev=true"
44 let sourceMappingUrl = this.sourceMapUtil.getSourceMapURL(scriptUrl, scriptBody); // sourceMappingUrl = "http://localhost:8081/index.ios.map?platform=ios&dev=true"
45
46 let waitForSourceMapping = Q<void>(void 0);
47 if (sourceMappingUrl) {
48 /* handle source map - request it and store it locally */
49 waitForSourceMapping = this.writeAppSourceMap(sourceMappingUrl, scriptUrl)
50 .then(() => {
51 scriptBody = this.sourceMapUtil.updateScriptPaths(scriptBody, <IStrictUrl>sourceMappingUrl);
52 });
53 }
54
55 return waitForSourceMapping
56 .then(() => this.writeAppScript(scriptBody, scriptUrl))
57 .then((scriptFilePath: string) => {
58 Log.logInternalMessage(LogLevel.Info, `Script ${overriddenScriptUrlString} downloaded to ${scriptFilePath}`);
59 return { contents: scriptBody, filepath: scriptFilePath };
60 });
61 });
62 }
63
64 public downloadDebuggerWorker(sourcesStoragePath: string): Q.Promise<void> {
65 return Packager.isPackagerRunning(Packager.getHostForPort(this.packagerPort))
66 .then(running => {
67 if (running) {
68 let debuggerWorkerURL = `http://${Packager.getHostForPort(this.packagerPort)}/${ScriptImporter.DEBUGGER_WORKER_FILENAME}`;
69 let debuggerWorkerLocalPath = path.join(sourcesStoragePath, ScriptImporter.DEBUGGER_WORKER_FILENAME);
70 Log.logInternalMessage(LogLevel.Info, "About to download: " + debuggerWorkerURL + " to: " + debuggerWorkerLocalPath);
71 return Request.request(debuggerWorkerURL, true).then((body: string) => {
72 return new FileSystem().writeFile(debuggerWorkerLocalPath, body);
73 });
74 }
75 throw new RangeError(`Cannot attach to packager. Are you sure there is a packager and it is running in the port ${this.packagerPort}? If your packager is configured to run in another port make sure to add that to the setting.json.`);
76 });
77 }
78
79 /**
80 * Writes the script file to the project temporary location.
81 */
82 private writeAppScript(scriptBody: string, scriptUrl: IStrictUrl): Q.Promise<String> {
83 let scriptFilePath = path.join(this.sourcesStoragePath, path.basename(scriptUrl.pathname)); // scriptFilePath = "$TMPDIR/index.ios.bundle"
84 return new FileSystem().writeFile(scriptFilePath, scriptBody)
85 .then(() => scriptFilePath);
86 }
87
88 /**
89 * Writes the source map file to the project temporary location.
90 */
91 private writeAppSourceMap(sourceMapUrl: IStrictUrl, scriptUrl: IStrictUrl): Q.Promise<void> {
92 return Request.request(sourceMapUrl.href, true)
93 .then((sourceMapBody: string) => {
94 let sourceMappingLocalPath = path.join(this.sourcesStoragePath, path.basename(sourceMapUrl.pathname)); // sourceMappingLocalPath = "$TMPDIR/index.ios.map"
95 let scriptFileRelativePath = path.basename(scriptUrl.pathname); // scriptFileRelativePath = "index.ios.bundle"
96 let updatedContent = this.sourceMapUtil.updateSourceMapFile(sourceMapBody, scriptFileRelativePath, this.sourcesStoragePath);
97 return new FileSystem().writeFile(sourceMappingLocalPath, updatedContent);
98 });
99 }
100
101 /**
102 * Changes the port of the url to be the one configured as this.packagerPort
103 */
104 private overridePackagerPort(urlToOverride: string): string {
105 let components = url.parse(urlToOverride);
106 components.port = this.packagerPort.toString();
107 delete components.host; // We delete the host, if not the port change will be ignored
108 return url.format(components);
109 }
110}
111