microsoft/vscode-react-native

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
0.17.0

Branches

Tags

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

Clone

HTTPS

Download ZIP

src/debugger/scriptImporter.ts

153lines · 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";
e3706a1cRedMickey6 years ago13import {ProjectVersionHelper, RNPackageVersions} from "../common/projectVersionHelper";
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 => {
e3706a1cRedMickey6 years ago51return ProjectVersionHelper.getReactNativeVersions(projectRootPath).then(rnVersions => {
979d7bfemax-mironov8 years ago52// 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
f6fb2d2aFrieder Bluemle5 years ago54// https://github.com/microsoft/vscode-react-native/issues/660
e3706a1cRedMickey6 years ago55if (ProjectVersionHelper.getRNVersionsWithBrokenMetroBundler().indexOf(rnVersions.reactNativeVersion) >= 0) {
979d7bfemax-mironov8 years ago56let 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);
7fa90b3bRedMickey6 years ago73if (semver.gte(rnVersions.reactNativeVersion, "0.61.0")) {
2f5c780bYuri Skorokhodov6 years ago74scriptBody = this.sourceMapUtil.removeSourceURL(scriptBody);
75}
979d7bfemax-mironov8 years ago76});
77}
78
79return waitForSourceMapping
2743f19cdlebu10 years ago80.then(() => this.writeAppScript(scriptBody, scriptUrl))
4677921cdigeff10 years ago81.then((scriptFilePath: string) => {
0a68f8dbArtem Egorov8 years ago82logger.verbose(`Script ${overriddenScriptUrlString} downloaded to ${scriptFilePath}`);
4677921cdigeff10 years ago83return { contents: scriptBody, filepath: scriptFilePath };
876df2a0dlebu10 years ago84});
979d7bfemax-mironov8 years ago85});
e00f7325unknown10 years ago86});
87}
88
cf911877Yuri Skorokhodov7 years ago89public downloadDebuggerWorker(sourcesStoragePath: string, projectRootPath: string, debuggerWorkerUrlPath?: string): Q.Promise<void> {
d124bf0eYuri Skorokhodov7 years ago90const errPackagerNotRunning = ErrorHelper.getInternalError(InternalErrorCode.CannotAttachToPackagerCheckPackagerRunningOnPort, this.packagerPort);
6eeec3c0Serge Svekolnikov8 years ago91return ensurePackagerRunning(this.packagerAddress, this.packagerPort, errPackagerNotRunning)
0a68f8dbArtem Egorov8 years ago92.then(() => {
e3706a1cRedMickey6 years ago93return ProjectVersionHelper.getReactNativeVersions(projectRootPath);
a1324704Artem Egorov8 years ago94})
7fa90b3bRedMickey6 years ago95.then((rnVersions: RNPackageVersions) => {
96let debuggerWorkerURL = this.prepareDebuggerWorkerURL(rnVersions.reactNativeVersion, debuggerWorkerUrlPath);
0a68f8dbArtem Egorov8 years ago97let debuggerWorkerLocalPath = path.join(sourcesStoragePath, ScriptImporter.DEBUGGER_WORKER_FILENAME);
98logger.verbose("About to download: " + debuggerWorkerURL + " to: " + debuggerWorkerLocalPath);
99
100return Request.request(debuggerWorkerURL, true)
101.then((body: string) => {
299b0557Patricio Beltran10 years ago102return new FileSystem().writeFile(debuggerWorkerLocalPath, body);
103});
104});
2743f19cdlebu10 years ago105}
106
cf911877Yuri Skorokhodov7 years ago107public prepareDebuggerWorkerURL(rnVersion: string, debuggerWorkerUrlPath?: string): string {
108let debuggerWorkerURL: string;
109// It can be empty string
110if (debuggerWorkerUrlPath !== undefined) {
111debuggerWorkerURL = `http://${this.packagerAddress}:${this.packagerPort}/${debuggerWorkerUrlPath}${ScriptImporter.DEBUGGER_WORKER_FILENAME}`;
112} else {
113let newPackager = "";
114if (!semver.valid(rnVersion) /*Custom RN implementations should support new packager*/ || (semver.gte(rnVersion, "0.50.0"))) {
115newPackager = "debugger-ui/";
116}
117debuggerWorkerURL = `http://${this.packagerAddress}:${this.packagerPort}/${newPackager}${ScriptImporter.DEBUGGER_WORKER_FILENAME}`;
118}
119return debuggerWorkerURL;
120}
121
e00f7325unknown10 years ago122/**
123* Writes the script file to the project temporary location.
124*/
90d15117JiglioNero6 years ago125private writeAppScript(scriptBody: string, scriptUrl: IStrictUrl): Q.Promise<string> {
bb77358cMark Oswald10 years ago126let scriptFilePath = path.join(this.sourcesStoragePath, path.basename(scriptUrl.pathname)); // scriptFilePath = "$TMPDIR/index.ios.bundle"
f218397cdlebu10 years ago127return new FileSystem().writeFile(scriptFilePath, scriptBody)
128.then(() => scriptFilePath);
3fb37ad5unknown10 years ago129}
130
e00f7325unknown10 years ago131/**
132* Writes the source map file to the project temporary location.
133*/
5c8365a6Artem Egorov8 years ago134private writeAppSourceMap(sourceMapUrl: IStrictUrl, scriptUrl: IStrictUrl): Q.Promise<void> {
833e37c7Vladimir Kotikov8 years ago135return Request.request(sourceMapUrl.href, true)
e00f7325unknown10 years ago136.then((sourceMapBody: string) => {
bb77358cMark Oswald10 years ago137let sourceMappingLocalPath = path.join(this.sourcesStoragePath, path.basename(sourceMapUrl.pathname)); // sourceMappingLocalPath = "$TMPDIR/index.ios.map"
138let scriptFileRelativePath = path.basename(scriptUrl.pathname); // scriptFileRelativePath = "index.ios.bundle"
6eeec3c0Serge Svekolnikov8 years ago139let updatedContent = this.sourceMapUtil.updateSourceMapFile(sourceMapBody, scriptFileRelativePath, this.sourcesStoragePath, this.packagerRemoteRoot, this.packagerLocalRoot);
f218397cdlebu10 years ago140return new FileSystem().writeFile(sourceMappingLocalPath, updatedContent);
e00f7325unknown10 years ago141});
3fb37ad5unknown10 years ago142}
5e651f3edigeff10 years ago143
144/**
145* Changes the port of the url to be the one configured as this.packagerPort
146*/
147private overridePackagerPort(urlToOverride: string): string {
148let components = url.parse(urlToOverride);
149components.port = this.packagerPort.toString();
150delete components.host; // We delete the host, if not the port change will be ignored
151return url.format(components);
152}
3fb37ad5unknown10 years ago153}