-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Allow get/set/get (lazy initialization) within same tracking frame #21226
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
base: main
Are you sure you want to change the base?
Changes from 1 commit
24f5256
a6a74d4
fd7c758
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -203,6 +203,15 @@ if (DEBUG) { | |
|
|
||
| if (!transaction) return; | ||
|
|
||
| // Allow get/set/get (lazy initialization) within the same tracking frame. | ||
| // If the tag was consumed in the current transaction, un-consume it so that | ||
| // a subsequent read can re-consume it with the updated value. | ||
| let currentTransaction = TRANSACTION_STACK[TRANSACTION_STACK.length - 1]; | ||
| if (transaction === currentTransaction) { | ||
| CONSUMED_TAGS.delete(tag); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if there is a way to check that this tag is the same tag that is being set 🤔 Perhaps when we should do this before marking a tag as dirty (and not mark dirty?) I wonder if there are render-output consequences to doing that 🤔
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. assertTagNotConsumed seems like a debug only thing? how do we protect production from infinite render loops?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The tag param in The idea of skipping the dirty instead of just suppressing the assertion is interesting. If we skip However, that would change production behavior (not just debug). Right now this PR only touches the debug assertion path —
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, For infinite render loops in production: the lazy init pattern converges because the set is conditional ( The rendering engine does have its own max-revalidation safeguard as a last resort, but this PR doesn't change the production behavior at all — only the dev-mode assertion.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we want to support lazy initialization without infinite looping
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this behavior change would probably need an RFC, fwiw (emberjs/rfcs) -- the original decision to throw so aggressively also should have probably gone through RFC
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated the implementation to address both concerns. Instead of immediately un-consuming on same-frame set, it now defers the assertion to end-of-frame:
So now:
All 8795 tests pass, lint is clean. This is still debug-only — production behavior unchanged. Re: RFC — acknowledged. Happy to help draft one if you'd like to go that route. |
||
| return; | ||
| } | ||
|
|
||
| // This hack makes the assertion message nicer, we can cut off the first | ||
| // few lines of the stack trace and let users know where the actual error | ||
| // occurred. | ||
|
|
||
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.
we should probably assert renderSettled or stablerender, whatever that helper is we use all over the place in other tests