aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.dockerignore14
-rw-r--r--.vscode/launch.json9
-rw-r--r--Dockerfile8
-rw-r--r--Dockerfile.zig52
-rw-r--r--Makefile98
-rw-r--r--README.md5
-rw-r--r--build.zig6
-rw-r--r--examples/hello-next/pages/index.tsx7
-rw-r--r--examples/hello-next/styles/Home.module.css4
-rw-r--r--package.json2
-rw-r--r--src/bundler.zig2
-rw-r--r--src/css_scanner.zig5
-rw-r--r--src/fs.zig26
-rw-r--r--src/global.zig9
-rw-r--r--src/http.zig54
-rw-r--r--src/javascript/jsc/JavascriptCore.zig4
m---------src/javascript/jsc/WebKit0
-rw-r--r--src/javascript/jsc/bindings/ZigGlobalObject.cpp17
-rw-r--r--src/main.zig1
-rw-r--r--src/runtime.version2
-rw-r--r--src/watcher.zig95
21 files changed, 320 insertions, 100 deletions
diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 000000000..9d969e9d0
--- /dev/null
+++ b/.dockerignore
@@ -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 \ No newline at end of file
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 53f298ca2..8501f676e 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -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",
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 000000000..16ee6dc40
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,8 @@
+FROM bun-zig:latest
+
+COPY . /home/ubuntu/bun
+WORKDIR /home/ubuntu/bun
+
+RUN make vendor-without-check
+
+
diff --git a/Dockerfile.zig b/Dockerfile.zig
new file mode 100644
index 000000000..57598be49
--- /dev/null
+++ b/Dockerfile.zig
@@ -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
+
+
+
+
+
diff --git a/Makefile b/Makefile
index 5a229cc52..bd3ebe0c7 100644
--- a/Makefile
+++ b/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 ../../
diff --git a/README.md b/README.md
index 6fa37cc67..a59526523 100644
--- a/README.md
+++ b/README.md
@@ -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: \ No newline at end of file
diff --git a/build.zig b/build.zig
index 4668aef04..fcd4b4b1d 100644
--- a/build.zig
+++ b/build.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");
diff --git a/examples/hello-next/pages/index.tsx b/examples/hello-next/pages/index.tsx
index f733efb51..9101ed8c7 100644
--- a/examples/hello-next/pages/index.tsx
+++ b/examples/hello-next/pages/index.tsx
@@ -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}>
diff --git a/examples/hello-next/styles/Home.module.css b/examples/hello-next/styles/Home.module.css
index 167d5f75b..4a04160d0 100644
--- a/examples/hello-next/styles/Home.module.css
+++ b/examples/hello-next/styles/Home.module.css
@@ -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;
diff --git a/package.json b/package.json
index 2052081df..23453625a 100644
--- a/package.json
+++ b/package.json
@@ -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"
diff --git a/src/bundler.zig b/src/bundler.zig
index cc82ccf41..262a22888 100644
--- a/src/bundler.zig
+++ b/src/bundler.zig
@@ -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{
diff --git a/src/css_scanner.zig b/src/css_scanner.zig
index 0adcd9917..41e43c22e 100644
--- a/src/css_scanner.zig
+++ b/src/css_scanner.zig
@@ -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);
diff --git a/src/fs.zig b/src/fs.zig
index 517dcdbd5..2313dc17b 100644
--- a/src/fs.zig
+++ b/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);
diff --git a/src/global.zig b/src/global.zig
index 236751a6b..64d5f1a82 100644
--- a/src/global.zig
+++ b/src/global.zig
@@ -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");
diff --git a/src/http.zig b/src/http.zig
index 0ddc02540..72a452327 100644
--- a/src/http.zig
+++ b/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 {};
diff --git a/src/javascript/jsc/JavascriptCore.zig b/src/javascript/jsc/JavascriptCore.zig
index f443799c1..dd271d2c0 100644
--- a/src/javascript/jsc/JavascriptCore.zig
+++ b/src/javascript/jsc/JavascriptCore.zig
@@ -544,3 +544,7 @@ pub const JSString = struct {
}
}
};
+
+
+// not official api functions
+pub extern "c" fn JSCInitialize() void;
diff --git a/src/javascript/jsc/WebKit b/src/javascript/jsc/WebKit
-Subproject 231267671049bbd7cd60cd6e66fbc76b9e5ee5e
+Subproject 487a7b31de9fa54dab1611799db26907c14dc5a
diff --git a/src/javascript/jsc/bindings/ZigGlobalObject.cpp b/src/javascript/jsc/bindings/ZigGlobalObject.cpp
index dd98742d2..e470e27b5 100644
--- a/src/javascript/jsc/bindings/ZigGlobalObject.cpp
+++ b/src/javascript/jsc/bindings/ZigGlobalObject.cpp
@@ -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();
diff --git a/src/main.zig b/src/main.zig
index 7b86f7360..f73f9c292 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -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.
diff --git a/src/runtime.version b/src/runtime.version
index 57659652b..2dcc8c529 100644
--- a/src/runtime.version
+++ b/src/runtime.version
@@ -1 +1 @@
-35057197d4ad54bc \ No newline at end of file
+4d09f9efba49d5ac \ No newline at end of file
diff --git a/src/watcher.zig b/src/watcher.zig
index 63fdb9007..f088d31d2 100644
--- a/src/watcher.zig
+++ b/src/watcher.zig
@@ -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);
+ 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);
+ }
- return std.os.inotify_add_watchZ(inotify_fd, pathname, add_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(.{