Fix exporting star when the export base is function
- Until now, only objects (no functions) were supported to be exported as a star.
- The reason is that
Object.createcalled on "function prototype" will not create callable function. - The clonning "function" before it's exported, will make it work.
- Adding default and other properties was kept as before.
It's not totally clear to me what problem this is solving because you didn't include any code demonstrating a problem. But if I had to guess, it looks like you're maybe trying to enable import * as fn from 'path' and then use fn as a function. Unfortunately that isn't how ECMAScript modules work. The ECMAScript standard says that fn here is a module namespace exotic object and is not callable.
I understand the desire to make this work because some older non-conformant JavaScript cross-compilers (e.g. TypeScript without the esModuleInterop setting enabled) do allow this to work. But JavaScript tooling is converging on the actual behavior in the ECMAScript specification and esbuild will not be deviating from the specification here. You will have to change your code instead. You should be able to do import fn from 'path' which will work in node, browsers, and esbuild.
Hi, thx for the quick reaction. Sorry that I didn't provide more info about the use case. But it's exactly what you've mentioned. I totally agree that since this is not a part of ECMA standard, it should not be merge as it is. However, sometimes, in the real world we have to live with a decision of our past us. This is the exact moment. We have a long-living project written in TypeScript compiled using webpack which is using this style of imports out of standards. I made this change and tried it on our company project and works great as a compatibility hack.
So what I propose is to allow configure esbuild to do this optionally based on options passed to esbuild.
Just one brainstormed proposal for a name: exportStarFunctionsCompatibility: boolean.
TL;DR Our project is currently using webpack configuration for bundling typescript, sass, images etc. This setup takes almost 2 minutes to complete the build from scratch (with no caches). Currently, I experimentally rewrote the configuration to esbuild and it takes under 5 seconds. WoW. This is really a must-have. The only blocker is this "feature" to perform everything with zero changes in code. If this "feature" is not possible, I'll be forced to maintain the fork with those few changes. I believe that more companies are dealing with the same problem.
P.S.: Could you point me where should I write E2E tests for this once we manage the final form?
@misak113 your use case sounds like it could be solved either with a plugin (to transform those import statements automatically) or a one time automated codemod to correct those cases in the source.
Hi @eyelidlessness,
Thank you for taking care of this PR. We're still using the forked version because I think it's correct to have an option to turn this on.
The reason is, that even though the official ES6+ standard doesn't contain the possibility to call an imported function using star *, it still works for transpilers like TypeScript or babel.
import * as fn from './some-function';
fn(); // works in typescript and babel transpiled code, works even in webpack bundled code, but NOT in esbuild bundled code.
I think that compatible behavior is more important than following the standards (if the standard is not broken, just extended).
I can check how to do this using plugin, but I'm not sure it's possible. This code of cloning imported object was hardcoded in golang string and couldn't be rewritten by plugins. If I'm not right, please could you point me out how to do it so?
Lets imagine that you are using the same code in bundled version for browser and also run your code in unit tests in node.js environments.
For the unit tests, you are probably not using esbuild but running something like jest.
So in this case, the unit tests are passing because all imports with star are callable. However, in production build for browser, it's not working. The inconsistent behavior is not ideal.