From 74b39b18131939bdc76bb2337a6a04a47531ec1e Mon Sep 17 00:00:00 2001 From: Arron Zou Date: Fri, 14 Aug 2026 17:42:16 +0800 Subject: [PATCH] fix: make disable() namespaces round-trip through enable() Historic enable() compiled '*' to '.*?'. disable() only inverted a trailing wildcard, so patterns like "*:error:*" came back as ".*?:error:*" and enable() rejected them. Normalize that encoding so enable(disable()) accepts mid-string wildcards and skip namespaces. Fixes #918 --- src/common.js | 16 ++++++++++++---- test.js | 19 +++++++++++++++++++ 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/common.js b/src/common.js index 141cb578..46ef8304 100644 --- a/src/common.js +++ b/src/common.js @@ -174,13 +174,21 @@ function setup(env) { for (const ns of split) { if (ns[0] === '-') { - createDebug.skips.push(ns.slice(1)); + createDebug.skips.push(toNamespace(ns.slice(1))); } else { - createDebug.names.push(ns); + createDebug.names.push(toNamespace(ns)); } } } + // Invert historic '*' → '.*?' encoding so disable()/enable() can round-trip. + function toNamespace(namespace) { + const value = namespace instanceof RegExp ? + namespace.source.replace(/^\^/, '').replace(/\$$/, '') : + String(namespace); + return value.replace(/\.\*\?/g, '*'); + } + /** * Checks if the given string matches a namespace template, honoring * asterisks as wildcards. @@ -232,8 +240,8 @@ function setup(env) { */ function disable() { const namespaces = [ - ...createDebug.names, - ...createDebug.skips.map(namespace => '-' + namespace) + ...createDebug.names.map(toNamespace), + ...createDebug.skips.map(namespace => '-' + toNamespace(namespace)) ].join(','); createDebug.enable(''); return namespaces; diff --git a/test.js b/test.js index a1d6f633..db5ecd8b 100644 --- a/test.js +++ b/test.js @@ -118,6 +118,25 @@ describe('debug', () => { assert.deepStrictEqual(oldSkips.map(String), debug.skips.map(String)); }); + it('round-trips wildcard namespaces including skips', () => { + debug.enable('*:error:*,-*:error:ignore'); + const namespaces = debug.disable(); + assert.deepStrictEqual(namespaces, '*:error:*,-*:error:ignore'); + assert.doesNotThrow(() => debug.enable(namespaces)); + assert.deepStrictEqual(debug.enabled('api:error:db'), true); + assert.deepStrictEqual(debug.enabled('api:error:ignore'), false); + assert.deepStrictEqual(debug.enabled('api:warn:db'), false); + }); + + it('accepts historic disable() wildcard encoding', () => { + debug.enable('.*?:error:*,-.*?:verbose'); + const namespaces = debug.disable(); + assert.deepStrictEqual(namespaces, '*:error:*,-*:verbose'); + assert.doesNotThrow(() => debug.enable(namespaces)); + assert.deepStrictEqual(debug.enabled('api:error:db'), true); + assert.deepStrictEqual(debug.enabled('api:verbose'), false); + }); + it('handles re-enabling existing instances', () => { debug.disable('*'); const inst = debug('foo');