diff options
author | Philip Chimento <philip.chimento@gmail.com> | 2022-08-10 05:13:14 +0000 |
---|---|---|
committer | Philip Chimento <philip.chimento@gmail.com> | 2022-08-10 05:13:14 +0000 |
commit | 2a1930b0ccc47bbd550e6cee453ca395e7496b10 (patch) | |
tree | 6b1de07fdd8047cec79df08f47f4692c0e2e2db9 | |
parent | 8bc3a8969f4a9c36a888121166abb96f71bce624 (diff) | |
parent | 0a28bf36b1fb073f4b01400a57d88dbd75f8c8f3 (diff) | |
download | gjs-2a1930b0ccc47bbd550e6cee453ca395e7496b10.tar.gz |
Merge branch '496-set-attribute' into 'master'
Gio: Add overrides for File.set_attribute and FileInfo.set_attribute
Closes #496
See merge request GNOME/gjs!788
-rw-r--r-- | installed-tests/js/testGio.js | 79 | ||||
-rw-r--r-- | modules/core/overrides/Gio.js | 61 |
2 files changed, 140 insertions, 0 deletions
diff --git a/installed-tests/js/testGio.js b/installed-tests/js/testGio.js index fc94bb58..c2281fae 100644 --- a/installed-tests/js/testGio.js +++ b/installed-tests/js/testGio.js @@ -341,3 +341,82 @@ describe('Gio.FileEnumerator overrides', function () { expect(count).toBeGreaterThan(0); }); }); + +describe('Non-introspectable file attribute overrides', function () { + let numExpectedWarnings, file, info; + const flags = [Gio.FileQueryInfoFlags.NONE, null]; + + function expectWarnings(count) { + numExpectedWarnings = count; + for (let c = 0; c < count; c++) { + GLib.test_expect_message('Gjs', GLib.LogLevelFlags.LEVEL_WARNING, + '*not introspectable*'); + } + } + + function assertWarnings(testName) { + for (let c = 0; c < numExpectedWarnings; c++) { + GLib.test_assert_expected_messages_internal('Gjs', 'testGio.js', 0, + `test Gio.${testName}`); + } + numExpectedWarnings = 0; + } + + beforeEach(function () { + numExpectedWarnings = 0; + [file] = Gio.File.new_tmp('XXXXXX'); + info = file.query_info('standard::*', ...flags); + }); + + it('invalid means unsetting the attribute', function () { + expectWarnings(2); + expect(() => + file.set_attribute('custom::remove', Gio.FileAttributeType.INVALID, null, ...flags)) + .toThrowError(/not introspectable/); + expect(() => info.set_attribute('custom::remove', Gio.FileAttributeType.INVALID)).not.toThrow(); + assertWarnings(); + }); + + it('works for boolean', function () { + expectWarnings(2); + expect(() => + file.set_attribute(Gio.FILE_ATTRIBUTE_STANDARD_IS_HIDDEN, Gio.FileAttributeType.BOOLEAN, false, ...flags)) + .toThrowError(/not introspectable/); + expect(() => info.set_attribute(Gio.FILE_ATTRIBUTE_STANDARD_IS_HIDDEN, Gio.FileAttributeType.BOOLEAN, false)) + .not.toThrow(); + assertWarnings(); + }); + + it('works for uint32', function () { + expectWarnings(2); + expect(() => file.set_attribute(Gio.FILE_ATTRIBUTE_TIME_MODIFIED_USEC, Gio.FileAttributeType.UINT32, 123456, ...flags)) + .not.toThrow(); + expect(() => info.set_attribute(Gio.FILE_ATTRIBUTE_TIME_MODIFIED_USEC, Gio.FileAttributeType.UINT32, 654321)) + .not.toThrow(); + assertWarnings(); + }); + + it('works for uint64', function () { + expectWarnings(2); + expect(() => file.set_attribute(Gio.FILE_ATTRIBUTE_TIME_MODIFIED, Gio.FileAttributeType.UINT64, Date.now() / 1000, ...flags)) + .not.toThrow(); + expect(() => info.set_attribute(Gio.FILE_ATTRIBUTE_TIME_MODIFIED, Gio.FileAttributeType.UINT64, Date.now() / 1000)) + .not.toThrow(); + assertWarnings(); + }); + + it('works for object', function () { + expectWarnings(2); + const icon = Gio.ThemedIcon.new_from_names(['list-add-symbolic']); + expect(() => + file.set_attribute(Gio.FILE_ATTRIBUTE_STANDARD_ICON, Gio.FileAttributeType.OBJECT, icon, ...flags)) + .toThrowError(/not introspectable/); + expect(() => info.set_attribute(Gio.FILE_ATTRIBUTE_STANDARD_ICON, Gio.FileAttributeType.OBJECT, icon)) + .not.toThrow(); + assertWarnings(); + }); + + afterEach(function () { + file.delete_async(GLib.PRIORITY_DEFAULT, null, (obj, res) => obj.delete_finish(res)); + }); +}); diff --git a/modules/core/overrides/Gio.js b/modules/core/overrides/Gio.js index 6303b802..37df69d9 100644 --- a/modules/core/overrides/Gio.js +++ b/modules/core/overrides/Gio.js @@ -462,6 +462,14 @@ function _promisify(proto, asyncFunc, finishFunc = undefined) { }; } +function _notIntrospectableError(funcName, replacement) { + return new Error(`${funcName} is not introspectable. Use ${replacement} instead.`); +} + +function _warnNotIntrospectable(funcName, replacement) { + logError(_notIntrospectableError(funcName, replacement)); +} + function _init() { Gio = this; @@ -545,6 +553,59 @@ function _init() { return this.replace_contents_bytes_async(contents, etag, make_backup, flags, cancellable, callback); }; + // Best-effort attempt to replace set_attribute(), which is not + // introspectable due to the pointer argument + Gio.File.prototype.set_attribute = function set_attribute(attribute, type, value, flags, cancellable) { + _warnNotIntrospectable('Gio.File.prototype.set_attribute', 'set_attribute_{type}'); + + switch (type) { + case Gio.FileAttributeType.STRING: + return this.set_attribute_string(attribute, value, flags, cancellable); + case Gio.FileAttributeType.BYTE_STRING: + return this.set_attribute_byte_string(attribute, value, flags, cancellable); + case Gio.FileAttributeType.UINT32: + return this.set_attribute_uint32(attribute, value, flags, cancellable); + case Gio.FileAttributeType.INT32: + return this.set_attribute_int32(attribute, value, flags, cancellable); + case Gio.FileAttributeType.UINT64: + return this.set_attribute_uint64(attribute, value, flags, cancellable); + case Gio.FileAttributeType.INT64: + return this.set_attribute_int64(attribute, value, flags, cancellable); + case Gio.FileAttributeType.INVALID: + case Gio.FileAttributeType.BOOLEAN: + case Gio.FileAttributeType.OBJECT: + case Gio.FileAttributeType.STRINGV: + throw _notIntrospectableError('This attribute type', 'Gio.FileInfo'); + } + }; + + Gio.FileInfo.prototype.set_attribute = function set_attribute(attribute, type, value) { + _warnNotIntrospectable('Gio.FileInfo.prototype.set_attribute', 'set_attribute_{type}'); + + switch (type) { + case Gio.FileAttributeType.INVALID: + return this.remove_attribute(attribute); + case Gio.FileAttributeType.STRING: + return this.set_attribute_string(attribute, value); + case Gio.FileAttributeType.BYTE_STRING: + return this.set_attribute_byte_string(attribute, value); + case Gio.FileAttributeType.BOOLEAN: + return this.set_attribute_boolean(attribute, value); + case Gio.FileAttributeType.UINT32: + return this.set_attribute_uint32(attribute, value); + case Gio.FileAttributeType.INT32: + return this.set_attribute_int32(attribute, value); + case Gio.FileAttributeType.UINT64: + return this.set_attribute_uint64(attribute, value); + case Gio.FileAttributeType.INT64: + return this.set_attribute_int64(attribute, value); + case Gio.FileAttributeType.OBJECT: + return this.set_attribute_object(attribute, value); + case Gio.FileAttributeType.STRINGV: + return this.set_attribute_stringv(attribute, value); + } + }; + Gio.FileEnumerator.prototype[Symbol.iterator] = function* FileEnumeratorIterator() { while (true) { try { |