Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -313,11 +313,19 @@ Usage :
`enable(namespaces)`
`namespaces` can include modes separated by a colon and wildcards.

Note that calling `enable()` completely overrides previously set DEBUG variable :
Calling `enable()` merges with previously set namespaces (including `DEBUG`)
instead of replacing them:

```
$ DEBUG=foo node -e 'var dbg = require("debug"); dbg.enable("bar"); console.log(dbg.enabled("foo"))'
=> false
$ DEBUG=foo node -e 'var dbg = require("debug"); dbg.enable("bar"); console.log(dbg.enabled("foo"), dbg.enabled("bar"))'
=> true true
```

To replace the set entirely, disable first:

```js
debug.disable();
debug.enable('bar');
```

`disable()`
Expand Down
68 changes: 50 additions & 18 deletions src/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,32 +153,64 @@ function setup(env) {
}

/**
* Enables a debug mode by namespaces. This can include modes
* separated by a colon and wildcards.
* Parse a namespace list into individual tokens.
*
* @param {String} namespaces
* @api public
* @return {Array}
* @api private
*/
function enable(namespaces) {
createDebug.save(namespaces);
createDebug.namespaces = namespaces;

createDebug.names = [];
createDebug.skips = [];

const split = (typeof namespaces === 'string' ? namespaces : '')
function parseNamespaces(namespaces) {
return (typeof namespaces === 'string' ? namespaces : '')
.trim()
.replace(/\s+/g, ',')
.split(',')
.filter(Boolean);
}

/**
* Serialize the current names/skips into a namespace string.
*
* @return {String}
* @api private
*/
function formatNamespaces() {
return [
...createDebug.names,
...createDebug.skips.map(namespace => '-' + namespace)
].join(',');
}

/**
* Enables a debug mode by namespaces. This can include modes
* separated by a colon and wildcards.
*
* New namespaces are merged with those already enabled.
* Call `disable()` first to replace the set instead of extending it.
*
* @param {String} namespaces
* @api public
*/
function enable(namespaces) {
const split = parseNamespaces(namespaces);

for (const ns of split) {
if (ns[0] === '-') {
createDebug.skips.push(ns.slice(1));
const name = ns.slice(1);
createDebug.names = createDebug.names.filter(existing => existing !== name);
if (!createDebug.skips.includes(name)) {
createDebug.skips.push(name);
}
} else {
createDebug.names.push(ns);
createDebug.skips = createDebug.skips.filter(existing => existing !== ns);
if (!createDebug.names.includes(ns)) {
createDebug.names.push(ns);
}
}
}

const merged = formatNamespaces();
createDebug.save(merged);
createDebug.namespaces = merged;
}

/**
Expand Down Expand Up @@ -231,11 +263,11 @@ function setup(env) {
* @api public
*/
function disable() {
const namespaces = [
...createDebug.names,
...createDebug.skips.map(namespace => '-' + namespace)
].join(',');
createDebug.enable('');
const namespaces = formatNamespaces();
createDebug.names = [];
createDebug.skips = [];
createDebug.save('');
createDebug.namespaces = '';
return namespaces;
}

Expand Down
66 changes: 66 additions & 0 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ const assert = require('assert');
const debug = require('./src');

describe('debug', () => {
beforeEach(() => {
debug.disable();
});

it('passes a basic sanity check', () => {
const log = debug('test');
log.enabled = true;
Expand All @@ -29,6 +33,68 @@ describe('debug', () => {
assert.deepStrictEqual(debug('test:67890').enabled, false);
});

describe('enable() does not flush existing namespaces (#425)', () => {
it('merges subsequent enable() calls with previously enabled namespaces', () => {
debug.enable('foo');
debug.enable('bar');

assert.deepStrictEqual(debug.enabled('foo'), true);
assert.deepStrictEqual(debug.enabled('bar'), true);
});

it('preserves namespaces from a prior enable() like DEBUG=foo then enable("bar")', () => {
debug.enable('foo');
debug.enable('bar');

assert.deepStrictEqual(debug.enabled('foo'), true);
assert.deepStrictEqual(debug.enabled('bar'), true);
assert.deepStrictEqual(debug.disable(), 'foo,bar');
});

it('does not drop earlier namespaces when a later module enables its own', () => {
debug.enable('my-module');
debug.enable('my-dep-module');

assert.deepStrictEqual(debug.enabled('my-module'), true);
assert.deepStrictEqual(debug.enabled('my-dep-module'), true);
});

it('can still replace the set via disable() then enable()', () => {
debug.enable('foo');
debug.disable();
debug.enable('bar');

assert.deepStrictEqual(debug.enabled('foo'), false);
assert.deepStrictEqual(debug.enabled('bar'), true);
});

it('adds skip patterns without dropping other namespaces', () => {
debug.enable('foo');
debug.enable('-foo');
debug.enable('bar');

assert.deepStrictEqual(debug.enabled('foo'), false);
assert.deepStrictEqual(debug.enabled('bar'), true);
});

it('re-enabling a skipped namespace removes the skip', () => {
debug.enable('foo');
debug.enable('-foo');
assert.deepStrictEqual(debug.enabled('foo'), false);

debug.enable('foo');
assert.deepStrictEqual(debug.enabled('foo'), true);
});

it('does not duplicate namespaces when enable() is repeated', () => {
debug.enable('foo');
debug.enable('foo');
debug.enable('bar,foo');

assert.deepStrictEqual(debug.disable(), 'foo,bar');
});
});

it('uses custom log function', () => {
const log = debug('test');
log.enabled = true;
Expand Down