Skip to content

Function calls are not supported in decorators when fullTemplateTypeCheck is not specified and @dynamic has no effect #23609

Closed

Description

@alan-agius4

I'm submitting a...


[X] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report  
[ ] Performance issue
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question
[ ] Other... Please describe:

Current behavior

When building a library and specifying both skipTemplateCodegen and strictMetadataEmit to true, and you try to call a method inside the ngModule decorate example RouterModule.forChild([]) this will cause a compilation error Function calls are not supported in decorators but 'RouterModule' was called.

When adding fullTemplateTypeCheck to true the error is not emitted.

Also, @dynamic seems not to have any effect in this particular case.

Expected behavior

No error emitted, or at least that it can be suppressed with the @dynamic.

I also expect that setting fullTemplateTypeCheck doesn't have any effect here as this flag relates more to binding in templates.

Minimal reproduction of the problem with instructions

Create a file example

import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';

@NgModule({
  imports: [
    RouterModule.forChild([])
  ]
})
export class LibModule { }

Have tsconfig set with the following options;

  "angularCompilerOptions": {
    "skipTemplateCodegen": true,
    "strictMetadataEmit": true
  }

When transpiling this will emit an error;

Error during template compile of 'LibModule' Function calls are not supported in decorators but 'RouterModule' was called.

Note when adding "fullTemplateTypeCheck": true no error is emitted. (Though this is kinda weird as I don't think this shouldn't have any effect)

Reproduction repo: https://github.com/alan-agius4/angular-issue-23609

What is the motivation / use case for changing the behavior?

No error was emitted in NG 5

Environment


Angular version: 6.0.0-rc-6

Related issues:
https://github.com/dherges/ng-packagr/issues/822
https://github.com/dherges/ng-packagr/issues/778
https://github.com/dherges/ng-packagr/issues/727
https://github.com/dherges/ng-packagr/issues/765
https://github.com/dherges/ng-packagr/issues/767
https://github.com/dherges/ng-packagr/issues/885

Activity

  1. changed the title [-]Function calls are not supported in decorators when fullTemplateTypeCheck is not specified[/-] [+]Function calls are not supported in decorators when fullTemplateTypeCheck is not specified and @dynamic has no effect[/+] on Apr 30, 2018
  2. alan-agius4 commented on Apr 30, 2018

    @alan-agius4
    ContributorAuthor

    Added a small repo reproducing this.

    From my quick debug, It looks like the static_reflector is not resolving members / statics properly. As for instance the RouterModule should have a forChild member.

    image

  3. added this to the needsTriage milestone on May 3, 2018
  4. modified the milestones: needsTriage, Backlog on May 3, 2018
  5. wardbell commented on May 5, 2018

    @wardbell
    Contributor

    I have this problem too. I tried fullTemplateTypeCheck in lib/tsconfig.json and it made no difference.

    My repro:

    git clone https://github.com/johnpapa/angular-ngrx-data.git ngrx-data-FAIL
    cd ngrx-data-FAIL
    git checkout ng-v6-FAIL
    npm install
    

    Now attempt to build the ngrx-data library

    npm run build-lib

    The build fails. The console says

    BUILD ERROR
    Error during template compile of 'NgrxDataModule'
      Function calls are not supported in decorators but 'StoreModule' was called.
      ...

    Comment out the two ngrx imports in NgrxDataModule (leaving the FooModule) and try building again.
    This time the build succeeds and generates a package in dist.

    Note that FooModule is just fine.

  6. dherges commented on May 6, 2018

    @dherges
    Contributor

    Regarding Ward's repro: @wardbell

    The build will succeed / fail depending on the combination of angularCompilerOptions. Added one example in this repro

    Build success

        "skipTemplateCodegen": true,
        "strictMetadataEmit": true,
        "fullTemplateTypeCheck": true
        "skipTemplateCodegen": false,
        "strictMetadataEmit": false
        "skipTemplateCodegen": false,
        "strictMetadataEmit": true,
        // fullTemplateTypeCheck omitted (= default value)

    Build failures

        "skipTemplateCodegen": true,
        "strictMetadataEmit": true,
        // fullTemplateTypeCheck omitted (= default value)
        "skipTemplateCodegen": true,
        "strictMetadataEmit": false
        // fullTemplateTypeCheck omitted (= default value)

    Observation

    In Ward's example, setting "skipTemplateCodegen": true requires that "fullTemplateTypeCheck": true is also enabled to get a success build from ngc.

    Side notes / other thoughts

    My experience is that the issue goes down to "everything statically analyzable for AoT" (see "need for static value resoltion" in the compiler docs). Imo, something is broken around the strictMetadataEmit option or my understanding of the option is horribly broken 😆

    From my experience I can tell that the issue is often produced in static forRoot(): ModuleWithProviders, sometimes depending on one line of code that becomes or becomes not "statically analyzable". Of course, I don't have reliable repros and I also don't want to speculate on some vague memories of code that I've seen working / non-working.

    Can ngc improve the error message?

    What will help that ngc prints out the line number in the source code that triggers the error.

  7. wardbell commented on May 7, 2018

    @wardbell
    Contributor

    Thanks, @dherges, for figuring out a combination that succeeds. I'm clearly flailing with no clue what these flags are doing to help or hurt.

    This issue should remain open until Angular makes these choices intelligible and documents appropriately.

  8. 123 remaining items

  9. removed
    P3An issue that is relevant to core functions, but does not impede progress. Important, but not urgent
    on Oct 1, 2020
  10. aescobar-icc commented on Jan 9, 2021

    @aescobar-icc

    this works for me:

    "angularCompilerOptions": {
    "skipTemplateCodegen": true,
    "strictMetadataEmit": true,
    "fullTemplateTypeCheck": true,
    "strictInjectionParameters": true,
    "enableResourceInlining": true
    },

  11. MickL commented on Jan 20, 2021

    @MickL

    So that's really our fix for this issue - Ivy will eventually make confusing and inconsistent metadata errors like this a thing of the past. With libraries the situation is a little complicated since for backwards compatibility, they still have to publish in View Engine format and thus deal with strictMetadataEmit for a little longer, but that's going to change sooner rather than later, hopefully.

    @alxhub I created a Library which is not allowed to be published to npm built with Ivy. Therefor I have to use ng build --prod which uses View Engine. But when I do so, I cant built:

    @NgModule({
      imports:      [
        LoggerModule.forRoot({
          level: NgxLoggerLevel.DEBUG
        }),
      ],
    })
    export class MyLibModule {}
    

    Error:

    Function calls are not supported in decorators but 'LoggerModule' was called.

    This issue is 2,5 years old and has >130 comments. A lot of suggestions from where I dont understand most of them. @alxhub would you mind write down a clear workaround? I wonder what this compiler options do and what downsides they have. And will there be ever a fix for View Engine? If not, and View Engine is required for libraries, then the issue and workaround should be documented in the documentation.

    Also @SergeyVolynkin @hitallow @bh3605 @antontemchenko would you mind write down why you downvoted @adrian1907 solution? Sounded like a quick and easy fix, but why isnt it?

  12. SergeyVolynkin commented on Jan 20, 2021

    @SergeyVolynkin
    Contributor

    Hey, there; Didn't downvote 😃 ; you probably mistyped me instead @SergeyMell

  13. TheRealOha commented on Mar 31, 2021

    @TheRealOha

    I'm having the same issue as @MickL but with NgxWebstorageModule.forRoot().
    I have the PrimeNg 11 Table as part of my library, which throws a very strange error when it's not compiled with Ivy.
    To circumvent this I set "fullTemplateTypeCheck": false", which seemed to remove the need to build with Ivy, but now I'm stuck with the same thing as Mick.
    Anyone's got a solution?
    I found that people were advising to build Libs that are only publisehd to internal NPM repos with Ivy by removing prebublishOnly from package.json, but I don't even have this set anywhere in my package.json, therefore I don't know how to remove it.
    However, this also is only a workaround and doesn't really fix the whole problem, that libs are not supposed to be built with Ivy but if you try to omit Ivy, you're stuck with problems like the one described here.

    Help, anyone?

  14. NiklasPor commented on May 4, 2021

    @NiklasPor

    Always make sure that when you're providing a module (inside an npm library / ngc / enableIvy: false) that you're keeping the withConfig forRoot methods as simple one liners. For example I had to remove the simple assignment at the start and move it into a parameter, instead of creating a variable:

    Classic "Function calls are not supported.." 👿 :

    @NgModule({})
    class MyModule {
      static withConfig(
        config: Partial<Config> = {}
      ): ModuleWithProviders<MyModule> {
        const mergedConfig: Config = {
          ...defaultConfig,
          ...config,
        };
    
        return {
          ngModule: MyModule,
          providers: [
            {
                provide: MY_VALUE_1,
                useValue: mergedConfig.myValue1,
              },
              {
                provide: MY_VALUE_2,
                useValue: mergedConfig.myValue2,
              },
          ],
        };
      }
    }

    Actually working 🤯 :

    @NgModule({})
    class MyModule {
      private static withMergedConfig(config: MyConfig) {
        return {
          ngModule: MyModule,
          providers: [
            {
              provide: MY_VALUE_1,
              useValue: config.myValue1,
            },
            {
              provide: MY_VALUE_2,
              useValue: config.myValue2,
            },
          ],
        };
      }
    
      static withConfig(
        config: Partial<MyConfig> = {}
      ): ModuleWithProviders<MyModule> {
        return MyModule.withMergedConfig({
          ...defaultConfig,
          ...config,
        });
      }
    }

    tsconfig.json (like already suggested above):

    "angularCompilerOptions": {
      "skipTemplateCodegen": true,
      "strictMetadataEmit": true,
      "enableResourceInlining": true,
      "fullTemplateTypeCheck": true,
    }
  15. JoostK commented on May 14, 2021

    @JoostK
    Member

    This has arguably been the most annoying error that libraries have had to deal with, and I'm glad that this class of issues has been resolved with the Ivy compiler.

    With v12 now allowing libraries to be compiled with the Ivy compiler, I am closing this issue as resolved.

  16. SuperITMan commented on Jun 9, 2021

    @SuperITMan

    Hey @JoostK

    Could you share your configuration to publish libraries with Ivy?

    Locally, with angular v12 and ng-packagr 12, I'm still not allowed to publish libraries with ivy enabled 😞
    Angular compiler-cli is still adding the following script in "package.json":

    "scripts": {
      "prepublishOnly": "node --eval \"console.error('ERROR: Trying to publish a package that has been compiled by Ivy in full compilation mode. This is not allowed.\\nPlease delete and rebuild the package with Ivy partial compilation mode, before attempting to publish.\\n')\" && exit 1"
    }

    According to official doc, Ivy is still not recommended for libraries:

    enableIvy
    Enables the Ivy compilation and rendering pipeline. Default is true, as of version 9. In version 9, you can opt out of Ivy to continue using the previous compiler, View Engine.

    For library projects generated with the CLI, the production configuration default is false in version 9.

    Thanks in advance for your help 👍

  17. NiklasPor commented on Jun 9, 2021

    @NiklasPor

    @SuperITMan what you're reading is valid for version 9 - 11.

    Starting with version 12 it's recommended to set enableIvy: true and compilationMode: 'partial'.

    ...Please delete and rebuild the package with Ivy partial compilation inside your error message refers to this compilation mode.


    compilationMode

    Specifies the compilation mode to use. The following modes are available:

    • 'full': generates fully AOT-compiled code according to the version of Angular that is currently being used.
    • 'partial': generates code in a stable, but intermediate form suitable for a published library.

    The default value is 'full'.

  18. JoostK commented on Jun 9, 2021

    @JoostK
    Member

    According to official doc, Ivy is still not recommended for libraries:

    That is something we should fix in the docs, then, as it's not the case anymore since v12.

    Other than that I think I got beaten by @NiklasPor, who has just given the correct answer :)

  19. SuperITMan commented on Jun 9, 2021

    @SuperITMan

    @NiklasPor @JoostK

    Thanks for your quick answers! 😃

    You're right, I missed the "compilationMode": "partial" part for libraries. With this option, the "prepublishOnly" is no longer present 👍

  20. angular-automatic-lock-bot commented on Jul 10, 2021

    @angular-automatic-lock-bot

    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.

  21. locked and limited conversation to collaborators on Jul 10, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P5The team acknowledges the request but does not plan to address it, it remains open for discussionarea: compilerIssues related to `ngc`, Angular's template compilerfreq3: highstate: confirmedtype: bug/fix

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions