-
Notifications
You must be signed in to change notification settings - Fork 339
feat: use Uint8Array.fromBase64 if available
#437
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
jonkoops
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This new code path should also be covered by the existing tests, since Jest is used to fake browser testing I don't think the test suite is currently actually hitting the Uint8Array.fromBase64() in any scenario.
lib/index.ts
Outdated
| if ( | ||
| typeof Uint8Array !== "undefined" && | ||
| "fromBase64" in Uint8Array && | ||
| typeof Uint8Array.fromBase64 === "function" | ||
| ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should be no need to feature detect Uint8Array itself, as it is widely supported. Additionally, the type of the method is already known, so there should be no need to make any assertions about its type, checking for its presence should be sufficient:
| if ( | |
| typeof Uint8Array !== "undefined" && | |
| "fromBase64" in Uint8Array && | |
| typeof Uint8Array.fromBase64 === "function" | |
| ) { | |
| if (Uint8Array.fromBase64) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
type check and casting is needed because ESLint complains about it, maybe it's also because currently Uint8Array.fromBase64 is not supported yet in Node.js.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if this could be fixed by updating the TypeScript version. Currently, the proposal is Stage 3, but I believe that TypeScript only adds features that are Stage 4. Still, if the error is caused by TypeScript, perhaps it would be better to cast the type of Uint8Array.fromBase64 there, rather than using runtime checks?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like this is still missing from the latest TypeScript, see microsoft/TypeScript#61695
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did some testing, and we could accomplish this by creating lib/types.d.ts:
declare global {
interface FromBase64Options {
alphabet?: "base64" | "base64url";
lastChunkHandling?: "loose" | "strict" | "stop-before-partial";
}
interface Uint8ArrayConstructor {
fromBase64?(base64: string, options?: FromBase64Options): Uint8Array;
}
}
export {}; // Ensure this is treated as a moduleThis can then be included in lib/index.ts by adding the following on the top of the file:
/// <reference types="./types.d.ts" />Which then allows the code to be simplified to:
if (Uint8Array.fromBase64) {
const bytes = Uint8Array.fromBase64(str, { alphabet: "base64url" });
return new TextDecoder().decode(bytes);
}Note that I have made fromBase64() optional in the type definition, which reflects the fact that we consider it something that is not supported in all environments (yet). In order to prevent the reference comment from showing up in the compiled result, we also have to update tsconfig.build.json to strip them out:
{
"compilerOptions": {
"removeComments": true
}
}
lib/index.ts
Outdated
| "fromBase64" in Uint8Array && | ||
| typeof Uint8Array.fromBase64 === "function" | ||
| ) { | ||
| // Use native Uint8Array.fromBase64 if available |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are no comments in this entire file, and this code is pretty self-explanatory, this can likely be removed.
| // Use native Uint8Array.fromBase64 if available |
lib/index.ts
Outdated
| typeof Uint8Array.fromBase64 === "function" | ||
| ) { | ||
| // Use native Uint8Array.fromBase64 if available | ||
| const bytes = Uint8Array.fromBase64(str) as Uint8Array; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if this matches the intended behavior, or if any other options need to be passed to match the existing behavior.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Upon closer inspection, perhaps we can do an even earlier exit by doing the decode in base64UrlDecode()?
function base64UrlDecode(str: string) {
const bytes = Uint8Array.fromBase64(str, { alphabet: "base64url" });
return new TextDecoder().decode(bytes);
}Signed-off-by: Alfi Maulana <[email protected]>
2210fa6 to
8ce1d78
Compare
|
@jonkoops I can't add test because |
|
Yes, we need to find a way to run the tests in an environment where this API is supported. Perhaps it's time to reconsider Vitest (see #198), that would allow running the tests in actual browsers, all the major browsers have support for this API. @frederikprijck WDYT? |
By submitting a PR to this repository, you agree to the terms within the Auth0 Code of Conduct. Please see the contributing guidelines for how to create and submit a high-quality PR for this repo.
Description
Use
Uint8Array.fromBase64if available inb64DecodeUnicodefunction.References
Resolves #395.
Testing
Test not viable for now because
Uint8Array.fromBase64is not available in Node.jsChecklist