= The Care and Feeding of WebCore Modules = This document describes how WebCore's module system works and how to use it when building a new feature. == Overview == As we add more features to WebCore, the project becomes more complex. Some self-contained features, like IndexedDB and MediaStream, expose JavaScript APIs but aren't otherwise involved in the core functionality of the engine, such as layout and rendering. The module system let us reduce the complexity of the project by loosening the coupling of between these features and the rest of WebCore. Often individual modules can be enabled with an `ENABLE` macro, but some modules are always enabled. == Should my feature be a module? == Not all features should be implemented as modules. For example, CSS features, such as flexbox or regions, are better implemented as part of the rest of the CSS machinery in WebCore because they often are tightly integrated with layout and rendering. Other features, such as IndexedDB, do not need to be tightly integrated with the rest of WebCore and are good candidates to be modules. Typically features defined in "satellite" specifications, such as those from the [http://www.w3.org/2008/webapps/ WebApps] working group, are good module candidates, whereas features defined in the "core" specifications, such as those from the [http://www.w3.org/html/wg/ HTML], [http://www.w3.org/Style/CSS/members.en.php3 CSS], or [http://www.w3.org/Graphics/SVG/ SVG] working groups, are more likely better implemented in WebCore proper. If you're unsure whether you should implement your feature as a module, feel free to ask when you [http://www.webkit.org/coding/adding-features.html announce your feature on webkit-dev]. == Dependency diagram == The code for a module belongs in a subdirectory of the [http://trac.webkit.org/browser/trunk/Source/WebCore/Modules/ Modules] directory and in a subdirectory of [http://trac.webkit.org/browser/trunk/Source/WebCore/platform/ WebCore/platform]. For example, the MediaStream module is contained in http://trac.webkit.org/browser/trunk/Source/WebCore/Modules/mediastream and http://trac.webkit.org/browser/trunk/Source/WebCore/platform/mediastream. Keeping the code for your feature in a single directory reduces the burden that your feature places on other WebKit contributors as they develop other modules and core functionality of the engine. This [https://docs.google.com/drawings/d/10WlCj2J3arxf4cDGRKteNinaP755iFnmYtYtnNSCQOY/edit?authkey=CP6plYAI dependency diagram] shows how the WebAudio, MediaStream, and IndexedDB modules fit into the WebKit's dependency diagram. Notice, in particular, that WebCore proper should not have dependencies on your module. == Associating JavaScript APIs with "core" objects == Even self-contained features often need to expose JavaScript APIs on "catch-all" interfaces like `DOMWindow` or `Navigator`. If we declared these APIs in [http://trac.webkit.org/browser/trunk/Source/WebCore/page/DOMWindow.idl DOMWindow.idl] and implemented them in [http://trac.webkit.org/browser/trunk/Source/WebCore/page/DOMWindow.cpp DOMWindow.cpp], the complexity of `DOMWindow` would increase with each added feature. To avoid complexity creep in these core classes, you can declare your JavaScript API in supplemental IDL files, mirroring the [http://www.w3.org/TR/WebIDL/#dfn-partial-interface "partial interface"] syntax used in specifications. For more details, see the [http://trac.webkit.org/wiki/WebKitIDL#Supplemental documentation of the Supplemental attribute]. For example, the MediaStream module [http://trac.webkit.org/browser/trunk/Source/WebCore/Modules/mediastream/NavigatorMediaStream.idl uses this mechanism] to add the `webkitGetUserMedia` API to `Navigator`. The API is implemented in [http://trac.webkit.org/browser/trunk/Source/WebCore/Modules/mediastream/NavigatorMediaStream.cpp NavigatorMediaStream.cpp], avoiding bloat in [http://trac.webkit.org/browser/trunk/Source/WebCore/page/Navigator.cpp Navigator.cpp] itself and helping to contain the MediaStream code in the MediaStream directory. == Associating state with "core" objects == Sometimes a module needs to associate state with a core object, such as `Page` or `Navigator`. Typically, this state doesn't interact with any of the core state and simply piggybacks on the lifetime of the core object. Rather than bloating the core objects with your feature-specific state, you can associate your feature's data with these objects using [http://trac.webkit.org/browser/trunk/Source/WebCore/platform/Supplementable.h Supplementable]. For example, the [http://trac.webkit.org/browser/trunk/Source/WebCore/Modules/gamepad/ Gamepad] module needs to associate a `GamepadList` with `Navigator`. Notice that in the [http://trac.webkit.org/browser/trunk/Source/WebCore/Modules/gamepad/NavigatorGamepad.h implementation] of its [http://trac.webkit.org/browser/trunk/Source/WebCore/Modules/gamepad/NavigatorGamepad.idl supplemental interface], the Gamepad module declares that `NavigatorGamepad` inherits from `Supplement`, which lets us store a `NavigatorGamepad` in [http://trac.webkit.org/browser/trunk/Source/WebCore/platform/Supplementable.h Navigator's m_supplements HashMap].