Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSS moar fixes #15719

Merged
merged 11 commits into from
Dec 12, 2024
6 changes: 3 additions & 3 deletions src/css/context.zig
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ pub const SupportsEntry = struct {
important_declarations: ArrayList(css.Property),

pub fn deinit(this: *@This(), allocator: std.mem.Allocator) void {
_ = this; // autofix
_ = allocator; // autofix
@panic(css.todo_stuff.depth);
this.condition.deinit(allocator);
css.deepDeinit(css.Property, allocator, &this.declarations);
css.deepDeinit(css.Property, allocator, &this.important_declarations);
}
};

Expand Down
99 changes: 88 additions & 11 deletions src/css/css_modules.zig
Original file line number Diff line number Diff line change
Expand Up @@ -70,17 +70,71 @@ pub const CssModule = struct {
// TODO: deinit
}

pub fn getReference(this: *CssModule, allocator: Allocator, name: []const u8, source_index: u32) void {
const gop = this.exports_by_source_index.items[source_index].getOrPut(allocator, name) catch bun.outOfMemory();
if (gop.found_existing) {
gop.value_ptr.is_referenced = true;
} else {
gop.value_ptr.* = CssModuleExport{
.name = this.config.pattern.writeToString(allocator, .{}, this.hashes.items[source_index], this.sources.items[source_index], name),
.composes = .{},
.is_referenced = true,
};
}
}

pub fn referenceDashed(
this: *CssModule,
allocator: std.mem.Allocator,
name: []const u8,
from: *const ?css.css_properties.css_modules.Specifier,
source_index: u32,
) ?[]const u8 {
_ = this; // autofix
_ = name; // autofix
_ = from; // autofix
_ = source_index; // autofix
@panic(css.todo_stuff.depth);
const reference, const key = if (from.*) |specifier| switch (specifier) {
.global => return name[2..],
.file => |file| .{
CssModuleReference{ .dependency = .{ .name = name[2..], .specifier = file } },
file,
},
.source_index => |dep_source_index| return this.config.pattern.writeToString(
allocator,
.{},
this.hashes.items[dep_source_index],
this.sources.items[dep_source_index],
name[2..],
),
} else {
// Local export. Mark as used.
const gop = this.exports_by_source_index.items[source_index].getOrPut(allocator, name) catch bun.outOfMemory();
if (gop.found_existing) {
gop.value_ptr.is_referenced = true;
} else {
var res = ArrayList(u8){};
res.appendSlice(allocator, "--") catch bun.outOfMemory();
gop.value_ptr.* = CssModuleExport{
.name = this.config.pattern.writeToString(
allocator,
res,
this.hashes.items[source_index],
this.sources.items[source_index],
name[2..],
),
.composes = .{},
.is_referenced = true,
};
}
return null;
};

const the_hash = hash(allocator, "{s}_{s}_{s}", .{ this.hashes.items[source_index], name, key }, false);

this.references.put(
allocator,
std.fmt.allocPrint(allocator, "--{s}", .{the_hash}) catch bun.outOfMemory(),
reference,
) catch bun.outOfMemory();

return the_hash;
}

pub fn handleComposes(
Expand Down Expand Up @@ -397,10 +451,33 @@ pub const CssModuleReference = union(enum) {

// TODO: replace with bun's hash
pub fn hash(allocator: Allocator, comptime fmt: []const u8, args: anytype, at_start: bool) []const u8 {
_ = fmt; // autofix
_ = args; // autofix
_ = allocator; // autofix
_ = at_start; // autofix
// @compileError(css.todo_stuff.depth);
@panic(css.todo_stuff.depth);
const count = std.fmt.count(fmt, args);
var stack_fallback = std.heap.stackFallback(128, allocator);
const fmt_alloc = if (count <= 128) stack_fallback.get() else allocator;
var hasher = bun.Wyhash11.init(0);
var fmt_str = std.fmt.allocPrint(fmt_alloc, fmt, args) catch bun.outOfMemory();
hasher.update(fmt_str);

const h: u32 = @truncate(hasher.final());
var h_bytes: [4]u8 = undefined;
std.mem.writeInt(u32, &h_bytes, h, .little);

const encode_len = bun.base64.encodeLen(h_bytes[0..]);

var slice_to_write = if (encode_len <= 128 - @as(usize, @intFromBool(at_start)))
allocator.alloc(u8, encode_len + @as(usize, @intFromBool(at_start))) catch bun.outOfMemory()
else
fmt_str[0..];

const base64_encoded_hash_len = bun.base64.encode(slice_to_write, &h_bytes);

const base64_encoded_hash = slice_to_write[0..base64_encoded_hash_len];

if (at_start and base64_encoded_hash.len > 0 and base64_encoded_hash[0] >= '0' and base64_encoded_hash[0] <= '9') {
std.mem.copyBackwards(u8, slice_to_write[1..][0..base64_encoded_hash_len], base64_encoded_hash);
slice_to_write[0] = '_';
return slice_to_write[0 .. base64_encoded_hash_len + 1];
}

return base64_encoded_hash;
}
41 changes: 26 additions & 15 deletions src/css/css_parser.zig
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ pub fn DefineShorthand(comptime T: type, comptime property_name: PropertyIdTag)
// }

// return null;
@panic(todo_stuff.depth);
@compileError(todo_stuff.depth);
}

/// Returns a shorthand from the longhand properties defined in the given declaration block.
Expand All @@ -405,7 +405,7 @@ pub fn DefineShorthand(comptime T: type, comptime property_name: PropertyIdTag)
// };
// return out;

@panic(todo_stuff.depth);
@compileError(todo_stuff.depth);
}

