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

SyntaxError: Indirectly exported binding name 'AnyArena' is not found. #5426

Closed
dpeek opened this issue Sep 15, 2023 · 12 comments · Fixed by #7259
Closed

SyntaxError: Indirectly exported binding name 'AnyArena' is not found. #5426

dpeek opened this issue Sep 15, 2023 · 12 comments · Fixed by #7259
Labels
bug Something isn't working transpiler parser || printer typescript Something for TypeScript

Comments

@dpeek
Copy link

dpeek commented Sep 15, 2023

What version of Bun is running?

1.0.1+31aec4ebe325982fc0ef27498984b0ad9969162b

What platform is your computer?

Darwin 22.3.0 arm64 arm

What steps can reproduce the bug?

// test.ts
const capnp = require('capnp-ts');
console.log(capnp);
bun test.ts

What is the expected behavior?

No error

What do you see instead?

SyntaxError: Indirectly exported binding name 'AnyArena' is not found.
      at loadCJS2ESM (:1:20)
      at requireESM (:1:20)
      at require (:1:20)
      at .../node_modules/capnp-ts/src/index.js:7:4
      at globalThis (.../node_modules/capnp-ts/src/index.js:52:106)
      at require (:1:20)
      at /Users/dpeek/code/estii/packages/api/test.ts:1:6
      at globalThis (.../packages/api/test.ts:2:17)

Additional information

Seems related to #1852, although I was unable to create a minimal repro.

Digging into the library, AnyArena is exported as a type that is a union of two classes exported from other modules.

import { MultiSegmentArena } from "./multi-segment-arena";
import { SingleSegmentArena } from "./single-segment-arena";

export type AnyArena = MultiSegmentArena | SingleSegmentArena;

See https://github.com/jdiaz5513/capnp-ts/blob/108850ece76b33755d552f78eac736055ec8f1b4/packages/capnp-ts/src/serialization/arena/any-arena.ts

@dpeek dpeek added the bug Something isn't working label Sep 15, 2023
@Electroid Electroid added the transpiler parser || printer label Sep 15, 2023
@zlooun
Copy link

zlooun commented Sep 17, 2023

Same ussue

@M-jerez
Copy link

M-jerez commented Sep 17, 2023

Similar error here 🙋‍♂️

Bellow re-export does not work

export {SerializedTypes} from '@mionkit/runtype';

neither re-export as type only

export type {SerializedTypes} from '@mionkit/runtype';

Workaround:

import {SerializedTypes} from '@mionkit/runtype';
export type {SerializedTypes};

similar to #74

@dpeek
Copy link
Author

dpeek commented Sep 18, 2023

I did a bit more digging into this today. It seems like the issue stems from capnp-ts shipping TypeScript source along side compiled JS and type definitions.

There's no mention of AnyArena in the JS source (it's a type export) which means bun is parsing the TS source instead.

The initial require('capnp-ts') loads node_modules/capnp-ts/src/index.js which does require("./serialization")

Strangely, this resolves to node_modules/capnp-ts/src/serialization/index.ts instead of node_modules/capnp-ts/src/serialization/index.js

I had a thought that perhaps allowImportingTsExtensions in tsconfig was preferring TS to JS in node_modules, but disabling that does not fix the issue.

@dpeek
Copy link
Author

dpeek commented Sep 18, 2023

https://github.com/oven-sh/bun/blob/main/src/resolver/resolver.zig#L3607 👀

I guess this is intended behaviour?

@dpeek
Copy link
Author

dpeek commented Sep 18, 2023

I think I understand now (and should have just listened to the referenced issue). The transpiler currently doesn't know the type-ness of re-exported values, hence you need export type for now. On the plus side I learnt a lot about the bun code base :)

@zlooun
Copy link

zlooun commented Sep 27, 2023

I think I understand now (and should have just listened to the referenced issue). The transpiler currently doesn't know the type-ness of re-exported values, hence you need export type for now. On the plus side I learnt a lot about the bun code base :)

But this is workaround. This needs fixing.

@AnActualEmerald
Copy link

Am I correct in thinking that if this bug is being caused by importing a 3rd party module that there's no workaround at the moment?

@mkosir
Copy link

mkosir commented Oct 9, 2023

Thanks @M-jerez , your workaround works!

@samuelslva-jlfs
Copy link

Had the same issue, if anything TS itself is dropping the ambiguity between type and non-type modules, cant blame bun for not handling the craziness.

Just use EsLint rule or the TSC compiler option and be happy.

If you're curious why this happens I'm pretty sure its getting confused in compiling back to JS and stripping the types, trying to import something that doesn’t exist anymore because it has been stripped but the import has lost the context that is is a type import and it doesn’t exist anymore something something, the TSC rule has more context on why.

@Jarred-Sumner
Copy link
Collaborator

This is happening because Bun is transpiling the .ts files in capnp-ts.

Specifically: AnyArena is a type definition and it is very difficult for Bun to figure out it is a type and not a runtime value, since it is in a different file and Bun doesn't bundle at runtime.

+ export {  type  AnyArena } from "./any-arena";
- export { AnyArena } from "./any-arena";

The fix is any of:

  • Change JavaScriptCore's ES Module implementation to optionally ignore unknown indirect export names from TypeScript files. This would make it always work, but diverges from standards a little (probably not a breaking change)
  • Track exported types at runtime and insert an undefined value for each type export (an observable difference)
  • Disable the behavior from Module imports need to recognize/ignore the file extension microsoft/TypeScript#4595 when the file path is in node_modules, causing Bun to prefer .js versions instead of implicit .ts versions in node_modules (easiest to implement, but a potentially breaking change)
  • Ask the library which hasn't been updated in about a year to use export type (only fixes this one case)

@robpalme
Copy link

robpalme commented Nov 16, 2023

This isn't Bun's fault.

Ordinarily projects need to opt-into "isolatedModules" to be compatible with non-tsc TS->JS per-file compilers. This is common practice today. See ESBuild's guidance.

Even better is to use "verbatimModuleSyntax" to keep things crystal clear. This is a relatively newer option and is rarely used today.

@robpalme
Copy link

So to answer your direct question, for npm compatibility, I think Bun will need to prefer loading the JS files from node_modules just like Node does.

And the reason is that even though packages may ship TS source, there is currently no guarantee that such source is compilable by anything other than tsc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working transpiler parser || printer typescript Something for TypeScript
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants