Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/StandaloneModuleGraph.zig
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,6 @@ pub const StandaloneModuleGraph = struct {
store.ref();

const b = bun.webcore.Blob.initWithStore(store, globalObject).new();
b.allocator = bun.default_allocator;

if (bun.http.MimeType.byExtensionNoDefault(bun.strings.trimLeadingChar(std.fs.path.extension(this.name), '.'))) |mime| {
store.mime_type = mime;
Expand Down
15 changes: 4 additions & 11 deletions src/ast/Macro.zig
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ pub const Runner = struct {
return _entry.value_ptr.*;
}

var blob_: ?jsc.WebCore.Blob = null;
var blob_: ?*const jsc.WebCore.Blob = null;
const mime_type: ?MimeType = null;

if (value.jsType() == .DOMWrapper) {
Expand All @@ -334,30 +334,23 @@ pub const Runner = struct {
} else if (value.as(jsc.WebCore.Request)) |resp| {
return this.run(try resp.getBlobWithoutCallFrame(this.global));
} else if (value.as(jsc.WebCore.Blob)) |resp| {
blob_ = resp.*;
blob_.?.allocator = null;
blob_ = resp;
} else if (value.as(bun.api.ResolveMessage) != null or value.as(bun.api.BuildMessage) != null) {
_ = this.macro.vm.uncaughtException(this.global, value, false);
return error.MacroFailed;
}
}

if (blob_) |*blob| {
const out_expr = Expr.fromBlob(
if (blob_) |blob| {
return Expr.fromBlob(
blob,
this.allocator,
mime_type,
this.log,
this.caller.loc,
) catch {
blob.deinit();
return error.MacroFailed;
};
if (out_expr.data == .e_string) {
blob.deinit();
}

return out_expr;
}

return Expr.init(E.String, E.String.empty, this.caller.loc);
Expand Down
4 changes: 0 additions & 4 deletions src/bun.js/api/BunObject.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1337,7 +1337,6 @@ pub fn getEmbeddedFiles(globalThis: *jsc.JSGlobalObject, _: *jsc.JSObject) bun.J
// We call .dupe() on this to ensure that we don't return a blob that might get freed later.
const input_blob = file.blob(globalThis);
const blob = jsc.WebCore.Blob.new(input_blob.dupeWithContentType(true));
blob.allocator = bun.default_allocator;
blob.name = input_blob.name.dupeRef();
try array.putIndex(globalThis, i, blob.toJS(globalThis));
i += 1;
Expand Down Expand Up @@ -2048,7 +2047,6 @@ pub fn createBunStdin(globalThis: *jsc.JSGlobalObject) callconv(.C) jsc.JSValue
var blob = jsc.WebCore.Blob.new(
jsc.WebCore.Blob.initWithStore(store, globalThis),
);
blob.allocator = bun.default_allocator;
return blob.toJS(globalThis);
}

Expand All @@ -2059,7 +2057,6 @@ pub fn createBunStderr(globalThis: *jsc.JSGlobalObject) callconv(.C) jsc.JSValue
var blob = jsc.WebCore.Blob.new(
jsc.WebCore.Blob.initWithStore(store, globalThis),
);
blob.allocator = bun.default_allocator;
return blob.toJS(globalThis);
}

Expand All @@ -2070,7 +2067,6 @@ pub fn createBunStdout(globalThis: *jsc.JSGlobalObject) callconv(.C) jsc.JSValue
var blob = jsc.WebCore.Blob.new(
jsc.WebCore.Blob.initWithStore(store, globalThis),
);
blob.allocator = bun.default_allocator;
return blob.toJS(globalThis);
}

Expand Down
4 changes: 2 additions & 2 deletions src/bun.js/api/server/FileRoute.zig
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ pub fn fromJS(globalThis: *jsc.JSGlobalObject, argument: jsc.JSValue) bun.JSErro
var blob = response.body.value.use();

blob.globalThis = globalThis;
blob.allocator = null;
bun.assertf(!blob.isHeapAllocated(), "expected blob not to be heap-allocated", .{});
response.body.value = .{ .Blob = blob.dupe() };
const headers = bun.handleOom(Headers.from(response.init.headers, bun.default_allocator, .{ .body = &.{ .Blob = blob } }));
Comment thread
taylordotfish marked this conversation as resolved.

Expand All @@ -87,7 +87,7 @@ pub fn fromJS(globalThis: *jsc.JSGlobalObject, argument: jsc.JSValue) bun.JSErro
if (blob.needsToReadFile()) {
var b = blob.dupe();
b.globalThis = globalThis;
b.allocator = null;
bun.assertf(!b.isHeapAllocated(), "expected blob not to be heap-allocated", .{});
return bun.new(FileRoute, .{
.ref_count = .init(),
Comment thread
taylordotfish marked this conversation as resolved.
.server = null,
Expand Down
6 changes: 5 additions & 1 deletion src/bun.js/api/server/StaticRoute.zig
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,11 @@ pub fn fromJS(globalThis: *jsc.JSGlobalObject, argument: jsc.JSValue) bun.JSErro
}
var blob = response.body.value.use();
blob.globalThis = globalThis;
blob.allocator = null;
bun.assertf(
!blob.isHeapAllocated(),
"expected blob not to be heap-allocated",
.{},
);
response.body.value = .{ .Blob = blob.dupe() };
Comment thread
taylordotfish marked this conversation as resolved.

break :brk .{ .Blob = blob };
Expand Down
6 changes: 3 additions & 3 deletions src/bun.js/bindings/blob.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
#include "ZigGeneratedClasses.h"

extern "C" JSC::EncodedJSValue SYSV_ABI Blob__create(JSC::JSGlobalObject* globalObject, void* impl);
extern "C" void* Blob__setAsFile(void* impl, BunString* filename);
extern "C" void Blob__setAsFile(void* impl, BunString* filename);

namespace WebCore {

JSC::JSValue toJS(JSC::JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject* globalObject, WebCore::Blob& impl)
{
BunString filename = Bun::toString(impl.fileName());
impl.m_impl = Blob__setAsFile(impl.impl(), &filename);
Blob__setAsFile(impl.impl(), &filename);

return JSC::JSValue::decode(Blob__create(lexicalGlobalObject, Blob__dupe(impl.impl())));
}
Expand All @@ -28,7 +28,7 @@ JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject* lexicalGlobalObject, JSDOMGlo

size_t Blob::memoryCost() const
{
return sizeof(Blob) + JSBlob::memoryCost(m_impl);
return sizeof(Blob) + JSBlob::memoryCost(impl());
}

}
68 changes: 46 additions & 22 deletions src/bun.js/bindings/blob.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,44 +8,60 @@ namespace WebCore {

extern "C" void* Blob__dupeFromJS(JSC::EncodedJSValue impl);
extern "C" void* Blob__dupe(void* impl);
extern "C" void Blob__destroy(void* impl);
extern "C" void* Blob__getDataPtr(JSC::EncodedJSValue blob);
extern "C" size_t Blob__getSize(JSC::EncodedJSValue blob);
extern "C" void* Blob__fromBytes(JSC::JSGlobalObject* globalThis, const void* ptr, size_t len);
extern "C" void* Blob__ref(void* impl);
extern "C" void* Blob__deref(void* impl);

class Blob : public RefCounted<Blob> {
public:
void* impl()
// Opaque type corresponding to `bun.webcore.Blob`.
class BlobImpl;

struct BlobImplRefDerefTraits {
static ALWAYS_INLINE BlobImpl* refIfNotNull(BlobImpl* ptr)
{
return m_impl;
if (ptr) [[likely]]
Blob__ref(ptr);
return ptr;
}

static RefPtr<Blob> create(JSC::JSValue impl)
static ALWAYS_INLINE BlobImpl& ref(BlobImpl& ref)
{
void* implPtr = Blob__dupeFromJS(JSValue::encode(impl));
if (!implPtr)
return nullptr;
Blob__ref(&ref);
return ref;
}

return adoptRef(*new Blob(implPtr));
static ALWAYS_INLINE void derefIfNotNull(BlobImpl* ptr)
{
if (ptr) [[likely]]
Blob__deref(ptr);
}
};

static RefPtr<Blob> create(std::span<const uint8_t> bytes, JSC::JSGlobalObject* globalThis)
using BlobRef = Ref<BlobImpl, RawPtrTraits<BlobImpl>, BlobImplRefDerefTraits>;
using BlobRefPtr = RefPtr<BlobImpl, RawPtrTraits<BlobImpl>, BlobImplRefDerefTraits>;

// TODO: Now that `bun.webcore.Blob` is ref-counted, can `RefPtr<Blob>` be replaced with `Blob`?
class Blob : public RefCounted<Blob> {
public:
BlobImpl* impl() const
{
return adoptRef(*new Blob(Blob__fromBytes(globalThis, bytes.data(), bytes.size())));
return m_impl.get();
}

static RefPtr<Blob> create(void* ptr)
static RefPtr<Blob> create(JSC::JSValue impl)
{
void* implPtr = Blob__dupe(ptr);
if (!implPtr)
return nullptr;
return createAdopted(Blob__dupeFromJS(JSValue::encode(impl)));
}

return adoptRef(*new Blob(implPtr));
static RefPtr<Blob> create(std::span<const uint8_t> bytes, JSC::JSGlobalObject* globalThis)
{
return createAdopted(Blob__fromBytes(globalThis, bytes.data(), bytes.size()));
}

~Blob()
static RefPtr<Blob> create(void* ptr)
{
Blob__destroy(m_impl);
return createAdopted(Blob__dupe(ptr));
}

String fileName()
Expand All @@ -57,17 +73,25 @@ class Blob : public RefCounted<Blob> {
{
m_fileName = fileName;
}
void* m_impl;

size_t memoryCost() const;

private:
Blob(void* impl, String fileName = String())
: m_impl(adoptRef<BlobImpl, RawPtrTraits<BlobImpl>, BlobImplRefDerefTraits>(
static_cast<BlobImpl*>(impl)))
, m_fileName(std::move(fileName))
{
m_impl = impl;
m_fileName = fileName;
}

static RefPtr<Blob> createAdopted(void* ptr)
{
if (!ptr)
return nullptr;
return adoptRef(new Blob(ptr));
}

BlobRefPtr m_impl;
String m_fileName;
};

Expand Down
Loading
Loading