fulmine.js 5.4.0 → 5.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/package.json +1 -1
- package/src/request.js +18 -21
package/README.md
CHANGED
|
@@ -96,7 +96,7 @@ to run it yourself.
|
|
|
96
96
|
Numbers produced by a project about itself deserve suspicion, so Fulmine also stands in public arenas, run by their own rigs under their own rules:
|
|
97
97
|
|
|
98
98
|
- **[HttpArena](https://www.http-arena.com/#sort=rps:-1&q=Js)** (the link lands filtered on the JavaScript entries): first among the JavaScript entries, across fifteen subscribed profiles. The saved runs measure 24.3 million WebSocket echoes per second pipelined and 3.77 million one-at-a-time (past Bun's own dedicated WebSocket entry), 7.3 million pipelined HTTP requests per second, 1.12 million on the json profile with 1.04 million of that surviving TLS, 457 thousand on compressed json, and 359 thousand on the Postgres CRUD profile, within ten percent of the leading Rust and C# entries there.
|
|
99
|
-
- **[web-frameworks](https://
|
|
99
|
+
- **[web-frameworks](https://web-frameworks-benchmark.netlify.app/result?l=javascript)**: entry merged, numbers arrive with their next published round.
|
|
100
100
|
|
|
101
101
|
More to come as their maintainers take the entries in.
|
|
102
102
|
|
package/package.json
CHANGED
package/src/request.js
CHANGED
|
@@ -266,9 +266,6 @@ Object.defineProperty(LazyReadableBase.prototype, "readable", {
|
|
|
266
266
|
});
|
|
267
267
|
|
|
268
268
|
module.exports = class Request extends LazyReadable {
|
|
269
|
-
/** @type {Record<string, any>|null} */
|
|
270
|
-
#cachedQuery = null;
|
|
271
|
-
|
|
272
269
|
/** @type {Record<string, any>|null} */
|
|
273
270
|
#cachedHeaders = null;
|
|
274
271
|
|
|
@@ -892,7 +889,6 @@ module.exports = class Request extends LazyReadable {
|
|
|
892
889
|
this._rawQuery = queryIndex === -1 ? "" : newUrl.slice(queryIndex + 1);
|
|
893
890
|
// a rewrite to "/a?" keeps its "?", as one arriving that way does
|
|
894
891
|
this.urlQuery = queryIndex === -1 ? "" : "?" + this._rawQuery;
|
|
895
|
-
this.#cachedQuery = null;
|
|
896
892
|
this._originalPath = prefix + newPath;
|
|
897
893
|
this.path = newPath;
|
|
898
894
|
this.endsWithSlash = newPath.charCodeAt(newPath.length - 1) === 0x2f;
|
|
@@ -913,27 +909,28 @@ module.exports = class Request extends LazyReadable {
|
|
|
913
909
|
* the parse cached and handed out as itself, the sanitised value leaked into req.query here and
|
|
914
910
|
* a handler written against express read a trimmed value where express gives it the raw one.
|
|
915
911
|
*
|
|
916
|
-
*
|
|
917
|
-
*
|
|
918
|
-
*
|
|
912
|
+
* And that is why there is no cache: the fresh object comes from parsing the raw string again,
|
|
913
|
+
* not from copying a kept parse. As first shipped this was parse-once-copy-per-read, and the
|
|
914
|
+
* copy was the expensive half: Object.assign between null-prototype objects, which live in
|
|
915
|
+
* V8's dictionary mode, measured 638ns for a two-parameter query where parsing the same string
|
|
916
|
+
* measures 119ns, and on a benchmark whose every request carries such a query it cost +1.5us
|
|
917
|
+
* of CPU per request, which a public arena saw as -8% on its query-carrying rows. A handler
|
|
918
|
+
* that reads req.query once per request now pays exactly what it paid when the parse was
|
|
919
|
+
* cached, one parse, and a handler that reads it N times pays N parses, which is express's
|
|
920
|
+
* own cost shape.
|
|
919
921
|
*
|
|
920
922
|
* @returns {Record<string, any>}
|
|
921
923
|
*/
|
|
922
924
|
get query() {
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
: Object.assign(Object.create(null), qp(this._rawQuery))
|
|
933
|
-
: Object.create(null);
|
|
934
|
-
this.#cachedQuery = parsed;
|
|
935
|
-
}
|
|
936
|
-
return Object.assign(Object.create(null), parsed);
|
|
925
|
+
const qp = this.app.get("query parser fn");
|
|
926
|
+
// the vendored default already answers on a bare null prototype, so it goes out as is;
|
|
927
|
+
// any other parser is copied onto one, which is what kept fast-querystring's result from
|
|
928
|
+
// inspecting as "Empty <[Object: null prototype] {}>" where Express shows the bare form
|
|
929
|
+
return qp
|
|
930
|
+
? qp === parseQuery
|
|
931
|
+
? parseQuery(this._rawQuery)
|
|
932
|
+
: Object.assign(Object.create(null), qp(this._rawQuery))
|
|
933
|
+
: Object.create(null);
|
|
937
934
|
}
|
|
938
935
|
|
|
939
936
|
/**
|