Compare commits

...

19 Commits

Author SHA1 Message Date
Don Isaac
b4950b15a2 Merge branch 'main' of https://github.com/oven-sh/bun into don/test/toml 2025-03-06 16:56:41 -08:00
Don Isaac
31ecf12b5b sort files alphabetically 2025-03-06 16:56:39 -08:00
Don Isaac
cdb46b9a28 update tesets 2025-03-05 20:14:23 -08:00
Don Isaac
9b39881b0f undo sni changes 2025-03-05 20:09:58 -08:00
Don Isaac
81ee014d04 '-' is a valid key 2025-03-05 20:09:04 -08:00
Don Isaac
46704a9b32 cleanup 2025-03-05 19:57:39 -08:00
Don Isaac
eab6c52588 re-generate snapshot 2025-03-05 18:44:02 -08:00
Don Isaac
daf3528c38 fix pct logic 2025-03-05 18:42:14 -08:00
Don Isaac
40c227f227 Merge branch 'main' into don/test/toml 2025-03-05 16:47:39 -08:00
DonIsaac
a633380e96 bun run clang-format 2025-03-06 00:43:43 +00:00
DonIsaac
9b463b4ae3 bun run zig-format 2025-03-06 00:43:21 +00:00
Don Isaac
1ce94ad9ad fix string-encoded index keys 2025-03-05 16:42:18 -08:00
Don Isaac
c1b15c6f54 Merge branch 'main' of https://github.com/oven-sh/bun into don/test/toml 2025-03-05 15:39:03 -08:00
Don Isaac
f6038498b0 read files as utf8 2025-03-05 14:22:01 -08:00
Don Isaac
db02d23b72 Merge branch 'main' of https://github.com/oven-sh/bun into don/test/toml 2025-03-05 14:19:47 -08:00
Don Isaac
746f63664e Merge branch 'main' of https://github.com/oven-sh/bun into don/test/toml 2025-03-04 14:24:28 -08:00
Don Isaac
92c779f0d4 add import cases 2025-03-03 17:30:03 -08:00
Don Isaac
1123a3e521 move tests to integration 2025-03-03 17:03:31 -08:00
Don Isaac
36f6b048ae test(bundler): comprehensive TOML testing 2025-03-03 16:31:27 -08:00
763 changed files with 5893 additions and 21 deletions

View File

@@ -92,6 +92,10 @@ else()
optionx(ENABLE_ASAN BOOL "If ASAN support should be enabled" DEFAULT OFF)
endif()
# enabling ASAN roughly doubles `zig build` times so we disable it by default, even in debug builds.
# It may optionally be enabled this way.
optionx(ENABLE_ZIG_ASAN BOOL "If ASAN support should be enabled when compiling Zig code" DEFAULT OFF)
optionx(ENABLE_PRETTIER BOOL "If prettier should be ran" DEFAULT OFF)
if(USE_VALGRIND AND NOT USE_BASELINE)

View File

@@ -590,6 +590,7 @@ register_command(
-Doptimize=${ZIG_OPTIMIZE}
-Dcpu=${ZIG_CPU}
-Denable_logs=$<IF:$<BOOL:${ENABLE_LOGS}>,true,false>
-Denable_asan=$<IF:$<BOOL:${ENABLE_ZIG_ASAN}>,true,false>
-Dversion=${VERSION}
-Dreported_nodejs_version=${NODEJS_VERSION}
-Dcanary=${CANARY_REVISION}

View File

@@ -32,6 +32,7 @@
"scripts": {
"build": "bun run build:debug",
"build:debug": "bun ./scripts/build.mjs -GNinja -DCMAKE_BUILD_TYPE=Debug -B build/debug",
"build:asan": "bun ./scripts/build.mjs -GNinja -DCMAKE_BUILD_TYPE=Debug -DENABLE_ZIG_ASAN=ON -B build/debug",
"build:valgrind": "bun ./scripts/build.mjs -GNinja -DCMAKE_BUILD_TYPE=Debug -DENABLE_BASELINE=ON -ENABLE_VALGRIND=ON -B build/debug-valgrind",
"build:release": "bun ./scripts/build.mjs -GNinja -DCMAKE_BUILD_TYPE=Release -B build/release",
"build:ci": "bun ./scripts/build.mjs -GNinja -DCMAKE_BUILD_TYPE=Release -DCMAKE_VERBOSE_MAKEFILE=ON -DCI=true -B build/release-ci --verbose --fresh",

View File

@@ -215,4 +215,4 @@ extern "C" {
#endif
#endif
#endif

View File

@@ -657,6 +657,8 @@ pub const JSValue = enum(i64) {
}
pub fn putZigString(value: JSValue, global: *JSGlobalObject, key: *const ZigString, result: JSC.JSValue) void {
// NOTE: JSC__JSVALUE__put calls `value.asCell()->getObject()`, which returns null if not an object
bun.debugAssert(value.isObject());
@import("./headers.zig").JSC__JSValue__put(value, global, key, result);
}
@@ -667,7 +669,15 @@ pub const JSValue = enum(i64) {
JSC__JSValue__putBunString(value, global, key, result);
}
/// Add a property to an object.
///
/// This is similar to `object[key] = value` in JS, but the prototype chain
/// is not traversed. Properties are added directly to the object.
///
/// `key` must be a `ZigString`, a `BunString`, or a pointer to one of those.
/// It cannot be a numeric value; use `putMayBeIndex` for that.
pub fn put(value: JSValue, global: *JSGlobalObject, key: anytype, result: JSC.JSValue) void {
bun.assert(value.isCell());
const Key = @TypeOf(key);
if (comptime @typeInfo(Key) == .pointer) {
const Elem = @typeInfo(Key).pointer.child;
@@ -690,12 +700,12 @@ pub const JSValue = enum(i64) {
}
/// Note: key can't be numeric (if so, use putMayBeIndex instead)
extern fn JSC__JSValue__putMayBeIndex(target: JSValue, globalObject: *JSGlobalObject, key: *const String, value: JSC.JSValue) void;
extern fn JSC__JSValue__putDirectMayBeIndex(target: JSValue, globalObject: *JSGlobalObject, key: *const String, value: JSC.JSValue) void;
/// Same as `.put` but accepts both non-numeric and numeric keys.
/// Prefer to use `.put` if the key is guaranteed to be non-numeric (e.g. known at comptime)
pub inline fn putMayBeIndex(this: JSValue, globalObject: *JSGlobalObject, key: *const String, value: JSValue) void {
JSC__JSValue__putMayBeIndex(this, globalObject, key, value);
JSC__JSValue__putDirectMayBeIndex(this, globalObject, key, value);
}
pub fn putIndex(value: JSValue, globalObject: *JSGlobalObject, i: u32, out: JSValue) void {

View File

@@ -3653,7 +3653,8 @@ void JSC__JSValue__put(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, const Z
object->putDirect(arg1->vm(), Zig::toIdentifier(*arg2, arg1), JSC::JSValue::decode(JSValue3));
}
extern "C" void JSC__JSValue__putMayBeIndex(JSC__JSValue target, JSC__JSGlobalObject* globalObject, const BunString* key, JSC__JSValue value)
// non-WTF `key`s get copied. Avoid ZigString if possible.
extern "C" void JSC__JSValue__putDirectMayBeIndex(JSC__JSValue target, JSC__JSGlobalObject* globalObject, const BunString* key, JSC__JSValue value)
{
auto& vm = JSC::getVM(globalObject);
ThrowScope scope = DECLARE_THROW_SCOPE(vm);

View File

@@ -4402,12 +4402,14 @@ pub fn CowSlice(T: type) type {
pub fn deinit(str: @This(), allocator: Allocator) void {
if (cow_str_assertions) if (str.debug) |debug| {
debug.mutex.lock();
bun.assert(
bun.assertf(
debug.allocator.ptr == allocator.ptr and
debug.allocator.vtable == allocator.vtable,
"Cow: cannot deinit with a different allocator",
.{},
);
if (str.flags.is_owned) {
bun.assert(debug.borrows == 0); // active borrows become invalid data
bun.assertf(debug.borrows == 0, "Cow: cannot deinit owned slice with active borrows", .{}); // active borrows become invalid data
} else {
debug.borrows -= 1; // double deinit of a borrowed string
}

View File

@@ -1936,8 +1936,9 @@ pub const E = struct {
if (prop.kind != .normal or prop.class_static_block != null or prop.key == null or prop.key.?.data != .e_string or prop.value == null) {
return error.@"Cannot convert argument type to JS";
}
var key = prop.key.?.data.e_string.toZigString(allocator);
obj.put(globalObject, &key, try prop.value.?.toJS(allocator, globalObject));
const key = prop.key.?.data.e_string.toBunString();
defer key.deref();
obj.putMayBeIndex(globalObject, &key, try prop.value.?.toJS(allocator, globalObject));
}
return obj;
@@ -2539,6 +2540,16 @@ pub const E = struct {
}
}
/// `data` is borrowed. Does not allocate.
pub fn toBunString(s: *const String) bun.String {
return if (s.len() == 0)
bun.String.empty
else if (s.isUTF8())
bun.String.fromUTF8(s.data)
else
bun.String.fromUTF16(s.slice16());
}
pub fn format(s: String, comptime fmt: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
comptime bun.assert(fmt.len == 0);

View File

@@ -66,8 +66,9 @@ pub const Lexer = struct {
string_literal_is_ascii: bool = true,
line_number: u32 = 0,
token: T = T.t_end_of_file,
allow_double_bracket: bool = true,
allow_double_bracket: bool = true,
wants_key: bool = false,
has_newline_before: bool = false,
should_redact_logs: bool,
@@ -530,6 +531,11 @@ pub const Lexer = struct {
while (true) {
lexer.start = lexer.end;
lexer.token = T.t_end_of_file;
// clear state from prev token. Not required for correctness, but
// helps us find bugs.
if (Environment.isDebug) {
lexer.identifier = "";
}
switch (lexer.code_point) {
-1 => {
@@ -575,8 +581,17 @@ pub const Lexer = struct {
lexer.token = T.t_plus;
},
'-' => {
if (lexer.wants_key) {
try lexer.lexIdentifier();
}
lexer.step();
lexer.token = T.t_minus;
switch (lexer.code_point) {
'a'...'z', 'A'...'Z', '-', '_' => {
@branchHint(.unlikely);
try lexer.lexIdentifier();
},
else => lexer.token = T.t_minus,
}
},
'{' => {
@@ -801,21 +816,18 @@ pub const Lexer = struct {
lexer.token = T.t_string_literal;
},
'.', '0'...'9' => {
'.' => {
try lexer.parseNumericLiteralOrDot();
},
'0'...'9' => {
try if (lexer.wants_key)
lexer.lexIdentifier()
else
lexer.parseNumericLiteralOrDot();
},
'@', 'a'...'z', 'A'...'Z', '$', '_' => {
lexer.step();
while (isIdentifierPart(lexer.code_point)) {
lexer.step();
}
lexer.identifier = lexer.raw();
lexer.token = switch (lexer.identifier.len) {
4 => if (strings.eqlComptimeIgnoreLen(lexer.identifier, "true")) T.t_true else T.t_identifier,
5 => if (strings.eqlComptimeIgnoreLen(lexer.identifier, "false")) T.t_false else T.t_identifier,
else => T.t_identifier,
};
try lexer.lexIdentifier();
},
else => try lexer.unexpected(),
@@ -824,6 +836,20 @@ pub const Lexer = struct {
}
}
fn lexIdentifier(lexer: *Lexer) !void {
// caller cannot have stepped yet
bun.debugAssert(isIdentifierPart(lexer.code_point));
while (isIdentifierPart(lexer.code_point)) {
lexer.step();
}
lexer.identifier = lexer.raw();
lexer.token = switch (lexer.identifier.len) {
4 => if (strings.eqlComptimeIgnoreLen(lexer.identifier, "true")) T.t_true else T.t_identifier,
5 => if (strings.eqlComptimeIgnoreLen(lexer.identifier, "false")) T.t_false else T.t_identifier,
else => T.t_identifier,
};
}
pub fn decodeEscapeSequences(lexer: *Lexer, start: usize, text: string, comptime allow_multiline: bool, comptime BufType: type, buf_: *BufType) !void {
var buf = buf_.*;
defer buf_.* = buf;

View File

@@ -136,6 +136,11 @@ pub const TOML = struct {
loc,
);
},
// `-` is a valid identifier
.t_minus => {
try p.lexer.next();
return p.e(E.String{ .data = "-" }, loc);
},
// what we see as a number here could actually be a string
.t_numeric_literal => {
const literal = p.lexer.raw();
@@ -148,6 +153,9 @@ pub const TOML = struct {
}
pub fn parseKey(p: *TOML, allocator: std.mem.Allocator) anyerror!*Rope {
p.lexer.wants_key = true;
defer p.lexer.wants_key = false;
var rope = try allocator.create(Rope);
const head = rope;
rope.* = .{

View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,17 @@
These test cases are copied from https://github.com/toml-lang/toml-test, which is MIT licensed
```
The MIT License (MIT)
Copyright (c) 2018 TOML authors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
```

View File

@@ -0,0 +1,18 @@
double-comma-1 = [1,,2]
double-comma-2 = [1,2,,]
only-comma-1 = [,]
only-comma-2 = [,,]
no-comma-1 = [true false]
no-comma-2 = [ 1 2 3 ]
no-comma-3 = [ 1 #,]
no-close-1 = [ 1, 2, 3
no-close-2 = [1,
no-close-3 = [42 #]
no-close-4 = [{ key = 42
no-close-5 = [{ key = 42}
no-close-6 = [{ key = 42 #}]
no-close-7 = [{ key = 42} #]
no-close-8 = [

View File

@@ -0,0 +1 @@
double-comma-1 = [1,,2]

View File

@@ -0,0 +1 @@
double-comma-2 = [1,2,,]

View File

@@ -0,0 +1,3 @@
[[tab.arr]]
[tab]
arr.val1=1

View File

@@ -0,0 +1,6 @@
a = [{ b = 1 }]
# Cannot extend tables within static arrays
# https://github.com/toml-lang/toml/issues/908
[a.c]
foo = 1

View File

@@ -0,0 +1 @@
arrr = [true false]

View File

@@ -0,0 +1 @@
wrong = [ 1 2 3 ]

View File

@@ -0,0 +1 @@
no-close-1 = [ 1, 2, 3

View File

@@ -0,0 +1 @@
no-close-2 = [1,

View File

@@ -0,0 +1 @@
no-close-3 = [42 #]

View File

@@ -0,0 +1 @@
no-close-4 = [{ key = 42

View File

@@ -0,0 +1 @@
no-close-5 = [{ key = 42}

View File

@@ -0,0 +1 @@
no-close-6 = [{ key = 42 #}]

View File

@@ -0,0 +1 @@
no-close-7 = [{ key = 42} #]

View File

@@ -0,0 +1 @@
no-close-8 = [

View File

@@ -0,0 +1 @@
x = [{ key = 42

View File

@@ -0,0 +1 @@
x = [{ key = 42 #

View File

@@ -0,0 +1 @@
no-comma-1 = [true false]

View File

@@ -0,0 +1 @@
no-comma-2 = [ 1 2 3 ]

View File

@@ -0,0 +1 @@
no-comma-3 = [ 1 #,]

View File

@@ -0,0 +1 @@
only-comma-1 = [,]

View File

@@ -0,0 +1 @@
only-comma-2 = [,,]

View File

@@ -0,0 +1,4 @@
# INVALID TOML DOC
fruit = []
[[fruit]] # Not allowed

View File

@@ -0,0 +1,10 @@
# INVALID TOML DOC
[[fruit]]
name = "apple"
[[fruit.variety]]
name = "red delicious"
# This table conflicts with the previous table
[fruit.variety]
name = "granny smith"

View File

@@ -0,0 +1,4 @@
array = [
"Is there life after an array separator?", No
"Entry"
]

View File

@@ -0,0 +1,4 @@
array = [
"Is there life before an array separator?" No,
"Entry"
]

View File

@@ -0,0 +1,5 @@
array = [
"Entry 1",
I don't belong,
"Entry 2",
]

View File

@@ -0,0 +1 @@
almost-false-with-extra = falsify

View File

@@ -0,0 +1 @@
almost-false = fals

View File

@@ -0,0 +1 @@
almost-true-with-extra = truthy

View File

@@ -0,0 +1 @@
almost-true = tru

View File

@@ -0,0 +1,15 @@
almost-false-with-extra = falsify
almost-false = fals
almost-true-with-extra = truthy
almost-true = tru
just-f = f
just-t = t
mixed-case = valid = False
starting-same-false = falsey
starting-same-true = truer
wrong-case-false = FALSE
wrong-case-true = TRUE
mixed-case-false = falsE
mixed-case-true = trUe
capitalized-false = False
capitalized-true = True

View File

@@ -0,0 +1 @@
capitalized-false = False

View File

@@ -0,0 +1 @@
capitalized-true = True

View File

@@ -0,0 +1 @@
just-f = f

View File

@@ -0,0 +1 @@
just-t = t

View File

@@ -0,0 +1 @@
mixed-case-false = falsE

View File

@@ -0,0 +1 @@
mixed-case-true = trUe

View File

@@ -0,0 +1 @@
mixed-case = valid = False

View File

@@ -0,0 +1 @@
starting-same-false = falsey

View File

@@ -0,0 +1 @@
starting-same-true = truer

View File

@@ -0,0 +1 @@
wrong-case-false = FALSE

View File

@@ -0,0 +1 @@
wrong-case-true = TRUE

View File

@@ -0,0 +1,2 @@
# The following line contains a single carriage return control character

View File

@@ -0,0 +1 @@
bare-formfeed =

View File

@@ -0,0 +1 @@
bare-vertical-tab =

View File

@@ -0,0 +1 @@
comment-cr = "Carriage return in comment" #

View File

@@ -0,0 +1 @@
comment-del = "0x7f" # 

View File

@@ -0,0 +1 @@
comment-ff = "0x7f" #

View File

@@ -0,0 +1 @@
comment-lf = "ctrl-P" # 

View File

@@ -0,0 +1 @@
comment-us = "ctrl-_" # 

View File

@@ -0,0 +1,38 @@
# "\x.." sequences are replaced with literal control characters.
comment-null = "null" # \x00
comment-ff = "0x7f" # \x0c
comment-lf = "ctrl-P" # \x10
comment-cr = "CR" # \x0d
comment-us = "ctrl-_" # \x1f
comment-del = "0x7f" # \x7f
comment-cr = "Carriage return in comment" # \x0da=1
string-null = "null\x00"
string-lf = "null\x10"
string-cr = "null\x0d"
string-us = "null\x1f"
string-del = "null\x7f"
string-bs = "backspace\x08"
rawstring-null = 'null\x00'
rawstring-lf = 'null\x10'
rawstring-cr = 'null\x0d'
rawstring-us = 'null\x1f'
rawstring-del = 'null\x7f'
multi-null = """null\x00"""
multi-lf = """null\x10"""
multi-cr = """null\x0d"""
multi-us = """null\x1f"""
multi-del = """null\x7f"""
rawmulti-null = '''null\x00'''
rawmulti-lf = '''null\x10'''
rawmulti-cd = '''null\x0d'''
rawmulti-us = '''null\x1f'''
rawmulti-del = '''null\x7f'''
bare-null = "some value" \x00
bare-formfeed = \x0c
bare-vertical-tab = \x0b

View File

@@ -0,0 +1 @@
multi-cr = """null

View File

@@ -0,0 +1 @@
multi-del = """null"""

View File

@@ -0,0 +1 @@
multi-lf = """null"""

View File

@@ -0,0 +1 @@
multi-us = """null"""

View File

@@ -0,0 +1 @@
rawmulti-cd = '''null

View File

@@ -0,0 +1 @@
rawmulti-del = '''null'''

View File

@@ -0,0 +1 @@
rawmulti-lf = '''null'''

View File

@@ -0,0 +1 @@
rawmulti-us = '''null'''

View File

@@ -0,0 +1 @@
rawstring-cr = 'null

View File

@@ -0,0 +1 @@
rawstring-del = 'null'

View File

@@ -0,0 +1 @@
rawstring-lf = 'null'

View File

@@ -0,0 +1 @@
rawstring-us = 'null'

View File

@@ -0,0 +1 @@
string-bs = "backspace"

View File

@@ -0,0 +1 @@
string-cr = "null

View File

@@ -0,0 +1 @@
string-del = "null"

View File

@@ -0,0 +1 @@
string-lf = "null"

View File

@@ -0,0 +1 @@
string-us = "null"

View File

@@ -0,0 +1 @@
"not a leap year" = 2100-02-29T15:15:15Z

View File

@@ -0,0 +1 @@
"only 28 or 29 days in february" = 1988-02-30T15:15:15Z

View File

@@ -0,0 +1,2 @@
# time-hour = 2DIGIT ; 00-23
d = 2006-01-01T24:00:00-00:00

View File

@@ -0,0 +1,3 @@
# date-mday = 2DIGIT ; 01-28, 01-29, 01-30, 01-31 based on
# ; month/year
d = 2006-01-32T00:00:00-00:00

View File

@@ -0,0 +1,3 @@
# date-mday = 2DIGIT ; 01-28, 01-29, 01-30, 01-31 based on
# ; month/year
d = 2006-01-00T00:00:00-00:00

View File

@@ -0,0 +1,2 @@
# time-minute = 2DIGIT ; 00-59
d = 2006-01-01T00:60:00-00:00

View File

@@ -0,0 +1,2 @@
# date-month = 2DIGIT ; 01-12
d = 2006-13-01T00:00:00-00:00

View File

@@ -0,0 +1,2 @@
# date-month = 2DIGIT ; 01-12
d = 2007-00-01T00:00:00-00:00

View File

@@ -0,0 +1,2 @@
# Month "7" instead of "07"; the leading zero is required.
no-leads = 1987-7-05T17:45:00Z

View File

@@ -0,0 +1,2 @@
# Day "5" instead of "05"; the leading zero is required.
with-milli = 1987-07-5T17:45:00.12Z

View File

@@ -0,0 +1,2 @@
# Month "7" instead of "07"; the leading zero is required.
no-leads = 1987-7-05T17:45:00Z

View File

@@ -0,0 +1,2 @@
# No seconds in time.
no-secs = 1987-07-05T17:45Z

Some files were not shown because too many files have changed in this diff Show More