build-debugger.js (3494B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */ 4 5 "use strict"; 6 7 // eslint-disable-next-line mozilla/reject-relative-requires 8 const Babel = require("./babel"); 9 const _path = require("path"); 10 11 function isRequire(t, node) { 12 return node && t.isCallExpression(node) && node.callee.name == "require"; 13 } 14 15 function shouldLazyLoad(value) { 16 return ( 17 !value.includes("codemirror/") && 18 !value.endsWith(".properties") && 19 !value.startsWith("devtools/") && 20 !value.startsWith("resource://devtools/") && 21 // XXX: the lazyRequire rewriter (in transformMC) fails for this module, it 22 // evaluates `t.thisExpression()` as `void 0` instead of `this`. But the 23 // rewriter still works for other call sites and seems mandatory for the 24 // debugger to start successfully (lazy requires help to break circular 25 // dependencies). 26 value !== "resource://gre/modules/AppConstants.jsm" 27 ); 28 } 29 30 /** 31 * This Babel plugin is used to transpile a single Debugger module into a module that 32 * can be loaded in Firefox via the regular DevTools loader. 33 */ 34 function transformMC({ types: t }) { 35 return { 36 visitor: { 37 StringLiteral(path, state) { 38 const { filePath } = state.opts; 39 let value = path.node.value; 40 41 if (!isRequire(t, path.parent)) { 42 return; 43 } 44 45 if (shouldLazyLoad(value)) { 46 const requireCall = path.parentPath; 47 const declarator = requireCall.parentPath; 48 const declaration = declarator.parentPath; 49 50 // require()s that are not assigned to a variable cannot be safely lazily required 51 // since we lack anything to initiate the require (= the getter for the variable) 52 if (declarator.type !== "VariableDeclarator") { 53 return; 54 } 55 56 // update relative paths to be "absolute" (starting with devtools/) 57 // e.g. ./utils/source-queue 58 if (value.startsWith(".")) { 59 // Create full path 60 // e.g. z:\build\build\src\devtools\client\debugger\src\utils\source-queue 61 let newValue = _path.join(_path.dirname(filePath), value); 62 63 // Select the devtools portion of the path 64 // e.g. devtools\client\debugger\src\utils\source-queue 65 if (!newValue.startsWith("devtools")) { 66 newValue = newValue.match(/^(.*?)(devtools.*)/)[2]; 67 } 68 69 // Replace forward slashes with back slashes 70 // e.g devtools/client/debugger/src/utils/source-queue 71 newValue = newValue.replace(/\\/g, "/"); 72 73 value = newValue; 74 } 75 76 // rewrite to: loader.lazyRequireGetter(this, "variableName", "pathToFile") 77 const lazyRequire = t.callExpression( 78 t.memberExpression( 79 t.identifier("loader"), 80 t.identifier("lazyRequireGetter") 81 ), 82 [ 83 t.thisExpression(), 84 t.stringLiteral(declarator.node.id.name || ""), 85 t.stringLiteral(value), 86 ] 87 ); 88 89 declaration.replaceWith(lazyRequire); 90 } 91 }, 92 }, 93 }; 94 } 95 96 Babel.registerPlugin("transform-mc", transformMC); 97 98 module.exports = function (filePath) { 99 return [ 100 "proposal-class-properties", 101 "transform-modules-commonjs", 102 ["transform-mc", { filePath }], 103 ]; 104 };