is-reference AST Node Identification
is-reference is a focused utility designed to accurately determine whether a given JavaScript Abstract Syntax Tree (AST) node, specifically an `Identifier`, constitutes a 'reference' in the context of scope analysis. This is crucial for tools like bundlers, minifiers, and linters that need to differentiate between identifiers that refer to a variable binding (e.g., `console.log(foo)`) and those that are property names (e.g., `obj.foo`). The package is currently at version 3.0.3 and appears to follow an infrequent release cadence, driven by the needs of projects like Rollup. Its primary differentiator is its precise definition of a 'reference' within the ESTree specification, distinguishing it from simply being an `Identifier` node. It ships with TypeScript types, ensuring type-safe usage in modern JavaScript environments.
Common errors
-
TypeError: is_reference is not a function
cause This error occurs when `is_reference` is incorrectly imported as a named export (e.g., `import { is_reference } from 'is-reference';`) or when a CommonJS `require()` call fails to resolve the default export correctly, typically in an ESM-first package.fixEnsure you are using the correct default import syntax: `import is_reference from 'is-reference';`. If in a CommonJS environment, verify that your tooling or Node.js version supports ESM interop for default exports, or consider bundling. -
TypeError: Cannot read properties of undefined (reading 'type') (or similar error related to accessing properties of `parent`)
cause This indicates that the `parent` argument passed to `is_reference` was `undefined`, `null`, or not a valid AST node object, preventing the function from inspecting the parent's properties to determine the context of the child node.fixAlways pass a valid AST `parent` node to `is_reference(node, parent)`. If you are at the root of the AST (e.g., a `Program` node), its `parent` would typically be `null` or `undefined`, and `is_reference` expects to handle this case, but for any child node, a correct parent must be provided by your AST traversal logic.
Warnings
- breaking Version 3.0.0 and above are primarily distributed as ES Modules (ESM). This means `require()` syntax may not work directly or correctly in Node.js environments without specific configuration (e.g., `type: 'module'` in package.json for consumer projects) or a transpilation step. Previous major versions might have supported CommonJS more directly.
- gotcha The `is_reference` function strictly requires both the AST `node` and its `parent` node as arguments to provide context. Passing only the `node` or an incorrect `parent` will lead to incorrect results or runtime errors, as the parent's type and structure are crucial for accurate reference determination.
- gotcha It's a common misconception that every `Identifier` AST node represents a 'reference'. `is-reference` specifically distinguishes identifiers that *refer* to a variable binding (e.g., `x` in `let y = x;`) from those that are purely property keys (e.g., `prop` in `obj.prop`) or other non-referencing syntax. It's designed for scope analysis, not general identifier finding.
Install
-
npm install is-reference -
yarn add is-reference -
pnpm add is-reference
Imports
- is_reference
import { is_reference } from 'is-reference';import is_reference from 'is-reference';
- is_reference (CommonJS)
import is_reference from 'is-reference'; // In CJS-only environments
const is_reference = require('is-reference');
Quickstart
import { parse } from 'acorn';
import { walk } from 'estree-walker';
import is_reference from 'is-reference';
const identifiers = [];
const references = [];
// Using ecmaVersion to support modern syntax for the AST parsing
const ast = parse(`
const x = 1;
let y = x + obj.prop;
function foo(param) { console.log(param, y); }
foo(x);
`, { ecmaVersion: 2020 });
walk(ast, {
enter(node, parent) {
if (node.type === 'Identifier') identifiers.push(node);
if (is_reference(node, parent)) references.push(node);
}
});
console.log('All Identifiers:', identifiers.map(node => node.name).join(', '));
// Expected: All Identifiers: x, y, x, obj, prop, foo, param, console, log, param, y, foo, x
console.log('References:', references.map(node => node.name).join(', '));
// Expected: References: x, y, x, obj, foo, param, console, log, param, y, foo, x