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 setting connector to re-enable saving user settings (cf. #7147) #7601
Fix setting connector to re-enable saving user settings (cf. #7147) #7601
Conversation
Thanks for making a pull request to JupyterLab! To try out this branch on binder, follow this link: |
@afshin I was a little lost at first going through the changes in #7174, but your earlier discussion with @vidartf made things a lot clearer:
One other question I had, though: why does |
The reasoning was that I didn't want to need to know the |
@@ -40,5 +40,9 @@ export class SettingConnector extends DataConnector< | |||
}; | |||
} | |||
|
|||
async save(id: string, raw: string): Promise<void> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🍳 🥚 on my face. Thanks for the fix 👍
@@ -40,5 +40,9 @@ export class SettingConnector extends DataConnector< | |||
}; | |||
} | |||
|
|||
async save(id: string, raw: string): Promise<void> { | |||
await this._connector.save(id, raw); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a slight preference toward return this._connector.save(id, raw);
but not a strong one. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was going to say "I'm happy to change it just because you asked, @afshin", but then I looked and saw that the function it's wrapping is also async
:
async save(id: string, raw: string): Promise<void> { |
so for consistency's sake, I think save
should stick with async/await
here.
To be 100% sure, the async
and return Promise
versions are semantically equivalent: both will immediately return a Promise
that resolves upon completion of the wrapped function, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there an extra promise getting wrapped up in here? Basically I'm wondering if these three are equivalent or if they return a different level of nesting.
save(id: string, raw: string): Promise<void> {
return this._connector.save(id, raw);
}
async save(id: string, raw: string): Promise<void> {
return this._connector.save(id, raw);
}
async save(id: string, raw: string): Promise<void> {
await this._connector.save(id, raw);
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've read over the async/await
docs and I've live inspected all three versions in DevTools. Here's my conclusions:
-
From the perspective of a caller, 1, 2, and 3 are identical. All return a singly nested promise that resolves to an
undefined
. -
1 and 2 are actually identical. If a function is already returning a
Promise
, all adding theasync
keyword does is allow for the use ofawait
within the function body. -
3 might involve one extra step in it's evaluation. Basically, 1/2 just return the inner promise, whereas 3 returns a promise that resolves when the wrapper function finishes. The extra step would then be the implicit
return void 0
that the wrapper function calls after it awaits the inner promise.
So at least I can confidently say that no, there's no extra promise getting wrapped up here. I can also say that for our purposes there are no important distinctions between 1/2/3. @afshin Do you still think I should change it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, so I think if we are exporting ES2015, 1 is the best answer, based on this experiment. Does that look right to you? You can play with the playground link to confirm.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(This is all very pedantic, but it's good to know what JS we are actually generating.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
I don't want it to delay getting a fix in for the settings bug, but it would be neat to get someone familiar with the deep magics of the JS runtime to weigh in as to whether there's any difference whatsoever in practice between the different ways to wrap an |
References
followup #7147
In the latest master, you cannot change/save any of the user settings. This PR fixes that.
Code changes
Digging through the merged PRs, it looks like in #7147 a
save
method was left out of theSettingConnector
that now wraps the preexistingSettingManager
. I addedSettingConnector.save
, which just forwardsSettingManager.save
.I also did a little bit of related code cleanup in
apputils-extension
, and moved the settings plugin out into its own src file (mostly for the sake of making it easier for me to grasp what had broken)User-facing changes
Unbreaks settings
Backwards-incompatible changes
None