eslint-plugin-react-web-api 1.23.3-next.8 → 1.24.0-next.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 (3) hide show
  1. package/dist/index.js +110 -116
  2. package/dist/index.mjs +111 -117
  3. package/package.json +11 -11
package/dist/index.js CHANGED
@@ -34,24 +34,24 @@ var VAR2__namespace = /*#__PURE__*/_interopNamespace(VAR2);
34
34
 
35
35
  // package.json
36
36
  var name = "eslint-plugin-react-web-api";
37
- var version = "1.23.3-next.8";
37
+ var version = "1.24.0-next.0";
38
38
  var createRule = shared.createRuleForPlugin("web-api");
39
39
  function getInstanceID(node, prev) {
40
40
  switch (true) {
41
41
  case (node.type === types.AST_NODE_TYPES.VariableDeclarator && node.init === prev):
42
- return eff.O.some(node.id);
42
+ return node.id;
43
43
  case (node.type === types.AST_NODE_TYPES.AssignmentExpression && node.right === prev):
44
- return eff.O.some(node.left);
44
+ return node.left;
45
45
  case (node.type === types.AST_NODE_TYPES.PropertyDefinition && node.value === prev):
46
- return eff.O.some(node.key);
46
+ return node.key;
47
47
  case (node.type === types.AST_NODE_TYPES.BlockStatement || node.type === types.AST_NODE_TYPES.Program || node.parent === node):
48
- return eff.O.none();
48
+ return eff._;
49
49
  default:
50
50
  return getInstanceID(node.parent, node);
51
51
  }
52
52
  }
53
53
  function getPhaseKindOfFunction(node) {
54
- return tsPattern.match(node).when(core.isSetupFunction, () => eff.O.some("setup")).when(core.isCleanupFunction, () => eff.O.some("cleanup")).when(core.isComponentDidMountFunction, () => eff.O.some("mount")).when(core.isComponentWillUnmountFunction, () => eff.O.some("unmount")).otherwise(eff.O.none);
54
+ return tsPattern.match(node).when(core.isSetupFunction, () => "setup").when(core.isCleanupFunction, () => "cleanup").when(core.isComponentDidMountFunction, () => "mount").when(core.isComponentWillUnmountFunction, () => "unmount").otherwise(() => eff._);
55
55
  }
56
56
  function isInstanceIDEqual(a, b, context) {
57
57
  return AST2__namespace.isNodeEqual(a, b) || VAR2__namespace.isNodeValueEqual(a, b, [
@@ -66,9 +66,9 @@ var RULE_FEATURES = [
66
66
  "CHK"
67
67
  ];
68
68
  var defaultOptions = {
69
- capture: eff.O.some(false),
70
- once: eff.O.some(false),
71
- signal: eff.O.none()
69
+ capture: false,
70
+ // once: false,
71
+ signal: eff._
72
72
  };
73
73
  function getCallKind(node) {
74
74
  switch (true) {
@@ -81,68 +81,59 @@ function getCallKind(node) {
81
81
  }
82
82
  }
83
83
  function getFunctionKind(node) {
84
- return eff.O.getOrElse(getPhaseKindOfFunction(node), eff.F.constant("other"));
84
+ return getPhaseKindOfFunction(node) ?? "other";
85
85
  }
86
86
  function getSignalValueExpression(node, initialScope) {
87
+ if (node === eff._) return eff._;
87
88
  switch (node.type) {
88
- case utils.AST_NODE_TYPES.Identifier:
89
- return eff.F.pipe(
90
- VAR2__namespace.findVariable(node, initialScope),
91
- eff.O.flatMap(VAR2__namespace.getVariableNode(0)),
92
- eff.O.flatMap((n) => getSignalValueExpression(n, initialScope))
93
- );
89
+ case utils.AST_NODE_TYPES.Identifier: {
90
+ return getSignalValueExpression(VAR2__namespace.getVariableNode(VAR2__namespace.findVariable(node, initialScope), 0), initialScope);
91
+ }
94
92
  case utils.AST_NODE_TYPES.MemberExpression:
95
- return eff.O.some(node);
93
+ return node;
96
94
  default:
97
- return eff.O.none();
95
+ return eff._;
98
96
  }
99
97
  }
100
98
  function getOptions(node, initialScope) {
101
- const findProp = (properties, propName) => {
102
- return JSX__namespace.findPropInProperties(properties, initialScope)(propName);
103
- };
104
- const getPropValue = (prop) => {
105
- if (prop.type !== utils.AST_NODE_TYPES.Property) {
106
- return eff.O.none();
107
- }
99
+ function findProp(properties, propName) {
100
+ return JSX__namespace.findPropInProperties(propName, properties, initialScope);
101
+ }
102
+ function getPropValue(prop, filter = (_6) => true) {
103
+ if (prop?.type !== utils.AST_NODE_TYPES.Property) return eff._;
108
104
  const { value } = prop;
105
+ let v = value;
109
106
  switch (value.type) {
110
107
  case utils.AST_NODE_TYPES.Literal: {
111
- return eff.O.some(value.value);
108
+ v = value.value;
109
+ break;
112
110
  }
113
111
  default: {
114
- return VAR2__namespace.getStaticValue(value, initialScope);
112
+ v = VAR2__namespace.toResolved({ kind: "lazy", node: value, initialScope }).value;
113
+ break;
115
114
  }
116
115
  }
117
- };
116
+ return filter(v) ? v : eff._;
117
+ }
118
118
  function getOpts(node2) {
119
119
  switch (node2.type) {
120
120
  case utils.AST_NODE_TYPES.Identifier: {
121
- return eff.F.pipe(
122
- VAR2__namespace.findVariable(node2, initialScope),
123
- eff.O.flatMap(VAR2__namespace.getVariableNode(0)),
124
- eff.O.filter(AST2__namespace.is(utils.AST_NODE_TYPES.ObjectExpression)),
125
- eff.O.map(getOpts),
126
- eff.O.getOrElse(() => defaultOptions)
127
- );
121
+ const variable = VAR2__namespace.findVariable(node2, initialScope);
122
+ const variableNode = VAR2__namespace.getVariableNode(variable, 0);
123
+ if (variableNode?.type === utils.AST_NODE_TYPES.ObjectExpression) {
124
+ return getOpts(variableNode);
125
+ }
126
+ return defaultOptions;
128
127
  }
129
128
  case utils.AST_NODE_TYPES.Literal: {
130
- return { ...defaultOptions, capture: eff.O.some(Boolean(node2.value)) };
129
+ return { ...defaultOptions, capture: Boolean(node2.value) };
131
130
  }
132
131
  case utils.AST_NODE_TYPES.ObjectExpression: {
133
- const pOnce = findProp(node2.properties, "once");
134
- const vOnce = eff.O.flatMap(pOnce, getPropValue).pipe(eff.O.filter(eff.isBoolean));
135
132
  const pCapture = findProp(node2.properties, "capture");
136
- const vCapture = eff.O.flatMap(pCapture, getPropValue).pipe(eff.O.filter(eff.isBoolean));
133
+ const vCapture = !!getPropValue(pCapture);
137
134
  const pSignal = findProp(node2.properties, "signal");
138
- const vSignal = eff.O.flatMap(pSignal, (prop) => {
139
- if (prop.type !== utils.AST_NODE_TYPES.Property) {
140
- return eff.O.none();
141
- }
142
- const { value } = prop;
143
- return getSignalValueExpression(value, initialScope);
144
- });
145
- return { capture: vCapture, once: vOnce, signal: vSignal };
135
+ const vSignal = pSignal?.type === utils.AST_NODE_TYPES.Property ? getSignalValueExpression(pSignal.value, initialScope) : eff._;
136
+ return { capture: vCapture, signal: vSignal };
146
137
  }
147
138
  default: {
148
139
  return defaultOptions;
@@ -173,7 +164,7 @@ var no_leaked_event_listener_default = createRule({
173
164
  if (!/use\w*Effect|componentDidMount|componentWillUnmount/u.test(context.sourceCode.text)) {
174
165
  return {};
175
166
  }
176
- const fStack = [];
167
+ const fEntries = [];
177
168
  const aEntries = [];
178
169
  const rEntries = [];
179
170
  const abortedSignals = [];
@@ -195,17 +186,17 @@ var no_leaked_event_listener_default = createRule({
195
186
  return isSameObject(aCallee, rCallee) && AST2__namespace.isNodeEqual(aListener, rListener) && VAR2__namespace.isNodeValueEqual(aType, rType, [
196
187
  context.sourceCode.getScope(aType),
197
188
  context.sourceCode.getScope(rType)
198
- ]) && eff.O.getOrElse(aCapture, eff.F.constFalse) === eff.O.getOrElse(rCapture, eff.F.constFalse);
189
+ ]) && aCapture === rCapture;
199
190
  }
200
191
  function checkInlineFunction(node, callKind, options) {
201
- const [_, listener] = node.arguments;
192
+ const listener = node.arguments.at(1);
202
193
  if (!AST2__namespace.isFunction(listener)) {
203
- return eff.O.none();
194
+ return;
204
195
  }
205
- if (eff.O.isSome(options.signal)) {
206
- return eff.O.none();
196
+ if (options.signal !== eff._) {
197
+ return;
207
198
  }
208
- return eff.O.some({
199
+ context.report({
209
200
  messageId: "noLeakedEventListenerOfInlineFunction",
210
201
  node: listener,
211
202
  data: { eventMethodKind: callKind }
@@ -213,15 +204,15 @@ var no_leaked_event_listener_default = createRule({
213
204
  }
214
205
  return {
215
206
  [":function"](node) {
216
- const functionKind = getFunctionKind(node);
217
- fStack.push([node, functionKind]);
207
+ const kind = getFunctionKind(node);
208
+ fEntries.push({ kind, node });
218
209
  },
219
210
  [":function:exit"]() {
220
- fStack.pop();
211
+ fEntries.pop();
221
212
  },
222
213
  ["CallExpression"](node) {
223
- const [fNode, fKind] = fStack.findLast((f) => f.at(1) !== "other") ?? [];
224
- if (fNode == null || fKind == null) {
214
+ const fKind = fEntries.findLast((x) => x.kind !== "other")?.kind;
215
+ if (fKind === eff._) {
225
216
  return;
226
217
  }
227
218
  if (!core.ERPhaseRelevance.has(fKind)) {
@@ -234,7 +225,7 @@ var no_leaked_event_listener_default = createRule({
234
225
  }
235
226
  const opts = options == null ? defaultOptions : getOptions(options, context.sourceCode.getScope(options));
236
227
  const { callee } = node;
237
- eff.O.map(checkInlineFunction(node, callKind, opts), context.report);
228
+ checkInlineFunction(node, callKind, opts);
238
229
  aEntries.push({
239
230
  ...opts,
240
231
  kind: "addEventListener",
@@ -251,7 +242,7 @@ var no_leaked_event_listener_default = createRule({
251
242
  }
252
243
  const opts = options == null ? defaultOptions : getOptions(options, context.sourceCode.getScope(options));
253
244
  const { callee } = node;
254
- eff.O.map(checkInlineFunction(node, callKind, opts), context.report);
245
+ checkInlineFunction(node, callKind, opts);
255
246
  rEntries.push({
256
247
  ...opts,
257
248
  kind: "removeEventListener",
@@ -263,11 +254,12 @@ var no_leaked_event_listener_default = createRule({
263
254
  });
264
255
  }).with("abort", () => {
265
256
  abortedSignals.push(node.callee);
266
- }).otherwise(eff.F.constVoid);
257
+ }).otherwise(() => eff._);
267
258
  },
268
259
  ["Program:exit"]() {
269
260
  for (const aEntry of aEntries) {
270
- if (eff.O.exists(aEntry.signal, (signal) => abortedSignals.some((as) => isSameObject(as, signal)))) {
261
+ const signal = aEntry.signal;
262
+ if (signal !== eff._ && abortedSignals.some((a) => isSameObject(a, signal))) {
271
263
  continue;
272
264
  }
273
265
  if (rEntries.some((rEntry) => isInverseEntry(aEntry, rEntry))) {
@@ -331,31 +323,31 @@ var no_leaked_interval_default = createRule({
331
323
  if (!context.sourceCode.text.includes("setInterval")) {
332
324
  return {};
333
325
  }
334
- const fStack = [];
326
+ const fEntries = [];
335
327
  const sEntries = [];
336
328
  const cEntries = [];
337
329
  function isInverseEntry(a, b) {
338
- return isInstanceIDEqual(a.timerID, b.timerID, context);
330
+ return isInstanceIDEqual(a.timerId, b.timerId, context);
339
331
  }
340
332
  return {
341
333
  [":function"](node) {
342
- const fKind = eff.O.getOrElse(getPhaseKindOfFunction(node), () => "other");
343
- fStack.push([node, fKind]);
334
+ const kind = getPhaseKindOfFunction(node) ?? "other";
335
+ fEntries.push({ kind, node });
344
336
  },
345
337
  [":function:exit"]() {
346
- fStack.pop();
338
+ fEntries.pop();
347
339
  },
348
340
  ["CallExpression"](node) {
349
341
  switch (getCallKind2(node)) {
350
342
  case "setInterval": {
351
- const [fNode, fKind] = fStack.findLast((f) => f.at(1) !== "other") ?? [];
352
- if (fNode == null || fKind == null) {
343
+ const fEntry = fEntries.findLast((x) => x.kind !== "other");
344
+ if (fEntry === eff._) {
353
345
  break;
354
346
  }
355
- if (!core.ERPhaseRelevance.has(fKind)) {
347
+ if (!core.ERPhaseRelevance.has(fEntry.kind)) {
356
348
  break;
357
349
  }
358
- const intervalIdNode = eff.O.getOrNull(VAR2__namespace.getVariableDeclaratorID(node));
350
+ const intervalIdNode = VAR2__namespace.getVariableDeclaratorId(node);
359
351
  if (intervalIdNode == null) {
360
352
  context.report({
361
353
  messageId: "noLeakedIntervalNoIntervalId",
@@ -367,17 +359,17 @@ var no_leaked_interval_default = createRule({
367
359
  kind: "interval",
368
360
  node,
369
361
  callee: node.callee,
370
- phase: fKind,
371
- timerID: intervalIdNode
362
+ phase: fEntry.kind,
363
+ timerId: intervalIdNode
372
364
  });
373
365
  break;
374
366
  }
375
367
  case "clearInterval": {
376
- const [fNode, fKind] = fStack.findLast((f) => f.at(1) !== "other") ?? [];
377
- if (fNode == null || fKind == null) {
368
+ const fEntry = fEntries.findLast((x) => x.kind !== "other");
369
+ if (fEntry === eff._) {
378
370
  break;
379
371
  }
380
- if (!core.ERPhaseRelevance.has(fKind)) {
372
+ if (!core.ERPhaseRelevance.has(fEntry.kind)) {
381
373
  break;
382
374
  }
383
375
  const [intervalIdNode] = node.arguments;
@@ -388,8 +380,8 @@ var no_leaked_interval_default = createRule({
388
380
  kind: "interval",
389
381
  node,
390
382
  callee: node.callee,
391
- phase: fKind,
392
- timerID: intervalIdNode
383
+ phase: fEntry.kind,
384
+ timerId: intervalIdNode
393
385
  });
394
386
  break;
395
387
  }
@@ -433,16 +425,15 @@ var RULE_FEATURES3 = [
433
425
  "CHK"
434
426
  ];
435
427
  function isNewResizeObserver(node) {
436
- return node.type === utils.AST_NODE_TYPES.NewExpression && node.callee.type === utils.AST_NODE_TYPES.Identifier && node.callee.name === "ResizeObserver";
428
+ return node?.type === utils.AST_NODE_TYPES.NewExpression && node.callee.type === utils.AST_NODE_TYPES.Identifier && node.callee.name === "ResizeObserver";
437
429
  }
438
430
  function isFromObserver(node, context) {
439
431
  switch (true) {
440
- case node.type === utils.AST_NODE_TYPES.Identifier:
441
- return eff.F.pipe(
442
- VAR2__namespace.findVariable(node, context.sourceCode.getScope(node)),
443
- eff.O.flatMap(VAR2__namespace.getVariableNode(0)),
444
- eff.O.exists(isNewResizeObserver)
445
- );
432
+ case node.type === utils.AST_NODE_TYPES.Identifier: {
433
+ const initialScope = context.sourceCode.getScope(node);
434
+ const object = VAR2__namespace.getVariableNode(VAR2__namespace.findVariable(node, initialScope), 0);
435
+ return isNewResizeObserver(object);
436
+ }
446
437
  case node.type === utils.AST_NODE_TYPES.MemberExpression:
447
438
  return isFromObserver(node.object, context);
448
439
  default:
@@ -460,7 +451,7 @@ function getCallKind3(node, context) {
460
451
  }
461
452
  }
462
453
  function getFunctionKind2(node) {
463
- return eff.O.getOrElse(getPhaseKindOfFunction(node), eff.F.constant("other"));
454
+ return getPhaseKindOfFunction(node) ?? "other";
464
455
  }
465
456
  var no_leaked_resize_observer_default = createRule({
466
457
  meta: {
@@ -481,25 +472,25 @@ var no_leaked_resize_observer_default = createRule({
481
472
  if (!context.sourceCode.text.includes("ResizeObserver")) {
482
473
  return {};
483
474
  }
484
- const fStack = [];
475
+ const fEntries = [];
485
476
  const observers = [];
486
477
  const oEntries = [];
487
478
  const uEntries = [];
488
479
  const dEntries = [];
489
480
  return {
490
481
  [":function"](node) {
491
- const functionKind = getFunctionKind2(node);
492
- fStack.push([node, functionKind]);
482
+ const kind = getFunctionKind2(node);
483
+ fEntries.push({ kind, node });
493
484
  },
494
485
  [":function:exit"]() {
495
- fStack.pop();
486
+ fEntries.pop();
496
487
  },
497
488
  ["CallExpression"](node) {
498
- const [_, fKind] = fStack.findLast((f) => f.at(1) !== "other") ?? [];
499
489
  if (node.callee.type !== utils.AST_NODE_TYPES.MemberExpression) {
500
490
  return;
501
491
  }
502
- if (!core.ERPhaseRelevance.has(fKind)) {
492
+ const fKind = fEntries.findLast((x) => x.kind !== "other")?.kind;
493
+ if (fKind === eff._ || !core.ERPhaseRelevance.has(fKind)) {
503
494
  return;
504
495
  }
505
496
  const { object } = node.callee;
@@ -540,36 +531,42 @@ var no_leaked_resize_observer_default = createRule({
540
531
  observerKind: "ResizeObserver",
541
532
  phase: fKind
542
533
  });
543
- }).otherwise(eff.F.constVoid);
534
+ }).otherwise(() => eff._);
544
535
  },
545
536
  ["NewExpression"](node) {
546
- const [fNode, fKind] = fStack.findLast((f) => f.at(1) !== "other") ?? [];
547
- if (fNode == null || !core.ERPhaseRelevance.has(fKind)) {
537
+ const fEntry = fEntries.findLast((x) => x.kind !== "other");
538
+ if (fEntry === eff._) return;
539
+ if (!core.ERPhaseRelevance.has(fEntry.kind)) {
548
540
  return;
549
541
  }
550
542
  if (!isNewResizeObserver(node)) {
551
543
  return;
552
544
  }
553
545
  const id = getInstanceID(node);
554
- if (eff.O.isNone(id)) {
546
+ if (id === eff._) {
555
547
  context.report({
556
548
  messageId: "noLeakedResizeObserverNoFloatingInstance",
557
549
  node
558
550
  });
559
551
  return;
560
552
  }
561
- observers.push([node, id.value, fKind, fNode]);
553
+ observers.push({
554
+ id,
555
+ node,
556
+ phase: fEntry.kind,
557
+ phaseNode: fEntry.node
558
+ });
562
559
  },
563
560
  ["Program:exit"]() {
564
- for (const [node, id, _, phaseNode] of observers) {
561
+ for (const { id, node, phaseNode } of observers) {
565
562
  if (dEntries.some((e) => isInstanceIDEqual(e.observer, id, context))) {
566
563
  continue;
567
564
  }
568
565
  const oentries = oEntries.filter((e) => isInstanceIDEqual(e.observer, id, context));
569
566
  const uentries = uEntries.filter((e) => isInstanceIDEqual(e.observer, id, context));
570
- const isDynamic = (node2) => node2.type === utils.AST_NODE_TYPES.CallExpression || AST2__namespace.isConditional(node2);
567
+ const isDynamic = (node2) => node2?.type === utils.AST_NODE_TYPES.CallExpression || AST2__namespace.isConditional(node2);
571
568
  const isPhaseNode = (node2) => node2 === phaseNode;
572
- const hasDynamicallyAdded = oentries.some((e) => eff.O.exists(AST2__namespace.findParentNode(e.node, eff.or(isDynamic, isPhaseNode)), eff.not(isPhaseNode)));
569
+ const hasDynamicallyAdded = oentries.some((e) => !isPhaseNode(AST2__namespace.findParentNode(e.node, eff.or(isDynamic, isPhaseNode))));
573
570
  if (hasDynamicallyAdded) {
574
571
  context.report({ messageId: "noLeakedResizeObserverInControlFlow", node });
575
572
  continue;
@@ -619,31 +616,28 @@ var no_leaked_timeout_default = createRule({
619
616
  if (!context.sourceCode.text.includes("setTimeout")) {
620
617
  return {};
621
618
  }
622
- const fStack = [];
619
+ const fEntries = [];
623
620
  const sEntries = [];
624
621
  const rEntries = [];
625
622
  function isInverseEntry(a, b) {
626
- return isInstanceIDEqual(a.timerID, b.timerID, context);
623
+ return isInstanceIDEqual(a.timerId, b.timerId, context);
627
624
  }
628
625
  return {
629
626
  [":function"](node) {
630
- const fKind = eff.O.getOrElse(getPhaseKindOfFunction(node), () => "other");
631
- fStack.push([node, fKind]);
627
+ const kind = getPhaseKindOfFunction(node) ?? "other";
628
+ fEntries.push({ kind, node });
632
629
  },
633
630
  [":function:exit"]() {
634
- fStack.pop();
631
+ fEntries.pop();
635
632
  },
636
633
  ["CallExpression"](node) {
637
- const [fNode, fKind] = fStack.findLast((f) => f.at(1) !== "other") ?? [];
638
- if (fNode == null || fKind == null) {
639
- return;
640
- }
641
- if (!core.ERPhaseRelevance.has(fKind)) {
634
+ const fEntry = fEntries.findLast((f) => f.kind !== "other");
635
+ if (!core.ERPhaseRelevance.has(fEntry?.kind)) {
642
636
  return;
643
637
  }
644
638
  switch (getCallKind4(node)) {
645
639
  case "setTimeout": {
646
- const timeoutIdNode = eff.O.getOrNull(VAR2__namespace.getVariableDeclaratorID(node));
640
+ const timeoutIdNode = VAR2__namespace.getVariableDeclaratorId(node);
647
641
  if (timeoutIdNode == null) {
648
642
  context.report({
649
643
  messageId: "noLeakedTimeoutNoTimeoutId",
@@ -655,8 +649,8 @@ var no_leaked_timeout_default = createRule({
655
649
  kind: "timeout",
656
650
  node,
657
651
  callee: node.callee,
658
- phase: fKind,
659
- timerID: timeoutIdNode
652
+ phase: fEntry.kind,
653
+ timerId: timeoutIdNode
660
654
  });
661
655
  break;
662
656
  }
@@ -669,8 +663,8 @@ var no_leaked_timeout_default = createRule({
669
663
  kind: "timeout",
670
664
  node,
671
665
  callee: node.callee,
672
- phase: fKind,
673
- timerID: timeoutIdNode
666
+ phase: fEntry.kind,
667
+ timerId: timeoutIdNode
674
668
  });
675
669
  break;
676
670
  }
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as AST2 from '@eslint-react/ast';
2
2
  import { ERPhaseRelevance, isSetupFunction, isCleanupFunction, isComponentDidMountFunction, isComponentWillUnmountFunction, isInversePhase } from '@eslint-react/core';
3
- import { O, F, or, not, isBoolean } from '@eslint-react/eff';
3
+ import { _, or } from '@eslint-react/eff';
4
4
  import * as JSX from '@eslint-react/jsx';
5
5
  import * as VAR2 from '@eslint-react/var';
6
6
  import { AST_NODE_TYPES } from '@typescript-eslint/utils';
@@ -10,24 +10,24 @@ import { AST_NODE_TYPES as AST_NODE_TYPES$1 } from '@typescript-eslint/types';
10
10
 
11
11
  // package.json
12
12
  var name = "eslint-plugin-react-web-api";
13
- var version = "1.23.3-next.8";
13
+ var version = "1.24.0-next.0";
14
14
  var createRule = createRuleForPlugin("web-api");
15
15
  function getInstanceID(node, prev) {
16
16
  switch (true) {
17
17
  case (node.type === AST_NODE_TYPES$1.VariableDeclarator && node.init === prev):
18
- return O.some(node.id);
18
+ return node.id;
19
19
  case (node.type === AST_NODE_TYPES$1.AssignmentExpression && node.right === prev):
20
- return O.some(node.left);
20
+ return node.left;
21
21
  case (node.type === AST_NODE_TYPES$1.PropertyDefinition && node.value === prev):
22
- return O.some(node.key);
22
+ return node.key;
23
23
  case (node.type === AST_NODE_TYPES$1.BlockStatement || node.type === AST_NODE_TYPES$1.Program || node.parent === node):
24
- return O.none();
24
+ return _;
25
25
  default:
26
26
  return getInstanceID(node.parent, node);
27
27
  }
28
28
  }
29
29
  function getPhaseKindOfFunction(node) {
30
- return match(node).when(isSetupFunction, () => O.some("setup")).when(isCleanupFunction, () => O.some("cleanup")).when(isComponentDidMountFunction, () => O.some("mount")).when(isComponentWillUnmountFunction, () => O.some("unmount")).otherwise(O.none);
30
+ return match(node).when(isSetupFunction, () => "setup").when(isCleanupFunction, () => "cleanup").when(isComponentDidMountFunction, () => "mount").when(isComponentWillUnmountFunction, () => "unmount").otherwise(() => _);
31
31
  }
32
32
  function isInstanceIDEqual(a, b, context) {
33
33
  return AST2.isNodeEqual(a, b) || VAR2.isNodeValueEqual(a, b, [
@@ -42,9 +42,9 @@ var RULE_FEATURES = [
42
42
  "CHK"
43
43
  ];
44
44
  var defaultOptions = {
45
- capture: O.some(false),
46
- once: O.some(false),
47
- signal: O.none()
45
+ capture: false,
46
+ // once: false,
47
+ signal: _
48
48
  };
49
49
  function getCallKind(node) {
50
50
  switch (true) {
@@ -57,68 +57,59 @@ function getCallKind(node) {
57
57
  }
58
58
  }
59
59
  function getFunctionKind(node) {
60
- return O.getOrElse(getPhaseKindOfFunction(node), F.constant("other"));
60
+ return getPhaseKindOfFunction(node) ?? "other";
61
61
  }
62
62
  function getSignalValueExpression(node, initialScope) {
63
+ if (node === _) return _;
63
64
  switch (node.type) {
64
- case AST_NODE_TYPES.Identifier:
65
- return F.pipe(
66
- VAR2.findVariable(node, initialScope),
67
- O.flatMap(VAR2.getVariableNode(0)),
68
- O.flatMap((n) => getSignalValueExpression(n, initialScope))
69
- );
65
+ case AST_NODE_TYPES.Identifier: {
66
+ return getSignalValueExpression(VAR2.getVariableNode(VAR2.findVariable(node, initialScope), 0), initialScope);
67
+ }
70
68
  case AST_NODE_TYPES.MemberExpression:
71
- return O.some(node);
69
+ return node;
72
70
  default:
73
- return O.none();
71
+ return _;
74
72
  }
75
73
  }
76
74
  function getOptions(node, initialScope) {
77
- const findProp = (properties, propName) => {
78
- return JSX.findPropInProperties(properties, initialScope)(propName);
79
- };
80
- const getPropValue = (prop) => {
81
- if (prop.type !== AST_NODE_TYPES.Property) {
82
- return O.none();
83
- }
75
+ function findProp(properties, propName) {
76
+ return JSX.findPropInProperties(propName, properties, initialScope);
77
+ }
78
+ function getPropValue(prop, filter = (_6) => true) {
79
+ if (prop?.type !== AST_NODE_TYPES.Property) return _;
84
80
  const { value } = prop;
81
+ let v = value;
85
82
  switch (value.type) {
86
83
  case AST_NODE_TYPES.Literal: {
87
- return O.some(value.value);
84
+ v = value.value;
85
+ break;
88
86
  }
89
87
  default: {
90
- return VAR2.getStaticValue(value, initialScope);
88
+ v = VAR2.toResolved({ kind: "lazy", node: value, initialScope }).value;
89
+ break;
91
90
  }
92
91
  }
93
- };
92
+ return filter(v) ? v : _;
93
+ }
94
94
  function getOpts(node2) {
95
95
  switch (node2.type) {
96
96
  case AST_NODE_TYPES.Identifier: {
97
- return F.pipe(
98
- VAR2.findVariable(node2, initialScope),
99
- O.flatMap(VAR2.getVariableNode(0)),
100
- O.filter(AST2.is(AST_NODE_TYPES.ObjectExpression)),
101
- O.map(getOpts),
102
- O.getOrElse(() => defaultOptions)
103
- );
97
+ const variable = VAR2.findVariable(node2, initialScope);
98
+ const variableNode = VAR2.getVariableNode(variable, 0);
99
+ if (variableNode?.type === AST_NODE_TYPES.ObjectExpression) {
100
+ return getOpts(variableNode);
101
+ }
102
+ return defaultOptions;
104
103
  }
105
104
  case AST_NODE_TYPES.Literal: {
106
- return { ...defaultOptions, capture: O.some(Boolean(node2.value)) };
105
+ return { ...defaultOptions, capture: Boolean(node2.value) };
107
106
  }
108
107
  case AST_NODE_TYPES.ObjectExpression: {
109
- const pOnce = findProp(node2.properties, "once");
110
- const vOnce = O.flatMap(pOnce, getPropValue).pipe(O.filter(isBoolean));
111
108
  const pCapture = findProp(node2.properties, "capture");
112
- const vCapture = O.flatMap(pCapture, getPropValue).pipe(O.filter(isBoolean));
109
+ const vCapture = !!getPropValue(pCapture);
113
110
  const pSignal = findProp(node2.properties, "signal");
114
- const vSignal = O.flatMap(pSignal, (prop) => {
115
- if (prop.type !== AST_NODE_TYPES.Property) {
116
- return O.none();
117
- }
118
- const { value } = prop;
119
- return getSignalValueExpression(value, initialScope);
120
- });
121
- return { capture: vCapture, once: vOnce, signal: vSignal };
111
+ const vSignal = pSignal?.type === AST_NODE_TYPES.Property ? getSignalValueExpression(pSignal.value, initialScope) : _;
112
+ return { capture: vCapture, signal: vSignal };
122
113
  }
123
114
  default: {
124
115
  return defaultOptions;
@@ -149,7 +140,7 @@ var no_leaked_event_listener_default = createRule({
149
140
  if (!/use\w*Effect|componentDidMount|componentWillUnmount/u.test(context.sourceCode.text)) {
150
141
  return {};
151
142
  }
152
- const fStack = [];
143
+ const fEntries = [];
153
144
  const aEntries = [];
154
145
  const rEntries = [];
155
146
  const abortedSignals = [];
@@ -171,17 +162,17 @@ var no_leaked_event_listener_default = createRule({
171
162
  return isSameObject(aCallee, rCallee) && AST2.isNodeEqual(aListener, rListener) && VAR2.isNodeValueEqual(aType, rType, [
172
163
  context.sourceCode.getScope(aType),
173
164
  context.sourceCode.getScope(rType)
174
- ]) && O.getOrElse(aCapture, F.constFalse) === O.getOrElse(rCapture, F.constFalse);
165
+ ]) && aCapture === rCapture;
175
166
  }
176
167
  function checkInlineFunction(node, callKind, options) {
177
- const [_, listener] = node.arguments;
168
+ const listener = node.arguments.at(1);
178
169
  if (!AST2.isFunction(listener)) {
179
- return O.none();
170
+ return;
180
171
  }
181
- if (O.isSome(options.signal)) {
182
- return O.none();
172
+ if (options.signal !== _) {
173
+ return;
183
174
  }
184
- return O.some({
175
+ context.report({
185
176
  messageId: "noLeakedEventListenerOfInlineFunction",
186
177
  node: listener,
187
178
  data: { eventMethodKind: callKind }
@@ -189,15 +180,15 @@ var no_leaked_event_listener_default = createRule({
189
180
  }
190
181
  return {
191
182
  [":function"](node) {
192
- const functionKind = getFunctionKind(node);
193
- fStack.push([node, functionKind]);
183
+ const kind = getFunctionKind(node);
184
+ fEntries.push({ kind, node });
194
185
  },
195
186
  [":function:exit"]() {
196
- fStack.pop();
187
+ fEntries.pop();
197
188
  },
198
189
  ["CallExpression"](node) {
199
- const [fNode, fKind] = fStack.findLast((f) => f.at(1) !== "other") ?? [];
200
- if (fNode == null || fKind == null) {
190
+ const fKind = fEntries.findLast((x) => x.kind !== "other")?.kind;
191
+ if (fKind === _) {
201
192
  return;
202
193
  }
203
194
  if (!ERPhaseRelevance.has(fKind)) {
@@ -210,7 +201,7 @@ var no_leaked_event_listener_default = createRule({
210
201
  }
211
202
  const opts = options == null ? defaultOptions : getOptions(options, context.sourceCode.getScope(options));
212
203
  const { callee } = node;
213
- O.map(checkInlineFunction(node, callKind, opts), context.report);
204
+ checkInlineFunction(node, callKind, opts);
214
205
  aEntries.push({
215
206
  ...opts,
216
207
  kind: "addEventListener",
@@ -227,7 +218,7 @@ var no_leaked_event_listener_default = createRule({
227
218
  }
228
219
  const opts = options == null ? defaultOptions : getOptions(options, context.sourceCode.getScope(options));
229
220
  const { callee } = node;
230
- O.map(checkInlineFunction(node, callKind, opts), context.report);
221
+ checkInlineFunction(node, callKind, opts);
231
222
  rEntries.push({
232
223
  ...opts,
233
224
  kind: "removeEventListener",
@@ -239,11 +230,12 @@ var no_leaked_event_listener_default = createRule({
239
230
  });
240
231
  }).with("abort", () => {
241
232
  abortedSignals.push(node.callee);
242
- }).otherwise(F.constVoid);
233
+ }).otherwise(() => _);
243
234
  },
244
235
  ["Program:exit"]() {
245
236
  for (const aEntry of aEntries) {
246
- if (O.exists(aEntry.signal, (signal) => abortedSignals.some((as) => isSameObject(as, signal)))) {
237
+ const signal = aEntry.signal;
238
+ if (signal !== _ && abortedSignals.some((a) => isSameObject(a, signal))) {
247
239
  continue;
248
240
  }
249
241
  if (rEntries.some((rEntry) => isInverseEntry(aEntry, rEntry))) {
@@ -307,31 +299,31 @@ var no_leaked_interval_default = createRule({
307
299
  if (!context.sourceCode.text.includes("setInterval")) {
308
300
  return {};
309
301
  }
310
- const fStack = [];
302
+ const fEntries = [];
311
303
  const sEntries = [];
312
304
  const cEntries = [];
313
305
  function isInverseEntry(a, b) {
314
- return isInstanceIDEqual(a.timerID, b.timerID, context);
306
+ return isInstanceIDEqual(a.timerId, b.timerId, context);
315
307
  }
316
308
  return {
317
309
  [":function"](node) {
318
- const fKind = O.getOrElse(getPhaseKindOfFunction(node), () => "other");
319
- fStack.push([node, fKind]);
310
+ const kind = getPhaseKindOfFunction(node) ?? "other";
311
+ fEntries.push({ kind, node });
320
312
  },
321
313
  [":function:exit"]() {
322
- fStack.pop();
314
+ fEntries.pop();
323
315
  },
324
316
  ["CallExpression"](node) {
325
317
  switch (getCallKind2(node)) {
326
318
  case "setInterval": {
327
- const [fNode, fKind] = fStack.findLast((f) => f.at(1) !== "other") ?? [];
328
- if (fNode == null || fKind == null) {
319
+ const fEntry = fEntries.findLast((x) => x.kind !== "other");
320
+ if (fEntry === _) {
329
321
  break;
330
322
  }
331
- if (!ERPhaseRelevance.has(fKind)) {
323
+ if (!ERPhaseRelevance.has(fEntry.kind)) {
332
324
  break;
333
325
  }
334
- const intervalIdNode = O.getOrNull(VAR2.getVariableDeclaratorID(node));
326
+ const intervalIdNode = VAR2.getVariableDeclaratorId(node);
335
327
  if (intervalIdNode == null) {
336
328
  context.report({
337
329
  messageId: "noLeakedIntervalNoIntervalId",
@@ -343,17 +335,17 @@ var no_leaked_interval_default = createRule({
343
335
  kind: "interval",
344
336
  node,
345
337
  callee: node.callee,
346
- phase: fKind,
347
- timerID: intervalIdNode
338
+ phase: fEntry.kind,
339
+ timerId: intervalIdNode
348
340
  });
349
341
  break;
350
342
  }
351
343
  case "clearInterval": {
352
- const [fNode, fKind] = fStack.findLast((f) => f.at(1) !== "other") ?? [];
353
- if (fNode == null || fKind == null) {
344
+ const fEntry = fEntries.findLast((x) => x.kind !== "other");
345
+ if (fEntry === _) {
354
346
  break;
355
347
  }
356
- if (!ERPhaseRelevance.has(fKind)) {
348
+ if (!ERPhaseRelevance.has(fEntry.kind)) {
357
349
  break;
358
350
  }
359
351
  const [intervalIdNode] = node.arguments;
@@ -364,8 +356,8 @@ var no_leaked_interval_default = createRule({
364
356
  kind: "interval",
365
357
  node,
366
358
  callee: node.callee,
367
- phase: fKind,
368
- timerID: intervalIdNode
359
+ phase: fEntry.kind,
360
+ timerId: intervalIdNode
369
361
  });
370
362
  break;
371
363
  }
@@ -409,16 +401,15 @@ var RULE_FEATURES3 = [
409
401
  "CHK"
410
402
  ];
411
403
  function isNewResizeObserver(node) {
412
- return node.type === AST_NODE_TYPES.NewExpression && node.callee.type === AST_NODE_TYPES.Identifier && node.callee.name === "ResizeObserver";
404
+ return node?.type === AST_NODE_TYPES.NewExpression && node.callee.type === AST_NODE_TYPES.Identifier && node.callee.name === "ResizeObserver";
413
405
  }
414
406
  function isFromObserver(node, context) {
415
407
  switch (true) {
416
- case node.type === AST_NODE_TYPES.Identifier:
417
- return F.pipe(
418
- VAR2.findVariable(node, context.sourceCode.getScope(node)),
419
- O.flatMap(VAR2.getVariableNode(0)),
420
- O.exists(isNewResizeObserver)
421
- );
408
+ case node.type === AST_NODE_TYPES.Identifier: {
409
+ const initialScope = context.sourceCode.getScope(node);
410
+ const object = VAR2.getVariableNode(VAR2.findVariable(node, initialScope), 0);
411
+ return isNewResizeObserver(object);
412
+ }
422
413
  case node.type === AST_NODE_TYPES.MemberExpression:
423
414
  return isFromObserver(node.object, context);
424
415
  default:
@@ -436,7 +427,7 @@ function getCallKind3(node, context) {
436
427
  }
437
428
  }
438
429
  function getFunctionKind2(node) {
439
- return O.getOrElse(getPhaseKindOfFunction(node), F.constant("other"));
430
+ return getPhaseKindOfFunction(node) ?? "other";
440
431
  }
441
432
  var no_leaked_resize_observer_default = createRule({
442
433
  meta: {
@@ -457,25 +448,25 @@ var no_leaked_resize_observer_default = createRule({
457
448
  if (!context.sourceCode.text.includes("ResizeObserver")) {
458
449
  return {};
459
450
  }
460
- const fStack = [];
451
+ const fEntries = [];
461
452
  const observers = [];
462
453
  const oEntries = [];
463
454
  const uEntries = [];
464
455
  const dEntries = [];
465
456
  return {
466
457
  [":function"](node) {
467
- const functionKind = getFunctionKind2(node);
468
- fStack.push([node, functionKind]);
458
+ const kind = getFunctionKind2(node);
459
+ fEntries.push({ kind, node });
469
460
  },
470
461
  [":function:exit"]() {
471
- fStack.pop();
462
+ fEntries.pop();
472
463
  },
473
464
  ["CallExpression"](node) {
474
- const [_, fKind] = fStack.findLast((f) => f.at(1) !== "other") ?? [];
475
465
  if (node.callee.type !== AST_NODE_TYPES.MemberExpression) {
476
466
  return;
477
467
  }
478
- if (!ERPhaseRelevance.has(fKind)) {
468
+ const fKind = fEntries.findLast((x) => x.kind !== "other")?.kind;
469
+ if (fKind === _ || !ERPhaseRelevance.has(fKind)) {
479
470
  return;
480
471
  }
481
472
  const { object } = node.callee;
@@ -516,36 +507,42 @@ var no_leaked_resize_observer_default = createRule({
516
507
  observerKind: "ResizeObserver",
517
508
  phase: fKind
518
509
  });
519
- }).otherwise(F.constVoid);
510
+ }).otherwise(() => _);
520
511
  },
521
512
  ["NewExpression"](node) {
522
- const [fNode, fKind] = fStack.findLast((f) => f.at(1) !== "other") ?? [];
523
- if (fNode == null || !ERPhaseRelevance.has(fKind)) {
513
+ const fEntry = fEntries.findLast((x) => x.kind !== "other");
514
+ if (fEntry === _) return;
515
+ if (!ERPhaseRelevance.has(fEntry.kind)) {
524
516
  return;
525
517
  }
526
518
  if (!isNewResizeObserver(node)) {
527
519
  return;
528
520
  }
529
521
  const id = getInstanceID(node);
530
- if (O.isNone(id)) {
522
+ if (id === _) {
531
523
  context.report({
532
524
  messageId: "noLeakedResizeObserverNoFloatingInstance",
533
525
  node
534
526
  });
535
527
  return;
536
528
  }
537
- observers.push([node, id.value, fKind, fNode]);
529
+ observers.push({
530
+ id,
531
+ node,
532
+ phase: fEntry.kind,
533
+ phaseNode: fEntry.node
534
+ });
538
535
  },
539
536
  ["Program:exit"]() {
540
- for (const [node, id, _, phaseNode] of observers) {
537
+ for (const { id, node, phaseNode } of observers) {
541
538
  if (dEntries.some((e) => isInstanceIDEqual(e.observer, id, context))) {
542
539
  continue;
543
540
  }
544
541
  const oentries = oEntries.filter((e) => isInstanceIDEqual(e.observer, id, context));
545
542
  const uentries = uEntries.filter((e) => isInstanceIDEqual(e.observer, id, context));
546
- const isDynamic = (node2) => node2.type === AST_NODE_TYPES.CallExpression || AST2.isConditional(node2);
543
+ const isDynamic = (node2) => node2?.type === AST_NODE_TYPES.CallExpression || AST2.isConditional(node2);
547
544
  const isPhaseNode = (node2) => node2 === phaseNode;
548
- const hasDynamicallyAdded = oentries.some((e) => O.exists(AST2.findParentNode(e.node, or(isDynamic, isPhaseNode)), not(isPhaseNode)));
545
+ const hasDynamicallyAdded = oentries.some((e) => !isPhaseNode(AST2.findParentNode(e.node, or(isDynamic, isPhaseNode))));
549
546
  if (hasDynamicallyAdded) {
550
547
  context.report({ messageId: "noLeakedResizeObserverInControlFlow", node });
551
548
  continue;
@@ -595,31 +592,28 @@ var no_leaked_timeout_default = createRule({
595
592
  if (!context.sourceCode.text.includes("setTimeout")) {
596
593
  return {};
597
594
  }
598
- const fStack = [];
595
+ const fEntries = [];
599
596
  const sEntries = [];
600
597
  const rEntries = [];
601
598
  function isInverseEntry(a, b) {
602
- return isInstanceIDEqual(a.timerID, b.timerID, context);
599
+ return isInstanceIDEqual(a.timerId, b.timerId, context);
603
600
  }
604
601
  return {
605
602
  [":function"](node) {
606
- const fKind = O.getOrElse(getPhaseKindOfFunction(node), () => "other");
607
- fStack.push([node, fKind]);
603
+ const kind = getPhaseKindOfFunction(node) ?? "other";
604
+ fEntries.push({ kind, node });
608
605
  },
609
606
  [":function:exit"]() {
610
- fStack.pop();
607
+ fEntries.pop();
611
608
  },
612
609
  ["CallExpression"](node) {
613
- const [fNode, fKind] = fStack.findLast((f) => f.at(1) !== "other") ?? [];
614
- if (fNode == null || fKind == null) {
615
- return;
616
- }
617
- if (!ERPhaseRelevance.has(fKind)) {
610
+ const fEntry = fEntries.findLast((f) => f.kind !== "other");
611
+ if (!ERPhaseRelevance.has(fEntry?.kind)) {
618
612
  return;
619
613
  }
620
614
  switch (getCallKind4(node)) {
621
615
  case "setTimeout": {
622
- const timeoutIdNode = O.getOrNull(VAR2.getVariableDeclaratorID(node));
616
+ const timeoutIdNode = VAR2.getVariableDeclaratorId(node);
623
617
  if (timeoutIdNode == null) {
624
618
  context.report({
625
619
  messageId: "noLeakedTimeoutNoTimeoutId",
@@ -631,8 +625,8 @@ var no_leaked_timeout_default = createRule({
631
625
  kind: "timeout",
632
626
  node,
633
627
  callee: node.callee,
634
- phase: fKind,
635
- timerID: timeoutIdNode
628
+ phase: fEntry.kind,
629
+ timerId: timeoutIdNode
636
630
  });
637
631
  break;
638
632
  }
@@ -645,8 +639,8 @@ var no_leaked_timeout_default = createRule({
645
639
  kind: "timeout",
646
640
  node,
647
641
  callee: node.callee,
648
- phase: fKind,
649
- timerID: timeoutIdNode
642
+ phase: fEntry.kind,
643
+ timerId: timeoutIdNode
650
644
  });
651
645
  break;
652
646
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-react-web-api",
3
- "version": "1.23.3-next.8",
3
+ "version": "1.24.0-next.0",
4
4
  "description": "ESLint React's ESLint plugin for interacting with Web APIs",
5
5
  "keywords": [
6
6
  "react",
@@ -10,13 +10,13 @@
10
10
  "eslint-plugin",
11
11
  "eslint-plugin-react-web-api"
12
12
  ],
13
- "homepage": "https://github.com/rEl1cx/eslint-react",
13
+ "homepage": "https://github.com/Rel1cx/eslint-react",
14
14
  "bugs": {
15
- "url": "https://github.com/rEl1cx/eslint-react/issues"
15
+ "url": "https://github.com/Rel1cx/eslint-react/issues"
16
16
  },
17
17
  "repository": {
18
18
  "type": "git",
19
- "url": "git+https://github.com/rEl1cx/eslint-react.git",
19
+ "url": "git+https://github.com/Rel1cx/eslint-react.git",
20
20
  "directory": "packages/plugins/eslint-plugin-react-web-api"
21
21
  },
22
22
  "license": "MIT",
@@ -46,13 +46,13 @@
46
46
  "@typescript-eslint/utils": "^8.19.1",
47
47
  "string-ts": "^2.2.0",
48
48
  "ts-pattern": "^5.6.0",
49
- "@eslint-react/core": "1.23.3-next.8",
50
- "@eslint-react/eff": "1.23.3-next.8",
51
- "@eslint-react/jsx": "1.23.3-next.8",
52
- "@eslint-react/shared": "1.23.3-next.8",
53
- "@eslint-react/types": "1.23.3-next.8",
54
- "@eslint-react/ast": "1.23.3-next.8",
55
- "@eslint-react/var": "1.23.3-next.8"
49
+ "@eslint-react/core": "1.24.0-next.0",
50
+ "@eslint-react/eff": "1.24.0-next.0",
51
+ "@eslint-react/jsx": "1.24.0-next.0",
52
+ "@eslint-react/shared": "1.24.0-next.0",
53
+ "@eslint-react/var": "1.24.0-next.0",
54
+ "@eslint-react/types": "1.24.0-next.0",
55
+ "@eslint-react/ast": "1.24.0-next.0"
56
56
  },
57
57
  "devDependencies": {
58
58
  "@types/react": "^19.0.4",