Index: sdk/lib/io/directory_impl.dart |
diff --git a/sdk/lib/io/directory_impl.dart b/sdk/lib/io/directory_impl.dart |
index 5429a294ecc96ca0fb92e0f02f8c6ce5456d573e..e24636d5aacbfaa0a3d9e104cd5e38c6d2d16811 100644 |
--- a/sdk/lib/io/directory_impl.dart |
+++ b/sdk/lib/io/directory_impl.dart |
@@ -322,6 +322,9 @@ class _AsyncDirectoryLister { |
bool nextRunning = false; |
bool closed = false; |
+ var pending; |
+ var cancelCompleter; |
+ |
_AsyncDirectoryLister(String this.path, |
bool this.recursive, |
bool this.followLinks) { |
@@ -348,15 +351,15 @@ class _AsyncDirectoryLister { |
} |
void onResume() { |
- if (!nextRunning) next(); |
+ handlePending(); |
} |
- void onCancel() { |
+ onCancel() { |
canceled = true; |
// If we are active, but not requesting, close. |
- if (!nextRunning) { |
- close(); |
- } |
+ cancelCompleter = new Completer(); |
+ close(); |
+ return cancelCompleter.future; |
} |
void next() { |
@@ -364,49 +367,70 @@ class _AsyncDirectoryLister { |
close(); |
return; |
} |
+ if (nextRunning) return; |
if (id == null) return; |
- if (controller.isPaused) return; |
- assert(!nextRunning); |
+ if (pending != null) return; |
nextRunning = true; |
_Directory._newServicePort().call([_Directory.LIST_NEXT_REQUEST, id]) |
.then((result) { |
- if (result is List) { |
- assert(result.length % 2 == 0); |
- for (int i = 0; i < result.length; i++) { |
- assert(i % 2 == 0); |
- switch (result[i++]) { |
- case LIST_FILE: |
- controller.add(new File(result[i])); |
- break; |
- case LIST_DIRECTORY: |
- controller.add(new Directory(result[i])); |
- break; |
- case LIST_LINK: |
- controller.add(new Link(result[i])); |
- break; |
- case LIST_ERROR: |
- error(result[i]); |
- break; |
- case LIST_DONE: |
- close(); |
- return; |
- } |
- } |
- } else { |
- controller.addError(new DirectoryException("Internal error")); |
- } |
nextRunning = false; |
- next(); |
+ pending = result; |
+ handlePending(); |
}); |
} |
+ void handlePending() { |
+ if (canceled) { |
+ close(); |
+ return; |
+ } |
+ if (pending != null) { |
+ if (controller.isPaused) return; |
+ var result = pending; |
+ pending = null; |
+ next(); |
+ if (result is List) { |
+ assert(result.length % 2 == 0); |
+ for (int i = 0; i < result.length; i++) { |
+ assert(i % 2 == 0); |
+ switch (result[i++]) { |
+ case LIST_FILE: |
+ controller.add(new File(result[i])); |
+ break; |
+ case LIST_DIRECTORY: |
+ controller.add(new Directory(result[i])); |
+ break; |
+ case LIST_LINK: |
+ controller.add(new Link(result[i])); |
+ break; |
+ case LIST_ERROR: |
+ error(result[i]); |
+ break; |
+ case LIST_DONE: |
+ close(); |
+ return; |
+ } |
+ } |
+ } else { |
+ controller.addError(new DirectoryException("Internal error")); |
+ } |
+ } else { |
+ next(); |
+ } |
+ } |
+ |
void close() { |
+ if (nextRunning) return; // Wait for it to complete. |
if (closed) return; |
if (id == null) return; |
closed = true; |
_Directory._newServicePort().call([_Directory.LIST_STOP_REQUEST, id]) |
.then((_) { |
- controller.close(); |
+ if (canceled) { |
+ cancelCompleter.complete(); |
+ } else { |
+ controller.close(); |
+ } |
}); |
} |