microsoft/vscode-react-native

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
3f381d8cbe397a4c94fbdcb93142cd2dc36ed84a

Branches

Tags

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

Clone

HTTPS

Download ZIP

src/debugger/scriptImporter.ts

150lines · modeblame

a31b007cunknown10 years ago1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for details.
3
b0061ac6Meena Kunnathur Balakrishnan10 years ago4import {FileSystem} from "../common/node/fileSystem";
0a68f8dbArtem Egorov8 years ago5import { logger } from "vscode-chrome-debug-core";
6import { ensurePackagerRunning } from "../common/packagerStatus";
3fb37ad5unknown10 years ago7import path = require("path");
8import Q = require("q");
b0061ac6Meena Kunnathur Balakrishnan10 years ago9import {Request} from "../common/node/request";
10import {SourceMapUtil} from "./sourceMap";
3fb37ad5unknown10 years ago11import url = require("url");
a1324704Artem Egorov8 years ago12import * as semver from "semver";
13import {ReactNativeProjectHelper} from "../common/reactNativeProjectHelper";
d124bf0eYuri Skorokhodov7 years ago14import { ErrorHelper } from "../common/error/errorHelper";
15import { InternalErrorCode } from "../common/error/internalErrorCode";
3fb37ad5unknown10 years ago16
5c8365a6Artem Egorov8 years ago17export interface DownloadedScript {
4677921cdigeff10 years ago18contents: string;
19filepath: string;
20}
21
5c8365a6Artem Egorov8 years ago22interface IStrictUrl extends url.Url {
23pathname: string;
24href: string;
25}
26
3fb37ad5unknown10 years ago27export class ScriptImporter {
2743f19cdlebu10 years ago28public static DEBUGGER_WORKER_FILE_BASENAME = "debuggerWorker";
29public static DEBUGGER_WORKER_FILENAME = ScriptImporter.DEBUGGER_WORKER_FILE_BASENAME + ".js";
6eeec3c0Serge Svekolnikov8 years ago30private packagerAddress: string;
e3ae4227digeff10 years ago31private packagerPort: number;
4677921cdigeff10 years ago32private sourcesStoragePath: string;
6eeec3c0Serge Svekolnikov8 years ago33private packagerRemoteRoot?: string;
34private packagerLocalRoot?: string;
4bd0c669dlebu10 years ago35private sourceMapUtil: SourceMapUtil;
3fb37ad5unknown10 years ago36
6eeec3c0Serge Svekolnikov8 years ago37constructor(packagerAddress: string, packagerPort: number, sourcesStoragePath: string, packagerRemoteRoot?: string, packagerLocalRoot?: string) {
38this.packagerAddress = packagerAddress;
e3ae4227digeff10 years ago39this.packagerPort = packagerPort;
4677921cdigeff10 years ago40this.sourcesStoragePath = sourcesStoragePath;
6eeec3c0Serge Svekolnikov8 years ago41this.packagerRemoteRoot = packagerRemoteRoot;
42this.packagerLocalRoot = packagerLocalRoot;
4bd0c669dlebu10 years ago43this.sourceMapUtil = new SourceMapUtil();
3fb37ad5unknown10 years ago44}
45
979d7bfemax-mironov8 years ago46public downloadAppScript(scriptUrlString: string, projectRootPath: string): Q.Promise<DownloadedScript> {
1c32fe84Patricio Beltran9 years ago47const parsedScriptUrl = url.parse(scriptUrlString);
48const overriddenScriptUrlString = (parsedScriptUrl.hostname === "localhost") ? this.overridePackagerPort(scriptUrlString) : scriptUrlString;
e00f7325unknown10 years ago49// We'll get the source code, and store it locally to have a better debugging experience
833e37c7Vladimir Kotikov8 years ago50return Request.request(overriddenScriptUrlString, true).then(scriptBody => {
979d7bfemax-mironov8 years ago51return ReactNativeProjectHelper.getReactNativeVersion(projectRootPath).then(rnVersion => {
52// unfortunatelly Metro Bundler is broken in RN 0.54.x versions, so use this workaround unless it will be fixed
53// https://github.com/facebook/metro/issues/147
54// https://github.com/Microsoft/vscode-react-native/issues/660
55if (ReactNativeProjectHelper.getRNVersionsWithBrokenMetroBundler().indexOf(rnVersion) >= 0) {
56let noSourceMappingUrlGenerated = scriptBody.match(/sourceMappingURL=/g) === null;
57if (noSourceMappingUrlGenerated) {
58let sourceMapPathUrl = overriddenScriptUrlString.replace("bundle", "map");
59scriptBody = this.sourceMapUtil.appendSourceMapPaths(scriptBody, sourceMapPathUrl);
60}
61}
e00f7325unknown10 years ago62
979d7bfemax-mironov8 years ago63// Extract sourceMappingURL from body
64let scriptUrl = <IStrictUrl>url.parse(overriddenScriptUrlString); // scriptUrl = "http://localhost:8081/index.ios.bundle?platform=ios&dev=true"
65let sourceMappingUrl = this.sourceMapUtil.getSourceMapURL(scriptUrl, scriptBody); // sourceMappingUrl = "http://localhost:8081/index.ios.map?platform=ios&dev=true"
4677921cdigeff10 years ago66
979d7bfemax-mironov8 years ago67let waitForSourceMapping = Q<void>(void 0);
68if (sourceMappingUrl) {
69/* handle source map - request it and store it locally */
70waitForSourceMapping = this.writeAppSourceMap(sourceMappingUrl, scriptUrl)
71.then(() => {
72scriptBody = this.sourceMapUtil.updateScriptPaths(scriptBody, <IStrictUrl>sourceMappingUrl);
73});
74}
75
76return waitForSourceMapping
2743f19cdlebu10 years ago77.then(() => this.writeAppScript(scriptBody, scriptUrl))
4677921cdigeff10 years ago78.then((scriptFilePath: string) => {
0a68f8dbArtem Egorov8 years ago79logger.verbose(`Script ${overriddenScriptUrlString} downloaded to ${scriptFilePath}`);
4677921cdigeff10 years ago80return { contents: scriptBody, filepath: scriptFilePath };
876df2a0dlebu10 years ago81});
979d7bfemax-mironov8 years ago82});
e00f7325unknown10 years ago83});
84}
85
cf911877Yuri Skorokhodov7 years ago86public downloadDebuggerWorker(sourcesStoragePath: string, projectRootPath: string, debuggerWorkerUrlPath?: string): Q.Promise<void> {
d124bf0eYuri Skorokhodov7 years ago87const errPackagerNotRunning = ErrorHelper.getInternalError(InternalErrorCode.CannotAttachToPackagerCheckPackagerRunningOnPort, this.packagerPort);
6eeec3c0Serge Svekolnikov8 years ago88return ensurePackagerRunning(this.packagerAddress, this.packagerPort, errPackagerNotRunning)
0a68f8dbArtem Egorov8 years ago89.then(() => {
a1324704Artem Egorov8 years ago90return ReactNativeProjectHelper.getReactNativeVersion(projectRootPath);
91})
92.then((rnVersion: string) => {
cf911877Yuri Skorokhodov7 years ago93let debuggerWorkerURL = this.prepareDebuggerWorkerURL(rnVersion, debuggerWorkerUrlPath);
0a68f8dbArtem Egorov8 years ago94let debuggerWorkerLocalPath = path.join(sourcesStoragePath, ScriptImporter.DEBUGGER_WORKER_FILENAME);
95logger.verbose("About to download: " + debuggerWorkerURL + " to: " + debuggerWorkerLocalPath);
96
97return Request.request(debuggerWorkerURL, true)
98.then((body: string) => {
299b0557Patricio Beltran10 years ago99return new FileSystem().writeFile(debuggerWorkerLocalPath, body);
100});
101});
2743f19cdlebu10 years ago102}
103
cf911877Yuri Skorokhodov7 years ago104public prepareDebuggerWorkerURL(rnVersion: string, debuggerWorkerUrlPath?: string): string {
105let debuggerWorkerURL: string;
106// It can be empty string
107if (debuggerWorkerUrlPath !== undefined) {
108debuggerWorkerURL = `http://${this.packagerAddress}:${this.packagerPort}/${debuggerWorkerUrlPath}${ScriptImporter.DEBUGGER_WORKER_FILENAME}`;
109} else {
110let newPackager = "";
111if (!semver.valid(rnVersion) /*Custom RN implementations should support new packager*/ || (semver.gte(rnVersion, "0.50.0"))) {
112newPackager = "debugger-ui/";
113}
114debuggerWorkerURL = `http://${this.packagerAddress}:${this.packagerPort}/${newPackager}${ScriptImporter.DEBUGGER_WORKER_FILENAME}`;
115}
116return debuggerWorkerURL;
117}
118
e00f7325unknown10 years ago119/**
120* Writes the script file to the project temporary location.
121*/
5c8365a6Artem Egorov8 years ago122private writeAppScript(scriptBody: string, scriptUrl: IStrictUrl): Q.Promise<String> {
bb77358cMark Oswald10 years ago123let scriptFilePath = path.join(this.sourcesStoragePath, path.basename(scriptUrl.pathname)); // scriptFilePath = "$TMPDIR/index.ios.bundle"
f218397cdlebu10 years ago124return new FileSystem().writeFile(scriptFilePath, scriptBody)
125.then(() => scriptFilePath);
3fb37ad5unknown10 years ago126}
127
e00f7325unknown10 years ago128/**
129* Writes the source map file to the project temporary location.
130*/
5c8365a6Artem Egorov8 years ago131private writeAppSourceMap(sourceMapUrl: IStrictUrl, scriptUrl: IStrictUrl): Q.Promise<void> {
833e37c7Vladimir Kotikov8 years ago132return Request.request(sourceMapUrl.href, true)
e00f7325unknown10 years ago133.then((sourceMapBody: string) => {
bb77358cMark Oswald10 years ago134let sourceMappingLocalPath = path.join(this.sourcesStoragePath, path.basename(sourceMapUrl.pathname)); // sourceMappingLocalPath = "$TMPDIR/index.ios.map"
135let scriptFileRelativePath = path.basename(scriptUrl.pathname); // scriptFileRelativePath = "index.ios.bundle"
6eeec3c0Serge Svekolnikov8 years ago136let updatedContent = this.sourceMapUtil.updateSourceMapFile(sourceMapBody, scriptFileRelativePath, this.sourcesStoragePath, this.packagerRemoteRoot, this.packagerLocalRoot);
f218397cdlebu10 years ago137return new FileSystem().writeFile(sourceMappingLocalPath, updatedContent);
e00f7325unknown10 years ago138});
3fb37ad5unknown10 years ago139}
5e651f3edigeff10 years ago140
141/**
142* Changes the port of the url to be the one configured as this.packagerPort
143*/
144private overridePackagerPort(urlToOverride: string): string {
145let components = url.parse(urlToOverride);
146components.port = this.packagerPort.toString();
147delete components.host; // We delete the host, if not the port change will be ignored
148return url.format(components);
149}
3fb37ad5unknown10 years ago150}