GeezerVison is showing github.com — timers: emit warning if delay is negative or NaN · nodejs/node@f5ed338
File treeExpand file treeCollapse file tree Open diff view settings fixtures/source-map/output
Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: doc/api/process.md +4Lines changed: 4 additions & 0 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -676,6 +676,10 @@ A few of the warning types that are most common include: | 676 | 676 | * `'TimeoutOverflowWarning'` - Indicates that a numeric value that cannot fit | 677 | 677 | within a 32-bit signed integer has been provided to either the `setTimeout()` | 678 | 678 | or `setInterval()` functions. | | 679 | +* `'TimeoutNegativeWarning'` - Indicates that a negative number has provided to | | 680 | + either the `setTimeout()` or `setInterval()` functions. | | 681 | +* `'TimeoutNaNWarning'` - Indicates that a value which is not a number has | | 682 | + provided to either the `setTimeout()` or `setInterval()` functions. | 679 | 683 | * `'UnsupportedWarning'` - Indicates use of an unsupported option or feature | 680 | 684 | that will be ignored rather than treated as an error. One example is use of | 681 | 685 | the HTTP response status message when using the HTTP/2 compatibility API. | |
Collapse file Copy file name to clipboardExpand all lines: doc/api/timers.md +3-3Lines changed: 3 additions & 3 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -239,8 +239,8 @@ changes: | 239 | 239 |
| 240 | 240 | Schedules repeated execution of `callback` every `delay` milliseconds. | 241 | 241 |
| 242 | | -When `delay` is larger than `2147483647` or less than `1`, the `delay` will be | 243 | | -set to `1`. Non-integer delays are truncated to an integer. | | 242 | +When `delay` is larger than `2147483647` or less than `1` or `NaN`, the `delay` | | 243 | +will be set to `1`. Non-integer delays are truncated to an integer. | 244 | 244 |
| 245 | 245 | If `callback` is not a function, a [`TypeError`][] will be thrown. | 246 | 246 |
| @@ -272,7 +272,7 @@ Node.js makes no guarantees about the exact timing of when callbacks will fire, | 272 | 272 | nor of their ordering. The callback will be called as close as possible to the | 273 | 273 | time specified. | 274 | 274 |
| 275 | | -When `delay` is larger than `2147483647` or less than `1`, the `delay` | | 275 | +When `delay` is larger than `2147483647` or less than `1` or `NaN`, the `delay` | 276 | 276 | will be set to `1`. Non-integer delays are truncated to an integer. | 277 | 277 |
| 278 | 278 | If `callback` is not a function, a [`TypeError`][] will be thrown. | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/timers.js +21-1Lines changed: 21 additions & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -76,6 +76,7 @@ const { | 76 | 76 | MathMax, | 77 | 77 | MathTrunc, | 78 | 78 | NumberIsFinite, | | 79 | + NumberIsNaN, | 79 | 80 | NumberMIN_SAFE_INTEGER, | 80 | 81 | ReflectApply, | 81 | 82 | Symbol, | @@ -164,17 +165,36 @@ function initAsyncResource(resource, type) { | 164 | 165 | if (initHooksExist()) | 165 | 166 | emitInit(asyncId, type, triggerAsyncId, resource); | 166 | 167 | } | | 168 | + | | 169 | +let warnedNegativeNumber = false; | | 170 | +let warnedNotNumber = false; | | 171 | + | 167 | 172 | class Timeout { | 168 | 173 | // Timer constructor function. | 169 | 174 | // The entire prototype is defined in lib/timers.js | 170 | 175 | constructor(callback, after, args, isRepeat, isRefed) { | 171 | | - after *= 1; // Coalesce to number or NaN | | 176 | + if (after === undefined) { | | 177 | + after = 1; | | 178 | + } else { | | 179 | + after *= 1; // Coalesce to number or NaN | | 180 | + } | | 181 | + | 172 | 182 | if (!(after >= 1 && after <= TIMEOUT_MAX)) { | 173 | 183 | if (after > TIMEOUT_MAX) { | 174 | 184 | process.emitWarning(`${after} does not fit into` + | 175 | 185 | ' a 32-bit signed integer.' + | 176 | 186 | '\nTimeout duration was set to 1.', | 177 | 187 | 'TimeoutOverflowWarning'); | | 188 | + } else if (after < 0 && !warnedNegativeNumber) { | | 189 | + warnedNegativeNumber = true; | | 190 | + process.emitWarning(`${after} is a negative number.` + | | 191 | + '\nTimeout duration was set to 1.', | | 192 | + 'TimeoutNegativeWarning'); | | 193 | + } else if (NumberIsNaN(after) && !warnedNotNumber) { | | 194 | + warnedNotNumber = true; | | 195 | + process.emitWarning(`${after} is not a number.` + | | 196 | + '\nTimeout duration was set to 1.', | | 197 | + 'TimeoutNaNWarning'); | 178 | 198 | } | 179 | 199 | after = 1; // Schedule on next tick, follows browser behavior | 180 | 200 | } | |
Collapse file Copy file name to clipboardExpand all lines: test/fixtures/source-map/output/source_map_throw_set_immediate.snapshot +1-1Lines changed: 1 addition & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
| 6 | 6 | Error: goodbye | 7 | 7 | at Hello (*uglify-throw-original.js:5:9) | 8 | 8 | at Immediate.<anonymous> (*uglify-throw-original.js:9:3) | 9 | | - at process.processImmediate (node:internal*timers:483:21) | | 9 | + at process.processImmediate (node:internal*timers:503:21) | 10 | 10 |
| 11 | 11 | Node.js * |
Collapse file Copy file name to clipboard +39Lines changed: 39 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +'use strict'; | | 2 | + | | 3 | +const common = require('../common'); | | 4 | +const assert = require('assert'); | | 5 | + | | 6 | +const NOT_A_NUMBER = NaN; | | 7 | + | | 8 | +function timerNotCanceled() { | | 9 | + assert.fail('Timer should be canceled'); | | 10 | +} | | 11 | + | | 12 | +process.on( | | 13 | + 'warning', | | 14 | + common.mustCall((warning) => { | | 15 | + if (warning.name === 'DeprecationWarning') return; | | 16 | + | | 17 | + const lines = warning.message.split('\n'); | | 18 | + | | 19 | + assert.strictEqual(warning.name, 'TimeoutNaNWarning'); | | 20 | + assert.strictEqual(lines[0], `${NOT_A_NUMBER} is not a number.`); | | 21 | + assert.strictEqual(lines.length, 2); | | 22 | + }, 1) | | 23 | +); | | 24 | + | | 25 | +{ | | 26 | + const timeout = setTimeout(timerNotCanceled, NOT_A_NUMBER); | | 27 | + clearTimeout(timeout); | | 28 | +} | | 29 | + | | 30 | +{ | | 31 | + const interval = setInterval(timerNotCanceled, NOT_A_NUMBER); | | 32 | + clearInterval(interval); | | 33 | +} | | 34 | + | | 35 | +{ | | 36 | + const timeout = setTimeout(timerNotCanceled, NOT_A_NUMBER); | | 37 | + timeout.refresh(); | | 38 | + clearTimeout(timeout); | | 39 | +} |
Collapse file Copy file name to clipboard +67Lines changed: 67 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +'use strict'; | | 2 | + | | 3 | +require('../common'); | | 4 | +const assert = require('assert'); | | 5 | +const child_process = require('child_process'); | | 6 | +const path = require('path'); | | 7 | + | | 8 | +const NOT_A_NUMBER = NaN; | | 9 | + | | 10 | +function timerNotCanceled() { | | 11 | + assert.fail('Timer should be canceled'); | | 12 | +} | | 13 | + | | 14 | +const testCases = ['timeout', 'interval', 'refresh']; | | 15 | + | | 16 | +function runTests() { | | 17 | + const args = process.argv.slice(2); | | 18 | + | | 19 | + const testChoice = args[0]; | | 20 | + | | 21 | + if (!testChoice) { | | 22 | + const filePath = path.join(__filename); | | 23 | + | | 24 | + testCases.forEach((testCase) => { | | 25 | + const { stdout } = child_process.spawnSync( | | 26 | + process.execPath, | | 27 | + [filePath, testCase], | | 28 | + { encoding: 'utf8' } | | 29 | + ); | | 30 | + | | 31 | + const lines = stdout.split('\n'); | | 32 | + | | 33 | + if (lines[0] === 'DeprecationWarning') return; | | 34 | + | | 35 | + assert.strictEqual(lines[0], 'TimeoutNaNWarning'); | | 36 | + assert.strictEqual(lines[1], `${NOT_A_NUMBER} is not a number.`); | | 37 | + assert.strictEqual(lines[2], 'Timeout duration was set to 1.'); | | 38 | + }); | | 39 | + } | | 40 | + | | 41 | + if (args[0] === testCases[0]) { | | 42 | + const timeout = setTimeout(timerNotCanceled, NOT_A_NUMBER); | | 43 | + clearTimeout(timeout); | | 44 | + } | | 45 | + | | 46 | + if (args[0] === testCases[1]) { | | 47 | + const interval = setInterval(timerNotCanceled, NOT_A_NUMBER); | | 48 | + clearInterval(interval); | | 49 | + } | | 50 | + | | 51 | + if (args[0] === testCases[2]) { | | 52 | + const timeout = setTimeout(timerNotCanceled, NOT_A_NUMBER); | | 53 | + timeout.refresh(); | | 54 | + clearTimeout(timeout); | | 55 | + } | | 56 | + | | 57 | + process.on( | | 58 | + 'warning', | | 59 | + | | 60 | + (warning) => { | | 61 | + console.log(warning.name); | | 62 | + console.log(warning.message); | | 63 | + } | | 64 | + ); | | 65 | +} | | 66 | + | | 67 | +runTests(); |
Collapse file Copy file name to clipboard +39Lines changed: 39 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +'use strict'; | | 2 | + | | 3 | +const common = require('../common'); | | 4 | +const assert = require('assert'); | | 5 | + | | 6 | +const NEGATIVE_NUMBER = -1; | | 7 | + | | 8 | +function timerNotCanceled() { | | 9 | + assert.fail('Timer should be canceled'); | | 10 | +} | | 11 | + | | 12 | +process.on( | | 13 | + 'warning', | | 14 | + common.mustCall((warning) => { | | 15 | + if (warning.name === 'DeprecationWarning') return; | | 16 | + | | 17 | + const lines = warning.message.split('\n'); | | 18 | + | | 19 | + assert.strictEqual(warning.name, 'TimeoutNegativeWarning'); | | 20 | + assert.strictEqual(lines[0], `${NEGATIVE_NUMBER} is a negative number.`); | | 21 | + assert.strictEqual(lines.length, 2); | | 22 | + }, 1) | | 23 | +); | | 24 | + | | 25 | +{ | | 26 | + const timeout = setTimeout(timerNotCanceled, NEGATIVE_NUMBER); | | 27 | + clearTimeout(timeout); | | 28 | +} | | 29 | + | | 30 | +{ | | 31 | + const interval = setInterval(timerNotCanceled, NEGATIVE_NUMBER); | | 32 | + clearInterval(interval); | | 33 | +} | | 34 | + | | 35 | +{ | | 36 | + const timeout = setTimeout(timerNotCanceled, NEGATIVE_NUMBER); | | 37 | + timeout.refresh(); | | 38 | + clearTimeout(timeout); | | 39 | +} |
Collapse file Copy file name to clipboard +67Lines changed: 67 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +'use strict'; | | 2 | + | | 3 | +require('../common'); | | 4 | +const assert = require('assert'); | | 5 | +const child_process = require('child_process'); | | 6 | +const path = require('path'); | | 7 | + | | 8 | +const NEGATIVE_NUMBER = -1; | | 9 | + | | 10 | +function timerNotCanceled() { | | 11 | + assert.fail('Timer should be canceled'); | | 12 | +} | | 13 | + | | 14 | +const testCases = ['timeout', 'interval', 'refresh']; | | 15 | + | | 16 | +function runTests() { | | 17 | + const args = process.argv.slice(2); | | 18 | + | | 19 | + const testChoice = args[0]; | | 20 | + | | 21 | + if (!testChoice) { | | 22 | + const filePath = path.join(__filename); | | 23 | + | | 24 | + testCases.forEach((testCase) => { | | 25 | + const { stdout } = child_process.spawnSync( | | 26 | + process.execPath, | | 27 | + [filePath, testCase], | | 28 | + { encoding: 'utf8' } | | 29 | + ); | | 30 | + | | 31 | + const lines = stdout.split('\n'); | | 32 | + | | 33 | + if (lines[0] === 'DeprecationWarning') return; | | 34 | + | | 35 | + assert.strictEqual(lines[0], 'TimeoutNegativeWarning'); | | 36 | + assert.strictEqual(lines[1], `${NEGATIVE_NUMBER} is a negative number.`); | | 37 | + assert.strictEqual(lines[2], 'Timeout duration was set to 1.'); | | 38 | + }); | | 39 | + } | | 40 | + | | 41 | + if (args[0] === testCases[0]) { | | 42 | + const timeout = setTimeout(timerNotCanceled, NEGATIVE_NUMBER); | | 43 | + clearTimeout(timeout); | | 44 | + } | | 45 | + | | 46 | + if (args[0] === testCases[1]) { | | 47 | + const interval = setInterval(timerNotCanceled, NEGATIVE_NUMBER); | | 48 | + clearInterval(interval); | | 49 | + } | | 50 | + | | 51 | + if (args[0] === testCases[2]) { | | 52 | + const timeout = setTimeout(timerNotCanceled, NEGATIVE_NUMBER); | | 53 | + timeout.refresh(); | | 54 | + clearTimeout(timeout); | | 55 | + } | | 56 | + | | 57 | + process.on( | | 58 | + 'warning', | | 59 | + | | 60 | + (warning) => { | | 61 | + console.log(warning.name); | | 62 | + console.log(warning.message); | | 63 | + } | | 64 | + ); | | 65 | +} | | 66 | + | | 67 | +runTests(); |
Collapse file Copy file name to clipboard +31Lines changed: 31 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +'use strict'; | | 2 | + | | 3 | +const common = require('../common'); | | 4 | +const assert = require('assert'); | | 5 | + | | 6 | +function timerNotCanceled() { | | 7 | + assert.fail('Timer should be canceled'); | | 8 | +} | | 9 | + | | 10 | +process.on( | | 11 | + 'warning', | | 12 | + common.mustNotCall(() => { | | 13 | + assert.fail('Timer should be canceled'); | | 14 | + }) | | 15 | +); | | 16 | + | | 17 | +{ | | 18 | + const timeout = setTimeout(timerNotCanceled, 0); | | 19 | + clearTimeout(timeout); | | 20 | +} | | 21 | + | | 22 | +{ | | 23 | + const interval = setInterval(timerNotCanceled, 0); | | 24 | + clearInterval(interval); | | 25 | +} | | 26 | + | | 27 | +{ | | 28 | + const timeout = setTimeout(timerNotCanceled, 0); | | 29 | + timeout.refresh(); | | 30 | + clearTimeout(timeout); | | 31 | +} |
|