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

[Bug]: Source maps now outputs helpers names additionally to input source names #15601

Open
1 task
Gabri3l opened this issue May 1, 2023 · 12 comments
Open
1 task

Comments

@Gabri3l
Copy link

Gabri3l commented May 1, 2023

💻

  • Would you like to work on a fix?

How are you using Babel?

Programmatic API (babel.transform, babel.parse)

Input code

async function myfunc() {
  return await someAsyncCall();
}

Configuration file name

No response

Configuration

{
    "presets": ["env"],
    "sourceMap": true
}

Current and expected behavior

I noticed that with v7.21.0 the result of sourcempas changed. Specifically the names tracked. Given this:

const result = babel.transform(src, opts);
console.log(result.map.names);

with the given input code I get 155 entries in result.map.names. A few of them being: _regeneratorRuntime, Op, Object, prototype, hasOwn, ...

Before this update I would only get the relevant names from the input code, in this case specifically: myfunc, someAsyncCall.

Environment

System:
OS: macOS 13.3.1
Binaries:
Node: 16.18.0 - /usr/local/bin/node
Yarn: 1.22.19 - /opt/homebrew/bin/yarn
npm: 8.19.2 - /usr/local/bin/npm
npmPackages:
@babel/core: ^7.21.5 => 7.21.5
@babel/preset-env: ^7.21.5 => 7.21.5
@babel/standalone: ^7.21.7 => 7.21.7

Possible solution

I might be missing more context but looking at the changelog I didn't notice anything that would highlight this change. I don't necessarily have a good recommendation but if this change was intentional it could be an opt-in via config rather than opt-out.

EDIT: On a second look maybe this #15022 change?

Additional context

No response

@babel-bot
Copy link
Collaborator

Hey @Gabri3l! 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.

@Gabri3l
Copy link
Author

Gabri3l commented Jun 6, 2023

@liuxingbaoyu just curious do you think your change in #15022 might have caused this?

@liuxingbaoyu
Copy link
Member

liuxingbaoyu commented Jun 11, 2023

Yes, this should be the change introduced in this PR. But I'm not sure if this is a bug, is this causing any problems?

@Gabri3l
Copy link
Author

Gabri3l commented Jun 11, 2023

With this, it inflates the bundle size up to 70% especially if you have multiple plugins. Not sure this was intentional, I had to revert back to a previous version because the current bundle size is not sustainable for our use case.

@JLHwung
Copy link
Contributor

JLHwung commented Jun 11, 2023

@Gabri3l The source map file *.map won't be downloaded to the browser unless users open the developer tools. They are meant to help developers, for example they can map call stacks from production code to source code. I am not sure how larger *.map file will impact end users.

@Gabri3l
Copy link
Author

Gabri3l commented Jun 11, 2023

Yes you're definitely right! For our use case we need the source map as well and I just wanted to make sure this change was intentional since it's a significant size change. I'm not sure it's helpful to have plugins variables as part of the source map, any specific reason why they were added?

I currently have to hack around it and I didn't see this in any change log (I might have missed it though), when I was looking for the reason for this.

@overlookmotel
Copy link
Contributor

I have run into the same problem via a different route. Identifiers added to AST programmatically with no source location can end up in names.

This does appear to me to be a bug, for 2 reasons:

  1. A source map is meant to map to the source, so it doesn't make sense to reference names which are not present in the source.
  2. It's inconsistent. Sometimes variables appear in names, sometimes they don't.

A simple demonstration of the inconsistency:

const {parse} = require('@babel/parser'),
  generate = require('@babel/generator').default;

const ast = parse('function foo() {}', {sourceFilename: '/foo.js'});

const programStatements = ast.program.body;
ast.program.body.unshift({
  type: 'VariableDeclaration',
  kind: 'let',
  declarations: [{
    type: 'VariableDeclarator',
    id: { type: 'Identifier', name: '_x' },
    init: null
  }]
});

const {code: code1, map: map1} = generate(ast, {sourceMaps: true});

console.log(code1);
// -> let _x; function foo() {}
console.log(map1.names);
// -> ['foo']
// `_x` is NOT in `names`

const fnStatements = programStatements[1].body.body;
fnStatements.push({
  type: 'ExpressionStatement',
  expression: { type: 'Identifier', name: '_x' }
});

console.log(code2);
// -> let _x; function foo() { _x; }
console.log(map2.names);
// -> ['foo', '_x']
// Now `_x` IS in `names`

This was introduced between 7.20.14 and 7.21.0, so #15022 does seem to be the most obvious cause.

@liuxingbaoyu
Copy link
Member

liuxingbaoyu commented Sep 2, 2023

Sorry forgot this.

I'm not sure it's helpful to have plugins variables as part of the source map, any specific reason why they were added?

To be honest, there's no particularly strong need to add them. One possible reason is #14907, which can make debugging easier. In this case I just thought more would be better than less, does this information bother you?

Additionally this information may be helpful to js-debug. (vs code)

A source map is meant to map to the source, so it doesn't make sense to reference names which are not present in the source.

Well, I guess you might be right. But unfortunately source maps are crude and difficult to standardize, and many times we have to guess and do things outside of the standard.
#15370 (comment)
Here is an even more striking example. We completely agree that this is not a good solution, but it may be the only way we can do it. 🤦‍♂️

It's inconsistent. Sometimes variables appear in names, sometimes they don't.

This may be a bug, thank you for finding it!

@overlookmotel
Copy link
Contributor

OK cool. I see it's complicated!

One small thing: It might be helpful for people to find this issue to correct the typo in the issue title - "Sourcemaps" not "Sourcempas".

@nicolo-ribaudo nicolo-ribaudo changed the title [Bug]: Sourcempas now outputs helpers names additionally to input source names [Bug]: Source maps now outputs helpers names additionally to input source names Sep 2, 2023
@Gabri3l
Copy link
Author

Gabri3l commented Sep 5, 2023

@liuxingbaoyu thank you for the additional info, do you have a recommendation then if I want to manually extract only names from the source and not the helpers. For my use case I really need to filter the helper ones out and I put together a custom plugin but wanted to make sure I do it correctly.

@liuxingbaoyu
Copy link
Member

Sorry I didn't think of a good way.
Can you provide an example?
For example
sourcemap

@liuxingbaoyu
Copy link
Member

liuxingbaoyu commented Sep 7, 2023

Here's a possible example.
We can notice that the helper name points to a segment that is not an identifier.
Maybe you could try taking advantage of this and check if a segment with an identifier name points to a valid identifier.
I admit this may not be perfect, but that's all I can think of.🤦‍♂️

image

vs

image

sourcemap

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants