From 396e352fbd5f279a3c430c911da9c80b7d85306c Mon Sep 17 00:00:00 2001 From: Maruthan G Date: Sun, 19 Apr 2026 15:20:12 +0530 Subject: [PATCH] tools: silence cpplint refs warning for v8 fast api options cpplint's runtime/references rule flags non-const reference parameters as a style violation. v8::FastApiCallbackOptions& is part of the V8 Fast API contract: V8 dictates the signature and Node.js has no say, so the warning is a false positive on every Fast API callback. Most call sites in src/ also `using v8::FastApiCallbackOptions;` and declare the parameter as the unqualified `FastApiCallbackOptions&`, which a fully qualified pattern would miss. Allowlist both forms in CheckForNonConstReference and add a unit test that exercises both spellings while keeping the rule active for unrelated `Type&` params. Fixes: https://github.com/nodejs/node/issues/45761 Signed-off-by: Maruthan G --- tools/cpplint.py | 11 +++++- tools/test_cpplint_fast_api.py | 72 ++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 tools/test_cpplint_fast_api.py diff --git a/tools/cpplint.py b/tools/cpplint.py index 464d95b8824f95..6e77c04f56dd76 100755 --- a/tools/cpplint.py +++ b/tools/cpplint.py @@ -6036,6 +6036,11 @@ def _GetTextInside(text, start_pattern): ) # Stream types. _RE_PATTERN_REF_STREAM_PARAM = r"(?:.*stream\s*&\s*" + _RE_PATTERN_IDENT + r")" +# V8 Fast API types whose signatures are dictated by V8 and require a +# non-const reference parameter; Node.js cannot change these. +_RE_PATTERN_REF_V8_FAST_API_PARAM = ( + r"(?:.*\b(?:v8::)?FastApiCallbackOptions\s*&\s*" + _RE_PATTERN_IDENT + r")" +) def CheckLanguage( @@ -6585,8 +6590,10 @@ def CheckForNonConstReference(filename, clean_lines, linenum, nesting_state, err decls = re.sub(r"{[^}]*}", " ", line) # exclude function body for parameter in re.findall(_RE_PATTERN_REF_PARAM, decls): - if not re.match(_RE_PATTERN_CONST_REF_PARAM, parameter) and not re.match( - _RE_PATTERN_REF_STREAM_PARAM, parameter + if ( + not re.match(_RE_PATTERN_CONST_REF_PARAM, parameter) + and not re.match(_RE_PATTERN_REF_STREAM_PARAM, parameter) + and not re.match(_RE_PATTERN_REF_V8_FAST_API_PARAM, parameter) ): error( filename, diff --git a/tools/test_cpplint_fast_api.py b/tools/test_cpplint_fast_api.py new file mode 100644 index 00000000000000..b0fad6e2b790c3 --- /dev/null +++ b/tools/test_cpplint_fast_api.py @@ -0,0 +1,72 @@ +"""Regression tests for cpplint runtime/references and V8 Fast API. + +Refs: https://github.com/nodejs/node/issues/45761 +""" + +import os +import sys +import unittest + +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +import cpplint # noqa: E402 + + +def _lint(source): + errors = [] + + def collect(filename, linenum, category, confidence, message): + errors.append((linenum, category, message)) + + cpplint.ProcessFileData("test.cc", "cc", source.splitlines(), collect) + return [e for e in errors if e[1] == "runtime/references"] + + +class FastApiCallbackOptionsRefTest(unittest.TestCase): + def test_unqualified_fast_api_callback_options_not_flagged(self): + # Mirrors src/node_buffer.cc usage after `using v8::FastApiCallbackOptions;`. + src = ( + "namespace node {\n" + "void FastFn(Local recv,\n" + " FastApiCallbackOptions& options) {\n" + "}\n" + "} // namespace node\n" + ) + self.assertEqual(_lint(src), []) + + def test_qualified_fast_api_callback_options_not_flagged(self): + src = ( + "namespace node {\n" + "void FastFn(Local recv,\n" + " v8::FastApiCallbackOptions& options) {\n" + "}\n" + "} // namespace node\n" + ) + self.assertEqual(_lint(src), []) + + def test_plain_non_const_reference_still_flagged(self): + src = ( + "namespace node {\n" + "void Bad(int& value) {\n" + "}\n" + "} // namespace node\n" + ) + errors = _lint(src) + self.assertEqual(len(errors), 1, errors) + self.assertIn("int& value", errors[0][2]) + + def test_unrelated_type_with_similar_name_still_flagged(self): + # Guard against an over-broad regex that would also accept e.g. + # FastApiCallbackOptionsExtra&. + src = ( + "namespace node {\n" + "void Bad(FastApiCallbackOptionsExtra& opts) {\n" + "}\n" + "} // namespace node\n" + ) + errors = _lint(src) + self.assertEqual(len(errors), 1, errors) + + +if __name__ == "__main__": + unittest.main()