Skip to content

Commit d66c329

Browse files
Merge branch 'main' into implement-ffast-math-21497
2 parents 42e68c4 + d020153 commit d66c329

File tree

6 files changed

+30
-185
lines changed

6 files changed

+30
-185
lines changed

ChangeLog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ See docs/process.md for more on how version tagging works.
2020

2121
4.0.16 (in development)
2222
-----------------------
23+
- For windows users, colored console output for error messages and logging now
24+
requires Windows 10 or above. (#25502)
2325
- A warning was added about usage of embind without C++17 or above. (#25424)
2426
- The minimum supported versions of Node, Chrome and Firefox were bumped
2527
enabling the removal of the `globalThis` polyfill and universally enabling

src/jsifier.mjs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,7 @@ function(${args}) {
642642
}
643643
});
644644

645-
let isFunction = false;
645+
const isFunction = typeof snippet == 'function';
646646
let isNativeAlias = false;
647647

648648
const postsetId = symbol + '__postset';
@@ -680,8 +680,7 @@ function(${args}) {
680680
} else if (typeof snippet == 'object') {
681681
snippet = stringifyWithFunctions(snippet);
682682
addImplicitDeps(snippet, deps);
683-
} else if (typeof snippet == 'function') {
684-
isFunction = true;
683+
} else if (isFunction) {
685684
snippet = processLibraryFunction(snippet, symbol, mangled, deps, isStub);
686685
addImplicitDeps(snippet, deps);
687686
if (CHECK_DEPS && !isUserSymbol) {
@@ -727,6 +726,7 @@ function(${args}) {
727726
// Handle arrow functions
728727
contentText = `var ${mangled} = ` + contentText + ';';
729728
} else if (contentText.startsWith('class ')) {
729+
// Handle class declarations (which also have typeof == 'function'.)
730730
contentText = contentText.replace(/^class /, `class ${mangled} `);
731731
} else {
732732
// Handle regular (non-arrow) functions

test/test_other.py

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11607,21 +11607,12 @@ def test_color_diagnostics_disable(self, flag):
1160711607
})
1160811608
def test_color_diagnostics_force(self, flag):
1160911609
create_file('src.c', 'int main() {')
11610-
# -fansi-escape-codes is needed here to make this test work on windows, which doesn't
11611-
# use ansi codes by default
11612-
output = self.expect_fail([EMCC, '-fansi-escape-codes', flag, 'src.c'])
11610+
# -fansi-escape-codes is needed on windows in order to get clang to emit ANSI colors
11611+
output = self.expect_fail([EMCC, flag, '-fansi-escape-codes', 'src.c'])
1161311612
self.assertIn("\x1b[1msrc.c:1:13: \x1b[0m\x1b[0;1;31merror: \x1b[0m\x1b[1mexpected '}'\x1b[0m", output)
11614-
# Verify that emcc errors show up as red and bold
11613+
# Verify that emcc errors show up as red and bold from emcc
1161511614
self.assertIn('emcc: \x1b[31m\x1b[1m', output)
1161611615

11617-
if WINDOWS:
11618-
# Also test without -fansi-escape-codes on windows.
11619-
# In those mode the code will use kernel calls such as SetConsoleTextAttribute to
11620-
# change the output color. We cannot detect this in the output, but we can at least
11621-
# get coverage of the code path in the diagnositics.py.
11622-
output = self.expect_fail([EMCC, flag, 'src.c'])
11623-
self.assertNotIn('\x1b', output)
11624-
1162511616
def test_sanitizer_color(self):
1162611617
create_file('src.c', '''
1162711618
#include <emscripten.h>

tools/cmdline.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -512,8 +512,6 @@ def consume_arg_file():
512512
diagnostics.color_enabled = True
513513
elif arg in ('-fno-color-diagnostics', '-fdiagnostics-color=never'):
514514
diagnostics.color_enabled = False
515-
elif arg == '-fansi-escape-codes':
516-
diagnostics.force_ansi = True
517515
elif arg == '-fno-exceptions':
518516
settings.DISABLE_EXCEPTION_CATCHING = 1
519517
settings.DISABLE_EXCEPTION_THROWING = 1

tools/colored_logger.py

Lines changed: 16 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -11,88 +11,25 @@
1111
import logging
1212

1313

14-
def add_coloring_to_emit_windows(fn):
14+
def ansi_color_available():
15+
if not sys.platform.startswith('win'):
16+
return sys.stderr.isatty()
17+
1518
# Constants from the Windows API
1619
STD_OUTPUT_HANDLE = -11
20+
ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004
1721

18-
def _get_color():
19-
SHORT = ctypes.c_short
20-
WORD = ctypes.c_ushort
21-
22-
class COORD(ctypes.Structure):
23-
_fields_ = [
24-
("X", SHORT),
25-
("Y", SHORT)]
26-
27-
class SMALL_RECT(ctypes.Structure):
28-
_fields_ = [
29-
("Left", SHORT),
30-
("Top", SHORT),
31-
("Right", SHORT),
32-
("Bottom", SHORT)]
33-
34-
class CONSOLE_SCREEN_BUFFER_INFO(ctypes.Structure):
35-
_fields_ = [
36-
("dwSize", COORD),
37-
("dwCursorPosition", COORD),
38-
("wAttributes", WORD),
39-
("srWindow", SMALL_RECT),
40-
("dwMaximumWindowSize", COORD)]
22+
kernel32 = ctypes.windll.kernel32
23+
stdout_handle = kernel32.GetStdHandle(STD_OUTPUT_HANDLE)
4124

42-
hdl = ctypes.windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE)
43-
csbi = CONSOLE_SCREEN_BUFFER_INFO()
44-
ctypes.windll.kernel32.GetConsoleScreenBufferInfo(hdl, ctypes.byref(csbi))
45-
return csbi.wAttributes
25+
# Get the current console mode
26+
console_mode = ctypes.c_uint()
27+
if not kernel32.GetConsoleMode(stdout_handle, ctypes.byref(console_mode)):
28+
# Handle error if GetConsoleMode fails
29+
return False
4630

47-
def _set_color(code):
48-
hdl = ctypes.windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE)
49-
ctypes.windll.kernel32.SetConsoleTextAttribute(hdl, code)
50-
51-
def new(*args):
52-
# wincon.h
53-
FOREGROUND_BLACK = 0x0000 # noqa
54-
FOREGROUND_BLUE = 0x0001 # noqa
55-
FOREGROUND_GREEN = 0x0002 # noqa
56-
FOREGROUND_CYAN = 0x0003 # noqa
57-
FOREGROUND_RED = 0x0004 # noqa
58-
FOREGROUND_MAGENTA = 0x0005 # noqa
59-
FOREGROUND_YELLOW = 0x0006 # noqa
60-
FOREGROUND_GREY = 0x0007 # noqa
61-
FOREGROUND_INTENSITY = 0x0008 # foreground color is intensified.
62-
63-
FOREGROUND_WHITE = FOREGROUND_BLUE|FOREGROUND_GREEN |FOREGROUND_RED # noqa
64-
65-
BACKGROUND_BLACK = 0x0000 # noqa
66-
BACKGROUND_BLUE = 0x0010 # noqa
67-
BACKGROUND_GREEN = 0x0020 # noqa
68-
BACKGROUND_CYAN = 0x0030 # noqa
69-
BACKGROUND_RED = 0x0040 # noqa
70-
BACKGROUND_MAGENTA = 0x0050 # noqa
71-
BACKGROUND_YELLOW = 0x0060 # noqa
72-
BACKGROUND_GREY = 0x0070 # noqa
73-
BACKGROUND_INTENSITY = 0x0080 # background color is intensified.
74-
levelno = args[1].levelno
75-
if (levelno >= 50):
76-
color = BACKGROUND_YELLOW | FOREGROUND_RED | FOREGROUND_INTENSITY | BACKGROUND_INTENSITY
77-
elif (levelno >= 40):
78-
color = FOREGROUND_RED | FOREGROUND_INTENSITY
79-
elif (levelno >= 30):
80-
color = FOREGROUND_YELLOW | FOREGROUND_INTENSITY
81-
elif (levelno >= 20):
82-
color = FOREGROUND_GREEN
83-
elif (levelno >= 10):
84-
color = FOREGROUND_MAGENTA
85-
else:
86-
color = FOREGROUND_WHITE
87-
88-
old_color = _get_color()
89-
_set_color(color)
90-
ret = fn(*args)
91-
_set_color(old_color)
92-
return ret
93-
94-
new.orig_func = fn
95-
return new
31+
# Check if the flag is set in the current console mode
32+
return (console_mode.value & ENABLE_VIRTUAL_TERMINAL_PROCESSING) != 0
9633

9734

9835
def add_coloring_to_emit_ansi(fn):
@@ -117,11 +54,8 @@ def new(*args):
11754

11855

11956
def enable():
120-
if sys.stderr.isatty():
121-
if sys.platform.startswith('win'):
122-
logging.StreamHandler.emit = add_coloring_to_emit_windows(logging.StreamHandler.emit)
123-
else:
124-
logging.StreamHandler.emit = add_coloring_to_emit_ansi(logging.StreamHandler.emit)
57+
if ansi_color_available():
58+
logging.StreamHandler.emit = add_coloring_to_emit_ansi(logging.StreamHandler.emit)
12559

12660

12761
def disable():

tools/diagnostics.py

Lines changed: 6 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,22 @@
66
"""Simple color-enabled diagnositics reporting functions.
77
"""
88

9-
import ctypes
109
import logging
1110
import os
1211
import sys
1312
from typing import Dict
1413

15-
WINDOWS = sys.platform.startswith('win')
14+
from . import colored_logger
1615

16+
color_enabled = colored_logger.ansi_color_available()
1717
logger = logging.getLogger('diagnostics')
18-
color_enabled = sys.stderr.isatty()
1918
tool_name = os.path.splitext(os.path.basename(sys.argv[0]))[0]
20-
force_ansi = False
2119

2220
# diagnostic levels
2321
WARN = 1
2422
ERROR = 2
2523

26-
# available colors
24+
# available (ANSI) colors
2725
RED = 1
2826
GREEN = 2
2927
YELLOW = 3
@@ -43,94 +41,19 @@
4341
ERROR: 'error: ',
4442
}
4543

46-
# Constants from the Windows API
47-
STD_OUTPUT_HANDLE = -11
48-
49-
50-
def output_color_windows(color):
51-
assert not force_ansi
52-
# TODO(sbc): This code is duplicated in colored_logger.py. Refactor.
53-
# wincon.h
54-
FOREGROUND_BLACK = 0x0000 # noqa
55-
FOREGROUND_BLUE = 0x0001 # noqa
56-
FOREGROUND_GREEN = 0x0002 # noqa
57-
FOREGROUND_CYAN = 0x0003 # noqa
58-
FOREGROUND_RED = 0x0004 # noqa
59-
FOREGROUND_MAGENTA = 0x0005 # noqa
60-
FOREGROUND_YELLOW = 0x0006 # noqa
61-
FOREGROUND_GREY = 0x0007 # noqa
62-
63-
color_map = {
64-
RED: FOREGROUND_RED,
65-
GREEN: FOREGROUND_GREEN,
66-
YELLOW: FOREGROUND_YELLOW,
67-
BLUE: FOREGROUND_BLUE,
68-
MAGENTA: FOREGROUND_MAGENTA,
69-
CYAN: FOREGROUND_CYAN,
70-
WHITE: FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED,
71-
}
72-
73-
sys.stderr.flush()
74-
hdl = ctypes.windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE)
75-
ctypes.windll.kernel32.SetConsoleTextAttribute(hdl, color_map[color])
76-
77-
78-
def get_color_windows():
79-
assert not force_ansi
80-
SHORT = ctypes.c_short
81-
WORD = ctypes.c_ushort
82-
83-
class COORD(ctypes.Structure):
84-
_fields_ = [
85-
("X", SHORT),
86-
("Y", SHORT)]
87-
88-
class SMALL_RECT(ctypes.Structure):
89-
_fields_ = [
90-
("Left", SHORT),
91-
("Top", SHORT),
92-
("Right", SHORT),
93-
("Bottom", SHORT)]
94-
95-
class CONSOLE_SCREEN_BUFFER_INFO(ctypes.Structure):
96-
_fields_ = [
97-
("dwSize", COORD),
98-
("dwCursorPosition", COORD),
99-
("wAttributes", WORD),
100-
("srWindow", SMALL_RECT),
101-
("dwMaximumWindowSize", COORD)]
102-
103-
hdl = ctypes.windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE)
104-
csbi = CONSOLE_SCREEN_BUFFER_INFO()
105-
ctypes.windll.kernel32.GetConsoleScreenBufferInfo(hdl, ctypes.byref(csbi))
106-
return csbi.wAttributes
107-
108-
109-
def reset_color_windows():
110-
assert not force_ansi
111-
sys.stderr.flush()
112-
hdl = ctypes.windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE)
113-
ctypes.windll.kernel32.SetConsoleTextAttribute(hdl, default_color)
114-
11544

11645
def output_color(color):
117-
if WINDOWS and not force_ansi:
118-
output_color_windows(color)
119-
return ''
46+
assert color_enabled
12047
return '\033[3%sm' % color
12148

12249

12350
def bold():
124-
if WINDOWS and not force_ansi:
125-
# AFAICT there is no way to enable bold output on windows
126-
return ''
51+
assert color_enabled
12752
return '\033[1m'
12853

12954

13055
def reset_color():
131-
if WINDOWS and not force_ansi:
132-
reset_color_windows()
133-
return ''
56+
assert color_enabled
13457
return '\033[0m'
13558

13659

@@ -260,7 +183,4 @@ def capture_warnings(argv):
260183
return manager.capture_warnings(argv)
261184

262185

263-
if WINDOWS:
264-
default_color = get_color_windows()
265-
266186
manager = WarningManager()

0 commit comments

Comments
 (0)