diff options
author | 2022-08-22 09:51:33 -0700 | |
---|---|---|
committer | 2022-08-22 09:51:33 -0700 | |
commit | 633bef7ef11ff204fba4afd06cde1b532be3d591 (patch) | |
tree | 4f878b9774504327d535cad0f46e493aeea522ba /src/bun.js | |
parent | fcd09abec6d4b0ff4560e847644674afb02ee248 (diff) | |
download | bun-633bef7ef11ff204fba4afd06cde1b532be3d591.tar.gz bun-633bef7ef11ff204fba4afd06cde1b532be3d591.tar.zst bun-633bef7ef11ff204fba4afd06cde1b532be3d591.zip |
[node:http] speed up assigning headers
Diffstat (limited to 'src/bun.js')
-rw-r--r-- | src/bun.js/bindings/webcore/JSFetchHeaders.cpp | 34 | ||||
-rw-r--r-- | src/bun.js/http.exports.js | 96 | ||||
-rw-r--r-- | src/bun.js/webcore/streams.zig | 3 |
3 files changed, 58 insertions, 75 deletions
diff --git a/src/bun.js/bindings/webcore/JSFetchHeaders.cpp b/src/bun.js/bindings/webcore/JSFetchHeaders.cpp index ef9474a1b..78ba9f2fc 100644 --- a/src/bun.js/bindings/webcore/JSFetchHeaders.cpp +++ b/src/bun.js/bindings/webcore/JSFetchHeaders.cpp @@ -73,7 +73,7 @@ static JSC_DECLARE_HOST_FUNCTION(jsFetchHeadersPrototypeFunction_forEach); // Non-standard functions static JSC_DECLARE_HOST_FUNCTION(jsFetchHeadersPrototypeFunction_toJSON); -static JSC_DECLARE_HOST_FUNCTION(jsFetchHeadersPrototypeFunction_size); +static JSC_DECLARE_CUSTOM_GETTER(jsFetchHeadersPrototypeFunction_size); // Attributes @@ -166,6 +166,19 @@ template<> void JSFetchHeadersDOMConstructor::initializeProperties(VM& vm, JSDOM putDirect(vm, vm.propertyNames->prototype, JSFetchHeaders::prototype(vm, globalObject), JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete); } +/** + * Non standard function. + **/ +JSC_DEFINE_CUSTOM_GETTER(jsFetchHeadersGetterCount, (JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName)) +{ + auto& vm = JSC::getVM(globalObject); + JSFetchHeaders* castedThis = jsCast<JSFetchHeaders*>(JSValue::decode(thisValue)); + + auto& impl = castedThis->wrapped(); + auto count = impl.size(); + return JSValue::encode(jsNumber(count)); +} + /* Hash table for prototype */ static const HashTableValue JSFetchHeadersPrototypeTableValues[] = { @@ -180,7 +193,7 @@ static const HashTableValue JSFetchHeadersPrototypeTableValues[] = { { "values"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsFetchHeadersPrototypeFunction_values), (intptr_t)(0) } }, { "forEach"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsFetchHeadersPrototypeFunction_forEach), (intptr_t)(1) } }, { "toJSON"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsFetchHeadersPrototypeFunction_toJSON), (intptr_t)(0) } }, - { "size"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsFetchHeadersPrototypeFunction_size), (intptr_t)(0) } }, + { "count"_s, static_cast<unsigned>(JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(jsFetchHeadersGetterCount), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } }, }; const ClassInfo JSFetchHeadersPrototype::s_info = { "Headers"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSFetchHeadersPrototype) }; @@ -305,23 +318,6 @@ JSC_DEFINE_HOST_FUNCTION(jsFetchHeadersPrototypeFunction_toJSON, (JSGlobalObject return IDLOperation<JSFetchHeaders>::call<jsFetchHeadersPrototypeFunction_toJSONBody>(*lexicalGlobalObject, *callFrame, "toJSON"); } -/** - * Non standard function. - **/ -static inline JSC::EncodedJSValue jsFetchHeadersPrototypeFunction_sizeBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSFetchHeaders>::ClassParameter castedThis) -{ - auto& vm = JSC::getVM(lexicalGlobalObject); - - auto& impl = castedThis->wrapped(); - auto size = impl.size(); - return JSValue::encode(jsNumber(size)); -} - -JSC_DEFINE_HOST_FUNCTION(jsFetchHeadersPrototypeFunction_size, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) -{ - return IDLOperation<JSFetchHeaders>::call<jsFetchHeadersPrototypeFunction_sizeBody>(*lexicalGlobalObject, *callFrame, "size"); -} - JSC_DEFINE_HOST_FUNCTION(jsFetchHeadersPrototypeFunction_append, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { return IDLOperation<JSFetchHeaders>::call<jsFetchHeadersPrototypeFunction_appendBody>(*lexicalGlobalObject, *callFrame, "append"); diff --git a/src/bun.js/http.exports.js b/src/bun.js/http.exports.js index cbaf937b7..01fdab696 100644 --- a/src/bun.js/http.exports.js +++ b/src/bun.js/http.exports.js @@ -91,6 +91,18 @@ export class Server extends EventEmitter { } } +function assignHeaders(object, req) { + var headers = req.headers.toJSON(); + const rawHeaders = new Array(req.headers.count * 2); + var i = 0; + for (const key in headers) { + rawHeaders[i++] = key; + rawHeaders[i++] = headers[key]; + } + object.headers = headers; + object.rawHeaders = rawHeaders; +} + export class IncomingMessage extends Readable { constructor(req) { const method = req.method; @@ -116,62 +128,35 @@ export class IncomingMessage extends Readable { this._socket = undefined; this.url = url.pathname; - this.#inputRequest = req; + assignHeaders(this, req); } - #inputRequest; - #headers; - #rawHeaders; + + headers; + rawHeaders; _consuming = false; _dumped = false; - - #constructHeaders() { - const rawHeaders = []; - const headers = Object.create(null); - var req = this.#inputRequest; - this.#inputRequest = undefined; - for (const [key, value] of req.headers.entries()) { - headers[key] = value; - rawHeaders.push(key, value); - } - this.#headers = headers; - this.#rawHeaders = rawHeaders; - } - - get headers() { - var _headers = this.#headers; - if (_headers) return _headers; - this.#constructHeaders(); - return this.#headers; - } - - set headers(val) { - this.#headers = val; - return true; - } - - get rawHeaders() { - var _rawHeaders = this.#rawHeaders; - if (_rawHeaders) return _rawHeaders; - this.#constructHeaders(); - return this.#rawHeaders; - } - - set rawHeaders(val) { - this.#rawHeaders = val; - return true; - } + _body; + _body_offset; + _socket; + _no_body; + _req; + url; _construct(callback) { // TODO: streaming + if (this._no_body) { + callback(); + return; + } + (async () => { - if (!this._no_body) - try { - this._body = Buffer.from(await this._req.arrayBuffer()); + try { + this._body = Buffer.from(await this._req.arrayBuffer()); - callback(); - } catch (err) { - callback(err); - } + callback(); + } catch (err) { + callback(err); + } })(); } @@ -254,7 +239,7 @@ export class ServerResponse extends Writable { this._reply = reply; this.sendDate = true; this.statusCode = 200; - this.#headers = undefined; + this.#headers = new Headers(); this.headersSent = false; this.statusMessage = undefined; this.#controller = undefined; @@ -290,6 +275,7 @@ export class ServerResponse extends Writable { } _writev(chunks, callback) { + console.trace("typeof chunk " + chunks[0].chunk); if (chunks.length === 1 && !this.headersSent && !this.#firstWrite) { this.#firstWrite = chunks[0].chunk; callback(); @@ -411,27 +397,27 @@ export class ServerResponse extends Writable { flushHeaders() {} removeHeader(name) { - var headers = (this.#headers ||= new Headers()); + var headers = this.#headers; headers.delete(name); } getHeader(name) { - var headers = (this.#headers ||= new Headers()); + var headers = this.#headers; return headers.get(name); } hasHeader(name) { - var headers = (this.#headers ||= new Headers()); + var headers = this.#headers; return headers.has(name); } getHeaderNames() { - var headers = (this.#headers ||= new Headers()); + var headers = this.#headers; return Array.from(headers.keys()); } setHeader(name, value) { - var headers = (this.#headers ||= new Headers()); + var headers = this.#headers; headers.set(name, value); @@ -446,7 +432,7 @@ export class ServerResponse extends Writable { getHeaders() { if (!this.#headers) return {}; - return Object.fromEntries(this.#headers.entries()); + return this.#headers.toJSON(); } } diff --git a/src/bun.js/webcore/streams.zig b/src/bun.js/webcore/streams.zig index 7851f93fe..32e6d9f19 100644 --- a/src/bun.js/webcore/streams.zig +++ b/src/bun.js/webcore/streams.zig @@ -1460,7 +1460,7 @@ pub fn HTTPServerWritable(comptime ssl: bool) type { std.debug.assert(!this.done); const success = if (!this.requested_end) this.res.write(buf) else this.res.tryEnd(buf, this.end_len); this.has_backpressure = !success; - log("send: {d} bytes ({d})", .{ buf.len, this.has_backpressure }); + log("send: {d} bytes (backpressure: {d})", .{ buf.len, this.has_backpressure }); return success; } @@ -1681,6 +1681,7 @@ pub fn HTTPServerWritable(comptime ssl: bool) type { this.res.onWritable(*@This(), onWritable, this); } else { + log("has backpressure", .{}); _ = this.buffer.write(this.allocator, bytes) catch { return .{ .err = Syscall.Error.fromCode(.NOMEM, .write) }; }; |