[gjs: 13/21] maint: Fix header includes once and for all



commit 01920362be26a2cb4e38b55cc211351391885d1d
Author: Philip Chimento <philip chimento gmail com>
Date:   Fri May 31 23:40:53 2019 -0700

    maint: Fix header includes once and for all
    
    Previously #include statements were a bit of a mess across the codebase.
    This commit is the result of a pass by the IWYU (Include What You Use)
    tool, which suggests headers to add or remove based on what is in the
    file, and can also suggest forward-declaring classes instead of
    including their headers, if they are only used as a pointer in a
    particular file. Cleaning this up should in general speed up compile
    times.
    
    IWYU isn't perfect, it produces a number of false positives, so we don't
    try to automate this process and we don't accept all of its
    recommendations. We do add a script and configuration file to the tools/
    directory so that IWYU can be every so often in the future.
    
    We also clean up all the includes according to a consistent style, which
    is now described clearly in the C++ style guide.

 CPPLINT.cfg                        |  5 +++
 Makefile.am                        |  4 +++
 configure.ac                       |  1 +
 doc/CPP_Style_Guide.md             | 65 ++++++++++++++++++++++++++++++++++++++
 gi/arg.cpp                         | 46 ++++++++++++++++-----------
 gi/arg.h                           | 12 ++++---
 gi/boxed.cpp                       | 29 +++++++++--------
 gi/boxed.h                         |  9 ++++--
 gi/closure.cpp                     | 14 ++++----
 gi/closure.h                       |  4 +--
 gi/enumeration.cpp                 | 20 ++++--------
 gi/enumeration.h                   |  8 ++---
 gi/foreign.cpp                     | 12 ++++---
 gi/foreign.h                       |  5 +--
 gi/function.cpp                    | 26 +++++++++------
 gi/function.h                      | 11 +++----
 gi/fundamental.cpp                 | 23 ++++++--------
 gi/fundamental.h                   |  7 ++--
 gi/gerror.cpp                      | 24 +++++++-------
 gi/gerror.h                        |  8 +++--
 gi/gjs_gi_trace.h                  |  4 +--
 gi/gobject.cpp                     | 15 ++++++---
 gi/gobject.h                       |  5 ++-
 gi/gtype.cpp                       | 12 +++----
 gi/gtype.h                         |  5 ++-
 gi/interface.cpp                   | 13 +++-----
 gi/interface.h                     |  7 ++--
 gi/ns.cpp                          | 17 +++++-----
 gi/ns.h                            |  7 ++--
 gi/object.cpp                      | 36 +++++++++++----------
 gi/object.h                        | 18 +++++++----
 gi/param.cpp                       | 16 +++++-----
 gi/param.h                         |  7 ++--
 gi/private.cpp                     | 20 +++++++-----
 gi/private.h                       |  1 +
 gi/repo.cpp                        | 21 +++++++-----
 gi/repo.h                          |  6 ++--
 gi/toggle.cpp                      |  7 ++--
 gi/toggle.h                        |  3 ++
 gi/union.cpp                       | 17 +++-------
 gi/union.h                         |  7 ++--
 gi/value.cpp                       | 45 +++++++++++++++-----------
 gi/value.h                         |  4 +--
 gi/wrapperutils.cpp                |  8 +++--
 gi/wrapperutils.h                  | 14 +++++++-
 gjs/atoms.cpp                      |  3 +-
 gjs/atoms.h                        |  1 +
 gjs/byteArray.cpp                  | 14 ++++++--
 gjs/byteArray.h                    |  6 ++--
 gjs/console.cpp                    | 15 ++++++---
 gjs/context-private.h              | 19 +++++++----
 gjs/context.cpp                    | 64 ++++++++++++++++++++-----------------
 gjs/context.h                      |  5 ++-
 gjs/coverage.cpp                   | 20 ++++++++----
 gjs/coverage.h                     |  7 ++--
 gjs/debugger.cpp                   | 26 ++++++++++-----
 gjs/deprecation.cpp                | 13 +++++---
 gjs/deprecation.h                  |  2 +-
 gjs/engine.cpp                     | 27 +++++++++-------
 gjs/engine.h                       |  7 ++--
 gjs/error-types.cpp                |  2 --
 gjs/error-types.h                  |  1 +
 gjs/global.cpp                     | 13 +++++---
 gjs/global.h                       |  3 +-
 gjs/importer.cpp                   | 35 ++++++++++++--------
 gjs/importer.h                     |  4 +--
 gjs/jsapi-class.h                  | 15 +++++----
 gjs/jsapi-dynamic-class.cpp        | 17 +++++-----
 gjs/jsapi-util-args.h              | 10 ++++--
 gjs/jsapi-util-error.cpp           | 16 +++++-----
 gjs/jsapi-util-root.h              | 12 +++++--
 gjs/jsapi-util-string.cpp          | 21 +++++++-----
 gjs/jsapi-util.cpp                 | 23 +++++---------
 gjs/jsapi-util.h                   | 16 ++++++----
 gjs/jsapi-wrapper.h                |  6 +++-
 gjs/macros.h                       |  2 +-
 gjs/mem.cpp                        |  2 +-
 gjs/mem.h                          |  3 +-
 gjs/module.cpp                     | 14 +++++---
 gjs/module.h                       |  3 +-
 gjs/native.cpp                     |  9 ++++--
 gjs/native.h                       |  4 +--
 gjs/profiler-private.h             |  4 +--
 gjs/profiler.cpp                   | 41 +++++++++++++++---------
 gjs/profiler.h                     |  3 +-
 gjs/stack.cpp                      | 12 ++++---
 installed-tests/minijasmine.cpp    |  8 ++---
 libgjs-private/gjs-gdbus-wrapper.c |  9 ++++--
 libgjs-private/gjs-gdbus-wrapper.h |  6 ++--
 libgjs-private/gjs-gtk-util.c      |  7 ++--
 libgjs-private/gjs-gtk-util.h      |  8 +++--
 libgjs-private/gjs-util.c          | 26 ++++++++++-----
 libgjs-private/gjs-util.h          |  5 +--
 modules/cairo-context.cpp          | 17 ++++++----
 modules/cairo-gradient.cpp         | 10 +++---
 modules/cairo-image-surface.cpp    | 12 ++++---
 modules/cairo-linear-gradient.cpp  | 11 ++++---
 modules/cairo-module.h             |  1 +
 modules/cairo-path.cpp             | 10 +++---
 modules/cairo-pattern.cpp          | 12 ++++---
 modules/cairo-pdf-surface.cpp      | 17 ++++++----
 modules/cairo-private.h            |  6 +++-
 modules/cairo-ps-surface.cpp       | 17 ++++++----
 modules/cairo-radial-gradient.cpp  | 11 ++++---
 modules/cairo-region.cpp           | 17 ++++++----
 modules/cairo-solid-pattern.cpp    | 11 ++++---
 modules/cairo-surface-pattern.cpp  | 11 ++++---
 modules/cairo-surface.cpp          | 15 ++++++---
 modules/cairo-svg-surface.cpp      | 17 ++++++----
 modules/cairo.cpp                  | 11 ++++---
 modules/console.cpp                | 20 ++++++------
 modules/console.h                  |  4 +--
 modules/modules.cpp                | 11 +++----
 modules/modules.h                  |  4 ---
 modules/system.cpp                 | 19 ++++++-----
 modules/system.h                   |  4 +--
 test/gjs-test-call-args.cpp        |  8 +++--
 test/gjs-test-common.cpp           |  1 +
 test/gjs-test-common.h             |  2 +-
 test/gjs-test-coverage.cpp         | 20 +++++-------
 test/gjs-test-rooting.cpp          |  7 ++--
 test/gjs-test-utils.cpp            |  6 ++--
 test/gjs-test-utils.h              |  4 ++-
 test/gjs-tests.cpp                 | 14 ++++----
 tools/gjs-private-iwyu.imp         | 53 +++++++++++++++++++++++++++++++
 tools/gjs-public-iwyu.imp          |  6 ++++
 tools/run_iwyu.sh.in               | 59 ++++++++++++++++++++++++++++++++++
 util/log.cpp                       | 17 ++++------
 util/misc.cpp                      |  5 +--
 util/misc.h                        |  2 --
 130 files changed, 1070 insertions(+), 639 deletions(-)
---
diff --git a/CPPLINT.cfg b/CPPLINT.cfg
index 30edcbf2..1f5f9ec6 100644
--- a/CPPLINT.cfg
+++ b/CPPLINT.cfg
@@ -4,3 +4,8 @@ set noparent
 # We give a limit to clang-format of 80, but we allow 100 here for cases where
 # it really is more readable to have a longer line
 linelength=100
+
+# Exceptions to Google style
+# - build/include_order: We have a special order for include files, see "Header
+#   inclusion order" in CPP_Style_Guide.md.
+filter=-build/include_order
diff --git a/Makefile.am b/Makefile.am
index 0949f63f..1b3b6d9d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -257,4 +257,8 @@ cppcheck:
                --enable=warning,performance,portability,information,missingInclude \
                --force -q $(top_srcdir) -I $(top_builddir)
 
+# Include What You Use: run 'make iwyu | tee iwyu.log'
+iwyu: tools/run_iwyu.sh
+       SRCDIR=$(abs_top_srcdir) BUILDDIR=$(abs_top_builddir) tools/run_iwyu.sh 2>&1
+
 -include $(top_srcdir)/git.mk
diff --git a/configure.ac b/configure.ac
index ef55099c..51bf6b02 100644
--- a/configure.ac
+++ b/configure.ac
@@ -371,6 +371,7 @@ dnl automake 1.11/1.12 defines this but does not substitute it
 AC_SUBST([pkglibexecdir], ["${libexecdir}/${PACKAGE}"])
 
 AC_CONFIG_FILES([Makefile gjs-1.0.pc win32/config.h.win32])
