diff --git a/.github/workflows/bun-windows.yml b/.github/workflows/bun-windows.yml index 6d26283716..e74f2843c8 100644 --- a/.github/workflows/bun-windows.yml +++ b/.github/workflows/bun-windows.yml @@ -178,6 +178,11 @@ jobs: path: bun-deps key: ${{ steps.cache-deps-restore.outputs.cache-primary-key }} + # TODO(@paperdave): stop relying on this and use bun.exe to build itself. + # we cant do that now because there isn't a tagged release to use. + # + # and at the time of writing, the minimum canary required to work is not + # yet released as it is the one *this* commit. windows-codegen: name: Codegen runs-on: ubuntu-latest diff --git a/CMakeLists.txt b/CMakeLists.txt index 30f0b5fe22..afc1852ea0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -374,10 +374,11 @@ elseif(NOT BUN_CPP_ONLY AND NOT BUN_LINK_ONLY) endif() # Bun -if(NOT WIN32) - find_program(BUN_EXECUTABLE bun ${REQUIRED_IF_NOT_ONLY_CPP_OR_LINK} DOC "Path to an already built release of Bun") - message(STATUS "Found Bun: ${BUN_EXECUTABLE}") -else() +find_program(BUN_EXECUTABLE bun ${REQUIRED_IF_NOT_ONLY_CPP_OR_LINK} DOC "Path to an already built release of Bun") +message(STATUS "Found Bun: ${BUN_EXECUTABLE}") + +if(WIN32 AND NO_CODEGEN) + # TODO(@paperdave): remove this, see bun-windows.yml's comment. set(BUN_EXECUTABLE "echo") endif() @@ -582,7 +583,7 @@ add_custom_command( "${BUN_WORKDIR}/codegen/ZigGeneratedClasses+DOMIsoSubspaces.h" "${BUN_WORKDIR}/codegen/ZigGeneratedClasses+lazyStructureImpl.h" "${BUN_WORKDIR}/codegen/ZigGeneratedClasses.zig" - COMMAND ${BUN_EXECUTABLE} "${BUN_CODEGEN_SRC}/generate-classes.ts" ${BUN_CLASSES_TS} "${BUN_WORKDIR}/codegen" + COMMAND ${BUN_EXECUTABLE} run "${BUN_CODEGEN_SRC}/generate-classes.ts" ${BUN_CLASSES_TS} "${BUN_WORKDIR}/codegen" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} MAIN_DEPENDENCY "${BUN_CODEGEN_SRC}/generate-classes.ts" DEPENDS ${BUN_CLASSES_TS} @@ -595,11 +596,12 @@ list(APPEND BUN_RAW_SOURCES "${BUN_WORKDIR}/codegen/ZigGeneratedClasses.cpp") add_custom_command( OUTPUT "${BUN_WORKDIR}/codegen/JSSink.cpp" "${BUN_WORKDIR}/codegen/JSSink.h" - COMMAND ${BUN_EXECUTABLE} "src/codegen/generate-jssink.ts" "${BUN_WORKDIR}/codegen" + COMMAND ${BUN_EXECUTABLE} run "src/codegen/generate-jssink.ts" "${BUN_WORKDIR}/codegen" VERBATIM MAIN_DEPENDENCY "src/codegen/generate-jssink.ts" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Generating JSSink" + USES_TERMINAL ) list(APPEND BUN_RAW_SOURCES "${BUN_WORKDIR}/codegen/JSSink.cpp") @@ -622,7 +624,7 @@ if(NOT BUN_LINK_ONLY) OUTPUT ${_output} MAIN_DEPENDENCY ${BUN_HASH_LUT_GENERATOR} DEPENDS ${_input} - COMMAND ${BUN_EXECUTABLE} ${BUN_HASH_LUT_GENERATOR} ${_input} ${_output} + COMMAND ${BUN_EXECUTABLE} run ${BUN_HASH_LUT_GENERATOR} ${_input} ${_output} VERBATIM COMMENT "Generating ${_display_name}" ) @@ -696,7 +698,7 @@ if(NOT NO_CODEGEN) "${BUN_WORKDIR}/codegen/NativeModuleImpl.h" "${BUN_WORKDIR}/codegen/ResolvedSourceTag.zig" "${BUN_WORKDIR}/codegen/SyntheticModuleType.h" - COMMAND ${BUN_EXECUTABLE} "${BUN_SRC}/codegen/bundle-modules.ts" "--debug=${DEBUG}" "${BUN_WORKDIR}" + COMMAND ${BUN_EXECUTABLE} run "${BUN_SRC}/codegen/bundle-modules.ts" "--debug=${DEBUG}" "${BUN_WORKDIR}" DEPENDS ${BUN_TS_MODULES} ${CODEGEN_FILES} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Bundling JS modules" @@ -711,7 +713,7 @@ WEBKIT_ADD_SOURCE_DEPENDENCIES( add_custom_command( OUTPUT "${BUN_WORKDIR}/codegen/WebCoreJSBuiltins.cpp" "${BUN_WORKDIR}/codegen/WebCoreJSBuiltins.h" - COMMAND ${BUN_EXECUTABLE} "${BUN_SRC}/codegen/bundle-functions.ts" "--debug=${DEBUG}" "${BUN_WORKDIR}" + COMMAND ${BUN_EXECUTABLE} run "${BUN_SRC}/codegen/bundle-functions.ts" "--debug=${DEBUG}" "${BUN_WORKDIR}" DEPENDS ${BUN_TS_FUNCTIONS} ${CODEGEN_FILES} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Bundling JS builtin functions" @@ -1109,9 +1111,10 @@ endif() if(WIN32) # Kill all instances of bun before linking. + # This is necessary because the file is locked by the process. add_custom_command( TARGET ${bun} - PRE_BUILD + PRE_LINK COMMAND "powershell" "/C" @@ -1287,6 +1290,7 @@ endif() if(USE_CUSTOM_LSHPACK) include_directories(${BUN_DEPS_DIR}/ls-hpack) + if(WIN32) include_directories(${BUN_DEPS_DIR}/ls-hpack/compat/queue) target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/lshpack.lib") diff --git a/docs/installation.md b/docs/installation.md index 5815bc619d..32965ca5ff 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -233,6 +233,10 @@ If you need to remove Bun from your system, use the following commands. $ rm -rf ~/.bun # for macOS, Linux, and WSL ``` +```bash#Windows +$ Remove-Item ~\.bun -Recurse +``` + ```bash#NPM $ npm uninstall -g bun ``` diff --git a/scripts/codegen.ps1 b/scripts/codegen.ps1 deleted file mode 100644 index 7c99d980de..0000000000 --- a/scripts/codegen.ps1 +++ /dev/null @@ -1,17 +0,0 @@ -$Script1=(Join-Path $PSScriptRoot "./cross-compile-codegen.sh") -$CrossCompileCodegen=(Get-Content $Script1 -Raw) -$CrossCompileCodegen.Replace("`r`n","`n") | Set-Content $Script1 -Force -NoNewline -$Script2=(Join-Path $PSScriptRoot "../src/codegen/create_hash_table") -$CreateHashTable=(Get-Content $Script2 -Raw) -$CreateHashTable.Replace("`r`n","`n") | Set-Content $Script2 -Force -NoNewline - -& 'C:\Program Files\WSL\wsl.exe' ./scripts/cross-compile-codegen.sh win32 x64 "build" - -Set-Content $Script1 -Force -NoNewline -Value $CrossCompileCodegen -Set-Content $Script2 -Force -NoNewline -Value $CreateHashTable - -# copy into build-release as well -Remove-Item -Path "build-release/codegen" -Recurse -Force -ErrorAction SilentlyContinue -Remove-Item -Path "build-release/js" -Recurse -Force -ErrorAction SilentlyContinue -Copy-Item -Path "build/codegen" -Destination "build-release/codegen" -Recurse -Force -Copy-Item -Path "build/js" -Destination "build-release/js" -Recurse -Force diff --git a/scripts/set-webkit-submodule-to-cmake.ps1 b/scripts/set-webkit-submodule-to-cmake.ps1 new file mode 100644 index 0000000000..975f86fcb8 --- /dev/null +++ b/scripts/set-webkit-submodule-to-cmake.ps1 @@ -0,0 +1,22 @@ +# Navigate to the parent directory of the script +$scriptPath = Split-Path -Parent $MyInvocation.MyCommand.Path +Push-Location $scriptPath\.. +try { + # Get the WEBKIT_TAG value from CMakeLists.txt + $WEBKIT_TAG = Select-String -Path 'CMakeLists.txt' -Pattern 'set\(WEBKIT_TAG (.*?)\)' | ForEach-Object { $_.Matches.Groups[1].Value } + if (-not $WEBKIT_TAG) { + Write-Host "Could not find WEBKIT_TAG in CMakeLists.txt" + exit 1 + } + + Write-Host "Setting WebKit submodule to $WEBKIT_TAG" + + # Navigate to the WebKit submodule directory + Set-Location src/bun.js/WebKit + + # Fetch and reset the submodule to the specified tag + git fetch origin "$WEBKIT_TAG" + git reset --hard "$WEBKIT_TAG" +} finally { + Pop-Location +} \ No newline at end of file diff --git a/src/bun.js/javascript.zig b/src/bun.js/javascript.zig index 3fe2f59ef6..50732c1beb 100644 --- a/src/bun.js/javascript.zig +++ b/src/bun.js/javascript.zig @@ -1718,7 +1718,7 @@ pub const VirtualMachine = struct { "../", }; - break :name bun.path.joinAbsStringBuf( + break :name bun.path.joinAbsStringBufZTrailingSlash( jsc_vm.bundler.fs.top_level_dir, &specifier_cache_resolver_buf, &parts, diff --git a/src/bun.zig b/src/bun.zig index 3da42ad257..820ed3100e 100644 --- a/src/bun.zig +++ b/src/bun.zig @@ -68,6 +68,7 @@ pub const FileDescriptor = enum(FileDescriptorInt) { _, pub inline fn int(fd: FileDescriptor) FileDescriptorInt { + // TODO(@paperdave): make this a compile error to call on windows. every usage is incorrect. return @intFromEnum(fd); } diff --git a/src/bundler.zig b/src/bundler.zig index 9dc6112e24..1668da0d55 100644 --- a/src/bundler.zig +++ b/src/bundler.zig @@ -372,19 +372,57 @@ pub const Bundler = struct { this.resolver.allocator = allocator; } - pub inline fn resolveEntryPoint(bundler: *Bundler, entry_point: string) anyerror!_resolver.Result { + fn _resolveEntryPoint(bundler: *Bundler, entry_point: string) !_resolver.Result { return bundler.resolver.resolve(bundler.fs.top_level_dir, entry_point, .entry_point) catch |err| { - const has_dot_slash_form = !strings.hasPrefix(entry_point, "./") and brk: { - return bundler.resolver.resolve(bundler.fs.top_level_dir, try strings.append(bundler.allocator, "./", entry_point), .entry_point) catch break :brk false; - }; - _ = has_dot_slash_form; - - bundler.log.addErrorFmt(null, logger.Loc.Empty, bundler.allocator, "{s} resolving \"{s}\" (entry point)", .{ @errorName(err), entry_point }) catch unreachable; - + if (!std.fs.path.isAbsolute(entry_point) and !strings.hasPrefix(entry_point, "./")) brk: { + return bundler.resolver.resolve( + bundler.fs.top_level_dir, + try strings.append(bundler.allocator, "./", entry_point), + .entry_point, + ) catch + // return the original error + break :brk; + } return err; }; } + pub fn resolveEntryPoint(bundler: *Bundler, entry_point: string) !_resolver.Result { + return _resolveEntryPoint(bundler, entry_point) catch |err| { + var cache_bust_buf: [bun.MAX_PATH_BYTES]u8 = undefined; + + // Bust directory cache and try again + const buster_name = name: { + if (std.fs.path.isAbsolute(entry_point)) { + if (std.fs.path.dirname(entry_point)) |dir| { + break :name strings.withTrailingSlash(dir, entry_point); + } + } + + var parts = [_]string{ + entry_point, + "../", + }; + + break :name bun.path.joinAbsStringBufZTrailingSlash( + bundler.fs.top_level_dir, + &cache_bust_buf, + &parts, + .auto, + ); + }; + + bundler.resolver.bustDirCache(buster_name); + + return _resolveEntryPoint(bundler, entry_point) catch { + // return the original error + bundler.log.addErrorFmt(null, logger.Loc.Empty, bundler.allocator, "{s} resolving \"{s}\" (entry point)", .{ @errorName(err), entry_point }) catch bun.outOfMemory(); + // return err; + @panic("lose"); + }; + }; + } + pub fn init( allocator: std.mem.Allocator, log: *logger.Log, diff --git a/src/cache.zig b/src/cache.zig index 1efaf3156a..42e990ccbd 100644 --- a/src/cache.zig +++ b/src/cache.zig @@ -189,7 +189,7 @@ pub const Fs = struct { } if (comptime !Environment.isWindows) // skip on Windows because NTCreateFile will do it. - debug("openat({d}, {s}) = {d}", .{ dirname_fd, path, bun.toFD(file_handle.handle).int() }); + debug("openat({d}, {s}) = {}", .{ dirname_fd, path, bun.toFD(file_handle.handle) }); const will_close = rfs.needToCloseFiles() and _file_handle == null; defer { diff --git a/src/codegen/client-js.ts b/src/codegen/client-js.ts index 4dfa6acf6c..d50368a995 100644 --- a/src/codegen/client-js.ts +++ b/src/codegen/client-js.ts @@ -1,3 +1,5 @@ +import { pathToUpperSnakeCase } from "./helpers"; + // This is the implementation for $debug export function createLogClientJS(filepath: string, publicName: string) { return ` @@ -5,16 +7,8 @@ let $debug_log_enabled = ((env) => ( // The rationale for checking all these variables is just so you don't have to exactly remember which one you set. (env.BUN_DEBUG_ALL && env.BUN_DEBUG_ALL !== '0') || (env.BUN_DEBUG_JS && env.BUN_DEBUG_JS !== '0') - || (env.BUN_DEBUG_${filepath - .replace(/^.*?:/, "") - .split(/[-_./]/g) - .join("_") - .toUpperCase()}) - || (env.DEBUG_${filepath - .replace(/^.*?:/, "") - .split(/[-_./]/g) - .join("_") - .toUpperCase()}) + || (env.BUN_DEBUG_${pathToUpperSnakeCase(filepath)}) + || (env.DEBUG_${pathToUpperSnakeCase(filepath)}) ))(Bun.env); let $debug_pid_prefix = Bun.env.SHOW_PID === '1'; let $debug_log = $debug_log_enabled ? (...args) => { diff --git a/src/codegen/create-hash-table.ts b/src/codegen/create-hash-table.ts index 7d646b2f1c..a94dc3d7c2 100644 --- a/src/codegen/create-hash-table.ts +++ b/src/codegen/create-hash-table.ts @@ -18,8 +18,9 @@ const to_remove = new RegExp(`#if\\s+(!OS\\(${os}\\)|OS\\((${other_oses.join("|" const input_preprocessed = to_preprocess.replace(to_remove, ""); +console.log("Generating " + output + " from " + input); const proc = spawn({ - cmd: [create_hash_table, "-"], + cmd: ["perl", create_hash_table, "-"], stdin: "pipe", stdout: "pipe", stderr: "inherit", diff --git a/src/codegen/generate-jssink.ts b/src/codegen/generate-jssink.ts index 48a0a07c8b..3f1f542d19 100644 --- a/src/codegen/generate-jssink.ts +++ b/src/codegen/generate-jssink.ts @@ -952,6 +952,7 @@ await Bun.write(resolve(outDir + "/JSSink.lut.txt"), lutInput()); Bun.spawnSync( [ process.execPath, + "run", join(import.meta.dir, "create-hash-table.ts"), resolve(outDir + "/JSSink.lut.txt"), join(outDir, "JSSink.lut.h"), diff --git a/src/codegen/helpers.ts b/src/codegen/helpers.ts index e1683376e1..f8dd9bba8f 100644 --- a/src/codegen/helpers.ts +++ b/src/codegen/helpers.ts @@ -80,3 +80,11 @@ export function writeIfNotChanged(file: string, contents: string) { fs.writeFileSync(file, contents); } } + +export function pathToUpperSnakeCase(filepath: string) { + return filepath + .replace(/^.*?:/, "") + .split(/[-_./\\]/g) + .join("_") + .toUpperCase(); +} diff --git a/src/codegen/internal-module-registry-scanner.ts b/src/codegen/internal-module-registry-scanner.ts index 362b02e5e1..6efcd1fc18 100644 --- a/src/codegen/internal-module-registry-scanner.ts +++ b/src/codegen/internal-module-registry-scanner.ts @@ -7,6 +7,7 @@ export function createInternalModuleRegistry(basedir: string) { .flatMap(dir => readdirRecursive(path.join(basedir, dir))) .filter(file => file.endsWith(".js") || (file.endsWith(".ts") && !file.endsWith(".d.ts"))) .map(file => file.slice(basedir.length + 1)) + .map(x => x.replaceAll("\\", "/")) .sort(); // Create the Internal Module Registry @@ -66,7 +67,7 @@ export function createInternalModuleRegistry(basedir: string) { resolveSyncOrNull(specifier, path.join(basedir, path.dirname(from))) ?? resolveSyncOrNull(specifier, basedir); if (relativeMatch) { - const found = moduleList.indexOf(path.relative(basedir, relativeMatch)); + const found = moduleList.indexOf(path.relative(basedir, relativeMatch).replaceAll("\\", "/")); if (found === -1) { throw new Error( `Builtin Bundler: "${specifier}" cannot be imported here because it doesn't get a module ID. Only files in "src/js" besides "src/js/builtins" can be used here. Note that the 'node:' or 'bun:' prefix is required here. `, diff --git a/src/fs.zig b/src/fs.zig index 1c338186cf..f4b187be5a 100644 --- a/src/fs.zig +++ b/src/fs.zig @@ -750,9 +750,7 @@ pub const FileSystem = struct { }; pub fn needToCloseFiles(rfs: *const RealFS) bool { - // On Windows, we must always close open file handles - // Windows locks files - if (comptime !FeatureFlags.store_file_descriptors) { + if (!FeatureFlags.store_file_descriptors) { return true; } diff --git a/src/resolver/resolver.zig b/src/resolver/resolver.zig index caeaf66101..ae9562d142 100644 --- a/src/resolver/resolver.zig +++ b/src/resolver/resolver.zig @@ -1584,6 +1584,7 @@ pub const Resolver = struct { pub fn bustDirCache(r: *ThisResolver, path: string) void { dev("Bust {s}", .{path}); + std.debug.assert(path[path.len - 1] == std.fs.path.sep); r.fs.fs.bustEntriesCache(path); r.dir_cache.remove(path); } @@ -3456,7 +3457,6 @@ pub const Resolver = struct { // Is this a file? if (r.loadAsFile(path, extension_order)) |file| { - // Determine the package folder by looking at the last node_modules/ folder in the path if (strings.lastIndexOf(file.path, "node_modules" ++ std.fs.path.sep_str)) |last_node_modules_folder| { const node_modules_folder_offset = last_node_modules_folder + ("node_modules" ++ std.fs.path.sep_str).len; @@ -3493,12 +3493,9 @@ pub const Resolver = struct { debug.addNoteFmt("Attempting to load \"{s}\" as a directory", .{path}); debug.increaseIndent(); } - - defer { - if (r.debug_logs) |*debug| { - debug.decreaseIndent(); - } - } + defer if (r.debug_logs) |*debug| { + debug.decreaseIndent(); + }; const dir_info = (r.dirInfoCached(path) catch |err| { if (comptime Environment.isDebug) Output.prettyErrorln("err: {s} reading {s}", .{ @errorName(err), path }); diff --git a/src/string_types.zig b/src/string_types.zig index c9bc56abde..456c7f186e 100644 --- a/src/string_types.zig +++ b/src/string_types.zig @@ -45,6 +45,10 @@ pub const PathString = packed struct { return this.len == 0; } + pub fn format(self: PathString, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { + try writer.writeAll(self.slice()); + } + pub const empty = @This(){ .ptr = 0, .len = 0 }; comptime { if (!bun.Environment.isWasm) { diff --git a/src/sys.zig b/src/sys.zig index 1ae3db4e51..2a45295483 100644 --- a/src/sys.zig +++ b/src/sys.zig @@ -598,7 +598,18 @@ pub fn openDirAtWindowsNtPath( ); if (comptime Environment.allow_assert) { - log("NtCreateFile({d}, {s}, iterable = {}) = {s} (dir) = {d}", .{ dirFd, bun.fmt.fmtUTF16(path), iterable, @tagName(rc), @intFromPtr(fd) }); + if (rc == .INVALID_PARAMETER) { + // Double check what flags you are passing to this + // + // - access_mask probably needs w.SYNCHRONIZE, + // - options probably needs w.FILE_SYNCHRONOUS_IO_NONALERT + // - disposition probably needs w.FILE_OPEN + bun.Output.debugWarn("NtCreateFile({}, {}) = {s} (dir) = {d}\nYou are calling this function with the wrong flags!!!", .{ dirFd, bun.fmt.fmtUTF16(path), @tagName(rc), @intFromPtr(fd) }); + } else if (rc == .OBJECT_PATH_SYNTAX_BAD or rc == .OBJECT_NAME_INVALID) { + bun.Output.debugWarn("NtCreateFile({}, {}) = {s} (dir) = {d}\nYou are calling this function without normalizing the path correctly!!!", .{ dirFd, bun.fmt.fmtUTF16(path), @tagName(rc), @intFromPtr(fd) }); + } else { + log("NtCreateFile({}, {}) = {s} (dir) = {d}", .{ dirFd, bun.fmt.fmtUTF16(path), @tagName(rc), @intFromPtr(fd) }); + } } switch (windows.Win32Error.fromNTStatus(rc)) {