diff --git a/lib/6to5/modules/amd.js b/lib/6to5/modules/amd.js index 6ffb6235ee..5ae4c44824 100644 --- a/lib/6to5/modules/amd.js +++ b/lib/6to5/modules/amd.js @@ -10,6 +10,8 @@ function AMDFormatter(file) { this.ids = {}; } +util.inherits(AMDFormatter, CommonJSFormatter); + AMDFormatter.prototype.transform = function (ast) { var program = ast.program; var body = program.body; @@ -76,8 +78,6 @@ AMDFormatter.prototype.importSpecifier = function (specifier, node, nodes) { ])); }; -AMDFormatter.prototype.export = CommonJSFormatter.prototype.export; - AMDFormatter.prototype.exportSpecifier = function (specifier, node, nodes) { var variableName = util.getSpecifierName(specifier); diff --git a/lib/6to5/modules/umd.js b/lib/6to5/modules/umd.js new file mode 100644 index 0000000000..a9b4a02ca7 --- /dev/null +++ b/lib/6to5/modules/umd.js @@ -0,0 +1,48 @@ +module.exports = UMDFormatter; + +var CommonJSFormatter = require("./common"); +var AMDFormatter = require("./amd"); +var util = require("../util"); +var b = require("ast-types").builders; +var _ = require("lodash"); + +function UMDFormatter(file) { + this.file = file; + this.ids = {}; +} + +util.inherits(UMDFormatter, AMDFormatter); + +UMDFormatter.prototype.transform = function (ast) { + var program = ast.program; + var body = program.body; + + // build an array of module names + + var names = []; + _.each(this.ids, function (id, name) { + names.push(b.literal(name)); + }); + + // factory + + var ids = _.values(this.ids); + var args = [b.identifier("exports")].concat(ids); + + var factory = b.functionExpression(null, args, b.blockStatement(body)); + + // runner + + var runner = util.template("umd-runner-body", { + AMD_ARGUMENTS: b.arrayExpression([b.literal("exports")].concat(names)), + + COMMON_ARGUMENTS: names.map(function (name) { + return b.callExpression(b.identifier("require"), [name]) + }) + }); + + // + + var call = b.callExpression(runner, [b.thisExpression(), factory]); + program.body = [b.expressionStatement(call)]; +}; diff --git a/lib/6to5/templates/umd-runner-body.js b/lib/6to5/templates/umd-runner-body.js new file mode 100644 index 0000000000..b78bb97cb6 --- /dev/null +++ b/lib/6to5/templates/umd-runner-body.js @@ -0,0 +1,7 @@ +(function (root, factory) { + if (typeof define === "function" && define.amd) { + define(AMD_ARGUMENTS, factory); + } else if (typeof exports !== "undefined") { + factory(exports, COMMON_ARGUMENTS); + } +}); diff --git a/lib/6to5/transform.js b/lib/6to5/transform.js index 24d78fdd29..1f3a3e96f3 100644 --- a/lib/6to5/transform.js +++ b/lib/6to5/transform.js @@ -106,7 +106,8 @@ transform.transformers = { transform.moduleFormatters = { common: require("./modules/common"), - amd: require("./modules/amd") + amd: require("./modules/amd"), + umd: require("./modules/umd") }; _.each(transform.transformers, function (transformer, key) { diff --git a/lib/6to5/util.js b/lib/6to5/util.js index c52ebe02d1..09cd30e33c 100644 --- a/lib/6to5/util.js +++ b/lib/6to5/util.js @@ -3,12 +3,15 @@ var astTypes = require("recast").types; var recast = require("recast"); var acorn = require("acorn"); var path = require("path"); +var util = require("util"); var fs = require("fs"); var _ = require("lodash"); var n = astTypes.namedTypes; var b = astTypes.builders; +exports.inherits = util.inherits; + exports.ensureBlock = function (node) { var block = node.body; if (block.type === "BlockStatement") return; diff --git a/test/fixtures/syntax/modules-umd/exports-default/actual.js b/test/fixtures/syntax/modules-umd/exports-default/actual.js new file mode 100644 index 0000000000..d7c96201d6 --- /dev/null +++ b/test/fixtures/syntax/modules-umd/exports-default/actual.js @@ -0,0 +1,8 @@ +export default 42; +export default {}; +export default []; +export default foo; +export default function () {} +export default class {} +export default function foo () {} +export default class foo {} diff --git a/test/fixtures/syntax/modules-umd/exports-default/expected.js b/test/fixtures/syntax/modules-umd/exports-default/expected.js new file mode 100644 index 0000000000..19c52b670d --- /dev/null +++ b/test/fixtures/syntax/modules-umd/exports-default/expected.js @@ -0,0 +1,27 @@ +"use strict"; + +(function (root, factory) { + if (typeof define === "function" && define.amd) { + define(["exports"], factory); + } else if (typeof exports !== "undefined") { + factory(exports); + } +})(this, function (exports) { + exports.default = 42; + exports.default = {}; + exports.default = []; + exports.default = foo; + exports.default = function() {}; + + exports.default = function() { + var _class = function() {}; + return _class; + }(); + + exports.default = function foo() {}; + + exports.default = function() { + var foo = function foo() {}; + return foo; + }(); +}); diff --git a/test/fixtures/syntax/modules-umd/exports-from/actual.js b/test/fixtures/syntax/modules-umd/exports-from/actual.js new file mode 100644 index 0000000000..60857f6542 --- /dev/null +++ b/test/fixtures/syntax/modules-umd/exports-from/actual.js @@ -0,0 +1,6 @@ +export * from "foo"; +export {foo} from "foo"; +export {foo, bar} from "foo"; +export {foo as bar} from "foo"; +export {foo as default} from "foo"; +export {foo as default, bar} from "foo"; diff --git a/test/fixtures/syntax/modules-umd/exports-from/expected.js b/test/fixtures/syntax/modules-umd/exports-from/expected.js new file mode 100644 index 0000000000..a9eac93074 --- /dev/null +++ b/test/fixtures/syntax/modules-umd/exports-from/expected.js @@ -0,0 +1,23 @@ +"use strict"; + +(function (root, factory) { + if (typeof define === "function" && define.amd) { + define(["exports", "foo"], factory); + } else if (typeof exports !== "undefined") { + factory(exports, require("foo")); + } +})(this, function (exports, _foo) { + (function(obj) { + for (var i in obj) { + exports[i] = obj[i]; + } + })(_foo); + + exports.foo = _foo.foo; + exports.foo = _foo.foo; + exports.bar = _foo.bar; + exports.bar = _foo.foo; + exports.default = _foo.foo; + exports.default = _foo.foo; + exports.bar = _foo.bar; +}); diff --git a/test/fixtures/syntax/modules-umd/exports-named/actual.js b/test/fixtures/syntax/modules-umd/exports-named/actual.js new file mode 100644 index 0000000000..8515ace759 --- /dev/null +++ b/test/fixtures/syntax/modules-umd/exports-named/actual.js @@ -0,0 +1,5 @@ +export {foo}; +export {foo, bar}; +export {foo as bar}; +export {foo as default}; +export {foo as default, bar}; diff --git a/test/fixtures/syntax/modules-umd/exports-named/expected.js b/test/fixtures/syntax/modules-umd/exports-named/expected.js new file mode 100644 index 0000000000..8f40cd0dc3 --- /dev/null +++ b/test/fixtures/syntax/modules-umd/exports-named/expected.js @@ -0,0 +1,17 @@ +"use strict"; + +(function (root, factory) { + if (typeof define === "function" && define.amd) { + define(["exports"], factory); + } else if (typeof exports !== "undefined") { + factory(exports); + } +})(this, function (exports) { + exports.foo = foo; + exports.foo = foo; + exports.bar = bar; + exports.bar = foo; + exports.default = foo; + exports.default = foo; + exports.bar = bar; +}); diff --git a/test/fixtures/syntax/modules-umd/exports-variable/actual.js b/test/fixtures/syntax/modules-umd/exports-variable/actual.js new file mode 100644 index 0000000000..b4629cc731 --- /dev/null +++ b/test/fixtures/syntax/modules-umd/exports-variable/actual.js @@ -0,0 +1,8 @@ +export var foo = 1; +export var foo2 = function () {}; +export var foo3; +export let foo4 = 2; +export let foo5; +export const foo6 = 3; +export function foo7 () {} +export class foo8 {} diff --git a/test/fixtures/syntax/modules-umd/exports-variable/expected.js b/test/fixtures/syntax/modules-umd/exports-variable/expected.js new file mode 100644 index 0000000000..32c11d7a54 --- /dev/null +++ b/test/fixtures/syntax/modules-umd/exports-variable/expected.js @@ -0,0 +1,31 @@ +"use strict"; + +(function (root, factory) { + if (typeof define === "function" && define.amd) { + define(["exports"], factory); + } else if (typeof exports !== "undefined") { + factory(exports); + } +})(this, function (exports) { + exports.foo7 = foo7; + var foo = 1; + exports.foo = foo; + var foo2 = function() {}; + exports.foo2 = foo2; + var foo3; + exports.foo3 = foo3; + var _foo4 = 2; + exports.foo4 = _foo4; + var _foo5; + exports.foo5 = _foo5; + var _foo6 = 3; + exports.foo6 = _foo6; + function foo7() {} + + var foo8 = function() { + var foo8 = function foo8() {}; + return foo8; + }(); + + exports.foo8 = foo8; +}); diff --git a/test/fixtures/syntax/modules-umd/hoist-function-exports/actual.js b/test/fixtures/syntax/modules-umd/hoist-function-exports/actual.js new file mode 100644 index 0000000000..aa0f9366ae --- /dev/null +++ b/test/fixtures/syntax/modules-umd/hoist-function-exports/actual.js @@ -0,0 +1,11 @@ +import { isEven } from "./evens"; + +export function nextOdd(n) { + return isEven(n) ? n + 1 : n + 2; +} + +export var isOdd = (function(isEven) { + return function(n) { + return !isEven(n); + }; +})(isEven); diff --git a/test/fixtures/syntax/modules-umd/hoist-function-exports/expected.js b/test/fixtures/syntax/modules-umd/hoist-function-exports/expected.js new file mode 100644 index 0000000000..bac912b1f6 --- /dev/null +++ b/test/fixtures/syntax/modules-umd/hoist-function-exports/expected.js @@ -0,0 +1,24 @@ +"use strict"; + +(function (root, factory) { + if (typeof define === "function" && define.amd) { + define(["exports", "./evens"], factory); + } else if (typeof exports !== "undefined") { + factory(exports, require("./evens")); + } +})(this, function (exports, _evens) { + exports.nextOdd = nextOdd; + var isEven = _evens.isEven; + + function nextOdd(n) { + return (isEven(n) ? n + 1 : n + 2); + } + + var isOdd = function(isEven) { + return function(n) { + return !isEven(n); + }; + }(isEven); + + exports.isOdd = isOdd; +}); diff --git a/test/fixtures/syntax/modules-umd/imports-default/actual.js b/test/fixtures/syntax/modules-umd/imports-default/actual.js new file mode 100644 index 0000000000..e67418654c --- /dev/null +++ b/test/fixtures/syntax/modules-umd/imports-default/actual.js @@ -0,0 +1,2 @@ +import foo from "foo"; +import {default as foo} from "foo"; diff --git a/test/fixtures/syntax/modules-umd/imports-default/expected.js b/test/fixtures/syntax/modules-umd/imports-default/expected.js new file mode 100644 index 0000000000..6acee23c2b --- /dev/null +++ b/test/fixtures/syntax/modules-umd/imports-default/expected.js @@ -0,0 +1,12 @@ +"use strict"; + +(function (root, factory) { + if (typeof define === "function" && define.amd) { + define(["exports", "foo"], factory); + } else if (typeof exports !== "undefined") { + factory(exports, require("foo")); + } +})(this, function (exports, _foo) { + var foo = _foo.default; + var foo = _foo.default; +}); diff --git a/test/fixtures/syntax/modules-umd/imports-glob/actual.js b/test/fixtures/syntax/modules-umd/imports-glob/actual.js new file mode 100644 index 0000000000..e55c077500 --- /dev/null +++ b/test/fixtures/syntax/modules-umd/imports-glob/actual.js @@ -0,0 +1 @@ +import * as foo from "foo"; diff --git a/test/fixtures/syntax/modules-umd/imports-glob/expected.js b/test/fixtures/syntax/modules-umd/imports-glob/expected.js new file mode 100644 index 0000000000..fb5a921da1 --- /dev/null +++ b/test/fixtures/syntax/modules-umd/imports-glob/expected.js @@ -0,0 +1,11 @@ +"use strict"; + +(function (root, factory) { + if (typeof define === "function" && define.amd) { + define(["exports", "foo"], factory); + } else if (typeof exports !== "undefined") { + factory(exports, require("foo")); + } +})(this, function (exports, _foo) { + var foo = _foo; +}); diff --git a/test/fixtures/syntax/modules-umd/imports-mixing/actual.js b/test/fixtures/syntax/modules-umd/imports-mixing/actual.js new file mode 100644 index 0000000000..ef78c95b1c --- /dev/null +++ b/test/fixtures/syntax/modules-umd/imports-mixing/actual.js @@ -0,0 +1 @@ +import foo, {baz as xyz} from "foo"; diff --git a/test/fixtures/syntax/modules-umd/imports-mixing/expected.js b/test/fixtures/syntax/modules-umd/imports-mixing/expected.js new file mode 100644 index 0000000000..102bd20f80 --- /dev/null +++ b/test/fixtures/syntax/modules-umd/imports-mixing/expected.js @@ -0,0 +1,12 @@ +"use strict"; + +(function (root, factory) { + if (typeof define === "function" && define.amd) { + define(["exports", "foo"], factory); + } else if (typeof exports !== "undefined") { + factory(exports, require("foo")); + } +})(this, function (exports, _foo) { + var foo = _foo.default; + var xyz = _foo.baz; +}); diff --git a/test/fixtures/syntax/modules-umd/imports-named/actual.js b/test/fixtures/syntax/modules-umd/imports-named/actual.js new file mode 100644 index 0000000000..83a766c62d --- /dev/null +++ b/test/fixtures/syntax/modules-umd/imports-named/actual.js @@ -0,0 +1,4 @@ +import {bar} from "foo"; +import {bar, baz} from "foo"; +import {bar as baz} from "foo"; +import {bar as baz, xyz} from "foo"; diff --git a/test/fixtures/syntax/modules-umd/imports-named/expected.js b/test/fixtures/syntax/modules-umd/imports-named/expected.js new file mode 100644 index 0000000000..ed10909514 --- /dev/null +++ b/test/fixtures/syntax/modules-umd/imports-named/expected.js @@ -0,0 +1,16 @@ +"use strict"; + +(function (root, factory) { + if (typeof define === "function" && define.amd) { + define(["exports", "foo"], factory); + } else if (typeof exports !== "undefined") { + factory(exports, require("foo")); + } +})(this, function (exports, _foo) { + var bar = _foo.bar; + var bar = _foo.bar; + var baz = _foo.baz; + var baz = _foo.bar; + var baz = _foo.bar; + var xyz = _foo.xyz; +}); diff --git a/test/fixtures/syntax/modules-umd/imports/actual.js b/test/fixtures/syntax/modules-umd/imports/actual.js new file mode 100644 index 0000000000..222b6885ac --- /dev/null +++ b/test/fixtures/syntax/modules-umd/imports/actual.js @@ -0,0 +1,3 @@ +import "foo"; +import "foo-bar"; +import "./directory/foo-bar"; diff --git a/test/fixtures/syntax/modules-umd/imports/expected.js b/test/fixtures/syntax/modules-umd/imports/expected.js new file mode 100644 index 0000000000..656e51677d --- /dev/null +++ b/test/fixtures/syntax/modules-umd/imports/expected.js @@ -0,0 +1,11 @@ +"use strict"; + +(function (root, factory) { + if (typeof define === "function" && define.amd) { + define(["exports", "foo", "foo-bar", "./directory/foo-bar"], factory); + } else if (typeof exports !== "undefined") { + factory(exports, require("foo"), require("foo-bar"), require("./directory/foo-bar")); + } +})(this, function (exports, _foo, _fooBar, _directoryFooBar) { + +}); diff --git a/test/fixtures/syntax/modules-umd/overview/actual.js b/test/fixtures/syntax/modules-umd/overview/actual.js new file mode 100644 index 0000000000..a77d4d5dfa --- /dev/null +++ b/test/fixtures/syntax/modules-umd/overview/actual.js @@ -0,0 +1,12 @@ +import "foo"; +import "foo-bar"; +import "./directory/foo-bar"; +import foo from "foo"; +import * as foo from "foo"; +import {bar} from "foo"; +import {foo as bar} from "foo"; + +export {test}; +export var test = 5; + +export default test; diff --git a/test/fixtures/syntax/modules-umd/overview/expected.js b/test/fixtures/syntax/modules-umd/overview/expected.js new file mode 100644 index 0000000000..475ce88de8 --- /dev/null +++ b/test/fixtures/syntax/modules-umd/overview/expected.js @@ -0,0 +1,18 @@ +"use strict"; + +(function (root, factory) { + if (typeof define === "function" && define.amd) { + define(["exports", "foo", "foo-bar", "./directory/foo-bar"], factory); + } else if (typeof exports !== "undefined") { + factory(exports, require("foo"), require("foo-bar"), require("./directory/foo-bar")); + } +})(this, function (exports, _foo, _fooBar, _directoryFooBar) { + var foo = _foo.default; + var foo = _foo; + var bar = _foo.bar; + var bar = _foo.foo; + exports.test = test; + var test = 5; + exports.test = test; + exports.default = test; +});