Bug 1044162 - part 1 - make EXTRA_{PP_,}JS_MODULES communicate their installation path; r=mshal
authorNathan Froyd <froydnj@mozilla.com>
Fri, 25 Jul 2014 13:40:07 -0400
changeset 218468 b961ba8f089273cfd94d079ab88565efbb3edc11
parent 218467 275a064b9345efb82d0850b08d9321c4fd3c527e
child 218469 85b40c4b8af7e8e61e4ff3bf24ee337841d87306
push id3979
push userraliiev@mozilla.com
push dateMon, 13 Oct 2014 16:35:44 +0000
treeherdermozilla-beta@30f2cc610691 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmshal
bugs1044162
milestone34.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1044162 - part 1 - make EXTRA_{PP_,}JS_MODULES communicate their installation path; r=mshal This patch makes EXTRA_{PP_,}JS_MODULES similar in functionality to TESTING_JS_MODULES: we indicate the path relative to $(FINAL_TARGET)/modules with an appropriate hierarchy of paths.
accessible/jsat/moz.build
addon-sdk/moz.build
addon-sdk/source/modules/system/moz.build
browser/components/loop/moz.build
browser/components/sessionstore/moz.build
browser/components/tabview/moz.build
browser/components/translation/moz.build
browser/devtools/app-manager/moz.build
browser/devtools/canvasdebugger/moz.build
browser/devtools/commandline/moz.build
browser/devtools/debugger/moz.build
browser/devtools/eyedropper/moz.build
browser/devtools/inspector/moz.build
browser/devtools/markupview/moz.build
browser/devtools/moz.build
browser/devtools/netmonitor/moz.build
browser/devtools/profiler/moz.build
browser/devtools/responsivedesign/moz.build
browser/devtools/scratchpad/moz.build
browser/devtools/shadereditor/moz.build
browser/devtools/sourceeditor/moz.build
browser/devtools/styleinspector/moz.build
browser/devtools/tilt/moz.build
browser/devtools/webaudioeditor/moz.build
browser/devtools/webconsole/moz.build
browser/devtools/webide/moz.build
browser/experiments/moz.build
dom/media/moz.build
python/mozbuild/mozbuild/backend/recursivemake.py
python/mozbuild/mozbuild/frontend/emitter.py
python/mozbuild/mozbuild/frontend/sandbox_symbols.py
python/mozbuild/mozbuild/test/backend/data/variable_passthru/moz.build
python/mozbuild/mozbuild/test/backend/test_recursivemake.py
python/mozbuild/mozbuild/test/frontend/data/variable-passthru/moz.build
python/mozbuild/mozbuild/test/frontend/test_emitter.py
services/metrics/moz.build
toolkit/components/osfile/modules/moz.build
toolkit/components/promiseworker/worker/moz.build
toolkit/components/sqlite/moz.build
toolkit/components/workerloader/moz.build
toolkit/components/workerlz4/moz.build
toolkit/crashreporter/test/Makefile.in
toolkit/devtools/acorn/moz.build
toolkit/devtools/apps/moz.build
toolkit/devtools/discovery/moz.build
toolkit/devtools/jsbeautify/moz.build
toolkit/devtools/pretty-fast/moz.build
toolkit/devtools/qrcode/decoder/moz.build
toolkit/devtools/qrcode/encoder/moz.build
toolkit/devtools/qrcode/moz.build
toolkit/devtools/styleinspector/moz.build
toolkit/devtools/tern/moz.build
toolkit/devtools/transport/moz.build
toolkit/devtools/webconsole/moz.build
toolkit/identity/moz.build
toolkit/mozapps/extensions/internal/moz.build
--- a/accessible/jsat/moz.build
+++ b/accessible/jsat/moz.build
@@ -1,17 +1,15 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-JS_MODULES_PATH = 'modules/accessibility'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.accessibility += [
     'AccessFu.jsm',
     'Constants.jsm',
     'ContentControl.jsm',
     'EventManager.jsm',
     'Gestures.jsm',
     'OutputGenerator.jsm',
     'PointerAdapter.jsm',
     'Presentation.jsm',
--- a/addon-sdk/moz.build
+++ b/addon-sdk/moz.build
@@ -3,13 +3,11 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
 
 DIRS += ["source/modules/system"]
 
-JS_MODULES_PATH = 'modules/sdk'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.sdk += [
     'source/app-extension/bootstrap.js',
 ]
--- a/addon-sdk/source/modules/system/moz.build
+++ b/addon-sdk/source/modules/system/moz.build
@@ -1,11 +1,9 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-JS_MODULES_PATH = 'modules/sdk/system'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.sdk.system += [
     'XulApp.js',
 ]
--- a/browser/components/loop/moz.build
+++ b/browser/components/loop/moz.build
@@ -1,22 +1,20 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 JAR_MANIFESTS += ['jar.mn']
 
-JS_MODULES_PATH = 'modules/loop'
-
 XPCSHELL_TESTS_MANIFESTS += ['test/xpcshell/xpcshell.ini']
 
 BROWSER_CHROME_MANIFESTS += [
     'test/mochitest/browser.ini',
 ]
 
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.loop += [
     'MozLoopAPI.jsm',
     'MozLoopPushHandler.jsm',
     'MozLoopService.jsm',
     'MozLoopWorker.js',
 ]
--- a/browser/components/sessionstore/moz.build
+++ b/browser/components/sessionstore/moz.build
@@ -17,19 +17,17 @@ XPIDL_SOURCES += [
 XPIDL_MODULE = 'sessionstore'
 
 EXTRA_COMPONENTS += [
     'nsSessionStartup.js',
     'nsSessionStore.js',
     'nsSessionStore.manifest',
 ]
 
-JS_MODULES_PATH = 'modules/sessionstore'
-
-EXTRA_JS_MODULES = [
+EXTRA_JS_MODULES.sessionstore = [
     'ContentRestore.jsm',
     'DocShellCapabilities.jsm',
     'FrameTree.jsm',
     'GlobalState.jsm',
     'PageStyle.jsm',
     'PrivacyFilter.jsm',
     'PrivacyLevel.jsm',
     'RecentlyClosedTabsAndWindowsMenuUtils.jsm',
@@ -41,13 +39,13 @@ EXTRA_JS_MODULES = [
     'SessionWorker.js',
     'SessionWorker.jsm',
     'TabAttributes.jsm',
     'TabState.jsm',
     'TabStateCache.jsm',
     'Utils.jsm',
 ]
 
-EXTRA_PP_JS_MODULES += [
+EXTRA_PP_JS_MODULES.sessionstore += [
     'SessionSaver.jsm',
     'SessionStore.jsm',
 ]
 
--- a/browser/components/tabview/moz.build
+++ b/browser/components/tabview/moz.build
@@ -1,14 +1,12 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-EXTRA_JS_MODULES = ['modules/utils.jsm']
-JS_MODULES_PATH  = 'modules/tabview'
-
+EXTRA_JS_MODULES.tabview = ['modules/utils.jsm']
 BROWSER_CHROME_MANIFESTS += [
     'test/browser.ini',
 ]
 
 JAR_MANIFESTS += ['jar.mn']
\ No newline at end of file
--- a/browser/components/translation/moz.build
+++ b/browser/components/translation/moz.build
@@ -1,15 +1,13 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-JS_MODULES_PATH = 'modules/translation'
-
-EXTRA_JS_MODULES = [
+EXTRA_JS_MODULES.translation = [
     'BingTranslator.jsm',
     'cld2/cld-worker.js',
     'cld2/cld-worker.js.mem',
     'LanguageDetector.jsm',
     'Translation.jsm',
     'TranslationContentHandler.jsm',
     'TranslationDocument.jsm'
 ]
--- a/browser/devtools/app-manager/moz.build
+++ b/browser/devtools/app-manager/moz.build
@@ -2,19 +2,17 @@
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
 MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
 
-JS_MODULES_PATH = 'modules/devtools/app-manager'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools["app-manager"] += [
     'app-projects.js',
     'app-validator.js',
     'builtin-adb-store.js',
     'connection-store.js',
     'device-store.js',
     'simulators-store.js',
     'webapps-store.js',
 ]
--- a/browser/devtools/canvasdebugger/moz.build
+++ b/browser/devtools/canvasdebugger/moz.build
@@ -1,12 +1,10 @@
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-JS_MODULES_PATH = 'modules/devtools/canvasdebugger'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.canvasdebugger += [
     'panel.js'
 ]
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
--- a/browser/devtools/commandline/moz.build
+++ b/browser/devtools/commandline/moz.build
@@ -1,11 +1,9 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-JS_MODULES_PATH = 'modules/devtools/commandline'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.commandline += [
     'commands-index.js'
 ]
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
--- a/browser/devtools/debugger/moz.build
+++ b/browser/devtools/debugger/moz.build
@@ -1,13 +1,11 @@
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-JS_MODULES_PATH = 'modules/devtools/debugger'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.debugger += [
     'debugger-commands.js',
     'panel.js'
 ]
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
--- a/browser/devtools/eyedropper/moz.build
+++ b/browser/devtools/eyedropper/moz.build
@@ -1,14 +1,12 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-JS_MODULES_PATH = 'modules/devtools/eyedropper'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.eyedropper += [
     'commands.js',
     'eyedropper.js'
 ]
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
--- a/browser/devtools/inspector/moz.build
+++ b/browser/devtools/inspector/moz.build
@@ -1,14 +1,12 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-JS_MODULES_PATH = 'modules/devtools/inspector'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.inspector += [
     'breadcrumbs.js',
     'inspector-commands.js',
     'inspector-panel.js',
     'selector-search.js'
 ]
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
--- a/browser/devtools/markupview/moz.build
+++ b/browser/devtools/markupview/moz.build
@@ -1,14 +1,12 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
 
-JS_MODULES_PATH = 'modules/devtools/markupview'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.markupview += [
     'html-editor.js',
     'markup-view.js',
 ]
--- a/browser/devtools/moz.build
+++ b/browser/devtools/moz.build
@@ -33,13 +33,11 @@ DIRS += [
 
 EXTRA_COMPONENTS += [
     'devtools-clhandler.js',
     'devtools-clhandler.manifest',
 ]
 
 JAR_MANIFESTS += ['jar.mn']
 
-JS_MODULES_PATH = 'modules/devtools'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools += [
     'main.js',
 ]
--- a/browser/devtools/netmonitor/moz.build
+++ b/browser/devtools/netmonitor/moz.build
@@ -1,12 +1,10 @@
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-JS_MODULES_PATH = 'modules/devtools/netmonitor'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.netmonitor += [
     'panel.js'
 ]
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
--- a/browser/devtools/profiler/moz.build
+++ b/browser/devtools/profiler/moz.build
@@ -1,18 +1,16 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
 
-JS_MODULES_PATH = 'modules/devtools/profiler'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.profiler += [
     'cleopatra.js',
     'commands.js',
     'consts.js',
     'controller.js',
     'panel.js',
     'sidebar.js',
 ]
--- a/browser/devtools/responsivedesign/moz.build
+++ b/browser/devtools/responsivedesign/moz.build
@@ -1,11 +1,9 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-JS_MODULES_PATH = 'modules/devtools'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools += [
     'resize-commands.js'
 ]
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
--- a/browser/devtools/scratchpad/moz.build
+++ b/browser/devtools/scratchpad/moz.build
@@ -1,14 +1,12 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-JS_MODULES_PATH = 'modules/devtools/scratchpad'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.scratchpad += [
     'scratchpad-commands.js',
     'scratchpad-panel.js'
 ]
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
--- a/browser/devtools/shadereditor/moz.build
+++ b/browser/devtools/shadereditor/moz.build
@@ -1,12 +1,10 @@
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-JS_MODULES_PATH = 'modules/devtools/shadereditor'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.shadereditor += [
     'panel.js'
 ]
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
--- a/browser/devtools/sourceeditor/moz.build
+++ b/browser/devtools/sourceeditor/moz.build
@@ -1,17 +1,15 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-JS_MODULES_PATH = 'modules/devtools/sourceeditor'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.sourceeditor += [
     'autocomplete.js',
     'css-autocompleter.js',
     'css-tokenizer.js',
     'debugger.js',
     'editor.js'
 ]
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
--- a/browser/devtools/styleinspector/moz.build
+++ b/browser/devtools/styleinspector/moz.build
@@ -2,17 +2,15 @@
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
 XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']
 
-JS_MODULES_PATH = 'modules/devtools/styleinspector'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.styleinspector += [
     'computed-view.js',
     'css-parsing-utils.js',
     'rule-view.js',
     'style-inspector-overlays.js',
     'style-inspector.js',
 ]
--- a/browser/devtools/tilt/moz.build
+++ b/browser/devtools/tilt/moz.build
@@ -1,15 +1,13 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-JS_MODULES_PATH = 'modules/devtools/tilt'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.tilt += [
     'tilt-commands.js',
     'tilt-gl.js',
     'tilt-math.js',
     'tilt-utils.js',
     'tilt-visualizer-style.js',
     'tilt-visualizer.js',
     'tilt.js',
     'TiltWorkerCrafter.js',
--- a/browser/devtools/webaudioeditor/moz.build
+++ b/browser/devtools/webaudioeditor/moz.build
@@ -1,12 +1,10 @@
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-JS_MODULES_PATH = 'modules/devtools/webaudioeditor'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.webaudioeditor += [
     'panel.js'
 ]
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
--- a/browser/devtools/webconsole/moz.build
+++ b/browser/devtools/webconsole/moz.build
@@ -1,18 +1,16 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
 
-JS_MODULES_PATH = 'modules/devtools/webconsole'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.webconsole += [
     'console-commands.js',
     'console-output.js',
     'hudservice.js',
     'network-panel.js',
     'panel.js',
     'webconsole.js',
 ]
--- a/browser/devtools/webide/moz.build
+++ b/browser/devtools/webide/moz.build
@@ -7,16 +7,14 @@
 DIRS += [
     'content',
     'components',
     'themes',
 ]
 
 MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
 
-JS_MODULES_PATH = 'modules/devtools/webide'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.webide += [
     'modules/addons.js',
     'modules/app-manager.js',
     'modules/remote-resources.js',
     'modules/runtimes.js'
 ]
--- a/browser/experiments/moz.build
+++ b/browser/experiments/moz.build
@@ -2,17 +2,15 @@
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 EXTRA_COMPONENTS += [
     'Experiments.manifest',
     'ExperimentsService.js',
 ]
 
-JS_MODULES_PATH = 'modules/experiments'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.experiments += [
   'Experiments.jsm',
 ]
 
 XPCSHELL_TESTS_MANIFESTS += ['test/xpcshell/xpcshell.ini']
 
 SPHINX_TREES['experiments'] = 'docs'
--- a/dom/media/moz.build
+++ b/dom/media/moz.build
@@ -41,19 +41,17 @@ UNIFIED_SOURCES += [
     'MediaManager.cpp',
 ]
 
 EXTRA_COMPONENTS += [
     'PeerConnection.js',
     'PeerConnection.manifest',
 ]
 
-JS_MODULES_PATH = 'modules/media'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.media += [
     'IdpProxy.jsm',
     'PeerConnectionIdp.jsm',
     'RTCStatsReport.jsm',
 ]
 
 if CONFIG['MOZ_B2G']:
     EXPORTS.mozilla += [
         'MediaPermissionGonk.h',
--- a/python/mozbuild/mozbuild/backend/recursivemake.py
+++ b/python/mozbuild/mozbuild/backend/recursivemake.py
@@ -946,18 +946,44 @@ class RecursiveMakeBackend(CommonBackend
             backend_file.write('FINAL_TARGET = $(DEPTH)/%s\n' % (obj.target))
         else:
             backend_file.write('FINAL_TARGET = $(if $(XPI_NAME),$(DIST)/xpi-stage/$(XPI_NAME),$(DIST)/bin)$(DIST_SUBDIR:%=/%)\n')
 
         if not obj.enabled:
             backend_file.write('NO_DIST_INSTALL := 1\n')
 
     def _process_javascript_modules(self, obj, backend_file):
-        if obj.flavor != 'testing':
-            raise Exception('We only support testing JavaScriptModules instances.')
+        if obj.flavor not in ('extra', 'extra_pp', 'testing'):
+            raise Exception('Unsupported JavaScriptModules instance: %s' % obj.flavor)
+
+        if obj.flavor == 'extra':
+            def onelement(element, namespace):
+                if not element.get_strings():
+                    return
+
+                prefix = 'extra_js_%s' % namespace.replace('/', '_')
+                backend_file.write('%s_FILES := %s\n'
+                                   % (prefix, ' '.join(element.get_strings())))
+                backend_file.write('%s_DEST = $(FINAL_TARGET)/%s\n' % (prefix, namespace))
+                backend_file.write('INSTALL_TARGETS += %s\n\n' % prefix)
+            self._process_hierarchy_elements(obj, obj.modules, 'modules', onelement)
+            return
+
+        if obj.flavor == 'extra_pp':
+            def onelement(element, namespace):
+                if not element.get_strings():
+                    return
+
+                prefix = 'extra_pp_js_%s' % namespace.replace('/', '_')
+                backend_file.write('%s := %s\n'
+                                   % (prefix, ' '.join(element.get_strings())))
+                backend_file.write('%s_PATH = $(FINAL_TARGET)/%s\n' % (prefix, namespace))
+                backend_file.write('PP_TARGETS += %s\n\n' % prefix)
+            self._process_hierarchy_elements(obj, obj.modules, 'modules', onelement)
+            return
 
         if not self.environment.substs.get('ENABLE_TESTS', False):
             return
 
         manifest = self._install_manifests['tests']
 
         def onmodule(source, dest, flags):
             manifest.add_symlink(source, mozpath.join('modules', dest))
--- a/python/mozbuild/mozbuild/frontend/emitter.py
+++ b/python/mozbuild/mozbuild/frontend/emitter.py
@@ -368,19 +368,17 @@ class TreeMetadataEmitter(LoggingMixin):
         varlist = [
             'ANDROID_GENERATED_RESFILES',
             'ANDROID_RES_DIRS',
             'DISABLE_STL_WRAPPING',
             'EXTRA_ASSEMBLER_FLAGS',
             'EXTRA_COMPILE_FLAGS',
             'EXTRA_COMPONENTS',
             'EXTRA_DSO_LDOPTS',
-            'EXTRA_JS_MODULES',
             'EXTRA_PP_COMPONENTS',
-            'EXTRA_PP_JS_MODULES',
             'FAIL_ON_WARNINGS',
             'FILES_PER_UNIFIED_FILE',
             'USE_STATIC_LIBS',
             'GENERATED_FILES',
             'IS_GYP_DIR',
             'JS_MODULES_PATH',
             'MSVC_ENABLE_PGO',
             'NO_DIST_INSTALL',
@@ -502,16 +500,24 @@ class TreeMetadataEmitter(LoggingMixin):
                         'because it is already used in %s' % (program, kind,
                         self._binaries[program].relativedir), sandbox)
                 self._binaries[program] = cls(sandbox, program,
                     is_unit_test=kind == 'CPP_UNIT_TESTS')
                 self._linkage.append((sandbox, self._binaries[program],
                     'HOST_USE_LIBS' if kind == 'HOST_SIMPLE_PROGRAMS'
                     else 'USE_LIBS'))
 
+        extra_js_modules = sandbox.get('EXTRA_JS_MODULES')
+        if extra_js_modules:
+            yield JavaScriptModules(sandbox, extra_js_modules, 'extra')
+
+        extra_pp_js_modules = sandbox.get('EXTRA_PP_JS_MODULES')
+        if extra_pp_js_modules:
+            yield JavaScriptModules(sandbox, extra_pp_js_modules, 'extra_pp')
+
         test_js_modules = sandbox.get('TESTING_JS_MODULES')
         if test_js_modules:
             yield JavaScriptModules(sandbox, test_js_modules, 'testing')
 
         simple_lists = [
             ('GENERATED_EVENTS_WEBIDL_FILES', GeneratedEventWebIDLFile),
             ('GENERATED_WEBIDL_FILES', GeneratedWebIDLFile),
             ('IPDL_SOURCES', IPDLFile),
--- a/python/mozbuild/mozbuild/frontend/sandbox_symbols.py
+++ b/python/mozbuild/mozbuild/frontend/sandbox_symbols.py
@@ -181,25 +181,25 @@ VARIABLES = {
 
     'EXTRA_COMPONENTS': (StrictOrderingOnAppendList, list,
         """Additional component files to distribute.
 
        This variable contains a list of files to copy into
        ``$(FINAL_TARGET)/components/``.
         """, 'libs'),
 
-    'EXTRA_JS_MODULES': (StrictOrderingOnAppendList, list,
+    'EXTRA_JS_MODULES': (HierarchicalStringList, list,
         """Additional JavaScript files to distribute.
 
         This variable contains a list of files to copy into
         ``$(FINAL_TARGET)/$(JS_MODULES_PATH)``. ``JS_MODULES_PATH`` defaults
         to ``modules`` if left undefined.
         """, 'libs'),
 
-    'EXTRA_PP_JS_MODULES': (StrictOrderingOnAppendList, list,
+    'EXTRA_PP_JS_MODULES': (HierarchicalStringList, list,
         """Additional JavaScript files to distribute.
 
         This variable contains a list of files to copy into
         ``$(FINAL_TARGET)/$(JS_MODULES_PATH)``, after preprocessing.
         ``JS_MODULES_PATH`` defaults to ``modules`` if left undefined.
         """, 'libs'),
 
     'TESTING_JS_MODULES': (HierarchicalStringList, list,
--- a/python/mozbuild/mozbuild/test/backend/data/variable_passthru/moz.build
+++ b/python/mozbuild/mozbuild/test/backend/data/variable_passthru/moz.build
@@ -2,19 +2,16 @@
 # Any copyright is dedicated to the Public Domain.
 # http://creativecommons.org/publicdomain/zero/1.0/
 
 SOURCES += ['bar.s', 'foo.asm']
 
 EXTRA_COMPONENTS = ['bar.js', 'foo.js']
 EXTRA_PP_COMPONENTS = ['bar.pp.js', 'foo.pp.js']
 
-EXTRA_JS_MODULES += ['bar.jsm', 'foo.jsm']
-EXTRA_PP_JS_MODULES = ['bar.pp.jsm', 'foo.pp.jsm']
-
 HOST_SOURCES += ['bar.cpp', 'foo.cpp']
 HOST_SOURCES += ['bar.c', 'foo.c']
 
 OS_LIBS = ['foo.so', '-l123', 'bar.a']
 
 SOURCES += ['bar.c', 'foo.c']
 
 SOURCES += ['bar.mm', 'foo.mm']
--- a/python/mozbuild/mozbuild/test/backend/test_recursivemake.py
+++ b/python/mozbuild/mozbuild/test/backend/test_recursivemake.py
@@ -271,24 +271,16 @@ class TestRecursiveMakeBackend(BackendTe
             'EXTRA_COMPONENTS': [
                 'EXTRA_COMPONENTS += bar.js',
                 'EXTRA_COMPONENTS += foo.js',
             ],
             'EXTRA_PP_COMPONENTS': [
                 'EXTRA_PP_COMPONENTS += bar.pp.js',
                 'EXTRA_PP_COMPONENTS += foo.pp.js',
             ],
-            'EXTRA_JS_MODULES': [
-                'EXTRA_JS_MODULES += bar.jsm',
-                'EXTRA_JS_MODULES += foo.jsm',
-            ],
-            'EXTRA_PP_JS_MODULES': [
-                'EXTRA_PP_JS_MODULES += bar.pp.jsm',
-                'EXTRA_PP_JS_MODULES += foo.pp.jsm',
-            ],
             'FAIL_ON_WARNINGS': [
                 'FAIL_ON_WARNINGS := 1',
             ],
             'HOST_CPPSRCS': [
                 'HOST_CPPSRCS += bar.cpp',
                 'HOST_CPPSRCS += foo.cpp',
             ],
             'HOST_CSRCS': [
--- a/python/mozbuild/mozbuild/test/frontend/data/variable-passthru/moz.build
+++ b/python/mozbuild/mozbuild/test/frontend/data/variable-passthru/moz.build
@@ -2,19 +2,16 @@
 # Any copyright is dedicated to the Public Domain.
 # http://creativecommons.org/publicdomain/zero/1.0/
 
 SOURCES += ['fans.asm', 'tans.s']
 
 EXTRA_COMPONENTS=['fans.js', 'tans.js']
 EXTRA_PP_COMPONENTS=['fans.pp.js', 'tans.pp.js']
 
-EXTRA_JS_MODULES += ['bar.jsm', 'foo.jsm']
-EXTRA_PP_JS_MODULES = ['bar.pp.jsm', 'foo.pp.jsm']
-
 HOST_SOURCES += ['fans.cpp', 'tans.cpp']
 HOST_SOURCES += ['fans.c', 'tans.c']
 
 OS_LIBS += ['foo.so', '-l123', 'aaa.a']
 
 SOURCES += ['fans.c', 'tans.c']
 
 SOURCES += ['fans.mm', 'tans.mm']
--- a/python/mozbuild/mozbuild/test/frontend/test_emitter.py
+++ b/python/mozbuild/mozbuild/test/frontend/test_emitter.py
@@ -149,18 +149,16 @@ class TestEmitterBasic(unittest.TestCase
 
         wanted = dict(
             ASFILES=['fans.asm', 'tans.s'],
             CMMSRCS=['fans.mm', 'tans.mm'],
             CSRCS=['fans.c', 'tans.c'],
             DISABLE_STL_WRAPPING=True,
             EXTRA_COMPONENTS=['fans.js', 'tans.js'],
             EXTRA_PP_COMPONENTS=['fans.pp.js', 'tans.pp.js'],
-            EXTRA_JS_MODULES=['bar.jsm', 'foo.jsm'],
-            EXTRA_PP_JS_MODULES=['bar.pp.jsm', 'foo.pp.jsm'],
             FAIL_ON_WARNINGS=True,
             HOST_CPPSRCS=['fans.cpp', 'tans.cpp'],
             HOST_CSRCS=['fans.c', 'tans.c'],
             MSVC_ENABLE_PGO=True,
             NO_DIST_INSTALL=True,
             OS_LIBS=['foo.so', '-l123', 'aaa.a'],
             SSRCS=['bans.S', 'fans.S'],
             VISIBILITY_FLAGS='',
--- a/services/metrics/moz.build
+++ b/services/metrics/moz.build
@@ -1,19 +1,17 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 TEST_DIRS += ['tests']
 
-EXTRA_PP_JS_MODULES += [
+EXTRA_PP_JS_MODULES.services.metrics += [
     'dataprovider.jsm',
     'providermanager.jsm',
     'storage.jsm',
 ]
 
-JS_MODULES_PATH = 'modules/services/metrics'
-
 TESTING_JS_MODULES.services.metrics += [
     'modules-testing/mocks.jsm',
 ]
--- a/toolkit/components/osfile/modules/moz.build
+++ b/toolkit/components/osfile/modules/moz.build
@@ -1,17 +1,15 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-JS_MODULES_PATH = 'modules/osfile'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.osfile += [
     'osfile_async_front.jsm',
     'osfile_async_worker.js',
     'osfile_native.jsm',
     'osfile_shared_allthreads.jsm',
     'osfile_shared_front.jsm',
     'osfile_unix_allthreads.jsm',
     'osfile_unix_back.jsm',
     'osfile_unix_front.jsm',
--- a/toolkit/components/promiseworker/worker/moz.build
+++ b/toolkit/components/promiseworker/worker/moz.build
@@ -1,11 +1,9 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-JS_MODULES_PATH = 'modules/workers'
-
-EXTRA_JS_MODULES = [
+EXTRA_JS_MODULES.workers = [
     'PromiseWorker.js',
 ]
--- a/toolkit/components/sqlite/moz.build
+++ b/toolkit/components/sqlite/moz.build
@@ -1,13 +1,11 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 XPCSHELL_TESTS_MANIFESTS += ['tests/xpcshell/xpcshell.ini']
 
-JS_MODULES_PATH = 'modules/sqlite'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.sqlite += [
     'sqlite_internal.js',
 ]
--- a/toolkit/components/workerloader/moz.build
+++ b/toolkit/components/workerloader/moz.build
@@ -1,13 +1,11 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 MOCHITEST_CHROME_MANIFESTS += ['tests/chrome.ini']
 
-JS_MODULES_PATH = 'modules/workers'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.workers += [
     'require.js'
 ]
--- a/toolkit/components/workerlz4/moz.build
+++ b/toolkit/components/workerlz4/moz.build
@@ -1,19 +1,17 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 XPCSHELL_TESTS_MANIFESTS += ['tests/xpcshell/xpcshell.ini']
 
-JS_MODULES_PATH = 'modules/workers'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.workers += [
     'lz4.js',
     'lz4_internal.js',
 ]
 
 SOURCES += [
     'lz4.cpp',
 ]
 
--- a/toolkit/crashreporter/test/Makefile.in
+++ b/toolkit/crashreporter/test/Makefile.in
@@ -1,14 +1,14 @@
 #
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 EXTRA_LIBS += $(NSPR_LIBS)
 
-UNIT_FILES = $(SHARED_LIBRARY) $(EXTRA_JS_MODULES)
+UNIT_FILES = $(SHARED_LIBRARY) CrashTestUtils.jsm
 UNIT_DEST = $(DEPTH)/_tests/xpcshell/$(relativesrcdir)/unit/
 INSTALL_TARGETS += UNIT
 
 UNIT_IPC_FILES = $(UNIT_FILES)
 UNIT_IPC_DEST = $(DEPTH)/_tests/xpcshell/$(relativesrcdir)/unit_ipc/
 INSTALL_TARGETS += UNIT_IPC
--- a/toolkit/devtools/acorn/moz.build
+++ b/toolkit/devtools/acorn/moz.build
@@ -1,15 +1,13 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
 
-JS_MODULES_PATH = 'modules/devtools/acorn'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.acorn += [
     'acorn.js',
     'acorn_loose.js',
     'walk.js',
 ]
--- a/toolkit/devtools/apps/moz.build
+++ b/toolkit/devtools/apps/moz.build
@@ -1,14 +1,12 @@
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 TEST_DIRS += ['tests']
 
-JS_MODULES_PATH = 'modules/devtools'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools += [
     'app-actor-front.js',
     'Devices.jsm',
     'Simulator.jsm'
 ]
--- a/toolkit/devtools/discovery/moz.build
+++ b/toolkit/devtools/discovery/moz.build
@@ -1,13 +1,11 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 TEST_DIRS += ['tests']
 
-JS_MODULES_PATH = 'modules/devtools/discovery'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.discovery += [
     'discovery.js',
 ]
--- a/toolkit/devtools/jsbeautify/moz.build
+++ b/toolkit/devtools/jsbeautify/moz.build
@@ -1,19 +1,17 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
 
-JS_MODULES_PATH = 'modules/devtools/jsbeautify'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.jsbeautify += [
     'beautify.js',
     'lib/sanitytest.js',
     'lib/urlencode_unpacker.js',
     'src/beautify-css.js',
     'src/beautify-html.js',
     'src/beautify-js.js',
     'src/beautify-tests.js'
 ]
--- a/toolkit/devtools/pretty-fast/moz.build
+++ b/toolkit/devtools/pretty-fast/moz.build
@@ -1,13 +1,11 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
 
-JS_MODULES_PATH = 'modules/devtools'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools += [
     'pretty-fast.js',
 ]
--- a/toolkit/devtools/qrcode/decoder/moz.build
+++ b/toolkit/devtools/qrcode/decoder/moz.build
@@ -1,11 +1,9 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-JS_MODULES_PATH = 'modules/devtools/qrcode/decoder'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.qrcode.decoder += [
     'index.js',
 ]
--- a/toolkit/devtools/qrcode/encoder/moz.build
+++ b/toolkit/devtools/qrcode/encoder/moz.build
@@ -1,11 +1,9 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-JS_MODULES_PATH = 'modules/devtools/qrcode/encoder'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.qrcode.encoder += [
     'index.js',
 ]
--- a/toolkit/devtools/qrcode/moz.build
+++ b/toolkit/devtools/qrcode/moz.build
@@ -4,16 +4,14 @@
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 DIRS += [
     'decoder',
     'encoder'
 ]
 
-JS_MODULES_PATH = 'modules/devtools/qrcode'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.qrcode += [
     'index.js',
 ]
 
 XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
 MOCHITEST_CHROME_MANIFESTS += ['tests/mochitest/chrome.ini']
--- a/toolkit/devtools/styleinspector/moz.build
+++ b/toolkit/devtools/styleinspector/moz.build
@@ -1,11 +1,9 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-JS_MODULES_PATH = 'modules/devtools/styleinspector'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.styleinspector += [
     'css-logic.js'
 ]
--- a/toolkit/devtools/tern/moz.build
+++ b/toolkit/devtools/tern/moz.build
@@ -1,19 +1,17 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
 
-JS_MODULES_PATH = 'modules/devtools/tern'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.tern += [
     'browser.js',
     'comment.js',
     'condense.js',
     'def.js',
     'ecma5.js',
     'infer.js',
     'signal.js',
     'tern.js',
--- a/toolkit/devtools/transport/moz.build
+++ b/toolkit/devtools/transport/moz.build
@@ -1,15 +1,13 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 TEST_DIRS += ['tests']
 
-JS_MODULES_PATH = 'modules/devtools/transport'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.transport += [
     'packets.js',
     'stream-utils.js',
     'transport.js'
 ]
--- a/toolkit/devtools/webconsole/moz.build
+++ b/toolkit/devtools/webconsole/moz.build
@@ -3,16 +3,14 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 if CONFIG['OS_TARGET'] != 'Android':
     MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
     XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']
 
-JS_MODULES_PATH = 'modules/devtools/toolkit/webconsole'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.toolkit.webconsole += [
     'client.js',
     'network-helper.js',
     'network-monitor.js',
     'utils.js',
 ]
--- a/toolkit/identity/moz.build
+++ b/toolkit/identity/moz.build
@@ -12,29 +12,27 @@ XPIDL_SOURCES += [
 ]
 
 XPIDL_MODULE = 'identity'
 
 SOURCES += [
     'IdentityCryptoService.cpp',
 ]
 
-JS_MODULES_PATH = 'modules/identity'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.identity += [
     'Identity.jsm',
     'IdentityProvider.jsm',
     'IdentityStore.jsm',
     'IdentityUtils.jsm',
     'jwcrypto.jsm',
     'LogUtils.jsm',
     'MinimalIdentity.jsm',
     'RelyingParty.jsm',
     'Sandbox.jsm',
 ]
 
-EXTRA_PP_JS_MODULES += [
+EXTRA_PP_JS_MODULES.identity += [
     'FirefoxAccounts.jsm',
 ]
 
 FAIL_ON_WARNINGS = True
 
 FINAL_LIBRARY = 'xul'
--- a/toolkit/mozapps/extensions/internal/moz.build
+++ b/toolkit/mozapps/extensions/internal/moz.build
@@ -1,29 +1,27 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-JS_MODULES_PATH = 'modules/addons'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.addons += [
     'AddonLogging.jsm',
     'AddonRepository.jsm',
     'AddonRepository_SQLiteMigrator.jsm',
     'AddonUpdateChecker.jsm',
     'Content.js',
     'LightweightThemeImageOptimizer.jsm',
     'OpenH264Provider.jsm',
     'PluginProvider.jsm',
     'SpellCheckDictionaryBootstrap.js',
 ]
 
-EXTRA_PP_JS_MODULES += [
+EXTRA_PP_JS_MODULES.addons += [
     'XPIProvider.jsm',
     'XPIProviderUtils.js',
 ]
 
 # This is used in multiple places, so is defined here to avoid it getting
 # out of sync.
 DEFINES['MOZ_EXTENSIONS_DB_SCHEMA'] = 16