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 { 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
|
||||
|
||||
@@ -1,43 +1,8 @@
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { outdent } from "outdent";
|
||||
import { createIdentifier, isIdentifier } from "./utilities.js";
|
||||
import createFunctionCallTransform from "./create-function-call-transform.js";
|
||||
|
||||
/*
|
||||
`Object.groupBy(items, callbackFn)` -> `__objectGroupBy(items, callbackFn)`
|
||||
*/
|
||||
const transformObjectGroupBy = createFunctionCallTransform({
|
||||
function: "Object.groupBy",
|
||||
argumentsLength: 2,
|
||||
});
|
||||
|
||||
const functionName = "__objectGroupBy";
|
||||
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;
|
||||
export default transformObjectGroupBy;
|
||||
@@ -1,33 +1,8 @@
|
||||
import { createMemberExpression, isIdentifier } from "./utilities.js";
|
||||
import createFunctionCallTransform from "./create-function-call-transform.js";
|
||||
|
||||
/*
|
||||
`Object.hasOwn(foo, "bar")` -> `Object.prototype.hasOwnProperty.call(foo, "bar")`
|
||||
*/
|
||||
const transformObjectHasOwn = createFunctionCallTransform({
|
||||
function: "Object.hasOwn",
|
||||
argumentsLength: 2,
|
||||
});
|
||||
|
||||
const transformObjectHasOwnCall = {
|
||||
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;
|
||||
export default transformObjectHasOwn;
|
||||
@@ -28,21 +28,23 @@ const transform = (code) =>
|
||||
) +
|
||||
"\n";
|
||||
|
||||
test("Object.hasOwn", () => {
|
||||
test("Object.hasOwn()", () => {
|
||||
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)"))
|
||||
.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(`
|
||||
"
|
||||
import __Object_hasOwn from "<SHIMS>/function-object-has-own.js";
|
||||
import __replaceAll from "<SHIMS>/method-replace-all.js";
|
||||
import __at from "<SHIMS>/method-at.js";
|
||||
import __findLast from "<SHIMS>/method-find-last.js";
|
||||
@@ -284,7 +287,7 @@ test("All", () => {
|
||||
align,
|
||||
line
|
||||
} = __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/, ""),
|
||||
b = __findLast(/* OPTIONAL_OBJECT: true */1, bar, () => true),
|
||||
c = __findLastIndex(/* OPTIONAL_OBJECT: false */0, foo, callback);
|
||||
|
||||
Reference in new issue
Block a user