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

Re-export statements are omitted from output using @babel/plugin-transform-typescript@7.5.0 #10162

Closed
elliottsj opened this issue Jul 4, 2019 · 20 comments · Fixed by #10167 or #10174
Closed
Labels
Has PR i: bug i: regression outdated A closed issue/PR that is archived due to age. Recommended to make a new issue Priority: High
Milestone

Comments

@elliottsj
Copy link

Bug Report

Current Behavior
Using @babel/plugin-transform-typescript@7.5.0 via @babel/preset-typescript@7.3.3, re-export statements are omitted from the transpiled output.

Repro:

$ npm install @babel/cli @babel/core @babel/preset-typescript
$ echo "export { bar } from './bar';" > script.ts
$ ./node_modules/.bin/babel --presets @babel/preset-typescript script.ts


$ # observe: the above output is empty

Note that separate import + export statements transpile properly:

$ echo "import { bar } from './bar'; export { bar };" > script.ts
$ ./node_modules/.bin/babel --presets @babel/preset-typescript script.ts
import { bar } from './bar';
export { bar };

$ # observe: the output is as expected

Input Code

export { bar } from './bar';

Expected behavior/code
The re-export statement should be included in the output.

Babel Configuration (.babelrc, package.json, cli command)

{
  "presets": ["@babel/preset-typescript"]
}

Environment

  • Babel version(s):

    $ npm ls --depth=1                                                                                                                                                                                                                                          (522ms)
    /Users/spencerelliott/Dev/temp
    ├─┬ @babel/cli@7.5.0
    │ ├── chokidar@2.1.6
    │ ├── commander@2.20.0
    │ ├── convert-source-map@1.6.0
    │ ├── fs-readdir-recursive@1.1.0
    │ ├── glob@7.1.4
    │ ├── lodash@4.17.11
    │ ├── mkdirp@0.5.1
    │ ├── output-file-sync@2.0.1
    │ ├── slash@2.0.0
    │ └── source-map@0.5.7
    ├─┬ @babel/core@7.5.0
    │ ├── @babel/code-frame@7.0.0
    │ ├── @babel/generator@7.5.0
    │ ├── @babel/helpers@7.5.0
    │ ├── @babel/parser@7.5.0
    │ ├── @babel/template@7.4.4
    │ ├── @babel/traverse@7.5.0
    │ ├── @babel/types@7.5.0
    │ ├── convert-source-map@1.6.0 deduped
    │ ├── debug@4.1.1 extraneous
    │ ├── json5@2.1.0
    │ ├── lodash@4.17.11 deduped
    │ ├── resolve@1.11.1
    │ ├── semver@5.7.0
    │ └── source-map@0.5.7 deduped
    └─┬ @babel/preset-typescript@7.3.3
      ├── @babel/helper-plugin-utils@7.0.0
      └── @babel/plugin-transform-typescript@7.5.0
    
  • Node/npm version: Node v10.15.0, npm 6.9.0

  • OS: macOS 10.14.5

  • Monorepo: no

  • How you are using Babel: see above

@babel-bot
Copy link
Collaborator

Hey @elliottsj! We really appreciate you taking the time to report an issue. The collaborators
on this project attempt to help as many people as possible, but we're a limited number of volunteers,
so it's possible this won't be addressed swiftly.

If you need any help, or just have general Babel or JavaScript questions, we have a vibrant Slack
community
that typically always has someone willing to help. You can sign-up here
for an invite.

@hzoo
Copy link
Member

hzoo commented Jul 4, 2019

Ah thanks for the report! I did want to confirm, is this only happening with the TS plugin?

edit: looking at https://github.com/babel/babel/releases/tag/v7.5.0 there's a few TS PRs. I'm thinking it's from #10034, so might not be too hard of a fix cc @Wolvereness? @airato

I would pin to the TS plugin to 7.4.5 for now, apologies!

@elliottsj
Copy link
Author

Yes, I've only noticed this issue with the TS plugin. Pinned to 7.4.5 for now. Thanks!

@eyousefifar
Copy link

I'm having the same problem

@Turbo87
Copy link

Turbo87 commented Jul 4, 2019

I just stepped through this after running into the same issue and I can confirm that 8d492b1 is the issue. The only change to that part of the code since v7.4.5 was that particular commit.

