diff --git a/benchmarks/benchmark.js b/benchmarks/benchmark.js index 9aed5d5607b..ce4a1e71895 100644 --- a/benchmarks/benchmark.js +++ b/benchmarks/benchmark.js @@ -19,7 +19,8 @@ const { promisify } = require('node:util') const request = promisify(require('request')) const iterations = (parseInt(process.env.SAMPLES, 10) || 10) + 1 -const errorThreshold = parseInt(process.env.ERROR_THRESHOLD, 10) || 3 +const parsedErrorThreshold = parseInt(process.env.ERROR_THRESHOLD, 10) +const errorThreshold = Number.isNaN(parsedErrorThreshold) ? 3 : parsedErrorThreshold const connections = parseInt(process.env.CONNECTIONS, 10) || 50 const pipelining = parseInt(process.env.PIPELINING, 10) || 10 const headersTimeout = parseInt(process.env.HEADERS_TIMEOUT, 10) || 0 @@ -121,10 +122,7 @@ async function cleanup () { requestAgent.destroy() superagentAgent.destroy() - await Promise.allSettled([ - dispatcher.destroy(), - globalDispatcher.destroy() - ]) + await Promise.allSettled([dispatcher.destroy(), globalDispatcher.destroy()]) } class SimpleRequest { @@ -246,21 +244,36 @@ if (process.env.PORT) { // fetch does not support the socket experiments['undici - fetch'] = () => { return makeParallelRequests(resolve => { - fetch(dest.url).then(res => { - res.body.pipeTo(new WritableStream({ write () { }, close () { resolve() } })) - }).catch(console.log) + fetch(dest.url) + .then(res => { + res.body.pipeTo( + new WritableStream({ + write () {}, + close () { + resolve() + } + }) + ) + }) + .catch(console.log) }) } experiments['node-fetch'] = () => { return makeParallelRequests(resolve => { - nodeFetch(dest.url, { agent: fetchAgent }).then(res => { - res.body.pipe(new Writable({ - write (chunk, encoding, callback) { - callback() - } - })).on('finish', resolve) - }).catch(console.log) + nodeFetch(dest.url, { agent: fetchAgent }) + .then(res => { + res.body + .pipe( + new Writable({ + write (chunk, encoding, callback) { + callback() + } + }) + ) + .on('finish', resolve) + }) + .catch(console.log) }) } @@ -272,13 +285,20 @@ if (process.env.PORT) { } experiments.axios = () => { return makeParallelRequests(resolve => { - axios.request(axiosOptions).then(res => { - res.data.pipe(new Writable({ - write (chunk, encoding, callback) { - callback() - } - })).on('finish', resolve) - }).catch(console.log) + axios + .request(axiosOptions) + .then(res => { + res.data + .pipe( + new Writable({ + write (chunk, encoding, callback) { + callback() + } + }) + ) + .on('finish', resolve) + }) + .catch(console.log) }) } @@ -293,11 +313,15 @@ if (process.env.PORT) { } experiments.got = () => { return makeParallelRequests(resolve => { - got(gotOptions).pipe(new Writable({ - write (chunk, encoding, callback) { - callback() - } - })).on('finish', resolve) + got(gotOptions) + .pipe( + new Writable({ + write (chunk, encoding, callback) { + callback() + } + }) + ) + .on('finish', resolve) }) } @@ -310,20 +334,27 @@ if (process.env.PORT) { } experiments.request = () => { return makeParallelRequests(resolve => { - request(requestOptions).then(() => { - // already body consumed - resolve() - }).catch(console.log) + request(requestOptions) + .then(() => { + // already body consumed + resolve() + }) + .catch(console.log) }) } experiments.superagent = () => { return makeParallelRequests(resolve => { - superagent.get(dest.url).pipe(new Writable({ - write (chunk, encoding, callback) { - callback() - } - })).on('finish', resolve) + superagent + .get(dest.url) + .pipe( + new Writable({ + write (chunk, encoding, callback) { + callback() + } + }) + ) + .on('finish', resolve) }) } } @@ -336,7 +367,7 @@ async function main () { got = _got.default const _superagent = await import('superagent') // https://github.com/ladjs/superagent/issues/1540#issue-561464561 - superagent = _superagent.agent().use((req) => req.agent(superagentAgent)) + superagent = _superagent.agent().use(req => req.agent(superagentAgent)) // cronometro runs each benchmark in a worker, so attach cleanup to every // test before the worker exits. diff --git a/build/milo.js b/build/milo.js new file mode 100644 index 00000000000..cdd08de36bd --- /dev/null +++ b/build/milo.js @@ -0,0 +1,29 @@ +'use strict' + +const { execFileSync } = require('node:child_process') +const { cpSync, existsSync, mkdirSync, rmSync } = require('node:fs') +const { join, resolve } = require('node:path') + +const ROOT = resolve(__dirname, '../') +const OUT = join(ROOT, 'lib/milo') +const PACKAGE = '@perseveranza-pets/milo-cjs@latest' +const PACKAGE_DIR = process.env.MILO_PACKAGE_DIR + +rmSync(OUT, { recursive: true, force: true }) +mkdirSync(OUT, { recursive: true }) + +if (PACKAGE_DIR) { + cpSync(PACKAGE_DIR, OUT, { recursive: true }) +} else { + const packResult = JSON.parse(execFileSync('npm', ['pack', PACKAGE, '--json'], { cwd: OUT, encoding: 'utf8' })) + + const tarball = join(OUT, packResult[0].filename) + if (!existsSync(tarball)) { + throw new Error('Failed to download milo package') + } + + execFileSync('tar', ['-xzf', tarball, '-C', OUT, '--strip-components=1'], { + stdio: 'inherit' + }) + rmSync(tarball) +} diff --git a/lib/dispatcher/client-h1.js b/lib/dispatcher/client-h1.js index 6d89dd09b5e..4e1b86b79ac 100644 --- a/lib/dispatcher/client-h1.js +++ b/lib/dispatcher/client-h1.js @@ -54,6 +54,7 @@ const { } = require('../core/symbols.js') const constants = require('../llhttp/constants.js') +const { H1Parser, getMiloEnabled } = require('./parser-h1.js') const EMPTY_BUF = Buffer.alloc(0) const FastBuffer = Buffer[Symbol.species] const removeAllListeners = util.removeAllListeners @@ -80,8 +81,7 @@ function lazyllhttp () { if (useWasmSIMD) { try { mod = new WebAssembly.Module(require('../llhttp/llhttp_simd-wasm.js')) - } catch { - } + } catch {} } if (!mod) { @@ -118,7 +118,7 @@ function lazyllhttp () { * @param {number} p * @returns {number} */ - wasm_on_message_begin: (p) => { + wasm_on_message_begin: p => { assert(currentParser.ptr === p) return currentParser.onMessageBegin() }, @@ -170,11 +170,10 @@ function lazyllhttp () { * @param {number} p * @returns {number} */ - wasm_on_message_complete: (p) => { + wasm_on_message_complete: p => { assert(currentParser.ptr === p) return currentParser.onMessageComplete() } - } }) } @@ -207,10 +206,10 @@ const TIMEOUT_KEEP_ALIVE = 8 | USE_NATIVE_TIMER class Parser { /** - * @param {import('./client.js')} client - * @param {import('net').Socket} socket - * @param {*} llhttp - */ + * @param {import('./client.js')} client + * @param {import('net').Socket} socket + * @param {*} llhttp + */ constructor (client, socket, { exports }) { this.llhttp = exports this.ptr = this.llhttp.llhttp_alloc(constants.TYPE.RESPONSE) @@ -245,10 +244,7 @@ class Parser { // If the existing timer and the new timer are of different timer type // (fast or native) or have different delay, we need to clear the existing // timer and set a new one. - if ( - delay !== this.timeoutValue || - (type & USE_FAST_TIMER) ^ (this.timeoutType & USE_FAST_TIMER) - ) { + if (delay !== this.timeoutValue || (type & USE_FAST_TIMER) ^ (this.timeoutType & USE_FAST_TIMER)) { // If a timeout is already set, clear it with clearTimeout of the fast // timer implementation, as it can clear fast and native timers. if (this.timeout) { @@ -433,9 +429,7 @@ class Parser { if (ptr) { const len = new Uint8Array(llhttp.memory.buffer, ptr).indexOf(0) message = - 'Response does not match the HTTP/1.1 protocol (' + - Buffer.from(llhttp.memory.buffer, ptr, len).toString() + - ')' + 'Response does not match the HTTP/1.1 protocol (' + Buffer.from(llhttp.memory.buffer, ptr, len).toString() + ')' } return new HTTPParserError(message, constants.ERROR[ret], data) @@ -536,7 +530,7 @@ class Parser { this.contentLength = 0 } for (let i = 0; i < buf.length; i++) { - this.contentLength = (this.contentLength * 10) + (buf[i] - 0x30) + this.contentLength = this.contentLength * 10 + (buf[i] - 0x30) } } @@ -643,16 +637,13 @@ class Parser { assert(this.timeoutType === TIMEOUT_HEADERS) this.statusCode = statusCode - this.shouldKeepAlive = ( + this.shouldKeepAlive = shouldKeepAlive || // Override llhttp value which does not allow keepAlive for HEAD. (request.method === 'HEAD' && !socket[kReset] && this.connectionKeepAlive) - ) if (this.statusCode >= 200) { - const bodyTimeout = request.bodyTimeout != null - ? request.bodyTimeout - : client[kBodyTimeout] + const bodyTimeout = request.bodyTimeout != null ? request.bodyTimeout : client[kBodyTimeout] this.setTimeout(bodyTimeout, TIMEOUT_BODY) } else if (this.timeout) { if (this.timeout.refresh) { @@ -680,10 +671,7 @@ class Parser { const keepAliveTimeout = this.keepAlive ? util.parseKeepAliveTimeout(this.keepAlive) : null if (keepAliveTimeout != null) { - const timeout = Math.min( - keepAliveTimeout - client[kKeepAliveTimeoutThreshold], - client[kKeepAliveMaxTimeout] - ) + const timeout = Math.min(keepAliveTimeout - client[kKeepAliveTimeoutThreshold], client[kKeepAliveMaxTimeout]) if (timeout <= 0) { socket[kReset] = true } else { @@ -878,7 +866,7 @@ function connectH1 (client, socket) { socket[kIdleSocketValidation] = 0 socket[kIdleSocketValidationTimeout] = null socket[kSocketUsed] = false - socket[kParser] = new Parser(client, socket, llhttpInstance) + socket[kParser] = getMiloEnabled() ? new H1Parser(client, socket) : new Parser(client, socket, llhttpInstance) util.addListener(socket, 'error', onHttpSocketError) util.addListener(socket, 'readable', onHttpSocketReadable) @@ -939,8 +927,11 @@ function connectH1 (client, socket) { return true } - if (client[kRunning] > 0 && util.bodyLength(request.body) !== 0 && - (util.isStream(request.body) || util.isAsyncIterable(request.body) || util.isFormDataLike(request.body))) { + if ( + client[kRunning] > 0 && + util.bodyLength(request.body) !== 0 && + (util.isStream(request.body) || util.isAsyncIterable(request.body) || util.isFormDataLike(request.body)) + ) { // Request with stream or iterator body can error while other requests // are inflight and indirectly error those as well. // Ensure this doesn't happen by waiting for inflight @@ -1120,9 +1111,7 @@ function resumeH1 (client) { } else if (client[kRunning] > 0 && socket[kParser].statusCode < 200) { if (socket[kParser].timeoutType !== TIMEOUT_HEADERS) { const request = client[kQueue][client[kRunningIdx]] - const headersTimeout = request.headersTimeout != null - ? request.headersTimeout - : client[kHeadersTimeout] + const headersTimeout = request.headersTimeout != null ? request.headersTimeout : client[kHeadersTimeout] socket[kParser].setTimeout(headersTimeout, TIMEOUT_HEADERS) } } @@ -1153,14 +1142,13 @@ function writeH1 (client, request) { // servers and corrupt connection state. Do not // re-use the connection for further requests. - const expectsPayload = ( + const expectsPayload = method === 'PUT' || method === 'POST' || method === 'PATCH' || method === 'QUERY' || method === 'PROPFIND' || method === 'PROPPATCH' - ) if (util.isFormDataLike(body)) { if (!extractBody) { @@ -1201,7 +1189,12 @@ function writeH1 (client, request) { // https://github.com/nodejs/undici/issues/2046 // A user agent may send a Content-Length header with 0 value, this should be allowed. - if (shouldSendContentLength(method) && contentLength > 0 && request.contentLength !== null && request.contentLength !== contentLength) { + if ( + shouldSendContentLength(method) && + contentLength > 0 && + request.contentLength !== null && + request.contentLength !== contentLength + ) { if (client[kStrictContentLength]) { util.errorRequest(client, request, new RequestContentLengthMismatchError()) return false @@ -1217,7 +1210,7 @@ function writeH1 (client, request) { * @param {Error} [err] * @returns {void} */ - const abort = (err) => { + const abort = err => { if (request.aborted || request.completed) { return } @@ -1404,14 +1397,9 @@ function writeStream (abort, body, client, request, socket, contentLength, heade assert(socket.destroyed || (socket[kWriting] && client[kRunning] <= 1)) - socket - .off('drain', onDrain) - .off('error', onFinished) + socket.off('drain', onDrain).off('error', onFinished) - body - .removeListener('data', onData) - .removeListener('end', onFinished) - .removeListener('close', onClose) + body.removeListener('data', onData).removeListener('end', onFinished).removeListener('close', onClose) if (!err) { try { @@ -1430,19 +1418,13 @@ function writeStream (abort, body, client, request, socket, contentLength, heade } } - body - .on('data', onData) - .on('end', onFinished) - .on('error', onFinished) - .on('close', onClose) + body.on('data', onData).on('end', onFinished).on('error', onFinished).on('close', onClose) if (body.resume) { body.resume() } - socket - .on('drain', onDrain) - .on('error', onFinished) + socket.on('drain', onDrain).on('error', onFinished) if (body.errorEmitted ?? body.errored) { setImmediate(onFinished, body.errored) @@ -1563,19 +1545,18 @@ async function writeIterable (abort, body, client, request, socket, contentLengt } } - const waitForDrain = () => new Promise((resolve, reject) => { - assert(callback === null) + const waitForDrain = () => + new Promise((resolve, reject) => { + assert(callback === null) - if (socket[kError]) { - reject(socket[kError]) - } else { - callback = resolve - } - }) + if (socket[kError]) { + reject(socket[kError]) + } else { + callback = resolve + } + }) - socket - .on('close', onDrain) - .on('drain', onDrain) + socket.on('close', onDrain).on('drain', onDrain) const writer = new AsyncWriter({ abort, socket, request, contentLength, client, expectsPayload, header }) try { @@ -1594,9 +1575,7 @@ async function writeIterable (abort, body, client, request, socket, contentLengt } catch (err) { writer.destroy(err) } finally { - socket - .off('close', onDrain) - .off('drain', onDrain) + socket.off('close', onDrain).off('drain', onDrain) } } diff --git a/lib/dispatcher/parser-h1.js b/lib/dispatcher/parser-h1.js new file mode 100644 index 00000000000..6a3fe5fbccf --- /dev/null +++ b/lib/dispatcher/parser-h1.js @@ -0,0 +1,935 @@ +'use strict' + +const assert = require('node:assert') +const util = require('../core/util.js') +const timers = require('../util/timers.js') +const { + HeadersTimeoutError, + HeadersOverflowError, + SocketError, + InformationalError, + BodyTimeoutError, + HTTPParserError, + ResponseContentLengthMismatchError, + ResponseExceededMaxSizeError +} = require('../core/errors.js') +const { + kUrl, + kReset, + kClient, + kParser, + kBlocking, + kRunning, + kWriting, + kQueue, + kKeepAliveDefaultTimeout, + kRunningIdx, + kError, + kPipelining, + kSocket, + kKeepAliveTimeoutValue, + kKeepAliveMaxTimeout, + kKeepAliveTimeoutThreshold, + kBodyTimeout, + kMaxResponseSize, + kResume, + kHTTPContext, + kMaxHeadersSize +} = require('../core/symbols.js') + +const FastBuffer = Buffer[Symbol.species] +const removeAllListeners = util.removeAllListeners + +const kPausedByHandler = Symbol('kPausedByHandler') + +const BUFFER_PAGE_SIZE = 4096 +const INITIAL_BUFFER_SIZE = 128 * 1024 +const EMPTY_BUF = Buffer.alloc(0) +const BODY_KIND_CONTENT_LENGTH = 0 +const EVENT_RANGE_SIZE = 9 +const EVENT_HEADERS_SIZE = 19 + +let miloPackage + +// We disable wasm SIMD on ppc64 as it seems to be broken on Power 9 architectures. +let useWasmSIMD = process.arch !== 'ppc64' +// The Env Variable UNDICI_NO_WASM_SIMD allows explicitly overriding the default behavior. +if (process.env.UNDICI_NO_WASM_SIMD === '1') { + useWasmSIMD = false +} else if (process.env.UNDICI_NO_WASM_SIMD === '0') { + useWasmSIMD = true +} + +if (useWasmSIMD) { + try { + miloPackage = require('../milo/src/simd/index.js') + } catch {} +} + +miloPackage = miloPackage || require('../milo/src/no-simd/index.js') +const { setup } = miloPackage + +const USE_NATIVE_TIMER = 0 +const USE_FAST_TIMER = 1 +const TIMEOUT_HEADERS = 2 | USE_FAST_TIMER +const TIMEOUT_BODY = 4 | USE_FAST_TIMER +const TIMEOUT_KEEP_ALIVE = 8 | USE_NATIVE_TIMER + +let miloEnabled = process.env.UNDICI_USE_MILO === '1' || process.env.UNDICI_USE_MILO === 'true' +let miloInstance = null +let currentBuffer = null +let currentBufferSize = 0 +let currentBufferPtr = null +let currentBufferRef = null + +function onParserTimeout (parserWeakRef) { + const parser = parserWeakRef.deref ? parserWeakRef.deref() : parserWeakRef + if (!parser) { + return + } + + const { socket, timeoutType, client, paused } = parser + + if (timeoutType === TIMEOUT_HEADERS) { + if (!socket[kWriting] || socket.writableNeedDrain || client[kRunning] > 1) { + assert(!paused, 'cannot be paused while waiting for headers') + util.destroy(socket, new HeadersTimeoutError()) + } + } else if (timeoutType === TIMEOUT_BODY) { + if (!paused) { + util.destroy(socket, new BodyTimeoutError()) + } + } else if (timeoutType === TIMEOUT_KEEP_ALIVE) { + assert(client[kRunning] === 0 && client[kKeepAliveTimeoutValue]) + util.destroy(socket, new InformationalError('socket idle timeout')) + } +} + +function getMilo () { + if (miloInstance) { + return miloInstance + } + + miloInstance = setup() + return miloInstance +} + +class H1Parser { + constructor (client, socket) { + this.milo = getMilo() + + this.client = client + this.socket = socket + this.parser = this.milo.create() + this.events = new FastBuffer(this.milo.memory.buffer, this.parser + this.milo.ParserFields.EVENTS, 4).readUInt32LE( + 0 + ) + + this.milo.setShouldAutodetect(this.parser, false) + this.milo.setIsRequest(this.parser, false) + this.milo.setShouldManageUnconsumed(this.parser, false) + this.milo.setShouldSuspendAfterHeaders(this.parser, true) + this.milo.setMaxHeaderLength(this.parser, client[kMaxHeadersSize]) + this.milo.setActiveEvents( + this.parser, + this.milo.EVENT_ACTIVE_ON_ERROR | + this.milo.EVENT_ACTIVE_ON_MESSAGE_COMPLETE | + this.milo.EVENT_ACTIVE_ON_REASON | + this.milo.EVENT_ACTIVE_ON_HEADER_NAME | + this.milo.EVENT_ACTIVE_ON_HEADER_VALUE | + this.milo.EVENT_ACTIVE_ON_HEADERS | + this.milo.EVENT_ACTIVE_ON_DATA | + this.milo.EVENT_ACTIVE_ON_TRAILER_NAME | + this.milo.EVENT_ACTIVE_ON_TRAILER_VALUE + ) + + this.timeout = null + this.timeoutWeakRef = new WeakRef(this) + this.timeoutValue = null + this.timeoutType = null + this.statusCode = 0 + this.statusText = '' + this.upgrade = false + this.responseStarted = false + this.pausedByParser = false + this.pauseStateIsStart = false + this.headers = [] + this.trailers = [] + this.headersSize = 0 + this.trailersSize = 0 + this.headersMaxSize = client[kMaxHeadersSize] + this.shouldKeepAlive = false + this.paused = false + this.errored = false + this.waitingForMoreData = 0 + this.resume = this.resume.bind(this) + this.bytesRead = 0 + this.keepAlive = '' + this.connectionKeepAlive = false + this.contentLength = -1 + this.maxResponseSize = client[kMaxResponseSize] + this.directBodyRemaining = 0 + this.directBodyCompletePending = false + this.headersSuspended = false + this.skipBody = false + + this[kPausedByHandler] = false + + if (INITIAL_BUFFER_SIZE > currentBufferSize || currentBuffer.buffer !== this.milo.memory.buffer) { + this.ensureBuffers(INITIAL_BUFFER_SIZE) + } else { + this.updateBuffers() + } + } + + setTimeout (delay, type) { + if (delay !== this.timeoutValue || (type & USE_FAST_TIMER) ^ (this.timeoutType & USE_FAST_TIMER)) { + if (this.timeout) { + timers.clearTimeout(this.timeout) + this.timeout = null + } + + if (delay) { + if (type & USE_FAST_TIMER) { + this.timeout = timers.setFastTimeout(onParserTimeout, delay, this.timeoutWeakRef) + } else { + this.timeout = setTimeout(onParserTimeout, delay, this.timeoutWeakRef) + this.timeout?.unref() + } + } + + this.timeoutValue = delay + } else if (this.timeout?.refresh) { + this.timeout.refresh() + } + + this.timeoutType = type + } + + ensureBuffers (size) { + const { milo } = this + + if (currentBufferPtr != null) { + milo.dealloc(currentBufferPtr) + } + + // Reallocate buffers + currentBufferSize = Math.ceil(size / BUFFER_PAGE_SIZE) * BUFFER_PAGE_SIZE + currentBufferPtr = milo.alloc(currentBufferSize) + currentBuffer = new FastBuffer(milo.memory.buffer, currentBufferPtr, currentBufferSize) + + this.updateBuffers() + } + + updateBuffers () { + this.parserFields = new FastBuffer(this.milo.memory.buffer, this.parser) + this.parserEvents = new FastBuffer(this.milo.memory.buffer, this.events, 64 * 1024) + } + + resume () { + if (this.socket.destroyed || !this.paused) { + return + } + + this.milo.resume(this.parser) + + assert(this.timeoutType === TIMEOUT_BODY) + if (this.timeout?.refresh) { + this.timeout.refresh() + } + + this.paused = false + if (this.directBodyCompletePending) { + try { + this.completeDirectBody() + } catch (err) { + util.destroy(this.socket, err) + return + } + + if (this.paused) { + return + } + } + + this.readMore() + } + + readMore () { + if (this.paused || !this.parser) { + return + } + + while (!this.paused && this.parser) { + if (this.waitingForMoreData && this.socket.readableLength <= this.waitingForMoreData) { + break + } + + this.waitingForMoreData = 0 + + const chunk = this.socket.read() + if (chunk === null) { + break + } + + if (this.execute(chunk) === false) { + break + } + } + } + + execute (data) { + const available = data.length + assert(!this.paused) + + const { socket, milo } = this + + try { + if (this.directBodyRemaining > 0) { + return this.consumeDirectBody(data) + } + + if (currentBuffer.buffer !== milo.memory.buffer) { + currentBuffer = new FastBuffer(milo.memory.buffer, currentBufferPtr, currentBufferSize) + this.updateBuffers() + } else if (this.parserEvents.buffer !== milo.memory.buffer) { + this.updateBuffers() + } + + let offset = 0 + let parseLen = available + const headersEnd = this.statusCode === 0 ? data.indexOf('\r\n\r\n') : -1 + + if (headersEnd !== -1) { + parseLen = headersEnd + 4 + } + + for (;;) { + if (parseLen > currentBufferSize) { + this.ensureBuffers(parseLen) + } + + const parseData = data.subarray(offset, offset + parseLen) + currentBuffer.set(parseData) + currentBufferRef = parseData + + const consumed = milo.parse(this.parser, currentBufferPtr, parseLen) + this.drainEvents() + + const consumedTotal = offset + consumed + + if (this.errored || (consumed === 0 && this.parserFields[milo.ParserFields.ERROR_CODE] !== milo.ERROR_NONE)) { + throw this.createError(data.subarray(consumedTotal)) + } else if (this.upgrade) { + this.onUpgrade(data.subarray(consumedTotal)) + return false + } else if (this.directBodyCompletePending) { + this.completeDirectBody() + + if (this.paused) { + return false + } + } else if (this.pausedByParser) { + this.pausedByParser = false + this.headersSuspended = false + if (this[kPausedByHandler] && this.pauseStateIsStart) { + this.pauseStateIsStart = false + milo.resume(this.parser) + this[kPausedByHandler] = false + return false + } + + this.pauseStateIsStart = false + this.paused = true + socket.unshift(data.subarray(consumedTotal)) + return false + } + + if (this.directBodyRemaining > 0) { + return this.consumeDirectBody(data.subarray(consumedTotal)) + } + + if (consumed < parseLen) { + const remaining = data.subarray(consumedTotal) + socket.unshift(remaining) + this.waitingForMoreData = consumed === 0 ? remaining.length : 0 + return false + } + + offset = consumedTotal + + if (offset >= available) { + if (this.headersSuspended) { + this.headersSuspended = false + parseLen = 0 + continue + } + + return true + } + + this.headersSuspended = false + parseLen = available - offset + } + } catch (err) { + util.destroy(socket, err) + return false + } finally { + currentBufferRef = null + } + } + + consumeDirectBody (data) { + const { socket, client, maxResponseSize } = this + const available = data.length + const len = Math.min(available, this.directBodyRemaining) + + if (this.timeout?.refresh) { + this.timeout.refresh() + } + + if (len > 0) { + const request = client[kQueue][client[kRunningIdx]] + assert(request) + assert(this.timeoutType === TIMEOUT_BODY) + assert(this.statusCode >= 200) + + if (maxResponseSize > -1 && this.bytesRead + len > maxResponseSize) { + throw new ResponseExceededMaxSizeError() + } + + this.bytesRead += len + this.directBodyRemaining -= len + + if (request.onResponseData(data.subarray(0, len)) === false) { + this.directBodyCompletePending = this.directBodyRemaining === 0 + this.pauseParser() + this[kPausedByHandler] = true + this.pausedByParser = false + this.paused = true + + if (len < available) { + socket.unshift(data.subarray(len)) + } + + return false + } + } + + if (this.directBodyRemaining === 0) { + this.completeDirectBody() + + const remaining = data.subarray(len) + if (this.errored || this.parserFields[this.milo.ParserFields.ERROR_CODE] !== this.milo.ERROR_NONE) { + throw this.createError(remaining) + } else if (this.pausedByParser) { + this.pausedByParser = false + this.pauseStateIsStart = false + this.paused = true + if (remaining.length > 0) { + socket.unshift(remaining) + } + return false + } + + if (remaining.length > 0) { + socket.unshift(remaining) + return false + } + } + + return true + } + + completeDirectBody () { + const { milo } = this + + if (currentBuffer.buffer !== milo.memory.buffer) { + currentBuffer = new FastBuffer(milo.memory.buffer, currentBufferPtr, currentBufferSize) + this.updateBuffers() + } else if (this.parserEvents.buffer !== milo.memory.buffer) { + this.updateBuffers() + } + + this.directBodyCompletePending = false + currentBufferRef = EMPTY_BUF + + milo.complete(this.parser) + this.drainEvents() + } + + setShouldSkipBody (value) { + if (this.skipBody !== value) { + this.skipBody = value + this.milo.setShouldSkipBody(this.parser, value) + } + } + + finish () { + if (!this.parser) { + return null + } + + if (this.directBodyRemaining > 0) { + return new ResponseContentLengthMismatchError() + } + + if (this.parserEvents.buffer !== this.milo.memory.buffer) { + this.updateBuffers() + } + + this.milo.finish(this.parser) + this.drainEvents() + + if (!this.errored) { + return null + } + + return this.createError(EMPTY_BUF) + } + + createError (data) { + const { contentLength, bytesRead } = this + + if (contentLength !== -1 && bytesRead !== contentLength) { + return new ResponseContentLengthMismatchError() + } + + const errorCode = this.parserFields[this.milo.ParserFields.ERROR_CODE] + const errorName = this.milo.Errors[errorCode] + const errorDescription = + errorName === 'UNEXPECTED_EOF' ? 'Invalid EOF state' : this.milo.getErrorDescription(this.parser) + const reason = + errorName === 'UNEXPECTED_EOF' + ? errorDescription + : errorDescription + ? `[ERROR_${errorName}] ${errorDescription}` + : `ERROR_${errorName}` + return new HTTPParserError(`Response does not match the HTTP/1.1 protocol (${reason})`, errorName, data) + } + + destroy () { + if (this.parser) { + this.milo.destroy(this.parser) + this.parser = null + } + + this.timeout && timers.clearTimeout(this.timeout) + this.timeout = null + this.timeoutValue = null + this.timeoutType = null + this.paused = false + this.responseStarted = false + this.pausedByParser = false + this.pauseStateIsStart = false + this.connectionKeepAlive = false + this.skipBody = false + } + + pauseParser (stateIsStart = false) { + this.milo.pause(this.parser) + this.pausedByParser = true + this.pauseStateIsStart = stateIsStart + } + + drainEvents () { + const { socket, client, milo } = this + let cursor = 0 + + const firstEvent = this.parserEvents[0] + if (firstEvent !== milo.EVENT_END && firstEvent !== milo.EVENT_ERROR && !this.responseStarted) { + this.responseStarted = true + + if (socket.destroyed) { + return this.fail(this.milo.ERROR_CALLBACK_ERROR, 'Other side closed') + } + + const request = client[kQueue][client[kRunningIdx]] + if (!request) { + return this.fail(this.milo.ERROR_CALLBACK_ERROR, 'Missing request') + } + + request.onResponseStarted() + } + + for (;;) { + const event = this.parserEvents[cursor] + let eventLen = EVENT_RANGE_SIZE + switch (event) { + case milo.EVENT_END: + return + case milo.EVENT_ERROR: + this.errored = true + return + case milo.EVENT_MESSAGE_COMPLETE: { + const { client, socket, statusCode, upgrade, trailers, contentLength, bytesRead, shouldKeepAlive } = this + + this.responseStarted = false + + if (socket.destroyed && (!statusCode || shouldKeepAlive)) { + return this.fail(milo.ERROR_CALLBACK_ERROR, 'Other side closed') + } + + if (upgrade) { + this.pauseParser() + return + } + + assert(statusCode >= 100) + + const request = client[kQueue][client[kRunningIdx]] + assert(request) + + this.statusCode = 0 + this.statusText = '' + this.bytesRead = 0 + this.contentLength = -1 + this.directBodyRemaining = 0 + this.directBodyCompletePending = false + this.headersSuspended = false + this.skipBody = false + this.keepAlive = '' + this.connectionKeepAlive = false + this.trailers = [] + this.trailersSize = 0 + + if (statusCode < 200) { + break + } + + if (request.method !== 'HEAD' && contentLength !== -1 && bytesRead !== contentLength) { + util.destroy(socket, new ResponseContentLengthMismatchError()) + this.pauseParser() + break + } + + request.onResponseEnd(trailers) + + client[kQueue][client[kRunningIdx]++] = null + + if (socket[kWriting]) { + assert(client[kRunning] === 0) + util.destroy(socket, new InformationalError('reset')) + this.pauseParser(true) + } else if (!shouldKeepAlive) { + util.destroy(socket, new InformationalError('reset')) + this.pauseParser(true) + } else if (socket[kReset] && client[kRunning] === 0) { + util.destroy(socket, new InformationalError('reset')) + this.pauseParser(true) + } else if (client[kPipelining] == null || client[kPipelining] === 1) { + setImmediate(client[kResume]) + } else { + client[kResume]() + } + + break + } + case milo.EVENT_REASON: { + const at = this.parserEvents.readUInt32LE(cursor + 1) + const len = this.parserEvents.readUInt32LE(cursor + 5) + this.statusText = new FastBuffer(currentBufferRef.buffer, currentBufferRef.byteOffset + at, len).toString() + break + } + case milo.EVENT_HEADER_NAME: { + const at = this.parserEvents.readUInt32LE(cursor + 1) + const len = this.parserEvents.readUInt32LE(cursor + 5) + const data = + len > 0 ? new FastBuffer(currentBufferRef.buffer, currentBufferRef.byteOffset + at, len) : EMPTY_BUF + + this.headers.push(data) + this.headersSize += len + if (this.headersSize >= this.headersMaxSize) { + util.destroy(this.socket, new HeadersOverflowError()) + return this.fail(milo.ERROR_CALLBACK_ERROR, 'Headers overflow') + } + + break + } + case milo.EVENT_HEADER_VALUE: { + const at = this.parserEvents.readUInt32LE(cursor + 1) + const len = this.parserEvents.readUInt32LE(cursor + 5) + const data = + len > 0 ? new FastBuffer(currentBufferRef.buffer, currentBufferRef.byteOffset + at, len) : EMPTY_BUF + const key = this.headers[this.headers.length - 1] + + this.headers.push(data) + + if (key.length === 10) { + const headerName = util.bufferToLowerCasedHeaderName(key) + if (headerName === 'keep-alive') { + this.keepAlive += data.toString() + } else if (headerName === 'connection') { + this.connectionKeepAlive = data.length === 10 && util.bufferToLowerCasedHeaderName(data) === 'keep-alive' + } + } + + this.headersSize += len + if (this.headersSize >= this.headersMaxSize) { + util.destroy(this.socket, new HeadersOverflowError()) + return this.fail(milo.ERROR_CALLBACK_ERROR, 'Headers overflow') + } + + break + } + case milo.EVENT_HEADERS: { + eventLen = EVENT_HEADERS_SIZE + + const statusCode = this.parserEvents.readUInt16LE(cursor + 5) + const shouldKeepAlive = this.parserEvents[cursor + 7] !== 0 + const shouldUpgrade = this.parserEvents[cursor + 8] !== 0 + const hasTrailers = this.parserEvents[cursor + 9] !== 0 + const bodyKind = this.parserEvents[cursor + 10] + const contentLength = + this.parserEvents.readUInt32LE(cursor + 11) + this.parserEvents.readUInt32LE(cursor + 15) * 0x100000000 + + const { socket, client, headers, statusText } = this + + if (socket.destroyed) { + return this.fail(milo.ERROR_CALLBACK_ERROR, 'Other side closed') + } + + const request = client[kQueue][client[kRunningIdx]] + if (!request) { + return this.fail(milo.ERROR_CALLBACK_ERROR, 'Missing request') + } + + assert(!this.upgrade) + assert(this.statusCode < 200) + + if (statusCode === 100) { + util.destroy(socket, new SocketError('bad response', util.getSocketInfo(socket))) + return this.fail(milo.ERROR_CALLBACK_ERROR, 'Bad response') + } + + if (shouldUpgrade && !request.upgrade) { + util.destroy(socket, new SocketError('bad upgrade', util.getSocketInfo(socket))) + return this.fail(milo.ERROR_CALLBACK_ERROR, 'Bad upgrade') + } + + assert(this.timeoutType === TIMEOUT_HEADERS) + + this.statusCode = statusCode + this.shouldKeepAlive = + shouldKeepAlive || (request.method === 'HEAD' && !socket[kReset] && this.connectionKeepAlive) + this.contentLength = bodyKind === BODY_KIND_CONTENT_LENGTH ? contentLength : -1 + + if (this.statusCode >= 200) { + const bodyTimeout = request.bodyTimeout != null ? request.bodyTimeout : client[kBodyTimeout] + this.setTimeout(bodyTimeout, TIMEOUT_BODY) + } else if (this.timeout?.refresh) { + this.timeout.refresh() + } + + if (request.method === 'CONNECT') { + assert(client[kRunning] === 1) + milo.setIsConnect(this.parser, true) + this.upgrade = true + return + } + + if (shouldUpgrade) { + assert(client[kRunning] === 1) + this.upgrade = true + this.pauseParser() + return + } + + this.headers = [] + this.headersSize = 0 + + if (this.shouldKeepAlive && client[kPipelining]) { + const keepAliveTimeout = this.keepAlive ? util.parseKeepAliveTimeout(this.keepAlive) : null + + if (keepAliveTimeout != null) { + const timeout = Math.min( + keepAliveTimeout - client[kKeepAliveTimeoutThreshold], + client[kKeepAliveMaxTimeout] + ) + if (timeout <= 0) { + socket[kReset] = true + } else { + client[kKeepAliveTimeoutValue] = timeout + } + } else { + client[kKeepAliveTimeoutValue] = client[kKeepAliveDefaultTimeout] + } + } else { + socket[kReset] = true + } + + const pause = request.onResponseStart(statusCode, headers, this.resume, statusText) === false + + if (request.aborted) { + return this.fail(milo.ERROR_CALLBACK_ERROR, 'Request aborted') + } + + if (request.method === 'HEAD' || statusCode < 200) { + this.setShouldSkipBody(true) + } + + this.headersSuspended = true + if ( + !pause && + request.method !== 'HEAD' && + statusCode >= 200 && + statusCode !== 204 && + statusCode !== 205 && + statusCode !== 304 && + bodyKind === BODY_KIND_CONTENT_LENGTH && + contentLength > 0 && + !hasTrailers + ) { + this.directBodyRemaining = contentLength + } + + if (socket[kBlocking]) { + socket[kBlocking] = false + client[kResume]() + } + + if (pause) { + this.pauseParser() + this[kPausedByHandler] = true + } else if ( + request.method === 'HEAD' || + statusCode < 200 || + statusCode === 204 || + statusCode === 205 || + statusCode === 304 || + (bodyKind === BODY_KIND_CONTENT_LENGTH && contentLength === 0) + ) { + this.directBodyCompletePending = true + } + + break + } + case milo.EVENT_DATA: { + const at = this.parserEvents.readUInt32LE(cursor + 1) + const len = this.parserEvents.readUInt32LE(cursor + 5) + const { client, socket, statusCode, maxResponseSize } = this + + if (socket.destroyed) { + return this.fail(milo.ERROR_CALLBACK_ERROR, 'Other side closed') + } + + const request = client[kQueue][client[kRunningIdx]] + assert(request) + assert(this.timeoutType === TIMEOUT_BODY) + + if (this.timeout?.refresh) { + this.timeout.refresh() + } + + assert(statusCode >= 200) + + if (maxResponseSize > -1 && this.bytesRead + len > maxResponseSize) { + util.destroy(socket, new ResponseExceededMaxSizeError()) + return this.fail(milo.ERROR_CALLBACK_ERROR, 'Response size exceeded') + } + + this.bytesRead += len + + const buffer = currentBufferRef + if (request.onResponseData(new FastBuffer(buffer.buffer, buffer.byteOffset + at, len)) === false) { + this.pauseParser() + this[kPausedByHandler] = true + } + + break + } + case milo.EVENT_TRAILER_NAME: { + const at = this.parserEvents.readUInt32LE(cursor + 1) + const len = this.parserEvents.readUInt32LE(cursor + 5) + const data = + len > 0 ? new FastBuffer(currentBufferRef.buffer, currentBufferRef.byteOffset + at, len) : EMPTY_BUF + + this.trailers.push(data) + + this.trailersSize += len + if (this.trailersSize >= this.headersMaxSize) { + util.destroy(this.socket, new HeadersOverflowError()) + return this.fail(milo.ERROR_CALLBACK_ERROR, 'Headers overflow') + } + + break + } + case milo.EVENT_TRAILER_VALUE: { + const at = this.parserEvents.readUInt32LE(cursor + 1) + const len = this.parserEvents.readUInt32LE(cursor + 5) + const data = + len > 0 ? new FastBuffer(currentBufferRef.buffer, currentBufferRef.byteOffset + at, len) : EMPTY_BUF + + this.trailers.push(data) + + this.trailersSize += len + if (this.trailersSize >= this.headersMaxSize) { + util.destroy(this.socket, new HeadersOverflowError()) + return this.fail(milo.ERROR_CALLBACK_ERROR, 'Headers overflow') + } + + break + } + default: + return + } + + cursor += eventLen + } + } + + fail (code, message) { + this.milo.fail(this.parser, code, message) + this.errored = true + } + + onUpgrade (head) { + const { upgrade, client, socket, headers, statusCode } = this + + assert(upgrade) + assert(client[kSocket] === socket) + assert(!socket.destroyed) + assert(!this.paused) + + const request = client[kQueue][client[kRunningIdx]] + assert(request) + assert(request.upgrade || request.method === 'CONNECT') + + this.statusCode = 0 + this.statusText = '' + this.shouldKeepAlive = false + this.headers = [] + this.headersSize = 0 + + socket.unshift(head) + socket[kParser].destroy() + socket[kParser] = null + socket[kClient] = null + socket[kError] = null + + removeAllListeners(socket) + + client[kSocket] = null + client[kHTTPContext] = null + client[kQueue][client[kRunningIdx]++] = null + client.emit('disconnect', client[kUrl], [client], new InformationalError('upgrade')) + + try { + request.onRequestUpgrade(statusCode, headers, socket) + } catch (err) { + util.destroy(socket, err) + } + + client[kResume]() + } +} + +function setMiloEnabled (value) { + miloEnabled = value +} + +function getMiloEnabled () { + return miloEnabled +} + +module.exports = { H1Parser, getMiloEnabled, setMiloEnabled } diff --git a/lib/milo/CODE_OF_CONDUCT.md b/lib/milo/CODE_OF_CONDUCT.md new file mode 100644 index 00000000000..c42431d657d --- /dev/null +++ b/lib/milo/CODE_OF_CONDUCT.md @@ -0,0 +1,76 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to make participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +- Using welcoming and inclusive language +- Being respectful of differing viewpoints and experiences +- Gracefully accepting constructive criticism +- Focusing on what is best for the community +- Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +- The use of sexualized language or imagery and unwelcome sexual attention or + advances +- Trolling, insulting/derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or electronic + address, without explicit permission +- Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies within all project spaces, and it also applies when +an individual is representing the project or its community in public spaces. +Examples of representing a project or community include using an official +project e-mail address, posting via an official social media account, or acting +as an appointed representative at an online or offline event. Representation of +a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at [INSERT EMAIL ADDRESS]. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see +https://www.contributor-covenant.org/faq diff --git a/lib/milo/LICENSE.md b/lib/milo/LICENSE.md new file mode 100644 index 00000000000..c485e26f764 --- /dev/null +++ b/lib/milo/LICENSE.md @@ -0,0 +1,7 @@ +ISC License + +Copyright (c) 2023, and above Paolo Insogna, NearForm and other contributors + +Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/lib/milo/README.md b/lib/milo/README.md new file mode 100644 index 00000000000..ce54400811b --- /dev/null +++ b/lib/milo/README.md @@ -0,0 +1,399 @@ +# @perseveranza-pets/milo + +Milo is a fast and embeddable HTTP/1.1 parser written in [Rust][rust]. + +Milo can report parser activity through callbacks or through parser-owned event buffers. See the language-specific API docs for event decoding details: [JavaScript](./docs/js.md), [Rust](./docs/rust.md), and [C++](./docs/cpp.md). + +## Support Matrix + +Milo supports strict HTTP/1.1 message parsing for Rust, C++, and JavaScript via WebAssembly. + +| Target | Status | Artifact | +| ---------- | --------- | --------------------------------------------- | +| Rust | Supported | `milo` crate | +| C++ | Supported | `milo.h` and `libmilo.a` | +| JavaScript | Supported | `@perseveranza-pets/milo` WebAssembly package | +| CLI | Supported | `milo-parser` binary | + +Milo intentionally rejects HTTP/0.9, HTTP/1.0, RTSP, obs-fold, bare LF, and bare CR. It does not parse HTTP/2 messages, except for strict `PRI * HTTP/2.0` switch-over detection. + +For security and ambiguity reduction, Milo rejects request bodies on `GET` and `HEAD`. Responses to `HEAD` are application context: callers must use `skip_body` when they know a response has no body because it belongs to a `HEAD` request. + +Use `max_body_payload` when an integration needs to cap body payload consumed by a single parse call. `0` means unlimited. Reaching the limit returns normally with unconsumed input left for the next parse call. + +Use `suspend_after_headers` when an integration needs to inspect headers before body parsing starts. Parsing returns after consuming the header terminator and can continue with the next parse call. + +For full parser scope, strictness, and protocol behavior, see [Milo Design](./docs/design.md). + +## How to use it (JavaScript via WebAssembly) + +Install it from npm: + +``` +npm install @perseveranza-pets/milo +``` + +For CommonJS projects, install the CJS-only package instead: + +``` +npm install @perseveranza-pets/milo-cjs +``` + +Then create a sample source file: + +```javascript +import { setup } from '@perseveranza-pets/milo' + +/* + Milo works using callbacks. + + All callbacks have the same signature, which characterizes the payload: + + * The current parser + * from: The payload offset. + * size: The payload length. + + The payload parameters above are relative to the last data sent to the milo.parse method. + + If the current callback has no payload, both values are set to 0. + + The callbacks must be provided using setup and are named in snake case. +*/ +const milo = setup({ + on_data (p, from, size) { + console.log(`Pos=${from} Body: ${message.slice(from, from + size).toString()}`) + } +}) + +// Prepare a message to parse. +const message = Buffer.from('HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nabc') + +// Allocate a memory in the WebAssembly space. This speeds up data copying to the WebAssembly layer. +const ptr = milo.alloc(message.length) + +// Create a buffer we can use normally. +const buffer = Buffer.from(milo.memory.buffer, ptr, message.length) + +// Create the parser. +const parser = milo.create() + +// Toggle on the callbacks you want to receive +milo.setActiveCallbacks(parser, milo.CALLBACK_ACTIVE_ON_DATA) + +// Now perform the main parsing using milo.parse. The method returns the number of consumed characters. +buffer.set(message, 0) +milo.parse(parser, ptr, message.length) + +// Cleanup used resources. +milo.destroy(parser) +milo.dealloc(ptr, message.length) +``` + +The default JavaScript entry point uses the SIMD WebAssembly build. Use `@perseveranza-pets/milo/no-simd` when SIMD is not available, and add `/unbundled` to either entry point to load the external `.wasm` file instead of the bundled JavaScript module. + +CommonJS projects can use the same entry points from `@perseveranza-pets/milo-cjs`: + +```javascript +const { setup } = require('@perseveranza-pets/milo-cjs') +``` + +Finally build and execute it using `node`: + +```bash +node index.js +# Pos=38 Body: abc +``` + +## How to use it (Rust) + +Add `milo-parser` to your `Cargo.toml`: + +```toml +[package] +name = "milo-example" +version = "0.1.0" +edition = "2024" +publish = false + +[dependencies] +milo-parser = "0.4.0" +``` + +Create a sample source file: + +```rust +use core::ffi::c_void; +use core::slice; + +use milo_parser::{Parser, CALLBACK_ACTIVE_ON_DATA}; + +fn main() { + // Create the parser. + let mut parser = Parser::new(); + + // Prepare a message to parse. + let message = String::from("HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nabc"); + parser.context = message.as_ptr() as *mut c_void; + + // Milo works using callbacks. + // + // All callbacks have the same signature, which characterizes the payload: + // + // p: The current parser. + // from: The payload offset. + // size: The payload length. + // + // The payload parameters above are relative to the last data sent to the parse + // method. + // + // If the current callback has no payload, both values are set to 0. + parser.callbacks.on_data = |p: &mut Parser, from: usize, size: usize| { + let message = + unsafe { std::str::from_utf8_unchecked(slice::from_raw_parts(p.context.add(from) as *const u8, size)) }; + + // Use the callback data. + println!("Pos={} Body: {}", from, message); + }; + + // Toggle on the callbacks you want to receive + parser.active_callbacks |= CALLBACK_ACTIVE_ON_DATA; + + // Now perform the main parsing using milo.parse. The method returns the number + // of consumed characters. + parser.parse(message.as_ptr(), message.len()); +} + +``` + +Finally build and execute it using `cargo`: + +```bash +cargo run +# Pos=38 Body: abc +``` + +## How to use it (C++) + +First, let's download Milo release from GitHub. + +You will need a static library file (for Linux/Unix/MacOS is `libmilo.a`) and a header file (`milo.h`). + +Create a sample source file: + +```cpp +#include "milo.h" +#include +#include +#include + +int main() { + // Create the parser. + milo_parser::Parser* parser = milo_parser::milo_create(); + + // Prepare a message to parse. + const char* message = "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nabc"; + + parser->context = (char*) message; + + /* + Milo works using callbacks. + + All callbacks have the same signature, which characterizes the payload: + + * p: The current parser. + * from: The payload offset. + * size: The payload length. + + The payload parameters above are relative to the last data sent to the milo_parse method. + + If the current callback has no payload, both values are set to 0. + */ + parser->callbacks.on_data = [](milo_parser::Parser* p, uintptr_t from, uintptr_t size) { + const char* payload = reinterpret_cast(p->context) + from; + + printf("Pos=%" PRIuPTR " Body: %.*s\n", from, static_cast(size), payload); + }; + + // Toggle on the callbacks you want to receive + parser->active_callbacks |= milo_parser::CALLBACK_ACTIVE_ON_DATA; + + // Now perform the main parsing using milo.parse. The method returns the number of consumed characters. + milo_parser::milo_parse(parser, reinterpret_cast(message), strlen(message)); + + // Cleanup used resources. + milo_parser::milo_destroy(parser); +} +``` + +And then you can compile using your preferred build system. For instance, let's try with [Clang]: + +```bash +clang++ -std=c++11 -o example main.cc libmilo.a +./example +# Pos=38 Body: abc +``` + +### Build milo (WebAssembly and C++) locally + +If you want to build it locally, you need the following tools: + +- [cargo-make][cargo-make] +- Rust toolchain - You can install it via [rustup]. +- [rust-cbindgen](https://github.com/mozilla/cbindgen) + +Make sure you have the `nightly` toolchain installed locally: + +```bash +rustup toolchain install nightly +``` + +Make sure you have the `wasm32-unknown-unknown` target: + +```bash +rustup target add wasm32-unknown-unknown +``` + +Install npm dependencies + +```bash +pnpm install +``` + +After all the requirements are met, you can then run: + +```bash +makers +``` + +The command above will produce debug and release builds for each language in the top-level `dist` folder. + +The WebAssembly release build uses immediate-abort panics to keep the artifact smaller. Panics trap without unwinding or rich panic messages. + +The debug build also enables the `on_state_change` callback and is more verbose in case of WebAssembly errors. + +## How to use it (CLI) + +Install it from crates.io: + +```bash +cargo install milo-parser +``` + +The `milo-parser` binary reads an HTTP/1.1 message from standard input by default and prints the callbacks emitted by Milo: + +```bash +printf 'GET / HTTP/1.1\r\nHost: example.com\r\n\r\n' | milo-parser +# offset=0 size=0 event=request +# offset=0 size=0 event=message_start +# offset=0 size=0 event=state_change +# offset=0 size=3 event=method +``` + +Each output line uses this format: + +```text +offset=$OFFSET size=$SIZE event=$EVENT +``` + +Parser errors are emitted as callback lines too: + +```text +offset=$OFFSET size=$SIZE event=error error=$ERROR description="$DESCRIPTION" +``` + +Use `-f` or `--file` to parse a file: + +```bash +milo-parser --file request.http +``` + +By default Milo autodetects request or response input. Use `-o` or `--request` to force request parsing, and `-i` or `--response` to force response parsing: + +```bash +milo-parser --request --file request.http +milo-parser --response --file response.http +``` + +## API + +See the following files, according to the language you are using: + +- [JavaScript via WebAssembly API](./docs/js.md) +- [Rust API](./docs/rust.md) +- [C++ API](./docs/cpp.md) + +## Strictness Differences From llhttp + +Milo does not aim for byte-for-byte llhttp compatibility when lenient behavior would conflict with Milo's strict parser policy. + +- Milo rejects HTTP/0.9, HTTP/1.0, RTSP, obs-fold, bare LF, and bare CR. +- Milo rejects normal HTTP/2 request and response messages. +- Milo rejects request bodies on `GET` and `HEAD`. +- Milo requires `skip_body` for application-known no-body response contexts such as responses to `HEAD`. +- Milo validates protocol framing and syntax, but leaves application semantics to callers. + +## Security Boundaries + +Milo validates HTTP/1.1 syntax, message framing, protocol switching, connection management, and data-after-close behavior. Milo does not validate routing, authorization, representation semantics, URI normalization, `Host` policy, method-specific request-target forms, CONNECT authority-form, or full header field semantics unless they affect safe framing. + +## How it works? + +Milo leverages Rust's [procedural macro], [syn] and [quote] crates to allow an easy definition of actions and matchers for the parser. + +See the [macros](./macros/README.md) internal crate for more information. + +The resulting parser is a simple state machine which copies data in only one optional case: automatically handling the unconsumed portion of the input data. + +In all other cases, no data is copied and the memory footprint is very small as only a few dozen `bool`, `uintptr_t`, or `uint64_t` fields can represent the entire parser state. + +## Why? + +The scope of Milo is to replace [llhttp] as [Node.js] main HTTP parser. + +This project aims to: + +- Make it maintainable and verifiable using easy to read Rust code. +- Be performant by avoiding any unnecessary data copy. +- Be self-contained and dependency-free. + +To see the rationale behind the replacement of llhttp, check Paolo's talk at [Vancouver's Node Collab Summit][vancouver-talk] in January 2023 ([slides][vancouver-slides]). + +To see the initial disclosure of milo, check Paolo's talk at [NodeConf EU 2023][nodeconf-talk] in November 2023 ([slides][slides]). + +## Sponsored by + +[![NearForm](https://raw.githubusercontent.com/ShogunPanda/milo/main/docs/nearform.jpg)][nearform] + +## Contributing to milo + +- Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet. +- Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it. +- Fork the project. +- Start a feature/bugfix branch. +- Commit and push until you are happy with your contribution. +- Make sure to add tests for it. This is important so I don't break it in a future version unintentionally. + +## Copyright + +Copyright (C) 2023 and above Paolo Insogna (paolo@cowtech.it) and NearForm (https://nearform.com). + +Licensed under the ISC license, which can be found at https://choosealicense.com/licenses/isc or in the [LICENSE.md](./LICENSE.md) file. + +[rust]: https://www.rust-lang.org/ +[webassembly]: https://webassembly.org/ +[nearform]: https://nearform.com +[llhttp]: https://github.com/nodejs/llhttp +[Node.js]: https://nodejs.org +[vancouver-talk]: https://youtube.com/watch?v=L-VONzXQ944 +[vancouver-slides]: https://talks.cowtech.it/http-parser +[nodeconf-talk]: https://youtube.com/watch?v=dcHbAeO_ccY +[slides]: https://talks.paoloinsogna.dev/milo +[isc]: https://choosealicense.com/licenses/isc +[procedural macro]: https://doc.rust-lang.org/reference/procedural-macros.html +[syn]: https://crates.io/crates/syn +[quote]: https://crates.io/crates/quote +[match]: https://doc.rust-lang.org/rust-by-example/flow_control/match.html +[match-slice]: https://doc.rust-lang.org/rust-by-example/flow_control/match/destructuring/destructure_slice.html +[cargo-make]: https://github.com/sagiegurari/cargo-make +[rustup]: https://rustup.rs/ +[Clang]: https://clang.llvm.org/ diff --git a/lib/milo/binary/no-simd.wasm b/lib/milo/binary/no-simd.wasm new file mode 100644 index 00000000000..a327bcb9900 Binary files /dev/null and b/lib/milo/binary/no-simd.wasm differ diff --git a/lib/milo/binary/simd.wasm b/lib/milo/binary/simd.wasm new file mode 100644 index 00000000000..508d6499ae3 Binary files /dev/null and b/lib/milo/binary/simd.wasm differ diff --git a/lib/milo/package.json b/lib/milo/package.json new file mode 100644 index 00000000000..b470435c482 --- /dev/null +++ b/lib/milo/package.json @@ -0,0 +1,38 @@ +{ + "name": "@perseveranza-pets/milo-cjs", + "version": "0.8.0", + "description": "A fast and embeddable HTTP/1.1 parser.", + "homepage": "https://sw.cowtech.it/milo", + "repository": { + "type": "git", + "url": "git+https://github.com/ShogunPanda/milo.git" + }, + "keywords": [ + "http", + "parser" + ], + "bugs": { + "url": "https://github.com/ShogunPanda/milo/issues" + }, + "author": "Shogun ", + "license": "ISC", + "private": false, + "type": "commonjs", + "files": [ + "binary", + "src", + "CODE_OF_CONDUCT.md", + "LICENSE.md", + "README.md" + ], + "main": "src/simd/index.js", + "exports": { + ".": "./src/simd/index.js", + "./unbundled": "./src/simd/unbundled.js", + "./no-simd": "./src/no-simd/index.js", + "./no-simd/unbundled": "./src/no-simd/unbundled.js" + }, + "engines": { + "node": ">= 22.21.0" + } +} \ No newline at end of file diff --git a/lib/milo/src/no-simd/index.js b/lib/milo/src/no-simd/index.js new file mode 100644 index 00000000000..1e0fa15907c --- /dev/null +++ b/lib/milo/src/no-simd/index.js @@ -0,0 +1,1087 @@ +const wasmModule = new WebAssembly.Module( + Buffer.from( + 'AGFzbQEAAAABQgtgA39/fwBgAX8Bf2ACf38AYAF/AGABfwF+YAJ/fgBgBH9/f38AYAABf2AIf39/f39/f3wAYAN/f38Bf2ACf38BfwKUBBwDZW52CG9uX2Vycm9yAAADZW52Cm9uX2hlYWRlcnMACANlbnYJb25fZmluaXNoAAADZW52EG9uX21lc3NhZ2Vfc3RhcnQAAANlbnYTb25fbWVzc2FnZV9jb21wbGV0ZQAAA2Vudgpvbl9yZXF1ZXN0AAADZW52C29uX3Jlc3BvbnNlAAADZW52CG9uX3Jlc2V0AAADZW52CW9uX21ldGhvZAAAA2VudgZvbl91cmwAAANlbnYLb25fcHJvdG9jb2wAAANlbnYKb25fdmVyc2lvbgAAA2Vudglvbl9zdGF0dXMAAANlbnYJb25fcmVhc29uAAADZW52Dm9uX2hlYWRlcl9uYW1lAAADZW52D29uX2hlYWRlcl92YWx1ZQAAA2Vudgpvbl9jb25uZWN0AAADZW52Cm9uX3VwZ3JhZGUAAANlbnYPb25fY2h1bmtfbGVuZ3RoAAADZW52F29uX2NodW5rX2V4dGVuc2lvbl9uYW1lAAADZW52GG9uX2NodW5rX2V4dGVuc2lvbl92YWx1ZQAAA2Vudghvbl9jaHVuawAAA2Vudgdvbl9ib2R5AAADZW52B29uX2RhdGEAAANlbnYPb25fdHJhaWxlcl9uYW1lAAADZW52EG9uX3RyYWlsZXJfdmFsdWUAAANlbnYLb25fdHJhaWxlcnMAAANlbnYPb25fc3RhdGVfY2hhbmdlAAADQUAGAQMDBwIDBgMEBAEEBAEBAQQBBAQBAQEBAQEBAQEBAQEBAQcJAwIDBQUCAgIFAgICAgICAgEBAQEKAQIDAgICBQMBABEGCQF/AUGAgMAACwedCDkGbWVtb3J5AgAFYWxsb2MAHQVjbGVhcgAeCGNvbXBsZXRlAB8GY3JlYXRlACAHZGVhbGxvYwAhB2Rlc3Ryb3kAIgRmYWlsACMGZmluaXNoACQOZ2V0X2NodW5rX3NpemUAJRJnZXRfY29udGVudF9sZW5ndGgAJg5nZXRfZXJyb3JfY29kZQAnGWdldF9lcnJvcl9kZXNjcmlwdGlvbl9yYXcAKBRnZXRfbWF4X2JvZHlfcGF5bG9hZAApFWdldF9tYXhfaGVhZGVyX2xlbmd0aAAqGWdldF9tYXhfc3RhcnRfbGluZV9sZW5ndGgAKwpnZXRfbWV0aG9kACwKZ2V0X3BhcnNlZAAtDGdldF9wb3NpdGlvbgAuGGdldF9yZW1haW5pbmdfY2h1bmtfc2l6ZQAvHGdldF9yZW1haW5pbmdfY29udGVudF9sZW5ndGgAMAlnZXRfc3RhdGUAMQpnZXRfc3RhdHVzADIdaGFzX2NodW5rZWRfdHJhbnNmZXJfZW5jb2RpbmcAMxRoYXNfY29ubmVjdGlvbl9jbG9zZQA0Fmhhc19jb25uZWN0aW9uX3VwZ3JhZGUANRJoYXNfY29udGVudF9sZW5ndGgANgxoYXNfdHJhaWxlcnMANxVoYXNfdHJhbnNmZXJfZW5jb2RpbmcAOAtoYXNfdXBncmFkZQA5DWlzX2F1dG9kZXRlY3QAOgppc19jb25uZWN0ADsIaXNfZGVidWcAPAlpc19wYXVzZWQAPQppc19yZXF1ZXN0AD4ObWlsb19oYXNfZGVidWcAPwVwYXJzZQBABXBhdXNlAEEFcmVzZXQAQgZyZXN1bWUAQxRzZXRfYWN0aXZlX2NhbGxiYWNrcwBEEXNldF9hY3RpdmVfZXZlbnRzAEUJc2V0X2RlYnVnAEYOc2V0X2lzX2Nvbm5lY3QARw5zZXRfaXNfcmVxdWVzdABIFHNldF9tYXhfYm9keV9wYXlsb2FkAEkVc2V0X21heF9oZWFkZXJfbGVuZ3RoAEoZc2V0X21heF9zdGFydF9saW5lX2xlbmd0aABLFXNldF9zaG91bGRfYXV0b2RldGVjdABMIHNldF9zaG91bGRfY29udGludWVfd2l0aG91dF9kYXRhAE0cc2V0X3Nob3VsZF9tYW5hZ2VfdW5jb25zdW1lZABOFHNldF9zaG91bGRfc2tpcF9ib2R5AE8gc2V0X3Nob3VsZF9zdXNwZW5kX2FmdGVyX2hlYWRlcnMAUBxzaG91bGRfY29udGludWVfd2l0aG91dF9kYXRhAFEYc2hvdWxkX21hbmFnZV91bmNvbnN1bWVkAFIQc2hvdWxkX3NraXBfYm9keQBTHHNob3VsZF9zdXNwZW5kX2FmdGVyX2hlYWRlcnMAVArmvwJAlgIBBH8CQCACIANPDQAgAS0AACEFAkAgAyACayIHQQNNBEAMAQtBgIKECCAFQYGChAhsIgEgAigAAHMiBmsgBnJBgIGChHhxQYCBgoR4RwRADAELIAJBfHFBBGohAgJAIAdBCU8EQCACIANBCGsiB0sNAQNAQYCChAggAigCACABcyIGayAGckGAgYKEeHFBgIGChHhHDQJBgIKECCACQQRqKAIAIAFzIgZrIAZyQYCBgoR4cUGAgYKEeEcNAiACQQhqIgIgB00NAAsMAQsgAiADTw0CDAELIAIgA08NAQsgA0EBa0EBIQQDQCAFIAItAABGDQEgAkEBaiICIANHDQALIQJBACEECyAAIAI2AgQgACAENgIACyYAAkAgAEEATgRAIABFBEBBASEADAILIABBARBVIgANAQsACyAACzMAIABCADcDKCAAQQA6ABUgAEIANwMwIABCADcDOCAAQgA3A0AgAEIANwNIIABBADYCUAvSAwIDfwF+AkAgACIBLQAkIgBBDk1BAEEBIAB0QYDPAXEbRQRAIAFBAzoAJiABQQI6ACQgAUENOgD0AkEAIQAgAUEAOgB5IAFBp5jAACkAADcAbCABQayYwAApAAA3AHECQCABKQNYIAEpA2CEp0EBcUUEQCABKAL4AiECDAELIAEoAvgCIgJBAToAACACQQVqQQM6AAAgAkEBaiABKAIgNgAAQQYhAAsgACACakEAOgAADAELAn9BACABKQNYIAEpA2CEIgRCyACDUA0AGiAEQgiDQgBSBEAgASgC+AIiAEEEOgAAIABBBWpBADYAACAAQQFqIAEoAiA2AABBCSECCyACIARCwACDUA0AGiABKAL4AiACaiIAQQc6AAAgAEEFakEANgAAIABBAWogASgCIDYAACACQQlqCyECIAFBADoAFiABQQA6ABQCQCABLQBSQQFGBEBBDiEAIAEtABFBAXENAQsgAS0AUCEDIARCAoNQBEAgAyEADAELQQEhACADQQFxRQRAIAMhAAwBCyABKAL4AiACaiIDQQI6AAAgA0EFakEANgAAIANBAWogASgCIDYAACACQQlqIQILIAEgADoAJCABKAL4AiACakEAOgAACwvfAgEDfyMAQeAAayIAJAACQEGAgAQQViICRQ0AIAJBBGstAABBA3FFDQAgAkEAQYCABPwLAAsCQCACRQ0AIABBADYAXCAAQgA3AFQgAEIANwBMIABCADcARCAAQgA3ADwgAEIANwA0IABCADcCHCAAQgA3AiQgAEEANgIsIABCADcADyAAQQA6ABdBgANBCBBVIgFFDQAgAUIANwARIAFBAToAECABQgA3AwggAUKAwICAgIAINwMAIAFCADcAGSABQgA3AB8gASAAKQAzNwAnIAEgACkAOzcALyABIAApAEM3ADcgASAAKQBLNwA/IAEgACkAUzcARyABIAApAFg3AEwgASAAKAIoNgJkIAEgACkCIDcCXCABIAApAhg3AlQgAUHsAGpBAEH/AfwLACABIAI2AvgCIAEgAC8AFjsA8wIgASAAKQAONwDrAiABIAE2AmggAEHgAGokACABDwsACxUAAkAgAEUNACABRQ0AIAAgARBXCwsjAQF/IAAEQCAAKAL4AiIBBEAgAUGAgAQQVwsgAEGAAxBXCwuSAQEBfyAAIAE6ACYgAEECOgAkIABB7ABqIQRB/gEgAyADQf4BTxsiAwRAIAQgAiAD/AoAAAsgACADOgD0AiADIARqQQA6AABBACEDIAApA1ggACkDYIRCAYOnBH8gACgC+AIiAkEBOgAAIAJBBWogAToAACACQQFqIAAoAiA2AABBBgVBAAsgACgC+AJqQQA6AAALrAIBAn8CQAJAAkAgAC0AJCIBQQlNBEBBASABdEEbcQ0BIAFBAkYNAyABQQlGDQILIABBBToAJiAAQQI6ACQgAEEWOgD0AiAAQQA6AIIBIABBgIjAACkAADcAbCAAQYiIwAApAAA3AHQgAEGOiMAAKQAANwB6AkAgACkDWCAAKQNghKdBAXFFBEAgACgC+AIhAQwBCyAAKAL4AiIBQQE6AAAgAUEFakEFOgAAIAFBAWogACgCIDYAAEEGIQILIAEgAmpBADoAAA8LIABBAToAJA8LAn8gACkDWCAAKQNghEIIg1AEQCAAKAL4AiEBQQAMAQsgACgC+AIiAUEEOgAAIAFBBWpBADYAACABQQFqIAAoAiA2AABBCQshAiAAQQE6ACQgASACakEAOgAACwsHACAAKQMwCwcAIAApAygLBwAgAC0AJgsTACAAMQD0AiAAQewAaq1CIIaECwcAIAApAwgLBwAgACgCBAsHACAAKAIACwcAIAAtAEwLBwAgACkDGAsHACAAKAIgCwcAIAApA0ALBwAgACkDOAsHACAALQAkCwcAIAAoAkgLBwAgAC0ATwsHACAALQBQCwcAIAAt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pw00DDULAkAgAiAFTw0AIAogAmsiBkEAIAYgCk0bIQkgBSACayENIAIgBGohBgNAIAlFDTEgBi0AAC0AgIBABEAgCUEBayEJIAZBAWohBiANQQFrIg1FDQIMAQsLQQYhAiADQQY6ACYgA0ECOgAkIANBJjoA9AJBACEHIANBADoAkgEgA0G1lcAAKQAANwBsIANBvZXAACkAADcAdCADQcWVwAApAAA3AHwgA0HNlcAAKQAANwCEASADQdOVwAApAAA3AIoBIAMpA1ggAykDYIRCAYOnDTQMNQsCQAJAAkACQAJAAkACQAJAAkAgBSAORg0AIAggCk8NOCAEIAhqLQAAQTtGDQAgCEEBaiIJIA5PDQEDQAJAIAQgCWotAAAiBkEJRg0AIAZBIEYNACAJQQFrIQgMAwsgCUEBaiIJIA5JDQALDAILAkAgO1AEQCAAIQEMAQsgAEEJaiIBQYCABE8NPiADKAIgIQYgAygC+AIgAGpBFDoAACADKAL4AiAAakEBaiACIAZqNgAAIAMoAvgCIABqQQVqIAUgAms2AAALIAggDkcEQCAIQQFqIQJBACEFIAMtACRBAkYNNSADQQs6ACQMNQsgAykDMEIAUgRAIA5BAmohAkEAIQUgAy0AJEECRg01IANBDDoAJAw1CwJAIDNQBEAgASEADAELIAFBCWoiAEGAgARPBEAgASEADD8LIAMoAiAhAiADKAL4AiABakEXOgAAIAMoAvgCIAFqQQFqIAI2AAAgAygC+AIgAWpBBWpBADYAAAsgDkECaiECQQAhBSADLQAkQQJGBEAgACEBDDULIANBDToAJCAAIQEMNAsgCSAORg0AIAkgCk8NNiAEIAlqIgwtAABBIkYiGUUNASAIQQJqIgggDksNAyAEQX9zISggDkEHayEpIBBBCGshKiABQX9zIARqIRUgDkEDayErIAghDwwCC0EGIQIgA0EGOgAmIANBAjoAJCADQR46APQCQQAhByADQQA6AIoBIANBuZbAACkAADcAbCADQcGWwAApAAA3AHQgA0HJlsAAKQAANwB8IANBz5bAACkAADcAggEgAykDWCADKQNghEIBg6cNOQw6CyAOIgYgCU8EQCALQTs6AHQgC0HYAGogC0H0AGogDCAMIAYgCGtqEBwgCygCWEEBcSIGBH8gCygCXCAMawUgAQsgCWogDiAG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IANBBjoAJiADQQI6ACQgA0EeOgD0AkEAIQcgA0EAOgCKASADQeGUwAApAAA3AGwgA0HplMAAKQAANwB0IANB8ZTAACkAADcAfCADQfeUwAApAAA3AIIBIAMpA1ggAykDYIRCAYOnDTYMNwsgCUEQSw0CQQAhAkIAISwDQCACIApGDTICQCACIARqLQAAIgZBMGsiAUH/AXFBCkkNACAGQeEAa0H/AXFBBk8EQCAGQcEAa0H/AXFBBk8EQEEGIQIgA0EGOgAmIANBAjoAJCADQR46APQCQQAhByADQQA6AIoBIANB4ZTAACkAADcAbCADQemUwAApAAA3AHQgA0HxlMAAKQAANwB8IANB95TAACkAADcAggEgAykDWCADKQNghEIBg6cNOQw6CyAGQTdrIQEMAQsgBkHXAGshAQsgAa1C/wGDICxCBIZ8ISwgAkEBaiICIAlHDQALDAELQQYhAiADQQY6ACYgA0ECOgAkIANBDToA9AJBACEHIANBADoAeSADQa6KwAApAAA3AGwgA0GzisAAKQAANwBxIAMpA1ggAykDYIRCAYOnDTQMNQsgAyAsNwNAIAMgLDcDMAJAIENQBEAgACEBDAELIABBCWoiAUGAgARPDTYgAygCICECIAMoAvgCIABqQRM6AAAgAygC+AIgAGpBAWogAjYAACADKAL4AiAAakEFaiAJNgAACwJAAkACQCAFIAlNBEAgA0EBOgAUIAMpAzBCAFINASA8QgBSDQIgASEADAMLIAlBAWohAkEAIQUgAy0AJEECRg0vIANBCzoAJAwvCyAFQQJqIQJBACEFIAMtACRBAkYNLiADQQw6ACQMLgsgAUEJaiIAQYCABE8EQCABIQAMNwsgAygCICECIAMoAvgCIAFqQRY6AAAgAygC+AIgAWpBAWogAkEDajYAACADKAL4AiABakEFakEANgAACwJAIDNQBEAgACEBDAELIABBCWoiAUGAgARPDTYgAygCICECIAMoAvgCIABqQRc6AAAgAygC+AIgAGpBAWogAkEDajYAACADKAL4AiAAakEFakEANgAACyAFQQJqIQJBACEFIAMtACRBAkYNLCADQQ06ACQMLAtBDyECIANBDzoAJiADQQI6ACQgA0EZOgD0AkEAIQcgA0EAOgCFASADQf+UwAApAAA3AGwgA0GHlcAAKQAANwB0IANB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WCADKQNghEIBg6cNMgwzC0EGIQIgA0EGOgAmIANBAjoAJCADQRA6APQCQQAhByADQQA6AHwgA0GeicAAKQAANwBsIANBponAACkAADcAdCADKQNYIAMpA2CEQgGDpw0xDDILAkAgOFAEQCACIQAMAQsgAkEJaiIAQYCABE8EQCACIQAMNAsgAygCICEBIAMoAvgCIAJqQQs6AAAgAygC+AIgAmpBAWogAUEFajYAACADKAL4AiACakEFakEDNgAACwJAIEBQBEAgACECDAELIABBCWoiAkGAgARPDTMgAygCICEBIAMoAvgCIABqQQw6AAAgAygC+AIgAGpBAWogAUEJajYAACADKAL4AiAAakEFakEDNgAACyA/UARAIAIhAQwBCyANBEAgAiEBDAELIAJBCWoiAUH//wNLBEAgAiEADDMLIAMoAiAhACADKAL4AiACakENOgAAIAMoAvgCIAJqQQFqIABBDWo2AAAgAygC+AIgAmpBBWogBkENazYAAAsgBkECaiECIAMtACRBAkYNKCADQQY6ACQMKAtBDCECIANBDDoAJiADQQI6ACQgA0EcOgD0AkEAIQcgA0EAOgCIASADQc+KwAApAAA3AGwgA0HXisAAKQAANwB0IANB34rAACkAADcAfCADQeeKwAAoAAA2AIQBIAMpA1ggAykDYIRCAYOnDS4MLwsgByADKAIASQ0vQQYhAiADQQY6ACYgA0ECOgAkIANBFDoA9AJBACEHIANBADoAgAEgA0G7isAAKQAANwBsIANBw4rAACkAADcAdCADQcuKwAAoAAA2AHwgAykDWCADKQNghEIBg6cNLQwuCyAHRQ0DIAdBAWsgCk8NAwJAIAdBBE8EQCAHIQEgBCECQYCChAggBCgAACIFQY2atOgAc2sgBXJBgIGChHhxQYCBgoR4RgRAIARBBCAEQQNxIgVrIgZqIQIgAUEJTwRAIAEgBGohBQJAIAYgAUEIa0sNACAFQQhrIQEDQEGAgoQIIAIoAgAiBkGNmrToAHNrIAZyQYCBgoR4cUGAgYKEeEcNAUGAgoQIIAJBBGooAgAiBkGNmrToAHNrIAZyQYCBgoR4cUGAgYKEeEcNASACQQhqIgIgAU0NAAsLIAIgBU8NBwNAIAItAABBDUYNBCAFIAJBAWoiAkcNAAsMBwsgBiAHTw0GIAUgB2pBBGshAQNAIAItAABBDUYNAyACQQFqIQIgAUEBayIBDQALDAYLA0AgAi0AAEENRg0CIAJBAWohAiABQQFrIgENAAsMBQsgBCECIAQtAABBDUYNACAHQQFGDQQgBC0AAUENRgRAIARBAWohAgwBCyAHQQJGDQQgBC0AAkENRw0EIARBAmohAgsgAiAEayIOQQFqIgEgB0YNLiABIApPDSggASAEaiIBLQAAQQpHDQFBACEFIAIgBEcNAgtBAiECDAYLQQYhAiADQQY6ACYgA0ECOgAkIANBDToA9AJBACEHIANBADoAeSADQa6KwAApAAA3AGwgA0GzisAAKQAANwBxIAMpA1ggAykDYIRCAYOnDSoMKwsCQAJAAkACfwJAIA5BDk8EQCASQgA3AwAgA0EAOgAVIBJCADcDCCASQgA3AxAgEkIANwMYIBJCADcDICASQQA2AiggC0EgOgB0IAtBEGogC0H0AGogBCABEBwCQCALKAIQQQFxBEAgCygCFCIBIARHDQELQQYhAiADQQY6ACYgA0ECOgAkIANBGzoA9AJBACEHIANBADoAhwEgA0H9icAAKQAANwBsIANBhYrAACkAADcAdCADQY2KwAApAAA3AHwgA0GUisAAKAAANgCDASADKQNYIAMpA2CEQgGDpw0wDDELAkACQCAOIAEgBGsiBk0NACALQSA6AHQgC0EIaiALQfQAaiAEIAZBAWoiCGoiASABIA4gBmtqEBwgCygCCEEBcUUNACALKAIMIgIgAUcNAQtBBiECIANBBjoAJiADQQI6ACQgA0EYOgD0AkEAIQcgA0EAOgCEASADQeWJwAApAAA3AGwgA0HticAAKQAANwB0IANB9YnAACkAADcAfCADKQNYIAMpA2CEQgGDpw0wDDELAkACQCAOIAIgAWsiCSAIaiINTQ0AIAtBLzoAdCALIAtB9ABqIAQgDUEBaiIQaiIMIAwgDiANa2oQHCALKAIAQQFxRQ0AIAsoAgQiEyAMRw0BC0EGIQIgA0EGOgAmIANBAjoAJCADQSI6APQCQQAhByADQQA6AI4BIANBw4nAACkAADcAbCADQcuJwAApAAA3AHQgA0HTicAAKQAANwB8IANB24nAACkAADcAhAEgA0HjicAALwAAOwCMASADKQNYIAMpA2CEQgGDpw0wDDELIAYgCksNKwJAAkACQAJAAkACQAJAIAZBA2sOBQABAgMEBgsCQCAELQAAQccAaw4KBQYGBgYGBgYGAAYLAkACQCAELQABQdIAaw4EAQcHAAcLIAQtAAJB1ABHDQZBBCECDAgLIAQtAAJByQBHDQVBCiECQQEMCAsCQAJAIAQtAABByABrDgkABgYGBgYGBgEGCyAELQABQcUARw0FIAQtAAJBwQBHDQUgBC0AA0HEAEcNBUECIQIMBwsgBC0AAUHPAEcNBCAELQACQdMARw0EIAQtAANB1ABHDQRBAyECDAYLAkACQCAELQAAQdAAaw4FAAUFBQEFCyAELQABQcEARw0EIAQtAAJB1ABHDQQgBC0AA0HDAEcNBCAELQAEQcgARw0EQQkhAgwGCyAELQABQdIARw0DIAQtAAJBwQBHDQMgBC0AA0HDAEcNAyAELQAEQcUARw0DQQghAgwFCyAELQAAQcQARw0CIAQtAAFBxQBHDQIgBC0AAkHMAEcNAiAELQADQcUARw0CIAQtAARB1ABHDQIgBC0ABUHFAEcNAkEFIQIMBAsCQAJAIAQtAABBwwBrDg0AAwMDAwMDAwMDAwMBAwsgBC0AAUHPAEcNAiAELQACQc4ARw0CIAQtAANBzgBHDQIgBC0ABEHFAEcNAiAELQAFQcMARw0CIAQtAAZB1ABHDQIgA0EBOgAVQQYhAgwECyAELQABQdAARw0BIAQtAAJB1ABHDQEgBC0AA0HJAEcNASAELQAEQc8ARw0BIAQtAAVBzgBHDQEgBC0ABkHTAEcNAUEHIQIMAwsgBC0AAUHFAEYNBAsgA0EAOgBMIAYhASAEIQIMBAtBBiECIANBBjoAJiADQQI6ACQgA0EWOgD0AkEAIQcgA0EAOgCCASADQZiKwAApAAA3AGwgA0GgisAAKQAANwB0IANBporAACkAADcAeiADKQNYIAMpA2CEQgGDpw0uDC8LQQALIQ8gAyACOgBMDAILIAMgBC0AAkHUAEYiDzoATCAGIQEgBCECIA9FDQBBACEPDAELAkADQCACLQAALQCAgEBFDQEgAkEBaiECIAFBAWsiAQ0AC0EAIQ8MAQtBBiECIANBBjoAJiADQQI6ACQgA0EYOgD0AkEAIQcgA0EAOgCEASADQbqIwAApAAA3AGwgA0HCiMAAKQAANwB0IANByojAACkAADcAfCADKQNYIAMpA2CEQgGDpw0qDCsLIBMgDGsiEyAQaiEVIAkhASAIIQICQANAIAIgCk8NJyACIARqLQAALQCAhkAEQCACQQFqIQIgAUEBayIBRQ0CDAELC0EGIQIgA0EGOgAmIANBAjoAJCADQRU6APQCQQAhByADQQA6AIEBIANB0ojAACkAADcAbCADQdqIwAApAAA3AHQgA0HfiMAAKQAANwB5IAMpA1ggAykDYIRCAYOnDSoMKwsCQCANQQlqIA5GBEACQAJAIA4gEGtBCEcNACAMKQAAIixCyKjRgvXFjJcwUQ0BICxCyKjRgvWljJcxUg0AIA9FDQNBESECIANBEToAJiADQQI6ACQgA0EfOgD0AkEAIQcgA0EAOgCLASADQeeIwAApAAA3AGwgA0HviMAAKQAANwB0IANB94jAACkAADcAfCADQf6IwAApAAA3AIMBIAMpA1ggAykDYIRCAYOnDS0MLgtBBiECIANBBjoAJiADQQI6ACQgA0EQOgD0AkEAIQcgA0EAOgB8IANBnonAACkAADcAbCADQaaJwAApAAA3AHQgAykDWCADKQNghEIBg6cNLAwtCyAPDQFBESECIANBEToAJiADQQI6ACQgA0EYOgD0AkEAIQcgA0EAOgCEASADQYaJwAApAAA3AGwgA0GOicAAKQAANwB0IANBlonAACkAADcAfCADKQNYIAMpA2CEQgGDpw0rDCwLQQYhAiADQQY6ACYgA0ECOgAkIANBFToA9AJBACEHIANBADoAgQEgA0GuicAAKQAANwBsIANBtonAACkAADcAdCADQbuJwAApAAA3AHkgAykDWCADKQNghEIBg6cNKgwrCwJAICJFBEAgACEBDAELAkAgPlAEQCAAIQIMAQsgAEEJaiICQYCABE8NLSADKAIgIQEgAygC+AIgAGpBCDoAACADKAL4AiAAakEBaiABNgAAIAMoAvgCIABqQQVqIAY2AAALAkAgPVAEQCACIQAMAQsgAkEJaiIAQYCABE8EQCACIQAMLgsgAygCICEBIAMoAvgCIAJqQQk6AAAgAygC+AIgAmpBAWogASAIajYAACADKAL4AiACakEFaiAJNgAACwJAIDlQBEAgACECDAELIABBCWoiAkGAgARPDS0gAygCICEBIAMoAvgCIABqQQo6AAAgAygC+AIgAGpBAWogASAQajYAACADKAL4AiAAakEFaiATNgAACyA4UARAIAIhAQwBCyACQQlqIgFB//8DSwRAIAIhAAwtCyADKAIgIQAgAygC+AIgAmpBCzoAACADKAL4AiACakEBaiAAIBVBAWpqNgAAIAMoAvgCIAJqQQVqQQM2AAALIA5BAmohAiADLQAkIQAgAy0ATEEKRgRAIABBAkYNIyADQQU6ACQMIwsgAEECRg0iIANBBjoAJAwiCyAHIAMoAgBJDSpBBiECIANBBjoAJiADQQI6ACQgA0EVOgD0AkEAIQcgA0EAOgCBASADQaWIwAApAAA3AGwgA0GtiMAAKQAANwB0IANBsojAACkAADcAeSADKQNYIAMpA2CEQgGDpw0oDCkLAkACQAJAAkACQAJAAkAgAy0AECIBRQRAIAMtABFBAXENAQsgAQ0CIBwNASAAIQEMBgsgHUUEQCAAIQEMBQsgNlAEQCAAIQIMBAsgAEEJaiICQYCABE8NLyADKAIgIQEgAygC+AIgAGpBBToAACADKAL4AiAAakEBaiABNgAAIAMoAvgCIABqQQVqQQA2AAAMAwsgN1AEQCAAIQIMAgsgAEEJaiICQYCABE8NLiADKAIgIQEgAygC+AIgAGpBBjoAACADKAL4AiAAakEBaiABNgAAIAMoAvgCIABqQQVqQQA2AAAMAQsCQAJAIApBBE0EQCAKQQFNDQIMAQsgBC0ABEEvRw0AIAQoAABByKjRggVHDQAgA0EAOgARAkAgHEUEQCAAIQEMAQsCQCA3UARAIAAhAgwBCyAAQQlqIgJBgIAETw0xIAMoAiAhASADKAL4AiAAakEGOgAAIAMoAvgCIABqQQFqIAE2AAAgAygC+AIgAGpBBWpBADYAAAsgMlAEQCACIQEMAQsgAkEJaiIBQf//A0sEQCACIQAMMQsgAygCICEAIAMoAvgCIAJqQQM6AAAgAygC+AIgAmpBAWogADYAACADKAL4AiACakEFakEANgAAC0EAIQUgAy0AJEECRg0nIANBBDoAJAwnCyAELwAAQY0URw0AQQAhBUECIQIMBwsgA0EBOgARAkAgHUUEQCAAIQEMAQsCQCA2UARAIAAhAgwBCyAAQQlqIgJBgIAETw0vIAMoAiAhASADKAL4AiAAakEFOgAAIAMoAvgCIABqQQFqIAE2AAAgAygC+AIgAGpBBWpBADYAAAsgMlAEQCACIQEMAQsgAkEJaiIBQf//A0sEQCACIQAMLwsgAygCICEAIAMoAvgCIAJqQQM6AAAgAygC+AIgAmpBAWogADYAACADKAL4AiACakEFakEANgAAC0EAIQUgAy0AJEECRg0lIANBAzoAJAwlCyAyUARAIAIhAQwDCyACQQlqIgFB//8DSwRAIAIhAAwtCyADKAIgIQAgAygC+AIgAmpBAzoAACADKAL4AiACakEBaiAANgAAIAMoAvgCIAJqQQVqQQA2AAAMAgsgMlAEQCACIQEMAQsgAkEJaiIBQf//A0sEQCACIQAMLAsgAygCICEAIAMoAvgCIAJqQQM6AAAgAygC+AIgAmpBAWogADYAACADKAL4AiACakEFakEANgAAC0EAIQUgAy0AJEECRg0iIANBAzoAJAwiC0EAIQUgAy0AJEECRg0hIANBBDoAJAwhC0EGIQIgA0EGOgAmIANBAjoAJCADQQ86APQCQQAhByADQQA6AHsgA0GWiMAAKQAANwBsIANBnYjAACkAADcAcyADKQNYIAMpA2CEQgGDpw0mDCcLIAdFDRdBACECQX8hBQNAAkACQAJAAkACQAJAAkACQAJAIAIgBGoiCS0AACIBQQ1GBEAgB0EBayACRg0yIAJBAWogCk8NLCAJQQFqIgEtAABBCkcNAQJAAkACQAJAIAJFBEAgI0UNASAAIQEMAgsgC0E6OgB0IAtBQGsgC0H0AGogBCABEBwgCygCQEEBcQRAIAsoAkQiASAERw0EC0EGIQIgA0EGOgAmIANBAjoAJCADQSM6APQCQQAhByADQQA6AI8BIANB/pHAACkAADcAbCADQYaSwAApAAA3AHQgA0GOksAAKQAANwB8IANBlpLAACkAADcAhAEgA0GdksAAKAAANgCLASADKQNYIAMpA2CEQgGDpw00DDULIABBE2oiAUGAgARPBEBBASEFQQIhAgwPCyADKQMoISwgAy0ATSECIAMtAE8hBSADLQBTIQYgAy0AUiEIIAMtAFEhCSADLQBQIQ4gAy8BSCEMIAMtAEwhDSADLQARIQ8gAygCICEQIAMoAvgCIABqQRA6AAAgAygC+AIgAGpBAWogEEECajYAACADKAL4AiAAakEFaiANIAwgDxs7AAAgAygC+AIgAGpBB2ogDkEBczoAACADKAL4AiAAakEIaiAIIAlxOgAAIAMoAvgCIABqQQlqIAY6AAAgAygC+AIgAGpBCmpBAEECIAVrIAIbOgAAIAMoAvgCIABqQQtqICxCACACGzcAACADLQAkQQJGDQELIANBBzoAJAsgA0EBOgAUIAMtABIhBUECIQIMKgsgASAEayIOQQFqIQgCQAJAAkAgBC0AACIBQcMAaw4zAQAAAAAAAAAAAAAAAAAAAAABAQAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAEBAAtBACEBA0AgASAKRg0vIAEgBGotAAAtAICAQARAIA4gAUEBaiIBRg0DDAELC0EGIQIgA0EGOgAmIANBAjoAJCADQSM6APQCQQAhByADQQA6AI8BIANB/pHAACkAADcAbCADQYaSwAApAAA3AHQgA0GOksAAKQAANwB8IANBlpLAACkAADcAhAEgA0GdksAAKAAANgCLASADKQNYIAMpA2CEQgGDpw0yDDMLIAogDkkNLSADKAJIIQwCQAJAAkACQCAOQQdrDgsDHx8CHx8fAB8fAR8LIA4hBiAEIAFBIHJB4wBHDR8aIAQgBC0AAUEgckHvAEcNHxogBCAELQACQSByQe4ARw0fGiAEIAQtAANBIHJB9ABHDR8aIAQgBC0ABEEgckHlAEcNHxogBCAELQAFQSByQe4ARw0fGiAEIAQtAAZBIHJB9ABHDR8aIAQgBC0AB0EtRw0fGiAEIAQtAAhBIHJB7ABHDR8aIAQgBC0ACUEgckHlAEcNHxogBCAELQAKQSByQe4ARw0fGiAEIAQtAAtBIHJB5wBHDR8aIAQgBC0ADEEgckH0AEcNHxogBCAELQANQSByQegARw0fGiADLQBODQYgDEF+cUHMAUcgDEHkAGtB5ABPcUUEQEEHIQIgA0EHOgAmIANBAjoAJEEAIQcgA0GVjMAAKQAANwBsIANBnYzAACkAADcAdCADQaWMwAApAAA3AHwgA0GtjMAAKQAANwCEASADQbWMwAApAAA3AIwBIANBvYzAACkAADcAlAEgA0HFjMAAKQAANwCcASADQc2MwAAoAAA2AKQBIANBPDoA9AIgA0EAOgCoASADKQNYIAMpA2CEQgGDpw01DDYLIAMtAE0NB0EPIQYgAiAITQ0cIAQgCGotAAAhAQJAIAlBAWstAAAiBkEJRiIJRQRAIAZBIEYiDEUNAQsCQCABQSBHDQAgCQ0AIAZBIEYNAEEQIQYgAiEJDB8LQQ8hBgNAIAQgBmotAAAiAUEJRyABQSBHcQ0eIAIgBkEBaiIGRw0ACyACIQYMHQtBECAIIAFBIEYbIgYgAk8NGyAEIAZqLQAAIghBCUYNGyACIQkgCEEgRg0bDB0LIA4hBiAEIAFBIHJB9ABHDR4aIAQgBC0AAUEgckHyAEcNHhogBCAELQACQSByQeEARw0eGiAEIAQtAANBIHJB7gBHDR4aIAQgBC0ABEEgckHzAEcNHhogBCAELQAFQSByQeYARw0eGiAEIAQtAAZBIHJB5QBHDR4aIAQgBC0AB0EgckHyAEcNHhogBCAELQAIQS1HDR4aIAQgBC0ACUEgckHlAEcNHhogBCAELQAKQSByQe4ARw0eGiAEIAQtAAtBIHJB4wBHDR4aIAQgBC0ADEEgckHvAEcNHhogBCAELQANQSByQeQARw0eGiAEIAQtAA5BIHJB6QBHDR4aIAQgBC0AD0EgckHuAEcNHhogBCAELQAQQSByQecARw0eGiADLQBNDQcgDEHMAWtBAkkNGSAMQbACRg0ZIAxB5ABrQeQASQ0ZQRIhBiACIAhNDRcCQCAEIAhqLQAAQSBHDQAgCUEBay0AACIBQQlGDQAgAUEgRg0AQRMhBiACIQkMGQsDQCAEIAZqLQAAIgFBCUcgAUEgR3ENGCACIAZBAWoiBkcNAAsgAiEGDBcLIA4hBiAEIAFBIHJB4wBHDR0aIAQgBC0AAUEgckHvAEcNHRogBCAELQACQSByQe4ARw0dGiAEIAQtAANBIHJB7gBHDR0aIAQgBC0ABEEgckHlAEcNHRogBCAELQAFQSByQeMARw0dGiAEIAQtAAZBIHJB9ABHDR0aIAQgBC0AB0EgckHpAEcNHRogBCAELQAIQSByQe8ARw0dGiAEIAQtAAlBIHJB7gBHDR0aQQshBiACIAhNDRQCQCAEIAhqLQAAQSBHDQAgCUEBay0AACIBQQlGDQAgAUEgRg0AQQwhBiACIQkMFgsDQCAEIAZqLQAAIgFBCUcgAUEgR3ENFSACIAZBAWoiBkcNAAsgAiEGDBQLAkACQCABQdQAaw4iAAEdHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0AAR0LAkAgBC0AAUEgckHyAEcNACAELQACQSByQeEARw0AIAQtAANBIHJB6QBHDQAgBC0ABEEgckHsAEcNACAELQAFQSByQeUARw0AIAQtAAZBIHJB8gBHDQAgA0EBOgBTQQghBiACIAhNDRQCQCAEIAhqLQAAQSBHDQAgCUEBay0AACIBQQlGDQAgAUEgRg0AQQkhBiACIQkMJQsDQCAEIAZqLQAAIgFBCUcgAUEgR3ENFSACIAZBAWoiBkcNAAsgAiEGDBQLIA4hBiAEIAFB1QBHDR0aCyAOIQYgBCAELQABQSByQfAARw0cGiAEIAQtAAJBIHJB5wBHDRwaIAQgBC0AA0EgckHyAEcNHBogBCAELQAEQSByQeEARw0cGiAEIAQtAAVBIHJB5ABHDRwaIAQgBC0ABkEgckHlAEcNHBpBCCEGIAIgCE0NEAJAIAQgCGotAABBIEcNACAJQQFrLQAAIgFBCUYNACABQSBGDQBBCSEGIAIhCQwSCwNAIAQgBmotAAAiAUEJRyABQSBHcQ0RIAIgBkEBaiIGRw0ACyACIQYMEAsgGEUNHyACIAhNDQ0gBCAIai0AAEEgRw0MIAlBAWstAAAiAUEgRg0MIAFBCUcNHAwMCwJAIAFBIE8EQCABQf8ARg0BDAoLIAFBCUYNCQsgAiAKTw0HIAJBAk0EQCACQQFqIQFBACEHA0AgBCAHai0AAEE6Rg0IIAEgB0EBaiIHRw0ACwwIC0GAgoQIIAQoAAAiAUG69OjRA3NrIAFyQYCBgoR4cUGAgYKEeEcEQCACQQFqIQFBACEHA0AgBCAHai0AAEE6Rg0IIAEgB0EBaiIHRw0ACwwIC0EEIARBA3EiBWshASACQQhJDQQgCUEBaiEFIAEgBGohByABIAJBB2siAksNBSACIARqIQEDQEGAgoQIIAcoAgAiAkG69OjRA3NrIAJyQYCBgoR4cUGAgYKEeEcNBkGAgoQIIAdBBGooAgAiAkG69OjRA3NrIAJyQYCBgoR4cUGAgYKEeEcNBiAHQQhqIgcgAU0NAAsMBQtBBiECIANBBjoAJiADQQI6ACQgA0ENOgD0AkEAIQcgA0EAOgB5IANBrorAACkAADcAbCADQbOKwAApAAA3AHEgAykDWCADKQNghEIBg6cNLgwvC0EHIQIgA0EHOgAmIANBAjoAJCADQewAakG5jcAAQckA/AoAACADQckAOgD0AkEAIQcgA0EAOgC1ASADKQNYIAMpA2CEQgGDpw0tDC4LQQ0hAiADQQ06ACYgA0ECOgAkIANBJzoA9AJBACEHIANBADoAkwEgA0GSjcAAKQAANwBsIANBmo3AACkAADcAdCADQaKNwAApAAA3AHwgA0GqjcAAKQAANwCEASADQbGNwAApAAA3AIsBIAMpA1ggAykDYIRCAYOnDSwMLQtBCCECIANBCDoAJiADQQI6ACQgA0HsAGpBoJDAAEHJAPwKAAAgA0HJADoA9AJBACEHIANBADoAtQEgAykDWCADKQNghEIBg6cNKwwsCyABIAJLDQIgBEEEaiEBIAJBA2shAkEAIAVrIQcDQCABIAdqLQAAQTpGDQIgB0EBaiIHIAJHDQALDAILIAUgB00NASAHQQFrIQcDQCAHQQFqIgctAABBOkYNASAHIAlHDQALDAELQQYhAiADQQY6ACYgA0ECOgAkIANBJDoA9AJBACEHIANBADoAkAEgA0GhksAAKQAANwBsIANBqZLAACkAADcAdCADQbGSwAApAAA3AHwgA0G5ksAAKQAANwCEASADQcGSwAAoAAA2AIwBIAMpA1ggAykDYIRCAYOnDSgMKQtBBiECIANBBjoAJiADQQI6ACQgA0EjOgD0AkEAIQcgA0EAOgCPASADQf6RwAApAAA3AGwgA0GGksAAKQAANwB0IANBjpLAACkAADcAfCADQZaSwAApAAA3AIQBIANBnZLAACgAADYAiwEgAykDWCADKQNghEIBg6cNJwwoCyAFQQFqIQUgByACQQFqIgJHDQALDBcLIAAhAQwdCwNAIAQgCGotAAAiAUEJRyABQSBHcQ0BIAIgCEEBaiIIRw0ACyACDAELIAgLIQYgAiAGTQRAIAIhCQwTCwNAIAUgCk8NHgJAIAQgBWotAAAiAUEJRg0AIAFBIEYNACAFQQFqIQkMFAsgBSAGSyAFQQFrIQUNAAsgBiEJDBILIAYCfyACIAIgBk0NABoCQANAIAUgCk8NHyAEIAVqLQAAIgFBCUcgAUEgR3ENASAFIAZLIAVBAWshBQ0ACyAGDAELIAVBAWoLIglHDQBBBiECIANBBjoAJiADQQI6ACQgA0EdOgD0AkEAIQcgA0EAOgCJASADQcWRwAApAAA3AGwgA0HNkcAAKQAANwB0IANB1ZHAACkAADcAfCADQdqRwAApAAA3AIEBIAMpA1ggAykDYIRCAYOnDSAMIQsgBEEBayEQIAQgCWpBAWohEyAGIQEDQAJAIAEgCU8NACABIApPDR0gASAEai0AACIFQQlGBEAgAUEBaiEBDAILIAVBIEcNACABQQFqIQEMAQsCQCABIAlGDQACQAJAAn8gCSAJIApPDQAaIAkgASAJSw0AGiALQSw6AHQgC0E4aiALQfQAaiABIARqIgwgExAcIAsoAjhBAXEiCAR/IAsoAjwgDGsFIAULIAFqIAkgCBsLIg0gAU0NACABIApPDR8CQCABIARqLQAAQSBHDQAgDUEBayIFIApPDSAgBCAFai0AACIFQQlGDQAgBUEgRg0AIAFBAWohASANIQUMAgsgASAKIAEgCksbIQgDQCABIAhGDSAgASAEai0AACIFQQlHIAVBIEdxDQEgDSABQQFqIgFHDQALIA0hAQsCQCANIgUgAU0NAANAIAVBAWsiCCAKTw0gIAUgEGotAAAiDEEJRyAMQSBHcQ0BIAgiBSABSw0ACyABIQULIAEgBUcNAEEGIQIgA0EGOgAmIANBAjoAJCADQR06APQCQQAhByADQQA6AIkBIANBxZHAACkAADcAbCADQc2RwAApAAA3AHQgA0HVkcAAKQAANwB8IANB2pHAACkAADcAgQEgAykDWCADKQNghEIBg6cNIgwjCwJAAkACfyAFIAUgCk8iFQ0AGiAFIAEgBUsNABogC0EvOgB0IAtBMGogC0H0AGogASAEaiIMIAQgBWpBAWoQHCALKAIwQQFxIg8EQCALKAI0IAxrIQgLIAEgCGogBSAPGwsiDyABRg0AIAEgD08NASAKIAFrIghBACAIIApNGyEIIA8gAWshDCABIARqIQEDQCAIRQ0gIAEtAAAtAICAQEUNASAIQQFrIQggAUEBaiEBIAxBAWsiDA0ACwwBC0EGIQIgA0EGOgAmIANBAjoAJCADQRw6APQCQQAhByADQQA6AIgBIANB4pHAACkAADcAbCADQeqRwAApAAA3AHQgA0HykcAAKQAANwB8IANB+pHAACgAADYAhAEgAykDWCADKQNghEIBg6cNIgwjCwJAIAUgD00NACAPQQFqIQECQCAVRQRAIAtBLzoAdCALQShqIAtB9ABqIAEgBGoiCCAIIAUgD2tqEBwgCygCKEEBcQ0BCyABIAVGDQAgASAFTw0BA0AgASAKTw0gIAEgBGotAAAtAICAQEUNASABQQFqIgEg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KQAANwCLASADKQNYIAMpA2CEQgGDpw0dDB4LIANBAToATiAFIApLDRggASAFSw0YAkACQCAFIAFrQQdHDQAgASAEaiIBLQAAQSByQeMARw0AIAEtAAFBIHJB6ABHDQAgAS0AAkEgckH1AEcNACABLQADQSByQe4ARw0AIAEtAARBIHJB6wBHDQAgAS0ABUEgckHlAEcNACABLQAGQSByQeQARw0AIA9BAXFFBEBBASEPIANBAToATwwCC0EOIQIgA0EOOgAmIANBAjoAJCADQewAakHojsAAQesA/AoAACADQesAOgD0AkEAIQcgA0EAOgDXASADKQNYIAMpA2CEQgGDpw0eDB8LIA9BAXFBACEPRQ0AQQ4hAiADQQ46ACYgA0ECOgAkIANB7ABqQdOPwABBzQD8CgAAIANBzQA6APQCQQAhByADQQA6ALkBIAMpA1ggAykDYIRCAYOnDR0MHgsgCCAJRg0NIAhBAWohAQwACwALIAMtAE9FBEAgA0EBOgBPDAwLQQ4hAiADQQ46ACYgA0ECOgAkIANB7ABqQeiOwABB6wD8CgAAIANB6wA6APQCQQAhByADQQA6ANcBIAMpA1ggAykDYIRCAYOnDRoMGwtBCCECIANBCDoAJiADQQI6ACRBACEHIANBgo7AACkAADcAbCADQYqOwAApAAA3AHQgA0GSjsAAKQAANwB8IANBmo7AACkAADcAhAEgA0GijsAAKQAANwCMASADQaqOwAApAAA3AJQBIANBso7AACkAADcAnAEgA0G5jsAAKQAANwCjASADQT86APQCIANBADoAqwEgAykDWCADKQNghEIBg6cNGQwaCyAMRQRAQRAhBiACIQkgAUEgRg0CC0EPIQYCQANAIAQgBmotAAAiAUEJRyABQSBHcQ0BIAIgBkEBaiIGRw0ACyACIQYLIAYCfyACIAIgBk0NABoCQANAIAUgCk8NFyAEIAVqLQAAIgFBCUcgAUEgR3ENASAFIAZLIAVBAWshBQ0ACyAGDAELIAVBAWoLIglHDQFBBiECIANBBjoAJiADQQI6ACQgA0EkOgD0AkEAIQcgA0EAOgCQASADQdGMwAApAAA3AGwgA0HZjMAAKQAANwB0IANB4YzAACkAADcAfCADQemMwAApAAA3AIQBIANB8YzAACgAADYAjAEgAykDWCADKQNghEIBg6cN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AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAEGhhsAAC14BAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAAEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAABAEGAiMAAC7QQVW5leHBlY3RlZCBlbmQgb2YgZGF0YVVuZXhwZWN0ZWQgZGF0YVJlcXVlc3QgbGluZSB0b28gbG9uZ0ludmFsaWQgbWV0aG9kIGNoYXJhY3RlckludmFsaWQgVVJMIGNoYXJhY3RlclBSSSBpcyBvbmx5IHZhbGlkIHdpdGggSFRUUC8yLjBVbnN1cHBvcnRlZCBIVFRQIHZlcnNpb25JbnZhbGlkIHByb3RvY29sSW52YWxpZCBwcm90b2NvbCBuYW1lRXhwZWN0ZWQgLyBhZnRlciB0aGUgcHJvdG9jb2wgbmFtZUV4cGVjdGVkIHNwYWNlIGFmdGVyIFVSTEV4cGVjdGVkIHNwYWNlIGFmdGVyIG1ldGhvZFJlcXVlc3QgbGluZSB0b28gc2hvcnRFeHBlY3RlZCBDUkxGU3RhdHVzIGxpbmUgdG9vIGxvbmdJbnZhbGlkIEhUVFAgcmVzcG9uc2Ugc3RhdHVzSW52YWxpZCBzdGF0dXMgcmVhc29uIGNoYXJhY3RlckV4cGVjdGVkIGEgc3BhY2UgYWZ0ZXIgSFRUUCByZXNwb25zZSBzdGF0dXNFeHBlY3RlZCBzcGFjZSBhZnRlciBwcm90b2NvbFN0YXR1cyBsaW5lIHRvbyBzaG9ydE1hbGZvcm1lZCBIVFRQLzIuMCBwcmVmYWNlSGVhZGVyIGxpbmUgdG9vIGxvbmdVbmV4cGVjdGVkIENvbnRlbnQtTGVuZ3RoIGhlYWRlciBmb3IgYSByZXNwb25zZSB3aXRob3V0IGJvZHlFeHBlY3RlZCBDb250ZW50LUxlbmd0aCBoZWFkZXIgdmFsdWVJbnZhbGlkIENvbnRlbnQtTGVuZ3RoIGhlYWRlckludmFsaWQgZHVwbGljYXRlIENvbnRlbnQtTGVuZ3RoIGhlYWRlclVuZXhwZWN0ZWQgQ29udGVudC1MZW5ndGggaGVhZGVyIHdoZW4gVHJhbnNmZXItRW5jb2RpbmcgaGVhZGVyIGlzIHByZXNlbnRVbmV4cGVjdGVkIFRyYW5zZmVyLUVuY29kaW5nIGhlYWRlciBmb3IgYSByZXNwb25zZSB3aXRob3V0IGJvZHlFeHBlY3RlZCBUcmFuc2Zlci1FbmNvZGluZyBoZWFkZXIgdmFsdWVUaGUgdmFsdWUgImNodW5rZWQiIGluIHRoZSBUcmFuc2Zlci1FbmNvZGluZyBoZWFkZXIgbXVzdCBiZSB0aGUgbGFzdCBwcm92aWRlZCBhbmQgY2FuIGJlIHByb3ZpZGVkIG9ubHkgb25jZVRoZSB2YWx1ZSAiY2h1bmtlZCIgaW4gdGhlIFRyYW5zZmVyLUVuY29kaW5nIGhlYWRlciBtdXN0IGJlIHRoZSBsYXN0IHByb3ZpZGVkVW5leHBlY3RlZCBUcmFuc2Zlci1FbmNvZGluZyBoZWFkZXIgd2hlbiBDb250ZW50LUxlbmd0aCBoZWFkZXIgaXMgcHJlc2VudEV4cGVjdGVkIENvbm5lY3Rpb24gaGVhZGVyIHZhbHVlSW52YWxpZCBDb25uZWN0aW9uIGhlYWRlciB2YWx1ZUV4cGVjdGVkIFRyYWlsZXIgaGVhZGVyIHZhbHVlRXhwZWN0ZWQgVXBncmFkZSBoZWFkZXIgdmFsdWVJbnZhbGlkIFVwZ3JhZGUgaGVhZGVyIHZhbHVlSW52YWxpZCBoZWFkZXIgZmllbGQgbmFtZSBjaGFyYWN0ZXJJbnZhbGlkIGhlYWRlciBmaWVsZCB2YWx1ZSBjaGFyYWN0ZXJNaXNzaW5nIENvbm5lY3Rpb24gaGVhZGVyIHNldCB0byAidXBncmFkZSIgd2hlbiB1c2luZyB0aGUgVXBncmFkZSBoZWFkZXJUcmFpbGVycyBhcmUgbm90IGFsbG93ZWQgd2hlbiBub3QgdXNpbmcgY2h1bmtlZCB0cmFuc2ZlciBlbmNvZGluZ1VuZXhwZWN0ZWQgY29udGVudCBmb3IgdGhlIHJlcXVlc3QgKEdFVCBvciBIRUFEKVRyYW5zZmVyLUVuY29kaW5nIGxhc3QgaGVhZGVyIHZhbHVlIG11c3QgYmUgImNodW5rZWQiIGlmIHRoZSBoZWFkZXIgaXMgcHJlc2VudENodW5rIGhlYWRlciB0b28gbG9uZ0ludmFsaWQgY2h1bmsgbGVuZ3RoIGNoYXJhY3RlckludmFsaWQgY2h1bmsgbGVuZ3RoIHNpemVFeHBlY3RlZCBjaHVuayBleHRlbnNpb24gbmFtZUludmFsaWQgY2h1bmsgZXh0ZW5zaW9uIG5hbWUgY2hhcmFjdGVyRXhwZWN0ZWQgY2xvc2luZyBxdW90ZSBmb3IgY2h1bmsgZXh0ZW5zaW9uIHZhbHVlSW52YWxpZCBjaHVuayBleHRlbnNpb24gcXVvdGVkIHZhbHVlIGNoYXJhY3RlckV4cGVjdGVkIGNodW5rIGV4dGVuc2lvbiB2YWx1ZUludmFsaWQgY2h1bmsgZXh0ZW5zaW9uIHZhbHVlIGNoYXJhY3RlckludmFsaWQgY2h1bmsgZXh0ZW5zaW9uIGNoYXJhY3RlciBhZnRlciB2YWx1ZUV4cGVjdGVkIENSTEYgYWZ0ZXIgY2h1bmsgZGF0YVRyYWlsZXIgbGluZSB0b28gbG9uZ0ludmFsaWQgdHJhaWxlciBmaWVsZCBuYW1lIGNoYXJhY3RlckludmFsaWQgdHJhaWxlciBmaWVsZCB2YWx1ZSBjaGFyYWN0ZXJJbnZhbGlkIHN0YXRl', + 'base64' + ) +) + +const textEncoder = new TextEncoder() +const textDecoder = new TextDecoder() + +function log (logger, raw) { + const len = Number(BigInt.asUintN(32, raw)) + const ptr = Number(raw >> 32n) + + logger(textDecoder.decode(new Uint8Array(this.memory.buffer, ptr, len))) +} + +function alloc (len) { + return this.alloc(len) >>> 0 +} + +function dealloc (ptr) { + return this.dealloc(ptr) +} + +function create () { + return this.create() >>> 0 +} + +function destroy (parser) { + this.destroy(parser) +} + +function parse (parser, data, limit) { + return this.parse(parser, data, limit) >>> 0 +} + +function fail (parser, code, description) { + const len = description.length + const ptr = this.alloc(len) + const buffer = new Uint8Array(this.memory.buffer, ptr, len) + textEncoder.encodeInto(description, buffer) + + this.fail(parser, code, ptr, len) + this.dealloc(ptr, len) +} + +function hasDebug () { + return this.milo_has_debug() !== 0 +} + +const Errors = Object.freeze({ + NONE: 0, + USER: 1, + CALLBACK_ERROR: 2, + UNEXPECTED_STATE: 3, + UNEXPECTED_DATA: 4, + UNEXPECTED_EOF: 5, + UNEXPECTED_CHARACTER: 6, + UNEXPECTED_CONTENT_LENGTH: 7, + UNEXPECTED_TRANSFER_ENCODING: 8, + UNEXPECTED_CONTENT: 9, + UNEXPECTED_TRAILERS: 10, + INVALID_VERSION: 11, + INVALID_STATUS: 12, + INVALID_CONTENT_LENGTH: 13, + INVALID_TRANSFER_ENCODING: 14, + INVALID_CHUNK_SIZE: 15, + MISSING_CONNECTION_UPGRADE: 16, + UNSUPPORTED_HTTP_VERSION: 17, + 0: 'NONE', + 1: 'USER', + 2: 'CALLBACK_ERROR', + 3: 'UNEXPECTED_STATE', + 4: 'UNEXPECTED_DATA', + 5: 'UNEXPECTED_EOF', + 6: 'UNEXPECTED_CHARACTER', + 7: 'UNEXPECTED_CONTENT_LENGTH', + 8: 'UNEXPECTED_TRANSFER_ENCODING', + 9: 'UNEXPECTED_CONTENT', + 10: 'UNEXPECTED_TRAILERS', + 11: 'INVALID_VERSION', + 12: 'INVALID_STATUS', + 13: 'INVALID_CONTENT_LENGTH', + 14: 'INVALID_TRANSFER_ENCODING', + 15: 'INVALID_CHUNK_SIZE', + 16: 'MISSING_CONNECTION_UPGRADE', + 17: 'UNSUPPORTED_HTTP_VERSION' +}) + +const Methods = Object.freeze({ + OTHER: 0, + GET: 1, + HEAD: 2, + POST: 3, + PUT: 4, + DELETE: 5, + CONNECT: 6, + OPTIONS: 7, + TRACE: 8, + PATCH: 9, + PRI: 10, + 0: 'OTHER', + 1: 'GET', + 2: 'HEAD', + 3: 'POST', + 4: 'PUT', + 5: 'DELETE', + 6: 'CONNECT', + 7: 'OPTIONS', + 8: 'TRACE', + 9: 'PATCH', + 10: 'PRI' +}) + +const Callbacks = Object.freeze({ + ON_ERROR: 0, + ON_FINISH: 1, + ON_MESSAGE_START: 2, + ON_MESSAGE_COMPLETE: 3, + ON_REQUEST: 4, + ON_RESPONSE: 5, + ON_RESET: 6, + ON_METHOD: 7, + ON_URL: 8, + ON_PROTOCOL: 9, + ON_VERSION: 10, + ON_STATUS: 11, + ON_REASON: 12, + ON_HEADER_NAME: 13, + ON_HEADER_VALUE: 14, + ON_HEADERS: 15, + ON_CONNECT: 16, + ON_UPGRADE: 17, + ON_CHUNK_LENGTH: 18, + ON_CHUNK_EXTENSION_NAME: 19, + ON_CHUNK_EXTENSION_VALUE: 20, + ON_CHUNK: 21, + ON_BODY: 22, + ON_DATA: 23, + ON_TRAILER_NAME: 24, + ON_TRAILER_VALUE: 25, + ON_TRAILERS: 26, + ON_STATE_CHANGE: 27, + 0: 'ON_ERROR', + 1: 'ON_FINISH', + 2: 'ON_MESSAGE_START', + 3: 'ON_MESSAGE_COMPLETE', + 4: 'ON_REQUEST', + 5: 'ON_RESPONSE', + 6: 'ON_RESET', + 7: 'ON_METHOD', + 8: 'ON_URL', + 9: 'ON_PROTOCOL', + 10: 'ON_VERSION', + 11: 'ON_STATUS', + 12: 'ON_REASON', + 13: 'ON_HEADER_NAME', + 14: 'ON_HEADER_VALUE', + 15: 'ON_HEADERS', + 16: 'ON_CONNECT', + 17: 'ON_UPGRADE', + 18: 'ON_CHUNK_LENGTH', + 19: 'ON_CHUNK_EXTENSION_NAME', + 20: 'ON_CHUNK_EXTENSION_VALUE', + 21: 'ON_CHUNK', + 22: 'ON_BODY', + 23: 'ON_DATA', + 24: 'ON_TRAILER_NAME', + 25: 'ON_TRAILER_VALUE', + 26: 'ON_TRAILERS', + 27: 'ON_STATE_CHANGE' +}) + +const CallbackActives = Object.freeze({ + NONE: 0n, + ON_ERROR: 1n, + ON_FINISH: 2n, + ON_MESSAGE_START: 4n, + ON_MESSAGE_COMPLETE: 8n, + ON_REQUEST: 16n, + ON_RESPONSE: 32n, + ON_RESET: 64n, + ON_METHOD: 128n, + ON_URL: 256n, + ON_PROTOCOL: 512n, + ON_VERSION: 1024n, + ON_STATUS: 2048n, + ON_REASON: 4096n, + ON_HEADER_NAME: 8192n, + ON_HEADER_VALUE: 16384n, + ON_HEADERS: 32768n, + ON_CONNECT: 65536n, + ON_UPGRADE: 131072n, + ON_CHUNK_LENGTH: 262144n, + ON_CHUNK_EXTENSION_NAME: 524288n, + ON_CHUNK_EXTENSION_VALUE: 1048576n, + ON_CHUNK: 2097152n, + ON_BODY: 4194304n, + ON_DATA: 8388608n, + ON_TRAILER_NAME: 16777216n, + ON_TRAILER_VALUE: 33554432n, + ON_TRAILERS: 67108864n, + ON_STATE_CHANGE: 134217728n, + ALL: 268435455n, + 0n: 'NONE', + 1n: 'ON_ERROR', + 2n: 'ON_FINISH', + 4n: 'ON_MESSAGE_START', + 8n: 'ON_MESSAGE_COMPLETE', + 16n: 'ON_REQUEST', + 32n: 'ON_RESPONSE', + 64n: 'ON_RESET', + 128n: 'ON_METHOD', + 256n: 'ON_URL', + 512n: 'ON_PROTOCOL', + 1024n: 'ON_VERSION', + 2048n: 'ON_STATUS', + 4096n: 'ON_REASON', + 8192n: 'ON_HEADER_NAME', + 16384n: 'ON_HEADER_VALUE', + 32768n: 'ON_HEADERS', + 65536n: 'ON_CONNECT', + 131072n: 'ON_UPGRADE', + 262144n: 'ON_CHUNK_LENGTH', + 524288n: 'ON_CHUNK_EXTENSION_NAME', + 1048576n: 'ON_CHUNK_EXTENSION_VALUE', + 2097152n: 'ON_CHUNK', + 4194304n: 'ON_BODY', + 8388608n: 'ON_DATA', + 16777216n: 'ON_TRAILER_NAME', + 33554432n: 'ON_TRAILER_VALUE', + 67108864n: 'ON_TRAILERS', + 134217728n: 'ON_STATE_CHANGE', + 268435455n: 'ALL' +}) + +const Events = Object.freeze({ + END: 0, + ERROR: 1, + FINISH: 2, + MESSAGE_START: 3, + MESSAGE_COMPLETE: 4, + REQUEST: 5, + RESPONSE: 6, + RESET: 7, + METHOD: 8, + URL: 9, + PROTOCOL: 10, + VERSION: 11, + STATUS: 12, + REASON: 13, + HEADER_NAME: 14, + HEADER_VALUE: 15, + HEADERS: 16, + CONNECT: 17, + UPGRADE: 18, + CHUNK_LENGTH: 19, + CHUNK_EXTENSION_NAME: 20, + CHUNK_EXTENSION_VALUE: 21, + CHUNK: 22, + BODY: 23, + DATA: 24, + TRAILER_NAME: 25, + TRAILER_VALUE: 26, + TRAILERS: 27, + STATE_CHANGE: 28, + 0: 'END', + 1: 'ERROR', + 2: 'FINISH', + 3: 'MESSAGE_START', + 4: 'MESSAGE_COMPLETE', + 5: 'REQUEST', + 6: 'RESPONSE', + 7: 'RESET', + 8: 'METHOD', + 9: 'URL', + 10: 'PROTOCOL', + 11: 'VERSION', + 12: 'STATUS', + 13: 'REASON', + 14: 'HEADER_NAME', + 15: 'HEADER_VALUE', + 16: 'HEADERS', + 17: 'CONNECT', + 18: 'UPGRADE', + 19: 'CHUNK_LENGTH', + 20: 'CHUNK_EXTENSION_NAME', + 21: 'CHUNK_EXTENSION_VALUE', + 22: 'CHUNK', + 23: 'BODY', + 24: 'DATA', + 25: 'TRAILER_NAME', + 26: 'TRAILER_VALUE', + 27: 'TRAILERS', + 28: 'STATE_CHANGE' +}) + +const EventActives = Object.freeze({ + NONE: 0n, + ON_ERROR: 1n, + ON_FINISH: 2n, + ON_MESSAGE_START: 4n, + ON_MESSAGE_COMPLETE: 8n, + ON_REQUEST: 16n, + ON_RESPONSE: 32n, + ON_RESET: 64n, + ON_METHOD: 128n, + ON_URL: 256n, + ON_PROTOCOL: 512n, + ON_VERSION: 1024n, + ON_STATUS: 2048n, + ON_REASON: 4096n, + ON_HEADER_NAME: 8192n, + ON_HEADER_VALUE: 16384n, + ON_HEADERS: 32768n, + ON_CONNECT: 65536n, + ON_UPGRADE: 131072n, + ON_CHUNK_LENGTH: 262144n, + ON_CHUNK_EXTENSION_NAME: 524288n, + ON_CHUNK_EXTENSION_VALUE: 1048576n, + ON_CHUNK: 2097152n, + ON_BODY: 4194304n, + ON_DATA: 8388608n, + ON_TRAILER_NAME: 16777216n, + ON_TRAILER_VALUE: 33554432n, + ON_TRAILERS: 67108864n, + ON_STATE_CHANGE: 134217728n, + ALL: 268435455n, + 0n: 'NONE', + 1n: 'ON_ERROR', + 2n: 'ON_FINISH', + 4n: 'ON_MESSAGE_START', + 8n: 'ON_MESSAGE_COMPLETE', + 16n: 'ON_REQUEST', + 32n: 'ON_RESPONSE', + 64n: 'ON_RESET', + 128n: 'ON_METHOD', + 256n: 'ON_URL', + 512n: 'ON_PROTOCOL', + 1024n: 'ON_VERSION', + 2048n: 'ON_STATUS', + 4096n: 'ON_REASON', + 8192n: 'ON_HEADER_NAME', + 16384n: 'ON_HEADER_VALUE', + 32768n: 'ON_HEADERS', + 65536n: 'ON_CONNECT', + 131072n: 'ON_UPGRADE', + 262144n: 'ON_CHUNK_LENGTH', + 524288n: 'ON_CHUNK_EXTENSION_NAME', + 1048576n: 'ON_CHUNK_EXTENSION_VALUE', + 2097152n: 'ON_CHUNK', + 4194304n: 'ON_BODY', + 8388608n: 'ON_DATA', + 16777216n: 'ON_TRAILER_NAME', + 33554432n: 'ON_TRAILER_VALUE', + 67108864n: 'ON_TRAILERS', + 134217728n: 'ON_STATE_CHANGE', + 268435455n: 'ALL' +}) + +const States = Object.freeze({ + START: 0, + FINISH: 1, + ERROR: 2, + REQUEST_LINE: 3, + STATUS_LINE: 4, + HTTP2_PREFACE: 5, + HEADER: 6, + BODY_DECISION: 7, + BODY_VIA_CONTENT_LENGTH: 8, + BODY_WITH_NO_LENGTH: 9, + CHUNK_HEADER: 10, + CHUNK_EXTENSIONS: 11, + CHUNK_DATA: 12, + TRAILER: 13, + TUNNEL: 14, + 0: 'START', + 1: 'FINISH', + 2: 'ERROR', + 3: 'REQUEST_LINE', + 4: 'STATUS_LINE', + 5: 'HTTP2_PREFACE', + 6: 'HEADER', + 7: 'BODY_DECISION', + 8: 'BODY_VIA_CONTENT_LENGTH', + 9: 'BODY_WITH_NO_LENGTH', + 10: 'CHUNK_HEADER', + 11: 'CHUNK_EXTENSIONS', + 12: 'CHUNK_DATA', + 13: 'TRAILER', + 14: 'TUNNEL' +}) + +const ParserFields = Object.freeze({ + MAX_START_LINE_LENGTH: 0, + MAX_HEADER_LENGTH: 4, + MAX_BODY_PAYLOAD: 8, + AUTODETECT: 16, + IS_REQUEST: 17, + SUSPEND_AFTER_HEADERS: 18, + MANAGE_UNCONSUMED: 19, + CONTINUE_WITHOUT_DATA: 20, + IS_CONNECT: 21, + SKIP_BODY: 22, + DEBUG: 23, + PARSED: 24, + POSITION: 32, + STATE: 36, + PAUSED: 37, + ERROR_CODE: 38, + CONTENT_LENGTH: 40, + CHUNK_SIZE: 48, + REMAINING_CONTENT_LENGTH: 56, + REMAINING_CHUNK_SIZE: 64, + STATUS: 72, + METHOD: 76, + HAS_CONTENT_LENGTH: 77, + HAS_TRANSFER_ENCODING: 78, + HAS_CHUNKED_TRANSFER_ENCODING: 79, + HAS_CONNECTION_CLOSE: 80, + HAS_CONNECTION_UPGRADE: 81, + HAS_UPGRADE: 82, + HAS_TRAILERS: 83, + ACTIVE_CALLBACKS: 88, + ACTIVE_EVENTS: 96, + PTR: 104, + ERROR_DESCRIPTION: 108, + UNCONSUMED: 364, + UNCONSUMED_LEN: 368, + ERROR_DESCRIPTION_LEN: 372, + EVENTS: 376, + 0: 'MAX_START_LINE_LENGTH', + 4: 'MAX_HEADER_LENGTH', + 8: 'MAX_BODY_PAYLOAD', + 16: 'AUTODETECT', + 17: 'IS_REQUEST', + 18: 'SUSPEND_AFTER_HEADERS', + 19: 'MANAGE_UNCONSUMED', + 20: 'CONTINUE_WITHOUT_DATA', + 21: 'IS_CONNECT', + 22: 'SKIP_BODY', + 23: 'DEBUG', + 24: 'PARSED', + 32: 'POSITION', + 36: 'STATE', + 37: 'PAUSED', + 38: 'ERROR_CODE', + 40: 'CONTENT_LENGTH', + 48: 'CHUNK_SIZE', + 56: 'REMAINING_CONTENT_LENGTH', + 64: 'REMAINING_CHUNK_SIZE', + 72: 'STATUS', + 76: 'METHOD', + 77: 'HAS_CONTENT_LENGTH', + 78: 'HAS_TRANSFER_ENCODING', + 79: 'HAS_CHUNKED_TRANSFER_ENCODING', + 80: 'HAS_CONNECTION_CLOSE', + 81: 'HAS_CONNECTION_UPGRADE', + 82: 'HAS_UPGRADE', + 83: 'HAS_TRAILERS', + 88: 'ACTIVE_CALLBACKS', + 96: 'ACTIVE_EVENTS', + 104: 'PTR', + 108: 'ERROR_DESCRIPTION', + 364: 'UNCONSUMED', + 368: 'UNCONSUMED_LEN', + 372: 'ERROR_DESCRIPTION_LEN', + 376: 'EVENTS' +}) + +function isAutodetect (parser) { + return this.is_autodetect(parser) !== 0 +} + +function isRequest (parser) { + return this.is_request(parser) !== 0 +} + +function isPaused (parser) { + return this.is_paused(parser) !== 0 +} + +function shouldManageUnconsumed (parser) { + return this.should_manage_unconsumed(parser) !== 0 +} + +function shouldSuspendAfterHeaders (parser) { + return this.should_suspend_after_headers(parser) !== 0 +} + +function getMaxStartLineLength (parser) { + return this.get_max_start_line_length(parser) >>> 0 +} + +function getMaxHeaderLength (parser) { + return this.get_max_header_length(parser) >>> 0 +} + +function getMaxBodyPayload (parser) { + return BigInt.asUintN(64, this.get_max_body_payload(parser)) +} + +function shouldContinueWithoutData (parser) { + return this.should_continue_without_data(parser) !== 0 +} + +function isConnect (parser) { + return this.is_connect(parser) !== 0 +} + +function isDebug (parser) { + return this.is_debug(parser) !== 0 +} + +function shouldSkipBody (parser) { + return this.should_skip_body(parser) !== 0 +} + +function getState (parser) { + return this.get_state(parser) >>> 0 +} + +function getPosition (parser) { + return this.get_position(parser) >>> 0 +} + +function getParsed (parser) { + return BigInt.asUintN(64, this.get_parsed(parser)) +} + +function getErrorCode (parser) { + return this.get_error_code(parser) >>> 0 +} + +function getMethod (parser) { + return this.get_method(parser) >>> 0 +} + +function getStatus (parser) { + return this.get_status(parser) >>> 0 +} + +function hasConnectionClose (parser) { + return this.has_connection_close(parser) !== 0 +} + +function hasConnectionUpgrade (parser) { + return this.has_connection_upgrade(parser) !== 0 +} + +function getContentLength (parser) { + return BigInt.asUintN(64, this.get_content_length(parser)) +} + +function getChunkSize (parser) { + return BigInt.asUintN(64, this.get_chunk_size(parser)) +} + +function getRemainingContentLength (parser) { + return BigInt.asUintN(64, this.get_remaining_content_length(parser)) +} + +function getRemainingChunkSize (parser) { + return BigInt.asUintN(64, this.get_remaining_chunk_size(parser)) +} + +function hasContentLength (parser) { + return this.has_content_length(parser) !== 0 +} + +function hasTransferEncoding (parser) { + return this.has_transfer_encoding(parser) !== 0 +} + +function hasChunkedTransferEncoding (parser) { + return this.has_chunked_transfer_encoding(parser) !== 0 +} + +function hasUpgrade (parser) { + return this.has_upgrade(parser) !== 0 +} + +function hasTrailers (parser) { + return this.has_trailers(parser) !== 0 +} + +function getErrorDescription (parser) { + const raw = this.get_error_description_raw(parser) + const len = Number(BigInt.asUintN(32, raw)) + const ptr = Number(raw >> 32n) + return textDecoder.decode(new Uint8Array(this.memory.buffer, ptr, len)) +} + +function setShouldAutodetect (parser, value) { + this.set_should_autodetect(parser, value) +} + +function setShouldContinueWithoutData (parser, value) { + this.set_should_continue_without_data(parser, value) +} + +function setIsRequest (parser, value) { + this.set_is_request(parser, value) +} + +function setIsConnect (parser, value) { + this.set_is_connect(parser, value) +} + +function setDebug (parser, value) { + this.set_debug(parser, value) +} + +function setShouldManageUnconsumed (parser, value) { + this.set_should_manage_unconsumed(parser, value) +} + +function setShouldSuspendAfterHeaders (parser, value) { + this.set_should_suspend_after_headers(parser, value) +} + +function setMaxStartLineLength (parser, value) { + this.set_max_start_line_length(parser, value) +} + +function setMaxHeaderLength (parser, value) { + this.set_max_header_length(parser, value) +} + +function setMaxBodyPayload (parser, value) { + this.set_max_body_payload(parser, value) +} + +function setShouldSkipBody (parser, value) { + this.set_should_skip_body(parser, value) +} + +function setActiveCallbacks (parser, value) { + this.set_active_callbacks(parser, value) +} + +function setActiveEvents (parser, value) { + this.set_active_events(parser, value) +} + +function simpleCreate (spans, create) { + const parser = create() + spans[parser] = [] + this.setActiveCallbacks(parser, this.CALLBACK_ACTIVE_ALL) + return parser +} + +function simpleDestroy (spans, destroy, parser) { + spans[parser] = undefined + destroy(parser) +} + +function noop () {} + +function setup (env = {}) { + let { logger: logOption, ...instanceEnvironment } = env + let logger = noop + const context = {} + + if (logOption) { + if (typeof logOption !== 'function') { + logOption = console.log + } + + logger = log.bind(context, logOption) + } + + // Create the WASM instance + /* eslint-disable-next-line no-undef */ + const instance = new WebAssembly.Instance(wasmModule, { + env: { + logger, + on_error: noop, + on_finish: noop, + on_message_start: noop, + on_message_complete: noop, + on_request: noop, + on_response: noop, + on_reset: noop, + on_method: noop, + on_url: noop, + on_protocol: noop, + on_version: noop, + on_status: noop, + on_reason: noop, + on_header_name: noop, + on_header_value: noop, + on_headers: noop, + on_connect: noop, + on_upgrade: noop, + on_chunk_length: noop, + on_chunk_extension_name: noop, + on_chunk_extension_value: noop, + on_chunk: noop, + on_body: noop, + on_data: noop, + on_trailer_name: noop, + on_trailer_value: noop, + on_trailers: noop, + on_state_change: noop, + ...instanceEnvironment + } + }) + + const wasm = instance.exports + context.memory = wasm.memory + + const milo = { + version: { + raw: '0.8.0', + major: 0, + minor: 8, + patch: 0, + prerelease: '' + }, + METHOD_OTHER: 0, + METHOD_GET: 1, + METHOD_HEAD: 2, + METHOD_POST: 3, + METHOD_PUT: 4, + METHOD_DELETE: 5, + METHOD_CONNECT: 6, + METHOD_OPTIONS: 7, + METHOD_TRACE: 8, + METHOD_PATCH: 9, + METHOD_PRI: 10, + CALLBACK_ON_ERROR: 0, + CALLBACK_ON_FINISH: 1, + CALLBACK_ON_MESSAGE_START: 2, + CALLBACK_ON_MESSAGE_COMPLETE: 3, + CALLBACK_ON_REQUEST: 4, + CALLBACK_ON_RESPONSE: 5, + CALLBACK_ON_RESET: 6, + CALLBACK_ON_METHOD: 7, + CALLBACK_ON_URL: 8, + CALLBACK_ON_PROTOCOL: 9, + CALLBACK_ON_VERSION: 10, + CALLBACK_ON_STATUS: 11, + CALLBACK_ON_REASON: 12, + CALLBACK_ON_HEADER_NAME: 13, + CALLBACK_ON_HEADER_VALUE: 14, + CALLBACK_ON_HEADERS: 15, + CALLBACK_ON_CONNECT: 16, + CALLBACK_ON_UPGRADE: 17, + CALLBACK_ON_CHUNK_LENGTH: 18, + CALLBACK_ON_CHUNK_EXTENSION_NAME: 19, + CALLBACK_ON_CHUNK_EXTENSION_VALUE: 20, + CALLBACK_ON_CHUNK: 21, + CALLBACK_ON_BODY: 22, + CALLBACK_ON_DATA: 23, + CALLBACK_ON_TRAILER_NAME: 24, + CALLBACK_ON_TRAILER_VALUE: 25, + CALLBACK_ON_TRAILERS: 26, + CALLBACK_ON_STATE_CHANGE: 27, + EVENT_END: 0, + EVENT_ERROR: 1, + EVENT_FINISH: 2, + EVENT_MESSAGE_START: 3, + EVENT_MESSAGE_COMPLETE: 4, + EVENT_REQUEST: 5, + EVENT_RESPONSE: 6, + EVENT_RESET: 7, + EVENT_METHOD: 8, + EVENT_URL: 9, + EVENT_PROTOCOL: 10, + EVENT_VERSION: 11, + EVENT_STATUS: 12, + EVENT_REASON: 13, + EVENT_HEADER_NAME: 14, + EVENT_HEADER_VALUE: 15, + EVENT_HEADERS: 16, + EVENT_CONNECT: 17, + EVENT_UPGRADE: 18, + EVENT_CHUNK_LENGTH: 19, + EVENT_CHUNK_EXTENSION_NAME: 20, + EVENT_CHUNK_EXTENSION_VALUE: 21, + EVENT_CHUNK: 22, + EVENT_BODY: 23, + EVENT_DATA: 24, + EVENT_TRAILER_NAME: 25, + EVENT_TRAILER_VALUE: 26, + EVENT_TRAILERS: 27, + EVENT_STATE_CHANGE: 28, + CALLBACK_ACTIVE_NONE: 0n, + EVENT_ACTIVE_NONE: 0n, + CALLBACK_ACTIVE_ON_ERROR: 1n, + EVENT_ACTIVE_ON_ERROR: 1n, + CALLBACK_ACTIVE_ON_FINISH: 2n, + EVENT_ACTIVE_ON_FINISH: 2n, + CALLBACK_ACTIVE_ON_MESSAGE_START: 4n, + EVENT_ACTIVE_ON_MESSAGE_START: 4n, + CALLBACK_ACTIVE_ON_MESSAGE_COMPLETE: 8n, + EVENT_ACTIVE_ON_MESSAGE_COMPLETE: 8n, + CALLBACK_ACTIVE_ON_REQUEST: 16n, + EVENT_ACTIVE_ON_REQUEST: 16n, + CALLBACK_ACTIVE_ON_RESPONSE: 32n, + EVENT_ACTIVE_ON_RESPONSE: 32n, + CALLBACK_ACTIVE_ON_RESET: 64n, + EVENT_ACTIVE_ON_RESET: 64n, + CALLBACK_ACTIVE_ON_METHOD: 128n, + EVENT_ACTIVE_ON_METHOD: 128n, + CALLBACK_ACTIVE_ON_URL: 256n, + EVENT_ACTIVE_ON_URL: 256n, + CALLBACK_ACTIVE_ON_PROTOCOL: 512n, + EVENT_ACTIVE_ON_PROTOCOL: 512n, + CALLBACK_ACTIVE_ON_VERSION: 1024n, + EVENT_ACTIVE_ON_VERSION: 1024n, + CALLBACK_ACTIVE_ON_STATUS: 2048n, + EVENT_ACTIVE_ON_STATUS: 2048n, + CALLBACK_ACTIVE_ON_REASON: 4096n, + EVENT_ACTIVE_ON_REASON: 4096n, + CALLBACK_ACTIVE_ON_HEADER_NAME: 8192n, + EVENT_ACTIVE_ON_HEADER_NAME: 8192n, + CALLBACK_ACTIVE_ON_HEADER_VALUE: 16384n, + EVENT_ACTIVE_ON_HEADER_VALUE: 16384n, + CALLBACK_ACTIVE_ON_HEADERS: 32768n, + EVENT_ACTIVE_ON_HEADERS: 32768n, + CALLBACK_ACTIVE_ON_CONNECT: 65536n, + EVENT_ACTIVE_ON_CONNECT: 65536n, + CALLBACK_ACTIVE_ON_UPGRADE: 131072n, + EVENT_ACTIVE_ON_UPGRADE: 131072n, + CALLBACK_ACTIVE_ON_CHUNK_LENGTH: 262144n, + EVENT_ACTIVE_ON_CHUNK_LENGTH: 262144n, + CALLBACK_ACTIVE_ON_CHUNK_EXTENSION_NAME: 524288n, + EVENT_ACTIVE_ON_CHUNK_EXTENSION_NAME: 524288n, + CALLBACK_ACTIVE_ON_CHUNK_EXTENSION_VALUE: 1048576n, + EVENT_ACTIVE_ON_CHUNK_EXTENSION_VALUE: 1048576n, + CALLBACK_ACTIVE_ON_CHUNK: 2097152n, + EVENT_ACTIVE_ON_CHUNK: 2097152n, + CALLBACK_ACTIVE_ON_BODY: 4194304n, + EVENT_ACTIVE_ON_BODY: 4194304n, + CALLBACK_ACTIVE_ON_DATA: 8388608n, + EVENT_ACTIVE_ON_DATA: 8388608n, + CALLBACK_ACTIVE_ON_TRAILER_NAME: 16777216n, + EVENT_ACTIVE_ON_TRAILER_NAME: 16777216n, + CALLBACK_ACTIVE_ON_TRAILER_VALUE: 33554432n, + EVENT_ACTIVE_ON_TRAILER_VALUE: 33554432n, + CALLBACK_ACTIVE_ON_TRAILERS: 67108864n, + EVENT_ACTIVE_ON_TRAILERS: 67108864n, + CALLBACK_ACTIVE_ON_STATE_CHANGE: 134217728n, + EVENT_ACTIVE_ON_STATE_CHANGE: 134217728n, + CALLBACK_ACTIVE_ALL: 268435455n, + EVENT_ACTIVE_ALL: 268435455n, + ERROR_NONE: 0, + ERROR_USER: 1, + ERROR_CALLBACK_ERROR: 2, + ERROR_UNEXPECTED_STATE: 3, + ERROR_UNEXPECTED_DATA: 4, + ERROR_UNEXPECTED_EOF: 5, + ERROR_UNEXPECTED_CHARACTER: 6, + ERROR_UNEXPECTED_CONTENT_LENGTH: 7, + ERROR_UNEXPECTED_TRANSFER_ENCODING: 8, + ERROR_UNEXPECTED_CONTENT: 9, + ERROR_UNEXPECTED_TRAILERS: 10, + ERROR_INVALID_VERSION: 11, + ERROR_INVALID_STATUS: 12, + ERROR_INVALID_CONTENT_LENGTH: 13, + ERROR_INVALID_TRANSFER_ENCODING: 14, + ERROR_INVALID_CHUNK_SIZE: 15, + ERROR_MISSING_CONNECTION_UPGRADE: 16, + ERROR_UNSUPPORTED_HTTP_VERSION: 17, + STATE_START: 0, + STATE_FINISH: 1, + STATE_ERROR: 2, + STATE_REQUEST_LINE: 3, + STATE_STATUS_LINE: 4, + STATE_HTTP2_PREFACE: 5, + STATE_HEADER: 6, + STATE_BODY_DECISION: 7, + STATE_BODY_VIA_CONTENT_LENGTH: 8, + STATE_BODY_WITH_NO_LENGTH: 9, + STATE_CHUNK_HEADER: 10, + STATE_CHUNK_EXTENSIONS: 11, + STATE_CHUNK_DATA: 12, + STATE_TRAILER: 13, + STATE_TUNNEL: 14, + PARSER_FIELD_MAX_START_LINE_LENGTH: 0, + PARSER_FIELD_MAX_HEADER_LENGTH: 4, + PARSER_FIELD_MAX_BODY_PAYLOAD: 8, + PARSER_FIELD_AUTODETECT: 16, + PARSER_FIELD_IS_REQUEST: 17, + PARSER_FIELD_SUSPEND_AFTER_HEADERS: 18, + PARSER_FIELD_MANAGE_UNCONSUMED: 19, + PARSER_FIELD_CONTINUE_WITHOUT_DATA: 20, + PARSER_FIELD_IS_CONNECT: 21, + PARSER_FIELD_SKIP_BODY: 22, + PARSER_FIELD_DEBUG: 23, + PARSER_FIELD_PARSED: 24, + PARSER_FIELD_POSITION: 32, + PARSER_FIELD_STATE: 36, + PARSER_FIELD_PAUSED: 37, + PARSER_FIELD_ERROR_CODE: 38, + PARSER_FIELD_CONTENT_LENGTH: 40, + PARSER_FIELD_CHUNK_SIZE: 48, + PARSER_FIELD_REMAINING_CONTENT_LENGTH: 56, + PARSER_FIELD_REMAINING_CHUNK_SIZE: 64, + PARSER_FIELD_STATUS: 72, + PARSER_FIELD_METHOD: 76, + PARSER_FIELD_HAS_CONTENT_LENGTH: 77, + PARSER_FIELD_HAS_TRANSFER_ENCODING: 78, + PARSER_FIELD_HAS_CHUNKED_TRANSFER_ENCODING: 79, + PARSER_FIELD_HAS_CONNECTION_CLOSE: 80, + PARSER_FIELD_HAS_CONNECTION_UPGRADE: 81, + PARSER_FIELD_HAS_UPGRADE: 82, + PARSER_FIELD_HAS_TRAILERS: 83, + PARSER_FIELD_ACTIVE_CALLBACKS: 88, + PARSER_FIELD_ACTIVE_EVENTS: 96, + PARSER_FIELD_PTR: 104, + PARSER_FIELD_ERROR_DESCRIPTION: 108, + PARSER_FIELD_UNCONSUMED: 364, + PARSER_FIELD_UNCONSUMED_LEN: 368, + PARSER_FIELD_ERROR_DESCRIPTION_LEN: 372, + PARSER_FIELD_EVENTS: 376, + Errors, + Methods, + Callbacks, + CallbackActives, + Events, + EventActives, + States, + ParserFields, + isAutodetect: isAutodetect.bind(wasm), + isRequest: isRequest.bind(wasm), + isPaused: isPaused.bind(wasm), + shouldManageUnconsumed: shouldManageUnconsumed.bind(wasm), + shouldSuspendAfterHeaders: shouldSuspendAfterHeaders.bind(wasm), + getMaxStartLineLength: getMaxStartLineLength.bind(wasm), + getMaxHeaderLength: getMaxHeaderLength.bind(wasm), + getMaxBodyPayload: getMaxBodyPayload.bind(wasm), + shouldContinueWithoutData: shouldContinueWithoutData.bind(wasm), + isConnect: isConnect.bind(wasm), + isDebug: isDebug.bind(wasm), + shouldSkipBody: shouldSkipBody.bind(wasm), + getState: getState.bind(wasm), + getPosition: getPosition.bind(wasm), + getParsed: getParsed.bind(wasm), + getErrorCode: getErrorCode.bind(wasm), + getMethod: getMethod.bind(wasm), + getStatus: getStatus.bind(wasm), + hasConnectionClose: hasConnectionClose.bind(wasm), + hasConnectionUpgrade: hasConnectionUpgrade.bind(wasm), + getContentLength: getContentLength.bind(wasm), + getChunkSize: getChunkSize.bind(wasm), + getRemainingContentLength: getRemainingContentLength.bind(wasm), + getRemainingChunkSize: getRemainingChunkSize.bind(wasm), + hasContentLength: hasContentLength.bind(wasm), + hasTransferEncoding: hasTransferEncoding.bind(wasm), + hasChunkedTransferEncoding: hasChunkedTransferEncoding.bind(wasm), + hasUpgrade: hasUpgrade.bind(wasm), + hasTrailers: hasTrailers.bind(wasm), + getErrorDescription: getErrorDescription.bind(wasm), + setShouldAutodetect: setShouldAutodetect.bind(wasm), + setShouldContinueWithoutData: setShouldContinueWithoutData.bind(wasm), + setIsRequest: setIsRequest.bind(wasm), + setIsConnect: setIsConnect.bind(wasm), + setDebug: setDebug.bind(wasm), + setShouldManageUnconsumed: setShouldManageUnconsumed.bind(wasm), + setShouldSuspendAfterHeaders: setShouldSuspendAfterHeaders.bind(wasm), + setMaxStartLineLength: setMaxStartLineLength.bind(wasm), + setMaxHeaderLength: setMaxHeaderLength.bind(wasm), + setMaxBodyPayload: setMaxBodyPayload.bind(wasm), + setShouldSkipBody: setShouldSkipBody.bind(wasm), + setActiveCallbacks: setActiveCallbacks.bind(wasm), + setActiveEvents: setActiveEvents.bind(wasm), + memory: wasm.memory, + alloc: alloc.bind(wasm), + dealloc: dealloc.bind(wasm), + create: create.bind(wasm), + destroy: destroy.bind(wasm), + parse: parse.bind(wasm), + fail: fail.bind(wasm), + hasDebug: hasDebug.bind(wasm), + clear: wasm.clear, + complete: wasm.complete, + finish: wasm.finish, + pause: wasm.pause, + reset: wasm.reset, + resume: wasm.resume + } + + return milo +} + +function simple () { + const spans = {} + + const milo = setup({ + on_error (parser, at, len) { + spans[parser].push([0, at, len]) + }, + on_finish (parser, at, len) { + spans[parser].push([1, at, len]) + }, + on_message_start (parser, at, len) { + spans[parser].push([2, at, len]) + }, + on_message_complete (parser, at, len) { + spans[parser].push([3, at, len]) + }, + on_request (parser, at, len) { + spans[parser].push([4, at, len]) + }, + on_response (parser, at, len) { + spans[parser].push([5, at, len]) + }, + on_reset (parser, at, len) { + spans[parser].push([6, at, len]) + }, + on_method (parser, at, len) { + spans[parser].push([7, at, len]) + }, + on_url (parser, at, len) { + spans[parser].push([8, at, len]) + }, + on_protocol (parser, at, len) { + spans[parser].push([9, at, len]) + }, + on_version (parser, at, len) { + spans[parser].push([10, at, len]) + }, + on_status (parser, at, len) { + spans[parser].push([11, at, len]) + }, + on_reason (parser, at, len) { + spans[parser].push([12, at, len]) + }, + on_header_name (parser, at, len) { + spans[parser].push([13, at, len]) + }, + on_header_value (parser, at, len) { + spans[parser].push([14, at, len]) + }, + on_headers (parser, at, len) { + spans[parser].push([15, at, len]) + }, + on_connect (parser, at, len) { + spans[parser].push([16, at, len]) + }, + on_upgrade (parser, at, len) { + spans[parser].push([17, at, len]) + }, + on_chunk_length (parser, at, len) { + spans[parser].push([18, at, len]) + }, + on_chunk_extension_name (parser, at, len) { + spans[parser].push([19, at, len]) + }, + on_chunk_extension_value (parser, at, len) { + spans[parser].push([20, at, len]) + }, + on_chunk (parser, at, len) { + spans[parser].push([21, at, len]) + }, + on_body (parser, at, len) { + spans[parser].push([22, at, len]) + }, + on_data (parser, at, len) { + spans[parser].push([23, at, len]) + }, + on_trailer_name (parser, at, len) { + spans[parser].push([24, at, len]) + }, + on_trailer_value (parser, at, len) { + spans[parser].push([25, at, len]) + }, + on_trailers (parser, at, len) { + spans[parser].push([26, at, len]) + }, + on_state_change (parser, at, len) { + spans[parser].push([27, at, len]) + } + }) + + milo.spans = spans + milo.create = simpleCreate.bind(milo, spans, milo.create) + milo.destroy = simpleDestroy.bind(milo, spans, milo.destroy) + + return milo +} + +module.exports = { wasmModule, noop, setup, simple } diff --git a/lib/milo/src/no-simd/unbundled.js b/lib/milo/src/no-simd/unbundled.js new file mode 100644 index 00000000000..87eac4a19e6 --- /dev/null +++ b/lib/milo/src/no-simd/unbundled.js @@ -0,0 +1,1085 @@ +const { readFileSync } = require('node:fs') +const { join } = require('node:path') + +const wasmModule = new WebAssembly.Module(readFileSync(join(__dirname, '../../binary/no-simd.wasm'))) + +const textEncoder = new TextEncoder() +const textDecoder = new TextDecoder() + +function log (logger, raw) { + const len = Number(BigInt.asUintN(32, raw)) + const ptr = Number(raw >> 32n) + + logger(textDecoder.decode(new Uint8Array(this.memory.buffer, ptr, len))) +} + +function alloc (len) { + return this.alloc(len) >>> 0 +} + +function dealloc (ptr) { + return this.dealloc(ptr) +} + +function create () { + return this.create() >>> 0 +} + +function destroy (parser) { + this.destroy(parser) +} + +function parse (parser, data, limit) { + return this.parse(parser, data, limit) >>> 0 +} + +function fail (parser, code, description) { + const len = description.length + const ptr = this.alloc(len) + const buffer = new Uint8Array(this.memory.buffer, ptr, len) + textEncoder.encodeInto(description, buffer) + + this.fail(parser, code, ptr, len) + this.dealloc(ptr, len) +} + +function hasDebug () { + return this.milo_has_debug() !== 0 +} + +const Errors = Object.freeze({ + NONE: 0, + USER: 1, + CALLBACK_ERROR: 2, + UNEXPECTED_STATE: 3, + UNEXPECTED_DATA: 4, + UNEXPECTED_EOF: 5, + UNEXPECTED_CHARACTER: 6, + UNEXPECTED_CONTENT_LENGTH: 7, + UNEXPECTED_TRANSFER_ENCODING: 8, + UNEXPECTED_CONTENT: 9, + UNEXPECTED_TRAILERS: 10, + INVALID_VERSION: 11, + INVALID_STATUS: 12, + INVALID_CONTENT_LENGTH: 13, + INVALID_TRANSFER_ENCODING: 14, + INVALID_CHUNK_SIZE: 15, + MISSING_CONNECTION_UPGRADE: 16, + UNSUPPORTED_HTTP_VERSION: 17, + 0: 'NONE', + 1: 'USER', + 2: 'CALLBACK_ERROR', + 3: 'UNEXPECTED_STATE', + 4: 'UNEXPECTED_DATA', + 5: 'UNEXPECTED_EOF', + 6: 'UNEXPECTED_CHARACTER', + 7: 'UNEXPECTED_CONTENT_LENGTH', + 8: 'UNEXPECTED_TRANSFER_ENCODING', + 9: 'UNEXPECTED_CONTENT', + 10: 'UNEXPECTED_TRAILERS', + 11: 'INVALID_VERSION', + 12: 'INVALID_STATUS', + 13: 'INVALID_CONTENT_LENGTH', + 14: 'INVALID_TRANSFER_ENCODING', + 15: 'INVALID_CHUNK_SIZE', + 16: 'MISSING_CONNECTION_UPGRADE', + 17: 'UNSUPPORTED_HTTP_VERSION' +}) + +const Methods = Object.freeze({ + OTHER: 0, + GET: 1, + HEAD: 2, + POST: 3, + PUT: 4, + DELETE: 5, + CONNECT: 6, + OPTIONS: 7, + TRACE: 8, + PATCH: 9, + PRI: 10, + 0: 'OTHER', + 1: 'GET', + 2: 'HEAD', + 3: 'POST', + 4: 'PUT', + 5: 'DELETE', + 6: 'CONNECT', + 7: 'OPTIONS', + 8: 'TRACE', + 9: 'PATCH', + 10: 'PRI' +}) + +const Callbacks = Object.freeze({ + ON_ERROR: 0, + ON_FINISH: 1, + ON_MESSAGE_START: 2, + ON_MESSAGE_COMPLETE: 3, + ON_REQUEST: 4, + ON_RESPONSE: 5, + ON_RESET: 6, + ON_METHOD: 7, + ON_URL: 8, + ON_PROTOCOL: 9, + ON_VERSION: 10, + ON_STATUS: 11, + ON_REASON: 12, + ON_HEADER_NAME: 13, + ON_HEADER_VALUE: 14, + ON_HEADERS: 15, + ON_CONNECT: 16, + ON_UPGRADE: 17, + ON_CHUNK_LENGTH: 18, + ON_CHUNK_EXTENSION_NAME: 19, + ON_CHUNK_EXTENSION_VALUE: 20, + ON_CHUNK: 21, + ON_BODY: 22, + ON_DATA: 23, + ON_TRAILER_NAME: 24, + ON_TRAILER_VALUE: 25, + ON_TRAILERS: 26, + ON_STATE_CHANGE: 27, + 0: 'ON_ERROR', + 1: 'ON_FINISH', + 2: 'ON_MESSAGE_START', + 3: 'ON_MESSAGE_COMPLETE', + 4: 'ON_REQUEST', + 5: 'ON_RESPONSE', + 6: 'ON_RESET', + 7: 'ON_METHOD', + 8: 'ON_URL', + 9: 'ON_PROTOCOL', + 10: 'ON_VERSION', + 11: 'ON_STATUS', + 12: 'ON_REASON', + 13: 'ON_HEADER_NAME', + 14: 'ON_HEADER_VALUE', + 15: 'ON_HEADERS', + 16: 'ON_CONNECT', + 17: 'ON_UPGRADE', + 18: 'ON_CHUNK_LENGTH', + 19: 'ON_CHUNK_EXTENSION_NAME', + 20: 'ON_CHUNK_EXTENSION_VALUE', + 21: 'ON_CHUNK', + 22: 'ON_BODY', + 23: 'ON_DATA', + 24: 'ON_TRAILER_NAME', + 25: 'ON_TRAILER_VALUE', + 26: 'ON_TRAILERS', + 27: 'ON_STATE_CHANGE' +}) + +const CallbackActives = Object.freeze({ + NONE: 0n, + ON_ERROR: 1n, + ON_FINISH: 2n, + ON_MESSAGE_START: 4n, + ON_MESSAGE_COMPLETE: 8n, + ON_REQUEST: 16n, + ON_RESPONSE: 32n, + ON_RESET: 64n, + ON_METHOD: 128n, + ON_URL: 256n, + ON_PROTOCOL: 512n, + ON_VERSION: 1024n, + ON_STATUS: 2048n, + ON_REASON: 4096n, + ON_HEADER_NAME: 8192n, + ON_HEADER_VALUE: 16384n, + ON_HEADERS: 32768n, + ON_CONNECT: 65536n, + ON_UPGRADE: 131072n, + ON_CHUNK_LENGTH: 262144n, + ON_CHUNK_EXTENSION_NAME: 524288n, + ON_CHUNK_EXTENSION_VALUE: 1048576n, + ON_CHUNK: 2097152n, + ON_BODY: 4194304n, + ON_DATA: 8388608n, + ON_TRAILER_NAME: 16777216n, + ON_TRAILER_VALUE: 33554432n, + ON_TRAILERS: 67108864n, + ON_STATE_CHANGE: 134217728n, + ALL: 268435455n, + 0n: 'NONE', + 1n: 'ON_ERROR', + 2n: 'ON_FINISH', + 4n: 'ON_MESSAGE_START', + 8n: 'ON_MESSAGE_COMPLETE', + 16n: 'ON_REQUEST', + 32n: 'ON_RESPONSE', + 64n: 'ON_RESET', + 128n: 'ON_METHOD', + 256n: 'ON_URL', + 512n: 'ON_PROTOCOL', + 1024n: 'ON_VERSION', + 2048n: 'ON_STATUS', + 4096n: 'ON_REASON', + 8192n: 'ON_HEADER_NAME', + 16384n: 'ON_HEADER_VALUE', + 32768n: 'ON_HEADERS', + 65536n: 'ON_CONNECT', + 131072n: 'ON_UPGRADE', + 262144n: 'ON_CHUNK_LENGTH', + 524288n: 'ON_CHUNK_EXTENSION_NAME', + 1048576n: 'ON_CHUNK_EXTENSION_VALUE', + 2097152n: 'ON_CHUNK', + 4194304n: 'ON_BODY', + 8388608n: 'ON_DATA', + 16777216n: 'ON_TRAILER_NAME', + 33554432n: 'ON_TRAILER_VALUE', + 67108864n: 'ON_TRAILERS', + 134217728n: 'ON_STATE_CHANGE', + 268435455n: 'ALL' +}) + +const Events = Object.freeze({ + END: 0, + ERROR: 1, + FINISH: 2, + MESSAGE_START: 3, + MESSAGE_COMPLETE: 4, + REQUEST: 5, + RESPONSE: 6, + RESET: 7, + METHOD: 8, + URL: 9, + PROTOCOL: 10, + VERSION: 11, + STATUS: 12, + REASON: 13, + HEADER_NAME: 14, + HEADER_VALUE: 15, + HEADERS: 16, + CONNECT: 17, + UPGRADE: 18, + CHUNK_LENGTH: 19, + CHUNK_EXTENSION_NAME: 20, + CHUNK_EXTENSION_VALUE: 21, + CHUNK: 22, + BODY: 23, + DATA: 24, + TRAILER_NAME: 25, + TRAILER_VALUE: 26, + TRAILERS: 27, + STATE_CHANGE: 28, + 0: 'END', + 1: 'ERROR', + 2: 'FINISH', + 3: 'MESSAGE_START', + 4: 'MESSAGE_COMPLETE', + 5: 'REQUEST', + 6: 'RESPONSE', + 7: 'RESET', + 8: 'METHOD', + 9: 'URL', + 10: 'PROTOCOL', + 11: 'VERSION', + 12: 'STATUS', + 13: 'REASON', + 14: 'HEADER_NAME', + 15: 'HEADER_VALUE', + 16: 'HEADERS', + 17: 'CONNECT', + 18: 'UPGRADE', + 19: 'CHUNK_LENGTH', + 20: 'CHUNK_EXTENSION_NAME', + 21: 'CHUNK_EXTENSION_VALUE', + 22: 'CHUNK', + 23: 'BODY', + 24: 'DATA', + 25: 'TRAILER_NAME', + 26: 'TRAILER_VALUE', + 27: 'TRAILERS', + 28: 'STATE_CHANGE' +}) + +const EventActives = Object.freeze({ + NONE: 0n, + ON_ERROR: 1n, + ON_FINISH: 2n, + ON_MESSAGE_START: 4n, + ON_MESSAGE_COMPLETE: 8n, + ON_REQUEST: 16n, + ON_RESPONSE: 32n, + ON_RESET: 64n, + ON_METHOD: 128n, + ON_URL: 256n, + ON_PROTOCOL: 512n, + ON_VERSION: 1024n, + ON_STATUS: 2048n, + ON_REASON: 4096n, + ON_HEADER_NAME: 8192n, + ON_HEADER_VALUE: 16384n, + ON_HEADERS: 32768n, + ON_CONNECT: 65536n, + ON_UPGRADE: 131072n, + ON_CHUNK_LENGTH: 262144n, + ON_CHUNK_EXTENSION_NAME: 524288n, + ON_CHUNK_EXTENSION_VALUE: 1048576n, + ON_CHUNK: 2097152n, + ON_BODY: 4194304n, + ON_DATA: 8388608n, + ON_TRAILER_NAME: 16777216n, + ON_TRAILER_VALUE: 33554432n, + ON_TRAILERS: 67108864n, + ON_STATE_CHANGE: 134217728n, + ALL: 268435455n, + 0n: 'NONE', + 1n: 'ON_ERROR', + 2n: 'ON_FINISH', + 4n: 'ON_MESSAGE_START', + 8n: 'ON_MESSAGE_COMPLETE', + 16n: 'ON_REQUEST', + 32n: 'ON_RESPONSE', + 64n: 'ON_RESET', + 128n: 'ON_METHOD', + 256n: 'ON_URL', + 512n: 'ON_PROTOCOL', + 1024n: 'ON_VERSION', + 2048n: 'ON_STATUS', + 4096n: 'ON_REASON', + 8192n: 'ON_HEADER_NAME', + 16384n: 'ON_HEADER_VALUE', + 32768n: 'ON_HEADERS', + 65536n: 'ON_CONNECT', + 131072n: 'ON_UPGRADE', + 262144n: 'ON_CHUNK_LENGTH', + 524288n: 'ON_CHUNK_EXTENSION_NAME', + 1048576n: 'ON_CHUNK_EXTENSION_VALUE', + 2097152n: 'ON_CHUNK', + 4194304n: 'ON_BODY', + 8388608n: 'ON_DATA', + 16777216n: 'ON_TRAILER_NAME', + 33554432n: 'ON_TRAILER_VALUE', + 67108864n: 'ON_TRAILERS', + 134217728n: 'ON_STATE_CHANGE', + 268435455n: 'ALL' +}) + +const States = Object.freeze({ + START: 0, + FINISH: 1, + ERROR: 2, + REQUEST_LINE: 3, + STATUS_LINE: 4, + HTTP2_PREFACE: 5, + HEADER: 6, + BODY_DECISION: 7, + BODY_VIA_CONTENT_LENGTH: 8, + BODY_WITH_NO_LENGTH: 9, + CHUNK_HEADER: 10, + CHUNK_EXTENSIONS: 11, + CHUNK_DATA: 12, + TRAILER: 13, + TUNNEL: 14, + 0: 'START', + 1: 'FINISH', + 2: 'ERROR', + 3: 'REQUEST_LINE', + 4: 'STATUS_LINE', + 5: 'HTTP2_PREFACE', + 6: 'HEADER', + 7: 'BODY_DECISION', + 8: 'BODY_VIA_CONTENT_LENGTH', + 9: 'BODY_WITH_NO_LENGTH', + 10: 'CHUNK_HEADER', + 11: 'CHUNK_EXTENSIONS', + 12: 'CHUNK_DATA', + 13: 'TRAILER', + 14: 'TUNNEL' +}) + +const ParserFields = Object.freeze({ + MAX_START_LINE_LENGTH: 0, + MAX_HEADER_LENGTH: 4, + MAX_BODY_PAYLOAD: 8, + AUTODETECT: 16, + IS_REQUEST: 17, + SUSPEND_AFTER_HEADERS: 18, + MANAGE_UNCONSUMED: 19, + CONTINUE_WITHOUT_DATA: 20, + IS_CONNECT: 21, + SKIP_BODY: 22, + DEBUG: 23, + PARSED: 24, + POSITION: 32, + STATE: 36, + PAUSED: 37, + ERROR_CODE: 38, + CONTENT_LENGTH: 40, + CHUNK_SIZE: 48, + REMAINING_CONTENT_LENGTH: 56, + REMAINING_CHUNK_SIZE: 64, + STATUS: 72, + METHOD: 76, + HAS_CONTENT_LENGTH: 77, + HAS_TRANSFER_ENCODING: 78, + HAS_CHUNKED_TRANSFER_ENCODING: 79, + HAS_CONNECTION_CLOSE: 80, + HAS_CONNECTION_UPGRADE: 81, + HAS_UPGRADE: 82, + HAS_TRAILERS: 83, + ACTIVE_CALLBACKS: 88, + ACTIVE_EVENTS: 96, + PTR: 104, + ERROR_DESCRIPTION: 108, + UNCONSUMED: 364, + UNCONSUMED_LEN: 368, + ERROR_DESCRIPTION_LEN: 372, + EVENTS: 376, + 0: 'MAX_START_LINE_LENGTH', + 4: 'MAX_HEADER_LENGTH', + 8: 'MAX_BODY_PAYLOAD', + 16: 'AUTODETECT', + 17: 'IS_REQUEST', + 18: 'SUSPEND_AFTER_HEADERS', + 19: 'MANAGE_UNCONSUMED', + 20: 'CONTINUE_WITHOUT_DATA', + 21: 'IS_CONNECT', + 22: 'SKIP_BODY', + 23: 'DEBUG', + 24: 'PARSED', + 32: 'POSITION', + 36: 'STATE', + 37: 'PAUSED', + 38: 'ERROR_CODE', + 40: 'CONTENT_LENGTH', + 48: 'CHUNK_SIZE', + 56: 'REMAINING_CONTENT_LENGTH', + 64: 'REMAINING_CHUNK_SIZE', + 72: 'STATUS', + 76: 'METHOD', + 77: 'HAS_CONTENT_LENGTH', + 78: 'HAS_TRANSFER_ENCODING', + 79: 'HAS_CHUNKED_TRANSFER_ENCODING', + 80: 'HAS_CONNECTION_CLOSE', + 81: 'HAS_CONNECTION_UPGRADE', + 82: 'HAS_UPGRADE', + 83: 'HAS_TRAILERS', + 88: 'ACTIVE_CALLBACKS', + 96: 'ACTIVE_EVENTS', + 104: 'PTR', + 108: 'ERROR_DESCRIPTION', + 364: 'UNCONSUMED', + 368: 'UNCONSUMED_LEN', + 372: 'ERROR_DESCRIPTION_LEN', + 376: 'EVENTS' +}) + +function isAutodetect (parser) { + return this.is_autodetect(parser) !== 0 +} + +function isRequest (parser) { + return this.is_request(parser) !== 0 +} + +function isPaused (parser) { + return this.is_paused(parser) !== 0 +} + +function shouldManageUnconsumed (parser) { + return this.should_manage_unconsumed(parser) !== 0 +} + +function shouldSuspendAfterHeaders (parser) { + return this.should_suspend_after_headers(parser) !== 0 +} + +function getMaxStartLineLength (parser) { + return this.get_max_start_line_length(parser) >>> 0 +} + +function getMaxHeaderLength (parser) { + return this.get_max_header_length(parser) >>> 0 +} + +function getMaxBodyPayload (parser) { + return BigInt.asUintN(64, this.get_max_body_payload(parser)) +} + +function shouldContinueWithoutData (parser) { + return this.should_continue_without_data(parser) !== 0 +} + +function isConnect (parser) { + return this.is_connect(parser) !== 0 +} + +function isDebug (parser) { + return this.is_debug(parser) !== 0 +} + +function shouldSkipBody (parser) { + return this.should_skip_body(parser) !== 0 +} + +function getState (parser) { + return this.get_state(parser) >>> 0 +} + +function getPosition (parser) { + return this.get_position(parser) >>> 0 +} + +function getParsed (parser) { + return BigInt.asUintN(64, this.get_parsed(parser)) +} + +function getErrorCode (parser) { + return this.get_error_code(parser) >>> 0 +} + +function getMethod (parser) { + return this.get_method(parser) >>> 0 +} + +function getStatus (parser) { + return this.get_status(parser) >>> 0 +} + +function hasConnectionClose (parser) { + return this.has_connection_close(parser) !== 0 +} + +function hasConnectionUpgrade (parser) { + return this.has_connection_upgrade(parser) !== 0 +} + +function getContentLength (parser) { + return BigInt.asUintN(64, this.get_content_length(parser)) +} + +function getChunkSize (parser) { + return BigInt.asUintN(64, this.get_chunk_size(parser)) +} + +function getRemainingContentLength (parser) { + return BigInt.asUintN(64, this.get_remaining_content_length(parser)) +} + +function getRemainingChunkSize (parser) { + return BigInt.asUintN(64, this.get_remaining_chunk_size(parser)) +} + +function hasContentLength (parser) { + return this.has_content_length(parser) !== 0 +} + +function hasTransferEncoding (parser) { + return this.has_transfer_encoding(parser) !== 0 +} + +function hasChunkedTransferEncoding (parser) { + return this.has_chunked_transfer_encoding(parser) !== 0 +} + +function hasUpgrade (parser) { + return this.has_upgrade(parser) !== 0 +} + +function hasTrailers (parser) { + return this.has_trailers(parser) !== 0 +} + +function getErrorDescription (parser) { + const raw = this.get_error_description_raw(parser) + const len = Number(BigInt.asUintN(32, raw)) + const ptr = Number(raw >> 32n) + return textDecoder.decode(new Uint8Array(this.memory.buffer, ptr, len)) +} + +function setShouldAutodetect (parser, value) { + this.set_should_autodetect(parser, value) +} + +function setShouldContinueWithoutData (parser, value) { + this.set_should_continue_without_data(parser, value) +} + +function setIsRequest (parser, value) { + this.set_is_request(parser, value) +} + +function setIsConnect (parser, value) { + this.set_is_connect(parser, value) +} + +function setDebug (parser, value) { + this.set_debug(parser, value) +} + +function setShouldManageUnconsumed (parser, value) { + this.set_should_manage_unconsumed(parser, value) +} + +function setShouldSuspendAfterHeaders (parser, value) { + this.set_should_suspend_after_headers(parser, value) +} + +function setMaxStartLineLength (parser, value) { + this.set_max_start_line_length(parser, value) +} + +function setMaxHeaderLength (parser, value) { + this.set_max_header_length(parser, value) +} + +function setMaxBodyPayload (parser, value) { + this.set_max_body_payload(parser, value) +} + +function setShouldSkipBody (parser, value) { + this.set_should_skip_body(parser, value) +} + +function setActiveCallbacks (parser, value) { + this.set_active_callbacks(parser, value) +} + +function setActiveEvents (parser, value) { + this.set_active_events(parser, value) +} + +function simpleCreate (spans, create) { + const parser = create() + spans[parser] = [] + this.setActiveCallbacks(parser, this.CALLBACK_ACTIVE_ALL) + return parser +} + +function simpleDestroy (spans, destroy, parser) { + spans[parser] = undefined + destroy(parser) +} + +function noop () {} + +function setup (env = {}) { + let { logger: logOption, ...instanceEnvironment } = env + let logger = noop + const context = {} + + if (logOption) { + if (typeof logOption !== 'function') { + logOption = console.log + } + + logger = log.bind(context, logOption) + } + + // Create the WASM instance + /* eslint-disable-next-line no-undef */ + const instance = new WebAssembly.Instance(wasmModule, { + env: { + logger, + on_error: noop, + on_finish: noop, + on_message_start: noop, + on_message_complete: noop, + on_request: noop, + on_response: noop, + on_reset: noop, + on_method: noop, + on_url: noop, + on_protocol: noop, + on_version: noop, + on_status: noop, + on_reason: noop, + on_header_name: noop, + on_header_value: noop, + on_headers: noop, + on_connect: noop, + on_upgrade: noop, + on_chunk_length: noop, + on_chunk_extension_name: noop, + on_chunk_extension_value: noop, + on_chunk: noop, + on_body: noop, + on_data: noop, + on_trailer_name: noop, + on_trailer_value: noop, + on_trailers: noop, + on_state_change: noop, + ...instanceEnvironment + } + }) + + const wasm = instance.exports + context.memory = wasm.memory + + const milo = { + version: { + raw: '0.8.0', + major: 0, + minor: 8, + patch: 0, + prerelease: '' + }, + METHOD_OTHER: 0, + METHOD_GET: 1, + METHOD_HEAD: 2, + METHOD_POST: 3, + METHOD_PUT: 4, + METHOD_DELETE: 5, + METHOD_CONNECT: 6, + METHOD_OPTIONS: 7, + METHOD_TRACE: 8, + METHOD_PATCH: 9, + METHOD_PRI: 10, + CALLBACK_ON_ERROR: 0, + CALLBACK_ON_FINISH: 1, + CALLBACK_ON_MESSAGE_START: 2, + CALLBACK_ON_MESSAGE_COMPLETE: 3, + CALLBACK_ON_REQUEST: 4, + CALLBACK_ON_RESPONSE: 5, + CALLBACK_ON_RESET: 6, + CALLBACK_ON_METHOD: 7, + CALLBACK_ON_URL: 8, + CALLBACK_ON_PROTOCOL: 9, + CALLBACK_ON_VERSION: 10, + CALLBACK_ON_STATUS: 11, + CALLBACK_ON_REASON: 12, + CALLBACK_ON_HEADER_NAME: 13, + CALLBACK_ON_HEADER_VALUE: 14, + CALLBACK_ON_HEADERS: 15, + CALLBACK_ON_CONNECT: 16, + CALLBACK_ON_UPGRADE: 17, + CALLBACK_ON_CHUNK_LENGTH: 18, + CALLBACK_ON_CHUNK_EXTENSION_NAME: 19, + CALLBACK_ON_CHUNK_EXTENSION_VALUE: 20, + CALLBACK_ON_CHUNK: 21, + CALLBACK_ON_BODY: 22, + CALLBACK_ON_DATA: 23, + CALLBACK_ON_TRAILER_NAME: 24, + CALLBACK_ON_TRAILER_VALUE: 25, + CALLBACK_ON_TRAILERS: 26, + CALLBACK_ON_STATE_CHANGE: 27, + EVENT_END: 0, + EVENT_ERROR: 1, + EVENT_FINISH: 2, + EVENT_MESSAGE_START: 3, + EVENT_MESSAGE_COMPLETE: 4, + EVENT_REQUEST: 5, + EVENT_RESPONSE: 6, + EVENT_RESET: 7, + EVENT_METHOD: 8, + EVENT_URL: 9, + EVENT_PROTOCOL: 10, + EVENT_VERSION: 11, + EVENT_STATUS: 12, + EVENT_REASON: 13, + EVENT_HEADER_NAME: 14, + EVENT_HEADER_VALUE: 15, + EVENT_HEADERS: 16, + EVENT_CONNECT: 17, + EVENT_UPGRADE: 18, + EVENT_CHUNK_LENGTH: 19, + EVENT_CHUNK_EXTENSION_NAME: 20, + EVENT_CHUNK_EXTENSION_VALUE: 21, + EVENT_CHUNK: 22, + EVENT_BODY: 23, + EVENT_DATA: 24, + EVENT_TRAILER_NAME: 25, + EVENT_TRAILER_VALUE: 26, + EVENT_TRAILERS: 27, + EVENT_STATE_CHANGE: 28, + CALLBACK_ACTIVE_NONE: 0n, + EVENT_ACTIVE_NONE: 0n, + CALLBACK_ACTIVE_ON_ERROR: 1n, + EVENT_ACTIVE_ON_ERROR: 1n, + CALLBACK_ACTIVE_ON_FINISH: 2n, + EVENT_ACTIVE_ON_FINISH: 2n, + CALLBACK_ACTIVE_ON_MESSAGE_START: 4n, + EVENT_ACTIVE_ON_MESSAGE_START: 4n, + CALLBACK_ACTIVE_ON_MESSAGE_COMPLETE: 8n, + EVENT_ACTIVE_ON_MESSAGE_COMPLETE: 8n, + CALLBACK_ACTIVE_ON_REQUEST: 16n, + EVENT_ACTIVE_ON_REQUEST: 16n, + CALLBACK_ACTIVE_ON_RESPONSE: 32n, + EVENT_ACTIVE_ON_RESPONSE: 32n, + CALLBACK_ACTIVE_ON_RESET: 64n, + EVENT_ACTIVE_ON_RESET: 64n, + CALLBACK_ACTIVE_ON_METHOD: 128n, + EVENT_ACTIVE_ON_METHOD: 128n, + CALLBACK_ACTIVE_ON_URL: 256n, + EVENT_ACTIVE_ON_URL: 256n, + CALLBACK_ACTIVE_ON_PROTOCOL: 512n, + EVENT_ACTIVE_ON_PROTOCOL: 512n, + CALLBACK_ACTIVE_ON_VERSION: 1024n, + EVENT_ACTIVE_ON_VERSION: 1024n, + CALLBACK_ACTIVE_ON_STATUS: 2048n, + EVENT_ACTIVE_ON_STATUS: 2048n, + CALLBACK_ACTIVE_ON_REASON: 4096n, + EVENT_ACTIVE_ON_REASON: 4096n, + CALLBACK_ACTIVE_ON_HEADER_NAME: 8192n, + EVENT_ACTIVE_ON_HEADER_NAME: 8192n, + CALLBACK_ACTIVE_ON_HEADER_VALUE: 16384n, + EVENT_ACTIVE_ON_HEADER_VALUE: 16384n, + CALLBACK_ACTIVE_ON_HEADERS: 32768n, + EVENT_ACTIVE_ON_HEADERS: 32768n, + CALLBACK_ACTIVE_ON_CONNECT: 65536n, + EVENT_ACTIVE_ON_CONNECT: 65536n, + CALLBACK_ACTIVE_ON_UPGRADE: 131072n, + EVENT_ACTIVE_ON_UPGRADE: 131072n, + CALLBACK_ACTIVE_ON_CHUNK_LENGTH: 262144n, + EVENT_ACTIVE_ON_CHUNK_LENGTH: 262144n, + CALLBACK_ACTIVE_ON_CHUNK_EXTENSION_NAME: 524288n, + EVENT_ACTIVE_ON_CHUNK_EXTENSION_NAME: 524288n, + CALLBACK_ACTIVE_ON_CHUNK_EXTENSION_VALUE: 1048576n, + EVENT_ACTIVE_ON_CHUNK_EXTENSION_VALUE: 1048576n, + CALLBACK_ACTIVE_ON_CHUNK: 2097152n, + EVENT_ACTIVE_ON_CHUNK: 2097152n, + CALLBACK_ACTIVE_ON_BODY: 4194304n, + EVENT_ACTIVE_ON_BODY: 4194304n, + CALLBACK_ACTIVE_ON_DATA: 8388608n, + EVENT_ACTIVE_ON_DATA: 8388608n, + CALLBACK_ACTIVE_ON_TRAILER_NAME: 16777216n, + EVENT_ACTIVE_ON_TRAILER_NAME: 16777216n, + CALLBACK_ACTIVE_ON_TRAILER_VALUE: 33554432n, + EVENT_ACTIVE_ON_TRAILER_VALUE: 33554432n, + CALLBACK_ACTIVE_ON_TRAILERS: 67108864n, + EVENT_ACTIVE_ON_TRAILERS: 67108864n, + CALLBACK_ACTIVE_ON_STATE_CHANGE: 134217728n, + EVENT_ACTIVE_ON_STATE_CHANGE: 134217728n, + CALLBACK_ACTIVE_ALL: 268435455n, + EVENT_ACTIVE_ALL: 268435455n, + ERROR_NONE: 0, + ERROR_USER: 1, + ERROR_CALLBACK_ERROR: 2, + ERROR_UNEXPECTED_STATE: 3, + ERROR_UNEXPECTED_DATA: 4, + ERROR_UNEXPECTED_EOF: 5, + ERROR_UNEXPECTED_CHARACTER: 6, + ERROR_UNEXPECTED_CONTENT_LENGTH: 7, + ERROR_UNEXPECTED_TRANSFER_ENCODING: 8, + ERROR_UNEXPECTED_CONTENT: 9, + ERROR_UNEXPECTED_TRAILERS: 10, + ERROR_INVALID_VERSION: 11, + ERROR_INVALID_STATUS: 12, + ERROR_INVALID_CONTENT_LENGTH: 13, + ERROR_INVALID_TRANSFER_ENCODING: 14, + ERROR_INVALID_CHUNK_SIZE: 15, + ERROR_MISSING_CONNECTION_UPGRADE: 16, + ERROR_UNSUPPORTED_HTTP_VERSION: 17, + STATE_START: 0, + STATE_FINISH: 1, + STATE_ERROR: 2, + STATE_REQUEST_LINE: 3, + STATE_STATUS_LINE: 4, + STATE_HTTP2_PREFACE: 5, + STATE_HEADER: 6, + STATE_BODY_DECISION: 7, + STATE_BODY_VIA_CONTENT_LENGTH: 8, + STATE_BODY_WITH_NO_LENGTH: 9, + STATE_CHUNK_HEADER: 10, + STATE_CHUNK_EXTENSIONS: 11, + STATE_CHUNK_DATA: 12, + STATE_TRAILER: 13, + STATE_TUNNEL: 14, + PARSER_FIELD_MAX_START_LINE_LENGTH: 0, + PARSER_FIELD_MAX_HEADER_LENGTH: 4, + PARSER_FIELD_MAX_BODY_PAYLOAD: 8, + PARSER_FIELD_AUTODETECT: 16, + PARSER_FIELD_IS_REQUEST: 17, + PARSER_FIELD_SUSPEND_AFTER_HEADERS: 18, + PARSER_FIELD_MANAGE_UNCONSUMED: 19, + PARSER_FIELD_CONTINUE_WITHOUT_DATA: 20, + PARSER_FIELD_IS_CONNECT: 21, + PARSER_FIELD_SKIP_BODY: 22, + PARSER_FIELD_DEBUG: 23, + PARSER_FIELD_PARSED: 24, + PARSER_FIELD_POSITION: 32, + PARSER_FIELD_STATE: 36, + PARSER_FIELD_PAUSED: 37, + PARSER_FIELD_ERROR_CODE: 38, + PARSER_FIELD_CONTENT_LENGTH: 40, + PARSER_FIELD_CHUNK_SIZE: 48, + PARSER_FIELD_REMAINING_CONTENT_LENGTH: 56, + PARSER_FIELD_REMAINING_CHUNK_SIZE: 64, + PARSER_FIELD_STATUS: 72, + PARSER_FIELD_METHOD: 76, + PARSER_FIELD_HAS_CONTENT_LENGTH: 77, + PARSER_FIELD_HAS_TRANSFER_ENCODING: 78, + PARSER_FIELD_HAS_CHUNKED_TRANSFER_ENCODING: 79, + PARSER_FIELD_HAS_CONNECTION_CLOSE: 80, + PARSER_FIELD_HAS_CONNECTION_UPGRADE: 81, + PARSER_FIELD_HAS_UPGRADE: 82, + PARSER_FIELD_HAS_TRAILERS: 83, + PARSER_FIELD_ACTIVE_CALLBACKS: 88, + PARSER_FIELD_ACTIVE_EVENTS: 96, + PARSER_FIELD_PTR: 104, + PARSER_FIELD_ERROR_DESCRIPTION: 108, + PARSER_FIELD_UNCONSUMED: 364, + PARSER_FIELD_UNCONSUMED_LEN: 368, + PARSER_FIELD_ERROR_DESCRIPTION_LEN: 372, + PARSER_FIELD_EVENTS: 376, + Errors, + Methods, + Callbacks, + CallbackActives, + Events, + EventActives, + States, + ParserFields, + isAutodetect: isAutodetect.bind(wasm), + isRequest: isRequest.bind(wasm), + isPaused: isPaused.bind(wasm), + shouldManageUnconsumed: shouldManageUnconsumed.bind(wasm), + shouldSuspendAfterHeaders: shouldSuspendAfterHeaders.bind(wasm), + getMaxStartLineLength: getMaxStartLineLength.bind(wasm), + getMaxHeaderLength: getMaxHeaderLength.bind(wasm), + getMaxBodyPayload: getMaxBodyPayload.bind(wasm), + shouldContinueWithoutData: shouldContinueWithoutData.bind(wasm), + isConnect: isConnect.bind(wasm), + isDebug: isDebug.bind(wasm), + shouldSkipBody: shouldSkipBody.bind(wasm), + getState: getState.bind(wasm), + getPosition: getPosition.bind(wasm), + getParsed: getParsed.bind(wasm), + getErrorCode: getErrorCode.bind(wasm), + getMethod: getMethod.bind(wasm), + getStatus: getStatus.bind(wasm), + hasConnectionClose: hasConnectionClose.bind(wasm), + hasConnectionUpgrade: hasConnectionUpgrade.bind(wasm), + getContentLength: getContentLength.bind(wasm), + getChunkSize: getChunkSize.bind(wasm), + getRemainingContentLength: getRemainingContentLength.bind(wasm), + getRemainingChunkSize: getRemainingChunkSize.bind(wasm), + hasContentLength: hasContentLength.bind(wasm), + hasTransferEncoding: hasTransferEncoding.bind(wasm), + hasChunkedTransferEncoding: hasChunkedTransferEncoding.bind(wasm), + hasUpgrade: hasUpgrade.bind(wasm), + hasTrailers: hasTrailers.bind(wasm), + getErrorDescription: getErrorDescription.bind(wasm), + setShouldAutodetect: setShouldAutodetect.bind(wasm), + setShouldContinueWithoutData: setShouldContinueWithoutData.bind(wasm), + setIsRequest: setIsRequest.bind(wasm), + setIsConnect: setIsConnect.bind(wasm), + setDebug: setDebug.bind(wasm), + setShouldManageUnconsumed: setShouldManageUnconsumed.bind(wasm), + setShouldSuspendAfterHeaders: setShouldSuspendAfterHeaders.bind(wasm), + setMaxStartLineLength: setMaxStartLineLength.bind(wasm), + setMaxHeaderLength: setMaxHeaderLength.bind(wasm), + setMaxBodyPayload: setMaxBodyPayload.bind(wasm), + setShouldSkipBody: setShouldSkipBody.bind(wasm), + setActiveCallbacks: setActiveCallbacks.bind(wasm), + setActiveEvents: setActiveEvents.bind(wasm), + memory: wasm.memory, + alloc: alloc.bind(wasm), + dealloc: dealloc.bind(wasm), + create: create.bind(wasm), + destroy: destroy.bind(wasm), + parse: parse.bind(wasm), + fail: fail.bind(wasm), + hasDebug: hasDebug.bind(wasm), + clear: wasm.clear, + complete: wasm.complete, + finish: wasm.finish, + pause: wasm.pause, + reset: wasm.reset, + resume: wasm.resume + } + + return milo +} + +function simple () { + const spans = {} + + const milo = setup({ + on_error (parser, at, len) { + spans[parser].push([0, at, len]) + }, + on_finish (parser, at, len) { + spans[parser].push([1, at, len]) + }, + on_message_start (parser, at, len) { + spans[parser].push([2, at, len]) + }, + on_message_complete (parser, at, len) { + spans[parser].push([3, at, len]) + }, + on_request (parser, at, len) { + spans[parser].push([4, at, len]) + }, + on_response (parser, at, len) { + spans[parser].push([5, at, len]) + }, + on_reset (parser, at, len) { + spans[parser].push([6, at, len]) + }, + on_method (parser, at, len) { + spans[parser].push([7, at, len]) + }, + on_url (parser, at, len) { + spans[parser].push([8, at, len]) + }, + on_protocol (parser, at, len) { + spans[parser].push([9, at, len]) + }, + on_version (parser, at, len) { + spans[parser].push([10, at, len]) + }, + on_status (parser, at, len) { + spans[parser].push([11, at, len]) + }, + on_reason (parser, at, len) { + spans[parser].push([12, at, len]) + }, + on_header_name (parser, at, len) { + spans[parser].push([13, at, len]) + }, + on_header_value (parser, at, len) { + spans[parser].push([14, at, len]) + }, + on_headers (parser, at, len) { + spans[parser].push([15, at, len]) + }, + on_connect (parser, at, len) { + spans[parser].push([16, at, len]) + }, + on_upgrade (parser, at, len) { + spans[parser].push([17, at, len]) + }, + on_chunk_length (parser, at, len) { + spans[parser].push([18, at, len]) + }, + on_chunk_extension_name (parser, at, len) { + spans[parser].push([19, at, len]) + }, + on_chunk_extension_value (parser, at, len) { + spans[parser].push([20, at, len]) + }, + on_chunk (parser, at, len) { + spans[parser].push([21, at, len]) + }, + on_body (parser, at, len) { + spans[parser].push([22, at, len]) + }, + on_data (parser, at, len) { + spans[parser].push([23, at, len]) + }, + on_trailer_name (parser, at, len) { + spans[parser].push([24, at, len]) + }, + on_trailer_value (parser, at, len) { + spans[parser].push([25, at, len]) + }, + on_trailers (parser, at, len) { + spans[parser].push([26, at, len]) + }, + on_state_change (parser, at, len) { + spans[parser].push([27, at, len]) + } + }) + + milo.spans = spans + milo.create = simpleCreate.bind(milo, spans, milo.create) + milo.destroy = simpleDestroy.bind(milo, spans, milo.destroy) + + return milo +} + +module.exports = { wasmModule, noop, setup, simple } diff --git a/lib/milo/src/simd/index.js b/lib/milo/src/simd/index.js new file mode 100644 index 00000000000..392129bac2f --- /dev/null +++ b/lib/milo/src/simd/index.js @@ -0,0 +1,1087 @@ +const wasmModule = new WebAssembly.Module( + Buffer.from( + 'AGFzbQEAAAABQgtgA39/fwBgAX8Bf2ACf38AYAF/AGABfwF+YAJ/fgBgBH9/f38AYAABf2AIf39/f39/f3wAYAN/f38Bf2ACf38BfwKUBBwDZW52CG9uX2Vycm9yAAADZW52Cm9uX2hlYWRlcnMACANlbnYJb25fZmluaXNoAAADZW52EG9uX21lc3NhZ2Vfc3RhcnQAAANlbnYTb25fbWVzc2FnZV9jb21wbGV0ZQAAA2Vudgpvbl9yZXF1ZXN0AAADZW52C29uX3Jlc3BvbnNlAAADZW52CG9uX3Jlc2V0AAADZW52CW9uX21ldGhvZAAAA2VudgZvbl91cmwAAANlbnYLb25fcHJvdG9jb2wAAANlbnYKb25fdmVyc2lvbgAAA2Vudglvbl9zdGF0dXMAAANlbnYJb25fcmVhc29uAAADZW52Dm9uX2hlYWRlcl9uYW1lAAADZW52D29uX2hlYWRlcl92YWx1ZQAAA2Vudgpvbl9jb25uZWN0AAADZW52Cm9uX3VwZ3JhZGUAAANlbnYPb25fY2h1bmtfbGVuZ3RoAAADZW52F29uX2NodW5rX2V4dGVuc2lvbl9uYW1lAAADZW52GG9uX2NodW5rX2V4dGVuc2lvbl92YWx1ZQAAA2Vudghvbl9jaHVuawAAA2Vudgdvbl9ib2R5AAADZW52B29uX2RhdGEAAANlbnYPb25fdHJhaWxlcl9uYW1lAAADZW52EG9uX3RyYWlsZXJfdmFsdWUAAANlbnYLb25fdHJhaWxlcnMAAANlbnYPb25fc3RhdGVfY2hhbmdlAAADQkEGAAEDAwcCAwYDBAQBBAQBAQEEAQQEAQEBAQEBAQEBAQEBAQEHCQMCAwUFAgICBQICAgICAgIBAQEBCgECAwICAgUDAQARBgkBfwFBgIDAAAsHnQg5Bm1lbW9yeQIABWFsbG9jAB4FY2xlYXIAHwhjb21wbGV0ZQAgBmNyZWF0ZQAhB2RlYWxsb2MAIgdkZXN0cm95ACMEZmFpbAAkBmZpbmlzaAAlDmdldF9jaHVua19zaXplACYSZ2V0X2NvbnRlbnRfbGVuZ3RoACcOZ2V0X2Vycm9yX2NvZGUAKBlnZXRfZXJyb3JfZGVzY3JpcHRpb25fcmF3ACkUZ2V0X21heF9ib2R5X3BheWxvYWQAKhVnZXRfbWF4X2hlYWRlcl9sZW5ndGgAKxlnZXRfbWF4X3N0YXJ0X2xpbmVfbGVuZ3RoACwKZ2V0X21ldGhvZAAtCmdldF9wYXJzZWQALgxnZXRfcG9zaXRpb24ALxhnZXRfcmVtYWluaW5nX2NodW5rX3NpemUAMBxnZXRfcmVtYWluaW5nX2NvbnRlbnRfbGVuZ3RoADEJZ2V0X3N0YXRlADIKZ2V0X3N0YXR1cwAzHWhhc19jaHVua2VkX3RyYW5zZmVyX2VuY29kaW5nADQUaGFzX2Nvbm5lY3Rpb25fY2xvc2UANRZoYXNfY29ubmVjdGlvbl91cGdyYWRlADYSaGFzX2NvbnRlbnRfbGVuZ3RoADcMaGFzX3RyYWlsZXJzADgVaGFzX3RyYW5zZmVyX2VuY29kaW5nADkLaGFzX3VwZ3JhZGUAOg1pc19hdXRvZGV0ZWN0ADsKaXNfY29ubmVjdAA8CGlzX2RlYnVnAD0JaXNfcGF1c2VkAD4KaXNfcmVxdWVzdAA/Dm1pbG9faGFzX2RlYnVnAEAFcGFyc2UAQQVwYXVzZQBCBXJlc2V0AEMGcmVzdW1lAEQUc2V0X2FjdGl2ZV9jYWxsYmFja3MARRFzZXRfYWN0aXZlX2V2ZW50cwBGCXNldF9kZWJ1ZwBHDnNldF9pc19jb25uZWN0AEgOc2V0X2lzX3JlcXVlc3QASRRzZXRfbWF4X2JvZHlfcGF5bG9hZABKFXNldF9tYXhfaGVhZGVyX2xlbmd0aABLGXNldF9tYXhfc3RhcnRfbGluZV9sZW5ndGgATBVzZXRfc2hvdWxkX2F1dG9kZXRlY3QATSBzZXRfc2hvdWxkX2NvbnRpbnVlX3dpdGhvdXRfZGF0YQBOHHNldF9zaG91bGRfbWFuYWdlX3VuY29uc3VtZWQATxRzZXRfc2hvdWxkX3NraXBfYm9keQBQIHNldF9zaG91bGRfc3VzcGVuZF9hZnRlcl9oZWFkZXJzAFEcc2hvdWxkX2NvbnRpbnVlX3dpdGhvdXRfZGF0YQBSGHNob3VsZF9tYW5hZ2VfdW5jb25zdW1lZABTEHNob3VsZF9za2lwX2JvZHkAVBxzaG91bGRfc3VzcGVuZF9hZnRlcl9oZWFkZXJzAFUK1ckCQdgDAgJ/BXsCQCACIANPDQAgAS0AACEBIAMgAmsiBUEPTQRAIANBAWsDQCAB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IAQtAANBwwBHDQQgBC0ABEHIAEcNBEEJIQIMBgsgBC0AAUHSAEcNAyAELQACQcEARw0DIAQtAANBwwBHDQMgBC0ABEHFAEcNA0EIIQIMBQsgBC0AAEHEAEcNAiAELQABQcUARw0CIAQtAAJBzABHDQIgBC0AA0HFAEcNAiAELQAEQdQARw0CIAQtAAVBxQBHDQJBBSECDAQLAkACQCAELQAAQcMAaw4NAAMDAwMDAwMDAwMDAQMLIAQtAAFBzwBHDQIgBC0AAkHOAEcNAiAELQADQc4ARw0CIAQtAARBxQBHDQIgBC0ABUHDAEcNAiAELQAGQdQARw0CIANBAToAFUEGIQIMBAsgBC0AAUHQAEcNASAELQACQdQARw0BIAQtAANByQBHDQEgBC0ABEHPAEcNASAELQAFQc4ARw0BIAQtAAZB0wBHDQFBByECDAMLIAQtAAFBxQBGDQQLIANBADoATCAGIQEgBCECDAQLQQYhCCADQQY6ACYgA0ECOgAkIANBFjoA9AJBACECIANBADoAggEgA0GYisAA/QAAAP0LAGwgA0GmisAAKQAANwB6IAMpA1ggAykDYIRCAYOnDSIMIwtBAAshDyADIAI6AEwMAgsgAyAELQACQdQARiIJOgBMIAYhASAEIQIgCUUNAEEAIQ8MAQsCQANAIAItAAAtAICAQEUNASACQQFqIQIgAUEBayIBDQALQQAhDwwBC0EGIQggA0EGOgAmIANBAjoAJCADQRg6APQCQQAhAiADQQA6AIQBIANBuojAACkAADcAbCADQcKIwAD9AAAA/QsAdCADKQNYIAMpA2CEQgGDpw0eDB8LIA0gEWsiDSAOaiEJIAchASALIQICQANAIAIgCk8NHSACIARqLQAALQCAhkAEQCACQQFqIQIgAUEBayIBRQ0CDAELC0EGIQggA0EGOgAmIANBAjoAJCADQRU6APQCQQAhAiADQQA6AIEBIANB0ojAAP0AAAD9CwBsIANB34jAACkAADcAeSADKQNYIAMpA2CEQgGDpw0eDB8LAkAgEEEJaiATRgRAAkACQCATIA5rQQhHDQAgESkAACItQsio0YL1xYyXMFENASAtQsio0YL1pYyXMVINACAPRQ0DQREhCCADQRE6ACYgA0ECOgAkIANBHzoA9AJBACECIANBADoAiwEgA0HniMAAKQAANwBsIANB74jAAP0AAAD9CwB0IANB/ojAACkAADcAgwEgAykDWCADKQNghEIBg6cNIQwiC0EGIQggA0EGOgAmIANBAjoAJCADQRA6APQCQQAhAiADQQA6AHwgA0GeicAA/QAAAP0LAGwgAykDWCADKQNghEIBg6cNIAwhCyAPDQFBESEIIANBEToAJiADQQI6ACQgA0EYOgD0AkEAIQIgA0EAOgCEASADQYaJwAApAAA3AGwgA0GOicAA/QAAAP0LAHQgAykDWCADKQNghEIBg6cNHwwgC0EGIQggA0EGOgAmIANBAjoAJCADQRU6APQCQQAhAiADQQA6AIEBIANBronAAP0AAAD9CwBsIANBu4nAACkAADcAeSADKQNYIAMpA2CEQgGDpw0eDB8LAkAgIkUEQCAAIQEMAQsCQCA/UARAIAAhAgwBCyAAQQlqIgJBgIAETw0hIAMoAiAhASADKAL4AiAAakEIOgAAIAMoAvgCIABqQQFqIAE2AAAgAygC+AIgAGpBBWogBjYAAAsCQCA+UARAIAIhAAwBCyACQQlqIgBBgIAETwRAIAIhAAwiCyADKAIgIQEgAygC+AIgAmpBCToAACADKAL4AiACakEBaiABIAtqNgAAIAMoAvgCIAJqQQVqIAc2AAALAkAgOlAEQCAAIQIMAQsgAEEJaiICQYCABE8NISADKAIgIQEgAygC+AIgAGpBCjoAACADKAL4AiAAakEBaiABIA5qNgAAIAMoAvgCIABqQQVqIA02AAALIDlQBEAgAiEBDAELIAJBCWoiAUH//wNLBEAgAiEADCELIAMoAiAhACADKAL4AiACakELOgAAIAMoAvgCIAJqQQFqIAAgCUEBamo2AAAgAygC+AIgAmpBBWpBAzYAAAsgE0ECaiECIAMtACQhACADLQBMQQpGBEAgAEECRg0SIANBBToAJAwSCyAAQQJGDREgA0EGOgAkDBELIDRQBEAgAiEBDAELIAJBCWoiAUH//wNLBEAgAiEADB8LIAMoAiAhACADKAL4AiACakEDOgAAIAMoAvgCIAJqQQFqIAA2AAAgAygC+AIgAmpBBWpBADYAAAtBACEFIAMtACRBAkYNFSADQQQ6ACQMFQsgBC8AAEGNFEcNAEEAIQVBAiECDAoLIANBAToAEQJAIB1FBEAgACEBDAELAkAgN1AEQCAAIQIMAQsgAEEJaiICQYCABE8NHSADKAIgIQEgAygC+AIgAGpBBToAACADKAL4AiAAakEBaiABNgAAIAMoAvgCIABqQQVqQQA2AAALIDRQBEAgAiEBDAELIAJBCWoiAUH//wNLBEAgAiEADB0LIAMoAiAhACADKAL4AiACakEDOgAAIAMoAvgCIAJqQQFqIAA2AAAgAygC+AIgAmpBBWpBADYAAAtBACEFIAMtACRBAkYNEyADQQM6ACQMEwsgNFAEQCACIQEMEgsgAkEJaiIBQf//A0sEQCACIQAMGwsgAygCICEAIAMoAvgCIAJqQQM6AAAgAygC+AIgAmpBAWogADYAACADKAL4AiACakEFakEANgAADBELIDRQBEAgAiEBDAELIAJBCWoiAUH//wNLBEAgAiEADBoLIAMoAiAhACADKAL4AiACakEDOgAAIAMoAvgCIAJqQQFqIAA2AAAgAygC+AIgAmpBBWpBADYAAAtBACEFIAMtACRBAkYNECADQQM6ACQMEAsgAiAJayECIAMoAiAgCWohAEEPCyEFIAMoAvgCIAZqIAU6AAAgAygC+AIgBmpBAWogADYAACADKAL4AiAGakEFaiACNgAAC0EAIQUgB0ECaiICDQcMDQsgCCADKAIESQ0UQQYhCCADQQY6ACYgA0ECOgAkIANBFToA9AJBACECIANBADoAgQEgA0HMlMAA/QAAAP0LAGwgA0HZlMAAKQAANwB5IAMpA1ggAykDYIRCAYOnDRIMEwsgCCADKAIESQ0TQQYhCCADQQY6ACYgA0ECOgAkIANBFToA9AJBACECIANBADoAgQEgA0HMlMAA/QAAAP0LAGwgA0HZlMAAKQAANwB5IAMpA1ggAykDYIRCAYOnDREMEgsgLlANEiAuIC98IS8gLqchAkEAIQUgNlANACAAQQlqIgFB//8DSw0SIAMoAiAhBiADKAL4AiAAakEYOgAAIAMoAvgCIABqQQFqIAY2AAAgAygC+AIgAGpBBWogAjYAAAwECyAAIQEMAwsgLlANECAuIC98IS8gLqchAgJAAkACQAJAIC4gM1oEQCA2QgBSDQEgACEFDAQLIDZCAFINASAAIQEMAgsgAEEJaiIFQYCABE8NEyADKAIgIQEgAygC+AIgAGpBGDoAACADKAL4AiAAakEBaiABNgAAIAMoAvgCIABqQQVqIAI2AAAM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AgAhAAJAIAEgBWsiAkEPTQRAQdybwABBADYCAEHUm8AAQQA2AgAgACABQQNyNgIEIAAgAWoiASABKAIEQQFyNgIEDAELQdSbwAAgAjYCAEHcm8AAIAAgBWoiBDYCACAEIAJBAXI2AgQgACABaiACNgIAIAAgBUEDcjYCBAsgAEEIaiEADAULIAAgBCAGajYCBEHgm8AAQeCbwAAoAgAiAEEPakF4cSIBQQhrIgI2AgBB2JvAAEHYm8AAKAIAIARqIgQgACABa2pBCGoiATYCACACIAFBAXI2AgQgACAEakEoNgIEQeybwABBgICAATYCAAwDC0Hgm8AAIAA2AgBB2JvAAEHYm8AAKAIAIAVqIgE2AgAgACABQQFyNgIEDAELQdybwAAgADYCAEHUm8AAQdSbwAAoAgAgBWoiATYCACAAIAFBAXI2AgQgACABaiABNgIACyAEQQhqIQAMAQtBACEAQdibwAAoAgAiASAFTQ0AQdibwAAgASAFayIBNgIAQeCbwABB4JvAACgCACIAIAVqIgI2AgAgAiABQQFyNgIEIAAgBUEDcjYCBCAAQQhqIQALIAhBEGokACAACz0BAn8CQCAAQQRrKAIAIgJBeHEiA0EEQQggAkEDcSICGyABakkNACACQQAgAyABQSdqSxsNACAAEFkPCwALogYBBH8gAEEIayIBIABBBGsoAgAiA0F4cSIAaiECAkACQCADQQFxDQAgA0ECcUUNASABKAIAIgMgAGohACABIANrIgFB3JvAACgCAEYEQCACKAIEQQNxQQNHDQFB1JvAACAANgIAIAIgAigCBEF+cTYCBCABIABBAXI2AgQgAiAANgIADwsgASADEFoLAkACQEH0m8AAAn8CQAJAAkACQCACKAIEIgNBAnFFBEAgAkHgm8AAKAIARg0CIAJB3JvAACgCAEYNAyACIANBeHEiAhBaIAEgACACaiIAQQFyNgIEIAAgAWogADYCACABQdybwAAoAgBHDQFB1JvAACAANgIADwsgAiADQX5xNgIEIAEgAEEBcjYCBCAAIAFqIAA2AgALIABBgAJJDQQgASAAEFxB9JvAAEH0m8AAKAIAQQFrIgA2AgAgAA0GQbyZwAAoAgAiAA0CQf8fDAMLQeCbwAAgATYCAEHYm8AAQdibwAAoAgAgAGoiADYCACABIABBAXI2AgRB3JvA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AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAQYmEwAALAQEAQaCEwAAL4AEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQBBoYbAAAteAQAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQABAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAQBBgIjAAAu0EFVuZXhwZWN0ZWQgZW5kIG9mIGRhdGFVbmV4cGVjdGVkIGRhdGFSZXF1ZXN0IGxpbmUgdG9vIGxvbmdJbnZhbGlkIG1ldGhvZCBjaGFyYWN0ZXJJbnZhbGlkIFVSTCBjaGFyYWN0ZXJQUkkgaXMgb25seSB2YWxpZCB3aXRoIEhUVFAvMi4wVW5zdXBwb3J0ZWQgSFRUUCB2ZXJzaW9uSW52YWxpZCBwcm90b2NvbEludmFsaWQgcHJvdG9jb2wgbmFtZUV4cGVjdGVkIC8gYWZ0ZXIgdGhlIHByb3RvY29sIG5hbWVFeHBlY3RlZCBzcGFjZSBhZnRlciBVUkxFeHBlY3RlZCBzcGFjZSBhZnRlciBtZXRob2RSZXF1ZXN0IGxpbmUgdG9vIHNob3J0RXhwZWN0ZWQgQ1JMRlN0YXR1cyBsaW5lIHRvbyBsb25nSW52YWxpZCBIVFRQIHJlc3BvbnNlIHN0YXR1c0ludmFsaWQgc3RhdHVzIHJlYXNvbiBjaGFyYWN0ZXJFeHBlY3RlZCBhIHNwYWNlIGFmdGVyIEhUVFAgcmVzcG9uc2Ugc3RhdHVzRXhwZWN0ZWQgc3BhY2UgYWZ0ZXIgcHJvdG9jb2xTdGF0dXMgbGluZSB0b28gc2hvcnRNYWxmb3JtZWQgSFRUUC8yLjAgcHJlZmFjZVVuZXhwZWN0ZWQgQ29udGVudC1MZW5ndGggaGVhZGVyIGZvciBhIHJlc3BvbnNlIHdpdGhvdXQgYm9keUV4cGVjdGVkIENvbnRlbnQtTGVuZ3RoIGhlYWRlciB2YWx1ZUludmFsaWQgQ29udGVudC1MZW5ndGggaGVhZGVySW52YWxpZCBkdXBsaWNhdGUgQ29udGVudC1MZW5ndGggaGVhZGVyVW5leHBlY3RlZCBDb250ZW50LUxlbmd0aCBoZWFkZXIgd2hlbiBUcmFuc2Zlci1FbmNvZGluZyBoZWFkZXIgaXMgcHJlc2VudFVuZXhwZWN0ZWQgVHJhbnNmZXItRW5jb2RpbmcgaGVhZGVyIGZvciBhIHJlc3BvbnNlIHdpdGhvdXQgYm9keUV4cGVjdGVkIFRyYW5zZmVyLUVuY29kaW5nIGhlYWRlciB2YWx1ZVRoZSB2YWx1ZSAiY2h1bmtlZCIgaW4gdGhlIFRyYW5zZmVyLUVuY29kaW5nIGhlYWRlciBtdXN0IGJlIHRoZSBsYXN0IHByb3ZpZGVkIGFuZCBjYW4gYmUgcHJvdmlkZWQgb25seSBvbmNlVGhlIHZhbHVlICJjaHVua2VkIiBpbiB0aGUgVHJhbnNmZXItRW5jb2RpbmcgaGVhZGVyIG11c3QgYmUgdGhlIGxhc3QgcHJvdmlkZWRVbmV4cGVjdGVkIFRyYW5zZmVyLUVuY29kaW5nIGhlYWRlciB3aGVuIENvbnRlbnQtTGVuZ3RoIGhlYWRlciBpcyBwcmVzZW50RXhwZWN0ZWQgQ29ubmVjdGlvbiBoZWFkZXIgdmFsdWVJbnZhbGlkIENvbm5lY3Rpb24gaGVhZGVyIHZhbHVlRXhwZWN0ZWQgVHJhaWxlciBoZWFkZXIgdmFsdWVFeHBlY3RlZCBVcGdyYWRlIGhlYWRlciB2YWx1ZUludmFsaWQgVXBncmFkZSBoZWFkZXIgdmFsdWVJbnZhbGlkIGhlYWRlciBmaWVsZCBuYW1lIGNoYXJhY3RlckludmFsaWQgaGVhZGVyIGZpZWxkIHZhbHVlIGNoYXJhY3RlckhlYWRlciBsaW5lIHRvbyBsb25nTWlzc2luZyBDb25uZWN0aW9uIGhlYWRlciBzZXQgdG8gInVwZ3JhZGUiIHdoZW4gdXNpbmcgdGhlIFVwZ3JhZGUgaGVhZGVyVHJhaWxlcnMgYXJlIG5vdCBhbGxvd2VkIHdoZW4gbm90IHVzaW5nIGNodW5rZWQgdHJhbnNmZXIgZW5jb2RpbmdVbmV4cGVjdGVkIGNvbnRlbnQgZm9yIHRoZSByZXF1ZXN0IChHRVQgb3IgSEVBRClUcmFuc2Zlci1FbmNvZGluZyBsYXN0IGhlYWRlciB2YWx1ZSBtdXN0IGJlICJjaHVua2VkIiBpZiB0aGUgaGVhZGVyIGlzIHByZXNlbnRDaHVuayBoZWFkZXIgdG9vIGxvbmdJbnZhbGlkIGNodW5rIGxlbmd0aCBjaGFyYWN0ZXJJbnZhbGlkIGNodW5rIGxlbmd0aCBzaXplRXhwZWN0ZWQgY2h1bmsgZXh0ZW5zaW9uIG5hbWVJbnZhbGlkIGNodW5rIGV4dGVuc2lvbiBuYW1lIGNoYXJhY3RlckV4cGVjdGVkIGNsb3NpbmcgcXVvdGUgZm9yIGNodW5rIGV4dGVuc2lvbiB2YWx1ZUludmFsaWQgY2h1bmsgZXh0ZW5zaW9uIHF1b3RlZCB2YWx1ZSBjaGFyYWN0ZXJFeHBlY3RlZCBjaHVuayBleHRlbnNpb24gdmFsdWVJbnZhbGlkIGNodW5rIGV4dGVuc2lvbiB2YWx1ZSBjaGFyYWN0ZXJJbnZhbGlkIGNodW5rIGV4dGVuc2lvbiBjaGFyYWN0ZXIgYWZ0ZXIgdmFsdWVFeHBlY3RlZCBDUkxGIGFmdGVyIGNodW5rIGRhdGFJbnZhbGlkIHRyYWlsZXIgZmllbGQgbmFtZSBjaGFyYWN0ZXJJbnZhbGlkIHRyYWlsZXIgZmllbGQgdmFsdWUgY2hhcmFjdGVyVHJhaWxlciBsaW5lIHRvbyBsb25nSW52YWxpZCBzdGF0ZQ==', + 'base64' + ) +) + +const textEncoder = new TextEncoder() +const textDecoder = new TextDecoder() + +function log (logger, raw) { + const len = Number(BigInt.asUintN(32, raw)) + const ptr = Number(raw >> 32n) + + logger(textDecoder.decode(new Uint8Array(this.memory.buffer, ptr, len))) +} + +function alloc (len) { + return this.alloc(len) >>> 0 +} + +function dealloc (ptr) { + return this.dealloc(ptr) +} + +function create () { + return this.create() >>> 0 +} + +function destroy (parser) { + this.destroy(parser) +} + +function parse (parser, data, limit) { + return this.parse(parser, data, limit) >>> 0 +} + +function fail (parser, code, description) { + const len = description.length + const ptr = this.alloc(len) + const buffer = new Uint8Array(this.memory.buffer, ptr, len) + textEncoder.encodeInto(description, buffer) + + this.fail(parser, code, ptr, len) + this.dealloc(ptr, len) +} + +function hasDebug () { + return this.milo_has_debug() !== 0 +} + +const Errors = Object.freeze({ + NONE: 0, + USER: 1, + CALLBACK_ERROR: 2, + UNEXPECTED_STATE: 3, + UNEXPECTED_DATA: 4, + UNEXPECTED_EOF: 5, + UNEXPECTED_CHARACTER: 6, + UNEXPECTED_CONTENT_LENGTH: 7, + UNEXPECTED_TRANSFER_ENCODING: 8, + UNEXPECTED_CONTENT: 9, + UNEXPECTED_TRAILERS: 10, + INVALID_VERSION: 11, + INVALID_STATUS: 12, + INVALID_CONTENT_LENGTH: 13, + INVALID_TRANSFER_ENCODING: 14, + INVALID_CHUNK_SIZE: 15, + MISSING_CONNECTION_UPGRADE: 16, + UNSUPPORTED_HTTP_VERSION: 17, + 0: 'NONE', + 1: 'USER', + 2: 'CALLBACK_ERROR', + 3: 'UNEXPECTED_STATE', + 4: 'UNEXPECTED_DATA', + 5: 'UNEXPECTED_EOF', + 6: 'UNEXPECTED_CHARACTER', + 7: 'UNEXPECTED_CONTENT_LENGTH', + 8: 'UNEXPECTED_TRANSFER_ENCODING', + 9: 'UNEXPECTED_CONTENT', + 10: 'UNEXPECTED_TRAILERS', + 11: 'INVALID_VERSION', + 12: 'INVALID_STATUS', + 13: 'INVALID_CONTENT_LENGTH', + 14: 'INVALID_TRANSFER_ENCODING', + 15: 'INVALID_CHUNK_SIZE', + 16: 'MISSING_CONNECTION_UPGRADE', + 17: 'UNSUPPORTED_HTTP_VERSION' +}) + +const Methods = Object.freeze({ + OTHER: 0, + GET: 1, + HEAD: 2, + POST: 3, + PUT: 4, + DELETE: 5, + CONNECT: 6, + OPTIONS: 7, + TRACE: 8, + PATCH: 9, + PRI: 10, + 0: 'OTHER', + 1: 'GET', + 2: 'HEAD', + 3: 'POST', + 4: 'PUT', + 5: 'DELETE', + 6: 'CONNECT', + 7: 'OPTIONS', + 8: 'TRACE', + 9: 'PATCH', + 10: 'PRI' +}) + +const Callbacks = Object.freeze({ + ON_ERROR: 0, + ON_FINISH: 1, + ON_MESSAGE_START: 2, + ON_MESSAGE_COMPLETE: 3, + ON_REQUEST: 4, + ON_RESPONSE: 5, + ON_RESET: 6, + ON_METHOD: 7, + ON_URL: 8, + ON_PROTOCOL: 9, + ON_VERSION: 10, + ON_STATUS: 11, + ON_REASON: 12, + ON_HEADER_NAME: 13, + ON_HEADER_VALUE: 14, + ON_HEADERS: 15, + ON_CONNECT: 16, + ON_UPGRADE: 17, + ON_CHUNK_LENGTH: 18, + ON_CHUNK_EXTENSION_NAME: 19, + ON_CHUNK_EXTENSION_VALUE: 20, + ON_CHUNK: 21, + ON_BODY: 22, + ON_DATA: 23, + ON_TRAILER_NAME: 24, + ON_TRAILER_VALUE: 25, + ON_TRAILERS: 26, + ON_STATE_CHANGE: 27, + 0: 'ON_ERROR', + 1: 'ON_FINISH', + 2: 'ON_MESSAGE_START', + 3: 'ON_MESSAGE_COMPLETE', + 4: 'ON_REQUEST', + 5: 'ON_RESPONSE', + 6: 'ON_RESET', + 7: 'ON_METHOD', + 8: 'ON_URL', + 9: 'ON_PROTOCOL', + 10: 'ON_VERSION', + 11: 'ON_STATUS', + 12: 'ON_REASON', + 13: 'ON_HEADER_NAME', + 14: 'ON_HEADER_VALUE', + 15: 'ON_HEADERS', + 16: 'ON_CONNECT', + 17: 'ON_UPGRADE', + 18: 'ON_CHUNK_LENGTH', + 19: 'ON_CHUNK_EXTENSION_NAME', + 20: 'ON_CHUNK_EXTENSION_VALUE', + 21: 'ON_CHUNK', + 22: 'ON_BODY', + 23: 'ON_DATA', + 24: 'ON_TRAILER_NAME', + 25: 'ON_TRAILER_VALUE', + 26: 'ON_TRAILERS', + 27: 'ON_STATE_CHANGE' +}) + +const CallbackActives = Object.freeze({ + NONE: 0n, + ON_ERROR: 1n, + ON_FINISH: 2n, + ON_MESSAGE_START: 4n, + ON_MESSAGE_COMPLETE: 8n, + ON_REQUEST: 16n, + ON_RESPONSE: 32n, + ON_RESET: 64n, + ON_METHOD: 128n, + ON_URL: 256n, + ON_PROTOCOL: 512n, + ON_VERSION: 1024n, + ON_STATUS: 2048n, + ON_REASON: 4096n, + ON_HEADER_NAME: 8192n, + ON_HEADER_VALUE: 16384n, + ON_HEADERS: 32768n, + ON_CONNECT: 65536n, + ON_UPGRADE: 131072n, + ON_CHUNK_LENGTH: 262144n, + ON_CHUNK_EXTENSION_NAME: 524288n, + ON_CHUNK_EXTENSION_VALUE: 1048576n, + ON_CHUNK: 2097152n, + ON_BODY: 4194304n, + ON_DATA: 8388608n, + ON_TRAILER_NAME: 16777216n, + ON_TRAILER_VALUE: 33554432n, + ON_TRAILERS: 67108864n, + ON_STATE_CHANGE: 134217728n, + ALL: 268435455n, + 0n: 'NONE', + 1n: 'ON_ERROR', + 2n: 'ON_FINISH', + 4n: 'ON_MESSAGE_START', + 8n: 'ON_MESSAGE_COMPLETE', + 16n: 'ON_REQUEST', + 32n: 'ON_RESPONSE', + 64n: 'ON_RESET', + 128n: 'ON_METHOD', + 256n: 'ON_URL', + 512n: 'ON_PROTOCOL', + 1024n: 'ON_VERSION', + 2048n: 'ON_STATUS', + 4096n: 'ON_REASON', + 8192n: 'ON_HEADER_NAME', + 16384n: 'ON_HEADER_VALUE', + 32768n: 'ON_HEADERS', + 65536n: 'ON_CONNECT', + 131072n: 'ON_UPGRADE', + 262144n: 'ON_CHUNK_LENGTH', + 524288n: 'ON_CHUNK_EXTENSION_NAME', + 1048576n: 'ON_CHUNK_EXTENSION_VALUE', + 2097152n: 'ON_CHUNK', + 4194304n: 'ON_BODY', + 8388608n: 'ON_DATA', + 16777216n: 'ON_TRAILER_NAME', + 33554432n: 'ON_TRAILER_VALUE', + 67108864n: 'ON_TRAILERS', + 134217728n: 'ON_STATE_CHANGE', + 268435455n: 'ALL' +}) + +const Events = Object.freeze({ + END: 0, + ERROR: 1, + FINISH: 2, + MESSAGE_START: 3, + MESSAGE_COMPLETE: 4, + REQUEST: 5, + RESPONSE: 6, + RESET: 7, + METHOD: 8, + URL: 9, + PROTOCOL: 10, + VERSION: 11, + STATUS: 12, + REASON: 13, + HEADER_NAME: 14, + HEADER_VALUE: 15, + HEADERS: 16, + CONNECT: 17, + UPGRADE: 18, + CHUNK_LENGTH: 19, + CHUNK_EXTENSION_NAME: 20, + CHUNK_EXTENSION_VALUE: 21, + CHUNK: 22, + BODY: 23, + DATA: 24, + TRAILER_NAME: 25, + TRAILER_VALUE: 26, + TRAILERS: 27, + STATE_CHANGE: 28, + 0: 'END', + 1: 'ERROR', + 2: 'FINISH', + 3: 'MESSAGE_START', + 4: 'MESSAGE_COMPLETE', + 5: 'REQUEST', + 6: 'RESPONSE', + 7: 'RESET', + 8: 'METHOD', + 9: 'URL', + 10: 'PROTOCOL', + 11: 'VERSION', + 12: 'STATUS', + 13: 'REASON', + 14: 'HEADER_NAME', + 15: 'HEADER_VALUE', + 16: 'HEADERS', + 17: 'CONNECT', + 18: 'UPGRADE', + 19: 'CHUNK_LENGTH', + 20: 'CHUNK_EXTENSION_NAME', + 21: 'CHUNK_EXTENSION_VALUE', + 22: 'CHUNK', + 23: 'BODY', + 24: 'DATA', + 25: 'TRAILER_NAME', + 26: 'TRAILER_VALUE', + 27: 'TRAILERS', + 28: 'STATE_CHANGE' +}) + +const EventActives = Object.freeze({ + NONE: 0n, + ON_ERROR: 1n, + ON_FINISH: 2n, + ON_MESSAGE_START: 4n, + ON_MESSAGE_COMPLETE: 8n, + ON_REQUEST: 16n, + ON_RESPONSE: 32n, + ON_RESET: 64n, + ON_METHOD: 128n, + ON_URL: 256n, + ON_PROTOCOL: 512n, + ON_VERSION: 1024n, + ON_STATUS: 2048n, + ON_REASON: 4096n, + ON_HEADER_NAME: 8192n, + ON_HEADER_VALUE: 16384n, + ON_HEADERS: 32768n, + ON_CONNECT: 65536n, + ON_UPGRADE: 131072n, + ON_CHUNK_LENGTH: 262144n, + ON_CHUNK_EXTENSION_NAME: 524288n, + ON_CHUNK_EXTENSION_VALUE: 1048576n, + ON_CHUNK: 2097152n, + ON_BODY: 4194304n, + ON_DATA: 8388608n, + ON_TRAILER_NAME: 16777216n, + ON_TRAILER_VALUE: 33554432n, + ON_TRAILERS: 67108864n, + ON_STATE_CHANGE: 134217728n, + ALL: 268435455n, + 0n: 'NONE', + 1n: 'ON_ERROR', + 2n: 'ON_FINISH', + 4n: 'ON_MESSAGE_START', + 8n: 'ON_MESSAGE_COMPLETE', + 16n: 'ON_REQUEST', + 32n: 'ON_RESPONSE', + 64n: 'ON_RESET', + 128n: 'ON_METHOD', + 256n: 'ON_URL', + 512n: 'ON_PROTOCOL', + 1024n: 'ON_VERSION', + 2048n: 'ON_STATUS', + 4096n: 'ON_REASON', + 8192n: 'ON_HEADER_NAME', + 16384n: 'ON_HEADER_VALUE', + 32768n: 'ON_HEADERS', + 65536n: 'ON_CONNECT', + 131072n: 'ON_UPGRADE', + 262144n: 'ON_CHUNK_LENGTH', + 524288n: 'ON_CHUNK_EXTENSION_NAME', + 1048576n: 'ON_CHUNK_EXTENSION_VALUE', + 2097152n: 'ON_CHUNK', + 4194304n: 'ON_BODY', + 8388608n: 'ON_DATA', + 16777216n: 'ON_TRAILER_NAME', + 33554432n: 'ON_TRAILER_VALUE', + 67108864n: 'ON_TRAILERS', + 134217728n: 'ON_STATE_CHANGE', + 268435455n: 'ALL' +}) + +const States = Object.freeze({ + START: 0, + FINISH: 1, + ERROR: 2, + REQUEST_LINE: 3, + STATUS_LINE: 4, + HTTP2_PREFACE: 5, + HEADER: 6, + BODY_DECISION: 7, + BODY_VIA_CONTENT_LENGTH: 8, + BODY_WITH_NO_LENGTH: 9, + CHUNK_HEADER: 10, + CHUNK_EXTENSIONS: 11, + CHUNK_DATA: 12, + TRAILER: 13, + TUNNEL: 14, + 0: 'START', + 1: 'FINISH', + 2: 'ERROR', + 3: 'REQUEST_LINE', + 4: 'STATUS_LINE', + 5: 'HTTP2_PREFACE', + 6: 'HEADER', + 7: 'BODY_DECISION', + 8: 'BODY_VIA_CONTENT_LENGTH', + 9: 'BODY_WITH_NO_LENGTH', + 10: 'CHUNK_HEADER', + 11: 'CHUNK_EXTENSIONS', + 12: 'CHUNK_DATA', + 13: 'TRAILER', + 14: 'TUNNEL' +}) + +const ParserFields = Object.freeze({ + MAX_START_LINE_LENGTH: 0, + MAX_HEADER_LENGTH: 4, + MAX_BODY_PAYLOAD: 8, + AUTODETECT: 16, + IS_REQUEST: 17, + SUSPEND_AFTER_HEADERS: 18, + MANAGE_UNCONSUMED: 19, + CONTINUE_WITHOUT_DATA: 20, + IS_CONNECT: 21, + SKIP_BODY: 22, + DEBUG: 23, + PARSED: 24, + POSITION: 32, + STATE: 36, + PAUSED: 37, + ERROR_CODE: 38, + CONTENT_LENGTH: 40, + CHUNK_SIZE: 48, + REMAINING_CONTENT_LENGTH: 56, + REMAINING_CHUNK_SIZE: 64, + STATUS: 72, + METHOD: 76, + HAS_CONTENT_LENGTH: 77, + HAS_TRANSFER_ENCODING: 78, + HAS_CHUNKED_TRANSFER_ENCODING: 79, + HAS_CONNECTION_CLOSE: 80, + HAS_CONNECTION_UPGRADE: 81, + HAS_UPGRADE: 82, + HAS_TRAILERS: 83, + ACTIVE_CALLBACKS: 88, + ACTIVE_EVENTS: 96, + PTR: 104, + ERROR_DESCRIPTION: 108, + UNCONSUMED: 364, + UNCONSUMED_LEN: 368, + ERROR_DESCRIPTION_LEN: 372, + EVENTS: 376, + 0: 'MAX_START_LINE_LENGTH', + 4: 'MAX_HEADER_LENGTH', + 8: 'MAX_BODY_PAYLOAD', + 16: 'AUTODETECT', + 17: 'IS_REQUEST', + 18: 'SUSPEND_AFTER_HEADERS', + 19: 'MANAGE_UNCONSUMED', + 20: 'CONTINUE_WITHOUT_DATA', + 21: 'IS_CONNECT', + 22: 'SKIP_BODY', + 23: 'DEBUG', + 24: 'PARSED', + 32: 'POSITION', + 36: 'STATE', + 37: 'PAUSED', + 38: 'ERROR_CODE', + 40: 'CONTENT_LENGTH', + 48: 'CHUNK_SIZE', + 56: 'REMAINING_CONTENT_LENGTH', + 64: 'REMAINING_CHUNK_SIZE', + 72: 'STATUS', + 76: 'METHOD', + 77: 'HAS_CONTENT_LENGTH', + 78: 'HAS_TRANSFER_ENCODING', + 79: 'HAS_CHUNKED_TRANSFER_ENCODING', + 80: 'HAS_CONNECTION_CLOSE', + 81: 'HAS_CONNECTION_UPGRADE', + 82: 'HAS_UPGRADE', + 83: 'HAS_TRAILERS', + 88: 'ACTIVE_CALLBACKS', + 96: 'ACTIVE_EVENTS', + 104: 'PTR', + 108: 'ERROR_DESCRIPTION', + 364: 'UNCONSUMED', + 368: 'UNCONSUMED_LEN', + 372: 'ERROR_DESCRIPTION_LEN', + 376: 'EVENTS' +}) + +function isAutodetect (parser) { + return this.is_autodetect(parser) !== 0 +} + +function isRequest (parser) { + return this.is_request(parser) !== 0 +} + +function isPaused (parser) { + return this.is_paused(parser) !== 0 +} + +function shouldManageUnconsumed (parser) { + return this.should_manage_unconsumed(parser) !== 0 +} + +function shouldSuspendAfterHeaders (parser) { + return this.should_suspend_after_headers(parser) !== 0 +} + +function getMaxStartLineLength (parser) { + return this.get_max_start_line_length(parser) >>> 0 +} + +function getMaxHeaderLength (parser) { + return this.get_max_header_length(parser) >>> 0 +} + +function getMaxBodyPayload (parser) { + return BigInt.asUintN(64, this.get_max_body_payload(parser)) +} + +function shouldContinueWithoutData (parser) { + return this.should_continue_without_data(parser) !== 0 +} + +function isConnect (parser) { + return this.is_connect(parser) !== 0 +} + +function isDebug (parser) { + return this.is_debug(parser) !== 0 +} + +function shouldSkipBody (parser) { + return this.should_skip_body(parser) !== 0 +} + +function getState (parser) { + return this.get_state(parser) >>> 0 +} + +function getPosition (parser) { + return this.get_position(parser) >>> 0 +} + +function getParsed (parser) { + return BigInt.asUintN(64, this.get_parsed(parser)) +} + +function getErrorCode (parser) { + return this.get_error_code(parser) >>> 0 +} + +function getMethod (parser) { + return this.get_method(parser) >>> 0 +} + +function getStatus (parser) { + return this.get_status(parser) >>> 0 +} + +function hasConnectionClose (parser) { + return this.has_connection_close(parser) !== 0 +} + +function hasConnectionUpgrade (parser) { + return this.has_connection_upgrade(parser) !== 0 +} + +function getContentLength (parser) { + return BigInt.asUintN(64, this.get_content_length(parser)) +} + +function getChunkSize (parser) { + return BigInt.asUintN(64, this.get_chunk_size(parser)) +} + +function getRemainingContentLength (parser) { + return BigInt.asUintN(64, this.get_remaining_content_length(parser)) +} + +function getRemainingChunkSize (parser) { + return BigInt.asUintN(64, this.get_remaining_chunk_size(parser)) +} + +function hasContentLength (parser) { + return this.has_content_length(parser) !== 0 +} + +function hasTransferEncoding (parser) { + return this.has_transfer_encoding(parser) !== 0 +} + +function hasChunkedTransferEncoding (parser) { + return this.has_chunked_transfer_encoding(parser) !== 0 +} + +function hasUpgrade (parser) { + return this.has_upgrade(parser) !== 0 +} + +function hasTrailers (parser) { + return this.has_trailers(parser) !== 0 +} + +function getErrorDescription (parser) { + const raw = this.get_error_description_raw(parser) + const len = Number(BigInt.asUintN(32, raw)) + const ptr = Number(raw >> 32n) + return textDecoder.decode(new Uint8Array(this.memory.buffer, ptr, len)) +} + +function setShouldAutodetect (parser, value) { + this.set_should_autodetect(parser, value) +} + +function setShouldContinueWithoutData (parser, value) { + this.set_should_continue_without_data(parser, value) +} + +function setIsRequest (parser, value) { + this.set_is_request(parser, value) +} + +function setIsConnect (parser, value) { + this.set_is_connect(parser, value) +} + +function setDebug (parser, value) { + this.set_debug(parser, value) +} + +function setShouldManageUnconsumed (parser, value) { + this.set_should_manage_unconsumed(parser, value) +} + +function setShouldSuspendAfterHeaders (parser, value) { + this.set_should_suspend_after_headers(parser, value) +} + +function setMaxStartLineLength (parser, value) { + this.set_max_start_line_length(parser, value) +} + +function setMaxHeaderLength (parser, value) { + this.set_max_header_length(parser, value) +} + +function setMaxBodyPayload (parser, value) { + this.set_max_body_payload(parser, value) +} + +function setShouldSkipBody (parser, value) { + this.set_should_skip_body(parser, value) +} + +function setActiveCallbacks (parser, value) { + this.set_active_callbacks(parser, value) +} + +function setActiveEvents (parser, value) { + this.set_active_events(parser, value) +} + +function simpleCreate (spans, create) { + const parser = create() + spans[parser] = [] + this.setActiveCallbacks(parser, this.CALLBACK_ACTIVE_ALL) + return parser +} + +function simpleDestroy (spans, destroy, parser) { + spans[parser] = undefined + destroy(parser) +} + +function noop () {} + +function setup (env = {}) { + let { logger: logOption, ...instanceEnvironment } = env + let logger = noop + const context = {} + + if (logOption) { + if (typeof logOption !== 'function') { + logOption = console.log + } + + logger = log.bind(context, logOption) + } + + // Create the WASM instance + /* eslint-disable-next-line no-undef */ + const instance = new WebAssembly.Instance(wasmModule, { + env: { + logger, + on_error: noop, + on_finish: noop, + on_message_start: noop, + on_message_complete: noop, + on_request: noop, + on_response: noop, + on_reset: noop, + on_method: noop, + on_url: noop, + on_protocol: noop, + on_version: noop, + on_status: noop, + on_reason: noop, + on_header_name: noop, + on_header_value: noop, + on_headers: noop, + on_connect: noop, + on_upgrade: noop, + on_chunk_length: noop, + on_chunk_extension_name: noop, + on_chunk_extension_value: noop, + on_chunk: noop, + on_body: noop, + on_data: noop, + on_trailer_name: noop, + on_trailer_value: noop, + on_trailers: noop, + on_state_change: noop, + ...instanceEnvironment + } + }) + + const wasm = instance.exports + context.memory = wasm.memory + + const milo = { + version: { + raw: '0.8.0', + major: 0, + minor: 8, + patch: 0, + prerelease: '' + }, + METHOD_OTHER: 0, + METHOD_GET: 1, + METHOD_HEAD: 2, + METHOD_POST: 3, + METHOD_PUT: 4, + METHOD_DELETE: 5, + METHOD_CONNECT: 6, + METHOD_OPTIONS: 7, + METHOD_TRACE: 8, + METHOD_PATCH: 9, + METHOD_PRI: 10, + CALLBACK_ON_ERROR: 0, + CALLBACK_ON_FINISH: 1, + CALLBACK_ON_MESSAGE_START: 2, + CALLBACK_ON_MESSAGE_COMPLETE: 3, + CALLBACK_ON_REQUEST: 4, + CALLBACK_ON_RESPONSE: 5, + CALLBACK_ON_RESET: 6, + CALLBACK_ON_METHOD: 7, + CALLBACK_ON_URL: 8, + CALLBACK_ON_PROTOCOL: 9, + CALLBACK_ON_VERSION: 10, + CALLBACK_ON_STATUS: 11, + CALLBACK_ON_REASON: 12, + CALLBACK_ON_HEADER_NAME: 13, + CALLBACK_ON_HEADER_VALUE: 14, + CALLBACK_ON_HEADERS: 15, + CALLBACK_ON_CONNECT: 16, + CALLBACK_ON_UPGRADE: 17, + CALLBACK_ON_CHUNK_LENGTH: 18, + CALLBACK_ON_CHUNK_EXTENSION_NAME: 19, + CALLBACK_ON_CHUNK_EXTENSION_VALUE: 20, + CALLBACK_ON_CHUNK: 21, + CALLBACK_ON_BODY: 22, + CALLBACK_ON_DATA: 23, + CALLBACK_ON_TRAILER_NAME: 24, + CALLBACK_ON_TRAILER_VALUE: 25, + CALLBACK_ON_TRAILERS: 26, + CALLBACK_ON_STATE_CHANGE: 27, + EVENT_END: 0, + EVENT_ERROR: 1, + EVENT_FINISH: 2, + EVENT_MESSAGE_START: 3, + EVENT_MESSAGE_COMPLETE: 4, + EVENT_REQUEST: 5, + EVENT_RESPONSE: 6, + EVENT_RESET: 7, + EVENT_METHOD: 8, + EVENT_URL: 9, + EVENT_PROTOCOL: 10, + EVENT_VERSION: 11, + EVENT_STATUS: 12, + EVENT_REASON: 13, + EVENT_HEADER_NAME: 14, + EVENT_HEADER_VALUE: 15, + EVENT_HEADERS: 16, + EVENT_CONNECT: 17, + EVENT_UPGRADE: 18, + EVENT_CHUNK_LENGTH: 19, + EVENT_CHUNK_EXTENSION_NAME: 20, + EVENT_CHUNK_EXTENSION_VALUE: 21, + EVENT_CHUNK: 22, + EVENT_BODY: 23, + EVENT_DATA: 24, + EVENT_TRAILER_NAME: 25, + EVENT_TRAILER_VALUE: 26, + EVENT_TRAILERS: 27, + EVENT_STATE_CHANGE: 28, + CALLBACK_ACTIVE_NONE: 0n, + EVENT_ACTIVE_NONE: 0n, + CALLBACK_ACTIVE_ON_ERROR: 1n, + EVENT_ACTIVE_ON_ERROR: 1n, + CALLBACK_ACTIVE_ON_FINISH: 2n, + EVENT_ACTIVE_ON_FINISH: 2n, + CALLBACK_ACTIVE_ON_MESSAGE_START: 4n, + EVENT_ACTIVE_ON_MESSAGE_START: 4n, + CALLBACK_ACTIVE_ON_MESSAGE_COMPLETE: 8n, + EVENT_ACTIVE_ON_MESSAGE_COMPLETE: 8n, + CALLBACK_ACTIVE_ON_REQUEST: 16n, + EVENT_ACTIVE_ON_REQUEST: 16n, + CALLBACK_ACTIVE_ON_RESPONSE: 32n, + EVENT_ACTIVE_ON_RESPONSE: 32n, + CALLBACK_ACTIVE_ON_RESET: 64n, + EVENT_ACTIVE_ON_RESET: 64n, + CALLBACK_ACTIVE_ON_METHOD: 128n, + EVENT_ACTIVE_ON_METHOD: 128n, + CALLBACK_ACTIVE_ON_URL: 256n, + EVENT_ACTIVE_ON_URL: 256n, + CALLBACK_ACTIVE_ON_PROTOCOL: 512n, + EVENT_ACTIVE_ON_PROTOCOL: 512n, + CALLBACK_ACTIVE_ON_VERSION: 1024n, + EVENT_ACTIVE_ON_VERSION: 1024n, + CALLBACK_ACTIVE_ON_STATUS: 2048n, + EVENT_ACTIVE_ON_STATUS: 2048n, + CALLBACK_ACTIVE_ON_REASON: 4096n, + EVENT_ACTIVE_ON_REASON: 4096n, + CALLBACK_ACTIVE_ON_HEADER_NAME: 8192n, + EVENT_ACTIVE_ON_HEADER_NAME: 8192n, + CALLBACK_ACTIVE_ON_HEADER_VALUE: 16384n, + EVENT_ACTIVE_ON_HEADER_VALUE: 16384n, + CALLBACK_ACTIVE_ON_HEADERS: 32768n, + EVENT_ACTIVE_ON_HEADERS: 32768n, + CALLBACK_ACTIVE_ON_CONNECT: 65536n, + EVENT_ACTIVE_ON_CONNECT: 65536n, + CALLBACK_ACTIVE_ON_UPGRADE: 131072n, + EVENT_ACTIVE_ON_UPGRADE: 131072n, + CALLBACK_ACTIVE_ON_CHUNK_LENGTH: 262144n, + EVENT_ACTIVE_ON_CHUNK_LENGTH: 262144n, + CALLBACK_ACTIVE_ON_CHUNK_EXTENSION_NAME: 524288n, + EVENT_ACTIVE_ON_CHUNK_EXTENSION_NAME: 524288n, + CALLBACK_ACTIVE_ON_CHUNK_EXTENSION_VALUE: 1048576n, + EVENT_ACTIVE_ON_CHUNK_EXTENSION_VALUE: 1048576n, + CALLBACK_ACTIVE_ON_CHUNK: 2097152n, + EVENT_ACTIVE_ON_CHUNK: 2097152n, + CALLBACK_ACTIVE_ON_BODY: 4194304n, + EVENT_ACTIVE_ON_BODY: 4194304n, + CALLBACK_ACTIVE_ON_DATA: 8388608n, + EVENT_ACTIVE_ON_DATA: 8388608n, + CALLBACK_ACTIVE_ON_TRAILER_NAME: 16777216n, + EVENT_ACTIVE_ON_TRAILER_NAME: 16777216n, + CALLBACK_ACTIVE_ON_TRAILER_VALUE: 33554432n, + EVENT_ACTIVE_ON_TRAILER_VALUE: 33554432n, + CALLBACK_ACTIVE_ON_TRAILERS: 67108864n, + EVENT_ACTIVE_ON_TRAILERS: 67108864n, + CALLBACK_ACTIVE_ON_STATE_CHANGE: 134217728n, + EVENT_ACTIVE_ON_STATE_CHANGE: 134217728n, + CALLBACK_ACTIVE_ALL: 268435455n, + EVENT_ACTIVE_ALL: 268435455n, + ERROR_NONE: 0, + ERROR_USER: 1, + ERROR_CALLBACK_ERROR: 2, + ERROR_UNEXPECTED_STATE: 3, + ERROR_UNEXPECTED_DATA: 4, + ERROR_UNEXPECTED_EOF: 5, + ERROR_UNEXPECTED_CHARACTER: 6, + ERROR_UNEXPECTED_CONTENT_LENGTH: 7, + ERROR_UNEXPECTED_TRANSFER_ENCODING: 8, + ERROR_UNEXPECTED_CONTENT: 9, + ERROR_UNEXPECTED_TRAILERS: 10, + ERROR_INVALID_VERSION: 11, + ERROR_INVALID_STATUS: 12, + ERROR_INVALID_CONTENT_LENGTH: 13, + ERROR_INVALID_TRANSFER_ENCODING: 14, + ERROR_INVALID_CHUNK_SIZE: 15, + ERROR_MISSING_CONNECTION_UPGRADE: 16, + ERROR_UNSUPPORTED_HTTP_VERSION: 17, + STATE_START: 0, + STATE_FINISH: 1, + STATE_ERROR: 2, + STATE_REQUEST_LINE: 3, + STATE_STATUS_LINE: 4, + STATE_HTTP2_PREFACE: 5, + STATE_HEADER: 6, + STATE_BODY_DECISION: 7, + STATE_BODY_VIA_CONTENT_LENGTH: 8, + STATE_BODY_WITH_NO_LENGTH: 9, + STATE_CHUNK_HEADER: 10, + STATE_CHUNK_EXTENSIONS: 11, + STATE_CHUNK_DATA: 12, + STATE_TRAILER: 13, + STATE_TUNNEL: 14, + PARSER_FIELD_MAX_START_LINE_LENGTH: 0, + PARSER_FIELD_MAX_HEADER_LENGTH: 4, + PARSER_FIELD_MAX_BODY_PAYLOAD: 8, + PARSER_FIELD_AUTODETECT: 16, + PARSER_FIELD_IS_REQUEST: 17, + PARSER_FIELD_SUSPEND_AFTER_HEADERS: 18, + PARSER_FIELD_MANAGE_UNCONSUMED: 19, + PARSER_FIELD_CONTINUE_WITHOUT_DATA: 20, + PARSER_FIELD_IS_CONNECT: 21, + PARSER_FIELD_SKIP_BODY: 22, + PARSER_FIELD_DEBUG: 23, + PARSER_FIELD_PARSED: 24, + PARSER_FIELD_POSITION: 32, + PARSER_FIELD_STATE: 36, + PARSER_FIELD_PAUSED: 37, + PARSER_FIELD_ERROR_CODE: 38, + PARSER_FIELD_CONTENT_LENGTH: 40, + PARSER_FIELD_CHUNK_SIZE: 48, + PARSER_FIELD_REMAINING_CONTENT_LENGTH: 56, + PARSER_FIELD_REMAINING_CHUNK_SIZE: 64, + PARSER_FIELD_STATUS: 72, + PARSER_FIELD_METHOD: 76, + PARSER_FIELD_HAS_CONTENT_LENGTH: 77, + PARSER_FIELD_HAS_TRANSFER_ENCODING: 78, + PARSER_FIELD_HAS_CHUNKED_TRANSFER_ENCODING: 79, + PARSER_FIELD_HAS_CONNECTION_CLOSE: 80, + PARSER_FIELD_HAS_CONNECTION_UPGRADE: 81, + PARSER_FIELD_HAS_UPGRADE: 82, + PARSER_FIELD_HAS_TRAILERS: 83, + PARSER_FIELD_ACTIVE_CALLBACKS: 88, + PARSER_FIELD_ACTIVE_EVENTS: 96, + PARSER_FIELD_PTR: 104, + PARSER_FIELD_ERROR_DESCRIPTION: 108, + PARSER_FIELD_UNCONSUMED: 364, + PARSER_FIELD_UNCONSUMED_LEN: 368, + PARSER_FIELD_ERROR_DESCRIPTION_LEN: 372, + PARSER_FIELD_EVENTS: 376, + Errors, + Methods, + Callbacks, + CallbackActives, + Events, + EventActives, + States, + ParserFields, + isAutodetect: isAutodetect.bind(wasm), + isRequest: isRequest.bind(wasm), + isPaused: isPaused.bind(wasm), + shouldManageUnconsumed: shouldManageUnconsumed.bind(wasm), + shouldSuspendAfterHeaders: shouldSuspendAfterHeaders.bind(wasm), + getMaxStartLineLength: getMaxStartLineLength.bind(wasm), + getMaxHeaderLength: getMaxHeaderLength.bind(wasm), + getMaxBodyPayload: getMaxBodyPayload.bind(wasm), + shouldContinueWithoutData: shouldContinueWithoutData.bind(wasm), + isConnect: isConnect.bind(wasm), + isDebug: isDebug.bind(wasm), + shouldSkipBody: shouldSkipBody.bind(wasm), + getState: getState.bind(wasm), + getPosition: getPosition.bind(wasm), + getParsed: getParsed.bind(wasm), + getErrorCode: getErrorCode.bind(wasm), + getMethod: getMethod.bind(wasm), + getStatus: getStatus.bind(wasm), + hasConnectionClose: hasConnectionClose.bind(wasm), + hasConnectionUpgrade: hasConnectionUpgrade.bind(wasm), + getContentLength: getContentLength.bind(wasm), + getChunkSize: getChunkSize.bind(wasm), + getRemainingContentLength: getRemainingContentLength.bind(wasm), + getRemainingChunkSize: getRemainingChunkSize.bind(wasm), + hasContentLength: hasContentLength.bind(wasm), + hasTransferEncoding: hasTransferEncoding.bind(wasm), + hasChunkedTransferEncoding: hasChunkedTransferEncoding.bind(wasm), + hasUpgrade: hasUpgrade.bind(wasm), + hasTrailers: hasTrailers.bind(wasm), + getErrorDescription: getErrorDescription.bind(wasm), + setShouldAutodetect: setShouldAutodetect.bind(wasm), + setShouldContinueWithoutData: setShouldContinueWithoutData.bind(wasm), + setIsRequest: setIsRequest.bind(wasm), + setIsConnect: setIsConnect.bind(wasm), + setDebug: setDebug.bind(wasm), + setShouldManageUnconsumed: setShouldManageUnconsumed.bind(wasm), + setShouldSuspendAfterHeaders: setShouldSuspendAfterHeaders.bind(wasm), + setMaxStartLineLength: setMaxStartLineLength.bind(wasm), + setMaxHeaderLength: setMaxHeaderLength.bind(wasm), + setMaxBodyPayload: setMaxBodyPayload.bind(wasm), + setShouldSkipBody: setShouldSkipBody.bind(wasm), + setActiveCallbacks: setActiveCallbacks.bind(wasm), + setActiveEvents: setActiveEvents.bind(wasm), + memory: wasm.memory, + alloc: alloc.bind(wasm), + dealloc: dealloc.bind(wasm), + create: create.bind(wasm), + destroy: destroy.bind(wasm), + parse: parse.bind(wasm), + fail: fail.bind(wasm), + hasDebug: hasDebug.bind(wasm), + clear: wasm.clear, + complete: wasm.complete, + finish: wasm.finish, + pause: wasm.pause, + reset: wasm.reset, + resume: wasm.resume + } + + return milo +} + +function simple () { + const spans = {} + + const milo = setup({ + on_error (parser, at, len) { + spans[parser].push([0, at, len]) + }, + on_finish (parser, at, len) { + spans[parser].push([1, at, len]) + }, + on_message_start (parser, at, len) { + spans[parser].push([2, at, len]) + }, + on_message_complete (parser, at, len) { + spans[parser].push([3, at, len]) + }, + on_request (parser, at, len) { + spans[parser].push([4, at, len]) + }, + on_response (parser, at, len) { + spans[parser].push([5, at, len]) + }, + on_reset (parser, at, len) { + spans[parser].push([6, at, len]) + }, + on_method (parser, at, len) { + spans[parser].push([7, at, len]) + }, + on_url (parser, at, len) { + spans[parser].push([8, at, len]) + }, + on_protocol (parser, at, len) { + spans[parser].push([9, at, len]) + }, + on_version (parser, at, len) { + spans[parser].push([10, at, len]) + }, + on_status (parser, at, len) { + spans[parser].push([11, at, len]) + }, + on_reason (parser, at, len) { + spans[parser].push([12, at, len]) + }, + on_header_name (parser, at, len) { + spans[parser].push([13, at, len]) + }, + on_header_value (parser, at, len) { + spans[parser].push([14, at, len]) + }, + on_headers (parser, at, len) { + spans[parser].push([15, at, len]) + }, + on_connect (parser, at, len) { + spans[parser].push([16, at, len]) + }, + on_upgrade (parser, at, len) { + spans[parser].push([17, at, len]) + }, + on_chunk_length (parser, at, len) { + spans[parser].push([18, at, len]) + }, + on_chunk_extension_name (parser, at, len) { + spans[parser].push([19, at, len]) + }, + on_chunk_extension_value (parser, at, len) { + spans[parser].push([20, at, len]) + }, + on_chunk (parser, at, len) { + spans[parser].push([21, at, len]) + }, + on_body (parser, at, len) { + spans[parser].push([22, at, len]) + }, + on_data (parser, at, len) { + spans[parser].push([23, at, len]) + }, + on_trailer_name (parser, at, len) { + spans[parser].push([24, at, len]) + }, + on_trailer_value (parser, at, len) { + spans[parser].push([25, at, len]) + }, + on_trailers (parser, at, len) { + spans[parser].push([26, at, len]) + }, + on_state_change (parser, at, len) { + spans[parser].push([27, at, len]) + } + }) + + milo.spans = spans + milo.create = simpleCreate.bind(milo, spans, milo.create) + milo.destroy = simpleDestroy.bind(milo, spans, milo.destroy) + + return milo +} + +module.exports = { wasmModule, noop, setup, simple } diff --git a/lib/milo/src/simd/unbundled.js b/lib/milo/src/simd/unbundled.js new file mode 100644 index 00000000000..44dc579a750 --- /dev/null +++ b/lib/milo/src/simd/unbundled.js @@ -0,0 +1,1085 @@ +const { readFileSync } = require('node:fs') +const { join } = require('node:path') + +const wasmModule = new WebAssembly.Module(readFileSync(join(__dirname, '../../binary/simd.wasm'))) + +const textEncoder = new TextEncoder() +const textDecoder = new TextDecoder() + +function log (logger, raw) { + const len = Number(BigInt.asUintN(32, raw)) + const ptr = Number(raw >> 32n) + + logger(textDecoder.decode(new Uint8Array(this.memory.buffer, ptr, len))) +} + +function alloc (len) { + return this.alloc(len) >>> 0 +} + +function dealloc (ptr) { + return this.dealloc(ptr) +} + +function create () { + return this.create() >>> 0 +} + +function destroy (parser) { + this.destroy(parser) +} + +function parse (parser, data, limit) { + return this.parse(parser, data, limit) >>> 0 +} + +function fail (parser, code, description) { + const len = description.length + const ptr = this.alloc(len) + const buffer = new Uint8Array(this.memory.buffer, ptr, len) + textEncoder.encodeInto(description, buffer) + + this.fail(parser, code, ptr, len) + this.dealloc(ptr, len) +} + +function hasDebug () { + return this.milo_has_debug() !== 0 +} + +const Errors = Object.freeze({ + NONE: 0, + USER: 1, + CALLBACK_ERROR: 2, + UNEXPECTED_STATE: 3, + UNEXPECTED_DATA: 4, + UNEXPECTED_EOF: 5, + UNEXPECTED_CHARACTER: 6, + UNEXPECTED_CONTENT_LENGTH: 7, + UNEXPECTED_TRANSFER_ENCODING: 8, + UNEXPECTED_CONTENT: 9, + UNEXPECTED_TRAILERS: 10, + INVALID_VERSION: 11, + INVALID_STATUS: 12, + INVALID_CONTENT_LENGTH: 13, + INVALID_TRANSFER_ENCODING: 14, + INVALID_CHUNK_SIZE: 15, + MISSING_CONNECTION_UPGRADE: 16, + UNSUPPORTED_HTTP_VERSION: 17, + 0: 'NONE', + 1: 'USER', + 2: 'CALLBACK_ERROR', + 3: 'UNEXPECTED_STATE', + 4: 'UNEXPECTED_DATA', + 5: 'UNEXPECTED_EOF', + 6: 'UNEXPECTED_CHARACTER', + 7: 'UNEXPECTED_CONTENT_LENGTH', + 8: 'UNEXPECTED_TRANSFER_ENCODING', + 9: 'UNEXPECTED_CONTENT', + 10: 'UNEXPECTED_TRAILERS', + 11: 'INVALID_VERSION', + 12: 'INVALID_STATUS', + 13: 'INVALID_CONTENT_LENGTH', + 14: 'INVALID_TRANSFER_ENCODING', + 15: 'INVALID_CHUNK_SIZE', + 16: 'MISSING_CONNECTION_UPGRADE', + 17: 'UNSUPPORTED_HTTP_VERSION' +}) + +const Methods = Object.freeze({ + OTHER: 0, + GET: 1, + HEAD: 2, + POST: 3, + PUT: 4, + DELETE: 5, + CONNECT: 6, + OPTIONS: 7, + TRACE: 8, + PATCH: 9, + PRI: 10, + 0: 'OTHER', + 1: 'GET', + 2: 'HEAD', + 3: 'POST', + 4: 'PUT', + 5: 'DELETE', + 6: 'CONNECT', + 7: 'OPTIONS', + 8: 'TRACE', + 9: 'PATCH', + 10: 'PRI' +}) + +const Callbacks = Object.freeze({ + ON_ERROR: 0, + ON_FINISH: 1, + ON_MESSAGE_START: 2, + ON_MESSAGE_COMPLETE: 3, + ON_REQUEST: 4, + ON_RESPONSE: 5, + ON_RESET: 6, + ON_METHOD: 7, + ON_URL: 8, + ON_PROTOCOL: 9, + ON_VERSION: 10, + ON_STATUS: 11, + ON_REASON: 12, + ON_HEADER_NAME: 13, + ON_HEADER_VALUE: 14, + ON_HEADERS: 15, + ON_CONNECT: 16, + ON_UPGRADE: 17, + ON_CHUNK_LENGTH: 18, + ON_CHUNK_EXTENSION_NAME: 19, + ON_CHUNK_EXTENSION_VALUE: 20, + ON_CHUNK: 21, + ON_BODY: 22, + ON_DATA: 23, + ON_TRAILER_NAME: 24, + ON_TRAILER_VALUE: 25, + ON_TRAILERS: 26, + ON_STATE_CHANGE: 27, + 0: 'ON_ERROR', + 1: 'ON_FINISH', + 2: 'ON_MESSAGE_START', + 3: 'ON_MESSAGE_COMPLETE', + 4: 'ON_REQUEST', + 5: 'ON_RESPONSE', + 6: 'ON_RESET', + 7: 'ON_METHOD', + 8: 'ON_URL', + 9: 'ON_PROTOCOL', + 10: 'ON_VERSION', + 11: 'ON_STATUS', + 12: 'ON_REASON', + 13: 'ON_HEADER_NAME', + 14: 'ON_HEADER_VALUE', + 15: 'ON_HEADERS', + 16: 'ON_CONNECT', + 17: 'ON_UPGRADE', + 18: 'ON_CHUNK_LENGTH', + 19: 'ON_CHUNK_EXTENSION_NAME', + 20: 'ON_CHUNK_EXTENSION_VALUE', + 21: 'ON_CHUNK', + 22: 'ON_BODY', + 23: 'ON_DATA', + 24: 'ON_TRAILER_NAME', + 25: 'ON_TRAILER_VALUE', + 26: 'ON_TRAILERS', + 27: 'ON_STATE_CHANGE' +}) + +const CallbackActives = Object.freeze({ + NONE: 0n, + ON_ERROR: 1n, + ON_FINISH: 2n, + ON_MESSAGE_START: 4n, + ON_MESSAGE_COMPLETE: 8n, + ON_REQUEST: 16n, + ON_RESPONSE: 32n, + ON_RESET: 64n, + ON_METHOD: 128n, + ON_URL: 256n, + ON_PROTOCOL: 512n, + ON_VERSION: 1024n, + ON_STATUS: 2048n, + ON_REASON: 4096n, + ON_HEADER_NAME: 8192n, + ON_HEADER_VALUE: 16384n, + ON_HEADERS: 32768n, + ON_CONNECT: 65536n, + ON_UPGRADE: 131072n, + ON_CHUNK_LENGTH: 262144n, + ON_CHUNK_EXTENSION_NAME: 524288n, + ON_CHUNK_EXTENSION_VALUE: 1048576n, + ON_CHUNK: 2097152n, + ON_BODY: 4194304n, + ON_DATA: 8388608n, + ON_TRAILER_NAME: 16777216n, + ON_TRAILER_VALUE: 33554432n, + ON_TRAILERS: 67108864n, + ON_STATE_CHANGE: 134217728n, + ALL: 268435455n, + 0n: 'NONE', + 1n: 'ON_ERROR', + 2n: 'ON_FINISH', + 4n: 'ON_MESSAGE_START', + 8n: 'ON_MESSAGE_COMPLETE', + 16n: 'ON_REQUEST', + 32n: 'ON_RESPONSE', + 64n: 'ON_RESET', + 128n: 'ON_METHOD', + 256n: 'ON_URL', + 512n: 'ON_PROTOCOL', + 1024n: 'ON_VERSION', + 2048n: 'ON_STATUS', + 4096n: 'ON_REASON', + 8192n: 'ON_HEADER_NAME', + 16384n: 'ON_HEADER_VALUE', + 32768n: 'ON_HEADERS', + 65536n: 'ON_CONNECT', + 131072n: 'ON_UPGRADE', + 262144n: 'ON_CHUNK_LENGTH', + 524288n: 'ON_CHUNK_EXTENSION_NAME', + 1048576n: 'ON_CHUNK_EXTENSION_VALUE', + 2097152n: 'ON_CHUNK', + 4194304n: 'ON_BODY', + 8388608n: 'ON_DATA', + 16777216n: 'ON_TRAILER_NAME', + 33554432n: 'ON_TRAILER_VALUE', + 67108864n: 'ON_TRAILERS', + 134217728n: 'ON_STATE_CHANGE', + 268435455n: 'ALL' +}) + +const Events = Object.freeze({ + END: 0, + ERROR: 1, + FINISH: 2, + MESSAGE_START: 3, + MESSAGE_COMPLETE: 4, + REQUEST: 5, + RESPONSE: 6, + RESET: 7, + METHOD: 8, + URL: 9, + PROTOCOL: 10, + VERSION: 11, + STATUS: 12, + REASON: 13, + HEADER_NAME: 14, + HEADER_VALUE: 15, + HEADERS: 16, + CONNECT: 17, + UPGRADE: 18, + CHUNK_LENGTH: 19, + CHUNK_EXTENSION_NAME: 20, + CHUNK_EXTENSION_VALUE: 21, + CHUNK: 22, + BODY: 23, + DATA: 24, + TRAILER_NAME: 25, + TRAILER_VALUE: 26, + TRAILERS: 27, + STATE_CHANGE: 28, + 0: 'END', + 1: 'ERROR', + 2: 'FINISH', + 3: 'MESSAGE_START', + 4: 'MESSAGE_COMPLETE', + 5: 'REQUEST', + 6: 'RESPONSE', + 7: 'RESET', + 8: 'METHOD', + 9: 'URL', + 10: 'PROTOCOL', + 11: 'VERSION', + 12: 'STATUS', + 13: 'REASON', + 14: 'HEADER_NAME', + 15: 'HEADER_VALUE', + 16: 'HEADERS', + 17: 'CONNECT', + 18: 'UPGRADE', + 19: 'CHUNK_LENGTH', + 20: 'CHUNK_EXTENSION_NAME', + 21: 'CHUNK_EXTENSION_VALUE', + 22: 'CHUNK', + 23: 'BODY', + 24: 'DATA', + 25: 'TRAILER_NAME', + 26: 'TRAILER_VALUE', + 27: 'TRAILERS', + 28: 'STATE_CHANGE' +}) + +const EventActives = Object.freeze({ + NONE: 0n, + ON_ERROR: 1n, + ON_FINISH: 2n, + ON_MESSAGE_START: 4n, + ON_MESSAGE_COMPLETE: 8n, + ON_REQUEST: 16n, + ON_RESPONSE: 32n, + ON_RESET: 64n, + ON_METHOD: 128n, + ON_URL: 256n, + ON_PROTOCOL: 512n, + ON_VERSION: 1024n, + ON_STATUS: 2048n, + ON_REASON: 4096n, + ON_HEADER_NAME: 8192n, + ON_HEADER_VALUE: 16384n, + ON_HEADERS: 32768n, + ON_CONNECT: 65536n, + ON_UPGRADE: 131072n, + ON_CHUNK_LENGTH: 262144n, + ON_CHUNK_EXTENSION_NAME: 524288n, + ON_CHUNK_EXTENSION_VALUE: 1048576n, + ON_CHUNK: 2097152n, + ON_BODY: 4194304n, + ON_DATA: 8388608n, + ON_TRAILER_NAME: 16777216n, + ON_TRAILER_VALUE: 33554432n, + ON_TRAILERS: 67108864n, + ON_STATE_CHANGE: 134217728n, + ALL: 268435455n, + 0n: 'NONE', + 1n: 'ON_ERROR', + 2n: 'ON_FINISH', + 4n: 'ON_MESSAGE_START', + 8n: 'ON_MESSAGE_COMPLETE', + 16n: 'ON_REQUEST', + 32n: 'ON_RESPONSE', + 64n: 'ON_RESET', + 128n: 'ON_METHOD', + 256n: 'ON_URL', + 512n: 'ON_PROTOCOL', + 1024n: 'ON_VERSION', + 2048n: 'ON_STATUS', + 4096n: 'ON_REASON', + 8192n: 'ON_HEADER_NAME', + 16384n: 'ON_HEADER_VALUE', + 32768n: 'ON_HEADERS', + 65536n: 'ON_CONNECT', + 131072n: 'ON_UPGRADE', + 262144n: 'ON_CHUNK_LENGTH', + 524288n: 'ON_CHUNK_EXTENSION_NAME', + 1048576n: 'ON_CHUNK_EXTENSION_VALUE', + 2097152n: 'ON_CHUNK', + 4194304n: 'ON_BODY', + 8388608n: 'ON_DATA', + 16777216n: 'ON_TRAILER_NAME', + 33554432n: 'ON_TRAILER_VALUE', + 67108864n: 'ON_TRAILERS', + 134217728n: 'ON_STATE_CHANGE', + 268435455n: 'ALL' +}) + +const States = Object.freeze({ + START: 0, + FINISH: 1, + ERROR: 2, + REQUEST_LINE: 3, + STATUS_LINE: 4, + HTTP2_PREFACE: 5, + HEADER: 6, + BODY_DECISION: 7, + BODY_VIA_CONTENT_LENGTH: 8, + BODY_WITH_NO_LENGTH: 9, + CHUNK_HEADER: 10, + CHUNK_EXTENSIONS: 11, + CHUNK_DATA: 12, + TRAILER: 13, + TUNNEL: 14, + 0: 'START', + 1: 'FINISH', + 2: 'ERROR', + 3: 'REQUEST_LINE', + 4: 'STATUS_LINE', + 5: 'HTTP2_PREFACE', + 6: 'HEADER', + 7: 'BODY_DECISION', + 8: 'BODY_VIA_CONTENT_LENGTH', + 9: 'BODY_WITH_NO_LENGTH', + 10: 'CHUNK_HEADER', + 11: 'CHUNK_EXTENSIONS', + 12: 'CHUNK_DATA', + 13: 'TRAILER', + 14: 'TUNNEL' +}) + +const ParserFields = Object.freeze({ + MAX_START_LINE_LENGTH: 0, + MAX_HEADER_LENGTH: 4, + MAX_BODY_PAYLOAD: 8, + AUTODETECT: 16, + IS_REQUEST: 17, + SUSPEND_AFTER_HEADERS: 18, + MANAGE_UNCONSUMED: 19, + CONTINUE_WITHOUT_DATA: 20, + IS_CONNECT: 21, + SKIP_BODY: 22, + DEBUG: 23, + PARSED: 24, + POSITION: 32, + STATE: 36, + PAUSED: 37, + ERROR_CODE: 38, + CONTENT_LENGTH: 40, + CHUNK_SIZE: 48, + REMAINING_CONTENT_LENGTH: 56, + REMAINING_CHUNK_SIZE: 64, + STATUS: 72, + METHOD: 76, + HAS_CONTENT_LENGTH: 77, + HAS_TRANSFER_ENCODING: 78, + HAS_CHUNKED_TRANSFER_ENCODING: 79, + HAS_CONNECTION_CLOSE: 80, + HAS_CONNECTION_UPGRADE: 81, + HAS_UPGRADE: 82, + HAS_TRAILERS: 83, + ACTIVE_CALLBACKS: 88, + ACTIVE_EVENTS: 96, + PTR: 104, + ERROR_DESCRIPTION: 108, + UNCONSUMED: 364, + UNCONSUMED_LEN: 368, + ERROR_DESCRIPTION_LEN: 372, + EVENTS: 376, + 0: 'MAX_START_LINE_LENGTH', + 4: 'MAX_HEADER_LENGTH', + 8: 'MAX_BODY_PAYLOAD', + 16: 'AUTODETECT', + 17: 'IS_REQUEST', + 18: 'SUSPEND_AFTER_HEADERS', + 19: 'MANAGE_UNCONSUMED', + 20: 'CONTINUE_WITHOUT_DATA', + 21: 'IS_CONNECT', + 22: 'SKIP_BODY', + 23: 'DEBUG', + 24: 'PARSED', + 32: 'POSITION', + 36: 'STATE', + 37: 'PAUSED', + 38: 'ERROR_CODE', + 40: 'CONTENT_LENGTH', + 48: 'CHUNK_SIZE', + 56: 'REMAINING_CONTENT_LENGTH', + 64: 'REMAINING_CHUNK_SIZE', + 72: 'STATUS', + 76: 'METHOD', + 77: 'HAS_CONTENT_LENGTH', + 78: 'HAS_TRANSFER_ENCODING', + 79: 'HAS_CHUNKED_TRANSFER_ENCODING', + 80: 'HAS_CONNECTION_CLOSE', + 81: 'HAS_CONNECTION_UPGRADE', + 82: 'HAS_UPGRADE', + 83: 'HAS_TRAILERS', + 88: 'ACTIVE_CALLBACKS', + 96: 'ACTIVE_EVENTS', + 104: 'PTR', + 108: 'ERROR_DESCRIPTION', + 364: 'UNCONSUMED', + 368: 'UNCONSUMED_LEN', + 372: 'ERROR_DESCRIPTION_LEN', + 376: 'EVENTS' +}) + +function isAutodetect (parser) { + return this.is_autodetect(parser) !== 0 +} + +function isRequest (parser) { + return this.is_request(parser) !== 0 +} + +function isPaused (parser) { + return this.is_paused(parser) !== 0 +} + +function shouldManageUnconsumed (parser) { + return this.should_manage_unconsumed(parser) !== 0 +} + +function shouldSuspendAfterHeaders (parser) { + return this.should_suspend_after_headers(parser) !== 0 +} + +function getMaxStartLineLength (parser) { + return this.get_max_start_line_length(parser) >>> 0 +} + +function getMaxHeaderLength (parser) { + return this.get_max_header_length(parser) >>> 0 +} + +function getMaxBodyPayload (parser) { + return BigInt.asUintN(64, this.get_max_body_payload(parser)) +} + +function shouldContinueWithoutData (parser) { + return this.should_continue_without_data(parser) !== 0 +} + +function isConnect (parser) { + return this.is_connect(parser) !== 0 +} + +function isDebug (parser) { + return this.is_debug(parser) !== 0 +} + +function shouldSkipBody (parser) { + return this.should_skip_body(parser) !== 0 +} + +function getState (parser) { + return this.get_state(parser) >>> 0 +} + +function getPosition (parser) { + return this.get_position(parser) >>> 0 +} + +function getParsed (parser) { + return BigInt.asUintN(64, this.get_parsed(parser)) +} + +function getErrorCode (parser) { + return this.get_error_code(parser) >>> 0 +} + +function getMethod (parser) { + return this.get_method(parser) >>> 0 +} + +function getStatus (parser) { + return this.get_status(parser) >>> 0 +} + +function hasConnectionClose (parser) { + return this.has_connection_close(parser) !== 0 +} + +function hasConnectionUpgrade (parser) { + return this.has_connection_upgrade(parser) !== 0 +} + +function getContentLength (parser) { + return BigInt.asUintN(64, this.get_content_length(parser)) +} + +function getChunkSize (parser) { + return BigInt.asUintN(64, this.get_chunk_size(parser)) +} + +function getRemainingContentLength (parser) { + return BigInt.asUintN(64, this.get_remaining_content_length(parser)) +} + +function getRemainingChunkSize (parser) { + return BigInt.asUintN(64, this.get_remaining_chunk_size(parser)) +} + +function hasContentLength (parser) { + return this.has_content_length(parser) !== 0 +} + +function hasTransferEncoding (parser) { + return this.has_transfer_encoding(parser) !== 0 +} + +function hasChunkedTransferEncoding (parser) { + return this.has_chunked_transfer_encoding(parser) !== 0 +} + +function hasUpgrade (parser) { + return this.has_upgrade(parser) !== 0 +} + +function hasTrailers (parser) { + return this.has_trailers(parser) !== 0 +} + +function getErrorDescription (parser) { + const raw = this.get_error_description_raw(parser) + const len = Number(BigInt.asUintN(32, raw)) + const ptr = Number(raw >> 32n) + return textDecoder.decode(new Uint8Array(this.memory.buffer, ptr, len)) +} + +function setShouldAutodetect (parser, value) { + this.set_should_autodetect(parser, value) +} + +function setShouldContinueWithoutData (parser, value) { + this.set_should_continue_without_data(parser, value) +} + +function setIsRequest (parser, value) { + this.set_is_request(parser, value) +} + +function setIsConnect (parser, value) { + this.set_is_connect(parser, value) +} + +function setDebug (parser, value) { + this.set_debug(parser, value) +} + +function setShouldManageUnconsumed (parser, value) { + this.set_should_manage_unconsumed(parser, value) +} + +function setShouldSuspendAfterHeaders (parser, value) { + this.set_should_suspend_after_headers(parser, value) +} + +function setMaxStartLineLength (parser, value) { + this.set_max_start_line_length(parser, value) +} + +function setMaxHeaderLength (parser, value) { + this.set_max_header_length(parser, value) +} + +function setMaxBodyPayload (parser, value) { + this.set_max_body_payload(parser, value) +} + +function setShouldSkipBody (parser, value) { + this.set_should_skip_body(parser, value) +} + +function setActiveCallbacks (parser, value) { + this.set_active_callbacks(parser, value) +} + +function setActiveEvents (parser, value) { + this.set_active_events(parser, value) +} + +function simpleCreate (spans, create) { + const parser = create() + spans[parser] = [] + this.setActiveCallbacks(parser, this.CALLBACK_ACTIVE_ALL) + return parser +} + +function simpleDestroy (spans, destroy, parser) { + spans[parser] = undefined + destroy(parser) +} + +function noop () {} + +function setup (env = {}) { + let { logger: logOption, ...instanceEnvironment } = env + let logger = noop + const context = {} + + if (logOption) { + if (typeof logOption !== 'function') { + logOption = console.log + } + + logger = log.bind(context, logOption) + } + + // Create the WASM instance + /* eslint-disable-next-line no-undef */ + const instance = new WebAssembly.Instance(wasmModule, { + env: { + logger, + on_error: noop, + on_finish: noop, + on_message_start: noop, + on_message_complete: noop, + on_request: noop, + on_response: noop, + on_reset: noop, + on_method: noop, + on_url: noop, + on_protocol: noop, + on_version: noop, + on_status: noop, + on_reason: noop, + on_header_name: noop, + on_header_value: noop, + on_headers: noop, + on_connect: noop, + on_upgrade: noop, + on_chunk_length: noop, + on_chunk_extension_name: noop, + on_chunk_extension_value: noop, + on_chunk: noop, + on_body: noop, + on_data: noop, + on_trailer_name: noop, + on_trailer_value: noop, + on_trailers: noop, + on_state_change: noop, + ...instanceEnvironment + } + }) + + const wasm = instance.exports + context.memory = wasm.memory + + const milo = { + version: { + raw: '0.8.0', + major: 0, + minor: 8, + patch: 0, + prerelease: '' + }, + METHOD_OTHER: 0, + METHOD_GET: 1, + METHOD_HEAD: 2, + METHOD_POST: 3, + METHOD_PUT: 4, + METHOD_DELETE: 5, + METHOD_CONNECT: 6, + METHOD_OPTIONS: 7, + METHOD_TRACE: 8, + METHOD_PATCH: 9, + METHOD_PRI: 10, + CALLBACK_ON_ERROR: 0, + CALLBACK_ON_FINISH: 1, + CALLBACK_ON_MESSAGE_START: 2, + CALLBACK_ON_MESSAGE_COMPLETE: 3, + CALLBACK_ON_REQUEST: 4, + CALLBACK_ON_RESPONSE: 5, + CALLBACK_ON_RESET: 6, + CALLBACK_ON_METHOD: 7, + CALLBACK_ON_URL: 8, + CALLBACK_ON_PROTOCOL: 9, + CALLBACK_ON_VERSION: 10, + CALLBACK_ON_STATUS: 11, + CALLBACK_ON_REASON: 12, + CALLBACK_ON_HEADER_NAME: 13, + CALLBACK_ON_HEADER_VALUE: 14, + CALLBACK_ON_HEADERS: 15, + CALLBACK_ON_CONNECT: 16, + CALLBACK_ON_UPGRADE: 17, + CALLBACK_ON_CHUNK_LENGTH: 18, + CALLBACK_ON_CHUNK_EXTENSION_NAME: 19, + CALLBACK_ON_CHUNK_EXTENSION_VALUE: 20, + CALLBACK_ON_CHUNK: 21, + CALLBACK_ON_BODY: 22, + CALLBACK_ON_DATA: 23, + CALLBACK_ON_TRAILER_NAME: 24, + CALLBACK_ON_TRAILER_VALUE: 25, + CALLBACK_ON_TRAILERS: 26, + CALLBACK_ON_STATE_CHANGE: 27, + EVENT_END: 0, + EVENT_ERROR: 1, + EVENT_FINISH: 2, + EVENT_MESSAGE_START: 3, + EVENT_MESSAGE_COMPLETE: 4, + EVENT_REQUEST: 5, + EVENT_RESPONSE: 6, + EVENT_RESET: 7, + EVENT_METHOD: 8, + EVENT_URL: 9, + EVENT_PROTOCOL: 10, + EVENT_VERSION: 11, + EVENT_STATUS: 12, + EVENT_REASON: 13, + EVENT_HEADER_NAME: 14, + EVENT_HEADER_VALUE: 15, + EVENT_HEADERS: 16, + EVENT_CONNECT: 17, + EVENT_UPGRADE: 18, + EVENT_CHUNK_LENGTH: 19, + EVENT_CHUNK_EXTENSION_NAME: 20, + EVENT_CHUNK_EXTENSION_VALUE: 21, + EVENT_CHUNK: 22, + EVENT_BODY: 23, + EVENT_DATA: 24, + EVENT_TRAILER_NAME: 25, + EVENT_TRAILER_VALUE: 26, + EVENT_TRAILERS: 27, + EVENT_STATE_CHANGE: 28, + CALLBACK_ACTIVE_NONE: 0n, + EVENT_ACTIVE_NONE: 0n, + CALLBACK_ACTIVE_ON_ERROR: 1n, + EVENT_ACTIVE_ON_ERROR: 1n, + CALLBACK_ACTIVE_ON_FINISH: 2n, + EVENT_ACTIVE_ON_FINISH: 2n, + CALLBACK_ACTIVE_ON_MESSAGE_START: 4n, + EVENT_ACTIVE_ON_MESSAGE_START: 4n, + CALLBACK_ACTIVE_ON_MESSAGE_COMPLETE: 8n, + EVENT_ACTIVE_ON_MESSAGE_COMPLETE: 8n, + CALLBACK_ACTIVE_ON_REQUEST: 16n, + EVENT_ACTIVE_ON_REQUEST: 16n, + CALLBACK_ACTIVE_ON_RESPONSE: 32n, + EVENT_ACTIVE_ON_RESPONSE: 32n, + CALLBACK_ACTIVE_ON_RESET: 64n, + EVENT_ACTIVE_ON_RESET: 64n, + CALLBACK_ACTIVE_ON_METHOD: 128n, + EVENT_ACTIVE_ON_METHOD: 128n, + CALLBACK_ACTIVE_ON_URL: 256n, + EVENT_ACTIVE_ON_URL: 256n, + CALLBACK_ACTIVE_ON_PROTOCOL: 512n, + EVENT_ACTIVE_ON_PROTOCOL: 512n, + CALLBACK_ACTIVE_ON_VERSION: 1024n, + EVENT_ACTIVE_ON_VERSION: 1024n, + CALLBACK_ACTIVE_ON_STATUS: 2048n, + EVENT_ACTIVE_ON_STATUS: 2048n, + CALLBACK_ACTIVE_ON_REASON: 4096n, + EVENT_ACTIVE_ON_REASON: 4096n, + CALLBACK_ACTIVE_ON_HEADER_NAME: 8192n, + EVENT_ACTIVE_ON_HEADER_NAME: 8192n, + CALLBACK_ACTIVE_ON_HEADER_VALUE: 16384n, + EVENT_ACTIVE_ON_HEADER_VALUE: 16384n, + CALLBACK_ACTIVE_ON_HEADERS: 32768n, + EVENT_ACTIVE_ON_HEADERS: 32768n, + CALLBACK_ACTIVE_ON_CONNECT: 65536n, + EVENT_ACTIVE_ON_CONNECT: 65536n, + CALLBACK_ACTIVE_ON_UPGRADE: 131072n, + EVENT_ACTIVE_ON_UPGRADE: 131072n, + CALLBACK_ACTIVE_ON_CHUNK_LENGTH: 262144n, + EVENT_ACTIVE_ON_CHUNK_LENGTH: 262144n, + CALLBACK_ACTIVE_ON_CHUNK_EXTENSION_NAME: 524288n, + EVENT_ACTIVE_ON_CHUNK_EXTENSION_NAME: 524288n, + CALLBACK_ACTIVE_ON_CHUNK_EXTENSION_VALUE: 1048576n, + EVENT_ACTIVE_ON_CHUNK_EXTENSION_VALUE: 1048576n, + CALLBACK_ACTIVE_ON_CHUNK: 2097152n, + EVENT_ACTIVE_ON_CHUNK: 2097152n, + CALLBACK_ACTIVE_ON_BODY: 4194304n, + EVENT_ACTIVE_ON_BODY: 4194304n, + CALLBACK_ACTIVE_ON_DATA: 8388608n, + EVENT_ACTIVE_ON_DATA: 8388608n, + CALLBACK_ACTIVE_ON_TRAILER_NAME: 16777216n, + EVENT_ACTIVE_ON_TRAILER_NAME: 16777216n, + CALLBACK_ACTIVE_ON_TRAILER_VALUE: 33554432n, + EVENT_ACTIVE_ON_TRAILER_VALUE: 33554432n, + CALLBACK_ACTIVE_ON_TRAILERS: 67108864n, + EVENT_ACTIVE_ON_TRAILERS: 67108864n, + CALLBACK_ACTIVE_ON_STATE_CHANGE: 134217728n, + EVENT_ACTIVE_ON_STATE_CHANGE: 134217728n, + CALLBACK_ACTIVE_ALL: 268435455n, + EVENT_ACTIVE_ALL: 268435455n, + ERROR_NONE: 0, + ERROR_USER: 1, + ERROR_CALLBACK_ERROR: 2, + ERROR_UNEXPECTED_STATE: 3, + ERROR_UNEXPECTED_DATA: 4, + ERROR_UNEXPECTED_EOF: 5, + ERROR_UNEXPECTED_CHARACTER: 6, + ERROR_UNEXPECTED_CONTENT_LENGTH: 7, + ERROR_UNEXPECTED_TRANSFER_ENCODING: 8, + ERROR_UNEXPECTED_CONTENT: 9, + ERROR_UNEXPECTED_TRAILERS: 10, + ERROR_INVALID_VERSION: 11, + ERROR_INVALID_STATUS: 12, + ERROR_INVALID_CONTENT_LENGTH: 13, + ERROR_INVALID_TRANSFER_ENCODING: 14, + ERROR_INVALID_CHUNK_SIZE: 15, + ERROR_MISSING_CONNECTION_UPGRADE: 16, + ERROR_UNSUPPORTED_HTTP_VERSION: 17, + STATE_START: 0, + STATE_FINISH: 1, + STATE_ERROR: 2, + STATE_REQUEST_LINE: 3, + STATE_STATUS_LINE: 4, + STATE_HTTP2_PREFACE: 5, + STATE_HEADER: 6, + STATE_BODY_DECISION: 7, + STATE_BODY_VIA_CONTENT_LENGTH: 8, + STATE_BODY_WITH_NO_LENGTH: 9, + STATE_CHUNK_HEADER: 10, + STATE_CHUNK_EXTENSIONS: 11, + STATE_CHUNK_DATA: 12, + STATE_TRAILER: 13, + STATE_TUNNEL: 14, + PARSER_FIELD_MAX_START_LINE_LENGTH: 0, + PARSER_FIELD_MAX_HEADER_LENGTH: 4, + PARSER_FIELD_MAX_BODY_PAYLOAD: 8, + PARSER_FIELD_AUTODETECT: 16, + PARSER_FIELD_IS_REQUEST: 17, + PARSER_FIELD_SUSPEND_AFTER_HEADERS: 18, + PARSER_FIELD_MANAGE_UNCONSUMED: 19, + PARSER_FIELD_CONTINUE_WITHOUT_DATA: 20, + PARSER_FIELD_IS_CONNECT: 21, + PARSER_FIELD_SKIP_BODY: 22, + PARSER_FIELD_DEBUG: 23, + PARSER_FIELD_PARSED: 24, + PARSER_FIELD_POSITION: 32, + PARSER_FIELD_STATE: 36, + PARSER_FIELD_PAUSED: 37, + PARSER_FIELD_ERROR_CODE: 38, + PARSER_FIELD_CONTENT_LENGTH: 40, + PARSER_FIELD_CHUNK_SIZE: 48, + PARSER_FIELD_REMAINING_CONTENT_LENGTH: 56, + PARSER_FIELD_REMAINING_CHUNK_SIZE: 64, + PARSER_FIELD_STATUS: 72, + PARSER_FIELD_METHOD: 76, + PARSER_FIELD_HAS_CONTENT_LENGTH: 77, + PARSER_FIELD_HAS_TRANSFER_ENCODING: 78, + PARSER_FIELD_HAS_CHUNKED_TRANSFER_ENCODING: 79, + PARSER_FIELD_HAS_CONNECTION_CLOSE: 80, + PARSER_FIELD_HAS_CONNECTION_UPGRADE: 81, + PARSER_FIELD_HAS_UPGRADE: 82, + PARSER_FIELD_HAS_TRAILERS: 83, + PARSER_FIELD_ACTIVE_CALLBACKS: 88, + PARSER_FIELD_ACTIVE_EVENTS: 96, + PARSER_FIELD_PTR: 104, + PARSER_FIELD_ERROR_DESCRIPTION: 108, + PARSER_FIELD_UNCONSUMED: 364, + PARSER_FIELD_UNCONSUMED_LEN: 368, + PARSER_FIELD_ERROR_DESCRIPTION_LEN: 372, + PARSER_FIELD_EVENTS: 376, + Errors, + Methods, + Callbacks, + CallbackActives, + Events, + EventActives, + States, + ParserFields, + isAutodetect: isAutodetect.bind(wasm), + isRequest: isRequest.bind(wasm), + isPaused: isPaused.bind(wasm), + shouldManageUnconsumed: shouldManageUnconsumed.bind(wasm), + shouldSuspendAfterHeaders: shouldSuspendAfterHeaders.bind(wasm), + getMaxStartLineLength: getMaxStartLineLength.bind(wasm), + getMaxHeaderLength: getMaxHeaderLength.bind(wasm), + getMaxBodyPayload: getMaxBodyPayload.bind(wasm), + shouldContinueWithoutData: shouldContinueWithoutData.bind(wasm), + isConnect: isConnect.bind(wasm), + isDebug: isDebug.bind(wasm), + shouldSkipBody: shouldSkipBody.bind(wasm), + getState: getState.bind(wasm), + getPosition: getPosition.bind(wasm), + getParsed: getParsed.bind(wasm), + getErrorCode: getErrorCode.bind(wasm), + getMethod: getMethod.bind(wasm), + getStatus: getStatus.bind(wasm), + hasConnectionClose: hasConnectionClose.bind(wasm), + hasConnectionUpgrade: hasConnectionUpgrade.bind(wasm), + getContentLength: getContentLength.bind(wasm), + getChunkSize: getChunkSize.bind(wasm), + getRemainingContentLength: getRemainingContentLength.bind(wasm), + getRemainingChunkSize: getRemainingChunkSize.bind(wasm), + hasContentLength: hasContentLength.bind(wasm), + hasTransferEncoding: hasTransferEncoding.bind(wasm), + hasChunkedTransferEncoding: hasChunkedTransferEncoding.bind(wasm), + hasUpgrade: hasUpgrade.bind(wasm), + hasTrailers: hasTrailers.bind(wasm), + getErrorDescription: getErrorDescription.bind(wasm), + setShouldAutodetect: setShouldAutodetect.bind(wasm), + setShouldContinueWithoutData: setShouldContinueWithoutData.bind(wasm), + setIsRequest: setIsRequest.bind(wasm), + setIsConnect: setIsConnect.bind(wasm), + setDebug: setDebug.bind(wasm), + setShouldManageUnconsumed: setShouldManageUnconsumed.bind(wasm), + setShouldSuspendAfterHeaders: setShouldSuspendAfterHeaders.bind(wasm), + setMaxStartLineLength: setMaxStartLineLength.bind(wasm), + setMaxHeaderLength: setMaxHeaderLength.bind(wasm), + setMaxBodyPayload: setMaxBodyPayload.bind(wasm), + setShouldSkipBody: setShouldSkipBody.bind(wasm), + setActiveCallbacks: setActiveCallbacks.bind(wasm), + setActiveEvents: setActiveEvents.bind(wasm), + memory: wasm.memory, + alloc: alloc.bind(wasm), + dealloc: dealloc.bind(wasm), + create: create.bind(wasm), + destroy: destroy.bind(wasm), + parse: parse.bind(wasm), + fail: fail.bind(wasm), + hasDebug: hasDebug.bind(wasm), + clear: wasm.clear, + complete: wasm.complete, + finish: wasm.finish, + pause: wasm.pause, + reset: wasm.reset, + resume: wasm.resume + } + + return milo +} + +function simple () { + const spans = {} + + const milo = setup({ + on_error (parser, at, len) { + spans[parser].push([0, at, len]) + }, + on_finish (parser, at, len) { + spans[parser].push([1, at, len]) + }, + on_message_start (parser, at, len) { + spans[parser].push([2, at, len]) + }, + on_message_complete (parser, at, len) { + spans[parser].push([3, at, len]) + }, + on_request (parser, at, len) { + spans[parser].push([4, at, len]) + }, + on_response (parser, at, len) { + spans[parser].push([5, at, len]) + }, + on_reset (parser, at, len) { + spans[parser].push([6, at, len]) + }, + on_method (parser, at, len) { + spans[parser].push([7, at, len]) + }, + on_url (parser, at, len) { + spans[parser].push([8, at, len]) + }, + on_protocol (parser, at, len) { + spans[parser].push([9, at, len]) + }, + on_version (parser, at, len) { + spans[parser].push([10, at, len]) + }, + on_status (parser, at, len) { + spans[parser].push([11, at, len]) + }, + on_reason (parser, at, len) { + spans[parser].push([12, at, len]) + }, + on_header_name (parser, at, len) { + spans[parser].push([13, at, len]) + }, + on_header_value (parser, at, len) { + spans[parser].push([14, at, len]) + }, + on_headers (parser, at, len) { + spans[parser].push([15, at, len]) + }, + on_connect (parser, at, len) { + spans[parser].push([16, at, len]) + }, + on_upgrade (parser, at, len) { + spans[parser].push([17, at, len]) + }, + on_chunk_length (parser, at, len) { + spans[parser].push([18, at, len]) + }, + on_chunk_extension_name (parser, at, len) { + spans[parser].push([19, at, len]) + }, + on_chunk_extension_value (parser, at, len) { + spans[parser].push([20, at, len]) + }, + on_chunk (parser, at, len) { + spans[parser].push([21, at, len]) + }, + on_body (parser, at, len) { + spans[parser].push([22, at, len]) + }, + on_data (parser, at, len) { + spans[parser].push([23, at, len]) + }, + on_trailer_name (parser, at, len) { + spans[parser].push([24, at, len]) + }, + on_trailer_value (parser, at, len) { + spans[parser].push([25, at, len]) + }, + on_trailers (parser, at, len) { + spans[parser].push([26, at, len]) + }, + on_state_change (parser, at, len) { + spans[parser].push([27, at, len]) + } + }) + + milo.spans = spans + milo.create = simpleCreate.bind(milo, spans, milo.create) + milo.destroy = simpleDestroy.bind(milo, spans, milo.destroy) + + return milo +} + +module.exports = { wasmModule, noop, setup, simple } diff --git a/package.json b/package.json index d44a283e563..04841e9ca04 100644 --- a/package.json +++ b/package.json @@ -63,6 +63,7 @@ "types": "index.d.ts", "scripts": { "build:node": "esbuild index-fetch.js --bundle --platform=node --outfile=undici-fetch.js --define:esbuildDetection=1 --keep-names && node scripts/strip-comments.js", + "build:milo": "node build/milo.js", "build:wasm": "node build/wasm.js --docker", "generate-pem": "node scripts/generate-pem.js", "lint": "eslint --cache", diff --git a/test/client-upgrade.js b/test/client-upgrade.js index a1871a96501..063cb201365 100644 --- a/test/client-upgrade.js +++ b/test/client-upgrade.js @@ -8,13 +8,16 @@ const http = require('node:http') const EE = require('node:events') const { kBusy } = require('../lib/core/symbols') +// RFC 9112 requires a space after the status code even when the reason phrase is empty. +const SWITCHING_PROTOCOLS = 'HTTP/1.1 101 Switching Protocols\r\n' + test('basic upgrade', async (t) => { t = tspl(t, { plan: 6 }) const server = net.createServer({ joinDuplicateHeaders: true }, (c) => { c.on('data', (d) => { t.ok(/upgrade: websocket/i.test(d)) - c.write('HTTP/1.1 101\r\n') + c.write(SWITCHING_PROTOCOLS) c.write('hello: world\r\n') c.write('connection: upgrade\r\n') c.write('upgrade: websocket\r\n') @@ -72,7 +75,7 @@ test('basic upgrade promise', async (t) => { const server = net.createServer({ joinDuplicateHeaders: true }, (c) => { c.on('data', (d) => { - c.write('HTTP/1.1 101\r\n') + c.write(SWITCHING_PROTOCOLS) c.write('hello: world\r\n') c.write('connection: upgrade\r\n') c.write('upgrade: websocket\r\n') @@ -121,7 +124,7 @@ test('upgrade error', async (t) => { const server = net.createServer({ joinDuplicateHeaders: true }, (c) => { c.on('data', (d) => { - c.write('HTTP/1.1 101\r\n') + c.write(SWITCHING_PROTOCOLS) c.write('hello: world\r\n') c.write('connection: upgrade\r\n') c.write('\r\n') @@ -184,7 +187,7 @@ test('basic upgrade2', async (t) => { const server = http.createServer({ joinDuplicateHeaders: true }) server.on('upgrade', (req, c, head) => { - c.write('HTTP/1.1 101\r\n') + c.write(SWITCHING_PROTOCOLS) c.write('hello: world\r\n') c.write('connection: upgrade\r\n') c.write('upgrade: websocket\r\n') @@ -238,7 +241,7 @@ test('upgrade wait for empty pipeline', async (t) => { }) server.on('upgrade', (req, c, firstBodyChunk) => { t.strictEqual(canConnect, true) - c.write('HTTP/1.1 101\r\n') + c.write(SWITCHING_PROTOCOLS) c.write('hello: world\r\n') c.write('connection: upgrade\r\n') c.write('upgrade: websocket\r\n') @@ -341,7 +344,7 @@ test('basic aborted after res', async (t) => { const signal = new EE() const server = http.createServer({ joinDuplicateHeaders: true }) server.on('upgrade', (req, c, head) => { - c.write('HTTP/1.1 101\r\n') + c.write(SWITCHING_PROTOCOLS) c.write('hello: world\r\n') c.write('connection: upgrade\r\n') c.write('upgrade: websocket\r\n') @@ -377,7 +380,7 @@ test('basic upgrade error', async (t) => { const server = net.createServer({ joinDuplicateHeaders: true }, (c) => { c.on('data', (d) => { - c.write('HTTP/1.1 101\r\n') + c.write(SWITCHING_PROTOCOLS) c.write('hello: world\r\n') c.write('connection: upgrade\r\n') c.write('upgrade: websocket\r\n') diff --git a/test/issue-4389.js b/test/issue-4389.js index ffd1be7d9aa..e2d1f902de8 100644 --- a/test/issue-4389.js +++ b/test/issue-4389.js @@ -27,7 +27,10 @@ describe('Interceptor should not break multi-value headers', () => { assert.deepStrictEqual(headers.getSetCookie(), ['a=1', 'b=2', 'c=3']) }) - test('Interceptor should not break other multi-value header', async (t) => { + test('Interceptor should not break other multi-value header', { + // Milo intentionally does not support HTTP/1.0 responses. + skip: process.env.UNDICI_USE_MILO === 'true' && 'Milo does not support HTTP/1.0 responses' + }, async (t) => { const server = createSocketServer((socket) => { socket.write('HTTP/1.0 204 No Content\r\n') socket.write('X-Test-Header: 1\r\n') diff --git a/test/pool.js b/test/pool.js index c3a5c992191..3146a5b8fce 100644 --- a/test/pool.js +++ b/test/pool.js @@ -24,6 +24,9 @@ const { errors } = require('..') +// RFC 9112 requires a space after the status code even when the reason phrase is empty. +const SWITCHING_PROTOCOLS = 'HTTP/1.1 101 Switching Protocols\r\n' + test('throws when connection is infinite', async (t) => { t = tspl(t, { plan: 2 }) @@ -514,7 +517,7 @@ test('pool upgrade promise', async (t) => { const server = net.createServer({ joinDuplicateHeaders: true }, (c) => { c.on('data', (d) => { - c.write('HTTP/1.1 101\r\n') + c.write(SWITCHING_PROTOCOLS) c.write('hello: world\r\n') c.write('connection: upgrade\r\n') c.write('upgrade: websocket\r\n') @@ -861,7 +864,7 @@ test('pool upgrade error', async (t) => { const server = net.createServer({ joinDuplicateHeaders: true }, (c) => { c.on('data', (d) => { - c.write('HTTP/1.1 101\r\n') + c.write(SWITCHING_PROTOCOLS) c.write('hello: world\r\n') c.write('connection: upgrade\r\n') c.write('\r\n')