Skip to content

Commit a187333

Browse files
committed
perf(linter/plugins): reuse descriptor objects for Object.defineProperty calls (#20505)
Small optimization. Don't create temporary objects repeatedly just to pass props to `Object.defineProperty`. Re-use a single object and reuse it instead.
1 parent 5984a66 commit a187333

File tree

2 files changed

+21
-5
lines changed

2 files changed

+21
-5
lines changed

apps/oxlint/src-js/plugins/lint.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ export const buffers: (BufferWithArrays | null)[] = [];
3434
// Array of `after` hooks to run after traversal. This array reused for every file.
3535
const afterHooks: AfterHook[] = [];
3636

37+
// Reusable property descriptor for updating `options` value on rule context objects.
38+
// `value` is updated before each call. Other attributes are omitted to retain existing values.
39+
const OPTIONS_DESCRIPTOR: PropertyDescriptor = { value: null };
40+
3741
/**
3842
* Lint a file.
3943
*
@@ -200,10 +204,11 @@ export function lintFileImpl(
200204
debugAssert(optionsId < allOptions.length, "Options ID out of bounds");
201205

202206
// If the rule has no user-provided options, use the plugin-provided default
203-
// options (which falls back to `DEFAULT_OPTIONS`)
204-
Object.defineProperty(ruleDetails.context, "options", {
205-
value: optionsId === DEFAULT_OPTIONS_ID ? ruleDetails.defaultOptions : allOptions[optionsId],
206-
});
207+
// options (which falls back to `DEFAULT_OPTIONS`).
208+
// Reuse `OPTIONS_DESCRIPTOR` object to avoid unnecessarily creating a temporary object each time.
209+
OPTIONS_DESCRIPTOR.value =
210+
optionsId === DEFAULT_OPTIONS_ID ? ruleDetails.defaultOptions : allOptions[optionsId];
211+
Object.defineProperty(ruleDetails.context, "options", OPTIONS_DESCRIPTOR);
207212

208213
let { visitor } = ruleDetails;
209214
if (visitor === null) {

apps/oxlint/src-js/plugins/location.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,11 +299,22 @@ export function getNodeLoc(node: Node): Location {
299299
//
300300
// We also don't make it configurable, because deleting it wouldn't make `node.loc` evaluate to `undefined`,
301301
// because the access would fall through to the getter on the prototype.
302-
Object.defineProperty(node, "loc", { value: loc, writable: true });
302+
//
303+
// Reuse `LOC_DESCRIPTOR` object to avoid unnecessarily creating a temporary object each time.
304+
LOC_DESCRIPTOR.value = loc;
305+
Object.defineProperty(node, "loc", LOC_DESCRIPTOR);
303306

304307
return loc;
305308
}
306309

310+
// Reusable property descriptor for `Object.defineProperty` in `getNodeLoc`.
311+
const LOC_DESCRIPTOR: PropertyDescriptor = {
312+
value: null,
313+
writable: true,
314+
enumerable: false,
315+
configurable: false,
316+
};
317+
307318
/**
308319
* Compute a `Location` from `start` and `end` source offsets.
309320
*

0 commit comments

Comments
 (0)