Skip to content

Commit

Permalink
fix: Refresh locations arrays also (#20483)
Browse files Browse the repository at this point in the history
  • Loading branch information
Artur- authored Nov 18, 2024
1 parent 32d1edb commit 107f2d5
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -294,20 +294,47 @@ public static void trackAttach(Component component) {
*/
public static void refreshLocation(Location location, int offset) {
refreshLocation(createLocation, location, offset);
refreshLocations(createLocations, location, offset);
refreshLocation(attachLocation, location, offset);
refreshLocations(attachLocations, location, offset);
}

private static boolean needsUpdate(Location l, Location referenceLocation) {
return Objects.equals(l.className, referenceLocation.className)
&& l.lineNumber > referenceLocation.lineNumber;
}

private static Location updateLocation(Location l, int offset) {
return new Location(l.className, l.filename, l.methodName,
l.lineNumber + offset);
}

private static void refreshLocation(Map<Component, Location> targetRef,
Location location, int offset) {
Location referenceLocation, int offset) {
Map<Component, Location> updatedLocations = new HashMap<>();
targetRef.entrySet().stream().filter(
e -> Objects.equals(e.getValue().className, location.className))
.filter(e -> e.getValue().lineNumber > location.lineNumber)
.forEach(e -> {
Location l = e.getValue();
updatedLocations.put(e.getKey(), new Location(l.className,
l.filename, l.methodName, l.lineNumber + offset));
});
for (Component c : targetRef.keySet()) {
Location l = targetRef.get(c);
if (needsUpdate(l, referenceLocation)) {
updatedLocations.put(c, updateLocation(l, offset));
}
}

targetRef.putAll(updatedLocations);
}

private static void refreshLocations(Map<Component, Location[]> targetRef,
Location referenceLocation, int offset) {
Map<Component, Location[]> updatedLocations = new HashMap<>();
for (Component c : targetRef.keySet()) {
Location[] locations = targetRef.get(c);

for (int i = 0; i < locations.length; i++) {
if (needsUpdate(locations[i], referenceLocation)) {
locations[i] = updateLocation(locations[i], offset);
}
}
}

targetRef.putAll(updatedLocations);
}

Expand Down
80 changes: 51 additions & 29 deletions flow-server/src/test/java/com/vaadin/flow/ComponentTrackerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import com.vaadin.flow.component.HasComponents;
import com.vaadin.flow.component.Tag;
import com.vaadin.flow.component.internal.ComponentTracker;
import com.vaadin.flow.component.internal.ComponentTracker.Location;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
Expand Down Expand Up @@ -69,13 +71,8 @@ public void createLocationTracked() {
Component c2;
c2 = new Component1();

ComponentTracker.Location c1Location = ComponentTracker.findCreate(c1);
Assert.assertEquals(68, c1Location.lineNumber());
Assert.assertEquals(getClass().getName(), c1Location.className());

ComponentTracker.Location c2Location = ComponentTracker.findCreate(c2);
Assert.assertEquals(70, c2Location.lineNumber());
Assert.assertEquals(getClass().getName(), c2Location.className());
assertCreateLocation(c1, 70, getClass().getName());
assertCreateLocation(c2, 72, getClass().getName());
}

@Test
Expand All @@ -86,24 +83,18 @@ public void attachLocationTracked() {

Layout layout = new Layout(c1);

ComponentTracker.Location c1Location = ComponentTracker.findAttach(c1);
Assert.assertEquals(87, c1Location.lineNumber());
Assert.assertEquals(getClass().getName(), c1Location.className());
assertCreateLocation(c1, 80, getClass().getName());

layout.add(c2);

ComponentTracker.Location c2Location = ComponentTracker.findAttach(c2);
Assert.assertEquals(93, c2Location.lineNumber());
Assert.assertEquals(getClass().getName(), c2Location.className());
assertAttachLocation(c2, 88, getClass().getName());

// Last attach is tracked
layout.add(c3);
layout.remove(c3);
layout.add(c3);

ComponentTracker.Location c3Location = ComponentTracker.findAttach(c3);
Assert.assertEquals(102, c3Location.lineNumber());
Assert.assertEquals(getClass().getName(), c3Location.className());
assertAttachLocation(c3, 95, getClass().getName());
}

@Test
Expand All @@ -112,45 +103,54 @@ public void offsetApplied() {
Component c2 = new Component1();
Component c3 = new Component1();

ComponentTracker.Location c1Location = ComponentTracker.findCreate(c1);
Assert.assertEquals(111, c1Location.lineNumber());
Assert.assertEquals(getClass().getName(), c1Location.className());
assertCreateLocation(c1, 102, getClass().getName());

ComponentTracker.refreshLocation(c1Location, 3);
ComponentTracker.refreshLocation(ComponentTracker.findCreate(c1), 3);

ComponentTracker.Location c2Location = ComponentTracker.findCreate(c2);
Assert.assertEquals(112 + 3, c2Location.lineNumber());
Assert.assertEquals(getClass().getName(), c2Location.className());
assertCreateLocation(c2, 103 + 3, getClass().getName());

ComponentTracker.refreshLocation(c2Location, 1);
ComponentTracker.refreshLocation(ComponentTracker.findCreate(c2), 1);

ComponentTracker.Location c3Location = ComponentTracker.findCreate(c3);
Assert.assertEquals(113 + 3 + 1, c3Location.lineNumber());
Assert.assertEquals(getClass().getName(), c3Location.className());
assertCreateLocation(c3, 104 + 3 + 1, getClass().getName());
}

@Test
public void memoryIsReleased() throws Exception {
Field createLocationField = ComponentTracker.class
.getDeclaredField("createLocation");
Field createLocationsField = ComponentTracker.class
.getDeclaredField("createLocations");
Field attachLocationField = ComponentTracker.class
.getDeclaredField("attachLocation");
Field attachLocationsField = ComponentTracker.class
.getDeclaredField("attachLocations");
createLocationField.setAccessible(true);
createLocationsField.setAccessible(true);
attachLocationField.setAccessible(true);
Map<Component, StackTraceElement> createMap = (Map<Component, StackTraceElement>) createLocationField
attachLocationsField.setAccessible(true);

Map<?, ?> createMap = (Map<?, ?>) createLocationField.get(null);
Map<?, ?> attachMap = (Map<?, ?>) attachLocationField.get(null);
Map<?, ?> createLocationsMap = (Map<?, ?>) createLocationsField
.get(null);
Map<Component, StackTraceElement> attachMap = (Map<Component, StackTraceElement>) attachLocationField
Map<?, ?> attachLocationsMap = (Map<?, ?>) attachLocationsField
.get(null);
createMap.clear();
createLocationsMap.clear();
attachMap.clear();
attachLocationsMap.clear();

new Layout(new Component1());

Assert.assertEquals(2, createMap.size());
Assert.assertEquals(2, createLocationsMap.size());
Assert.assertEquals(1, attachMap.size());
Assert.assertEquals(1, attachLocationsMap.size());

Assert.assertTrue(isCleared(createMap));
Assert.assertTrue(isCleared(createLocationsMap));
Assert.assertTrue(isCleared(attachMap));
Assert.assertTrue(isCleared(attachLocationsMap));
}

private boolean isCleared(Map<?, ?> map) throws InterruptedException {
Expand All @@ -164,4 +164,26 @@ private boolean isCleared(Map<?, ?> map) throws InterruptedException {
return false;
}

private void assertCreateLocation(Component c, int lineNumber,
String name) {
ComponentTracker.Location location = ComponentTracker.findCreate(c);
Assert.assertEquals(lineNumber, location.lineNumber());
Assert.assertEquals(name, location.className());

Location[] locations = ComponentTracker.findCreateLocations(c);
Assert.assertEquals(lineNumber, locations[1].lineNumber());
Assert.assertEquals(name, locations[1].className());
}

private void assertAttachLocation(Component c, int lineNumber,
String name) {
ComponentTracker.Location location = ComponentTracker.findAttach(c);
Assert.assertEquals(lineNumber, location.lineNumber());
Assert.assertEquals(name, location.className());

Location[] locations = ComponentTracker.findAttachLocations(c);
Assert.assertEquals(lineNumber, locations[0].lineNumber());
Assert.assertEquals(name, locations[0].className());
}

}

0 comments on commit 107f2d5

Please sign in to comment.