-
Notifications
You must be signed in to change notification settings - Fork 844
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
[sdk] change transpile target to ~~ES2020~~ ES2022 #5393
Comments
From slack discussion: The semantic-conventions package is going to go back/remain compatible with node IIUC, the current target (from tsconfig.base.json) is |
As requested by @pichlermarc, moving my discussion here. I was suggest that we want to at least consider ES2022 for SDK 2.x, because it supports top-level await (TLA) – it's supported since Node 14 and in the included in browsers baseline (widely available) for quite some time (but consumers are probably using a bundler anyway, which has also supported TLA for a long time). It would be quite handy to have, and in some cases, probably necessary to migrate form top-level require statements. As a concrete example, #5298 was looking at a module like this: import * as process from 'process';
let getMachineId: () => Promise<string>;
switch (process.platform) {
case 'darwin':
({ getMachineId } = require('./getMachineId-darwin'));
break;
case 'linux':
({ getMachineId } = require('./getMachineId-linux'));
break;
case 'freebsd':
({ getMachineId } = require('./getMachineId-bsd'));
break;
case 'win32':
({ getMachineId } = require('./getMachineId-win'));
break;
default:
({ getMachineId } = require('./getMachineId-unsupported'));
}
export { getMachineId }; This is problematic as, the use of We can replace the import * as process from 'process';
let getMachineId: () => Promise<string>;
switch (process.platform) {
case 'darwin':
({ getMachineId } = await import('./getMachineId-darwin.js'));
break;
case 'linux':
({ getMachineId } = await import('./getMachineId-linux.js'));
break;
case 'freebsd':
({ getMachineId } = await import('./getMachineId-bsd.js'));
break;
case 'win32':
({ getMachineId } = await import('./getMachineId-win.js'));
break;
default:
({ getMachineId } = await import('./getMachineId-unsupported.js'));
}
export { getMachineId }; Without TLA, we are kind of stuck. In this particular instance, since the function happens to be async, we can work with it: import * as process from 'process';
let _getMachineId: () => Promise<string> | null = null;
export async function getMachineId(): Promise<string> {
if (_getMachineId === null) {
switch (process.platform) {
case 'darwin':
_getMachineId = await import('./getMachineId-darwin.js')).getMachineId;
break;
case 'linux':
_getMachineId = await import('./getMachineId-linux.js')).getMachineId;
break;
case 'freebsd':
_getMachineId = await import('./getMachineId-bsd.js')).getMachineId;
break;
case 'win32':
_getMachineId = await import('./getMachineId-win.js')).getMachineId;
break;
default:
_getMachineId = await import('./getMachineId-unsupported.js')).getMachineId;
}
}
return _getMachineId();
}
export { getMachineId }; This changes the timing and semantics slightly, perhaps that's acceptable in this case, but I can see other places where this would be an important tool to have. In general, wherever we are using
Sometimes we may be able to get away with pushing the async operation deeper down/to be more lazy, but a lot of times it forces the rest of the code in that file/module to work around that, whereas TLA lets you deal with it upfront and write the rest of the code the same way as if it was a synchronous There are some other nice-to-have language and library features (I think Just wanted to highlight that and make sure it was considered. |
don't use TLA, it may break require es module in cjs |
@xiaoxiangmoe can you expand on that or provide an example? We're talking about the minimum supported syntax here, and IIUC we'd be talking about requiring es2022 as a minimum version supported by the runtime, which should allow us to use TLA. I guess you're advocating for keeping our minimum version lower. According to node.green ES2022 support is 97% complete in all versions of node To me it seems to boil down to this:
This means we have to make a choice between supporting existing CJS users and supporting ESM users. There are also middle-ground options which would be to separately publish es2022 packages for ESM users which use top-level await. Let's talk about this at the SIG meeting tomorrow |
My speculation is that they are pointing out/referring to the fact that:
I don't necessarily disagree that under today's convoluted Node inter-op rules, whether a ESM module is asynchronous is a visible feature to CJS consumers (but not to ESM consumers), so...
However, consider:
I don't disagree that the inter-op stuff needs to be tread carefully, but we can figure out those details when the time comes. At this point, given the limited timeframe we have for the research and analysis, I think the main thing to focus on is whether there is a very good reason we want to stay at ES2020 (is someone asking for it?). I get that from a usage/support perspective, supporting an older format = more conservative, thus seems like a better default. But on the maintainability side, ES2022 gives us some additional tools that could become important at some point during 2.x as we navigate the modules transition, so IMO it is more conservative to have them in case we need them – we don't have to use them today. |
I support raising it to es2022 or esnext, but we should ban TLA for node's cjs compatibility, as @chancancode 's statement. |
Decision from SIG meeting today: we will change to ES2022 but will disallow TLA in linting rules in order to avoid breaking existing CJS users. Users which need to target a lower version of ECMAScript will need to transpile code to a lower version. |
I will allocate some time to work on it :) |
IIUC we now should compile with 2 different targets:
Then I guess we should review the build/release process since the compilation task for that workflow is using
I think tsconfig references was made to speed up the compile process so I'll try 1st approach. |
Description
We've updated our guidelines to state that we only support ES2020 starting with 2.0. To avoid confusion when we release, we should actually transpile to ES2020 right away.
This issue is considered done when
ES2020ES2022@opentelemetry/api
) has been held back to the current state to avoid breaking in a minor version@opentelemetry/semantic-conventions
) is held back to current state to avoid breaking in a minor version.Additional context:
Follows up on:
The text was updated successfully, but these errors were encountered: