Skip to content

Conversation

@GabrielRatener
Copy link
Contributor

@GeoffreyBooth To address your JS interoperability concerns in #3757, this PR enables usage of CS-only keywords as local names in import lists and as any name in export lists. This will enable people to do the following

// now possible
import {unless as someLocalName} from 'foo'

// but not
import {someImportedName as unless} from 'bar'

// for exports CS keywords are allowed everywhere
export {someLocalVar as unless}
export {unless, loop as until} from 'baz'

Copy link
Collaborator

@GeoffreyBooth GeoffreyBooth left a comment

Choose a reason for hiding this comment

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

Thanks for doing this!

This should also be submitted against master, this is basically a bug in the current modules implementation.

eq toJS(input), output

test "CS only keywords can't be used as unaliased names in import lists", ->
throws ->
Copy link
Collaborator

Choose a reason for hiding this comment

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

This and the following test should be in error_messages.coffee.

src/lexer.coffee Outdated
@token 'AS', id
return id.length
if id is 'as' and @seenImport
# loop hack
Copy link
Collaborator

Choose a reason for hiding this comment

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

“Loop hack”? Why isn’t this block:

    if id is 'as' and @seenImport
      if @value() is '*'
        @tokens[@tokens.length - 1][0] = 'IMPORT_ALL'
      else if @value() in COFFEE_KEYWORDS
        @tokens[@tokens.length - 1][0] = 'IDENTIFIER'

      @token 'AS', id
      return id.length

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because the code is more selective with the loop. In your case when encountering an as after an { on an import line, the as would always become an AS token, which would prevent its currently allowed usage as an import variable.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Are you sure about that?

coffee -ne "import { as as as } from 'lib'"
Block
  ImportDeclaration
    ImportClause
      ImportSpecifierList
        ImportSpecifier IdentifierLiteral: as IdentifierLiteral: as StringLiteral: 'lib'

See https://github.com/jashkenas/coffeescript/blob/master/test/modules.coffee#L587-L609

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think, are you using a version of CS with that code in it?

Copy link
Collaborator

Choose a reason for hiding this comment

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

That’s from 1.11.1. See the link.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I haven't tried it but I think those tests would fail with the code you're suggesting.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Those tests pass in 1.11.1. They should still pass after your PR. I didn’t test the code I put in the comment, it was just meant to pose a question about the loop. I don’t like the idea of loop, which becomes while (true). I feel like whatever you’re trying to do here, you should be able to do with a simple if/else tree. Is there a reason we need a loop?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's not ideal, I basically wan't to reach the @token 'AS', id and return only for a select few token types. So basically if none of the conditionals run, I want to skip that part and not return. Since CS doesn't have goto, I used this as a hack.

It's possible to do it without a loop, but it would require more code.

src/lexer.coffee Outdated
if @value() is '!'
poppedToken = @tokens.pop()
id = '!' + id
unless @exportList and id in COFFEE_KEYWORDS
Copy link
Collaborator

Choose a reason for hiding this comment

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

Combine these two lines:

if tag is 'IDENTIFIER' and (id in JS_KEYWORDS or id in COFFEE_KEYWORDS) and
not (@exportList and id in COFFEE_KEYWORDS)

@lydell
Copy link
Collaborator

lydell commented Oct 25, 2016

If I import {unless} from 'foo', I can't do anything with unless then, can I? What am I missing here?

@GeoffreyBooth
Copy link
Collaborator

You would need to do import { unless as somethingElse } from 'foo'. This is such an edge case, I’m not sure it’s worth throwing an error warning people that they’re creating an inaccessible variable. Unless wouldn’t import { unless } from 'foo' be accessible via module.unless?

@GabrielRatener GabrielRatener changed the base branch from 2 to master October 25, 2016 17:02
@GabrielRatener
Copy link
Contributor Author

@lydell Right, so this PR prevents that.

@GabrielRatener
Copy link
Contributor Author

I moved the error tests to error_messages.coffee, so is this PR ready to be merged?

@GeoffreyBooth
Copy link
Collaborator

The following is valid JavaScript, according to Babel:

import { if } from 'lib';

I’m not sure how you would access this if in a runtime that natively supports modules; module.if/window.if? But regardless of that, there’s simply no way to generate this output via CoffeeScript, either before or after this PR. Maybe we don’t care, especially since even in Babel there’s no way to access this if unless it’s aliased?

@GeoffreyBooth
Copy link
Collaborator

This looks good to me. @lydell, @jashkenas?

@GabrielRatener
Copy link
Contributor Author

@GeoffreyBooth I don't think we need to worry about it for now, plus Babel isn't always standards compliant anyway.

@lydell
Copy link
Collaborator

lydell commented Oct 26, 2016

Looks good to me too. Good work!

@lydell lydell merged commit 26ad6d4 into jashkenas:master Oct 26, 2016
@GabrielRatener GabrielRatener deleted the es-modules branch October 26, 2016 18:27
EsrefDurna pushed a commit to EsrefDurna/coffeescript that referenced this pull request Nov 12, 2025
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.

3 participants