v8 150.2.0

Rust bindings to V8
Documentation
#!/usr/bin/env python3
# Copyright 2026 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import dataclasses
import pathlib
import textwrap
import unittest

import modulemap_config

from generate_system_modulemap import (
    AllowList,
    Header,
    calculate_transitive_headers,
    combine_modulemaps,
    parse_depfile,
    parse_modulemap,
    split_modulemap,
    modify_modulemap,
)

_TESTDATA = (pathlib.Path(__file__).parent / 'testdata').resolve()
_LIBCXX = _TESTDATA / 'libc++'
_SYSROOT = _TESTDATA / 'sysroot'
_CHROMIUM = pathlib.Path(__file__).parents[3]
_CLANG = _CHROMIUM / 'third_party/llvm-build/Release+Asserts/bin/clang++'
_WANT_MODULEMAP = """module "//system" [system] {
module root {
  requires gnuinlineasm, !systemz
  header "../../libc++/root.h"

  module submodule {
    requires arm64
    requires x64, gnuinlineasm
    header "../../libc++/subdir/requires_unmet.h"
  }
  textual header "../../libc++/textual.h"
  private header "../../libc++/private.h"
}

module "never_referenced.h" {
  textual header "../../sysroot/usr/include/never_referenced.h"
  export *
}
module "public_root.h" {
  header "../../sysroot/usr/include/public_root.h"
  export *
}
module "sysroot.h" {
  header "../../sysroot/usr/include/sysroot.h"
  export *
}
module "public_subdir.h" {
  textual header \
"../../sysroot/usr/include/x86_64-linux-gnu/bits/public_subdir.h"
  export *
}
}
"""
_MODULES = """
module foo {
   module submodule {
     header "bar.h"
   }
}
explicit framework module "bar" [system] {
   header "bar.h"
}
"""
_WANT_SPLIT_MODULEMAP = {
    "foo": """module foo {
   module submodule {
     header "bar.h"
   }
}""",
    "bar": """explicit framework module "bar" [system] {
   header "bar.h"
}"""
}


