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

Content Model: Potential perf improvement in getFormatState #2187

Merged
merged 3 commits into from
Nov 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -57,37 +57,34 @@ export function reducedModelChildProcessor(
parent: ParentNode,
context: FormatStateContext
) {
const selectionRootNode = getSelectionRootNode(context.selection);

if (selectionRootNode) {
if (!context.nodeStack) {
context.nodeStack = createNodeStack(parent, selectionRootNode);
}
if (!context.nodeStack) {
const selectionRootNode = getSelectionRootNode(context.selection);
context.nodeStack = selectionRootNode ? createNodeStack(parent, selectionRootNode) : [];
}

const stackChild = context.nodeStack.pop();
const stackChild = context.nodeStack.pop();

if (stackChild) {
const [nodeStartOffset, nodeEndOffset] = getRegularSelectionOffsets(context, parent);
if (stackChild) {
const [nodeStartOffset, nodeEndOffset] = getRegularSelectionOffsets(context, parent);

// If selection is not on this node, skip getting node index to save some time since we don't need it here
const index =
nodeStartOffset >= 0 || nodeEndOffset >= 0 ? getChildIndex(parent, stackChild) : -1;
// If selection is not on this node, skip getting node index to save some time since we don't need it here
const index =
nodeStartOffset >= 0 || nodeEndOffset >= 0 ? getChildIndex(parent, stackChild) : -1;

if (index >= 0) {
handleRegularSelection(index, context, group, nodeStartOffset, nodeEndOffset);
}
if (index >= 0) {
handleRegularSelection(index, context, group, nodeStartOffset, nodeEndOffset);
}

processChildNode(group, stackChild, context);
processChildNode(group, stackChild, context);

if (index >= 0) {
handleRegularSelection(index + 1, context, group, nodeStartOffset, nodeEndOffset);
}
} else {
// No child node from node stack, that means we have reached the deepest node of selection.
// Now we can use default child processor to perform full sub tree scanning for content model,
// So that all selected node will be included.
context.defaultElementProcessors.child(group, parent, context);
if (index >= 0) {
handleRegularSelection(index + 1, context, group, nodeStartOffset, nodeEndOffset);
}
} else {
// No child node from node stack, that means we have reached the deepest node of selection.
// Now we can use default child processor to perform full sub tree scanning for content model,
// So that all selected node will be included.
context.defaultElementProcessors.child(group, parent, context);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as getPendingFormat from '../../../lib/modelApi/format/pendingFormat';
import * as getSelectionRootNode from '../../../lib/modelApi/selection/getSelectionRootNode';
import * as retrieveModelFormatState from '../../../lib/modelApi/common/retrieveModelFormatState';
import { ContentModelFormatState } from '../../../lib/publicTypes/format/formatState/ContentModelFormatState';
import { DomToModelContext } from 'roosterjs-content-model-types';
Expand Down Expand Up @@ -180,15 +181,22 @@ describe('getFormatState', () => {
);
});
});

describe('reducedModelChildProcessor', () => {
let context: DomToModelContext;
let getSelectionRootNodeSpy: jasmine.Spy;

beforeEach(() => {
context = createDomToModelContext(undefined, {
processorOverride: {
child: reducedModelChildProcessor,
},
});

getSelectionRootNodeSpy = spyOn(
getSelectionRootNode,
'getSelectionRootNode'
).and.callThrough();
});

it('Empty DOM', () => {
Expand All @@ -201,6 +209,7 @@ describe('reducedModelChildProcessor', () => {
blockGroupType: 'Document',
blocks: [],
});
expect(getSelectionRootNodeSpy).toHaveBeenCalledTimes(1);
});

it('Single child node, with selected Node in context', () => {
Expand Down Expand Up @@ -236,6 +245,7 @@ describe('reducedModelChildProcessor', () => {
},
],
});
expect(getSelectionRootNodeSpy).toHaveBeenCalledTimes(1);
});

it('Multiple child nodes, with selected Node in context', () => {
Expand Down Expand Up @@ -277,6 +287,7 @@ describe('reducedModelChildProcessor', () => {
},
],
});
expect(getSelectionRootNodeSpy).toHaveBeenCalledTimes(1);
});

it('Multiple child nodes, with selected Node in context, with more child nodes under selected node', () => {
Expand Down Expand Up @@ -340,6 +351,7 @@ describe('reducedModelChildProcessor', () => {
},
],
});
expect(getSelectionRootNodeSpy).toHaveBeenCalledTimes(1);
});

it('Multiple layer with multiple child nodes, with selected Node in context, with more child nodes under selected node', () => {
Expand Down Expand Up @@ -399,6 +411,7 @@ describe('reducedModelChildProcessor', () => {
{ blockType: 'Paragraph', segments: [], format: {}, isImplicit: true },
],
});
expect(getSelectionRootNodeSpy).toHaveBeenCalledTimes(1);
});

it('With table, need to do format for all table cells', () => {
Expand Down Expand Up @@ -478,5 +491,6 @@ describe('reducedModelChildProcessor', () => {
},
],
});
expect(getSelectionRootNodeSpy).toHaveBeenCalledTimes(1);
});
});
Loading