Codebase list gjs / c081fe5
Update upstream source from tag 'upstream/1.63.92' Update to upstream version '1.63.92' with Debian dir dee4109b12284a8e9a85d44ce5ee7a260e93b5c8 Iain Lane 4 years ago
8 changed file(s) with 340 addition(s) and 16 deletion(s). Raw diff Collapse all Expand all
0 Version 1.63.92
1 ---------------
2
3 - Closed bugs and merge requests:
4 * object: Use g_irepository_get_object_gtype_interfaces [Colin Walters, Philip
5 Chimento, #55, !52]
6 * Add -fno-semantic-interposition to -Bsymbolic-functions [Jan Alexander
7 Steffens (heftig), #303, !397]
8 * examples: add a dbus-client and dbus-service example [Andy Holmes, !398]
9 * Various GNOME Shell crashes during GC, mozjs68 regression [Jan Alexander
10 Steffens (heftig), Philip Chimento, #301, !396]
11
012 Version 1.63.91
113 ---------------
214
0 'use strict';
1
2 const GLib = imports.gi.GLib;
3 const Gio = imports.gi.Gio;
4
5
6 /*
7 * An XML DBus Interface
8 */
9 const ifaceXml = `
10 <node>
11 <interface name="org.gnome.gjs.Test">
12 <method name="SimpleMethod"/>
13 <method name="ComplexMethod">
14 <arg type="s" direction="in" name="input"/>
15 <arg type="u" direction="out" name="length"/>
16 </method>
17 <signal name="TestSignal">
18 <arg name="type" type="s"/>
19 <arg name="value" type="b"/>
20 </signal>
21 <property name="ReadOnlyProperty" type="s" access="read"/>
22 <property name="ReadWriteProperty" type="b" access="readwrite"/>
23 </interface>
24 </node>`;
25
26
27
28 // Pass the XML string to make a re-usable proxy class for an interface proxies.
29 const TestProxy = Gio.DBusProxy.makeProxyWrapper(ifaceXml);
30
31
32 let proxy = null;
33 let proxySignalId = 0;
34 let proxyPropId = 0;
35
36
37 // Watching a name on DBus. Another option is to create a proxy with the
38 // `Gio.DBusProxyFlags.DO_NOT_AUTO_START` flag and watch the `g-name-owner`
39 // property.
40 function onNameAppeared(connection, name, _owner) {
41 print(`"${name}" appeared on the session bus`);
42
43 // If creating a proxy synchronously, errors will be thrown as normal
44 try {
45 proxy = new TestProxy(
46 Gio.DBus.session,
47 'org.gnome.gjs.Test',
48 '/org/gnome/gjs/Test'
49 );
50 } catch (e) {
51 logError(e);
52 return;
53 }
54
55
56 // Proxy wrapper signals use the special functions `connectSignal()` and
57 // `disconnectSignal()` to avoid conflicting with regular GObject signals.
58 proxySignalId = proxy.connectSignal('TestSignal', (proxy_, name_, args) => {
59 print(`TestSignal: ${args[0]}, ${args[1]}`);
60 });
61
62
63 // To watch property changes, you can connect to the `g-properties-changed`
64 // GObject signal with `connect()`
65 proxyPropId = proxy.connect('g-properties-changed', (proxy_, changed, invalidated) => {
66 for (let [prop, value] of Object.entries(changed.deepUnpack()))
67 print(`Property '${prop}' changed to '${value.deepUnpack()}'`);
68
69 for (let prop of invalidated)
70 print(`Property '${prop}' invalidated`);
71 });
72
73
74 // Reading and writing properties is straight-forward
75 print(`ReadOnlyProperty: ${proxy.ReadOnlyProperty}`);
76
77 print(`ReadWriteProperty: ${proxy.ReadWriteProperty}`);
78
79 proxy.ReadWriteProperty = !proxy.ReadWriteProperty;
80 print(`ReadWriteProperty: ${proxy.ReadWriteProperty}`);
81
82
83 // Both synchronous and asynchronous functions will be generated
84 try {
85 let value = proxy.SimpleMethodSync();
86
87 print(`SimpleMethod: ${value}`);
88 } catch (e) {
89 logError(`SimpleMethod: ${e.message}`);
90 }
91
92 proxy.ComplexMethodRemote('input string', (value, error, fdList) => {
93
94 // If @error is not `null`, then an error occurred
95 if (error !== null) {
96 logError(error);
97 return;
98 }
99
100 print(`ComplexMethod: ${value}`);
101
102 // Methods that return file descriptors are fairly rare, so you should
103 // know to expect one or not.
104 if (fdList !== null) {
105 //
106 }
107 });
108 }
109
110 function onNameVanished(connection, name) {
111 print(`"${name}" vanished from the session bus`);
112
113 if (proxy !== null) {
114 proxy.disconnectSignal(proxySignalId);
115 proxy.disconnect(proxyPropId);
116 proxy = null;
117 }
118 }
119
120 let busWatchId = Gio.bus_watch_name(
121 Gio.BusType.SESSION,
122 'org.gnome.gjs.Test',
123 Gio.BusNameWatcherFlags.NONE,
124 onNameAppeared,
125 onNameVanished
126 );
127
128 // Start an event loop
129 let loop = GLib.MainLoop.new(null, false);
130 loop.run();
131
132 // Unwatching names works just like disconnecting signal handlers.
133 Gio.bus_unown_name(busWatchId);
134
135
136 /* Asynchronous Usage
137 *
138 * Below is the alternative, asynchronous usage of proxy wrappers. If creating
139 * a proxy asynchronously, you should not consider the proxy ready to use until
140 * the callback is invoked without error.
141 */
142 proxy = null;
143
144 new TestProxy(
145 Gio.DBus.session,
146 'org.gnome.gjs.Test',
147 '/org/gnome/gjs/Test',
148 (sourceObj, error) => {
149 // If @error is not `null` it will be an Error object indicating the
150 // failure. @proxy will be `null` in this case.
151 if (error !== null) {
152 logError(error);
153 return;
154 }
155
156 // At this point the proxy is initialized and you can start calling
157 // functions, using properties and so on.
158 proxy = sourceObj;
159 print(`ReadOnlyProperty: ${proxy.ReadOnlyProperty}`);
160 },
161 // Optional Gio.Cancellable object. Pass `null` if you need to pass flags.
162 null,
163 // Optional flags passed to the Gio.DBusProxy constructor
164 Gio.DBusProxyFlags.NONE
165 );
166
0 'use strict';
1
2 const GLib = imports.gi.GLib;
3 const Gio = imports.gi.Gio;
4
5
6 /*
7 * An XML DBus Interface
8 */
9 const ifaceXml = `
10 <node>
11 <interface name="org.gnome.gjs.Test">
12 <method name="SimpleMethod"/>
13 <method name="ComplexMethod">
14 <arg type="s" direction="in" name="input"/>
15 <arg type="u" direction="out" name="length"/>
16 </method>
17 <signal name="TestSignal">
18 <arg name="type" type="s"/>
19 <arg name="value" type="b"/>
20 </signal>
21 <property name="ReadOnlyProperty" type="s" access="read"/>
22 <property name="ReadWriteProperty" type="b" access="readwrite"/>
23 </interface>
24 </node>`;
25
26
27 // An example of the service-side implementation of the above interface.
28 class Service {
29
30 constructor() {
31 this.dbus = Gio.DBusExportedObject.wrapJSObject(ifaceXml, this);
32 }
33
34 // Properties
35 get ReadOnlyProperty() {
36 return 'a string';
37 }
38
39 get ReadWriteProperty() {
40 if (this._readWriteProperty === undefined)
41 return false;
42
43 return this._readWriteProperty;
44 }
45
46 set ReadWriteProperty(value) {
47 if (this.ReadWriteProperty !== value) {
48 this._readWriteProperty = value;
49
50 // Emitting property changes over DBus
51 this.dbus.emit_property_changed(
52 'ReadWriteProperty',
53 new GLib.Variant('b', value)
54 );
55 }
56 }
57
58 // Methods
59 SimpleMethod() {
60 print('SimpleMethod() invoked');
61 }
62
63 ComplexMethod(input) {
64 print(`ComplexMethod() invoked with "${input}"`);
65
66 return input.length;
67 }
68
69 // Signals
70 emitTestSignal() {
71 this.dbus.emit_signal(
72 'TestSignal',
73 new GLib.Variant('(sb)', ['string', false])
74 );
75 }
76 }
77
78
79 // Once you've created an instance of your service, you will want to own a name
80 // on the bus so clients can connect to it.
81 let serviceObj = new Service();
82 let serviceSignalId = 0;
83
84
85 function onBusAcquired(connection, _name) {
86 // At this point you have acquired a connection to the bus, and you should
87 // export your interfaces now.
88 serviceObj.dbus.export(connection, '/org/gnome/gjs/Test');
89 }
90
91 function onNameAcquired(_connection, _name) {
92 // Clients will typically start connecting and using your interface now.
93
94 // Emit the TestSignal every few seconds
95 serviceSignalId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 3, () => {
96 serviceObj.emitTestSignal();
97
98 return GLib.SOURCE_CONTINUE;
99 });
100 }
101
102 function onNameLost(_connection, _name) {
103 // Clients will know not to call methods on your interface now. Usually this
104 // callback will only be invoked if you try to own a name on DBus that
105 // already has an owner.
106
107 // Stop emitting the test signal
108 if (serviceSignalId > 0) {
109 GLib.Source.remove(serviceSignalId);
110 serviceSignalId = 0;
111 }
112 }
113
114 let ownerId = Gio.bus_own_name(
115 Gio.BusType.SESSION,
116 'org.gnome.gjs.Test',
117 Gio.BusNameOwnerFlags.NONE,
118 onBusAcquired,
119 onNameAcquired,
120 onNameLost
121 );
122
123
124 // Start an event loop
125 let loop = GLib.MainLoop.new(null, false);
126 loop.run();
127
128 // Unowning names works just like disconnecting, but note that `onNameLost()`
129 // will not be invoked in this case.
130 Gio.bus_unown_name(ownerId);
131
132 if (serviceSignalId > 0) {
133 GLib.Source.remove(serviceSignalId);
134 serviceSignalId = 0;
135 }
136
666666 canonicalize_key(canonical_name);
667667 }
668668
669 GjsAutoFree<GType> interfaces = g_type_interfaces(m_gtype, &n_interfaces);
669 GIInterfaceInfo** interfaces;
670 g_irepository_get_object_gtype_interfaces(nullptr, m_gtype, &n_interfaces,
671 &interfaces);
670672
671673 /* Fallback to GType system for non custom GObjects with no GI information
672674 */
678680 return lazy_define_gobject_property(cx, obj, id, resolved, name);
679681
680682 for (i = 0; i < n_interfaces; i++) {
681 if (!G_TYPE_IS_CLASSED(interfaces[i]))
683 GType iface_gtype =
684 g_registered_type_info_get_g_type(interfaces[i]);
685 if (!G_TYPE_IS_CLASSED(iface_gtype))
682686 continue;
683687
684 GjsAutoTypeClass<GObjectClass> iclass(interfaces[i]);
688 GjsAutoTypeClass<GObjectClass> iclass(iface_gtype);
685689
686690 if (g_object_class_find_property(iclass, canonical_name))
687691 return lazy_define_gobject_property(cx, obj, id, resolved, name);
689693 }
690694
691695 for (i = 0; i < n_interfaces; i++) {
692 GjsAutoInterfaceInfo iface_info =
693 g_irepository_find_by_gtype(nullptr, interfaces[i]);
694 if (!iface_info)
695 continue;
696
696 GIInterfaceInfo* iface_info = interfaces[i];
697697 GjsAutoFunctionInfo method_info =
698698 g_interface_info_find_method(iface_info, name);
699699 if (method_info) {
881881
882882 /**
883883 * Search through any interfaces implemented by the GType;
884 * this could be done better. See
885 * https://bugzilla.gnome.org/show_bug.cgi?id=632922
884 * See https://bugzilla.gnome.org/show_bug.cgi?id=632922
885 * for background on why we need to do this.
886886 */
887887 if (!method_info)
888888 return resolve_no_info(context, obj, id, resolved, name,
10701070 ObjectInstance::gobj_dispose_notify(void)
10711071 {
10721072 m_gobj_disposed = true;
1073 unlink();
10741073 }
10751074
10761075 void ObjectInstance::iterate_wrapped_gobjects(
193193 JS_ShutDown();
194194 }
195195
196 operator bool() const {
197 return true;
198 }
196 explicit operator bool() const { return true; }
199197 };
200198
201199 static GjsInit gjs_is_inited;
228228 inline bool operator!=(std::nullptr_t) const { return !(*this == nullptr); }
229229
230230 /* Likewise the truth value does not require a read barrier */
231 inline operator bool() const { return *this != nullptr; }
231 inline explicit operator bool() const { return *this != nullptr; }
232232
233233 /* You can get a Handle<T> if the thing is rooted, so that you can use this
234234 * wrapper with stack rooting. However, you must not do this if the
0 project('gjs', 'cpp', 'c', version: '1.63.91', license: ['MIT', 'LGPL2+'],
0 project('gjs', 'cpp', 'c', version: '1.63.92', license: ['MIT', 'LGPL2+'],
11 meson_version: '>= 0.50.0',
22 default_options: ['cpp_std=c++14', 'c_std=c99', 'warning_level=2'])
33
5959 -Dbsymbolic_functions=false''')
6060 endif
6161 add_project_link_arguments('-Bsymbolic-functions', language: ['cpp', 'c'])
62 if cc.has_argument('-fno-semantic-interposition')
63 add_project_arguments('-fno-semantic-interposition', language: 'c')
64 endif
65 if cxx.has_argument('-fno-semantic-interposition')
66 add_project_arguments('-fno-semantic-interposition', language: 'cpp')
67 endif
6268 endif
6369 endif
6470
2828
2929 #include <glib-object.h>
3030 #include <glib.h>
31 #include <glib/gstdio.h> // for g_unlink
3132
3233 #include <js/CharacterEncoding.h>
3334 #include <js/RootingAPI.h>
367368 nullptr));
368369 GjsProfiler *profiler = gjs_context_get_profiler(context);
369370
371 gjs_profiler_set_filename(profiler, "dont-conflict-with-other-test.syscap");
370372 gjs_profiler_start(profiler);
371373
372374 for (size_t ix = 0; ix < 100; ix++) {
382384 }
383385
384386 gjs_profiler_stop(profiler);
387
388 if (g_unlink("dont-conflict-with-other-test.syscap") != 0)
389 g_message("Temp profiler file not deleted");
385390 }
386391
387392 int