Skip to content
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

fix: Add workaround for OpenTelemetry/Zone.js #1719

Merged
merged 4 commits into from
Feb 18, 2025
Merged

fix: Add workaround for OpenTelemetry/Zone.js #1719

merged 4 commits into from
Feb 18, 2025

Conversation

amannn
Copy link
Owner

@amannn amannn commented Feb 17, 2025

Fixes #1711

Copy link

vercel bot commented Feb 17, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
next-intl-docs ✅ Ready (Inspect) Visit Preview 💬 Add feedback Feb 17, 2025 0:51am
next-intl-example-app-router ✅ Ready (Inspect) Visit Preview 💬 Add feedback Feb 17, 2025 0:51am
next-intl-example-app-router-without-i18n-routing ✅ Ready (Inspect) Visit Preview 💬 Add feedback Feb 17, 2025 0:51am

value: Value | Promise<Value>
): value is Promise<Value> {
// https://github.com/amannn/next-intl/issues/1711
return typeof (value as any).then === 'function';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about adding an additional check of the well-known symbol [Symbol.toStringTag] prototype?
Zone.js returns 'Promise', the same as the native Promise. https://github.com/angular/zone.js/blob/master/lib/common/promise.ts#L364

Promise.prototype[Symbol.toStringTag] === 'Promise'
zonePromise[Symbol.toStringTag] === 'Promise'

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean in addition to then === 'function'? Hmm, it's an interesting point, I honestly didn't know about Symbol.toStringTag.

Based on the MDN docs on Symbol.toStringTag it seems like this would be safe to use on promises. However, I'm a bit reluctant as I've already encountered a range of weird cases where Next.js' overrides internals, patched something here and there, and sometimes things go off the rails.

Is there a specific use case where you think the current check might not work well?

As an additional note on the implementation, I put the focus on providing a minimal implementation that minifies as much as possible while being reliable. I took the is-promise implementation as inspiration and removed some checks that are not necessary for the ways isPromise is currently used in this codebase.

What do you think?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @amannn, first of all thanks for the quick support 😄, I tested locally with version 0.0.0-canary-84fe6d0 and it works as expected!

as @SalmenBejaoui suggest, probably Promise.prototype[Symbol.toStringTag] === 'Promise' could be useful, at least it should also handle the native promise override case.

about the zonePromise[Symbol.toStringTag] === 'Promise' could be a bit unsafe? it seems only zonejs related which isn't used on this library.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, that's great to hear!

What I'm trying to understand is how the additional usage of Symbol.toStringTag is benefical? Is there a case where the current check for then === 'function' is not sufficient?

Please also see:

My main motivation is to have something that minifies as much as possible. Additionally, for the way isPromise is used in this codebase we can take some shortcuts in comparison to the is-promise package npm.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh ok, now with the Promise spec I got it, so yes, I think then === 'function' is sufficient to cover the promise case (I don't think that someone besides overwriting the global promise object, also edits the signature of the functions, hopefully...).
looks good like this to me.

Copy link
Contributor

@SalmenBejaoui SalmenBejaoui Feb 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@amannn the thenable check is sufficient and follows A+ spec. Promise.prototype[Symbol.toStringTag] could be too strict.

I was thinking more widely, but it's not the case for next-intl.

isPromise({ then: () => {} }); // true

LGTM 👍

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, sounds good! Many thanks for your research on this and for providing feedback, I really appreciate it and I'm sure other Next.js users will benefit from this too!

@amannn amannn merged commit 1cac9a6 into main Feb 18, 2025
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Server Translation not working if client use Grafana Faro
3 participants