Skip to content

property decorators break at runtime with ES2015 and circular deps #30141

Closed

Description

@filipesilva

🐞 bug report

Affected Package

The issue is caused by package @angular/core

Is this a regression?

No

Description

Using the `@Input()` property decorator (or any other property decorators I imagine) targetting ES2015 with a circular dependency on a type will cause a `Uncaught ReferenceError` at runtime.

🔬 Minimal Reproduction

git clone https://github.com/filipesilva/istiti-circular-deps-es2015
cd istiti-circular-deps-es2015
ng serve
# src/app/autocomplete.directive.ts contains the problematic decorator and circular dep

🔥 Exception or Error


main.js:9545 Uncaught ReferenceError: Cannot access 'AutocompleteAbstract' before initialization
    at Module.AutocompleteAbstract (main.js:9545)
    at Module../src/app/autocomplete.directive.ts (main.js:9580)
    at __webpack_require__ (runtime.js:79)
    at Module../src/app/autocomplete.abstract.ts (main.js:9546)
    at __webpack_require__ (runtime.js:79)
    at Module../src/app/parent.component.ts (main.js:9605)
    at __webpack_require__ (runtime.js:79)
    at Module../src/app/app.module.ts (main.js:9507)
    at __webpack_require__ (runtime.js:79)
    at Module../src/main.ts (main.js:9666)

🌍 Your Environment

Angular Version:


Angular CLI: 8.0.0-beta.16
Node: 10.10.0
OS: win32 x64
Angular: 8.0.0-beta.13
... animations, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.800.0-beta.16
@angular-devkit/build-angular     0.800.0-beta.16
@angular-devkit/build-optimizer   0.800.0-beta.16
@angular-devkit/build-webpack     0.800.0-beta.16
@angular-devkit/core              8.0.0-beta.16
@angular-devkit/schematics        8.0.0-beta.16
@angular/cli                      8.0.0-beta.16
@ngtools/webpack                  8.0.0-beta.16
@schematics/angular               8.0.0-beta.16
@schematics/update                0.800.0-beta.16
rxjs                              6.4.0
typescript                        3.4.4
webpack                           4.30.0

Anything else relevant?

cc @istiti

This is similar to #30106. In this case it is not a constructor parameter type, but rather a class property type.

A class property by itself doesn't need metadata with a type reference:

// transpiled src/app/autocomplete.directive.ts without Input() decorator
import * as tslib_1 from "tslib";
import { Directive } from '@angular/core';
let AutocompleteDirective = class AutocompleteDirective {
    constructor() { }
};
// this is used in autocomplete.abstract.ts
AutocompleteDirective.EMPTYLIST_ELEMENT = "_EMPTYLIST_";
AutocompleteDirective = tslib_1.__decorate([
    Directive({
        selector: '[appAutocomplete]'
    }),
    tslib_1.__metadata("design:paramtypes", [])
], AutocompleteDirective);
export { AutocompleteDirective };

But when the property is decorated, the metadata will contain a reference to the type:

// transpiled src/app/autocomplete.directive.ts with Input() decorator
import * as tslib_1 from "tslib";
import { Directive, Input } from '@angular/core';
import { AutocompleteAbstract } from './autocomplete.abstract';
let AutocompleteDirective = class AutocompleteDirective {
    constructor() { }
};
// this is used in autocomplete.abstract.ts
AutocompleteDirective.EMPTYLIST_ELEMENT = "_EMPTYLIST_";
tslib_1.__decorate([
    Input('appAutocomplete'),
    tslib_1.__metadata("design:type", AutocompleteAbstract)
], AutocompleteDirective.prototype, "autocomplete", void 0);
AutocompleteDirective = tslib_1.__decorate([
    Directive({
        selector: '[appAutocomplete]'
    }),
    tslib_1.__metadata("design:paramtypes", [])
], AutocompleteDirective);
export { AutocompleteDirective };

In ES5 there are no class declarations, so TS instead uses a var. One important different between var and class/let/const is that the latter are all subject to the Temporal Dead Zone.

Without the Input() decorator this isn't a problem because there is no circular dependency on the type.

Activity

  1. added this to the needsTriage milestone on Apr 26, 2019
  2. alxhub commented on May 7, 2019

    @alxhub
    Member

    Fundamentally, this feature of TypeScript (emitDecoratorMetadata) is broken in ES2015. There's not much we can do other than not rely on it. Unfortunately, it's central to how JIT works.

  3. modified the milestones: needsTriage, Backlog on May 7, 2019
  4. Alv3s commented on Jan 8, 2020

    @Alv3s

    I am also facing this issue. It is a shame, since the whole purpose of decorators are adding metadata, and this having this issue kinda breaks it. I am using some custom decorators, so I can workaround the issue, but still... :(

  5. Venipa commented on Feb 13, 2020

    @Venipa

    still not fixed

    Uncaught ReferenceError: Cannot access 'CustomDirectivesModule' before initialization
        at Module.CustomDirectivesModule (custom-directives.module.ts:1)
        at Module../src/app/core/core.module.ts (core.module.ts:133)
        at __webpack_require__ (bootstrap:84)
        at Module../src/app/core/index.ts (index.ts:1)
        at __webpack_require__ (bootstrap:84)
        at Module../src/app/_directives/extract.pipe.ts (extract.pipe.ts:1)
        at __webpack_require__ (bootstrap:84)
        at Module../src/app/_directives/custom-directives.module.ts (custom-directives.module.ts:1)
        at __webpack_require__ (bootstrap:84)
        at Module../src/app/material.module.ts (material.module.ts:1)
    
  6. added
    area: compilerIssues related to `ngc`, Angular's template compiler
    and removed
    area: coreIssues related to the framework runtime
    on Mar 17, 2020
  7. 13 remaining items

  8. added a commit that references this issue on Jun 10, 2020
    323651b
  9. added a commit that references this issue on Jun 25, 2020
    0e102c6
  10. angular-automatic-lock-bot commented on Jul 11, 2020

    @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.

  11. locked and limited conversation to collaborators on Jul 11, 2020
  12. added a commit that references this issue on Sep 5, 2020
    fa320af
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions