Skip to content

Instantly share code, notes, and snippets.

@juliandescottes
Last active April 26, 2024 23:01
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save juliandescottes/169f3a57e1441542565b to your computer and use it in GitHub Desktop.
Save juliandescottes/169f3a57e1441542565b to your computer and use it in GitHub Desktop.
Devtools file loading
╔═════════════════════════════════════════════════════════════════════════════════╗
║ How to load/import a file in Firefox Devtools ? ║
╚═════════════════════════════════════════════════════════════════════════════════╝
╔════════════════════════╗
║ SYNC FILE LOADING ║
╚════════════════════════╝
┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┌───────────────────────────────┐
Is it a JSM ? │──yes──▶│ Use require() │ (see [1])
└ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ └───────────────────────────────┘
│no
┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┌───────────────────────────────┐
Is it a Service ? │──yes──▶│ Use Cc["name"].getService() │
└ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ └───────────────────────────────┘
│no
┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┌───────────────────────────────┐
Need browser │──yes──▶│ Use BrowserLoader's │
│ environment ? │ require() │ (see [2])
─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘ └───────────────────────────────┘
│no
┌────────────────────────┐
│ Use require() │ (see [1])
└────────────────────────┘
═══════════════════════════════════════════════════════════════════════════════════
╔════════════════════════╗
║ LAZY FILE LOADING ║
╚════════════════════════╝
┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┌────────────────────────────────┐
Is it a JSM ? │──yes─▶│ Use loader.lazyImporter() │
└ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ └────────────────────────────────┘
│no
┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┌────────────────────────────────┐
Is it a Service ? │──yes─▶│ Use loader.lazyServiceGetter() │
└ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ └────────────────────────────────┘
│no
┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┌────────────────────────────────┐
Need browser │ │ Use BrowserLoader's │
│ environment ? ──yes─▶│ lazyRequireGetter() │ (see [2])
─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘ └────────────────────────────────┘
│no
┌────────────────────────┐
│ Use loader. │
│ lazyRequireGetter() │
└────────────────────────┘
═══════════════════════════════════════════════════════════════════════════════════
What is loader, require, lazyRequireGetter, etc... ?
Loaders
========
Two loaders are available in DevTools :
* DevToolsLoader (devtools/shared/Loader.jsm)
* BrowserLoader (devtools/client/shared/browser-loader.js)
Both provide a `require()` method to load dependencies synchronously. BrowserLoader
can load files in a browser environment (window available etc...).
They also provide various helpers for lazy loading/getting :
* `lazyRequireGetter()`: lazy load a js/jsm using the loader's require.
Dependency is loaded first time the corresponding property is accessed.
* `lazyGetter()`: helper to replace a property by the return value of a provided
callback
* `lazyImporter()`: helper to lazy load a module relying on Cu.import (not
sure how useful this is compared to lazyRequireGetter)
* `lazyServiceGetter()`: helper to lazily retrieve a Service
Depending on how the file was loaded, it may have access to the loader API directly
or not.
File loaded via require()
=========================
If the file was loaded via require(), the following globals will be available:
* require: mapped to the current loader's require. Synchronously loads a js/jsm.
* loader: NOT the loader instance, but has all the lazySomething helpers :
loader.lazyRequireGetter(), loader.lazyImporter(), etc...
You should be able to rely on the helpers above to load any dependency needed (see
chart below).
Files NOT loaded using require()
================================
In this case, `require` and `loader` will not be available straight away. The
easiest is probably to import the DevToolsLoader :
> const { loader } = Components.utils.import(
> "resource://devtools/shared/Loader.jsm", {});
This loader is an instance of `DevToolsLoader`.
If a browser environment is needed, instantiate a `BrowserLoader` instead:
> const { BrowserLoader } = Components.utils.import(
> "resource://devtools/client/shared/browser-loader.js", {});
> const browserLoader = BrowserLoader(
> "resource://{base/uri/for/browser/modules}", window);
═══════════════════════════════════════════════════════════════════════════════════
┌───────────────────────────────────────────────────────────────────────────────┐
│Note [1] │
│ │
│As explained in the introduction, `require()` is either available as a global, │
│or has to be used on a loader instance: `loader.require()`. │
└───────────────────────────────────────────────────────────────────────────────┘
┌───────────────────────────────────────────────────────────────────────────────┐
│Note [2] │
│ │
│BrowserLoader's `require` and `lazyRequireGetter`. If you are in a file or │
│module loaded via `BrowserLoader`, you can use the global require and │
│loader.lazyRequireGetter. │
│ │
│If not, a BrowserLoader has to be loaded and instantiated. │
└───────────────────────────────────────────────────────────────────────────────┘
┌───────────────────────────────────────────────────────────────────────────────┐
│Note [3]: Some other loading methods found in devtools code : │
│ │
│* Cu.import or Component.utils.import : sometimes used to load synchronously │
│js/jsm files. If a loader is already available, this can normally be replaced │
│using this loader's require() │
│ │
│* XPCOMUtils.defineLazyModuleGetter : same as loader.lazyImporter │
│* XPCOMUtils.defineLazyServiceGetter : same as loader.lazyServiceGetter │
│* XPCOMUtils.defineLazyGetter : same as loader.lazyGetter │
│ │
│Prefer the loader methods over XPCOMUtils. │
└───────────────────────────────────────────────────────────────────────────────┘
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment