Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/ripe-lamps-follow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@clerk/shared": patch
---

Use `globalThis` instead of `global` in `isomorphicBtoa` and `isomorphicAtob` for cross-platform compatibility
37 changes: 37 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,33 @@ const noNavigateUseClerk = {
},
};

const noGlobalObject = {
meta: {
type: 'problem',
docs: {
description: 'Disallow direct usage of `global.` - use `globalThis` instead for cross-platform compatibility',
recommended: false,
},
messages: {
noGlobal:
'Use `globalThis` instead of `global` for cross-platform compatibility. The `global` object is Node.js-specific and may not exist in browser or other environments.',
},
schema: [],
},
create(context) {
return {
MemberExpression(node) {
if (node.object.type === 'Identifier' && node.object.name === 'global') {
context.report({
node,
messageId: 'noGlobal',
});
}
},
};
},
};

const noUnstableMethods = {
meta: {
type: 'problem',
Expand Down Expand Up @@ -219,6 +246,7 @@ export default tseslint.config([
plugins: {
'custom-rules': {
rules: {
'no-global-object': noGlobalObject,
'no-unstable-methods': noUnstableMethods,
},
},
Expand Down Expand Up @@ -442,6 +470,7 @@ export default tseslint.config([
name: 'packages/shared',
files: ['packages/shared/src/**/*'],
rules: {
'custom-rules/no-global-object': 'error',
'no-restricted-imports': [
'error',
{
Expand All @@ -461,6 +490,14 @@ export default tseslint.config([
],
},
},
{
name: 'packages/shared - tests',
files: ['packages/shared/src/**/__tests__/**/*', 'packages/shared/src/**/*.test.{ts,tsx}'],
rules: {
// Allow `global.` in test files for mocking (e.g., global.window, global.console)
'custom-rules/no-global-object': 'off',
},
},
{
name: 'packages/expo-passkeys',
files: ['packages/expo-passkeys/src/**/*'],
Expand Down
6 changes: 3 additions & 3 deletions packages/shared/src/isomorphicAtob.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
/**
* A function that decodes a string of data which has been encoded using base-64 encoding.
* Uses `atob` if available, otherwise uses `Buffer` from `global`. If neither are available, returns the data as-is.
* Uses `atob` if available, otherwise uses `Buffer` from `globalThis`. If neither are available, returns the data as-is.
*/
export const isomorphicAtob = (data: string) => {
if (typeof atob !== 'undefined' && typeof atob === 'function') {
return atob(data);
} else if (typeof global !== 'undefined' && global.Buffer) {
return new global.Buffer(data, 'base64').toString();
} else if (typeof globalThis.Buffer !== 'undefined') {
return globalThis.Buffer.from(data, 'base64').toString();
}
return data;
};
4 changes: 2 additions & 2 deletions packages/shared/src/isomorphicBtoa.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
export const isomorphicBtoa = (data: string) => {
if (typeof btoa !== 'undefined' && typeof btoa === 'function') {
return btoa(data);
} else if (typeof global !== 'undefined' && global.Buffer) {
return new global.Buffer(data).toString('base64');
} else if (typeof globalThis.Buffer !== 'undefined') {
return globalThis.Buffer.from(data).toString('base64');
}
return data;
};
Loading