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

Clear scope cache before crawling to fix scope hoisting classes #2986

Merged
merged 2 commits into from May 8, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -0,0 +1,2 @@
import Test from './b';
output = Test.create();
@@ -0,0 +1,9 @@
export default class Test {
constructor() {
this.foo = 'bar';
}

static create() {
return new Test();
}
}
@@ -0,0 +1,5 @@
{
"name": "default-export-class-rename",
"private": true,
"browserslist": ["last 1 Chrome version"]
}
12 changes: 12 additions & 0 deletions packages/core/integration-tests/test/scope-hoisting.js
Expand Up @@ -568,6 +568,18 @@ describe('scope hoisting', function() {
assert(!/bar/.test(contents));
assert(!/displayName/.test(contents));
});

it('should correctly rename references to default exported classes', async function() {
let b = await bundle(
path.join(
__dirname,
'/integration/scope-hoisting/es6/default-export-class-rename/a.js'
)
);

let output = await run(b);
assert.deepEqual(output.foo, 'bar');
});
});

describe('commonjs', function() {
Expand Down
2 changes: 2 additions & 0 deletions packages/core/parcel-bundler/src/scope-hoisting/hoist.js
Expand Up @@ -2,6 +2,7 @@ const path = require('path');
const mm = require('micromatch');
const t = require('@babel/types');
const template = require('@babel/template').default;
const traverse = require('@babel/traverse').default;
const rename = require('./renamer');
const {getName, getIdentifier, getExportIdentifier} = require('./utils');

Expand Down Expand Up @@ -51,6 +52,7 @@ function hasSideEffects(asset, {sideEffects} = asset._package) {
module.exports = {
Program: {
enter(path, asset) {
traverse.cache.clearScope();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this have (performance) side effects for every import of @babel/traverse ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possibly, but it’s the only way. I believe Babel’s behavior may actually be correct. I don’t think scope.crawl was meant to be called manually. It is called automatically by Babel when setting up a scope for a path, and only re-crawls that scope, not child scopes. So we need to clear the cache so that Babel will automatically crawl child scopes again when we traverse them.

Ideally we wouldn’t need to re-crawl at all, but some Babel plugins are badly behaved and don’t update the scope properly when they mutate the AST.

path.scope.crawl();

asset.cacheData.imports = asset.cacheData.imports || Object.create(null);
Expand Down