microsoft/vscode-react-native

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
58882bb6b3dda8f9ee5cf6fad0f03021b3cb44a3

Branches

Tags

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

Clone

HTTPS

Download ZIP

src/debugger/scriptImporter.ts

152lines · 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
a6562589RedMickey6 years ago4import { logger } from "vscode-debugadapter";
0a68f8dbArtem Egorov8 years ago5import { ensurePackagerRunning } from "../common/packagerStatus";
3fb37ad5unknown10 years ago6import path = require("path");
b0061ac6Meena Kunnathur Balakrishnan10 years ago7import {Request} from "../common/node/request";
8import {SourceMapUtil} from "./sourceMap";
3fb37ad5unknown10 years ago9import url = require("url");
a1324704Artem Egorov8 years ago10import * as semver from "semver";
e3706a1cRedMickey6 years ago11import {ProjectVersionHelper, RNPackageVersions} from "../common/projectVersionHelper";
d124bf0eYuri Skorokhodov7 years ago12import { ErrorHelper } from "../common/error/errorHelper";
13import { InternalErrorCode } from "../common/error/internalErrorCode";
ce5e88eeYuri Skorokhodov5 years ago14import { FileSystem } from "../common/node/fileSystem";
3fb37ad5unknown10 years ago15
5c8365a6Artem Egorov8 years ago16export interface DownloadedScript {
4677921cdigeff10 years ago17contents: string;
18filepath: string;
19}
20
5c8365a6Artem Egorov8 years ago21interface IStrictUrl extends url.Url {
22pathname: string;
23href: string;
24}
25
3fb37ad5unknown10 years ago26export class ScriptImporter {
2743f19cdlebu10 years ago27public static DEBUGGER_WORKER_FILE_BASENAME = "debuggerWorker";
28public static DEBUGGER_WORKER_FILENAME = ScriptImporter.DEBUGGER_WORKER_FILE_BASENAME + ".js";
6eeec3c0Serge Svekolnikov8 years ago29private packagerAddress: string;
e3ae4227digeff10 years ago30private packagerPort: number;
4677921cdigeff10 years ago31private sourcesStoragePath: string;
6eeec3c0Serge Svekolnikov8 years ago32private packagerRemoteRoot?: string;
33private packagerLocalRoot?: string;
4bd0c669dlebu10 years ago34private sourceMapUtil: SourceMapUtil;
3fb37ad5unknown10 years ago35
6eeec3c0Serge Svekolnikov8 years ago36constructor(packagerAddress: string, packagerPort: number, sourcesStoragePath: string, packagerRemoteRoot?: string, packagerLocalRoot?: string) {
37this.packagerAddress = packagerAddress;
e3ae4227digeff10 years ago38this.packagerPort = packagerPort;
4677921cdigeff10 years ago39this.sourcesStoragePath = sourcesStoragePath;
6eeec3c0Serge Svekolnikov8 years ago40this.packagerRemoteRoot = packagerRemoteRoot;
41this.packagerLocalRoot = packagerLocalRoot;
4bd0c669dlebu10 years ago42this.sourceMapUtil = new SourceMapUtil();
3fb37ad5unknown10 years ago43}
44
ce5e88eeYuri Skorokhodov5 years ago45public downloadAppScript(scriptUrlString: string, projectRootPath: string): Promise<DownloadedScript> {
1c32fe84Patricio Beltran9 years ago46const parsedScriptUrl = url.parse(scriptUrlString);
47const overriddenScriptUrlString = (parsedScriptUrl.hostname === "localhost") ? this.overridePackagerPort(scriptUrlString) : scriptUrlString;
e00f7325unknown10 years ago48// We'll get the source code, and store it locally to have a better debugging experience
833e37c7Vladimir Kotikov8 years ago49return Request.request(overriddenScriptUrlString, true).then(scriptBody => {
e3706a1cRedMickey6 years ago50return ProjectVersionHelper.getReactNativeVersions(projectRootPath).then(rnVersions => {
979d7bfemax-mironov8 years ago51// unfortunatelly Metro Bundler is broken in RN 0.54.x versions, so use this workaround unless it will be fixed
52// https://github.com/facebook/metro/issues/147
af0c5c30Yuri Skorokhodov5 years ago53// https://github.com/microsoft/vscode-react-native/issues/660
e3706a1cRedMickey6 years ago54if (ProjectVersionHelper.getRNVersionsWithBrokenMetroBundler().indexOf(rnVersions.reactNativeVersion) >= 0) {
979d7bfemax-mironov8 years ago55let noSourceMappingUrlGenerated = scriptBody.match(/sourceMappingURL=/g) === null;
56if (noSourceMappingUrlGenerated) {
57let sourceMapPathUrl = overriddenScriptUrlString.replace("bundle", "map");
58scriptBody = this.sourceMapUtil.appendSourceMapPaths(scriptBody, sourceMapPathUrl);
59}
60}
e00f7325unknown10 years ago61
979d7bfemax-mironov8 years ago62// Extract sourceMappingURL from body
63let scriptUrl = <IStrictUrl>url.parse(overriddenScriptUrlString); // scriptUrl = "http://localhost:8081/index.ios.bundle?platform=ios&dev=true"
64let sourceMappingUrl = this.sourceMapUtil.getSourceMapURL(scriptUrl, scriptBody); // sourceMappingUrl = "http://localhost:8081/index.ios.map?platform=ios&dev=true"
4677921cdigeff10 years ago65
ce5e88eeYuri Skorokhodov5 years ago66let waitForSourceMapping: Promise<void> = Promise.resolve();
979d7bfemax-mironov8 years ago67if (sourceMappingUrl) {
68/* handle source map - request it and store it locally */
69waitForSourceMapping = this.writeAppSourceMap(sourceMappingUrl, scriptUrl)
70.then(() => {
71scriptBody = this.sourceMapUtil.updateScriptPaths(scriptBody, <IStrictUrl>sourceMappingUrl);
7fa90b3bRedMickey6 years ago72if (semver.gte(rnVersions.reactNativeVersion, "0.61.0")) {
2f5c780bYuri Skorokhodov6 years ago73scriptBody = this.sourceMapUtil.removeSourceURL(scriptBody);
74}
979d7bfemax-mironov8 years ago75});
76}
77
78return waitForSourceMapping
2743f19cdlebu10 years ago79.then(() => this.writeAppScript(scriptBody, scriptUrl))
4677921cdigeff10 years ago80.then((scriptFilePath: string) => {
0a68f8dbArtem Egorov8 years ago81logger.verbose(`Script ${overriddenScriptUrlString} downloaded to ${scriptFilePath}`);
4677921cdigeff10 years ago82return { contents: scriptBody, filepath: scriptFilePath };
876df2a0dlebu10 years ago83});
979d7bfemax-mironov8 years ago84});
e00f7325unknown10 years ago85});
86}
87
ce5e88eeYuri Skorokhodov5 years ago88public downloadDebuggerWorker(sourcesStoragePath: string, projectRootPath: string, debuggerWorkerUrlPath?: string): Promise<void> {
d124bf0eYuri Skorokhodov7 years ago89const errPackagerNotRunning = ErrorHelper.getInternalError(InternalErrorCode.CannotAttachToPackagerCheckPackagerRunningOnPort, this.packagerPort);
6eeec3c0Serge Svekolnikov8 years ago90return ensurePackagerRunning(this.packagerAddress, this.packagerPort, errPackagerNotRunning)
0a68f8dbArtem Egorov8 years ago91.then(() => {
e3706a1cRedMickey6 years ago92return ProjectVersionHelper.getReactNativeVersions(projectRootPath);
a1324704Artem Egorov8 years ago93})
7fa90b3bRedMickey6 years ago94.then((rnVersions: RNPackageVersions) => {
95let debuggerWorkerURL = this.prepareDebuggerWorkerURL(rnVersions.reactNativeVersion, debuggerWorkerUrlPath);
0a68f8dbArtem Egorov8 years ago96let debuggerWorkerLocalPath = path.join(sourcesStoragePath, ScriptImporter.DEBUGGER_WORKER_FILENAME);
97logger.verbose("About to download: " + debuggerWorkerURL + " to: " + debuggerWorkerLocalPath);
98
99return Request.request(debuggerWorkerURL, true)
100.then((body: string) => {
299b0557Patricio Beltran10 years ago101return new FileSystem().writeFile(debuggerWorkerLocalPath, body);
102});
103});
2743f19cdlebu10 years ago104}
105
cf911877Yuri Skorokhodov7 years ago106public prepareDebuggerWorkerURL(rnVersion: string, debuggerWorkerUrlPath?: string): string {
107let debuggerWorkerURL: string;
108// It can be empty string
109if (debuggerWorkerUrlPath !== undefined) {
110debuggerWorkerURL = `http://${this.packagerAddress}:${this.packagerPort}/${debuggerWorkerUrlPath}${ScriptImporter.DEBUGGER_WORKER_FILENAME}`;
111} else {
112let newPackager = "";
113if (!semver.valid(rnVersion) /*Custom RN implementations should support new packager*/ || (semver.gte(rnVersion, "0.50.0"))) {
114newPackager = "debugger-ui/";
115}
116debuggerWorkerURL = `http://${this.packagerAddress}:${this.packagerPort}/${newPackager}${ScriptImporter.DEBUGGER_WORKER_FILENAME}`;
117}
118return debuggerWorkerURL;
119}
120
e00f7325unknown10 years ago121/**
122* Writes the script file to the project temporary location.
123*/
ce5e88eeYuri Skorokhodov5 years ago124private writeAppScript(scriptBody: string, scriptUrl: IStrictUrl): Promise<string> {
bb77358cMark Oswald10 years ago125let scriptFilePath = path.join(this.sourcesStoragePath, path.basename(scriptUrl.pathname)); // scriptFilePath = "$TMPDIR/index.ios.bundle"
f218397cdlebu10 years ago126return new FileSystem().writeFile(scriptFilePath, scriptBody)
127.then(() => scriptFilePath);
3fb37ad5unknown10 years ago128}
129
e00f7325unknown10 years ago130/**
131* Writes the source map file to the project temporary location.
132*/
ce5e88eeYuri Skorokhodov5 years ago133private writeAppSourceMap(sourceMapUrl: IStrictUrl, scriptUrl: IStrictUrl): Promise<void> {
833e37c7Vladimir Kotikov8 years ago134return Request.request(sourceMapUrl.href, true)
e00f7325unknown10 years ago135.then((sourceMapBody: string) => {
bb77358cMark Oswald10 years ago136let sourceMappingLocalPath = path.join(this.sourcesStoragePath, path.basename(sourceMapUrl.pathname)); // sourceMappingLocalPath = "$TMPDIR/index.ios.map"
137let scriptFileRelativePath = path.basename(scriptUrl.pathname); // scriptFileRelativePath = "index.ios.bundle"
6eeec3c0Serge Svekolnikov8 years ago138let updatedContent = this.sourceMapUtil.updateSourceMapFile(sourceMapBody, scriptFileRelativePath, this.sourcesStoragePath, this.packagerRemoteRoot, this.packagerLocalRoot);
f218397cdlebu10 years ago139return new FileSystem().writeFile(sourceMappingLocalPath, updatedContent);
e00f7325unknown10 years ago140});
3fb37ad5unknown10 years ago141}
5e651f3edigeff10 years ago142
143/**
144* Changes the port of the url to be the one configured as this.packagerPort
145*/
146private overridePackagerPort(urlToOverride: string): string {
147let components = url.parse(urlToOverride);
148components.port = this.packagerPort.toString();
149delete components.host; // We delete the host, if not the port change will be ignored
150return url.format(components);
151}
3fb37ad5unknown10 years ago152}