Skip to content

Commit

Permalink
fix(no-unsupported): Correctly handle recursive objects on a per modu…
Browse files Browse the repository at this point in the history
…le basis (#396)
  • Loading branch information
scagood authored Dec 10, 2024
1 parent 1466bec commit db384d1
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 14 deletions.
22 changes: 10 additions & 12 deletions lib/util/enumerate-property-names.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,16 @@ const unprefixNodeColon = require("./unprefix-node-colon")
* Enumerate property names of a given object recursively.
* @param {TraceMap} traceMap The map for APIs to enumerate.
* @param {string[]} [path] The path to the current map.
* @param {WeakSet<TraceMap>} [recursionSet] A WeakSet used to block recursion (eg Module, Module.Module, Module.Module.Module)
* @param {{ [key: string]: WeakSet<TraceMap> }} [recursion] An object to block recursion (per module)
* @returns {IterableIterator<string>} The property names of the map.
*/
function* enumeratePropertyNames(
traceMap,
path = [],
recursionSet = new WeakSet()
) {
if (recursionSet.has(traceMap)) {
function* enumeratePropertyNames(traceMap, path = [], recursion = {}) {
const recursionSet =
typeof path[0] === "string"
? (recursion[path[0]] ??= new WeakSet())
: undefined

if (recursionSet?.has(traceMap)) {
return
}

Expand All @@ -48,11 +49,8 @@ function* enumeratePropertyNames(
yield childName
}

yield* enumeratePropertyNames(
childValue,
childPath,
recursionSet.add(traceMap)
)
recursionSet?.add(traceMap)
yield* enumeratePropertyNames(childValue, childPath, recursion)
}
}

Expand Down
90 changes: 88 additions & 2 deletions tests/lib/rules/no-unsupported-features/node-builtins.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,58 @@
*/
"use strict"

/** @import { Linter } from 'eslint' */

const RuleTester = require("../../../test-helpers").RuleTester
const rule = require("../../../../lib/rules/no-unsupported-features/node-builtins")

/**
* @typedef ValidTestCase
* @property {string} [name]
* @property {string} code
* @property {any} [options]
* @property {string | undefined} [filename]
* @property {boolean} [only]
* @property {Linter.LanguageOptions | undefined} [languageOptions]
* @property {{ [name: string]: any } | undefined} [settings]
*/
/**
* @typedef SuggestionOutput
* @property {string} [messageId]
* @property {string} [desc]
* @property {Record<string, unknown> | undefined} [data]
* @property {string} output
*/
/**
* @typedef InvalidTestExtras
* @property {number | Array<TestCaseError | string>} errors
* @property {string | null | undefined} [output]
*/
/**
* @typedef {ValidTestCase & InvalidTestExtras} InvalidTestCase
*/
/**
* @typedef TestCaseError
* @property {string | RegExp} [message]
* @property {string} [messageId]
* @property {string | undefined} [type]
* @property {any} [data]
* @property {number | undefined} [line]
* @property {number | undefined} [column]
* @property {number | undefined} [endLine]
* @property {number | undefined} [endColumn]
* @property {SuggestionOutput[] | undefined} [suggestions]
*/
/**
* @typedef Pattern
* @property {ValidTestCase[]} [valid]
* @property {InvalidTestCase[]} [invalid]
*/

/**
* Concatenate patterns.
* @param {Array<{valid:Array,invalid:Array}>} patterns The patterns to concat.
* @returns {{valid:Array,invalid:Array}} The concatenated patterns.
* @param {Pattern[]} patterns The patterns to concat.
* @returns {Pattern} The concatenated patterns.
*/
function concat(patterns) {
const ret = {
Expand Down Expand Up @@ -5372,6 +5417,47 @@ new RuleTester({ languageOptions: { sourceType: "module" } }).run(
],
},

//----------------------------------------------------------------------
// timers/promises
//----------------------------------------------------------------------
{
valid: [
{
code: `
import { scheduler } from 'node:timers/promises';
await scheduler.wait( 1000 );
`,
options: [
{
version: ">= 20.0.0",
ignores: ["timers/promises.scheduler.wait"],
},
],
languageOptions: { ecmaVersion: "latest" },
},
],
invalid: [
{
code: `
import { scheduler } from 'node:timers/promises';
await scheduler.wait( 1000 );
`,
options: [{ version: ">= 20.0.0" }],
languageOptions: { ecmaVersion: "latest" },

errors: [
{
messageId: "not-supported-yet",
data: {
name: "timers/promises.scheduler.wait",
version: ">= 20.0.0",
},
},
],
},
],
},

{
valid: [
{
Expand Down

0 comments on commit db384d1

Please sign in to comment.