Skip to content

Commit

Permalink
Merge branch 'main' into strip-comments
Browse files Browse the repository at this point in the history
  • Loading branch information
KhafraDev authored Feb 11, 2024
2 parents a5ec540 + 94a9b56 commit 0aa33ae
Show file tree
Hide file tree
Showing 80 changed files with 2,078 additions and 1,374 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ jobs:

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@012739e5082ff0c22ca6d6ab32e07c36df03c4a4 # v2.3.3
uses: github/codeql-action/init@b7bf0a3ed3ecfa44160715d7c442788f65f0f923 # v2.3.3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
Expand All @@ -60,7 +60,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@012739e5082ff0c22ca6d6ab32e07c36df03c4a4 # v2.3.3
uses: github/codeql-action/autobuild@b7bf0a3ed3ecfa44160715d7c442788f65f0f923 # v2.3.3

# ℹ️ Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
Expand All @@ -73,6 +73,6 @@ jobs:
# ./location_of_script_within_repo/buildscript.sh

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@012739e5082ff0c22ca6d6ab32e07c36df03c4a4 # v2.3.3
uses: github/codeql-action/analyze@b7bf0a3ed3ecfa44160715d7c442788f65f0f923 # v2.3.3
with:
category: "/language:${{matrix.language}}"
2 changes: 1 addition & 1 deletion .github/workflows/dependency-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,4 @@ jobs:
- name: 'Checkout Repository'
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
- name: 'Dependency Review'
uses: actions/dependency-review-action@6c5ccdad469c9f8a2996bfecaec55a631a347034 # v3.1.0
uses: actions/dependency-review-action@4901385134134e04cec5fbe5ddfe3b2c5bd5d976 # v4.0.0
3 changes: 2 additions & 1 deletion .github/workflows/nodejs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ name: Node CI
on:
push:
branches:
- main
- current
- next
- 'v*'
Expand All @@ -22,7 +23,7 @@ jobs:
timeout-minutes: 15
post-test-steps: |
- name: Coverage Report
uses: codecov/codecov-action@v3
uses: codecov/codecov-action@v4
automerge:
if: >
github.event_name == 'pull_request' && github.event.pull_request.user.login == 'dependabot[bot]'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/scorecard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,6 @@ jobs:

# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@012739e5082ff0c22ca6d6ab32e07c36df03c4a4 # v3.22.12
uses: github/codeql-action/upload-sarif@b7bf0a3ed3ecfa44160715d7c442788f65f0f923 # v3.23.2
with:
sarif_file: results.sarif
19 changes: 19 additions & 0 deletions benchmarks/benchmark.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const { Pool, Client, fetch, Agent, setGlobalDispatcher } = require('..')

let nodeFetch
const axios = require('axios')
let superagent
let got

const util = require('node:util')
Expand Down Expand Up @@ -85,6 +86,11 @@ const requestAgent = new http.Agent({
maxSockets: connections
})

const superagentAgent = new http.Agent({
keepAlive: true,
maxSockets: connections
})

const undiciOptions = {
path: '/',
method: 'GET',
Expand Down Expand Up @@ -318,6 +324,16 @@ if (process.env.PORT) {
}).catch(console.log)
})
}

experiments.superagent = () => {
return makeParallelRequests(resolve => {
superagent.get(dest.url).pipe(new Writable({
write (chunk, encoding, callback) {
callback()
}
})).on('finish', resolve)
})
}
}

async function main () {
Expand All @@ -326,6 +342,9 @@ async function main () {
nodeFetch = _nodeFetch.default
const _got = await import('got')
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))

