Skip to content

Commit 0098591

Browse files
authored
fix(logger): console.assert() throws exception #395
Problem: Exception when calling `console.assert()`. Example from vscode-neovim/vscode-neovim#2242 : {"tag":"dap.send","timestamp":1726115647837,"metadata":{"connectionId":3,"message":{"seq":1,"type":"response","request_seq":1,"command":"initialize","success":false,"body":{"error":{"id":9221,"format": "Error processing initialize: TypeError: Cannot read properties of undefined (reading 'apply') at console.<computed> [as assert] (/home/vscode/.vscode-server/extensions/asvetliakov.vscode-neovim-1.18.11/node_modules/neovim/lib/utils/logger.js:72:46) at r.onInitialize (/vscode/vscode-server/…/extensions/ms-vscode.js-debug/src/extension.js:120:345) at /vscode/vscode-server/…/extensions/ms-vscode.js-debug/src/extension.js:119:1632 at zc._onMessage (/vscode/vscode-server/…/extensions/ms-vscode.js-debug/src/extension.js:34:4948) at /vscode/vscode-server/…/extensions/ms-vscode.js-debug/src/extension.js:34:3426 at D.fire (/vscode/vscode-server/…/extensions/ms-vscode.js-debug/src/extension.js:30:10962) at Socket._handleData (/vscode/vscode-server/…/extensions/ms-vscode.js-debug/src/extension.js:116:688) at Socket.emit (node:events:519:28) at addChunk (node:internal/streams/readable:559:12) at readableAddChunkPushByteMode (node:internal/streams/readable:510:3) at Socket.Readable.push (node:internal/streams/readable:390:5) at Pipe.onStreamRead (node:internal/stream_base_commons:191:23)","showUser":false,"sendTelemetry":false}}}},"level":0} 9a2cf4c restored "console.x monkey-patching", but the logic was sloppy: it replaces every console.x function instead of only the ones that our logger actually supports. Solution: - Only patch `console.x` functions we can actually support. - Special-case `console.assert`.
1 parent bbc0b42 commit 0098591

File tree

3 files changed

+32
-9
lines changed

3 files changed

+32
-9
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## [5.3.0](https://github.com/neovim/node-client/compare/v5.2.0...v5.3.0)
44

5-
- TBD
5+
- fix(logger): console.assert() throws exception
66

77
## [5.2.0](https://github.com/neovim/node-client/compare/v5.1.0...v5.2.0)
88

packages/neovim/src/attach/attach.test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,17 @@ describe('Nvim API', () => {
4747
expect(await nvim.eval('1+1')).toEqual(2);
4848
});
4949

50+
it('console.assert is monkey-patched', async () => {
51+
const spy = jest.spyOn(nvim.logger, 'error');
52+
// eslint-disable-next-line no-console
53+
console.assert(false, 'foo', 42, { x: [1, 2] });
54+
expect(spy).toHaveBeenCalledWith('assertion failed', 'foo', 42, {
55+
x: [1, 2],
56+
});
57+
// Still alive?
58+
expect(await nvim.eval('1+1')).toEqual(2);
59+
});
60+
5061
it('console.log NOT monkey-patched if custom logger passed to attach()', async () => {
5162
const [proc2] = testUtil.startNvim(false);
5263
const logged: string[] = [];

packages/neovim/src/utils/logger.ts

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,8 @@ import { inspect } from 'node:util';
33

44
const level = process.env.NVIM_NODE_LOG_LEVEL || 'debug';
55

6-
export type Logger = Pick<
7-
winston.Logger,
8-
'info' | 'warn' | 'error' | 'debug' | 'level'
9-
>;
6+
const loggerKeys = ['info', 'warn', 'error', 'debug', 'level'] as const;
7+
export type Logger = Pick<winston.Logger, (typeof loggerKeys)[number]>;
108

119
function getFormat(colorize: boolean) {
1210
return winston.format.combine(
@@ -61,10 +59,24 @@ function setupWinstonLogger(): Logger {
6159

6260
// Monkey-patch `console` so that it does not write to the RPC (stdio) channel.
6361
Object.keys(console).forEach((k: string) => {
64-
(console as any)[k] = function () {
65-
// eslint-disable-next-line prefer-rest-params
66-
(logger as any)[k === 'log' ? 'info' : k].apply(logger, arguments);
67-
};
62+
const loggerKey = k === 'log' ? 'info' : k;
63+
if (k === 'assert') {
64+
// XXX: support console.assert() even though our logger doesn't define it.
65+
// eslint-disable-next-line no-console
66+
console.assert = function (
67+
condition?: boolean | undefined,
68+
...data: any[]
69+
) {
70+
if (!condition) {
71+
logger.error('assertion failed', ...data);
72+
}
73+
};
74+
} else if (loggerKeys.includes(loggerKey as any)) {
75+
(console as any)[k] = function (...args: any[]) {
76+
const loggerFn = (logger as any)[loggerKey];
77+
loggerFn.apply(logger, args);
78+
};
79+
}
6880
});
6981

7082
return logger;

0 commit comments

Comments
 (0)