mirror of
https://github.com/oven-sh/bun
synced 2026-02-09 18:38:55 +00:00
more mutexes
Former-commit-id: 52966012b4b74d24ab28a0c75740aef35fb75327
This commit is contained in:
@@ -144,14 +144,19 @@ pub fn BSSList(comptime ValueType: type, comptime _count: anytype) type {
|
||||
|
||||
overflow_list: OverflowListType,
|
||||
allocator: *Allocator,
|
||||
mutex: Mutex = Mutex.init(),
|
||||
|
||||
pub var instance: Self = undefined;
|
||||
pub var loaded = false;
|
||||
|
||||
pub fn init(allocator: *std.mem.Allocator) *Self {
|
||||
instance = Self{
|
||||
.allocator = allocator,
|
||||
.overflow_list = OverflowListType{},
|
||||
};
|
||||
if (!loaded) {
|
||||
instance = Self{
|
||||
.allocator = allocator,
|
||||
.overflow_list = OverflowListType{},
|
||||
};
|
||||
loaded = true;
|
||||
}
|
||||
|
||||
return &instance;
|
||||
}
|
||||
@@ -175,6 +180,8 @@ pub fn BSSList(comptime ValueType: type, comptime _count: anytype) type {
|
||||
}
|
||||
|
||||
pub fn append(self: *Self, value: ValueType) !IndexType {
|
||||
self.mutex.lock();
|
||||
defer self.mutex.unlock();
|
||||
var result = IndexType{ .index = std.math.maxInt(u31), .is_overflow = backing_buf_used > max_index };
|
||||
if (result.is_overflow) {
|
||||
result.index = @intCast(u31, self.overflow_list.items.len);
|
||||
@@ -192,6 +199,9 @@ pub fn BSSList(comptime ValueType: type, comptime _count: anytype) type {
|
||||
}
|
||||
pub const Pair = struct { index: IndexType, value: *ValueType };
|
||||
pub fn appendGet(self: *Self, value: ValueType) !Pair {
|
||||
self.mutex.lock();
|
||||
defer self.mutex.unlock();
|
||||
|
||||
var result = IndexType{ .index = std.math.maxInt(u31), .is_overflow = backing_buf_used > max_index };
|
||||
if (result.is_overflow) {
|
||||
result.index = @intCast(u31, self.overflow_list.items.len);
|
||||
@@ -209,6 +219,9 @@ pub fn BSSList(comptime ValueType: type, comptime _count: anytype) type {
|
||||
}
|
||||
|
||||
pub fn update(self: *Self, result: *IndexType, value: ValueType) !*ValueType {
|
||||
self.mutex.lock();
|
||||
defer self.mutex.unlock();
|
||||
|
||||
if (result.index.index == NotFound.index or result.index.index == Unassigned.index) {
|
||||
result.index.is_overflow = backing_buf_used > max_index;
|
||||
if (result.index.is_overflow) {
|
||||
@@ -267,7 +280,7 @@ pub fn BSSList(comptime ValueType: type, comptime _count: anytype) type {
|
||||
};
|
||||
}
|
||||
|
||||
const Mutex = @import("./sync.zig").Mutex;
|
||||
const Mutex = @import("./lock.zig").Lock;
|
||||
|
||||
/// Append-only list.
|
||||
/// Stores an initial count in .bss section of the object file
|
||||
@@ -480,15 +493,21 @@ pub fn BSSMap(comptime ValueType: type, comptime count: anytype, store_keys: boo
|
||||
index: IndexMap,
|
||||
overflow_list: std.ArrayListUnmanaged(ValueType),
|
||||
allocator: *Allocator,
|
||||
mutex: Mutex = Mutex.init(),
|
||||
|
||||
pub var instance: Self = undefined;
|
||||
|
||||
var loaded: bool = false;
|
||||
|
||||
pub fn init(allocator: *std.mem.Allocator) *Self {
|
||||
instance = Self{
|
||||
.index = IndexMap{},
|
||||
.allocator = allocator,
|
||||
.overflow_list = std.ArrayListUnmanaged(ValueType){},
|
||||
};
|
||||
if (!loaded) {
|
||||
instance = Self{
|
||||
.index = IndexMap{},
|
||||
.allocator = allocator,
|
||||
.overflow_list = std.ArrayListUnmanaged(ValueType){},
|
||||
};
|
||||
loaded = true;
|
||||
}
|
||||
|
||||
return &instance;
|
||||
}
|
||||
@@ -500,6 +519,9 @@ pub fn BSSMap(comptime ValueType: type, comptime count: anytype, store_keys: boo
|
||||
pub fn getOrPut(self: *Self, denormalized_key: []const u8) !Result {
|
||||
const key = if (comptime remove_trailing_slashes) std.mem.trimRight(u8, denormalized_key, "/") else denormalized_key;
|
||||
const _key = Wyhash.hash(Seed, key);
|
||||
|
||||
self.mutex.lock();
|
||||
defer self.mutex.unlock();
|
||||
var index = try self.index.getOrPut(self.allocator, _key);
|
||||
|
||||
if (index.found_existing) {
|
||||
@@ -522,14 +544,19 @@ pub fn BSSMap(comptime ValueType: type, comptime count: anytype, store_keys: boo
|
||||
};
|
||||
}
|
||||
|
||||
pub fn get(self: *const Self, denormalized_key: []const u8) ?*ValueType {
|
||||
pub fn get(self: *Self, denormalized_key: []const u8) ?*ValueType {
|
||||
const key = if (comptime remove_trailing_slashes) std.mem.trimRight(u8, denormalized_key, "/") else denormalized_key;
|
||||
const _key = Wyhash.hash(Seed, key);
|
||||
self.mutex.lock();
|
||||
defer self.mutex.unlock();
|
||||
const index = self.index.get(_key) orelse return null;
|
||||
return self.atIndex(index);
|
||||
}
|
||||
|
||||
pub fn markNotFound(self: *Self, result: Result) void {
|
||||
self.mutex.lock();
|
||||
defer self.mutex.unlock();
|
||||
|
||||
self.index.put(self.allocator, result.hash, NotFound) catch unreachable;
|
||||
}
|
||||
|
||||
@@ -544,6 +571,9 @@ pub fn BSSMap(comptime ValueType: type, comptime count: anytype, store_keys: boo
|
||||
}
|
||||
|
||||
pub fn put(self: *Self, result: *Result, value: ValueType) !*ValueType {
|
||||
self.mutex.lock();
|
||||
defer self.mutex.unlock();
|
||||
|
||||
if (result.index.index == NotFound.index or result.index.index == Unassigned.index) {
|
||||
result.index.is_overflow = backing_buf_used > max_index;
|
||||
if (result.index.is_overflow) {
|
||||
@@ -576,6 +606,9 @@ pub fn BSSMap(comptime ValueType: type, comptime count: anytype, store_keys: boo
|
||||
}
|
||||
|
||||
pub fn remove(self: *Self, denormalized_key: []const u8) void {
|
||||
self.mutex.lock();
|
||||
defer self.mutex.unlock();
|
||||
|
||||
const key = if (comptime remove_trailing_slashes) std.mem.trimRight(u8, denormalized_key, "/") else denormalized_key;
|
||||
|
||||
const _key = Wyhash.hash(Seed, key);
|
||||
@@ -671,6 +704,8 @@ pub fn BSSMap(comptime ValueType: type, comptime count: anytype, store_keys: boo
|
||||
// 1. Storing the underyling string.
|
||||
// 2. Making the key accessible at the index.
|
||||
pub fn putKey(self: *Self, key: anytype, result: *Result) !void {
|
||||
self.map.mutex.lock();
|
||||
defer self.map.mutex.unlock();
|
||||
var slice: []u8 = undefined;
|
||||
|
||||
// Is this actually a slice into the map? Don't free it.
|
||||
@@ -715,240 +750,6 @@ pub fn BSSMap(comptime ValueType: type, comptime count: anytype, store_keys: boo
|
||||
};
|
||||
}
|
||||
|
||||
pub fn TBSSMap(comptime ValueType: type, comptime count: anytype, store_keys: bool, estimated_key_length: usize) type {
|
||||
const max_index = count - 1;
|
||||
const BSSMapType = struct {
|
||||
pub threadlocal var backing_buf: [count]ValueType = undefined;
|
||||
pub threadlocal var backing_buf_used: u16 = 0;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const Self = @This();
|
||||
|
||||
index: IndexMap,
|
||||
overflow_list: std.ArrayListUnmanaged(ValueType),
|
||||
allocator: *Allocator,
|
||||
|
||||
pub threadlocal var instance: Self = undefined;
|
||||
|
||||
pub fn init(allocator: *std.mem.Allocator) *Self {
|
||||
instance = Self{
|
||||
.index = IndexMap{},
|
||||
.allocator = allocator,
|
||||
.overflow_list = std.ArrayListUnmanaged(ValueType){},
|
||||
};
|
||||
|
||||
return &instance;
|
||||
}
|
||||
|
||||
pub fn isOverflowing() bool {
|
||||
return backing_buf_used >= @as(u16, count);
|
||||
}
|
||||
|
||||
pub fn getOrPut(self: *Self, key: []const u8) !Result {
|
||||
const _key = Wyhash.hash(Seed, key);
|
||||
var index = try self.index.getOrPut(self.allocator, _key);
|
||||
|
||||
if (index.found_existing) {
|
||||
return Result{
|
||||
.hash = _key,
|
||||
.index = index.value_ptr.*,
|
||||
.status = switch (index.value_ptr.index) {
|
||||
NotFound.index => .not_found,
|
||||
Unassigned.index => .unknown,
|
||||
else => .exists,
|
||||
},
|
||||
};
|
||||
}
|
||||
index.value_ptr.* = Unassigned;
|
||||
|
||||
return Result{
|
||||
.hash = _key,
|
||||
.index = Unassigned,
|
||||
.status = .unknown,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn get(self: *const Self, key: []const u8) ?*ValueType {
|
||||
const _key = Wyhash.hash(Seed, key);
|
||||
const index = self.index.get(_key) orelse return null;
|
||||
return self.atIndex(index);
|
||||
}
|
||||
|
||||
pub fn markNotFound(self: *Self, result: Result) void {
|
||||
self.index.put(self.allocator, result.hash, NotFound) catch unreachable;
|
||||
}
|
||||
|
||||
pub fn atIndex(self: *const Self, index: IndexType) ?*ValueType {
|
||||
if (index.index == NotFound.index or index.index == Unassigned.index) return null;
|
||||
|
||||
if (index.is_overflow) {
|
||||
return &self.overflow_list.items[index.index];
|
||||
} else {
|
||||
return &backing_buf[index.index];
|
||||
}
|
||||
}
|
||||
|
||||
pub fn put(self: *Self, result: *Result, value: ValueType) !*ValueType {
|
||||
if (result.index.index == NotFound.index or result.index.index == Unassigned.index) {
|
||||
result.index.is_overflow = backing_buf_used > max_index;
|
||||
if (result.index.is_overflow) {
|
||||
result.index.index = @intCast(u31, self.overflow_list.items.len);
|
||||
} else {
|
||||
result.index.index = backing_buf_used;
|
||||
backing_buf_used += 1;
|
||||
if (backing_buf_used >= max_index) {
|
||||
self.overflow_list = try @TypeOf(self.overflow_list).initCapacity(self.allocator, count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try self.index.put(self.allocator, result.hash, result.index);
|
||||
|
||||
if (result.index.is_overflow) {
|
||||
if (self.overflow_list.items.len == result.index.index) {
|
||||
const real_index = self.overflow_list.items.len;
|
||||
try self.overflow_list.append(self.allocator, value);
|
||||
} else {
|
||||
self.overflow_list.items[result.index.index] = value;
|
||||
}
|
||||
|
||||
return &self.overflow_list.items[result.index.index];
|
||||
} else {
|
||||
backing_buf[result.index.index] = value;
|
||||
|
||||
return &backing_buf[result.index.index];
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remove(self: *Self, key: []const u8) IndexType {
|
||||
const _key = Wyhash.hash(Seed, key);
|
||||
const index = self.index.get(_key) orelse return;
|
||||
defer _ = self.index.remove(_key);
|
||||
|
||||
switch (index) {
|
||||
NotFound.index, Unassigned.index => {},
|
||||
0...max_index => {
|
||||
// if (hasDeinit(ValueType)) {
|
||||
// backing_buf[index].deinit();
|
||||
// }
|
||||
backing_buf[index] = undefined;
|
||||
},
|
||||
else => {
|
||||
const i = index - count;
|
||||
if (hasDeinit(ValueType)) {
|
||||
self.overflow_list.items[i].deinit();
|
||||
}
|
||||
self.overflow_list.items[index - count] = undefined;
|
||||
},
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
};
|
||||
if (!store_keys) {
|
||||
return BSSMapType;
|
||||
}
|
||||
|
||||
return struct {
|
||||
map: *BSSMapType,
|
||||
const Self = @This();
|
||||
pub threadlocal var instance: Self = undefined;
|
||||
threadlocal var key_list_buffer: [count * estimated_key_length]u8 = undefined;
|
||||
threadlocal var key_list_buffer_used: usize = 0;
|
||||
threadlocal var key_list_slices: [count][]u8 = undefined;
|
||||
threadlocal var key_list_overflow: std.ArrayListUnmanaged([]u8) = undefined;
|
||||
|
||||
pub fn init(allocator: *std.mem.Allocator) *Self {
|
||||
instance = Self{
|
||||
.map = BSSMapType.init(allocator),
|
||||
};
|
||||
|
||||
return &instance;
|
||||
}
|
||||
|
||||
pub fn isOverflowing() bool {
|
||||
return instance.map.backing_buf_used >= count;
|
||||
}
|
||||
pub fn getOrPut(self: *Self, key: []const u8) !Result {
|
||||
return try self.map.getOrPut(key);
|
||||
}
|
||||
pub fn get(self: *Self, key: []const u8) ?*ValueType {
|
||||
return @call(.{ .modifier = .always_inline }, BSSMapType.get, .{ self.map, key });
|
||||
}
|
||||
|
||||
pub fn atIndex(self: *Self, index: IndexType) ?*ValueType {
|
||||
return @call(.{ .modifier = .always_inline }, BSSMapType.atIndex, .{ self.map, index });
|
||||
}
|
||||
|
||||
pub fn keyAtIndex(self: *Self, index: IndexType) ?[]const u8 {
|
||||
return switch (index.index) {
|
||||
Unassigned.index, NotFound.index => null,
|
||||
else => {
|
||||
if (!index.is_overflow) {
|
||||
return key_list_slices[index.index];
|
||||
} else {
|
||||
return key_list_overflow.items[index.index];
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub fn put(self: *Self, key: anytype, comptime store_key: bool, result: *Result, value: ValueType) !*ValueType {
|
||||
var ptr = try self.map.put(result, value);
|
||||
if (store_key) {
|
||||
try self.putKey(key, result);
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
pub fn isKeyStaticallyAllocated(key: anytype) bool {
|
||||
return isSliceInBuffer(key, &key_list_buffer);
|
||||
}
|
||||
|
||||
// There's two parts to this.
|
||||
// 1. Storing the underyling string.
|
||||
// 2. Making the key accessible at the index.
|
||||
pub fn putKey(self: *Self, key: anytype, result: *Result) !void {
|
||||
var slice: []u8 = undefined;
|
||||
|
||||
// Is this actually a slice into the map? Don't free it.
|
||||
if (isKeyStaticallyAllocated(key)) {
|
||||
slice = constStrToU8(key);
|
||||
} else if (key_list_buffer_used + key.len < key_list_buffer.len) {
|
||||
const start = key_list_buffer_used;
|
||||
key_list_buffer_used += key.len;
|
||||
slice = key_list_buffer[start..key_list_buffer_used];
|
||||
std.mem.copy(u8, slice, key);
|
||||
} else {
|
||||
slice = try self.map.allocator.dupe(u8, key);
|
||||
}
|
||||
|
||||
if (!result.index.is_overflow) {
|
||||
key_list_slices[result.index.index] = slice;
|
||||
} else {
|
||||
if (@intCast(u31, key_list_overflow.items.len) > result.index.index) {
|
||||
const existing_slice = key_list_overflow.items[result.index.index];
|
||||
if (!isKeyStaticallyAllocated(existing_slice)) {
|
||||
self.map.allocator.free(existing_slice);
|
||||
}
|
||||
key_list_overflow.items[result.index.index] = slice;
|
||||
} else {
|
||||
try key_list_overflow.append(self.map.allocator, slice);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn markNotFound(self: *Self, result: Result) void {
|
||||
self.map.markNotFound(result);
|
||||
}
|
||||
|
||||
// For now, don't free the keys.
|
||||
pub fn remove(self: *Self, key: string) IndexType {
|
||||
return self.map.remove(key);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub inline fn constStrToU8(s: []const u8) []u8 {
|
||||
return @intToPtr([*]u8, @ptrToInt(s.ptr))[0..s.len];
|
||||
}
|
||||
|
||||
@@ -422,10 +422,9 @@ pub fn NewBundler(cache_files: bool) type {
|
||||
};
|
||||
worker.data.shared_buffer = try MutableString.init(generator.allocator, 0);
|
||||
worker.data.scan_pass_result = js_parser.ScanPassResult.init(generator.allocator);
|
||||
worker.data.log = generator.log.*;
|
||||
worker.data.log = generator.log;
|
||||
|
||||
defer {
|
||||
generator.log.* = worker.data.log;
|
||||
worker.data.deinit(generator.allocator);
|
||||
}
|
||||
|
||||
@@ -441,10 +440,6 @@ pub fn NewBundler(cache_files: bool) type {
|
||||
std.atomic.spinLoopHint();
|
||||
}
|
||||
|
||||
for (this.workers[0..this.workers_used]) |*worker| {
|
||||
worker.data.log.appendTo(generator.log) catch {};
|
||||
}
|
||||
|
||||
for (this.workers[0..this.workers_used]) |*worker| {
|
||||
@atomicStore(bool, &worker.quit, true, .Release);
|
||||
}
|
||||
@@ -479,7 +474,7 @@ pub fn NewBundler(cache_files: bool) type {
|
||||
pub const WorkerData = struct {
|
||||
shared_buffer: MutableString = undefined,
|
||||
scan_pass_result: js_parser.ScanPassResult = undefined,
|
||||
log: logger.Log,
|
||||
log: *logger.Log,
|
||||
|
||||
pub fn deinit(this: *WorkerData, allocator: *std.mem.Allocator) void {
|
||||
this.shared_buffer.deinit();
|
||||
@@ -533,12 +528,19 @@ pub fn NewBundler(cache_files: bool) type {
|
||||
js_ast.Stmt.Data.Store.create(this.generator.allocator);
|
||||
this.data = this.generator.allocator.create(WorkerData) catch unreachable;
|
||||
this.data.* = WorkerData{
|
||||
.log = logger.Log.init(this.generator.allocator),
|
||||
.log = this.generator.allocator.create(logger.Log) catch unreachable,
|
||||
};
|
||||
this.data.log.* = logger.Log.init(this.generator.allocator);
|
||||
this.data.shared_buffer = try MutableString.init(this.generator.allocator, 0);
|
||||
this.data.scan_pass_result = js_parser.ScanPassResult.init(this.generator.allocator);
|
||||
|
||||
defer {
|
||||
{
|
||||
this.generator.log_lock.lock();
|
||||
this.data.log.appendTo(this.generator.log) catch {};
|
||||
this.generator.log_lock.unlock();
|
||||
}
|
||||
|
||||
this.data.deinit(this.generator.allocator);
|
||||
}
|
||||
|
||||
@@ -557,7 +559,7 @@ pub fn NewBundler(cache_files: bool) type {
|
||||
};
|
||||
};
|
||||
write_lock: Lock,
|
||||
|
||||
log_lock: Lock = Lock.init(),
|
||||
module_list: std.ArrayList(Api.JavascriptBundledModule),
|
||||
package_list: std.ArrayList(Api.JavascriptBundledPackage),
|
||||
header_string_buffer: MutableString,
|
||||
@@ -1085,7 +1087,7 @@ pub fn NewBundler(cache_files: bool) type {
|
||||
defer scan_pass_result.reset();
|
||||
defer shared_buffer.reset();
|
||||
defer this.bundler.resetStore();
|
||||
var log = &worker.data.log;
|
||||
var log = worker.data.log;
|
||||
|
||||
// If we're in a node_module, build that almost normally
|
||||
if (is_from_node_modules) {
|
||||
@@ -1585,6 +1587,7 @@ pub fn NewBundler(cache_files: bool) type {
|
||||
pub const BuildResolveResultPair = struct {
|
||||
written: usize,
|
||||
input_fd: ?StoredFileDescriptorType,
|
||||
empty: bool = false,
|
||||
};
|
||||
pub fn buildWithResolveResult(
|
||||
bundler: *ThisBundler,
|
||||
@@ -1700,7 +1703,7 @@ pub fn NewBundler(cache_files: bool) type {
|
||||
};
|
||||
|
||||
if (result.empty) {
|
||||
return BuildResolveResultPair{ .written = 0, .input_fd = result.input_fd };
|
||||
return BuildResolveResultPair{ .written = 0, .input_fd = result.input_fd, .empty = true };
|
||||
}
|
||||
|
||||
try bundler.linker.link(file_path, &result, import_path_format, false);
|
||||
|
||||
@@ -701,6 +701,10 @@ test "DotEnv Loader" {
|
||||
\\
|
||||
\\NESTED_VALUES_RESPECT_ESCAPING='\$API_KEY'
|
||||
\\
|
||||
\\EMPTY_SINGLE_QUOTED_VALUE_IS_EMPTY_STRING_CHARS=''
|
||||
\\
|
||||
\\EMPTY_DOUBLE_QUOTED_VALUE_IS_EMPTY_STRING_CHARS=""
|
||||
\\
|
||||
;
|
||||
const source = logger.Source.initPathString(".env", VALID_ENV);
|
||||
var map = Map.init(default_allocator);
|
||||
@@ -726,6 +730,8 @@ test "DotEnv Loader" {
|
||||
try expect(map.get("NO_VALUE_IS_EMPTY_STRING").?.len == 0);
|
||||
try expectString(map.get("IGNORING_DOESNT_BREAK_OTHER_LINES").?, "'yes'");
|
||||
try expectString(map.get("LEADING_SPACE_IN_UNQUOTED_VALUE_IS_TRIMMED").?, "yes");
|
||||
try expectString(map.get("EMPTY_SINGLE_QUOTED_VALUE_IS_EMPTY_STRING_CHARS").?, "''");
|
||||
try expectString(map.get("EMPTY_DOUBLE_QUOTED_VALUE_IS_EMPTY_STRING_CHARS").?, "\"\"");
|
||||
}
|
||||
|
||||
test "DotEnv Process" {
|
||||
|
||||
26
src/http.zig
26
src/http.zig
@@ -1823,6 +1823,30 @@ pub const RequestContext = struct {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (written.empty) {
|
||||
switch (loader) {
|
||||
.css => try ctx.sendNoContent(),
|
||||
.js, .jsx, .ts, .tsx, .json => {
|
||||
const buf = "export default {};";
|
||||
const strong_etag = comptime std.hash.Wyhash.hash(1, buf);
|
||||
const etag_content_slice = std.fmt.bufPrintIntToSlice(strong_etag_buffer[0..49], strong_etag, 16, .upper, .{});
|
||||
ctx.appendHeader("ETag", etag_content_slice);
|
||||
|
||||
if (ctx.header("If-None-Match")) |etag_header| {
|
||||
if (std.mem.eql(u8, etag_content_slice, etag_header.value)) {
|
||||
try ctx.sendNotModified();
|
||||
return;
|
||||
}
|
||||
}
|
||||
defer ctx.done();
|
||||
try ctx.writeStatus(200);
|
||||
try ctx.prepareToSendBody(buf.len, false);
|
||||
try ctx.writeBodyBuf(buf);
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
},
|
||||
.noop => {
|
||||
try ctx.sendNotFound();
|
||||
@@ -2045,7 +2069,7 @@ pub const RequestContext = struct {
|
||||
ctx.url.pathWithoutAssetPrefix(ctx.bundler.options.routes.asset_prefix_path),
|
||||
ctx.url.extname,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
#include "root.h"
|
||||
#include <JavaScriptCore/SourceProvider.h>
|
||||
|
||||
#include <wtf/Lock.h>
|
||||
|
||||
namespace JSC {
|
||||
|
||||
// SourceProvider::SourceProvider(const SourceOrigin&, String&& sourceURL, const TextPosition& startPosition, SourceProviderSourceType) {
|
||||
|
||||
// }
|
||||
|
||||
|
||||
// SourceProvider::SourceProvider(const SourceOrigin& sourceOrigin, String&& sourceURL, const TextPosition& startPosition, SourceProviderSourceType sourceType)
|
||||
// : m_sourceType(sourceType)
|
||||
// , m_sourceOrigin(sourceOrigin)
|
||||
// , m_sourceURL(WTFMove(sourceURL))
|
||||
// , m_startPosition(startPosition)
|
||||
// {
|
||||
// }
|
||||
|
||||
// SourceProvider::~SourceProvider()
|
||||
// {
|
||||
// }
|
||||
|
||||
// static Lock providerIdLock;
|
||||
|
||||
// void SourceProvider::getID()
|
||||
// {
|
||||
// Locker locker { providerIdLock };
|
||||
// if (!m_id) {
|
||||
// static intptr_t nextProviderID = 0;
|
||||
// m_id = ++nextProviderID;
|
||||
// RELEASE_ASSERT(m_id);
|
||||
// }
|
||||
// }
|
||||
|
||||
} // namespace JSC
|
||||
|
||||
@@ -82,14 +82,16 @@ namespace JSCastingHelpers = JSC::JSCastingHelpers;
|
||||
|
||||
extern "C" JSC__JSGlobalObject *Zig__GlobalObject__create(JSClassRef *globalObjectClass, int count,
|
||||
void *console_client) {
|
||||
JSC::Options::useSourceProviderCache() = true;
|
||||
JSC::Options::useUnlinkedCodeBlockJettisoning() = false;
|
||||
JSC::Options::useTopLevelAwait() = true;
|
||||
JSC::Options::exposeInternalModuleLoader() = true;
|
||||
|
||||
std::set_terminate([]() { Zig__GlobalObject__onCrash(); });
|
||||
WTF::initializeMainThread();
|
||||
JSC::initialize();
|
||||
|
||||
// JSC::Options::useCodeCache() = false;
|
||||
JSC::Options::useSourceProviderCache() = true;
|
||||
JSC::Options::useUnlinkedCodeBlockJettisoning() = false;
|
||||
JSC::Options::useTopLevelAwait() = true;
|
||||
|
||||
JSC::VM &vm = JSC::VM::create(JSC::LargeHeap).leakRef();
|
||||
vm.heap.acquireAccess();
|
||||
@@ -288,8 +290,6 @@ extern "C" bool Zig__GlobalObject__resetModuleRegistryMap(JSC__JSGlobalObject *g
|
||||
obj->putDirect(globalObject->vm(), identifier,
|
||||
map->clone(globalObject, globalObject->vm(), globalObject->mapStructure()));
|
||||
|
||||
vm.codeCache()->write(vm);
|
||||
vm.shrinkFootprintWhenIdle();
|
||||
// vm.deleteAllLinkedCode(JSC::DeleteAllCodeEffort::DeleteAllCodeIfNotCollecting);
|
||||
// JSC::Heap::PreventCollectionScope(vm.heap);
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "ZigSourceProvider.h"
|
||||
#include "helpers.h"
|
||||
#include "root.h"
|
||||
#include <JavaScriptCore/BytecodeCacheError.h>
|
||||
#include <JavaScriptCore/CodeCache.h>
|
||||
|
||||
@@ -39,12 +40,8 @@ Ref<SourceProvider> SourceProvider::create(ResolvedSource resolvedSource) {
|
||||
JSC::SourceProviderSourceType::Module));
|
||||
|
||||
} else {
|
||||
Ref<WTF::ExternalStringImpl> stringImpl_ = WTF::ExternalStringImpl::create(
|
||||
resolvedSource.source_code.ptr, resolvedSource.source_code.len,
|
||||
[=](WTF::ExternalStringImpl *str, void *ptr, unsigned int len) {
|
||||
// ZigString__free((const unsigned char *)ptr, len,
|
||||
// allocator);
|
||||
});
|
||||
Ref<WTF::ExternalStringImpl> stringImpl_ = WTF::ExternalStringImpl::createStatic(
|
||||
resolvedSource.source_code.ptr, resolvedSource.source_code.len);
|
||||
return adoptRef(*new SourceProvider(
|
||||
resolvedSource, reinterpret_cast<WTF::StringImpl *>(stringImpl_.ptr()),
|
||||
JSC::SourceOrigin(WTF::URL::fileURLWithFileSystemPath(toString(resolvedSource.source_url))),
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace JSC {
|
||||
class Structure;
|
||||
class Identifier;
|
||||
class SourceCodeKey;
|
||||
|
||||
class SourceProvider;
|
||||
} // namespace JSC
|
||||
|
||||
#include "ZigConsoleClient.h"
|
||||
|
||||
@@ -1434,6 +1434,9 @@ const WTF__StringImpl *JSC__PropertyName__uid(JSC__PropertyName *arg0) { return
|
||||
|
||||
#pragma mark - JSC::VM
|
||||
|
||||
void JSC__VM__shrinkFootprint(JSC__VM *arg0) { arg0->shrinkFootprintWhenIdle(); };
|
||||
void JSC__VM__whenIdle(JSC__VM *arg0, void (*ArgFn1)()) { arg0->whenIdle(ArgFn1); };
|
||||
|
||||
JSC__JSLock *JSC__VM__apiLock(JSC__VM *arg0) { return makeRefPtr((*arg0).apiLock()).leakRef(); }
|
||||
JSC__VM *JSC__VM__create(unsigned char HeapType0) {
|
||||
JSC::VM *vm =
|
||||
|
||||
@@ -1555,6 +1555,21 @@ pub const VM = extern struct {
|
||||
return cppFn("deleteAllCode", .{ vm, global_object });
|
||||
}
|
||||
|
||||
pub fn whenIdle(
|
||||
vm: *VM,
|
||||
callback: fn (...) callconv(.C) void,
|
||||
) void {
|
||||
return cppFn("whenIdle", .{ vm, callback });
|
||||
}
|
||||
|
||||
pub fn shrinkFootprint(
|
||||
vm: *VM,
|
||||
) void {
|
||||
return cppFn("shrinkFootprint", .{
|
||||
vm,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn setExecutionForbidden(vm: *VM, forbidden: bool) void {
|
||||
cppFn("setExecutionForbidden", .{ vm, forbidden });
|
||||
}
|
||||
@@ -1597,7 +1612,7 @@ pub const VM = extern struct {
|
||||
});
|
||||
}
|
||||
|
||||
pub const Extern = [_][]const u8{ "deleteAllCode", "apiLock", "create", "deinit", "setExecutionForbidden", "executionForbidden", "isEntered", "throwError", "drainMicrotasks" };
|
||||
pub const Extern = [_][]const u8{ "deleteAllCode", "apiLock", "create", "deinit", "setExecutionForbidden", "executionForbidden", "isEntered", "throwError", "drainMicrotasks", "whenIdle", "shrinkFootprint" };
|
||||
};
|
||||
|
||||
pub const ThrowScope = extern struct {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//-- AUTOGENERATED FILE -- 1630718473
|
||||
//-- AUTOGENERATED FILE -- 1630806668
|
||||
// clang-format off
|
||||
#pragma once
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//-- AUTOGENERATED FILE -- 1630718473
|
||||
//-- AUTOGENERATED FILE -- 1630806668
|
||||
// clang-format: off
|
||||
#pragma once
|
||||
|
||||
@@ -493,7 +493,9 @@ CPP_DECL void JSC__VM__drainMicrotasks(JSC__VM* arg0);
|
||||
CPP_DECL bool JSC__VM__executionForbidden(JSC__VM* arg0);
|
||||
CPP_DECL bool JSC__VM__isEntered(JSC__VM* arg0);
|
||||
CPP_DECL void JSC__VM__setExecutionForbidden(JSC__VM* arg0, bool arg1);
|
||||
CPP_DECL void JSC__VM__shrinkFootprint(JSC__VM* arg0);
|
||||
CPP_DECL bool JSC__VM__throwError(JSC__VM* arg0, JSC__JSGlobalObject* arg1, JSC__ThrowScope* arg2, const unsigned char* arg3, size_t arg4);
|
||||
CPP_DECL void JSC__VM__whenIdle(JSC__VM* arg0, void (* ArgFn1)());
|
||||
|
||||
#pragma mark - JSC::ThrowScope
|
||||
|
||||
|
||||
@@ -307,7 +307,9 @@ pub extern fn JSC__VM__drainMicrotasks(arg0: [*c]JSC__VM) void;
|
||||
pub extern fn JSC__VM__executionForbidden(arg0: [*c]JSC__VM) bool;
|
||||
pub extern fn JSC__VM__isEntered(arg0: [*c]JSC__VM) bool;
|
||||
pub extern fn JSC__VM__setExecutionForbidden(arg0: [*c]JSC__VM, arg1: bool) void;
|
||||
pub extern fn JSC__VM__shrinkFootprint(arg0: [*c]JSC__VM) void;
|
||||
pub extern fn JSC__VM__throwError(arg0: [*c]JSC__VM, arg1: [*c]JSC__JSGlobalObject, arg2: [*c]JSC__ThrowScope, arg3: [*c]const u8, arg4: usize) bool;
|
||||
pub extern fn JSC__VM__whenIdle(arg0: [*c]JSC__VM, ArgFn1: ?fn (...) callconv(.C) void) void;
|
||||
pub extern fn JSC__ThrowScope__clearException(arg0: [*c]JSC__ThrowScope) void;
|
||||
pub extern fn JSC__ThrowScope__declare(arg0: [*c]JSC__VM, arg1: [*c]u8, arg2: [*c]u8, arg3: usize) bJSC__ThrowScope;
|
||||
pub extern fn JSC__ThrowScope__exception(arg0: [*c]JSC__ThrowScope) [*c]JSC__Exception;
|
||||
|
||||
@@ -211,9 +211,32 @@ fn JSONLikeParser(opts: js_lexer.JSONOptions) type {
|
||||
|
||||
const JSONParser = JSONLikeParser(js_lexer.JSONOptions{});
|
||||
const TSConfigParser = JSONLikeParser(js_lexer.JSONOptions{ .allow_comments = true, .allow_trailing_commas = true });
|
||||
var empty_string = E.String{ .utf8 = "" };
|
||||
var empty_object = E.Object{};
|
||||
var empty_array = E.Array{ .items = &[_]ExprNodeIndex{} };
|
||||
var empty_string_data = Expr.Data{ .e_string = &empty_string };
|
||||
var empty_object_data = Expr.Data{ .e_object = &empty_object };
|
||||
var empty_array_data = Expr.Data{ .e_array = &empty_array };
|
||||
|
||||
pub fn ParseJSON(source: *const logger.Source, log: *logger.Log, allocator: *std.mem.Allocator) !Expr {
|
||||
var parser = try JSONParser.init(allocator, source, log);
|
||||
switch (source.contents.len) {
|
||||
// This is to be consisntent with how disabled JS files are handled
|
||||
0 => {
|
||||
return Expr{ .loc = logger.Loc{ .start = 0 }, .data = empty_object_data };
|
||||
},
|
||||
// This is a fast pass I guess
|
||||
2 => {
|
||||
if (strings.eqlComptime(source.contents[0..1], "\"\"") or strings.eqlComptime(source.contents[0..1], "''")) {
|
||||
return Expr{ .loc = logger.Loc{ .start = 0 }, .data = empty_string_data };
|
||||
} else if (strings.eqlComptime(source.contents[0..1], "{}")) {
|
||||
return Expr{ .loc = logger.Loc{ .start = 0 }, .data = empty_object_data };
|
||||
} else if (strings.eqlComptime(source.contents[0..1], "[]")) {
|
||||
return Expr{ .loc = logger.Loc{ .start = 0 }, .data = empty_array_data };
|
||||
}
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
|
||||
return parser.parseExpr();
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
ed96593b8e099dd5
|
||||
913cb9780447be7d
|
||||
Reference in New Issue
Block a user