cronometro(
experiments,
Expand Down
2 changes: 2 additions & 0 deletions build/wasm.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ if (EXTERNAL_PATH) {
writeFileSync(join(ROOT, 'loader.js'), `
'use strict'
globalThis.__UNDICI_IS_NODE__ = true
module.exports = require('node:module').createRequire('${EXTERNAL_PATH}/loader.js')('./index-fetch.js')
delete globalThis.__UNDICI_IS_NODE__
`)
}
3 changes: 3 additions & 0 deletions index-fetch.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,7 @@ module.exports.FormData = require('./lib/fetch/formdata').FormData
module.exports.Headers = require('./lib/fetch/headers').Headers
module.exports.Response = require('./lib/fetch/response').Response
module.exports.Request = require('./lib/fetch/request').Request

module.exports.WebSocket = require('./lib/websocket/websocket').WebSocket

module.exports.EventSource = require('./lib/eventsource/eventsource').EventSource
23 changes: 21 additions & 2 deletions lib/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -808,6 +808,7 @@ class Parser {
.removeListener('close', onSocketClose)

client[kSocket] = null
client[kHTTP2Session] = null
client[kQueue][client[kRunningIdx]++] = null
client.emit('disconnect', client[kUrl], [client], new InformationalError('upgrade'))

Expand Down Expand Up @@ -1421,7 +1422,7 @@ function _resume (client, sync) {
return
}

if (!socket && !client[kHTTP2Session]) {
if (!socket) {
connect(client)
return
}
Expand Down Expand Up @@ -1796,7 +1797,25 @@ function writeH2 (client, session, request) {
})

stream.once('end', () => {
request.onComplete([])
// When state is null, it means we haven't consumed body and the stream still do not have
// a state.
// Present specially when using pipeline or stream
if (stream.state?.state == null || stream.state.state < 6) {
request.onComplete([])
return
}

// Stream is closed or half-closed-remote (6), decrement counter and cleanup
// It does not have sense to continue working with the stream as we do not
// have yet RST_STREAM support on client-side
h2State.openStreams -= 1
if (h2State.openStreams === 0) {
session.unref()
}

const err = new InformationalError('HTTP/2: stream half-closed (remote)')
errorRequest(client, request, err)
util.destroy(stream, err)
})

stream.on('data', (chunk) => {
Expand Down
17 changes: 13 additions & 4 deletions lib/core/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,10 +164,19 @@ class Request {
processHeader(this, headers[i], headers[i + 1])
}
} else if (headers && typeof headers === 'object') {
const keys = Object.keys(headers)
for (let i = 0; i < keys.length; i++) {
const key = keys[i]
processHeader(this, key, headers[key])
if (headers[Symbol.iterator]) {
for (const header of headers) {
if (!Array.isArray(header) || header.length !== 2) {
throw new InvalidArgumentError('headers must be in key-value pair format')
}
const [key, value] = header
processHeader(this, key, value)
}
} else {
const keys = Object.keys(headers)
for (const key of keys) {
processHeader(this, key, headers[key])
}
}
} else if (headers != null) {
throw new InvalidArgumentError('headers must be an object or an array')
Expand Down
8 changes: 1 addition & 7 deletions lib/core/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -438,13 +438,7 @@ const hasToWellFormed = !!String.prototype.toWellFormed
* @param {string} val
*/
function toUSVString (val) {
if (hasToWellFormed) {
return `${val}`.toWellFormed()
} else if (nodeUtil.toUSVString) {
return nodeUtil.toUSVString(val)
}

return `${val}`
return hasToWellFormed ? `${val}`.toWellFormed() : nodeUtil.toUSVString(val)
}

/**
Expand Down
42 changes: 25 additions & 17 deletions lib/fetch/body.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,19 @@ const {
isReadableStreamLike,
readableStreamClose,
createDeferredPromise,
fullyReadBody
fullyReadBody,
extractMimeType
} = require('./util')
const { FormData } = require('./formdata')
const { kState } = require('./symbols')
const { webidl } = require('./webidl')
const { Blob, File: NativeFile } = require('node:buffer')
const { kBodyUsed, kHeadersList } = require('../core/symbols')
const { kBodyUsed } = require('../core/symbols')
const assert = require('node:assert')
const { isErrored } = require('../core/util')
const { isUint8Array, isArrayBuffer } = require('util/types')
const { File: UndiciFile } = require('./file')
const { parseMIMEType, serializeAMimeType } = require('./dataURL')
const { serializeAMimeType } = require('./dataURL')

/** @type {globalThis['File']} */
const File = NativeFile ?? UndiciFile
Expand Down Expand Up @@ -330,7 +331,7 @@ function bodyMixinMethods (instance) {
return specConsumeBody(this, (bytes) => {
let mimeType = bodyMimeType(this)

if (mimeType === 'failure') {
if (mimeType === null) {
mimeType = ''
} else if (mimeType) {
mimeType = serializeAMimeType(mimeType)
Expand Down Expand Up @@ -369,12 +370,11 @@ function bodyMixinMethods (instance) {

throwIfAborted(this[kState])

const contentType = this.headers[kHeadersList].get('content-type', true)

const mimeType = contentType !== null ? parseMIMEType(contentType) : 'failure'
// 1. Let mimeType be the result of get the MIME type with this.
const mimeType = bodyMimeType(this)

// If mimeType’s essence is "multipart/form-data", then:
if (mimeType !== 'failure' && mimeType.essence === 'multipart/form-data') {
if (mimeType !== null && mimeType.essence === 'multipart/form-data') {
const headers = {}
for (const [key, value] of this.headers) headers[key] = value

Expand Down Expand Up @@ -432,7 +432,7 @@ function bodyMixinMethods (instance) {
await busboyResolve

return responseFormData
} else if (mimeType !== 'failure' && mimeType.essence === 'application/x-www-form-urlencoded') {
} else if (mimeType !== null && mimeType.essence === 'application/x-www-form-urlencoded') {
// Otherwise, if mimeType’s essence is "application/x-www-form-urlencoded", then:

// 1. Let entries be the result of parsing bytes.
Expand Down Expand Up @@ -581,17 +581,25 @@ function parseJSONFromBytes (bytes) {

/**
* @see https://fetch.spec.whatwg.org/#concept-body-mime-type
* @param {import('./response').Response|import('./request').Request} object
* @param {import('./response').Response|import('./request').Request} requestOrResponse
*/
function bodyMimeType (object) {
const { headersList } = object[kState]
const contentType = headersList.get('content-type')

if (contentType === null) {
return 'failure'
function bodyMimeType (requestOrResponse) {
// 1. Let headers be null.
// 2. If requestOrResponse is a Request object, then set headers to requestOrResponse’s request’s header list.
// 3. Otherwise, set headers to requestOrResponse’s response’s header list.
/** @type {import('./headers').HeadersList} */
const headers = requestOrResponse[kState].headersList

// 4. Let mimeType be the result of extracting a MIME type from headers.
const mimeType = extractMimeType(headers)

// 5. If mimeType is failure, then return null.
if (mimeType === 'failure') {
return null
}

return parseMIMEType(contentType)
// 6. Return mimeType.
return mimeType
}

module.exports = {
Expand Down
Loading

0 comments on commit 0aa33ae

Please sign in to comment.