src/vs/workbench/api/common/extHostConsoleForwarder.ts/safeStringifyArgumentsToArray
function safeStringifyArgumentsToArray(args: IArguments, includeStack: boolean): string {
	const argsArray = [];

	// Massage some arguments with special treatment
	if (args.length) {
		for (let i = 0; i < args.length; i++) {
			let arg = args[i];

			// Any argument of type 'undefined' needs to be specially treated because
			// JSON.stringify will simply ignore those. We replace them with the string
			// 'undefined' which is not 100% right, but good enough to be logged to console
			if (typeof arg === 'undefined') {
				arg = 'undefined';
			}

			// Any argument that is an Error will be changed to be just the error stack/message
			// itself because currently cannot serialize the error over entirely.
			else if (arg instanceof Error) {
				const errorObj = arg;
				if (errorObj.stack) {
					arg = errorObj.stack;
				} else {
					arg = errorObj.toString();
				}
			}

			argsArray.push(arg);
		}
	}

	// Add the stack trace as payload if we are told so. We remove the message and the 2 top frames
	// to start the stacktrace where the console message was being written
	if (includeStack) {
		const stack = new Error().stack;
		if (stack) {
			argsArray.push({ __$stack: stack.split('\n').slice(3).join('\n') } as IStackArgument);
		}
	}

	try {
		const res = safeStringify(argsArray);

		if (res.length > MAX_LENGTH) {
			return 'Output omitted for a large object that exceeds the limits';
		}

		return res;
	} catch (error) {
		return `Output omitted for an object that cannot be inspected ('${error.toString()}')`;
	}
}