/// Returns a longhand property for this shorthand.
Expand All @@ -430,7 +430,7 @@ pub fn DefineShorthand(comptime T: type, comptime property_name: PropertyIdTag)
// }
// }
// return null;
@panic(todo_stuff.depth);
@compileError(todo_stuff.depth);
}

/// Updates this shorthand from a longhand property.
Expand All @@ -451,7 +451,7 @@ pub fn DefineShorthand(comptime T: type, comptime property_name: PropertyIdTag)
// }
// }
// return false;
@panic(todo_stuff.depth);
@compileError(todo_stuff.depth);
}
};
}
Expand Down Expand Up @@ -916,26 +916,22 @@ pub fn DeriveValueType(comptime T: type) type {
}

fn consume_until_end_of_block(block_type: BlockType, tokenizer: *Tokenizer) void {
const StackCount = 16;
var sfb = std.heap.stackFallback(@sizeOf(BlockType) * StackCount, tokenizer.allocator);
const alloc = sfb.get();
var stack = std.ArrayList(BlockType).initCapacity(alloc, StackCount) catch unreachable;
defer stack.deinit();

@setCold(true);
var stack = SmallList(BlockType, 16){};
stack.appendAssumeCapacity(block_type);

while (switch (tokenizer.next()) {
.result => |v| v,
.err => null,
}) |tok| {
if (BlockType.closing(&tok)) |b| {
if (stack.getLast() == b) {
if (stack.getLastUnchecked() == b) {
_ = stack.pop();
if (stack.items.len == 0) return;
if (stack.len() == 0) return;
}
}

if (BlockType.opening(&tok)) |bt| stack.append(bt) catch unreachable;
if (BlockType.opening(&tok)) |bt| stack.append(tokenizer.allocator, bt);
}
}

Expand Down Expand Up @@ -4200,8 +4196,6 @@ const Tokenizer = struct {
.position = 0,
};

// make current point to the first token
_ = lexer.next();
lexer.position = 0;

return lexer;
Expand Down Expand Up @@ -6253,6 +6247,22 @@ pub const serializer = struct {
};
} else notation: {
var buf: [129]u8 = undefined;
// We must pass finite numbers to dtoa_short
if (std.math.isPositiveInf(value)) {
const output = "1e999";
@memcpy(buf[0..output.len], output);
try writer.writeAll(buf[0..output.len]);
zackradisic marked this conversation as resolved.
Show resolved Hide resolved
return;
} else if (std.math.isNegativeInf(value)) {
const output = "-1e999";
@memcpy(buf[0..output.len], output);
try writer.writeAll(buf[0..output.len]);
zackradisic marked this conversation as resolved.
Show resolved Hide resolved
return;
}
// We shouldn't receive NaN here.
// NaN is not a valid CSS token and any inlined calculations from `calc()` we ensure
// are not NaN.
bun.debugAssert(!std.math.isNan(value));
const str, const notation = dtoa_short(&buf, value, 6);
try writer.writeAll(str);
break :notation notation;
Expand Down Expand Up @@ -6691,6 +6701,7 @@ const Notation = struct {

pub fn dtoa_short(buf: *[129]u8, value: f32, comptime precision: u8) struct { []u8, Notation } {
buf[0] = '0';
bun.debugAssert(std.math.isFinite(value));
const buf_len = bun.fmt.FormatDouble.dtoa(@ptrCast(buf[1..].ptr), @floatCast(value)).len;
return restrict_prec(buf[0 .. buf_len + 1], precision);
}
Expand Down
41 changes: 38 additions & 3 deletions src/css/properties/animation.zig
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,44 @@ pub const AnimationName = union(enum) {
}

pub fn toCss(this: *const This, comptime W: type, dest: *Printer(W)) PrintErr!void {
_ = this; // autofix
_ = dest; // autofix
@panic(css.todo_stuff.depth);
const css_module_animation_enabled = if (dest.css_module) |css_module|
css_module.config.animation
else
false;

switch (this.*) {
.none => return dest.writeStr("none"),
.ident => |s| {
if (css_module_animation_enabled) {
if (dest.css_module) |*css_module| {
css_module.getReference(dest.allocator, s.v, dest.loc.source_index);
}
}
return s.toCssWithOptions(W, dest, css_module_animation_enabled);
},
.string => |s| {
if (css_module_animation_enabled) {
if (dest.css_module) |*css_module| {
css_module.getReference(dest.allocator, s, dest.loc.source_index);
}
}

// CSS-wide keywords and `none` cannot remove quotes
if (bun.strings.eqlCaseInsensitiveASCIIICheckLength(s, "none") or
bun.strings.eqlCaseInsensitiveASCIIICheckLength(s, "initial") or
bun.strings.eqlCaseInsensitiveASCIIICheckLength(s, "inherit") or
bun.strings.eqlCaseInsensitiveASCIIICheckLength(s, "unset") or
bun.strings.eqlCaseInsensitiveASCIIICheckLength(s, "default") or
bun.strings.eqlCaseInsensitiveASCIIICheckLength(s, "revert") or
bun.strings.eqlCaseInsensitiveASCIIICheckLength(s, "revert-layer"))
{
css.serializer.serializeString(s, dest) catch return dest.addFmtError();
return;
}

return dest.writeIdent(s, css_module_animation_enabled);
},
}
}
};

Expand Down
27 changes: 25 additions & 2 deletions src/css/properties/css_modules.zig
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,20 @@ pub const Composes = struct {
loc: Location,

pub fn parse(input: *css.Parser) css.Result(Composes) {
_ = input; // autofix
@panic(css.todo_stuff.depth);
const loc = input.currentSourceLocation();
var names: CustomIdentList = .{};
while (input.tryParse(parseOneIdent, .{}).asValue()) |name| {
names.append(input.allocator(), name);
}

if (names.len() == 0) return .{ .err = input.newCustomError(css.ParserError{ .invalid_declaration = {} }) };

const from = if (input.tryParse(css.Parser.expectIdentMatching, .{"from"}).isOk()) switch (Specifier.parse(input)) {
.result => |v| v,
.err => |e| return .{ .err = e },
} else null;

return .{ .result = Composes{ .names = names, .from = from, .loc = Location.fromSourceLocation(loc) } };
}

pub fn toCss(this: *const @This(), comptime W: type, dest: *Printer(W)) PrintErr!void {
Expand All @@ -61,6 +73,17 @@ pub const Composes = struct {
}
}

fn parseOneIdent(input: *css.Parser) css.Result(CustomIdent) {
const name: CustomIdent = switch (CustomIdent.parse(input)) {
.result => |v| v,
.err => |e| return .{ .err = e },
};

if (bun.strings.eqlCaseInsensitiveASCII(name.v, "from", true)) return .{ .err = input.newErrorForNextToken() };

return .{ .result = name };
}

pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() {
return css.implementDeepClone(@This(), this, allocator);
}
Expand Down
39 changes: 31 additions & 8 deletions src/css/properties/font.zig
Original file line number Diff line number Diff line change
Expand Up @@ -160,17 +160,25 @@ pub const FontStretch = union(enum) {
percentage: Percentage,

// TODO: implement this
// pub usingnamespace css.DeriveParse(@This());
pub usingnamespace css.DeriveParse(@This());

pub fn toCss(this: *const FontStretch, comptime W: type, dest: *css.Printer(W)) css.PrintErr!void {
if (dest.minify) {
const percentage: Percentage = this.intoPercentage();
return percentage.toCss(W, dest);
}

pub fn parse(input: *css.Parser) css.Result(FontStretch) {
_ = input; // autofix
@panic(css.todo_stuff.depth);
return switch (this.*) {
.percentage => |*val| val.toCss(W, dest),
.keyword => |*kw| kw.toCss(W, dest),
};
}

pub fn toCss(this: *const FontStretch, comptime W: type, dest: *css.Printer(W)) css.PrintErr!void {
_ = this; // autofix
_ = dest; // autofix
@panic(css.todo_stuff.depth);
pub fn intoPercentage(this: *const FontStretch) Percentage {
return switch (this.*) {
.percentage => |*val| val.*,
.keyword => |*kw| kw.intoPercentage(),
};
}

pub fn eql(lhs: *const FontStretch, rhs: *const FontStretch) bool {
Expand Down Expand Up @@ -215,6 +223,21 @@ pub const FontStretchKeyword = enum {
pub inline fn default() FontStretchKeyword {
return .normal;
}

pub fn intoPercentage(this: *const FontStretchKeyword) Percentage {
const val: f32 = switch (this.*) {
.@"ultra-condensed" => 0.5,
.@"extra-condensed" => 0.625,
.condensed => 0.75,
.@"semi-condensed" => 0.875,
.normal => 1.0,
.@"semi-expanded" => 1.125,
.expanded => 1.25,
.@"extra-expanded" => 1.5,
.@"ultra-expanded" => 2.0,
};
return .{ .v = val };
}
};

/// A value for the [font-family](https://www.w3.org/TR/css-fonts-4/#font-family-prop) property.
Expand Down
Loading
Loading