Skip to content

Conversation

@citizengabe
Copy link
Contributor

Resolves #1888. See that issue and this discussion on Discourse for background.

The changes in this PR are two-fold:

  1. Add a new field on Language.PureScript.CoreFn.Module to hold re-export data so it can be used during code generation
  2. Use that data to import the necessary modules and export the relevant members in the generated code.

I added a test for parsing the re-exports, but no others. Is there somewhere we test the output of Language.PureScript.CodeGen.JS.moduleToJs?

I'd also like to add this GitHub account to CONTRIBUTORS.md, but am waiting on guidance from my company as to how to reference it as this work was done on company time.

We need to make the `ExportSource` from
`Language.PureScript.AST.Declarations.ReExportRef` available during code-gen.
This requires adding it to `Module`.

We don't actually do the work of adding the data in this commit, we merely add
the field, update the JSON codecs, appease the compiler, and add a test for
parsing the new field.
@citizengabe
Copy link
Contributor Author

I have some tests that are failing in CI that weren't failing locally. I cleared .psci_modules, .test_modules, and output and ran again locally and got similar failures. I'll investigate and push up a fix.

@citizengabe
Copy link
Contributor Author

It was an issue with bundling. I was handling regular dot notation for exported member access, but not bracket notation.

@citizengabe
Copy link
Contributor Author

I'd also like to add this GitHub account to CONTRIBUTORS.md, but am waiting on guidance from my company as to how to reference it as this work was done on company time.

This is done, so the PR is ready to merge pending review.

Copy link

@joneshf-cn joneshf-cn left a comment

Choose a reason for hiding this comment

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

This seems to do what it says it does, but I don't know enough about module re-exports to approve or reject. @hdgarrood, can you take a peek when you get a second?

@kritzcreek
Copy link
Member

I'd also like to check that all the re-exporting logic in the IDE still works with this change. Please don't merge before I've approved. I'll check this weekend!

@citizengabe
Copy link
Contributor Author

citizengabe commented May 22, 2020

I'd also like to check that all the re-exporting logic in the IDE still works with this change. Please don't merge before I've approved. I'll check this weekend!

That sounds prudent, but know that the changes are additive only. Nothing was changed WRT externs, and moduleReExports is an additional field. The rest of Language.PureScript.CoreFn.Module.Module and its contents remain unchanged.

@kritzcreek
Copy link
Member

Yeah, after checking none of these changes affect the IDE. All good from my side.

Copy link
Contributor

@hdgarrood hdgarrood left a comment

Choose a reason for hiding this comment

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

Is there somewhere we test the output of Language.PureScript.CodeGen.JS.moduleToJs?

We mostly don't do unit testing, testing is generally done end-to-end via tests/purs/{passing,failing,warning}. Perhaps we could test this by having a module re-export something, having a separate module import that module via the FFI, and test that the re-exports are present in the generated JS that way?

@citizengabe citizengabe force-pushed the citizengabe/FBCM-3329/have-module-reexports-appear-in-generated-code branch from 6fd4be2 to 653d783 Compare May 26, 2020 16:11
Now that we have a field for them, we add the re-exports to the module so they
show up as both imported modules and exported members during code-gen.
Now that we're threading the necessary information down to `moduleToJs`, we can
use it to generate the imports we need to later re-export.
We build up the key/value pairs for the re-exports and append them to the rest
of the exports.

This broke bundling and required allowing `<module name>.<member name>` in
addition to `$foreign.<member name>`. This is the only place where I'm unsure of
my changes.
In the last commit, we handled the case of member access using dot notation, but
the passing tests were a fluke of caching. Now both cases are handled and tests
are passing.
I have a separate account that I use for work and prefer to include this in
addition to my personal acccount to differentiate who owns the copyright for
what work.

I also add my employer to the list of companies holding copyright.
Previously, it was possible to forget to handle new constructors added to
`DeclarationRef`. Now we handle them explicitly thus eliminating this potential
source of bugs.
@citizengabe citizengabe force-pushed the citizengabe/FBCM-3329/have-module-reexports-appear-in-generated-code branch from 653d783 to 24df28d Compare May 26, 2020 18:26
@hdgarrood
Copy link
Contributor

Don't worry about it now, but for future reference could you please just push new commits to the branch after review? I'd like to be able to review what's changed since I last looked, and we will tidy up the history when merging.

@citizengabe
Copy link
Contributor Author

Don't worry about it now, but for future reference could you please just push new commits to the branch after review?

Sure thing!

@hdgarrood
Copy link
Contributor

Looks great! If you could write a test along the lines of what I wrote here: #3883 (review) that would be ideal, then I'm happy to approve.

As suggested by @hdgarrood in
purescript#3883 (review),
we use the FFI to import a re-exported value.

Module `A` defines a value `a`, module `B` re-exports `A`, and module `Main`
does a foreign import of `a` via `B`. Logging the imported value proves that
the re-export chain was successful.
@hdgarrood
Copy link
Contributor

hdgarrood commented May 26, 2020

Oh wait, sorry, just a couple more cases that I've just remembered about that I think would be worth testing:

  • re-exporting a re-export
  • re-exporting something from a module if we have a data constructor with the same name in scope (to make sure this continues to work well together with the module name renaming mnLookup thing, in CodeGen/JS.hs), eg
module B (module A, A(..)) where

import A
data A = A

to make sure the exports list refers to A_1, which is what the module A should be imported as in the JS, rather than just A.

@citizengabe
Copy link
Contributor Author

Would you prefer separate test suites for the different cases or is a single suite sufficient?

@hdgarrood
Copy link
Contributor

Whatever's easiest - I think putting them all under tests/purs/passing/ReExportsExported is fine.

We tested that the value defined in one module could be re-exported and then
imported via FFI. Now, we test that:

1. a re-exported module doesn't cause a name clash with any data constructors
defined in the re-exporting module

2. a value, `a`, defined in a module, `A`, may be re-exported from another
module, `B`, and again re-exported from a third module, `C`, which imported `a`
from `B`.
Copy link
Contributor

@hdgarrood hdgarrood left a comment

Choose a reason for hiding this comment

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

Thanks!

I forgot to export the data constructor `A`. I had visually inspected the
generated code and saw that the names didn't conflict. However, it's better to
have the test make this assurance.
@citizengabe
Copy link
Contributor Author

@hdgarrood is there anything preventing this PR from being merged?

@hdgarrood
Copy link
Contributor

Our policy is that PRs require at least two core team approvals (if the person who submits the PR is already a core team member, that counts).

@citizengabe
Copy link
Contributor Author

@kritzcreek You took a look a couple of weeks ago. Does it still look good?

@kritzcreek
Copy link
Member

You took a look a couple of weeks ago. Does it still look good?

Sorry, I was on vacation last week. Change still looks good to me 👍

@hdgarrood hdgarrood merged commit c044d69 into purescript:master Jun 13, 2020
@citizengabe
Copy link
Contributor Author

Thank you both for the reviews!

Sorry, I was on vacation last week.

Hope it was a good one 😄

@hedefalk
Copy link

Oooh, think I struck this and asked in slack https://functionalprogramming.slack.com/archives/C717K38CE/p1592399197296900

Does this solve the issue I'm having right now when trying to re-export for commonjs:

Foo.purs:

module Foo ( module Foo ) where
import Bar (bar) as Foo

Bar.purs:

module Bar where
bar :: String
bar = "bar"

npx spago bundle-module --main Foo gives me:

// Generated by purs bundle 0.13.8
var PS = {};
module.exports = PS["Foo"];

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.

Have module reexports appear in generated code

5 participants