From a8cde960ce626c77416edd4b58a8e502bcb0bacc Mon Sep 17 00:00:00 2001 From: Marvin Hagemeister Date: Wed, 13 Aug 2025 15:46:51 +0200 Subject: [PATCH] fix(unstable): lint node properties should be enumerable (#30391) This makes npm libraries that traverse the ESTree format like `zimmerframe` or `periscopic` work with our lint ast. --- cli/js/40_lint.js | 3 +++ tests/unit/lint_plugin_test.ts | 20 +++++++++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/cli/js/40_lint.js b/cli/js/40_lint.js index 5d0a10538e..8355c056a5 100644 --- a/cli/js/40_lint.js +++ b/cli/js/40_lint.js @@ -607,6 +607,9 @@ function setNodeGetters(ctx) { const name = getString(ctx.strTable, id); Object.defineProperty(FacadeNode.prototype, name, { + // The `parent` key is expected to be non-enumerable. + // See the npm `zimmerframe` library. + enumerable: name !== "parent", get() { return readValue( this[INTERNAL_CTX], diff --git a/tests/unit/lint_plugin_test.ts b/tests/unit/lint_plugin_test.ts index 6c1b70719e..30ea116e69 100644 --- a/tests/unit/lint_plugin_test.ts +++ b/tests/unit/lint_plugin_test.ts @@ -1,6 +1,6 @@ // Copyright 2018-2025 the Deno authors. MIT license. -import { assertEquals } from "./test_util.ts"; +import { assert, assertEquals } from "./test_util.ts"; import { assertSnapshot } from "@std/testing/snapshot"; // TODO(@marvinhagemeister) Remove once we land "official" types @@ -1228,3 +1228,21 @@ Deno.test("Plugin - TS keywords", async (t) => { await testSnapshot(t, "type A = unknown", "TSUnknownKeyword"); await testSnapshot(t, "type A = void", "TSVoidKeyword"); }); + +Deno.test("Plugin - enumerable properties", () => { + const keys: string[] = []; + testPlugin(`const a = 42`, { + create() { + return { + Program(node) { + // deno-lint-ignore guard-for-in + for (const k in node) { + keys.push(k); + } + }, + }; + }, + }); + + assert(keys.length > 0); +});