Bug 1287915 - support webpack "raw!" requires in devtools loader; r?jryans
MozReview-Commit-ID: 1H6ogaMrZPV
--- a/.eslintignore
+++ b/.eslintignore
@@ -123,16 +123,17 @@ devtools/server/actors/**
!devtools/server/actors/string.js
!devtools/server/actors/csscoverage.js
devtools/server/performance/**
devtools/server/tests/**
devtools/shared/*.js
!devtools/shared/css-lexer.js
!devtools/shared/defer.js
!devtools/shared/event-emitter.js
+!devtools/shared/loader-plugin-raw.jsm
!devtools/shared/task.js
devtools/shared/*.jsm
!devtools/shared/Loader.jsm
devtools/shared/apps/**
devtools/shared/client/**
devtools/shared/discovery/**
devtools/shared/gcli/**
!devtools/shared/gcli/templater.js
--- a/devtools/client/shared/browser-loader.js
+++ b/devtools/client/shared/browser-loader.js
@@ -96,16 +96,22 @@ function BrowserLoaderBuilder({ baseURI,
const opts = {
id: "browser-loader",
sharedGlobal: true,
sandboxPrototype: window,
paths: Object.assign({}, dynamicPaths, loaderOptions.paths),
invisibleToDebugger: loaderOptions.invisibleToDebugger,
requireHook: (id, require) => {
+ // If |id| requires special handling, simply defer to devtools
+ // immediately.
+ if (devtools.isLoaderPluginId(id)) {
+ return devtools.require(id);
+ }
+
const uri = require.resolve(id);
let isBrowserDir = BROWSER_BASED_DIRS.filter(dir => {
return uri.startsWith(dir);
}).length > 0;
// If the URI doesn't match hardcoded paths try the regexp.
if (!isBrowserDir) {
isBrowserDir = uri.match(browserBasedDirsRegExp) != null;
--- a/devtools/client/shared/test/browser.ini
+++ b/devtools/client/shared/test/browser.ini
@@ -142,16 +142,17 @@ skip-if = e10s # Layouthelpers test shou
[browser_mdn-docs-03.js]
[browser_num-l10n.js]
[browser_options-view-01.js]
[browser_outputparser.js]
skip-if = e10s # Test intermittently fails with e10s. Bug 1124162.
[browser_poller.js]
[browser_prefs-01.js]
[browser_prefs-02.js]
+[browser_require_raw.js]
[browser_spectrum.js]
[browser_theme.js]
[browser_tableWidget_basic.js]
[browser_tableWidget_keyboard_interaction.js]
[browser_tableWidget_mouse_interaction.js]
[browser_telemetry_button_eyedropper.js]
[browser_telemetry_button_paintflashing.js]
skip-if = e10s # Bug 937167 - e10s paintflashing
new file mode 100644
--- /dev/null
+++ b/devtools/client/shared/test/browser_require_raw.js
@@ -0,0 +1,20 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const { BrowserLoader } = Cu.import("resource://devtools/client/shared/browser-loader.js", {});
+
+const { require: browserRequire } = BrowserLoader({
+ baseURI: "resource://devtools/client/shared/",
+ window: this
+});
+
+const variableFileContents = browserRequire("raw!devtools/client/themes/variables.css");
+
+function test() {
+ ok(variableFileContents.length > 0, "raw browserRequire worked");
+ finish();
+}
--- a/devtools/client/shared/theme.js
+++ b/devtools/client/shared/theme.js
@@ -4,55 +4,31 @@
"use strict";
/**
* Colors for themes taken from:
* https://developer.mozilla.org/en-US/docs/Tools/DevToolsColors
*/
-const { Cu } = require("chrome");
-const { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm", {});
const Services = require("Services");
const { gDevTools } = require("devtools/client/framework/devtools");
-const VARIABLES_URI = "chrome://devtools/skin/variables.css";
+const variableFileContents = require("raw!devtools/client/themes/variables.css");
+
const THEME_SELECTOR_STRINGS = {
light: ":root.theme-light {",
dark: ":root.theme-dark {"
};
-let variableFileContents;
-
-/**
- * Returns a string of the file found at URI
- */
-function readURI(uri) {
- let stream = NetUtil.newChannel({
- uri: NetUtil.newURI(uri, "UTF-8"),
- loadUsingSystemPrincipal: true}
- ).open2();
-
- let count = stream.available();
- let data = NetUtil.readInputStreamToString(stream, count, {
- charset: "UTF-8"
- });
- stream.close();
- return data;
-}
-
/**
* Takes a theme name and returns the contents of its variable rule block.
* The first time this runs fetches the variables CSS file and caches it.
*/
function getThemeFile(name) {
- if (!variableFileContents) {
- variableFileContents = readURI(VARIABLES_URI);
- }
-
// If there's no theme expected for this name, use `light` as default.
let selector = THEME_SELECTOR_STRINGS[name] ||
THEME_SELECTOR_STRINGS.light;
// This is a pretty naive way to find the contents between:
// selector {
// name: val;
// }
--- a/devtools/shared/Loader.jsm
+++ b/devtools/shared/Loader.jsm
@@ -6,16 +6,17 @@
/**
* Manages the addon-sdk loader instance used to load the developer tools.
*/
var { utils: Cu } = Components;
var { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
var { Loader, descriptor, resolveURI } = Cu.import("resource://gre/modules/commonjs/toolkit/loader.js", {});
+var { requireRawId } = Cu.import("resource://devtools/shared/loader-plugin-raw.jsm", {});
this.EXPORTED_SYMBOLS = ["DevToolsLoader", "devtools", "BuiltinProvider",
"require", "loader"];
/**
* Providers are different strategies for loading the devtools.
*/
@@ -54,16 +55,22 @@ BuiltinProvider.prototype = {
paths.promise = "resource://gre/modules/Promise-backend.js";
}
this.loader = new Loader.Loader({
id: "fx-devtools",
paths,
invisibleToDebugger: this.invisibleToDebugger,
sharedGlobal: true,
sharedGlobalBlocklist,
+ requireHook: (id, require) => {
+ if (id.startsWith("raw!")) {
+ return requireRawId(id, require);
+ }
+ return require(id);
+ },
});
},
unload: function (reason) {
Loader.unload(this.loader, reason);
delete this.loader;
},
};
@@ -116,16 +123,24 @@ DevToolsLoader.prototype = {
require: function () {
if (!this._provider) {
this._loadProvider();
}
return this.require.apply(this, arguments);
},
/**
+ * Return true if |id| refers to something requiring help from a
+ * loader plugin.
+ */
+ isLoaderPluginId: function (id) {
+ return id.startsWith("raw!");
+ },
+
+ /**
* Override the provider used to load the tools.
*/
setProvider: function (provider) {
if (provider === this._provider) {
return;
}
if (this._provider) {
new file mode 100644
--- /dev/null
+++ b/devtools/shared/loader-plugin-raw.jsm
@@ -0,0 +1,41 @@
+/* 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/. */
+
+"use strict";
+
+const { utils: Cu } = Components;
+const { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm", {});
+
+/**
+ * A function that can be used as part of a require hook for a
+ * loader.js Loader. This function only handles webpack-style "raw!"
+ * requires; other requires should not be passed to this. See
+ * https://github.com/webpack/raw-loader.
+ */
+function requireRawId(id, require) {
+ let uri = require.resolve(id.slice(4));
+ // If the original string did not end with ".js", then
+ // require.resolve might have added the suffix. We don't want to
+ // add a suffix for a raw load (if needed the caller can specify it
+ // manually), so remove it here.
+ if (!id.endsWith(".js") && uri.endsWith(".js")) {
+ uri = uri.slice(0, -3);
+ }
+ let stream = NetUtil.newChannel({
+ uri: NetUtil.newURI(uri, "UTF-8"),
+ loadUsingSystemPrincipal: true
+ }).open2();
+
+ let count = stream.available();
+ let data = NetUtil.readInputStreamToString(stream, count, {
+ charset: "UTF-8"
+ });
+ stream.close();
+
+ // For the time being it doesn't seem worthwhile to cache the
+ // result here.
+ return data;
+}
+
+this.EXPORTED_SYMBOLS = ["requireRawId"];
--- a/devtools/shared/moz.build
+++ b/devtools/shared/moz.build
@@ -49,16 +49,17 @@ DevToolsModules(
'css-properties-db.js',
'defer.js',
'deprecated-sync-thenables.js',
'DevToolsUtils.js',
'dom-node-constants.js',
'dom-node-filter-constants.js',
'event-emitter.js',
'indentation.js',
+ 'loader-plugin-raw.jsm',
'Loader.jsm',
'Parser.jsm',
'path.js',
'protocol.js',
'system.js',
'task.js',
'ThreadSafeDevToolsUtils.js',
)
new file mode 100644
--- /dev/null
+++ b/devtools/shared/tests/unit/test_require_raw.js
@@ -0,0 +1,12 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Test require using "raw!".
+
+function run_test() {
+ let loader = new DevToolsLoader();
+ let require = loader.require;
+
+ let variableFileContents = require("raw!devtools/client/themes/variables.css");
+ ok(variableFileContents.length > 0, "raw browserRequire worked");
+}
--- a/devtools/shared/tests/unit/xpcshell.ini
+++ b/devtools/shared/tests/unit/xpcshell.ini
@@ -20,12 +20,13 @@ support-files =
[test_invisible_loader.js]
[test_isSet.js]
[test_safeErrorString.js]
[test_defineLazyPrototypeGetter.js]
[test_async-utils.js]
[test_console_filtering.js]
[test_prettifyCSS.js]
[test_require_lazy.js]
+[test_require_raw.js]
[test_require.js]
[test_stack.js]
[test_defer.js]
[test_executeSoon.js]