[gjs/ewlsh/interface-resolution: 6/6] (review and squash) Documentation and tests improvements
- From: Philip Chimento <pchimento src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs/ewlsh/interface-resolution: 6/6] (review and squash) Documentation and tests improvements
- Date: Fri, 15 Oct 2021 22:18:30 +0000 (UTC)
commit 766c647e14c6933e64cd76222789eaf2c83cb625
Author: Philip Chimento <philip chimento gmail com>
Date: Fri Oct 15 15:17:30 2021 -0700
(review and squash) Documentation and tests improvements
gi/object.cpp | 27 ++++++++++++++++++++-------
installed-tests/js/testGObjectInterface.js | 11 +++++++++++
2 files changed, 31 insertions(+), 7 deletions(-)
---
diff --git a/gi/object.cpp b/gi/object.cpp
index 85cc9a60..4493dd60 100644
--- a/gi/object.cpp
+++ b/gi/object.cpp
@@ -688,24 +688,37 @@ static bool interface_setter(JSContext* cx, unsigned argc, JS::Value* vp) {
static bool resolve_on_interface_prototype(JSContext* cx,
GIObjectInfo* iface_info,
JS::HandleId identifier,
- JS::HandleObject target_prototype,
+ JS::HandleObject class_prototype,
bool* found) {
GType gtype = g_base_info_get_type(iface_info);
- JS::RootedObject prototype(
+ JS::RootedObject interface_prototype(
cx, gjs_lookup_object_prototype_from_info(cx, iface_info, gtype));
- if (!prototype)
+ if (!interface_prototype)
return false;
JS::Rooted<JS::PropertyDescriptor> desc(cx);
- if (!JS_GetPropertyDescriptorById(cx, prototype, identifier, &desc))
+ if (!JS_GetPropertyDescriptorById(cx, interface_prototype, identifier,
+ &desc))
return false;
- // Check if the property exists on the prototype...
+ // If the property doesn't exist on the interface prototype, we don't need
+ // to perform this trick.
if (!desc.object()) {
*found = false;
return true;
}
+ // We are lazily defining a property on the class prototype, and a property
+ // of that name is present on the interface prototype that the class
+ // implements. Define a property of that name on the class prototype, with a
+ // getter and setter. This is so that e.g. file.dup() calls the _current_,
+ // not the original, value of Gio.File.prototype.dup(), so that it can be
+ // monkeypatched.
+ //
+ // The setter (interface_setter() above) marks the property as overridden if
+ // it is set from user code. The getter (interface_getter() above) proxies
+ // the interface prototype's property, unless it was marked as overridden.
+
JS::Rooted<JS::PropertyDescriptor> target_desc(cx, desc);
JS::RootedObject getter(
cx, JS_GetFunctionObject(js::NewFunctionByIdWithReserved(
@@ -729,7 +742,7 @@ static bool resolve_on_interface_prototype(JSContext* cx,
JS::ObjectValue(*accessor));
const GjsAtoms& atoms = GjsContextPrivate::atoms(cx);
- JS::RootedValue v_prototype(cx, JS::ObjectValue(*prototype));
+ JS::RootedValue v_prototype(cx, JS::ObjectValue(*interface_prototype));
if (!JS_SetPropertyById(cx, accessor, atoms.prototype(), v_prototype))
return false;
@@ -738,7 +751,7 @@ static bool resolve_on_interface_prototype(JSContext* cx,
target_desc.setGetterObject(getter);
target_desc.setSetterObject(setter);
- if (!JS_DefinePropertyById(cx, target_prototype, identifier, target_desc))
+ if (!JS_DefinePropertyById(cx, class_prototype, identifier, target_desc))
return false;
*found = true;
diff --git a/installed-tests/js/testGObjectInterface.js b/installed-tests/js/testGObjectInterface.js
index 2451de06..cbeaa4f9 100644
--- a/installed-tests/js/testGObjectInterface.js
+++ b/installed-tests/js/testGObjectInterface.js
@@ -330,6 +330,9 @@ describe('GObject interface', function () {
Gio.File.prototype._originalDup = 5;
expect(file._originalDup).toBe(5);
+
+ delete Gio.File.prototype._originalDup;
+ expect(file._originalDup).not.toBeDefined();
});
it('original property can be shadowed by class prototype property', function () {
@@ -347,6 +350,14 @@ describe('GObject interface', function () {
expect(Gio._LocalFilePrototype.dup).toHaveBeenCalled();
expect(Gio.File.prototype.dup).not.toHaveBeenCalled();
});
+
+ it('shadowed property can be restored', function () {
+ Gio._LocalFilePrototype.dup = 5;
+ expect(file.dup).toBe(5);
+
+ delete Gio._LocalFilePrototype.dup;
+ expect(file.dup).toBeInstanceOf(Function);
+ });
});
});
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]