Skip to content

Comments

refactor(linter/plugins): convert global properties to vars with TSDown plugin, instead of manually#16961

Merged
graphite-app[bot] merged 1 commit intomainfrom
12-16-refactor_linter_plugins_convert_global_properties_to_vars_with_tsdown_plugin_instead_of_manually
Dec 16, 2025
Merged

refactor(linter/plugins): convert global properties to vars with TSDown plugin, instead of manually#16961
graphite-app[bot] merged 1 commit intomainfrom
12-16-refactor_linter_plugins_convert_global_properties_to_vars_with_tsdown_plugin_instead_of_manually

Conversation

@overlookmotel
Copy link
Member

@overlookmotel overlookmotel commented Dec 16, 2025

Previously we had a pattern of destructuring properties of global objects into top-level vars. e.g.:

const { keys: ObjectKeys, hasOwn } = Object,
  { isArray } = Array;

Doing this is more performant, but it makes the code harder to read.

Instead, write code normally, and use a TSDown plugin to convert:

const keys = Object.keys(obj);

to:

import { ObjectKeys } from "../utils/globals.ts";
const keys = ObjectKeys(obj);

Defining all the destructured globals in a single file (utils/globals.ts) is advantageous for bundle size. If the TSDown plugin created top level const ObjectKeys = Object.keys; statements in each file, then you can end up with this in bundle as minifier doesn't de-duplicate:

const ObjectKeys = Object.keys;
const ObjectKeys$1 = Object.keys;
const ObjectKeys$2 = Object.keys;

The globals we use have to be manually added to utils/globals.ts, but TSDown plugin warns when this needs to be done, and doesn't generate a broken build in the meantime.

This plugin is run in debug builds too, so that the tests will catch any bugs.

@github-actions github-actions bot added A-linter Area - Linter A-cli Area - CLI A-linter-plugins Area - Linter JS plugins C-cleanup Category - technical debt or refactoring. Solution not expected to change behavior labels Dec 16, 2025
Copy link
Member Author

overlookmotel commented Dec 16, 2025


How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:

  • 0-merge - adds this PR to the back of the merge queue
  • hotfix - for urgent hot fixes, skip the queue and merge this PR next

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the codebase to eliminate manual destructuring of global object properties in favor of an automated TSDown plugin transformation. The plugin converts direct usage of properties like Object.keys() into imports of optimized global variables (e.g., ObjectKeys) from a centralized utils/globals.ts file, improving both performance and bundle size.

Key changes:

  • Implements a new TSDown plugin (createReplaceGlobalsPlugin) that automatically transforms global property accesses
  • Creates a centralized utils/globals.ts file exporting commonly-used global properties as variables
  • Removes manual destructuring patterns from all source files

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
apps/oxlint/tsdown.config.ts Adds the new createReplaceGlobalsPlugin with AST transformation logic and integrates it into the build pipeline
apps/oxlint/src-js/utils/globals.ts New file centralizing exports of global object properties as optimized variables
apps/oxlint/src-js/plugins/visitor.ts Removes manual ObjectKeys destructuring; reverts to direct Object.keys() usage
apps/oxlint/src-js/plugins/tokens.ts Removes manual Math.max/min destructuring; reverts to direct usage
apps/oxlint/src-js/plugins/source_code.ts Removes manual Math.max destructuring; reverts to direct usage
apps/oxlint/src-js/plugins/selector.ts Removes manual ObjectKeys destructuring; reverts to direct usage
apps/oxlint/src-js/plugins/report.ts Removes manual Object.hasOwn/keys destructuring; reverts to direct usage
apps/oxlint/src-js/plugins/options.ts Removes manual destructuring of Object, Array, and Math methods; reverts to direct usage
apps/oxlint/src-js/plugins/location.ts Removes manual Object.defineProperty and Array.isArray destructuring; reverts to direct usage
apps/oxlint/src-js/plugins/load.ts Removes manual destructuring of Object.keys, Array.isArray, and JSON methods; reverts to direct usage
apps/oxlint/src-js/plugins/json.ts Removes manual Array.isArray and Object.freeze destructuring; reverts to direct usage
apps/oxlint/src-js/plugins/globals.ts Removes manual Object.freeze and Array.isArray destructuring; reverts to direct usage
apps/oxlint/src-js/plugins/fix.ts Removes manual destructuring of Array, Object, Reflect, and Symbol properties; reverts to direct usage
apps/oxlint/src-js/plugins/context.ts Removes manual destructuring of Object methods; reverts to direct usage
apps/oxlint/src-js/package/rule_tester.ts Removes manual destructuring of Object.hasOwn, Array.isArray, and JSON.stringify; reverts to direct usage
apps/oxlint/src-js/package/define.ts Removes manual destructuring of multiple Object methods; reverts to direct usage

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@overlookmotel overlookmotel changed the base branch from 12-16-refactor_linter_plugins_simplify_binding_it.only_in_ruletester_ to graphite-base/16961 December 16, 2025 16:27
@overlookmotel overlookmotel force-pushed the 12-16-refactor_linter_plugins_convert_global_properties_to_vars_with_tsdown_plugin_instead_of_manually branch from 1abbb33 to 1351d60 Compare December 16, 2025 16:27
@overlookmotel overlookmotel changed the base branch from graphite-base/16961 to 12-16-refactor_linter_plugins_simplify_binding_it.only_in_ruletester_ December 16, 2025 16:27
@graphite-app graphite-app bot changed the base branch from 12-16-refactor_linter_plugins_simplify_binding_it.only_in_ruletester_ to graphite-base/16961 December 16, 2025 16:39
@graphite-app graphite-app bot force-pushed the 12-16-refactor_linter_plugins_convert_global_properties_to_vars_with_tsdown_plugin_instead_of_manually branch from 1351d60 to 1a6536f Compare December 16, 2025 16:46
@graphite-app graphite-app bot force-pushed the graphite-base/16961 branch from e88c42b to 0cbd88c Compare December 16, 2025 16:46
@graphite-app graphite-app bot changed the base branch from graphite-base/16961 to main December 16, 2025 16:46
@graphite-app graphite-app bot force-pushed the 12-16-refactor_linter_plugins_convert_global_properties_to_vars_with_tsdown_plugin_instead_of_manually branch from 1a6536f to d827a4a Compare December 16, 2025 16:46
Copy link
Contributor

