mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-28 06:53:42 +08:00
A require cycle was always refused (SC1016). Node answers a require of a
module that is still evaluating with its exports as they stand, while the
compiled bindings alias the final declarations; the two agree when every
module of the cycle assigns all of its exports before its first statement
that can run another module's code, every other use of its export object
is a plain member read, and no module's top-level code can reach its
binding of another member. Each module then initializes exactly as it
would outside the cycle. This admits semver's comparator/range cycle
("hoisted class for cyclic dependency"); other cycles keep SC1016 with a
reason naming the offending statement.
The require reachability scan no longer treats a declaration's own name
as a read (esbuild's `var X = class {...}` before its requires), treats a
plain write of an export member as running only a setter published for it
(on-finished's `module.exports.isFinished = isFinished`), and keeps the
conservative scan for writes of __proto__, __esModule and members of a
replaced export object.
Evidence: corpus 6145 (the cycle), 6142 gains the esbuild layout; the
npm-static harness compiles the published fs.realpath@1.0.0,
on-finished@2.4.1 (with ee-first@1.1.1) and statuses@2.0.1 statically;
program.test.ts pins the TDZ analysis through var bindings plus the cycle
admission and refusals. Preflight/order baselines recorded for the new
fixtures; a full re-record changed no other fixture. Dependencies and
limitations docs describe the supported require forms.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
147 lines
2.5 KiB
JavaScript
147 lines
2.5 KiB
JavaScript
/*!
|
|
* statuses
|
|
* Copyright(c) 2014 Jonathan Ong
|
|
* Copyright(c) 2016 Douglas Christopher Wilson
|
|
* MIT Licensed
|
|
*/
|
|
|
|
'use strict'
|
|
|
|
/**
|
|
* Module dependencies.
|
|
* @private
|
|
*/
|
|
|
|
var codes = require('./codes.json')
|
|
|
|
/**
|
|
* Module exports.
|
|
* @public
|
|
*/
|
|
|
|
module.exports = status
|
|
|
|
// status code to message map
|
|
status.message = codes
|
|
|
|
// status message (lower-case) to code map
|
|
status.code = createMessageToStatusCodeMap(codes)
|
|
|
|
// array of status codes
|
|
status.codes = createStatusCodeList(codes)
|
|
|
|
// status codes for redirects
|
|
status.redirect = {
|
|
300: true,
|
|
301: true,
|
|
302: true,
|
|
303: true,
|
|
305: true,
|
|
307: true,
|
|
308: true
|
|
}
|
|
|
|
// status codes for empty bodies
|
|
status.empty = {
|
|
204: true,
|
|
205: true,
|
|
304: true
|
|
}
|
|
|
|
// status codes for when you should retry the request
|
|
status.retry = {
|
|
502: true,
|
|
503: true,
|
|
504: true
|
|
}
|
|
|
|
/**
|
|
* Create a map of message to status code.
|
|
* @private
|
|
*/
|
|
|
|
function createMessageToStatusCodeMap (codes) {
|
|
var map = {}
|
|
|
|
Object.keys(codes).forEach(function forEachCode (code) {
|
|
var message = codes[code]
|
|
var status = Number(code)
|
|
|
|
// populate map
|
|
map[message.toLowerCase()] = status
|
|
})
|
|
|
|
return map
|
|
}
|
|
|
|
/**
|
|
* Create a list of all status codes.
|
|
* @private
|
|
*/
|
|
|
|
function createStatusCodeList (codes) {
|
|
return Object.keys(codes).map(function mapCode (code) {
|
|
return Number(code)
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Get the status code for given message.
|
|
* @private
|
|
*/
|
|
|
|
function getStatusCode (message) {
|
|
var msg = message.toLowerCase()
|
|
|
|
if (!Object.prototype.hasOwnProperty.call(status.code, msg)) {
|
|
throw new Error('invalid status message: "' + message + '"')
|
|
}
|
|
|
|
return status.code[msg]
|
|
}
|
|
|
|
/**
|
|
* Get the status message for given code.
|
|
* @private
|
|
*/
|
|
|
|
function getStatusMessage (code) {
|
|
if (!Object.prototype.hasOwnProperty.call(status.message, code)) {
|
|
throw new Error('invalid status code: ' + code)
|
|
}
|
|
|
|
return status.message[code]
|
|
}
|
|
|
|
/**
|
|
* Get the status code.
|
|
*
|
|
* Given a number, this will throw if it is not a known status
|
|
* code, otherwise the code will be returned. Given a string,
|
|
* the string will be parsed for a number and return the code
|
|
* if valid, otherwise will lookup the code assuming this is
|
|
* the status message.
|
|
*
|
|
* @param {string|number} code
|
|
* @returns {number}
|
|
* @public
|
|
*/
|
|
|
|
function status (code) {
|
|
if (typeof code === 'number') {
|
|
return getStatusMessage(code)
|
|
}
|
|
|
|
if (typeof code !== 'string') {
|
|
throw new TypeError('code must be a number or string')
|
|
}
|
|
|
|
// '403'
|
|
var n = parseInt(code, 10)
|
|
if (!isNaN(n)) {
|
|
return getStatusMessage(n)
|
|
}
|
|
|
|
return getStatusCode(code)
|
|
}
|