profile
viewpoint
If you are wondering where the data of this site comes from, please visit https://api.github.com/users/Ethan-Arrowood/events. GitMemory does not store any data, but only uses NGINX to cache data for a period of time. The idea behind GitMemory is simply to give users a better reading experience.
Ethan Arrowood Ethan-Arrowood @Microsoft ethanarrowood.com 👻 Node.js, Fastify, Undici, TypeScript he/him

beaucarnes/freeCodeCamp 1

The https://freeCodeCamp.com open source codebase and curriculum. Learn to code and help nonprofits.

bonham000/FreeCodeCamp 1

The https://FreeCodeCamp.com open source codebase and curriculum. Learn to code and help nonprofits.

Ethan-Arrowood/applying-advanced-typescript-definition-patterns 1

Code repo for my talk "Applying Advanced TypeScript Definition Patterns"

BboyAkers/pino-application-insights 0

fastify plugin: pino application insights

Ethan-Arrowood/100-days-of-code 0

Fork this template for the 100 days journal - to keep yourself accountable

Ethan-Arrowood/15puzzle 0

Old 15 puzzle game I made using jQuery

Ethan-Arrowood/25-days-of-serverless 0

Repository responsible for 25 days of Serverless challenges

Ethan-Arrowood/advanced-react-patterns-v2 0

Created with CodeSandbox

Pull request review commentfastify/fastify

