google / traceur-compiler

Traceur is a JavaScript.next-to-JavaScript-of-today compiler
Apache License 2.0
8.17k stars 580 forks source link

import failures without the .js postfix #1997

Closed iislucas closed 8 years ago

iislucas commented 8 years ago

Given:

test.js:

import * as toylib from "./toylib";
toylib.toy();

toylib.js:

export function toy() {
    console.log("toy library called.")
    return "toy!";
}
$ traceur test.js --out test_es5.js
Error: Error: ENOENT: no such file or directory, open '/Users/ldixon/code/respect-engine/typescript-polymer/build/home_page/toylib'
Specified as ./toylib.
Imported by test.js.
Normalizes to toylib
locate resolved against base '/Users/ldixon/code/respect-engine/typescript-polymer/build/home_page/'

    at InternalLoader.loaderCompiler.handleCodeUnitLoadError (/Users/ldixon/code/respect-engine/typescript-polymer/node_modules/traceur/bin/traceur.js:31014:40)
    at /Users/ldixon/code/respect-engine/typescript-polymer/node_modules/traceur/bin/traceur.js:30872:21

However, if I change the import statement to: import * as toylib from "./toylib.js", then it compiles as expected.

I think ES6 is supposed to correctly guess .js extensions (from looking at places like: http://www.2ality.com/2014/09/es6-modules-final.html and https://github.com/ModuleLoader/es6-module-loader/wiki/Brief-Overview-of-ES6-Module-syntax and http://www.ecma-international.org/ecma-262/6.0/index.html#table-40 )

iislucas commented 8 years ago

OK, Having looked around the Traceur code, I think I see what's happening... https://github.com/google/traceur-compiler/blob/master/src/runtime/TraceurLoader.js#L143

The fetch call assumes the address given is a fully resolved address, but when you miss the .js postfix, this is false. There are several levels this can be fixed at:

  1. the loader implementation, e.g. https://github.com/google/traceur-compiler/blob/master/src/node/nodeLoader.js
  2. The Traveur loader: https://github.com/google/traceur-compiler/blob/master/src/runtime/TraceurLoader.js#L143 If the original fetch fails, we can try a new address with postfixed ".js" in the fetch.

(2) looks like it's probably the best way to go. I'll put together a pull request to experiment with this fix.

arv commented 8 years ago

This is intentional.

We made this change to better match the upcoming spec.

iislucas commented 8 years ago

I see. In that case I need to file a bug in the compiler that is producing the import statements that miss the .js postfix. Can you point me to where the es6 spec says that the import names should include the postfix? Thanks!

arv commented 8 years ago

@iislucas The spec is still work in progress but here is where things will be fleshed out further:

http://whatwg.github.io/loader/#browser-loader-prototype-%40%40resolve

iislucas commented 8 years ago

@arv Thanks! At the moment, Typescript doesn't create import statements with ".js" postfixes - they are waiting for spec to solidify. This means that the es6 created by Typescript is incompatible with Traceur. Would you object to me creating a pull request that, if the name doesn't end in ".js" and the file doesn't exist without the ".js" postfix, then the TraceurLoader tries adding/loading a filename with ".js" postfixed to the filename? (I'd really like a way to have Traceur be compatible with TypeScript).