3

Closed

Compiler freezes visual studio during single file compilation

description

I'm compiling about 20-30 class-per-files into a single application.js using --out application.js flag in compiler.

When I build the application I get:

MyWebProject.csproj error MSB3073: The command "tsc --sourcemap --target ES5 --module AMD --out application.js "...filepaths" exited with code 1

To make things worse, after getting this error VS 2012 hangs for so long I've resorted to immediately closing it as soon as I see the error show up. I'm scared to build my solution...

If I monitor my project root folder I can see my application.js file compiles when I build despite TSC throwing an error and visual studio hanging.

Since that's the case I commented out my BeforeBuild tsc command and ran the application without re-compiling the file. I made major changes since I last ran the application so I expected some run time errors.

And indeed there were some run time dependency problems that I traced down in the compiled application.js related to improper compilation order of the classes

Errors like:

App.Core.Models is undefined

and

TypeError: b is undefined function __() { this.constructor = d; }


I know the TypeError: b is undefined error precisely as I commonly encounter it. It happens when a child class is defined before it's base class. And indeed I can track one of my classes "TableCoordinator" being defined somewhere in the middle of the file and its base class "BaseTableCoordinator" somehow ends up as the last class defined all the way at the bottom of the file. This is very weird because I reference them one after the other!:

__/// <reference path="../../App/Coordinators/BaseTableCoordinator.ts" />
/// <reference path="../../App/Coordinators/TableCoordinator.ts" />__


Anyways, I'll have to work these out manually and see if that solves my problem but this will be very time consuming because in order to test a change I have to:
  1. Build solution with change
  2. As soon as TSC compile error shows up close and re-open to avoid hang
  3. Comment out BeforeBuild in project file
  4. Build/Run solution without re-compiling the ts file
  5. Test change
Obviously very time consuming...

Two Questions:
  1. Is there any way to ensure the classes/files compile in the correct order without having to micro manage this? I'm currently using this approach: (http://stackoverflow.com/a/13850286/1267778) but seems like it's not enough
  2. How to fix TSC from hanging visual studio in this case.
Closed Mar 25, 2013 at 6:00 PM by RyanCavanaugh
Glad you got it working. Please open a separate issue with repro steps if you're still having problems with VS freezing. Thanks!

comments

parliament718 wrote Mar 21, 2013 at 9:01 PM

Here's something interesting to add.

When I build the solution, my typescript files actually still get compiled to my single application.js file (I can watch it appear in my project root when I compile) despite the compiler error and visual studio freezing...

danquirk wrote Mar 23, 2013 at 2:35 AM

The order things are emitted depends on your build step, not your reference path ordering. Consider this setup:
a.ts:
/// <reference path='refs.ts'/>
class Base {}
b.ts:
/// <reference path='refs.ts'/>
class Derived extends Base {}
refs.ts:
/// <reference path='a.ts'/>
/// <reference path='b.ts'/>

Now if I compile tsc.exe a.ts b.ts --out o.js then in o.js I have Derived emitted before Base. If I compile tsc.exe b.ts a.ts --out o.js then I have Base emitted before Derived. Reversing the order of the reference paths in refs.ts has no effect.

It is hard to tell from your description what might be causing Visual Studio to hang. Note that you could always build from the command line when trying to solve an issue like this. Please re-open this if your issues persist and are you're able to nail down a specific repro we can try.

Also, Typescript will still produce JavaScript output even in the presence of errors. In particular, type errors (as opposed to parse errors) like the ones you're seeing will generally still allow the compiler to generate JavaScript (which may or may not work at runtime). That explains the behavior you noted in your comment.

danquirk wrote Mar 23, 2013 at 2:35 AM

** Closed by danquirk 03/22/2013 6:35PM

parliament718 wrote Mar 23, 2013 at 4:52 AM

Danquirk, can you please say more about the "build step" you speak off?

You say reversing the order of the reference paths has no effect, but then what determines the default order if I do not specify the order? How do I get the order right because it does manifest in a runtime error that my BaseTableCoordinator is defined last in the file while DerivedTableCoordinator is somewhere in the middle.

If I look at the order of the files from the error emitted BaseTableCoordinator.ts is actually first in line then DerivedTableCoordinator.ts.... So why does it throw the base to the end of the file and the derived to the middle.

How was this order even determined to begin with if I did not specify one and my references have no effect?

parliament718 wrote Mar 23, 2013 at 7:43 AM

"The order things are emitted depends on your build step, not your reference path ordering."

Trying to verify this and it's simply wrong in my case. The order I place the references actually changes the order of the classes defined in my output file.

I have _references.ts:
/// <reference path="Typings/Internal/_coordinators.dependencies.ts" />
/// <reference path="Typings/Internal/_charting.dependencies.ts" />

/// <reference path="AppMain.ts" />
Then in _coordinators.dependencies.ts :

