Skip to content

Commit

Permalink
Add codemod for globalthis
Browse files Browse the repository at this point in the history
  • Loading branch information
filipre committed Aug 2, 2024
1 parent 8ddb3f7 commit fc60629
Show file tree
Hide file tree
Showing 18 changed files with 161 additions and 9 deletions.
37 changes: 37 additions & 0 deletions codemods/globalthis/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
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: 'globalthis',
transform: ({ file }) => {
const j = jscodeshift;
const root = j(file.source);
const identifier1 = removeImport('globalthis', root, j).identifier;
const identifier2 = removeImport(
'globalthis/polyfill',
root,
j,
).identifier;
const identifier3 = removeImport('globalthis/shim', root, j).identifier;
const identifier = identifier1 || identifier2 || identifier3;

if (identifier) {
root
.find(j.Identifier, { name: identifier })
.replaceWith(j.identifier('globalThis'));
}

return root.toSource({ quote: 'single' });
},
};
}
109 changes: 101 additions & 8 deletions codemods/shared.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,91 @@ export function removeImport(name, root, j) {
},
});

// Require statements with call expressions like `var globalThis = require('globalthis')()`
const requireCallExpression = root.find(j.VariableDeclarator, {
init: {
callee: {
type: 'CallExpression',
callee: {
name: 'require',
},
arguments: [
{
value: name,
},
],
},
},
});

// Same as above without variable declaration like `require('globalthis')()`
const sideEffectRequireCallExpression = root.find(j.ExpressionStatement, {
expression: {
callee: {
type: 'CallExpression',
callee: {
name: 'require',
},
arguments: [
{
value: name,
},
],
},
},
});

// Require chained call expressions like `var globalThis = require('globalthis').shim()`
const requireMethodCallExpression = root.find(j.VariableDeclarator, {
init: {
type: 'CallExpression',
callee: {
type: 'MemberExpression',
object: {
type: 'CallExpression',
callee: {
name: 'require',
},
arguments: [
{
value: name,
},
],
},
property: {
type: 'Identifier',
},
},
},
});

// Same as above without variable declaration like `require('globalthis').shim()`
const sideEffectRequireMethodCallExpression = root.find(
j.ExpressionStatement,
{
expression: {
type: 'CallExpression',
callee: {
type: 'MemberExpression',
object: {
type: 'CallExpression',
callee: {
name: 'require',
},
arguments: [
{
value: name,
},
],
},
property: {
type: 'Identifier',
},
},
},
},
);

// Require statements without declarations like `Object.is = require("object-is");`
const requireAssignment = root.find(j.AssignmentExpression, {
operator: '=',
Expand Down Expand Up @@ -64,17 +149,25 @@ export function removeImport(name, root, j) {

// Return the identifier name, e.g. 'fn' in `import { fn } from 'is-boolean-object'`
// or `var fn = require('is-boolean-object')`
const identifier =
importDeclaration.paths().length > 0
? importDeclaration.get().node.specifiers[0].local.name
: requireDeclaration.paths().length > 0
? requireDeclaration.find(j.Identifier).get().node.name
: requireAssignment.paths().length > 0
? requireAssignment.find(j.Identifier).get().node.name
: null;
let identifier = null;
if (importDeclaration.paths().length > 0) {
identifier = importDeclaration.get().node.specifiers[0].local.name;
} else if (requireDeclaration.paths().length > 0) {
identifier = requireDeclaration.find(j.Identifier).get().node.name;
} else if (requireCallExpression.paths().length > 0) {
identifier = requireCallExpression.find(j.Identifier).get().node.name;
} else if (requireMethodCallExpression.paths().length > 0) {
identifier = requireMethodCallExpression.find(j.Identifier).get().node.name;
} else if (requireAssignment.paths().length > 0) {
identifier = requireAssignment.find(j.Identifier).get().node.name;
}

importDeclaration.remove();
requireDeclaration.remove();
requireCallExpression.remove();
sideEffectRequireCallExpression.remove();
requireMethodCallExpression.remove();
sideEffectRequireMethodCallExpression.remove();
requireAssignment.remove();
sideEffectRequireExpression.remove();

Expand Down
4 changes: 3 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ import functionBind from './codemods/function-bind/index.js';
import functionPrototypeName from './codemods/function.prototype.name/index.js';
import functionsHaveNames from './codemods/functions-have-names/index.js';
import getSymbolDescription from './codemods/get-symbol-description/index.js';
import globalthis from './codemods/globalthis/index.js';
import gopd from './codemods/gopd/index.js';
import has from './codemods/has/index.js';
import hasOwnProp from './codemods/has-own-prop/index.js';
Expand Down Expand Up @@ -210,6 +211,7 @@ export const codemods = {
"function.prototype.name": functionPrototypeName,
"functions-have-names": functionsHaveNames,
"get-symbol-description": getSymbolDescription,
"globalthis": globalthis,
"gopd": gopd,
"has": has,
"has-own-prop": hasOwnProp,
Expand Down Expand Up @@ -300,4 +302,4 @@ export const codemods = {
"typed-array-length": typedArrayLength,
"typedarray.prototype.slice": typedarrayPrototypeSlice,
"xtend": xtend,
};
};
1 change: 1 addition & 0 deletions test/fixtures/globalthis/case-1/after.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
globalThis.a = 42;
2 changes: 2 additions & 0 deletions test/fixtures/globalthis/case-1/before.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
var globalThis = require('globalthis')();
globalThis.a = 42;
1 change: 1 addition & 0 deletions test/fixtures/globalthis/case-1/result.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
globalThis.a = 42;
1 change: 1 addition & 0 deletions test/fixtures/globalthis/case-2/after.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
globalThis.a = 42;
2 changes: 2 additions & 0 deletions test/fixtures/globalthis/case-2/before.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
var globalThis = require('globalthis/polyfill')();
globalThis.a = 42;
1 change: 1 addition & 0 deletions test/fixtures/globalthis/case-2/result.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
globalThis.a = 42;
1 change: 1 addition & 0 deletions test/fixtures/globalthis/case-3/after.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
globalThis.a = 42;
2 changes: 2 additions & 0 deletions test/fixtures/globalthis/case-3/before.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
var newGlobalThis = require('globalthis')();
newGlobalThis.a = 42;
1 change: 1 addition & 0 deletions test/fixtures/globalthis/case-3/result.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
globalThis.a = 42;
1 change: 1 addition & 0 deletions test/fixtures/globalthis/case-4/after.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
globalThis.a = 42;
2 changes: 2 additions & 0 deletions test/fixtures/globalthis/case-4/before.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
var shimmedGlobal = require('globalthis').shim();
shimmedGlobal.a = 42;
1 change: 1 addition & 0 deletions test/fixtures/globalthis/case-4/result.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
globalThis.a = 42;
1 change: 1 addition & 0 deletions test/fixtures/globalthis/case-5/after.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
globalThis.a = 42;
2 changes: 2 additions & 0 deletions test/fixtures/globalthis/case-5/before.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
var shimmedGlobal = require('globalthis/shim')();
shimmedGlobal.a = 42;
1 change: 1 addition & 0 deletions test/fixtures/globalthis/case-5/result.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
globalThis.a = 42;

0 comments on commit fc60629

Please sign in to comment.