@@ -4,6 +4,7 @@ const Cinnamon = imports.gi.Cinnamon;
44const Clutter = imports . gi . Clutter ;
55const Cogl = imports . gi . Cogl ;
66const Gio = imports . gi . Gio ;
7+ const Gir = imports . gi . GIRepository ;
78const GLib = imports . gi . GLib ;
89const GObject = imports . gi . GObject ;
910const Lang = imports . lang ;
@@ -39,14 +40,24 @@ var commandHeader = 'const Clutter = imports.gi.Clutter; ' +
3940const HISTORY_KEY = 'looking-glass-history' ;
4041
4142/* fake types for special cases:
42- * -"array": objects that pass Array.isArray() and should only show enumerable properties
43- * -"boxedproto": boxed prototypes throw an error on property access
44- * -"importer": objects that load modules on property access
43+ * -"array": Array() - should only show enumerable properties
44+ * -"gobject": gobject instance proxy - inspected via GIRepository
45+ * -"gboxed": gboxed instance proxy - inspected via GIRepository
46+ * -"prototype": prototypes for gobjects and gboxed objects - not inspectable
47+ * -"importer": file importers - load modules on property access, not inspectable
4548 */
4649
50+
51+ // matches gi tostring patterns
52+ const GI_RE = / ^ \[ ( b o x e d | o b j e c t ) ( i n s t a n c e | p r o t o t y p e ) (?: p r o x y | o f ) G I N a m e : ( [ \w . ] + ) [ ^ \r \n ] + \] $ / ;
53+
54+ // matches known importers
55+ const IMPORT_RE = / ^ \[ (?: G j s F i l e I m p o r t e r \w + | o b j e c t G j s M o d u l e g i ) \] $ / ;
56+
4757// returns [typeString, valueString] for any object
4858function getObjInfo ( o ) {
4959 let type , value ;
60+
5061 if ( o === null )
5162 type = "null" ;
5263 else if ( o === undefined )
@@ -55,28 +66,34 @@ function getObjInfo(o) {
5566 if ( type ) {
5667 value = "[" + type + "]" ;
5768 } else {
58- // try to detect importers via their string representation
59- try {
60- value = o . toString ( ) ;
61- } catch ( e ) {
62- if ( e . message . includes ( "not an object instance - cannot convert to GObject*" ) ) {
63- // work around Clutter.Actor.prototype.toString override not handling being
64- // called with the prototype itself as 'this'
65- value = GObject . Object . prototype . toString . call ( o ) ;
66- } else {
69+ // try to detect detailed type via their string representation
70+ if ( o instanceof GObject . Object ) {
71+ // this works around Clutter.Actor.prototype.toString overrides
72+ value = GObject . Object . prototype . toString . call ( o ) ;
73+ } else {
74+ try {
75+ value = o . toString ( ) ;
76+ } catch ( e ) {
6777 value = "[error getting value]" ;
6878 }
6979 }
7080
7181 type = typeof ( o ) ;
72- if ( type == "object" ) {
73- if ( value . startsWith ( "[GjsFileImporter" )
74- || value . startsWith ( "[object GjsModule gi" ) ) {
82+ if ( type === "object" ) {
83+ let matches = IMPORT_RE . test ( value ) ;
84+ if ( matches ) {
7585 type = "importer" ;
76- } else if ( value . startsWith ( "[boxed prototype" ) ) {
77- type = "boxedproto" ;
78- } else if ( Array . isArray ( o ) ) {
79- type = "array" ;
86+ } else {
87+ matches = GI_RE . exec ( value ) ;
88+ if ( matches ) {
89+ if ( matches [ 2 ] === "prototype" ) {
90+ type = "prototype" ;
91+ } else {
92+ type = `g${ matches [ 1 ] } ` ;
93+ }
94+ } else if ( Array . isArray ( o ) ) {
95+ type = "array" ;
96+ }
8097 }
8198 }
8299
@@ -90,10 +107,23 @@ function getObjInfo(o) {
90107
91108// returns an array of dictionaries conforming to the Inspect dbus schema
92109function getObjKeysInfo ( obj ) {
110+ let keys ;
93111 let [ type , ] = getObjInfo ( obj ) ;
94- if ( ! [ "array" , "object" ] . includes ( type ) )
112+ if ( [ "gobject" , "gboxed" ] . includes ( type ) )
113+ keys = _giObjectGetKeys ( obj , type ) ;
114+ else if ( [ "array" , "object" ] . includes ( type ) )
115+ keys = _jsObjectGetKeys ( obj , type ) ;
116+ else
95117 return [ ] ;
96118
119+ return keys . map ( ( k ) => {
120+ let [ t , v ] = getObjInfo ( obj [ k ] ) ;
121+ return { name : k . toString ( ) , type : t , value : v , shortValue : "" } ;
122+ } ) ;
123+ }
124+
125+ // get list of keys for js objects
126+ function _jsObjectGetKeys ( obj , type ) {
97127 let keys = new Set ( ) ;
98128 let curProto = obj ;
99129
@@ -112,11 +142,60 @@ function getObjKeysInfo(obj) {
112142 curProto = Object . getPrototypeOf ( curProto ) ;
113143 }
114144
145+ return Array . from ( keys ) ;
146+ }
115147
116- return Array . from ( keys ) . map ( ( k ) => {
117- let [ t , v ] = getObjInfo ( obj [ k ] ) ;
118- return { name : k . toString ( ) , type : t , value : v , shortValue : "" } ;
119- } ) ;
148+ // get list of keys for gboxed and gobject
149+ function _giObjectGetKeys ( obj , type ) {
150+ let baseInfo = Gir . Repository . get_default ( ) . find_by_gtype ( obj . constructor . $gtype ) ;
151+ if ( type === "gboxed" )
152+ return _giStructInfoGetKeys ( baseInfo ) ;
153+ else if ( type === "gobject" )
154+ return _giObjectInfoGetKeys ( baseInfo ) ;
155+ else
156+ return [ ] ;
157+ }
158+
159+ // get a list of fields and methods for a gi struct info
160+ function _giStructInfoGetKeys ( info ) {
161+ let keys = [ ] ;
162+ while ( info ) {
163+ let n = Gir . struct_info_get_n_fields ( info ) ;
164+ for ( let i = 0 ; i < n ; i ++ )
165+ keys . push ( Gir . struct_info_get_field ( info , i ) . get_name ( ) ) ;
166+
167+ n = Gir . struct_info_get_n_methods ( info ) ;
168+ for ( let i = 0 ; i < n ; i ++ )
169+ keys . push ( Gir . struct_info_get_method ( info , i ) . get_name ( ) ) ;
170+
171+ info = Gir . object_info_get_parent ( info ) ;
172+ }
173+ return keys ;
174+ }
175+
176+ // get a list of fields and methods for a gi object info
177+ function _giObjectInfoGetKeys ( info ) {
178+ let keys = [ ] ;
179+ while ( info ) {
180+ let n = Gir . object_info_get_n_constants ( info ) ;
181+ for ( let i = 0 ; i < n ; i ++ )
182+ keys . push ( Gir . object_info_get_constant ( info , i ) . get_name ( ) ) ;
183+
184+ n = Gir . object_info_get_n_properties ( info ) ;
185+ for ( let i = 0 ; i < n ; i ++ ) {
186+ let propInfo = Gir . object_info_get_property ( info , i ) ;
187+ let flags = Gir . property_info_get_flags ( propInfo ) ;
188+ if ( ( flags & GObject . ParamFlags . READABLE ) === GObject . ParamFlags . READABLE )
189+ keys . push ( propInfo . get_name ( ) ) ;
190+ }
191+
192+ n = Gir . object_info_get_n_methods ( info ) ;
193+ for ( let i = 0 ; i < n ; i ++ )
194+ keys . push ( Gir . object_info_get_method ( info , i ) . get_name ( ) ) ;
195+
196+ info = Gir . object_info_get_parent ( info ) ;
197+ }
198+ return keys ;
120199}
121200
122201// always returns an object we can give back to melange.
0 commit comments