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

Allow HMR status handlers to return a Promise #13576

Merged
merged 2 commits into from
Jul 18, 2021

Conversation

rockwalrus
Copy link
Contributor

This change allows handlers registered using addStatusHandler to return a Promise. The HMR system will wait until the promise settles before continuing. This allows asynchronous handling of state changes.

In our case, we use this to make sure that when our service worker is modified the update is complete and the service worker installed before the dev server triggers a reload on an unaccepted update.

The diff is much easier to read with ignore whitespace turned on.

What kind of change does this PR introduce?
New feature.

Did you add tests for your changes?
Yes.

Does this PR introduce a breaking change?
No. Handler return values were ignored before, but the worst thing that could happen in the unlikely case that someone was inadvertently returning a Promise from a handler that they weren't expecting to be waited for is that the HMR process might be delayed.

What needs to be documented once your changes are merged?
Document in the Hot Module Replacement Management API section that if a status handler returns a Promise that it will wait for the Promise before continuing.

The HMR system will wait until the promise settles before continuing.
@webpack-bot
Copy link
Contributor

webpack-bot commented Jun 17, 2021

For maintainers only:

  • This needs to be documented (issue in webpack/webpack.js.org will be filed when merged)
  • This needs to be backported to webpack 4 (issue will be created when merged)

for (var i = 0; i < modules.length; i++) {
outdatedModules.push(modules[i]);
// Now in "apply" phase
return setStatus("apply").then(function () {
Copy link
Member

Choose a reason for hiding this comment

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

Here is the only problem I'm seeing.

By this being a Promise, dispose and apply does no longer run in a single go.
This introduces the ability that user code is run in between, while the runtime is in a incomplete state.

e. g. A timeout could fire which imports a module, which is correctly in process of being replaced.

We can't introduce a break here, but I think it would work to all setState("apply") and await the Promise later (before setStatus("idle")/setStatus("fail")).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That will complicate documentation somewhat, but I agree that it's the best option. I considered just not supporting Promises at all for dispose and apply, but it seemed uglier to support Promises for some statuses but not others, and this does provide the somewhat useful ability to write code that always runs after apply is finished regardless of whether there is an error or not.

Copy link
Member

Choose a reason for hiding this comment

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

You can explain it as "running in parallel to the normal apply logic".

expect(a.value).not.toBe(oldA);
expect(b.value).not.toBe(oldB);
expect(c.value).toBe(oldC);
module.hot.apply().then(function () {
Copy link
Member

Choose a reason for hiding this comment

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

Make sure that the apply() API stay sync as long there is no async status handler registered, to avoid a breaking change.

Since setStatus is only internal you could return a { then: fn => fn() } when no Promise was returned from status handlers

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Depending on the synchronously-executed part of an API that's documented to return a Promise seems dangerous, and even before this patch error handling is broken if you try to do so. But I can still implement the synchronous then() if you'd like.

@webpack-bot
Copy link
Contributor

@rockwalrus Thanks for your update.

I labeled the Pull Request so reviewers will review it again.

@sokra Please review the new changes.

@sokra
Copy link
Member

sokra commented Jun 22, 2021

Could you sign the CLA: https://cla.js.foundation/webpack/webpack?pullRequest=13576 ?

@rockwalrus
Copy link
Contributor Author

Could you sign the CLA: https://cla.js.foundation/webpack/webpack?pullRequest=13576 ?

Do you have a corporate CLA that State Farm can sign on my behalf?

Thanks.

@alexander-akait
Copy link
Member

Do you have a corporate CLA that State Farm can sign on my behalf?

We have only general CLA...

@rexb1971
Copy link

I see that the CLA is still showing as being unsigned, but an officer of our company has now signed the document and affirmed that State Farm owns copyright of the contributing code, so I am hoping that you can validate that his signature has been accepted and move the status from unsigned to signed.

@sokra sokra closed this Jun 28, 2021
@sokra sokra reopened this Jun 28, 2021
@sokra
Copy link
Member

sokra commented Jun 28, 2021

@rockwalrus you have to click this link and sign there: https://cla.js.foundation/webpack/webpack?pullRequest=13576
After that the bot will flag the CLA as accepted (after closing and reopening, because it's a bit buggy)

@rockwalrus
Copy link
Contributor Author

I don't have authorization to sign on behalf of the copyright owner, @StateFarmIns. The executive in charge of open source contribution, @RandyMcBeath, who does have that authorization, signed the CLA. Is there a way for you to manually mark that the CLA has been signed for this request? If not, State Farm is going to have to officially license the code to me, at which point I'll be legally able to license the code to you by signing the CLA. But that will take some time to accomplish.

@sokra
Copy link
Member

sokra commented Jun 30, 2021

I don't have authorization to sign on behalf of the copyright owner, @StateFarmIns.

Yeah, but that's not what you need to do. You only need to sign it for yourself.

By signing the CLA you only certify that you created that code, and you are allowed to submit it under our Licence (MIT). Since your company seem to allow it, that should be fine.

But I'm not a lawyer so not super sure...

Is there a way for you to manually mark that the CLA has been signed for this request?

Not really. We could merge the PR without CLA, but that's not the idea of that...

Actually nobody requested that in the last > 5 year since he have this CLA...

@rexb1971
Copy link

I don't have authorization to sign on behalf of the copyright owner, @StateFarmIns.

Yeah, but that's not what you need to do. You only need to sign it for yourself.

By signing the CLA you only certify that you created that code, and you are allowed to submit it under our Licence (MIT). Since your company seem to allow it, that should be fine.

But I'm not a lawyer so not super sure...

Is there a way for you to manually mark that the CLA has been signed for this request?

Not really. We could merge the PR without CLA, but that's not the idea of that...

Actually nobody requested that in the last > 5 year since he have this CLA...

@sokra - according to our lawyers, the problem is that the copyright for this code is no longer held by @rockwalrus - it is instead held by State Farm. So @rockwalrus no longer has the "right" to affirm the terms of the CLA unless we somehow transfer the copyright back to him. So we will need to do our own legal paperwork in order for him to legally sign this CLA himself - according to our lawyers.

@rockwalrus
Copy link
Contributor Author

Sorry for the delay. We'll let you know when we've worked this out internally.

@rockwalrus
Copy link
Contributor Author

I am now authorized to sign the CLA, and have done so!

@alexander-akait
Copy link
Member

we rewrite tests, maybe make sense to do rebase for CI

@webpack-bot
Copy link
Contributor

@rockwalrus The most important CI builds failed. This way your PR can't be merged.

Please take a look at the CI results from azure (1 errors / 1 warnings) and appveyor (success) and fix these issues.

@sokra sokra merged commit a87dba4 into webpack:main Jul 18, 2021
@sokra
Copy link
Member

sokra commented Jul 18, 2021

Thanks

@rockwalrus
Copy link
Contributor Author

You're welcome!

@webpack-bot
Copy link
Contributor

I've created an issue to document this in webpack/webpack.js.org.

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

Successfully merging this pull request may close these issues.

None yet

6 participants