Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix injection of optional properties #1308

Merged
merged 9 commits into from
Apr 17, 2021

Conversation

notaphplover
Copy link
Member

@notaphplover notaphplover commented Apr 14, 2021

Description

This PR updates the planner to get the right bindings when a constructor has optional parameters and adds ES6 ci test jobs to ensure the library works fine when ES6 is the Typescript compilation target.

Related Issue

#928

Motivation and Context

A constructor with injected rest parameters won't be injected with those rest parameters injection. Typescript users who targets ECMAScript 6 could have issues because of this.

How Has This Been Tested?

A test case have been added.
New ci test jobs have been added.

Types of changes

  • Updated docs / Refactor code / Added a tests case (non-breaking change)
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.
  • I have updated the changelog.

@@ -19,21 +19,21 @@ describe("Issue 543", () => {

@injectable()
class Child2 {
public circ: Circular;
public circ: unknown;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need unknown here ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think yes. If you try to run the tests targeting ES6 and you do not change typings, you get the folloing error:

ReferenceError: Cannot access 'Circular' before initialization
      at Context.<anonymous> (test/bugs/issue_543.test.ts:24:46)
      at processImmediate (internal/timers.js:456:21)

I think we can change the type because at the end it's sugar syntax. What we really want to check is we are able to detect a circular dependency but maybe I'm missing something

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was working on this yesterday and rewrote the tests I will try to add just that part

@notaphplover notaphplover marked this pull request as ready for review April 15, 2021 20:15
@notaphplover notaphplover requested review from PodaruDragos, dcavanagh and a team April 16, 2021 13:55
Copy link
Contributor

@PodaruDragos PodaruDragos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks fine to me, but maybe we can find a way to actually keep types as types there in tests.
I guess we can do that later

@notaphplover
Copy link
Member Author

this looks fine to me, but maybe we can find a way to actually keep types as types there in tests.
I guess we can do that later

Yeah, I'd love to find a way. I've been compiling the code targeting es6 modules and targeting es5:

The following code fragment:

@injectable()
class Child2 {
    public circ: Circular;
    public constructor(
        @inject(TYPE.Circular) circ: Circular
    ) {
        this.circ = circ;
    }
}
...
@injectable()
class Circular {
    public irrelevant: unknown;
    public child: unknown;
    public constructor(
        @inject(TYPE.Irrelevant) irrelevant: Irrelevant,
        @inject(TYPE.Child) child: Child
    ) {
        this.irrelevant = irrelevant;
        this.child = child;
    }
}

Is compiled into this fragment: (ES5)

var Child2 = (function () {
    function Child2(circ) {
        this.circ = circ;
    }
    Child2 = __decorate([
        inversify_1.injectable(),
        __param(0, inversify_1.inject(TYPE.Circular)),
        __metadata("design:paramtypes", [Circular])
    ], Child2);
    return Child2;
}());
...
var Circular = (function () {
    function Circular(irrelevant, child) {
        this.irrelevant = irrelevant;
        this.child = child;
    }
    Circular = __decorate([
        __param(0, inversify_1.inject(TYPE.Irrelevant)),
        __param(1, inversify_1.inject(TYPE.Child)),
        __metadata("design:paramtypes", [Irrelevant, Child])
    ], Circular);
    return Circular;
}());

So we are "fine" thanks to the var scope (even if metadata is not being decorated properly).

Let's see the same compiled fragment on es6:

let Child2 = class Child2 {
    constructor(circ) {
        this.circ = circ;
    }
};
Child2 = __decorate([
    inversify_1.injectable(),
    __param(0, inversify_1.inject(TYPE.Circular)),
    __metadata("design:paramtypes", [Circular])
], Child2);
...
let Circular = class Circular {
    constructor(irrelevant, child) {
        this.irrelevant = irrelevant;
        this.child = child;
    }
};
Circular = __decorate([
    __param(0, inversify_1.inject(TYPE.Irrelevant)),
    __param(1, inversify_1.inject(TYPE.Child)),
    __metadata("design:paramtypes", [Irrelevant, Child])
], Circular);

let scope is being used instead, so it won't work.

Since we need to emit class metadata and one class must be the first one (splitting classes in multiple files wouln't work the problem since we would be creating a circular dependency), I wonder if we can solve this :( without the unknown workaround.

@dcavanagh dcavanagh force-pushed the fix/issue-928-constructor-injection-broken branch 4 times, most recently from 8cd8ddc to 7790cb2 Compare April 17, 2021 15:44
Comment on lines +13 to +24
"-r",
"ts-node/register",
"--require",
"reflect-metadata",
"-u",
"tdd",
"--timeout",
"999999",
"--colors",
"${workspaceRoot}/test/**/*.test.js"
"${workspaceRoot}/test/**/*.test.ts"
],
"sourceMaps": true,
"outFiles": [
"${workspaceRoot}/test",
"${workspaceRoot}/src"
],
"internalConsoleOptions": "openOnSessionStart"
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"protocol": "inspector"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️

es config updated for es6
ci for es6 test

Co-authored-by: Dan Cavanagh <djcavanagh@gmail.com>
@notaphplover notaphplover force-pushed the fix/issue-928-constructor-injection-broken branch from 7790cb2 to 3dfcb5d Compare April 17, 2021 16:36
@notaphplover
Copy link
Member Author

this looks fine to me, but maybe we can find a way to actually keep types as types there in tests.
I guess we can do that later

At the @dcavanagh was able to find a way though interfaces 😃

Copy link
Member

@dcavanagh dcavanagh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixes #928

@dcavanagh dcavanagh merged commit d72de9b into master Apr 17, 2021
@dcavanagh dcavanagh deleted the fix/issue-928-constructor-injection-broken branch April 22, 2021 20:05
dcavanagh added a commit that referenced this pull request Apr 25, 2021
* fix: update getTargets to correclty get constructorTargets when a constructor has optional arguments

* chore: update ci with es6 ci test jobs

* chore: add typescript config that targets es6

* style: add missing line feed

* style: add missing line feed

* docs: update changelog

* refactor: move e6 tsconfig with the other ts config files

* refactor tests for es6
es config updated for es6
ci for es6 test

Co-authored-by: Dan Cavanagh <djcavanagh@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants