Skip to content

Instantly share code, notes, and snippets.

@ifandelse
Last active August 29, 2015 14:05
Show Gist options
  • Save ifandelse/54c264a9eb262c5be0ea to your computer and use it in GitHub Desktop.
Save ifandelse/54c264a9eb262c5be0ea to your computer and use it in GitHub Desktop.
Trying to understand traceur's module transpilation output

The AMD output of traceur has me a bit confused. The return value looks a lot like an ES6 class - shouldn't this be converting all the way to ES5? FWIW, my options (to traceur) are:

{
  modules: "amd",
	outputLanguage: 'es5'
}
define([], function() {
"use strict";
var myVar = {};
var $__default = myVar;
return {
get default() {
return $__default;
},
__esModule: true
};
});
var myVar = {};
export default myVar;
@guybedford
Copy link

This is to replicate the immutability of ES6 modules so that you can't write to the AMD exported object.

What about it specifically is the issue though?

@ifandelse
Copy link
Author

@guybedford - thanks for the quick reply. I'm relatively new to traceur, and have been attempting to research the issue before reaching out. I'm confused by the return value using ES6 class-like syntax in what I expected to be ES5 output. A return value of { get default() {} } isn't valid ES5 syntax as far as I understand. Am I misunderstanding the purpose of traceur's support of transpiling ES6 modules to AMD/CJS - is this an interim step that still needs "to-ES5" transpilation?

@domenic
Copy link

domenic commented Aug 18, 2014

{ get default() {} }

This is valid ES5 syntax; why would you think it's not?

@rauschma
Copy link

[Edit: I removed much of this comment, especially what I wrote about cyclic dependencies.]

ECMAScript 6 modules export bindings, not values. The indirection via getters emulates this behavior.

@ifandelse
Copy link
Author

@domenic - I'm sorry. This exposed a gap in my knowledge on apparent shorthand syntax for creating a defined prop. When this wasn't working in IE (I'm cross testing the output in multiple browsers...the last being IE11...where { get default() {} } lands you with default = undefined.), it prompted the assumption that perhaps I: 1.) don't properly understand what traceur's doing here and 2.) wondered if I was dealing with interim transpiler output...

UPDATE: oh good lord it's been one of those days for me (brain not working AND fighting IE). I was looking at the wrong output in IE in my tests. Sigh. 👊 to my face....

So - I chalk this up to my ignorance (hence why I asked for help).

@ifandelse
Copy link
Author

@rauschma - thanks for the explanation. That makes sense.

@guybedford
Copy link

Glad it makes sense. There is certainly room to argue removing these guards for older IE support / performance.

@eventualbuddha
Copy link

@rauschma, I believe your CommonJS cycle example actually would work properly. It has the potential to cause an infinite loop depending on how you fill in the blanks, but so does the ES6 version. Could you come up with another example that can be run to show the difference?

@rauschma
Copy link

@eventualbuddha You may be right. I’ll have to give this more thought (which will take a while – busy ATM).

@calvinmetcalf
Copy link

@eventualbuddha: ES6 and (node flavored) CJS both have different cyclic dependency strategies so

ES6 cyclic dependencies that don't work in CJS

//even.js

  import { odd } from './odd'

  export var counter = 0;

  export function even(n) {
    counter++;
    return n == 0 || odd(n - 1);
  }

//odd.js

  import { even } from './even';

  export function odd(n) {
    return n != 0 && even(n - 1);
  }

//app.js
import { even } from './even';
even(); //this works

CJS circular dependencies that don't work in ES6

//a.js
exports.obj = {};
var b = require('./b');
b.something();

//b.js
var a = require('./a');
a.obj.val = 'asdf';
exports.something = function() {};

//app.js
require('./a'); // this doesn't throw

@michaelficarra
Copy link

Agreed with @eventualbuddha, that example would work because of partially loaded modules.

Modules are cached after the first time they are loaded. This means (among other things) that every call to require('foo') will get exactly the same object returned, if it would resolve to the same file. Multiple calls to require('foo') may not cause the module code to be executed multiple times. This is an important feature. With it, "partially done" objects can be returned, thus allowing transitive dependencies to be loaded even when they would cause cycles.

edit: This was posted way after composing it, and a few comments were posted before it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment