From e4ba03117b0ea730d5be976b80257959339948d3 Mon Sep 17 00:00:00 2001 From: Amr Gad Date: Sun, 21 Jul 2024 20:16:12 +0000 Subject: [PATCH] feat: add `es-set-tostringtag` feat: add `es-set-tostringtag` --- codemods/es-set-tostringtag/index.js | 61 +++++++++++++++++++ .../es-set-tostringtag/case-1/after.js | 31 ++++++++++ .../es-set-tostringtag/case-1/before.js | 26 ++++++++ .../es-set-tostringtag/case-1/result.js | 31 ++++++++++ 4 files changed, 149 insertions(+) create mode 100644 codemods/es-set-tostringtag/index.js create mode 100644 test/fixtures/es-set-tostringtag/case-1/after.js create mode 100644 test/fixtures/es-set-tostringtag/case-1/before.js create mode 100644 test/fixtures/es-set-tostringtag/case-1/result.js diff --git a/codemods/es-set-tostringtag/index.js b/codemods/es-set-tostringtag/index.js new file mode 100644 index 0000000..34355d1 --- /dev/null +++ b/codemods/es-set-tostringtag/index.js @@ -0,0 +1,61 @@ +import jscodeshift from 'jscodeshift'; +import { removeImport } from '../shared.js'; + +/** + * @typedef {import('../../types.js').Codemod} Codemod + * @typedef {import('../../types.js').CodemodOptions} CodemodOptions + */ + +/** + * @param {CodemodOptions} [options] + * @returns {Codemod} + */ +export default function (options) { + return { + name: 'es-set-tostringtag', + transform: ({ file }) => { + const j = jscodeshift; + const root = j(file.source); + let dirtyFlag = false; + + const { identifier } = removeImport('es-set-tostringtag', root, j); + + root + .find(j.CallExpression, { + callee: { + type: 'Identifier', + name: identifier, + }, + }) + .forEach((path) => { + const args = path.value.arguments; + const newExpression = j.callExpression( + j.memberExpression( + j.identifier('Object'), + j.identifier('defineProperty'), + ), + [ + args[0], + j.memberExpression( + j.identifier('Symbol'), + j.identifier('toStringTag'), + ), + j.objectExpression([ + j.property( + 'init', + j.identifier('configurable'), + j.booleanLiteral(true), + ), + // @ts-expect-error + j.property('init', j.identifier('value'), args[1]), + ]), + ], + ); + j(path).replaceWith(newExpression); + dirtyFlag = true; + }); + + return dirtyFlag ? root.toSource(options) : file.source; + }, + }; +} diff --git a/test/fixtures/es-set-tostringtag/case-1/after.js b/test/fixtures/es-set-tostringtag/case-1/after.js new file mode 100644 index 0000000..6577d95 --- /dev/null +++ b/test/fixtures/es-set-tostringtag/case-1/after.js @@ -0,0 +1,31 @@ +const assert = require("assert"); + +const obj = {}; +const sentinel = {}; + +Object.defineProperty(obj, Symbol.toStringTag, { + configurable: true, + value: sentinel, +}); + +assert.equal( + obj[Symbol.toStringTag], + sentinel, + "toStringTag property is as expected" +); + +assert.equal(String(obj), "[object Object]", "toStringTag works"); + +var tagged = {}; +tagged[Symbol.toStringTag] = "already tagged"; +assert.equal(String(tagged), "[object already tagged]", "toStringTag works"); + +Object.defineProperty(tagged, Symbol.toStringTag, { + configurable: true, + value: "new tag", +}); +assert.equal( + String(tagged), + "[object already tagged]", + "toStringTag is unchanged" +); diff --git a/test/fixtures/es-set-tostringtag/case-1/before.js b/test/fixtures/es-set-tostringtag/case-1/before.js new file mode 100644 index 0000000..f19cbcd --- /dev/null +++ b/test/fixtures/es-set-tostringtag/case-1/before.js @@ -0,0 +1,26 @@ +const assert = require("assert"); +const setToStringTag = require("es-set-tostringtag"); + +const obj = {}; +const sentinel = {}; + +setToStringTag(obj, sentinel); + +assert.equal( + obj[Symbol.toStringTag], + sentinel, + "toStringTag property is as expected" +); + +assert.equal(String(obj), "[object Object]", "toStringTag works"); + +var tagged = {}; +tagged[Symbol.toStringTag] = "already tagged"; +assert.equal(String(tagged), "[object already tagged]", "toStringTag works"); + +setToStringTag(tagged, "new tag"); +assert.equal( + String(tagged), + "[object already tagged]", + "toStringTag is unchanged" +); diff --git a/test/fixtures/es-set-tostringtag/case-1/result.js b/test/fixtures/es-set-tostringtag/case-1/result.js new file mode 100644 index 0000000..7175fc5 --- /dev/null +++ b/test/fixtures/es-set-tostringtag/case-1/result.js @@ -0,0 +1,31 @@ +const assert = require("assert"); + +const obj = {}; +const sentinel = {}; + +Object.defineProperty(obj, Symbol.toStringTag, { + configurable: true, + value: sentinel +}); + +assert.equal( + obj[Symbol.toStringTag], + sentinel, + "toStringTag property is as expected" +); + +assert.equal(String(obj), "[object Object]", "toStringTag works"); + +var tagged = {}; +tagged[Symbol.toStringTag] = "already tagged"; +assert.equal(String(tagged), "[object already tagged]", "toStringTag works"); + +Object.defineProperty(tagged, Symbol.toStringTag, { + configurable: true, + value: "new tag" +}); +assert.equal( + String(tagged), + "[object already tagged]", + "toStringTag is unchanged" +);