aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bun.js/api/bun.zig21
-rw-r--r--src/bun.js/api/bun/socket.zig71
-rw-r--r--src/bun.js/api/server.zig130
-rw-r--r--src/bun.js/bindings/ImportMetaObject.cpp26
-rw-r--r--src/bun.js/bindings/ImportMetaObject.h4
-rw-r--r--src/bun.js/bindings/JSBufferList.cpp22
-rw-r--r--src/bun.js/bindings/JSBufferList.h9
-rw-r--r--src/bun.js/bindings/JSStringDecoder.cpp23
-rw-r--r--src/bun.js/bindings/JSStringDecoder.h6
-rw-r--r--src/bun.js/bindings/bindings.zig16
-rw-r--r--src/bun.js/bindings/headers-cpp.h2
-rw-r--r--src/bun.js/bindings/headers.h2
-rw-r--r--src/bun.js/javascript.zig81
-rw-r--r--src/bun.js/modules/NodeModuleModule.cpp44
-rw-r--r--src/bun.js/net.exports.js21
-rw-r--r--src/bun.js/test/jest.zig49
-rw-r--r--src/bun.zig1
-rw-r--r--src/cli/test_command.zig8
-rw-r--r--src/deps/uws.zig6
-rw-r--r--src/js_parser.zig5
-rw-r--r--src/options.zig2
-rw-r--r--src/runtime.zig3
22 files changed, 387 insertions, 165 deletions
diff --git a/src/bun.js/api/bun.zig b/src/bun.js/api/bun.zig
index e9b760de5..32bd0a9ec 100644
--- a/src/bun.js/api/bun.zig
+++ b/src/bun.js/api/bun.zig
@@ -942,7 +942,17 @@ fn doResolve(
return null;
}
- return doResolveWithArgs(ctx, specifier.getZigString(ctx.ptr()), from.getZigString(ctx.ptr()), exception, false);
+ var is_esm = true;
+ if (args.nextEat()) |next| {
+ if (next.isBoolean()) {
+ is_esm = next.toBoolean();
+ } else {
+ JSC.throwInvalidArguments("esm must be a boolean", .{}, ctx, exception);
+ return null;
+ }
+ }
+
+ return doResolveWithArgs(ctx, specifier.getZigString(ctx.ptr()), from.getZigString(ctx.ptr()), exception, is_esm, false);
}
fn doResolveWithArgs(
@@ -950,6 +960,7 @@ fn doResolveWithArgs(
specifier: ZigString,
from: ZigString,
exception: js.ExceptionRef,
+ is_esm: bool,
comptime is_file_path: bool,
) ?JSC.JSValue {
var errorable: ErrorableZigString = undefined;
@@ -960,6 +971,7 @@ fn doResolveWithArgs(
ctx.ptr(),
specifier,
from,
+ is_esm,
);
} else {
VirtualMachine.resolveForAPI(
@@ -967,6 +979,7 @@ fn doResolveWithArgs(
ctx.ptr(),
specifier,
from,
+ is_esm,
);
}
@@ -1010,10 +1023,11 @@ export fn Bun__resolve(
global: *JSGlobalObject,
specifier: JSValue,
source: JSValue,
+ is_esm: bool,
) JSC.JSValue {
var exception_ = [1]JSC.JSValueRef{null};
var exception = &exception_;
- const value = doResolveWithArgs(global, specifier.getZigString(global), source.getZigString(global), exception, true) orelse {
+ const value = doResolveWithArgs(global, specifier.getZigString(global), source.getZigString(global), exception, is_esm, true) orelse {
return JSC.JSPromise.rejectedPromiseValue(global, JSC.JSValue.fromRef(exception[0]));
};
return JSC.JSPromise.resolvedPromiseValue(global, value);
@@ -1023,10 +1037,11 @@ export fn Bun__resolveSync(
global: *JSGlobalObject,
specifier: JSValue,
source: JSValue,
+ is_esm: bool,
) JSC.JSValue {
var exception_ = [1]JSC.JSValueRef{null};
var exception = &exception_;
- return doResolveWithArgs(global, specifier.getZigString(global), source.getZigString(global), exception, true) orelse {
+ return doResolveWithArgs(global, specifier.getZigString(global), source.getZigString(global), exception, is_esm, true) orelse {
return JSC.JSValue.fromRef(exception[0]);
};
}
diff --git a/src/bun.js/api/bun/socket.zig b/src/bun.js/api/bun/socket.zig
index f4dcfb01c..911dc9e89 100644
--- a/src/bun.js/api/bun/socket.zig
+++ b/src/bun.js/api/bun/socket.zig
@@ -232,38 +232,65 @@ pub const SocketConfig = struct {
}
}
- if (opts.getTruthy(globalObject, "hostname")) |hostname| {
- if (hostname.isEmptyOrUndefinedOrNull() or !hostname.isString()) {
- exception.* = JSC.toInvalidArguments("Expected \"hostname\" to be a string", .{}, globalObject).asObjectRef();
- return null;
- }
+ hostname_or_unix: {
+ if (opts.getTruthy(globalObject, "unix")) |unix_socket| {
+ if (!unix_socket.isString()) {
+ exception.* = JSC.toInvalidArguments("Expected \"unix\" to be a string", .{}, globalObject).asObjectRef();
+ return null;
+ }
- const port_value = opts.get(globalObject, "port") orelse JSValue.zero;
- if (port_value.isEmptyOrUndefinedOrNull() or !port_value.isNumber() or port_value.toInt64() > std.math.maxInt(u16) or port_value.toInt64() < 0) {
- exception.* = JSC.toInvalidArguments("Expected \"port\" to be a number between 0 and 65535", .{}, globalObject).asObjectRef();
- return null;
- }
+ hostname_or_unix = unix_socket.getZigString(globalObject).toSlice(bun.default_allocator);
- hostname_or_unix = hostname.getZigString(globalObject).toSlice(bun.default_allocator);
- port = port_value.toU16();
+ if (strings.hasPrefixComptime(hostname_or_unix.slice(), "file://") or strings.hasPrefixComptime(hostname_or_unix.slice(), "unix://") or strings.hasPrefixComptime(hostname_or_unix.slice(), "sock://")) {
+ hostname_or_unix.ptr += 7;
+ hostname_or_unix.len -|= 7;
+ }
- if (hostname_or_unix.len == 0) {
- exception.* = JSC.toInvalidArguments("Expected \"hostname\" to be a non-empty string", .{}, globalObject).asObjectRef();
- return null;
- }
- } else if (opts.getTruthy(globalObject, "unix")) |unix_socket| {
- if (unix_socket.isEmptyOrUndefinedOrNull() or !unix_socket.isString()) {
- exception.* = JSC.toInvalidArguments("Expected \"unix\" to be a string", .{}, globalObject).asObjectRef();
- return null;
+ if (hostname_or_unix.len > 0) {
+ break :hostname_or_unix;
+ }
}
- hostname_or_unix = unix_socket.getZigString(globalObject).toSlice(bun.default_allocator);
+ if (opts.getTruthy(globalObject, "hostname")) |hostname| {
+ if (!hostname.isString()) {
+ exception.* = JSC.toInvalidArguments("Expected \"hostname\" to be a string", .{}, globalObject).asObjectRef();
+ return null;
+ }
+
+ var port_value = opts.get(globalObject, "port") orelse JSValue.zero;
+ hostname_or_unix = hostname.getZigString(globalObject).toSlice(bun.default_allocator);
+
+ if (port_value.isEmptyOrUndefinedOrNull() and hostname_or_unix.len > 0) {
+ const parsed_url = bun.URL.parse(hostname_or_unix.slice());
+ if (parsed_url.getPort()) |port_num| {
+ port_value = JSValue.jsNumber(port_num);
+ hostname_or_unix.ptr = parsed_url.hostname.ptr;
+ hostname_or_unix.len = @truncate(u32, parsed_url.hostname.len);
+ }
+ }
+
+ if (port_value.isEmptyOrUndefinedOrNull() or !port_value.isNumber() or port_value.toInt64() > std.math.maxInt(u16) or port_value.toInt64() < 0) {
+ exception.* = JSC.toInvalidArguments("Expected \"port\" to be a number between 0 and 65535", .{}, globalObject).asObjectRef();
+ return null;
+ }
+
+ port = port_value.toU16();
+
+ if (hostname_or_unix.len == 0) {
+ exception.* = JSC.toInvalidArguments("Expected \"hostname\" to be a non-empty string", .{}, globalObject).asObjectRef();
+ return null;
+ }
+
+ if (hostname_or_unix.len > 0) {
+ break :hostname_or_unix;
+ }
+ }
if (hostname_or_unix.len == 0) {
exception.* = JSC.toInvalidArguments("Expected \"unix\" to be a non-empty string", .{}, globalObject).asObjectRef();
return null;
}
- } else {
+
exception.* = JSC.toInvalidArguments("Expected either \"hostname\" or \"unix\"", .{}, globalObject).asObjectRef();
return null;
}
diff --git a/src/bun.js/api/server.zig b/src/bun.js/api/server.zig
index f47ee9fc0..137d164f0 100644
--- a/src/bun.js/api/server.zig
+++ b/src/bun.js/api/server.zig
@@ -2135,8 +2135,8 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
const result = JSC.C.JSObjectCallAsFunctionReturnValue(this.server.globalThis, this.server.config.onError.asObjectRef(), this.server.thisObject.asObjectRef(), 1, &args);
if (!result.isEmptyOrUndefinedOrNull()) {
- if (result.isError() or result.isAggregateError(this.server.globalThis)) {
- this.finishRunningErrorHandler(result, status);
+ if (result.toError()) |err| {
+ this.finishRunningErrorHandler(err, status);
return;
} else if (result.as(Response)) |response| {
this.render(response);
@@ -2514,7 +2514,10 @@ pub const WebSocketServer = struct {
active_connections: usize = 0,
/// used by publish()
- ssl: bool = false,
+ flags: packed struct(u2) {
+ ssl: bool = false,
+ publish_to_self: bool = true,
+ } = .{},
pub fn fromJS(globalObject: *JSC.JSGlobalObject, object: JSC.JSValue) ?Handler {
var handler = Handler{ .globalObject = globalObject };
@@ -2752,6 +2755,17 @@ pub const WebSocketServer = struct {
}
}
+ if (object.get(globalObject, "publishToSelf")) |value| {
+ if (!value.isUndefinedOrNull()) {
+ if (!value.isBoolean()) {
+ globalObject.throwInvalidArguments("websocket expects publishToSelf to be a boolean", .{});
+ return null;
+ }
+
+ server.handler.flags.publish_to_self = value.toBoolean();
+ }
+ }
+
server.protect();
return server;
}
@@ -3025,7 +3039,9 @@ pub const ServerWebSocket = struct {
log("publish() closed", .{});
return JSValue.jsNumber(0);
};
- const ssl = this.handler.ssl;
+ const flags = this.handler.flags;
+ const ssl = flags.ssl;
+ const publish_to_self = flags.publish_to_self;
const topic_value = args.ptr[0];
const message_value = args.ptr[1];
@@ -3051,16 +3067,23 @@ pub const ServerWebSocket = struct {
return .zero;
}
- if (message_value.asArrayBuffer(globalThis)) |buffer| {
+ if (message_value.asArrayBuffer(globalThis)) |array_buffer| {
+ const buffer = array_buffer.slice();
+
if (buffer.len == 0) {
globalThis.throw("publish requires a non-empty message", .{});
return .zero;
}
+ const result = if (!publish_to_self)
+ this.websocket.publish(topic_slice.slice(), buffer, .binary, compress)
+ else
+ uws.AnyWebSocket.publishWithOptions(ssl, app, topic_slice.slice(), buffer, .binary, compress);
+
return JSValue.jsNumber(
// if 0, return 0
// else return number of bytes sent
- @as(i32, @boolToInt(uws.AnyWebSocket.publishWithOptions(ssl, app, topic_slice.slice(), buffer.slice(), .binary, compress))) * @intCast(i32, @truncate(u31, buffer.len)),
+ if (result) @intCast(i32, @truncate(u31, buffer.len)) else @as(i32, 0),
);
}
@@ -3072,10 +3095,16 @@ pub const ServerWebSocket = struct {
}
const buffer = string_slice.slice();
+
+ const result = if (!publish_to_self)
+ this.websocket.publish(topic_slice.slice(), buffer, .text, compress)
+ else
+ uws.AnyWebSocket.publishWithOptions(ssl, app, topic_slice.slice(), buffer, .text, compress);
+
return JSValue.jsNumber(
// if 0, return 0
// else return number of bytes sent
- @as(i32, @boolToInt(uws.AnyWebSocket.publishWithOptions(ssl, app, topic_slice.slice(), buffer, .text, compress))) * @intCast(i32, @truncate(u31, buffer.len)),
+ if (result) @intCast(i32, @truncate(u31, buffer.len)) else @as(i32, 0),
);
}
@@ -3099,7 +3128,9 @@ pub const ServerWebSocket = struct {
log("publish() closed", .{});
return JSValue.jsNumber(0);
};
- const ssl = this.handler.ssl;
+ const flags = this.handler.flags;
+ const ssl = flags.ssl;
+ const publish_to_self = flags.publish_to_self;
const topic_value = args.ptr[0];
const message_value = args.ptr[1];
@@ -3132,10 +3163,16 @@ pub const ServerWebSocket = struct {
}
const buffer = string_slice.slice();
+
+ const result = if (!publish_to_self)
+ this.websocket.publish(topic_slice.slice(), buffer, .text, compress)
+ else
+ uws.AnyWebSocket.publishWithOptions(ssl, app, topic_slice.slice(), buffer, .text, compress);
+
return JSValue.jsNumber(
// if 0, return 0
// else return number of bytes sent
- @as(i32, @boolToInt(uws.AnyWebSocket.publishWithOptions(ssl, app, topic_slice.slice(), buffer, .text, compress))) * @intCast(i32, @truncate(u31, buffer.len)),
+ if (result) @intCast(i32, @truncate(u31, buffer.len)) else @as(i32, 0),
);
}
@@ -3156,7 +3193,9 @@ pub const ServerWebSocket = struct {
log("publish() closed", .{});
return JSValue.jsNumber(0);
};
- const ssl = this.handler.ssl;
+ const flags = this.handler.flags;
+ const ssl = flags.ssl;
+ const publish_to_self = flags.publish_to_self;
const topic_value = args.ptr[0];
const message_value = args.ptr[1];
const compress_value = args.ptr[2];
@@ -3180,19 +3219,25 @@ pub const ServerWebSocket = struct {
globalThis.throw("publishBinary requires a non-empty message", .{});
return .zero;
}
- const buffer = message_value.asArrayBuffer(globalThis) orelse {
+ const array_buffer = message_value.asArrayBuffer(globalThis) orelse {
globalThis.throw("publishBinary expects an ArrayBufferView", .{});
return .zero;
};
+ const buffer = array_buffer.slice();
if (buffer.len == 0) {
return JSC.JSValue.jsNumber(0);
}
+ const result = if (!publish_to_self)
+ this.websocket.publish(topic_slice.slice(), buffer, .binary, compress)
+ else
+ uws.AnyWebSocket.publishWithOptions(ssl, app, topic_slice.slice(), buffer, .binary, compress);
+
return JSValue.jsNumber(
// if 0, return 0
// else return number of bytes sent
- @as(i32, @boolToInt(uws.AnyWebSocket.publishWithOptions(ssl, app, topic_slice.slice(), buffer.slice(), .binary, compress))) * @intCast(i32, @truncate(u31, buffer.len)),
+ if (result) @intCast(i32, @truncate(u31, buffer.len)) else @as(i32, 0),
);
}
@@ -3200,13 +3245,15 @@ pub const ServerWebSocket = struct {
this: *ServerWebSocket,
globalThis: *JSC.JSGlobalObject,
topic_str: *JSC.JSString,
- buffer: *JSC.JSUint8Array,
+ array: *JSC.JSUint8Array,
) callconv(.C) JSC.JSValue {
var app = this.handler.app orelse {
log("publish() closed", .{});
return JSValue.jsNumber(0);
};
- const ssl = this.handler.ssl;
+ const flags = this.handler.flags;
+ const ssl = flags.ssl;
+ const publish_to_self = flags.publish_to_self;
var topic_slice = topic_str.toSlice(globalThis, bun.default_allocator);
defer topic_slice.deinit();
@@ -3217,30 +3264,20 @@ pub const ServerWebSocket = struct {
const compress = true;
- const slice = buffer.slice();
- if (slice.len == 0) {
+ const buffer = array.slice();
+ if (buffer.len == 0) {
return JSC.JSValue.jsNumber(0);
}
+ const result = if (!publish_to_self)
+ this.websocket.publish(topic_slice.slice(), buffer, .binary, compress)
+ else
+ uws.AnyWebSocket.publishWithOptions(ssl, app, topic_slice.slice(), buffer, .binary, compress);
+
return JSValue.jsNumber(
// if 0, return 0
// else return number of bytes sent
- @as(
- i32,
- @boolToInt(
- uws.AnyWebSocket.publishWithOptions(
- ssl,
- app,
- topic_slice.slice(),
- slice,
- .binary,
- compress,
- ),
- ),
- ) * @intCast(
- i32,
- @truncate(u31, slice.len),
- ),
+ if (result) @intCast(i32, @truncate(u31, buffer.len)) else @as(i32, 0),
);
}
@@ -3254,7 +3291,9 @@ pub const ServerWebSocket = struct {
log("publish() closed", .{});
return JSValue.jsNumber(0);
};
- const ssl = this.handler.ssl;
+ const flags = this.handler.flags;
+ const ssl = flags.ssl;
+ const publish_to_self = flags.publish_to_self;
var topic_slice = topic_str.toSlice(globalThis, bun.default_allocator);
defer topic_slice.deinit();
@@ -3266,24 +3305,21 @@ pub const ServerWebSocket = struct {
const compress = true;
const slice = str.toSlice(globalThis, bun.default_allocator);
- if (slice.len == 0) {
+ defer slice.deinit();
+ const buffer = slice.slice();
+
+ if (buffer.len == 0) {
return JSC.JSValue.jsNumber(0);
}
+ const result = if (!publish_to_self)
+ this.websocket.publish(topic_slice.slice(), buffer, .text, compress)
+ else
+ uws.AnyWebSocket.publishWithOptions(ssl, app, topic_slice.slice(), buffer, .text, compress);
return JSValue.jsNumber(
// if 0, return 0
// else return number of bytes sent
- @as(i32, @boolToInt(uws.AnyWebSocket.publishWithOptions(
- ssl,
- app,
- topic_slice.slice(),
- slice.slice(),
- .text,
- compress,
- ))) * @intCast(
- i32,
- @truncate(u31, slice.len),
- ),
+ if (result) @intCast(i32, @truncate(u31, buffer.len)) else @as(i32, 0),
);
}
@@ -4107,7 +4143,7 @@ pub fn NewServer(comptime ssl_enabled_: bool, comptime debug_mode_: bool) type {
}
if (new_config.websocket) |*ws| {
- ws.handler.ssl = ssl_enabled;
+ ws.handler.flags.ssl = ssl_enabled;
if (ws.handler.onMessage != .zero or ws.handler.onOpen != .zero) {
if (this.config.websocket) |old_ws| {
old_ws.unprotect();
@@ -4671,7 +4707,7 @@ pub fn NewServer(comptime ssl_enabled_: bool, comptime debug_mode_: bool) type {
if (this.config.websocket) |*websocket| {
websocket.globalObject = this.globalThis;
websocket.handler.app = this.app;
- websocket.handler.ssl = ssl_enabled;
+ websocket.handler.flags.ssl = ssl_enabled;
this.app.ws(
"/*",
this,
diff --git a/src/bun.js/bindings/ImportMetaObject.cpp b/src/bun.js/bindings/ImportMetaObject.cpp
index 5838bde04..0247b5140 100644
--- a/src/bun.js/bindings/ImportMetaObject.cpp
+++ b/src/bun.js/bindings/ImportMetaObject.cpp
@@ -80,7 +80,7 @@ static EncodedJSValue functionRequireResolve(JSC::JSGlobalObject* globalObject,
}
}
- auto result = Bun__resolveSync(globalObject, JSC::JSValue::encode(moduleName), from);
+ auto result = Bun__resolveSync(globalObject, JSC::JSValue::encode(moduleName), from, false);
auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
if (!JSC::JSValue::decode(result).isString()) {
@@ -156,17 +156,18 @@ JSObject* Zig::ImportMetaObject::createRequireFunction(VM& vm, JSGlobalObject* g
JSFunction* requireFunction = JSFunction::create(vm, importMetaObjectRequireCodeGenerator(vm), globalObject);
auto clientData = WebCore::clientData(vm);
requireFunction->putDirectCustomAccessor(vm, clientData->builtinNames().resolvePublicName(), JSC::CustomGetterSetter::create(vm, functionRequireResolveLazyGetter, functionRequireResolveLazySetter), 0);
- requireFunction->putDirect(vm, clientData->builtinNames().pathPrivateName(), jsOwnedString(vm, pathString), JSC::PropertyAttribute::DontEnum | 0);
+ requireFunction->putDirect(vm, clientData->builtinNames().pathPublicName(), jsString(vm, pathString), JSC::PropertyAttribute::DontEnum | 0);
return requireFunction;
}
extern "C" EncodedJSValue functionImportMeta__resolveSync(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame)
{
JSC::VM& vm = globalObject->vm();
+ auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
switch (callFrame->argumentCount()) {
case 0: {
- auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
+
// not "requires" because "require" could be confusing
JSC::throwTypeError(globalObject, scope, "import.meta.resolveSync needs 1 argument (a string)"_s);
scope.release();
@@ -176,13 +177,13 @@ extern "C" EncodedJSValue functionImportMeta__resolveSync(JSC::JSGlobalObject* g
JSC::JSValue moduleName = callFrame->argument(0);
if (moduleName.isUndefinedOrNull()) {
- auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
JSC::throwTypeError(globalObject, scope, "import.meta.resolveSync expects a string"_s);
scope.release();
return JSC::JSValue::encode(JSC::JSValue {});
}
JSC__JSValue from;
+ bool isESM = true;
if (callFrame->argumentCount() > 1) {
JSC::JSValue fromValue = callFrame->argument(1);
@@ -195,8 +196,20 @@ extern "C" EncodedJSValue functionImportMeta__resolveSync(JSC::JSGlobalObject* g
fromValue = array->getIndex(globalObject, 0);
}
}
+
+ if (callFrame->argumentCount() > 2) {
+ JSC::JSValue isESMValue = callFrame->argument(2);
+ if (isESMValue.isBoolean()) {
+ isESM = isESMValue.toBoolean(globalObject);
+ RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(JSC::JSValue {}));
+ }
+ }
+ } else if (fromValue.isBoolean()) {
+ isESM = fromValue.toBoolean(globalObject);
+ RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(JSC::JSValue {}));
}
from = JSC::JSValue::encode(fromValue);
+
} else {
JSC::JSObject* thisObject = JSC::jsDynamicCast<JSC::JSObject*>(callFrame->thisValue());
if (UNLIKELY(!thisObject)) {
@@ -210,8 +223,7 @@ extern "C" EncodedJSValue functionImportMeta__resolveSync(JSC::JSGlobalObject* g
from = JSC::JSValue::encode(thisObject->get(globalObject, clientData->builtinNames().pathPublicName()));
}
- auto result = Bun__resolveSync(globalObject, JSC::JSValue::encode(moduleName), from);
- auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
+ auto result = Bun__resolveSync(globalObject, JSC::JSValue::encode(moduleName), from, isESM);
if (!JSC::JSValue::decode(result).isString()) {
JSC::throwException(globalObject, scope, JSC::JSValue::decode(result));
@@ -266,7 +278,7 @@ JSC_DEFINE_HOST_FUNCTION(functionImportMeta__resolve,
from = JSC::JSValue::encode(thisObject->get(globalObject, clientData->builtinNames().pathPublicName()));
}
- return Bun__resolve(globalObject, JSC::JSValue::encode(moduleName), from);
+ return Bun__resolve(globalObject, JSC::JSValue::encode(moduleName), from, true);
}
}
}
diff --git a/src/bun.js/bindings/ImportMetaObject.h b/src/bun.js/bindings/ImportMetaObject.h
index 3ce50ebbb..ff32c85d4 100644
--- a/src/bun.js/bindings/ImportMetaObject.h
+++ b/src/bun.js/bindings/ImportMetaObject.h
@@ -9,8 +9,8 @@
#include "JSDOMWrapperCache.h"
extern "C" JSC_DECLARE_HOST_FUNCTION(functionImportMeta__resolveSync);
-extern "C" EncodedJSValue Bun__resolve(JSC::JSGlobalObject* global, JSC::EncodedJSValue specifier, JSC::EncodedJSValue from);
-extern "C" EncodedJSValue Bun__resolveSync(JSC::JSGlobalObject* global, JSC::EncodedJSValue specifier, JSC::EncodedJSValue from);
+extern "C" EncodedJSValue Bun__resolve(JSC::JSGlobalObject* global, JSC::EncodedJSValue specifier, JSC::EncodedJSValue from, bool is_esm);
+extern "C" EncodedJSValue Bun__resolveSync(JSC::JSGlobalObject* global, JSC::EncodedJSValue specifier, JSC::EncodedJSValue from, bool is_esm);
namespace Zig {
diff --git a/src/bun.js/bindings/JSBufferList.cpp b/src/bun.js/bindings/JSBufferList.cpp
index e54b433e5..9b9990598 100644
--- a/src/bun.js/bindings/JSBufferList.cpp
+++ b/src/bun.js/bindings/JSBufferList.cpp
@@ -32,7 +32,7 @@ void JSBufferList::finishCreation(JSC::VM& vm, JSC::JSGlobalObject* globalObject
JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly);
}
-JSC::JSValue JSBufferList::concat(JSC::VM& vm, JSC::JSGlobalObject* lexicalGlobalObject, int32_t n)
+JSC::JSValue JSBufferList::concat(JSC::VM& vm, JSC::JSGlobalObject* lexicalGlobalObject, size_t n)
{
auto throwScope = DECLARE_THROW_SCOPE(vm);
auto* subclassStructure = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject)->JSBufferSubclassStructure();
@@ -75,6 +75,8 @@ JSC::JSValue JSBufferList::concat(JSC::VM& vm, JSC::JSGlobalObject* lexicalGloba
i += length;
}
+ memset(uint8Array->typedVector() + i, 0, n - i);
+
RELEASE_AND_RETURN(throwScope, uint8Array);
}
@@ -100,7 +102,7 @@ JSC::JSValue JSBufferList::join(JSC::VM& vm, JSC::JSGlobalObject* lexicalGlobalO
RELEASE_AND_RETURN(throwScope, ropeBuilder.release());
}
-JSC::JSValue JSBufferList::consume(JSC::VM& vm, JSC::JSGlobalObject* lexicalGlobalObject, int32_t n, bool hasString)
+JSC::JSValue JSBufferList::consume(JSC::VM& vm, JSC::JSGlobalObject* lexicalGlobalObject, size_t n, bool hasString)
{
if (hasString)
return _getString(vm, lexicalGlobalObject, n);
@@ -108,7 +110,7 @@ JSC::JSValue JSBufferList::consume(JSC::VM& vm, JSC::JSGlobalObject* lexicalGlob
return _getBuffer(vm, lexicalGlobalObject, n);
}
-JSC::JSValue JSBufferList::_getString(JSC::VM& vm, JSC::JSGlobalObject* lexicalGlobalObject, int32_t total)
+JSC::JSValue JSBufferList::_getString(JSC::VM& vm, JSC::JSGlobalObject* lexicalGlobalObject, size_t total)
{
auto throwScope = DECLARE_THROW_SCOPE(vm);
if (total <= 0 || length() == 0) {
@@ -150,13 +152,14 @@ JSC::JSValue JSBufferList::_getString(JSC::VM& vm, JSC::JSGlobalObject* lexicalG
if (!ropeBuilder.append(str))
return throwOutOfMemoryError(lexicalGlobalObject, throwScope);
m_deque.removeFirst();
- if (n == len) break;
+ if (n == len)
+ break;
n -= len;
}
RELEASE_AND_RETURN(throwScope, ropeBuilder.release());
}
-JSC::JSValue JSBufferList::_getBuffer(JSC::VM& vm, JSC::JSGlobalObject* lexicalGlobalObject, int32_t total)
+JSC::JSValue JSBufferList::_getBuffer(JSC::VM& vm, JSC::JSGlobalObject* lexicalGlobalObject, size_t total)
{
auto throwScope = DECLARE_THROW_SCOPE(vm);
auto* subclassStructure = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject)->JSBufferSubclassStructure();
@@ -205,16 +208,23 @@ JSC::JSValue JSBufferList::_getBuffer(JSC::VM& vm, JSC::JSGlobalObject* lexicalG
auto buffer = array->possiblySharedBuffer();
JSC::JSUint8Array* newArray = JSC::JSUint8Array::create(lexicalGlobalObject, subclassStructure, buffer, n, len - n);
iter->set(vm, this, newArray);
+ offset += n;
break;
}
if (UNLIKELY(!uint8Array->setFromTypedArray(lexicalGlobalObject, offset, array, 0, len, JSC::CopyType::Unobservable))) {
return throwOutOfMemoryError(lexicalGlobalObject, throwScope);
}
m_deque.removeFirst();
- if (n == len) break;
+ if (n == len) {
+ offset += len;
+ break;
+ }
n -= len;
offset += len;
}
+
+ memset(uint8Array->typedVector() + offset, 0, total - offset);
+
RELEASE_AND_RETURN(throwScope, uint8Array);
}
diff --git a/src/bun.js/bindings/JSBufferList.h b/src/bun.js/bindings/JSBufferList.h
index a9227e981..94a69c8d1 100644
--- a/src/bun.js/bindings/JSBufferList.h
+++ b/src/bun.js/bindings/JSBufferList.h
@@ -76,11 +76,11 @@ public:
return JSC::JSValue(m_deque.first().get());
}
- JSC::JSValue concat(JSC::VM&, JSC::JSGlobalObject*, int32_t);
+ JSC::JSValue concat(JSC::VM&, JSC::JSGlobalObject*, size_t);
JSC::JSValue join(JSC::VM&, JSC::JSGlobalObject*, JSString*);
- JSC::JSValue consume(JSC::VM&, JSC::JSGlobalObject*, int32_t, bool);
- JSC::JSValue _getBuffer(JSC::VM&, JSC::JSGlobalObject*, int32_t);
- JSC::JSValue _getString(JSC::VM&, JSC::JSGlobalObject*, int32_t);
+ JSC::JSValue consume(JSC::VM&, JSC::JSGlobalObject*, size_t, bool);
+ JSC::JSValue _getBuffer(JSC::VM&, JSC::JSGlobalObject*, size_t);
+ JSC::JSValue _getString(JSC::VM&, JSC::JSGlobalObject*, size_t);
private:
Deque<WriteBarrier<Unknown>> m_deque;
@@ -134,6 +134,7 @@ public:
// Must be defined for each specialization class.
static JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES construct(JSC::JSGlobalObject*, JSC::CallFrame*);
DECLARE_EXPORT_INFO;
+
private:
JSBufferListConstructor(JSC::VM& vm, JSC::Structure* structure, JSC::NativeFunction nativeFunction)
: Base(vm, structure, nativeFunction, nativeFunction)
diff --git a/src/bun.js/bindings/JSStringDecoder.cpp b/src/bun.js/bindings/JSStringDecoder.cpp
index 66f9cb654..ca79e9e1c 100644
--- a/src/bun.js/bindings/JSStringDecoder.cpp
+++ b/src/bun.js/bindings/JSStringDecoder.cpp
@@ -206,9 +206,30 @@ JSC::JSValue JSStringDecoder::write(JSC::VM& vm, JSC::JSGlobalObject* globalObje
}
}
-JSC::JSValue JSStringDecoder::end(JSC::VM& vm, JSC::JSGlobalObject* globalObject, uint8_t* bufPtr, uint32_t length)
+class ResetScope final {
+public:
+ ResetScope(JSStringDecoder* decoder);
+ ~ResetScope();
+ JSStringDecoder* m_decoder;
+};
+
+ResetScope::ResetScope(JSStringDecoder* decoder)
+{
+ m_decoder = decoder;
+}
+
+ResetScope::~ResetScope()
+{
+ m_decoder->m_lastTotal = 0;
+ m_decoder->m_lastNeed = 0;
+ memset(m_decoder->m_lastChar, 0, 4);
+}
+
+JSC::JSValue
+JSStringDecoder::end(JSC::VM& vm, JSC::JSGlobalObject* globalObject, uint8_t* bufPtr, uint32_t length)
{
auto throwScope = DECLARE_THROW_SCOPE(vm);
+ auto resetScope = ResetScope(this);
switch (m_encoding) {
case BufferEncodingType::ucs2:
case BufferEncodingType::utf16le: {
diff --git a/src/bun.js/bindings/JSStringDecoder.h b/src/bun.js/bindings/JSStringDecoder.h
index 299c2fb96..bce1ae05d 100644
--- a/src/bun.js/bindings/JSStringDecoder.h
+++ b/src/bun.js/bindings/JSStringDecoder.h
@@ -11,7 +11,10 @@ class JSStringDecoder : public JSC::JSDestructibleObject {
public:
JSStringDecoder(JSC::VM& vm, JSC::Structure* structure, BufferEncodingType encoding)
- : Base(vm, structure), m_lastNeed(0), m_lastTotal(0), m_encoding(encoding)
+ : Base(vm, structure)
+ , m_lastNeed(0)
+ , m_lastTotal(0)
+ , m_encoding(encoding)
{
}
@@ -108,6 +111,7 @@ public:
// Must be defined for each specialization class.
static JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES construct(JSC::JSGlobalObject*, JSC::CallFrame*);
DECLARE_EXPORT_INFO;
+
private:
JSStringDecoderConstructor(JSC::VM& vm, JSC::Structure* structure, JSC::NativeFunction nativeFunction)
: Base(vm, structure, nativeFunction, nativeFunction)
diff --git a/src/bun.js/bindings/bindings.zig b/src/bun.js/bindings/bindings.zig
index 41a52956d..1bee13fc0 100644
--- a/src/bun.js/bindings/bindings.zig
+++ b/src/bun.js/bindings/bindings.zig
@@ -1339,7 +1339,7 @@ pub fn NewGlobalObject(comptime Type: type) type {
}
pub fn resolve(res: *ErrorableZigString, global: *JSGlobalObject, specifier: *ZigString, source: *ZigString) callconv(.C) void {
if (comptime @hasDecl(Type, "resolve")) {
- @call(.always_inline, Type.resolve, .{ res, global, specifier.*, source.* });
+ @call(.always_inline, Type.resolve, .{ res, global, specifier.*, source.*, true });
return;
}
res.* = ErrorableZigString.err(error.ResolveFailed, ZigString.init(resolveNotImpl).toErrorInstance(global).asVoid());
@@ -1506,7 +1506,7 @@ pub const JSPromise = extern struct {
) JSValue {
if (value.isEmpty()) {
return resolvedPromiseValue(globalObject, JSValue.jsUndefined());
- } else if (value.isUndefinedOrNull() or !value.isCell()) {
+ } else if (value.isEmptyOrUndefinedOrNull() or !value.isCell()) {
return resolvedPromiseValue(globalObject, value);
}
@@ -2484,10 +2484,8 @@ pub const JSValue = enum(JSValueReprInt) {
}
pub fn isObject(this: JSType) bool {
- return switch (this) {
- .Object, .FinalObject => true,
- else => false,
- };
+ // inline constexpr bool isObjectType(JSType type) { return type >= ObjectType; }
+ return @enumToInt(this) >= @enumToInt(JSType.Object);
}
pub fn isFunction(this: JSType) bool {
@@ -2663,7 +2661,7 @@ pub const JSValue = enum(JSValueReprInt) {
}
pub fn isInstanceOf(this: JSValue, global: *JSGlobalObject, constructor: JSValue) bool {
- if (this.isEmptyOrUndefinedOrNull())
+ if (!this.isCell())
return false;
return JSC.C.JSValueIsInstanceOfConstructor(global, this.asObjectRef(), constructor.asObjectRef(), null);
@@ -3112,8 +3110,8 @@ pub const JSValue = enum(JSValueReprInt) {
pub fn isCustomGetterSetter(this: JSValue) bool {
return cppFn("isCustomGetterSetter", .{this});
}
- pub fn isObject(this: JSValue) bool {
- return cppFn("isObject", .{this});
+ pub inline fn isObject(this: JSValue) bool {
+ return this.isCell() and this.jsType().isObject();
}
pub fn isClass(this: JSValue, global: *JSGlobalObject) bool {
diff --git a/src/bun.js/bindings/headers-cpp.h b/src/bun.js/bindings/headers-cpp.h
index 065fd8caa..a05007fff 100644
--- a/src/bun.js/bindings/headers-cpp.h
+++ b/src/bun.js/bindings/headers-cpp.h
@@ -1,4 +1,4 @@
-//-- AUTOGENERATED FILE -- 1673374722
+//-- AUTOGENERATED FILE -- 1673376494
// clang-format off
#pragma once
diff --git a/src/bun.js/bindings/headers.h b/src/bun.js/bindings/headers.h
index 4e5dabe4e..71a8d1034 100644
--- a/src/bun.js/bindings/headers.h
+++ b/src/bun.js/bindings/headers.h
@@ -1,5 +1,5 @@
// clang-format off
-//-- AUTOGENERATED FILE -- 1673374722
+//-- AUTOGENERATED FILE -- 1673376494
#pragma once
#include <stddef.h>
diff --git a/src/bun.js/javascript.zig b/src/bun.js/javascript.zig
index fd2ded108..c2c43cf81 100644
--- a/src/bun.js/javascript.zig
+++ b/src/bun.js/javascript.zig
@@ -429,7 +429,7 @@ pub const VirtualMachine = struct {
auto_install_dependencies: bool = false,
load_builtins_from_path: []const u8 = "",
- onUnhandledRejection: *const fn (*VirtualMachine, globalObject: *JSC.JSGlobalObject, JSC.JSValue) void = defaultOnUnhandledRejection,
+ onUnhandledRejection: *const OnUnhandledRejection = defaultOnUnhandledRejection,
onUnhandledRejectionCtx: ?*anyopaque = null,
unhandled_error_counter: usize = 0,
@@ -438,6 +438,8 @@ pub const VirtualMachine = struct {
gc_controller: JSC.GarbageCollectionController = .{},
+ pub const OnUnhandledRejection = fn (*VirtualMachine, globalObject: *JSC.JSGlobalObject, JSC.JSValue) void;
+
const VMHolder = struct {
pub threadlocal var vm: ?*VirtualMachine = null;
};
@@ -454,6 +456,30 @@ pub const VirtualMachine = struct {
pub threadlocal var is_main_thread_vm: bool = false;
+ pub const UnhandledRejectionScope = struct {
+ ctx: ?*anyopaque = null,
+ onUnhandledRejection: *const OnUnhandledRejection = undefined,
+ count: usize = 0,
+
+ pub fn apply(this: *UnhandledRejectionScope, vm: *JSC.VirtualMachine) void {
+ vm.onUnhandledRejection = this.onUnhandledRejection;
+ vm.onUnhandledRejectionCtx = this.ctx;
+ vm.unhandled_error_counter = this.count;
+ }
+ };
+
+ pub fn onQuietUnhandledRejectionHandler(this: *VirtualMachine, _: *JSC.JSGlobalObject, _: JSC.JSValue) void {
+ this.unhandled_error_counter += 1;
+ }
+
+ pub fn unhandledRejectionScope(this: *VirtualMachine) UnhandledRejectionScope {
+ return .{
+ .onUnhandledRejection = this.onUnhandledRejection,
+ .ctx = this.onUnhandledRejectionCtx,
+ .count = this.unhandled_error_counter,
+ };
+ }
+
pub fn resetUnhandledRejection(this: *VirtualMachine) void {
this.onUnhandledRejection = defaultOnUnhandledRejection;
}
@@ -891,6 +917,7 @@ pub const VirtualMachine = struct {
_: *JSGlobalObject,
specifier: string,
source: string,
+ is_esm: bool,
comptime is_a_file_path: bool,
comptime realpath: bool,
) !void {
@@ -936,7 +963,7 @@ pub const VirtualMachine = struct {
jsc_vm.bundler.fs.top_level_dir,
// TODO: do we need to handle things like query string params?
if (strings.hasPrefixComptime(specifier, "file://")) specifier["file://".len..] else specifier,
- .stmt,
+ if (is_esm) .stmt else .require,
.read_only,
)) {
.success => |r| r,
@@ -1012,19 +1039,53 @@ pub const VirtualMachine = struct {
}
}
- pub fn resolveForAPI(res: *ErrorableZigString, global: *JSGlobalObject, specifier: ZigString, source: ZigString) void {
- resolveMaybeNeedsTrailingSlash(res, global, specifier, source, false, true);
+ pub fn resolveForAPI(
+ res: *ErrorableZigString,
+ global: *JSGlobalObject,
+ specifier: ZigString,
+ source: ZigString,
+ is_esm: bool,
+ ) void {
+ resolveMaybeNeedsTrailingSlash(res, global, specifier, source, is_esm, false, true);
}
- pub fn resolveFilePathForAPI(res: *ErrorableZigString, global: *JSGlobalObject, specifier: ZigString, source: ZigString) void {
- resolveMaybeNeedsTrailingSlash(res, global, specifier, source, true, true);
+ pub fn resolveFilePathForAPI(
+ res: *ErrorableZigString,
+ global: *JSGlobalObject,
+ specifier: ZigString,
+ source: ZigString,
+ is_esm: bool,
+ ) void {
+ resolveMaybeNeedsTrailingSlash(res, global, specifier, source, is_esm, true, true);
+ }
+
+ pub fn resolve(
+ res: *ErrorableZigString,
+ global: *JSGlobalObject,
+ specifier: ZigString,
+ source: ZigString,
+ is_esm: bool,
+ ) void {
+ resolveMaybeNeedsTrailingSlash(res, global, specifier, source, is_esm, true, false);
}
- pub fn resolve(res: *ErrorableZigString, global: *JSGlobalObject, specifier: ZigString, source: ZigString) void {
- resolveMaybeNeedsTrailingSlash(res, global, specifier, source, true, false);
+ fn normalizeSource(source: []const u8) []const u8 {
+ if (strings.hasPrefixComptime(source, "file://")) {
+ return source["file://".len..];
+ }
+
+ return source;
}
- pub fn resolveMaybeNeedsTrailingSlash(res: *ErrorableZigString, global: *JSGlobalObject, specifier: ZigString, source: ZigString, comptime is_a_file_path: bool, comptime realpath: bool) void {
+ pub fn resolveMaybeNeedsTrailingSlash(
+ res: *ErrorableZigString,
+ global: *JSGlobalObject,
+ specifier: ZigString,
+ source: ZigString,
+ is_esm: bool,
+ comptime is_a_file_path: bool,
+ comptime realpath: bool,
+ ) void {
var result = ResolveFunctionResult{ .path = "", .result = null };
var jsc_vm = VirtualMachine.get();
if (jsc_vm.plugin_runner) |plugin_runner| {
@@ -1057,7 +1118,7 @@ pub const VirtualMachine = struct {
jsc_vm.bundler.linker.log = old_log;
jsc_vm.bundler.resolver.log = old_log;
}
- _resolve(&result, global, specifier.slice(), source.slice(), is_a_file_path, realpath) catch |err_| {
+ _resolve(&result, global, specifier.slice(), normalizeSource(source.slice()), is_esm, is_a_file_path, realpath) catch |err_| {
var err = err_;
const msg: logger.Msg = brk: {
var msgs: []logger.Msg = log.msgs.items;
diff --git a/src/bun.js/modules/NodeModuleModule.cpp b/src/bun.js/modules/NodeModuleModule.cpp
index 02e4e3849..01e061499 100644
--- a/src/bun.js/modules/NodeModuleModule.cpp
+++ b/src/bun.js/modules/NodeModuleModule.cpp
@@ -19,36 +19,24 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionNodeModuleCreateRequire,
return JSC::JSValue::encode(JSC::jsUndefined());
}
- Zig::ImportMetaObject *importMetaObject = Zig::ImportMetaObject::create(
- globalObject, callFrame->uncheckedArgument(0));
+ auto str = callFrame->uncheckedArgument(0).toStringOrNull(globalObject);
+ RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(JSC::jsUndefined()));
+ WTF::String val = str->value(globalObject);
+ auto *meta = Zig::ImportMetaObject::create(globalObject, str);
auto clientData = WebCore::clientData(vm);
-
- RETURN_IF_EXCEPTION(scope, {});
-
- if (!importMetaObject) {
- throwTypeError(globalObject, scope, "Invalid path"_s);
- return JSC::JSValue::encode(JSC::jsUndefined());
- }
-
- auto requireFunctionValue = importMetaObject->get(
- globalObject, clientData->builtinNames().requirePublicName());
- RETURN_IF_EXCEPTION(scope, {});
-
- JSC::JSBoundFunction *boundRequireFunction = JSC::JSBoundFunction::create(
- vm, globalObject, requireFunctionValue.getObject(), importMetaObject,
- nullptr, 1, jsString(vm, String("require"_s)));
- RETURN_IF_EXCEPTION(scope, {});
- auto resolveFunction = importMetaObject->get(
- globalObject, clientData->builtinNames().resolveSyncPublicName());
-
- JSC::JSBoundFunction *boundResolveFunction = JSC::JSBoundFunction::create(
- vm, globalObject, resolveFunction.getObject(), importMetaObject, nullptr,
- 1, jsString(vm, String("resolve"_s)));
+ auto requireFunction =
+ Zig::ImportMetaObject::createRequireFunction(vm, globalObject, val);
+ auto nameStr = jsCast<JSFunction *>(requireFunction)->name(vm);
+ JSC::JSBoundFunction *boundRequireFunction =
+ JSC::JSBoundFunction::create(vm, globalObject, requireFunction, meta,
+ nullptr, 0, jsString(vm, nameStr));
boundRequireFunction->putDirect(
- vm, clientData->builtinNames().resolvePublicName(), boundResolveFunction,
- JSC::PropertyAttribute::Function | 0);
+ vm, clientData->builtinNames().resolvePublicName(),
+ requireFunction->getDirect(
+ vm, clientData->builtinNames().resolvePublicName()),
+ 0);
- RELEASE_AND_RETURN(scope, JSC::JSValue::encode(boundRequireFunction));
+ RELEASE_AND_RETURN(scope, JSValue::encode(boundRequireFunction));
}
JSC_DEFINE_HOST_FUNCTION(jsFunctionNodeModulePaths,
(JSC::JSGlobalObject * globalObject,
@@ -113,7 +101,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionResolveFileName,
auto result =
Bun__resolveSync(globalObject, JSC::JSValue::encode(moduleName),
- JSValue::encode(callFrame->argument(1)));
+ JSValue::encode(callFrame->argument(1)), false);
auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
if (!JSC::JSValue::decode(result).isString()) {
diff --git a/src/bun.js/net.exports.js b/src/bun.js/net.exports.js
index 8d283dd1e..f894cd5fa 100644
--- a/src/bun.js/net.exports.js
+++ b/src/bun.js/net.exports.js
@@ -86,11 +86,10 @@ export const Socket = (function (InternalSocket) {
self.emit("error", error);
},
- data(socket, buffer) {
- const self = socket.data;
- self.bytesRead += buffer.length;
+ data({ data: self }, { length, buffer }) {
+ self.bytesRead += length;
const queue = self.#readQueue;
- const ret = new Buffer(buffer.buffer);
+ const ret = new Buffer(buffer);
if (queue.isEmpty()) {
if (self.push(ret)) return;
}
@@ -197,7 +196,10 @@ export const Socket = (function (InternalSocket) {
connect(port, host, connectListener) {
// TODO support IPC sockets
var path;
- if (typeof host == "function") {
+ if (arguments.length === 1 && typeof port === "string") {
+ path = port;
+ port = undefined;
+ } else if (typeof host == "function") {
if (typeof port === "string") {
path = port;
port = undefined;
@@ -336,7 +338,14 @@ export const Socket = (function (InternalSocket) {
} else if (this.#writeCallback) {
callback(new Error("overlapping _write()"));
} else {
- if (written > 0) chunk = chunk.slice(written);
+ if (written > 0) {
+ if (typeof chunk == "string") {
+ chunk = chunk.slice(written);
+ } else {
+ chunk = chunk.subarray(written);
+ }
+ }
+
this.#writeCallback = callback;
this.#writeChunk = chunk;
}
diff --git a/src/bun.js/test/jest.zig b/src/bun.js/test/jest.zig
index 00c8148b2..4b31f7309 100644
--- a/src/bun.js/test/jest.zig
+++ b/src/bun.js/test/jest.zig
@@ -1124,12 +1124,38 @@ pub const Expect = struct {
}
const not = this.op.contains(.not);
- const result_ = value.call(globalObject, &.{}).toError();
+
+ const result_: ?JSValue = brk: {
+ var vm = globalObject.bunVM();
+ var scope = vm.unhandledRejectionScope();
+ vm.onUnhandledRejection = &VirtualMachine.onQuietUnhandledRejectionHandler;
+ const return_value: JSValue = value.call(globalObject, &.{});
+
+ if (return_value.asAnyPromise()) |promise| {
+ globalObject.bunVM().waitForPromise(promise);
+ scope.apply(vm);
+ const promise_result = promise.result(globalObject.vm());
+
+ switch (promise.status(globalObject.vm())) {
+ .Fulfilled => {
+ break :brk null;
+ },
+ .Rejected => {
+ // since we know for sure it rejected, we should always return the error
+ break :brk promise_result.toError() orelse promise_result;
+ },
+ .Pending => unreachable,
+ }
+ }
+ scope.apply(vm);
+
+ break :brk return_value.toError();
+ };
+
const did_throw = result_ != null;
const matched_expectation = did_throw == !not;
- if (matched_expectation) return thisValue;
- if (expected_value.isEmptyOrUndefinedOrNull()) {
+ if (!matched_expectation) {
if (!not)
globalObject.throw("Expected function to throw", .{})
else {
@@ -1139,7 +1165,14 @@ pub const Expect = struct {
return .zero;
}
- const result = result_.?;
+
+ // If you throw a string, it's treated as the message of an Error
+ // If you are expected not to throw and you didn't throw, then you pass
+ // If you are expected to throw a specific message and you throw a different one, then you fail.
+ if (matched_expectation and (!expected_value.isCell() or not))
+ return thisValue;
+
+ const result = result_ orelse JSC.JSValue.jsUndefined();
const expected_error = expected_value.toError();
@@ -1148,7 +1181,10 @@ pub const Expect = struct {
if (expected_value.isString()) break :brk expected_value;
break :brk expected_error.?.get(globalObject, "message");
};
- const actual = result.get(globalObject, "message");
+ const actual: ?JSValue = if (result.isObject())
+ result.get(globalObject, "message")
+ else
+ null;
// TODO support partial match
const pass = brk: {
if (expected) |expected_message|
@@ -1460,7 +1496,6 @@ pub const TestScope = struct {
.Internal => vm.waitForPromise(promise),
else => {},
}
-
switch (promise.status(vm.global.vm())) {
.Rejected => {
vm.runErrorHandler(promise.result(vm.global.vm()), null);
@@ -1737,7 +1772,7 @@ pub const DescribeScope = struct {
var scope = allocator.create(DescribeScope) catch unreachable;
scope.* = .{
.label = (label.toSlice(allocator).cloneIfNeeded(allocator) catch unreachable).slice(),
- .parent = this,
+ .parent = active,
.file_id = this.file_id,
};
var new_this = DescribeScope.Class.make(ctx, scope);
diff --git a/src/bun.zig b/src/bun.zig
index 00bceeea4..732862e8f 100644
--- a/src/bun.zig
+++ b/src/bun.zig
@@ -765,3 +765,4 @@ pub fn zero(comptime Type: type) Type {
return @bitCast(Type, out);
}
pub const c_ares = @import("./deps/c_ares.zig");
+pub const URL = @import("./url.zig").URL;
diff --git a/src/cli/test_command.zig b/src/cli/test_command.zig
index a36561be0..8fb8bf01b 100644
--- a/src/cli/test_command.zig
+++ b/src/cli/test_command.zig
@@ -113,7 +113,9 @@ pub const CommandLineReporter = struct {
const color_code = comptime if (skip) "<yellow>" else "";
if (Output.enable_ansi_colors_stderr) {
- for (scopes) |scope| {
+ for (scopes) |_, i| {
+ const index = (scopes.len - 1) - i;
+ const scope = scopes[index];
if (scope.label.len == 0) continue;
writer.writeAll(" ") catch unreachable;
@@ -123,7 +125,9 @@ pub const CommandLineReporter = struct {
writer.writeAll(" >") catch unreachable;
}
} else {
- for (scopes) |scope| {
+ for (scopes) |_, i| {
+ const index = (scopes.len - 1) - i;
+ const scope = scopes[index];
if (scope.label.len == 0) continue;
writer.writeAll(" ") catch unreachable;
writer.writeAll(scope.label) catch unreachable;
diff --git a/src/deps/uws.zig b/src/deps/uws.zig
index 62821c85c..bfcd00e7a 100644
--- a/src/deps/uws.zig
+++ b/src/deps/uws.zig
@@ -756,10 +756,10 @@ pub const AnyWebSocket = union(enum) {
// pub fn iterateTopics(this: AnyWebSocket) {
// return uws_ws_iterate_topics(ssl_flag, this.raw(), callback: ?*const fn ([*c]const u8, usize, ?*anyopaque) callconv(.C) void, user_data: ?*anyopaque) void;
// }
- pub fn publish(this: AnyWebSocket, topic: []const u8, message: []const u8) bool {
+ pub fn publish(this: AnyWebSocket, topic: []const u8, message: []const u8, opcode: Opcode, compress: bool) bool {
return switch (this) {
- .ssl => uws_ws_publish(1, this.ssl.raw(), topic.ptr, topic.len, message.ptr, message.len),
- .tcp => uws_ws_publish(0, this.tcp.raw(), topic.ptr, topic.len, message.ptr, message.len),
+ .ssl => uws_ws_publish_with_options(1, this.ssl.raw(), topic.ptr, topic.len, message.ptr, message.len, opcode, compress),
+ .tcp => uws_ws_publish_with_options(0, this.tcp.raw(), topic.ptr, topic.len, message.ptr, message.len, opcode, compress),
};
}
pub fn publishWithOptions(ssl: bool, app: *anyopaque, topic: []const u8, message: []const u8, opcode: Opcode, compress: bool) bool {
diff --git a/src/js_parser.zig b/src/js_parser.zig
index 1fa86041f..1dbf1ebf9 100644
--- a/src/js_parser.zig
+++ b/src/js_parser.zig
@@ -117,8 +117,9 @@ fn foldStringAddition(lhs: Expr, rhs: Expr) ?Expr {
switch (lhs.data) {
.e_string => |left| {
if (rhs.data == .e_string and left.isUTF8() and rhs.data.e_string.isUTF8()) {
- lhs.data.e_string.push(rhs.data.e_string);
- return lhs;
+ var orig = lhs.data.e_string.*;
+ orig.push(rhs.data.e_string);
+ return Expr.init(E.String, orig, lhs.loc);
}
},
.e_binary => |bin| {
diff --git a/src/options.zig b/src/options.zig
index 024ff188a..b9268f400 100644
--- a/src/options.zig
+++ b/src/options.zig
@@ -597,6 +597,7 @@ pub const Platform = enum {
default_conditions_strings.bun,
default_conditions_strings.worker,
default_conditions_strings.module,
+ default_conditions_strings.node,
default_conditions_strings.browser,
},
);
@@ -606,6 +607,7 @@ pub const Platform = enum {
default_conditions_strings.bun,
default_conditions_strings.worker,
default_conditions_strings.module,
+ default_conditions_strings.node,
default_conditions_strings.browser,
},
);
diff --git a/src/runtime.zig b/src/runtime.zig
index c942afb13..197dc4264 100644
--- a/src/runtime.zig
+++ b/src/runtime.zig
@@ -116,7 +116,6 @@ pub const Fallback = struct {
};
pub inline fn scriptContent() string {
- if (true) return;
if (comptime Environment.isDebug) {
var dirpath = comptime bun.Environment.base_path ++ std.fs.path.dirname(@src().file).?;
var env = std.process.getEnvMap(default_allocator) catch unreachable;
@@ -166,7 +165,6 @@ pub const Fallback = struct {
fallback: string,
entry_point: string,
};
- if (true) return;
try writer.print(HTMLTemplate, PrintArgs{
.blob = Base64FallbackMessage{ .msg = msg, .allocator = allocator },
.preload = preload,
@@ -188,7 +186,6 @@ pub const Fallback = struct {
fallback: string,
bun_error_page_css: string,
};
- if (true) return;
try writer.print(HTMLBackendTemplate, PrintArgs{
.blob = Base64FallbackMessage{ .msg = msg, .allocator = allocator },
.bun_error_css = ErrorCSS.sourceContent(),