[gjs: 1/2] Make GFileEnumerator iterable and async iterable




commit 3b1eee40e92eb0445f08731b0d58807375f5413c
Author: Sonny Piers <sonny fastmail net>
Date:   Sun Aug 7 01:45:17 2022 +0200

    Make GFileEnumerator iterable and async iterable

 installed-tests/js/testGio.js | 30 ++++++++++++++++++++++
 modules/core/overrides/Gio.js | 60 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 90 insertions(+)
---
diff --git a/installed-tests/js/testGio.js b/installed-tests/js/testGio.js
index 0f315b7b8..fc94bb587 100644
--- a/installed-tests/js/testGio.js
+++ b/installed-tests/js/testGio.js
@@ -311,3 +311,33 @@ describe('Gio.add_action_entries override', function () {
         expect(() => app.add_action_entries(entries)).toThrow();
     });
 });
+
+describe('Gio.FileEnumerator overrides', function () {
+    it('iterates synchronously', function () {
+        const dir = Gio.File.new_for_path('.');
+        let count = 0;
+        for (const value of dir.enumerate_children(
+            'standard::name',
+            Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS,
+            null
+        )) {
+            expect(value).toBeInstanceOf(Gio.FileInfo);
+            count++;
+        }
+        expect(count).toBeGreaterThan(0);
+    });
+
+    it('iterates asynchronously', async function () {
+        const dir = Gio.File.new_for_path('.');
+        let count = 0;
+        for await (const value of dir.enumerate_children(
+            'standard::name',
+            Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS,
+            null
+        )) {
+            expect(value).toBeInstanceOf(Gio.FileInfo);
+            count++;
+        }
+        expect(count).toBeGreaterThan(0);
+    });
+});
diff --git a/modules/core/overrides/Gio.js b/modules/core/overrides/Gio.js
index 1dfa54e55..6303b8023 100644
--- a/modules/core/overrides/Gio.js
+++ b/modules/core/overrides/Gio.js
@@ -545,6 +545,66 @@ function _init() {
         return this.replace_contents_bytes_async(contents, etag, make_backup, flags, cancellable, callback);
     };
 
+    Gio.FileEnumerator.prototype[Symbol.iterator] = function* FileEnumeratorIterator() {
+        while (true) {
+            try {
+                const info = this.next_file(null);
+                if (info === null)
+                    break;
+                yield info;
+            } catch (err) {
+                this.close(null);
+                throw err;
+            }
+        }
+        this.close(null);
+    };
+
+    Gio.FileEnumerator.prototype[Symbol.asyncIterator] = async function* AsyncFileEnumatorIterator() {
+        const self = this;
+
+        function next() {
+            return new Promise((resolve, reject) => {
+                self.next_files_async(1, Gio.PRIORITY_DEFAULT, null, (_self, res) => {
+                    try {
+                        const files = self.next_files_finish(res);
+                        resolve(files.length === 0 ? null : files[0]);
+                    } catch (err) {
+                        reject(err);
+                    }
+                });
+            });
+        }
+
+        function close() {
+            return new Promise((resolve, reject) => {
+                self.close_async(Gio.PRIORITY_DEFAULT, null, (_self, res) => {
+                    try {
+                        resolve(self.close_finish(res));
+                    } catch (err) {
+                        reject(err);
+                    }
+                });
+            });
+        }
+
+        while (true) {
+            try {
+                // eslint-disable-next-line no-await-in-loop
+                const info = await next();
+                if (info === null)
+                    break;
+                yield info;
+            } catch (err) {
+                // eslint-disable-next-line no-await-in-loop
+                await close();
+                throw err;
+            }
+        }
+
+        return close();
+    };
+
     // Override Gio.Settings and Gio.SettingsSchema - the C API asserts if
     // trying to access a nonexistent schema or key, which is not handy for
     // shell-extension writers


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]