Skip to content

Commit dd689f0

Browse files
committed
immortal dom nodes -- this commit actually works very well and doesn't have any issues with overlap, multiple cells with same html, etc.
... BUT! It has no strategy or technique for garbage collection! It's a big heinous memory leaker.
1 parent 87688ac commit dd689f0

File tree

6 files changed

+39
-12
lines changed

6 files changed

+39
-12
lines changed

src/packages/frontend/jupyter/output-messages/iframe.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ interface Props {
3030
sha1: string;
3131
project_id: string;
3232
cacheId?: string;
33+
index?: number;
3334
}
3435

3536
export default function IFrame(props: Props) {
@@ -41,6 +42,8 @@ export default function IFrame(props: Props) {
4142
const src = get_blob_url(props.project_id, "html", props.sha1);
4243
return (
4344
<HTML
45+
id={props.cacheId}
46+
index={props.index}
4447
value={`<iframe src="${src}" style="border:0;height:${HEIGHT};width:${WIDTH}"/>`}
4548
/>
4649
);

src/packages/frontend/jupyter/output-messages/immortal-dom-node.tsx

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ import { useCallback, useEffect, useRef } from "react";
88
import $ from "jquery";
99
import { useFrameContext } from "@cocalc/frontend/frame-editors/frame-tree/frame-context";
1010
import { useIFrameContext } from "@cocalc/frontend/jupyter/cell-list";
11+
import { sha1 } from "@cocalc/util/misc";
1112

1213
interface Props {
13-
globalKey: string;
14+
docId: string;
1415
html: string;
1516
zIndex?: number;
1617
}
@@ -35,15 +36,17 @@ const PADDING = 0;
3536
const STYLE = {} as const;
3637

3738
export default function ImmortalDomNode({
38-
globalKey,
39+
docId,
3940
html,
4041
zIndex = Z_INDEX, // todo: support changing?
4142
}: Props) {
4243
const divRef = useRef<any>(null);
4344
const intervalRef = useRef<any>(null);
44-
const { isVisible } = useFrameContext();
45+
const { isVisible, project_id, path, id } = useFrameContext();
4546
const iframeContext = useIFrameContext();
4647

48+
const globalKey = sha1(`${project_id}-${id}-${docId}-${path}-${html}`);
49+
4750
const position = useCallback(() => {
4851
// make it so elt is exactly positioned on top of divRef.current using CSS
4952
if (divRef.current == null) {
@@ -82,7 +85,6 @@ export default function ImmortalDomNode({
8285
const parent = $(iframeContext.cellListDivRef?.current)[0];
8386
if (parent != null) {
8487
const parentRect = parent.getBoundingClientRect();
85-
console.log({ parentRect, eltRect });
8688
// Calculate the overlap area
8789
const top = Math.max(0, parentRect.top - eltRect.top);
8890
// leave 30px on right so to not block scrollbar
@@ -149,8 +151,9 @@ export default function ImmortalDomNode({
149151
}, [isVisible]);
150152

151153
useEffect(() => {
152-
intervalRef.current = setInterval(position, 1000);
153-
154+
// TOOD: can we get rid of interval by using a resize observer on
155+
// this iframeContext.cellListDivRef?
156+
intervalRef.current = setInterval(position, 500);
154157
if (iframeContext.iframeOnScrolls != null) {
155158
let count = 0;
156159
iframeContext.iframeOnScrolls[globalKey] = async () => {
@@ -168,6 +171,9 @@ export default function ImmortalDomNode({
168171
position();
169172
};
170173
}
174+
position();
175+
setTimeout(position, 0);
176+
setTimeout(position, 5);
171177

172178
return () => {
173179
delete iframeContext.iframeOnScrolls?.[globalKey];

src/packages/frontend/jupyter/output-messages/message.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ interface CellOutputMessageProps {
5656
actions?: JupyterActions; // optional - not needed by most messages
5757
name?: string;
5858
id?: string; // optional, and not usually needed either; this is the id of the cell. It is needed for iframe + windowing.
59+
index?: number;
5960
trust?: boolean; // is notebook trusted by the user (if not won't eval javascript)
6061
}
6162

@@ -71,6 +72,7 @@ export const CellOutputMessage: React.FC<CellOutputMessageProps> = React.memo(
7172
name={props.name}
7273
trust={props.trust}
7374
id={props.id}
75+
index={props.index}
7476
/>
7577
);
7678
},
@@ -137,6 +139,7 @@ export const CellOutputMessages: React.FC<CellOutputMessagesProps> = React.memo(
137139
v.push(
138140
<CellOutputMessage
139141
key={n}
142+
index={n}
140143
message={mesg}
141144
project_id={project_id}
142145
directory={directory}

src/packages/frontend/jupyter/output-messages/mime-types/html.tsx

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,21 @@
11
import register from "./register";
22
//import HTML from "@cocalc/frontend/components/html-ssr";
33
import ImmortalDomNode from "../immortal-dom-node";
4-
import { sha1 } from "@cocalc/util/misc";
54

6-
const Html = ({ value }: { value: string }) => {
5+
const Html = ({
6+
value,
7+
id,
8+
index,
9+
}: {
10+
value: string;
11+
id?: string;
12+
index?: number;
13+
}) => {
714
// <HTML value={value} />
8-
15+
console.log("HTML", { id, index });
916
return (
1017
<div style={{ margin: "5px 0" }}>
11-
<ImmortalDomNode html={value} globalKey={sha1(value)} />
18+
<ImmortalDomNode html={value} docId={`${id}-${index}`} />
1219
</div>
1320
);
1421
};
Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
11
import register from "./register";
22
import IFrame from "../iframe";
33

4-
register("iframe", 7, ({ id, project_id, value }) => {
4+
register("iframe", 7, ({ id, project_id, value, index }) => {
55
if (value == null || project_id == null) {
66
return <pre>iframe must specify project_id and sha1</pre>;
77
}
8-
return <IFrame cacheId={id} sha1={value} project_id={project_id} />;
8+
return (
9+
<IFrame
10+
cacheId={id}
11+
sha1={value}
12+
project_id={project_id}
13+
index={index}
14+
/>
15+
);
916
});

src/packages/frontend/jupyter/output-messages/mime-types/register.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export interface HandlerProps {
2424
name?: string;
2525
trust?: boolean;
2626
id?: string;
27+
index?: number;
2728
}
2829

2930
type Handler = React.FC<HandlerProps>;

0 commit comments

Comments
 (0)