Refactor Object.{groupBy,hasOwn}() transform (#19218)
This commit is contained in:
1 parent
6ec71b6463
commit
c018e68c5e
7 files changed
+90
-79
No files matched your search
File renamed without changes.
@@ -0,0 +1,5 @@
|
|||||||
|
const hasOwn =
|
||||||
|
Object.hasOwn ??
|
||||||
|
Function.prototype.call.bind(Object.prototype.hasOwnProperty);
|
||||||
|
|
||||||
|
export default hasOwn;
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
import { fileURLToPath } from "node:url";
|
||||||
|
import { outdent } from "outdent";
|
||||||
|
import { createIdentifier, isIdentifier } from "./utilities.js";
|
||||||
|
|
||||||
|
/* Only works for function `Object.hasOwn()` and `Object.groupBy()` */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {import("@babel/types").Node} node
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
function isFunctionCall(node, { function: name, argumentsLength }) {
|
||||||
|
const [objectName, methodName] = name.split(".");
|
||||||
|
|
||||||
|
return (
|
||||||
|
node.type === "CallExpression" &&
|
||||||
|
!node.optional &&
|
||||||
|
node.arguments.length === argumentsLength &&
|
||||||
|
node.arguments.every(({ type }) => type !== "SpreadElement") &&
|
||||||
|
node.callee.type === "MemberExpression" &&
|
||||||
|
!node.callee.optional &&
|
||||||
|
!node.callee.computed &&
|
||||||
|
isIdentifier(node.callee.object, objectName) &&
|
||||||
|
isIdentifier(node.callee.property, methodName)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* `Object.hasOwn(foo, bar)` -> `__Object_hasOwn(foo, bar)`
|
||||||
|
*
|
||||||
|
* @param {import("@babel/types").CallExpression | import("@babel/types").OptionalCallExpression} node
|
||||||
|
* @returns {import("@babel/types").CallExpression}
|
||||||
|
*/
|
||||||
|
function transformFunctionCall(node, functionName) {
|
||||||
|
return {
|
||||||
|
...node,
|
||||||
|
callee: createIdentifier(functionName),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function createFunctionCallTransform({ function: name, argumentsLength }) {
|
||||||
|
const functionName = `__${name.replaceAll(".", "_")}`;
|
||||||
|
const fileName = `function-${name
|
||||||
|
.replace(/^[A-Z]/, (character) => character.toLowerCase())
|
||||||
|
.replaceAll(/\W/g, "-")
|
||||||
|
.replaceAll(/[A-Z]/g, (character) => `-${character.toLowerCase()}`)}.js`;
|
||||||
|
const functionImplementationUrl = new URL(
|
||||||
|
`../../shims/${fileName}`,
|
||||||
|
import.meta.url,
|
||||||
|
);
|
||||||
|
const functionImplementationPath = fileURLToPath(functionImplementationUrl);
|
||||||
|
|
||||||
|
return {
|
||||||
|
shouldSkip: (text, file) =>
|
||||||
|
!text.includes(`${name}(`) || file === functionImplementationPath,
|
||||||
|
test: (node) => isFunctionCall(node, { function: name, argumentsLength }),
|
||||||
|
transform: (node) => transformFunctionCall(node, functionName),
|
||||||
|
inject: outdent`
|
||||||
|
import ${functionName} from ${JSON.stringify(functionImplementationPath)};
|
||||||
|
`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default createFunctionCallTransform;
|
||||||
@@ -3,7 +3,7 @@ import { outdent } from "outdent";
|
|||||||
import { OPTIONAL_OBJECT } from "../../shims/shared.js";
|
import { OPTIONAL_OBJECT } from "../../shims/shared.js";
|
||||||
import { createIdentifier, isIdentifier } from "./utilities.js";
|
import { createIdentifier, isIdentifier } from "./utilities.js";
|
||||||
|
|
||||||
/* Doesn't work for optional call, computed property, and spread arguments */
|
/* Doesn't work for computed property, and spread arguments */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {import("@babel/types").Node} node
|
* @param {import("@babel/types").Node} node
|
||||||
|
|||||||
@@ -1,43 +1,8 @@
|
|||||||
import { fileURLToPath } from "node:url";
|
import createFunctionCallTransform from "./create-function-call-transform.js";
|
||||||
import { outdent } from "outdent";
|
|
||||||
import { createIdentifier, isIdentifier } from "./utilities.js";
|
|
||||||
|
|
||||||
/*
|
const transformObjectGroupBy = createFunctionCallTransform({
|
||||||
`Object.groupBy(items, callbackFn)` -> `__objectGroupBy(items, callbackFn)`
|
function: "Object.groupBy",
|
||||||
*/
|
argumentsLength: 2,
|
||||||
|
});
|
||||||
|
|
||||||
const functionName = "__objectGroupBy";
|
export default transformObjectGroupBy;
|
||||||
const functionImplementationPath = fileURLToPath(
|
|
||||||
new URL("../../shims/object-group-by.js", import.meta.url),
|
|
||||||
);
|
|
||||||
|
|
||||||
const transformObjectHasOwnCall = {
|
|
||||||
shouldSkip: (text) => !text.includes("Object.groupBy("),
|
|
||||||
/**
|
|
||||||
* @param {import("@babel/types").Node} node
|
|
||||||
* @returns {boolean}
|
|
||||||
*/
|
|
||||||
test: (node) =>
|
|
||||||
node.type === "CallExpression" &&
|
|
||||||
!node.optional &&
|
|
||||||
node.arguments.length === 2 &&
|
|
||||||
node.arguments.every(({ type }) => type !== "SpreadElement") &&
|
|
||||||
node.callee.type === "MemberExpression" &&
|
|
||||||
!node.callee.optional &&
|
|
||||||
!node.callee.computed &&
|
|
||||||
isIdentifier(node.callee.object, "Object") &&
|
|
||||||
isIdentifier(node.callee.property, "groupBy"),
|
|
||||||
/**
|
|
||||||
* @param {import("@babel/types").CallExpression} node
|
|
||||||
* @returns {import("@babel/types").CallExpression}
|
|
||||||
*/
|
|
||||||
transform: (node) => ({
|
|
||||||
...node,
|
|
||||||
callee: createIdentifier(functionName),
|
|
||||||
}),
|
|
||||||
inject: outdent`
|
|
||||||
import ${functionName} from ${JSON.stringify(functionImplementationPath)};
|
|
||||||
`,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default transformObjectHasOwnCall;
|
|
||||||
@@ -1,33 +1,8 @@
|
|||||||
import { createMemberExpression, isIdentifier } from "./utilities.js";
|
import createFunctionCallTransform from "./create-function-call-transform.js";
|
||||||
|
|
||||||
/*
|
const transformObjectHasOwn = createFunctionCallTransform({
|
||||||
`Object.hasOwn(foo, "bar")` -> `Object.prototype.hasOwnProperty.call(foo, "bar")`
|
function: "Object.hasOwn",
|
||||||
*/
|
argumentsLength: 2,
|
||||||
|
});
|
||||||
|
|
||||||
const transformObjectHasOwnCall = {
|
export default transformObjectHasOwn;
|
||||||
shouldSkip: (text) => !text.includes("Object.hasOwn("),
|
|
||||||
/**
|
|
||||||
* @param {import("@babel/types").Node} node
|
|
||||||
* @returns {boolean}
|
|
||||||
*/
|
|
||||||
test: (node) =>
|
|
||||||
node.type === "CallExpression" &&
|
|
||||||
!node.optional &&
|
|
||||||
node.arguments.length === 2 &&
|
|
||||||
node.arguments.every(({ type }) => type !== "SpreadElement") &&
|
|
||||||
node.callee.type === "MemberExpression" &&
|
|
||||||
!node.callee.optional &&
|
|
||||||
!node.callee.computed &&
|
|
||||||
isIdentifier(node.callee.object, "Object") &&
|
|
||||||
isIdentifier(node.callee.property, "hasOwn"),
|
|
||||||
/**
|
|
||||||
* @param {import("@babel/types").CallExpression} node
|
|
||||||
* @returns {import("@babel/types").CallExpression}
|
|
||||||
*/
|
|
||||||
transform: (node) => ({
|
|
||||||
...node,
|
|
||||||
callee: createMemberExpression("Object.prototype.hasOwnProperty.call"),
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
|
|
||||||
export default transformObjectHasOwnCall;
|
|
||||||
@@ -28,21 +28,23 @@ const transform = (code) =>
|
|||||||
) +
|
) +
|
||||||
"\n";
|
"\n";
|
||||||
|
|
||||||
test("Object.hasOwn", () => {
|
test("Object.hasOwn()", () => {
|
||||||
expect(transform("Object.hasOwn(foo, bar)")).toMatchInlineSnapshot(`
|
expect(transform("Object.hasOwn(foo, bar)")).toMatchInlineSnapshot(`
|
||||||
"
|
"
|
||||||
Object.prototype.hasOwnProperty.call(foo, bar);
|
import __Object_hasOwn from "<SHIMS>/function-object-has-own.js";
|
||||||
|
|
||||||
|
__Object_hasOwn(foo, bar);
|
||||||
"
|
"
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Object.groupBy", () => {
|
test("Object.groupBy()", () => {
|
||||||
expect(transform("const {} = Object.groupBy(foo, bar)"))
|
expect(transform("const {} = Object.groupBy(foo, bar)"))
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
"
|
"
|
||||||
import __objectGroupBy from "<SHIMS>/object-group-by.js";
|
import __Object_groupBy from "<SHIMS>/function-object-group-by.js";
|
||||||
|
|
||||||
const {} = __objectGroupBy(foo, bar);
|
const {} = __Object_groupBy(foo, bar);
|
||||||
"
|
"
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
@@ -272,6 +274,7 @@ test("All", () => {
|
|||||||
`),
|
`),
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
"
|
"
|
||||||
|
import __Object_hasOwn from "<SHIMS>/function-object-has-own.js";
|
||||||
import __replaceAll from "<SHIMS>/method-replace-all.js";
|
import __replaceAll from "<SHIMS>/method-replace-all.js";
|
||||||
import __at from "<SHIMS>/method-at.js";
|
import __at from "<SHIMS>/method-at.js";
|
||||||
import __findLast from "<SHIMS>/method-find-last.js";
|
import __findLast from "<SHIMS>/method-find-last.js";
|
||||||
@@ -284,7 +287,7 @@ test("All", () => {
|
|||||||
align,
|
align,
|
||||||
line
|
line
|
||||||
} = __doc_builders;
|
} = __doc_builders;
|
||||||
if (Object.prototype.hasOwnProperty.call(foo, bar)) {
|
if (__Object_hasOwn(foo, bar)) {
|
||||||
const a = __replaceAll(/* OPTIONAL_OBJECT: true */1, __at(/* OPTIONAL_OBJECT: true */1, foo, -1), /bar/, ""),
|
const a = __replaceAll(/* OPTIONAL_OBJECT: true */1, __at(/* OPTIONAL_OBJECT: true */1, foo, -1), /bar/, ""),
|
||||||
b = __findLast(/* OPTIONAL_OBJECT: true */1, bar, () => true),
|
b = __findLast(/* OPTIONAL_OBJECT: true */1, bar, () => true),
|
||||||
c = __findLastIndex(/* OPTIONAL_OBJECT: false */0, foo, callback);
|
c = __findLastIndex(/* OPTIONAL_OBJECT: false */0, foo, callback);
|
||||||
|
|||||||
Reference in new issue
Block a user