_const.mjs

//本檔為內部使用之常數, 不由index匯出


/**
 * 計時器(setTimeout、setInterval)之延遲毫秒上限
 *
 * 值為 2^31 - 1 = 2147483647 毫秒, 約 24.8 天。
 *
 *
 * 【為何需要此上限 —— nodejs與瀏覽器之行為不同, 且皆為靜默失效】
 *
 * 兩環境對超界值之處理機制不同, 實測(nodejs v24 / chromium)如下:
 *
 *   輸入ms          nodejs                    chromium
 *   -------------- ------------------------- -----------------------------------
 *   2147483647     正常排程                    正常排程
 *   2^31           立即觸發(1ms)+警告          立即觸發(ToInt32為-2147483648)
 *   2^32 - 5000    立即觸發(1ms)+警告          立即觸發(ToInt32為-5000)
 *   2^32 + 5000    立即觸發(1ms)+警告          【約5秒後觸發】(ToInt32為5000)
 *   2^32 + 100     立即觸發(1ms)+警告          【約100ms後觸發】(ToInt32為100)
 *   Infinity       立即觸發(1ms)+警告          立即觸發(ToInt32為0)
 *   NaN            立即觸發(1ms)+警告          立即觸發(ToInt32為0)
 *   -1             立即觸發(1ms)+警告          立即觸發
 *
 * nodejs為自家實作: 超過 2^31-1 一律夾為 1ms, 並以 process.on('warning') 發出
 * TimeoutOverflowWarning(NaN為TimeoutNaNWarning、負數為TimeoutNegativeWarning), 不拋錯。
 *
 * 瀏覽器則依 WebIDL 之 long 型別轉換(即 ToInt32), 對超界值做 modulo 2^32 之【環繞】而非夾制,
 * 且【完全沒有警告】。故 2^32 + 5000 於瀏覽器不是立即觸發, 而是 5 秒後觸發 ——
 * 表面上看起來正常運作, 只是時間完全錯了(49.7天變成5秒), 比nodejs之立即觸發更難察覺。
 * 環繞亦非單調: 輸入越大不代表延遲越長, 無法由行為反推輸入。
 *
 * wsemi為同構套件(前後端皆用), 故不可依賴runtime之行為, 必須於進入setTimeout之前自行夾制。
 * 夾制後兩環境行為一致(皆為正常排程至上限), 環境差異消失。
 *
 *
 * 【為何是夾制而非退回預設值或拋錯】
 *
 * 呼叫端給出超大值時, 其意圖顯然是「很久」或「幾乎不觸發」, 夾至 24.8 天最接近該意圖;
 * 退回預設值(如50ms)會變成高頻輪詢, 與意圖完全相反且更危險; 拋錯則對既有呼叫端為破壞性變更。
 *
 *
 * 【與安全整數界線之區別 —— 兩者須分開檢核】
 *
 * ispint(v, { useLimitSafe: true }) 擋的是「非安全整數」(Infinity、1e300、超出
 * Number.MAX_SAFE_INTEGER 者), 但 2^31 本身【是】合法的安全整數, 只是超過計時器之32位元上限。
 * 故型別與安全整數之檢核【擋不住】本上限, 兩層界線必須各自處理:
 *   第一層 ispint / isp0int 等: 擋型別錯誤與非安全整數
 *   第二層 本常數之夾制:       擋超過計時器上限者
 *
 *
 * 【用法】
 *
 *   import cst from './_const.mjs'
 *   timeAlive = Math.min(timeAlive, cst.TIMER_TIME_MAX) //須用min, 用max會把正常值放大為上限
 *
 * @type {Integer}
 */
let TIMER_TIME_MAX = 2147483647


let cst = {
    TIMER_TIME_MAX,
}


export default cst