@Wolvereness
Copy link
Contributor

Just to confirm, 2080042 and a6392bd do not have the issue?

@pixelass
Copy link

pixelass commented Jul 4, 2019

I noticed that all my default exports were missing.

export default "foo"

with 7.5.0

var _default = "foo";
;

with 7.4.5

const _default = "foo";
var _default2 = _default;
exports.default = _default2;
;

@Wolvereness related to a6392bd

@JLHwung
Copy link
Contributor

JLHwung commented Jul 4, 2019

@Wolvereness Hi I just figure out a quick fix of this issue and it works well on my cases. Are you also working on a fix? If so I would leave it as-is and stop here.

diff --git a/packages/babel-plugin-transform-typescript/src/index.js b/packages/babel-plugin-transform-typescript/src/index.js
index a768907a5..79ca00102 100644
--- a/packages/babel-plugin-transform-typescript/src/index.js
+++ b/packages/babel-plugin-transform-typescript/src/index.js
@@ -98,9 +98,10 @@ export default declare(
         ExportNamedDeclaration(path) {
           // remove export declaration if it's exporting only types
           if (
+            !path.node.source &&
             path.node.specifiers.length > 0 &&
             !path.node.specifiers.find(exportSpecifier =>
-              path.scope.hasOwnBinding(exportSpecifier.local.name),
+              path.scope.hasBinding(exportSpecifier.local.name),
             )
           ) {
             path.remove();
@@ -109,7 +110,10 @@ export default declare(
 
         ExportSpecifier(path) {
           // remove type exports
-          if (!path.scope.hasOwnBinding(path.node.local.name)) {
+          if (
+            !path.parent.source &&
+            !path.scope.hasBinding(path.node.local.name)
+          ) {
             path.remove();
           }
         },
@@ -118,7 +122,7 @@ export default declare(
           // remove whole declaration if it's exporting a TS type
           if (
             t.isIdentifier(path.node.declaration) &&
-            !path.scope.hasOwnBinding(path.node.declaration.name)
+            !path.scope.hasBinding(path.node.declaration.name)
           ) {
             path.remove();
           }

@Wolvereness
Copy link
Contributor

Wolvereness commented Jul 5, 2019

Edit: was told I may have messed up the tests - updated with reruns, and this is only babel-plugin-transform-typescript

bff79e1 (fix commit):

  • Input:

    export default "foo";

    Output:

    export default "foo";
  • Input:

    export { bar } from './bar';

    Output:

    export { bar } from './bar';
  • Input:

    export default "foo";
    export { bar } from './bar';

    Output:

    export default "foo";
    export { bar } from './bar';

bff79e1~1:

  • Input:

    export default "foo";

    Output:

    export default "foo";
  • Input:

    export { bar } from './bar';

    Output:

  • Input:

    export default "foo";
    export { bar } from './bar';

    Output:

    export default "foo";

8d492b1 (my rewrite commit):

  • Input:

    export default "foo";

    Output:

    export default "foo";
  • Input:

    export { bar } from './bar';

    Output:

  • Input:

    export default "foo";
    export { bar } from './bar';

    Output:

    export default "foo";

8d492b1~1:

  • Input:

    export default "foo";

    Output:

    export default "foo";
  • Input:

    export { bar } from './bar';

    Output:

    export { bar } from './bar';
  • Input:

    export default "foo";
    export { bar } from './bar';

    Output:

    export default "foo";
    export { bar } from './bar';

a6392bd:

  • Input:

    export default "foo";

    Output:

    export default "foo";
  • Input:

    export { bar } from './bar';

    Output:

    export { bar } from './bar';
  • Input:

    export default "foo";
    export { bar } from './bar';

    Output:

    export default "foo";
    export { bar } from './bar';

2080042 No change from parent:

  • Input:

    export default "foo";

    Output:

    export default "foo";
  • Input:

    export { bar } from './bar';

    Output:

    export { bar } from './bar';
  • Input:

    export default "foo";
    export { bar } from './bar';

    Output:

    export default "foo";
    export { bar } from './bar';

2080042~1

  • Input:

    export default "foo";

    Output:

    export default "foo";
  • Input:

    export { bar } from './bar';

    Output:

    export { bar } from './bar';
  • Input:

    export default "foo";
    export { bar } from './bar';

    Output:

    export default "foo";
    export { bar } from './bar';

@pixelass - Your issue is probably unrelated based on these tests.

@babel babel deleted a comment from shrinktofit Jul 5, 2019
Turbo87 added a commit to Turbo87/ember-cli-typescript that referenced this issue Jul 5, 2019
pointless annoying conventional commit messages restrictions....... 🤬

Restrict `@babel/plugin-transform-typescript` to v7.4.x

see babel/babel#10162
dfreeman added a commit to typed-ember/ember-cli-typescript that referenced this issue Jul 5, 2019
@qiqiboy
Copy link

qiqiboy commented Jul 6, 2019

This issue seems still exists in v7.5.1.

@JoshRobertson
Copy link

In my case:
In 7.5.0 compilation was successful but would throw an error at runtime.
In 7.5.1 compilation fails with an export was not found error, which is the same error I had with 7.4.5. So I'm stuck on 7.4.4 still.

@nicolo-ribaudo nicolo-ribaudo reopened this Jul 6, 2019
@nicolo-ribaudo
Copy link
Member

@qiqiboy @JoshRobertson Can you share your code?

@JoshRobertson
Copy link

@nicolo-ribaudo
Copy link
Member

nicolo-ribaudo commented Jul 6, 2019

@JoshRobertson Babel can't handle re-exports of TypeScript types, since we don't do cross-file analysis and by looking at this code:

export { Avatar, AvatarProps } from "./Avatar";

it's impossible to know that AvatarProps is a type.

Since usages of AvatarProps will be removed anyway, you can safely ignore the webpack warning: it tells you that something can't be exported, but it isn't being used anyway.

If you want to make that warning go away, you can "hint" Babel that AvatarProps is a type by using it as such:

export { Avatar } from "./Avatar";

import { AvatarProps as Props } from "./Avatar";
export type AvatarProps = Props;

@qiqiboy
Copy link

qiqiboy commented Jul 6, 2019

.babelrc

{
  "plugins": ["react-hot-loader/babel", "@babel/plugin-transform-typescript"]
}

Input:

export defualt 'Foo';

Output:

const _default = 'Foo';
; // what???

May this is related with react-hot-loader? I think it's because the updates from >=v7.5.0 make some third-party plugins incompatible.

@nicolo-ribaudo
Copy link
Member

Yes, it is a problem with react-hot-loader. A plugin is responsible of maintaining scope information up-to-date, and Babel 7.5.0 brought to the surface that bug in react-hot-loader/babel because it uses scope information to remove exports.
I'm surprised that this didn't come up before, since we use scope info in many other places.

Would you be willing to open a PR to that package (or open an issue)?
https://github.com/gaearon/react-hot-loader/blob/master/src/babel.dev.js#L118
insertBefore returns an array of ast paths, and that plugin should call path.scope.registerDeclaration(resultOfInsertBefore[0])

@theKashey
Copy link

So that stuff was there for years, and everybody was just lucky :)

@theKashey
Copy link

If someone could verify gaearon/react-hot-loader#1293 with a patch @nicolo-ribaudo proposed - I'll issue a new version of React-Hot-Loader.
I was unable to find documentation for registerDeclaration and have no tests previously red, so you are the ones, who could say "👍"

@sciyoshi
Copy link

sciyoshi commented Jul 7, 2019

Seems to be fixed for me by updating react-hot-loader to 4.12.5 with gaearon/react-hot-loader#1293 Thank you @theKashey @nicolo-ribaudo!

@nicolo-ribaudo
Copy link
Member

We just released Babel 7.5.2. Please check that in your lockfile it contains v7.5.2 of @babel/plugin-transform-typescript!

@nicolo-ribaudo nicolo-ribaudo unpinned this issue Jul 8, 2019
@lock lock bot added the outdated A closed issue/PR that is archived due to age. Recommended to make a new issue label Oct 7, 2019
@lock lock bot locked as resolved and limited conversation to collaborators Oct 7, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Has PR i: bug i: regression outdated A closed issue/PR that is archived due to age. Recommended to make a new issue Priority: High
Projects
None yet