mirror of
https://github.com/oven-sh/bun
synced 2026-02-05 08:28:55 +00:00
Compare commits
4 Commits
dylan/pyth
...
don/fix/la
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9676f8b922 | ||
|
|
d1da677eff | ||
|
|
8455414042 | ||
|
|
3ed8518a91 |
@@ -3343,7 +3343,7 @@ noinline fn assertionFailureAtLocation(src: std.builtin.SourceLocation) noreturn
|
||||
@compileError(std.fmt.comptimePrint("assertion failure"));
|
||||
} else {
|
||||
@branchHint(.cold);
|
||||
Output.panic(assertion_failure_msg ++ "at {s}:{d}:{d}", .{ src.file, src.line, src.column });
|
||||
Output.panic(assertion_failure_msg ++ " at {s}:{d}:{d}", .{ src.file, src.line, src.column });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -970,7 +970,8 @@ pub const PackageManifest = struct {
|
||||
// - v0.0.3: added serialization of registry url. it's used to invalidate when it changes
|
||||
// - v0.0.4: fixed bug with cpu & os tag not being added correctly
|
||||
// - v0.0.5: added bundled dependencies
|
||||
pub const version = "bun-npm-manifest-cache-v0.0.5\n";
|
||||
// - v0.0.6: change patch from u32 to u64 to support date-formatted patch versions
|
||||
pub const version = "bun-npm-manifest-cache-v0.0.6\n";
|
||||
const header_bytes: string = "#!/usr/bin/env bun\n" ++ version;
|
||||
|
||||
pub const sizes = blk: {
|
||||
@@ -1580,7 +1581,7 @@ pub const PackageManifest = struct {
|
||||
}
|
||||
}
|
||||
|
||||
var result: PackageManifest = bun.serializable(PackageManifest{});
|
||||
var manifest: PackageManifest = bun.serializable(PackageManifest{});
|
||||
|
||||
var string_pool = String.Builder.StringPool.init(default_allocator);
|
||||
defer string_pool.deinit();
|
||||
@@ -1831,7 +1832,7 @@ pub const PackageManifest = struct {
|
||||
|
||||
// Using `expected_name` instead of the name from the manifest. Custom registries might
|
||||
// have a different name than the dependency name in package.json.
|
||||
result.pkg.name = string_builder.append(ExternalString, expected_name);
|
||||
manifest.pkg.name = string_builder.append(ExternalString, expected_name);
|
||||
|
||||
get_versions: {
|
||||
if (json.asProperty("versions")) |versions_q| {
|
||||
@@ -2291,14 +2292,14 @@ pub const PackageManifest = struct {
|
||||
}
|
||||
}
|
||||
|
||||
result.pkg.dist_tags = DistTagMap{
|
||||
manifest.pkg.dist_tags = DistTagMap{
|
||||
.tags = ExternalStringList.init(all_extern_strings, extern_strings_slice[0..dist_tag_i]),
|
||||
.versions = VersionSlice.init(all_semver_versions, dist_tag_versions[0..dist_tag_i]),
|
||||
};
|
||||
|
||||
if (comptime Environment.allow_assert) {
|
||||
bun.assertWithLocation(std.meta.eql(result.pkg.dist_tags.versions.get(all_semver_versions), dist_tag_versions[0..dist_tag_i]), @src());
|
||||
bun.assertWithLocation(std.meta.eql(result.pkg.dist_tags.tags.get(all_extern_strings), extern_strings_slice[0..dist_tag_i]), @src());
|
||||
bun.assertWithLocation(std.meta.eql(manifest.pkg.dist_tags.versions.get(all_semver_versions), dist_tag_versions[0..dist_tag_i]), @src());
|
||||
bun.assertWithLocation(std.meta.eql(manifest.pkg.dist_tags.tags.get(all_extern_strings), extern_strings_slice[0..dist_tag_i]), @src());
|
||||
}
|
||||
|
||||
extern_strings = extern_strings[dist_tag_i..];
|
||||
@@ -2306,24 +2307,24 @@ pub const PackageManifest = struct {
|
||||
}
|
||||
|
||||
if (last_modified.len > 0) {
|
||||
result.pkg.last_modified = string_builder.append(String, last_modified);
|
||||
manifest.pkg.last_modified = string_builder.append(String, last_modified);
|
||||
}
|
||||
|
||||
if (etag.len > 0) {
|
||||
result.pkg.etag = string_builder.append(String, etag);
|
||||
manifest.pkg.etag = string_builder.append(String, etag);
|
||||
}
|
||||
|
||||
if (json.asProperty("modified")) |name_q| {
|
||||
const field = name_q.expr.asString(allocator) orelse return null;
|
||||
|
||||
result.pkg.modified = string_builder.append(String, field);
|
||||
manifest.pkg.modified = string_builder.append(String, field);
|
||||
}
|
||||
|
||||
result.pkg.releases.keys = VersionSlice.init(all_semver_versions, all_release_versions);
|
||||
result.pkg.releases.values = PackageVersionList.init(versioned_packages, all_versioned_package_releases);
|
||||
manifest.pkg.releases.keys = VersionSlice.init(all_semver_versions, all_release_versions);
|
||||
manifest.pkg.releases.values = PackageVersionList.init(versioned_packages, all_versioned_package_releases);
|
||||
|
||||
result.pkg.prereleases.keys = VersionSlice.init(all_semver_versions, all_prerelease_versions);
|
||||
result.pkg.prereleases.values = PackageVersionList.init(versioned_packages, all_versioned_package_prereleases);
|
||||
manifest.pkg.prereleases.keys = VersionSlice.init(all_semver_versions, all_prerelease_versions);
|
||||
manifest.pkg.prereleases.values = PackageVersionList.init(versioned_packages, all_versioned_package_prereleases);
|
||||
|
||||
const max_versions_count = @max(all_release_versions.len, all_prerelease_versions.len);
|
||||
|
||||
@@ -2364,7 +2365,7 @@ pub const PackageManifest = struct {
|
||||
|
||||
var all_indices = try bun.default_allocator.alloc(Int, max_versions_count);
|
||||
defer bun.default_allocator.free(all_indices);
|
||||
const releases_list = .{ &result.pkg.releases, &result.pkg.prereleases };
|
||||
const releases_list = .{ &manifest.pkg.releases, &manifest.pkg.prereleases };
|
||||
|
||||
var all_cloned_versions = try bun.default_allocator.alloc(Semver.Version, max_versions_count);
|
||||
defer bun.default_allocator.free(all_cloned_versions);
|
||||
@@ -2373,7 +2374,7 @@ pub const PackageManifest = struct {
|
||||
defer bun.default_allocator.free(all_cloned_packages);
|
||||
|
||||
inline for (0..2) |release_i| {
|
||||
var release = releases_list[release_i];
|
||||
var release: *ExternVersionMap = releases_list[release_i];
|
||||
const indices = all_indices[0..release.keys.len];
|
||||
const cloned_packages = all_cloned_packages[0..release.keys.len];
|
||||
const cloned_versions = all_cloned_versions[0..release.keys.len];
|
||||
@@ -2428,25 +2429,25 @@ pub const PackageManifest = struct {
|
||||
all_extern_strings = all_extern_strings[0 .. all_extern_strings.len - extern_strings.len];
|
||||
}
|
||||
|
||||
result.pkg.string_lists_buf.off = 0;
|
||||
result.pkg.string_lists_buf.len = @as(u32, @truncate(all_extern_strings.len));
|
||||
manifest.pkg.string_lists_buf.off = 0;
|
||||
manifest.pkg.string_lists_buf.len = @as(u32, @truncate(all_extern_strings.len));
|
||||
|
||||
result.pkg.versions_buf.off = 0;
|
||||
result.pkg.versions_buf.len = @as(u32, @truncate(all_semver_versions.len));
|
||||
manifest.pkg.versions_buf.off = 0;
|
||||
manifest.pkg.versions_buf.len = @as(u32, @truncate(all_semver_versions.len));
|
||||
|
||||
result.versions = all_semver_versions;
|
||||
result.external_strings = all_extern_strings;
|
||||
result.external_strings_for_versions = version_extern_strings;
|
||||
result.package_versions = versioned_packages;
|
||||
result.extern_strings_bin_entries = all_extern_strings_bin_entries[0 .. all_extern_strings_bin_entries.len - extern_strings_bin_entries.len];
|
||||
result.bundled_deps_buf = bundled_deps_buf;
|
||||
result.pkg.public_max_age = public_max_age;
|
||||
manifest.versions = all_semver_versions;
|
||||
manifest.external_strings = all_extern_strings;
|
||||
manifest.external_strings_for_versions = version_extern_strings;
|
||||
manifest.package_versions = versioned_packages;
|
||||
manifest.extern_strings_bin_entries = all_extern_strings_bin_entries[0 .. all_extern_strings_bin_entries.len - extern_strings_bin_entries.len];
|
||||
manifest.bundled_deps_buf = bundled_deps_buf;
|
||||
manifest.pkg.public_max_age = public_max_age;
|
||||
|
||||
if (string_builder.ptr) |ptr| {
|
||||
result.string_buf = ptr[0..string_builder.len];
|
||||
manifest.string_buf = ptr[0..string_builder.len];
|
||||
}
|
||||
|
||||
return result;
|
||||
return manifest;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -91,6 +91,7 @@ fn runTests() u8 {
|
||||
const tests: []const TestFn = builtin.test_functions;
|
||||
for (tests) |t| {
|
||||
std.testing.allocator_instance = .{};
|
||||
defer Output.flush();
|
||||
|
||||
var did_lock = true;
|
||||
stderr.lock(.exclusive) catch {
|
||||
|
||||
@@ -12,11 +12,11 @@ pub const ExternalString = extern struct {
|
||||
return lhs.value.order(&rhs.value, lhs_buf, rhs_buf);
|
||||
}
|
||||
|
||||
/// ExternalString but without the hash
|
||||
/// Create an `ExternalString`, calculating its hash.
|
||||
pub inline fn from(in: string) ExternalString {
|
||||
return ExternalString{
|
||||
.value = String.init(in, in),
|
||||
.hash = bun.Wyhash.hash(0, in),
|
||||
.hash = String.Builder.stringHash(in),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,10 @@ pub inline fn init(buf: string, slice: string) SlicedString {
|
||||
return SlicedString{ .buf = buf, .slice = slice };
|
||||
}
|
||||
|
||||
pub inline fn from(slice: string) SlicedString {
|
||||
return .{ .buf = slice, .slice = slice };
|
||||
}
|
||||
|
||||
pub inline fn external(this: SlicedString) ExternalString {
|
||||
if (comptime Environment.allow_assert) {
|
||||
assert(@intFromPtr(this.buf.ptr) <= @intFromPtr(this.slice.ptr) and ((@intFromPtr(this.slice.ptr) + this.slice.len) <= (@intFromPtr(this.buf.ptr) + this.buf.len)));
|
||||
|
||||
@@ -1,8 +1,33 @@
|
||||
const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
const bun = @import("root").bun;
|
||||
const string = bun.string;
|
||||
const Output = bun.Output;
|
||||
const Global = bun.Global;
|
||||
const Environment = bun.Environment;
|
||||
const strings = bun.strings;
|
||||
const MutableString = bun.MutableString;
|
||||
const stringZ = bun.stringZ;
|
||||
const default_allocator = bun.default_allocator;
|
||||
const C = bun.C;
|
||||
const JSC = bun.JSC;
|
||||
const IdentityContext = @import("../identity_context.zig").IdentityContext;
|
||||
const OOM = bun.OOM;
|
||||
const TruncatedPackageNameHash = bun.install.TruncatedPackageNameHash;
|
||||
const Lockfile = bun.install.Lockfile;
|
||||
const ExternalString = bun.Semver.ExternalString;
|
||||
const SlicedString = bun.Semver.SlicedString;
|
||||
const String = bun.Semver.String;
|
||||
|
||||
const Query = bun.Semver.Query;
|
||||
const assert = bun.assert;
|
||||
|
||||
pub const Version = extern struct {
|
||||
major: u32 = 0,
|
||||
minor: u32 = 0,
|
||||
patch: u32 = 0,
|
||||
_tag_padding: [4]u8 = .{0} ** 4, // [see padding_checker.zig]
|
||||
/// Some packages use the current date, e.g. `20241225` to make the patch number unique. Some
|
||||
/// dates are large enough to overflow a u32.
|
||||
patch: u64 = 0,
|
||||
tag: Tag = .{},
|
||||
|
||||
/// Assumes that there is only one buffer for all the strings
|
||||
@@ -221,7 +246,7 @@ pub const Version = extern struct {
|
||||
pub const Partial = struct {
|
||||
major: ?u32 = null,
|
||||
minor: ?u32 = null,
|
||||
patch: ?u32 = null,
|
||||
patch: ?u64 = null,
|
||||
tag: Tag = .{},
|
||||
|
||||
pub fn min(this: Partial) Version {
|
||||
@@ -241,6 +266,27 @@ pub const Version = extern struct {
|
||||
.tag = this.tag,
|
||||
};
|
||||
}
|
||||
|
||||
pub const PartialFormatter = struct {
|
||||
version: Partial,
|
||||
input: string,
|
||||
|
||||
pub fn format(formatter: PartialFormatter, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
|
||||
const self = formatter.version;
|
||||
try std.fmt.format(writer, "{?d}.{?d}.{?d}", .{ self.major orelse 0, self.minor orelse 0, self.patch orelse 0 });
|
||||
|
||||
if (self.tag.hasPre()) {
|
||||
const pre = self.tag.pre.slice(formatter.input);
|
||||
try writer.writeAll("-");
|
||||
try writer.writeAll(pre);
|
||||
}
|
||||
if (self.tag.hasBuild()) {
|
||||
const build = self.tag.build.slice(formatter.input);
|
||||
try writer.writeAll("+");
|
||||
try writer.writeAll(build);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const Hashable = extern struct {
|
||||
@@ -815,15 +861,15 @@ pub const Version = extern struct {
|
||||
|
||||
switch (part_i) {
|
||||
0 => {
|
||||
result.version.major = parseVersionNumber(input[part_start_i..last_char_i]);
|
||||
result.version.major = parseVersionNumber(u32, input[part_start_i..last_char_i]);
|
||||
part_i = 1;
|
||||
},
|
||||
1 => {
|
||||
result.version.minor = parseVersionNumber(input[part_start_i..last_char_i]);
|
||||
result.version.minor = parseVersionNumber(u32, input[part_start_i..last_char_i]);
|
||||
part_i = 2;
|
||||
},
|
||||
2 => {
|
||||
result.version.patch = parseVersionNumber(input[part_start_i..last_char_i]);
|
||||
result.version.patch = parseVersionNumber(u64, input[part_start_i..last_char_i]);
|
||||
part_i = 3;
|
||||
},
|
||||
else => {},
|
||||
@@ -945,9 +991,14 @@ pub const Version = extern struct {
|
||||
return result;
|
||||
}
|
||||
|
||||
fn parseVersionNumber(input: string) ?u32 {
|
||||
// max decimal u32 is 4294967295
|
||||
var bytes: [10]u8 = undefined;
|
||||
fn parseVersionNumber(T: type, input: string) ?T {
|
||||
// max decimal u32 is 4294967295. Max decimal u64 is 18446744073709551615
|
||||
const buflen = switch (T) {
|
||||
u32 => 10,
|
||||
u64 => 20,
|
||||
else => @compileError("parseVersionNumber only supports u32 and u64"),
|
||||
};
|
||||
var bytes: [buflen]u8 = undefined;
|
||||
var byte_i: u8 = 0;
|
||||
|
||||
assert(input[0] != '.');
|
||||
@@ -970,41 +1021,96 @@ pub const Version = extern struct {
|
||||
// If there are no numbers
|
||||
if (byte_i == 0) return null;
|
||||
|
||||
if (comptime Environment.isDebug) {
|
||||
return std.fmt.parseInt(u32, bytes[0..byte_i], 10) catch |err| {
|
||||
return std.fmt.parseInt(T, bytes[0..byte_i], 10) catch |err| {
|
||||
if (comptime Environment.isDebug) {
|
||||
Output.prettyErrorln("ERROR {s} parsing version: \"{s}\", bytes: {s}", .{
|
||||
@errorName(err),
|
||||
input,
|
||||
bytes[0..byte_i],
|
||||
});
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
return std.fmt.parseInt(u32, bytes[0..byte_i], 10) catch 0;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
const bun = @import("root").bun;
|
||||
const string = bun.string;
|
||||
const Output = bun.Output;
|
||||
const Global = bun.Global;
|
||||
const Environment = bun.Environment;
|
||||
const strings = bun.strings;
|
||||
const MutableString = bun.MutableString;
|
||||
const stringZ = bun.stringZ;
|
||||
const default_allocator = bun.default_allocator;
|
||||
const C = bun.C;
|
||||
const JSC = bun.JSC;
|
||||
const IdentityContext = @import("../identity_context.zig").IdentityContext;
|
||||
const OOM = bun.OOM;
|
||||
const TruncatedPackageNameHash = bun.install.TruncatedPackageNameHash;
|
||||
const Lockfile = bun.install.Lockfile;
|
||||
const ExternalString = bun.Semver.ExternalString;
|
||||
const SlicedString = bun.Semver.SlicedString;
|
||||
const String = bun.Semver.String;
|
||||
const t = std.testing;
|
||||
const expect = t.expect;
|
||||
const expectEqual = t.expectEqual;
|
||||
const expectEqualStrings = t.expectEqualStrings;
|
||||
|
||||
const Query = bun.Semver.Query;
|
||||
const assert = bun.assert;
|
||||
test "Version.parse simple cases" {
|
||||
const TestCase = struct { []const u8, Version.Partial };
|
||||
const cases = &[_]TestCase{
|
||||
.{ "1.0.0", .{ .major = 1, .minor = 0, .patch = 0 } },
|
||||
.{ "2", .{ .major = 2 } },
|
||||
.{ "0.1", .{ .major = 0, .minor = 1 } },
|
||||
.{
|
||||
"0.0.202410031711", // date-formatted patches could cause u32 overflows
|
||||
.{ .major = 0, .minor = 0, .patch = 202410031711 },
|
||||
},
|
||||
.{
|
||||
"1.0.0-alpha",
|
||||
.{ .major = 1, .minor = 0, .patch = 0, .tag = Version.Tag{ .pre = .from("alpha") } },
|
||||
},
|
||||
.{
|
||||
"1.0.0+build",
|
||||
.{ .major = 1, .minor = 0, .patch = 0, .tag = Version.Tag{ .build = .from("build") } },
|
||||
},
|
||||
.{
|
||||
"0.5.0-foo+bar",
|
||||
.{ .major = 0, .minor = 5, .patch = 0, .tag = Version.Tag{
|
||||
.pre = .from("foo"),
|
||||
.build = .from("bar"),
|
||||
} },
|
||||
},
|
||||
};
|
||||
|
||||
for (cases) |test_case| {
|
||||
const src, const expected = test_case;
|
||||
const parsed = Version.parseUTF8(src);
|
||||
expect(parsed.valid) catch |e| {
|
||||
bun.Output.printErrorln("'{s}' produced an invalid Version.", .{src});
|
||||
return e;
|
||||
};
|
||||
expectEqual(expected, parsed.version) catch |err| {
|
||||
bun.Output.printErrorln(
|
||||
\\Parsed '{s}' into unexpected version.
|
||||
\\Expected: {any}
|
||||
\\Received: {}
|
||||
\\ Raw: {any}
|
||||
,
|
||||
.{
|
||||
src,
|
||||
expected,
|
||||
parsed.version.fmt(src),
|
||||
parsed.version,
|
||||
},
|
||||
);
|
||||
return err;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
test "Version.parse with large pre/build parts" {
|
||||
{
|
||||
const src = "0.0.0-202410031711";
|
||||
const version = Version.parseUTF8(src).version;
|
||||
|
||||
try expectEqual(version.major, 0);
|
||||
try expectEqual(version.minor, 0);
|
||||
try expectEqual(version.patch, 0);
|
||||
try expect(version.tag.hasPre());
|
||||
try expectEqualStrings(version.tag.pre.slice(src), "202410031711");
|
||||
try expect(!version.tag.hasBuild());
|
||||
}
|
||||
{
|
||||
const src = "0.0.0-some.pre.tag.thing+some.build.ID.thatislong";
|
||||
const version = Version.parseUTF8(src).version;
|
||||
|
||||
try expect(version.tag.hasPre());
|
||||
try expectEqualStrings(version.tag.pre.slice(src), "some.pre.tag.thing");
|
||||
try expect(version.tag.hasBuild());
|
||||
try expectEqualStrings(version.tag.build.slice(src), "some.build.ID.thatislong");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ const t = std.testing;
|
||||
test {
|
||||
_ = @import("shell/braces.zig");
|
||||
_ = @import("bun.js/node/assert/myers_diff.zig");
|
||||
_ = @import("semver/Version.zig");
|
||||
}
|
||||
|
||||
test "basic string usage" {
|
||||
|
||||
Reference in New Issue
Block a user