DevTools/Hacking: Difference between revisions

From MozillaWiki
Jump to navigation Jump to search
(→‎Enabling DevTools Assertions: describe when assertions are not enabled)
(Update outdated link to devtools contributor docs)
 
(43 intermediate revisions by 7 users not shown)
Line 1: Line 1:
Want to hack on [[DevTools|Firefox Developer Tools]]?  You've come to the right place!  If you want more information about contributing, check out our guide for [[DevTools/GetInvolved|getting involved]].
The contents of this section have been moved to


= First Build =
https://firefox-source-docs.mozilla.org/devtools/index.html
 
Follow the instructions on [https://developer.mozilla.org/En/Simple_Firefox_build how to build Firefox].
 
(If you want to work with the very latest code, you will need to use:
 
hg clone http://hg.mozilla.org/integration/fx-team
 
Instead of:
 
hg clone http://hg.mozilla.org/mozilla-central
 
but for most purposes a mozilla-central clone is fine.)
 
For your first build, running <code>./mach build</code> should do the trick after you get the source code.  If you are going to be building a lot, you may want to set up your [https://developer.mozilla.org/en-US/docs/Configuring_Build_Options .mozconfig file].
 
== First Run ==
 
Once you have built Firefox, you can run it with
 
  $ ./mach run
 
or
 
  $ ./mach run -P development
 
What is the <code>-P development</code>?  It is a flag telling Firefox to use a different [https://support.mozilla.org/en-US/kb/profiles-where-firefox-stores-user-data profile], named "development" (this name can be anything you want).  If it does not exist the first time you run it, Firefox will open a popup and you can create a new profile with the name you passed in.  If you don't specify a profile, <code>mach</code> will create a temporary profile in the path <code><objdir>/tmp/scratch_user</code>.
 
Once this command runs, you should see a new Firefox window, called "Nightly".  You will want to make a couple of quick changes to the profile.
 
Open DevTools, and click the "Toolbox Options" gear in the top left.  Make sure the following two options are checked: '''Enable Chrome Debugging''' and '''Enable Remote Debugging'''.  These settings allow you to use the [https://developer.mozilla.org/docs/Tools/Browser_Toolbox browser toolbox] to set breakpoints inside of the DevTools code, inspect the DevTools themselves, and let you run the [https://developer.mozilla.org/en-US/docs/Tools/Scratchpad Scratchpad] in the ''Browser'' environment. 
 
[[Image:DevToolsDeveloperSettings.png|center|600px|Settings for developer tools - "Enable Chrome Debugging" and "Enable Remote Debugging"]]
 
= Developer Tools Directories Overview =
 
* '''<tt>devtools/shared</tt>''': Code shared by both the DevTools client (front-end UI) and server. If we are using any third party libraries, or importing external repositories into our tree, those libraries generally live here (eg, <tt>devtools/shared/acorn</tt>), assuming they are used by both client and server.
** '''<tt>devtools/shared/client</tt>''': Code for the DevTools [[Remote Debugging Protocol]] client.  (You may wonder why this is not in <tt>devtools/client</tt> below: it's mainly because tests in server also need access to the RDP client.)
* '''<tt>devtools/server</tt>''': Code for the DevTools [[Remote Debugging Protocol]] server and transport layer.
** '''<tt>devtools/server/actors</tt>''': [[Remote_Debugging_Protocol#Actors RDP Actors]]. Note that if you're modifying the RDP, you may need to worry about [[DevTools/Backwards_Compatibility|backwards compatibilty with older protocol implementations]].
* '''<tt>devtools/client</tt>''': Front end user interfaces for our tools.  Should be pretty obvious what is what based on the directory names and each panel we have in our toolbox.  This directory is only shipped with desktop Firefox, as opposed to other directories above, which are shipped with all Gecko products (Firefox OS, Firefox for Android, etc.)
 
For the moment, we also have few other directories used by localization (l10n) files:
 
* '''<tt>browser/locales/en-US/chrome/browser/devtools</tt>''': Strings used in the DevTools client (front-end UI)
* '''<tt>toolkit/locales/en-US/chrome/global/devtools</tt>''': Strings used in the DevTools server
 
These l10n files will soon be moved under <tt>/devtools</tt> in [https://bugzilla.mozilla.org/show_bug.cgi?id=1182722 bug 1182722].
 
= Development Workflow =
 
== Incremental Builds ==
 
Once you've already built Firefox once, and you just want to incrementally update your build with your latest DevTools changes, you can run:
 
  $ ./mach build devtools/*
 
which is much faster than your first build or clobber builds and should only take a few seconds. You can run your build the same way you did before:
 
  $ ./mach run -P development
 
Note that whenever you pull the latest changes from <tt>fx-team</tt> into your local repository, you may need to "clobber". A "clobber" is similar to a "<tt>make clean</tt>". You'll know you need to clobber when you get a big error message telling you to do a clobber build after you tried to do an incremental build. To do a clobber build, enter these commands:
 
  $ ./mach clobber
  $ ./mach build
 
== Enabling DevTools Logging ==
 
Depending on what you are working on, you may want to make some changes to your profile to enable more logging. If you type  '''<tt>about:config</tt>''' in the URL bar, click through the warning page, and search for '''<tt>devtools</tt>''' you can see some of them.
 
Add the global "dump" function to all windows which logs strings to stdout.
 
  '''browser.dom.window.dump.enabled''' = true
 
Dumps all packets sent over the remote debugging protocol to stdout (requires browser.dom.window.dump.enabled):
 
  '''devtools.debugger.log''' = true
 
Log every event notification from the EventEmitter class (toolkit/devtools/event-emitter.js) (requires browser.dom.window.dump.enabled)
 
  '''devtools.dump.emit''' = true
 
Restart the browser to apply configuration changes.
 
You may also be interested in the remote protocol inspector add-on: https://github.com/firebug/rdp-inspector/wiki
 
== Enabling DevTools Assertions ==
 
Highly recommended for DevTools hackers!
 
Add this to your '''<tt>.mozconfig</tt>''':
 
  ac_add_options --enable-debug-js-modules
 
Assert your own invariants like this:
 
  const { assert } = require("devtools/shared/DevToolsUtils");
  // ...
  assert(1 + 1 === 2, "I really hope this is true...");
 
When assertions are enabled, assertion failures are fatal, log console warnings, and throw errors.
 
When assertions are not enabled, the <tt>assert</tt> function is a no-op.
 
It also enables the "debug" builds of certain third party libraries, such as React.
 
== JavaScript Modules ==
 
=== Build Configuration ===
 
JavaScript modules are installed by our build system using <tt>moz.build</tt> files.  If you add a new JavaScript module, you'll need to update (or add) one of these files to make the build system aware of your new module.  See the example below.
 
A <tt>moz.build</tt> file must live in the same directory as the files to be installed.  Don't list files from a subdirectory in a <tt>moz.build</tt> from a parent directory.
 
Following these steps ensures that <tt>require()</tt> and <tt>resource://</tt> paths map directly to locations in the source tree, instead of being totally arbitrary.
 
Example:
 
* File: <tt>/devtools/server/actors/layout.js</tt>
* In <tt>/devtools/server/actors/moz.build</tt>:
 
  DevToolsModules(
      'layout.js'
  )
 
=== <tt>require()</tt> ===
 
Most DevTools JS code is in the form of CommonJS modules that loaded with <tt>require()</tt>.
 
To <tt>require()</tt> a file, the module ID is exactly its source tree path.
 
Example:
 
* File: <tt>/devtools/server/actors/layout.js</tt>
* Usage (prefer lazy in most cases):
** <tt>loader.lazyRequireGetter(this, "layout", "devtools/server/actors/layout")</tt>
** <tt>require("devtools/server/actors/layout")</tt>
 
=== <tt>Cu.import()</tt> ===
 
Some older DevTools JS modules use the Gecko [https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/Using "JavaScript code module"] format with the file extension <tt>.jsm</tt>.  We are trying to move away from this format, so it's unlikely you would add a new one, but you might need to import an existing one in your code.
 
These modules are loaded using <tt>Cu.import()</tt>.  To <tt>import()</tt> a file, you provide a <tt>resource://</tt> URL, which is derived directly from the source tree path.  There is a slight difference between client and server URLs because the non-client files have extra <tt>gre</tt> segment. In more detail:
 
* <tt>/devtools/client/<X></tt>: <tt>resource:///modules/devtools/client/<X></tt>
* <tt>/devtools/server/<X></tt>: <tt>resource://gre/modules/devtools/server/<X></tt>
* <tt>/devtools/shared/<X></tt>: <tt>resource://gre/modules/devtools/shared/<X></tt>
 
Example:
 
* File: <tt>/devtools/shared/Loader.jsm</tt>
* Usage:
** <tt>Cu.import("resource://gre/modules/devtools/shared/Loader.jsm")</tt>
 
Example:
 
* File: <tt>/devtools/client/framework/gDevTools.jsm</tt>
* Usage (prefer lazy in most cases):
** <tt>loader.lazyImporter(this, "gDevTools", "resource:///modules/devtools/client/framework/gDevTools.jsm")</tt>
** <tt>Cu.import("resource:///modules/devtools/client/framework/gDevTools.jsm")</tt>
 
== Chrome Content ==
 
Much of the DevTools front-end / UI is currently loaded using <tt>chrome://</tt> (meaning "browser chrome" as in the UI, no relation to the Chrome browser) URLs which allow those files to have privileged access to platform internals.  (We'd like to move away from this on the DevTools and be more like regular web sites, but most tools are using <tt>chrome://</tt> URLs for now.)
 
Chrome content is typically used to load XUL, HTML, and JS files in the UI.
 
=== Packaging ===
 
If you add a new file that should be loaded via <tt>chrome://</tt> (such as a new script file for a tool UI), you need to update a manifest file at <tt>/devtools/client/jar.mn</tt> so that it's packaged correctly.
 
Please ensure that any new files are added so their entire source tree path is part of the URL. To do so, the <tt>jar.mn</tt> entry should look like:
 
    content/<X> (<X>)
 
where <tt><X></tt> is the path to your file after removing the <tt>/devtools/client</tt> prefix.
 
Example:
 
* File: <tt>/devtools/client/webaudioeditor/models.js</tt>
* Entry: <tt>content/webaudioeditor/models.js (webaudioeditor/models.js)</tt>
 
=== Usage ===
 
Chrome content URLs almost match their source tree path, with one difference: the segment <tt>client</tt> is replaced by <tt>content</tt>.  This is a requirement of the <tt>chrome://</tt> protocol handler.
 
Example:
 
* File: <tt>/devtools/client/webaudioeditor/models.js</tt>
* Usage: <tt>chrome://devtools/content/webaudioeditor/models.js</tt>
 
For files within a single tool, consider relative URLs. They're shorter!
 
== Chrome Themes ==
 
Similar to the chrome content section above, we also use chrome themes (or <tt>skin</tt> URLs) in the DevTools UI.  These are typically used to load CSS and images.
 
=== Packaging ===
 
If you add a new file that should be loaded via <tt>chrome://</tt> (such as a new CSS file for a tool UI), you need to update a manifest file at <tt>/devtools/client/jar.mn</tt> so that it's packaged correctly.
 
Please ensure that any new files are added so their entire source tree path is part of the URL. To do so, the <tt>jar.mn</tt> entry should look like:
 
    skin/<X> (<X>)
 
where <tt><X></tt> is the path to your file after removing the <tt>/devtools/client</tt> prefix.
 
Example:
 
* File: <tt>/devtools/client/themes/images/add.svg</tt>
* Entry: <tt>skin/themes/images/add.svg (themes/images/add.svg)</tt>
 
=== Usage ===
 
Chrome theme URLs almost match their source tree path, with one difference: the segment <tt>client</tt> is replaced by <tt>skin</tt>. This is a requirement of the <tt>chrome://</tt> protocol handler.
 
Example:
 
* File: <tt>/devtools/client/themes/images/add.svg</tt>
* Usage: <tt>chrome://devtools/skin/themes/images/add.svg</tt>
 
For files within a single tool, consider relative URLs. They're shorter!
 
= Making and Submitting a Patch =
 
Before you make any changes, read [http://mozilla-version-control-tools.readthedocs.org/en/latest/hgmozilla/index.html the documentation on how to use Mozilla's version control].
 
If you read through the source code about something you do not know about, you may find documentation here:
 
* [http://developer.mozilla.org/ Mozilla Developer Network] has a ton of info about XUL elements, HTML, JS, DOM, Web APIs, Gecko-specific APIs, and more.
* [http://dxr.mozilla.org/mozilla-central/source/ DXR] is a source code search engine - search for symbols you want to learn about, eg. nsIDocument.
* Before you submit a patch, you should read our [[DevTools/CodingStandards|Coding Standards]] and run [https://wiki.mozilla.org/DevTools/CodingStandards#JS_linting_with_ESLint ESLint] to validate your code changes (to avoid loosing time during code reviews with formatting details for instance).
** In general, try to be File Consistent. For new files, follow the standards.
 
We recommend [https://support.mozilla.org/en-US/kb/how-search-from-address-bar adding a smart keyword search] for DXR and MDN.
 
If you still have questions, [[DevTools/GetInvolved#Communication|ask us on IRC]] or leave a comment on the Bugzilla ticket.
 
Once you have a patch file, add it as an attachment to the Bugzilla ticket you are working on and add the '''feedback?''' or '''review?''' flag depending on if you just want feedback and confirmation you're doing the right thing or if you think the patch is ready to land respectively. Read more about [https://developer.mozilla.org/en-US/docs/Developer_Guide/How_to_Submit_a_Patch how to submit a patch and the Bugzilla review cycle here].
 
= Running the Developer Tools Tests =
 
We use three suites of tests:
 
* '''xpcshell''': More unit-test style of tests. No browser window, just a JavaScript shell. Mostly testing APIs directly.
* '''mochitest-chrome''': More unit-test style of tests, but with a browser window. Mostly testing APIs that interact with the DOM directly.
* '''mochitest-devtools''': More of an integration style of tests. Fires up a whole browser window with every test and you can test clicking on buttons, etc.
 
More information about the different types of tests can be found on the [https://developer.mozilla.org/en-US/docs/Mozilla/QA/Automated_testing MDN automated testing page]
 
To run all DevTools tests, regardless of suite type:
 
  $ ./mach test devtools/*
 
The following sections show more specific commands for running only a single suite or single test in a suite.
 
== xpcshell Tests ==
 
To run all of the xpcshell tests:
 
  $ ./mach xpcshell-test --tag devtools
 
To run a specific xpcshell test:
 
  $ ./mach xpcshell-test devtools/path/to/the/test_you_want_to_run.js
 
== Chrome Mochitests ==
 
To run the whole suite of chrome mochitests for DevTools:
 
  $ ./mach mochitest -f chrome --tag devtools
 
To run a specific chrome mochitest:
 
  $ ./mach mochitest devtools/path/to/the/test_you_want_to_run.html
 
== DevTools Mochitests ==
 
To run the whole suite of browser mochitests for DevTools (sit back and relax):
 
  $ ./mach mochitest --subsuite devtools --tag devtools
 
To run a specific tool's suite of browser mochitests:
 
  $ ./mach mochitest devtools/client/<tool>
 
For example, run all of the debugger browser mochitests:
 
  $ ./mach mochitest devtools/client/debugger
 
To run a specific DevTools mochitest:
 
  $ ./mach mochitest devtools/client/path/to/the/test_you_want_to_run.js
 
To help with writing nice, maintainable and consistent DevTools mochitests, please follow our [https://wiki.mozilla.org/DevTools/mochitests_coding_standards DevTools mochitests coding guide].
 
Note that the mochitests '''must''' have focus while running.
 
= Coding Standards =
 
DevTools has some [[DevTools/CodingStandards|coding standards]] that your changes should follow.  That page also shows how to set up ESLint to check your code for compliance.
 
= Potential Pitfalls =
 
Today there are a few techniques and conventions we use that can be confusing, especially when you first start working with the code base.  We hope to improve these with time to make things easier for everyone, but for now this [https://etherpad.mozilla.org/devtools-intro-pitfalls etherpad] might be a helpful set of notes if you are having trouble.  If you find new pitfalls that aren't listed there, feel free to add your own entries, so we know to address them.  Also, please come talk to us in #devtools on IRC, as that might be the fastest path to solving the issue.

Latest revision as of 06:21, 16 March 2022

The contents of this section have been moved to

https://firefox-source-docs.mozilla.org/devtools/index.html