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

Fix for #1992, along with chunk interface refactoring #1994

Merged
merged 3 commits into from
Feb 25, 2018

Conversation

guybedford
Copy link
Contributor

@guybedford guybedford commented Feb 20, 2018

Resolves #1992.

The fix for #1992 was relatively straightforward here.

While I was at it I noticed chunk.externalModules is a kind of semi-public interface used by finalisers, which could easily get out of sync with further optimization, so I refactored the usage here to be entirely dependent on the data structure created by chunks for their boundaries instead of needing to reach into internals like this. It's not the prettiest of code, but it provides the encapsulation which is necessary to separate thinking about the input graph from thinking about the output graph.

Copy link
Member

@lukastaegert lukastaegert left a comment

Choose a reason for hiding this comment

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

Nice, I really like the new abstractions this introduces!

src/Chunk.ts Outdated
reexports?: ReexportSpecifier[];
imports?: ImportSpecifier[];
}[];
};
Copy link
Member

Choose a reason for hiding this comment

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

As far as I know, interfaces work syntactically like functions and classes in that trailing semicolons are treated like empty statements (in contrast to types).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

To be honest, I have no idea what the rules are so have just defaulted to using a semicolon everywhere. But you are probably right in that it is a declaration.

@@ -97,7 +97,6 @@ export default class Chunk {
}
};
dependencies: (ExternalModule | Chunk)[];
externalModules: ExternalModule[];
Copy link
Member

Choose a reason for hiding this comment

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

Awesome you could get rid of this! Really like this kind of change!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Great, yes worth keeping the refactorings going!

src/Chunk.ts Outdated
@@ -592,10 +586,26 @@ export default class Chunk {
}

let reexports = reexportDeclarations[dep.id];
const isExternal = !!(<ExternalModule>dep).isExternal;
Copy link
Member

Choose a reason for hiding this comment

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

I would suggest to inline this constant. Also I think the boolean type-cast is rather unnecessary if we just write if ((<ExternalModule>dep).isExternal === true)

dependencies.push({
id: dep.id,
name: dep.name,
isChunk: !(<ExternalModule>dep).isExternal,
exportsNames,
exportsNamespace,
exportsDefault,
reexports,
imports
});
Copy link
Member

Choose a reason for hiding this comment

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

As this is becoming bigger, I would suggest to extract the forEach loop into a private method getModuleDeclarationDependencies(reexportDeclarations). Also you convinced me that for-of-loops are really more efficient while usually being just as readable so we might switch to one of those 😉

Even better, we might also extract the top part of this function into a private method getReexportDeclarations() and call this directly from getModuleDeclarationDependencies() and get rid of this last parameter there. Apart from better structuring, this would also make it clear that there are no dependencies between these code blocks which should make it easier to make confident refactorings in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Unfortunately the scope of all variables in this function follows the whole function. See for example reexportDeclarations is referenced by the dependencies loop, and imports being referenced from above as well.

Copy link
Member

@lukastaegert lukastaegert Feb 22, 2018

Choose a reason for hiding this comment

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

No, this is exactly the kind of confusion I would like to avoid with this extraction. I was talking about the forEach loop starting at L.573. Except for the variables reexportDeclarations as an input and dependencies as an output, this loop is completely self-contained (as I tried out in my IDE). This is easily overlooked as long as it is just somewhere inside the larger function scope.
The same goes for the for-loop starting at L.553 which only produces reexportDeclarations.

So to repeat, my suggestion is:

  • extract L.549-L.569 into a private method getReexportDeclarations().
  • extract L.571-L.610 into a private method getModuleDeclarationDependencies() which itself calls getReexportDeclarations() to get the re-exports.

So everything that remains in this function is a call to getModuleDeclarationDependencies() and the generation of exports which may or may not be extracted itself for symmetry reasons.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nice!

@guybedford
Copy link
Contributor Author

I may try and bring this work into the current default fix refactoring I'm doing as it may have some related parts - please hold off on merging for a little while till I can confirm!

@guybedford
Copy link
Contributor Author

I've checked and this merges fine separately to the default naming fix PR, so this can be merged anytime.

@lukastaegert lukastaegert added this to the 0.56.3 milestone Feb 22, 2018
Copy link
Member

@lukastaegert lukastaegert left a comment

Choose a reason for hiding this comment

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

Awesome 👍

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

Successfully merging this pull request may close these issues.

JavaScript API no longer provides names of imports
2 participants