Skip to content

Commit

Permalink
Merge branch 'oven-sh:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
ShlomoCode authored Jan 27, 2025
2 parents 478093d + ce53290 commit 0304e37
Show file tree
Hide file tree
Showing 35 changed files with 474 additions and 396 deletions.
2 changes: 2 additions & 0 deletions src/analytics/analytics_thread.zig
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ pub const Features = struct {
pub var workers_terminated: usize = 0;
pub var napi_module_register: usize = 0;
pub var process_dlopen: usize = 0;
pub var postgres_connections: usize = 0;
pub var s3: usize = 0;

comptime {
@export(napi_module_register, .{ .name = "Bun__napi_module_register_count" });
Expand Down
3 changes: 3 additions & 0 deletions src/api/schema.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1702,6 +1702,9 @@ pub const Api = struct {
/// [serve.static]
/// plugins = ["tailwindcss"]
serve_plugins: ?[]const []const u8 = null,
serve_minify_syntax: ?bool = null,
serve_minify_whitespace: ?bool = null,
serve_minify_identifiers: ?bool = null,
bunfig_path: []const u8,

pub fn decode(reader: anytype) anyerror!TransformOptions {
Expand Down
30 changes: 26 additions & 4 deletions src/bun.js/api/server/HTMLBundle.zig
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ bunfig_dir: []const u8,
/// `plugins` is array of serve plugins defined in the bunfig.toml file. They will be resolved and loaded.
/// `bunfig_path` is the path to the bunfig.toml configuration file. It used to resolve the plugins relative
/// to the bunfig.toml file.
pub fn init(globalObject: *JSGlobalObject, path: []const u8, bunfig_path: []const u8, plugins: ?[]const []const u8) !*HTMLBundle {
pub fn init(
globalObject: *JSGlobalObject,
path: []const u8,
bunfig_path: []const u8,
plugins: ?[]const []const u8,
) !*HTMLBundle {
var config = bun.JSC.API.JSBundler.Config{};
try config.entry_points.insert(path);
config.target = .browser;
Expand Down Expand Up @@ -261,12 +266,29 @@ pub const HTMLBundleRoute = struct {
config.entry_points = config.entry_points.clone() catch bun.outOfMemory();
config.public_path = config.public_path.clone() catch bun.outOfMemory();
config.define = config.define.clone() catch bun.outOfMemory();
if (!server.config().development) {
config.minify.syntax = true;
config.minify.whitespace = true;

if (bun.CLI.Command.get().args.serve_minify_identifiers) |minify_identifiers| {
config.minify.identifiers = minify_identifiers;
} else if (!server.config().development) {
config.minify.identifiers = true;
}

if (bun.CLI.Command.get().args.serve_minify_whitespace) |minify_whitespace| {
config.minify.whitespace = minify_whitespace;
} else if (!server.config().development) {
config.minify.whitespace = true;
}

if (bun.CLI.Command.get().args.serve_minify_syntax) |minify_syntax| {
config.minify.syntax = minify_syntax;
} else if (!server.config().development) {
config.minify.syntax = true;
}

if (!server.config().development) {
config.define.put("process.env.NODE_ENV", "\"production\"") catch bun.outOfMemory();
}

config.source_map = .linked;

const completion_task = bun.BundleV2.createAndScheduleCompletionTask(
Expand Down
47 changes: 22 additions & 25 deletions src/bun.js/bindings/BunObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -550,14 +550,20 @@ JSC_DEFINE_HOST_FUNCTION(functionPathToFileURL, (JSC::JSGlobalObject * lexicalGl
auto throwScope = DECLARE_THROW_SCOPE(vm);
auto pathValue = callFrame->argument(0);

WTF::String pathString = pathValue.toWTFString(lexicalGlobalObject);
RETURN_IF_EXCEPTION(throwScope, JSC::JSValue::encode({}));
JSValue jsValue;

pathString = pathResolveWTFString(lexicalGlobalObject, pathString);
{
WTF::String pathString = pathValue.toWTFString(lexicalGlobalObject);
RETURN_IF_EXCEPTION(throwScope, JSC::JSValue::encode({}));
pathString = pathResolveWTFString(lexicalGlobalObject, pathString);

auto fileURL = WTF::URL::fileURLWithFileSystemPath(pathString);
auto object = WebCore::DOMURL::create(fileURL.string(), String());
jsValue = WebCore::toJSNewlyCreated<IDLInterface<DOMURL>>(*lexicalGlobalObject, globalObject, throwScope, WTFMove(object));
}

auto fileURL = WTF::URL::fileURLWithFileSystemPath(pathString);
auto object = WebCore::DOMURL::create(fileURL.string(), String());
auto jsValue = WebCore::toJSNewlyCreated<IDLInterface<DOMURL>>(*lexicalGlobalObject, globalObject, throwScope, WTFMove(object));
auto* jsDOMURL = jsCast<JSDOMURL*>(jsValue.asCell());
vm.heap.reportExtraMemoryAllocated(jsDOMURL, jsDOMURL->wrapped().memoryCostForGC());
RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(jsValue));
}

Expand Down Expand Up @@ -646,28 +652,19 @@ JSC_DEFINE_HOST_FUNCTION(functionFileURLToPath, (JSC::JSGlobalObject * globalObj
#endif

// ban url-encoded slashes. '/' on posix, '/' and '\' on windows.
StringView p = url.path();
if (p.length() > 3) {
for (int i = 0; i < p.length() - 2; i++) {
if (p[i] == '%') {
const char second = p[i + 1];
const uint8_t third = p[i + 2] | 0x20;
const StringView p = url.path();
if (p.contains('%')) {
#if OS(WINDOWS)
if (
(second == '2' && third == 102) || // 2f 2F '/'
(second == '5' && third == 99) // 5c 5C '\'
) {
Bun::ERR::INVALID_FILE_URL_PATH(scope, globalObject, "must not include encoded \\ or / characters"_s);
return {};
}
if (p.contains("%2f"_s) || p.contains("%5c"_s) || p.contains("%2F"_s) || p.contains("%5C"_s)) {
Bun::ERR::INVALID_FILE_URL_PATH(scope, globalObject, "must not include encoded \\ or / characters"_s);
return {};
}
#else
if (second == '2' && third == 102) {
Bun::ERR::INVALID_FILE_URL_PATH(scope, globalObject, "must not include encoded / characters"_s);
return {};
}
#endif
}
if (p.contains("%2f"_s) || p.contains("%2F"_s)) {
Bun::ERR::INVALID_FILE_URL_PATH(scope, globalObject, "must not include encoded / characters"_s);
return {};
}
#endif
}

auto fileSystemPath = url.fileSystemPath();
Expand Down
35 changes: 32 additions & 3 deletions src/bun.js/bindings/BunString.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -328,16 +328,15 @@ extern "C" BunString BunString__fromUTF8(const char* bytes, size_t length)
return { .tag = BunStringTag::Dead };
}
RELEASE_ASSERT(simdutf::convert_utf8_to_utf16(bytes, length, ptr.data()) == u16Length);
impl->ref();
return { BunStringTag::WTFStringImpl, { .wtf = impl.leakRef() } };
}

auto str = WTF::String::fromUTF8ReplacingInvalidSequences(std::span { reinterpret_cast<const LChar*>(bytes), length });
if (UNLIKELY(str.isNull())) {
return { .tag = BunStringTag::Dead };
}
str.impl()->ref();
return Bun::toString(str);
auto impl = str.releaseImpl();
return Bun::toString(impl.leakRef());
}

extern "C" BunString BunString__fromLatin1(const char* bytes, size_t length)
Expand Down Expand Up @@ -481,6 +480,8 @@ extern "C" JSC__JSValue BunString__toJSDOMURL(JSC::JSGlobalObject* lexicalGlobal

auto object = WebCore::DOMURL::create(str, String());
auto jsValue = WebCore::toJSNewlyCreated<WebCore::IDLInterface<WebCore::DOMURL>>(*lexicalGlobalObject, globalObject, throwScope, WTFMove(object));
auto* jsDOMURL = jsCast<WebCore::JSDOMURL*>(jsValue.asCell());
vm.heap.reportExtraMemoryAllocated(jsDOMURL, jsDOMURL->wrapped().memoryCostForGC());
RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(jsValue));
}

Expand Down Expand Up @@ -663,6 +664,34 @@ WTF::String BunString::toWTFString(ZeroCopyTag) const
return WTF::String();
}

WTF::String BunString::transferToWTFString()
{
if (this->tag == BunStringTag::ZigString) {
if (Zig::isTaggedUTF8Ptr(this->impl.zig.ptr)) {
auto str = Zig::toStringCopy(this->impl.zig);
*this = Zig::BunStringEmpty;
return str;
} else {
auto str = Zig::toString(this->impl.zig);
*this = Zig::BunStringEmpty;
return str;
}
} else if (this->tag == BunStringTag::StaticZigString) {
auto str = Zig::toStringStatic(this->impl.zig);
*this = Zig::BunStringEmpty;
return str;
} else if (this->tag == BunStringTag::WTFStringImpl) {
ASSERT(this->impl.wtf->refCount() > 0 && !this->impl.wtf->isEmpty());

auto str = WTF::String(this->impl.wtf);
this->impl.wtf->deref();
*this = Zig::BunStringEmpty;
return str;
}

return WTF::String();
}

extern "C" BunString BunString__createExternalGloballyAllocatedLatin1(
const LChar* bytes,
size_t length)
Expand Down
1 change: 1 addition & 0 deletions src/bun.js/bindings/DOMURL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ static inline String redact(const String& input)

inline DOMURL::DOMURL(URL&& completeURL)
: m_url(WTFMove(completeURL))
, m_initialURLCostForGC(std::min(static_cast<short>(m_url.string().impl()->costDuringGC()), std::numeric_limits<short>::max()))
{
ASSERT(m_url.isValid());
}
Expand Down
5 changes: 5 additions & 0 deletions src/bun.js/bindings/DOMURL.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ class DOMURL final : public RefCounted<DOMURL>, public CanMakeWeakPtr<DOMURL>, p
{
return sizeof(DOMURL) + m_url.string().sizeInBytes();
}
size_t memoryCostForGC() const
{
return sizeof(DOMURL) + m_initialURLCostForGC;
}

private:
static ExceptionOr<Ref<DOMURL>> create(const String& url, const URL& base);
Expand All @@ -75,6 +79,7 @@ class DOMURL final : public RefCounted<DOMURL>, public CanMakeWeakPtr<DOMURL>, p

URL m_url;
RefPtr<URLSearchParams> m_searchParams;
short m_initialURLCostForGC { 0 };
};

} // namespace WebCore
3 changes: 2 additions & 1 deletion src/bun.js/bindings/JSBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1618,11 +1618,12 @@ static inline JSC::EncodedJSValue jsBufferToString(JSC::VM& vm, JSC::JSGlobalObj
case WebCore::BufferEncodingType::base64url:
case WebCore::BufferEncodingType::hex: {
ret = Bun__encoding__toString(reinterpret_cast<const unsigned char*>(castedThis->vector()) + offset, length, lexicalGlobalObject, static_cast<uint8_t>(encoding));
RETURN_IF_EXCEPTION(scope, {});
break;
}
default: {
throwTypeError(lexicalGlobalObject, scope, "Unsupported encoding? This shouldn't happen"_s);
break;
return {};
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/bun.js/bindings/PathInlines.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,11 @@ ALWAYS_INLINE bool isAbsolutePath(WTF::String input)
extern "C" BunString ResolvePath__joinAbsStringBufCurrentPlatformBunString(JSC::JSGlobalObject*, BunString);

/// CWD is determined by the global object's current cwd.
ALWAYS_INLINE WTF::String pathResolveWTFString(JSC::JSGlobalObject* globalToGetCwdFrom, WTF::String input)
ALWAYS_INLINE WTF::String pathResolveWTFString(JSC::JSGlobalObject* globalToGetCwdFrom, const WTF::String& input)
{
if (isAbsolutePath(input))
return input;
BunString in = Bun::toString(input);
BunString out = ResolvePath__joinAbsStringBufCurrentPlatformBunString(globalToGetCwdFrom, in);
return out.toWTFString();
return out.transferToWTFString();
}
2 changes: 1 addition & 1 deletion src/bun.js/bindings/bindings.zig
Original file line number Diff line number Diff line change
Expand Up @@ -5330,7 +5330,7 @@ pub const JSValue = enum(i64) {
return getOwnTruthy(this, global, property);
}

pub fn truthyPropertyValue(prop: JSValue) ?JSValue {
fn truthyPropertyValue(prop: JSValue) ?JSValue {
return switch (prop) {
.zero => unreachable,

Expand Down
2 changes: 2 additions & 0 deletions src/bun.js/bindings/headers-handwritten.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ typedef struct BunString {
// It's only truly zero-copy if it was already a WTFStringImpl (which it is if it came from JS and we didn't use ZigString)
WTF::String toWTFString(ZeroCopyTag) const;

WTF::String transferToWTFString();

// This one usually will clone the raw bytes.
WTF::String toWTFString() const;

Expand Down
3 changes: 3 additions & 0 deletions src/bun.js/bindings/webcore/JSDOMURL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@ template<> EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSDOMURLDOMConstructor::const
RETURN_IF_EXCEPTION(throwScope, {});
setSubclassStructureIfNeeded<DOMURL>(lexicalGlobalObject, callFrame, asObject(jsValue));
RETURN_IF_EXCEPTION(throwScope, {});
auto* jsDOMURL = jsCast<JSDOMURL*>(jsValue.asCell());
vm.heap.reportExtraMemoryAllocated(jsDOMURL, jsDOMURL->wrapped().memoryCostForGC());
return JSValue::encode(jsValue);
}
JSC_ANNOTATE_HOST_FUNCTION(JSDOMURLDOMConstructorConstruct, JSDOMURLDOMConstructor::construct);
Expand Down Expand Up @@ -787,6 +789,7 @@ void JSDOMURL::visitChildrenImpl(JSCell* cell, Visitor& visitor)
ASSERT_GC_OBJECT_INHERITS(thisObject, info());
Base::visitChildren(thisObject, visitor);
visitor.append(thisObject->m_searchParams);
visitor.reportExtraMemoryVisited(thisObject->protectedWrapped()->memoryCostForGC());
}

DEFINE_VISIT_CHILDREN(JSDOMURL);
Expand Down
4 changes: 2 additions & 2 deletions src/bun.js/bindings/webcore/WebSocket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1464,9 +1464,9 @@ extern "C" void WebSocket__didAbruptClose(WebCore::WebSocket* webSocket, int32_t
{
webSocket->didFailWithErrorCode(errorCode);
}
extern "C" void WebSocket__didClose(WebCore::WebSocket* webSocket, uint16_t errorCode, const BunString* reason)
extern "C" void WebSocket__didClose(WebCore::WebSocket* webSocket, uint16_t errorCode, BunString* reason)
{
WTF::String wtf_reason = reason->toWTFString(BunString::ZeroCopy);
WTF::String wtf_reason = reason->transferToWTFString();
webSocket->didClose(0, errorCode, WTFMove(wtf_reason));
}

Expand Down
22 changes: 15 additions & 7 deletions src/bun.js/webcore/encoding.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1153,7 +1153,14 @@ pub const Encoder = struct {
return str;
},
.buffer, .utf8 => {
return bun.String.createUTF8(input);
const converted = strings.toUTF16Alloc(bun.default_allocator, input, false, false) catch return bun.String.dead;
if (converted) |utf16| {
return bun.String.createExternalGloballyAllocated(.utf16, utf16);
}

// If we get here, it means we can safely assume the string is 100% ASCII characters
// For this, we rely on WebKit to manage the memory.
return bun.String.createLatin1(input);
},
.ucs2, .utf16le => {
// Avoid incomplete characters
Expand All @@ -1176,16 +1183,17 @@ pub const Encoder = struct {
},

.base64url => {
const str, const chars = bun.String.createUninitialized(.latin1, bun.base64.urlSafeEncodeLen(input));
_ = bun.base64.encodeURLSafe(chars, input);
return str;
const to_len = bun.base64.urlSafeEncodeLen(input);
const to = bun.default_allocator.alloc(u8, to_len) catch return bun.String.dead;
const wrote = bun.base64.encodeURLSafe(to, input);
return bun.String.createExternalGloballyAllocated(.latin1, to[0..wrote]);
},

.base64 => {
const to_len = bun.base64.encodeLen(input);
const str, const chars = bun.String.createUninitialized(.latin1, to_len);
_ = bun.base64.encode(chars, input);
return str;
const to = bun.default_allocator.alloc(u8, to_len) catch return bun.String.dead;
const wrote = bun.base64.encode(to, input);
return bun.String.createExternalGloballyAllocated(.latin1, to[0..wrote]);
},
}
}
Expand Down
1 change: 1 addition & 0 deletions src/bun.js/webcore/request.zig
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,7 @@ pub const Request = struct {
const href = bun.JSC.URL.hrefFromString(this.url);
// TODO: what is the right thing to do for invalid URLS?
if (!href.isEmpty()) {
this.url.deref();
this.url = href;
}

Expand Down
22 changes: 22 additions & 0 deletions src/bunfig.zig
Original file line number Diff line number Diff line change
Expand Up @@ -656,7 +656,29 @@ pub const Bunfig = struct {
}
};

// TODO: accept entire config object.
this.bunfig.serve_plugins = plugins;
if (serve_obj.get("minify")) |minify| {
if (minify.asBool()) |value| {
this.bunfig.serve_minify_syntax = value;
this.bunfig.serve_minify_whitespace = value;
this.bunfig.serve_minify_identifiers = value;
} else if (minify.isObject()) {
if (minify.get("syntax")) |syntax| {
this.bunfig.serve_minify_syntax = syntax.asBool() orelse false;
}

if (minify.get("whitespace")) |whitespace| {
this.bunfig.serve_minify_whitespace = whitespace.asBool() orelse false;
}

if (minify.get("identifiers")) |identifiers| {
this.bunfig.serve_minify_identifiers = identifiers.asBool() orelse false;
}
} else {
try this.addError(minify.loc, "Expected minify to be boolean or object");
}
}
this.bunfig.bunfig_path = bun.default_allocator.dupe(u8, this.source.path.text) catch bun.outOfMemory();
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/http/websocket_http_client.zig
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ const CppWebSocket = opaque {
defer loop.exit();
WebSocket__didAbruptClose(this, reason);
}
pub fn didClose(this: *CppWebSocket, code: u16, reason: *const bun.String) void {
pub fn didClose(this: *CppWebSocket, code: u16, reason: *bun.String) void {
const loop = JSC.VirtualMachine.get().eventLoop();
loop.enter();
defer loop.exit();
Expand Down Expand Up @@ -1846,7 +1846,7 @@ pub fn NewWebSocketClient(comptime ssl: bool) type {
this.deref();
}

fn dispatchClose(this: *WebSocket, code: u16, reason: *const bun.String) void {
fn dispatchClose(this: *WebSocket, code: u16, reason: *bun.String) void {
var out = this.outgoing_websocket orelse return;
this.poll_ref.unref(this.globalThis.bunVM());
JSC.markBinding(@src());
Expand Down
Loading

0 comments on commit 0304e37

Please sign in to comment.