aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--examples/lambda.ts214
-rw-r--r--src/baby_list.zig49
-rw-r--r--src/javascript/jsc/bindings/JSSink+custom.h10
-rw-r--r--src/javascript/jsc/bindings/JSSink.cpp220
-rw-r--r--src/javascript/jsc/bindings/JSSink.h106
-rw-r--r--src/javascript/jsc/bindings/Sink.h15
-rw-r--r--src/javascript/jsc/bindings/ZigGlobalObject.cpp41
-rw-r--r--src/javascript/jsc/bindings/ZigGlobalObject.h4
-rw-r--r--src/javascript/jsc/bindings/bindings.zig2
-rw-r--r--src/javascript/jsc/bindings/builtins/js/ReadableStream.js4
-rw-r--r--src/javascript/jsc/bindings/exports.zig22
-rw-r--r--src/javascript/jsc/bindings/headers-cpp.h8
-rw-r--r--src/javascript/jsc/bindings/headers-handwritten.h2
-rw-r--r--src/javascript/jsc/bindings/headers-replacements.zig4
-rw-r--r--src/javascript/jsc/bindings/headers.h20
-rw-r--r--src/javascript/jsc/bindings/headers.zig8
-rw-r--r--src/javascript/jsc/bindings/shimmer.zig14
-rw-r--r--src/javascript/jsc/bindings/webcore/DOMClientIsoSubspaces.h2
-rw-r--r--src/javascript/jsc/bindings/webcore/DOMIsoSubspaces.h2
-rw-r--r--src/javascript/jsc/generate-jssink.js380
-rw-r--r--src/javascript/jsc/node/types.zig49
-rw-r--r--src/javascript/jsc/webcore.zig8
-rw-r--r--src/javascript/jsc/webcore/response.zig69
-rw-r--r--src/javascript/jsc/webcore/streams.zig966
-rw-r--r--src/main.zig3
26 files changed, 2054 insertions, 170 deletions
diff --git a/Makefile b/Makefile
index d3ec53bbe..f98c8c44e 100644
--- a/Makefile
+++ b/Makefile
@@ -1210,7 +1210,7 @@ wasm-return1:
EMIT_LLVM_FOR_RELEASE=-emit-llvm -flto="full"
EMIT_LLVM_FOR_DEBUG=
-EMIT_LLVM=$(EMIT_LLVM_FOR_RELEASE)
+EMIT_LLVM=$(EMIT_LLVM_FOR_DEBUG)
# We do this outside of build.zig for performance reasons
# The C compilation stuff with build.zig is really slow and we don't need to run this as often as the rest
diff --git a/examples/lambda.ts b/examples/lambda.ts
new file mode 100644
index 000000000..ab2d5bb2b
--- /dev/null
+++ b/examples/lambda.ts
@@ -0,0 +1,214 @@
+const { AWS_LAMBDA_RUNTIME_API, LAMBDA_TASK_ROOT, _HANDLER } = process.env;
+
+if (!AWS_LAMBDA_RUNTIME_API || AWS_LAMBDA_RUNTIME_API === "") {
+ throw new Error("AWS_LAMBDA_RUNTIME_API is not set");
+}
+
+const nextURL = `http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/next`;
+const sourceDir = LAMBDA_TASK_ROOT;
+if (!sourceDir) {
+ throw new Error("handler is not set");
+}
+
+// don't care if this fails
+if (process.cwd() !== sourceDir) {
+ try {
+ process.chdir(sourceDir);
+ } catch (e) {}
+}
+
+var handlerDot = _HANDLER.lastIndexOf(".");
+var sourcefile = handlerDot > 0 ? _HANDLER.substring(0, handlerDot) : _HANDLER;
+if (sourcefile.length === 0) {
+ throw new Error("handler is not set");
+}
+if (!sourcefile.startsWith("/")) {
+ sourcefile = `./${sourcefile}`;
+}
+function noop() {}
+const method = (handlerDot > 0 ? _HANDLER.substring(handlerDot) : "") || "GET";
+
+if (typeof process.env.VERBOSE !== "undefined") {
+ console.time(`Loaded ${sourcefile}`);
+}
+var Handler;
+
+try {
+ Handler = await import(sourcefile);
+} catch (e) {
+ console.error("Error loading sourcefile:", e);
+ try {
+ await fetch(
+ new URL(`http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/init/error`)
+ .href,
+ {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({
+ errorMessage: e.message,
+ errorType: e.name,
+ stackTrace: e?.stack?.split("\n") ?? [],
+ }),
+ }
+ );
+ } catch (e2) {
+ console.error("Error sending error to runtime:", e2);
+ }
+ process.exit(1);
+}
+
+if (typeof process.env.VERBOSE !== "undefined") {
+ console.timeEnd(`Loaded ${sourcefile}`);
+}
+
+const handlerFunction = Handler.default?.fetch;
+if (typeof handlerFunction !== "function") {
+ const e = new Error(`${sourcefile} must export default a function called fetch
+
+Here is an example:
+
+export default {
+ fetch(req) {
+ return new Response("Hello World");
+ }
+}
+`);
+
+ console.error(e);
+
+ try {
+ await fetch(
+ new URL(`http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/init/error`)
+ .href,
+ {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({
+ errorMessage: e.message,
+ errorType: e.name,
+ stackTrace: e?.stack?.split("\n") ?? [],
+ }),
+ }
+ );
+ } catch (e2) {
+ console.error("Error sending error to runtime:", e2);
+ }
+
+ process.exit(1);
+}
+
+var baseURLString = AWS_LAMBDA_RUNTIME_API;
+if ("baseURI" in Handler.default) {
+ baseURLString = Handler.default.baseURI?.toString();
+}
+
+var baseURL;
+try {
+ baseURL = new URL(baseURLString);
+} catch (e) {
+ console.error("Error parsing baseURI:", e);
+ try {
+ await fetch(
+ new URL(`http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/init/error`)
+ .href,
+ {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({
+ errorMessage: e.message,
+ errorType: e.name,
+ stackTrace: e?.stack?.split("\n") || [],
+ }),
+ }
+ );
+ } catch (e2) {
+ console.error("Error sending error to runtime:", e2);
+ }
+
+ process.exit(1);
+}
+
+async function runHandler(response: Response) {
+ const traceID = response.headers.get("Lambda-Runtime-Trace-Id");
+ const requestID = response.headers.get("Lambda-Runtime-Aws-Request-Id");
+ var request = new Request(baseURL.href, {
+ method,
+ headers: response.headers,
+ body:
+ parseInt(response.headers.get("Content-Length") || "0", 10) > 0
+ ? await response.blob()
+ : undefined,
+ });
+ // we are done with the Response object here
+ // allow it to be GC'd
+ response = undefined;
+
+ var result: Response;
+ try {
+ if (typeof process.env.VERBOSE !== "undefined") {
+ console.time(`[${traceID}] Run ${request.url}`);
+ }
+ result = handlerFunction(request, {});
+ if (result && result.then) {
+ await result;
+ }
+ } catch (e1) {
+ if (typeof process.env.VERBOSE !== "undefined") {
+ console.error(`[${traceID}] Error running handler:`, e1);
+ }
+ fetch(
+ `http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/${requestID}/error`,
+ {
+ method: "POST",
+
+ body: JSON.stringify({
+ errorMessage: e1.message,
+ errorType: e1.name,
+ stackTrace: e1?.stack?.split("\n") ?? [],
+ }),
+ }
+ ).finally(noop);
+ return;
+ } finally {
+ if (typeof process.env.VERBOSE !== "undefined") {
+ console.timeEnd(`[${traceID}] Run ${request.url}`);
+ }
+ }
+
+ if (!result || !("headers" in result)) {
+ await fetch(
+ `http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/${requestID}/error`,
+ {
+ method: "POST",
+ body: JSON.stringify({
+ errorMessage: "Expected Response object",
+ errorType: "ExpectedResponseObject",
+ stackTrace: [],
+ }),
+ }
+ );
+ return;
+ }
+
+ await fetch(
+ `http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/${requestID}/response`,
+ {
+ method: "POST",
+ headers: result.headers,
+ body: await result.blob(),
+ }
+ );
+ result = undefined;
+}
+
+while (true) {
+ fetch(nextURL).then(runHandler, console.error);
+}
+
+export {};
diff --git a/src/baby_list.zig b/src/baby_list.zig
index b1bfc1786..dcb808936 100644
--- a/src/baby_list.zig
+++ b/src/baby_list.zig
@@ -1,5 +1,6 @@
const std = @import("std");
const Environment = @import("./env.zig");
+const strings = @import("./string_immutable.zig");
/// This is like ArrayList except it stores the length and capacity as u32
/// In practice, it is very unusual to have lengths above 4 GB
@@ -100,5 +101,53 @@ pub fn BabyList(comptime Type: type) type {
@setRuntimeSafety(false);
return this.ptr[0..this.len];
}
+
+ pub fn write(this: *@This(), allocator: std.mem.Allocator, str: []const u8) !u32 {
+ if (comptime Type != u8)
+ @compileError("Unsupported for type " ++ @typeName(Type));
+ const initial = this.len;
+ var list_ = this.listManaged(allocator);
+ try list_.appendSlice(str);
+ this.update(list_);
+ return this.len - initial;
+ }
+ pub fn writeLatin1(this: *@This(), allocator: std.mem.Allocator, str: []const u8) !u32 {
+ if (comptime Type != u8)
+ @compileError("Unsupported for type " ++ @typeName(Type));
+ const initial = this.len;
+ var list_ = this.listManaged(allocator);
+ defer this.update(list_);
+ const start = list_.items.len;
+ try list_.appendSlice(str);
+
+ strings.replaceLatin1WithUTF8(list_.items[start..list_.items.len]);
+
+ return this.len - initial;
+ }
+ pub fn writeUTF16(this: *@This(), allocator: std.mem.Allocator, str: []const u16) !u32 {
+ if (comptime Type != u8)
+ @compileError("Unsupported for type " ++ @typeName(Type));
+
+ var list_ = this.listManaged(allocator);
+ defer this.update(list_);
+ try list_.ensureTotalCapacityPrecise(list_.items.len + str.len);
+ const initial = this.len;
+ var remain = str;
+ while (remain.len > 0) {
+ const orig_len = list_.items.len;
+
+ var slice_ = list_.items.ptr[orig_len..list_.capacity];
+ const result = strings.copyUTF16IntoUTF8(slice_, []const u16, remain);
+ remain = remain[result.read..];
+ list_.items.len += @as(usize, result.written);
+ if (remain.len > 0) {
+ try list_.ensureTotalCapacityPrecise(list_.items.len + strings.elementLengthUTF16IntoUTF8([]const u16, remain));
+ continue;
+ }
+ if (result.read == 0 or result.written == 0) break;
+ }
+
+ return this.len - initial;
+ }
};
}
diff --git a/src/javascript/jsc/bindings/JSSink+custom.h b/src/javascript/jsc/bindings/JSSink+custom.h
new file mode 100644
index 000000000..744691f53
--- /dev/null
+++ b/src/javascript/jsc/bindings/JSSink+custom.h
@@ -0,0 +1,10 @@
+
+static const HashTableValue JSArrayBufferSinkPrototypeTableValues[]
+ = {
+ { "close"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(ArrayBufferSink__close), (intptr_t)(0) } },
+ { "closeWithError"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(ArrayBufferSink__closeWithError), (intptr_t)(1) } },
+ { "drain"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(ArrayBufferSink__drain), (intptr_t)(1) } },
+ { "end"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(ArrayBufferSink__end), (intptr_t)(0) } },
+ { "start"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(ArrayBufferSink__start), (intptr_t)(1) } },
+ { "write"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(ArrayBufferSink__write), (intptr_t)(1) } },
+ };
diff --git a/src/javascript/jsc/bindings/JSSink.cpp b/src/javascript/jsc/bindings/JSSink.cpp
new file mode 100644
index 000000000..041f03fa3
--- /dev/null
+++ b/src/javascript/jsc/bindings/JSSink.cpp
@@ -0,0 +1,220 @@
+
+// AUTO-GENERATED FILE. DO NOT EDIT.
+// Generated by /Users/jarred/Code/bun/src/javascript/jsc/generate-jssink.js at 2022-06-13T03:43:14.001Z
+// To regenerate this file, run:
+//
+// bun src/javascript/jsc/generate-jssink.js
+//
+#include "root.h"
+#include "JSSink.h"
+
+#include "ActiveDOMObject.h"
+#include "ExtendedDOMClientIsoSubspaces.h"
+#include "ExtendedDOMIsoSubspaces.h"
+#include "IDLTypes.h"
+// #include "JSBlob.h"
+#include "JSDOMAttribute.h"
+#include "JSDOMBinding.h"
+#include "JSDOMConstructor.h"
+#include "JSDOMConvertBase.h"
+#include "JSDOMConvertInterface.h"
+#include "JSDOMConvertStrings.h"
+#include "JSDOMExceptionHandling.h"
+#include "JSDOMGlobalObject.h"
+#include "JSDOMGlobalObjectInlines.h"
+#include "JSDOMOperation.h"
+#include "JSDOMWrapperCache.h"
+#include "ScriptExecutionContext.h"
+#include "WebCoreJSClientData.h"
+#include "JavaScriptCore/FunctionPrototype.h"
+#include "JavaScriptCore/HeapAnalyzer.h"
+
+#include "JavaScriptCore/JSDestructibleObjectHeapCellType.h"
+#include "JavaScriptCore/SlotVisitorMacros.h"
+#include "JavaScriptCore/SubspaceInlines.h"
+#include "wtf/GetPtr.h"
+#include "wtf/PointerPreparations.h"
+#include "wtf/URL.h"
+#include "JavaScriptCore/BuiltinNames.h"
+
+#include "JSBufferEncodingType.h"
+#include "JSBufferPrototypeBuiltins.h"
+#include "JSBufferConstructorBuiltins.h"
+#include "JavaScriptCore/JSBase.h"
+#if ENABLE(MEDIA_SOURCE)
+#include "BufferMediaSource.h"
+#include "JSMediaSource.h"
+#endif
+
+// #include "JavaScriptCore/JSTypedArrayViewPrototype.h"
+#include "JavaScriptCore/JSArrayBufferViewInlines.h"
+
+namespace WebCore {
+using namespace JSC;
+
+
+
+JSC_DEFINE_CUSTOM_GETTER(functionArrayBufferSink__getter, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName))
+{
+ auto& vm = lexicalGlobalObject->vm();
+ Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject);
+
+ return JSC::JSValue::encode(globalObject->ArrayBufferSink());
+}
+
+static const HashTableValue JSArrayBufferSinkPrototypeTableValues[]
+ = {
+ { "close"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(ArrayBufferSink__close), (intptr_t)(0) } },
+ { "closeWithError"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(ArrayBufferSink__closeWithError), (intptr_t)(1) } },
+ { "drain"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(ArrayBufferSink__drain), (intptr_t)(1) } },
+ { "end"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(ArrayBufferSink__end), (intptr_t)(0) } },
+ { "start"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(ArrayBufferSink__start), (intptr_t)(1) } },
+ { "write"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(ArrayBufferSink__write), (intptr_t)(1) } },
+ };
+
+#pragma mark - ArrayBufferSink
+
+class JSArrayBufferSinkPrototype final : public JSC::JSNonFinalObject {
+public:
+ using Base = JSC::JSNonFinalObject;
+
+ static JSArrayBufferSinkPrototype* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure)
+ {
+ JSArrayBufferSinkPrototype* ptr = new (NotNull, JSC::allocateCell<JSArrayBufferSinkPrototype>(vm)) JSArrayBufferSinkPrototype(vm, globalObject, structure);
+ ptr->finishCreation(vm, globalObject);
+ return ptr;
+ }
+
+ DECLARE_INFO;
+ template<typename CellType, JSC::SubspaceAccess>
+ static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
+ {
+ return &vm.plainObjectSpace();
+ }
+ static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
+ {
+ return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
+ }
+
+private:
+ JSArrayBufferSinkPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure)
+ : Base(vm, structure)
+ {
+ }
+
+ void finishCreation(JSC::VM&, JSC::JSGlobalObject*);
+};
+STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSArrayBufferSinkPrototype, JSArrayBufferSinkPrototype::Base);
+
+
+
+const ClassInfo JSArrayBufferSinkPrototype::s_info = { "ArrayBufferSink"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSArrayBufferSinkPrototype) };
+const ClassInfo JSArrayBufferSink::s_info = { "ArrayBufferSink"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSArrayBufferSink) };
+const ClassInfo JSArrayBufferSinkConstructor::s_info = { "ArrayBufferSink"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSArrayBufferSinkConstructor) };
+
+JSArrayBufferSink::~JSArrayBufferSink()
+{
+ if (m_sinkPtr) {
+ ArrayBufferSink__finalize(m_sinkPtr);
+ }
+}
+
+
+
+
+JSArrayBufferSinkConstructor* JSArrayBufferSinkConstructor::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSObject* prototype)
+{
+ JSArrayBufferSinkConstructor* ptr = new (NotNull, JSC::allocateCell<JSArrayBufferSinkConstructor>(vm)) JSArrayBufferSinkConstructor(vm, structure, ArrayBufferSink__construct);
+ ptr->finishCreation(vm, globalObject, prototype);
+ return ptr;
+}
+
+JSArrayBufferSink* JSArrayBufferSink::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* sinkPtr)
+{
+ JSArrayBufferSink* ptr = new (NotNull, JSC::allocateCell<JSArrayBufferSink>(vm)) JSArrayBufferSink(vm, structure, sinkPtr);
+ ptr->finishCreation(vm);
+ return ptr;
+}
+
+void JSArrayBufferSinkConstructor::finishCreation(VM& vm, JSC::JSGlobalObject* globalObject, JSObject* prototype)
+{
+ Base::finishCreation(vm);
+ ASSERT(inherits(info()));
+ initializeProperties(vm, globalObject, prototype);
+}
+
+JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSArrayBufferSinkConstructor::construct(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) {
+ return ArrayBufferSink__construct(globalObject, callFrame);
+}
+
+
+void JSArrayBufferSinkConstructor::initializeProperties(VM& vm, JSC::JSGlobalObject* globalObject, JSObject* prototype)
+{
+ putDirect(vm, vm.propertyNames->length, jsNumber(0), JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum);
+ JSString* nameString = jsNontrivialString(vm, "ArrayBufferSink"_s);
+ m_originalName.set(vm, this, nameString);
+ putDirect(vm, vm.propertyNames->name, nameString, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum);
+}
+
+void JSArrayBufferSinkPrototype::finishCreation(JSC::VM& vm, JSC::JSGlobalObject* globalObject)
+{
+ Base::finishCreation(vm);
+ reifyStaticProperties(vm, JSArrayBufferSink::info(), JSArrayBufferSinkPrototypeTableValues, *this);
+ JSC_TO_STRING_TAG_WITHOUT_TRANSITION();
+}
+
+void JSArrayBufferSink::finishCreation(VM& vm)
+{
+ Base::finishCreation(vm);
+ ASSERT(inherits(info()));
+}
+
+void JSArrayBufferSink::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer)
+{
+ auto* thisObject = jsCast<JSArrayBufferSink*>(cell);
+ if (void* wrapped = thisObject->wrapped()) {
+ analyzer.setWrappedObjectForCell(cell, wrapped);
+ // if (thisObject->scriptExecutionContext())
+ // analyzer.setLabelForCell(cell, "url " + thisObject->scriptExecutionContext()->url().string());
+ }
+ Base::analyzeHeap(cell, analyzer);
+}
+
+void JSArrayBufferSink::destroy(JSCell* cell)
+{
+ static_cast<JSArrayBufferSink*>(cell)->JSArrayBufferSink::~JSArrayBufferSink();
+}
+
+
+
+ JSObject* createJSSinkPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, SinkID sinkID)
+ {
+ switch (sinkID) {
+
+ case ArrayBufferSink:
+ return JSArrayBufferSinkPrototype::create(vm, globalObject, JSArrayBufferSinkPrototype::createStructure(vm, globalObject, globalObject->objectPrototype()));
+
+default:
+ RELEASE_ASSERT_NOT_REACHED();
+ }
+}
+} // namespace WebCore
+
+
+extern "C" JSC__JSValue ArrayBufferSink__createObject(JSC__JSGlobalObject* arg0, void* sinkPtr)
+{
+ auto& vm = arg0->vm();
+ Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(arg0);
+ JSC::JSValue prototype = globalObject->ArrayBufferSinkPrototype();
+ JSC::Structure* structure = WebCore::JSArrayBufferSink::createStructure(vm, globalObject, prototype);
+ return JSC::JSValue::encode(WebCore::JSArrayBufferSink::create(vm, globalObject, structure, sinkPtr));
+}
+
+extern "C" void* ArrayBufferSink__fromJS(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1)
+{
+ JSC::VM& vm = WebCore::getVM(arg0);
+ if (auto* sink = JSC::jsDynamicCast<WebCore::JSArrayBufferSink*>(JSC::JSValue::decode(JSValue1)))
+ return sink->wrapped();
+
+ return nullptr;
+}
diff --git a/src/javascript/jsc/bindings/JSSink.h b/src/javascript/jsc/bindings/JSSink.h
new file mode 100644
index 000000000..c8e935c8e
--- /dev/null
+++ b/src/javascript/jsc/bindings/JSSink.h
@@ -0,0 +1,106 @@
+
+// AUTO-GENERATED FILE. DO NOT EDIT.
+// Generated by /Users/jarred/Code/bun/src/javascript/jsc/generate-jssink.js at 2022-06-13T03:43:13.999Z
+//
+#pragma once
+
+#include "root.h"
+
+#include "JSDOMWrapper.h"
+#include "wtf/NeverDestroyed.h"
+
+#include "Sink.h"
+
+extern "C" bool JSSink_isSink(JSC::JSGlobalObject*, JSC::EncodedJSValue);
+
+namespace WebCore {
+using namespace JSC;
+class JSArrayBufferSinkConstructor final : public JSC::InternalFunction {
+ public:
+ using Base = JSC::InternalFunction;
+ static JSArrayBufferSinkConstructor* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSC::JSObject* prototype);
+ static constexpr SinkID Sink = SinkID::ArrayBufferSink;
+
+ static constexpr unsigned StructureFlags = Base::StructureFlags;
+ static constexpr bool needsDestruction = false;
+
+ DECLARE_EXPORT_INFO;
+ template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
+ {
+ if constexpr (mode == JSC::SubspaceAccess::Concurrently)
+ return nullptr;
+ return WebCore::subspaceForImpl<JSArrayBufferSinkConstructor, WebCore::UseCustomHeapCellType::No>(
+ vm,
+ [](auto& spaces) { return spaces.m_clientSubspaceForJSSinkConstructor.get(); },
+ [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForJSSinkConstructor = WTFMove(space); },
+ [](auto& spaces) { return spaces.m_subspaceForJSSinkConstructor.get(); },
+ [](auto& spaces, auto&& space) { spaces.m_subspaceForJSSinkConstructor = WTFMove(space); });
+ }
+
+ static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
+ {
+ return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info());
+ }
+ void initializeProperties(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSObject* prototype);
+
+
+ // Must be defined for each specialization class.
+ static JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES construct(JSC::JSGlobalObject*, JSC::CallFrame*);
+
+ private:
+ JSArrayBufferSinkConstructor(JSC::VM& vm, JSC::Structure* structure, JSC::NativeFunction nativeFunction)
+ : Base(vm, structure, nativeFunction, nativeFunction)
+
+ {
+ }
+
+ void finishCreation(JSC::VM&, JSC::JSGlobalObject* globalObject, JSC::JSObject* prototype);
+ };
+
+ class JSArrayBufferSink final : public JSC::JSDestructibleObject {
+ public:
+ using Base = JSC::JSDestructibleObject;
+ static JSArrayBufferSink* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* sinkPtr);
+ static constexpr SinkID Sink = SinkID::ArrayBufferSink;
+
+ DECLARE_EXPORT_INFO;
+ template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
+ {
+ if constexpr (mode == JSC::SubspaceAccess::Concurrently)
+ return nullptr;
+ return WebCore::subspaceForImpl<JSArrayBufferSink, WebCore::UseCustomHeapCellType::No>(
+ vm,
+ [](auto& spaces) { return spaces.m_clientSubspaceForJSSink.get(); },
+ [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForJSSink = WTFMove(space); },
+ [](auto& spaces) { return spaces.m_subspaceForJSSink.get(); },
+ [](auto& spaces, auto&& space) { spaces.m_subspaceForJSSink = WTFMove(space); });
+ }
+
+ static void destroy(JSC::JSCell*);
+ static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
+ {
+ return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
+ }
+
+ ~JSArrayBufferSink();
+
+ void* wrapped() const { return m_sinkPtr; }
+
+ static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&);
+
+ void* m_sinkPtr;
+
+ JSArrayBufferSink(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr)
+ : Base(vm, structure)
+ {
+ m_sinkPtr = sinkPtr;
+ }
+
+ void finishCreation(JSC::VM&);
+ };
+JSC_DECLARE_CUSTOM_GETTER(functionArrayBufferSink__getter);
+
+
+JSObject* createJSSinkPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, WebCore::SinkID sinkID);
+
+} // namespace WebCore
diff --git a/src/javascript/jsc/bindings/Sink.h b/src/javascript/jsc/bindings/Sink.h
new file mode 100644
index 000000000..3d7435b29
--- /dev/null
+++ b/src/javascript/jsc/bindings/Sink.h
@@ -0,0 +1,15 @@
+#include "root.h"
+
+namespace WebCore {
+
+enum SinkID : uint8_t {
+ ArrayBufferSink = 0,
+ TextSink = 1,
+ FileSink = 2,
+ HTMLRewriterSink = 3,
+
+};
+static constexpr unsigned numberOfSinkIDs
+ = 4;
+
+} \ No newline at end of file
diff --git a/src/javascript/jsc/bindings/ZigGlobalObject.cpp b/src/javascript/jsc/bindings/ZigGlobalObject.cpp
index f0fb661a4..ba1965c9a 100644
--- a/src/javascript/jsc/bindings/ZigGlobalObject.cpp
+++ b/src/javascript/jsc/bindings/ZigGlobalObject.cpp
@@ -136,6 +136,8 @@ using JSBuffer = WebCore::JSBuffer;
#include "StructuredClone.h"
#include "ReadableStream.h"
+#include "JSSink.h"
+
// #include <iostream>
static bool has_loaded_jsc = false;
@@ -1635,6 +1637,26 @@ void GlobalObject::finishCreation(VM& vm)
Base::finishCreation(vm);
ASSERT(inherits(info()));
+ m_NapiClassStructure.initLater(
+ [](LazyClassStructure::Initializer& init) {
+ init.setStructure(Zig::NapiClass::createStructure(init.vm, init.global, init.global->functionPrototype()));
+ });
+
+ m_JSArrayBufferSinkClassStructure.initLater(
+ [](LazyClassStructure::Initializer& init) {
+ auto* prototype = createJSSinkPrototype(init.vm, init.global, WebCore::SinkID::ArrayBufferSink);
+ auto* structure = JSArrayBufferSink::createStructure(init.vm, init.global, prototype);
+ auto* constructor = JSArrayBufferSinkConstructor::create(init.vm, init.global, JSArrayBufferSinkConstructor::createStructure(init.vm, init.global, init.global->functionPrototype()), jsCast<JSObject*>(prototype));
+ init.setPrototype(prototype);
+ init.setStructure(structure);
+ init.setConstructor(constructor);
+ });
+
+ m_JSFFIFunctionStructure.initLater(
+ [](LazyClassStructure::Initializer& init) {
+ init.setStructure(Zig::JSFFIFunction::createStructure(init.vm, init.global, init.global->functionPrototype()));
+ });
+
addBuiltinGlobals(vm);
RELEASE_ASSERT(classInfo());
@@ -1878,6 +1900,12 @@ void GlobalObject::installAPIGlobals(JSClassRef* globals, int count, JSC::VM& vm
}
{
+ JSC::Identifier identifier = JSC::Identifier::fromString(vm, "ArrayBufferSink"_s);
+ object->putDirectCustomAccessor(vm, identifier, JSC::CustomGetterSetter::create(vm, functionArrayBufferSink__getter, nullptr),
+ JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly);
+ }
+
+ {
object->putDirectBuiltinFunction(vm, this, builtinNames.readableStreamToArrayPublicName(), readableStreamReadableStreamToArrayCodeGenerator(vm), PropertyAttribute::Builtin | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly);
}
@@ -1926,16 +1954,6 @@ void GlobalObject::installAPIGlobals(JSClassRef* globals, int count, JSC::VM& vm
this->addStaticGlobals(extraStaticGlobals.data(), extraStaticGlobals.size());
- m_NapiClassStructure.initLater(
- [](LazyClassStructure::Initializer& init) {
- init.setStructure(Zig::NapiClass::createStructure(init.vm, init.global, init.global->m_functionPrototype.get()));
- });
-
- m_JSFFIFunctionStructure.initLater(
- [](LazyClassStructure::Initializer& init) {
- init.setStructure(Zig::JSFFIFunction::createStructure(init.vm, init.global, init.global->m_functionPrototype.get()));
- });
-
// putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "SQL"_s), JSC::CustomGetterSetter::create(vm, JSSQLStatement_getter, nullptr),
// JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly);
@@ -1970,10 +1988,13 @@ void GlobalObject::visitChildrenImpl(JSCell* cell, Visitor& visitor)
thisObject->m_builtinInternalFunctions.visit(visitor);
thisObject->m_JSFFIFunctionStructure.visit(visitor);
+ thisObject->m_JSArrayBufferSinkClassStructure.visit(visitor);
+
visitor.append(thisObject->m_readableStreamToArrayBufferResolve);
visitor.append(thisObject->m_readableStreamToText);
visitor.append(thisObject->m_readableStreamToJSON);
visitor.append(thisObject->m_readableStreamToBlob);
+
ScriptExecutionContext* context = thisObject->scriptExecutionContext();
visitor.addOpaqueRoot(context);
}
diff --git a/src/javascript/jsc/bindings/ZigGlobalObject.h b/src/javascript/jsc/bindings/ZigGlobalObject.h
index 54d511c94..34c9ef412 100644
--- a/src/javascript/jsc/bindings/ZigGlobalObject.h
+++ b/src/javascript/jsc/bindings/ZigGlobalObject.h
@@ -148,6 +148,9 @@ public:
WebCore::JSBuiltinInternalFunctions& builtinInternalFunctions() { return m_builtinInternalFunctions; }
JSC::Structure* FFIFunctionStructure() { return m_JSFFIFunctionStructure.getInitializedOnMainThread(this); }
JSC::Structure* NapiClassStructure() { return m_NapiClassStructure.getInitializedOnMainThread(this); }
+ JSC::Structure* ArrayBufferSinkStructure() { return m_JSArrayBufferSinkClassStructure.getInitializedOnMainThread(this); }
+ JSC::JSObject* ArrayBufferSink() { return m_JSArrayBufferSinkClassStructure.constructorInitializedOnMainThread(this); }
+ JSC::JSValue ArrayBufferSinkPrototype() { return m_JSArrayBufferSinkClassStructure.prototypeInitializedOnMainThread(this); }
void* bunVM() { return m_bunVM; }
bool isThreadLocalDefaultGlobalObject = false;
@@ -171,6 +174,7 @@ private:
Ref<WebCore::DOMWrapperWorld> m_world;
LazyClassStructure m_JSFFIFunctionStructure;
LazyClassStructure m_NapiClassStructure;
+ LazyClassStructure m_JSArrayBufferSinkClassStructure;
DOMGuardedObjectSet m_guardedObjects WTF_GUARDED_BY_LOCK(m_gcLock);
void* m_bunVM;
diff --git a/src/javascript/jsc/bindings/bindings.zig b/src/javascript/jsc/bindings/bindings.zig
index 31f9b497d..cb606ba39 100644
--- a/src/javascript/jsc/bindings/bindings.zig
+++ b/src/javascript/jsc/bindings/bindings.zig
@@ -3236,6 +3236,8 @@ pub const CallFrame = opaque {
const argumentsCount_offset = thisValue_offset - 1;
const alignment = std.meta.alignment([]const JSC.JSValue);
+ pub const name = "JSC::CallFrame";
+
pub fn argumentsPtr(self: *const CallFrame) [*]const JSC.JSValue {
return @ptrCast([*]const JSC.JSValue, @alignCast(alignment, self)) + arguments_offset;
}
diff --git a/src/javascript/jsc/bindings/builtins/js/ReadableStream.js b/src/javascript/jsc/bindings/builtins/js/ReadableStream.js
index 4874067c3..57a683162 100644
--- a/src/javascript/jsc/bindings/builtins/js/ReadableStream.js
+++ b/src/javascript/jsc/bindings/builtins/js/ReadableStream.js
@@ -313,6 +313,8 @@ function consumeReadableStream(nativePtr, nativeType, inputStream) {
if (!this.#ptr) return @throwTypeError("ReadableStreamSink is already closed");
return this.processResult(this.#reader.readMany());
}
+
+
};
const minlength = nativeType + 1;
@@ -326,7 +328,7 @@ function consumeReadableStream(nativePtr, nativeType, inputStream) {
@throwTypeError("Cannot start reading from a locked stream");
}
- return new Prototype(inputStream.getReader(), nativePtr);
+ return new Prototype(inputStream.getReader(), nativePtr);
}
@globalPrivate
diff --git a/src/javascript/jsc/bindings/exports.zig b/src/javascript/jsc/bindings/exports.zig
index 4311eed61..47cd3488d 100644
--- a/src/javascript/jsc/bindings/exports.zig
+++ b/src/javascript/jsc/bindings/exports.zig
@@ -183,6 +183,9 @@ pub const NodePath = JSC.Node.Path;
pub const JSReadableStreamBlob = JSC.WebCore.ByteBlobLoader.Source.JSReadableStreamSource;
pub const JSReadableStreamFile = JSC.WebCore.FileBlobLoader.Source.JSReadableStreamSource;
+// Sinks
+pub const JSArrayBufferSink = JSC.WebCore.ArrayBufferSink.JSArrayBufferSink;
+
pub fn Errorable(comptime Type: type) type {
return extern struct {
result: Result,
@@ -1599,9 +1602,8 @@ pub const ZigConsoleClient = struct {
writer.print(comptime Output.prettyFmt("<r><yellow>{d}<r>", enable_ansi_colors), .{value.toInt64()});
},
.BigInt => {
- var sliced = value.toSlice(this.globalThis, bun.default_allocator);
- defer sliced.deinit();
- writer.print(comptime Output.prettyFmt("<r><yellow>{s}<r>", enable_ansi_colors), .{sliced.slice()});
+ var wtf = value.toWTFString(this.globalThis);
+ writer.print(comptime Output.prettyFmt("<r><yellow>{s}n<r>", enable_ansi_colors), .{wtf.slice()});
},
.Double => {
writer.print(comptime Output.prettyFmt("<r><yellow>{d}<r>", enable_ansi_colors), .{value.asNumber()});
@@ -2507,12 +2509,14 @@ comptime {
_ = Process.setTitle;
_ = Zig__getAPIGlobals;
_ = Zig__getAPIConstructors;
- std.testing.refAllDecls(NodeReadableStream);
- std.testing.refAllDecls(Bun.Timer);
- std.testing.refAllDecls(NodeWritableStream);
- std.testing.refAllDecls(NodePath);
- std.testing.refAllDecls(JSReadableStreamBlob);
- std.testing.refAllDecls(JSReadableStreamFile);
+ NodeReadableStream.shim.ref();
+ Bun.Timer.shim.ref();
+ NodeWritableStream.shim.ref();
+ NodePath.shim.ref();
+ JSReadableStreamBlob.shim.ref();
+ JSArrayBufferSink.shim.ref();
+
+ JSReadableStreamFile.shim.ref();
_ = ZigString__free;
_ = ZigString__free_global;
}
diff --git a/src/javascript/jsc/bindings/headers-cpp.h b/src/javascript/jsc/bindings/headers-cpp.h
index 28db16511..c2c68bc60 100644
--- a/src/javascript/jsc/bindings/headers-cpp.h
+++ b/src/javascript/jsc/bindings/headers-cpp.h
@@ -1,4 +1,4 @@
-//-- AUTOGENERATED FILE -- 1654055796
+//-- AUTOGENERATED FILE -- 1655075078
// clang-format off
#pragma once
@@ -256,8 +256,8 @@ extern "C" const size_t Zig__ConsoleClient_object_align_ = alignof(Zig::ConsoleC
extern "C" const size_t Bun__Timer_object_size_ = sizeof(Bun__Timer);
extern "C" const size_t Bun__Timer_object_align_ = alignof(Bun__Timer);
-const size_t sizes[31] = {sizeof(JSC::JSObject), sizeof(WebCore::DOMURL), sizeof(WebCore::FetchHeaders), sizeof(SystemError), sizeof(JSC::JSCell), sizeof(JSC::JSString), sizeof(Inspector::ScriptArguments), sizeof(JSC::JSModuleLoader), sizeof(JSC::JSModuleRecord), sizeof(JSC::JSPromise), sizeof(JSC::JSInternalPromise), sizeof(JSC::SourceOrigin), sizeof(JSC::SourceCode), sizeof(JSC::JSFunction), sizeof(JSC::JSGlobalObject), sizeof(WTF::URL), sizeof(WTF::String), sizeof(JSC::JSValue), sizeof(JSC::PropertyName), sizeof(JSC::Exception), sizeof(JSC::VM), sizeof(JSC::ThrowScope), sizeof(JSC::CatchScope), sizeof(JSC::Identifier), sizeof(WTF::StringImpl), sizeof(WTF::ExternalStringImpl), sizeof(WTF::StringView), sizeof(Zig::GlobalObject), sizeof(Bun__Readable), sizeof(Bun__Writable), sizeof(Bun__Path)};
+const size_t sizes[32] = {sizeof(JSC::JSObject), sizeof(WebCore::DOMURL), sizeof(WebCore::FetchHeaders), sizeof(SystemError), sizeof(JSC::JSCell), sizeof(JSC::JSString), sizeof(Inspector::ScriptArguments), sizeof(JSC::JSModuleLoader), sizeof(JSC::JSModuleRecord), sizeof(JSC::JSPromise), sizeof(JSC::JSInternalPromise), sizeof(JSC::SourceOrigin), sizeof(JSC::SourceCode), sizeof(JSC::JSFunction), sizeof(JSC::JSGlobalObject), sizeof(WTF::URL), sizeof(WTF::String), sizeof(JSC::JSValue), sizeof(JSC::PropertyName), sizeof(JSC::Exception), sizeof(JSC::VM), sizeof(JSC::ThrowScope), sizeof(JSC::CatchScope), sizeof(JSC::Identifier), sizeof(WTF::StringImpl), sizeof(WTF::ExternalStringImpl), sizeof(WTF::StringView), sizeof(Zig::GlobalObject), sizeof(Bun__Readable), sizeof(Bun__Writable), sizeof(Bun__Path), sizeof(ArrayBufferSink)};
-const char* names[31] = {"JSC__JSObject", "WebCore__DOMURL", "WebCore__FetchHeaders", "SystemError", "JSC__JSCell", "JSC__JSString", "Inspector__ScriptArguments", "JSC__JSModuleLoader", "JSC__JSModuleRecord", "JSC__JSPromise", "JSC__JSInternalPromise", "JSC__SourceOrigin", "JSC__SourceCode", "JSC__JSFunction", "JSC__JSGlobalObject", "WTF__URL", "WTF__String", "JSC__JSValue", "JSC__PropertyName", "JSC__Exception", "JSC__VM", "JSC__ThrowScope", "JSC__CatchScope", "JSC__Identifier", "WTF__StringImpl", "WTF__ExternalStringImpl", "WTF__StringView", "Zig__GlobalObject", "Bun__Readable", "Bun__Writable", "Bun__Path"};
+const char* names[32] = {"JSC__JSObject", "WebCore__DOMURL", "WebCore__FetchHeaders", "SystemError", "JSC__JSCell", "JSC__JSString", "Inspector__ScriptArguments", "JSC__JSModuleLoader", "JSC__JSModuleRecord", "JSC__JSPromise", "JSC__JSInternalPromise", "JSC__SourceOrigin", "JSC__SourceCode", "JSC__JSFunction", "JSC__JSGlobalObject", "WTF__URL", "WTF__String", "JSC__JSValue", "JSC__PropertyName", "JSC__Exception", "JSC__VM", "JSC__ThrowScope", "JSC__CatchScope", "JSC__Identifier", "WTF__StringImpl", "WTF__ExternalStringImpl", "WTF__StringView", "Zig__GlobalObject", "Bun__Readable", "Bun__Writable", "Bun__Path", "ArrayBufferSink"};
-const size_t aligns[31] = {alignof(JSC::JSObject), alignof(WebCore::DOMURL), alignof(WebCore::FetchHeaders), alignof(SystemError), alignof(JSC::JSCell), alignof(JSC::JSString), alignof(Inspector::ScriptArguments), alignof(JSC::JSModuleLoader), alignof(JSC::JSModuleRecord), alignof(JSC::JSPromise), alignof(JSC::JSInternalPromise), alignof(JSC::SourceOrigin), alignof(JSC::SourceCode), alignof(JSC::JSFunction), alignof(JSC::JSGlobalObject), alignof(WTF::URL), alignof(WTF::String), alignof(JSC::JSValue), alignof(JSC::PropertyName), alignof(JSC::Exception), alignof(JSC::VM), alignof(JSC::ThrowScope), alignof(JSC::CatchScope), alignof(JSC::Identifier), alignof(WTF::StringImpl), alignof(WTF::ExternalStringImpl), alignof(WTF::StringView), alignof(Zig::GlobalObject), alignof(Bun__Readable), alignof(Bun__Writable), alignof(Bun__Path)};
+const size_t aligns[32] = {alignof(JSC::JSObject), alignof(WebCore::DOMURL), alignof(WebCore::FetchHeaders), alignof(SystemError), alignof(JSC::JSCell), alignof(JSC::JSString), alignof(Inspector::ScriptArguments), alignof(JSC::JSModuleLoader), alignof(JSC::JSModuleRecord), alignof(JSC::JSPromise), alignof(JSC::JSInternalPromise), alignof(JSC::SourceOrigin), alignof(JSC::SourceCode), alignof(JSC::JSFunction), alignof(JSC::JSGlobalObject), alignof(WTF::URL), alignof(WTF::String), alignof(JSC::JSValue), alignof(JSC::PropertyName), alignof(JSC::Exception), alignof(JSC::VM), alignof(JSC::ThrowScope), alignof(JSC::CatchScope), alignof(JSC::Identifier), alignof(WTF::StringImpl), alignof(WTF::ExternalStringImpl), alignof(WTF::StringView), alignof(Zig::GlobalObject), alignof(Bun__Readable), alignof(Bun__Writable), alignof(Bun__Path), alignof(ArrayBufferSink)};
diff --git a/src/javascript/jsc/bindings/headers-handwritten.h b/src/javascript/jsc/bindings/headers-handwritten.h
index 7409427ac..a2f15cb74 100644
--- a/src/javascript/jsc/bindings/headers-handwritten.h
+++ b/src/javascript/jsc/bindings/headers-handwritten.h
@@ -44,6 +44,8 @@ typedef struct SystemError {
ZigString syscall;
} SystemError;
+typedef void* ArrayBufferSink;
+
typedef uint8_t ZigStackFrameCode;
const ZigStackFrameCode ZigStackFrameCodeNone = 0;
const ZigStackFrameCode ZigStackFrameCodeEval = 1;
diff --git a/src/javascript/jsc/bindings/headers-replacements.zig b/src/javascript/jsc/bindings/headers-replacements.zig
index fb5cf1496..4491c79af 100644
--- a/src/javascript/jsc/bindings/headers-replacements.zig
+++ b/src/javascript/jsc/bindings/headers-replacements.zig
@@ -1,6 +1,6 @@
// GENERATED FILE - do not modify!
const bindings = @import("../../../jsc.zig");
-
+pub const struct_JSC__CallFrame = bindings.CallFrame;
pub const struct_JSC__StringPrototype = bindings.StringPrototype;
pub const struct_JSC__SetIteratorPrototype = bindings.SetIteratorPrototype;
pub const struct_JSC__RegExpPrototype = bindings.RegExpPrototype;
@@ -17,6 +17,7 @@ pub const struct_JSC__AsyncGeneratorPrototype = bindings.AsyncGeneratorPrototype
pub const struct_JSC__AsyncGeneratorFunctionPrototype = bindings.AsyncGeneratorFunctionPrototype;
pub const struct_JSC__AsyncFunctionPrototype = bindings.AsyncFunctionPrototype;
pub const struct_JSC__ArrayPrototype = bindings.ArrayPrototype;
+
pub const struct_JSC__ArrayIteratorPrototype = bindings.ArrayIteratorPrototype;
pub const bWTF__URL = bindings.URL;
pub const bWTF__StringView = bindings.StringView;
@@ -63,3 +64,4 @@ pub const struct_WebCore__DOMURL = bindings.DOMURL;
pub const struct_WebCore__FetchHeaders = bindings.FetchHeaders;
pub const StringPointer = @import("../../../api/schema.zig").Api.StringPointer;
pub const struct_VirtualMachine = bindings.VirtualMachine;
+pub const ArrayBufferSink = @import("../webcore/streams.zig").ArrayBufferSink;
diff --git a/src/javascript/jsc/bindings/headers.h b/src/javascript/jsc/bindings/headers.h
index 217fdd884..e3d642676 100644
--- a/src/javascript/jsc/bindings/headers.h
+++ b/src/javascript/jsc/bindings/headers.h
@@ -1,5 +1,5 @@
// clang-format: off
-//-- AUTOGENERATED FILE -- 1654055796
+//-- AUTOGENERATED FILE -- 1655075078
#pragma once
#include <stddef.h>
@@ -105,6 +105,7 @@ typedef void* JSClassRef;
typedef struct JSC__RegExpPrototype JSC__RegExpPrototype; // JSC::RegExpPrototype
typedef struct JSC__MapIteratorPrototype JSC__MapIteratorPrototype; // JSC::MapIteratorPrototype
typedef struct WebCore__FetchHeaders WebCore__FetchHeaders; // WebCore::FetchHeaders
+ typedef struct JSC__CallFrame JSC__CallFrame; // JSC::CallFrame
typedef bWTF__StringView WTF__StringView; // WTF::StringView
typedef bJSC__ThrowScope JSC__ThrowScope; // JSC::ThrowScope
typedef bWTF__StringImpl WTF__StringImpl; // WTF::StringImpl
@@ -165,6 +166,7 @@ typedef void* JSClassRef;
class SourceCode;
class FunctionPrototype;
class IteratorPrototype;
+ class CallFrame;
class ObjectPrototype;
}
namespace WTF {
@@ -228,6 +230,7 @@ typedef void* JSClassRef;
using JSC__SourceCode = JSC::SourceCode;
using JSC__FunctionPrototype = JSC::FunctionPrototype;
using JSC__IteratorPrototype = JSC::IteratorPrototype;
+ using JSC__CallFrame = JSC::CallFrame;
using JSC__ObjectPrototype = JSC::ObjectPrototype;
using WTF__URL = WTF::URL;
using WTF__StringImpl = WTF::StringImpl;
@@ -727,6 +730,21 @@ ZIG_DECL JSC__JSValue ByteBlob__JSReadableStreamSource__load(JSC__JSGlobalObject
ZIG_DECL JSC__JSValue FileBlobLoader__JSReadableStreamSource__load(JSC__JSGlobalObject* arg0);
#endif
+CPP_DECL JSC__JSValue ArrayBufferSink__createObject(JSC__JSGlobalObject* arg0, void* arg1);
+CPP_DECL void* ArrayBufferSink__fromJS(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1);
+
+#ifdef __cplusplus
+
+ZIG_DECL JSC__JSValue ArrayBufferSink__close(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1);
+ZIG_DECL JSC__JSValue ArrayBufferSink__closeWithError(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1);
+ZIG_DECL JSC__JSValue ArrayBufferSink__construct(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1);
+ZIG_DECL JSC__JSValue ArrayBufferSink__drain(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1);
+ZIG_DECL JSC__JSValue ArrayBufferSink__end(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1);
+ZIG_DECL void ArrayBufferSink__finalize(void* arg0);
+ZIG_DECL JSC__JSValue ArrayBufferSink__start(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1);
+ZIG_DECL JSC__JSValue ArrayBufferSink__write(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1);
+
+#endif
#ifdef __cplusplus
diff --git a/src/javascript/jsc/bindings/headers.zig b/src/javascript/jsc/bindings/headers.zig
index ce7cbee1e..e6417ab0f 100644
--- a/src/javascript/jsc/bindings/headers.zig
+++ b/src/javascript/jsc/bindings/headers.zig
@@ -1,6 +1,6 @@
// GENERATED FILE - do not modify!
const bindings = @import("../../../jsc.zig");
-
+pub const struct_JSC__CallFrame = bindings.CallFrame;
pub const struct_JSC__StringPrototype = bindings.StringPrototype;
pub const struct_JSC__SetIteratorPrototype = bindings.SetIteratorPrototype;
pub const struct_JSC__RegExpPrototype = bindings.RegExpPrototype;
@@ -17,6 +17,7 @@ pub const struct_JSC__AsyncGeneratorPrototype = bindings.AsyncGeneratorPrototype
pub const struct_JSC__AsyncGeneratorFunctionPrototype = bindings.AsyncGeneratorFunctionPrototype;
pub const struct_JSC__AsyncFunctionPrototype = bindings.AsyncFunctionPrototype;
pub const struct_JSC__ArrayPrototype = bindings.ArrayPrototype;
+
pub const struct_JSC__ArrayIteratorPrototype = bindings.ArrayIteratorPrototype;
pub const bWTF__URL = bindings.URL;
pub const bWTF__StringView = bindings.StringView;
@@ -63,6 +64,7 @@ pub const struct_WebCore__DOMURL = bindings.DOMURL;
pub const struct_WebCore__FetchHeaders = bindings.FetchHeaders;
pub const StringPointer = @import("../../../api/schema.zig").Api.StringPointer;
pub const struct_VirtualMachine = bindings.VirtualMachine;
+pub const ArrayBufferSink = @import("../webcore/streams.zig").ArrayBufferSink;
// GENERATED CODE - DO NOT MODIFY BY HAND
pub const ptrdiff_t = c_long;
@@ -116,6 +118,8 @@ pub const JSC__RegExpPrototype = struct_JSC__RegExpPrototype;
pub const JSC__MapIteratorPrototype = struct_JSC__MapIteratorPrototype;
pub const WebCore__FetchHeaders = struct_WebCore__FetchHeaders;
+
+pub const JSC__CallFrame = struct_JSC__CallFrame;
pub const WTF__StringView = bWTF__StringView;
pub const JSC__ThrowScope = bJSC__ThrowScope;
pub const WTF__StringImpl = bWTF__StringImpl;
@@ -460,4 +464,6 @@ pub extern fn Zig__GlobalObject__resetModuleRegistryMap(arg0: [*c]JSC__JSGlobalO
pub extern fn Bun__Readable__create(arg0: [*c]Bun__Readable, arg1: [*c]JSC__JSGlobalObject) JSC__JSValue;
pub extern fn Bun__Writable__create(arg0: [*c]Bun__Writable, arg1: [*c]JSC__JSGlobalObject) JSC__JSValue;
pub extern fn Bun__Path__create(arg0: [*c]JSC__JSGlobalObject, arg1: bool) JSC__JSValue;
+pub extern fn ArrayBufferSink__createObject(arg0: [*c]JSC__JSGlobalObject, arg1: ?*anyopaque) JSC__JSValue;
+pub extern fn ArrayBufferSink__fromJS(arg0: [*c]JSC__JSGlobalObject, JSValue1: JSC__JSValue) ?*anyopaque;
pub extern fn ZigException__fromException(arg0: [*c]JSC__Exception) ZigException;
diff --git a/src/javascript/jsc/bindings/shimmer.zig b/src/javascript/jsc/bindings/shimmer.zig
index 116327207..8d8fda591 100644
--- a/src/javascript/jsc/bindings/shimmer.zig
+++ b/src/javascript/jsc/bindings/shimmer.zig
@@ -13,6 +13,20 @@ pub fn Shimmer(comptime _namespace: []const u8, comptime _name: []const u8, comp
pub const namespace = _namespace;
pub const name = _name;
+ pub fn ref() void {
+ if (comptime @hasDecl(Parent, "Export")) {
+ inline for (Parent.Export) |exp| {
+ _ = exp;
+ }
+ }
+
+ if (comptime @hasDecl(Parent, "Extern")) {
+ inline for (Parent.Extern) |exp| {
+ _ = @field(Parent, exp);
+ }
+ }
+ }
+
// fn toCppType(comptime FromType: type) type {
// var NewReturnType = FromType;
diff --git a/src/javascript/jsc/bindings/webcore/DOMClientIsoSubspaces.h b/src/javascript/jsc/bindings/webcore/DOMClientIsoSubspaces.h
index 14e748a9a..876b6843f 100644
--- a/src/javascript/jsc/bindings/webcore/DOMClientIsoSubspaces.h
+++ b/src/javascript/jsc/bindings/webcore/DOMClientIsoSubspaces.h
@@ -22,6 +22,8 @@ public:
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForNapiPrototype;
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForJSSQLStatement;
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForJSSQLStatementConstructor;
+ std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForJSSinkConstructor;
+ std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForJSSink;
/* --- bun --- */
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForDOMException;
diff --git a/src/javascript/jsc/bindings/webcore/DOMIsoSubspaces.h b/src/javascript/jsc/bindings/webcore/DOMIsoSubspaces.h
index b434ff771..6b55f05e7 100644
--- a/src/javascript/jsc/bindings/webcore/DOMIsoSubspaces.h
+++ b/src/javascript/jsc/bindings/webcore/DOMIsoSubspaces.h
@@ -22,6 +22,8 @@ public:
std::unique_ptr<IsoSubspace> m_subspaceForNapiPrototype;
std::unique_ptr<IsoSubspace> m_subspaceForJSSQLStatement;
std::unique_ptr<IsoSubspace> m_subspaceForJSSQLStatementConstructor;
+ std::unique_ptr<IsoSubspace> m_subspaceForJSSinkConstructor;
+ std::unique_ptr<IsoSubspace> m_subspaceForJSSink;
/*-- BUN --*/
// std::unique_ptr<IsoSubspace> m_subspaceForTouch;
diff --git a/src/javascript/jsc/generate-jssink.js b/src/javascript/jsc/generate-jssink.js
new file mode 100644
index 000000000..ba1bbf7ab
--- /dev/null
+++ b/src/javascript/jsc/generate-jssink.js
@@ -0,0 +1,380 @@
+const classes = ["ArrayBufferSink"];
+
+function header() {
+ function classTemplate(idName) {
+ const name = `JS${idName}`;
+ const constructor = `${name}Constructor`;
+ const constructorName = `JS${name}Constructor`;
+
+ return `class ${constructor} final : public JSC::InternalFunction {
+ public:
+ using Base = JSC::InternalFunction;
+ static ${constructor}* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSC::JSObject* prototype);
+ static constexpr SinkID Sink = SinkID::${idName};
+
+ static constexpr unsigned StructureFlags = Base::StructureFlags;
+ static constexpr bool needsDestruction = false;
+
+ DECLARE_EXPORT_INFO;
+ template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
+ {
+ if constexpr (mode == JSC::SubspaceAccess::Concurrently)
+ return nullptr;
+ return WebCore::subspaceForImpl<${constructor}, WebCore::UseCustomHeapCellType::No>(
+ vm,
+ [](auto& spaces) { return spaces.m_clientSubspaceForJSSinkConstructor.get(); },
+ [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForJSSinkConstructor = WTFMove(space); },
+ [](auto& spaces) { return spaces.m_subspaceForJSSinkConstructor.get(); },
+ [](auto& spaces, auto&& space) { spaces.m_subspaceForJSSinkConstructor = WTFMove(space); });
+ }
+
+ static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
+ {
+ return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info());
+ }
+ void initializeProperties(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSObject* prototype);
+
+
+ // Must be defined for each specialization class.
+ static JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES construct(JSC::JSGlobalObject*, JSC::CallFrame*);
+
+ private:
+ ${constructor}(JSC::VM& vm, JSC::Structure* structure, JSC::NativeFunction nativeFunction)
+ : Base(vm, structure, nativeFunction, nativeFunction)
+
+ {
+ }
+
+ void finishCreation(JSC::VM&, JSC::JSGlobalObject* globalObject, JSC::JSObject* prototype);
+ };
+
+ class ${name} final : public JSC::JSDestructibleObject {
+ public:
+ using Base = JSC::JSDestructibleObject;
+ static ${name}* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* sinkPtr);
+ static constexpr SinkID Sink = SinkID::${idName};
+
+ DECLARE_EXPORT_INFO;
+ template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
+ {
+ if constexpr (mode == JSC::SubspaceAccess::Concurrently)
+ return nullptr;
+ return WebCore::subspaceForImpl<${name}, WebCore::UseCustomHeapCellType::No>(
+ vm,
+ [](auto& spaces) { return spaces.m_clientSubspaceForJSSink.get(); },
+ [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForJSSink = WTFMove(space); },
+ [](auto& spaces) { return spaces.m_subspaceForJSSink.get(); },
+ [](auto& spaces, auto&& space) { spaces.m_subspaceForJSSink = WTFMove(space); });
+ }
+
+ static void destroy(JSC::JSCell*);
+ static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
+ {
+ return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
+ }
+
+ ~${name}();
+
+ void* wrapped() const { return m_sinkPtr; }
+
+ static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&);
+
+ void* m_sinkPtr;
+
+ ${name}(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr)
+ : Base(vm, structure)
+ {
+ m_sinkPtr = sinkPtr;
+ }
+
+ void finishCreation(JSC::VM&);
+ };
+JSC_DECLARE_CUSTOM_GETTER(function${idName}__getter);
+
+ `;
+ }
+
+ const outer = `
+// AUTO-GENERATED FILE. DO NOT EDIT.
+// Generated by ${import.meta.path} at ${new Date().toISOString()}
+//
+#pragma once
+
+#include "root.h"
+
+#include "JSDOMWrapper.h"
+#include "wtf/NeverDestroyed.h"
+
+#include "Sink.h"
+
+extern "C" bool JSSink_isSink(JSC::JSGlobalObject*, JSC::EncodedJSValue);
+
+namespace WebCore {
+using namespace JSC;
+`;
+
+ const bottom = `JSObject* createJSSinkPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, WebCore::SinkID sinkID);
+
+} // namespace WebCore
+`;
+ var templ = outer;
+ for (let name of classes) {
+ templ += classTemplate(name) + "\n";
+ }
+ templ += bottom;
+ return templ;
+}
+
+async function implementation() {
+ const head = `
+// AUTO-GENERATED FILE. DO NOT EDIT.
+// Generated by ${import.meta.path} at ${new Date().toISOString()}
+// To regenerate this file, run:
+//
+// bun src/javascript/jsc/generate-jssink.js
+//
+#include "root.h"
+#include "JSSink.h"
+
+#include "ActiveDOMObject.h"
+#include "ExtendedDOMClientIsoSubspaces.h"
+#include "ExtendedDOMIsoSubspaces.h"
+#include "IDLTypes.h"
+// #include "JSBlob.h"
+#include "JSDOMAttribute.h"
+#include "JSDOMBinding.h"
+#include "JSDOMConstructor.h"
+#include "JSDOMConvertBase.h"
+#include "JSDOMConvertInterface.h"
+#include "JSDOMConvertStrings.h"
+#include "JSDOMExceptionHandling.h"
+#include "JSDOMGlobalObject.h"
+#include "JSDOMGlobalObjectInlines.h"
+#include "JSDOMOperation.h"
+#include "JSDOMWrapperCache.h"
+#include "ScriptExecutionContext.h"
+#include "WebCoreJSClientData.h"
+#include "JavaScriptCore/FunctionPrototype.h"
+#include "JavaScriptCore/HeapAnalyzer.h"
+
+#include "JavaScriptCore/JSDestructibleObjectHeapCellType.h"
+#include "JavaScriptCore/SlotVisitorMacros.h"
+#include "JavaScriptCore/SubspaceInlines.h"
+#include "wtf/GetPtr.h"
+#include "wtf/PointerPreparations.h"
+#include "wtf/URL.h"
+#include "JavaScriptCore/BuiltinNames.h"
+
+#include "JSBufferEncodingType.h"
+#include "JSBufferPrototypeBuiltins.h"
+#include "JSBufferConstructorBuiltins.h"
+#include "JavaScriptCore/JSBase.h"
+#if ENABLE(MEDIA_SOURCE)
+#include "BufferMediaSource.h"
+#include "JSMediaSource.h"
+#endif
+
+// #include "JavaScriptCore/JSTypedArrayViewPrototype.h"
+#include "JavaScriptCore/JSArrayBufferViewInlines.h"
+
+namespace WebCore {
+using namespace JSC;
+
+
+`;
+ var templ = head;
+
+ for (let name of classes) {
+ templ += `
+JSC_DEFINE_CUSTOM_GETTER(function${name}__getter, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName))
+{
+ auto& vm = lexicalGlobalObject->vm();
+ Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject);
+
+ return JSC::JSValue::encode(globalObject->${name}());
+}
+`;
+ }
+
+ templ += `
+${(await Bun.file(import.meta.dir + "/bindings/JSSink+custom.h").text()).trim()}
+`;
+
+ const footer = `
+} // namespace WebCore
+
+`;
+
+ for (let name of classes) {
+ const constructorName = `JS${name}Constructor`;
+ const className = `JS${name}`;
+ const prototypeName = `JS${name}Prototype`;
+
+ templ += `
+#pragma mark - ${name}
+
+class ${prototypeName} final : public JSC::JSNonFinalObject {
+public:
+ using Base = JSC::JSNonFinalObject;
+
+ static ${prototypeName}* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure)
+ {
+ ${prototypeName}* ptr = new (NotNull, JSC::allocateCell<${prototypeName}>(vm)) ${prototypeName}(vm, globalObject, structure);
+ ptr->finishCreation(vm, globalObject);
+ return ptr;
+ }
+
+ DECLARE_INFO;
+ template<typename CellType, JSC::SubspaceAccess>
+ static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
+ {
+ return &vm.plainObjectSpace();
+ }
+ static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
+ {
+ return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
+ }
+
+private:
+ ${prototypeName}(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure)
+ : Base(vm, structure)
+ {
+ }
+
+ void finishCreation(JSC::VM&, JSC::JSGlobalObject*);
+};
+STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(${prototypeName}, ${prototypeName}::Base);
+
+
+
+const ClassInfo ${prototypeName}::s_info = { "${name}"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(${prototypeName}) };
+const ClassInfo ${className}::s_info = { "${name}"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(${className}) };
+const ClassInfo ${constructorName}::s_info = { "${name}"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(${constructorName}) };
+
+${className}::~${className}()
+{
+ if (m_sinkPtr) {
+ ${name}__finalize(m_sinkPtr);
+ }
+}
+
+
+`;
+
+ templ += `
+
+${constructorName}* ${constructorName}::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSObject* prototype)
+{
+ ${constructorName}* ptr = new (NotNull, JSC::allocateCell<${constructorName}>(vm)) ${constructorName}(vm, structure, ${name}__construct);
+ ptr->finishCreation(vm, globalObject, prototype);
+ return ptr;
+}
+
+${className}* ${className}::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* sinkPtr)
+{
+ ${className}* ptr = new (NotNull, JSC::allocateCell<${className}>(vm)) ${className}(vm, structure, sinkPtr);
+ ptr->finishCreation(vm);
+ return ptr;
+}
+
+void ${constructorName}::finishCreation(VM& vm, JSC::JSGlobalObject* globalObject, JSObject* prototype)
+{
+ Base::finishCreation(vm);
+ ASSERT(inherits(info()));
+ initializeProperties(vm, globalObject, prototype);
+}
+
+JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES ${constructorName}::construct(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) {
+ return ${name}__construct(globalObject, callFrame);
+}
+
+
+void ${constructorName}::initializeProperties(VM& vm, JSC::JSGlobalObject* globalObject, JSObject* prototype)
+{
+ putDirect(vm, vm.propertyNames->length, jsNumber(0), JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum);
+ JSString* nameString = jsNontrivialString(vm, "${name}"_s);
+ m_originalName.set(vm, this, nameString);
+ putDirect(vm, vm.propertyNames->name, nameString, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum);
+}
+
+void ${prototypeName}::finishCreation(JSC::VM& vm, JSC::JSGlobalObject* globalObject)
+{
+ Base::finishCreation(vm);
+ reifyStaticProperties(vm, ${className}::info(), ${className}PrototypeTableValues, *this);
+ JSC_TO_STRING_TAG_WITHOUT_TRANSITION();
+}
+
+void ${className}::finishCreation(VM& vm)
+{
+ Base::finishCreation(vm);
+ ASSERT(inherits(info()));
+}
+
+void ${className}::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer)
+{
+ auto* thisObject = jsCast<${className}*>(cell);
+ if (void* wrapped = thisObject->wrapped()) {
+ analyzer.setWrappedObjectForCell(cell, wrapped);
+ // if (thisObject->scriptExecutionContext())
+ // analyzer.setLabelForCell(cell, "url " + thisObject->scriptExecutionContext()->url().string());
+ }
+ Base::analyzeHeap(cell, analyzer);
+}
+
+void ${className}::destroy(JSCell* cell)
+{
+ static_cast<${className}*>(cell)->${className}::~${className}();
+}
+
+
+`;
+ }
+
+ templ += `
+ JSObject* createJSSinkPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, SinkID sinkID)
+ {
+ switch (sinkID) {
+ `;
+ for (let name of classes) {
+ templ += `
+ case ${name}:
+ return JS${name}Prototype::create(vm, globalObject, JS${name}Prototype::createStructure(vm, globalObject, globalObject->objectPrototype()));
+`;
+ }
+ templ += `
+default:
+ RELEASE_ASSERT_NOT_REACHED();
+ }
+}`;
+
+ templ += footer;
+
+ for (let name of classes) {
+ templ += `
+extern "C" JSC__JSValue ${name}__createObject(JSC__JSGlobalObject* arg0, void* sinkPtr)
+{
+ auto& vm = arg0->vm();
+ Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(arg0);
+ JSC::JSValue prototype = globalObject->${name}Prototype();
+ JSC::Structure* structure = WebCore::JS${name}::createStructure(vm, globalObject, prototype);
+ return JSC::JSValue::encode(WebCore::JS${name}::create(vm, globalObject, structure, sinkPtr));
+}
+
+extern "C" void* ${name}__fromJS(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1)
+{
+ JSC::VM& vm = WebCore::getVM(arg0);
+ if (auto* sink = JSC::jsDynamicCast<WebCore::JS${name}*>(JSC::JSValue::decode(JSValue1)))
+ return sink->wrapped();
+
+ return nullptr;
+}
+`;
+ return templ;
+ }
+}
+
+await Bun.write(import.meta.dir + "/bindings/JSSink.h", header());
+await Bun.write(
+ import.meta.dir + "/bindings/JSSink.cpp",
+ await implementation()
+);
diff --git a/src/javascript/jsc/node/types.zig b/src/javascript/jsc/node/types.zig
index 3906da392..0f9c31683 100644
--- a/src/javascript/jsc/node/types.zig
+++ b/src/javascript/jsc/node/types.zig
@@ -85,6 +85,55 @@ pub fn Maybe(comptime ResultType: type) type {
pub const todo: @This() = @This(){ .err = Syscall.Error.todo };
+ pub fn toJS(this: @This(), globalThis: *JSC.JSGlobalObject) JSC.JSValue {
+ switch (this) {
+ .err => |e| {
+ return e.toJSC(globalThis);
+ },
+ .result => |r| {
+ if (comptime ReturnType == void) {
+ return JSC.JSValue.jsUndefined();
+ }
+
+ if (comptime ReturnType == JSC.ArrayBuffer) {
+ return r.toJS(globalThis, null);
+ }
+
+ if (comptime std.meta.trait.isNumber(ResultType) or std.meta.trait.isFloat(ResultType)) {
+ return JSC.JSValue.jsNumber(r);
+ }
+
+ if (comptime std.meta.trait.isZigString(ResultType)) {
+ if (ResultType == []u8) {
+ return JSC.ArrayBuffer.fromBytes(r, .ArrayBuffer).toJS(globalThis, null);
+ }
+ return JSC.ZigString.init(std.mem.span(r)).withEncoding().toValueAuto(globalThis);
+ }
+
+ if (comptime @typeInfo(ReturnType) == .Bool) {
+ return JSC.JSValue.jsBoolean(r);
+ }
+
+ if (comptime std.meta.trait.isContainer(ReturnType)) {
+ return r.toJS(globalThis);
+ }
+
+ @compileError("toJS Not implemented for type " ++ @typeName(ReturnType));
+ },
+ }
+ }
+
+ pub fn toArrayBuffer(this: @This(), globalThis: *JSC.JSGlobalObject) JSC.JSValue {
+ switch (this) {
+ .err => |e| {
+ return e.toJSC(globalThis);
+ },
+ .result => |r| {
+ return JSC.ArrayBuffer.fromBytes(r, .ArrayBuffer).toJS(globalThis, null);
+ },
+ }
+ }
+
pub inline fn getErrno(this: @This()) os.E {
return switch (this) {
.result => os.E.SUCCESS,
diff --git a/src/javascript/jsc/webcore.zig b/src/javascript/jsc/webcore.zig
index 1ed585018..799b408f2 100644
--- a/src/javascript/jsc/webcore.zig
+++ b/src/javascript/jsc/webcore.zig
@@ -5,6 +5,14 @@ pub usingnamespace @import("./webcore/streams.zig");
const JSC = @import("../../jsc.zig");
const std = @import("std");
+pub const Lifetime = enum {
+ clone,
+ transfer,
+ share,
+ /// When reading from a fifo like STDIN/STDERR
+ temporary,
+};
+
pub const Crypto = struct {
const UUID = @import("./uuid.zig");
diff --git a/src/javascript/jsc/webcore/response.zig b/src/javascript/jsc/webcore/response.zig
index 8d585f93c..75c9f8d98 100644
--- a/src/javascript/jsc/webcore/response.zig
+++ b/src/javascript/jsc/webcore/response.zig
@@ -3122,14 +3122,7 @@ pub const Blob = struct {
return this.store.?.sharedView()[this.offset..][0..this.size];
}
- pub const Lifetime = enum {
- clone,
- transfer,
- share,
- /// When reading from a fifo like STDIN/STDERR
- temporary,
- };
-
+ pub const Lifetime = JSC.WebCore.Lifetime;
pub fn setIsASCIIFlag(this: *Blob, is_all_ascii: bool) void {
this.is_all_ascii = is_all_ascii;
// if this Blob represents the entire binary data
@@ -3811,7 +3804,8 @@ pub const Body = struct {
pub const PendingValue = struct {
promise: ?JSValue = null,
- stream: ?JSC.WebCore.ReadableStream = null,
+ readable: ?JSC.WebCore.ReadableStream = null,
+ // writable: JSC.WebCore.Sink
global: *JSGlobalObject,
task: ?*anyopaque = null,
@@ -3826,28 +3820,28 @@ pub const Body = struct {
pub fn setPromise(value: *PendingValue, globalThis: *JSC.JSGlobalObject, action: Action) JSValue {
value.action = action;
- if (value.stream) |*stream| {
- // switch (stream.ptr) {
+ if (value.readable) |*readable| {
+ // switch (readable.ptr) {
// .JavaScript
// }
switch (action) {
.getText, .getJSON, .getBlob, .getArrayBuffer => {
- switch (stream.ptr) {
+ switch (readable.ptr) {
.Blob => unreachable,
else => {},
}
value.promise = switch (action) {
- .getJSON => globalThis.readableStreamToJSON(stream.value),
- .getArrayBuffer => globalThis.readableStreamToArrayBuffer(stream.value),
- .getText => globalThis.readableStreamToText(stream.value),
- .getBlob => globalThis.readableStreamToBlob(stream.value),
+ .getJSON => globalThis.readableStreamToJSON(readable.value),
+ .getArrayBuffer => globalThis.readableStreamToArrayBuffer(readable.value),
+ .getText => globalThis.readableStreamToText(readable.value),
+ .getBlob => globalThis.readableStreamToBlob(readable.value),
else => unreachable,
};
value.promise.?.ensureStillAlive();
- stream.value.unprotect();
+ readable.value.unprotect();
// js now owns the memory
- value.stream = null;
+ value.readable = null;
return value.promise.?;
},
@@ -3894,15 +3888,15 @@ pub const Body = struct {
pub const empty = Value{ .Empty = .{} };
- pub fn fromReadableStream(stream: JSC.WebCore.ReadableStream, globalThis: *JSGlobalObject) Value {
- if (stream.isLocked(globalThis)) {
+ pub fn fromReadableStream(readable: JSC.WebCore.ReadableStream, globalThis: *JSGlobalObject) Value {
+ if (readable.isLocked(globalThis)) {
return .{ .Error = ZigString.init("Cannot use a locked ReadableStream").toErrorInstance(globalThis) };
}
- stream.value.protect();
+ readable.value.protect();
return .{
.Locked = .{
- .stream = stream,
+ .readable = readable,
.global = globalThis,
},
};
@@ -3911,9 +3905,9 @@ pub const Body = struct {
pub fn resolve(this: *Value, new: *Value, global: *JSGlobalObject) void {
if (this.* == .Locked) {
var locked = &this.Locked;
- if (locked.stream) |stream| {
- stream.done();
- locked.stream = null;
+ if (locked.readable) |readable| {
+ readable.done();
+ locked.readable = null;
}
if (locked.callback) |callback| {
@@ -3988,9 +3982,9 @@ pub const Body = struct {
locked.promise = null;
}
- if (locked.stream) |stream| {
- stream.done();
- locked.stream = null;
+ if (locked.readable) |readable| {
+ readable.done();
+ locked.readable = null;
}
this.* = .{ .Error = error_instance };
@@ -4024,8 +4018,8 @@ pub const Body = struct {
pub fn deinit(this: *Value) void {
const tag = @as(Tag, this.*);
if (tag == .Locked) {
- if (this.Locked.stream) |*stream| {
- stream.done();
+ if (this.Locked.readable) |*readable| {
+ readable.done();
}
this.Locked.deinit = true;
@@ -4593,6 +4587,21 @@ fn BlobInterface(comptime Type: type) type {
blob.allocator = getAllocator(ctx);
return JSC.JSPromise.resolvedPromiseValue(ctx.ptr(), JSValue.fromRef(Blob.Class.make(ctx, ptr))).asObjectRef();
}
+
+ // pub fn getBody(
+ // this: *Type,
+ // ctx: js.JSContextRef,
+ // _: js.JSObjectRef,
+ // _: js.JSObjectRef,
+ // _: []const js.JSValueRef,
+ // _: js.ExceptionRef,
+ // ) js.JSValueRef {
+ // var value: *Body.Value = this.getBodyValue();
+
+ // switch (value.*) {
+ // .Empty => {},
+ // }
+ // }
};
}
diff --git a/src/javascript/jsc/webcore/streams.zig b/src/javascript/jsc/webcore/streams.zig
index cb7791e0f..e78bd5e48 100644
--- a/src/javascript/jsc/webcore/streams.zig
+++ b/src/javascript/jsc/webcore/streams.zig
@@ -49,7 +49,7 @@ const Request = JSC.WebCore.Request;
pub const ReadableStream = struct {
value: JSValue,
- ptr: Handle,
+ ptr: Source,
pub fn done(this: *const ReadableStream) void {
this.value.unprotect();
@@ -63,14 +63,22 @@ pub const ReadableStream = struct {
File = 2,
HTTPRequest = 3,
HTTPSRequest = 4,
+ HTTPResponse = 5,
+ HTTPSResponse = 6,
};
- pub const Handle = union(Tag) {
+ pub const Source = union(Tag) {
Invalid: void,
JavaScript: void,
Blob: *ByteBlobLoader,
File: *FileBlobLoader,
+ // HTTPRequest: *HTTPRequest,
HTTPRequest: void,
+ // HTTPSRequest: *HTTPSRequest,
HTTPSRequest: void,
+ // HTTPRequest: *HTTPRequest,
+ HTTPResponse: void,
+ // HTTPSRequest: *HTTPSRequest,
+ HTTPSResponse: void,
};
extern fn ReadableStreamTag__tagged(globalObject: *JSGlobalObject, possibleReadableStream: JSValue, ptr: *JSValue) Tag;
@@ -116,6 +124,19 @@ pub const ReadableStream = struct {
.File = ptr.asPtr(FileBlobLoader),
},
},
+
+ // .HTTPRequest => ReadableStream{
+ // .value = value,
+ // .ptr = .{
+ // .HTTPRequest = ptr.asPtr(HTTPRequest),
+ // },
+ // },
+ // .HTTPSRequest => ReadableStream{
+ // .value = value,
+ // .ptr = .{
+ // .HTTPSRequest = ptr.asPtr(HTTPSRequest),
+ // },
+ // },
else => null,
};
}
@@ -181,81 +202,6 @@ pub const ReadableStream = struct {
return @intCast(JSC.Node.FileDescriptor, out);
}
};
-
- pub fn NewNativeReader(
- comptime Context: type,
- comptime onEnqueue: anytype,
- comptime onEnqueueMany: anytype,
- comptime onClose: anytype,
- comptime onError: anytype,
- comptime name_: []const u8,
- ) type {
- return struct {
- pub const JSReadableStreamReaderNative = struct {
- pub const shim = JSC.Shimmer(std.mem.span(name_), "JSReadableStreamReaderNative", @This());
- pub const tag = Context.tag;
- pub const name = std.fmt.comptimePrint("{s}_JSReadableStreamReaderNative", .{std.mem.span(name_)});
-
- pub fn enqueue(globalThis: *JSGlobalObject, callframe: *const JSC.CallFrame) callconv(.C) JSC.JSValue {
- var this = callframe.argument(0).asPtr(*Context);
- var buffer = callframe.argument(1).asArrayBuffer(globalThis) orelse {
- globalThis.vm().throwError(globalThis, JSC.toInvalidArguments("Expected TypedArray or ArrayBuffer", .{}, globalThis));
- return JSC.JSValue.jsUndefined();
- };
- return onEnqueue(this, globalThis, buffer.slice(), callframe.argument(1));
- }
-
- pub fn enqueueMany(globalThis: *JSGlobalObject, callframe: *const JSC.CallFrame) callconv(.C) JSC.JSValue {
- var this = callframe.argument(0).asPtr(*Context);
- return onEnqueueMany(this, globalThis, callframe.argument(1));
- }
-
- pub fn close(globalThis: *JSGlobalObject, callframe: *const JSC.CallFrame) callconv(.C) JSC.JSValue {
- var this = callframe.argument(0).asPtr(*Context);
- return onClose(this, globalThis, callframe.argument(1));
- }
-
- pub fn @"error"(globalThis: *JSGlobalObject, callframe: *const JSC.CallFrame) callconv(.C) JSC.JSValue {
- var this = callframe.argument(0).asPtr(*Context);
- return onError(this, globalThis, callframe.argument(1));
- }
-
- pub fn load(globalThis: *JSGlobalObject) callconv(.C) JSC.JSValue {
- if (comptime JSC.is_bindgen) unreachable;
- if (comptime Environment.allow_assert) {
- // this should be cached per globals object
- const OnlyOnce = struct {
- pub threadlocal var last_globals: ?*JSGlobalObject = null;
- };
- if (OnlyOnce.last_globals) |last_globals| {
- std.debug.assert(last_globals != globalThis);
- }
- OnlyOnce.last_globals = globalThis;
- }
- return JSC.JSArray.from(globalThis, &.{
- JSC.NewFunction(globalThis, null, 2, JSReadableStreamReaderNative.enqueue),
- JSC.NewFunction(globalThis, null, 2, JSReadableStreamReaderNative.enqueueMany),
- JSC.NewFunction(globalThis, null, 2, JSReadableStreamReaderNative.close),
- JSC.NewFunction(globalThis, null, 2, JSReadableStreamReaderNative.@"error"),
- });
- }
-
- pub const Export = shim.exportFunctions(.{
- .@"load" = load,
- });
-
- comptime {
- if (!JSC.is_bindgen) {
- @export(load, .{ .name = Export[0].symbol_name });
- _ = JSReadableStreamReaderNative.enqueue;
- _ = JSReadableStreamReaderNative.enqueueMany;
- _ = JSReadableStreamReaderNative.close;
- _ = JSReadableStreamReaderNative.@"error";
- }
- }
- };
- };
- }
};
pub const StreamStart = union(enum) {
@@ -263,9 +209,36 @@ pub const StreamStart = union(enum) {
err: JSC.Node.Syscall.Error,
chunk_size: Blob.SizeType,
ready: void,
+
+ pub fn toJS(this: StreamStart, globalThis: *JSGlobalObject) JSC.JSValue {
+ switch (this) {
+ .empty, .ready => {
+ return JSC.JSValue.jsUndefined();
+ },
+ .chunk_size => |chunk| {
+ return JSC.JSValue.jsNumber(@intCast(Blob.SizeType, chunk));
+ },
+ .err => |err| {
+ globalThis.vm().throwError(globalThis, err.toJSC(globalThis));
+ return JSC.JSValue.jsUndefined();
+ },
+ }
+ }
+
+ pub fn fromJS(globalThis: *JSGlobalObject, value: JSValue) StreamStart {
+ if (value.isEmptyOrUndefinedOrNull() or !value.isObject()) {
+ return .{ .empty = {} };
+ }
+
+ if (value.get(globalThis, "chunkSize")) |chunkSize| {
+ return .{ .chunk_size = @intCast(Blob.SizeType, @truncate(i52, chunkSize.toInt64())) };
+ }
+
+ return .{ .empty = {} };
+ }
};
-pub const StreamResult = union(enum) {
+pub const StreamResult = union(Tag) {
owned: bun.ByteList,
owned_and_done: bun.ByteList,
temporary_and_done: bun.ByteList,
@@ -276,6 +249,117 @@ pub const StreamResult = union(enum) {
err: JSC.Node.Syscall.Error,
done: void,
+ pub const Tag = enum {
+ owned,
+ owned_and_done,
+ temporary_and_done,
+ temporary,
+ into_array,
+ into_array_and_done,
+ pending,
+ err,
+ done,
+ };
+
+ pub fn slice(this: *const StreamResult) []const u8 {
+ return switch (this.*) {
+ .owned => |owned| owned.slice(),
+ .owned_and_done => |owned_and_done| owned_and_done.slice(),
+ .temporary_and_done => |temporary_and_done| temporary_and_done.slice(),
+ .temporary => |temporary| temporary.slice(),
+ else => "",
+ };
+ }
+
+ pub const Writable = union(StreamResult.Tag) {
+ owned: Blob.SizeType,
+ owned_and_done: Blob.SizeType,
+ temporary_and_done: Blob.SizeType,
+ temporary: Blob.SizeType,
+ into_array: Blob.SizeType,
+ into_array_and_done: Blob.SizeType,
+ pending: *Writable.Pending,
+ err: JSC.Node.Syscall.Error,
+ done: void,
+
+ pub const Pending = struct {
+ frame: anyframe,
+ result: Writable,
+ consumed: Blob.SizeType = 0,
+ used: bool = false,
+ };
+
+ pub fn toPromised(globalThis: *JSGlobalObject, promise: *JSPromise, pending: *Writable.Pending) void {
+ var frame = bun.default_allocator.create(@Frame(Writable.toPromisedWrap)) catch unreachable;
+ frame.* = async Writable.toPromisedWrap(globalThis, promise, pending);
+ pending.frame = frame;
+ }
+
+ pub fn isDone(this: *const Writable) bool {
+ return switch (this.*) {
+ .owned_and_done, .temporary_and_done, .into_array_and_done, .done, .err => true,
+ else => false,
+ };
+ }
+ fn toPromisedWrap(globalThis: *JSGlobalObject, promise: *JSPromise, pending: *Writable.Pending) void {
+ suspend {}
+
+ pending.used = true;
+ const result: Writable = pending.result;
+
+ switch (result) {
+ .err => |err| {
+ promise.reject(globalThis, err.toJSC(globalThis));
+ },
+ .done => {
+ promise.resolve(globalThis, JSValue.jsBoolean(false));
+ },
+ else => {
+ promise.resolve(globalThis, result.toJS(globalThis));
+ },
+ }
+ }
+
+ pub fn toJS(this: *const Writable, globalThis: *JSGlobalObject) JSValue {
+ switch (this.*) {
+ .pending => |pending| {
+ var promise = JSC.JSPromise.create(globalThis);
+ Writable.toPromised(globalThis, promise, pending);
+ return promise.asValue(globalThis);
+ },
+
+ .err => |err| {
+ return JSC.JSPromise.rejectedPromise(globalThis, JSValue.c(err.toJS(globalThis.ref()))).asValue(globalThis);
+ },
+
+ .owned => |len| {
+ return JSC.JSValue.jsNumber(len);
+ },
+ .owned_and_done => |len| {
+ return JSC.JSValue.jsNumber(len);
+ },
+ .temporary_and_done => |len| {
+ return JSC.JSValue.jsNumber(len);
+ },
+ .temporary => |len| {
+ return JSC.JSValue.jsNumber(len);
+ },
+ .into_array => |len| {
+ return JSC.JSValue.jsNumber(len);
+ },
+ .into_array_and_done => |len| {
+ return JSC.JSValue.jsNumber(len);
+ },
+
+ // false == controller.close()
+ // undefined == noop, but we probably won't send it
+ .done => {
+ return JSC.JSValue.jsBoolean(true);
+ },
+ }
+ }
+ };
+
pub const IntoArray = struct {
value: JSValue = JSValue.zero,
len: Blob.SizeType = std.math.maxInt(Blob.SizeType),
@@ -329,14 +413,14 @@ pub const StreamResult = union(enum) {
},
.temporary => |temp| {
var array = JSC.JSValue.createUninitializedUint8Array(globalThis, temp.len);
- var slice = array.asArrayBuffer(globalThis).?.slice();
- @memcpy(slice.ptr, temp.ptr, temp.len);
+ var slice_ = array.asArrayBuffer(globalThis).?.slice();
+ @memcpy(slice_.ptr, temp.ptr, temp.len);
return array;
},
.temporary_and_done => |temp| {
var array = JSC.JSValue.createUninitializedUint8Array(globalThis, temp.len);
- var slice = array.asArrayBuffer(globalThis).?.slice();
- @memcpy(slice.ptr, temp.ptr, temp.len);
+ var slice_ = array.asArrayBuffer(globalThis).?.slice();
+ @memcpy(slice_.ptr, temp.ptr, temp.len);
return array;
},
.into_array => |array| {
@@ -364,6 +448,680 @@ pub const StreamResult = union(enum) {
}
};
+pub const Signal = struct {
+ ptr: *anyopaque = @intToPtr(*anyopaque, 0xaaaaaaaa),
+ vtable: VTable = VTable.Dead,
+
+ pub fn isDead(this: Signal) bool {
+ return this.ptr == @intToPtr(*anyopaque, 0xaaaaaaaa);
+ }
+
+ pub fn initWithType(comptime Type: type, handler: *Type) Sink {
+ return .{
+ .ptr = handler,
+ .vtable = VTable.wrap(Type),
+ };
+ }
+
+ pub fn init(handler: anytype) Signal {
+ return initWithType(std.meta.Child(@TypeOf(handler)), handler);
+ }
+
+ pub fn close(this: Signal, err: ?JSC.Node.Syscall.Error) void {
+ if (this.isDead())
+ return;
+ this.vtable.close(this.ptr, err);
+ }
+ pub fn ready(this: Signal, amount: ?Blob.SizeType, offset: ?Blob.SizeType) void {
+ if (this.isDead())
+ return;
+ this.vtable.ready(this.ptr, amount, offset);
+ }
+ pub fn start(this: Signal) void {
+ if (this.isDead())
+ return;
+ this.vtable.start(this.ptr);
+ }
+
+ pub const VTable = struct {
+ pub const OnCloseFn = fn (this: *anyopaque, err: ?JSC.Node.Syscall.Error) void;
+ pub const OnReadyFn = fn (this: *anyopaque, amount: ?Blob.SizeType, offset: ?Blob.SizeType) void;
+ pub const OnStartFn = fn (this: *anyopaque) void;
+ close: OnCloseFn,
+ ready: OnReadyFn,
+ start: OnStartFn,
+
+ const DeadFns = struct {
+ pub fn close(_: *anyopaque, _: ?JSC.Node.Syscall.Error) void {
+ unreachable;
+ }
+ pub fn ready(_: *anyopaque, _: ?Blob.SizeType, _: ?Blob.SizeType) void {
+ unreachable;
+ }
+
+ pub fn start(_: *anyopaque) void {
+ unreachable;
+ }
+ };
+
+ pub const Dead = VTable{ .close = DeadFns.close, .ready = DeadFns.ready, .start = DeadFns.start };
+
+ pub fn wrap(
+ comptime Wrapped: type,
+ ) VTable {
+ const Functions = struct {
+ fn onClose(this: *anyopaque, err: ?JSC.Node.Syscall.Error) void {
+ Wrapped.close(@ptrCast(*Wrapped, @alignCast(std.meta.alignment(Wrapped), this)), err);
+ }
+ fn onReady(this: *anyopaque, amount: ?Blob.SizeType, offset: ?Blob.SizeType) void {
+ Wrapped.ready(@ptrCast(*Wrapped, @alignCast(std.meta.alignment(Wrapped), this)), amount, offset);
+ }
+ fn onStart(this: *anyopaque) void {
+ Wrapped.start(@ptrCast(*Wrapped, @alignCast(std.meta.alignment(Wrapped), this)));
+ }
+ };
+
+ return VTable{
+ .close = Functions.onClose,
+ .ready = Functions.onReady,
+ .start = Functions.onStart,
+ };
+ }
+ };
+};
+
+pub const Sink = struct {
+ ptr: *anyopaque,
+ vtable: VTable,
+ status: Status = Status.closed,
+ used: bool = false,
+
+ pub const Status = enum {
+ ready,
+ closed,
+ };
+
+ pub const Data = union(enum) {
+ utf16: StreamResult,
+ latin1: StreamResult,
+ bytes: StreamResult,
+ };
+
+ pub fn initWithType(comptime Type: type, handler: *Type) Sink {
+ return .{
+ .ptr = handler,
+ .vtable = VTable.wrap(Type),
+ .status = .ready,
+ .used = false,
+ };
+ }
+
+ pub fn init(handler: anytype) Sink {
+ return initWithType(std.meta.Child(@TypeOf(handler)), handler);
+ }
+
+ pub const UTF8Fallback = struct {
+ const stack_size = 1024;
+ pub fn writeLatin1(comptime Ctx: type, ctx: *Ctx, input: StreamResult, comptime writeFn: anytype) StreamResult.Writable {
+ var str = input.slice();
+ if (strings.isAllASCII(str)) {
+ return writeFn(
+ ctx,
+ input,
+ );
+ }
+
+ if (stack_size >= str.len) {
+ var buf: [stack_size]u8 = undefined;
+ @memcpy(&buf, str.ptr, str.len);
+ strings.replaceLatin1WithUTF8(buf[0..str.len]);
+ if (input.isDone()) {
+ const result = writeFn(ctx, .{ .temporary_and_done = bun.ByteList.init(buf[0..str.len]) });
+ return result;
+ } else {
+ const result = writeFn(ctx, .{ .temporary = bun.ByteList.init(buf[0..str.len]) });
+ return result;
+ }
+ }
+
+ {
+ var slice = bun.default_allocator.alloc(u8, str.len) catch return .{ .err = JSC.Node.Syscall.Error.oom };
+ @memcpy(slice.ptr, str.ptr, str.len);
+ strings.replaceLatin1WithUTF8(slice[0..str.len]);
+ if (input.isDone()) {
+ return writeFn(ctx, .{ .owned_and_done = bun.ByteList.init(slice) });
+ } else {
+ return writeFn(ctx, .{ .owned = bun.ByteList.init(slice) });
+ }
+ }
+ }
+
+ pub fn writeUTF16(comptime Ctx: type, ctx: *Ctx, input: StreamResult, comptime writeFn: anytype) StreamResult.Writable {
+ var str: []const u16 = std.mem.bytesAsSlice(u16, input.slice());
+
+ if (stack_size >= str.len * 2) {
+ var buf: [stack_size]u8 = undefined;
+ const copied = strings.copyUTF16IntoUTF8(&buf, []const u16, str);
+ std.debug.assert(copied.written <= stack_size);
+ std.debug.assert(copied.read <= stack_size);
+ if (input.isDone()) {
+ const result = writeFn(ctx, .{ .temporary_and_done = bun.ByteList.init(buf[0..copied.written]) });
+ return result;
+ } else {
+ const result = writeFn(ctx, .{ .temporary = bun.ByteList.init(buf[0..copied.written]) });
+ return result;
+ }
+ }
+
+ {
+ var allocated = strings.toUTF8Alloc(bun.default_allocator, str) catch return .{ .err = JSC.Node.Syscall.Error.oom };
+ if (input.isDone()) {
+ return writeFn(ctx, .{ .owned_and_done = bun.ByteList.init(allocated) });
+ } else {
+ return writeFn(ctx, .{ .owned = bun.ByteList.init(allocated) });
+ }
+ }
+ }
+ };
+
+ pub const VTable = struct {
+ pub const WriteUTF16Fn = fn (this: *anyopaque, data: StreamResult) StreamResult.Writable;
+ pub const WriteUTF8Fn = fn (this: *anyopaque, data: StreamResult) StreamResult.Writable;
+ pub const WriteLatin1Fn = fn (this: *anyopaque, data: StreamResult) StreamResult.Writable;
+ pub const EndFn = fn (this: *anyopaque, err: ?JSC.Node.Syscall.Error) JSC.Node.Maybe(void);
+ pub const ConnectFn = fn (this: *anyopaque, signal: Signal) JSC.Node.Maybe(void);
+
+ connect: ConnectFn,
+ write: WriteUTF8Fn,
+ writeLatin1: WriteLatin1Fn,
+ writeUTF16: WriteUTF16Fn,
+ end: EndFn,
+
+ pub fn wrap(
+ comptime Wrapped: type,
+ ) VTable {
+ const Functions = struct {
+ pub fn onWrite(this: *anyopaque, data: StreamResult) StreamResult.Writable {
+ return Wrapped.write(@ptrCast(*Wrapped, @alignCast(std.meta.alignment(Wrapped), this)), data);
+ }
+ pub fn onConnect(this: *anyopaque, signal: Signal) JSC.Node.Maybe(void) {
+ return Wrapped.connect(@ptrCast(*Wrapped, @alignCast(std.meta.alignment(Wrapped), this)), signal);
+ }
+ pub fn onWriteLatin1(this: *anyopaque, data: StreamResult) StreamResult.Writable {
+ return Wrapped.writeLatin1(@ptrCast(*Wrapped, @alignCast(std.meta.alignment(Wrapped), this)), data);
+ }
+ pub fn onWriteUTF16(this: *anyopaque, data: StreamResult) StreamResult.Writable {
+ return Wrapped.writeUTF16(@ptrCast(*Wrapped, @alignCast(std.meta.alignment(Wrapped), this)), data);
+ }
+ pub fn onEnd(this: *anyopaque, err: ?JSC.Node.Syscall.Error) JSC.Node.Maybe(void) {
+ return Wrapped.end(@ptrCast(*Wrapped, @alignCast(std.meta.alignment(Wrapped), this)), err);
+ }
+ };
+
+ return VTable{
+ .write = Functions.onWrite,
+ .writeLatin1 = Functions.onWriteLatin1,
+ .writeUTF16 = Functions.onWriteUTF16,
+ .end = Functions.onEnd,
+ .connect = Functions.onConnect,
+ };
+ }
+ };
+
+ pub fn end(this: *Sink, err: ?JSC.Node.Syscall.Error) JSC.Node.Maybe(void) {
+ if (this.status == .closed) {
+ return .{ .result = {} };
+ }
+
+ this.status = .closed;
+ return this.vtable.end(this.ptr, err);
+ }
+
+ pub fn writeLatin1(this: *Sink, data: StreamResult) StreamResult.Writable {
+ if (this.status == .closed) {
+ return .{ .done = {} };
+ }
+
+ const res = this.vtable.writeLatin1(this.ptr, data);
+ this.status = if ((res.isDone()) or this.status == .closed)
+ Status.closed
+ else
+ Status.ready;
+ this.used = true;
+ return res;
+ }
+
+ pub fn writeBytes(this: *Sink, data: StreamResult) StreamResult.Writable {
+ if (this.status == .closed) {
+ return .{ .done = {} };
+ }
+
+ const res = this.vtable.write(this.ptr, data);
+ this.status = if ((res.isDone()) or this.status == .closed)
+ Status.closed
+ else
+ Status.ready;
+ this.used = true;
+ return res;
+ }
+
+ pub fn writeUTF16(this: *Sink, data: StreamResult) StreamResult.Writable {
+ if (this.status == .closed) {
+ return .{ .done = {} };
+ }
+
+ const res = this.vtable.writeUTF16(this.ptr, data);
+ this.status = if ((res.isDone()) or this.status == .closed)
+ Status.closed
+ else
+ Status.ready;
+ this.used = true;
+ return res;
+ }
+
+ pub fn write(this: *Sink, data: Data) StreamResult.Writable {
+ switch (data) {
+ .utf16 => |str| {
+ return this.writeUTF16(str);
+ },
+ .latin1 => |str| {
+ return this.writeLatin1(str);
+ },
+ .bytes => |bytes| {
+ return this.writeBytes(bytes);
+ },
+ }
+ }
+};
+
+pub const ArrayBufferSink = struct {
+ bytes: bun.ByteList,
+ allocator: std.mem.Allocator,
+ done: bool = false,
+ signal: Signal = .{},
+ next: ?Sink = null,
+
+ pub fn connect(this: *ArrayBufferSink, signal: Signal) void {
+ std.debug.assert(this.reader == null);
+ this.signal = signal;
+ }
+
+ pub fn start(this: *ArrayBufferSink, config: StreamStart) JSC.Node.Maybe(void) {
+ var list = this.bytes.listManaged(this.allocator);
+ list.clearAndFree();
+
+ switch (config) {
+ .chunk_size => |chunk_size| {
+ if (chunk_size > 0) {
+ list.ensureTotalCapacityPrecise(chunk_size) catch return .{ .err = JSC.Node.Syscall.Error.oom };
+ this.bytes.update(list);
+ }
+ },
+ else => {},
+ }
+
+ this.done = false;
+
+ this.signal.start();
+ return .{ .result = {} };
+ }
+
+ pub fn drain(_: *ArrayBufferSink) JSC.Node.Maybe(void) {
+ return .{ .result = {} };
+ }
+
+ pub fn finalize(this: *ArrayBufferSink) void {
+ if (this.bytes.len > 0) {
+ this.bytes.listManaged(this.allocator).deinit();
+ this.bytes = bun.ByteList.init("");
+ this.done = true;
+ }
+ }
+
+ pub fn init(allocator: std.mem.Allocator, next: ?Sink) !*ArrayBufferSink {
+ var this = try allocator.create(ArrayBufferSink);
+ this.* = ArrayBufferSink{
+ .bytes = bun.ByteList.init(&.{}),
+ .allocator = allocator,
+ .next = next,
+ };
+ return this;
+ }
+
+ pub fn construct(this: *ArrayBufferSink, allocator: std.mem.Allocator) void {
+ this.* = ArrayBufferSink{
+ .bytes = bun.ByteList.init(&.{}),
+ .allocator = allocator,
+ .next = null,
+ };
+ }
+
+ pub fn write(this: *@This(), data: StreamResult) StreamResult.Writable {
+ if (this.next) |*next| {
+ return next.writeBytes(data);
+ }
+
+ const len = this.bytes.write(this.allocator, data.slice()) catch {
+ return .{ .err = JSC.Node.Syscall.Error.oom };
+ };
+ this.signal.ready(null, null);
+ return .{ .owned = len };
+ }
+ pub const writeBytes = write;
+ pub fn writeLatin1(this: *@This(), data: StreamResult) StreamResult.Writable {
+ if (this.next) |*next| {
+ return next.writeLatin1(data);
+ }
+ const len = this.bytes.writeLatin1(this.allocator, data.slice()) catch {
+ return .{ .err = JSC.Node.Syscall.Error.oom };
+ };
+ this.signal.ready(null, null);
+ return .{ .owned = len };
+ }
+ pub fn writeUTF16(this: *@This(), data: StreamResult) StreamResult.Writable {
+ if (this.next) |*next| {
+ return next.writeUTF16(data);
+ }
+ const len = this.bytes.writeUTF16(this.allocator, @ptrCast([*]const u16, @alignCast(@alignOf(u16), data.slice().ptr))[0..std.mem.bytesAsSlice(u16, data.slice()).len]) catch {
+ return .{ .err = JSC.Node.Syscall.Error.oom };
+ };
+ this.signal.ready(null, null);
+ return .{ .owned = len };
+ }
+
+ pub fn end(this: *ArrayBufferSink, err: ?JSC.Node.Syscall.Error) JSC.Node.Maybe(void) {
+ if (this.next) |*next| {
+ return next.end(err);
+ }
+ return .{ .result = {} };
+ }
+
+ pub fn toJS(this: *ArrayBufferSink, err: ?JSC.Node.Syscall.Error) JSC.Node.Maybe(void) {
+ if (this.next) |*next| {
+ return next.end(err);
+ }
+ return .{ .result = {} };
+ }
+
+ pub fn endFromJS(this: *ArrayBufferSink, _: *JSGlobalObject) JSC.Node.Maybe(ArrayBuffer) {
+ if (this.done) {
+ return .{ .result = ArrayBuffer.fromBytes(&[_]u8{}, .ArrayBuffer) };
+ }
+
+ std.debug.assert(this.next == null);
+ var list = this.bytes.listManaged(this.allocator);
+ this.bytes = bun.ByteList.init("");
+ this.done = true;
+ this.signal.close(null);
+ return .{ .result = ArrayBuffer.fromBytes(list.toOwnedSlice(), .ArrayBuffer) };
+ }
+
+ pub fn sink(this: *ArrayBufferSink) Sink {
+ return Sink.init(this);
+ }
+
+ pub const JSArrayBufferSink = NewJSSink(@This(), "ArrayBufferSink");
+};
+
+pub fn NewJSSink(comptime SinkType: type, comptime name_: []const u8) type {
+ return struct {
+ sink: SinkType,
+
+ const ThisSink = @This();
+
+ pub const shim = JSC.Shimmer("", std.mem.span(name_), @This());
+ pub const name = std.fmt.comptimePrint("{s}", .{std.mem.span(name_)});
+
+ pub fn createObject(globalThis: *JSGlobalObject, object: *anyopaque) callconv(.C) JSValue {
+ JSC.markBinding();
+
+ return shim.cppFn("createObject", .{ globalThis, object });
+ }
+
+ pub fn fromJS(globalThis: *JSGlobalObject, value: JSValue) ?*anyopaque {
+ JSC.markBinding();
+
+ return shim.cppFn("fromJS", .{ globalThis, value });
+ }
+
+ pub fn construct(globalThis: *JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSValue {
+ JSC.markBinding();
+ var allocator = globalThis.bunVM().allocator;
+ var this = allocator.create(ThisSink) catch {
+ globalThis.vm().throwError(globalThis, JSC.Node.Syscall.Error.oom.toJSC(
+ globalThis,
+ ));
+ return JSC.JSValue.jsUndefined();
+ };
+ this.sink.construct(allocator);
+ return createObject(globalThis, this);
+ }
+
+ pub fn finalize(ptr: *anyopaque) callconv(.C) void {
+ var this = @ptrCast(*ThisSink, @alignCast(std.meta.alignment(ThisSink), ptr));
+
+ this.sink.finalize();
+ }
+
+ pub fn write(globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue {
+ JSC.markBinding();
+ var this = @ptrCast(*ThisSink, @alignCast(std.meta.alignment(ThisSink), fromJS(globalThis, callframe.this()) orelse {
+ const err = JSC.toTypeError(JSC.Node.ErrorCode.ERR_INVALID_THIS, "Expected Sink", .{}, globalThis);
+ globalThis.vm().throwError(globalThis, err);
+ return JSC.JSValue.jsUndefined();
+ }));
+
+ if (comptime @hasDecl(SinkType, "getPendingError")) {
+ if (this.sink.getPendingError()) |err| {
+ globalThis.vm().throwError(globalThis, err);
+ return JSC.JSValue.jsUndefined();
+ }
+ }
+
+ const args = callframe.arguments();
+ if (args.len == 0 or args[0].isEmptyOrUndefinedOrNull() or args[0].isNumber()) {
+ const err = JSC.toTypeError(
+ if (args.len == 0) JSC.Node.ErrorCode.ERR_MISSING_ARGS else JSC.Node.ErrorCode.ERR_INVALID_ARG_TYPE,
+ "write() expects a string, ArrayBufferView, or ArrayBuffer",
+ .{},
+ globalThis,
+ );
+ globalThis.vm().throwError(globalThis, err);
+ return JSC.JSValue.jsUndefined();
+ }
+
+ const arg = args[0];
+ if (arg.asArrayBuffer(globalThis)) |buffer| {
+ const slice = buffer.slice();
+ if (slice.len == 0) {
+ return JSC.JSValue.jsNumber(0);
+ }
+
+ return this.sink.writeBytes(.{ .temporary = bun.ByteList.init(slice) }).toJS(globalThis);
+ }
+
+ const str = arg.getZigString(globalThis);
+ if (str.len == 0) {
+ return JSC.JSValue.jsNumber(0);
+ }
+
+ if (str.is16Bit()) {
+ return this.sink.writeUTF16(.{ .temporary = bun.ByteList.init(std.mem.sliceAsBytes(str.utf16SliceAligned())) }).toJS(globalThis);
+ }
+
+ return this.sink.writeLatin1(.{ .temporary = bun.ByteList.init(str.slice()) }).toJS(globalThis);
+ }
+
+ pub fn writeString(globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue {
+ JSC.markBinding();
+
+ var this = @ptrCast(*ThisSink, @alignCast(std.meta.alignment(ThisSink), fromJS(globalThis, callframe.this()) orelse {
+ const err = JSC.toTypeError(JSC.Node.ErrorCode.ERR_INVALID_THIS, "Expected Sink", .{}, globalThis);
+ globalThis.vm().throwError(globalThis, err);
+ return JSC.JSValue.jsUndefined();
+ }));
+
+ if (comptime @hasDecl(SinkType, "getPendingError")) {
+ if (this.sink.getPendingError()) |err| {
+ globalThis.vm().throwError(globalThis, err);
+ return JSC.JSValue.jsUndefined();
+ }
+ }
+
+ const args = callframe.arguments();
+ if (args.len == 0 or args[0].isEmptyOrUndefinedOrNull() or args[0].isNumber()) {
+ const err = JSC.toTypeError(
+ if (args.len == 0) JSC.Node.ErrorCode.ERR_MISSING_ARGS else JSC.Node.ErrorCode.ERR_INVALID_ARG_TYPE,
+ "write() expects a string, ArrayBufferView, or ArrayBuffer",
+ .{},
+ globalThis,
+ );
+ globalThis.vm().throwError(globalThis, err);
+ return JSC.JSValue.jsUndefined();
+ }
+
+ const arg = args[0];
+
+ const str = arg.getZigString(globalThis);
+ if (str.len == 0) {
+ return JSC.JSValue.jsNumber(0);
+ }
+
+ if (str.is16Bit()) {
+ return this.sink.writeUTF16(.{ .temporary = str.utf16SliceAligned() }).toJS(globalThis);
+ }
+
+ return this.sink.writeLatin1(.{ .temporary = str.slice() }).toJS(globalThis);
+ }
+
+ pub fn close(globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue {
+ JSC.markBinding();
+ var this = @ptrCast(*ThisSink, @alignCast(std.meta.alignment(ThisSink), fromJS(globalThis, callframe.this()) orelse {
+ const err = JSC.toTypeError(JSC.Node.ErrorCode.ERR_INVALID_THIS, "Expected Sink", .{}, globalThis);
+ globalThis.vm().throwError(globalThis, err);
+ return JSC.JSValue.jsUndefined();
+ }));
+
+ if (comptime @hasDecl(SinkType, "getPendingError")) {
+ if (this.sink.getPendingError()) |err| {
+ globalThis.vm().throwError(globalThis, err);
+ return JSC.JSValue.jsUndefined();
+ }
+ }
+
+ return this.sink.end(null).toJS(globalThis);
+ }
+ pub fn closeWithError(globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue {
+ JSC.markBinding();
+ var this = @ptrCast(*ThisSink, @alignCast(std.meta.alignment(ThisSink), fromJS(globalThis, callframe.this()) orelse {
+ const err = JSC.toTypeError(JSC.Node.ErrorCode.ERR_INVALID_THIS, "Expected Sink", .{}, globalThis);
+ globalThis.vm().throwError(globalThis, err);
+ return JSC.JSValue.jsUndefined();
+ }));
+
+ if (comptime @hasDecl(SinkType, "getPendingError")) {
+ if (this.sink.getPendingError()) |err| {
+ globalThis.vm().throwError(globalThis, err);
+ return JSC.JSValue.jsUndefined();
+ }
+ }
+
+ if (callframe.argumentsCount() == 0) {
+ const err = JSC.toTypeError(JSC.Node.ErrorCode.ERR_MISSING_ARGS, "closeWithError() expects an error", .{}, globalThis);
+ globalThis.vm().throwError(globalThis, err);
+ return JSC.JSValue.jsUndefined();
+ }
+
+ return this.sink.end(null).toJS(globalThis);
+ }
+
+ pub fn drain(globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue {
+ JSC.markBinding();
+
+ var this = @ptrCast(*ThisSink, @alignCast(std.meta.alignment(ThisSink), fromJS(globalThis, callframe.this()) orelse {
+ const err = JSC.toTypeError(JSC.Node.ErrorCode.ERR_INVALID_THIS, "Expected Sink", .{}, globalThis);
+ globalThis.vm().throwError(globalThis, err);
+ return JSC.JSValue.jsUndefined();
+ }));
+
+ if (comptime @hasDecl(SinkType, "getPendingError")) {
+ if (this.sink.getPendingError()) |err| {
+ globalThis.vm().throwError(globalThis, err);
+ return JSC.JSValue.jsUndefined();
+ }
+ }
+
+ return this.sink.drain().toJS(globalThis);
+ }
+
+ pub fn start(globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue {
+ JSC.markBinding();
+
+ var this = @ptrCast(*ThisSink, @alignCast(std.meta.alignment(ThisSink), fromJS(globalThis, callframe.this()) orelse {
+ const err = JSC.toTypeError(JSC.Node.ErrorCode.ERR_INVALID_THIS, "Expected Sink", .{}, globalThis);
+ globalThis.vm().throwError(globalThis, err);
+ return JSC.JSValue.jsUndefined();
+ }));
+
+ if (comptime @hasDecl(SinkType, "getPendingError")) {
+ if (this.sink.getPendingError()) |err| {
+ globalThis.vm().throwError(globalThis, err);
+ return JSC.JSValue.jsUndefined();
+ }
+ }
+
+ return this.sink.start(
+ if (callframe.argumentsCount() > 0) StreamStart.fromJS(globalThis, callframe.argument(0)) else StreamStart{ .empty = {} },
+ ).toJS(globalThis);
+ }
+
+ pub fn end(globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue {
+ JSC.markBinding();
+
+ var this = @ptrCast(*ThisSink, @alignCast(std.meta.alignment(ThisSink), fromJS(globalThis, callframe.this()) orelse {
+ const err = JSC.toTypeError(JSC.Node.ErrorCode.ERR_INVALID_THIS, "Expected Sink", .{}, globalThis);
+ globalThis.vm().throwError(globalThis, err);
+ return JSC.JSValue.jsUndefined();
+ }));
+
+ if (comptime @hasDecl(SinkType, "getPendingError")) {
+ if (this.sink.getPendingError()) |err| {
+ globalThis.vm().throwError(globalThis, err);
+ return JSC.JSValue.jsUndefined();
+ }
+ }
+
+ return this.sink.endFromJS(globalThis).toJS(globalThis);
+ }
+
+ pub const Export = shim.exportFunctions(.{
+ .@"finalize" = finalize,
+ .@"write" = write,
+ .@"close" = close,
+ .@"closeWithError" = closeWithError,
+ .@"drain" = drain,
+ .@"start" = start,
+ .@"end" = end,
+ .@"construct" = construct,
+ });
+
+ comptime {
+ if (!JSC.is_bindgen) {
+ @export(finalize, .{ .name = Export[0].symbol_name });
+ @export(write, .{ .name = Export[1].symbol_name });
+ @export(close, .{ .name = Export[2].symbol_name });
+ @export(closeWithError, .{ .name = Export[3].symbol_name });
+ @export(drain, .{ .name = Export[4].symbol_name });
+ @export(start, .{ .name = Export[5].symbol_name });
+ @export(end, .{ .name = Export[6].symbol_name });
+ @export(construct, .{ .name = Export[7].symbol_name });
+ }
+ }
+
+ pub const Extern = [_][]const u8{ "createObject", "fromJS" };
+ };
+}
+
pub fn WritableStreamSink(
comptime Context: type,
comptime onStart: ?fn (this: Context) void,
@@ -824,23 +1582,6 @@ pub fn RequestBodyStreamer(
else if (is_ssl)
ReadableStream.Tag.HTTPSRequest;
- pub fn setup(
- this: *ByteBlobLoader,
- blob: *const Blob,
- user_chunk_size: Blob.SizeType,
- ) void {
- blob.store.?.ref();
- var blobe = blob.*;
- blobe.resolveSize();
- this.* = ByteBlobLoader{
- .offset = blobe.offset,
- .store = blobe.store.?,
- .chunk_size = if (user_chunk_size > 0) @minimum(user_chunk_size, blobe.size) else @minimum(1024 * 1024 * 2, blobe.size),
- .remain = blobe.size,
- .done = false,
- };
- }
-
pub fn onStart(this: *ByteBlobLoader) StreamStart {
return .{ .chunk_size = this.chunk_size };
}
@@ -910,6 +1651,7 @@ pub const FileBlobLoader = struct {
user_chunk_size: Blob.SizeType = 0,
scheduled_count: u32 = 0,
concurrent: Concurrent = Concurrent{},
+ input_tag: StreamResult.Tag = StreamResult.Tag.done,
const FileReader = @This();
@@ -1195,8 +1937,9 @@ pub const FileBlobLoader = struct {
@minimum(available_to_read, chunk_size);
}
- pub fn onPull(this: *FileBlobLoader, buffer: []u8, view: JSC.JSValue) StreamResult {
+ pub fn onPullInto(this: *FileBlobLoader, buffer: []u8, view: JSC.JSValue) StreamResult {
const chunk_size = this.calculateChunkSize(std.math.maxInt(usize));
+ this.input_tag = .into_array;
switch (chunk_size) {
0 => {
@@ -1362,16 +2105,17 @@ pub const FileBlobLoader = struct {
bun.default_allocator.destroy(this);
}
- pub const Source = ReadableStreamSource(@This(), "FileBlobLoader", onStart, onPull, onCancel, deinit);
+ pub const Source = ReadableStreamSource(@This(), "FileBlobLoader", onStart, onPullInto, onCancel, deinit);
};
-pub const StreamSource = struct {
- ptr: ?*anyopaque = null,
- vtable: VTable,
-
- pub const VTable = struct {
- onStart: fn (this: StreamSource) JSC.WebCore.StreamStart,
- onPull: fn (this: StreamSource) JSC.WebCore.StreamResult,
- onError: fn (this: StreamSource) void,
- };
-};
+// pub const HTTPRequest = RequestBodyStreamer(false);
+// pub const HTTPSRequest = RequestBodyStreamer(true);
+// pub fn ResponseBodyStreamer(comptime is_ssl: bool) type {
+// return struct {
+// const Streamer = @This();
+// pub fn onEnqueue(this: *Streamer, buffer: []u8, ): anytype,
+// pub fn onEnqueueMany(this: *Streamer): anytype,
+// pub fn onClose(this: *Streamer): anytype,
+// pub fn onError(this: *Streamer): anytype,
+// };
+// }
diff --git a/src/main.zig b/src/main.zig
index f70642819..4fd2b8234 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -37,7 +37,8 @@ pub fn PLCrashReportHandler() void {
pub var start_time: i128 = 0;
pub fn main() void {
- CrashReporter.start(null, Report.CrashReportWriter.printFrame, Report.handleCrash);
+ if (comptime Environment.isRelease)
+ CrashReporter.start(null, Report.CrashReportWriter.printFrame, Report.handleCrash);
start_time = std.time.nanoTimestamp();