nested validation stacks break because they've already been normalized
See original GitHub issueDo you want to request a feature or report a bug?
Bug.
What’s the current behavior?
If you write a custom normalize
function for a schema, and it happens to do something like change.moveNodeByKey
, there’s a chance that calling that change method will initialize its own validation stack, fixing problems that the parent validation stack assumes are still there.
For example, consider that you have two child text nodes adjacent to each other, which is invalid in Slate. If in your normalize
function you make any change to the parent of those text nodes, that change will end up normalizing internally, and the text nodes will be combined. However, the parent validation stack still thinks that an invalid rule that needs to be fixed, so it tries to normalize them again, and fails.
What’s the expected behavior?
Not sure.
The ideal would be to prevent the double-checking from happening. I haven’t dug into this yet, so I’m not sure if it’s impossible to do or not.
Another option would be to automatically pass options.normalize: false
to all change methods called while performing a validations. The “core” validateNode
handlers already do this automatically. But this feels like it might be too magic-y?
Have others run into this? Thoughts?
Issue Analytics
- State:
- Created 6 years ago
- Reactions:1
- Comments:15 (13 by maintainers)
This can be solved by using
deferNormalization
, in combination with improvements to the performance from https://github.com/ianstormtaylor/slate/issues/2136.Pretty sure I’m running into this with
wrapBlockByKey
. Here’s an example trace (pardon webpack indirection) that shows the multiple normalization passes withwrapBlockByKey
callingmoveNodeByKey
internally. In the trace, it’s isolated down to a single schema rule and a single validation failure:This is a blocker for some of the more complex operations (most of them) in my schema rules. I can’t seem to find a way around it. Maybe
validateNode
is best for now on the stuff that may trigger this, until there’s a way to prevent the extra normalization?I’m not sure how I feel about needing to pass
options.normalize: false
on every change method (could get redundant). Feels kind of clunky compared to the rest of the lib, especially when chaining lots of methods. Maybe thechange
object itself could be callable and take anormalize
option, then return a new change object internally configured not to normalize when its change methods are called?So instead of:
It could be:
But, then, in that case is it not mutating the change object that ultimately gets applied? If it has to be the original change throughout the rule, maybe something semantically along the lines of:
That almost looks like a context manager. Is there syntax for that in js?
It definitely wouldn’t feel too magical to me to have normalization always disabled inside schema rules, if there were a way to still have the nodes undergo internal normalization after the fact. Is that possible? Maybe there would be a way to collect keys where
normalizeNodeByKey
was called within a schema rule, then attempt to normalize those keys after the rule normalization is finished? Not sure if that could get too weird with the rule normalization already having performed its own changes.