angular / angular-cli

CLI tool for Angular
https://cli.angular.io
MIT License
26.73k stars 11.98k forks source link

TypeError: Cannot read property 'length' of undefined, when karma tests re-load #9588

Closed jschank closed 4 years ago

jschank commented 6 years ago

This bug report is from using Angular2 and Karma/Jasmine But the error is emitted from Typescript. I am hoping that is the relevant part.

Versions

    _                      _                 ____ _     ___
   / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
  / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
 / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
/_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
               |___/

Angular CLI: 1.6.5
Node: 8.7.0
OS: darwin x64
Angular: 4.3.6
... animations, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, router, tsc-wrapped

@angular/.DS_Store: error
@angular/cli: 1.6.5
@angular-devkit/build-optimizer: 0.0.41
@angular-devkit/core: 0.0.28
@angular-devkit/schematics: 0.0.51
@ngtools/json-schema: 1.1.0
@ngtools/webpack: 1.9.5
@schematics/angular: 0.1.16
typescript: 2.3.4
webpack-bundle-analyzer: 2.9.2
webpack: 3.10.0

----
Some more versions that might be helpful

        "jasmine-core": "^2.99.1",
        "jasmine-expect": "^3.8.3",
        "jasmine-matchers": "^0.2.3",
        "jasmine-spec-reporter": "~4.1.0",
        "karma": "~1.7.0",
        "karma-chrome-launcher": "^2.2.0",
        "karma-cli": "~1.0.1",
        "karma-coverage-istanbul-reporter": "^1.2.1",
        "karma-jasmine": "^1.1.1",
        "karma-jasmine-html-reporter": "^0.2.2",
        "karma-jasmine-matchers": "^3.7.0",

I am using macOS Sierra, 10.12.6

Repro steps

When I run $ npm run test, my tests pass fine.
But if I then save one of my spec files (even if I don't change it) Then a new run is kicked off, but always produces this error:

Observed behavior

ERROR in TypeError: Cannot read property 'length' of undefined
    at createSourceFile (/Users/jschank/ddc-advocacy/projects/ddca-iceland/node_modules/typescript/lib/typescript.js:15464:110)
    at parseSourceFileWorker (/Users/jschank/ddc-advocacy/projects/ddca-iceland/node_modules/typescript/lib/typescript.js:15389:26)
    at Object.parseSourceFile (/Users/jschank/ddc-advocacy/projects/ddca-iceland/node_modules/typescript/lib/typescript.js:15338:26)
    at Object.createSourceFile (/Users/jschank/ddc-advocacy/projects/ddca-iceland/node_modules/typescript/lib/typescript.js:15192:29)
    at new TypeScriptFileRefactor (/Users/jschank/ddc-advocacy/projects/ddca-iceland/node_modules/@ngtools/webpack/src/refactor.js:79:35)
    at Object.findLazyRoutes (/Users/jschank/ddc-advocacy/projects/ddca-iceland/node_modules/@ngtools/webpack/src/lazy_routes.js:18:22)
    at AotPlugin._findLazyRoutesInAst (/Users/jschank/ddc-advocacy/projects/ddca-iceland/node_modules/@ngtools/webpack/src/plugin.js:217:50)
    at _donePromise.Promise.resolve.then.then.then.then.then (/Users/jschank/ddc-advocacy/projects/ddca-iceland/node_modules/@ngtools/webpack/src/plugin.js:496:24)
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:188:7)

Desired behavior