+AC_CONFIG_FILES([tools/run_iwyu.sh], [chmod +x tools/run_iwyu.sh])
 dnl Symlink the files from gobject-introspection's test libraries into the tree;
 dnl Automake plans to drop support for compiling them in-place.
 AC_CONFIG_LINKS([
diff --git a/doc/CPP_Style_Guide.md b/doc/CPP_Style_Guide.md
index 59731670..321c843a 100644
--- a/doc/CPP_Style_Guide.md
+++ b/doc/CPP_Style_Guide.md
@@ -407,6 +407,71 @@ in the implementation file (as mentioned above).
 This way there won't be any hidden dependencies that you'll find out
 about later.
 
+The tool [IWYU][iwyu] can help with this, but it generates a lot of
+false positives, so we don't automate it.
+
+[iwyu]: https://include-what-you-use.org/
+
+#### Header inclusion order ####
+
+Headers should be included in the following order:
+
+- `<config.h>`
+- C system headers
+- C++ system headers
+- GNOME library headers
+- SpiderMonkey library headers
+- GJS headers
+
+Each of these groups must be separated by blank lines.
+Within each group, all the headers should be alphabetized.
+The first four groups should use angle brackets for the includes.
+
+SpiderMonkey headers should in theory also all use angle brackets, but
+currently due to a bug in SpiderMonkey, the GJS header
+`"gjs/jsapi-wrapper.h"` must be included instead of `<jsapi.h>` and
+`<jsfriendapi.h>`, and before any other SpiderMonkey headers.
+So the SpiderMonkey headers should use quotes for the includes.
+
+GJS headers should use quotes, _except_ in public header files (any
+header file included from `<gjs/gjs.h>`.)
+
+If you need to include headers conditionally, add the conditional
+after the group that it belongs to, separated by a blank line.
+
+If it is not obvious, you may add a comment after the include,
+explaining what this header is included for.
+This makes it easier to figure out whether to remove a header later if
+its functionality is no longer used in the file.
+
+Here is an example of all of the above rules together:
+
+```c++
+#include <config.h>  // for ENABLE_CAIRO
+
+#include <string.h>  // for strlen
+
+#ifdef XP_WIN
+#    define WIN32_LEAN_AND_MEAN
+#    include <windows.h>
+#endif
+
+#include <codecvt>  // for codecvt_utf8_utf16
+#include <locale>   // for wstring_convert
+#include <vector>
+
+#include <girepository.h>
+#include <glib.h>
+
+#include "gjs/jsapi-wrapper.h"
+#include "js/GCHashTable.h"  // for GCHashMap
+#include "mozilla/Unused.h"
+
+#include "gjs/atoms.h"
+#include "gjs/context-private.h"
+#include "gjs/jsapi-util.h"
+```
+
 #### Keep "Internal" Headers Private ####
 
 Many modules have a complex implementation that causes them to use more
diff --git a/gi/arg.cpp b/gi/arg.cpp
index 5c5c2001..21f1de33 100644
--- a/gi/arg.cpp
+++ b/gi/arg.cpp
@@ -21,25 +21,35 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
-
-#include <cmath>
-#include <cstdlib>
-
-#include "arg.h"
-#include "gtype.h"
-#include "object.h"
-#include "interface.h"
-#include "foreign.h"
-#include "fundamental.h"
-#include "boxed.h"
-#include "union.h"
-#include "param.h"
-#include "value.h"
-#include "gerror.h"
-#include "gjs/byteArray.h"
+#include <string.h>  // for strcmp, strlen, memcpy
+
+#include <cmath>   // for std::abs
+#include <limits>  // for numeric_limits
+#include <string>
+
+#include <girepository.h>
+#include <glib-object.h>
+#include <glib.h>
+
 #include "gjs/jsapi-wrapper.h"
-#include <util/log.h>
+
+#include "gi/arg.h"
+#include "gi/boxed.h"
+#include "gi/foreign.h"
+#include "gi/fundamental.h"
+#include "gi/gerror.h"
+#include "gi/gtype.h"
+#include "gi/interface.h"
+#include "gi/object.h"
+#include "gi/param.h"
+#include "gi/union.h"
+#include "gi/value.h"
+#include "gi/wrapperutils.h"
+#include "gjs/atoms.h"
+#include "gjs/byteArray.h"
+#include "gjs/context-private.h"
+#include "gjs/jsapi-util.h"
+#include "util/log.h"
 
 bool _gjs_flags_value_is_valid(JSContext* context, GType gtype, int64_t value) {
     GFlagsValue *v;
diff --git a/gi/arg.h b/gi/arg.h
index 7e7077d4..e09d440f 100644
--- a/gi/arg.h
+++ b/gi/arg.h
@@ -24,13 +24,15 @@
 #ifndef GI_ARG_H_
 #define GI_ARG_H_
 
-#include <stdbool.h>
-#include <glib.h>
-
-#include "gjs/jsapi-util.h"
-#include "gjs/macros.h"
+#include <stddef.h>  // for size_t
+#include <stdint.h>
 
 #include <girepository.h>
+#include <glib-object.h>
+
+#include "gjs/jsapi-wrapper.h"
+
+#include "gjs/macros.h"
 
 // Different roles for a GIArgument; currently used only in exception and debug
 // messages.
diff --git a/gi/boxed.cpp b/gi/boxed.cpp
index f6db484a..9e196abd 100644
--- a/gi/boxed.cpp
+++ b/gi/boxed.cpp
@@ -21,29 +21,30 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
+#include <stdint.h>
+#include <string.h>  // for memcpy, size_t, strcmp
 
-#include <string.h>
+#include <string>       // for string
+#include <type_traits>  // for remove_reference
+#include <utility>      // for move, forward
 
-#include <utility>
+#include <girepository.h>
+#include <glib-object.h>
 
 #include "gjs/jsapi-wrapper.h"
-#include "js/GCHashTable.h"
+#include "js/GCHashTable.h"  // for GCHashMap
 
-#include "arg.h"
-#include "boxed.h"
-#include "function.h"
+#include "gi/arg.h"
+#include "gi/boxed.h"
+#include "gi/function.h"
 #include "gi/gerror.h"
+#include "gi/repo.h"
 #include "gi/wrapperutils.h"
+#include "gjs/atoms.h"
+#include "gjs/context-private.h"
 #include "gjs/jsapi-class.h"
 #include "gjs/mem-private.h"
-#include "gtype.h"
-#include "object.h"
-#include "repo.h"
-
-#include <util/log.h>
-
-#include <girepository.h>
+#include "util/log.h"
 
 BoxedInstance::BoxedInstance(JSContext* cx, JS::HandleObject obj)
     : GIWrapperInstance(cx, obj), m_owning_ptr(false) {
diff --git a/gi/boxed.h b/gi/boxed.h
index 9b571cc4..5aed8644 100644
--- a/gi/boxed.h
+++ b/gi/boxed.h
@@ -24,17 +24,20 @@
 #ifndef GI_BOXED_H_
 #define GI_BOXED_H_
 
+#include <stdint.h>
+
 #include <girepository.h>
+#include <glib-object.h>
 #include <glib.h>
 
+#include "gjs/jsapi-wrapper.h"
+#include "js/GCHashTable.h"  // for GCHashMap
+
 #include "gi/wrapperutils.h"
 #include "gjs/jsapi-util.h"
-#include "gjs/jsapi-wrapper.h"
 #include "gjs/macros.h"
 #include "util/log.h"
 
-#include "js/GCHashTable.h"
-
 class BoxedPrototype;
 class BoxedInstance;
 
diff --git a/gi/closure.cpp b/gi/closure.cpp
index a952a14f..860ca678 100644
--- a/gi/closure.cpp
+++ b/gi/closure.cpp
@@ -21,16 +21,18 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
+#include <glib.h>
 
-#include <string.h>
-#include <limits.h>
-#include <util/log.h>
+#include <new>
 
-#include "closure.h"
-#include "gjs/jsapi-util-root.h"
 #include "gjs/jsapi-wrapper.h"
+
+#include "gi/closure.h"
+#include "gjs/context-private.h"
+#include "gjs/jsapi-util-root.h"
+#include "gjs/jsapi-util.h"
 #include "gjs/mem-private.h"
+#include "util/log.h"
 
 struct Closure {
     JSContext *context;
diff --git a/gi/closure.h b/gi/closure.h
index ef85c05f..fb8a1455 100644
--- a/gi/closure.h
+++ b/gi/closure.h
@@ -24,10 +24,10 @@
 #ifndef GI_CLOSURE_H_
 #define GI_CLOSURE_H_
 
-#include <stdbool.h>
 #include <glib-object.h>
 
-#include "gjs/jsapi-util.h"
+#include "gjs/jsapi-wrapper.h"
+
 #include "gjs/macros.h"
 
 GJS_USE
diff --git a/gi/enumeration.cpp b/gi/enumeration.cpp
index 78c77c0c..de2a3be4 100644
--- a/gi/enumeration.cpp
+++ b/gi/enumeration.cpp
@@ -21,22 +21,16 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
-
-#include <string.h>
+#include <girepository.h>
+#include <glib-object.h>
+#include <glib.h>
 
-#include "function.h"
-#include "gi/wrapperutils.h"
-#include "gjs/context-private.h"
 #include "gjs/jsapi-wrapper.h"
-#include "gtype.h"
-#include "repo.h"
-
-#include <util/log.h>
 
-#include <girepository.h>
-
-#include "enumeration.h"
+#include "gi/enumeration.h"
+#include "gi/wrapperutils.h"
+#include "gjs/jsapi-util.h"
+#include "util/log.h"
 
 GJS_JSAPI_RETURN_CONVENTION
 static bool
diff --git a/gi/enumeration.h b/gi/enumeration.h
index ac78a974..0115c3eb 100644
--- a/gi/enumeration.h
+++ b/gi/enumeration.h
@@ -24,13 +24,11 @@
 #ifndef GI_ENUMERATION_H_
 #define GI_ENUMERATION_H_
 
-#include <stdbool.h>
-#include <glib.h>
+#include <girepository.h>
 
-#include "gjs/jsapi-util.h"
-#include "gjs/macros.h"
+#include "gjs/jsapi-wrapper.h"
 
-#include <girepository.h>
+#include "gjs/macros.h"
 
 GJS_JSAPI_RETURN_CONVENTION
 bool gjs_define_enum_values(JSContext       *context,
diff --git a/gi/foreign.cpp b/gi/foreign.cpp
index 3082c6c0..cb8da5d8 100644
--- a/gi/foreign.cpp
+++ b/gi/foreign.cpp
@@ -21,16 +21,18 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
+#include <string.h>  // for strcmp
 
-#include <string.h>
 #include <girepository.h>
+#include <glib.h>
 
-#include "arg.h"
-#include "foreign.h"
-#include "gjs/context-private.h"
 #include "gjs/jsapi-wrapper.h"
 
+#include "gi/arg.h"
+#include "gi/foreign.h"
+#include "gjs/context-private.h"
+#include "gjs/jsapi-util.h"
+
 static struct {
     char *gi_namespace;
     char *module; // relative to "imports."
diff --git a/gi/foreign.h b/gi/foreign.h
index b2644f20..fbf6111a 100644
--- a/gi/foreign.h
+++ b/gi/foreign.h
@@ -24,10 +24,11 @@
 #ifndef GI_FOREIGN_H_
 #define GI_FOREIGN_H_
 
-#include <stdbool.h>
 #include <girepository.h>
 
-#include "arg.h"
+#include "gjs/jsapi-wrapper.h"
+
+#include "gi/arg.h"
 #include "gjs/macros.h"
 
 typedef bool (*GjsArgOverrideToGArgumentFunc) (JSContext      *context,
diff --git a/gi/function.cpp b/gi/function.cpp
index 269deac3..ce04027f 100644
--- a/gi/function.cpp
+++ b/gi/function.cpp
@@ -21,7 +21,20 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
+#include <stdint.h>
+#include <stdlib.h>  // for exit
+#include <string.h>  // for strcmp, memset, size_t
+
+#include <new>
+
+#include <ffi.h>
+#include <girepository.h>
+#include <girffi.h>
+#include <glib-object.h>
+#include <glib.h>
+
+#include "gjs/jsapi-wrapper.h"
+#include "mozilla/Maybe.h"
 
 #include "gi/arg.h"
 #include "gi/boxed.h"
@@ -34,16 +47,11 @@
 #include "gi/param.h"
 #include "gi/union.h"
 #include "gjs/context-private.h"
+#include "gjs/context.h"
 #include "gjs/jsapi-class.h"
-#include "gjs/jsapi-wrapper.h"
+#include "gjs/jsapi-util.h"
 #include "gjs/mem-private.h"
-
-#include <util/log.h>
-
-#include <girepository.h>
-
-#include <errno.h>
-#include <string.h>
+#include "util/log.h"
 
 /* We use guint8 for arguments; functions can't
  * have more than this.
diff --git a/gi/function.h b/gi/function.h
index d9bc3d69..f9b14254 100644
--- a/gi/function.h
+++ b/gi/function.h
@@ -24,14 +24,13 @@
 #ifndef GI_FUNCTION_H_
 #define GI_FUNCTION_H_
 
-#include <stdbool.h>
-#include <glib.h>
+#include <ffi.h>
+#include <girepository.h>
+#include <glib-object.h>
 
-#include "gjs/jsapi-util.h"
-#include "gjs/macros.h"
+#include "gjs/jsapi-wrapper.h"
 
-#include <girepository.h>
-#include <girffi.h>
+#include "gjs/macros.h"
 
 typedef enum {
     PARAM_NORMAL,
diff --git a/gi/fundamental.cpp b/gi/fundamental.cpp
index 35791309..da8f5a08 100644
--- a/gi/fundamental.cpp
+++ b/gi/fundamental.cpp
@@ -22,25 +22,22 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
+#include <girepository.h>
+#include <glib.h>
 
-#include "fundamental.h"
+#include "gjs/jsapi-wrapper.h"
+#include "js/GCHashTable.h"  // for WeakCache
 
-#include "arg.h"
-#include "boxed.h"
-#include "function.h"
-#include "gi/gtype.h"
-#include "gi/object.h"
+#include "gi/arg.h"
+#include "gi/function.h"
+#include "gi/fundamental.h"
 #include "gi/repo.h"
 #include "gi/wrapperutils.h"
+#include "gjs/atoms.h"
 #include "gjs/context-private.h"
-#include "gjs/jsapi-class.h"
-#include "gjs/jsapi-wrapper.h"
+#include "gjs/jsapi-util.h"
 #include "gjs/mem-private.h"
-
-#include <gjs/context.h>
-#include <util/log.h>
-#include <girepository.h>
+#include "util/log.h"
 
 FundamentalInstance::FundamentalInstance(JSContext* cx, JS::HandleObject obj)
     : GIWrapperInstance(cx, obj) {
diff --git a/gi/fundamental.h b/gi/fundamental.h
index aea7e35a..9756aaf2 100644
--- a/gi/fundamental.h
+++ b/gi/fundamental.h
@@ -25,13 +25,14 @@
 #ifndef GI_FUNDAMENTAL_H_
 #define GI_FUNDAMENTAL_H_
 
-#include <stdbool.h>
-#include <glib.h>
 #include <girepository.h>
+#include <glib-object.h>
+
+#include "gjs/jsapi-wrapper.h"
 
 #include "gi/wrapperutils.h"
-#include "gjs/jsapi-util.h"
 #include "gjs/macros.h"
+#include "util/log.h"
 
 class FundamentalPrototype;
 class FundamentalInstance;
diff --git a/gi/gerror.cpp b/gi/gerror.cpp
index 7f2b8bfa..a1b1a546 100644
--- a/gi/gerror.cpp
+++ b/gi/gerror.cpp
@@ -21,23 +21,23 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
+#include <stdint.h>
 
-#include <string.h>
+#include <girepository.h>
+#include <glib-object.h>
+
+#include "gjs/jsapi-wrapper.h"
 
-#include "boxed.h"
-#include "enumeration.h"
-#include "gerror.h"
+#include "gi/boxed.h"
+#include "gi/enumeration.h"
+#include "gi/gerror.h"
+#include "gi/repo.h"
+#include "gjs/atoms.h"
 #include "gjs/context-private.h"
 #include "gjs/error-types.h"
-#include "gjs/jsapi-class.h"
-#include "gjs/jsapi-wrapper.h"
+#include "gjs/jsapi-util.h"
 #include "gjs/mem-private.h"
-#include "repo.h"
-
-#include <util/log.h>
-
-#include <girepository.h>
+#include "util/log.h"
 
 ErrorPrototype::ErrorPrototype(GIEnumInfo* info, GType gtype)
     : GIWrapperPrototype(info, gtype),
diff --git a/gi/gerror.h b/gi/gerror.h
index 5cd08b5b..730f864a 100644
--- a/gi/gerror.h
+++ b/gi/gerror.h
@@ -24,13 +24,15 @@
 #ifndef GI_GERROR_H_
 #define GI_GERROR_H_
 
-#include <stdbool.h>
-#include <glib.h>
 #include <girepository.h>
+#include <glib-object.h>
+#include <glib.h>
+
+#include "gjs/jsapi-wrapper.h"
 
 #include "gi/wrapperutils.h"
-#include "gjs/jsapi-util.h"
 #include "gjs/macros.h"
+#include "util/log.h"
 
 class ErrorPrototype;
 class ErrorInstance;
diff --git a/gi/gjs_gi_trace.h b/gi/gjs_gi_trace.h
index ff9758cb..77e6c6fe 100644
--- a/gi/gjs_gi_trace.h
+++ b/gi/gjs_gi_trace.h
@@ -26,9 +26,7 @@
 #ifndef GI_GJS_GI_TRACE_H_
 #define GI_GJS_GI_TRACE_H_
 
-#ifndef GJS_VERSION
-#    error "config.h must be included prior to gjs_trace.h"
-#endif
+#include <config.h>  // IWYU pragma: keep
 
 #ifdef HAVE_DTRACE
 
diff --git a/gi/gobject.cpp b/gi/gobject.cpp
index 00a4ae61..cc17086b 100644
--- a/gi/gobject.cpp
+++ b/gi/gobject.cpp
@@ -21,16 +21,21 @@
  * IN THE SOFTWARE.
  */
 
+#include <unordered_map>
+#include <utility>  // for move, pair
+
 #include <glib-object.h>
+#include <glib.h>
 
-#include <unordered_map>
+#include "gjs/jsapi-wrapper.h"
 
+#include "gi/gobject.h"
+#include "gi/object.h"
+#include "gi/value.h"
+#include "gjs/context-private.h"
 #include "gjs/context.h"
 #include "gjs/jsapi-util.h"
-#include "gjs/jsapi-wrapper.h"
-#include "gobject.h"
-#include "object.h"
-#include "value.h"
+#include "gjs/macros.h"
 
 static std::unordered_map<GType, AutoParamArray> class_init_properties;
 
diff --git a/gi/gobject.h b/gi/gobject.h
index 1d925e05..2179bec8 100644
--- a/gi/gobject.h
+++ b/gi/gobject.h
@@ -23,11 +23,10 @@
 #ifndef GI_GOBJECT_H_
 #define GI_GOBJECT_H_
 
-#include <glib-object.h>
-
-#include <unordered_map>
 #include <vector>
 
+#include <glib-object.h>
+
 #include "gjs/jsapi-util.h"
 
 using AutoParamArray = std::vector<GjsAutoParam>;
diff --git a/gi/gtype.cpp b/gi/gtype.cpp
index 1b10ea99..a915bf66 100644
--- a/gi/gtype.cpp
+++ b/gi/gtype.cpp
@@ -22,17 +22,17 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
+#include <glib-object.h>
+#include <glib.h>
 
-#include <girepository.h>
-
-#include <unordered_map>
+#include "gjs/jsapi-wrapper.h"
+#include "js/GCHashTable.h"  // for WeakCache
 
 #include "gi/gtype.h"
+#include "gjs/atoms.h"
 #include "gjs/context-private.h"
 #include "gjs/jsapi-class.h"
-#include "gjs/jsapi-wrapper.h"
-#include "util/log.h"
+#include "gjs/jsapi-util.h"
 
 GJS_USE static JSObject* gjs_gtype_get_proto(JSContext* cx) G_GNUC_UNUSED;
 GJS_JSAPI_RETURN_CONVENTION
diff --git a/gi/gtype.h b/gi/gtype.h
index 9a32dbf3..cbe6278d 100644
--- a/gi/gtype.h
+++ b/gi/gtype.h
@@ -25,11 +25,10 @@
 #ifndef GI_GTYPE_H_
 #define GI_GTYPE_H_
 
-#include <stdbool.h>
-#include <glib.h>
-#include <girepository.h>
+#include <glib-object.h>
 
 #include "gjs/jsapi-wrapper.h"
+
 #include "gjs/macros.h"
 
 GJS_JSAPI_RETURN_CONVENTION
diff --git a/gi/interface.cpp b/gi/interface.cpp
index 90ca2066..57a0537b 100644
--- a/gi/interface.cpp
+++ b/gi/interface.cpp
@@ -22,21 +22,18 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
+#include <girepository.h>
+
+#include "gjs/jsapi-wrapper.h"
 
 #include "gi/function.h"
-#include "gi/gtype.h"
 #include "gi/interface.h"
 #include "gi/object.h"
 #include "gi/repo.h"
-#include "gjs/jsapi-class.h"
-#include "gjs/jsapi-wrapper.h"
+#include "gjs/atoms.h"
+#include "gjs/context-private.h"
 #include "gjs/mem-private.h"
 
-#include <util/log.h>
-
-#include <girepository.h>
-
 InterfacePrototype::InterfacePrototype(GIInterfaceInfo* info, GType gtype)
     : GIWrapperPrototype(info, gtype),
       m_vtable(
diff --git a/gi/interface.h b/gi/interface.h
index 7730b4a0..e10bf561 100644
--- a/gi/interface.h
+++ b/gi/interface.h
@@ -25,13 +25,16 @@
 #ifndef GI_INTERFACE_H_
 #define GI_INTERFACE_H_
 
-#include <stdbool.h>
-#include <glib.h>
 #include <girepository.h>
+#include <glib-object.h>
+#include <glib.h>
+
+#include "gjs/jsapi-wrapper.h"
 
 #include "gi/wrapperutils.h"
 #include "gjs/jsapi-util.h"
 #include "gjs/macros.h"
+#include "util/log.h"
 
 class InterfacePrototype;
 class InterfaceInstance;
diff --git a/gi/ns.cpp b/gi/ns.cpp
index 241573ac..d66b5df3 100644
--- a/gi/ns.cpp
+++ b/gi/ns.cpp
@@ -21,19 +21,20 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
+#include <girepository.h>
+#include <glib.h>
+
+#include "gjs/jsapi-wrapper.h"
 
 #include "gi/ns.h"
-#include "gi/param.h"
 #include "gi/repo.h"
+#include "gjs/atoms.h"
+#include "gjs/context-private.h"
 #include "gjs/jsapi-class.h"
-#include "gjs/jsapi-wrapper.h"
+#include "gjs/jsapi-util.h"
+#include "gjs/macros.h"
 #include "gjs/mem-private.h"
-
-#include <util/log.h>
-#include <girepository.h>
-
-#include <string.h>
+#include "util/log.h"
 
 typedef struct {
     char *gi_namespace;
diff --git a/gi/ns.h b/gi/ns.h
index 3d5fa7b9..e18e978b 100644
--- a/gi/ns.h
+++ b/gi/ns.h
@@ -24,12 +24,11 @@
 #ifndef GI_NS_H_
 #define GI_NS_H_
 
-#include <glib.h>
-#include <girepository.h>
-
-#include "gjs/jsapi-util.h"
 #include "gjs/macros.h"
 
+class JSObject;
+struct JSContext;
+
 GJS_JSAPI_RETURN_CONVENTION
 JSObject* gjs_create_ns(JSContext    *context,
                         const char   *ns_name);
diff --git a/gi/object.cpp b/gi/object.cpp
index 5404fe15..04a1c5f5 100644
--- a/gi/object.cpp
+++ b/gi/object.cpp
@@ -22,37 +22,39 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
+#include <string.h>  // for memset, strcmp
 
-#include <memory>
-#include <string.h>
-#include <tuple>
-#include <unordered_map>
+#include <algorithm>   // for move, find
+#include <functional>  // for mem_fn
+#include <string>
+#include <tuple>        // for tie
+#include <type_traits>  // for remove_reference<>::type
 #include <vector>
 
+#include <ffi.h>
+#include <girepository.h>
+#include <glib-object.h>
+#include <glib.h>
+
+#include "gjs/jsapi-wrapper.h"
+
 #include "gi/arg.h"
 #include "gi/closure.h"
 #include "gi/function.h"
 #include "gi/gjs_gi_trace.h"
 #include "gi/object.h"
-#include "gi/param.h"
+#include "gi/repo.h"
+#include "gi/toggle.h"
+#include "gi/value.h"
 #include "gi/wrapperutils.h"
+#include "gjs/atoms.h"
 #include "gjs/context-private.h"
+#include "gjs/context.h"
 #include "gjs/jsapi-class.h"
 #include "gjs/jsapi-util-args.h"
 #include "gjs/jsapi-util-root.h"
-#include "gjs/jsapi-wrapper.h"
 #include "gjs/mem-private.h"
-#include "gtype.h"
-#include "interface.h"
-#include "repo.h"
-#include "toggle.h"
-#include "value.h"
-
-#include <util/log.h>
-#include <girepository.h>
-
-#include "js/GCHashTable.h"
+#include "util/log.h"
 
 /* This is a trick to print out the sizes of the structs at compile time, in
  * an error message. */
diff --git a/gi/object.h b/gi/object.h
index 27272f6e..c7df2039 100644
--- a/gi/object.h
+++ b/gi/object.h
@@ -24,22 +24,28 @@
 #ifndef GI_OBJECT_H_
 #define GI_OBJECT_H_
 
-#include <glib-object.h>
-#include <girepository.h>
+#include <stddef.h>  // for size_t
 
 #include <forward_list>
 #include <functional>
 #include <vector>
 
+#include <girepository.h>
+#include <glib-object.h>
+#include <glib.h>
+
+#include "gjs/jsapi-wrapper.h"
+#include "js/GCHashTable.h"  // for GCHashMap
+
 #include "gi/wrapperutils.h"
 #include "gjs/jsapi-util-root.h"
 #include "gjs/jsapi-util.h"
-#include "gjs/jsapi-wrapper.h"
 #include "gjs/macros.h"
+#include "util/log.h"
 
-#include "js/GCHashTable.h"
-
+class GjsAtoms;
 class ObjectInstance;
+class ObjectPrototype;
 
 class GjsListLink {
  private:
@@ -62,8 +68,6 @@ struct AutoGValueVector : public std::vector<GValue> {
     }
 };
 
-class ObjectPrototype;
-
 /*
  * ObjectBase:
  *
diff --git a/gi/param.cpp b/gi/param.cpp
index b47eae42..ccf66039 100644
--- a/gi/param.cpp
+++ b/gi/param.cpp
@@ -21,21 +21,21 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
+#include <girepository.h>
+#include <glib.h>
 
-#include <string.h>
+#include "gjs/jsapi-wrapper.h"
 
-#include "gi/arg.h"
 #include "gi/function.h"
-#include "gi/gtype.h"
-#include "gi/object.h"
 #include "gi/param.h"
 #include "gi/repo.h"
+#include "gi/wrapperutils.h"
+#include "gjs/atoms.h"
+#include "gjs/context-private.h"
 #include "gjs/jsapi-class.h"
-#include "gjs/jsapi-wrapper.h"
+#include "gjs/jsapi-util.h"
 #include "gjs/mem-private.h"
-
-#include <util/log.h>
+#include "util/log.h"
 
 typedef struct {
     GParamSpec* gparam;  // nullptr if we are the prototype and not an instance
diff --git a/gi/param.h b/gi/param.h
index 751b1e4b..b2e205e2 100644
--- a/gi/param.h
+++ b/gi/param.h
@@ -24,11 +24,10 @@
 #ifndef GI_PARAM_H_
 #define GI_PARAM_H_
 
-#include <stdbool.h>
-#include <glib.h>
-#include <girepository.h>
+#include <glib-object.h>
+
+#include "gjs/jsapi-wrapper.h"
 
-#include "gjs/jsapi-util.h"
 #include "gjs/macros.h"
 
 GJS_JSAPI_RETURN_CONVENTION
diff --git a/gi/private.cpp b/gi/private.cpp
index b2060e58..dea49100 100644
--- a/gi/private.cpp
+++ b/gi/private.cpp
@@ -22,20 +22,24 @@
  * IN THE SOFTWARE.
  */
 
+#include <stdint.h>
+
 #include <glib-object.h>
+#include <glib.h>
 
-#include <unordered_map>
+#include "gjs/jsapi-wrapper.h"
 
+#include "gi/gobject.h"
+#include "gi/gtype.h"
+#include "gi/interface.h"
+#include "gi/object.h"
+#include "gi/param.h"
+#include "gi/private.h"
+#include "gi/repo.h"
+#include "gjs/atoms.h"
 #include "gjs/context-private.h"
 #include "gjs/jsapi-util-args.h"
 #include "gjs/jsapi-util.h"
-#include "gjs/jsapi-wrapper.h"
-#include "gobject.h"
-#include "interface.h"
-#include "object.h"
-#include "param.h"
-#include "private.h"
-#include "repo.h"
 
 /* gi/private.cpp - private "imports._gi" module with operations that we need
  * to use from JS in order to create GObject classes, but should not be exposed
diff --git a/gi/private.h b/gi/private.h
index 9c789f22..26cbadd6 100644
--- a/gi/private.h
+++ b/gi/private.h
@@ -25,6 +25,7 @@
 #define GI_PRIVATE_H_
 
 #include "gjs/jsapi-wrapper.h"
+
 #include "gjs/macros.h"
 
 GJS_JSAPI_RETURN_CONVENTION
diff --git a/gi/repo.cpp b/gi/repo.cpp
index 40f0d7d3..75ce4cee 100644
--- a/gi/repo.cpp
+++ b/gi/repo.cpp
@@ -21,12 +21,18 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
+#include <stdint.h>
+#include <string.h>  // for strlen
+
+#include <girepository.h>
+#include <glib-object.h>
+#include <glib.h>
+
+#include "gjs/jsapi-wrapper.h"
 
 #include "gi/arg.h"
 #include "gi/boxed.h"
 #include "gi/enumeration.h"
-#include "gi/foreign.h"
 #include "gi/function.h"
 #include "gi/fundamental.h"
 #include "gi/gerror.h"
@@ -36,14 +42,13 @@
 #include "gi/param.h"
 #include "gi/repo.h"
 #include "gi/union.h"
+#include "gjs/atoms.h"
+#include "gjs/context-private.h"
+#include "gjs/global.h"
 #include "gjs/jsapi-class.h"
-#include "gjs/jsapi-wrapper.h"
+#include "gjs/jsapi-util.h"
 #include "gjs/mem-private.h"
-
-#include <util/misc.h>
-
-#include <girepository.h>
-#include <string.h>
+#include "util/log.h"
 
 typedef struct {
     void *dummy;
diff --git a/gi/repo.h b/gi/repo.h
index 20221f0c..b4a09da0 100644
--- a/gi/repo.h
+++ b/gi/repo.h
@@ -24,14 +24,12 @@
 #ifndef GI_REPO_H_
 #define GI_REPO_H_
 
-#include <stdbool.h>
-#include <glib.h>
-
 #include <girepository.h>
 
-#include <util/log.h>
 #include "gjs/jsapi-wrapper.h"
+
 #include "gjs/macros.h"
+#include "util/log.h"
 
 GJS_JSAPI_RETURN_CONVENTION
 bool gjs_define_repo(JSContext              *cx,
diff --git a/gi/toggle.cpp b/gi/toggle.cpp
index 8fae06d0..3807ae13 100644
--- a/gi/toggle.cpp
+++ b/gi/toggle.cpp
@@ -23,12 +23,15 @@
  * Authored by: Philip Chimento <philip endlessm com>, <philip chimento gmail com>
  */
 
-#include <algorithm>
+#include <algorithm>  // for find_if
 #include <deque>
 #include <mutex>
+#include <utility>  // for pair
+
 #include <glib-object.h>
+#include <glib.h>
 
-#include "toggle.h"
+#include "gi/toggle.h"
 
 std::deque<ToggleQueue::Item>::iterator
 ToggleQueue::find_operation_locked(const GObject               *gobj,
diff --git a/gi/toggle.h b/gi/toggle.h
index 44db802f..fa7e01ae 100644
--- a/gi/toggle.h
+++ b/gi/toggle.h
@@ -29,7 +29,10 @@
 #include <atomic>
 #include <deque>
 #include <mutex>
+#include <utility>  // for pair
+
 #include <glib-object.h>
+#include <glib.h>
 
 #include "gjs/macros.h"
 #include "util/log.h"
diff --git a/gi/union.cpp b/gi/union.cpp
index f0f5bec3..56540599 100644
--- a/gi/union.cpp
+++ b/gi/union.cpp
@@ -21,25 +21,16 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
-
-#include <string.h>
-
 #include <girepository.h>
 
-/* include first for logging related #define used in repo.h */
-#include <util/log.h>
+#include "gjs/jsapi-wrapper.h"
 
-#include "arg.h"
 #include "gi/function.h"
-#include "gi/gtype.h"
-#include "gi/object.h"
+#include "gi/repo.h"
 #include "gi/union.h"
-#include "gi/wrapperutils.h"
-#include "gjs/jsapi-class.h"
-#include "gjs/jsapi-wrapper.h"
+#include "gjs/jsapi-util.h"
 #include "gjs/mem-private.h"
-#include "repo.h"
+#include "util/log.h"
 
 UnionPrototype::UnionPrototype(GIUnionInfo* info, GType gtype)
     : GIWrapperPrototype(info, gtype) {
diff --git a/gi/union.h b/gi/union.h
index f9078fcc..ed97d819 100644
--- a/gi/union.h
+++ b/gi/union.h
@@ -24,13 +24,14 @@
 #ifndef GI_UNION_H_
 #define GI_UNION_H_
 
-#include <stdbool.h>
-#include <glib.h>
 #include <girepository.h>
+#include <glib-object.h>
+
+#include "gjs/jsapi-wrapper.h"
 
 #include "gi/wrapperutils.h"
-#include "gjs/jsapi-util.h"
 #include "gjs/macros.h"
+#include "util/log.h"
 
 class UnionPrototype;
 class UnionInstance;
diff --git a/gi/value.cpp b/gi/value.cpp
index 9a25e18e..a375c34a 100644
--- a/gi/value.cpp
+++ b/gi/value.cpp
@@ -21,27 +21,34 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
-
-#include <mozilla/Unused.h>
-
-#include <util/log.h>
-
-#include "foreign.h"
-#include "value.h"
-#include "closure.h"
-#include "arg.h"
-#include "param.h"
-#include "object.h"
-#include "fundamental.h"
-#include "boxed.h"
-#include "union.h"
-#include "gtype.h"
-#include "gerror.h"
-#include "gjs/context-private.h"
-#include "gjs/jsapi-wrapper.h"
+#include <limits.h>  // for SCHAR_MAX, SCHAR_MIN, UCHAR_MAX
+#include <stdint.h>
+#include <string.h>  // for memset
 
 #include <girepository.h>
+#include <glib-object.h>
+#include <glib.h>
+
+#include "gjs/jsapi-wrapper.h"
+#include "mozilla/Unused.h"
+
+#include "gi/arg.h"
+#include "gi/boxed.h"
+#include "gi/closure.h"
+#include "gi/foreign.h"
+#include "gi/fundamental.h"
+#include "gi/gerror.h"
+#include "gi/gtype.h"
+#include "gi/object.h"
+#include "gi/param.h"
+#include "gi/union.h"
+#include "gi/value.h"
+#include "gi/wrapperutils.h"
+#include "gjs/atoms.h"
+#include "gjs/context-private.h"
+#include "gjs/context.h"
+#include "gjs/jsapi-util.h"
+#include "util/log.h"
 
 GJS_JSAPI_RETURN_CONVENTION
 static bool gjs_value_from_g_value_internal(JSContext             *context,
diff --git a/gi/value.h b/gi/value.h
index dab779a2..d929c9e3 100644
--- a/gi/value.h
+++ b/gi/value.h
@@ -24,10 +24,10 @@
 #ifndef GI_VALUE_H_
 #define GI_VALUE_H_
 
-#include <stdbool.h>
 #include <glib-object.h>
 
-#include "gjs/jsapi-util.h"
+#include "gjs/jsapi-wrapper.h"
+
 #include "gjs/macros.h"
 
 GJS_JSAPI_RETURN_CONVENTION
diff --git a/gi/wrapperutils.cpp b/gi/wrapperutils.cpp
index d5bb72ba..b5428c17 100644
--- a/gi/wrapperutils.cpp
+++ b/gi/wrapperutils.cpp
@@ -21,13 +21,17 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
+#include <girepository.h>
+#include <glib-object.h>
 
-#include <string.h>
+#include "gjs/jsapi-wrapper.h"
 
 #include "gi/function.h"
+#include "gi/gtype.h"
 #include "gi/wrapperutils.h"
+#include "gjs/atoms.h"
 #include "gjs/context-private.h"
+#include "gjs/jsapi-util.h"
 
 /* Default spidermonkey toString is worthless.  Replace it
  * with something that gives us both the introspection name
diff --git a/gi/wrapperutils.h b/gi/wrapperutils.h
index 80d71459..95666216 100644
--- a/gi/wrapperutils.h
+++ b/gi/wrapperutils.h
@@ -25,8 +25,20 @@
 #ifndef GI_WRAPPERUTILS_H_
 #define GI_WRAPPERUTILS_H_
 
+#include <stdint.h>
+
+#include <new>
+#include <string>
+
+#include <girepository.h>
+#include <glib-object.h>
+#include <glib.h>
+
+#include "gjs/jsapi-wrapper.h"
+
+#include "gjs/atoms.h"
 #include "gjs/context-private.h"
-#include "gjs/jsapi-class.h"
+#include "gjs/jsapi-class.h"  // IWYU pragma: keep
 #include "gjs/jsapi-util.h"
 #include "gjs/macros.h"
 #include "util/log.h"
diff --git a/gjs/atoms.cpp b/gjs/atoms.cpp
index 9c8be155..f8f968a3 100644
--- a/gjs/atoms.cpp
+++ b/gjs/atoms.cpp
@@ -24,9 +24,10 @@
 
 #define GJS_USE_ATOM_FOREACH
 
-#include "gjs/atoms.h"
 #include "gjs/jsapi-wrapper.h"
 
+#include "gjs/atoms.h"
+
 bool GjsAtom::init(JSContext* cx, const char* str) {
     JSString* s = JS_AtomizeAndPinString(cx, str);
     if (!s)
diff --git a/gjs/atoms.h b/gjs/atoms.h
index dbe536a1..77cc6226 100644
--- a/gjs/atoms.h
+++ b/gjs/atoms.h
@@ -26,6 +26,7 @@
 #define GJS_ATOMS_H_
 
 #include "gjs/jsapi-wrapper.h"
+
 #include "gjs/macros.h"
 
 // clang-format off
diff --git a/gjs/byteArray.cpp b/gjs/byteArray.cpp
index 7d878c7c..d034a418 100644
--- a/gjs/byteArray.cpp
+++ b/gjs/byteArray.cpp
@@ -21,14 +21,22 @@
  * IN THE SOFTWARE.
  */
 
+#include <stdint.h>
+#include <string.h>  // for strcmp, memchr, strlen
+
+#include <girepository.h>
+#include <glib-object.h>
 #include <glib.h>
 
-#include "byteArray.h"
+#include "gjs/jsapi-wrapper.h"
+
 #include "gi/boxed.h"
+#include "gjs/atoms.h"
+#include "gjs/byteArray.h"
 #include "gjs/context-private.h"
 #include "gjs/deprecation.h"
-#include "jsapi-util-args.h"
-#include "jsapi-wrapper.h"
+#include "gjs/jsapi-util-args.h"
+#include "gjs/jsapi-util.h"
 
 /* Callbacks to use with JS_NewExternalArrayBuffer() */
 
diff --git a/gjs/byteArray.h b/gjs/byteArray.h
index 714bc7bc..e9899748 100644
--- a/gjs/byteArray.h
+++ b/gjs/byteArray.h
@@ -24,10 +24,12 @@
 #ifndef GJS_BYTEARRAY_H_
 #define GJS_BYTEARRAY_H_
 
-#include <stdbool.h>
+#include <stddef.h>  // for size_t
+
 #include <glib.h>
 
-#include "gjs/jsapi-util.h"
+#include "gjs/jsapi-wrapper.h"
+
 #include "gjs/macros.h"
 
 GJS_JSAPI_RETURN_CONVENTION
diff --git a/gjs/console.cpp b/gjs/console.cpp
index 2f813c7c..6c10d532 100644
--- a/gjs/console.cpp
+++ b/gjs/console.cpp
@@ -21,12 +21,19 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
-#include <string.h>
-#include <stdlib.h>
-#include <locale.h>
+#include <config.h>  // for PACKAGE_STRING
+
+#include <locale.h>  // for setlocale, LC_ALL
+#include <stdlib.h>  // for exit
+#include <string.h>  // for strcmp, strlen
+
+#ifdef HAVE_UNISTD_H
+#    include <unistd.h>  // for close
+#endif
 
 #include <gio/gio.h>
+#include <glib-object.h>
+#include <glib.h>
 
 #include <gjs/gjs.h>
 
diff --git a/gjs/context-private.h b/gjs/context-private.h
index 262cadb1..f3a528c9 100644
--- a/gjs/context-private.h
+++ b/gjs/context-private.h
@@ -24,18 +24,23 @@
 #ifndef GJS_CONTEXT_PRIVATE_H_
 #define GJS_CONTEXT_PRIVATE_H_
 
-#include <inttypes.h>
+#include <stdint.h>
+#include <sys/types.h>  // for ssize_t
 
+#include <type_traits>  // for is_same
 #include <unordered_map>
 
-#include "context.h"
-#include "gjs/atoms.h"
-#include "jsapi-util.h"
-#include "jsapi-wrapper.h"
+#include <glib-object.h>
+#include <glib.h>
 
+#include "gjs/jsapi-wrapper.h"
 #include "js/GCHashTable.h"
-#include "js/GCPolicyAPI.h"
-#include "js/SweepingAPI.h"
+
+#include "gjs/atoms.h"
+#include "gjs/context.h"
+#include "gjs/jsapi-util.h"
+#include "gjs/macros.h"
+#include "gjs/profiler.h"
 
 using JobQueue = JS::GCVector<JS::Heap<JSObject*>, 0, js::SystemAllocPolicy>;
 using ObjectInitList =
diff --git a/gjs/context.cpp b/gjs/context.cpp
index 8f0dc56c..f14846d5 100644
--- a/gjs/context.cpp
+++ b/gjs/context.cpp
@@ -23,46 +23,52 @@
 
 #include <config.h>
 
-#include <signal.h>
-#include <sys/types.h>
+#include <signal.h>  // for sigaction, SIGUSR1, sa_handler
+#include <stdint.h>
+#include <stdio.h>      // for FILE, fclose, size_t
+#include <string.h>     // for memset
+#include <sys/types.h>  // IWYU pragma: keep
 
-#include <array>
-#include <codecvt>
-#include <locale>
+#ifdef HAVE_UNISTD_H
+#    include <unistd.h>  // for getpid
+#endif
+
+#include <new>
+#include <string>  // for u16string
 #include <unordered_map>
+#include <utility>  // for move
 
 #include <gio/gio.h>
-
-#include "byteArray.h"
-#include "context-private.h"
-#include "engine.h"
-#include "gi/object.h"
-#include "gi/private.h"
-#include "gi/repo.h"
-#include "gjs/error-types.h"
-#include "global.h"
-#include "importer.h"
-#include "jsapi-util.h"
-#include "jsapi-wrapper.h"
-#include "mem.h"
-#include "native.h"
-#include "profiler-private.h"
-
-#include <modules/modules.h>
-
-#include <util/log.h>
-#include "util/misc.h"
+#include <girepository.h>
+#include <glib-object.h>
+#include <glib.h>
 
 #ifdef G_OS_WIN32
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 #endif
 
-#ifdef HAVE_UNISTD_H
-#    include <unistd.h>
-#endif
+#include "gjs/jsapi-wrapper.h"
+#include "js/GCHashTable.h"  // for WeakCache
 
-#include <string.h>
+#include "gi/object.h"
+#include "gi/private.h"
+#include "gi/repo.h"
+#include "gjs/atoms.h"
+#include "gjs/byteArray.h"
+#include "gjs/context-private.h"
+#include "gjs/context.h"
+#include "gjs/engine.h"
+#include "gjs/error-types.h"
+#include "gjs/global.h"
+#include "gjs/importer.h"
+#include "gjs/jsapi-util.h"
+#include "gjs/mem.h"
+#include "gjs/native.h"
+#include "gjs/profiler-private.h"
+#include "gjs/profiler.h"
+#include "modules/modules.h"
+#include "util/log.h"
 
 static void     gjs_context_dispose           (GObject               *object);
 static void     gjs_context_finalize          (GObject               *object);
diff --git a/gjs/context.h b/gjs/context.h
index 5ac5e65e..a02deb0b 100644
--- a/gjs/context.h
+++ b/gjs/context.h
@@ -28,8 +28,11 @@
 #    error "Only <gjs/gjs.h> can be included directly."
 #endif
 
-#include <stdbool.h>
+#include <stdbool.h>    /* IWYU pragma: keep */
+#include <sys/signal.h> /* for siginfo_t */
+
 #include <glib-object.h>
+#include <glib.h>
 
 #include <gjs/macros.h>
 #include <gjs/profiler.h>
diff --git a/gjs/coverage.cpp b/gjs/coverage.cpp
index f02472d5..ce7292c8 100644
--- a/gjs/coverage.cpp
+++ b/gjs/coverage.cpp
@@ -23,17 +23,23 @@
  * Authored By: Sam Spilsbury <sam endlessm com>
  */
 
-#include <sys/stat.h>
+#include <stdlib.h>  // for free, size_t
+#include <string.h>  // for strcmp, strlen
+
+#include <new>
+
 #include <gio/gio.h>
+#include <glib-object.h>
 
-#include <gjs/context.h>
+#include "gjs/jsapi-wrapper.h"
 
-#include "coverage.h"
+#include "gjs/atoms.h"
 #include "gjs/context-private.h"
-#include "gjs/error-types.h"
-#include "global.h"
-#include "importer.h"
-#include "jsapi-util-args.h"
+#include "gjs/context.h"
+#include "gjs/coverage.h"
+#include "gjs/global.h"
+#include "gjs/jsapi-util.h"
+#include "gjs/macros.h"
 
 struct _GjsCoverage {
     GObject parent;
diff --git a/gjs/coverage.h b/gjs/coverage.h
index 3e93a339..75acf4bb 100644
--- a/gjs/coverage.h
+++ b/gjs/coverage.h
@@ -30,11 +30,12 @@
 #    error "Only <gjs/gjs.h> can be included directly."
 #endif
 
-#include <glib-object.h>
 #include <gio/gio.h>
+#include <glib-object.h>
+#include <glib.h> /* for G_BEGIN_DECLS, G_END_DECLS */
 
-#include "context.h"
-#include "gjs/macros.h"
+#include <gjs/context.h>
+#include <gjs/macros.h>
 
 G_BEGIN_DECLS
 
diff --git a/gjs/debugger.cpp b/gjs/debugger.cpp
index 43723829..05db7ced 100644
--- a/gjs/debugger.cpp
+++ b/gjs/debugger.cpp
@@ -22,20 +22,18 @@
  * Authored By: Philip Chimento <philip chimento gmail com>
  */
 
-#include <gio/gio.h>
+#include <config.h>  // for HAVE_READLINE_READLINE_H, HAVE_UNISTD_H
 
-#include "gjs/context-private.h"
-#include "gjs/global.h"
-#include "gjs/jsapi-util-args.h"
+#include <stdint.h>
+#include <stdio.h>  // for feof, fflush, fgets, stdin, stdout
 
 #ifdef HAVE_READLINE_READLINE_H
-#include <readline/history.h>
-#include <readline/readline.h>
-#include <stdio.h>
+#    include <readline/history.h>
+#    include <readline/readline.h>
 #endif
 
 #ifdef HAVE_UNISTD_H
-#    include <unistd.h>
+#    include <unistd.h>  // for isatty, STDIN_FILENO
 #elif defined(XP_WIN)
 #    include <io.h>
 #    ifndef STDIN_FILENO
@@ -43,6 +41,18 @@
 #    endif
 #endif
 
+#include <glib.h>
+
+#include "gjs/jsapi-wrapper.h"
+
+#include "gjs/atoms.h"
+#include "gjs/context-private.h"
+#include "gjs/context.h"
+#include "gjs/global.h"
+#include "gjs/jsapi-util-args.h"
+#include "gjs/jsapi-util.h"
+#include "gjs/macros.h"
+
 GJS_JSAPI_RETURN_CONVENTION
 static bool quit(JSContext* cx, unsigned argc, JS::Value* vp) {
     JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
diff --git a/gjs/deprecation.cpp b/gjs/deprecation.cpp
index 5431c435..b6b9ca0f 100644
--- a/gjs/deprecation.cpp
+++ b/gjs/deprecation.cpp
@@ -21,13 +21,18 @@
  * IN THE SOFTWARE.
  */
 
-#include <string>
-#include <unordered_set>
+#include <cstddef>        // for size_t
+#include <string>         // for string
+#include <unordered_set>  // for unordered_set
+#include <utility>        // for hash, move
+
+#include <glib.h>  // for g_warning
+
+#include "gjs/jsapi-wrapper.h"
 
-#include "gjs/context-private.h"
 #include "gjs/deprecation.h"
 #include "gjs/jsapi-util.h"
-#include "gjs/jsapi-wrapper.h"
+#include "gjs/macros.h"
 
 const char* messages[] = {
     // None:
diff --git a/gjs/deprecation.h b/gjs/deprecation.h
index a76d9d35..14921972 100644
--- a/gjs/deprecation.h
+++ b/gjs/deprecation.h
@@ -24,7 +24,7 @@
 #ifndef GJS_DEPRECATION_H_
 #define GJS_DEPRECATION_H_
 
-#include "gjs/jsapi-wrapper.h"
+struct JSContext;
 
 enum GjsDeprecationMessageId {
     None,
diff --git a/gjs/engine.cpp b/gjs/engine.cpp
index 3ce16553..80c892a8 100644
--- a/gjs/engine.cpp
+++ b/gjs/engine.cpp
@@ -21,24 +21,29 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
+#include <stdint.h>
+
+#ifdef G_OS_WIN32
+#    define WIN32_LEAN_AND_MEAN
+#    include <windows.h>
+#endif
+
+#include <utility>  // for move
 
 #include <gio/gio.h>
+#include <glib.h>
 
-#include "jsapi-wrapper.h"
-#include <js/Initialization.h>
+#include "gjs/jsapi-wrapper.h"
+#include "js/Initialization.h"  // for JS_Init, JS_ShutDown
+#include "mozilla/UniquePtr.h"
 
-#include "context-private.h"
-#include "engine.h"
 #include "gi/object.h"
-#include "jsapi-util.h"
+#include "gjs/context-private.h"
+#include "gjs/engine.h"
+#include "gjs/jsapi-util.h"
+#include "gjs/macros.h"
 #include "util/log.h"
 
-#ifdef G_OS_WIN32
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#endif
-
 /* Implementations of locale-specific operations; these are used
  * in the implementation of String.localeCompare(), Date.toLocaleDateString(),
  * and so forth. We take the straight-forward approach of converting
diff --git a/gjs/engine.h b/gjs/engine.h
index 250255fe..a87ee273 100644
--- a/gjs/engine.h
+++ b/gjs/engine.h
@@ -24,8 +24,11 @@
 #ifndef GJS_ENGINE_H_
 #define GJS_ENGINE_H_
 
-#include "gjs/context-private.h"
-#include "jsapi-wrapper.h"
+#include <stddef.h>  // for size_t
+
+#include "gjs/jsapi-wrapper.h"
+
+class GjsContextPrivate;
 
 JSContext* gjs_create_js_context(GjsContextPrivate* uninitialized_gjs);
 
diff --git a/gjs/error-types.cpp b/gjs/error-types.cpp
index 0abf7545..86cb8789 100644
--- a/gjs/error-types.cpp
+++ b/gjs/error-types.cpp
@@ -21,8 +21,6 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
-
 #include <glib-object.h>
 
 #include "gjs/error-types.h"
diff --git a/gjs/error-types.h b/gjs/error-types.h
index bf7fb9a1..a92bfc4a 100644
--- a/gjs/error-types.h
+++ b/gjs/error-types.h
@@ -29,6 +29,7 @@
 #endif
 
 #include <glib-object.h>
+#include <glib.h>
 
 #include <gjs/macros.h>
 
diff --git a/gjs/global.cpp b/gjs/global.cpp
index f9e6b869..5e90da46 100644
--- a/gjs/global.cpp
+++ b/gjs/global.cpp
@@ -23,14 +23,17 @@
  * IN THE SOFTWARE.
  */
 
-#include <gio/gio.h>
+#include <stddef.h>  // for size_t
 
+#include <glib.h>
+
+#include "gjs/jsapi-wrapper.h"
+
+#include "gjs/atoms.h"
 #include "gjs/context-private.h"
 #include "gjs/engine.h"
-#include "global.h"
-#include "importer.h"
-#include "jsapi-util.h"
-#include "jsapi-wrapper.h"
+#include "gjs/global.h"
+#include "gjs/jsapi-util.h"
 
 GJS_JSAPI_RETURN_CONVENTION
 static bool
diff --git a/gjs/global.h b/gjs/global.h
index 882f6bd4..9470be53 100644
--- a/gjs/global.h
+++ b/gjs/global.h
@@ -24,10 +24,9 @@
 #ifndef GJS_GLOBAL_H_
 #define GJS_GLOBAL_H_
 
-#include <glib.h>
+#include "gjs/jsapi-wrapper.h"
 
 #include "gjs/macros.h"
-#include "jsapi-wrapper.h"
 
 typedef enum {
     GJS_GLOBAL_SLOT_IMPORTS,
diff --git a/gjs/importer.cpp b/gjs/importer.cpp
index a7e888a1..722cbbb1 100644
--- a/gjs/importer.cpp
+++ b/gjs/importer.cpp
@@ -21,29 +21,36 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
+#include <string.h>  // for size_t, strcmp, strlen
+
+#ifdef G_OS_WIN32
+#    define WIN32_LEAN_AND_MEAN
+#    include <windows.h>
+#endif
+
+#include <memory>   // for allocator_traits<>::value_type
+#include <utility>  // for move
+#include <vector>   // for vector
 
 #include <gio/gio.h>
+#include <glib-object.h>
+#include <glib.h>
 
-#include <vector>
+#include "gjs/jsapi-wrapper.h"
+#include "mozilla/UniquePtr.h"
 
+#include "gjs/atoms.h"
 #include "gjs/context-private.h"
+#include "gjs/global.h"
+#include "gjs/importer.h"
+#include "gjs/jsapi-class.h"
+#include "gjs/jsapi-util.h"
 #include "gjs/mem-private.h"
-#include "importer.h"
-#include "jsapi-class.h"
-#include "jsapi-wrapper.h"
-#include "module.h"
-#include "native.h"
+#include "gjs/module.h"
+#include "gjs/native.h"
 #include "util/log.h"
 #include "util/misc.h"
 
-#ifdef G_OS_WIN32
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#endif
-
-#include <string.h>
-
 #define MODULE_INIT_FILENAME "__init__.js"
 
 static char **gjs_search_path = NULL;
diff --git a/gjs/importer.h b/gjs/importer.h
index 4a8ec1d4..c178bb83 100644
--- a/gjs/importer.h
+++ b/gjs/importer.h
@@ -24,10 +24,8 @@
 #ifndef GJS_IMPORTER_H_
 #define GJS_IMPORTER_H_
 
-#include <stdbool.h>
-#include <glib.h>
+#include "gjs/jsapi-wrapper.h"
 
-#include "gjs/jsapi-util.h"
 #include "gjs/macros.h"
 
 GJS_JSAPI_RETURN_CONVENTION
diff --git a/gjs/jsapi-class.h b/gjs/jsapi-class.h
index 3a628972..c090336f 100644
--- a/gjs/jsapi-class.h
+++ b/gjs/jsapi-class.h
@@ -24,12 +24,15 @@
 #ifndef GJS_JSAPI_CLASS_H_
 #define GJS_JSAPI_CLASS_H_
 
-#include "gi/wrapperutils.h"
-#include "gjs/context-private.h"
-#include "global.h"
-#include "jsapi-util.h"
-#include "jsapi-wrapper.h"
-#include "util/log.h"
+#include <glib-object.h>
+#include <glib.h>
+
+#include "gjs/jsapi-wrapper.h"
+
+#include "gi/wrapperutils.h"  // IWYU pragma: keep
+#include "gjs/global.h"       // IWYU pragma: keep
+#include "gjs/jsapi-util.h"
+#include "gjs/macros.h"
 
 GJS_JSAPI_RETURN_CONVENTION
 bool gjs_init_class_dynamic(
diff --git a/gjs/jsapi-dynamic-class.cpp b/gjs/jsapi-dynamic-class.cpp
index fa20092f..43365bb3 100644
--- a/gjs/jsapi-dynamic-class.cpp
+++ b/gjs/jsapi-dynamic-class.cpp
@@ -22,18 +22,17 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
+#include <string.h>  // for strlen
 
-#include <util/log.h>
-#include <util/misc.h>
+#include <glib.h>
 
-#include "gjs/context-private.h"
-#include "jsapi-class.h"
-#include "jsapi-util.h"
-#include "jsapi-wrapper.h"
+#include "gjs/jsapi-wrapper.h"
 
-#include <string.h>
-#include <math.h>
+#include "gjs/atoms.h"
+#include "gjs/context-private.h"
+#include "gjs/jsapi-class.h"  // IWYU pragma: keep
+#include "gjs/jsapi-util.h"
+#include "gjs/macros.h"
 
 /* Reserved slots of JSNative accessor wrappers */
 enum {
diff --git a/gjs/jsapi-util-args.h b/gjs/jsapi-util-args.h
index 99f39f59..9419acbe 100644
--- a/gjs/jsapi-util-args.h
+++ b/gjs/jsapi-util-args.h
@@ -26,12 +26,16 @@
 #ifndef GJS_JSAPI_UTIL_ARGS_H_
 #define GJS_JSAPI_UTIL_ARGS_H_
 
-#include <type_traits>
+#include <stdint.h>
+
+#include <type_traits>  // for enable_if, is_enum, is_same
 
 #include <glib.h>
 
-#include "jsapi-util.h"
-#include "jsapi-wrapper.h"
+#include "gjs/jsapi-wrapper.h"
+
+#include "gjs/jsapi-util.h"
+#include "gjs/macros.h"
 
 GJS_ALWAYS_INLINE GJS_USE static inline bool check_nullable(
     const char*& fchar, const char*& fmt_string) {
diff --git a/gjs/jsapi-util-error.cpp b/gjs/jsapi-util-error.cpp
index dcd9d78d..391234e9 100644
--- a/gjs/jsapi-util-error.cpp
+++ b/gjs/jsapi-util-error.cpp
@@ -21,17 +21,17 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
+#include <stdarg.h>
 
-#include "gi/gerror.h"
-#include "gjs/context-private.h"
-#include "jsapi-util.h"
-#include "jsapi-wrapper.h"
-#include "util/misc.h"
+#include <glib.h>
 
-#include <util/log.h>
+#include "gjs/jsapi-wrapper.h"
 
-#include <string.h>
+#include "gjs/atoms.h"
+#include "gjs/context-private.h"
+#include "gjs/jsapi-util.h"
+#include "util/log.h"
+#include "util/misc.h"
 
 /*
  * See:
diff --git a/gjs/jsapi-util-root.h b/gjs/jsapi-util-root.h
index 1457387d..2fd79681 100644
--- a/gjs/jsapi-util-root.h
+++ b/gjs/jsapi-util-root.h
@@ -24,12 +24,20 @@
 #ifndef GJS_JSAPI_UTIL_ROOT_H_
 #define GJS_JSAPI_UTIL_ROOT_H_
 
-#include <glib.h>
+#include <stdint.h>  // for uintptr_t
+
+#include <cstddef>  // for nullptr_t
+#include <new>
+#include <type_traits>  // for enable_if_t, is_pointer
+
 #include <glib-object.h>
+#include <glib.h>
+
+#include "gjs/jsapi-wrapper.h"
 
 #include "gjs/context-private.h"
 #include "gjs/context.h"
-#include "gjs/jsapi-wrapper.h"
+#include "gjs/macros.h"
 #include "util/log.h"
 
 /* jsapi-util-root.h - Utilities for dealing with the lifetime and ownership of
diff --git a/gjs/jsapi-util-string.cpp b/gjs/jsapi-util-string.cpp
index e1107f95..06b56507 100644
--- a/gjs/jsapi-util-string.cpp
+++ b/gjs/jsapi-util-string.cpp
@@ -21,16 +21,21 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
+#include <stdint.h>
+#include <string.h>     // for size_t, strlen
+#include <sys/types.h>  // for ssize_t
 
-#include <algorithm>
-#include <iomanip>
-#include <sstream>
-#include <string>
-#include <string.h>
+#include <algorithm>  // for copy
+#include <iomanip>    // for operator<<, setfill, setw
+#include <sstream>    // for operator<<, basic_ostream, ostring...
+#include <string>     // for allocator, char_traits
 
-#include "jsapi-util.h"
-#include "jsapi-wrapper.h"
+#include <glib.h>
+
+#include "gjs/jsapi-wrapper.h"
+
+#include "gjs/jsapi-util.h"
+#include "gjs/macros.h"
 
 char* gjs_hyphen_to_underscore(const char* str) {
     char *s = g_strdup(str);
diff --git a/gjs/jsapi-util.cpp b/gjs/jsapi-util.cpp
index 8257d448..c365c7f8 100644
--- a/gjs/jsapi-util.cpp
+++ b/gjs/jsapi-util.cpp
@@ -22,29 +22,22 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
-
-#include <math.h>
-#include <string.h>
-
-#include <codecvt>
-#include <locale>
-
-#include "jsapi-wrapper.h"
-#include <js/GCAPI.h>
-#include <js/Printf.h>
+#include <stdio.h>   // for sscanf
+#include <string.h>  // for strlen
 
 #ifdef XP_WIN
 #    define WIN32_LEAN_AND_MEAN
 #    include <windows.h>
 #endif
 
+#include <codecvt>  // for codecvt_utf8_utf16
+#include <locale>   // for wstring_convert
+
+#include "gjs/jsapi-wrapper.h"
+
+#include "gjs/atoms.h"
 #include "gjs/context-private.h"
-#include "gjs/error-types.h"
-#include "gjs/jsapi-class.h"
 #include "gjs/jsapi-util.h"
-#include "util/log.h"
-#include "util/misc.h"
 
 static void
 throw_property_lookup_error(JSContext       *cx,
diff --git a/gjs/jsapi-util.h b/gjs/jsapi-util.h
index 8ee1874b..06f57b5b 100644
--- a/gjs/jsapi-util.h
+++ b/gjs/jsapi-util.h
@@ -24,16 +24,20 @@
 #ifndef GJS_JSAPI_UTIL_H_
 #define GJS_JSAPI_UTIL_H_
 
-#include <memory>
-#include <string>
-#include <stdbool.h>
+#include <stddef.h>  // for size_t
+#include <stdint.h>
+#include <sys/types.h>  // for ssize_t
 
+#include <memory>  // for unique_ptr
+#include <string>  // for string, u16string
+
+#include <girepository.h>
 #include <glib-object.h>
+#include <glib.h>
 
-#include "gi/gtype.h"
-#include "gjs/macros.h"
-#include "jsapi-wrapper.h"
+#include "gjs/jsapi-wrapper.h"
 
+#include "gjs/macros.h"
 
 struct GjsAutoTakeOwnership {};
 
diff --git a/gjs/jsapi-wrapper.h b/gjs/jsapi-wrapper.h
index 0c27918e..fb17b710 100644
--- a/gjs/jsapi-wrapper.h
+++ b/gjs/jsapi-wrapper.h
@@ -38,8 +38,12 @@
 #if defined(__clang__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
 #pragma GCC system_header
 #endif
+// COMPAT: These are the headers that cause compiler warnings and need to be
+// marked as system headers.
+// IWYU pragma: begin_exports
+#include <js/Conversions.h>
 #include <jsapi.h>
 #include <jsfriendapi.h>
-#include <js/Conversions.h>
+// IWYU pragma: end_exports
 
 #endif  // GJS_JSAPI_WRAPPER_H_
diff --git a/gjs/macros.h b/gjs/macros.h
index e2066eed..a0090d1a 100644
--- a/gjs/macros.h
+++ b/gjs/macros.h
@@ -24,7 +24,7 @@
 #ifndef GJS_MACROS_H_
 #define GJS_MACROS_H_
 
-#include <glib.h>
+#include <glib.h> /* IWYU pragma: keep */
 
 #ifdef G_OS_WIN32
 # ifdef GJS_COMPILATION
diff --git a/gjs/mem.cpp b/gjs/mem.cpp
index 2f54c30d..3e3acb2f 100644
--- a/gjs/mem.cpp
+++ b/gjs/mem.cpp
@@ -21,7 +21,7 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
+#include <glib.h>
 
 #include "gjs/mem-private.h"
 #include "gjs/mem.h"
diff --git a/gjs/mem.h b/gjs/mem.h
index 720f2995..9940e80e 100644
--- a/gjs/mem.h
+++ b/gjs/mem.h
@@ -28,7 +28,8 @@
 #    error "Only <gjs/gjs.h> can be included directly."
 #endif
 
-#include <stdbool.h>
+#include <stdbool.h> /* IWYU pragma: keep */
+
 #include <glib.h>
 
 #include "gjs/macros.h"
diff --git a/gjs/module.cpp b/gjs/module.cpp
index d223c76d..727c86fc 100644
--- a/gjs/module.cpp
+++ b/gjs/module.cpp
@@ -21,16 +21,20 @@
  * IN THE SOFTWARE.
  */
 
-#include <codecvt>
-#include <locale>
+#include <stddef.h>     // for size_t
+#include <sys/types.h>  // for ssize_t
+
+#include <string>  // for u16string
 
 #include <gio/gio.h>
+#include <glib.h>
+
+#include "gjs/jsapi-wrapper.h"
 
 #include "gjs/context-private.h"
+#include "gjs/jsapi-util.h"
 #include "gjs/mem-private.h"
-#include "jsapi-util.h"
-#include "jsapi-wrapper.h"
-#include "module.h"
+#include "gjs/module.h"
 #include "util/log.h"
 
 class GjsModule {
diff --git a/gjs/module.h b/gjs/module.h
index 717685ca..7952fead 100644
--- a/gjs/module.h
+++ b/gjs/module.h
@@ -26,8 +26,9 @@
 
 #include <gio/gio.h>
 
+#include "gjs/jsapi-wrapper.h"
+
 #include "gjs/macros.h"
-#include "jsapi-wrapper.h"
 
 GJS_JSAPI_RETURN_CONVENTION
 JSObject *
diff --git a/gjs/native.cpp b/gjs/native.cpp
index 4dfe8950..d42e2480 100644
--- a/gjs/native.cpp
+++ b/gjs/native.cpp
@@ -21,13 +21,16 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
-
 #include <string>
+#include <tuple>  // for tie
 #include <unordered_map>
+#include <utility>  // for pair
+
+#include <glib.h>
 
-#include "gjs/jsapi-util.h"
 #include "gjs/jsapi-wrapper.h"
+
+#include "gjs/jsapi-util.h"
 #include "gjs/native.h"
 #include "util/log.h"
 
diff --git a/gjs/native.h b/gjs/native.h
index 0d2f2b1a..f1c68227 100644
--- a/gjs/native.h
+++ b/gjs/native.h
@@ -24,10 +24,8 @@
 #ifndef GJS_NATIVE_H_
 #define GJS_NATIVE_H_
 
-#include <stdbool.h>
-#include <glib.h>
+#include "gjs/jsapi-wrapper.h"
 
-#include "gjs/jsapi-util.h"
 #include "gjs/macros.h"
 
 typedef bool (* GjsDefineModuleFunc) (JSContext              *context,
diff --git a/gjs/profiler-private.h b/gjs/profiler-private.h
index e9a3b914..fde18bd6 100644
--- a/gjs/profiler-private.h
+++ b/gjs/profiler-private.h
@@ -26,9 +26,9 @@
 
 #include <stdint.h>
 
-#include "context.h"
+#include "gjs/context.h"
 #include "gjs/macros.h"
-#include "profiler.h"
+#include "gjs/profiler.h"
 
 GjsProfiler *_gjs_profiler_new(GjsContext *context);
 void _gjs_profiler_free(GjsProfiler *self);
diff --git a/gjs/profiler.cpp b/gjs/profiler.cpp
index 55aa8916..86cf632f 100644
--- a/gjs/profiler.cpp
+++ b/gjs/profiler.cpp
@@ -21,28 +21,30 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
+#include <config.h>  // for ENABLE_PROFILER, HAVE_SYS_SYSCALL_H, HAVE_UNISTD_H
 
-#include <algorithm>
-#include <errno.h>
-#include <memory>
-#include <signal.h>
-#include <sys/types.h>
+#include <sys/signal.h>  // for siginfo_t, sigevent, ...
 
-#include "jsapi-wrapper.h"
-#include <js/ProfilingStack.h>
-
-#include "context.h"
-#include "jsapi-util.h"
-#include "profiler-private.h"
+#include <glib-object.h>
+#include <glib.h>
 
 #ifdef ENABLE_PROFILER
-# include <alloca.h>
+#    include <alloca.h>
+#    include <errno.h>
+#    include <signal.h>  // for sigaction, SIGPROF, sigemptyset
+#    include <stddef.h>  // for size_t
+#    include <stdint.h>
+#    include <stdio.h>      // for sscanf
+#    include <string.h>     // for memcpy, strlen
+#    include <sys/time.h>   // for CLOCK_MONOTONIC
+#    include <sys/types.h>  // for timer_t
+#    include <syscall.h>    // for __NR_gettid
+#    include <time.h>       // for itimerspec, timer_delete, ...
 #    ifdef HAVE_SYS_SYSCALL_H
-#        include <sys/syscall.h>
+#        include <sys/syscall.h>  // IWYU pragma: keep
 #    endif
 #    ifdef HAVE_UNISTD_H
-#        include <unistd.h>
+#        include <unistd.h>  // for getpid, syscall
 #    endif
 #    ifdef G_OS_UNIX
 #        include <glib-unix.h>
@@ -50,6 +52,15 @@
 #    include <sysprof-capture.h>
 #endif
 
+#include "gjs/jsapi-wrapper.h"  // IWYU pragma: keep
+#include "js/ProfilingStack.h"  // for EnableContextProfilingStack, ...
+
+#include "gjs/context.h"
+#include "gjs/jsapi-util.h"
+#include "gjs/macros.h"
+#include "gjs/profiler-private.h"  // IWYU pragma: keep
+#include "gjs/profiler.h"
+
 #define FLUSH_DELAY_SECONDS 3
 
 /*
diff --git a/gjs/profiler.h b/gjs/profiler.h
index 35d00c6d..d3518b87 100644
--- a/gjs/profiler.h
+++ b/gjs/profiler.h
@@ -28,9 +28,10 @@
 #    error "Only <gjs/gjs.h> can be included directly."
 #endif
 
+#include <glib-object.h>
 #include <glib.h>
 
-#include <gjs/context.h>
+#include <gjs/macros.h>
 
 G_BEGIN_DECLS
 
diff --git a/gjs/stack.cpp b/gjs/stack.cpp
index c2c6c0f3..b9684930 100644
--- a/gjs/stack.cpp
+++ b/gjs/stack.cpp
@@ -40,12 +40,14 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
-#include <config.h>
+#include <stdio.h>  // for stderr
+
+#include <glib-object.h>
 #include <glib.h>
-#include <string.h>
-#include "context.h"
-#include "jsapi-util.h"
-#include "jsapi-wrapper.h"
+
+#include "gjs/jsapi-wrapper.h"
+
+#include "gjs/context.h"
 
 void
 gjs_context_print_stack_stderr(GjsContext *context)
diff --git a/installed-tests/minijasmine.cpp b/installed-tests/minijasmine.cpp
index f3f0e49f..52960cce 100644
--- a/installed-tests/minijasmine.cpp
+++ b/installed-tests/minijasmine.cpp
@@ -21,15 +21,15 @@
  * IN THE SOFTWARE.
  */
 
-#include <locale.h>
-#include <unistd.h>
+#include <locale.h>  // for setlocale, LC_ALL
+#include <stdlib.h>  // for exit
 
 #include <gio/gio.h>
 #include <girepository.h>
+#include <glib-object.h>
 #include <glib.h>
-#include <glib/gstdio.h>
 
-#include "gjs/gjs.h"
+#include <gjs/gjs.h>
 
 G_GNUC_NORETURN
 static void
diff --git a/libgjs-private/gjs-gdbus-wrapper.c b/libgjs-private/gjs-gdbus-wrapper.c
index c11b0b0c..17a7c6c8 100644
--- a/libgjs-private/gjs-gdbus-wrapper.c
+++ b/libgjs-private/gjs-gdbus-wrapper.c
@@ -1,10 +1,13 @@
 /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
 /* Copyright 2011 Giovanni Campagna. All Rights Reserved. */
 
-#include <config.h>
-#include <string.h>
+#include <string.h>  // for strcmp
 
-#include "gjs-gdbus-wrapper.h"
+#include <gio/gio.h>
+#include <glib-object.h>
+#include <glib.h>
+
+#include "libgjs-private/gjs-gdbus-wrapper.h"
 
 enum {
     PROP_0,
diff --git a/libgjs-private/gjs-gdbus-wrapper.h b/libgjs-private/gjs-gdbus-wrapper.h
index ebeee5cb..8d704c48 100644
--- a/libgjs-private/gjs-gdbus-wrapper.h
+++ b/libgjs-private/gjs-gdbus-wrapper.h
@@ -23,11 +23,11 @@
 #ifndef LIBGJS_PRIVATE_GJS_GDBUS_WRAPPER_H_
 #define LIBGJS_PRIVATE_GJS_GDBUS_WRAPPER_H_
 
-#include <glib.h>
-#include <glib-object.h>
 #include <gio/gio.h>
+#include <glib-object.h>
+#include <glib.h>
 
-#include <gjs/macros.h>
+#include "gjs/macros.h"
 
 G_BEGIN_DECLS
 
diff --git a/libgjs-private/gjs-gtk-util.c b/libgjs-private/gjs-gtk-util.c
index f15bfd5f..55840a6f 100644
--- a/libgjs-private/gjs-gtk-util.c
+++ b/libgjs-private/gjs-gtk-util.c
@@ -20,10 +20,13 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
+#include <stddef.h>  // for NULL
+
+#include <glib-object.h>
+#include <glib.h>
 #include <gtk/gtk.h>
 
-#include "gjs-gtk-util.h"
+#include "libgjs-private/gjs-gtk-util.h"
 
 void
 gjs_gtk_container_child_set_property (GtkContainer *container,
diff --git a/libgjs-private/gjs-gtk-util.h b/libgjs-private/gjs-gtk-util.h
index 24f3a99b..e2785004 100644
--- a/libgjs-private/gjs-gtk-util.h
+++ b/libgjs-private/gjs-gtk-util.h
@@ -23,13 +23,15 @@
 #ifndef LIBGJS_PRIVATE_GJS_GTK_UTIL_H_
 #define LIBGJS_PRIVATE_GJS_GTK_UTIL_H_
 
-#include "config.h"
+#include <config.h> /* for ENABLE_GTK */
 
 #ifdef ENABLE_GTK
 
-#include <gtk/gtk.h>
+#    include <glib-object.h>
+#    include <glib.h>
+#    include <gtk/gtk.h>
 
-#include <gjs/macros.h>
+#    include "gjs/macros.h"
 
 G_BEGIN_DECLS
 
diff --git a/libgjs-private/gjs-util.c b/libgjs-private/gjs-util.c
index c110cc93..f27e4c76 100644
--- a/libgjs-private/gjs-util.c
+++ b/libgjs-private/gjs-util.c
@@ -20,22 +20,28 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
+#include <config.h> /* IWYU pragma: keep */
 
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
+#include <locale.h>    /* for setlocale */
+#include <stddef.h>    /* for size_t */
+#include <sys/types.h> /* IWYU pragma: keep */
 
 #include <gio/gio.h>
+#include <glib-object.h>
 #include <glib.h>
-#include <glib/gi18n.h>
-
-#include "gjs-util.h"
+#include <glib/gi18n.h> /* for bindtextdomain, bind_textdomain_codeset, textdomain */
 
 #ifdef G_OS_UNIX
-#    include <glib-unix.h>
+#    include <errno.h>
+#    include <fcntl.h> /* for FD_CLOEXEC */
+#    include <stdarg.h>
+#    include <unistd.h> /* for close, write */
+
+#    include <glib-unix.h> /* for g_unix_open_pipe */
 #endif
 
+#include "libgjs-private/gjs-util.h"
+
 char *
 gjs_format_int_alternative_output(int n)
 {
@@ -117,6 +123,8 @@ gjs_param_spec_get_owner_type(GParamSpec *pspec)
     return pspec->owner_type;
 }
 
+#ifdef G_OS_UNIX
+
 // Adapted from glnx_throw_errno_prefix()
 G_GNUC_PRINTF(2, 3)
 static gboolean throw_errno_prefix(GError** error, const char* fmt, ...) {
@@ -148,6 +156,8 @@ static gboolean throw_errno_prefix(GError** error, const char* fmt, ...) {
     return FALSE;
 }
 
+#endif /* G_OS_UNIX */
+
 /**
  * gjs_open_bytes:
  * @bytes: bytes to send to the pipe
diff --git a/libgjs-private/gjs-util.h b/libgjs-private/gjs-util.h
index 43b5e8cc..a1c907c1 100644
--- a/libgjs-private/gjs-util.h
+++ b/libgjs-private/gjs-util.h
@@ -24,10 +24,11 @@
 #define LIBGJS_PRIVATE_GJS_UTIL_H_
 
 #include <locale.h>
-#include <glib.h>
+
 #include <glib-object.h>
+#include <glib.h>
 
-#include <gjs/macros.h>
+#include "gjs/macros.h"
 
 G_BEGIN_DECLS
 
diff --git a/modules/cairo-context.cpp b/modules/cairo-context.cpp
index 2d54228d..963d7663 100644
--- a/modules/cairo-context.cpp
+++ b/modules/cairo-context.cpp
@@ -20,19 +20,22 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
-
 #include <vector>
 
+#include <cairo-gobject.h>
+#include <cairo.h>
+#include <girepository.h>
+#include <glib.h>
+
+#include "gjs/jsapi-wrapper.h"
+
+#include "gi/arg.h"
 #include "gi/foreign.h"
 #include "gjs/jsapi-class.h"
 #include "gjs/jsapi-util-args.h"
-#include "gjs/jsapi-wrapper.h"
+#include "gjs/jsapi-util.h"
 #include "gjs/macros.h"
-
-#include <cairo.h>
-#include <cairo-gobject.h>
-#include "cairo-private.h"
+#include "modules/cairo-private.h"
 
 #define _GJS_CAIRO_CONTEXT_DEFINE_FUNC_BEGIN(mname)                        \
     GJS_JSAPI_RETURN_CONVENTION                                            \
diff --git a/modules/cairo-gradient.cpp b/modules/cairo-gradient.cpp
index 924f14e9..e6f7461b 100644
--- a/modules/cairo-gradient.cpp
+++ b/modules/cairo-gradient.cpp
@@ -20,13 +20,15 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
+#include <cairo.h>
+
+#include "gjs/jsapi-wrapper.h"
 
 #include "gjs/jsapi-class.h"
 #include "gjs/jsapi-util-args.h"
-#include "gjs/jsapi-wrapper.h"
-#include <cairo.h>
-#include "cairo-private.h"
+#include "gjs/jsapi-util.h"
+#include "gjs/macros.h"
+#include "modules/cairo-private.h"
 
 GJS_DEFINE_PROTO_ABSTRACT_WITH_PARENT("Gradient", cairo_gradient,
                                       cairo_pattern,
diff --git a/modules/cairo-image-surface.cpp b/modules/cairo-image-surface.cpp
index ee463426..f2382e8b 100644
--- a/modules/cairo-image-surface.cpp
+++ b/modules/cairo-image-surface.cpp
@@ -20,14 +20,16 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
+#include <cairo.h>
+#include <glib.h>
+
+#include "gjs/jsapi-wrapper.h"
 
 #include "gjs/jsapi-class.h"
-#include "gjs/jsapi-util.h"
 #include "gjs/jsapi-util-args.h"
-#include "gjs/jsapi-wrapper.h"
-#include <cairo.h>
-#include "cairo-private.h"
+#include "gjs/jsapi-util.h"
+#include "gjs/macros.h"
+#include "modules/cairo-private.h"
 
 GJS_USE
 static JSObject *gjs_cairo_image_surface_get_proto(JSContext *);
diff --git a/modules/cairo-linear-gradient.cpp b/modules/cairo-linear-gradient.cpp
index 7892a1c4..2fca7e3f 100644
--- a/modules/cairo-linear-gradient.cpp
+++ b/modules/cairo-linear-gradient.cpp
@@ -20,13 +20,16 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
+#include <cairo.h>
+#include <glib.h>
+
+#include "gjs/jsapi-wrapper.h"
 
 #include "gjs/jsapi-class.h"
 #include "gjs/jsapi-util-args.h"
-#include "gjs/jsapi-wrapper.h"
-#include <cairo.h>
-#include "cairo-private.h"
+#include "gjs/jsapi-util.h"
+#include "gjs/macros.h"
+#include "modules/cairo-private.h"
 
 GJS_USE
 static JSObject *gjs_cairo_linear_gradient_get_proto(JSContext *);
diff --git a/modules/cairo-module.h b/modules/cairo-module.h
index fdc7e643..36944a0e 100644
--- a/modules/cairo-module.h
+++ b/modules/cairo-module.h
@@ -24,6 +24,7 @@
 #define MODULES_CAIRO_MODULE_H_
 
 #include "gjs/jsapi-wrapper.h"
+
 #include "gjs/macros.h"
 
 GJS_JSAPI_RETURN_CONVENTION
diff --git a/modules/cairo-path.cpp b/modules/cairo-path.cpp
index 46cb905e..a5052515 100644
--- a/modules/cairo-path.cpp
+++ b/modules/cairo-path.cpp
@@ -20,13 +20,15 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
+#include <cairo.h>
+#include <glib.h>
+
+#include "gjs/jsapi-wrapper.h"
 
 #include "gjs/jsapi-class.h"
 #include "gjs/jsapi-util.h"
-#include "gjs/jsapi-wrapper.h"
-#include <cairo.h>
-#include "cairo-private.h"
+#include "gjs/macros.h"
+#include "modules/cairo-private.h"  // IWYU pragma: keep
 
 typedef struct {
     JSContext       *context;
diff --git a/modules/cairo-pattern.cpp b/modules/cairo-pattern.cpp
index 008f49b1..c2a307dc 100644
--- a/modules/cairo-pattern.cpp
+++ b/modules/cairo-pattern.cpp
@@ -20,14 +20,16 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
+#include <cairo-gobject.h>
+#include <cairo.h>
+#include <glib.h>
+
+#include "gjs/jsapi-wrapper.h"
 
 #include "gjs/jsapi-class.h"
 #include "gjs/jsapi-util.h"
-#include "gjs/jsapi-wrapper.h"
-#include <cairo.h>
-#include <cairo-gobject.h>
-#include "cairo-private.h"
+#include "gjs/macros.h"
+#include "modules/cairo-private.h"
 
 typedef struct {
     void            *dummy;
diff --git a/modules/cairo-pdf-surface.cpp b/modules/cairo-pdf-surface.cpp
index 78d430ee..d1862f0a 100644
--- a/modules/cairo-pdf-surface.cpp
+++ b/modules/cairo-pdf-surface.cpp
@@ -20,16 +20,21 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
+#include <cairo-features.h>  // for CAIRO_HAS_PDF_SURFACE
+#include <cairo.h>
 
-#include "gjs/jsapi-class.h"
-#include "gjs/jsapi-util-args.h"
 #include "gjs/jsapi-wrapper.h"
-#include <cairo.h>
-#include "cairo-private.h"
+
+#include "gjs/jsapi-util.h"
 
 #if CAIRO_HAS_PDF_SURFACE
-#include <cairo-pdf.h>
+#    include <cairo-pdf.h>
+#    include <glib.h>
+
+#    include "gjs/jsapi-class.h"
+#    include "gjs/jsapi-util-args.h"
+#    include "gjs/macros.h"
+#    include "modules/cairo-private.h"
 
 GJS_USE
 static JSObject *gjs_cairo_pdf_surface_get_proto(JSContext *);
diff --git a/modules/cairo-private.h b/modules/cairo-private.h
index cb75c7af..7634c76f 100644
--- a/modules/cairo-private.h
+++ b/modules/cairo-private.h
@@ -23,9 +23,13 @@
 #ifndef MODULES_CAIRO_PRIVATE_H_
 #define MODULES_CAIRO_PRIVATE_H_
 
-#include "cairo-module.h"
+#include <cairo-features.h>  // for CAIRO_HAS_PDF_SURFACE, CAIRO_HAS_PS_SURFACE
 #include <cairo.h>
 
+#include "gjs/jsapi-wrapper.h"
+
+#include "gjs/macros.h"
+
 GJS_JSAPI_RETURN_CONVENTION
 bool             gjs_cairo_check_status                 (JSContext       *context,
                                                          cairo_status_t   status,
diff --git a/modules/cairo-ps-surface.cpp b/modules/cairo-ps-surface.cpp
index 863beb71..2d6186fc 100644
--- a/modules/cairo-ps-surface.cpp
+++ b/modules/cairo-ps-surface.cpp
@@ -20,16 +20,21 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
+#include <cairo-features.h>  // for CAIRO_HAS_PS_SURFACE
+#include <cairo.h>
 
-#include "gjs/jsapi-class.h"
-#include "gjs/jsapi-util-args.h"
 #include "gjs/jsapi-wrapper.h"
-#include <cairo.h>
-#include "cairo-private.h"
+
+#include "gjs/jsapi-util.h"
 
 #if CAIRO_HAS_PS_SURFACE
-#include <cairo-ps.h>
+#    include <cairo-ps.h>
+#    include <glib.h>
+
+#    include "gjs/jsapi-class.h"
+#    include "gjs/jsapi-util-args.h"
+#    include "gjs/macros.h"
+#    include "modules/cairo-private.h"
 
 GJS_USE
 static JSObject *gjs_cairo_ps_surface_get_proto(JSContext *);
diff --git a/modules/cairo-radial-gradient.cpp b/modules/cairo-radial-gradient.cpp
index e2db7417..289508cf 100644
--- a/modules/cairo-radial-gradient.cpp
+++ b/modules/cairo-radial-gradient.cpp
@@ -20,13 +20,16 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
+#include <cairo.h>
+#include <glib.h>
+
+#include "gjs/jsapi-wrapper.h"
 
 #include "gjs/jsapi-class.h"
 #include "gjs/jsapi-util-args.h"
-#include "gjs/jsapi-wrapper.h"
-#include <cairo.h>
-#include "cairo-private.h"
+#include "gjs/jsapi-util.h"
+#include "gjs/macros.h"
+#include "modules/cairo-private.h"
 
 GJS_USE
 static JSObject *gjs_cairo_radial_gradient_get_proto(JSContext *);
diff --git a/modules/cairo-region.cpp b/modules/cairo-region.cpp
index 9ebcfc0b..6fd57612 100644
--- a/modules/cairo-region.cpp
+++ b/modules/cairo-region.cpp
@@ -20,17 +20,22 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
+#include <cairo-gobject.h>
+#include <cairo.h>
+#include <girepository.h>
+#include <glib.h>
+
+#include "gjs/jsapi-wrapper.h"
 
+#include "gi/arg.h"
 #include "gi/foreign.h"
+#include "gjs/atoms.h"
 #include "gjs/context-private.h"
 #include "gjs/jsapi-class.h"
 #include "gjs/jsapi-util-args.h"
-#include "gjs/jsapi-wrapper.h"
-
-#include <cairo.h>
-#include <cairo-gobject.h>
-#include "cairo-private.h"
+#include "gjs/jsapi-util.h"
+#include "gjs/macros.h"
+#include "modules/cairo-private.h"
 
 typedef struct {
     JSContext *context;
diff --git a/modules/cairo-solid-pattern.cpp b/modules/cairo-solid-pattern.cpp
index ab66265a..4d3ec524 100644
--- a/modules/cairo-solid-pattern.cpp
+++ b/modules/cairo-solid-pattern.cpp
@@ -20,13 +20,16 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
+#include <cairo.h>
+#include <glib.h>
+
+#include "gjs/jsapi-wrapper.h"
 
 #include "gjs/jsapi-class.h"
 #include "gjs/jsapi-util-args.h"
-#include "gjs/jsapi-wrapper.h"
-#include <cairo.h>
-#include "cairo-private.h"
+#include "gjs/jsapi-util.h"
+#include "gjs/macros.h"
+#include "modules/cairo-private.h"
 
 GJS_USE
 static JSObject *gjs_cairo_solid_pattern_get_proto(JSContext *);
diff --git a/modules/cairo-surface-pattern.cpp b/modules/cairo-surface-pattern.cpp
index ba7dccd5..613b9049 100644
--- a/modules/cairo-surface-pattern.cpp
+++ b/modules/cairo-surface-pattern.cpp
@@ -20,13 +20,16 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
+#include <cairo.h>
+#include <glib.h>
+
+#include "gjs/jsapi-wrapper.h"
 
 #include "gjs/jsapi-class.h"
 #include "gjs/jsapi-util-args.h"
-#include "gjs/jsapi-wrapper.h"
-#include <cairo.h>
-#include "cairo-private.h"
+#include "gjs/jsapi-util.h"
+#include "gjs/macros.h"
+#include "modules/cairo-private.h"
 
 GJS_USE
 static JSObject *gjs_cairo_surface_pattern_get_proto(JSContext *);
diff --git a/modules/cairo-surface.cpp b/modules/cairo-surface.cpp
index a1e0e8d5..a2bb9514 100644
--- a/modules/cairo-surface.cpp
+++ b/modules/cairo-surface.cpp
@@ -20,15 +20,20 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
+#include <cairo-gobject.h>
+#include <cairo.h>
+#include <girepository.h>
+#include <glib.h>
+
+#include "gjs/jsapi-wrapper.h"
 
+#include "gi/arg.h"
 #include "gi/foreign.h"
 #include "gjs/jsapi-class.h"
 #include "gjs/jsapi-util-args.h"
-#include "gjs/jsapi-wrapper.h"
-#include <cairo.h>
-#include <cairo-gobject.h>
-#include "cairo-private.h"
+#include "gjs/jsapi-util.h"
+#include "gjs/macros.h"
+#include "modules/cairo-private.h"
 
 typedef struct {
     void            *dummy;
diff --git a/modules/cairo-svg-surface.cpp b/modules/cairo-svg-surface.cpp
index 601dca94..80937faf 100644
--- a/modules/cairo-svg-surface.cpp
+++ b/modules/cairo-svg-surface.cpp
@@ -20,16 +20,21 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
+#include <cairo-features.h>  // for CAIRO_HAS_SVG_SURFACE
+#include <cairo.h>
 
-#include "gjs/jsapi-class.h"
-#include "gjs/jsapi-util-args.h"
 #include "gjs/jsapi-wrapper.h"
-#include <cairo.h>
-#include "cairo-private.h"
+
+#include "gjs/jsapi-util.h"
 
 #if CAIRO_HAS_SVG_SURFACE
-#include <cairo-svg.h>
+#    include <cairo-svg.h>
+#    include <glib.h>
+
+#    include "gjs/jsapi-class.h"
+#    include "gjs/jsapi-util-args.h"
+#    include "gjs/macros.h"
+#    include "modules/cairo-private.h"
 
 GJS_USE
 static JSObject *gjs_cairo_svg_surface_get_proto(JSContext *);
diff --git a/modules/cairo.cpp b/modules/cairo.cpp
index 4698640d..279b2566 100644
--- a/modules/cairo.cpp
+++ b/modules/cairo.cpp
@@ -20,14 +20,17 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
+#include <cairo-features.h>  // for CAIRO_HAS_PDF_SURFACE, CAIRO_HAS_PS_SURFA...
+#include <cairo.h>
 
-#include "gjs/jsapi-util.h"
 #include "gjs/jsapi-wrapper.h"
-#include "cairo-private.h"
+
+#include "gjs/jsapi-util.h"
+#include "modules/cairo-module.h"  // IWYU pragma: keep
+#include "modules/cairo-private.h"
 
 #ifdef CAIRO_HAS_XLIB_SURFACE
-#include "cairo-xlib.h"
+#    include <cairo-xlib.h>
 
 class XLibConstructor {
  public:
diff --git a/modules/console.cpp b/modules/console.cpp
index d37b568b..3426c99f 100644
--- a/modules/console.cpp
+++ b/modules/console.cpp
@@ -38,27 +38,27 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
-#include <config.h>
+#include <config.h>  // for HAVE_READLINE_READLINE_H
 
-#include <mozilla/Unused.h>
-#include <stdlib.h>
-#include <string.h>
+#include <stdio.h>   // for fputc, fputs, stderr, size_t, fflush
+#include <string.h>  // for strchr
 
 #ifdef HAVE_READLINE_READLINE_H
-#include <stdio.h>
 #include <readline/readline.h>
 #include <readline/history.h>
 #endif
 
 #include <glib.h>
-#include <glib/gprintf.h>
+#include <glib/gprintf.h>  // for g_fprintf
 
-#include <string>
+#include "gjs/jsapi-wrapper.h"
+#include "mozilla/UniquePtr.h"
+#include "mozilla/Unused.h"
 
-#include "console.h"
-#include "gjs/context.h"
+#include "gjs/atoms.h"
 #include "gjs/context-private.h"
-#include "gjs/jsapi-wrapper.h"
+#include "gjs/jsapi-util.h"
+#include "modules/console.h"
 
 enum class PrintErrorKind { Error, Warning, StrictWarning, Note };
 
diff --git a/modules/console.h b/modules/console.h
index 7232566a..59b144a0 100644
--- a/modules/console.h
+++ b/modules/console.h
@@ -24,10 +24,8 @@
 #ifndef MODULES_CONSOLE_H_
 #define MODULES_CONSOLE_H_
 
-#include <config.h>
-#include <glib.h>
+#include "gjs/jsapi-wrapper.h"
 
-#include "gjs/jsapi-util.h"
 #include "gjs/macros.h"
 
 GJS_JSAPI_RETURN_CONVENTION
diff --git a/modules/modules.cpp b/modules/modules.cpp
index a4f4f018..ff8aa24e 100644
--- a/modules/modules.cpp
+++ b/modules/modules.cpp
@@ -21,18 +21,17 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
+#include <config.h>  // for ENABLE_CAIRO
 
 #include "gjs/native.h"
-#include "modules.h"
+#include "modules/console.h"
+#include "modules/modules.h"
+#include "modules/system.h"
 
 #ifdef ENABLE_CAIRO
-#include "cairo-module.h"
+#    include "modules/cairo-module.h"
 #endif
 
-#include "system.h"
-#include "console.h"
-
 void
 gjs_register_static_modules (void)
 {
diff --git a/modules/modules.h b/modules/modules.h
index 2922113e..a244b89f 100644
--- a/modules/modules.h
+++ b/modules/modules.h
@@ -24,10 +24,6 @@
 #ifndef MODULES_MODULES_H_
 #define MODULES_MODULES_H_
 
-#include <config.h>
-#include <glib.h>
-#include "gjs/jsapi-util.h"
-
 void gjs_register_static_modules (void);
 
 #endif  // MODULES_MODULES_H_
diff --git a/modules/system.cpp b/modules/system.cpp
index 6ca99195..f748aac2 100644
--- a/modules/system.cpp
+++ b/modules/system.cpp
@@ -22,22 +22,25 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
+#include <config.h>  // for GJS_VERSION
 
 #include <errno.h>
-#include <string.h>
-#include <sys/types.h>
-#include <time.h>
+#include <stdio.h>   // for FILE, fclose, stdout
+#include <string.h>  // for strerror
+#include <time.h>    // for tzset
 
-#include "gjs/jsapi-wrapper.h"
-#include <js/Date.h>
+#include <glib-object.h>
+#include <glib.h>
 
-#include <gjs/context.h>
+#include "gjs/jsapi-wrapper.h"
+#include "js/Date.h"  // for ResetTimeZone
 
 #include "gi/object.h"
+#include "gjs/atoms.h"
 #include "gjs/context-private.h"
 #include "gjs/jsapi-util-args.h"
-#include "system.h"
+#include "gjs/jsapi-util.h"
+#include "modules/system.h"
 
 /* Note that this cannot be relied on to test whether two objects are the same!
  * SpiderMonkey can move objects around in memory during garbage collection,
diff --git a/modules/system.h b/modules/system.h
index 30e365d4..ed0e3e12 100644
--- a/modules/system.h
+++ b/modules/system.h
@@ -25,10 +25,8 @@
 #ifndef MODULES_SYSTEM_H_
 #define MODULES_SYSTEM_H_
 
-#include <config.h>
-#include <glib.h>
+#include "gjs/jsapi-wrapper.h"
 
-#include "gjs/jsapi-util.h"
 #include "gjs/macros.h"
 
 GJS_JSAPI_RETURN_CONVENTION
diff --git a/test/gjs-test-call-args.cpp b/test/gjs-test-call-args.cpp
index 6a76568b..3e681573 100644
--- a/test/gjs-test-call-args.cpp
+++ b/test/gjs-test-call-args.cpp
@@ -1,10 +1,12 @@
-#include <string.h>
+#include <stdint.h>
+#include <string.h>  // for strlen, strstr
 
 #include <glib.h>
 
-#include "gjs/context.h"
-#include "gjs/jsapi-util-args.h"
 #include "gjs/jsapi-wrapper.h"
+
+#include "gjs/jsapi-util-args.h"
+#include "gjs/jsapi-util.h"
 #include "test/gjs-test-common.h"
 #include "test/gjs-test-utils.h"
 
diff --git a/test/gjs-test-common.cpp b/test/gjs-test-common.cpp
index a4158e55..1535d457 100644
--- a/test/gjs-test-common.cpp
+++ b/test/gjs-test-common.cpp
@@ -24,6 +24,7 @@
 #include <glib.h>
 
 #include "gjs/jsapi-wrapper.h"
+
 #include "test/gjs-test-common.h"
 
 char* gjs_test_get_exception_message(JSContext* cx) {
diff --git a/test/gjs-test-common.h b/test/gjs-test-common.h
index ad0c493b..91f78dcb 100644
--- a/test/gjs-test-common.h
+++ b/test/gjs-test-common.h
@@ -24,7 +24,7 @@
 #ifndef TEST_GJS_TEST_COMMON_H_
 #define TEST_GJS_TEST_COMMON_H_
 
-#include "gjs/jsapi-wrapper.h"
+struct JSContext;
 
 char* gjs_test_get_exception_message(JSContext* cx);
 
diff --git a/test/gjs-test-coverage.cpp b/test/gjs-test-coverage.cpp
index 7c0ede7a..d477d5ec 100644
--- a/test/gjs-test-coverage.cpp
+++ b/test/gjs-test-coverage.cpp
@@ -23,23 +23,19 @@
  * Authored By: Sam Spilsbury <sam endlessm com>
  */
 
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
+#include <errno.h>   // for errno
+#include <stdio.h>   // for sscanf, size_t
+#include <stdlib.h>  // for strtol, atoi, mkdtemp
+#include <string.h>  // for strlen, strstr, strcmp, strncmp, strcspn
 
-#include <sys/types.h>
-#include <fcntl.h>
-#include <ftw.h>
-
-#include <glib.h>
 #include <gio/gio.h>
-#include <gjs/gjs.h>
+#include <glib-object.h>
+#include <glib.h>
 
+#include "gjs/context.h"
 #include "gjs/coverage.h"
 #include "gjs/jsapi-util.h"
-#include "gjs-test-utils.h"
+#include "test/gjs-test-utils.h"  // IWYU pragma: keep
 
 typedef struct _GjsCoverageFixture {
     GjsContext    *context;
diff --git a/test/gjs-test-rooting.cpp b/test/gjs-test-rooting.cpp
index 75bb76da..d50b23b6 100644
--- a/test/gjs-test-rooting.cpp
+++ b/test/gjs-test-rooting.cpp
@@ -1,6 +1,9 @@
-#include "gjs/jsapi-util.h"
+#include <glib.h>
+
+#include "gjs/jsapi-wrapper.h"
+
 #include "gjs/jsapi-util-root.h"
-#include "gjs-test-utils.h"
+#include "test/gjs-test-utils.h"
 
 static GMutex gc_lock;
 static GCond gc_finished;
diff --git a/test/gjs-test-utils.cpp b/test/gjs-test-utils.cpp
index 124e9457..5855364a 100644
--- a/test/gjs-test-utils.cpp
+++ b/test/gjs-test-utils.cpp
@@ -22,13 +22,15 @@
  * IN THE SOFTWARE.
  */
 
+#include <glib-object.h>
 #include <glib.h>
 
+#include "gjs/jsapi-wrapper.h"
+
 #include "gjs/context.h"
 #include "gjs/jsapi-util.h"
-#include "gjs/jsapi-wrapper.h"
-#include "gjs-test-utils.h"
 #include "test/gjs-test-common.h"
+#include "test/gjs-test-utils.h"
 
 void gjs_unit_test_fixture_setup(GjsUnitTestFixture* fx, const void*) {
     fx->gjs_context = gjs_context_new();
diff --git a/test/gjs-test-utils.h b/test/gjs-test-utils.h
index 9c3d7554..6af5d2d9 100644
--- a/test/gjs-test-utils.h
+++ b/test/gjs-test-utils.h
@@ -27,7 +27,9 @@
 #define TEST_GJS_TEST_UTILS_H_
 
 #include "gjs/context.h"
-#include "gjs/jsapi-wrapper.h"
+
+struct JSCompartment;
+struct JSContext;
 
 typedef struct _GjsUnitTestFixture GjsUnitTestFixture;
 struct _GjsUnitTestFixture {
diff --git a/test/gjs-tests.cpp b/test/gjs-tests.cpp
index 3a7f25b3..45ebe243 100644
--- a/test/gjs-tests.cpp
+++ b/test/gjs-tests.cpp
@@ -21,18 +21,20 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
+#include <string.h>  // for size_t, strlen
 
-#include <string>
+#include <string>  // for u16string, u32string
 
-#include <glib.h>
 #include <glib-object.h>
+#include <glib.h>
 
-#include <gjs/gjs.h>
-#include "gjs-test-utils.h"
+#include "gjs/jsapi-wrapper.h"
+
+#include "gjs/context.h"
 #include "gjs/error-types.h"
 #include "gjs/jsapi-util.h"
-#include "gjs/jsapi-wrapper.h"
+#include "gjs/profiler.h"
+#include "test/gjs-test-utils.h"
 #include "util/misc.h"
 
 #define VALID_UTF8_STRING "\303\211\303\226 foobar \343\203\237"
diff --git a/tools/gjs-private-iwyu.imp b/tools/gjs-private-iwyu.imp
new file mode 100644
index 00000000..6d3a097c
--- /dev/null
+++ b/tools/gjs-private-iwyu.imp
@@ -0,0 +1,53 @@
+# IWYU mapping file for files that are part of libgjs
+[
+  {"include": ["<bits/std_abs.h>", "private", "<stdlib.h>", "public"]},
+  {"include": ["<bits/std_function.h>", "private", "<functional>", "public"]},
+  {"include": ["@<bits/stdint-.*>", "private", "<stdint.h>", "public"]},
+  {"include": ["<bits/types/sigevent_t.h>", "private", "<sys/signal.h>", "public"]},
+  {"include": ["<bits/types/siginfo_t.h>", "private", "<sys/signal.h>", "public"]},
+  {"include": ["<bits/types/struct_itimerspec.h>", "private", "<time.h>", "public"]},
+  {"include": ["<bits/types/struct_timespec.h>", "private", "<time.h>", "public"]},
+  {"include": ["<bits/types/timer_t.h>", "private", "<sys/types.h>", "public"]},
+  {"include": ["<ext/alloc_traits.h>", "private", "<memory>", "public"]},
+
+  {"include": ["@<ffi.*>", "private", "<ffi.h>", "public"]},
+  {"include": ["@\"gio/.*\"", "private", "<gio/gio.h>", "public"]},
+  {"include": ["@<gio/.*>", "private", "<gio/gio.h>", "public"]},
+  {"include": ["<glib/gtypes.h>", "private", "<glib.h>", "public"]},
+  {"include": ["@\"gobject/.*\"", "private", "<glib-object.h>", "public"]},
+  {"include": ["@<gobject/.*>", "private", "<glib-object.h>", "public"]},
+  {"include": ["<libintl.h>", "private", "<glib/gi18n.h>", "public"]},
+  {"include": ["@\"sysprof-capture-.*\"", "private", "<sysprof-capture.h>", "public"]},
+  {"include": ["@<sysprof-capture-.*>", "private", "<sysprof-capture.h>", "public"]},
+  {"include": ["<X11/Xlib.h>", "private", "<cairo-xlib.h>", "public"]},
+
+  # Remove when it is no longer necessary to include jsapi-wrapper.h
+  {"include": ["\"js/AllocPolicy.h\"", "private", "\"gjs/jsapi-wrapper.h\"", "public"]},
+  {"include": ["\"js/CallArgs.h\"", "private", "\"gjs/jsapi-wrapper.h\"", "public"]},
+  {"include": ["\"js/CharacterEncoding.h\"", "private", "\"gjs/jsapi-wrapper.h\"", "public"]},
+  {"include": ["\"js/Class.h\"", "private", "\"gjs/jsapi-wrapper.h\"", "public"]},
+  {"include": ["\"js/Conversions.h\"", "private", "\"gjs/jsapi-wrapper.h\"", "public"]},
+  {"include": ["\"js/GCAPI.h\"", "private", "\"gjs/jsapi-wrapper.h\"", "public"]},
+  {"include": ["\"js/GCPolicyAPI.h\"", "private", "\"gjs/jsapi-wrapper.h\"", "public"]},
+  {"include": ["\"js/GCVector.h\"", "private", "\"gjs/jsapi-wrapper.h\"", "public"]},
+  {"include": ["\"js/HashTable.h\"", "private", "\"gjs/jsapi-wrapper.h\"", "public"]},
+  {"include": ["\"js/HeapAPI.h\"", "private", "\"gjs/jsapi-wrapper.h\"", "public"]},
+  {"include": ["\"js/Id.h\"", "private", "\"gjs/jsapi-wrapper.h\"", "public"]},
+  {"include": ["\"js/RootingAPI.h\"", "private", "\"gjs/jsapi-wrapper.h\"", "public"]},
+  {"include": ["\"js/TracingAPI.h\"", "private", "\"gjs/jsapi-wrapper.h\"", "public"]},
+  {"include": ["\"js/TypeDecls.h\"", "private", "\"gjs/jsapi-wrapper.h\"", "public"]},
+  {"include": ["\"js/Utility.h\"", "private", "\"gjs/jsapi-wrapper.h\"", "public"]},
+  {"include": ["\"js/Value.h\"", "private", "\"gjs/jsapi-wrapper.h\"", "public"]},
+  {"include": ["\"jspubtd.h\"", "private", "\"gjs/jsapi-wrapper.h\"", "public"]},
+  {"include": ["\"jstypes.h\"", "private", "\"gjs/jsapi-wrapper.h\"", "public"]},
+  {"symbol": ["JS::GCPolicy<T>", "private", "\"gjs/jsapi-wrapper.h\"", "public"]},
+  {"symbol": ["JS::Symbol", "private", "\"gjs/jsapi-wrapper.h\"", "public"]},
+  {"symbol": ["JS::Value", "private", "\"gjs/jsapi-wrapper.h\"", "public"]},
+  {"symbol": ["JS::WeakCache<T>", "private", "\"gjs/jsapi-wrapper.h\"", "public"]},
+  {"symbol": ["JSContext", "private", "\"gjs/jsapi-wrapper.h\"", "public"]},
+  {"symbol": ["JSFlatString", "private", "\"gjs/jsapi-wrapper.h\"", "public"]},
+  {"symbol": ["JSFunction", "private", "\"gjs/jsapi-wrapper.h\"", "public"]},
+  {"symbol": ["JSLinearString", "private", "\"gjs/jsapi-wrapper.h\"", "public"]},
+  {"symbol": ["JSObject", "private", "\"gjs/jsapi-wrapper.h\"", "public"]},
+  {"symbol": ["JSString", "private", "\"gjs/jsapi-wrapper.h\"", "public"]}
+]
\ No newline at end of file
diff --git a/tools/gjs-public-iwyu.imp b/tools/gjs-public-iwyu.imp
new file mode 100644
index 00000000..7f805e4b
--- /dev/null
+++ b/tools/gjs-public-iwyu.imp
@@ -0,0 +1,6 @@
+# IWYU mapping file for files that use the API of libgjs
+[
+  {"ref": "gjs-private-iwyu.imp"},
+
+  {"include": ["\"gjs/macros.h\"", "private", "<gjs/gjs.h>", "public"]}
+]
\ No newline at end of file
diff --git a/tools/run_iwyu.sh.in b/tools/run_iwyu.sh.in
new file mode 100755
index 00000000..705e09c6
--- /dev/null
+++ b/tools/run_iwyu.sh.in
@@ -0,0 +1,59 @@
+#!/bin/bash
+
+# run with 'make iwyu | tee iwyu.log'
+
+if test -z "$BUILDDIR" -o -z "$SRCDIR"; then
+    echo "SRCDIR and BUILDDIR must be defined. Try running 'make iwyu' instead."
+    exit 1
+fi
+
+cd "$SRCDIR"
+
+PRIVATE_MAPPING="-Xiwyu --mapping_file=tools/gjs-private-iwyu.imp"
+PUBLIC_MAPPING="-Xiwyu --mapping_file=tools/gjs-public-iwyu.imp"
+
+LIBS_INCLUDES=$(pkg-config --cflags \
+    "@AX_PACKAGE_REQUIRES@ @AX_PACKAGE_REQUIRES_PRIVATE@")
+INCLUDES="-I. -I$BUILDDIR"
+DEFINES="-DGJS_COMPILATION -DPKGLIBDIR=\"\" -DINSTTESTDIR=\"\" -DGJS_JS_DIR=\"\""
+CPP_ARGS="$LIBS_INCLUDES @SYSPROF_CAPTURE_CFLAGS@ $INCLUDES $DEFINES"
+
+LANG_CXX="--language=c++ -std=c++14"
+LANG_C="--language=c"
+CXX_STDLIB_INCLUDES=$(clang -Wp,-v $LANG_CXX -fsyntax-only /dev/null 2>&1 | \
+    grep '^ ' | sed -e 's/^ /-I/')
+C_STDLIB_INCLUDES=$(clang -Wp,-v $LANG_C -fsyntax-only /dev/null 2>&1 | \
+    grep '^ ' | sed -e 's/^ /-I/')
+CXX_ARGS="$LANG_CXX $CXX_STDLIB_INCLUDES $CPP_ARGS"
+C_ARGS="$LANG_C $C_STDLIB_INCLUDES $CPP_ARGS"
+
+for FILE in gi/*.cpp gi/gjs_gi_trace.h gjs/atoms.cpp gjs/byteArray.cpp \
+    gjs/coverage.cpp gjs/debugger.cpp gjs/deprecation.cpp gjs/error-types.cpp \
+    gjs/engine.cpp gjs/global.cpp gjs/importer.cpp gjs/jsapi-util-args.h \
+    gjs/jsapi-util-error.cpp gjs/jsapi-util-root.h gjs/jsapi-util-string.cpp \
+    gjs/jsapi-util.cpp gjs/module.cpp gjs/native.cpp gjs/stack.cpp \
+    modules/cairo-*.cpp modules/console.cpp modules/system.cpp test/*.cpp \
+    util/*.cpp
+do
+    iwyu $PRIVATE_MAPPING $CXX_ARGS $FILE
+done
+iwyu $PRIVATE_MAPPING $CXX_ARGS gjs/context.cpp \
+    -Xiwyu --check_also=gjs/context-private.h
+iwyu $PRIVATE_MAPPING $CXX_ARGS gjs/jsapi-dynamic-class.cpp \
+    -Xiwyu --check_also=gjs/jsapi-class.h
+iwyu $PRIVATE_MAPPING $CXX_ARGS gjs/mem.cpp \
+    -Xiwyu --check_also=gjs/mem-private.h
+iwyu $PRIVATE_MAPPING $CXX_ARGS gjs/profiler.cpp \
+    -Xiwyu --check_also=gjs/profiler-private.h
+iwyu $PRIVATE_MAPPING $CXX_ARGS modules/cairo.cpp \
+    -Xiwyu --check_also=modules/cairo-module.h \
+    -Xiwyu --check_also=modules/cairo-private.h
+
+for FILE in gjs/console.cpp installed-tests/minijasmine.cpp; do
+    iwyu $PUBLIC_MAPPING $CXX_ARGS $FILE
+done
+
+for FILE in libgjs-private/*.c; do
+    iwyu $PRIVATE_MAPPING $C_ARGS $FILE
+done
+iwyu $PUBLIC_MAPPING $C_ARGS gjs/macros.h
diff --git a/util/log.cpp b/util/log.cpp
index 410913e4..4286a408 100644
--- a/util/log.cpp
+++ b/util/log.cpp
@@ -21,16 +21,10 @@
  * IN THE SOFTWARE.
  */
 
-#include "config.h"
-
-#include "log.h"
-#include "misc.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
 #include <errno.h>
-#include <sys/types.h>
+#include <stdarg.h>
+#include <stdio.h>   // for FILE, fprintf, fflush, fopen, fputs, fseek
+#include <string.h>  // for strchr, strcmp
 
 #ifdef G_OS_WIN32
 # include <io.h>
@@ -39,9 +33,12 @@
 #  define F_OK 0
 # endif
 #else
-# include <unistd.h>
+#    include <unistd.h>  // for getpid
 #endif
 
+#include "util/log.h"
+#include "util/misc.h"
+
 /* prefix is allowed if it's in the ;-delimited environment variable
  * GJS_DEBUG_TOPICS or if that variable is not set.
  */
diff --git a/util/misc.cpp b/util/misc.cpp
index 6bc03c27..b59aabb5 100644
--- a/util/misc.cpp
+++ b/util/misc.cpp
@@ -21,8 +21,9 @@
  * IN THE SOFTWARE.
  */
 
-#include <config.h>
-#include "misc.h"
+#include <glib.h>
+
+#include "util/misc.h"
 
 bool
 gjs_environment_variable_is_set(const char *env_variable_name)
diff --git a/util/misc.h b/util/misc.h
index e0b42d8b..141e9b7f 100644
--- a/util/misc.h
+++ b/util/misc.h
@@ -24,8 +24,6 @@
 #ifndef UTIL_MISC_H_
 #define UTIL_MISC_H_
 
-#include <glib.h>
-
 bool    gjs_environment_variable_is_set   (const char *env_variable_name);
 
 char** gjs_g_strv_concat(char*** strv_array, int len);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]