|
| 1 | +package no_deprecated_api |
| 2 | + |
| 3 | +// deprecatedInfo describes a single deprecated API entry, mirroring upstream's |
| 4 | +// `DeprecatedInfo` object ({ since, removed?, replacedBy }). |
| 5 | +// |
| 6 | +// replacedBy has three upstream shapes that map to two fields here: |
| 7 | +// - a plain string -> replacedText (used verbatim, no version filtering) |
| 8 | +// - an array -> replacedList (filtered by the configured node version) |
| 9 | +// - null -> both empty (no "Use ... instead" suffix) |
| 10 | +type deprecatedInfo struct { |
| 11 | + since string |
| 12 | + removed string // "" unless the API was removed (uses the "removed" messageId) |
| 13 | + replacedText string |
| 14 | + replacedList []replaceEntry |
| 15 | +} |
| 16 | + |
| 17 | +// replaceEntry is one `{ name, supported }` alternative in a replacedBy array. |
| 18 | +type replaceEntry struct { |
| 19 | + name string |
| 20 | + supported string |
| 21 | +} |
| 22 | + |
| 23 | +// traceMap is the Go equivalent of upstream's `DeprecatedInfoTraceMap`: a tree |
| 24 | +// keyed by property name, where the READ/CALL/CONSTRUCT slots mark a terminal |
| 25 | +// deprecated access of that kind. |
| 26 | +type traceMap struct { |
| 27 | + read *deprecatedInfo |
| 28 | + call *deprecatedInfo |
| 29 | + construct *deprecatedInfo |
| 30 | + children map[string]*traceMap |
| 31 | +} |
| 32 | + |
| 33 | +// --- deprecatedInfo constructors (keep the data tables below compact) --- |
| 34 | + |
| 35 | +func depNull(since string) *deprecatedInfo { return &deprecatedInfo{since: since} } |
| 36 | + |
| 37 | +func depRemoved(since, removed string) *deprecatedInfo { |
| 38 | + return &deprecatedInfo{since: since, removed: removed} |
| 39 | +} |
| 40 | + |
| 41 | +func depStr(since, replaced string) *deprecatedInfo { |
| 42 | + return &deprecatedInfo{since: since, replacedText: replaced} |
| 43 | +} |
| 44 | + |
| 45 | +func depList(since string, entries ...replaceEntry) *deprecatedInfo { |
| 46 | + return &deprecatedInfo{since: since, replacedList: entries} |
| 47 | +} |
| 48 | + |
| 49 | +func rep(name, supported string) replaceEntry { return replaceEntry{name: name, supported: supported} } |
| 50 | + |
| 51 | +// rawModules mirrors upstream lib/rules/no-deprecated-api.js `rawModules` |
| 52 | +// (the CommonJS / ESM module deprecation table) 1:1. |
| 53 | +var rawModules = map[string]*traceMap{ |
| 54 | + "_linklist": {read: depNull("5.0.0")}, |
| 55 | + "_stream_wrap": {read: depNull("12.0.0")}, |
| 56 | + "async_hooks": {children: map[string]*traceMap{ |
| 57 | + "currentId": {read: depList("8.2.0", rep("'async_hooks.executionAsyncId()'", "8.1.0"))}, |
| 58 | + "triggerId": {read: depStr("8.2.0", "'async_hooks.triggerAsyncId()'")}, |
| 59 | + }}, |
| 60 | + "buffer": {children: map[string]*traceMap{ |
| 61 | + "Buffer": { |
| 62 | + construct: depList("6.0.0", rep("'buffer.Buffer.alloc()'", "5.10.0"), rep("'buffer.Buffer.from()'", "5.10.0")), |
| 63 | + call: depList("6.0.0", rep("'buffer.Buffer.alloc()'", "5.10.0"), rep("'buffer.Buffer.from()'", "5.10.0")), |
| 64 | + }, |
| 65 | + "SlowBuffer": {read: depList("6.0.0", rep("'buffer.Buffer.allocUnsafeSlow()'", "5.12.0"))}, |
| 66 | + }}, |
| 67 | + "constants": {read: depStr("6.3.0", "'constants' property of each module")}, |
| 68 | + "crypto": {children: map[string]*traceMap{ |
| 69 | + "_toBuf": {read: depNull("11.0.0")}, |
| 70 | + "Credentials": {read: depStr("0.12.0", "'tls.SecureContext'")}, |
| 71 | + "DEFAULT_ENCODING": {read: depNull("10.0.0")}, |
| 72 | + "createCipher": {read: depList("10.0.0", rep("'crypto.createCipheriv()'", "0.1.94"))}, |
| 73 | + "createCredentials": {read: depList("0.12.0", rep("'tls.createSecureContext()'", "0.11.13"))}, |
| 74 | + "createDecipher": {read: depList("10.0.0", rep("'crypto.createDecipheriv()'", "0.1.94"))}, |
| 75 | + "fips": {read: depList("10.0.0", rep("'crypto.getFips()' and 'crypto.setFips()'", "10.0.0"))}, |
| 76 | + "prng": {read: depList("11.0.0", rep("'crypto.randomBytes()'", "0.5.8"))}, |
| 77 | + "pseudoRandomBytes": {read: depList("11.0.0", rep("'crypto.randomBytes()'", "0.5.8"))}, |
| 78 | + "rng": {read: depList("11.0.0", rep("'crypto.randomBytes()'", "0.5.8"))}, |
| 79 | + }}, |
| 80 | + "domain": {read: depNull("4.0.0")}, |
| 81 | + "events": {children: map[string]*traceMap{ |
| 82 | + "EventEmitter": {children: map[string]*traceMap{ |
| 83 | + "listenerCount": {read: depList("4.0.0", rep("'events.EventEmitter#listenerCount()'", "3.2.0"))}, |
| 84 | + }}, |
| 85 | + "listenerCount": {read: depList("4.0.0", rep("'events.EventEmitter#listenerCount()'", "3.2.0"))}, |
| 86 | + }}, |
| 87 | + "freelist": {read: depNull("4.0.0")}, |
| 88 | + "fs": {children: map[string]*traceMap{ |
| 89 | + "SyncWriteStream": {read: depNull("4.0.0")}, |
| 90 | + "exists": {read: depList("4.0.0", rep("'fs.stat()'", "0.0.2"), rep("'fs.access()'", "0.11.15"))}, |
| 91 | + "lchmod": {read: depNull("0.4.0")}, |
| 92 | + "lchmodSync": {read: depNull("0.4.0")}, |
| 93 | + }}, |
| 94 | + "http": {children: map[string]*traceMap{ |
| 95 | + "createClient": {read: depList("0.10.0", rep("'http.request()'", "0.3.6"))}, |
| 96 | + }}, |
| 97 | + "module": {children: map[string]*traceMap{ |
| 98 | + "Module": {children: map[string]*traceMap{ |
| 99 | + "createRequireFromPath": {read: depList("12.2.0", rep("'module.createRequire()'", "12.2.0"))}, |
| 100 | + "requireRepl": {read: depStr("6.0.0", "'require(\"repl\")'")}, |
| 101 | + "_debug": {read: depNull("9.0.0")}, |
| 102 | + }}, |
| 103 | + "createRequireFromPath": {read: depList("12.2.0", rep("'module.createRequire()'", "12.2.0"))}, |
| 104 | + "requireRepl": {read: depStr("6.0.0", "'require(\"repl\")'")}, |
| 105 | + "_debug": {read: depNull("9.0.0")}, |
| 106 | + }}, |
| 107 | + "net": {children: map[string]*traceMap{ |
| 108 | + "_setSimultaneousAccepts": {read: depNull("12.0.0")}, |
| 109 | + }}, |
| 110 | + "os": {children: map[string]*traceMap{ |
| 111 | + "getNetworkInterfaces": {read: depList("0.6.0", rep("'os.networkInterfaces()'", "0.6.0"))}, |
| 112 | + "tmpDir": {read: depList("7.0.0", rep("'os.tmpdir()'", "0.9.9"))}, |
| 113 | + }}, |
| 114 | + "path": {children: map[string]*traceMap{ |
| 115 | + "_makeLong": {read: depList("9.0.0", rep("'path.toNamespacedPath()'", "9.0.0"))}, |
| 116 | + }}, |
| 117 | + "process": {children: map[string]*traceMap{ |
| 118 | + "EventEmitter": {read: depStr("0.6.0", "'require(\"events\")'")}, |
| 119 | + "assert": {read: depStr("10.0.0", "'require(\"assert\")'")}, |
| 120 | + "binding": {read: depNull("10.9.0")}, |
| 121 | + "env": {children: map[string]*traceMap{ |
| 122 | + "NODE_REPL_HISTORY_FILE": {read: depStr("4.0.0", "'NODE_REPL_HISTORY'")}, |
| 123 | + }}, |
| 124 | + "report": {children: map[string]*traceMap{ |
| 125 | + "triggerReport": {read: depStr("11.12.0", "'process.report.writeReport()'")}, |
| 126 | + }}, |
| 127 | + }}, |
| 128 | + "punycode": {read: depStr("7.0.0", "'https://www.npmjs.com/package/punycode'")}, |
| 129 | + "readline": {children: map[string]*traceMap{ |
| 130 | + "codePointAt": {read: depNull("4.0.0")}, |
| 131 | + "getStringWidth": {read: depNull("6.0.0")}, |
| 132 | + "isFullWidthCodePoint": {read: depNull("6.0.0")}, |
| 133 | + "stripVTControlCharacters": {read: depNull("6.0.0")}, |
| 134 | + }}, |
| 135 | + "repl": {children: map[string]*traceMap{ |
| 136 | + "REPLServer": {read: depStr("22.9.0", "new repl.REPLServer()")}, |
| 137 | + "Recoverable": {read: depStr("22.9.0", "new repl.Recoverable()")}, |
| 138 | + "REPL_MODE_MAGIC": {read: depNull("8.0.0")}, |
| 139 | + "builtinModules": {read: depStr("22.16.0", "module.builtinModules")}, |
| 140 | + }}, |
| 141 | + // safe-buffer.Buffer function/constructor is just a re-export of buffer.Buffer |
| 142 | + // and should be deprecated likewise. |
| 143 | + "safe-buffer": {children: map[string]*traceMap{ |
| 144 | + "Buffer": { |
| 145 | + construct: depList("6.0.0", rep("'buffer.Buffer.alloc()'", "5.10.0"), rep("'buffer.Buffer.from()'", "5.10.0")), |
| 146 | + call: depList("6.0.0", rep("'buffer.Buffer.alloc()'", "5.10.0"), rep("'buffer.Buffer.from()'", "5.10.0")), |
| 147 | + }, |
| 148 | + "SlowBuffer": {read: depList("6.0.0", rep("'buffer.Buffer.allocUnsafeSlow()'", "5.12.0"))}, |
| 149 | + }}, |
| 150 | + "sys": {read: depStr("0.3.0", "'util' module")}, |
| 151 | + "timers": {children: map[string]*traceMap{ |
| 152 | + "enroll": {read: depList("10.0.0", rep("'setTimeout()'", "0.0.1"), rep("'setInterval()'", "0.0.1"))}, |
| 153 | + "unenroll": {read: depList("10.0.0", rep("'clearTimeout()'", "0.0.1"), rep("'clearInterval()'", "0.0.1"))}, |
| 154 | + }}, |
| 155 | + "tls": {children: map[string]*traceMap{ |
| 156 | + "CleartextStream": {read: depNull("0.10.0")}, |
| 157 | + "CryptoStream": {read: depList("0.12.0", rep("'tls.TLSSocket'", "0.11.4"))}, |
| 158 | + "SecurePair": {read: depList("6.0.0", rep("'tls.TLSSocket'", "0.11.4"))}, |
| 159 | + "convertNPNProtocols": {read: depNull("10.0.0")}, |
| 160 | + "createSecurePair": {read: depList("6.0.0", rep("'tls.TLSSocket'", "0.11.4"))}, |
| 161 | + "parseCertString": {read: depList("8.6.0", rep("'querystring.parse()'", "0.1.25"))}, |
| 162 | + }}, |
| 163 | + "tty": {children: map[string]*traceMap{ |
| 164 | + "setRawMode": {read: depStr("0.10.0", "'tty.ReadStream#setRawMode()' (e.g. 'process.stdin.setRawMode()')")}, |
| 165 | + }}, |
| 166 | + "url": {children: map[string]*traceMap{ |
| 167 | + "parse": {read: depList("11.0.0", rep("'url.URL' constructor", "6.13.0"))}, |
| 168 | + "resolve": {read: depList("11.0.0", rep("'url.URL' constructor", "6.13.0"))}, |
| 169 | + }}, |
| 170 | + "util": {children: map[string]*traceMap{ |
| 171 | + "debug": {read: depList("0.12.0", rep("'console.error()'", "0.1.100"))}, |
| 172 | + "error": {read: depList("0.12.0", rep("'console.error()'", "0.1.100"))}, |
| 173 | + "isArray": {read: depList("4.0.0", rep("'Array.isArray()'", "0.1.100"))}, |
| 174 | + "isBoolean": {read: depNull("4.0.0")}, |
| 175 | + "isBuffer": {read: depList("4.0.0", rep("'Buffer.isBuffer()'", "0.1.101"))}, |
| 176 | + "isDate": {read: depNull("4.0.0")}, |
| 177 | + "isError": {read: depNull("4.0.0")}, |
| 178 | + "isFunction": {read: depNull("4.0.0")}, |
| 179 | + "isNull": {read: depNull("4.0.0")}, |
| 180 | + "isNullOrUndefined": {read: depNull("4.0.0")}, |
| 181 | + "isNumber": {read: depNull("4.0.0")}, |
| 182 | + "isObject": {read: depNull("4.0.0")}, |
| 183 | + "isPrimitive": {read: depNull("4.0.0")}, |
| 184 | + "isRegExp": {read: depNull("4.0.0")}, |
| 185 | + "isString": {read: depNull("4.0.0")}, |
| 186 | + "isSymbol": {read: depNull("4.0.0")}, |
| 187 | + "isUndefined": {read: depNull("4.0.0")}, |
| 188 | + "log": {read: depStr("6.0.0", "a third party module")}, |
| 189 | + "print": {read: depList("0.12.0", rep("'console.log()'", "0.1.100"))}, |
| 190 | + "pump": {read: depList("0.10.0", rep("'stream.Readable#pipe()'", "0.9.4"))}, |
| 191 | + "puts": {read: depList("0.12.0", rep("'console.log()'", "0.1.100"))}, |
| 192 | + "_extend": {read: depList("6.0.0", rep("'Object.assign()'", "4.0.0"))}, |
| 193 | + }}, |
| 194 | + "vm": {children: map[string]*traceMap{ |
| 195 | + "runInDebugContext": {read: depNull("8.0.0")}, |
| 196 | + }}, |
| 197 | + "zlib": {children: map[string]*traceMap{ |
| 198 | + "BrotliCompress": {call: depStr("22.9.0", "new zlib.BrotliCompress()")}, |
| 199 | + "BrotliDecompress": {call: depStr("22.9.0", "new zlib.BrotliDecompress()")}, |
| 200 | + "Deflate": {call: depStr("22.9.0", "new zlib.Deflate()")}, |
| 201 | + "DeflateRaw": {call: depStr("22.9.0", "new zlib.DeflateRaw()")}, |
| 202 | + "Gunzip": {call: depStr("22.9.0", "new zlib.Gunzip()")}, |
| 203 | + "Gzip": {call: depStr("22.9.0", "new zlib.Gzip()")}, |
| 204 | + "Inflate": {call: depStr("22.9.0", "new zlib.Inflate()")}, |
| 205 | + "InflateRaw": {call: depStr("22.9.0", "new zlib.InflateRaw()")}, |
| 206 | + "Unzip": {call: depStr("22.9.0", "new zlib.Unzip()")}, |
| 207 | + }}, |
| 208 | +} |
| 209 | + |
| 210 | +// modules is rawModules extended with `node:`-prefixed aliases for builtins. |
| 211 | +var modules = extendTraceMapWithNodePrefix(rawModules) |
| 212 | + |
| 213 | +// globals mirrors upstream's `globals` table (deprecated global variables). |
| 214 | +// `process` reuses the module trace map so `process.binding` etc. are detected |
| 215 | +// as global member accesses too. |
| 216 | +var globals = map[string]*traceMap{ |
| 217 | + "Buffer": { |
| 218 | + construct: depList("6.0.0", rep("'Buffer.alloc()'", "5.10.0"), rep("'Buffer.from()'", "5.10.0")), |
| 219 | + call: depList("6.0.0", rep("'Buffer.alloc()'", "5.10.0"), rep("'Buffer.from()'", "5.10.0")), |
| 220 | + }, |
| 221 | + "COUNTER_NET_SERVER_CONNECTION": {read: depNull("11.0.0")}, |
| 222 | + "COUNTER_NET_SERVER_CONNECTION_CLOSE": {read: depNull("11.0.0")}, |
| 223 | + "COUNTER_HTTP_SERVER_REQUEST": {read: depNull("11.0.0")}, |
| 224 | + "COUNTER_HTTP_SERVER_RESPONSE": {read: depNull("11.0.0")}, |
| 225 | + "COUNTER_HTTP_CLIENT_REQUEST": {read: depNull("11.0.0")}, |
| 226 | + "COUNTER_HTTP_CLIENT_RESPONSE": {read: depNull("11.0.0")}, |
| 227 | + "GLOBAL": {read: depList("6.0.0", rep("'global'", "0.1.27"))}, |
| 228 | + "Intl": {children: map[string]*traceMap{ |
| 229 | + "v8BreakIterator": {read: depRemoved("7.0.0", "9.0.0")}, |
| 230 | + }}, |
| 231 | + "require": {children: map[string]*traceMap{ |
| 232 | + "extensions": {read: depStr("0.12.0", "compiling them ahead of time")}, |
| 233 | + }}, |
| 234 | + "root": {read: depList("6.0.0", rep("'global'", "0.1.27"))}, |
| 235 | + "process": rawModules["process"], |
| 236 | +} |
| 237 | + |
| 238 | +// nodeBuiltinModules is the set of Node.js builtin module names, used as the |
| 239 | +// `module.isBuiltin` equivalent for extendTraceMapWithNodePrefix. Names with a |
| 240 | +// leading underscore, removed modules (`sys`, `freelist`), and third-party |
| 241 | +// re-exports (`safe-buffer`) are intentionally absent — they get no `node:` |
| 242 | +// alias, matching upstream's `isBuiltin` filter. |
| 243 | +var nodeBuiltinModules = map[string]bool{ |
| 244 | + "assert": true, "assert/strict": true, "async_hooks": true, "buffer": true, |
| 245 | + "child_process": true, "cluster": true, "console": true, "constants": true, |
| 246 | + "crypto": true, "dgram": true, "diagnostics_channel": true, "dns": true, |
| 247 | + "dns/promises": true, "domain": true, "events": true, "fs": true, |
| 248 | + "fs/promises": true, "http": true, "http2": true, "https": true, |
| 249 | + "inspector": true, "inspector/promises": true, "module": true, "net": true, |
| 250 | + "os": true, "path": true, "path/posix": true, "path/win32": true, |
| 251 | + "perf_hooks": true, "process": true, "punycode": true, "querystring": true, |
| 252 | + "readline": true, "readline/promises": true, "repl": true, "stream": true, |
| 253 | + "stream/consumers": true, "stream/promises": true, "stream/web": true, |
| 254 | + "string_decoder": true, "timers": true, "timers/promises": true, "tls": true, |
| 255 | + "trace_events": true, "tty": true, "url": true, "util": true, |
| 256 | + "util/types": true, "v8": true, "vm": true, "wasi": true, |
| 257 | + "worker_threads": true, "zlib": true, |
| 258 | +} |
| 259 | + |
| 260 | +// extendTraceMapWithNodePrefix mirrors upstream's util of the same name: for |
| 261 | +// every builtin module key it adds a `node:`-prefixed alias pointing at the same |
| 262 | +// trace map (so `require('node:buffer')` is treated like `require('buffer')`). |
| 263 | +func extendTraceMapWithNodePrefix(src map[string]*traceMap) map[string]*traceMap { |
| 264 | + out := make(map[string]*traceMap, len(src)*2) |
| 265 | + for name, value := range src { |
| 266 | + out[name] = value |
| 267 | + if nodeBuiltinModules[name] { |
| 268 | + out["node:"+name] = value |
| 269 | + } |
| 270 | + } |
| 271 | + return out |
| 272 | +} |
| 273 | + |
| 274 | +// unprefixNodeColon removes a leading `node:` from a module name for reporting, |
| 275 | +// mirroring upstream's util of the same name. |
| 276 | +func unprefixNodeColon(name string) string { |
| 277 | + if len(name) > 5 && name[:5] == "node:" { |
| 278 | + return name[5:] |
| 279 | + } |
| 280 | + return name |
| 281 | +} |
0 commit comments