Skip to content

Commit 66a1997

Browse files
committed
AEDebugging_ Fix some memory leaks
SQUASHED: AUTO-COMMIT-src-client-files.js,AUTO-COMMIT-src-client-reactive-active-expression-rewriting-active-expression-rewriting.js,AUTO-COMMIT-src-client-reactive-active-expression-rewriting-composite-key.js,AUTO-COMMIT-src-client-reactive-active-expression-rewriting-injective-map.js,AUTO-COMMIT-src-client-reactive-components-basic-aexpr-timeline.js,AUTO-COMMIT-src-client-reactive-components-rewritten-jumping-cubes.js,AUTO-COMMIT-src-components-widgets-lively-code-mirror.js,
1 parent 2a6bb4b commit 66a1997

File tree

7 files changed

+80
-35
lines changed

7 files changed

+80
-35
lines changed

src/client/files.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -261,10 +261,14 @@ export default class Files {
261261
}).then(resp => resp.status == 200);
262262
}
263263

264-
var resp = (await fetch(urlString, {method: "OPTIONS"}))
265-
if (resp.status != 200) return false
266-
var stats = await resp.json()
267-
return stats.error ? false : true
264+
try {
265+
var resp = (await fetch(urlString, {method: "OPTIONS"}))
266+
if (resp.status != 200) return false
267+
var stats = await resp.json()
268+
return stats.error ? false : true
269+
} catch (e) {
270+
return false;
271+
}
268272
}
269273

270274

