Flush queued IDE writes and restart validation after host revision changes
This commit is contained in:
@@ -554,6 +554,11 @@ public final class DesignerPane extends BorderPane implements AutoCloseable {
|
||||
|
||||
private void load(DocumentSnapshot value) {
|
||||
if (closed) return;
|
||||
// A newer host revision can have identical text (edit/revert or native reload).
|
||||
// Its predecessor's validation reply will be rejected by revision, so it must
|
||||
// not leave an in-flight marker that absorbs every subsequent render request.
|
||||
if (draft == null || draft.revision() != value.revision() || !draft.text().equals(value.text()))
|
||||
invalidateBindings("Document synchronized; target validation outdated.");
|
||||
loading = true;
|
||||
layoutPasses = 0;
|
||||
canvasCommitQueued = false;
|
||||
@@ -635,6 +640,9 @@ public final class DesignerPane extends BorderPane implements AutoCloseable {
|
||||
report(error);
|
||||
} finally {
|
||||
loading = false;
|
||||
// The change debounce may already have fired against the previous draft.
|
||||
// Render only after the authoritative revision and its projection agree.
|
||||
if (projection != null && examples.getValue() != null) resize.playFromStart();
|
||||
if (pendingSourceOffset != null) {
|
||||
int offset = pendingSourceOffset;
|
||||
pendingSourceOffset = null;
|
||||
|
||||
@@ -1604,7 +1604,72 @@ public final class ProjectionHostChecks {
|
||||
await(() -> fx(() -> source(pane).getText().equals(original)));
|
||||
}
|
||||
|
||||
private static Object field(DesignerPane pane, String name) throws Exception {
|
||||
var field = DesignerPane.class.getDeclaredField(name);
|
||||
field.setAccessible(true);
|
||||
return field.get(pane);
|
||||
}
|
||||
|
||||
/** Force a host revision to arrive after validation starts, with identical final text. */
|
||||
public static void renderRevisionRace(DesignerPane pane, DocumentSession document)
|
||||
throws Exception {
|
||||
String original = document.snapshot().toCompletableFuture().get().text();
|
||||
var poll = (javafx.animation.Timeline) field(pane, "poll");
|
||||
var resize = (javafx.animation.PauseTransition) field(pane, "resize");
|
||||
fx(
|
||||
() -> {
|
||||
poll.stop();
|
||||
resize.stop();
|
||||
return null;
|
||||
});
|
||||
try {
|
||||
set(document, original + "<!-- transient external edit -->");
|
||||
set(document, original);
|
||||
long revision = document.snapshot().toCompletableFuture().get().revision();
|
||||
fx(
|
||||
() -> {
|
||||
resize.stop();
|
||||
pane.render();
|
||||
check(original.equals(field(pane, "validatingSource")), "Validation was not in flight");
|
||||
// Deliver the real host-poll callback before the worker validation reply.
|
||||
poll.getKeyFrames().getFirst().getOnFinished().handle(new javafx.event.ActionEvent());
|
||||
return null;
|
||||
});
|
||||
await(() -> fx(() -> ((DocumentSnapshot) field(pane, "draft")).revision() == revision));
|
||||
long deadline = System.nanoTime() + TimeUnit.SECONDS.toNanos(10);
|
||||
boolean rendered = false;
|
||||
while (System.nanoTime() < deadline) {
|
||||
rendered =
|
||||
fx(
|
||||
() ->
|
||||
List.of("card", "second").stream()
|
||||
.allMatch(
|
||||
id -> {
|
||||
var region = (SnapshotRegion) object(pane, id).getSceneGraphObject();
|
||||
return region.image() != null
|
||||
&& region.statusText().equals("Target runtime");
|
||||
}));
|
||||
if (rendered) break;
|
||||
Thread.sleep(25);
|
||||
}
|
||||
check(rendered, "Host revision stranded target validation/rendering");
|
||||
check(
|
||||
document.snapshot().toCompletableFuture().get().text().equals(original),
|
||||
"Render edited source");
|
||||
System.out.println(
|
||||
"PASS host revision during validation: identical text, fresh target pixels, no extra"
|
||||
+ " action");
|
||||
} finally {
|
||||
fx(
|
||||
() -> {
|
||||
poll.playFromStart();
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static void run(DesignerPane pane, DocumentSession document) throws Exception {
|
||||
renderRevisionRace(pane, document);
|
||||
String original = document.snapshot().toCompletableFuture().get().text();
|
||||
// The same real application, now with nested, fully-qualified Component declarations.
|
||||
String nested =
|
||||
|
||||
Reference in New Issue
Block a user