@camc314 camc314 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice

@camc314 camc314 added the 0-merge Merge with Graphite Merge Queue label Dec 16, 2025
Copy link
Contributor

camc314 commented Dec 16, 2025

Merge activity

…wn plugin, instead of manually (#16961)

Previously we had a pattern of destructuring properties of global objects into top-level vars. e.g.:

```js
const { keys: ObjectKeys, hasOwn } = Object,
  { isArray } = Array;
```

Doing this is more performant, but it makes the code harder to read.

Instead, write code normally, and use a TSDown plugin to convert:

```js
const keys = Object.keys(obj);
```

to:

```js
import { ObjectKeys } from "../utils/globals.ts";
const keys = ObjectKeys(obj);
```

Defining all the destructured globals in a single file (`utils/globals.ts`) is advantageous for bundle size. If the TSDown plugin created top level `const ObjectKeys = Object.keys;` statements in each file, then you can end up with this in bundle as minifier doesn't de-duplicate:

```js
const ObjectKeys = Object.keys;
const ObjectKeys$1 = Object.keys;
const ObjectKeys$2 = Object.keys;
```

The globals we use have to be manually added to `utils/globals.ts`, but TSDown plugin warns when this needs to be done, and doesn't generate a broken build in the meantime.

This plugin is run in debug builds too, so that the tests will catch any bugs.
@graphite-app graphite-app bot force-pushed the 12-16-refactor_linter_plugins_convert_global_properties_to_vars_with_tsdown_plugin_instead_of_manually branch from d827a4a to da509be Compare December 16, 2025 17:33
@graphite-app graphite-app bot merged commit da509be into main Dec 16, 2025
18 checks passed
@graphite-app graphite-app bot deleted the 12-16-refactor_linter_plugins_convert_global_properties_to_vars_with_tsdown_plugin_instead_of_manually branch December 16, 2025 17:39
@graphite-app graphite-app bot removed the 0-merge Merge with Graphite Merge Queue label Dec 16, 2025
overlookmotel added a commit that referenced this pull request Dec 16, 2025
Follow-on after #16961. Just fix a typo in a comment.
qinyuhang pushed a commit to qinyuhang/oxc that referenced this pull request Jan 22, 2026
…wn plugin, instead of manually (oxc-project#16961)

Previously we had a pattern of destructuring properties of global objects into top-level vars. e.g.:

```js
const { keys: ObjectKeys, hasOwn } = Object,
  { isArray } = Array;
```

Doing this is more performant, but it makes the code harder to read.

Instead, write code normally, and use a TSDown plugin to convert:

```js
const keys = Object.keys(obj);
```

to:

```js
import { ObjectKeys } from "../utils/globals.ts";
const keys = ObjectKeys(obj);
```

Defining all the destructured globals in a single file (`utils/globals.ts`) is advantageous for bundle size. If the TSDown plugin created top level `const ObjectKeys = Object.keys;` statements in each file, then you can end up with this in bundle as minifier doesn't de-duplicate:

```js
const ObjectKeys = Object.keys;
const ObjectKeys$1 = Object.keys;
const ObjectKeys$2 = Object.keys;
```

The globals we use have to be manually added to `utils/globals.ts`, but TSDown plugin warns when this needs to be done, and doesn't generate a broken build in the meantime.

This plugin is run in debug builds too, so that the tests will catch any bugs.
qinyuhang pushed a commit to qinyuhang/oxc that referenced this pull request Jan 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-cli Area - CLI A-linter Area - Linter A-linter-plugins Area - Linter JS plugins C-cleanup Category - technical debt or refactoring. Solution not expected to change behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants