diff --git a/packages/compiler-cli/src/ngtsc/partial_evaluator/src/builtin.ts b/packages/compiler-cli/src/ngtsc/partial_evaluator/src/builtin.ts index 51373de9ba..6e40825840 100644 --- a/packages/compiler-cli/src/ngtsc/partial_evaluator/src/builtin.ts +++ b/packages/compiler-cli/src/ngtsc/partial_evaluator/src/builtin.ts @@ -22,3 +22,21 @@ export class ArraySliceBuiltinFn extends BuiltinFn { } } } + +export class ArrayConcatBuiltinFn extends BuiltinFn { + constructor(private node: ts.Node, private lhs: ResolvedValueArray) { super(); } + + evaluate(args: ResolvedValueArray): ResolvedValue { + const result: ResolvedValueArray = [...this.lhs]; + for (const arg of args) { + if (arg instanceof DynamicValue) { + result.push(DynamicValue.fromDynamicInput(this.node, arg)); + } else if (Array.isArray(arg)) { + result.push(...arg); + } else { + result.push(arg); + } + } + return result; + } +} diff --git a/packages/compiler-cli/src/ngtsc/partial_evaluator/src/interpreter.ts b/packages/compiler-cli/src/ngtsc/partial_evaluator/src/interpreter.ts index 5b4cb6afc9..3e34af4bc6 100644 --- a/packages/compiler-cli/src/ngtsc/partial_evaluator/src/interpreter.ts +++ b/packages/compiler-cli/src/ngtsc/partial_evaluator/src/interpreter.ts @@ -12,7 +12,7 @@ import {Reference} from '../../imports'; import {OwningModule} from '../../imports/src/references'; import {Declaration, ReflectionHost} from '../../reflection'; -import {ArraySliceBuiltinFn} from './builtin'; +import {ArrayConcatBuiltinFn, ArraySliceBuiltinFn} from './builtin'; import {DynamicValue} from './dynamic'; import {ForeignFunctionResolver, VisitedFilesCallback} from './interface'; import {BuiltinFn, EnumValue, ResolvedValue, ResolvedValueArray, ResolvedValueMap} from './result'; @@ -340,6 +340,8 @@ export class StaticInterpreter { return lhs.length; } else if (rhs === 'slice') { return new ArraySliceBuiltinFn(node, lhs); + } else if (rhs === 'concat') { + return new ArrayConcatBuiltinFn(node, lhs); } if (typeof rhs !== 'number' || !Number.isInteger(rhs)) { return DynamicValue.fromUnknown(node); diff --git a/packages/compiler-cli/src/ngtsc/partial_evaluator/test/evaluator_spec.ts b/packages/compiler-cli/src/ngtsc/partial_evaluator/test/evaluator_spec.ts index da3b76b563..bdd0b2b089 100644 --- a/packages/compiler-cli/src/ngtsc/partial_evaluator/test/evaluator_spec.ts +++ b/packages/compiler-cli/src/ngtsc/partial_evaluator/test/evaluator_spec.ts @@ -130,6 +130,14 @@ describe('ngtsc metadata', () => { expect(evaluate(`const a = [1, 2, 3];`, 'a[\'slice\']()')).toEqual([1, 2, 3]); }); + it('array `concat` function works', () => { + expect(evaluate(`const a = [1, 2], b = [3, 4];`, 'a[\'concat\'](b)')).toEqual([1, 2, 3, 4]); + expect(evaluate(`const a = [1, 2], b = 3;`, 'a[\'concat\'](b)')).toEqual([1, 2, 3]); + expect(evaluate(`const a = [1, 2], b = 3, c = [4, 5];`, 'a[\'concat\'](b, c)')).toEqual([ + 1, 2, 3, 4, 5 + ]); + }); + it('negation works', () => { expect(evaluate(`const x = 3;`, '!x')).toEqual(false); expect(evaluate(`const x = 3;`, '!!x')).toEqual(true);