Skip to content
Permalink
Branch: master
Commits on Jan 6, 2020
  1. refactor(ivy): let `strictTemplates` imply `fullTemplateTypeCheck` (#…

    JoostK authored and alxhub committed Dec 2, 2019
    …34195)
    
    Previously, it was required that both `fullTemplateTypeCheck` and
    `strictTemplates` had to be enabled for strict mode to be enabled. This
    is strange, as `strictTemplates` implies `fullTemplateTypeCheck`. This
    commit makes setting the `fullTemplateTypeCheck` flag optional so that
    strict mode can be enabled by just setting `strictTemplates`.
    
    PR Close #34195
  2. refactor(ivy): verify template type check options are compatible (#34195

    JoostK authored and alxhub committed Dec 2, 2019
    )
    
    It is now an error if '"fullTemplateTypeCheck"' is disabled while
    `"strictTemplates"` is enabled, as enabling the latter implies that the
    former is also enabled.
    
    PR Close #34195
  3. refactor(ivy): consistently translate types to `ts.TypeNode` (#34021)

    JoostK authored and alxhub committed Dec 14, 2019
    The compiler has a translation mechanism to convert from an Angular
    `Type` to a `ts.TypeNode`, as appropriate. Prior to this change, it
    would translate certain Angular expressions into their value equivalent
    in TypeScript, instead of the correct type equivalent. This was possible
    as the `ExpressionVisitor` interface is not strictly typed, with `any`s
    being used for return values.
    
    For example, a literal object was translated into a
    `ts.ObjectLiteralExpression`, containing `ts.PropertyAssignment` nodes
    as its entries. This has worked without issues as their printed
    representation is identical, however it was incorrect from a semantic
    point of view. Instead, a `ts.TypeLiteralNode` is created with
    `ts.PropertySignature` as its members, which corresponds with the type
    declaration of an object literal.
    
    PR Close #34021
  4. perf(ivy): support simple generic type constraints in local type ctors (

    JoostK authored and alxhub committed Nov 24, 2019
    #34021)
    
    In Ivy's template type checker, type constructors are created for all
    directive types to allow for accurate type inference to work. The type
    checker has two strategies for dealing with such type constructors:
    
    1. They can be emitted local to the type check block/type check file.
    2. They can be emitted as static `ngTypeCtor` field into the directive
    itself.
    
    The first strategy is preferred, as it avoids having to update the
    directive type which would cause a more expensive rebuild. However, this
    strategy is not suitable for directives that have constrained generic
    types, as those constraints would need to be present on the local type
    constructor declaration. This is not trivial, as it requires that any
    type references within a type parameter's constraint are imported into
    the local context of the type check block.
    
    For example, lets consider the `NgForOf` directive from '@angular/core'
    looks as follows:
    
    ```typescript
    import {NgIterable} from '@angular/core';
    
    export class NgForOf<T, U extends NgIterable<T>> {}
    ```
    
    The type constructor will then have the signature:
    `(o: Pick<i1.NgForOf<T, U>, 'ngForOf'>) => i1.NgForOf<T, U>`
    
    Notice how this refers to the type parameters `T` and `U`, so the type
    constructor needs to be emitted into a scope where those types are
    available, _and_ have the correct constraints.
    
    Previously, the template type checker would detect the situation where a
    type parameter is constrained, and would emit the type constructor
    using strategy 2; within the directive type itself. This approach makes
    any type references within the generic type constraints lexically
    available:
    
    ```typescript
    export class NgForOf<T, U extends NgIterable<T>> {
      static ngTypeCtor<T = any, U extends NgIterable<T> = any>
        (o: Pick<NgForOf<T, U>, 'ngForOf'>): NgForOf<T, U> { return null!; }
    }
    ```
    
    This commit introduces the ability to emit a type parameter with
    constraints into a different context, under the condition that it can
    be imported from an absolute module. This allows a generic type
    constructor to be emitted into a type check block or type check file
    according to strategy 1, as imports have been generated for all type
    references within generic type constraints. For example:
    
    ```typescript
    import * as i0 from '@angular/core';
    import * as i1 from '@angular/common';
    
    const _ctor1: <T = any, U extends i0.NgIterable<T> = any>
      (o: Pick<i1.NgForOf<T, U>, 'ngForOf'>) => i1.NgForOf<T, U> = null!;
    ```
    
    Notice how the generic type constraint of `U` has resulted in an import
    of `@angular/core`, and the `NgIterable` is transformed into a qualified
    name during the emitting process.
    
    Resolves FW-1739
    
    PR Close #34021
Commits on Dec 18, 2019
  1. fix(ivy): avoid duplicate errors in safe navigations and template gua…

    JoostK authored and kara committed Dec 15, 2019
    …rds (#34417)
    
    The template type checker generates TypeScript expressions for any
    expression that occurs in a template, so that TypeScript can check it
    and produce errors. Some expressions as they occur in a template may be
    translated into TypeScript code multiple times, for instance a binding
    to a directive input that has a template guard.
    
    One example would be the `NgIf` directive, which has a template guard to
    narrow the type in the template as appropriate. Given the following
    template:
    
    ```typescript
    @component({
      template: '<div *ngIf="person">{{ person.name }}</div>'
    })
    class AppComponent {
      person?: { name: string };
    }
    ```
    
    A type check block (TCB) with roughly the following structure is
    created:
    
    ```typescript
    function tcb(ctx: AppComponent) {
      const t1 = NgIf.ngTypeCtor({ ngIf: ctx.person });
      if (ctx.person) {
        "" + ctx.person.name;
      }
    }
    ```
    
    Notice how the `*ngIf="person"` binding is present twice: once in the
    type constructor call and once in the `if` guard. As such, TypeScript
    will check both instances and would produce duplicate errors, if any
    were found.
    
    Another instance is when the safe navigation operator is used, where an
    expression such as `person?.name` is emitted into the TCB as
    `person != null ? person!.name : undefined`. As can be seen, the
    left-hand side expression `person` occurs twice in the TCB.
    
    This commit adds the ability to insert markers into the TCB that
    indicate that any errors within the expression should be ignored. This
    is similar to `@ts-ignore`, however it can be applied more granularly.
    
    PR Close #34417
  2. refactor(ivy): cleanup translation of source spans in type checker (#…

    JoostK authored and kara committed Dec 15, 2019
    …34417)
    
    This commit cleans up the template type checker regarding how
    diagnostics are produced.
    
    PR Close #34417
  3. refactor(ivy): use absolute source spans in type checker (#34417)

    JoostK authored and kara committed Dec 15, 2019
    Previously, the type checker would compute an absolute source span by
    combining an expression AST node's `ParseSpan` (relative to the start of
    the expression) together with the absolute offset of the expression as
    represented in a `ParseSourceSpan`, to arrive at a span relative to the
    start of the file. This information is now directly available on an
    expression AST node in the `AST.sourceSpan` property, which can be used
    instead.
    
    PR Close #34417
Commits on Dec 16, 2019
  1. test(ngcc): cleanup entry-point bundle testcases (#34415)

    JoostK authored and kara committed Dec 14, 2019
    There was an issue with the program under test and two tests with the
    same description, this has been fixed.
    
    PR Close #34415
Commits on Dec 12, 2019
  1. perf(compiler): speed up i18n digest computations (#34332)

    JoostK authored and kara committed Dec 8, 2019
    Avoids the usage of array destructuring, as it introduces calls to
    a `__values` helper function in ES5 that has a relatively high
    performance impact. This shaves off roughly 130ms of CPU time for a
    large compilation with big templates that uses i18n.
    
    PR Close #34332
  2. perf(compiler): use a shared interpolation regex (#34332)

    JoostK authored and kara committed Dec 8, 2019
    The template parser has a certain interpolation config associated with
    it and builds a regular expression each time it needs to extract the
    interpolations from an input string. Since the interpolation config is
    typically the default of `{{` and `}}`, the regular expression doesn't
    have to be recreated each time. Therefore, this commit creates only a
    single regular expression instance that is used for the default
    configuration.
    
    In a large compilation unit with big templates, computing the regular
    expression took circa 275ms. This change reduces this to effectively
    zero.
    
    PR Close #34332
  3. perf(compiler): optimize cloning cursors state (#34332)

    JoostK authored and kara committed Dec 8, 2019
    On a large compilation unit with big templates, the total time spent in
    the `PlainCharacterCursor` constructor was 470ms. This commit applies
    two optimizations to reduce this time:
    
    1. Avoid the object spread operator within the constructor, as the
    generated `__assign` helper in the emitted UMD bundle (ES5) does not
    optimize well compared to a hardcoded object literal. This results in a
    significant performance improvement. Because of the straight-forward
    object literal, the VM is now much better able to optimize the memory
    allocations which makes a significant difference as the
    `PlainCharacterCursor` constructor is called in tight loops.
    
    2. Reduce the number of `CharacterCursor` clones. Although cloning
    itself is now much faster because of the optimization above, several
    clone operations were not necessary.
    
    Combined, these changes reduce the total time spent in the
    `PlainCharacterCursor` constructor to just 10ms.
    
    PR Close #34332
  4. perf(ivy): use module resolution cache (#34332)

    JoostK authored and kara committed Dec 7, 2019
    During TypeScript module resolution, a lot of filesystem requests are
    done. This is quite an expensive operation, so a module resolution cache
    can be used to speed up the process significantly.
    
    This commit lets the Ivy compiler perform all module resolution with a
    module resolution cache. Note that the module resolution behavior can be
    changed with a custom compiler host, in which case that custom host
    implementation is responsible for caching. In the case of the Angular
    CLI a custom compiler host with proper module resolution caching is
    already in place, so the CLI already has this optimization.
    
    PR Close #34332
  5. perf(ivy): cache export scopes extracted from declaration files (#34332)

    JoostK authored and kara committed Dec 7, 2019
    The export scope of NgModules from external compilations units, as
    present in .d.ts declarations, does not change during a compilation so
    can be easily shared. There was already a cache but the computed export
    scope was not actually stored there. This commit fixes that.
    
    PR Close #34332
  6. perf(ivy): share instances of `DomElementSchemaRegistry` (#34332)

    JoostK authored and kara committed Dec 7, 2019
    To create a binding parser, an instance of `ElementSchemaRegistry` is
    required. Prior to this change, each time a new binding parser was
    created a new instance of `DomElementSchemaRegistry` would be
    instantiated. This is an expensive operation that takes roughly 1ms per
    instantiation, so it is key that multiple allocations are avoided.
    
    By sharing a single `DomElementSchemaRegistry`, we avoid two such
    allocations, i.e. save ~2ms, per component template.
    
    PR Close #34332
Commits on Dec 11, 2019
  1. refactor(ivy): include generic type for `ModuleWithProviders` in .d.t…

    JoostK authored and AndrewKushnir committed Dec 3, 2019
    …s files (#34235)
    
    The `ModuleWithProviders` type has an optional type parameter that
    should be specified to indicate what NgModule class will be provided.
    This enables the Ivy compiler to statically determine the NgModule type
    from the declaration files. This type parameter will become required in
    the future, however to aid in the migration the compiler will detect
    code patterns where using `ModuleWithProviders` as return type is
    appropriate, in which case it transforms the emitted .d.ts files to
    include the generic type argument.
    
    This should reduce the number of occurrences where `ModuleWithProviders`
    is referenced without its generic type argument.
    
    Resolves FW-389
    
    PR Close #34235
  2. fix(compiler-cli): allow declaration-only template type check members (

    JoostK authored and AndrewKushnir committed Dec 7, 2019
    …#34296)
    
    The metadata collector for View Engine compilations emits error symbols
    for static class members that have not been initialized, which prevents
    a library from building successfully when `strictMetadataEmit` is
    enabled, which is recommended for libraries to avoid issues in library
    consumers. This is troublesome for libraries that are adopting static
    members for the Ivy template type checker: these members don't need a
    value assignment as only their type is of importance, however this
    causes metadata errors. As such, a library used to be required to
    initialize the special static members to workaround this error,
    undesirably introducing a code-size overhead in terms of emitted
    JavaScript code.
    
    This commit modifies the collector logic to specifically ignore
    the special static members for Ivy's template type checker, preventing
    any errors from being recorded during the metadata collection.
    
    PR Close #34296
  3. fix(ivy): inherit static coercion members from base classes (#34296)

    JoostK authored and AndrewKushnir committed Dec 7, 2019
    For Ivy's template type checker it is possible to let a directive
    specify static members to allow a wider type for some input:
    
    ```typescript
    export class MatSelect {
      @input() disabled: boolean;
    
      static ngAcceptInputType_disabled: boolean | string;
    }
    ```
    
    This allows a binding to the `MatSelect.disabled` input to be of type
    boolean or string, whereas the `disabled` property itself is only of
    type boolean.
    
    Up until now, any static `ngAcceptInputType_*` property was not
    inherited for subclasses of a directive class. This is cumbersome, as
    the directive's inputs are inherited, so any acceptance member should as
    well. To resolve this limitation, this commit extends the flattening of
    directive metadata to include the acceptance members.
    
    Fixes #33830
    Resolves FW-1759
    
    PR Close #34296
Commits on Dec 10, 2019
  1. fix(ngcc): fix undecorated child migration when `exportAs` is present (

    JoostK authored and AndrewKushnir committed Nov 23, 2019
    …#34014)
    
    The undecorated child migration creates a synthetic decorator, which
    contained `"exportAs": ["exportName"]` as obtained from the metadata of
    the parent class. This is a problem, as `exportAs` needs to specified
    as a comma-separated string instead of an array. This commit fixes the
    bug by transforming the array of export names back to a comma-separated
    string.
    
    PR Close #34014
  2. fix(ngcc): log Angular error codes correctly (#34014)

    JoostK authored and AndrewKushnir committed Nov 23, 2019
    Replaces the "TS-99" sequence with just "NG", so that error codes are
    logged correctly.
    
    PR Close #34014
  3. fix(ngcc): report diagnostics from migrations (#34014)

    JoostK authored and AndrewKushnir committed Nov 23, 2019
    When ngcc is analyzing synthetically inserted decorators from a
    migration, it is typically not expected that any diagnostics are
    produced. In the situation where a diagnostic is produced, however, the
    diagnostic would not be reported at all. This commit ensures that
    diagnostics in migrations are reported.
    
    PR Close #34014
Commits on Nov 22, 2019
  1. fix(ngcc): do not crash on packages that specify typings as an array (#…

    JoostK authored and matsko committed Nov 21, 2019
    …33973)
    
    In a package.json file, the "typings" or "types" field could be an array
    of typings files. ngcc would previously crash unexpectedly for such
    packages, as it assumed that the typings field would be a string. This
    commit lets ngcc skip over such packages, as having multiple typing
    entry-points is not supported for Angular packages so it is safe to
    ignore them.
    
    Fixes #33646
    
    PR Close #33973
Commits on Nov 20, 2019
  1. fix(ivy): avoid infinite recursion when evaluation source files (#33772)

    JoostK authored and alxhub committed Nov 12, 2019
    When ngtsc comes across a source file during partial evaluation, it
    would determine all exported symbols from that module and evaluate their
    values greedily. This greedy evaluation strategy introduces unnecessary
    work and can fall into infinite recursion when the evaluation result of
    an exported expression would circularly depend on the source file. This
    would primarily occur in CommonJS code, where the `exports` variable can
    be used to refer to an exported variable. This variable would be
    resolved to the source file itself, thereby greedily evaluating all
    exported symbols and thus ending up evaluating the `exports` variable
    again. This variable would be resolved to the source file itself,
    thereby greedily evaluating all exported symbols and thus ending u
    evaluating the `exports` variable again. This variable would be
    resolved to the source file itself, thereby greedily evaluating all
    exported symbols and thus ending up evaluating the `exports` variable
    again. This variable would be resolved to the source file itself,
    thereby greedily evaluating all exported symbols and thus ending up
    evaluating the `exports` variable again. This went on for some time
    until all stack frames were exhausted.
    
    This commit introduces a `ResolvedModule` that delays the evaluation of
    its exports until they are actually requested. This avoids the circular
    dependency when evaluating `exports`, thereby fixing the issue.
    
    Fix #33734
    
    PR Close #33772
  2. fix(ivy): handle non-standard input/output names in template type che…

    JoostK authored and alxhub committed Nov 11, 2019
    …cking (#33741)
    
    The template type checker generates code to check directive inputs and
    outputs, whose name may contain characters that can not be used as
    identifier in TypeScript. Prior to this change, such names would be
    emitted into the generated code as is, resulting in invalid code and
    unexpected template type check errors.
    
    This commit fixes the bug by representing the potentially invalid names
    as string literal instead of raw identifier.
    
    Fixes #33590
    
    PR Close #33741
Commits on Nov 18, 2019
  1. fix(ngcc): always add exports for `ModuleWithProviders` references (#…

    JoostK authored and alxhub committed Nov 16, 2019
    …33875)
    
    In #32902 a bug was supposedly fixed where internal classes as used
    within `ModuleWithProviders` are publicly exported, even when the
    typings file already contained the generic type on the
    `ModuleWithProviders`. This fix turns out to have been incomplete, as
    the `ModuleWithProviders` analysis is not done when not processing the
    typings files.
    
    The effect of this bug is that formats that are processed after the
    initial format had been processed would not have exports for internal
    symbols, resulting in "export '...' was not found in '...'" errors.
    
    This commit fixes the bug by always running the `ModuleWithProviders`
    analyzer. An integration test has been added that would fail prior to
    this change.
    
    Fixes #33701
    
    PR Close #33875
  2. test(ngcc): expand integration tests with APF like package layouts (#…

    JoostK authored and alxhub committed Nov 16, 2019
    …33875)
    
    ngcc has a basic integration test infrastructure that downlevels
    TypeScript code into bundle formats that need to be processed by ngcc.
    Until now, only ES5 bundles were created with a flat structure, however
    more complex scenarios require an APF-like layout containing multiple
    bundle formats.
    
    PR Close #33875
  3. fix(ngcc): correctly include internal .d.ts files (#33875)

    JoostK authored and alxhub committed Nov 16, 2019
    Some declaration files may not be referenced from an entry-point's
    main typings file, as it may declare types that are only used internally.
    ngcc has logic to include declaration files based on all source files,
    to ensure internal declaration files are available.
    
    For packages following APF layout, however, this logic was insufficient.
    Consider an entry-point with base path of `/esm2015/testing` and typings
    residing in `/testing`, the file
    `/esm2015/testing/src/nested/internal.js` has its typings file at
    `/testing/src/nested/internal.d.ts`. Previously, the declaration was
    assumed to be located at `/esm2015/testing/testing/internal.d.ts` (by
    means of `/esm2015/testing/src/nested/../../testing/internal.d.ts`)
    which is not where the declaration file can be found. This commit
    resolves the issue by looking in the correct directory.
    
    PR Close #33875
  4. fix(ngcc): correctly associate decorators with aliased classes (#33878)

    JoostK authored and alxhub committed Nov 16, 2019
    In flat bundle formats, multiple classes that have the same name can be
    suffixed to become unique. In ES5-like bundles this results in the outer
    declaration from having a different name from the "implementation"
    declaration within the class' IIFE, as the implementation declaration
    may not have been suffixed.
    
    As an example, the following code would fail to have a `Directive`
    decorator as ngcc would search for `__decorate` calls that refer to
    `AliasedDirective$1` by name, whereas the `__decorate` call actually
    uses the `AliasedDirective` name.
    
    ```javascript
    var AliasedDirective$1 = /** @Class */ (function () {
        function AliasedDirective() {}
        AliasedDirective = tslib_1.__decorate([
            Directive({ selector: '[someDirective]' }),
        ], AliasedDirective);
        return AliasedDirective;
    }());
    ```
    
    This commit fixes the problem by not relying on comparing names, but
    instead finding the declaration and matching it with both the outer
    and inner declaration.
    
    PR Close #33878
  5. test(ngcc): avoid using spy in `Esm2015ReflectionHost` test (#33878)

    JoostK authored and alxhub committed Nov 16, 2019
    A testcase that was using a spy has shown itself to be brittle, and its
    assertions can easily be moved into a related test.
    
    PR Close #33878
Commits on Nov 12, 2019
  1. fix(ivy): ensure module scope is rebuild on dependent change (#33522)

    JoostK authored and kara committed Oct 31, 2019
    During incremental compilations, ngtsc needs to know which metadata
    from a previous compilation can be reused, versus which metadata has to
    be recomputed as some dependency was updated. Changes to
    directives/components should cause the NgModule in which they are
    declared to be recompiled, as the NgModule's compilation is dependent
    on its directives/components.
    
    When a dependent source file of a directive/component is updated,
    however, a more subtle dependency should also cause to NgModule's source
    file to be invalidated. During the reconciliation of state from a
    previous compilation into the new program, the component's source file
    is invalidated because one of its dependency has changed, ergo the
    NgModule needs to be invalidated as well. Up until now, this implicit
    dependency was not imposed on the NgModule. Additionally, any change to
    a dependent file may influence the module scope to change, so all
    components within the module must be invalidated as well.
    
    This commit fixes the bug by introducing additional file dependencies,
    as to ensure a proper rebuild of the module scope and its components.
    
    Fixes #32416
    
    PR Close #33522
  2. fix(ivy): recompile component when template changes in ngc watch mode (

    JoostK authored and kara committed Nov 2, 2019
    …#33551)
    
    When the Angular compiler is operated through the ngc binary in watch
    mode, changing a template in an external file would not cause the
    component to be recompiled if Ivy is enabled.
    
    There was a problem with how a cached compiler host was present that was
    unaware of the changed resources, therefore failing to trigger a
    recompilation of a component whenever its template changes. This commit
    fixes the issue by ensuring that information about modified resources is
    correctly available to the cached compiler host.
    
    Fixes #32869
    
    PR Close #33551
Commits on Nov 7, 2019
  1. fix(ngcc): add reexports only once (#33658)

    JoostK authored and atscott committed Nov 7, 2019
    When ngcc is configured to generate reexports for a package using the
    `generateDeepReexports` configuration option, it could incorrectly
    render the reexports as often as the number of compiled classes in the
    declaration file. This would cause compilation errors due to duplicated
    declarations.
    
    PR Close #33658
  2. fix(ivy): recompile component when template changes in ngc watch mode (

    JoostK authored and atscott committed Nov 2, 2019
    …#33551)
    
    When the Angular compiler is operated through the ngc binary in watch
    mode, changing a template in an external file would not cause the
    component to be recompiled if Ivy is enabled.
    
    There was a problem with how a cached compiler host was present that was
    unaware of the changed resources, therefore failing to trigger a
    recompilation of a component whenever its template changes. This commit
    fixes the issue by ensuring that information about modified resources is
    correctly available to the cached compiler host.
    
    Fixes #32869
    
    PR Close #33551
  3. fix(ivy): match directives on namespaced elements (#33555)

    JoostK authored and atscott committed Nov 3, 2019
    Prior to this change, namespaced elements such as SVG elements would not
    participate correctly in directive matching as their namespace was not
    ignored, which was the case with the View Engine compiler. This led to
    incorrect behavior at runtime and template type checking.
    
    This commit resolved the issue by ignoring the namespace of elements and
    attributes like they were in View Engine.
    
    Fixes #32061
    
    PR Close #33555
Commits on Nov 6, 2019
  1. fix(ivy): avoid implicit any errors in event handlers (#33550)

    JoostK authored and atscott committed Nov 2, 2019
    When template type checking is configured with `strictDomEventTypes` or
    `strictOutputEventTypes` disabled, in compilation units that have
    `noImplicitAny` enabled but `strictNullChecks` disabled, a template type
    checking error could be produced for certain event handlers.
    
    The error is avoided by letting an event handler in the generated TCB
    always have an explicit `any` return type.
    
    Fixes #33528
    
    PR Close #33550
Commits on Nov 1, 2019
  1. feat(ivy): graceful evaluation of unknown or invalid expressions (#33453

    JoostK authored and atscott committed Oct 28, 2019
    )
    
    During static evaluation of expressions within ngtsc, it may occur that
    certain expressions or just parts thereof cannot be statically
    interpreted for some reason. The static interpreter keeps track of the
    failure reason and the code path that was evaluated by means of
    `DynamicValue`, which will allow descriptive errors. In some situations
    however, the static interpreter would throw an exception instead,
    resulting in a crash of the compilation. Not only does this cause
    non-descriptive errors, more importantly does it prevent the evaluated
    result from being partial, i.e. parts of the result can be dynamic if
    their value does not have to be statically available to the compiler.
    
    This commit refactors the static interpreter to never throw errors for
    certain expressions that it cannot evaluate.
    
    Resolves FW-1582
    
    PR Close #33453
Older
You can’t perform that action at this time.