src/client/reactive/active-expression-rewriting/active-expression-rewriting.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,10 @@ class Dependency {
149149

150150
untrack() {
151151
this.isTracked = false;
152+
const compKey = CompositeKeyToDependencies.getLeftFor(this);
153+
CompositeKeyToDependencies.removeRight(this);
152154
HooksToDependencies.disconnectAllForDependency(this);
155+
ContextAndIdentifierCompositeKey.remove(compKey);
153156
}
154157

155158
contextIdentifierValue() {
@@ -494,17 +497,18 @@ const HooksToDependencies = {
494497
},
495498

496499
disconnectAllForDependency(dep) {
497-
this._hooksToDeps.removeAllLeftFor(dep);
498-
499500
// Track affected files
500501
for (const hook of HooksToDependencies.getHooksForDep(dep)) {
502+
hook.untrack();
501503
hook.getLocations().then(locations => DebuggingCache.updateFiles(locations.map(loc => loc.file)));
502504
}
503505
for (const ae of DependenciesToAExprs.getAExprsForDep(dep)) {
504506
if (ae.meta().has("location")) {
505507
DebuggingCache.updateFiles([ae.meta().get("location").file]);
506508
}
507509
}
510+
511+
this._hooksToDeps.removeAllLeftFor(dep);
508512
},
509513

510514
getDepsForHook(hook) {
@@ -580,6 +584,8 @@ class Hook {
580584
this.locations = await Promise.all(this.locations);
581585
return this.locations;
582586
}
587+
588+
untrack() {}
583589

584590
notifyDependencies(location) {
585591
HooksToDependencies.getDepsForHook(this).forEach(dep => dep.notifyAExprs(location));
@@ -605,6 +611,10 @@ class SourceCodeHook extends Hook {
605611
const compKey = ContextAndIdentifierCompositeKey.for(context, identifier);
606612
return CompositeKeyToSourceCodeHook.getRightFor(compKey);
607613
}
614+
615+
untrack() {
616+
CompositeKeyToSourceCodeHook.removeRight(this);
617+
}
608618

609619
constructor(context, identifier) {
610620
super();

src/client/reactive/active-expression-rewriting/composite-key.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,17 @@ export default class CompositeKey {
3131
return this._compositeKeyStoreReverse.get(compKey) || [];
3232
}
3333

34+
remove(compKey) {
35+
const [obj1, obj2] = this._compositeKeyStoreReverse.get(compKey);
36+
37+
const secondKeyMap = this._getByPrimaryKey(obj1);
38+
secondKeyMap.delete(obj2);
39+
if(secondKeyMap.size === 0) {
40+
this._compositeKeyStore.delete(obj1);
41+
}
42+
this._compositeKeyStoreReverse.delete(compKey);
43+
}
44+
3445
clear() {
3546
this._compositeKeyStore.clear();
3647
this._compositeKeyStoreReverse.clear();

src/client/reactive/active-expression-rewriting/injective-map.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,14 @@ export default class InjectiveMap {
2424
}
2525
return this.leftToRight.get(left);
2626
}
27+
28+
removeRight(right) {
29+
const left = this.rightToLeft.get(right);
30+
if(left) {
31+
this.leftToRight.delete(left);
32+
}
33+
this.rightToLeft.delete(right);
34+
}
2735

2836
getLeftFor(right) {
2937
return this.rightToLeft.get(right);
@@ -39,6 +47,14 @@ export default class InjectiveMap {
3947
}
4048
return this.rightToLeft.get(right);
4149
}
50+
51+
removeLeft(left) {
52+
const right = this.leftToRight.get(left);
53+
if(right) {
54+
this.rightToLeft.delete(right);
55+
}
56+
this.leftToRight.delete(left);
57+
}
4258

4359
clear() {
4460
this.leftToRight.clear();

src/client/reactive/components/basic/aexpr-timeline.js

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -53,18 +53,16 @@ export default class EventDrops extends Morph {
5353
case 'changed value':
5454
{
5555
const location = data.value.trigger;
56-
const start = { line: location.line - 1, ch: location.column };
57-
lively.openBrowser(location.source, true, start, false, undefined, true);
56+
this.openLocationInBrowser(location);
57+
5858
break;
5959
}
6060
case 'created':
6161
case 'disposed':
6262
{
6363
const ae = data.value;
6464
const location = ae.meta().get("location");
65-
const start = { line: location.start.line - 1, ch: location.start.column };
66-
const end = { line: location.end.line - 1, ch: location.end.column };
67-
lively.openBrowser(location.file, true, { start, end }, false, undefined, true);
65+
this.openLocationInBrowser(location);
6866
break;
6967
}
7068
case 'dependencies changed':
@@ -122,7 +120,7 @@ export default class EventDrops extends Morph {
122120
jQuery(this.aeOverview).on("changed.jstree", (e, data) => {
123121
this.eventsChanged();
124122
});
125-
this.ready = false;
123+
this.ready = false;
126124
jQuery(this.aeOverview).one("ready.jstree", (e, data) => {
127125
this.ready = true;
128126
});
@@ -150,10 +148,22 @@ export default class EventDrops extends Morph {
150148
});
151149
}
152150

151+
openLocationInBrowser(location) {
152+
const start = { line: location.start.line - 1, ch: location.start.column };
153+
const end = { line: location.end.line - 1, ch: location.end.column };
154+
lively.files.exists(location.file).then(exists => {
155+
if(exists) {
156+
lively.openBrowser(location.file, true, { start, end }, false, undefined, true);
157+
} else {
158+
lively.notify("Unable to find file:" + location.file);
159+
}
160+
});
161+
}
162+
153163
humanizeEventData(event) {
154164
switch (event.type) {
155165
case 'changed value':
156-
return <div>{this.humanizePosition(event.value.trigger.source, event.value.trigger.line)} <br /> <span style="color:#00AAAA">{event.value.lastValue}</span><span style="color:#00AAAA">{event.value.value}</span></div>;
166+
return <div>{this.humanizePosition(event.value.trigger.file, event.value.trigger.start.line)} <br /> <span style="color:#00AAAA">{event.value.lastValue}</span><span style="color:#00AAAA">{event.value.value}</span></div>;
157167
case 'created':
158168
case 'disposed':
159169
{
@@ -337,23 +347,17 @@ export default class EventDrops extends Morph {
337347
filterToAEs(aes) {
338348
const tree = jQuery(this.aeOverview).jstree(true);
339349
tree.deselect_all();
340-
if(this.ready) {
341-
for(const ae of aes) {
350+
if (this.ready) {
351+
for (const ae of aes) {
342352
tree.select_node(ae.timelineID + 1);
343353
}
344-
} else {
345-
this.filteredAEs = aes;
346-
jQuery(this.aeOverview).on("refresh.jstree", (e, data) => {
347-
if(this.filteredAEs) {
348-
for(const ae of this.filteredAEs) {
349-
tree.select_node(ae.timelineID + 1);
350-
}
351-
if(tree.get_node([...this.filteredAEs][0])) {
352-
this.filteredAEs = [];
353-
}
354+
} else {
355+
//This is not the best workaround, but the event callbacks do not work reliably
356+
setTimeout(() => {
357+
for (const ae of aes) {
358+
tree.select_node(ae.timelineID + 1);
354359
}
355-
});
356-
tree.refresh();
360+
}, 100);
357361
}
358362
}
359363

src/client/reactive/components/rewritten/jumping-cubes.js

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ export default class JumpingCubes extends Morph {
343343
this.buildFieldOfCubes(startingInfo);
344344

345345
// #TODO connect: this.energy <= this.cubes.sumBy('value')
346-
this.ae(() => this.cubes.sumBy('value')).dataflow(v => this.energy = v);
346+
this.registerAE(aexpr(() => this.cubes.sumBy('value'))).dataflow(v => this.energy = v);
347347

348348
const checkEnd = (color, v) => {
349349
const numCubes = this.fieldSize * this.fieldSize;
@@ -352,10 +352,10 @@ export default class JumpingCubes extends Morph {
352352
}
353353
};
354354

355-
const greenCubes = this.ae(() => this.cubes.count(cube => cube.color === 'green'));
355+
const greenCubes = this.registerAE(aexpr(() => this.cubes.count(cube => cube.color === 'green')));
356356
greenCubes.dataflow(v => this.updatePlayerWidget('green', v));
357357
greenCubes.onChange(v => checkEnd('green', v));
358-
const redCubes = this.ae(() => this.cubes.count(cube => cube.color === 'red'));
358+
const redCubes = this.registerAE(aexpr(() => this.cubes.count(cube => cube.color === 'red')));
359359
redCubes.dataflow(v => this.updatePlayerWidget('red', v));
360360
redCubes.onChange(v => checkEnd('red', v));
361361

@@ -440,12 +440,12 @@ export default class JumpingCubes extends Morph {
440440
});
441441

442442
this.cubes.forEach(cube => {
443-
this.ae(() => cube.value).dataflow(value => cube.button.innerHTML = value).dataflow(value => {
443+
this.registerAE(aexpr(() => cube.value)).dataflow(value => cube.button.innerHTML = value).dataflow(value => {
444444
if (value > cube.neighbours.length) {
445445
this.addAnimation(new Explode(cube, this));
446446
}
447447
});
448-
this.ae(() => cube.color).dataflow(value => cube.button.style.background = COLOR_MAP.get(value));
448+
this.registerAE(aexpr(() => cube.color)).dataflow(value => cube.button.style.background = COLOR_MAP.get(value));
449449
});
450450

451451
const fieldSize = this.cubes.size;
@@ -484,8 +484,7 @@ export default class JumpingCubes extends Morph {
484484
this.processQueue(clickables.sample());
485485
}
486486

487-
ae(fn) {
488-
const ae = aexpr(fn);
487+
registerAE(ae) {
489488
this.aexprs.add(ae);
490489
return ae;
491490
}

src/components/widgets/lively-code-mirror.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1526,7 +1526,8 @@ export default class LivelyCodeMirror extends HTMLElement {
15261526
const AELine = AELocation.start.line - 1;
15271527

15281528
var valueChangedEvents = ae.meta().get("events").filter(event => event.type === "changed value");
1529-
const relatedEvents = valueChangedEvents.filter(event => dependencyFile.includes(event.value.trigger.file) && event.value.trigger.start.line - 1 === dependencyLine);
1529+
debugger;
1530+
const relatedEvents = valueChangedEvents.filter(event => event.value.trigger && dependencyFile.includes(event.value.trigger.file) && event.value.trigger.start.line - 1 === dependencyLine);
15301531

15311532
if (dependencyFile.includes(this.fileURL())) {
15321533
// Dependency is in this file

0 commit comments

Comments
 (0)