Porting to Gnome 45

I’m trying to port a Gnome-shell app to version 45

I have the following code:

const ExtensionUtils = imports.misc.extensionUtils;  // Updated import for better practice
const Me = ExtensionUtils.getCurrentExtension();

Following the guide:
https://gjs.guide/extensions/upgrading/gnome-shell-45.html

This should be:

import * as MyModule from './MyModule.js';

However I get the following error message:

ReferenceError: Me is not defined

Keep in mind I have no experience with gnome-shell

This is simply because you haven’t declared the variable Me or assigned anything to it.

You are probably looking for Extension.lookupByURL(), which is documented in the Extension (ESModule) topic page:

import {Extension} from 'resource:///org/gnome/shell/extensions/extension.js';

let extensionObject = Extension.lookupByUUID('example@gjs.guide');

Thanks for the help @andyholmes !

This result in:

TypeError: Me is null

I’m sure I took the right UUID from the metadata.json.

This is the following code where the error occure:

this.extensionString = `[${Me.metadata.name}] `;  // String interpolation for clarity

Any help appriciated

const Me = Extension.lookupByUUID('my-uuid@example.com');

cannot be used at the toplevel.

That is because the code is evaluated while gnome-shell imports the module, and therefore before it can construct the extension object that the function returns.

If this is inside your main extension class, then

this.extensionString = `[${this.metadata.name}]`;

should work.

Thanks for your help @fmuellner !

Keep in mind that it is a long time I worked with javascript.

The first file I am porting to Gnome-shell 45 is the console file for error reporting.

So it’s not the main extension file.

I now get the error message:

Error: Console did not pass metadata to parent

Google didn’t help much.

I’m looking at the following:
https://gjs.guide/extensions/overview/anatomy.html

Here the whole file:

"use strict";
//const ExtensionUtils = imports.misc.extensionUtils;  // Updated import for better practice
//const Me = ExtensionUtils.getCurrentExtension();
import {Extension} from 'resource:///org/gnome/shell/extensions/extension.js';
//import {ExtensionPreferences} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js';

//extensionObject = Extension.lookupByUUID('gnomeemailtray46@patrick.libert.com');

//class Console {
export default class Console extends Extension {
    /**
    * @param {ExtensionMeta} metadata
    **/
    constructor(metadata) {
        super(metadata);
        this.extensionString = `[${this.metadata.name}]`; // String interpolation for clarity
        //const gettextDomain = this.metadata['gettext-domain'];
    }

    log(...args) {
        log(this.extensionString + args.join(' '));  // Ensures arguments are space-separated
    }

    error(err) {
        this.log(err.message, err.stack);  // Logs both the error message and stack trace
    }

    json(obj) {
        this.log(JSON.stringify(obj, null, 2));  // Pretty-print JSON for readability
    }
}

// Using `const` instead of `var` to declare `console`, which is now best practice
const console = new Console();

console/Console is a reserved global name/class already, so it probably thinks you are trying to construct one.

It’s common practice to call the Extension subclass something like ConsoleExtension, since that will show up in the logs as well.

@andyholmes
This seems not to be the problem.
Changed everything.
Still:

Error: ConsoleExtension did not pass metadata to parent

That’s probably a result of this line, then. This line is not necessary in your extension, but when you call new Console(<metadata should be here>).

When GNOME Shell constructs your extension, it will pass the metadata object.

The issue is that an Extension subclass is used for something that isn’t the extension entry point, and ends up not being constructed by gnome-shell.

There simply is no neat trick that someone could apply to get access to any information from the extension object before that object is constructed.

If you want to define your own console object that uses metadata from the extension, then you have several options:

  • only construct the console object when your extension is enabled
  • create it with placeholder values, and update it with the real metadata when it becomes available
  • use a getter for this.extensionString so that you can cache its value lazily (that is, when first used)

I’m sure there are other options to pick from.

I removed the line:

const console = new Console();

and it seems to work.

I’m now already 3 gnome-shell javascript files further.

Next question that I don’t find in google.

I ported:

const Soup = imports.gi.Soup;

to

import Soup from 'gi://Soup?version=3.0';

Don’t know how to port SessionAsync();

const Session = new Soup.SessionAsync();

GNOME Shell 43 Port Guide: Soup 3

1 Like