Yes, the previous version in which this bug was not present was: 8.3.25
When running ng build --prod with "target": "es2015", not using Ivy, compilation fails when generating es5 bundles, with a Babel error.
Edit: the error does not occur when building without --prod.
This error had never happened before, and appeared just after v9 update. Seems to be related to a heterodox for-of syntax, maybe in a dependency but which one ?
No idea, the app is quite complex…
Generating ES5 bundles for differential loading...
An unhandled exception occurred: /home/mathias/src/nghyd/main-es2015.037c4c9354d91b8c3932.js: Property body expected type of array but got null
See "/tmp/ng-bRVUux/angular-errors.log" for further details.
The /tmp/ng-bRVUux/angular-errors.log log file contains:
[error] TypeError: /home/mathias/src/nghyd/main-es2015.037c4c9354d91b8c3932.js: Property body expected type of array but got null
at validate (/home/mathias/src/nghyd/node_modules/@angular-devkit/build-angular/node_modules/@babel/types/lib/definitions/utils.js:159:13)
at Object.validate (/home/mathias/src/nghyd/node_modules/@angular-devkit/build-angular/node_modules/@babel/types/lib/definitions/utils.js:196:7)
at validateField (/home/mathias/src/nghyd/node_modules/@angular-devkit/build-angular/node_modules/@babel/types/lib/validators/validate.js:24:9)
at Object.validate (/home/mathias/src/nghyd/node_modules/@angular-devkit/build-angular/node_modules/@babel/types/lib/validators/validate.js:17:3)
at NodePath._replaceWith (/home/mathias/src/nghyd/node_modules/@angular-devkit/build-angular/node_modules/@babel/traverse/lib/path/replacement.js:172:7)
at NodePath._remove (/home/mathias/src/nghyd/node_modules/@angular-devkit/build-angular/node_modules/@babel/traverse/lib/path/removal.js:53:10)
at NodePath.remove (/home/mathias/src/nghyd/node_modules/@angular-devkit/build-angular/node_modules/@babel/traverse/lib/path/removal.js:32:8)
at PluginPass.ForOfStatement (/home/mathias/src/nghyd/node_modules/@angular-devkit/build-angular/node_modules/@babel/plugin-transform-for-of/lib/index.js:195:16)
at newFn (/home/mathias/src/nghyd/node_modules/@angular-devkit/build-angular/node_modules/@babel/traverse/lib/visitors.js:179:21)
at NodePath._call (/home/mathias/src/nghyd/node_modules/@angular-devkit/build-angular/node_modules/@babel/traverse/lib/path/context.js:55:20)
at NodePath.call (/home/mathias/src/nghyd/node_modules/@angular-devkit/build-angular/node_modules/@babel/traverse/lib/path/context.js:42:17)
at NodePath.visit (/home/mathias/src/nghyd/node_modules/@angular-devkit/build-angular/node_modules/@babel/traverse/lib/path/context.js:90:31)
at TraversalContext.visitQueue (/home/mathias/src/nghyd/node_modules/@angular-devkit/build-angular/node_modules/@babel/traverse/lib/context.js:112:16)
at TraversalContext.visitSingle (/home/mathias/src/nghyd/node_modules/@angular-devkit/build-angular/node_modules/@babel/traverse/lib/context.js:84:19)
at TraversalContext.visit (/home/mathias/src/nghyd/node_modules/@angular-devkit/build-angular/node_modules/@babel/traverse/lib/context.js:140:19)
at Function.traverse.node (/home/mathias/src/nghyd/node_modules/@angular-devkit/build-angular/node_modules/@babel/traverse/lib/index.js:84:17)
The incriminated main-es2015.037c4c9354d91b8c3932.js temp file, even unminified, shows more than 400 for-of statements, hard to tell which one is responsible (but I'll review them anyway).
Angular CLI: 9.0.2
Node: 13.6.0
OS: linux x64
Angular: 9.0.1
... animations, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router
Ivy Workspace: Yes
Package Version
-----------------------------------------------------------
@angular-devkit/architect 0.900.2
@angular-devkit/build-angular 0.900.2
@angular-devkit/build-optimizer 0.900.2
@angular-devkit/build-webpack 0.900.2
@angular-devkit/core 9.0.2
@angular-devkit/schematics 9.0.2
@angular/cdk 9.0.0
@angular/cli 9.0.2
@angular/flex-layout 9.0.0-beta.29
@angular/material 9.0.0
@ngtools/webpack 9.0.2
@schematics/angular 9.0.2
@schematics/update 0.900.2
rxjs 6.5.4
typescript 3.7.5
webpack 4.41.2
Anything else relevant?
tsconfig.app.json:
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/app",
"baseUrl": "./",
"types": [ "node" ],
"typeRoots": [ "../node_modules/@types" ]
},
"angularCompilerOptions": {
"enableIvy": false
},
"files": [
"main.ts",
"polyfills.ts"
]
}
tsconfig.json:
{
"compileOnSave": false,
"compilerOptions": {
"downlevelIteration": true,
"importHelpers": true,
"outDir": "./dist/out-tsc",
"sourceMap": true,
"declaration": false,
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es2015",
"typeRoots": [
"node_modules/@types"
],
"lib": [
"es2017",
"dom"
],
"module": "esnext",
"baseUrl": "./"
},
"include": [
"src/**/*.ts"
]
}
Thanks
This appears to be a bug but we will need to look at a reproduction to find and fix the problem. Can you setup a minimal reproduction please?
You can read here why this is needed. A good way to make a minimal reproduction is to create a new app via ng new repro-app and adding the minimum possible code to show the problem. Then you can push this repository to github and link it here.
Hello, thanks for your answer.
After some investigation, it happens that an if statement followed by a loop label is compiled in a way that Babel doesn't understand.
Source:
public isLinkedToResultOfNubs(nubs: Nub[], followLinksChain: boolean = true): boolean {
let linked = false;
if (this._valueMode === ParamValueMode.LINK && this.isReferenceDefined()) {
const targetNubUid = this.referencedValue.nub.uid;
if (this.referencedValue.isResult() || this.referencedValue.isExtraResult()) {
outerloop:
for (const y of nubs) {
if (y.uid === targetNubUid) {
linked = true;
break outerloop;
} else if (this.referencedValue.nub.dependsOnNubResult(y)) {
linked = true;
break outerloop;
}
}
} else {
if (followLinksChain) {
linked = (this.referencedValue.element as ParamDefinition).isLinkedToResultOfNubs(nubs);
}
}
}
return linked;
}
Compiled es2015:
isLinkedToResultOfNubs(nubs, followLinksChain = !0) {
let linked = !1;
if (this._valueMode === ParamValueMode.LINK && this.isReferenceDefined()) {
const targetNubUid = this.referencedValue.nub.uid;
if (this.referencedValue.isResult() || this.referencedValue.isExtraResult()) outerloop: for (const y of nubs) {
if (y.uid === targetNubUid) {
linked = !0;
break outerloop
}
if (this.referencedValue.nub.dependsOnNubResult(y)) {
linked = !0;
break outerloop
}
} else followLinksChain && (linked = this.referencedValue.element.isLinkedToResultOfNubs(nubs))
}
return linked
}
The second if that contains the loop has its braces removed, which is understandable as it contains only one expression. So it ends up being immediately followed by the loop label. This compiled es2015 version works in the browser.
But then Babel fails to translate it to es5 - failure confirmed with babel-cli on a file containing this function only.
Is if (foo) label: for (const b of bar) { in the generated code a valid syntax ? If it is, then I guess it's a Babel issue. If not, is it a Typescript issue ?
Well… it happens that this code was poorly refactored at some time because the loop label is not needed here, so problem solved :) My bad. But it might still be a problem in other contexts.
Thanks
Confirmed that loop labels also caused the same problem here. Changing the flow of code slightly allowed us to work around the problem, but this isn't ideal ;)
I get the exact same error as mentioned in the starting post:
Property body expected type of array but got null
And it appears that this issue is the only one mentioning this particular bug. However, I have no labled breakpoints. At least I find nothing with the regex break[^;].
So have there been any updates regarding this issue?
Edit: Angular version
ng --version
```bash
Angular CLI: 9.1.12
Node: 10.16.3
OS: linux x64
Angular: 9.1.12
... animations, cli, common, compiler, compiler-cli, core, forms
... language-service, localize, platform-browser
... platform-browser-dynamic, router
Ivy Workspace: Yes
@angular-devkit/architect 0.901.12
@angular-devkit/build-angular 0.901.12
@angular-devkit/build-optimizer 0.901.12
@angular-devkit/build-webpack 0.901.12
@angular-devkit/core 9.1.12
@angular-devkit/schematics 9.1.12
@ngtools/webpack 9.1.12
@schematics/angular 9.1.12
@schematics/update 0.901.12
rxjs 6.5.5
typescript 3.8.3
webpack 4.42.0
```
Sorry, I was looking in the wrong place :)
We have a in-house library which was using loop labels. Refactored the code and now it works. Thanks a lot for your hint! Never would have found the issue without it.
Most helpful comment
Hello, thanks for your answer.
cause of the problem
After some investigation, it happens that an
ifstatement followed by a loop label is compiled in a way that Babel doesn't understand.Source:
Compiled es2015:
The second
ifthat contains the loop has its braces removed, which is understandable as it contains only one expression. So it ends up being immediately followed by the loop label. This compiled es2015 version works in the browser.But then Babel fails to translate it to es5 - failure confirmed with
babel-clion a file containing this function only.Is
if (foo) label: for (const b of bar) {in the generated code a valid syntax ? If it is, then I guess it's a Babel issue. If not, is it a Typescript issue ?disclosure
Well… it happens that this code was poorly refactored at some time because the loop label is not needed here, so problem solved :) My bad. But it might still be a problem in other contexts.
Thanks