diff --git a/tools/@angular/tsc-wrapped/src/evaluator.ts b/tools/@angular/tsc-wrapped/src/evaluator.ts index f3445e2df7..5f83f6fe5c 100644 --- a/tools/@angular/tsc-wrapped/src/evaluator.ts +++ b/tools/@angular/tsc-wrapped/src/evaluator.ts @@ -154,7 +154,8 @@ export class Evaluator { case ts.SyntaxKind.CallExpression: const callExpression = node; // We can fold a .concat(). - if (isMethodCallOf(callExpression, 'concat') && callExpression.arguments.length === 1) { + if (isMethodCallOf(callExpression, 'concat') && + arrayOrEmpty(callExpression.arguments).length === 1) { const arrayNode = (callExpression.expression).expression; if (this.isFoldableWorker(arrayNode, folding) && this.isFoldableWorker(callExpression.arguments[0], folding)) { @@ -167,7 +168,8 @@ export class Evaluator { } // We can fold a call to CONST_EXPR - if (isCallOf(callExpression, 'CONST_EXPR') && callExpression.arguments.length === 1) + if (isCallOf(callExpression, 'CONST_EXPR') && + arrayOrEmpty(callExpression.arguments).length === 1) return this.isFoldableWorker(callExpression.arguments[0], folding); return false; case ts.SyntaxKind.NoSubstitutionTemplateLiteral: @@ -295,14 +297,15 @@ export class Evaluator { return recordEntry({__symbolic: 'spread', expression: spreadExpression}, node); case ts.SyntaxKind.CallExpression: const callExpression = node; - if (isCallOf(callExpression, 'forwardRef') && callExpression.arguments.length === 1) { + if (isCallOf(callExpression, 'forwardRef') && + arrayOrEmpty(callExpression.arguments).length === 1) { const firstArgument = callExpression.arguments[0]; if (firstArgument.kind == ts.SyntaxKind.ArrowFunction) { const arrowFunction = firstArgument; return recordEntry(this.evaluateNode(arrowFunction.body), node); } } - const args = callExpression.arguments.map(arg => this.evaluateNode(arg)); + const args = arrayOrEmpty(callExpression.arguments).map(arg => this.evaluateNode(arg)); if (!this.options.verboseInvalidExpression && args.some(isMetadataError)) { return args.find(isMetadataError); } @@ -315,7 +318,8 @@ export class Evaluator { } } // Always fold a CONST_EXPR even if the argument is not foldable. - if (isCallOf(callExpression, 'CONST_EXPR') && callExpression.arguments.length === 1) { + if (isCallOf(callExpression, 'CONST_EXPR') && + arrayOrEmpty(callExpression.arguments).length === 1) { return recordEntry(args[0], node); } const expression = this.evaluateNode(callExpression.expression); @@ -329,7 +333,7 @@ export class Evaluator { return recordEntry(result, node); case ts.SyntaxKind.NewExpression: const newExpression = node; - const newArgs = newExpression.arguments.map(arg => this.evaluateNode(arg)); + const newArgs = arrayOrEmpty(newExpression.arguments).map(arg => this.evaluateNode(arg)); if (!this.options.verboseInvalidExpression && newArgs.some(isMetadataError)) { return recordEntry(newArgs.find(isMetadataError), node); } @@ -575,3 +579,9 @@ export class Evaluator { function isPropertyAssignment(node: ts.Node): node is ts.PropertyAssignment { return node.kind == ts.SyntaxKind.PropertyAssignment; } + +const empty = [] as ts.NodeArray; + +function arrayOrEmpty(v: ts.NodeArray): ts.NodeArray { + return v || empty; +} \ No newline at end of file diff --git a/tools/@angular/tsc-wrapped/test/evaluator.spec.ts b/tools/@angular/tsc-wrapped/test/evaluator.spec.ts index 30d28ac32c..0e5e05350a 100644 --- a/tools/@angular/tsc-wrapped/test/evaluator.spec.ts +++ b/tools/@angular/tsc-wrapped/test/evaluator.spec.ts @@ -215,8 +215,21 @@ describe('Evaluator', () => { 0, {__symbolic: 'spread', expression: {__symbolic: 'reference', name: 'arrImport'}}, 5 ]); }); + + it('should be able to handle a new expression with no arguments', () => { + const source = sourceFileOf(` + export var a = new f; + `); + const expr = findVar(source, 'a'); + expect(evaluator.evaluateNode(expr.initializer)) + .toEqual({__symbolic: 'new', expression: {__symbolic: 'reference', name: 'f'}}); + }); }); +function sourceFileOf(text: string): ts.SourceFile { + return ts.createSourceFile('test.ts', text, ts.ScriptTarget.Latest, true); +} + const FILES: Directory = { 'directives.ts': ` export function Pipe(options: { name?: string, pure?: boolean}) {