mirror of
https://github.com/oven-sh/bun
synced 2026-02-02 15:08:46 +00:00
Linux works now.
This commit is contained in:
14
.dockerignore
Normal file
14
.dockerignore
Normal file
@@ -0,0 +1,14 @@
|
||||
node_modules
|
||||
**/node_modules
|
||||
src/javascript/jsc/WebKit/LayoutTests
|
||||
zig-out
|
||||
zig-build
|
||||
**/*.o
|
||||
**/*.a
|
||||
|
||||
examples
|
||||
|
||||
**/.next
|
||||
.git
|
||||
src/javascript/jsc/WebKit/WebKitBuild
|
||||
**/CMakeCache.txt
|
||||
9
.vscode/launch.json
vendored
9
.vscode/launch.json
vendored
@@ -79,6 +79,15 @@
|
||||
"cwd": "${workspaceFolder}/src/test/fixtures",
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "Linux Launch",
|
||||
"program": "${workspaceFolder}/packages/debug-bun-cli-linux-x64/bin/bun-debug",
|
||||
"args": ["--origin=http://jarred-desktop.local:3000/"],
|
||||
"cwd": "${workspaceFolder}/examples/hello-next",
|
||||
"console": "internalConsole"
|
||||
},
|
||||
|
||||
{
|
||||
"type": "lldb",
|
||||
|
||||
8
Dockerfile
Normal file
8
Dockerfile
Normal file
@@ -0,0 +1,8 @@
|
||||
FROM bun-zig:latest
|
||||
|
||||
COPY . /home/ubuntu/bun
|
||||
WORKDIR /home/ubuntu/bun
|
||||
|
||||
RUN make vendor-without-check
|
||||
|
||||
|
||||
52
Dockerfile.zig
Normal file
52
Dockerfile.zig
Normal file
@@ -0,0 +1,52 @@
|
||||
FROM ubuntu:latest
|
||||
|
||||
RUN apt-get update && apt-get install --no-install-recommends -y wget gnupg2 curl lsb-release wget software-properties-common
|
||||
RUN curl -s https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add -
|
||||
|
||||
RUN wget https://apt.llvm.org/llvm.sh --no-check-certificate
|
||||
RUN chmod +x llvm.sh
|
||||
RUN ./llvm.sh 12
|
||||
|
||||
RUN apt-get update && apt-get install --no-install-recommends -y \
|
||||
ca-certificates \
|
||||
curl \
|
||||
gnupg2 \
|
||||
software-properties-common \
|
||||
cmake \
|
||||
build-essential \
|
||||
git \
|
||||
libssl-dev \
|
||||
ruby \
|
||||
liblld-12-dev \
|
||||
libclang-12-dev \
|
||||
nodejs \
|
||||
gcc \
|
||||
g++ \
|
||||
npm \
|
||||
clang-12 \
|
||||
clang-format-12 \
|
||||
libc++-12-dev \
|
||||
libc++abi-12-dev \
|
||||
lld-12 \
|
||||
libicu-dev
|
||||
|
||||
RUN update-alternatives --install /usr/bin/ld ld /usr/bin/lld-12 90 && \
|
||||
update-alternatives --install /usr/bin/cc cc /usr/bin/clang-12 90 && \
|
||||
update-alternatives --install /usr/bin/cpp cpp /usr/bin/clang++-12 90 && \
|
||||
update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++-12 90
|
||||
|
||||
|
||||
ENV CC=clang-12
|
||||
ENV CXX=clang++-12
|
||||
|
||||
# Compile zig
|
||||
RUN mkdir -p /home/ubuntu/zig; cd /home/ubuntu; git clone https://github.com/jarred-sumner/zig.git; cd /home/ubuntu/zig && git checkout jarred/zig-sloppy-with-small-structs && cmake . -DCMAKE_BUILD_TYPE=Release && make -j$(nproc)
|
||||
|
||||
ENV PATH="/home/ubuntu/zig:$PATH"
|
||||
|
||||
RUN npm install -g esbuild
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
98
Makefile
98
Makefile
@@ -24,7 +24,10 @@ CXX := clang++
|
||||
|
||||
bun: vendor build-obj bun-link-lld-release
|
||||
|
||||
vendor: require init-submodules api node-fallbacks runtime_js fallback_decoder bun_error mimalloc picohttp jsc
|
||||
|
||||
vendor-without-check: api node-fallbacks runtime_js fallback_decoder bun_error mimalloc picohttp
|
||||
|
||||
vendor: require init-submodules vendor-without-check
|
||||
|
||||
require:
|
||||
@echo "Checking if the required utilities are available..."
|
||||
@@ -67,6 +70,30 @@ runtime_js:
|
||||
bun_error:
|
||||
@cd packages/bun-error; npm install; npm run --silent build
|
||||
|
||||
|
||||
DEFAULT_USE_BMALLOC := 1
|
||||
# ifeq ($(OS_NAME),linux)
|
||||
# DEFAULT_USE_BMALLOC = 0
|
||||
# endif
|
||||
|
||||
USE_BMALLOC ?= DEFAULT_USE_BMALLOC
|
||||
|
||||
DEFAULT_JSC_LIB :=
|
||||
|
||||
ifeq ($(OS_NAME),linux)
|
||||
DEFAULT_JSC_LIB = ${HOME}/webkit-build/lib
|
||||
endif
|
||||
|
||||
ifeq ($(OS_NAME),darwin)
|
||||
DEFAULT_JSC_LIB = src/deps
|
||||
endif
|
||||
|
||||
JSC_LIB ?= $(DEFAULT_JSC_LIB)
|
||||
|
||||
JSC_INCLUDE_DIR ?= ${HOME}/webkit-build/include
|
||||
|
||||
JSC_FILES := $(JSC_LIB)/libJavaScriptCore.a $(JSC_LIB)/libWTF.a
|
||||
|
||||
JSC_BUILD_STEPS :=
|
||||
ifeq ($(OS_NAME),linux)
|
||||
JSC_BUILD_STEPS += jsc-build-linux jsc-copy-headers
|
||||
@@ -75,6 +102,10 @@ ifeq ($(OS_NAME),darwin)
|
||||
JSC_BUILD_STEPS += jsc-build-mac jsc-copy-headers
|
||||
endif
|
||||
|
||||
# ifeq ($(USE_BMALLOC),1)
|
||||
JSC_FILES += $(JSC_LIB)/libbmalloc.a
|
||||
# endif
|
||||
|
||||
|
||||
jsc: jsc-build jsc-bindings
|
||||
jsc-build: $(JSC_BUILD_STEPS)
|
||||
@@ -177,10 +208,12 @@ jsc-build-mac-copy:
|
||||
cp src/javascript/jsc/WebKit/WebKitBuild/Release/lib/libWTF.a src/deps/libWTF.a
|
||||
cp src/javascript/jsc/WebKit/WebKitBuild/Release/lib/libbmalloc.a src/deps/libbmalloc.a
|
||||
|
||||
JSC_FILES := src/deps/libJavaScriptCore.a \
|
||||
src/deps/libWTF.a \
|
||||
src/deps/libbmalloc.a
|
||||
clean-bindings:
|
||||
rm -rf $(OBJ_DIR)/*.o
|
||||
|
||||
clean: clean-bindings
|
||||
rm src/deps/*.a src/deps/*.o
|
||||
cd src/deps/mimalloc && make clean;
|
||||
|
||||
ifeq ($(OS_NAME),darwin)
|
||||
HOMEBREW_PREFIX := $(shell brew --prefix)/
|
||||
@@ -190,18 +223,31 @@ SRC_DIR := src/javascript/jsc/bindings
|
||||
OBJ_DIR := src/javascript/jsc/bindings-obj
|
||||
SRC_FILES := $(wildcard $(SRC_DIR)/*.cpp)
|
||||
OBJ_FILES := $(patsubst $(SRC_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(SRC_FILES))
|
||||
INCLUDE_DIRS := -Isrc/javascript/jsc/WebKit/WebKitBuild/Release/JavaScriptCore/PrivateHeaders \
|
||||
MAC_INCLUDE_DIRS := -Isrc/javascript/jsc/WebKit/WebKitBuild/Release/JavaScriptCore/PrivateHeaders \
|
||||
-Isrc/javascript/jsc/WebKit/WebKitBuild/Release/WTF/Headers \
|
||||
-Isrc/javascript/jsc/WebKit/WebKitBuild/Release/ICU/Headers \
|
||||
-Isrc/javascript/jsc/WebKit/WebKitBuild/Release/ \
|
||||
-Isrc/javascript/jsc/bindings/ \
|
||||
-Isrc/javascript/jsc/WebKit/Source/bmalloc
|
||||
|
||||
LINUX_INCLUDE_DIRS := -I$(JSC_INCLUDE_DIR) \
|
||||
-Isrc/javascript/jsc/bindings/
|
||||
|
||||
INCLUDE_DIRS :=
|
||||
|
||||
ifeq ($(OS_NAME),linux)
|
||||
INCLUDE_DIRS += $(LINUX_INCLUDE_DIRS)
|
||||
endif
|
||||
|
||||
ifeq ($(OS_NAME),darwin)
|
||||
INCLUDE_DIRS += $(MAC_INCLUDE_DIRS)
|
||||
endif
|
||||
|
||||
CLANG_FLAGS := $(INCLUDE_DIRS) \
|
||||
-std=gnu++17 \
|
||||
-stdlib=libc++ \
|
||||
-DSTATICALLY_LINKED_WITH_JavaScriptCore=1 \
|
||||
-DSTATICALLY_LINKED_WITH_WTF=1 \
|
||||
-DSTATICALLY_LINKED_WITH_BMALLOC=1 \
|
||||
-DBUILDING_WITH_CMAKE=1 \
|
||||
-DNDEBUG=1 \
|
||||
-DNOMINMAX \
|
||||
@@ -209,8 +255,15 @@ CLANG_FLAGS := $(INCLUDE_DIRS) \
|
||||
-g \
|
||||
-DENABLE_INSPECTOR_ALTERNATE_DISPATCHERS=0 \
|
||||
-DBUILDING_JSCONLY__ \
|
||||
-DASSERT_ENABLED=0\
|
||||
-DDU_DISABLE_RENAMING=1
|
||||
-DASSERT_ENABLED=0 \
|
||||
-fPIE
|
||||
|
||||
# This flag is only added to webkit builds on Apple platforms
|
||||
# It has something to do with ICU
|
||||
ifeq ($(OS_NAME), darwin)
|
||||
CLANG_FLAGS += -DDU_DISABLE_RENAMING=1
|
||||
endif
|
||||
|
||||
|
||||
jsc-bindings-mac: $(OBJ_FILES)
|
||||
|
||||
@@ -239,7 +292,20 @@ BUN_LLD_FLAGS := $(OBJ_FILES) \
|
||||
src/deps/picohttpparser.o \
|
||||
src/deps/mimalloc/libmimalloc.a \
|
||||
$(CLANG_FLAGS) \
|
||||
-fpie \
|
||||
|
||||
|
||||
ifeq ($(OS_NAME), linux)
|
||||
BUN_LLD_FLAGS += -lstdc++fs \
|
||||
-pthread \
|
||||
-ldl \
|
||||
-lc \
|
||||
-fuse-ld=lld \
|
||||
-Wl,-z,now \
|
||||
-Wl,--as-needed \
|
||||
-Wl,-z,stack-size=12800000 \
|
||||
-Wl,-z,notext
|
||||
endif
|
||||
|
||||
|
||||
mimalloc:
|
||||
cd src/deps/mimalloc; cmake .; make;
|
||||
@@ -248,17 +314,19 @@ bun-link-lld-debug:
|
||||
$(CXX) $(BUN_LLD_FLAGS) \
|
||||
$(DEBUG_BIN)/bun-debug.o \
|
||||
-W \
|
||||
-ftls-model=local-exec \
|
||||
-flto \
|
||||
-o $(DEBUG_BIN)/bun-debug
|
||||
-o $(DEBUG_BIN)/bun-debug \
|
||||
-march=native \
|
||||
-flto
|
||||
|
||||
|
||||
bun-link-lld-release:
|
||||
$(CXX) $(BUN_LLD_FLAGS) \
|
||||
$(BIN_DIR)/bun.o \
|
||||
-o $(BIN_DIR)/bun \
|
||||
-W \
|
||||
-ftls-model=local-exec \
|
||||
-flto \
|
||||
-ftls-model=initial-exec \
|
||||
-march=native \
|
||||
-O3
|
||||
rm $(BIN_DIR)/bun.o
|
||||
|
||||
@@ -267,7 +335,7 @@ bun-link-lld-release-aarch64:
|
||||
build/macos-aarch64/bun.o \
|
||||
-o build/macos-aarch64/bun \
|
||||
-Wl,-dead_strip \
|
||||
-ftls-model=local-exec \
|
||||
-ftls-model=initial-exec \
|
||||
-flto \
|
||||
-O3
|
||||
|
||||
@@ -283,4 +351,4 @@ sizegen:
|
||||
/tmp/sizegen > src/javascript/jsc/bindings/sizes.zig
|
||||
|
||||
picohttp:
|
||||
$(CC) -O3 -g -c src/deps/picohttpparser.c -Isrc/deps -o src/deps/picohttpparser.o; cd ../../
|
||||
$(CC) -O3 -g -fPIE -c src/deps/picohttpparser.c -Isrc/deps -o src/deps/picohttpparser.o; cd ../../
|
||||
|
||||
@@ -600,7 +600,4 @@ Additionally, you'll need `cmake`, `npm` and `esbuild` installed globally.
|
||||
|
||||
## Linux
|
||||
|
||||
```bash
|
||||
git submodule update --init --recursive --progress --depth=1
|
||||
make vendor
|
||||
```
|
||||
Compile Zig:
|
||||
@@ -237,9 +237,13 @@ pub fn build(b: *std.build.Builder) !void {
|
||||
true,
|
||||
);
|
||||
|
||||
|
||||
step.addObjectFile("src/deps/libJavaScriptCore.a");
|
||||
step.addObjectFile("src/deps/libWTF.a");
|
||||
step.addObjectFile("src/deps/libbmalloc.a");
|
||||
|
||||
if (target.getOs().tag != .linux) {
|
||||
step.addObjectFile("src/deps/libbmalloc.a");
|
||||
}
|
||||
|
||||
step.addObjectFile("src/deps/mimalloc/libmimalloc.a");
|
||||
step.addLibPath("src/deps/mimalloc");
|
||||
|
||||
@@ -5,12 +5,11 @@ import styles from "../styles/Home.module.css";
|
||||
|
||||
export async function getStaticProps(ctx) {
|
||||
return {
|
||||
props: {
|
||||
},
|
||||
props: {},
|
||||
};
|
||||
}
|
||||
|
||||
export default function Home({ }) {
|
||||
export default function Home({}) {
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<Head>
|
||||
@@ -21,7 +20,7 @@ export default function Home({ }) {
|
||||
|
||||
<main className={styles.main}>
|
||||
<h1 className={styles.title}>
|
||||
Welcome to <a href="https://nextjs.org">Next.js!</a>
|
||||
Welcome!!to <a href="https://nextjs.org">Next.js!</a>
|
||||
</h1>
|
||||
|
||||
<p className={styles.description}>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
@import url("./2.css");
|
||||
.container {
|
||||
min-height: 100vh;
|
||||
min-height: 99vh;
|
||||
padding: 0 0.5rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -8,6 +8,8 @@
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
|
||||
.main {
|
||||
padding: 5rem 0;
|
||||
flex: 1;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"moment": "^2.29.1",
|
||||
"peechy": "^0.4.18",
|
||||
"peechy": "^0.4.19",
|
||||
"puppeteer": "^10.2.0",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2"
|
||||
|
||||
@@ -2920,7 +2920,7 @@ pub const Transformer = struct {
|
||||
var arena: std.heap.ArenaAllocator = undefined;
|
||||
const use_arenas = opts.entry_points.len > 8;
|
||||
|
||||
var ulimit: usize = Fs.FileSystem.RealFS.adjustUlimit();
|
||||
var ulimit: usize = Fs.FileSystem.RealFS.adjustUlimit() catch unreachable;
|
||||
var care_about_closing_files = !(FeatureFlags.store_file_descriptors and opts.entry_points.len * 2 < ulimit);
|
||||
|
||||
var transformer = Transformer{
|
||||
|
||||
@@ -1263,7 +1263,12 @@ pub fn NewBundler(
|
||||
|
||||
if (watcher_index == null) {
|
||||
var file = try std.fs.openFileAbsolute(absolute_path, .{ .read = true });
|
||||
|
||||
try this.watcher.appendFile(file.handle, absolute_path, hash, .css, 0, null, true);
|
||||
if (this.watcher.watchloop_handle == null) {
|
||||
try this.watcher.start();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
try this.import_queue.writeItem(hash);
|
||||
|
||||
26
src/fs.zig
26
src/fs.zig
@@ -541,16 +541,22 @@ pub const FileSystem = struct {
|
||||
}
|
||||
|
||||
// Always try to max out how many files we can keep open
|
||||
pub fn adjustUlimit() usize {
|
||||
var limit = std.os.getrlimit(.NOFILE) catch return 32;
|
||||
if (limit.cur < limit.max) {
|
||||
var new_limit = std.mem.zeroes(std.os.rlimit);
|
||||
new_limit.cur = limit.max;
|
||||
new_limit.max = limit.max;
|
||||
std.os.setrlimit(.NOFILE, new_limit) catch return limit.cur;
|
||||
return new_limit.cur;
|
||||
pub fn adjustUlimit() !usize {
|
||||
const LIMITS = [_]std.os.rlimit_resource{std.os.rlimit_resource.STACK, std.os.rlimit_resource.NOFILE};
|
||||
inline for (LIMITS) |limit_type, i| {
|
||||
const limit = try std.os.getrlimit(limit_type);
|
||||
|
||||
if (limit.cur < limit.max) {
|
||||
var new_limit = std.mem.zeroes(std.os.rlimit);
|
||||
new_limit.cur = limit.max;
|
||||
new_limit.max = limit.max;
|
||||
|
||||
try std.os.setrlimit(limit_type, new_limit);
|
||||
|
||||
}
|
||||
|
||||
if (i == LIMITS.len - 1) return limit.max;
|
||||
}
|
||||
return limit.cur;
|
||||
}
|
||||
|
||||
var _entries_option_map: *EntriesOption.Map = undefined;
|
||||
@@ -559,7 +565,7 @@ pub const FileSystem = struct {
|
||||
allocator: *std.mem.Allocator,
|
||||
cwd: string,
|
||||
) RealFS {
|
||||
const file_limit = adjustUlimit();
|
||||
const file_limit = adjustUlimit() catch unreachable;
|
||||
|
||||
if (!_entries_option_map_loaded) {
|
||||
_entries_option_map = EntriesOption.Map.init(allocator);
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
const std = @import("std");
|
||||
pub usingnamespace @import("strings.zig");
|
||||
pub const Environment = @import("env.zig");
|
||||
|
||||
pub const default_allocator: *std.mem.Allocator = if (isTest) std.heap.c_allocator else @import("./memory_allocator.zig").c_allocator;
|
||||
|
||||
pub const default_allocator: *std.mem.Allocator = if (isTest or Environment.isLinux)
|
||||
std.heap.c_allocator
|
||||
else
|
||||
@import("./memory_allocator.zig").c_allocator;
|
||||
|
||||
pub const C = @import("c.zig");
|
||||
pub const Environment = @import("env.zig");
|
||||
|
||||
pub usingnamespace Environment;
|
||||
|
||||
pub const FeatureFlags = @import("feature_flags.zig");
|
||||
|
||||
54
src/http.zig
54
src/http.zig
@@ -50,6 +50,7 @@ threadlocal var req_headers_buf: [100]picohttp.Header = undefined;
|
||||
threadlocal var res_headers_buf: [100]picohttp.Header = undefined;
|
||||
const sync = @import("./sync.zig");
|
||||
const JavaScript = @import("./javascript/jsc/javascript.zig");
|
||||
const JavaScriptCore = @import("./javascript/jsc/JavascriptCore.zig");
|
||||
usingnamespace @import("./javascript/jsc/bindings/bindings.zig");
|
||||
usingnamespace @import("./javascript/jsc/bindings/exports.zig");
|
||||
const Router = @import("./router.zig");
|
||||
@@ -1102,11 +1103,11 @@ pub const RequestContext = struct {
|
||||
pub var channel: Channel = undefined;
|
||||
var has_loaded_channel = false;
|
||||
pub var javascript_disabled = false;
|
||||
|
||||
var js_thread: std.Thread = undefined;
|
||||
pub fn spawnThread(handler: *HandlerThread) !void {
|
||||
var thread = try std.Thread.spawn(.{}, spawn, .{handler});
|
||||
thread.setName("WebSocket") catch {};
|
||||
thread.detach();
|
||||
js_thread = try std.Thread.spawn(.{.stack_size = 64 * 1024 * 1024}, spawn, .{handler});
|
||||
js_thread.setName("JavaScript SSR") catch {};
|
||||
js_thread.detach();
|
||||
}
|
||||
|
||||
pub fn spawn(handler: *HandlerThread) void {
|
||||
@@ -1118,20 +1119,19 @@ pub const RequestContext = struct {
|
||||
javascript_disabled = true;
|
||||
}
|
||||
var start_timer = std.time.Timer.start() catch unreachable;
|
||||
|
||||
|
||||
var stdout = std.io.getStdOut();
|
||||
// var stdout = std.io.bufferedWriter(stdout_file.writer());
|
||||
var stderr = std.io.getStdErr();
|
||||
// var stderr = std.io.bufferedWriter(stderr_file.writer());
|
||||
var output_source = Output.Source.init(stdout, stderr);
|
||||
// defer stdout.flush() catch {};
|
||||
// defer stderr.flush() catch {};
|
||||
defer Output.flush();
|
||||
Output.Source.set(&output_source);
|
||||
|
||||
|
||||
js_ast.Stmt.Data.Store.create(std.heap.c_allocator);
|
||||
js_ast.Expr.Data.Store.create(std.heap.c_allocator);
|
||||
|
||||
defer Output.flush();
|
||||
|
||||
var vm = JavaScript.VirtualMachine.init(
|
||||
std.heap.c_allocator,
|
||||
handler.args,
|
||||
@@ -1947,6 +1947,8 @@ pub const RequestContext = struct {
|
||||
// CSS handles this specially
|
||||
if (loader != .css and client_entry_point_ == null) {
|
||||
if (written.input_fd) |written_fd| {
|
||||
|
||||
|
||||
try ctx.watcher.addFile(
|
||||
written_fd,
|
||||
result.file.input.text,
|
||||
@@ -1958,8 +1960,9 @@ pub const RequestContext = struct {
|
||||
);
|
||||
|
||||
if (ctx.watcher.watchloop_handle == null) {
|
||||
try ctx.watcher.start();
|
||||
ctx.watcher.start() catch {};
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
if (written.written > 0) {
|
||||
@@ -2008,6 +2011,7 @@ pub const RequestContext = struct {
|
||||
if (file.autowatch) {
|
||||
// we must never autowatch a file that will be closed
|
||||
std.debug.assert(!file.close_handle_on_complete);
|
||||
|
||||
if (ctx.watcher.addFile(
|
||||
file.fd,
|
||||
result.file.input.text,
|
||||
@@ -2438,16 +2442,6 @@ pub const Server = struct {
|
||||
transform_options: Api.TransformOptions,
|
||||
javascript_enabled: bool = false,
|
||||
|
||||
pub fn adjustUlimit() !void {
|
||||
var limit = try std.os.getrlimit(.NOFILE);
|
||||
if (limit.cur < limit.max) {
|
||||
var new_limit = std.mem.zeroes(std.os.rlimit);
|
||||
new_limit.cur = limit.max;
|
||||
new_limit.max = limit.max;
|
||||
try std.os.setrlimit(.NOFILE, new_limit);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn onTCPConnection(server: *Server, conn: tcp.Connection, comptime features: ConnectionFeatures) void {
|
||||
conn.client.setNoDelay(true) catch {};
|
||||
conn.client.setQuickACK(true) catch {};
|
||||
@@ -2502,6 +2496,9 @@ pub const Server = struct {
|
||||
defer ctx.watcher.flushEvictions();
|
||||
defer Output.flush();
|
||||
|
||||
var rfs: *Fs.FileSystem.RealFS = &ctx.bundler.fs.fs;
|
||||
|
||||
|
||||
// It's important that this function does not do any memory allocations
|
||||
// If this blocks, it can cause cascading bad things to happen
|
||||
for (events) |event| {
|
||||
@@ -2526,7 +2523,6 @@ pub const Server = struct {
|
||||
switch (kind) {
|
||||
.file => {
|
||||
if (event.op.delete or event.op.rename) {
|
||||
var rfs: *Fs.FileSystem.RealFS = &ctx.bundler.fs.fs;
|
||||
ctx.watcher.removeAtIndex(
|
||||
event.index,
|
||||
0,
|
||||
@@ -2559,12 +2555,12 @@ pub const Server = struct {
|
||||
}
|
||||
},
|
||||
.directory => {
|
||||
var rfs: *Fs.FileSystem.RealFS = &ctx.bundler.fs.fs;
|
||||
|
||||
rfs.bustEntriesCache(file_path);
|
||||
ctx.bundler.resolver.dir_cache.remove(file_path);
|
||||
|
||||
if (event.op.delete or event.op.rename)
|
||||
ctx.watcher.removeAtIndex(event.index, hashes[event.index], parent_hashes, .directory);
|
||||
// if (event.op.delete or event.op.rename)
|
||||
// ctx.watcher.removeAtIndex(event.index, hashes[event.index], parent_hashes, .directory);
|
||||
|
||||
if (comptime is_emoji_enabled) {
|
||||
Output.prettyln("<r>📁 <d>Dir change: {s}<r>", .{ctx.bundler.fs.relativeTo(file_path)});
|
||||
@@ -2577,7 +2573,7 @@ pub const Server = struct {
|
||||
}
|
||||
|
||||
fn run(server: *Server, comptime features: ConnectionFeatures) !void {
|
||||
adjustUlimit() catch {};
|
||||
_ = Fs.FileSystem.RealFS.adjustUlimit() catch {};
|
||||
RequestContext.WebsocketHandler.open_websockets = @TypeOf(
|
||||
RequestContext.WebsocketHandler.open_websockets,
|
||||
).init(server.allocator);
|
||||
@@ -2723,6 +2719,7 @@ pub const Server = struct {
|
||||
};
|
||||
};
|
||||
|
||||
threadlocal var req_ctx_: RequestContext = undefined;
|
||||
pub fn handleConnection(server: *Server, conn: *tcp.Connection, comptime features: ConnectionFeatures) void {
|
||||
|
||||
// https://stackoverflow.com/questions/686217/maximum-on-http-header-values
|
||||
@@ -2745,9 +2742,9 @@ pub const Server = struct {
|
||||
|
||||
var request_arena = server.allocator.create(std.heap.ArenaAllocator) catch unreachable;
|
||||
request_arena.* = std.heap.ArenaAllocator.init(server.allocator);
|
||||
var req_ctx: RequestContext = undefined;
|
||||
|
||||
|
||||
req_ctx = RequestContext.init(
|
||||
req_ctx_ = RequestContext.init(
|
||||
req,
|
||||
request_arena,
|
||||
conn,
|
||||
@@ -2759,6 +2756,7 @@ pub const Server = struct {
|
||||
conn.client.deinit();
|
||||
return;
|
||||
};
|
||||
var req_ctx = &req_ctx_;
|
||||
req_ctx.timer.reset();
|
||||
|
||||
if (req_ctx.url.needs_redirect) {
|
||||
@@ -2880,7 +2878,7 @@ pub const Server = struct {
|
||||
|
||||
if (comptime features.filesystem_router) {
|
||||
if (!finished) {
|
||||
req_ctx.bundler.router.?.match(server, RequestContext, &req_ctx) catch |err| {
|
||||
req_ctx.bundler.router.?.match(server, RequestContext, req_ctx) catch |err| {
|
||||
switch (err) {
|
||||
error.ModuleNotFound => {
|
||||
req_ctx.sendNotFound() catch {};
|
||||
|
||||
@@ -544,3 +544,7 @@ pub const JSString = struct {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// not official api functions
|
||||
pub extern "c" fn JSCInitialize() void;
|
||||
|
||||
Submodule src/javascript/jsc/WebKit updated: 2312676710...487a7b31de
@@ -58,6 +58,8 @@
|
||||
#include <wtf/text/StringView.h>
|
||||
#include <wtf/text/WTFString.h>
|
||||
|
||||
#include <wtf/Gigacage.h>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
@@ -82,22 +84,21 @@ namespace JSCastingHelpers = JSC::JSCastingHelpers;
|
||||
|
||||
bool has_loaded_jsc = false;
|
||||
|
||||
extern "C" JSC__JSGlobalObject *Zig__GlobalObject__create(JSClassRef *globalObjectClass, int count,
|
||||
void *console_client) {
|
||||
|
||||
if (!has_loaded_jsc) {
|
||||
extern "C" void JSCInitialize() {
|
||||
if (has_loaded_jsc) return;
|
||||
JSC::Options::useSourceProviderCache() = true;
|
||||
JSC::Options::useUnlinkedCodeBlockJettisoning() = false;
|
||||
// JSC::Options::useTopLevelAwait() = true;
|
||||
JSC::Options::exposeInternalModuleLoader() = true;
|
||||
std::set_terminate([]() { Zig__GlobalObject__onCrash(); });
|
||||
// std::set_terminate([]() { Zig__GlobalObject__onCrash(); });
|
||||
WTF::initializeMainThread();
|
||||
JSC::initialize();
|
||||
// Gigacage::disablePrimitiveGigacage();
|
||||
has_loaded_jsc = true;
|
||||
}
|
||||
|
||||
// JSC::Options::useCodeCache() = false;
|
||||
}
|
||||
|
||||
extern "C" JSC__JSGlobalObject *Zig__GlobalObject__create(JSClassRef *globalObjectClass, int count,
|
||||
void *console_client) {
|
||||
auto heapSize = JSC::LargeHeap;
|
||||
|
||||
JSC::VM &vm = JSC::VM::create(heapSize).leakRef();
|
||||
|
||||
@@ -22,6 +22,7 @@ pub fn panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace) nore
|
||||
}
|
||||
pub var start_time: i128 = 0;
|
||||
pub fn main() anyerror!void {
|
||||
@import("javascript/jsc/JavascriptCore.zig").JSCInitialize();
|
||||
start_time = std.time.nanoTimestamp();
|
||||
|
||||
// The memory allocator makes a massive difference.
|
||||
|
||||
@@ -1 +1 @@
|
||||
35057197d4ad54bc
|
||||
4d09f9efba49d5ac
|
||||
@@ -60,17 +60,29 @@ pub const INotify = struct {
|
||||
var eventlist: EventListBuffer = undefined;
|
||||
var eventlist_ptrs: [128]*const INotifyEvent = undefined;
|
||||
|
||||
const add_mask = IN_EXCL_UNLINK | IN_MOVE_SELF | IN_CREATE | IN_DELETE | IN_DELETE_SELF;
|
||||
var watch_count: std.atomic.Atomic(u32) = std.atomic.Atomic(u32).init(0);
|
||||
|
||||
pub fn watchPath(pathname: [*:0]const u8) !EventListIndex {
|
||||
const watch_file_mask = IN_EXCL_UNLINK | IN_MOVE_SELF | IN_DELETE_SELF | IN_CLOSE_WRITE;
|
||||
const watch_dir_mask = IN_EXCL_UNLINK | IN_DELETE | IN_DELETE_SELF | IN_CREATE | IN_MOVE_SELF | IN_ONLYDIR;
|
||||
|
||||
pub fn watchPath(pathname: [:0]const u8) !EventListIndex {
|
||||
std.debug.assert(loaded_inotify);
|
||||
|
||||
return std.os.inotify_add_watchZ(inotify_fd, pathname, add_mask);
|
||||
const old_count = watch_count.fetchAdd(1, .Release);
|
||||
defer if (old_count == 0) std.Thread.Futex.wake(&watch_count, 10);
|
||||
return std.os.inotify_add_watchZ(inotify_fd, pathname, watch_file_mask);
|
||||
}
|
||||
|
||||
pub fn watchDir(pathname: [:0]const u8) !EventListIndex {
|
||||
std.debug.assert(loaded_inotify);
|
||||
const old_count = watch_count.fetchAdd(1, .Release);
|
||||
defer if (old_count == 0) std.Thread.Futex.wake(&watch_count, 10);
|
||||
return std.os.inotify_add_watchZ(inotify_fd, pathname, watch_dir_mask);
|
||||
}
|
||||
|
||||
|
||||
pub fn unwatch(wd: EventListIndex) void {
|
||||
std.debug.assert(loaded_inotify);
|
||||
|
||||
_ = watch_count.fetchSub(1, .Release);
|
||||
std.os.inotify_rm_watch(inotify_fd, wd);
|
||||
}
|
||||
|
||||
@@ -84,6 +96,10 @@ pub const INotify = struct {
|
||||
pub fn read() ![]*const INotifyEvent {
|
||||
std.debug.assert(loaded_inotify);
|
||||
|
||||
restart: while (true) {
|
||||
|
||||
|
||||
std.Thread.Futex.wait(&watch_count,0, null) catch unreachable;
|
||||
const rc = std.os.system.read(
|
||||
inotify_fd,
|
||||
@ptrCast([*]u8, @alignCast(@alignOf([*]u8), &eventlist)),
|
||||
@@ -110,12 +126,14 @@ pub const INotify = struct {
|
||||
|
||||
return eventlist_ptrs[0..count];
|
||||
},
|
||||
.AGAIN => continue :restart,
|
||||
.INVAL => return error.ShortRead,
|
||||
.BADF => return error.INotifyFailedToStart,
|
||||
|
||||
else => unreachable,
|
||||
}
|
||||
|
||||
}
|
||||
unreachable;
|
||||
}
|
||||
|
||||
@@ -183,6 +201,21 @@ pub const WatchEvent = struct {
|
||||
op: Op,
|
||||
|
||||
const KEvent = std.os.Kevent;
|
||||
|
||||
pub const Sorter = void;
|
||||
|
||||
pub fn sortByIndex(context: Sorter, event: WatchEvent, rhs: WatchEvent) bool {
|
||||
return event.index < rhs.index;
|
||||
}
|
||||
|
||||
pub fn merge(this: *WatchEvent, other: WatchEvent) void {
|
||||
this.op = Op{
|
||||
.delete = this.op.delete or other.op.delete,
|
||||
.metadata = this.op.metadata or other.op.metadata,
|
||||
.rename = this.op.rename or other.op.rename,
|
||||
.write = this.op.write or other.op.write,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn fromKEvent(this: *WatchEvent, kevent: KEvent) void {
|
||||
this.* =
|
||||
@@ -200,13 +233,10 @@ pub const WatchEvent = struct {
|
||||
pub fn fromINotify(this: *WatchEvent, event: INotify.INotifyEvent, index: WatchItemIndex) void {
|
||||
this.* = WatchEvent{
|
||||
.op = Op{
|
||||
.delete = (event.mask & INotify.IN_DELETE_SELF) > 0,
|
||||
// only applies to directories
|
||||
.metadata = (event.mask & INotify.IN_CREATE) > 0 or
|
||||
(event.mask & INotify.IN_DELETE) > 0 or
|
||||
(event.mask & INotify.IN_MOVE) > 0,
|
||||
.delete = (event.mask & INotify.IN_DELETE_SELF) > 0 or (event.mask & INotify.IN_DELETE) > 0,
|
||||
.metadata = false,
|
||||
.rename = (event.mask & INotify.IN_MOVE_SELF) > 0,
|
||||
.write = (event.mask & INotify.IN_MODIFY) > 0,
|
||||
.write = (event.mask & INotify.IN_MODIFY) > 0 or (event.mask & INotify.IN_MOVE) > 0,
|
||||
},
|
||||
.index = index,
|
||||
};
|
||||
@@ -257,6 +287,8 @@ pub fn NewWatcher(comptime ContextType: type) type {
|
||||
|
||||
pub fn init(ctx: ContextType, fs: *Fs.FileSystem, allocator: *std.mem.Allocator) !*Watcher {
|
||||
var watcher = try allocator.create(Watcher);
|
||||
try PlatformWatcher.init();
|
||||
|
||||
watcher.* = Watcher{
|
||||
.fs = fs,
|
||||
.fd = 0,
|
||||
@@ -272,7 +304,6 @@ pub fn NewWatcher(comptime ContextType: type) type {
|
||||
}
|
||||
|
||||
pub fn start(this: *Watcher) !void {
|
||||
try PlatformWatcher.init();
|
||||
std.debug.assert(this.watchloop_handle == null);
|
||||
var thread = try std.Thread.spawn(.{}, Watcher.watchLoop, .{this});
|
||||
thread.setName("File Watcher") catch {};
|
||||
@@ -389,7 +420,7 @@ pub fn NewWatcher(comptime ContextType: type) type {
|
||||
this.ctx.onFileUpdate(watchevents, this.watchlist);
|
||||
}
|
||||
} else if (Environment.isLinux) {
|
||||
while (true) {
|
||||
restart: while (true) {
|
||||
defer Output.flush();
|
||||
|
||||
var events = try INotify.read();
|
||||
@@ -417,7 +448,21 @@ pub fn NewWatcher(comptime ContextType: type) type {
|
||||
watch_event_id += 1;
|
||||
}
|
||||
|
||||
this.ctx.onFileUpdate(watchevents[0..watch_event_id], this.watchlist);
|
||||
var all_events = watchevents[0..watch_event_id];
|
||||
std.sort.sort(WatchEvent, all_events, void{}, WatchEvent.sortByIndex);
|
||||
|
||||
var last_event_index: usize = 0;
|
||||
var last_event_id: INotify.EventListIndex = std.math.maxInt(INotify.EventListIndex);
|
||||
for (all_events) |event, i| {
|
||||
if (event.index == last_event_id) {
|
||||
all_events[last_event_index].merge(event);
|
||||
continue;
|
||||
}
|
||||
last_event_index = i;
|
||||
last_event_id = event.index;
|
||||
}
|
||||
if (all_events.len == 0) continue :restart;
|
||||
this.ctx.onFileUpdate(all_events[0..last_event_index+1], this.watchlist);
|
||||
remaining_events -= slice.len;
|
||||
}
|
||||
}
|
||||
@@ -503,11 +548,13 @@ pub fn NewWatcher(comptime ContextType: type) type {
|
||||
null,
|
||||
);
|
||||
} else if (Environment.isLinux) {
|
||||
var sentineled = file_path_;
|
||||
var file_path_to_use_ptr: [*c]u8 = @intToPtr([*c]u8, @ptrToInt(file_path_.ptr));
|
||||
var file_path_to_use: [:0]u8 = file_path_to_use_ptr[0..sentineled.len :0];
|
||||
|
||||
index = try INotify.watchPath(file_path_to_use);
|
||||
// var file_path_to_use_ = std.mem.trimRight(u8, file_path_, "/");
|
||||
// var buf: [std.fs.MAX_PATH_BYTES+1]u8 = undefined;
|
||||
// std.mem.copy(u8, &buf, file_path_to_use_);
|
||||
// buf[file_path_to_use_.len] = 0;
|
||||
var buf = file_path_.ptr;
|
||||
var slice: [:0]const u8 = buf[0..file_path_.len:0];
|
||||
index = try INotify.watchPath(slice);
|
||||
}
|
||||
|
||||
this.watchlist.appendAssumeCapacity(.{
|
||||
@@ -587,12 +634,12 @@ pub fn NewWatcher(comptime ContextType: type) type {
|
||||
null,
|
||||
);
|
||||
} else if (Environment.isLinux) {
|
||||
// This works around a Zig compiler bug when casting a slice from a string to a sentineled string.
|
||||
var sentineled = file_path_;
|
||||
var file_path_to_use_ptr: [*c]u8 = @intToPtr([*c]u8, @ptrToInt(file_path_.ptr));
|
||||
var file_path_to_use: [:0]u8 = file_path_to_use_ptr[0..sentineled.len :0];
|
||||
|
||||
index = try INotify.watchPath(file_path_to_use);
|
||||
var file_path_to_use_ = std.mem.trimRight(u8, file_path_, "/");
|
||||
var buf: [std.fs.MAX_PATH_BYTES+1]u8 = undefined;
|
||||
std.mem.copy(u8, &buf, file_path_to_use_);
|
||||
buf[file_path_to_use_.len] = 0;
|
||||
var slice: [:0]u8 = buf[0..file_path_to_use_.len:0];
|
||||
index = try INotify.watchDir(slice);
|
||||
}
|
||||
|
||||
this.watchlist.appendAssumeCapacity(.{
|
||||
|
||||
Reference in New Issue
Block a user