@flemist/test-variants 1.0.7 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/bundle/browser.js +437 -212
  2. package/dist/lib/index.cjs +10 -2
  3. package/dist/lib/index.d.ts +6 -2
  4. package/dist/lib/index.mjs +9 -2
  5. package/dist/lib/test-variants/argsToString.cjs +17 -0
  6. package/dist/lib/test-variants/argsToString.d.ts +2 -0
  7. package/dist/lib/test-variants/argsToString.mjs +13 -0
  8. package/dist/lib/test-variants/createTestVariants.cjs +71 -188
  9. package/dist/lib/test-variants/createTestVariants.d.ts +8 -30
  10. package/dist/lib/test-variants/createTestVariants.mjs +71 -188
  11. package/dist/lib/test-variants/createTestVariants.perf.cjs +32 -20
  12. package/dist/lib/test-variants/createTestVariants.perf.mjs +32 -20
  13. package/dist/lib/test-variants/prime.cjs +65 -0
  14. package/dist/lib/test-variants/prime.d.ts +3 -0
  15. package/dist/lib/test-variants/prime.mjs +59 -0
  16. package/dist/lib/test-variants/prime.perf.cjs +30 -0
  17. package/dist/lib/test-variants/prime.perf.d.ts +1 -0
  18. package/dist/lib/test-variants/prime.perf.mjs +28 -0
  19. package/dist/lib/test-variants/saveErrorVariants.cjs +97 -0
  20. package/dist/lib/test-variants/saveErrorVariants.d.ts +9 -0
  21. package/dist/lib/test-variants/saveErrorVariants.mjs +69 -0
  22. package/dist/lib/test-variants/testVariantsCreateTestRun.cjs +80 -0
  23. package/dist/lib/test-variants/testVariantsCreateTestRun.d.ts +22 -0
  24. package/dist/lib/test-variants/testVariantsCreateTestRun.mjs +76 -0
  25. package/dist/lib/test-variants/testVariantsIterable.cjs +67 -0
  26. package/dist/lib/test-variants/testVariantsIterable.d.ts +12 -0
  27. package/dist/lib/test-variants/testVariantsIterable.mjs +63 -0
  28. package/dist/lib/test-variants/testVariantsRun.cjs +235 -0
  29. package/dist/lib/test-variants/testVariantsRun.d.ts +33 -0
  30. package/dist/lib/test-variants/testVariantsRun.mjs +211 -0
  31. package/dist/lib/test-variants/types.cjs +2 -0
  32. package/dist/lib/test-variants/types.d.ts +18 -0
  33. package/dist/lib/test-variants/types.mjs +1 -0
  34. package/package.json +12 -9
@@ -1,199 +1,82 @@
1
1
  import { __awaiter } from 'tslib';
2
- import { garbageCollect } from '../garbage-collect/garbageCollect.mjs';
3
- import { AbortControllerFast } from '@flemist/abort-controller-fast';
4
- import { Pool } from '@flemist/time-limits';
5
- import { combineAbortSignals } from '@flemist/async-utils';
2
+ import { testVariantsIterable } from './testVariantsIterable.mjs';
3
+ import { testVariantsCreateTestRun } from './testVariantsCreateTestRun.mjs';
4
+ import { testVariantsRun } from './testVariantsRun.mjs';
5
+ import '@flemist/async-utils';
6
+ import './argsToString.mjs';
7
+ import '@flemist/abort-controller-fast';
8
+ import '@flemist/time-limits';
9
+ import '../garbage-collect/garbageCollect.mjs';
10
+ import './saveErrorVariants.mjs';
11
+ import 'fs';
12
+ import 'path';
6
13
 
