-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
[lexical-history][lexical-selection][lexical-react] Fix: #6409 TextNode change detection #6420
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
size-limit report 📦
|
Add delay option to HistoryPlugin Add test for facebook#6409 Fix lint issues Fix $cloneWithProperties and test expectations Targeted fix for TextNode leaf change
…ed in LexicalNode.getWritable())
d7fca44
to
1e0187a
Compare
if ($isParagraphNode(node) && $isParagraphNode(clone)) { | ||
return $updateParagraphNodeProperties(clone, node); | ||
} |
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 was wrong because ParagraphNode is always an ElementNode and the exit already happened. This was implemented correctly in LexicalNode.getWritable() so I extracted and exported that implementation instead
if ($isTextNode(clone)) { | ||
invariant($isTextNode(node), 'Expected node be a TextNode'); | ||
clone.__text = node.__text; | ||
} |
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 could not find any possible reason for this code to be here, TextNode.clone already guarantees clone.__text === node.__text
@@ -51,6 +51,6 @@ export function useFilteredExamples(examples: Array<Example>) { | |||
searchName, | |||
tags, | |||
}), | |||
[examples, searchName], | |||
[examples, searchName, tags], |
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.
eslint fix
cloneNotNeeded.add(key); | ||
mutableNode.__key = key; |
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 was not necessary because Node.clone must already do this, I added an invariant to guarantee it
@@ -2272,42 +2272,44 @@ describe('LexicalSelection tests', () => { | |||
it('adjust offset for inline elements text formatting', async () => { | |||
await init(); | |||
|
|||
await editor!.update(() => { | |||
const root = $getRoot(); | |||
await ReactTestUtils.act(async () => { |
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.
Wrapping this is necessary because the update causes a react update
@@ -17,13 +17,15 @@ export {createEmptyHistoryState} from '@lexical/history'; | |||
export type {HistoryState}; | |||
|
|||
export function HistoryPlugin({ | |||
delay, |
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.
Seemed reasonable to fix this missing option while I was in here
@@ -15,7 +15,6 @@ import {forwardRef, Ref, useLayoutEffect, useState} from 'react'; | |||
import {ContentEditableElement} from './shared/LexicalContentEditableElement'; | |||
import {useCanShowPlaceholder} from './shared/useCanShowPlaceholder'; | |||
|
|||
/* eslint-disable @typescript-eslint/ban-types */ |
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.
Could not find a reason for this, if there's an internal meta reason we should sync the eslint config to match whatever that rule is
I don't see the typical Lexical Tests checks running on this PR? /cc @potatowagon @Sahejkm |
mutableNode.__mode = latestNode.__mode; | ||
mutableNode.__detail = latestNode.__detail; | ||
} | ||
if (__DEV__) { |
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 moved this to a __DEV__
because it's a new invariant in a relatively hot code path but we might want to run it unconditionally?
thats strange, why are the jobs skipped, will investigate |
it seems like the core test runs are missing |
think its because of this: lexical/.github/workflows/tests.yml Line 12 in 666ccb2
could be its ignoring core test trigger because this PR modifies the lexical website path. will fix it |
fixed in #6423 |
prolly not the reason since core tests are triggered on #6425. im not sure what else is causing the core test jobs to not trigger on this PR. could it be a transient issue? at least on test PR #6425 the core tests are triggering |
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.
thankyou for the fix! changes look fine according to e2e test results
Description
TextNode
change detection when only one text leaf is dirty but unchanged$cloneWithProperties
- the previous implementation did not correctly handle__textFormat
fromParagraphNode
. Also updated the very incorrect doc string.$cloneWithProperties
to the lexical package because the correct implementation was already inlined inLexicalNode.getWritable()
A more general fix may be possible, it's unclear whether this hack is really necessary for MaxLengthPlugin but other text node transforms may have similar issues so removing the hack could be backwards incompatible.
Closes #6409
Test plan
Before
History's TextNode change detection did not work correctly for subclasses where only properties that did not exist on TextNode changed.
After
The tests show that the behavior is consistent with expectations