Compare commits

...

2 Commits

Author SHA1 Message Date
Ben Grant
6220f7a6f1 Remove f64 case from JSValue.coerce() 2024-12-12 10:24:02 -08:00
Ben Grant
f0e2c0a9fe Rename JSValue.toInt32 2024-12-10 17:37:38 -08:00
17 changed files with 107 additions and 93 deletions

View File

@@ -704,13 +704,13 @@ pub const FormatOptions = struct {
if (arg1.isObject()) {
if (try arg1.getTruthy(globalThis, "depth")) |opt| {
if (opt.isInt32()) {
const arg = opt.toInt32();
const arg = opt.asInt32();
if (arg < 0) {
return globalThis.throwInvalidArguments("expected depth to be greater than or equal to 0, got {d}", .{arg});
}
formatOptions.max_depth = @as(u16, @truncate(@as(u32, @intCast(@min(arg, std.math.maxInt(u16))))));
} else if (opt.isNumber()) {
const v = opt.coerce(f64, globalThis);
const v = opt.coerceToDouble(globalThis);
if (std.math.isInf(v)) {
formatOptions.max_depth = std.math.maxInt(u16);
} else {
@@ -733,13 +733,13 @@ pub const FormatOptions = struct {
if (arguments.len > 0) {
var depthArg = arg1;
if (depthArg.isInt32()) {
const arg = depthArg.toInt32();
const arg = depthArg.asInt32();
if (arg < 0) {
return globalThis.throwInvalidArguments("expected depth to be greater than or equal to 0, got {d}", .{arg});
}
formatOptions.max_depth = @as(u16, @truncate(@as(u32, @intCast(@min(arg, std.math.maxInt(u16))))));
} else if (depthArg.isNumber()) {
const v = depthArg.coerce(f64, globalThis);
const v = depthArg.coerceToDouble(globalThis);
if (std.math.isInf(v)) {
formatOptions.max_depth = std.math.maxInt(u16);
} else {
@@ -2552,7 +2552,7 @@ pub const Formatter = struct {
},
.Map => {
const length_value = value.get_unsafe(this.globalThis, "size") orelse JSC.JSValue.jsNumberFromInt32(0);
const length = length_value.toInt32();
const length = length_value.numberToInt32Clamp();
const prev_quote_strings = this.quote_strings;
this.quote_strings = true;
@@ -2656,7 +2656,7 @@ pub const Formatter = struct {
},
.Set => {
const length_value = value.get_unsafe(this.globalThis, "size") orelse JSC.JSValue.jsNumberFromInt32(0);
const length = length_value.toInt32();
const length = length_value.numberToInt32Clamp();
const prev_quote_strings = this.quote_strings;
this.quote_strings = true;

View File

@@ -550,7 +550,7 @@ pub fn registerMacro(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFram
if (arguments.len != 2 or !arguments[0].isNumber()) {
return globalObject.throwInvalidArguments("Internal error registering macros: invalid args", .{});
}
const id = arguments[0].toInt32();
const id = arguments[0].numberToInt32Clamp();
if (id == -1 or id == 0) {
return globalObject.throwInvalidArguments("Internal error registering macros: invalid id", .{});
}

View File

@@ -251,7 +251,10 @@ pub const All = struct {
globalThis.bunVM().timer.last_id +%= 1;
const interval: i32 = @max(
countdown.coerce(i32, globalThis),
if (std.math.isInf(countdown.getNumber() orelse 0.0)) // 0.0 is finite so that we don't treat non-numeric values as infinity
0
else
countdown.coerce(i32, globalThis),
// It must be 1 at minimum or setTimeout(cb, 0) will seemingly hang
1,
);
@@ -276,7 +279,11 @@ pub const All = struct {
// We don't deal with nesting levels directly
// but we do set the minimum timeout to be 1ms for repeating timers
const interval: i32 = @max(
countdown.coerce(i32, globalThis),
if (std.math.isInf(countdown.getNumber() orelse 0.0)) // 0.0 is finite so that we don't treat non-numeric values as infinity
0
else
countdown.coerce(i32, globalThis),
// It must be 1 at minimum or setTimeout(cb, 0) will seemingly hang
1,
);
return set(id, globalThis, wrappedCallback, interval, arguments, true) catch

View File

@@ -337,7 +337,7 @@ fn jsAssertSettings(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame
if (try options.get(globalObject, "headerTableSize")) |headerTableSize| {
if (headerTableSize.isNumber()) {
const headerTableSizeValue = headerTableSize.toInt32();
const headerTableSizeValue = headerTableSize.numberToInt32Clamp();
if (headerTableSizeValue > MAX_HEADER_TABLE_SIZE or headerTableSizeValue < 0) {
return globalObject.throw("Expected headerTableSize to be a number between 0 and 2^32-1", .{});
}
@@ -354,7 +354,7 @@ fn jsAssertSettings(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame
if (try options.get(globalObject, "initialWindowSize")) |initialWindowSize| {
if (initialWindowSize.isNumber()) {
const initialWindowSizeValue = initialWindowSize.toInt32();
const initialWindowSizeValue = initialWindowSize.numberToInt32Clamp();
if (initialWindowSizeValue > MAX_HEADER_TABLE_SIZE or initialWindowSizeValue < 0) {
return globalObject.throw("Expected initialWindowSize to be a number between 0 and 2^32-1", .{});
}
@@ -365,7 +365,7 @@ fn jsAssertSettings(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame
if (try options.get(globalObject, "maxFrameSize")) |maxFrameSize| {
if (maxFrameSize.isNumber()) {
const maxFrameSizeValue = maxFrameSize.toInt32();
const maxFrameSizeValue = maxFrameSize.numberToInt32Clamp();
if (maxFrameSizeValue > MAX_FRAME_SIZE or maxFrameSizeValue < 16384) {
return globalObject.throw("Expected maxFrameSize to be a number between 16,384 and 2^24-1", .{});
}
@@ -376,7 +376,7 @@ fn jsAssertSettings(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame
if (try options.get(globalObject, "maxConcurrentStreams")) |maxConcurrentStreams| {
if (maxConcurrentStreams.isNumber()) {
const maxConcurrentStreamsValue = maxConcurrentStreams.toInt32();
const maxConcurrentStreamsValue = maxConcurrentStreams.numberToInt32Clamp();
if (maxConcurrentStreamsValue > MAX_HEADER_TABLE_SIZE or maxConcurrentStreamsValue < 0) {
return globalObject.throw("Expected maxConcurrentStreams to be a number between 0 and 2^32-1", .{});
}
@@ -387,7 +387,7 @@ fn jsAssertSettings(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame
if (try options.get(globalObject, "maxHeaderListSize")) |maxHeaderListSize| {
if (maxHeaderListSize.isNumber()) {
const maxHeaderListSizeValue = maxHeaderListSize.toInt32();
const maxHeaderListSizeValue = maxHeaderListSize.numberToInt32Clamp();
if (maxHeaderListSizeValue > MAX_HEADER_TABLE_SIZE or maxHeaderListSizeValue < 0) {
return globalObject.throw("Expected maxHeaderListSize to be a number between 0 and 2^32-1", .{});
}
@@ -398,7 +398,7 @@ fn jsAssertSettings(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame
if (try options.get(globalObject, "maxHeaderSize")) |maxHeaderSize| {
if (maxHeaderSize.isNumber()) {
const maxHeaderSizeValue = maxHeaderSize.toInt32();
const maxHeaderSizeValue = maxHeaderSize.numberToInt32Clamp();
if (maxHeaderSizeValue > MAX_HEADER_TABLE_SIZE or maxHeaderSizeValue < 0) {
return globalObject.throw("Expected maxHeaderSize to be a number between 0 and 2^32-1", .{});
}
@@ -423,7 +423,7 @@ fn jsGetPackedSettings(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFr
if (try options.get(globalObject, "headerTableSize")) |headerTableSize| {
if (headerTableSize.isNumber()) {
const headerTableSizeValue = headerTableSize.toInt32();
const headerTableSizeValue = headerTableSize.numberToInt32Clamp();
if (headerTableSizeValue > MAX_HEADER_TABLE_SIZE or headerTableSizeValue < 0) {
return globalObject.throw("Expected headerTableSize to be a number between 0 and 2^32-1", .{});
}
@@ -443,7 +443,7 @@ fn jsGetPackedSettings(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFr
if (try options.get(globalObject, "initialWindowSize")) |initialWindowSize| {
if (initialWindowSize.isNumber()) {
const initialWindowSizeValue = initialWindowSize.toInt32();
const initialWindowSizeValue = initialWindowSize.numberToInt32Clamp();
if (initialWindowSizeValue > MAX_HEADER_TABLE_SIZE or initialWindowSizeValue < 0) {
return globalObject.throw("Expected initialWindowSize to be a number between 0 and 2^32-1", .{});
}
@@ -455,7 +455,7 @@ fn jsGetPackedSettings(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFr
if (try options.get(globalObject, "maxFrameSize")) |maxFrameSize| {
if (maxFrameSize.isNumber()) {
const maxFrameSizeValue = maxFrameSize.toInt32();
const maxFrameSizeValue = maxFrameSize.numberToInt32Clamp();
if (maxFrameSizeValue > MAX_FRAME_SIZE or maxFrameSizeValue < 16384) {
return globalObject.throw("Expected maxFrameSize to be a number between 16,384 and 2^24-1", .{});
}
@@ -467,7 +467,7 @@ fn jsGetPackedSettings(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFr
if (try options.get(globalObject, "maxConcurrentStreams")) |maxConcurrentStreams| {
if (maxConcurrentStreams.isNumber()) {
const maxConcurrentStreamsValue = maxConcurrentStreams.toInt32();
const maxConcurrentStreamsValue = maxConcurrentStreams.numberToInt32Clamp();
if (maxConcurrentStreamsValue > MAX_HEADER_TABLE_SIZE or maxConcurrentStreamsValue < 0) {
return globalObject.throw("Expected maxConcurrentStreams to be a number between 0 and 2^32-1", .{});
}
@@ -479,7 +479,7 @@ fn jsGetPackedSettings(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFr
if (try options.get(globalObject, "maxHeaderListSize")) |maxHeaderListSize| {
if (maxHeaderListSize.isNumber()) {
const maxHeaderListSizeValue = maxHeaderListSize.toInt32();
const maxHeaderListSizeValue = maxHeaderListSize.numberToInt32Clamp();
if (maxHeaderListSizeValue > MAX_HEADER_TABLE_SIZE or maxHeaderListSizeValue < 0) {
return globalObject.throw("Expected maxHeaderListSize to be a number between 0 and 2^32-1", .{});
}
@@ -491,7 +491,7 @@ fn jsGetPackedSettings(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFr
if (try options.get(globalObject, "maxHeaderSize")) |maxHeaderSize| {
if (maxHeaderSize.isNumber()) {
const maxHeaderSizeValue = maxHeaderSize.toInt32();
const maxHeaderSizeValue = maxHeaderSize.numberToInt32Clamp();
if (maxHeaderSizeValue > MAX_HEADER_TABLE_SIZE or maxHeaderSizeValue < 0) {
return globalObject.throw("Expected maxHeaderSize to be a number between 0 and 2^32-1", .{});
}
@@ -2322,7 +2322,7 @@ pub const H2FrameParser = struct {
if (try options.get(globalObject, "headerTableSize")) |headerTableSize| {
if (headerTableSize.isNumber()) {
const headerTableSizeValue = headerTableSize.toInt32();
const headerTableSizeValue = headerTableSize.numberToInt32Clamp();
if (headerTableSizeValue > MAX_HEADER_TABLE_SIZE or headerTableSizeValue < 0) {
return globalObject.throw("Expected headerTableSize to be a number between 0 and 2^32-1", .{});
}
@@ -2342,7 +2342,7 @@ pub const H2FrameParser = struct {
if (try options.get(globalObject, "initialWindowSize")) |initialWindowSize| {
if (initialWindowSize.isNumber()) {
const initialWindowSizeValue = initialWindowSize.toInt32();
const initialWindowSizeValue = initialWindowSize.numberToInt32Clamp();
if (initialWindowSizeValue > MAX_HEADER_TABLE_SIZE or initialWindowSizeValue < 0) {
return globalObject.throw("Expected initialWindowSize to be a number between 0 and 2^32-1", .{});
}
@@ -2354,7 +2354,7 @@ pub const H2FrameParser = struct {
if (try options.get(globalObject, "maxFrameSize")) |maxFrameSize| {
if (maxFrameSize.isNumber()) {
const maxFrameSizeValue = maxFrameSize.toInt32();
const maxFrameSizeValue = maxFrameSize.numberToInt32Clamp();
if (maxFrameSizeValue > MAX_FRAME_SIZE or maxFrameSizeValue < 16384) {
return globalObject.throw("Expected maxFrameSize to be a number between 16,384 and 2^24-1", .{});
}
@@ -2366,7 +2366,7 @@ pub const H2FrameParser = struct {
if (try options.get(globalObject, "maxConcurrentStreams")) |maxConcurrentStreams| {
if (maxConcurrentStreams.isNumber()) {
const maxConcurrentStreamsValue = maxConcurrentStreams.toInt32();
const maxConcurrentStreamsValue = maxConcurrentStreams.numberToInt32Clamp();
if (maxConcurrentStreamsValue > MAX_HEADER_TABLE_SIZE or maxConcurrentStreamsValue < 0) {
return globalObject.throw("Expected maxConcurrentStreams to be a number between 0 and 2^32-1", .{});
}
@@ -2378,7 +2378,7 @@ pub const H2FrameParser = struct {
if (try options.get(globalObject, "maxHeaderListSize")) |maxHeaderListSize| {
if (maxHeaderListSize.isNumber()) {
const maxHeaderListSizeValue = maxHeaderListSize.toInt32();
const maxHeaderListSizeValue = maxHeaderListSize.numberToInt32Clamp();
if (maxHeaderListSizeValue > MAX_HEADER_TABLE_SIZE or maxHeaderListSizeValue < 0) {
return globalObject.throw("Expected maxHeaderListSize to be a number between 0 and 2^32-1", .{});
}
@@ -2390,7 +2390,7 @@ pub const H2FrameParser = struct {
if (try options.get(globalObject, "maxHeaderSize")) |maxHeaderSize| {
if (maxHeaderSize.isNumber()) {
const maxHeaderSizeValue = maxHeaderSize.toInt32();
const maxHeaderSizeValue = maxHeaderSize.numberToInt32Clamp();
if (maxHeaderSizeValue > MAX_HEADER_TABLE_SIZE or maxHeaderSizeValue < 0) {
return globalObject.throw("Expected maxHeaderSize to be a number between 0 and 2^32-1", .{});
}
@@ -2444,7 +2444,7 @@ pub const H2FrameParser = struct {
if (!error_code_arg.isNumber()) {
return globalObject.throw("Expected errorCode to be a number", .{});
}
const errorCode = error_code_arg.toInt32();
const errorCode = error_code_arg.numberToInt32Clamp();
if (errorCode < 1 and errorCode > 13) {
return globalObject.throw("invalid errorCode", .{});
}
@@ -2456,7 +2456,7 @@ pub const H2FrameParser = struct {
if (!last_stream_arg.isNumber()) {
return globalObject.throw("Expected lastStreamId to be a number", .{});
}
const id = last_stream_arg.toInt32();
const id = last_stream_arg.numberToInt32Clamp();
if (id < 0 and id > MAX_STREAM_ID) {
return globalObject.throw("Expected lastStreamId to be a number between 1 and 2147483647", .{});
}
@@ -3434,7 +3434,7 @@ pub const H2FrameParser = struct {
if (try options.get(globalObject, "parent")) |parent_js| {
if (parent_js.isNumber() or parent_js.isInt32()) {
has_priority = true;
parent = parent_js.toInt32();
parent = parent_js.numberToInt32Clamp();
if (parent <= 0 or parent > MAX_STREAM_ID) {
stream.state = .CLOSED;
stream.rstCode = @intFromEnum(ErrorCode.INTERNAL_ERROR);
@@ -3448,7 +3448,7 @@ pub const H2FrameParser = struct {
if (try options.get(globalObject, "weight")) |weight_js| {
if (weight_js.isNumber() or weight_js.isInt32()) {
has_priority = true;
weight = weight_js.toInt32();
weight = weight_js.numberToInt32Clamp();
if (weight < 1 or weight > 256) {
stream.state = .CLOSED;
stream.rstCode = @intFromEnum(ErrorCode.INTERNAL_ERROR);

View File

@@ -1358,7 +1358,7 @@ pub const FFI = struct {
if (try value.getTruthy(global, "returns")) |ret_value| brk: {
if (ret_value.isAnyInt()) {
const int = ret_value.toInt32();
const int = ret_value.numberToInt32Clamp();
switch (int) {
0...ABIType.max => {
return_type = @as(ABIType, @enumFromInt(int));

View File

@@ -3451,7 +3451,7 @@ pub const JSGlobalObject = opaque {
const max = range.max;
if (value.isInt32()) {
const int = value.toInt32();
const int = value.asInt32();
if (always_allow_zero and int == 0) {
return 0;
}
@@ -4052,6 +4052,7 @@ pub const JSValue = enum(i64) {
JSC__JSValue__forEachPropertyOrdered(this, globalObject, ctx, callback);
}
/// Clears exceptions thrown during the coercion (e.g. by valueOf or [Symbol.toPrimitive])
pub fn coerceToDouble(
this: JSValue,
globalObject: *JSC.JSGlobalObject,
@@ -4059,17 +4060,10 @@ pub const JSValue = enum(i64) {
return cppFn("coerceToDouble", .{ this, globalObject });
}
/// May execute JavaScript and throw an exception if `this` is an object.
pub fn coerce(this: JSValue, comptime T: type, globalThis: *JSC.JSGlobalObject) T {
return switch (T) {
ZigString => this.getZigString(globalThis),
bool => this.toBoolean(),
f64 => {
if (this.isDouble()) {
return this.asDouble();
}
return this.coerceToDouble(globalThis);
},
i64 => {
return this.coerceToInt64(globalThis);
},
@@ -4099,15 +4093,15 @@ pub const JSValue = enum(i64) {
u32 => toU32(this),
u16 => toU16(this),
c_uint => @as(c_uint, @intCast(toU32(this))),
c_int => @as(c_int, @intCast(toInt32(this))),
c_int => @as(c_int, @intCast(numberToInt32Clamp(this))),
?AnyPromise => asAnyPromise(this),
u52 => @as(u52, @truncate(@as(u64, @intCast(@max(this.toInt64(), 0))))),
i52 => @as(i52, @truncate(@as(i52, @intCast(this.toInt64())))),
u64 => toUInt64NoTruncate(this),
u8 => @as(u8, @truncate(toU32(this))),
i16 => @as(i16, @truncate(toInt32(this))),
i8 => @as(i8, @truncate(toInt32(this))),
i32 => @as(i32, @truncate(toInt32(this))),
i16 => @as(i16, @truncate(numberToInt32Clamp(this))),
i8 => @as(i8, @truncate(numberToInt32Clamp(this))),
i32 => @as(i32, @truncate(numberToInt32Clamp(this))),
i64 => this.toInt64(),
bool => this.toBoolean(),
else => @compileError("Not implemented yet"),
@@ -5811,24 +5805,22 @@ pub const JSValue = enum(i64) {
return coerceJSValueDoubleTruncatingTT(i52, i64, this.asNumber());
}
pub fn toInt32(this: JSValue) i32 {
/// Asserts this is an i32 or a double.
/// If this is a double, NaN is converted to zero, and other values are truncated and clamped
/// to i32 range. Infinities are clamped to the minimum and maximum values of i32.
///
/// This may not be the behavior you want, because it doesn't match JavaScript's coercion to i32
/// (value >> 0)
pub fn numberToInt32Clamp(this: JSValue) i32 {
if (comptime bun.Environment.allow_assert) {
bun.assert(this.isNumber()); // use coerce() instead
}
if (this.isInt32()) {
return asInt32(this);
}
if (this.getNumber()) |num| {
return coerceJSValueDoubleTruncatingT(i32, num);
}
if (comptime bun.Environment.allow_assert) {
bun.assert(!this.isString()); // use coerce() instead
bun.assert(!this.isCell()); // use coerce() instead
}
// TODO: this shouldn't be reachable.
return cppFn("toInt32", .{
this,
});
return coerceJSValueDoubleTruncatingT(i32, this.getNumber().?);
}
pub fn asInt32(this: JSValue) i32 {
@@ -5845,11 +5837,11 @@ pub const JSValue = enum(i64) {
pub fn asFileDescriptor(this: JSValue) bun.FileDescriptor {
bun.assert(this.isNumber());
return bun.FDImpl.fromUV(this.toInt32()).encode();
return bun.FDImpl.fromUV(this.numberToInt32Clamp()).encode();
}
pub inline fn toU16(this: JSValue) u16 {
return @as(u16, @truncate(@max(this.toInt32(), 0)));
return @as(u16, @truncate(@max(this.numberToInt32Clamp(), 0)));
}
pub inline fn toU32(this: JSValue) u32 {

View File

@@ -126,7 +126,7 @@ pub const InternalMsgHolder = struct {
if (try message.get(globalThis, "ack")) |p| {
if (!p.isUndefined()) {
const ack = p.toInt32();
const ack = p.numberToInt32Clamp();
if (this.callbacks.getEntry(ack)) |entry| {
var cbstrong = entry.value_ptr.*;
if (cbstrong.get()) |callback| {
@@ -223,7 +223,7 @@ pub fn handleInternalMessagePrimary(globalThis: *JSC.JSGlobalObject, subprocess:
if (try message.get(globalThis, "ack")) |p| {
if (!p.isUndefined()) {
const ack = p.toInt32();
const ack = p.numberToInt32Clamp();
if (ipc_data.internal_msg_queue.callbacks.getEntry(ack)) |entry| {
var cbstrong = entry.value_ptr.*;
defer cbstrong.clear();

View File

@@ -1515,7 +1515,7 @@ pub const Arguments = struct {
if (!uid_value.isNumber()) {
return ctx.throwInvalidArgumentTypeValue("uid", "number", uid_value);
}
break :brk @as(uid_t, @intCast(uid_value.toInt32()));
break :brk @as(uid_t, @intCast(uid_value.numberToInt32Clamp()));
};
const gid: gid_t = brk: {
@@ -1527,7 +1527,7 @@ pub const Arguments = struct {
if (!gid_value.isNumber()) {
return ctx.throwInvalidArgumentTypeValue("gid", "number", gid_value);
}
break :brk @as(gid_t, @intCast(gid_value.toInt32()));
break :brk @as(gid_t, @intCast(gid_value.numberToInt32Clamp()));
};
return Chown{ .path = path, .uid = uid, .gid = gid };
@@ -1556,7 +1556,7 @@ pub const Arguments = struct {
};
arguments.eat();
break :brk @as(uid_t, @intCast(uid_value.toInt32()));
break :brk @as(uid_t, @intCast(uid_value.numberToInt32Clamp()));
};
const gid: gid_t = brk: {
@@ -1565,7 +1565,7 @@ pub const Arguments = struct {
};
arguments.eat();
break :brk @as(gid_t, @intCast(gid_value.toInt32()));
break :brk @as(gid_t, @intCast(gid_value.numberToInt32Clamp()));
};
return Fchown{ .fd = fd, .uid = uid, .gid = gid };
@@ -2741,7 +2741,7 @@ pub const Arguments = struct {
}
if (try arg.get(ctx, "bufferSize")) |buffer_size_| {
buffer_size = buffer_size_.toInt32();
buffer_size = buffer_size_.numberToInt32Clamp();
if (buffer_size < 0) {
return ctx.throwInvalidArguments("bufferSize must be > 0", .{});
}

View File

@@ -14,7 +14,7 @@ pub fn internalErrorName(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFr
}
const err_value = arguments[0];
const err_int = err_value.toInt32();
const err_int = err_value.numberToInt32Clamp();
if (err_int == -4095) return bun.String.static("EOF").toJS(globalThis);
if (err_int == -4094) return bun.String.static("UNKNOWN").toJS(globalThis);

View File

@@ -1233,7 +1233,7 @@ pub fn timeLikeFromJS(globalObject: *JSC.JSGlobalObject, value: JSC.JSValue) ?Ti
return null;
}
const seconds = value.coerce(f64, globalObject);
const seconds = value.coerceToDouble(globalObject);
if (!std.math.isFinite(seconds)) {
return null;
}
@@ -1734,16 +1734,16 @@ pub fn StatType(comptime Big: bool) type {
const birthtime_ms: f64 = if (args.len > 13 and args[13].isNumber()) args[13].asNumber() else 0;
const this = This.new(.{
.dev = if (args.len > 0 and args[0].isNumber()) @intCast(args[0].toInt32()) else 0,
.mode = if (args.len > 1 and args[1].isNumber()) args[1].toInt32() else 0,
.nlink = if (args.len > 2 and args[2].isNumber()) args[2].toInt32() else 0,
.uid = if (args.len > 3 and args[3].isNumber()) args[3].toInt32() else 0,
.gid = if (args.len > 4 and args[4].isNumber()) args[4].toInt32() else 0,
.rdev = if (args.len > 5 and args[5].isNumber()) args[5].toInt32() else 0,
.blksize = if (args.len > 6 and args[6].isNumber()) args[6].toInt32() else 0,
.ino = if (args.len > 7 and args[7].isNumber()) @intCast(args[7].toInt32()) else 0,
.size = if (args.len > 8 and args[8].isNumber()) args[8].toInt32() else 0,
.blocks = if (args.len > 9 and args[9].isNumber()) args[9].toInt32() else 0,
.dev = if (args.len > 0 and args[0].isNumber()) @intCast(args[0].numberToInt32Clamp()) else 0,
.mode = if (args.len > 1 and args[1].isNumber()) args[1].numberToInt32Clamp() else 0,
.nlink = if (args.len > 2 and args[2].isNumber()) args[2].numberToInt32Clamp() else 0,
.uid = if (args.len > 3 and args[3].isNumber()) args[3].numberToInt32Clamp() else 0,
.gid = if (args.len > 4 and args[4].isNumber()) args[4].numberToInt32Clamp() else 0,
.rdev = if (args.len > 5 and args[5].isNumber()) args[5].numberToInt32Clamp() else 0,
.blksize = if (args.len > 6 and args[6].isNumber()) args[6].numberToInt32Clamp() else 0,
.ino = if (args.len > 7 and args[7].isNumber()) @intCast(args[7].numberToInt32Clamp()) else 0,
.size = if (args.len > 8 and args[8].isNumber()) args[8].numberToInt32Clamp() else 0,
.blocks = if (args.len > 9 and args[9].isNumber()) args[9].numberToInt32Clamp() else 0,
.atime_ms = atime_ms,
.mtime_ms = mtime_ms,
.ctime_ms = ctime_ms,

View File

@@ -2112,11 +2112,11 @@ pub const Expect = struct {
var pass = false;
if (value.isBigInt32()) {
pass = value.toInt32() & 1 == 1;
pass = value.numberToInt32Clamp() & 1 == 1;
} else if (value.isBigInt()) {
pass = value.toInt64() & 1 == 1;
} else if (value.isInt32()) {
const _value = value.toInt32();
const _value = value.numberToInt32Clamp();
pass = @mod(_value, 2) == 1;
} else if (value.isAnyInt()) {
const _value = value.toInt64();
@@ -3024,7 +3024,7 @@ pub const Expect = struct {
incrementExpectCallCounter();
const not = this.flags.not;
var pass = value.jsType().isArray() and @as(i32, @intCast(value.getLength(globalThis))) == size.toInt32();
var pass = value.jsType().isArray() and value.getLength(globalThis) == size.toInt64();
if (not) pass = !pass;
if (pass) return .undefined;

View File

@@ -1311,7 +1311,7 @@ pub const JestPrettyFormat = struct {
},
.Map => {
const length_value = value.get_unsafe(this.globalThis, "size") orelse JSC.JSValue.jsNumberFromInt32(0);
const length = length_value.toInt32();
const length = length_value.numberToInt32Clamp();
const prev_quote_strings = this.quote_strings;
this.quote_strings = true;
@@ -1339,7 +1339,7 @@ pub const JestPrettyFormat = struct {
},
.Set => {
const length_value = value.get_unsafe(this.globalThis, "size") orelse JSC.JSValue.jsNumberFromInt32(0);
const length = length_value.toInt32();
const length = length_value.numberToInt32Clamp();
const prev_quote_strings = this.quote_strings;
this.quote_strings = true;
@@ -2053,8 +2053,8 @@ pub const JestPrettyFormat = struct {
const number_value = expect.ExpectCloseTo.numberValueGetCached(value) orelse return true;
const digits_value = expect.ExpectCloseTo.digitsValueGetCached(value) orelse return true;
const number = number_value.toInt32();
const digits = digits_value.toInt32();
const number = number_value.numberToInt32Clamp();
const digits = digits_value.numberToInt32Clamp();
printAsymmetricMatcherPromisePrefix(matcher.flags, this, writer);
if (matcher.flags.not) {

View File

@@ -1479,7 +1479,7 @@ pub const Blob = struct {
if (try options.getTruthy(globalThis, "lastModified")) |last_modified| {
set_last_modified = true;
blob.last_modified = last_modified.coerce(f64, globalThis);
blob.last_modified = last_modified.coerceToDouble(globalThis);
}
}
}
@@ -1574,7 +1574,7 @@ pub const Blob = struct {
}
}
if (try opts.getTruthy(globalObject, "lastModified")) |last_modified| {
blob.last_modified = last_modified.coerce(f64, globalObject);
blob.last_modified = last_modified.coerceToDouble(globalObject);
}
}
}

View File

@@ -415,7 +415,7 @@ pub const Response = struct {
if (args.nextEat()) |init| {
if (init.isUndefinedOrNull()) {} else if (init.isNumber()) {
response.init.status_code = @as(u16, @intCast(@min(@max(0, init.toInt32()), std.math.maxInt(u16))));
response.init.status_code = @as(u16, @intCast(@min(@max(0, init.numberToInt32Clamp()), std.math.maxInt(u16))));
} else {
if (Response.Init.init(globalThis, init) catch |err| if (err == error.JSError) return .zero else null) |_init| {
response.init = _init;
@@ -466,7 +466,7 @@ pub const Response = struct {
if (args.nextEat()) |init| {
if (init.isUndefinedOrNull()) {} else if (init.isNumber()) {
response.init.status_code = @as(u16, @intCast(@min(@max(0, init.toInt32()), std.math.maxInt(u16))));
response.init.status_code = @as(u16, @intCast(@min(@max(0, init.numberToInt32Clamp()), std.math.maxInt(u16))));
} else {
if (Response.Init.init(globalThis, init) catch |err|
if (err == error.JSError) return .zero else null) |_init|

View File

@@ -8384,7 +8384,7 @@ pub const Macro = struct {
},
.Integer => {
return Expr.init(E.Number, E.Number{ .value = @as(f64, @floatFromInt(value.toInt32())) }, this.caller.loc);
return Expr.init(E.Number, E.Number{ .value = @as(f64, @floatFromInt(value.numberToInt32Clamp())) }, this.caller.loc);
},
.Double => {
return Expr.init(E.Number, E.Number{ .value = value.asNumber() }, this.caller.loc);

View File

@@ -1374,7 +1374,7 @@ pub const PostgresSQLConnection = struct {
defer password_str.deref();
const database_str = arguments[4].toBunString(globalObject);
defer database_str.deref();
const ssl_mode: SSLMode = switch (arguments[5].toInt32()) {
const ssl_mode: SSLMode = switch (arguments[5].numberToInt32Clamp()) {
0 => .disable,
1 => .prefer,
2 => .require,

View File

@@ -2694,6 +2694,21 @@ describe("expect()", () => {
expect(o).toContainAnyValues([20.5]);
});
test("toBeArrayOfSize", () => {
expect([]).toBeArrayOfSize(0);
expect([1, 2, 3]).toBeArrayOfSize(3);
// holes
expect(new Array(3)).toBeArrayOfSize(3);
const nonContiguous = [1];
nonContiguous[5] = 2;
expect(nonContiguous).toBeArrayOfSize(6);
// array-likes
expect(new Uint8Array([1, 2, 3])).not.toBeArrayOfSize(3);
expect({ 0: 1, 1: 2, 2: 3 }).not.toBeArrayOfSize(3);
// size exceeds i32 range
expect(new Array(2 ** 31)).toBeArrayOfSize(2 ** 31);
});
test("toBeTruthy()", () => {
expect("test").toBeTruthy();
expect(true).toBeTruthy();