7
- /* eslint-disable @typescript-eslint/no-shadow */
8
- function isPromiseLike(value) {
9
- return typeof value === 'object'
10
- && value
11
- && typeof value.then === 'function';
12
- }
13
14
  function createTestVariants(test) {
14
15
  return function testVariantsArgs(args) {
15
- return function testVariantsCall({ GC_Iterations = 1000000, GC_IterationsAsync = 10000, GC_Interval = 1000, logInterval = 5000, logCompleted = true, onError: onErrorCallback = null, abortSignal: abortSignalExternal = null, parallel: _parallel, } = {}) {
16
- const abortControllerParallel = new AbortControllerFast();
17
- const abortSignalParallel = combineAbortSignals(abortSignalExternal, abortControllerParallel.signal);
18
- const abortSignalAll = abortSignalParallel;
19
- const argsKeys = Object.keys(args);
20
- const argsValues = Object.values(args);
21
- const argsLength = argsKeys.length;
22
- const variantArgs = {};
23
- function getArgValues(nArg) {
24
- let argValues = argsValues[nArg];
25
- if (typeof argValues === 'function') {
26
- argValues = argValues(variantArgs);
27
- }
28
- return argValues;
29
- }
30
- const indexes = [];
31
- const values = [];
32
- for (let nArg = 0; nArg < argsLength; nArg++) {
33
- indexes[nArg] = -1;
34
- values[nArg] = [];
35
- }
36
- values[0] = getArgValues(0);
37
- function nextVariant() {
38
- for (let nArg = argsLength - 1; nArg >= 0; nArg--) {
39
- const index = indexes[nArg] + 1;
40
- if (index < values[nArg].length) {
41
- indexes[nArg] = index;
42
- variantArgs[argsKeys[nArg]] = values[nArg][index];
43
- for (nArg++; nArg < argsLength; nArg++) {
44
- const argValues = getArgValues(nArg);
45
- if (argValues.length === 0) {
46
- break;
47
- }
48
- indexes[nArg] = 0;
49
- values[nArg] = argValues;
50
- variantArgs[argsKeys[nArg]] = argValues[0];
51
- }
52
- if (nArg >= argsLength) {
53
- return true;
54
- }
55
- }
56
- }
57
- return false;
58
- }
59
- let iterations = 0;
60
- let iterationsAsync = 0;
61
- let debug = false;
62
- let debugIteration = 0;
63
- let isNewError = true;
64
- function onError(error, iterations, variantArgs) {
65
- return __awaiter(this, void 0, void 0, function* () {
66
- const _isNewError = isNewError;
67
- isNewError = false;
68
- if (_isNewError) {
69
- abortControllerParallel.abort(error);
70
- console.error(`error variant: ${iterations}\r\n${JSON.stringify(variantArgs, (_, value) => {
71
- if (value
72
- && typeof value === 'object'
73
- && !Array.isArray(value)
74
- && value.constructor !== Object) {
75
- return value + '';
76
- }
77
- return value;
78
- }, 2)}`);
79
- console.error(error);
80
- }
81
- // rerun failed variant 5 times for debug
82
- const time0 = Date.now();
83
- // eslint-disable-next-line no-debugger
84
- debugger;
85
- if (Date.now() - time0 > 50 && debugIteration < 5) {
86
- console.log('DEBUG ITERATION: ' + debugIteration);
87
- debug = true;
88
- yield next();
89
- debugIteration++;
90
- }
91
- if (_isNewError) {
92
- if (onErrorCallback) {
93
- onErrorCallback({
94
- iteration: iterations,
95
- variant: variantArgs,
96
- error,
97
- });
98
- }
99
- throw error;
100
- }
101
- });
102
- }
103
- function onCompleted() {
104
- if (logCompleted) {
105
- console.log('variants: ' + iterations);
106
- }
107
- }
108
- let prevLogTime = Date.now();
109
- let prevGC_Time = prevLogTime;
110
- let prevGC_Iterations = iterations;
111
- let prevGC_IterationsAsync = iterationsAsync;
112
- const parallel = _parallel === true
113
- ? Math.pow(2, 31)
114
- : !_parallel || _parallel <= 0
115
- ? 1
116
- : _parallel;
117
- const pool = parallel <= 1
118
- ? null
119
- : new Pool(parallel);
120
- function runTest(_iterations, variantArgs, abortSignal) {
121
- return __awaiter(this, void 0, void 0, function* () {
122
- try {
123
- const promiseOrIterations = test(variantArgs, abortSignal);
124
- if (isPromiseLike(promiseOrIterations)) {
125
- const value = yield promiseOrIterations;
126
- const newIterations = typeof value === 'number' ? value : 1;
127
- iterationsAsync += newIterations;
128
- iterations += newIterations;
129
- return;
130
- }
131
- iterations += typeof promiseOrIterations === 'number' ? promiseOrIterations : 1;
132
- }
133
- catch (err) {
134
- yield onError(err, _iterations, variantArgs);
135
- }
16
+ return function testVariantsCall(options) {
17
+ return __awaiter(this, void 0, void 0, function* () {
18
+ const testRun = testVariantsCreateTestRun(test, {
19
+ onError: options === null || options === void 0 ? void 0 : options.onError,
136
20
  });
137
- }
138
- function next() {
139
- return __awaiter(this, void 0, void 0, function* () {
140
- while (!(abortSignalExternal === null || abortSignalExternal === void 0 ? void 0 : abortSignalExternal.aborted) && (debug || nextVariant())) {
141
- const _iterations = iterations;
142
- const _variantArgs = !pool
143
- ? variantArgs
144
- : Object.assign({}, variantArgs);
145
- const now = (logInterval || GC_Interval) && Date.now();
146
- if (logInterval && now - prevLogTime >= logInterval) {
147
- // the log is required to prevent the karma browserNoActivityTimeout
148
- console.log(iterations);
149
- prevLogTime = now;
150
- }
151
- if (GC_Iterations && iterations - prevGC_Iterations >= GC_Iterations
152
- || GC_IterationsAsync && iterationsAsync - prevGC_IterationsAsync >= GC_IterationsAsync
153
- || GC_Interval && now - prevGC_Time >= GC_Interval) {
154
- prevGC_Iterations = iterations;
155
- prevGC_IterationsAsync = iterationsAsync;
156
- prevGC_Time = now;
157
- yield garbageCollect(1);
158
- }
159
- if (abortSignalExternal === null || abortSignalExternal === void 0 ? void 0 : abortSignalExternal.aborted) {
160
- continue;
161
- }
162
- if (!pool || abortSignalParallel.aborted) {
163
- yield runTest(_iterations, _variantArgs, abortSignalExternal);
164
- }
165
- else {
166
- if (!pool.hold(1)) {
167
- yield pool.holdWait(1);
168
- }
169
- void (() => __awaiter(this, void 0, void 0, function* () {
170
- try {
171
- if (abortSignalParallel === null || abortSignalParallel === void 0 ? void 0 : abortSignalParallel.aborted) {
172
- return;
173
- }
174
- yield runTest(_iterations, _variantArgs, abortSignalParallel);
175
- }
176
- finally {
177
- void pool.release(1);
178
- }
179
- }))();
180
- }
181
- }
182
- if (pool) {
183
- yield pool.holdWait(parallel);
184
- void pool.release(parallel);
185
- }
186
- if (abortSignalAll === null || abortSignalAll === void 0 ? void 0 : abortSignalAll.aborted) {
187
- throw abortSignalAll.reason;
188
- }
189
- onCompleted();
190
- yield garbageCollect(1);
191
- return iterations;
21
+ const variants = testVariantsIterable({
22
+ argsTemplates: args,
192
23
  });
193
- }
194
- return next();
24
+ return testVariantsRun(testRun, variants, options);
25
+ });
195
26
  };
196
27
  };
197
28
  }
29
+ /*
30
+ export class TestVariants<Args extends Obj> {
31
+ private readonly _test: TestVariantsTest<Args>
32
+ test(args: Args, abortSignal: IAbortSignalFast) {
33
+ return this._test(args, abortSignal)
34
+ }
35
+
36
+ constructor(
37
+ test: TestVariantsTest<Args>,
38
+ ) {
39
+ this.test = test
40
+ }
41
+
42
+ createVariants<ArgsExtra extends Obj>(
43
+ argsTemplates: TestVariantsTemplatesExt<Args, ArgsExtra>,
44
+ ): Iterable<Args> {
45
+ return testVariantsIterable<Args, ArgsExtra>(argsTemplates)
46
+ }
47
+
48
+ createTestRun(
49
+ options?: null | TestVariantsCreateTestRunOptions<Args>,
50
+ ) {
51
+ return testVariantsCreateTestRun<Args>(this._test, options)
52
+ }
53
+
54
+ testAll<ArgsExtra extends Obj>(
55
+ argsTemplates: TestVariantsTemplatesExt<Args, ArgsExtra>,
56
+ ): TestVariantsCall<Args>
57
+ testAll(
58
+ variants: Iterable<Args>,
59
+ ): TestVariantsCall<Args>
60
+ testAll<ArgsExtra extends Obj>(
61
+ variantsOrTemplates: Iterable<Args> | TestVariantsTemplatesExt<Args, ArgsExtra>,
62
+ ): TestVariantsCall<Args> {
63
+ const variants = Symbol.iterator in variantsOrTemplates
64
+ ? variantsOrTemplates as Iterable<Args>
65
+ : this.createVariants(variantsOrTemplates as TestVariantsTemplatesExt<Args, ArgsExtra>)
66
+
67
+ const _this = this
68
+
69
+ return function testVariantsCall(
70
+ options?: null | TestVariantsRunOptions & TestVariantsCreateTestRunOptions<Args>,
71
+ ) {
72
+ const testRun = _this.createTestRun({
73
+ onError: options?.onError,
74
+ })
75
+
76
+ return testVariantsRun<Args>(testRun, variants, options)
77
+ }
78
+ }
79
+ }
80
+ */
198
81
 
199
82
  export { createTestVariants };
@@ -1,32 +1,44 @@
1
1
  'use strict';
2
2
 
3
- var rdtsc = require('rdtsc');
3
+ var tslib = require('tslib');
4
+ var node = require('rdtsc/node');
4
5
  var testVariants_createTestVariants = require('./createTestVariants.cjs');
5
- require('tslib');
6
- require('../garbage-collect/garbageCollect.cjs');
6
+ require('./testVariantsIterable.cjs');
7
+ require('./testVariantsCreateTestRun.cjs');
8
+ require('@flemist/async-utils');
9
+ require('./argsToString.cjs');
10
+ require('./testVariantsRun.cjs');
7
11
  require('@flemist/abort-controller-fast');
8
12
  require('@flemist/time-limits');
9
- require('@flemist/async-utils');
13
+ require('../garbage-collect/garbageCollect.cjs');
14
+ require('./saveErrorVariants.cjs');
15
+ require('fs');
16
+ require('path');
10
17
 
11
18
  describe('test > testVariants perf', function () {
12
19
  this.timeout(300000);
13
20
  it('sync', function () {
14
- let value = 0;
15
- const testVariantsSync = testVariants_createTestVariants.createTestVariants(({ a, b, c }) => {
16
- if (a === 1 && b === '4' && c === false) {
17
- value++;
18
- }
19
- });
20
- const args = {
21
- a: [1, 2],
22
- b: ['3', '4'],
23
- c: [true, false],
24
- };
25
- const result = rdtsc.calcPerformance(10000, () => {
26
- }, () => {
21
+ return tslib.__awaiter(this, void 0, void 0, function* () {
22
+ const testVariantsSync = testVariants_createTestVariants.createTestVariants(({ a, b, c }) => {
23
+ });
24
+ const args = {
25
+ a: [1, 2],
26
+ b: ['3', '4'],
27
+ c: [true, false],
28
+ };
29
+ const perfResult = node.calcPerformance({
30
+ time: 10000,
31
+ funcs: [
32
+ () => {
33
+ },
34
+ () => {
35
+ testVariantsSync(args)();
36
+ },
37
+ ],
38
+ });
39
+ const result = yield testVariantsSync(args)();
40
+ perfResult.absoluteDiff = perfResult.absoluteDiff.map(o => o / result.iterations);
41
+ console.log('testVariants perf:', result);
27
42
  });
28
- const count = testVariantsSync(args)();
29
- result.absoluteDiff = result.absoluteDiff.map(o => o / count);
30
- console.log('testVariants perf:', result);
31
43
  });
32
44
  });
@@ -1,30 +1,42 @@
1
- import { calcPerformance } from 'rdtsc';
1
+ import { __awaiter } from 'tslib';
2
+ import { calcPerformance } from 'rdtsc/node';
2
3
  import { createTestVariants } from './createTestVariants.mjs';
3
- import 'tslib';
4
- import '../garbage-collect/garbageCollect.mjs';
4
+ import './testVariantsIterable.mjs';
5
+ import './testVariantsCreateTestRun.mjs';
6
+ import '@flemist/async-utils';
7
+ import './argsToString.mjs';
8
+ import './testVariantsRun.mjs';
5
9
  import '@flemist/abort-controller-fast';
6
10
  import '@flemist/time-limits';
7
- import '@flemist/async-utils';
11
+ import '../garbage-collect/garbageCollect.mjs';
12
+ import './saveErrorVariants.mjs';
13
+ import 'fs';
14
+ import 'path';
8
15
 
9
16
  describe('test > testVariants perf', function () {
10
17
  this.timeout(300000);
11
18
  it('sync', function () {
12
- let value = 0;
13
- const testVariantsSync = createTestVariants(({ a, b, c }) => {
14
- if (a === 1 && b === '4' && c === false) {
15
- value++;
16
- }
17
- });
18
- const args = {
19
- a: [1, 2],
20
- b: ['3', '4'],
21
- c: [true, false],
22
- };
23
- const result = calcPerformance(10000, () => {
24
- }, () => {
19
+ return __awaiter(this, void 0, void 0, function* () {
20
+ const testVariantsSync = createTestVariants(({ a, b, c }) => {
21
+ });
22
+ const args = {
23
+ a: [1, 2],
24
+ b: ['3', '4'],
25
+ c: [true, false],
26
+ };
27
+ const perfResult = calcPerformance({
28
+ time: 10000,
29
+ funcs: [
30
+ () => {
31
+ },
32
+ () => {
33
+ testVariantsSync(args)();
34
+ },
35
+ ],
36
+ });
37
+ const result = yield testVariantsSync(args)();
38
+ perfResult.absoluteDiff = perfResult.absoluteDiff.map(o => o / result.iterations);
39
+ console.log('testVariants perf:', result);
25
40
  });
26
- const count = testVariantsSync(args)();
27
- result.absoluteDiff = result.absoluteDiff.map(o => o / count);
28
- console.log('testVariants perf:', result);
29
41
  });
30
42
  });
@@ -0,0 +1,65 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ const MAX_NUMBER = (Math.pow(2, 31) - 1) | 0;
6
+ const MAX_NUMBER_PRIME = 2147483647;
7
+ function isPrime(n) {
8
+ if (n > MAX_NUMBER) {
9
+ throw new Error(`Number is too large: ${n}, max is ${MAX_NUMBER}`);
10
+ }
11
+ // convert number to 32-bit integer for performance
12
+ n = n | 0;
13
+ if (n <= 1) {
14
+ return false;
15
+ }
16
+ if (n <= 3) {
17
+ return true;
18
+ }
19
+ if (n % 2 === 0 || n % 3 === 0) {
20
+ return false;
21
+ }
22
+ for (let i = 5; i * i <= n; i += 6) {
23
+ if (n % i === 0 || n % (i + 2) === 0) {
24
+ return false;
25
+ }
26
+ }
27
+ return true;
28
+ }
29
+ function nextPrime(n) {
30
+ if (n >= MAX_NUMBER_PRIME) {
31
+ throw new Error(`Number is too large: ${n}, max is ${MAX_NUMBER_PRIME - 1}`);
32
+ }
33
+ // convert number to 32-bit integer for performance
34
+ n = n | 0;
35
+ if (n < 2) {
36
+ return 2;
37
+ }
38
+ let candidate = n + (n % 2 === 0 ? 1 : 2);
39
+ while (!isPrime(candidate)) {
40
+ candidate += 2;
41
+ }
42
+ return candidate;
43
+ }
44
+ function prevPrime(n) {
45
+ if (n > MAX_NUMBER) {
46
+ throw new Error(`Number is too large: ${n}, max is ${MAX_NUMBER}`);
47
+ }
48
+ // convert number to 32-bit integer for performance
49
+ n = n | 0;
50
+ if (n <= 2) {
51
+ return null;
52
+ }
53
+ let candidate = n - (n % 2 === 0 ? 1 : 2);
54
+ while (candidate > 2 && !isPrime(candidate)) {
55
+ candidate -= 2;
56
+ }
57
+ if (candidate > 2) {
58
+ return candidate;
59
+ }
60
+ return 2;
61
+ }
62
+
63
+ exports.isPrime = isPrime;
64
+ exports.nextPrime = nextPrime;
65
+ exports.prevPrime = prevPrime;
@@ -0,0 +1,3 @@
1
+ export declare function isPrime(n: number): boolean;
2
+ export declare function nextPrime(n: number): number;
3
+ export declare function prevPrime(n: number): number;
@@ -0,0 +1,59 @@
1
+ const MAX_NUMBER = (Math.pow(2, 31) - 1) | 0;
2
+ const MAX_NUMBER_PRIME = 2147483647;
3
+ function isPrime(n) {
4
+ if (n > MAX_NUMBER) {
5
+ throw new Error(`Number is too large: ${n}, max is ${MAX_NUMBER}`);
6
+ }
7
+ // convert number to 32-bit integer for performance
8
+ n = n | 0;
9
+ if (n <= 1) {
10
+ return false;
11
+ }
12
+ if (n <= 3) {
13
+ return true;
14
+ }
15
+ if (n % 2 === 0 || n % 3 === 0) {
16
+ return false;
17
+ }
18
+ for (let i = 5; i * i <= n; i += 6) {
19
+ if (n % i === 0 || n % (i + 2) === 0) {
20
+ return false;
21
+ }
22
+ }
23
+ return true;
24
+ }
25
+ function nextPrime(n) {
26
+ if (n >= MAX_NUMBER_PRIME) {
27
+ throw new Error(`Number is too large: ${n}, max is ${MAX_NUMBER_PRIME - 1}`);
28
+ }
29
+ // convert number to 32-bit integer for performance
30
+ n = n | 0;
31
+ if (n < 2) {
32
+ return 2;
33
+ }
34
+ let candidate = n + (n % 2 === 0 ? 1 : 2);
35
+ while (!isPrime(candidate)) {
36
+ candidate += 2;
37
+ }
38
+ return candidate;
39
+ }
40
+ function prevPrime(n) {
41
+ if (n > MAX_NUMBER) {
42
+ throw new Error(`Number is too large: ${n}, max is ${MAX_NUMBER}`);
43
+ }
44
+ // convert number to 32-bit integer for performance
45
+ n = n | 0;
46
+ if (n <= 2) {
47
+ return null;
48
+ }
49
+ let candidate = n - (n % 2 === 0 ? 1 : 2);
50
+ while (candidate > 2 && !isPrime(candidate)) {
51
+ candidate -= 2;
52
+ }
53
+ if (candidate > 2) {
54
+ return candidate;
55
+ }
56
+ return 2;
57
+ }
58
+
59
+ export { isPrime, nextPrime, prevPrime };
@@ -0,0 +1,30 @@
1
+ 'use strict';
2
+
3
+ var node = require('rdtsc/node');
4
+ var testVariants_prime = require('./prime.cjs');
5
+
6
+ describe('test-variants > prime perf', function () {
7
+ this.timeout(300000);
8
+ it('isPrime', function () {
9
+ let number1 = testVariants_prime.nextPrime(Math.pow(2, 30));
10
+ let number2 = testVariants_prime.prevPrime(Math.pow(2, 31) - 1);
11
+ console.log('number:', number1);
12
+ console.log('number:', number2);
13
+ const result = node.calcPerformance({
14
+ time: 10000,
15
+ funcs: [
16
+ () => {
17
+ },
18
+ () => {
19
+ number1 = testVariants_prime.nextPrime(number1);
20
+ },
21
+ () => {
22
+ number2 = testVariants_prime.prevPrime(number2);
23
+ },
24
+ ],
25
+ });
26
+ console.log('number1:', number1);
27
+ console.log('number2:', number2);
28
+ console.log('perf:', result);
29
+ });
30
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,28 @@
1
+ import { calcPerformance } from 'rdtsc/node';
2
+ import { nextPrime, prevPrime } from './prime.mjs';
3
+
4
+ describe('test-variants > prime perf', function () {
5
+ this.timeout(300000);
6
+ it('isPrime', function () {
7
+ let number1 = nextPrime(Math.pow(2, 30));
8
+ let number2 = prevPrime(Math.pow(2, 31) - 1);
9
+ console.log('number:', number1);
10
+ console.log('number:', number2);
11
+ const result = calcPerformance({
12
+ time: 10000,
13
+ funcs: [
14
+ () => {
15
+ },
16
+ () => {
17
+ number1 = nextPrime(number1);
18
+ },
19
+ () => {
20
+ number2 = prevPrime(number2);
21
+ },
22
+ ],
23
+ });
24
+ console.log('number1:', number1);
25
+ console.log('number2:', number2);
26
+ console.log('perf:', result);
27
+ });
28
+ });