Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions Source/WTF/wtf/bun/BannedIncludes/iostream
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// This directory is placed first on the include search path for non-Debug
// builds when USE_BUN_JSC_ADDITIONS is on, so `#include <iostream>` resolves
// here instead of the toolchain header.
//
// <iostream> is unlike <ostream>/<istream>/<sstream>: on libstdc++ it emits a
// reference to std::ios_base_library_init in every translation unit that
// includes it. One such reference anywhere in the link pulls globals_io.o from
// libstdc++, whose static initializer constructs cin/cout/cerr/clog and their
// wchar_t siblings before main, dragging the full std::locale facet set in
// with it. Bun never touches C++ iostreams at runtime.
//
// Use WTF::dataLog()/dataLogLn() or fputs/fprintf for diagnostics.
#ifndef BUN_ALLOW_IOSTREAM
#error "<iostream> is banned in Bun WebKit release builds: it forces std::ios_base::Init and the full std::locale facet set to run before main in every bun process. Use WTF::dataLog() or <cstdio>. See Source/WTF/wtf/bun/BannedIncludes/iostream."
#else
#include_next <iostream>
#endif
2 changes: 0 additions & 2 deletions Source/WTF/wtf/simdutf/simdutf_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -9942,11 +9942,9 @@ static_assert(to_base64_url_value[uint8_t('_')] == 63,
#ifndef SIMDUTF_BASE64_H
#define SIMDUTF_BASE64_H

#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <iostream>

namespace simdutf {
namespace scalar {
Expand Down
10 changes: 10 additions & 0 deletions Source/cmake/OptionsJSCOnly.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,16 @@ if(USE_BUN_JSC_ADDITIONS)
# Causing test/cli/test/bun-test.test.ts to fail.
SET_AND_EXPOSE_TO_BUILD(BUSE_TZONE 0)
SET_AND_EXPOSE_TO_BUILD(USE_TZONE_MALLOC 0)

# Shadow <iostream> with a #error shim in non-Debug builds. On libstdc++ a
# single <iostream> include anywhere emits a reference to
# std::ios_base_library_init, which pulls globals_io.o (the
# cin/cout/cerr/clog + full std::locale facet static initializer) into the
# final Bun link. <ostream>/<istream>/<sstream> are unaffected. Debug
# builds keep the real header for ad-hoc dataLog-style debugging.
if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
include_directories(BEFORE "${WTF_DIR}/wtf/bun/BannedIncludes")
endif()
Comment on lines +56 to +58

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 This include_directories(BEFORE ...) runs at top-level project scope (OptionsJSCOnly.cmake is include()'d, not add_subdirectory()'d), so the <iostream> shim propagates to every target — including Source/ThirdParty/gtest and Tools/TestWebKitAPI, which are pulled in on non-Windows via ENABLE_API_TESTS ON. gtest unconditionally includes <iostream> (gtest-port.h:291, gtest.cc:52), so a plain ninja / cmake --build . (default all target) with -DUSE_BUN_JSC_ADDITIONS=ON in Release now fails on gtest-all.cc. All Bun CI/release paths build only --target jsc and are unaffected, but you may want to set(ENABLE_API_TESTS OFF) under USE_BUN_JSC_ADDITIONS, or add target_compile_definitions(gtest PRIVATE BUN_ALLOW_IOSTREAM), so the default target still builds.

Extended reasoning...

What breaks

The new include_directories(BEFORE "${WTF_DIR}/wtf/bun/BannedIncludes") is intended to shadow <iostream> for the WebKit sources that end up in the Bun link. However, it is applied at a scope that also covers third-party test code that legitimately uses iostreams, so building the default all target on non-Windows now fails.

Why the shim leaks to gtest

OptionsJSCOnly.cmake is not a subdirectory script — it is pulled in via include():

  • CMakeLists.txt:22include(WebKitCommon)
  • WebKitCommon.cmake:320include(Options${PORT})

include() does not create a new directory scope, so the include_directories(BEFORE ...) call executes in the top-level CMakeLists.txt directory scope. Every add_subdirectory() that follows (starting with add_subdirectory(Source) at CMakeLists.txt:75) inherits it.

A few lines further down in this same file, ENABLE_API_TESTS is set ON for all non-Windows platforms. That causes:

  • Source/CMakeLists.txt:27-28add_subdirectory(ThirdParty/gtest)
  • Tools/CMakeLists.txt:24-26add_subdirectory(TestWebKitAPI)

Neither of these is added with EXCLUDE_FROM_ALL, so both are part of the default all target. gtest's own CMakeLists.txt does not clear the inherited directory-level include list and does not define BUN_ALLOW_IOSTREAM. And gtest unconditionally includes <iostream>:

  • Source/ThirdParty/gtest/include/gtest/internal/gtest-port.h:291
  • Source/ThirdParty/gtest/src/gtest.cc:52

Because the shim directory is added BEFORE and directory-level -I paths precede system include paths, #include <iostream> in gtest resolves to the shim and hits the #error.

Step-by-step reproduction

  1. On Linux or macOS, configure with -DPORT=JSCOnly -DUSE_BUN_JSC_ADDITIONS=ON -DCMAKE_BUILD_TYPE=Release (or RelWithDebInfo).
  2. WTF_DIR is set by WebKitFS.cmake (included at WebKitCommon.cmake:308, i.e. before Options${PORT}), so the shim path expands correctly.
  3. Run ninja (or cmake --build .) with no explicit target.
  4. Ninja builds gtest-all.cc, which #includes gtest.cc#include <iostream> → resolves to Source/WTF/wtf/bun/BannedIncludes/iostream#error "<iostream> is banned in Bun WebKit release builds…".
  5. Build fails.

Impact

Every documented and CI build path in this repo — Dockerfile*, build.ts, mac-release.bash, release.sh, windows-release.ps1 — invokes cmake --build … --target jsc (or --target artifact), which does not depend on gtest. So CI, autobuild artifacts, and the shipped Bun binaries are unaffected. This only bites a developer who runs a bare ninja / cmake --build . in a Release-flavored USE_BUN_JSC_ADDITIONS tree, and the #error message itself points at the -DBUN_ALLOW_IOSTREAM opt-out. It's a real regression in an ostensibly-supported configuration (this file is the one that sets ENABLE_API_TESTS ON), but not one that blocks the PR's goal.

Suggested fixes

Any one of:

  • set(ENABLE_API_TESTS OFF) inside the if(USE_BUN_JSC_ADDITIONS) block — Bun doesn't ship or run these tests anyway.
  • Add target_compile_definitions(gtest PRIVATE BUN_ALLOW_IOSTREAM) (e.g. via a Source/ThirdParty/gtest/PlatformJSCOnly.cmake), and similarly for TestWebKitAPI.
  • Scope the shim to the libraries that actually feed the Bun link by using target_include_directories(... BEFORE ...) on WTF/JavaScriptCore/bmalloc instead of the global include_directories().

endif()

# Only works on macOS for now.
Expand Down
Loading