doc: fixing encapsulation

 fastify.register(async function authenticatedContext (childServer) {   childServer.register(require('fastify-bearer-auth'), { keys: ['abc123'] })    childServer.route({-    path: '/one',+    url: '/one',     method: 'GET',-    handler (request, response) {+    handler: (request, response) => {

I very specifically did not use an arrow function here. I used shorthand method notation: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Method_definitions#description

zekth

comment created time in 22 minutes

Pull request review commentfastify/fastify

doc: fixing encapsulation

 fastify.register(async function authenticatedContext (childServer) {   childServer.register(require('fastify-bearer-auth'), { keys: ['abc123'] })    childServer.route({-    path: '/one',+    url: '/one',

path is a valid alias.

zekth

comment created time in 23 minutes

PR opened fastify/fastify

doc: fixing encapsulation
+10 -10

0 comment

1 changed file

pr created time in 25 minutes

startednpm/benchmarks

started time in 14 hours

MemberEvent

PR closed nodejs/undici

use parser.execute
+12 -107

5 comments

2 changed files

ronag

pr closed time in 21 hours

pull request commentnodejs/undici

use parser.execute

Has been rebased into https://github.com/nodejs/undici/pull/575

ronag

comment created time in 21 hours

pull request commentnodejs/undici

Use llhttp wasm build

Rebased against #571. I'll fix tests iteratively next.

dnlup

comment created time in 21 hours

pull request commentnodejs/undici

Use llhttp wasm build

The llhttp repo is cloned using ssh.

dnlup

comment created time in 21 hours

pull request commentnodejs/undici

Use llhttp wasm build

If you have time could you try npm run build on mac? I only have a Linux box.

dnlup

comment created time in 21 hours

Pull request review commentfastify/fastify

Expose the avvio pretty printer for printing the plugin tree

 fastify.ready(() => { }) ``` +<a name="print-plugins"></a>+#### printPlugins++`fastify.printPlugins()`: Prints the representation of the internal plugin tree used by the avvio, useful for debugging require order issues.<br/>+*Remember to call it inside or after a `ready` call.*++```js+fastify.get('/test', () => {})+fastify.get('/test/hello', () => {})+fastify.get('/hello/world', () => {})
fastify.register(async function foo (instance) {
  instance.register(async function bar () {})
  instance.register(async function baz () {})
})
airhorns

comment created time in a day

pull request commentnodejs/undici

Use llhttp wasm build

Things that might be worth moving to native code:

  • https://github.com/nodejs/undici/blob/master/lib/core/client.js#L546-L555
  • https://github.com/nodejs/undici/blob/master/lib/core/client.js#L557
  • https://github.com/nodejs/undici/blob/master/lib/core/client.js#L560
  • https://github.com/nodejs/undici/blob/master/lib/core/client.js#L694-L707
  • https://github.com/nodejs/undici/blob/master/lib/core/client.js#L434-L446
dnlup

comment created time in a day

pull request commentnodejs/undici

Use llhttp wasm build

Codecov Report

Merging #575 (b462c5c) into master (30e75b7) will decrease coverage by 0.41%. The diff coverage is n/a.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #575      +/-   ##
==========================================
- Coverage   99.57%   99.15%   -0.42%     
==========================================
  Files          16       16              
  Lines        1400     1418      +18     
==========================================
+ Hits         1394     1406      +12     
- Misses          6       12       +6     
Impacted Files Coverage Δ
lib/core/request.js 96.93% <0.00%> (-3.07%) :arrow_down:
lib/core/client.js 99.13% <0.00%> (-0.52%) :arrow_down:

Continue to review full report at Codecov.

Legend - Click here to learn more Δ = absolute <relative> (impact), ø = not affected, ? = missing data Powered by Codecov. Last update 30e75b7...b462c5c. Read the comment docs.

dnlup

comment created time in a day

Pull request review commentnodejs/undici

Use llhttp wasm build

+'use strict';++/* global WebAssembly */++const { resolve } = require('path')+const { readFileSync } = require('fs');+const constants = require('./constants');+const WASM_BUILD = resolve(__dirname, './build/llhttp.wasm')+const bin = readFileSync(WASM_BUILD);+const mod = new WebAssembly.Module(bin);++const REQUEST = constants.TYPE.REQUEST;+const RESPONSE = constants.TYPE.RESPONSE;+const kOnMessageBegin = 0;+const kOnHeaders = 1;+const kOnHeadersComplete = 2;+const kOnBody = 3;+const kOnMessageComplete = 4;++const kPtr = Symbol('kPrt');+const kUrl = Symbol('kUrl');+const kStatusMessage = Symbol('kStatusMessage');+const kHeadersFields = Symbol('kHeadersFields');+const kHeadersValues = Symbol('kHeadersValues');+const kBody = Symbol('kBody');+const kReset = Symbol('kReset');+const kCheckErr = Symbol('kCheckErr');++const cstr = (ptr, len) =>+  Buffer.from(inst.exports.memory.buffer, ptr, len).toString();++const wasm_on_message_begin = p => {+  const i = instMap.get(p);+  i[kReset]();+  return i[kOnMessageBegin]();+};++const wasm_on_url = (p, at, length) => {+  instMap.get(p)[kUrl] = cstr(at, length);+  return 0;+};++const wasm_on_status = (p, at, length) => {+  instMap.get(p)[kStatusMessage] = cstr(at, length);+  return 0;+};++const wasm_on_header_field = (p, at, length) => {+  const i= instMap.get(p)+  i[kHeadersFields].push(cstr(at, length));+  return 0;+};++const wasm_on_header_value = (p, at, length) => {+  const i = instMap.get(p);+  i[kHeadersValues].push(cstr(at, length));+  return 0;+};++const wasm_on_headers_complete = p => {+  const i = instMap.get(p);+  const type = inst.exports.llhttp_get_type(p);+  const versionMajor = inst.exports.llhttp_get_http_major(p);+  const versionMinor = inst.exports.llhttp_get_http_minor(p);+  const rawHeaders = [];+  let method;+  let url;+  let statusCode;+  let statusMessage;+  const upgrade = inst.exports.llhttp_get_upgrade(p);+  const shouldKeepAlive = inst.exports.llhttp_should_keep_alive(p);++  for (let c = 0; c < i[kHeadersFields].length; c++) {+    rawHeaders.push(i[kHeadersFields][c], i[kHeadersValues][c])+  }+  i[kOnHeaders](rawHeaders);++  if (type === HTTPParser.REQUEST) {+    method = constants.METHODS[inst.exports.llhttp_get_method(p)];+    url = i[kUrl];+  } else if (type === HTTPParser.RESPONSE) {+    statusCode = inst.exports.llhttp_get_status_code(p);+    statusMessage = i[kStatusMessage];+  }+  return i[kOnHeadersComplete](versionMajor, versionMinor, rawHeaders, method,+url, statusCode, statusMessage, upgrade, shouldKeepAlive);+};++const wasm_on_body = (p, at, length) => {+  const i = instMap.get(p);+  const body = Buffer.from(inst.exports.memory.buffer, at, length);+  return i[kOnBody](body);+};++const wasm_on_message_complete = (p) => {+  return instMap.get(p)[kOnMessageComplete]();+};++const instMap = new Map();++const inst = new WebAssembly.Instance(mod, {+  env: {+    wasm_on_message_begin,+    wasm_on_url,+    wasm_on_status,+    wasm_on_header_field,+    wasm_on_header_value,+    wasm_on_headers_complete,+    wasm_on_body,+    wasm_on_message_complete,+  },+});++inst.exports._initialize(); // wasi reactor++class HTTPParser {+  static REQUEST = REQUEST;+  static RESPONSE = RESPONSE;+  static kOnMessageBegin = kOnMessageBegin;+  static kOnHeaders = kOnHeaders;+  static kOnHeadersComplete = kOnHeadersComplete;+  static kOnBody = kOnBody;+  static kOnMessageComplete = kOnMessageComplete;

It seems supported on 12, not on 10, however. standard complains about it on all versions 😄 .

dnlup

comment created time in a day

Pull request review commentnodejs/undici

Use llhttp wasm build

+'use strict';++/* global WebAssembly */++const { resolve } = require('path')+const { readFileSync } = require('fs');+const constants = require('./constants');+const WASM_BUILD = resolve(__dirname, './build/llhttp.wasm')+const bin = readFileSync(WASM_BUILD);+const mod = new WebAssembly.Module(bin);++const REQUEST = constants.TYPE.REQUEST;+const RESPONSE = constants.TYPE.RESPONSE;+const kOnMessageBegin = 0;+const kOnHeaders = 1;+const kOnHeadersComplete = 2;+const kOnBody = 3;+const kOnMessageComplete = 4;++const kPtr = Symbol('kPrt');+const kUrl = Symbol('kUrl');+const kStatusMessage = Symbol('kStatusMessage');+const kHeadersFields = Symbol('kHeadersFields');+const kHeadersValues = Symbol('kHeadersValues');+const kBody = Symbol('kBody');+const kReset = Symbol('kReset');+const kCheckErr = Symbol('kCheckErr');++const cstr = (ptr, len) =>+  Buffer.from(inst.exports.memory.buffer, ptr, len).toString();++const wasm_on_message_begin = p => {+  const i = instMap.get(p);+  i[kReset]();+  return i[kOnMessageBegin]();+};++const wasm_on_url = (p, at, length) => {+  instMap.get(p)[kUrl] = cstr(at, length);+  return 0;+};++const wasm_on_status = (p, at, length) => {+  instMap.get(p)[kStatusMessage] = cstr(at, length);+  return 0;+};++const wasm_on_header_field = (p, at, length) => {+  const i= instMap.get(p)+  i[kHeadersFields].push(cstr(at, length));+  return 0;+};++const wasm_on_header_value = (p, at, length) => {+  const i = instMap.get(p);+  i[kHeadersValues].push(cstr(at, length));+  return 0;+};++const wasm_on_headers_complete = p => {+  const i = instMap.get(p);+  const type = inst.exports.llhttp_get_type(p);+  const versionMajor = inst.exports.llhttp_get_http_major(p);+  const versionMinor = inst.exports.llhttp_get_http_minor(p);+  const rawHeaders = [];+  let method;+  let url;+  let statusCode;+  let statusMessage;+  const upgrade = inst.exports.llhttp_get_upgrade(p);+  const shouldKeepAlive = inst.exports.llhttp_should_keep_alive(p);++  for (let c = 0; c < i[kHeadersFields].length; c++) {+    rawHeaders.push(i[kHeadersFields][c], i[kHeadersValues][c])+  }+  i[kOnHeaders](rawHeaders);++  if (type === HTTPParser.REQUEST) {+    method = constants.METHODS[inst.exports.llhttp_get_method(p)];+    url = i[kUrl];+  } else if (type === HTTPParser.RESPONSE) {+    statusCode = inst.exports.llhttp_get_status_code(p);+    statusMessage = i[kStatusMessage];+  }+  return i[kOnHeadersComplete](versionMajor, versionMinor, rawHeaders, method,+url, statusCode, statusMessage, upgrade, shouldKeepAlive);+};++const wasm_on_body = (p, at, length) => {+  const i = instMap.get(p);+  const body = Buffer.from(inst.exports.memory.buffer, at, length);+  return i[kOnBody](body);+};++const wasm_on_message_complete = (p) => {+  return instMap.get(p)[kOnMessageComplete]();+};++const instMap = new Map();++const inst = new WebAssembly.Instance(mod, {+  env: {+    wasm_on_message_begin,+    wasm_on_url,+    wasm_on_status,+    wasm_on_header_field,+    wasm_on_header_value,+    wasm_on_headers_complete,+    wasm_on_body,+    wasm_on_message_complete,+  },+});++inst.exports._initialize(); // wasi reactor++class HTTPParser {+  static REQUEST = REQUEST;+  static RESPONSE = RESPONSE;+  static kOnMessageBegin = kOnMessageBegin;+  static kOnHeaders = kOnHeaders;+  static kOnHeadersComplete = kOnHeadersComplete;+  static kOnBody = kOnBody;+  static kOnMessageComplete = kOnMessageComplete;

I'll check it out 👍🏻

dnlup

comment created time in a day

Pull request review commentnodejs/undici

Use llhttp wasm build

+'use strict';++/* global WebAssembly */++const { resolve } = require('path')+const { readFileSync } = require('fs');+const constants = require('./constants');+const WASM_BUILD = resolve(__dirname, './build/llhttp.wasm')+const bin = readFileSync(WASM_BUILD);+const mod = new WebAssembly.Module(bin);++const REQUEST = constants.TYPE.REQUEST;+const RESPONSE = constants.TYPE.RESPONSE;+const kOnMessageBegin = 0;+const kOnHeaders = 1;+const kOnHeadersComplete = 2;+const kOnBody = 3;+const kOnMessageComplete = 4;++const kPtr = Symbol('kPrt');+const kUrl = Symbol('kUrl');+const kStatusMessage = Symbol('kStatusMessage');+const kHeadersFields = Symbol('kHeadersFields');+const kHeadersValues = Symbol('kHeadersValues');+const kBody = Symbol('kBody');+const kReset = Symbol('kReset');+const kCheckErr = Symbol('kCheckErr');++const cstr = (ptr, len) =>+  Buffer.from(inst.exports.memory.buffer, ptr, len).toString();++const wasm_on_message_begin = p => {+  const i = instMap.get(p);+  i[kReset]();+  return i[kOnMessageBegin]();+};++const wasm_on_url = (p, at, length) => {+  instMap.get(p)[kUrl] = cstr(at, length);+  return 0;+};++const wasm_on_status = (p, at, length) => {+  instMap.get(p)[kStatusMessage] = cstr(at, length);+  return 0;+};++const wasm_on_header_field = (p, at, length) => {+  const i= instMap.get(p)+  i[kHeadersFields].push(cstr(at, length));+  return 0;+};++const wasm_on_header_value = (p, at, length) => {+  const i = instMap.get(p);+  i[kHeadersValues].push(cstr(at, length));+  return 0;+};++const wasm_on_headers_complete = p => {+  const i = instMap.get(p);+  const type = inst.exports.llhttp_get_type(p);+  const versionMajor = inst.exports.llhttp_get_http_major(p);+  const versionMinor = inst.exports.llhttp_get_http_minor(p);+  const rawHeaders = [];+  let method;+  let url;+  let statusCode;+  let statusMessage;+  const upgrade = inst.exports.llhttp_get_upgrade(p);+  const shouldKeepAlive = inst.exports.llhttp_should_keep_alive(p);++  for (let c = 0; c < i[kHeadersFields].length; c++) {+    rawHeaders.push(i[kHeadersFields][c], i[kHeadersValues][c])+  }+  i[kOnHeaders](rawHeaders);++  if (type === HTTPParser.REQUEST) {+    method = constants.METHODS[inst.exports.llhttp_get_method(p)];+    url = i[kUrl];+  } else if (type === HTTPParser.RESPONSE) {+    statusCode = inst.exports.llhttp_get_status_code(p);+    statusMessage = i[kStatusMessage];+  }+  return i[kOnHeadersComplete](versionMajor, versionMinor, rawHeaders, method,+url, statusCode, statusMessage, upgrade, shouldKeepAlive);+};++const wasm_on_body = (p, at, length) => {+  const i = instMap.get(p);+  const body = Buffer.from(inst.exports.memory.buffer, at, length);+  return i[kOnBody](body);+};++const wasm_on_message_complete = (p) => {+  return instMap.get(p)[kOnMessageComplete]();+};++const instMap = new Map();++const inst = new WebAssembly.Instance(mod, {+  env: {+    wasm_on_message_begin,+    wasm_on_url,+    wasm_on_status,+    wasm_on_header_field,+    wasm_on_header_value,+    wasm_on_headers_complete,+    wasm_on_body,+    wasm_on_message_complete,+  },+});++inst.exports._initialize(); // wasi reactor++class HTTPParser {+  static REQUEST = REQUEST;+  static RESPONSE = RESPONSE;+  static kOnMessageBegin = kOnMessageBegin;+  static kOnHeaders = kOnHeaders;+  static kOnHeadersComplete = kOnHeadersComplete;+  static kOnBody = kOnBody;+  static kOnMessageComplete = kOnMessageComplete;

I don't think static works?

dnlup

comment created time in a day

Pull request review commentnodejs/undici

Use llhttp wasm build

+'use strict';++/* global WebAssembly */++const { resolve } = require('path')+const { readFileSync } = require('fs');+const constants = require('./constants');+const WASM_BUILD = resolve(__dirname, './build/llhttp.wasm')+const bin = readFileSync(WASM_BUILD);+const mod = new WebAssembly.Module(bin);++const REQUEST = constants.TYPE.REQUEST;+const RESPONSE = constants.TYPE.RESPONSE;+const kOnMessageBegin = 0;+const kOnHeaders = 1;+const kOnHeadersComplete = 2;+const kOnBody = 3;+const kOnMessageComplete = 4;++const kPtr = Symbol('kPrt');+const kUrl = Symbol('kUrl');+const kStatusMessage = Symbol('kStatusMessage');+const kHeadersFields = Symbol('kHeadersFields');+const kHeadersValues = Symbol('kHeadersValues');+const kBody = Symbol('kBody');+const kReset = Symbol('kReset');+const kCheckErr = Symbol('kCheckErr');++const cstr = (ptr, len) =>+  Buffer.from(inst.exports.memory.buffer, ptr, len).toString();++const wasm_on_message_begin = p => {+  const i = instMap.get(p);+  i[kReset]();+  return i[kOnMessageBegin]();+};++const wasm_on_url = (p, at, length) => {+  instMap.get(p)[kUrl] = cstr(at, length);+  return 0;+};++const wasm_on_status = (p, at, length) => {+  instMap.get(p)[kStatusMessage] = cstr(at, length);+  return 0;+};++const wasm_on_header_field = (p, at, length) => {+  const i= instMap.get(p)+  i[kHeadersFields].push(cstr(at, length));+  return 0;+};++const wasm_on_header_value = (p, at, length) => {+  const i = instMap.get(p);+  i[kHeadersValues].push(cstr(at, length));+  return 0;+};++const wasm_on_headers_complete = p => {+  const i = instMap.get(p);+  const type = inst.exports.llhttp_get_type(p);+  const versionMajor = inst.exports.llhttp_get_http_major(p);+  const versionMinor = inst.exports.llhttp_get_http_minor(p);+  const rawHeaders = [];+  let method;+  let url;+  let statusCode;+  let statusMessage;+  const upgrade = inst.exports.llhttp_get_upgrade(p);+  const shouldKeepAlive = inst.exports.llhttp_should_keep_alive(p);++  for (let c = 0; c < i[kHeadersFields].length; c++) {+    rawHeaders.push(i[kHeadersFields][c], i[kHeadersValues][c])+  }+  i[kOnHeaders](rawHeaders);++  if (type === HTTPParser.REQUEST) {+    method = constants.METHODS[inst.exports.llhttp_get_method(p)];+    url = i[kUrl];+  } else if (type === HTTPParser.RESPONSE) {+    statusCode = inst.exports.llhttp_get_status_code(p);+    statusMessage = i[kStatusMessage];+  }+  return i[kOnHeadersComplete](versionMajor, versionMinor, rawHeaders, method,+url, statusCode, statusMessage, upgrade, shouldKeepAlive);+};++const wasm_on_body = (p, at, length) => {+  const i = instMap.get(p);+  const body = Buffer.from(inst.exports.memory.buffer, at, length);+  return i[kOnBody](body);+};++const wasm_on_message_complete = (p) => {+  return instMap.get(p)[kOnMessageComplete]();+};++const instMap = new Map();++const inst = new WebAssembly.Instance(mod, {+  env: {+    wasm_on_message_begin,+    wasm_on_url,+    wasm_on_status,+    wasm_on_header_field,+    wasm_on_header_value,+    wasm_on_headers_complete,+    wasm_on_body,+    wasm_on_message_complete,+  },+});++inst.exports._initialize(); // wasi reactor++class HTTPParser {+  static REQUEST = REQUEST;+  static RESPONSE = RESPONSE;+  static kOnMessageBegin = kOnMessageBegin;+  static kOnHeaders = kOnHeaders;+  static kOnHeadersComplete = kOnHeadersComplete;+  static kOnBody = kOnBody;+  static kOnMessageComplete = kOnMessageComplete;

Ok 👍🏻 . Are you referring to something already in these changes that is not supported?

dnlup

comment created time in a day

Pull request review commentnodejs/undici

Use llhttp wasm build

+'use strict';++/* global WebAssembly */++const { resolve } = require('path')+const { readFileSync } = require('fs');+const constants = require('./constants');+const WASM_BUILD = resolve(__dirname, './build/llhttp.wasm')+const bin = readFileSync(WASM_BUILD);+const mod = new WebAssembly.Module(bin);++const REQUEST = constants.TYPE.REQUEST;+const RESPONSE = constants.TYPE.RESPONSE;+const kOnMessageBegin = 0;+const kOnHeaders = 1;+const kOnHeadersComplete = 2;+const kOnBody = 3;+const kOnMessageComplete = 4;++const kPtr = Symbol('kPrt');+const kUrl = Symbol('kUrl');+const kStatusMessage = Symbol('kStatusMessage');+const kHeadersFields = Symbol('kHeadersFields');+const kHeadersValues = Symbol('kHeadersValues');+const kBody = Symbol('kBody');+const kReset = Symbol('kReset');+const kCheckErr = Symbol('kCheckErr');++const cstr = (ptr, len) =>+  Buffer.from(inst.exports.memory.buffer, ptr, len).toString();++const wasm_on_message_begin = p => {+  const i = instMap.get(p);+  i[kReset]();+  return i[kOnMessageBegin]();+};++const wasm_on_url = (p, at, length) => {+  instMap.get(p)[kUrl] = cstr(at, length);+  return 0;+};++const wasm_on_status = (p, at, length) => {+  instMap.get(p)[kStatusMessage] = cstr(at, length);+  return 0;+};++const wasm_on_header_field = (p, at, length) => {+  const i= instMap.get(p)+  i[kHeadersFields].push(cstr(at, length));+  return 0;+};++const wasm_on_header_value = (p, at, length) => {+  const i = instMap.get(p);+  i[kHeadersValues].push(cstr(at, length));+  return 0;+};++const wasm_on_headers_complete = p => {+  const i = instMap.get(p);+  const type = inst.exports.llhttp_get_type(p);+  const versionMajor = inst.exports.llhttp_get_http_major(p);+  const versionMinor = inst.exports.llhttp_get_http_minor(p);+  const rawHeaders = [];+  let method;+  let url;+  let statusCode;+  let statusMessage;+  const upgrade = inst.exports.llhttp_get_upgrade(p);+  const shouldKeepAlive = inst.exports.llhttp_should_keep_alive(p);++  for (let c = 0; c < i[kHeadersFields].length; c++) {+    rawHeaders.push(i[kHeadersFields][c], i[kHeadersValues][c])+  }+  i[kOnHeaders](rawHeaders);++  if (type === HTTPParser.REQUEST) {+    method = constants.METHODS[inst.exports.llhttp_get_method(p)];+    url = i[kUrl];+  } else if (type === HTTPParser.RESPONSE) {+    statusCode = inst.exports.llhttp_get_status_code(p);+    statusMessage = i[kStatusMessage];+  }+  return i[kOnHeadersComplete](versionMajor, versionMinor, rawHeaders, method,+url, statusCode, statusMessage, upgrade, shouldKeepAlive);+};++const wasm_on_body = (p, at, length) => {+  const i = instMap.get(p);+  const body = Buffer.from(inst.exports.memory.buffer, at, length);+  return i[kOnBody](body);+};++const wasm_on_message_complete = (p) => {+  return instMap.get(p)[kOnMessageComplete]();+};++const instMap = new Map();++const inst = new WebAssembly.Instance(mod, {+  env: {+    wasm_on_message_begin,+    wasm_on_url,+    wasm_on_status,+    wasm_on_header_field,+    wasm_on_header_value,+    wasm_on_headers_complete,+    wasm_on_body,+    wasm_on_message_complete,+  },+});++inst.exports._initialize(); // wasi reactor++class HTTPParser {+  static REQUEST = REQUEST;+  static RESPONSE = RESPONSE;+  static kOnMessageBegin = kOnMessageBegin;+  static kOnHeaders = kOnHeaders;+  static kOnHeadersComplete = kOnHeadersComplete;+  static kOnBody = kOnBody;+  static kOnMessageComplete = kOnMessageComplete;

Remember we need this to work on Node 12 as well.

dnlup

comment created time in a day

Pull request review commentnodejs/undici

Use llhttp wasm build

+'use strict';++/* global WebAssembly */++const { resolve } = require('path')+const { readFileSync } = require('fs');+const constants = require('./constants');+const WASM_BUILD = resolve(__dirname, './build/llhttp.wasm')+const bin = readFileSync(WASM_BUILD);+const mod = new WebAssembly.Module(bin);++const REQUEST = constants.TYPE.REQUEST;+const RESPONSE = constants.TYPE.RESPONSE;+const kOnMessageBegin = 0;+const kOnHeaders = 1;+const kOnHeadersComplete = 2;+const kOnBody = 3;+const kOnMessageComplete = 4;++const kPtr = Symbol('kPrt');+const kUrl = Symbol('kUrl');+const kStatusMessage = Symbol('kStatusMessage');+const kHeadersFields = Symbol('kHeadersFields');+const kHeadersValues = Symbol('kHeadersValues');+const kBody = Symbol('kBody');+const kReset = Symbol('kReset');+const kCheckErr = Symbol('kCheckErr');++const cstr = (ptr, len) =>+  Buffer.from(inst.exports.memory.buffer, ptr, len).toString();++const wasm_on_message_begin = p => {+  const i = instMap.get(p);+  i[kReset]();+  return i[kOnMessageBegin]();+};++const wasm_on_url = (p, at, length) => {+  instMap.get(p)[kUrl] = cstr(at, length);+  return 0;+};++const wasm_on_status = (p, at, length) => {+  instMap.get(p)[kStatusMessage] = cstr(at, length);+  return 0;+};++const wasm_on_header_field = (p, at, length) => {+  const i= instMap.get(p)+  i[kHeadersFields].push(cstr(at, length));+  return 0;+};++const wasm_on_header_value = (p, at, length) => {+  const i = instMap.get(p);+  i[kHeadersValues].push(cstr(at, length));+  return 0;+};++const wasm_on_headers_complete = p => {+  const i = instMap.get(p);+  const type = inst.exports.llhttp_get_type(p);+  const versionMajor = inst.exports.llhttp_get_http_major(p);+  const versionMinor = inst.exports.llhttp_get_http_minor(p);+  const rawHeaders = [];+  let method;+  let url;+  let statusCode;+  let statusMessage;+  const upgrade = inst.exports.llhttp_get_upgrade(p);+  const shouldKeepAlive = inst.exports.llhttp_should_keep_alive(p);++  for (let c = 0; c < i[kHeadersFields].length; c++) {+    rawHeaders.push(i[kHeadersFields][c], i[kHeadersValues][c])+  }+  i[kOnHeaders](rawHeaders);++  if (type === HTTPParser.REQUEST) {+    method = constants.METHODS[inst.exports.llhttp_get_method(p)];+    url = i[kUrl];+  } else if (type === HTTPParser.RESPONSE) {+    statusCode = inst.exports.llhttp_get_status_code(p);+    statusMessage = i[kStatusMessage];+  }+  return i[kOnHeadersComplete](versionMajor, versionMinor, rawHeaders, method,+url, statusCode, statusMessage, upgrade, shouldKeepAlive);+};++const wasm_on_body = (p, at, length) => {+  const i = instMap.get(p);+  const body = Buffer.from(inst.exports.memory.buffer, at, length);+  return i[kOnBody](body);+};++const wasm_on_message_complete = (p) => {+  return instMap.get(p)[kOnMessageComplete]();+};++const instMap = new Map();++const inst = new WebAssembly.Instance(mod, {+  env: {+    wasm_on_message_begin,+    wasm_on_url,+    wasm_on_status,+    wasm_on_header_field,+    wasm_on_header_value,+    wasm_on_headers_complete,+    wasm_on_body,+    wasm_on_message_complete,+  },+});++inst.exports._initialize(); // wasi reactor++class HTTPParser {+  static REQUEST = REQUEST;+  static RESPONSE = RESPONSE;+  static kOnMessageBegin = kOnMessageBegin;+  static kOnHeaders = kOnHeaders;+  static kOnHeadersComplete = kOnHeadersComplete;+  static kOnBody = kOnBody;+  static kOnMessageComplete = kOnMessageComplete;++  constructor(type) {+    this[kPtr] = inst.exports.llhttp_alloc(constants.TYPE[type]);+    instMap.set(this[kPtr], this);++    this[kUrl] = '';+    this[kStatusMessage] = null;+    this[kHeadersFields] = [];+    this[kHeadersValues] = [];+    this[kBody] = null;+  }+ +  [kReset]() {+    this[kUrl] = '';+    this[kStatusMessage] = null;+    this[kHeadersFields] = [];+    this[kHeadersValues] = [];+    this[kBody] = null;+  }++  [kOnMessageBegin]() {+    return 0;+  }++  [kOnHeaders](rawHeaders) {}++  [kOnHeadersComplete](versionMajor, versionMinor, rawHeaders, method,+    url, statusCode, statusMessage, upgrade, shouldKeepAlive) {+    return 0;+  }++  [kOnBody](body) {+    this[kBody] = body;+    return 0;+  }++  [kOnMessageComplete]() {+    return 0;+  }++  destroy() {+    instMap.delete(this[kPtr]);+    inst.exports.llhttp_free(this[kPtr]);+  }++  execute(data) {+    // TODO(devsnek): could probably use static alloc and chunk but i'm lazy+    const ptr = inst.exports.malloc(data.byteLength);+    const u8 = new Uint8Array(inst.exports.memory.buffer);+    u8.set(data, ptr);+    const ret = inst.exports.llhttp_execute(this[kPtr], ptr, data.length);+    inst.exports.free(ptr);+    this[kCheckErr](ret);+    return ret;+  }

Yup, I agree.

dnlup

comment created time in a day

issue commentfastify/fastify

Support RegExp for the addContentTypeParser API

Yes, I will send a PR as soon as I am done.

matthyk

comment created time in a day

issue commentfastify/fastify

Support RegExp for the addContentTypeParser API

Would you like to send a Pull Request to address this issue? Remember to add unit tests.

matthyk

comment created time in a day

pull request commentnodejs/undici

Use llhttp wasm build

I agree!

dnlup

comment created time in a day

issue openedfastify/fastify

Support RegExp for the addContentTypeParser API

<!-- Before you submit an issue we recommend you visit Fastify Help and ask any questions you have or mention any problems you've had getting started with Fastify.

Please read this entire template before posting any issue. If you ignore these instructions and post an issue here that does not follow the instructions, your issue might be closed, locked, and assigned the missing discussion label. -->

🚀 Feature Proposal

Support RegExp for the addContentTypeParser API.

Motivation

Currently, you need to add a new content type parser for each new content type you use. So you have to add 2 parsers if you use the content types application/vnd.user+json and application/vnd.book+json, even though both are valid JSON objects and could use the same content type parser. This could be possible if the addContentTypeParser API supported RegExp in addition to string values.

Example

fastify.addContentTypeParser(/s*\+json$/, { parseAs: "string" }, function (req, body, done) {
  try {
    var json = JSON.parse(body)
    done(null, json)
  } catch (err) {
    err.statusCode = 400
    done(err, undefined)
  }
})

created time in a day

pull request commentnodejs/undici

Use llhttp wasm build

We also probably want to reduce the number of calls across the js <-> wasm border so we might want to modify the c level code as well.

dnlup

comment created time in a day

Pull request review commentnodejs/undici

Use llhttp wasm build

+'use strict';++/* global WebAssembly */++const { resolve } = require('path')+const { readFileSync } = require('fs');+const constants = require('./constants');+const WASM_BUILD = resolve(__dirname, './build/llhttp.wasm')+const bin = readFileSync(WASM_BUILD);+const mod = new WebAssembly.Module(bin);++const REQUEST = constants.TYPE.REQUEST;+const RESPONSE = constants.TYPE.RESPONSE;+const kOnMessageBegin = 0;+const kOnHeaders = 1;+const kOnHeadersComplete = 2;+const kOnBody = 3;+const kOnMessageComplete = 4;++const kPtr = Symbol('kPrt');+const kUrl = Symbol('kUrl');+const kStatusMessage = Symbol('kStatusMessage');+const kHeadersFields = Symbol('kHeadersFields');+const kHeadersValues = Symbol('kHeadersValues');+const kBody = Symbol('kBody');+const kReset = Symbol('kReset');+const kCheckErr = Symbol('kCheckErr');++const cstr = (ptr, len) =>+  Buffer.from(inst.exports.memory.buffer, ptr, len).toString();++const wasm_on_message_begin = p => {+  const i = instMap.get(p);+  i[kReset]();+  return i[kOnMessageBegin]();+};++const wasm_on_url = (p, at, length) => {+  instMap.get(p)[kUrl] = cstr(at, length);+  return 0;+};++const wasm_on_status = (p, at, length) => {+  instMap.get(p)[kStatusMessage] = cstr(at, length);+  return 0;+};++const wasm_on_header_field = (p, at, length) => {+  const i= instMap.get(p)+  i[kHeadersFields].push(cstr(at, length));+  return 0;+};++const wasm_on_header_value = (p, at, length) => {+  const i = instMap.get(p);+  i[kHeadersValues].push(cstr(at, length));+  return 0;+};++const wasm_on_headers_complete = p => {+  const i = instMap.get(p);+  const type = inst.exports.llhttp_get_type(p);+  const versionMajor = inst.exports.llhttp_get_http_major(p);+  const versionMinor = inst.exports.llhttp_get_http_minor(p);+  const rawHeaders = [];+  let method;+  let url;+  let statusCode;+  let statusMessage;+  const upgrade = inst.exports.llhttp_get_upgrade(p);+  const shouldKeepAlive = inst.exports.llhttp_should_keep_alive(p);++  for (let c = 0; c < i[kHeadersFields].length; c++) {+    rawHeaders.push(i[kHeadersFields][c], i[kHeadersValues][c])+  }+  i[kOnHeaders](rawHeaders);++  if (type === HTTPParser.REQUEST) {+    method = constants.METHODS[inst.exports.llhttp_get_method(p)];+    url = i[kUrl];+  } else if (type === HTTPParser.RESPONSE) {+    statusCode = inst.exports.llhttp_get_status_code(p);+    statusMessage = i[kStatusMessage];+  }+  return i[kOnHeadersComplete](versionMajor, versionMinor, rawHeaders, method,+url, statusCode, statusMessage, upgrade, shouldKeepAlive);+};++const wasm_on_body = (p, at, length) => {+  const i = instMap.get(p);+  const body = Buffer.from(inst.exports.memory.buffer, at, length);+  return i[kOnBody](body);+};++const wasm_on_message_complete = (p) => {+  return instMap.get(p)[kOnMessageComplete]();+};++const instMap = new Map();++const inst = new WebAssembly.Instance(mod, {+  env: {+    wasm_on_message_begin,+    wasm_on_url,+    wasm_on_status,+    wasm_on_header_field,+    wasm_on_header_value,+    wasm_on_headers_complete,+    wasm_on_body,+    wasm_on_message_complete,+  },+});++inst.exports._initialize(); // wasi reactor++class HTTPParser {+  static REQUEST = REQUEST;+  static RESPONSE = RESPONSE;+  static kOnMessageBegin = kOnMessageBegin;+  static kOnHeaders = kOnHeaders;+  static kOnHeadersComplete = kOnHeadersComplete;+  static kOnBody = kOnBody;+  static kOnMessageComplete = kOnMessageComplete;++  constructor(type) {+    this[kPtr] = inst.exports.llhttp_alloc(constants.TYPE[type]);+    instMap.set(this[kPtr], this);++    this[kUrl] = '';+    this[kStatusMessage] = null;+    this[kHeadersFields] = [];+    this[kHeadersValues] = [];+    this[kBody] = null;+  }+ +  [kReset]() {+    this[kUrl] = '';+    this[kStatusMessage] = null;+    this[kHeadersFields] = [];+    this[kHeadersValues] = [];+    this[kBody] = null;+  }++  [kOnMessageBegin]() {+    return 0;+  }++  [kOnHeaders](rawHeaders) {}++  [kOnHeadersComplete](versionMajor, versionMinor, rawHeaders, method,+    url, statusCode, statusMessage, upgrade, shouldKeepAlive) {+    return 0;+  }++  [kOnBody](body) {+    this[kBody] = body;+    return 0;+  }++  [kOnMessageComplete]() {+    return 0;+  }++  destroy() {+    instMap.delete(this[kPtr]);+    inst.exports.llhttp_free(this[kPtr]);+  }++  execute(data) {+    // TODO(devsnek): could probably use static alloc and chunk but i'm lazy+    const ptr = inst.exports.malloc(data.byteLength);+    const u8 = new Uint8Array(inst.exports.memory.buffer);+    u8.set(data, ptr);+    const ret = inst.exports.llhttp_execute(this[kPtr], ptr, data.length);+    inst.exports.free(ptr);+    this[kCheckErr](ret);+    return ret;+  }

FYI, this is where we are likely losing throughput.

dnlup

comment created time in a day

pull request commentnodejs/undici

Use llhttp wasm build

The goal for this activity should be to verify that we suffer minimal slowdowns from using wasm instead of native.

dnlup

comment created time in a day

push eventnodejs/undici

Robert Nagy

commit sha d39f3c9df889a1ff7cbdd9327d0feb8ffa49cee0

fixup

view details

push time in a day

push eventnodejs/undici

Robert Nagy

commit sha ddd133da2585d17762127fc89d902f3d594d2a6f

fixup

view details

push time in a day

push eventnodejs/undici

Robert Nagy

commit sha b35f5cab47abe7fd2ca04ace05d94284148796d8

fixup

view details

push time in a day