Saving my spec files should result in karma tests being run again. (I know that isn't the responsibility of this repo. But the error Appears to me to be in Typescript)

Mention any other details that might be useful (optional)

Most of the googling about this error, leads to the advice of putting a console.log(fileName); statement. To dump the offending file to the console. When I look at that location, I see this

function createSourceFile(fileName, languageVersion, scriptKind) {
    // code from createNode is inlined here so createNode won't have to deal with special case of creating source files
    // this is quite rare comparing to other nodes and createNode should be as fast as possible
    var sourceFile = new SourceFileConstructor(265 /* SourceFile */, /*pos*/ 0, /* end */ sourceText.length);
    nodeCount++;
    sourceFile.text = sourceText;
    sourceFile.bindDiagnostics = [];
    sourceFile.languageVersion = languageVersion;
    sourceFile.fileName = ts.normalizePath(fileName);
    sourceFile.languageVariant = getLanguageVariant(scriptKind);
    sourceFile.isDeclarationFile = ts.fileExtensionIs(sourceFile.fileName, ".d.ts");
    sourceFile.scriptKind = scriptKind;
    return sourceFile;
}

It looks to me, like the problem is that sourceText, is undefined. And we're calling length on it here.
If I reset the sourceText to an empty string, when it is undefined or null. My tests re-run on changes, with no errors. Unfortunately, I have no idea if that is a reasonable solution to the problem.

function createSourceFile(fileName, languageVersion, scriptKind) {
    if (!sourceText) {
        // console.log("*** Filename: ", fileName);
        // console.log("*** languageVersion: ", languageVersion);
        // console.log("*** scriptKind: ", scriptKind);
        // Note: this seems to allow the typescript parser to continue when a file is updated
        sourceText = "";
    }
    // code from createNode is inlined here so createNode won't have to deal with special case of creating source files
    // this is quite rare comparing to other nodes and createNode should be as fast as possible
    var sourceFile = new SourceFileConstructor(265 /* SourceFile */, /*pos*/ 0, /* end */ sourceText.length);
    nodeCount++;
    sourceFile.text = sourceText;
    sourceFile.bindDiagnostics = [];
    sourceFile.languageVersion = languageVersion;
    sourceFile.fileName = ts.normalizePath(fileName);
    sourceFile.languageVariant = getLanguageVariant(scriptKind);
    sourceFile.isDeclarationFile = ts.fileExtensionIs(sourceFile.fileName, ".d.ts");
    sourceFile.scriptKind = scriptKind;
    return sourceFile;
}
mhamel06 commented 6 years ago

Been trying to track down the exact cause of this error as well. In the meantime, it appears that 1.6.1 does not have this bug.

Duplicate issues: https://github.com/angular/angular-cli/issues/9331 https://github.com/angular/angular-cli/issues/5053

mexican-plumber commented 6 years ago

Been fighting with the same problem for a few weeks and finally got the chance to do something about it - finally got it sorted. I believe that part of the problem was because the 'app' folder had been moved to the same level as the 'src' (which was deleted) and also because the 'app' folder was also renamed 'App'. So anyway I created a brand new angular app and reproduced the folder related steps, which broke the app to a degree, but managed to get it all working again. From that point i started comparing the files on my real app with the dummy app and after some effort i have it working perfectly. One thing that i realised (note that im working on Windows, which is case insensitive when it comes to paths), was that some of my import statements didnt all have the correct case - apparently 'app/some-component' and 'App/some-component' aren't really the same. This led me normalise my folder names to kebab-case and it solved part of the problem. The only catch in the middle of all of this is that i ended up upgrading from angular 4 to 5.

Hope this helps anyone with the same type of issue (only took me around a day and a half to get it sorted lol)

Current version:

Angular CLI: 1.6.8 Node: 8.9.4 OS: win32 x64 Angular: 5.2.4 ... animations, common, compiler, compiler-cli, core, forms ... http, language-service, platform-browser ... platform-browser-dynamic, router

@angular/cli: 1.6.8 @angular-devkit/build-optimizer: 0.0.42 @angular-devkit/core: 0.0.29 @angular-devkit/schematics: 0.0.52 @ngtools/json-schema: 1.1.0 @ngtools/webpack: 1.9.8 @schematics/angular: 0.1.17 typescript: 2.5.3 webpack: 3.11.0

uweDuesing commented 6 years ago

The same problem occurs with Angular CLI version 1.7.1

davcri commented 6 years ago

Same here on Ubuntu 17.10 (4.13.0-36-generic). I also tried updating node, but it didn't fix the issue.

Angular CLI: 1.7.1
Node: 6.11.4
OS: linux x64
Angular: 4.4.6
... animations, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, router, tsc-wrapped

@angular/cli: 1.7.1
@angular-devkit/build-optimizer: 0.3.2
@angular-devkit/core: 0.3.2
@angular-devkit/schematics: 0.3.2
@ngtools/json-schema: 1.2.0
@ngtools/webpack: 1.10.1
@schematics/angular: 0.3.2
@schematics/package-update: 0.3.2
typescript: 2.7.2
webpack: 3.11.0
Adam-Pond commented 6 years ago

As identified in https://github.com/angular/angular-cli/issues/5053, downgrading Angular CLI to 1.6.0 works. Seems to be a known issue

npm uninstall -g @angular/cli
npm uninstall --save-dev @angular/cli
npm install -g @angular/cli@1.6.0

rmdir /s node_modules
npm install --save-dev @angular/cli@1.6.0
npm install
SergeyShurygin commented 6 years ago

I have the same error with cli 1.6.8

I've done some debugging and figured out that problem is in the next line in \node_modules\@ngtools\webpack\src\plugin.js file:

const changedFilePaths = this._compilerHost.getChangedFilePaths();

in 1.6.0 version getChangedFilePaths returns only several files ( [ '../app/src/polyfills.ts', '../app/node_modules/classlist.js/package.json', '../app/src/app/data-models/store/test.side-effects.spec.ts' ], but in 1.6.8 it returns them all plus '../app/src/' directory, which does not have any sourceText and cause the mentioned error

uchitha commented 6 years ago

I have encountered the same issue with 1.6.5, 1.7.4 (latest) and 1.6.0 (downgraded as per suggested above). It's caused by exactly the same reason as suggested by @SergeyShurygin above. Any update on this would be awesome as I can't afford to patch node modules from public registry.

johngrimsey commented 6 years ago

Same here, downgrade from 1.7.4 to 1.6.0 needed to avoid the issue when watching tests

davcri commented 6 years ago

Update: now it's working fine for me with ng test.

Angular CLI: 1.7.4
Node: 6.11.4
OS: linux x64
Angular: 5.2.9

These days I'm using Angular CLI: 1.7.4 with ng test --watch --poll 256 -sm=false and it's working as expected. I haven't tried ng test in a while.

gangsthub commented 6 years ago

Please. There's no need to delete node_modules. This issue happens for a mismatch between you global @angular/cli, the angular tools (installed locally) and typescrypt (installed locally, also).

I would recommend to run:

npm update # do it at your own risk: it updates everything! If you have versions specified with `^` this may break your code
npm i -g @angular/cli@latest # global
npm i typescript@latest # or the one that `@angular/compiler-cli` says whenever you start the application (`ng serve --aot` or whatever)

And before running the tests, make a compilation to avoid fixing things in the @ngtools/webpack on your own.

Just tested this in production when I switched to my master branch and those errors appeared.

Take into consideration adding npm i -g @angular/cli@latest to the postinstall of your npm scripts.

What @Adam-Pond suggested will only work if you are lucky and the three breaking points I mentioned are in harmony.

Hope it helps! 🐋

rao53 commented 6 years ago

For anyone hitting this issue.

It seems to be down to version conflicts. The only way I have been able to get around it was to generate a new app with 'ng new appname' and copy the component folders (01-fundamentals etc) over from the app you're trying to run your tests on.

This also bypasses the angular cli conflicts others have reported.

wqoq commented 6 years ago

I was having a similar problem on my Windows machine using Angular CLI 1.7.3, Node 6.11.0, and Angular 4.4.6.

It was trying to get the sourceText.length of a file that was actually a directory (the root directory of the project actually... src). WebpackCompilerHost.getChangedFilePaths() had the src directory in it.

I tracked that back to Watchpack's _onChange method. _dirWatcher was detecting a change, and calling _onChange, with the item param being the directory, and the file param being the file.

This is the block of code that adds the directory to the list of changes:

    if(this.aggregatedChanges.indexOf(item) < 0)
        this.aggregatedChanges.push(item);

Once I changed this to:

    if(this.aggregatedChanges.indexOf(file) < 0)
        this.aggregatedChanges.push(file);

The length error went away, and my tests rebuilt flawlessly.

Also, for reference, these are my versions:

Angular CLI: 1.7.3
Node: 6.11.0
OS: win32 x64
Angular: 4.4.6
... common, compiler, compiler-cli, core, forms, http
... platform-browser, platform-browser-dynamic, router
... tsc-wrapped

@angular/cdk: 2.0.0-beta.12
@angular/cli: 1.7.3
@angular-devkit/build-optimizer: 0.3.2
@angular-devkit/core: 0.3.2
@angular-devkit/schematics: 0.3.2
@ngtools/json-schema: 1.2.0
@ngtools/webpack: 1.10.2
@schematics/angular: 0.3.2
@schematics/package-update: 0.3.2
typescript: 2.3.4
webpack: 3.11.0
wqoq commented 6 years ago

Okay, there's more going on here than just that. I think this is an incompatibility (of sorts) between the file watcher in webpack and Visual Studio (the editor I'm using).

I'm getting the same error now after making simple changes to a file (add a new line, then delete it, and save).

And Parser.createSourceFile is now trying to get the source text of filenames like "vv510u0i.lax~" and "xftxzxob.smp~" which look very much like Microsoft's temp file naming convention.

So if I had to guess, I'd say the file watcher is detecting those temp files, then by the time ng-cli tries to parse them, Visual Studio has deleted them.

Edit: In the end, I just hacked the watcher to ignore files that end with "~".

VitalyName commented 6 years ago

I solved this problem (error during refactoring test). All is good for angular v4.3. and v4.4 1) Change @angular/cli" version 1.7.3 to 1.4.10 in package.json (latest for angular4) 2) rm -rf node_modules 3) npm install --no-optional

majdrd commented 6 years ago

Thank you @VitalyName , issue solved after downgrade to cli 1.4.10. I am using Angular -v 4.4.7

Adam-Pond commented 6 years ago

Would be nice to know if there was a fix for this by now. First reported in Feb. Anyone have any ideas?

AndersonBP commented 6 years ago

Verify your environments names.

filipesilva commented 4 years ago

Thanks for reporting this issue. This issue was originally reported a long time ago and since then we've had many releases, one of which might have addressed this problem. Please update to the most recent Angular CLI version.

If the problem persists after upgrading, please open a new issue, provide a simple repository reproducing the problem, and describe the difference between the expected and current behavior.

angular-automatic-lock-bot[bot] commented 4 years ago

This issue has been automatically locked due to inactivity. Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.