class GenerateSysrootModulemapTest(unittest.TestCase):
  maxDiff = None

  def test_allowlist(self):
    # Test successful allowlist extraction
    hdrs = [
        modulemap_config.Header('normal.h'),
        modulemap_config.Header('only_on_win.h',
                                module_name='only_on_win',
                                exports=['*', 'other']),
        modulemap_config.Header('textual.h', textual=True),
        modulemap_config.Header('win_lazy.h', lazy=True),
        modulemap_config.Header('win_textual.h', textual=True),
    ]
    al = AllowList(hdrs)
    self.assertEqual(
        al.includes(),
        ['normal.h', 'only_on_win.h', 'textual.h', 'win_textual.h'])
    self.assertIsNone(al.textual('normal.h'))
    self.assertTrue(al.textual('textual.h'))
    self.assertTrue(al.textual('win_textual.h'))
    self.assertTrue(al.textual('bits/some.h'))
    self.assertFalse(al.private('normal.h'))
    self.assertTrue(al.private('unknown.h'))
    self.assertEqual(al.module_name('only_on_win.h'), 'only_on_win')
    self.assertIsNone(al.module_name('normal.h'))
    self.assertEqual(al.exports('only_on_win.h'), ['*', 'other'])
    self.assertEqual(al.exports('normal.h'), ['*'])

  def test_generate_system_modulemap(self):
    common_dir, headers = parse_modulemap(_TESTDATA / 'gen/module.modulemap',
                                          {}, set())
    self.assertEqual(common_dir, _LIBCXX)

    self.assertEqual(headers, [
        Header(path=pathlib.Path('root.h'),
               private=False,
               textual=False,
               requires=['gnuinlineasm', '!systemz']),
        Header(path=pathlib.Path('subdir/requires_unmet.h'),
               private=False,
               textual=False,
               requires=[
                   'gnuinlineasm', '!systemz', 'arm64', 'x64', 'gnuinlineasm'
               ]),
        Header(path=pathlib.Path('textual.h'),
               private=False,
               textual=True,
               requires=['gnuinlineasm', '!systemz']),
        Header(path=pathlib.Path('private.h'),
               private=True,
               textual=False,
               requires=['gnuinlineasm', '!systemz']),
    ])

    deps = calculate_transitive_headers(
        clang_args=[
            str(_CLANG), '-isystem',
            str(_LIBCXX), f'--sysroot={_SYSROOT}', '--target=x86_64-linux-gnu'
        ],
        include_dirs=[(common_dir, headers)],
        sysroot_dirs=[
            _SYSROOT / 'usr/include', _SYSROOT / 'usr/include/x86_64-linux-gnu'
        ],
        allowlist=AllowList([
            modulemap_config.Header('bits/public_subdir.h'),
            modulemap_config.Header('public_root.h'),
            modulemap_config.AllowedHeader('sysroot.h'),
            modulemap_config.AllowedHeader('never_referenced.h'),
        ]),
        target_os='linux',
        target_cpu='x64',
    )

    self.assertEqual(sorted(deps), [
        Header(
            path=_LIBCXX / 'subdir/bits/missing.h', private=True, textual=True),
        Header(path=_LIBCXX / 'subdir/missing.h', private=True, textual=True),
        Header(path=_SYSROOT / 'usr/include/never_referenced.h',
               private=False,
               textual=True),
        Header(path=_SYSROOT / 'usr/include/public_root.h',
               private=False,
               textual=False),
        Header(path=_SYSROOT / 'usr/include/sysroot.h',
               private=False,
               textual=False),
        Header(
            path=_SYSROOT / 'usr/include/x86_64-linux-gnu/bits/public_subdir.h',
            private=False,
            textual=True),
        Header(path=_SYSROOT / 'usr/include/x86_64-linux-gnu/bits/sysroot.h',
               private=True,
               textual=True),
    ])

    combined = combine_modulemaps(
        out=_TESTDATA / 'want/subdir' / 'module.modulemap',
        modulemaps=[_TESTDATA / 'gen/module.modulemap'],
        headers=deps,
        module_name='//system',
        extra_modules=[],
        modify_modules={},
        modified_modules=set())
    self.assertEqual(combined, _WANT_MODULEMAP)

  def test_find_modules(self):
    modules = split_modulemap(_MODULES)
    # We can just do assertEqual on the dict, but the diff isn't very nice
    self.assertCountEqual(modules.keys(), _WANT_SPLIT_MODULEMAP.keys())
    for k, v in _WANT_SPLIT_MODULEMAP.items():
      self.assertEqual(modules[k], v)

  def test_parse_depfile(self):
    self.assertEqual(
        parse_depfile(r"""dummy.o: \
  /path/to/header1.h \
  /path/to/header2.h \
  /path/to/header\ with\ spaces.h \
  /path/to/header3.h
"""), [
            pathlib.Path('/path/to/header1.h'),
            pathlib.Path('/path/to/header2.h'),
            pathlib.Path('/path/to/header with spaces.h'),
            pathlib.Path('/path/to/header3.h'),
        ])

  def test_modify_modulemap(self):
    modulemap = textwrap.dedent("""\
        module foo {
          module submodule {
            header "bar.h"
          }
        }""")
    modified_modules = set()
    content = modify_modulemap(modulemap, {
        'foo': lambda s: '',
        'unused': lambda s: '',
    }, modified_modules)
    self.assertEqual(content, '')
    self.assertEqual(modified_modules, {'foo'})

    modified_modules = set()
    content = modify_modulemap(
        modulemap, {'foo.submodule': lambda s: s[:-1] + '  export *\n  }'},
        modified_modules)
    self.assertEqual(
        content,
        textwrap.dedent("""\
            module foo {
              module submodule {
                header "bar.h"
                export *
              }
            }"""))
    self.assertIn('foo.submodule', modified_modules)

    modified_modules = set()
    content = modify_modulemap(
        modulemap, {
            'foo.submodule': lambda s: s[:-1] + '  export submodule\n  }',
            'foo': lambda s: s[:-1] + '  export foo\n}',
            'other.submodule': lambda s: '',
        }, modified_modules)
    self.assertEqual(
        content,
        textwrap.dedent("""\
            module foo {
              module submodule {
                header "bar.h"
                export submodule
              }
              export foo
            }"""))
    self.assertIn('foo.submodule', modified_modules)
    self.assertIn('foo', modified_modules)
    self.assertNotIn('other.submodule', modified_modules)


if __name__ == '__main__':
  unittest.main()