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

Bad timing routing issue, failing test #16342

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

wagenet
Copy link
Member

@wagenet wagenet commented Mar 8, 2018

Not really sure what to name this, or if this test is in the right area,
but it is an issue!


this.add('route:dummy', Route.extend({
redirect() {
return RSVP.resolve()
Copy link
Contributor

Choose a reason for hiding this comment

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

If I understand well, this is specifically what the test is about ?

Copy link
Member Author

Choose a reason for hiding this comment

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

Correct.

@sly7-7
Copy link
Contributor

sly7-7 commented Mar 8, 2021

@wagenet I've updated (locally) this test to highlight the real issue (it needs an expectDeprecation because of the call to this.replaceWith()).
I don't understand what's going on. The only thing I can tell for now, is that adding this Promise.resolve() (so some kind of asynchrony I guess) causes the router to be in a very bad state, ultimately hitting https://github.com/emberjs/ember.js/blob/master/packages/@ember/-internals/routing/lib/system/router.ts#L1750 with an undefined defaultParentState.

'route:dummy',
Route.extend({
redirect() {
return RSVP.resolve().then(() => this.replaceWith('index'));
Copy link
Contributor

Choose a reason for hiding this comment

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

Needs something like this:

expectDeprecation(() => {
  this.replaceWith('index');
}, 'Calling replaceWith on a route is deprecated. Use the RouterService instead.');

Copy link
Member Author

Choose a reason for hiding this comment

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

Updated.

@sly7-7
Copy link
Contributor

sly7-7 commented Mar 9, 2021

@rwjblue @wagenet, Could you guys please explain me the difference in term of behavior using return Promise.resolve().then(replaceWith()) and await Promise.resolve(); replaceWith()?

Because for me, they are be the same.

The one from Peter's test (somehow makes the test fail)

this.add(
        'route:dummy',
        Route.extend({
          redirect() {
            return RSVP.resolve().then(() => {
              expectDeprecation(() => {
                this.replaceWith('index');
              }, 'Calling replaceWith on a route is deprecated. Use the RouterService instead.');
            });
          },
        })
      );

The one I just tried (the test is green this way).

this.add(
        'route:dummy',
        Route.extend({
          async redirect() {
            await RSVP.resolve();
            expectDeprecation(() => {
              this.replaceWith('index');
            }, 'Calling replaceWith on a route is deprecated. Use the RouterService instead.');
          },
        })
      );

image

I was thinking maybe await Promise.resolve() would be somehow synchronous, so I modified resolving the Promise after 500ms, and it's working too:
Screenshot from 2021-03-09 08-30-57

@sly7-7
Copy link
Contributor

sly7-7 commented Mar 9, 2021

I've made some other tiny experiment around return Promise.resolve().then() / await Promise.resolve().
Maybe this could you give you some clue.

 redirect() {
   return new RSVP.Promise((resolve) => {
     count++;
     // later(resolve, 1); // pass
     // later(resolve, 0); // pass
     // next(resolve); // pass
     // run(resolve); // fails
     // resolve(); // fails
   }).then(() => {
     assert.equal(count, 1);
     expectDeprecation(() => {
       this.replaceWith('index');
     }, 'Calling replaceWith on a route is deprecated. Use the RouterService instead.');
   });
 },

 async redirect() {
   await new RSVP.Promise((resolve) => {
     count++;
     // later(resolve, 1); // pass
     // later(resolve, 0); // pass
     // next(resolve); // pass
     // run(resolve); // pass
     // resolve(); // pass
   });
   assert.equal(count, 1);
   expectDeprecation(() => {
     this.replaceWith('index');
   }, 'Calling replaceWith on a route is deprecated. Use the RouterService instead.');
 },

@wagenet
Copy link
Member Author

wagenet commented Mar 9, 2021

Possibly it has to do with the difference in the code generated by the transpiler.

@sly7-7
Copy link
Contributor

sly7-7 commented Mar 10, 2021

@wagenet I've had a discussion with @rwjblue on this thing. From the discord chat:
I'm putting that here, so we don't forget:

  • at a high level, we have a somewhat fundamental problem when you return a promise that then redirects

seems related to: tildeio/router.js#310 and emberjs/ember-test-helpers#332

@locks
Copy link
Contributor

locks commented Feb 5, 2022

@wagenet is this still relevant?

@wagenet
Copy link
Member Author

wagenet commented Feb 7, 2022

@locks I just rebased. Looks like CI still fails.

@kategengler
Copy link
Member

Is this still relevant?

@wagenet
Copy link
Member Author

wagenet commented Jan 10, 2024

Rebased again. If this still fails, it's relevant though if we replace the router then it won't be :D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Todo
Development

Successfully merging this pull request may close these issues.

None yet

4 participants