aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/bun.js/api/server.zig2
-rw-r--r--src/bun.js/api/transpiler.zig2
-rw-r--r--src/bun.js/bindings/ZigGeneratedClasses.cpp120
-rw-r--r--src/bun.js/bindings/bindings.cpp7
-rw-r--r--src/bun.js/bindings/bindings.zig10
-rw-r--r--src/bun.js/bindings/exports.zig2
-rw-r--r--src/bun.js/bindings/generated_classes.zig18
-rw-r--r--src/bun.js/bindings/headers.h5
-rw-r--r--src/bun.js/bindings/headers.zig3
-rw-r--r--src/bun.js/module_loader.zig1
-rw-r--r--src/bun.js/scripts/generate-classes.ts4
-rw-r--r--src/bun.js/test/jest.classes.ts24
-rw-r--r--src/bun.js/test/jest.zig387
-rw-r--r--src/js_ast.zig4
-rw-r--r--src/napi/napi.zig2
-rw-r--r--test/bun.js/test-test.test.ts144
16 files changed, 670 insertions, 65 deletions
diff --git a/src/bun.js/api/server.zig b/src/bun.js/api/server.zig
index 1f47af8a0..866b08e34 100644
--- a/src/bun.js/api/server.zig
+++ b/src/bun.js/api/server.zig
@@ -3942,7 +3942,7 @@ pub fn NewServer(comptime ssl_enabled_: bool, comptime debug_mode_: bool) type {
_: js.ExceptionRef,
) js.JSObjectRef {
var globalThis = ctx.ptr();
-
+ JSC.markBinding(@src());
if (arguments.len == 0) {
const fetch_error = WebCore.Fetch.fetch_error_no_args;
return JSPromise.rejectedPromiseValue(globalThis, ZigString.init(fetch_error).toErrorInstance(globalThis)).asRef();
diff --git a/src/bun.js/api/transpiler.zig b/src/bun.js/api/transpiler.zig
index c48f1f093..4b6b72565 100644
--- a/src/bun.js/api/transpiler.zig
+++ b/src/bun.js/api/transpiler.zig
@@ -606,7 +606,7 @@ fn transformOptionsFromJSC(ctx: JSC.C.JSContextRef, temp_allocator: std.mem.Allo
var length_iter = iter;
while (length_iter.next()) |value| {
if (value.isString()) {
- const length = value.getLengthOfArray(globalThis);
+ const length = @truncate(u32, value.getLengthOfArray(globalThis));
string_count += @as(u32, @boolToInt(length > 0));
total_name_buf_len += length;
}
diff --git a/src/bun.js/bindings/ZigGeneratedClasses.cpp b/src/bun.js/bindings/ZigGeneratedClasses.cpp
index 9acbbb1b1..40ced4888 100644
--- a/src/bun.js/bindings/ZigGeneratedClasses.cpp
+++ b/src/bun.js/bindings/ZigGeneratedClasses.cpp
@@ -5333,6 +5333,12 @@ JSC_DECLARE_HOST_FUNCTION(ExpectPrototype__toBeCallback);
extern "C" EncodedJSValue ExpectPrototype__toBeCloseTo(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame);
JSC_DECLARE_HOST_FUNCTION(ExpectPrototype__toBeCloseToCallback);
+extern "C" EncodedJSValue ExpectPrototype__toBeDefined(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame);
+JSC_DECLARE_HOST_FUNCTION(ExpectPrototype__toBeDefinedCallback);
+
+extern "C" EncodedJSValue ExpectPrototype__toBeFalsy(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame);
+JSC_DECLARE_HOST_FUNCTION(ExpectPrototype__toBeFalsyCallback);
+
extern "C" EncodedJSValue ExpectPrototype__toBeGreaterThan(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame);
JSC_DECLARE_HOST_FUNCTION(ExpectPrototype__toBeGreaterThanCallback);
@@ -5348,6 +5354,18 @@ JSC_DECLARE_HOST_FUNCTION(ExpectPrototype__toBeLessThanCallback);
extern "C" EncodedJSValue ExpectPrototype__toBeLessThanOrEqual(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame);
JSC_DECLARE_HOST_FUNCTION(ExpectPrototype__toBeLessThanOrEqualCallback);
+extern "C" EncodedJSValue ExpectPrototype__toBeNaN(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame);
+JSC_DECLARE_HOST_FUNCTION(ExpectPrototype__toBeNaNCallback);
+
+extern "C" EncodedJSValue ExpectPrototype__toBeNull(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame);
+JSC_DECLARE_HOST_FUNCTION(ExpectPrototype__toBeNullCallback);
+
+extern "C" EncodedJSValue ExpectPrototype__toBeTruthy(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame);
+JSC_DECLARE_HOST_FUNCTION(ExpectPrototype__toBeTruthyCallback);
+
+extern "C" EncodedJSValue ExpectPrototype__toBeUndefined(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame);
+JSC_DECLARE_HOST_FUNCTION(ExpectPrototype__toBeUndefinedCallback);
+
extern "C" EncodedJSValue ExpectPrototype__toContain(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame);
JSC_DECLARE_HOST_FUNCTION(ExpectPrototype__toContainCallback);
@@ -5419,11 +5437,17 @@ static const HashTableValue JSExpectPrototypeTableValues[] = {
{ "resolves"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { HashTableValue::GetterSetterType, ExpectPrototype__resolvesGetterWrap, 0 } },
{ "toBe"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toBeCallback, 1 } },
{ "toBeCloseTo"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toBeCloseToCallback, 1 } },
+ { "toBeDefined"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toBeDefinedCallback, 0 } },
+ { "toBeFalsy"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toBeFalsyCallback, 0 } },
{ "toBeGreaterThan"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toBeGreaterThanCallback, 1 } },
{ "toBeGreaterThanOrEqual"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toBeGreaterThanOrEqualCallback, 1 } },
{ "toBeInstanceOf"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toBeInstanceOfCallback, 1 } },
{ "toBeLessThan"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toBeLessThanCallback, 1 } },
{ "toBeLessThanOrEqual"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toBeLessThanOrEqualCallback, 1 } },
+ { "toBeNaN"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toBeNaNCallback, 0 } },
+ { "toBeNull"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toBeNullCallback, 0 } },
+ { "toBeTruthy"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toBeTruthyCallback, 0 } },
+ { "toBeUndefined"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toBeUndefinedCallback, 0 } },
{ "toContain"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toContainCallback, 1 } },
{ "toContainEqual"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toContainEqualCallback, 1 } },
{ "toEqual"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toEqualCallback, 1 } },
@@ -5529,6 +5553,38 @@ JSC_DEFINE_HOST_FUNCTION(ExpectPrototype__toBeCloseToCallback, (JSGlobalObject *
return ExpectPrototype__toBeCloseTo(thisObject->wrapped(), lexicalGlobalObject, callFrame);
}
+JSC_DEFINE_HOST_FUNCTION(ExpectPrototype__toBeDefinedCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
+{
+ auto& vm = lexicalGlobalObject->vm();
+
+ JSExpect* thisObject = jsDynamicCast<JSExpect*>(callFrame->thisValue());
+
+ if (UNLIKELY(!thisObject)) {
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ return throwVMTypeError(lexicalGlobalObject, throwScope);
+ }
+
+ JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
+
+ return ExpectPrototype__toBeDefined(thisObject->wrapped(), lexicalGlobalObject, callFrame);
+}
+
+JSC_DEFINE_HOST_FUNCTION(ExpectPrototype__toBeFalsyCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
+{
+ auto& vm = lexicalGlobalObject->vm();
+
+ JSExpect* thisObject = jsDynamicCast<JSExpect*>(callFrame->thisValue());
+
+ if (UNLIKELY(!thisObject)) {
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ return throwVMTypeError(lexicalGlobalObject, throwScope);
+ }
+
+ JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
+
+ return ExpectPrototype__toBeFalsy(thisObject->wrapped(), lexicalGlobalObject, callFrame);
+}
+
JSC_DEFINE_HOST_FUNCTION(ExpectPrototype__toBeGreaterThanCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
{
auto& vm = lexicalGlobalObject->vm();
@@ -5609,6 +5665,70 @@ JSC_DEFINE_HOST_FUNCTION(ExpectPrototype__toBeLessThanOrEqualCallback, (JSGlobal
return ExpectPrototype__toBeLessThanOrEqual(thisObject->wrapped(), lexicalGlobalObject, callFrame);
}
+JSC_DEFINE_HOST_FUNCTION(ExpectPrototype__toBeNaNCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
+{
+ auto& vm = lexicalGlobalObject->vm();
+
+ JSExpect* thisObject = jsDynamicCast<JSExpect*>(callFrame->thisValue());
+
+ if (UNLIKELY(!thisObject)) {
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ return throwVMTypeError(lexicalGlobalObject, throwScope);
+ }
+
+ JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
+
+ return ExpectPrototype__toBeNaN(thisObject->wrapped(), lexicalGlobalObject, callFrame);
+}
+
+JSC_DEFINE_HOST_FUNCTION(ExpectPrototype__toBeNullCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
+{
+ auto& vm = lexicalGlobalObject->vm();
+
+ JSExpect* thisObject = jsDynamicCast<JSExpect*>(callFrame->thisValue());
+
+ if (UNLIKELY(!thisObject)) {
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ return throwVMTypeError(lexicalGlobalObject, throwScope);
+ }
+
+ JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
+
+ return ExpectPrototype__toBeNull(thisObject->wrapped(), lexicalGlobalObject, callFrame);
+}
+
+JSC_DEFINE_HOST_FUNCTION(ExpectPrototype__toBeTruthyCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
+{
+ auto& vm = lexicalGlobalObject->vm();
+
+ JSExpect* thisObject = jsDynamicCast<JSExpect*>(callFrame->thisValue());
+
+ if (UNLIKELY(!thisObject)) {
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ return throwVMTypeError(lexicalGlobalObject, throwScope);
+ }
+
+ JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
+
+ return ExpectPrototype__toBeTruthy(thisObject->wrapped(), lexicalGlobalObject, callFrame);
+}
+
+JSC_DEFINE_HOST_FUNCTION(ExpectPrototype__toBeUndefinedCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
+{
+ auto& vm = lexicalGlobalObject->vm();
+
+ JSExpect* thisObject = jsDynamicCast<JSExpect*>(callFrame->thisValue());
+
+ if (UNLIKELY(!thisObject)) {
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ return throwVMTypeError(lexicalGlobalObject, throwScope);
+ }
+
+ JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
+
+ return ExpectPrototype__toBeUndefined(thisObject->wrapped(), lexicalGlobalObject, callFrame);
+}
+
JSC_DEFINE_HOST_FUNCTION(ExpectPrototype__toContainCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
{
auto& vm = lexicalGlobalObject->vm();
diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp
index 25a1b3fc7..f2ce1d201 100644
--- a/src/bun.js/bindings/bindings.cpp
+++ b/src/bun.js/bindings/bindings.cpp
@@ -456,7 +456,7 @@ JSC__JSValue JSC__JSValue__createEmptyObject(JSC__JSGlobalObject* globalObject,
JSC::constructEmptyObject(globalObject, globalObject->objectPrototype(), initialCapacity));
}
-uint32_t JSC__JSValue__getLengthOfArray(JSC__JSValue value, JSC__JSGlobalObject* globalObject)
+uint64_t JSC__JSValue__getLengthOfArray(JSC__JSValue value, JSC__JSGlobalObject* globalObject)
{
JSC::JSValue jsValue = JSC::JSValue::decode(value);
JSC::JSObject* object = jsValue.toObject(globalObject);
@@ -3161,3 +3161,8 @@ JSC__JSValue JSC__JSValue__fastGet_(JSC__JSValue JSValue0, JSC__JSGlobalObject*
return JSValue::encode(
value.getObject()->getIfPropertyExists(globalObject, builtinNameMap(globalObject, arg2)));
}
+
+bool JSC__JSValue__toBooleanSlow(JSC__JSValue JSValue0, JSC__JSGlobalObject* globalObject)
+{
+ return JSValue::decode(JSValue0).toBoolean(globalObject);
+}
diff --git a/src/bun.js/bindings/bindings.zig b/src/bun.js/bindings/bindings.zig
index e9e4d5cbf..a43f68772 100644
--- a/src/bun.js/bindings/bindings.zig
+++ b/src/bun.js/bindings/bindings.zig
@@ -2368,7 +2368,7 @@ pub const JSArrayIterator = struct {
return .{
.array = value,
.global = global,
- .len = value.getLengthOfArray(global),
+ .len = @truncate(u32, value.getLengthOfArray(global)),
};
}
@@ -3463,6 +3463,10 @@ pub const JSValue = enum(JSValueReprInt) {
return fromPtrAddress(@ptrToInt(addr));
}
+ pub fn toBooleanSlow(this: JSValue, global: *JSGlobalObject) bool {
+ return cppFn("toBooleanSlow", .{ this, global });
+ }
+
pub fn toBoolean(this: JSValue) bool {
if (isUndefinedOrNull(this)) {
return false;
@@ -3506,7 +3510,7 @@ pub const JSValue = enum(JSValueReprInt) {
return @intCast(u32, @maximum(this.toInt32(), 0));
}
- pub fn getLengthOfArray(this: JSValue, globalThis: *JSGlobalObject) u32 {
+ pub fn getLengthOfArray(this: JSValue, globalThis: *JSGlobalObject) u64 {
return cppFn("getLengthOfArray", .{
this,
globalThis,
@@ -3577,7 +3581,7 @@ pub const JSValue = enum(JSValueReprInt) {
return this.asNullableVoid().?;
}
- pub const Extern = [_][]const u8{ "coerceToInt32", "fastGet_", "getStaticProperty", "createUninitializedUint8Array", "fromInt64NoTruncate", "fromUInt64NoTruncate", "toUInt64NoTruncate", "asPromise", "toInt64", "_then", "put", "makeWithNameAndPrototype", "parseJSON", "symbolKeyFor", "symbolFor", "getSymbolDescription", "createInternalPromise", "asInternalPromise", "asArrayBuffer_", "fromEntries", "createTypeError", "createRangeError", "createObject2", "getIfPropertyExistsImpl", "jsType", "jsonStringify", "kind_", "isTerminationException", "isSameValue", "getLengthOfArray", "toZigString", "createStringArray", "createEmptyObject", "putRecord", "asPromise", "isClass", "getNameProperty", "getClassName", "getErrorsProperty", "toInt32", "toBoolean", "isInt32", "isIterable", "forEach", "isAggregateError", "toError", "toZigException", "isException", "toWTFString", "hasProperty", "getPropertyNames", "getDirect", "putDirect", "getIfExists", "asString", "asObject", "asNumber", "isError", "jsNull", "jsUndefined", "jsTDZValue", "jsBoolean", "jsDoubleNumber", "jsNumberFromDouble", "jsNumberFromChar", "jsNumberFromU16", "jsNumberFromInt64", "isBoolean", "isAnyInt", "isUInt32AsAnyInt", "isInt32AsAnyInt", "isNumber", "isString", "isBigInt", "isHeapBigInt", "isBigInt32", "isSymbol", "isPrimitive", "isGetterSetter", "isCustomGetterSetter", "isObject", "isCell", "asCell", "toString", "toStringOrNull", "toPropertyKey", "toPropertyKeyValue", "toObject", "toString", "getPrototype", "getPropertyByPropertyName", "eqlValue", "eqlCell", "isCallable" };
+ pub const Extern = [_][]const u8{ "coerceToInt32", "fastGet_", "getStaticProperty", "createUninitializedUint8Array", "fromInt64NoTruncate", "fromUInt64NoTruncate", "toUInt64NoTruncate", "asPromise", "toInt64", "_then", "put", "makeWithNameAndPrototype", "parseJSON", "symbolKeyFor", "symbolFor", "getSymbolDescription", "createInternalPromise", "asInternalPromise", "asArrayBuffer_", "fromEntries", "createTypeError", "createRangeError", "createObject2", "getIfPropertyExistsImpl", "jsType", "jsonStringify", "kind_", "isTerminationException", "isSameValue", "getLengthOfArray", "toZigString", "createStringArray", "createEmptyObject", "putRecord", "asPromise", "isClass", "getNameProperty", "getClassName", "getErrorsProperty", "toInt32", "toBoolean", "isInt32", "isIterable", "forEach", "isAggregateError", "toError", "toZigException", "isException", "toWTFString", "hasProperty", "getPropertyNames", "getDirect", "putDirect", "getIfExists", "asString", "asObject", "asNumber", "isError", "jsNull", "jsUndefined", "jsTDZValue", "jsBoolean", "jsDoubleNumber", "jsNumberFromDouble", "jsNumberFromChar", "jsNumberFromU16", "jsNumberFromInt64", "isBoolean", "isAnyInt", "isUInt32AsAnyInt", "isInt32AsAnyInt", "isNumber", "isString", "isBigInt", "isHeapBigInt", "isBigInt32", "isSymbol", "isPrimitive", "isGetterSetter", "isCustomGetterSetter", "isObject", "isCell", "asCell", "toString", "toStringOrNull", "toPropertyKey", "toPropertyKeyValue", "toObject", "toString", "getPrototype", "getPropertyByPropertyName", "eqlValue", "eqlCell", "isCallable", "toBooleanSlow" };
};
extern "c" fn Microtask__run(*Microtask, *JSGlobalObject) void;
diff --git a/src/bun.js/bindings/exports.zig b/src/bun.js/bindings/exports.zig
index 1c0a393ce..efa5ab9ef 100644
--- a/src/bun.js/bindings/exports.zig
+++ b/src/bun.js/bindings/exports.zig
@@ -1766,7 +1766,7 @@ pub const ZigConsoleClient = struct {
}
},
.Array => {
- const len = value.getLengthOfArray(this.globalThis);
+ const len = @truncate(u32, value.getLengthOfArray(this.globalThis));
if (len == 0) {
writer.writeAll("[]");
return;
diff --git a/src/bun.js/bindings/generated_classes.zig b/src/bun.js/bindings/generated_classes.zig
index d1d1b8f68..67f56082d 100644
--- a/src/bun.js/bindings/generated_classes.zig
+++ b/src/bun.js/bindings/generated_classes.zig
@@ -1623,6 +1623,10 @@ pub const JSExpect = struct {
@compileLog("Expected Expect.toBe to be a callback");
if (@TypeOf(Expect.toBeCloseTo) != CallbackType)
@compileLog("Expected Expect.toBeCloseTo to be a callback");
+ if (@TypeOf(Expect.toBeDefined) != CallbackType)
+ @compileLog("Expected Expect.toBeDefined to be a callback");
+ if (@TypeOf(Expect.toBeFalsy) != CallbackType)
+ @compileLog("Expected Expect.toBeFalsy to be a callback");
if (@TypeOf(Expect.toBeGreaterThan) != CallbackType)
@compileLog("Expected Expect.toBeGreaterThan to be a callback");
if (@TypeOf(Expect.toBeGreaterThanOrEqual) != CallbackType)
@@ -1633,6 +1637,14 @@ pub const JSExpect = struct {
@compileLog("Expected Expect.toBeLessThan to be a callback");
if (@TypeOf(Expect.toBeLessThanOrEqual) != CallbackType)
@compileLog("Expected Expect.toBeLessThanOrEqual to be a callback");
+ if (@TypeOf(Expect.toBeNaN) != CallbackType)
+ @compileLog("Expected Expect.toBeNaN to be a callback");
+ if (@TypeOf(Expect.toBeNull) != CallbackType)
+ @compileLog("Expected Expect.toBeNull to be a callback");
+ if (@TypeOf(Expect.toBeTruthy) != CallbackType)
+ @compileLog("Expected Expect.toBeTruthy to be a callback");
+ if (@TypeOf(Expect.toBeUndefined) != CallbackType)
+ @compileLog("Expected Expect.toBeUndefined to be a callback");
if (@TypeOf(Expect.toContain) != CallbackType)
@compileLog("Expected Expect.toContain to be a callback");
if (@TypeOf(Expect.toContainEqual) != CallbackType)
@@ -1728,11 +1740,17 @@ pub const JSExpect = struct {
@export(Expect.stringMatching, .{ .name = "ExpectClass__stringMatching" });
@export(Expect.toBe, .{ .name = "ExpectPrototype__toBe" });
@export(Expect.toBeCloseTo, .{ .name = "ExpectPrototype__toBeCloseTo" });
+ @export(Expect.toBeDefined, .{ .name = "ExpectPrototype__toBeDefined" });
+ @export(Expect.toBeFalsy, .{ .name = "ExpectPrototype__toBeFalsy" });
@export(Expect.toBeGreaterThan, .{ .name = "ExpectPrototype__toBeGreaterThan" });
@export(Expect.toBeGreaterThanOrEqual, .{ .name = "ExpectPrototype__toBeGreaterThanOrEqual" });
@export(Expect.toBeInstanceOf, .{ .name = "ExpectPrototype__toBeInstanceOf" });
@export(Expect.toBeLessThan, .{ .name = "ExpectPrototype__toBeLessThan" });
@export(Expect.toBeLessThanOrEqual, .{ .name = "ExpectPrototype__toBeLessThanOrEqual" });
+ @export(Expect.toBeNaN, .{ .name = "ExpectPrototype__toBeNaN" });
+ @export(Expect.toBeNull, .{ .name = "ExpectPrototype__toBeNull" });
+ @export(Expect.toBeTruthy, .{ .name = "ExpectPrototype__toBeTruthy" });
+ @export(Expect.toBeUndefined, .{ .name = "ExpectPrototype__toBeUndefined" });
@export(Expect.toContain, .{ .name = "ExpectPrototype__toContain" });
@export(Expect.toContainEqual, .{ .name = "ExpectPrototype__toContainEqual" });
@export(Expect.toEqual, .{ .name = "ExpectPrototype__toEqual" });
diff --git a/src/bun.js/bindings/headers.h b/src/bun.js/bindings/headers.h
index a3f71adb3..ffaa896df 100644
--- a/src/bun.js/bindings/headers.h
+++ b/src/bun.js/bindings/headers.h
@@ -1,5 +1,5 @@
// clang-format off
-//-- AUTOGENERATED FILE -- 1667784809
+//-- AUTOGENERATED FILE -- 1668835252
#pragma once
#include <stddef.h>
@@ -496,7 +496,7 @@ CPP_DECL JSC__JSValue JSC__JSValue__fromUInt64NoTruncate(JSC__JSGlobalObject* ar
CPP_DECL void JSC__JSValue__getClassName(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, ZigString* arg2);
CPP_DECL JSC__JSValue JSC__JSValue__getErrorsProperty(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1);
CPP_DECL JSC__JSValue JSC__JSValue__getIfPropertyExistsImpl(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, const unsigned char* arg2, uint32_t arg3);
-CPP_DECL uint32_t JSC__JSValue__getLengthOfArray(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1);
+CPP_DECL uint64_t JSC__JSValue__getLengthOfArray(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1);
CPP_DECL void JSC__JSValue__getNameProperty(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, ZigString* arg2);
CPP_DECL JSC__JSValue JSC__JSValue__getPrototype(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1);
CPP_DECL void JSC__JSValue__getSymbolDescription(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, ZigString* arg2);
@@ -542,6 +542,7 @@ CPP_DECL void JSC__JSValue__putRecord(JSC__JSValue JSValue0, JSC__JSGlobalObject
CPP_DECL JSC__JSValue JSC__JSValue__symbolFor(JSC__JSGlobalObject* arg0, ZigString* arg1);
CPP_DECL bool JSC__JSValue__symbolKeyFor(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, ZigString* arg2);
CPP_DECL bool JSC__JSValue__toBoolean(JSC__JSValue JSValue0);
+CPP_DECL bool JSC__JSValue__toBooleanSlow(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1);
CPP_DECL JSC__JSValue JSC__JSValue__toError(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1);
CPP_DECL int32_t JSC__JSValue__toInt32(JSC__JSValue JSValue0);
CPP_DECL int64_t JSC__JSValue__toInt64(JSC__JSValue JSValue0);
diff --git a/src/bun.js/bindings/headers.zig b/src/bun.js/bindings/headers.zig
index e0909ba8c..5e7ace610 100644
--- a/src/bun.js/bindings/headers.zig
+++ b/src/bun.js/bindings/headers.zig
@@ -289,7 +289,7 @@ pub extern fn JSC__JSValue__fromUInt64NoTruncate(arg0: ?*JSC__JSGlobalObject, ar
pub extern fn JSC__JSValue__getClassName(JSValue0: JSC__JSValue, arg1: ?*JSC__JSGlobalObject, arg2: [*c]ZigString) void;
pub extern fn JSC__JSValue__getErrorsProperty(JSValue0: JSC__JSValue, arg1: ?*JSC__JSGlobalObject) JSC__JSValue;
pub extern fn JSC__JSValue__getIfPropertyExistsImpl(JSValue0: JSC__JSValue, arg1: ?*JSC__JSGlobalObject, arg2: [*c]const u8, arg3: u32) JSC__JSValue;
-pub extern fn JSC__JSValue__getLengthOfArray(JSValue0: JSC__JSValue, arg1: ?*JSC__JSGlobalObject) u32;
+pub extern fn JSC__JSValue__getLengthOfArray(JSValue0: JSC__JSValue, arg1: ?*JSC__JSGlobalObject) u64;
pub extern fn JSC__JSValue__getNameProperty(JSValue0: JSC__JSValue, arg1: ?*JSC__JSGlobalObject, arg2: [*c]ZigString) void;
pub extern fn JSC__JSValue__getPrototype(JSValue0: JSC__JSValue, arg1: ?*JSC__JSGlobalObject) JSC__JSValue;
pub extern fn JSC__JSValue__getSymbolDescription(JSValue0: JSC__JSValue, arg1: ?*JSC__JSGlobalObject, arg2: [*c]ZigString) void;
@@ -335,6 +335,7 @@ pub extern fn JSC__JSValue__putRecord(JSValue0: JSC__JSValue, arg1: ?*JSC__JSGlo
pub extern fn JSC__JSValue__symbolFor(arg0: ?*JSC__JSGlobalObject, arg1: [*c]ZigString) JSC__JSValue;
pub extern fn JSC__JSValue__symbolKeyFor(JSValue0: JSC__JSValue, arg1: ?*JSC__JSGlobalObject, arg2: [*c]ZigString) bool;
pub extern fn JSC__JSValue__toBoolean(JSValue0: JSC__JSValue) bool;
+pub extern fn JSC__JSValue__toBooleanSlow(JSValue0: JSC__JSValue, arg1: ?*JSC__JSGlobalObject) bool;
pub extern fn JSC__JSValue__toError(JSValue0: JSC__JSValue, arg1: ?*JSC__JSGlobalObject) JSC__JSValue;
pub extern fn JSC__JSValue__toInt32(JSValue0: JSC__JSValue) i32;
pub extern fn JSC__JSValue__toInt64(JSValue0: JSC__JSValue) i64;
diff --git a/src/bun.js/module_loader.zig b/src/bun.js/module_loader.zig
index 59a4288fb..290f3bf85 100644
--- a/src/bun.js/module_loader.zig
+++ b/src/bun.js/module_loader.zig
@@ -547,6 +547,7 @@ pub const ModuleLoader = struct {
}
pub fn onDone(this: *AsyncModule) void {
+ JSC.markBinding(@src());
var jsc_vm = this.globalThis.bunVM();
jsc_vm.modules.scheduled -= 1;
if (jsc_vm.modules.scheduled == 0) {
diff --git a/src/bun.js/scripts/generate-classes.ts b/src/bun.js/scripts/generate-classes.ts
index 6689667b2..aa0eab9d8 100644
--- a/src/bun.js/scripts/generate-classes.ts
+++ b/src/bun.js/scripts/generate-classes.ts
@@ -823,7 +823,7 @@ JSC_DEFINE_CUSTOM_GETTER(${symbolName(
typeName,
proto[name].getter,
)}(thisObject->wrapped(),${
- proto[name].this!! ? " thisValue, " : ""
+ !!proto[name].this ? " thisValue, " : ""
} globalObject);
RETURN_IF_EXCEPTION(throwScope, {});
RELEASE_AND_RETURN(throwScope, result);
@@ -852,7 +852,7 @@ JSC_DEFINE_CUSTOM_SETTER(${symbolName(
typeName,
proto[name].setter || proto[name].accessor.setter,
)}(thisObject->wrapped(),${
- proto[name].this!! ? " thisValue, " : ""
+ !!proto[name].this ? " thisValue, " : ""
} lexicalGlobalObject, encodedValue);
RELEASE_AND_RETURN(throwScope, result);
diff --git a/src/bun.js/test/jest.classes.ts b/src/bun.js/test/jest.classes.ts
index d1d225f64..ad2a5d6e8 100644
--- a/src/bun.js/test/jest.classes.ts
+++ b/src/bun.js/test/jest.classes.ts
@@ -128,6 +128,30 @@ export default [
fn: "toBeInstanceOf",
length: 1,
},
+ toBeTruthy: {
+ fn: "toBeTruthy",
+ length: 0,
+ },
+ toBeUndefined: {
+ fn: "toBeUndefined",
+ length: 0,
+ },
+ toBeNaN: {
+ fn: "toBeNaN",
+ length: 0,
+ },
+ toBeNull: {
+ fn: "toBeNull",
+ length: 0,
+ },
+ toBeFalsy: {
+ fn: "toBeFalsy",
+ length: 0,
+ },
+ toBeDefined: {
+ fn: "toBeDefined",
+ length: 0,
+ },
toContain: {
fn: "toContain",
length: 1,
diff --git a/src/bun.js/test/jest.zig b/src/bun.js/test/jest.zig
index 4d67ea97f..3439e46a4 100644
--- a/src/bun.js/test/jest.zig
+++ b/src/bun.js/test/jest.zig
@@ -37,6 +37,7 @@ const JSPromise = JSC.JSPromise;
const JSValue = JSC.JSValue;
const JSError = JSC.JSError;
const JSGlobalObject = JSC.JSGlobalObject;
+const JSObject = JSC.JSObject;
const VirtualMachine = @import("../javascript.zig").VirtualMachine;
const Task = @import("../javascript.zig").Task;
@@ -315,31 +316,29 @@ pub const Expect = struct {
return .zero;
};
right.ensureStillAlive();
- const eql = left.isSameValue(right, globalObject);
+
+ const not = this.op.contains(.not);
+ var pass = left.isSameValue(right, globalObject);
if (comptime Environment.allow_assert) {
- std.debug.assert(eql == JSC.C.JSValueIsStrictEqual(globalObject, left.asObjectRef(), right.asObjectRef()));
+ std.debug.assert(pass == JSC.C.JSValueIsStrictEqual(globalObject, left.asObjectRef(), right.asObjectRef()));
}
- if (!eql) {
- var lhs_formatter: JSC.ZigConsoleClient.Formatter = JSC.ZigConsoleClient.Formatter{ .globalThis = globalObject };
- var rhs_formatter: JSC.ZigConsoleClient.Formatter = JSC.ZigConsoleClient.Formatter{ .globalThis = globalObject };
-
- if (comptime Environment.allow_assert) {
- Output.prettyErrorln("\nJSType: {s}\nJSType: {s}\n\n", .{ @tagName(left.jsType()), @tagName(right.jsType()) });
- }
-
- globalObject.throw(
- "Expected: {any}\n\tReceived: {any}",
- .{
- left.toFmt(globalObject, &lhs_formatter),
- right.toFmt(globalObject, &rhs_formatter),
- },
- );
+ if (not) pass = !pass;
+ if (pass) return thisValue;
- return .zero;
+ // handle failure
+ var lhs_fmt = JSC.ZigConsoleClient.Formatter{ .globalThis = globalObject };
+ var rhs_fmt = JSC.ZigConsoleClient.Formatter{ .globalThis = globalObject };
+ if (comptime Environment.allow_assert) {
+ Output.prettyErrorln("\nJSType: {s}\nJSType: {s}\n\n", .{ @tagName(left.jsType()), @tagName(right.jsType()) });
}
- return thisValue;
+ if (not) {
+ globalObject.throw("\n\tExpected: not {any}\n\tReceived: {any}", .{ left.toFmt(globalObject, &lhs_fmt), right.toFmt(globalObject, &rhs_fmt) });
+ } else {
+ globalObject.throw("\n\tExpected: {any}\n\tReceived: {any}", .{ left.toFmt(globalObject, &lhs_fmt), right.toFmt(globalObject, &rhs_fmt) });
+ }
+ return .zero;
}
pub fn toHaveLength(
@@ -363,25 +362,304 @@ pub const Expect = struct {
active_test_expectation_counter.actual += 1;
- const expected = arguments[0].coerce(i32, globalObject);
- const value = JSC.Jest.Expect.capturedValueGetCached(thisValue) orelse {
+ const expected: JSValue = arguments[0];
+ const value: JSValue = JSC.Jest.Expect.capturedValueGetCached(thisValue) orelse {
globalObject.throw("Internal consistency error: the expect(value) was garbage collected but it should not have been!", .{});
return .zero;
};
- const actual = value.getLengthOfArray(globalObject);
- if (expected != actual) {
- globalObject.throw("Expected length to equal {d} but received {d}\n Expected: {d}\n Actual: {d}\n", .{
- expected,
- actual,
- expected,
- actual,
- });
+ value.ensureStillAlive();
+
+ if (!value.isObject() and !value.isString()) {
+ var fmt = JSC.ZigConsoleClient.Formatter{ .globalThis = globalObject };
+ globalObject.throw("Received value does not have a length property: {any}", .{value.toFmt(globalObject, &fmt)});
return .zero;
}
- return thisValue;
+ if (!expected.isNumber()) {
+ var fmt = JSC.ZigConsoleClient.Formatter{ .globalThis = globalObject };
+ globalObject.throw("Expected value must be a non-negative integer: {any}", .{expected.toFmt(globalObject, &fmt)});
+ return .zero;
+ }
+
+ const expected_length: f64 = expected.asNumber();
+ if (@round(expected_length) != expected_length or std.math.isInf(expected_length) or std.math.isNan(expected_length) or expected_length < 0) {
+ var fmt = JSC.ZigConsoleClient.Formatter{ .globalThis = globalObject };
+ globalObject.throw("Expected value must be a non-negative integer: {any}", .{expected.toFmt(globalObject, &fmt)});
+ return .zero;
+ }
+
+ const not = this.op.contains(.not);
+ var pass = false;
+
+ var actual_length: f64 = undefined;
+ if (value.isString()) {
+ actual_length = @intToFloat(f64, value.asString().length());
+ if (actual_length == expected_length) pass = true;
+ } else {
+ const length_value: JSValue = value.getIfPropertyExistsImpl(globalObject, "length", "length".len);
+
+ if (length_value.isEmpty()) {
+ var fmt = JSC.ZigConsoleClient.Formatter{ .globalThis = globalObject };
+ globalObject.throw("Received value does not have a length property: {any}", .{value.toFmt(globalObject, &fmt)});
+ return .zero;
+ } else if (!length_value.isNumber()) {
+ var fmt = JSC.ZigConsoleClient.Formatter{ .globalThis = globalObject };
+ globalObject.throw("Received value has non-number length property: {any}", .{length_value.toFmt(globalObject, &fmt)});
+ return .zero;
+ }
+
+ actual_length = length_value.asNumber();
+ if (@round(actual_length) == actual_length) {
+ if (actual_length == expected_length) pass = true;
+ }
+ }
+
+ if (not) pass = !pass;
+ if (pass) return thisValue;
+
+ // handle failure
+ if (not) {
+ globalObject.throw("\n\tExpected: not {d}\n\tReceived: {d}", .{ expected_length, actual_length });
+ } else {
+ globalObject.throw("\n\tExpected: {d}\n\tReceived: {d}", .{ expected_length, actual_length });
+ }
+ return .zero;
+ }
+
+ pub fn toContain(
+ this: *Expect,
+ globalObject: *JSC.JSGlobalObject,
+ callFrame: *JSC.CallFrame,
+ ) callconv(.C) JSC.JSValue {
+ const thisValue = callFrame.this();
+ const arguments_ = callFrame.arguments(1);
+ const arguments = arguments_.ptr[0..arguments_.len];
+
+ if (arguments.len < 1) {
+ globalObject.throwInvalidArguments("toContain() takes 1 argument", .{});
+ return .zero;
+ }
+
+ if (this.scope.tests.items.len <= this.test_id) {
+ globalObject.throw("toContain() must be called in a test", .{});
+ return .zero;
+ }
+
+ active_test_expectation_counter.actual += 1;
+
+ const expected = arguments[0];
+ expected.ensureStillAlive();
+ const value: JSValue = JSC.Jest.Expect.capturedValueGetCached(thisValue) orelse {
+ globalObject.throw("Internal consistency error: the expect(value) was garbage collected but it should not have been!", .{});
+ return .zero;
+ };
+ value.ensureStillAlive();
+
+ const not = this.op.contains(.not);
+ var pass = false;
+
+ if (value.isIterable(globalObject)) {
+ var itr = value.arrayIterator(globalObject);
+ while (itr.next()) |item| {
+ if (item.isSameValue(expected, globalObject)) {
+ pass = true;
+ break;
+ }
+ }
+ } else if (value.isString() and expected.isString()) {
+ const value_string = value.toString(globalObject).toSlice(globalObject, default_allocator).slice();
+ const expected_string = expected.toString(globalObject).toSlice(globalObject, default_allocator).slice();
+ if (strings.contains(value_string, expected_string)) {
+ pass = true;
+ }
+ } else {
+ globalObject.throw("Received value must be an array type, or both received and expected values must be strings.", .{});
+ return .zero;
+ }
+
+ if (not) pass = !pass;
+ if (pass) return thisValue;
+
+ // handle failure
+ var fmt = JSC.ZigConsoleClient.Formatter{ .globalThis = globalObject };
+ if (not) {
+ globalObject.throw("Expected to not contain \"{any}\"", .{expected.toFmt(globalObject, &fmt)});
+ } else {
+ globalObject.throw("Expected to contain \"{any}\"", .{expected.toFmt(globalObject, &fmt)});
+ }
+ return .zero;
}
+ pub fn toBeTruthy(this: *Expect, globalObject: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSC.JSValue {
+ const thisValue = callFrame.this();
+ const value: JSValue = Expect.capturedValueGetCached(thisValue) orelse {
+ globalObject.throw("Internal consistency error: the expect(value) was garbage collected but it should not have been!", .{});
+ return .zero;
+ };
+ value.ensureStillAlive();
+
+ if (this.scope.tests.items.len <= this.test_id) {
+ globalObject.throw("toBeTruthy() must be called in a test", .{});
+ return .zero;
+ }
+
+ active_test_expectation_counter.actual += 1;
+
+ const not = this.op.contains(.not);
+ var pass = false;
+
+ const truthy = value.toBooleanSlow(globalObject);
+ if (truthy) pass = true;
+
+ if (not) pass = !pass;
+ if (pass) return thisValue;
+
+ // handle failure
+ var fmt = JSC.ZigConsoleClient.Formatter{ .globalThis = globalObject };
+ if (not) {
+ globalObject.throw("Expected \"{any}\" to be not truthy.", .{value.toFmt(globalObject, &fmt)});
+ } else {
+ globalObject.throw("Expected \"{any}\" to be truthy.", .{value.toFmt(globalObject, &fmt)});
+ }
+ return .zero;
+ }
+
+ pub fn toBeUndefined(this: *Expect, globalObject: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSC.JSValue {
+ const thisValue = callFrame.this();
+ const value: JSValue = Expect.capturedValueGetCached(thisValue) orelse {
+ globalObject.throw("Interal consistency error: the expect(value) was garbage collected but it should not have been!", .{});
+ return .zero;
+ };
+ value.ensureStillAlive();
+
+ active_test_expectation_counter.actual += 1;
+
+ const not = this.op.contains(.not);
+ var pass = false;
+ if (value.isUndefined()) pass = true;
+
+ if (not) pass = !pass;
+ if (pass) return thisValue;
+
+ // handle failure
+ var fmt = JSC.ZigConsoleClient.Formatter{ .globalThis = globalObject };
+ if (not) {
+ globalObject.throw("Expected \"{any}\" to be not undefined.", .{value.toFmt(globalObject, &fmt)});
+ } else {
+ globalObject.throw("Expected \"{any}\" to be undefined.", .{value.toFmt(globalObject, &fmt)});
+ }
+ return .zero;
+ }
+
+ pub fn toBeNaN(this: *Expect, globalObject: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSC.JSValue {
+ const thisValue = callFrame.this();
+ const value: JSValue = Expect.capturedValueGetCached(thisValue) orelse {
+ globalObject.throw("Interal consistency error: the expect(value) was garbage collected but it should not have been!", .{});
+ return .zero;
+ };
+ value.ensureStillAlive();
+
+ active_test_expectation_counter.actual += 1;
+
+ const not = this.op.contains(.not);
+ var pass = false;
+ if (value.isNumber()) {
+ const number = value.asNumber();
+ if (number != number) pass = true;
+ }
+
+ if (not) pass = !pass;
+ if (pass) return thisValue;
+
+ // handle failure
+ var fmt = JSC.ZigConsoleClient.Formatter{ .globalThis = globalObject };
+ if (not) {
+ globalObject.throw("Expected \"{any}\" to be not NaN.", .{value.toFmt(globalObject, &fmt)});
+ } else {
+ globalObject.throw("Expected \"{any}\" to be NaN.", .{value.toFmt(globalObject, &fmt)});
+ }
+ return .zero;
+ }
+
+ pub fn toBeNull(this: *Expect, globalObject: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSC.JSValue {
+ const thisValue = callFrame.this();
+ const value: JSValue = Expect.capturedValueGetCached(thisValue) orelse {
+ globalObject.throw("Interal consistency error: the expect(value) was garbage collected but it should not have been!", .{});
+ return .zero;
+ };
+ value.ensureStillAlive();
+
+ active_test_expectation_counter.actual += 1;
+
+ const not = this.op.contains(.not);
+ var pass = value.isNull();
+ if (not) pass = !pass;
+ if (pass) return thisValue;
+
+ // handle failure
+ var fmt = JSC.ZigConsoleClient.Formatter{ .globalThis = globalObject };
+ if (not) {
+ globalObject.throw("Expected \"{any}\" to be not null.", .{value.toFmt(globalObject, &fmt)});
+ } else {
+ globalObject.throw("Expected \"{any}\" to be null.", .{value.toFmt(globalObject, &fmt)});
+ }
+ return .zero;
+ }
+
+ pub fn toBeDefined(this: *Expect, globalObject: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSC.JSValue {
+ const thisValue = callFrame.this();
+ const value: JSValue = Expect.capturedValueGetCached(thisValue) orelse {
+ globalObject.throw("Interal consistency error: the expect(value) was garbage collected but it should not have been!", .{});
+ return .zero;
+ };
+ value.ensureStillAlive();
+
+ active_test_expectation_counter.actual += 1;
+
+ const not = this.op.contains(.not);
+ var pass = !value.isUndefined();
+ if (not) pass = !pass;
+ if (pass) return thisValue;
+
+ // handle failure
+ var fmt = JSC.ZigConsoleClient.Formatter{ .globalThis = globalObject };
+ if (not) {
+ globalObject.throw("Expected \"{any}\" to be not defined.", .{value.toFmt(globalObject, &fmt)});
+ } else {
+ globalObject.throw("Expected \"{any}\" to be defined.", .{value.toFmt(globalObject, &fmt)});
+ }
+ return .zero;
+ }
+
+ pub fn toBeFalsy(this: *Expect, globalObject: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSC.JSValue {
+ const thisValue = callFrame.this();
+
+ const value: JSValue = Expect.capturedValueGetCached(thisValue) orelse {
+ globalObject.throw("internal consistency error: the expect(value) was garbage collected but it should not have been!", .{});
+ return .zero;
+ };
+ value.ensureStillAlive();
+
+ const not = this.op.contains(.not);
+ var pass = false;
+
+ const truthy = value.toBooleanSlow(globalObject);
+ if (!truthy) pass = true;
+
+ if (not) pass = !pass;
+ if (pass) return thisValue;
+
+ // handle failure
+ var fmt = JSC.ZigConsoleClient.Formatter{ .globalThis = globalObject };
+ if (not) {
+ globalObject.throw("Expected \"{any}\" to be not falsy.", .{value.toFmt(globalObject, &fmt)});
+ } else {
+ globalObject.throw("Expected \"{any}\" to be falsy.", .{value.toFmt(globalObject, &fmt)});
+ }
+ return .zero;
+ }
+
+ pub const toHaveProperty = notImplementedJSCFn;
pub const toHaveBeenCalledTimes = notImplementedJSCFn;
pub const toHaveBeenCalledWith = notImplementedJSCFn;
pub const toHaveBeenLastCalledWith = notImplementedJSCFn;
@@ -390,14 +668,12 @@ pub const Expect = struct {
pub const toHaveReturnedWith = notImplementedJSCFn;
pub const toHaveLastReturnedWith = notImplementedJSCFn;
pub const toHaveNthReturnedWith = notImplementedJSCFn;
- pub const toHaveProperty = notImplementedJSCFn;
pub const toBeCloseTo = notImplementedJSCFn;
pub const toBeGreaterThan = notImplementedJSCFn;
pub const toBeGreaterThanOrEqual = notImplementedJSCFn;
pub const toBeLessThan = notImplementedJSCFn;
pub const toBeLessThanOrEqual = notImplementedJSCFn;
pub const toBeInstanceOf = notImplementedJSCFn;
- pub const toContain = notImplementedJSCFn;
pub const toContainEqual = notImplementedJSCFn;
pub const toEqual = notImplementedJSCFn;
pub const toMatch = notImplementedJSCFn;
@@ -409,6 +685,35 @@ pub const Expect = struct {
pub const toThrowErrorMatchingSnapshot = notImplementedJSCFn;
pub const toThrowErrorMatchingInlineSnapshot = notImplementedJSCFn;
+ pub const getStaticNot = notImplementedStaticProp;
+ pub const getStaticResolves = notImplementedStaticProp;
+ pub const getStaticRejects = notImplementedStaticProp;
+
+ pub fn getNot(this: *Expect, thisValue: JSValue, globalObject: *JSGlobalObject) callconv(.C) JSValue {
+ _ = Expect.capturedValueGetCached(thisValue) orelse {
+ globalObject.throw("Internal consistency error: the expect(value) was garbage collected but it should not have been!", .{});
+ return .zero;
+ };
+
+ this.op.toggle(.not);
+
+ return thisValue;
+ }
+
+ pub const getResolves = notImplementedJSCProp;
+ pub const getRejects = notImplementedJSCProp;
+
+ pub const extend = notImplementedStaticFn;
+ pub const anything = notImplementedStaticFn;
+ pub const any = notImplementedStaticFn;
+ pub const arrayContaining = notImplementedStaticFn;
+ pub const assertions = notImplementedStaticFn;
+ pub const hasAssertions = notImplementedStaticFn;
+ pub const objectContaining = notImplementedStaticFn;
+ pub const stringContaining = notImplementedStaticFn;
+ pub const stringMatching = notImplementedStaticFn;
+ pub const addSnapshotSerializer = notImplementedStaticFn;
+
pub fn notImplementedJSCFn(_: *Expect, globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue {
globalObject.throw("Not implemented", .{});
return .zero;
@@ -428,24 +733,6 @@ pub const Expect = struct {
globalObject.throw("Not implemented", .{});
return .zero;
}
-
- pub const getStaticNot = notImplementedStaticProp;
- pub const getStaticResolves = notImplementedStaticProp;
- pub const getStaticRejects = notImplementedStaticProp;
- pub const getNot = notImplementedJSCProp;
- pub const getResolves = notImplementedJSCProp;
- pub const getRejects = notImplementedJSCProp;
-
- pub const extend = notImplementedStaticFn;
- pub const anything = notImplementedStaticFn;
- pub const any = notImplementedStaticFn;
- pub const arrayContaining = notImplementedStaticFn;
- pub const assertions = notImplementedStaticFn;
- pub const hasAssertions = notImplementedStaticFn;
- pub const objectContaining = notImplementedStaticFn;
- pub const stringContaining = notImplementedStaticFn;
- pub const stringMatching = notImplementedStaticFn;
- pub const addSnapshotSerializer = notImplementedStaticFn;
};
pub const TestScope = struct {
diff --git a/src/js_ast.zig b/src/js_ast.zig
index 0bd73c93f..0ca11272a 100644
--- a/src/js_ast.zig
+++ b/src/js_ast.zig
@@ -7128,7 +7128,7 @@ pub const Macro = struct {
while (i < count) {
var nextArg = writer.eatArg() orelse return false;
if (js.JSValueIsArray(writer.ctx, nextArg.asRef())) {
- const extras = nextArg.getLengthOfArray(writer.ctx.ptr());
+ const extras = @truncate(u32, nextArg.getLengthOfArray(writer.ctx.ptr()));
count += std.math.max(@truncate(@TypeOf(count), extras), 1) - 1;
items.ensureUnusedCapacity(extras) catch unreachable;
items.expandToCapacity();
@@ -7511,7 +7511,7 @@ pub const Macro = struct {
.allocator = JSCBase.getAllocator(ctx),
.exception = exception,
.args_value = args_value,
- .args_len = args_value.getLengthOfArray(ctx.ptr()),
+ .args_len = @truncate(u32, args_value.getLengthOfArray(ctx.ptr())),
.args_i = 0,
.errored = false,
};
diff --git a/src/napi/napi.zig b/src/napi/napi.zig
index c30f1d565..260e5ba22 100644
--- a/src/napi/napi.zig
+++ b/src/napi/napi.zig
@@ -604,7 +604,7 @@ pub export fn napi_get_array_length(env: napi_env, value: napi_value, result: [*
return .array_expected;
}
- result.* = value.getLengthOfArray(env);
+ result.* = @truncate(u32, value.getLengthOfArray(env));
return .ok;
}
pub export fn napi_strict_equals(env: napi_env, lhs: napi_value, rhs: napi_value, result: *bool) napi_status {
diff --git a/test/bun.js/test-test.test.ts b/test/bun.js/test-test.test.ts
new file mode 100644
index 000000000..8ada29ed0
--- /dev/null
+++ b/test/bun.js/test-test.test.ts
@@ -0,0 +1,144 @@
+import { expect, test } from "@jest/globals";
+
+test("toBe()", () => {
+ const a = 1;
+ const b = 1;
+ expect(a).toBe(a);
+ expect(a).toBe(b);
+ expect(a).toBe(1);
+ expect(1).toBe(a);
+ expect(b).toBe(a);
+
+ const c = { a: 1 };
+ const d = { a: 1 };
+ expect(c).toBe(c);
+ expect(c).not.toBe(d);
+ expect(c).not.toBe({ a: 1 });
+ expect({ a: 1 }).not.toBe(c);
+ expect(d).not.toBe(c);
+
+ expect(1).toBe(1);
+ // expect(1).not.toBe(1);
+
+ expect(1).not.toBe(2);
+ expect(1).not.toBe("1");
+ expect("hello test").toBe("hello test");
+ expect("hello test").not.toBe("hello test2");
+});
+
+test("toHaveLength()", () => {
+ expect({ length: Number.MAX_SAFE_INTEGER }).toHaveLength(
+ Number.MAX_SAFE_INTEGER,
+ );
+ expect("123").toHaveLength(3);
+ expect([1, 2, 3]).toHaveLength(3);
+ expect([1, 2, 3]).not.toHaveLength(2);
+ expect("123").not.toHaveLength(2);
+ expect({ length: 3 }).toHaveLength(3);
+ expect({ length: 3 }).not.toHaveLength(2);
+ expect({ length: 3 }).not.toHaveLength(Number.MAX_SAFE_INTEGER);
+ expect({ length: Number.MAX_SAFE_INTEGER }).not.toHaveLength(
+ Number.MAX_SAFE_INTEGER - 1,
+ );
+ expect({ length: 3.3 }).not.toHaveLength(3);
+ expect("123").not.toHaveLength(-0);
+});
+
+test("toContain()", () => {
+ const s1 = new String("123");
+ expect(s1).not.toContain("12");
+ const s2 = "123";
+ expect(s2).toContain("12");
+
+ expect("test").toContain("es");
+ expect("test").toContain("est");
+ expect("test").toContain("test");
+ expect(["test", "es"]).toContain("es");
+ expect("").toContain("");
+ expect([""]).toContain("");
+
+ expect(["lemon", "lime"]).not.toContain("orange");
+ expect("citrus fruits").toContain("fruit");
+
+ const a = new Uint16Array([1, 2, 3]);
+ expect(a).toContain(2);
+ expect(a).not.toContain(4);
+ // expect([4, 5, 6]).not.toContain(5);
+
+ expect([]).not.toContain([]);
+});
+
+test("toBeTruthy()", () => {
+ expect("test").toBeTruthy();
+ expect(true).toBeTruthy();
+ expect(1).toBeTruthy();
+ expect({}).toBeTruthy();
+ expect([]).toBeTruthy();
+ expect(() => {}).toBeTruthy();
+ // expect(() => {}).not.toBeTruthy();
+
+ expect("").not.toBeTruthy();
+ expect(0).not.toBeTruthy();
+ expect(-0).not.toBeTruthy();
+ expect(NaN).not.toBeTruthy();
+ expect(0n).not.toBeTruthy();
+ expect(false).not.toBeTruthy();
+ expect(null).not.toBeTruthy();
+ expect(undefined).not.toBeTruthy();
+});
+
+test("toBeUndefined()", () => {
+ expect(undefined).toBeUndefined();
+ // expect(undefined).not.toBeUndefined();
+
+ expect(null).not.toBeUndefined();
+ expect(null).not.not.not.toBeUndefined();
+ expect(0).not.toBeUndefined();
+ expect("hello defined").not.toBeUndefined();
+});
+
+test("toBeNaN()", () => {
+ expect(NaN).toBeNaN();
+ // expect(NaN).not.toBeNaN();
+
+ expect(0).not.toBeNaN();
+ expect("hello not NaN").not.toBeNaN();
+});
+
+test("toBeNull()", () => {
+ expect(null).toBeNull();
+ // expect(null).not.toBeNull();
+
+ expect(undefined).not.toBeNull();
+ expect(0).not.toBeNull();
+ expect("hello not null").not.toBeNull();
+});
+
+test("toBeDefined()", () => {
+ expect(0).toBeDefined();
+ expect("hello defined").toBeDefined();
+ expect(null).toBeDefined();
+ // expect(null).not.toBeDefined();
+
+ expect(undefined).not.toBeDefined();
+});
+
+test("toBeFalsy()", () => {
+ expect("").toBeFalsy();
+ expect(0).toBeFalsy();
+ expect(-0).toBeFalsy();
+ expect(NaN).toBeFalsy();
+ expect(0n).toBeFalsy();
+ expect(false).toBeFalsy();
+ expect(null).toBeFalsy();
+ expect(undefined).toBeFalsy();
+ // expect(undefined).not.toBeFalsy();
+
+ expect("hello not falsy").not.toBeFalsy();
+ expect("hello not falsy").not.not.not.toBeFalsy();
+ expect(1).not.toBeFalsy();
+ expect(true).not.toBeFalsy();
+ expect({}).not.toBeFalsy();
+ expect([]).not.toBeFalsy();
+ expect(() => {}).not.toBeFalsy();
+});