diff --git a/devtools/server/actors/watcher/SessionDataHelpers.jsm b/devtools/server/actors/watcher/SessionDataHelpers.jsm index a9c111a53b23..c70df1744f00 100644 --- a/devtools/server/actors/watcher/SessionDataHelpers.jsm +++ b/devtools/server/actors/watcher/SessionDataHelpers.jsm @@ -31,15 +31,11 @@ if (typeof module == "object") { true ); } else { - // Ignore the "duplicate" definitions here as this are also defined - // in the if block above. - // eslint-disable-next-line mozilla/valid-lazy ChromeUtils.defineLazyGetter(lazy, "validateBreakpointLocation", () => { return ChromeUtils.import( "resource://devtools/shared/validate-breakpoint.jsm" ).validateBreakpointLocation; }); - // eslint-disable-next-line mozilla/valid-lazy ChromeUtils.defineLazyGetter(lazy, "validateEventBreakpoint", () => { const { loader } = ChromeUtils.importESModule( "resource://devtools/shared/loader/Loader.sys.mjs" diff --git a/services/sync/modules/main.sys.mjs b/services/sync/modules/main.sys.mjs index 283d4c7f093f..838da15742f0 100644 --- a/services/sync/modules/main.sys.mjs +++ b/services/sync/modules/main.sys.mjs @@ -8,7 +8,6 @@ const lazy = {}; // We want these to be lazily loaded, which helps performance and also tests // to not have these loaded before they are ready. -// eslint-disable-next-line mozilla/valid-lazy ChromeUtils.defineESModuleGetters(lazy, { Service: "resource://services-sync/service.sys.mjs", Status: "resource://services-sync/status.sys.mjs", @@ -16,7 +15,6 @@ ChromeUtils.defineESModuleGetters(lazy, { Utils: "resource://services-sync/util.sys.mjs", }); -// eslint-disable-next-line mozilla/valid-lazy ChromeUtils.defineLazyGetter(lazy, "Crypto", () => { let { WeaveCrypto } = ChromeUtils.importESModule( "resource://services-crypto/WeaveCrypto.sys.mjs" diff --git a/toolkit/modules/subprocess/Subprocess.sys.mjs b/toolkit/modules/subprocess/Subprocess.sys.mjs index f26fe50fc243..ffbeb0acbb56 100644 --- a/toolkit/modules/subprocess/Subprocess.sys.mjs +++ b/toolkit/modules/subprocess/Subprocess.sys.mjs @@ -20,9 +20,6 @@ if (AppConstants.platform == "win") { SubprocessImpl: "resource://gre/modules/subprocess/subprocess_win.sys.mjs", }); } else { - // Ignore the "duplicate" definitions here as this are also defined - // in the "win" block above. - // eslint-disable-next-line mozilla/valid-lazy ChromeUtils.defineESModuleGetters(lazy, { SubprocessImpl: "resource://gre/modules/subprocess/subprocess_unix.sys.mjs", }); diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/valid-lazy.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/valid-lazy.js index 64e7f4184263..6b678a89bf41 100644 --- a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/valid-lazy.js +++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/valid-lazy.js @@ -67,8 +67,46 @@ module.exports = { let unknownProperties = []; let isLazyExported = false; + function getAncestorNodes(node) { + const ancestors = []; + node = node.parent; + while (node) { + ancestors.unshift(node); + node = node.parent; + } + return ancestors; + } + + // Returns true if lazy getter definitions in prevNode and currNode are + // duplicate. + // This returns false if prevNode and currNode have the same IfStatement as + // ancestor and they're in different branches. + function isDuplicate(prevNode, currNode) { + const prevAncestors = getAncestorNodes(prevNode); + const currAncestors = getAncestorNodes(currNode); + + for ( + let i = 0; + i < prevAncestors.length && i < currAncestors.length; + i++ + ) { + const prev = prevAncestors[i]; + const curr = currAncestors[i]; + if (prev === curr && prev.type === "IfStatement") { + if (prevAncestors[i + 1] !== currAncestors[i + 1]) { + return false; + } + } + } + + return true; + } + function addProp(node, name) { - if (lazyProperties.has(name)) { + if ( + lazyProperties.has(name) && + isDuplicate(lazyProperties.get(name).node, node) + ) { context.report({ node, messageId: "duplicateSymbol", @@ -135,7 +173,10 @@ module.exports = { for (let reg of callExpressionDefinitions) { let match = source.match(reg); if (match) { - if (lazyProperties.has(match[1])) { + if ( + lazyProperties.has(match[1]) && + isDuplicate(lazyProperties.get(match[1]).node, node) + ) { context.report({ node, messageId: "duplicateSymbol", diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/valid-lazy.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/valid-lazy.js index 8da035b717ed..ba0a8dafab38 100644 --- a/tools/lint/eslint/eslint-plugin-mozilla/tests/valid-lazy.js +++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/valid-lazy.js @@ -102,6 +102,15 @@ ruleTester.run("valid-lazy", rule, { ChromeUtils.defineLazyGetter(lazy, "foo", () => {}); export { lazy as Foo }; `, + ` + const lazy = {}; + if (cond) { + ChromeUtils.defineLazyGetter(lazy, "foo", () => { return 1; }); + } else { + ChromeUtils.defineLazyGetter(lazy, "foo", () => { return 2; }); + } + if (x) { lazy.foo; } + `, ], invalid: [ invalidCode("if (x) { lazy.bar; }", "bar", "unknownProperty"),