fix: Various compounding memory leaks in editor (#5950)
This commit is contained in:
@@ -302,6 +302,7 @@ export class Editor extends React.PureComponent<
|
|||||||
|
|
||||||
public componentWillUnmount(): void {
|
public componentWillUnmount(): void {
|
||||||
window.removeEventListener("theme-changed", this.dispatchThemeChanged);
|
window.removeEventListener("theme-changed", this.dispatchThemeChanged);
|
||||||
|
this.view.destroy();
|
||||||
this.mutationObserver?.disconnect();
|
this.mutationObserver?.disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -349,27 +350,26 @@ export class Editor extends React.PureComponent<
|
|||||||
private createNodeViews() {
|
private createNodeViews() {
|
||||||
return this.extensions.extensions
|
return this.extensions.extensions
|
||||||
.filter((extension: ReactNode) => extension.component)
|
.filter((extension: ReactNode) => extension.component)
|
||||||
.reduce((nodeViews, extension: ReactNode) => {
|
.reduce(
|
||||||
const nodeView = (
|
(nodeViews, extension: ReactNode) => ({
|
||||||
node: ProsemirrorNode,
|
|
||||||
view: EditorView,
|
|
||||||
getPos: () => number,
|
|
||||||
decorations: Decoration[]
|
|
||||||
) =>
|
|
||||||
new ComponentView(extension.component, {
|
|
||||||
editor: this,
|
|
||||||
extension,
|
|
||||||
node,
|
|
||||||
view,
|
|
||||||
getPos,
|
|
||||||
decorations,
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
...nodeViews,
|
...nodeViews,
|
||||||
[extension.name]: nodeView,
|
[extension.name]: (
|
||||||
};
|
node: ProsemirrorNode,
|
||||||
}, {});
|
view: EditorView,
|
||||||
|
getPos: () => number,
|
||||||
|
decorations: Decoration[]
|
||||||
|
) =>
|
||||||
|
new ComponentView(extension.component, {
|
||||||
|
editor: this,
|
||||||
|
extension,
|
||||||
|
node,
|
||||||
|
view,
|
||||||
|
getPos,
|
||||||
|
decorations,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
{}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private createCommands() {
|
private createCommands() {
|
||||||
|
|||||||
@@ -171,7 +171,7 @@
|
|||||||
"prosemirror-state": "^1.4.3",
|
"prosemirror-state": "^1.4.3",
|
||||||
"prosemirror-tables": "^1.3.2",
|
"prosemirror-tables": "^1.3.2",
|
||||||
"prosemirror-transform": "^1.7.3",
|
"prosemirror-transform": "^1.7.3",
|
||||||
"prosemirror-view": "^1.31.3",
|
"prosemirror-view": "^1.32.0",
|
||||||
"query-string": "^7.1.3",
|
"query-string": "^7.1.3",
|
||||||
"quoted-printable": "^1.0.1",
|
"quoted-printable": "^1.0.1",
|
||||||
"randomstring": "1.2.3",
|
"randomstring": "1.2.3",
|
||||||
|
|||||||
@@ -29,10 +29,10 @@ const Image = (props: Props) => {
|
|||||||
const [loaded, setLoaded] = React.useState(false);
|
const [loaded, setLoaded] = React.useState(false);
|
||||||
const [naturalWidth, setNaturalWidth] = React.useState(node.attrs.width);
|
const [naturalWidth, setNaturalWidth] = React.useState(node.attrs.width);
|
||||||
const [naturalHeight, setNaturalHeight] = React.useState(node.attrs.height);
|
const [naturalHeight, setNaturalHeight] = React.useState(node.attrs.height);
|
||||||
const documentBounds = useComponentSize(props.view.dom);
|
|
||||||
const containerBounds = useComponentSize(
|
const containerBounds = useComponentSize(
|
||||||
document.body.querySelector("#full-width-container")
|
document.body.querySelector("#full-width-container")
|
||||||
);
|
);
|
||||||
|
const documentBounds = props.view.dom.getBoundingClientRect();
|
||||||
const maxWidth = layoutClass
|
const maxWidth = layoutClass
|
||||||
? documentBounds.width / 3
|
? documentBounds.width / 3
|
||||||
: documentBounds.width;
|
: documentBounds.width;
|
||||||
|
|||||||
@@ -14,48 +14,44 @@ const defaultRect = {
|
|||||||
export default function useComponentSize(
|
export default function useComponentSize(
|
||||||
element: HTMLElement | null
|
element: HTMLElement | null
|
||||||
): DOMRect | typeof defaultRect {
|
): DOMRect | typeof defaultRect {
|
||||||
const [size, setSize] = useState(element?.getBoundingClientRect());
|
const [size, setSize] = useState(() => element?.getBoundingClientRect());
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const sizeObserver = new ResizeObserver((entries) => {
|
const sizeObserver = new ResizeObserver(() => {
|
||||||
entries.forEach(({ target }) => {
|
element?.dispatchEvent(new CustomEvent("resize"));
|
||||||
const rect = target?.getBoundingClientRect();
|
|
||||||
setSize((state) =>
|
|
||||||
state?.width === rect?.width &&
|
|
||||||
state?.height === rect?.height &&
|
|
||||||
state?.x === rect?.x &&
|
|
||||||
state?.y === rect?.y
|
|
||||||
? state
|
|
||||||
: rect
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (element) {
|
if (element) {
|
||||||
sizeObserver.observe(element);
|
sizeObserver.observe(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
return () => sizeObserver.disconnect();
|
return () => sizeObserver.disconnect();
|
||||||
}, [element]);
|
}, [element]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleResize = () => {
|
const handleResize = () => {
|
||||||
const rect = element?.getBoundingClientRect();
|
setSize((state: DOMRect) => {
|
||||||
setSize((state) =>
|
const rect = element?.getBoundingClientRect();
|
||||||
state?.width === rect?.width &&
|
|
||||||
state?.height === rect?.height &&
|
if (
|
||||||
state?.x === rect?.x &&
|
rect &&
|
||||||
state?.y === rect?.y
|
Math.round(state.width) === Math.round(rect.width) &&
|
||||||
? state
|
Math.round(state.height) === Math.round(rect.height) &&
|
||||||
: rect
|
Math.round(state.x) === Math.round(rect.x) &&
|
||||||
);
|
Math.round(state.y) === Math.round(rect.y)
|
||||||
|
) {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
return rect;
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
window.addEventListener("click", handleResize);
|
window.addEventListener("click", handleResize);
|
||||||
window.addEventListener("resize", handleResize);
|
window.addEventListener("resize", handleResize);
|
||||||
|
element?.addEventListener("resize", handleResize);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
window.removeEventListener("click", handleResize);
|
window.removeEventListener("click", handleResize);
|
||||||
window.removeEventListener("resize", handleResize);
|
window.removeEventListener("resize", handleResize);
|
||||||
|
element?.removeEventListener("resize", handleResize);
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -10848,10 +10848,10 @@ prosemirror-transform@^1.0.0, prosemirror-transform@^1.1.0, prosemirror-transfor
|
|||||||
dependencies:
|
dependencies:
|
||||||
prosemirror-model "^1.0.0"
|
prosemirror-model "^1.0.0"
|
||||||
|
|
||||||
prosemirror-view@^1.0.0, prosemirror-view@^1.1.0, prosemirror-view@^1.13.3, prosemirror-view@^1.27.0, prosemirror-view@^1.31.0, prosemirror-view@^1.31.3:
|
prosemirror-view@^1.0.0, prosemirror-view@^1.1.0, prosemirror-view@^1.13.3, prosemirror-view@^1.27.0, prosemirror-view@^1.31.0, prosemirror-view@^1.32.0:
|
||||||
version "1.31.3"
|
version "1.32.0"
|
||||||
resolved "https://registry.yarnpkg.com/prosemirror-view/-/prosemirror-view-1.31.3.tgz#cfe171c4e50a577526d0235d9ec757cdddf6017d"
|
resolved "https://registry.yarnpkg.com/prosemirror-view/-/prosemirror-view-1.32.0.tgz#2022538d02932c0901232d1e0430c064f79a8ea2"
|
||||||
integrity sha512-UYDa8WxRFZm0xQLXiPJUVTl6H08Fn0IUVDootA7ZlQwzooqVWnBOXLovJyyTKgws1nprfsPhhlvWgt2jo4ZA6g==
|
integrity sha512-HwW7IWgca6ehiW2PA48H/8yl0TakA0Ms5LgN5Krc97oar7GfjIKE/NocUsLe74Jq4mwyWKUNoBljE8WkXKZwng==
|
||||||
dependencies:
|
dependencies:
|
||||||
prosemirror-model "^1.16.0"
|
prosemirror-model "^1.16.0"
|
||||||
prosemirror-state "^1.0.0"
|
prosemirror-state "^1.0.0"
|
||||||
|
|||||||
Reference in New Issue
Block a user