Skip to content

Commit

Permalink
Backport changes from Node
Browse files Browse the repository at this point in the history
This doesn’t really do anything.
  • Loading branch information
wooorm committed Apr 24, 2023
1 parent 4a25fe6 commit c6aa7d5
Show file tree
Hide file tree
Showing 7 changed files with 275 additions and 50 deletions.
135 changes: 135 additions & 0 deletions lib/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,21 @@ const isWindows = process.platform === 'win32'

const own = {}.hasOwnProperty

const classRegExp = /^([A-Z][a-z\d]*)+$/
// Sorted by a rough estimate on most frequently used entries.
const kTypes = new Set([
'string',
'function',
'number',
'object',
// Accept 'Function' and 'Object' as alternative to the lower cased version.
'Function',
'Object',
'boolean',
'bigint',
'symbol'
])

export const codes = {}

/**
Expand All @@ -53,6 +68,95 @@ const nodeInternalPrefix = '__node_internal_'
/** @type {number} */
let userStackTraceLimit

codes.ERR_INVALID_ARG_TYPE = createError(
'ERR_INVALID_ARG_TYPE',
/**
* @param {string} name
* @param {Array<string> | string} expected
* @param {unknown} actual
*/
(name, expected, actual) => {
assert(typeof name === 'string', "'name' must be a string")
if (!Array.isArray(expected)) {
expected = [expected]
}

let message = 'The '
if (name.endsWith(' argument')) {
// For cases like 'first argument'
message += `${name} `
} else {
const type = name.includes('.') ? 'property' : 'argument'
message += `"${name}" ${type} `
}

message += 'must be '

/** @type {Array<string>} */
const types = []
/** @type {Array<string>} */
const instances = []
/** @type {Array<string>} */
const other = []

for (const value of expected) {
assert(
typeof value === 'string',
'All expected entries have to be of type string'
)

if (kTypes.has(value)) {
types.push(value.toLowerCase())
} else if (classRegExp.exec(value) === null) {
assert(
value !== 'object',
'The value "object" should be written as "Object"'
)
other.push(value)
} else {
instances.push(value)
}
}

// Special handle `object` in case other instances are allowed to outline
// the differences between each other.
if (instances.length > 0) {
const pos = types.indexOf('object')
if (pos !== -1) {
types.slice(pos, 1)
instances.push('Object')
}
}

if (types.length > 0) {
message += `${types.length > 1 ? 'one of type' : 'of type'} ${formatList(
types,
'or'
)}`
if (instances.length > 0 || other.length > 0) message += ' or '
}

if (instances.length > 0) {
message += `an instance of ${formatList(instances, 'or')}`
if (other.length > 0) message += ' or '
}

if (other.length > 0) {
if (other.length > 1) {
message += `one of ${formatList(other, 'or')}`
} else {
if (other[0].toLowerCase() !== other[0]) message += 'an '
message += `${other[0]}`
}
}

message += `. Received ${determineSpecificType(actual)}`

return message
},
TypeError
)

codes.ERR_INVALID_MODULE_SPECIFIER = createError(
'ERR_INVALID_MODULE_SPECIFIER',
/**
Expand Down Expand Up @@ -387,3 +491,34 @@ function getMessage(key, args, self) {
args.unshift(message)
return Reflect.apply(format, null, args)
}

/**
* Determine the specific type of a value for type-mismatch errors.
* @param {unknown} value
* @returns {string}
*/
function determineSpecificType(value) {
if (value === null || value === undefined) {
return String(value)
}

if (typeof value === 'function' && value.name) {
return `function ${value.name}`
}

if (typeof value === 'object') {
if (value.constructor && value.constructor.name) {
return `an instance of ${value.constructor.name}`
}

return `${inspect(value, {depth: -1})}`
}

let inspected = inspect(value, {colors: false})

if (inspected.length > 28) {
inspected = `${inspected.slice(0, 25)}...`
}

return `type ${typeof value} (${inspected})`
}
41 changes: 36 additions & 5 deletions lib/get-format.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
// Manually “tree shaken” from:
// <https://github.com/nodejs/node/blob/6668c4d/lib/internal/modules/esm/get_format.js>
// Last checked on: Jan 6, 2023.
// <https://github.com/nodejs/node/blob/3e74590/lib/internal/modules/esm/get_format.js>
// Last checked on: Apr 24, 2023.

import path from 'node:path'
import {URL, fileURLToPath} from 'node:url'
import {getPackageType} from './resolve-get-package-type.js'
import {codes} from './errors.js'
Expand Down Expand Up @@ -68,12 +67,43 @@ function getDataProtocolModuleFormat(parsed) {
return mimeToFormat(mime)
}

/**
* Returns the file extension from a URL.
*
* Should give similar result to
* `require('node:path').extname(require('node:url').fileURLToPath(url))`
* when used with a `file:` URL.
*
* @param {URL} url
* @returns {string}
*/
function extname(url) {
const pathname = url.pathname
let index = pathname.length

while (index--) {
const code = pathname.codePointAt(index)

if (code === 47 /* `/` */) {
return ''
}

if (code === 46 /* `.` */) {
return pathname.codePointAt(index - 1) === 47 /* `/` */
? ''
: pathname.slice(index)
}
}

return ''
}

/**
* @type {ProtocolHandler}
*/
function getFileProtocolModuleFormat(url, _context, ignoreErrors) {
const filepath = fileURLToPath(url)
const ext = path.extname(filepath)
const ext = extname(url)

if (ext === '.js') {
return getPackageType(url) === 'module' ? 'module' : 'commonjs'
}
Expand All @@ -86,6 +116,7 @@ function getFileProtocolModuleFormat(url, _context, ignoreErrors) {
return undefined
}

const filepath = fileURLToPath(url)
throw new ERR_UNKNOWN_FILE_EXTENSION(ext, filepath)
}

Expand Down
4 changes: 2 additions & 2 deletions lib/package-config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Manually “tree shaken” from:
// <https://github.com/nodejs/node/blob/6668c4d/lib/internal/modules/esm/package_config.js>
// Last checked on: Jan 6, 2023.
// <https://github.com/nodejs/node/blob/3e74590/lib/internal/modules/esm/package_config.js>
// Last checked on: Apr 24, 2023.

/**
* @typedef {import('./errors.js').ErrnoException} ErrnoException
Expand Down
4 changes: 2 additions & 2 deletions lib/package-json-reader.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Manually “tree shaken” from:
// <https://github.com/nodejs/node/blob/6668c4d/lib/internal/modules/package_json_reader.js>
// Last checked on: Jan 6, 2023.
// <https://github.com/nodejs/node/blob/3e74590/lib/internal/modules/package_json_reader.js>
// Last checked on: Apr 24, 2023.
// Removed the native dependency.
// Also: no need to cache, we do that in resolve already.

Expand Down
4 changes: 2 additions & 2 deletions lib/resolve-get-package-type.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Manually “tree shaken” from:
// <https://github.com/nodejs/node/blob/6668c4d/lib/internal/modules/esm/resolve.js>
// Last checked on: Jan 6, 2023.
// <https://github.com/nodejs/node/blob/3e74590/lib/internal/modules/esm/resolve.js>
// Last checked on: Apr 24, 2023.
//
// This file solves a circular dependency.
// In Node.js, `getPackageType` is in `resolve.js`.
Expand Down
Loading

0 comments on commit c6aa7d5

Please sign in to comment.