Open andersk opened 3 years ago
It is not safe to use this function to produce a file that is loaded into a global context (thus the name transpileModule
, not transpileFile
)
It doesn't matter whether the file is loaded into the global context. There is no context in which { var console = 'local'; } console.log('ok')
is a correct translation of { const console = 'local'; } console.log('ok')
.
(Note that, importantly, the console.log
statement is part of the code being translated. If it weren't, I would agree with you.)
You're right; I misread.
This seems expensive to fix and I'm sort of curious why no one else has noticed this.
@RyanCavanaugh i did spot that also i often reference to that in my issues like
Typescript needs to implement ast views else it will not scale. some functions or proxys that represent the ast out of diffrent view.
const ast = {
entry: {
module: ..
}
}
view representing the ast under ESM Conditions and also support inlining Scrpts typescript does know 2 kinds of js Scripts and Modules i am referencing to that. so it should get supported for modules as also eval to be driven from the same ast and show diffrent code hints based on diffrent views as JS is always intended to run in multiple environments often.
I think I found another instance of this while rolling out ts.transpileModule
in our code base.
export function foo() {
for (const name of ["from loop"]) {
// with `noLib: false`, the variable is called `var name_1`
// with `noLib: true`, the variable is called `var name`
console.log(name);
}
console.log(name); // when `noLib: true` is set, this incorrectly logs "from loop"
}
I wonder if this sort of thing could be flagged by isolatedModules
. Though I imagine it may still be expensive?
For what it's worth, I only noticed this as an emit difference. It does not actually cause an error in our code. And it's only an issue with target: es5
, so maybe not worth the effort.
This did now cause an issue for us. Here is the problematic piece of code:
export function updateUrl(newHash: string) {
if (newHash !== window.location.hash) {
window.history.replaceState(null, '', newHash);
for (const window of getChildWindows()) {
window.history.replaceState(null, '', newHash);
}
}
}
With target: es5
and noLib: true
, the window
inside the loop turns into a var window
. Therefore the window.location
access above fails.
I kinda feel like having an error on the window
loop variable under isolatedDeclarations
would be quite annoying.
I tried modifying isSymbolOfDeclarationWithCollidingName
in the type checker, so that block scoped names are always renamed. ~300 baselines need updates: https://github.com/microsoft/TypeScript/commit/9ffe9a061acb57c6a1ceb1ccd3717b36d1d1c61e. Is that feasible? Or is that too native or does that make the emit too expensive?
Bug Report
typescript.transpileModule
incorrectly compiles{ const console = 'local'; }
, which does not shadow the globalconsole
, to{ var console = 'local'; }
, which does.π Search Terms
transpileModule, const, let, var, rename, scope, shadow, global
(#14542 is possibly related, but that doesnβt show a miscompilation.)
π Version & Regression Information
transpileModule
β― Playground Link
(Playground does not expose
transpileModule
.)π» Code
π Actual behavior
π Expected behavior