New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support (ios)-project-path param #227
Support (ios)-project-path param #227
Conversation
Hi @mroswald, I'm your friendly neighborhood Microsoft Pull Request Bot (You can call me MSBOT). Thanks for your contribution! TTYL, MSBOT; |
d949071
to
fbcf9a0
Compare
Just a short question aside: Which part does control the order in which the launch arguments are coming in? It's just a mess that the (vsc) extension relies on the correct order and count of parameters. Is there no better way to get them? |
Our extension builds on top of the core vscode node debugging extension; you can see their code at https://github.com/Microsoft/vscode-node-debug We primarily try to make sure that the project fits their requirements, and then pass it over. Why are you modifying the path at all? |
Regarding your second question: The current architecture is a little bit of a mess, but we haven't had a chance to clean it up yet. There are 2 parts to the debugger: one is the nodeDebugWrapper which is a proper vscode debug adapter, and in its However we have implemented most of our logic in the second part of the debugger, which is actually in what is normally the app being debugged. This is everything starting from launchReactNative.js. Since this isn't a standard way of doing things, we went with the path of least resistance and pass the few properties we need via the argv of the process. The argv is read in launcher.ts, and constructed in nodeDebugWrapper.ts. Ideally the bulk of our logic should be stripped out of the "app being debugged" process and put into the debug adapter process, but as I said we haven't had time to go back and fix it yet. |
@@ -49,6 +49,7 @@ interface ILaunchArgs { | |||
platform: string; | |||
target?: string; | |||
internalDebuggerPort?: any; | |||
iosProjectPath?: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the react-native help it says that this path is relative the the project root. I think it'd be clearer if we renamed this argument to iosRelativeProjectPath, and then in iOSPlatform.ts we can combine it with projectPath to create the value iosProjectPath.
There were a few tslint errors which caused the automated build to fail, reporting them here for convenience: [gulp-tslint] error (no-trailing-whitespace) src/debugger/nodeDebugWrapper.ts[164, 1]: trailing whitespace |
@@ -20,6 +20,7 @@ export class Xcodeproj { | |||
} | |||
|
|||
public findXcodeprojFile(projectRoot: string): Q.Promise<string> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you should pass the absolute iosProjectPath to this method instead. I think that most ios methods only need to know the location of the ios project, so you'll be able to remove the projectRoot in most of them if you pass the iosProjectPath instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do, this line only checks if there is a trailing "ios/" and removes it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All the places where you are using that regexp are iOS related code, and they are all using projectRoot + "ios" in every case except for calls to new CommandExecutor(this.projectRoot) which I don't think it'll break if you also change it to use projectRoot + "ios" instead.
I think it'd be better to just pass iosProjectRoot to:
PlistBuddy.getBundleId
Xcodeproj.findXcodeprojFile
new Compiler
new DeviceDeployer
new DeviceRunner
And then modify the code where they later add the "ios" to the path, so the code still keeps working (as in this line: https://github.com/mroswald/vscode-react-native/blob/feat/support-iosprojectpath-param/src/common/ios/plistBuddy.ts#L29 )
@guillaumejenkins thanks. I didn't care about linting since the functionality is not complete :-) I'll fix the issues soon |
@MSLaguana thanks for your in-deep explanation. The reason why I want to change this, is that some React Native projects do not have a single "ios" folder, but a subfolder structure where one or more XCode projects live. The React Native cli got this feature with 0.24 (facebook/react-native#6134). |
@mroswald I think that @MSLaguana Was asking why are you replacing the / for _ in the paths in src/debugger/scriptImporter.ts ? Adding support for --project-path completely makes sense! |
@digeff @MSLaguana ah, sry :-) That's the point on which I'm struggling. In .vscode/.react/ there is no directory structure, so I'd have to create it. But then vs code does not map / finds the connection between source code and downloaded source + sourcemap. I'm not sure how this is supposed to work |
In the cases we've seen so far, only the bundle file is downloaded. What's your scenario? Why do you need a directory structure there? Which scripts are being imported in your project? |
Only index.ios.bundle and index.ios.map. I also tried to remove the path and just save them directly into this directory. That works so far, but the breakpoints are moved (when starting the debugging) from line x to something like line 32034 which is near the "breakpointed" module in the bundle (index.ios.js). Not sure what is responsible for matching/moving the breakpoints |
Looks not that like these. What actually works is to set the breakpoint via "debugger;" statement. But then it stops inside the index.ios.bundle. |
You can add the launch option: |
Ok, this is what the trace tells me:
(I had to hide the project names here. /Users/mark/** is my project root, Examples is the directory which hosts the ios Projects) |
That means that the source map it's telling VS Code that the line index.ios.js:20:0 matches to: index.ios.bundle:37025:0 |
Yes, that's the bug with the react-native source maps not mapping to the correct line numbers. We are hoping that react-native will fix this issue soon, |
Ok, I just tested a breakpoint in a file without JSX / without a react component. It's definitely related to transpiled jsx or react classes. Let me just clean my current code, then I'll push an update. |
@digeff Ok, I refactored as you suggested (relative path) |
@@ -15,7 +15,7 @@ interface ISourceMap { | |||
} | |||
|
|||
export class SourceMapUtil { | |||
private static SourceMapURLRegex: RegExp = /\/\/(#|@) sourceMappingURL=(.+?)\s*$/m; | |||
private static SourceMapURLRegex: RegExp = /\/\/(#|@) sourceMappingURL=(.+index\.ios\.map.*?)\s*$/m; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We've seen some example projects where this file is not called index.ios. Also, this won't work for Android. Why is this change necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In my example, there are different SourceMaps provided. But you're right - Shall we change that to index\.(android|ios)\.map
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the advantage of that implementation over the current implementation?
If I remember correctly, in the Movies example app, this file is called Movies.ios.map, so that change will break that example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the script body returns multiple sourceMappingUrl=
then this error happens:
[6:39:12 PM] <END> request:/**/index.ios.bundle?platform=ios (67ms)
[6:39:12 PM] <START> request:/exp.js.map
Error: Error validating module options: child "platform" fails because ["platform" must be a string]
at declareOpts.js:60:13
at index.js:222:20
at tryCallOne (/Users/mark/**/node_modules/promise/lib/core.js:37:12)
at /Users/mark/**/node_modules/promise/lib/core.js:123:15
at flush (/Users/mark/**/node_modules/asap/raw.js:50:29)
at _combinedTickCallback (node.js:370:9)
at process._tickCallback (node.js:401:11)
$ grep "sourceMappingURL=" index.ios.bundle
//# sourceMappingURL=exp.js.map
//# sourceMappingURL=cldr.js.map
//# sourceMappingURL=core.js.map
//# sourceMappingURL=en.js.map
//# sourceMappingURL=main.js.map
//# sourceMappingURL=utils.js.map
//# sourceMappingURL=es5.js.map
//# sourceMappingURL=compiler.js.map
//# sourceMappingURL=en.js.map
//# sourceMappingURL=main.js.map
//# sourceMappingURL=diff.js.map
//# sourceMappingURL=es5.js.map
//# sourceMappingURL=core.js.map
//# sourceMappingURL=es5.js.map
//# sourceMappingURL=memoizer.js.map
//# sourceMappingURL=core.js.map
//# sourceMappingURL=parser.js.map
//# sourceMappingURL=index.ios.map
The only source map of interest is the index.ios/android.map, right? Or should we trust that the correct one is the last match?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the source has multiple sourceMappingURL entries, that is a violation of the spec and the source must be cleaned up (There is a babel loader called something like strip-sourcemap which does this I believe). If we want to try and support non-compliant pages, then my suggestion would be picking the last sourceMappingURL, not fuzzy matching on the assumed name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, you're right. I'll investigate why we have multiple source maps in one body (maybe it's related to babel telling me [BABEL] Note: The code generator has deoptimised the styling of "/Users/mark/**/node_modules/immutable/dist/immutable.js" as it exceeds the max of "100KB".
and remove this change from the PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, found it. This is an issues related to react-intl
@mroswald, Thanks for signing the contribution license agreement so quickly! Actual humans will now validate the agreement and then evaluate the PR. |
@digeff anything left? |
"iosRelativeProjectPath": { | ||
"type": "string", | ||
"description": "Relative path to the ios/ folder, if it is not located on the project root.", | ||
"default": null |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The default in this case would be "ios" (That what we'll use if they don't provide this property).
- always send --project-path param to react-packager - removed change to sourceMap pattern - allow empty string for iosRelativeProjectPath
32432d6
to
eef7ed0
Compare
@digeff I rebased to current master, tests should pass now (fingerscrossed) |
@mroswald Have you tested this both on iOS simulators and a real iOS device? |
@digeff sorry, forgot one. Tested on simulator and iPhone with one project having ios in root folder and one having xcode project in subfolder |
@@ -21,7 +21,7 @@ export class Xcodeproj { | |||
|
|||
public findXcodeprojFile(projectRoot: string): Q.Promise<string> { | |||
return this.nodeFileSystem | |||
.findFilesByExtension(path.join(projectRoot, "ios"), "xcodeproj") | |||
.findFilesByExtension(path.join(projectRoot), "xcodeproj") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can remove the call to path.join
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
right, that can be removed
👍 |
@@ -71,7 +71,7 @@ export class ScriptImporter { | |||
* Writes the script file to the project temporary location. | |||
*/ | |||
private writeAppScript(scriptBody: string, scriptUrl: url.Url): Q.Promise<String> { | |||
let scriptFilePath = path.join(this.sourcesStoragePath, scriptUrl.pathname); // scriptFilePath = "$TMPDIR/index.ios.bundle" | |||
let scriptFilePath = path.join(this.sourcesStoragePath, path.basename(scriptUrl.pathname)); // scriptFilePath = "$TMPDIR/index.ios.bundle" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to make sure I understand correctly, these two path.basename
changes are so if the packager gets a request for http://localhost/foo/index.bundle.ios
it will search in .vscode/.react/index.bundle.ios
and not .vscode/.react/foo/index.bundle.ios
, is that right?
If that is correct, then while this wouldn't work for multiple apps running concurrently, it should work for running one app at a time I think, so it looks ok to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@MSLaguana I hate this timezone difference :-) The React Native packager can serve multiple apps at a time, but vscode won't hande multiple apps concurrently (as all index.ios* maps will be stored at .vscode/.react/index.bundle.ios
. I experimented with replacing the path separator /
with _
but then the IDE didn't match anything. That's the part where I don't have a clue how that works. How does vscode map the source code to anything stored under .vscode/.react
?
But - anyway. Just for the moment this will be an improvement (@digeff merge pls :-) ). I'm willing to drive this to the next level - in another PR, hopefully with your assistance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The source files refer to a sourcemap at the end of the file, and we do some tweaks to that (see https://github.com/Microsoft/vscode-react-native/blob/master/src/debugger/sourceMap.ts#L70 ) to make sure that it refers to the correct file. As long as the foo.js
file refers to a bar.js.map
file in a sourcemap comment, I believe that the debugger should correctly pick up the source map.
@mroswald Thank you very much for your contribution! The code that we download to .vscode/.react/ gets executed in the appWorker.ts file on line 116: The issues you may run into source mapping if you modify the file path, is that the bundle file has a reference to the .map.js file, and the .map.js file has references to the bundle and to the source files themselves. You need to make sure that all the paths are valid if you change anything. Maybe it'd be easier to just download foo/index.ios.bundle to .vscode/.react/foo/index.ios.bundle Does the packager support debugging multiple apps at the same time? Does this work in Chrome? |
@digeff Is it possible to release a new version? There are bugs left on the milestone, but indeed the features are not usable until this bugs are fixed. |
@mroswald We are looking into creating a new release in a week or so |
@digeff @MSLaguana
I need your help please :-) I wanted to support the new --project-path param for "react-native run-ios" which allows you to have your iOS project in a subfolder (like Examples/MyExampleApp/ios/).
Currently I'm struggling with the VSC not matching the source code files to the source maps. In the ScriptImporter I change the "/", which represent the paths, to "_". But the IDE itself does not recognize / map it to the source files. I can't find where this happens - can you enlighten me? :-)
This PR is related to facebook/react-native#6134