/// <reference path="../../App/Coordinators/BaseTableCoordinator.ts" />
/// <reference path="../../App/Coordinators/DerivedTableCoordinator.ts" />
/// <reference path="../../App/Coordinators/UnrelatedCoordinator.ts" />
This compiles in this order:
(function (Coordinators) {  var DerivedTableCoordinator = (function (_super) { ... } .....
(function (Coordinators) {  var UnrelatedCoordinator= (function () { ... } ....
_....all the way at the bottom..._
(function (Coordinators) { var BaseTableCoordinator= (function () { ... } ....
If I push the UnrelatedCoordinator reference to the top:
/// <reference path="../../App/Coordinators/UnrelatedCoordinator.ts" />
/// <reference path="../../App/Coordinators/BaseTableCoordinator.ts" />
/// <reference path="../../App/Coordinators/DerivedTableCoordinator.ts" />
I get the corresponding order change in the compiled single file:
(function (Coordinators) {  var UnrelatedCoordinator= (function () { ... } ....
(function (Coordinators) {  var DerivedTableCoordinator= (function (_super) { ... } .....
_....all the way at the bottom..._
(function (Coordinators) { var BaseTableCoordinator= (function () { ... } ....
As you can see the order is determined by the reference paths when using the --out flag. What baffled me at that point was that no matter where I put the BaseTableCoordinator reference it always ended up as the last defined class in the file.

Going down that path made me wonder what is it actually compiling when my BeforeBuild would execute:
    <Exec Command="tsc$(TypeScriptSourceMap) --target ES5 --module AMD --out application.js @(TypeScriptCompile ->'&quot;%(fullpath)&quot;', ' ')" />
Since I'm specifying my desired build order in my _references.ts file (that references other files that in turn reference my class files) I decided to try to set the _references.ts file as my compilation target:
    <Exec Command="tsc$(TypeScriptSourceMap) --target ES5 --module AMD --out application.js &quot;C:\MyProject\Scripts\_references.ts&quot; @(TypeScriptCompile ->'&quot;%(fullpath)&quot;', ' ')" />
Finally I got the correct compilation order:
(function (Coordinators) {  var UnrelatedCoordinator= (function () { ... } ....
(function (Coordinators) { var BaseTableCoordinator= (function () { ... } ....
(function (Coordinators) {  var DerivedTableCoordinator= (function (_super) { ... } .....
With my BeforeBuild command commented out I can run the app and it works! This is great!

Um, not really.... if I bring back my BeforeBuild command the compiler still throws the error that hangs VS despite everything being perfectly fine now with the output file.

I still don't know what's causing this but I did figure out a workaround and also have a clue to a potential lead...

Workaround: Instead of closing VS immediately upon getting the error to prevent hang, it's sufficient to immediately switch away from the Error List pane the second the error comes up (I switched to the Output pane). This seems to prevent some kind of post error processing that causes VS to hang.

As a by product of having the Output view in my face I noticed right before the compiler chokes I get something like this:

Error reading file "C:\MyProject\Scripts\Typings\Internal_models.deendencies.ts": File not found
THEN COMPILER CHOKES: error MSB3073: The command "tsc --sourcemap --target ES5 --module AMD --out application.js "...file paths" exited with code 1

NOTICE how _models.dependencies is missing that "p" ... I checked, double checked, and triple checked, that I did not misspell this anywhere in my solution.

Funny part is it's not even consistent. I cannot replicate but when I built a few times before it was the same error with a different file path with a randomly stripped letter. From memory it was this path:

Error reading file "C:\MyProject\Scripts\ypings\Internal\keymaster.d.ts": File not found

It jacked the "T" in Typings folder! Quadruple checked and this is not my error either.

Apparently the compiler chokes immediately following this error so hoping to get this resolved...

parliament718 wrote Mar 23, 2013 at 11:05 AM

Major Update:

The following build process allows me to compile without errors:
<Target Name="BeforeBuild">
    <WriteLinesToFile
      File="typescriptcompiler.input"
      Lines="@(TypeScriptCompile ->'&quot;%(fullpath)&quot;', ' ')"
      Overwrite="true"
      Encoding="Unicode"/>
    
    <Exec Command="tsc$(TypeScriptSourceMap) --target ES5 --module AMD --out application.js @typescriptcompiler.input" />
  </Target>
It dumps the code to a file to bypass the buffer bug in the WScript library. The fix attached by Ryan did not work for me and restoring the original (removing the fix) did not break it and I was still able to compile successfully.

BUT the problem is then back to the compilation order I described in my previous comment. As the solution above dumps TypeScriptCompile to the file the order depends on the "build-steps" danquirk was talking about. However, I do not want to manage dependencies here because it forced me to unload the project each time and then on top of that I have to manage the references anyways to get type checking. It is much preferably to compile the root _references.ts like I described in the previous comment and have it traverse the dependency chain.

So basically there's no way to get the benefit of the compiler traversing my reference paths from a root AND being able to use a file as the input. To do that the compiler would have to return a string that is the dependency chain after it traverses the file starting from the root given, then than string could be dumped to a file, then finally fed back into the compiler.

This is a compiler bug.
This current fix by Ryan does not work.
The fix proposed above is also not ideal.

As for VS hanging... that's an issue in itself.

parliament718 wrote Mar 23, 2013 at 8:52 PM

Ok, finally solved this. This following build process compiles without error AND gets the compilation order right from traversing your reference paths starting for the root:
<Target Name="BeforeBuild">
<WriteLinesToFile
  File="typescriptcompiler.input"
  Lines="&quot;C:\MyProject\Scripts\_references.ts&quot;"
  Overwrite="true"
  Encoding="Unicode"/>

<Exec Command="tsc$(TypeScriptSourceMap) --target ES5 --module AMD --out application.js @typescriptcompiler.input" />
</Target>
Note: previous comment I accidentally posted incomplete answer. Mod can delete previous comment.