diff --git a/test/_helper.js b/test/_helper.js index a988f30d73..8273a11443 100644 --- a/test/_helper.js +++ b/test/_helper.js @@ -1,5 +1,6 @@ -var fs = require("fs"); -var _ = require("lodash"); +var path = require("path"); +var fs = require("fs"); +var _ = require("lodash"); var humanise = function (val) { return val.replace(/-/g, " "); @@ -37,7 +38,6 @@ exports.get = function (entryName) { _.each(fs.readdirSync(suite.filename), function (taskName) { var taskDir = suite.filename + "/" + taskName; - if (fs.statSync(taskDir).isFile()) return; var actualLocAlias = suiteName + "/" + taskName + "/actual.js"; var expectLocAlias = suiteName + "/" + taskName + "/expected.js"; @@ -47,6 +47,13 @@ exports.get = function (entryName) { var expectLoc = taskDir + "/expected.js"; var execLoc = taskDir + "/exec.js"; + if (fs.statSync(taskDir).isFile()) { + var ext = path.extname(taskDir); + if (ext === ".json") return; + + execLoc = taskDir; + } + var taskOpts = _.merge({ filenameRelative: expectLocAlias, sourceFileName: actualLocAlias, diff --git a/test/fixtures/transformation/esnext-es6-arrow-functions/arguments-refers-to-parent-function.js b/test/fixtures/transformation/esnext-es6-arrow-functions/arguments-refers-to-parent-function.js new file mode 100644 index 0000000000..d299fb5379 --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-arrow-functions/arguments-refers-to-parent-function.js @@ -0,0 +1,57 @@ +function makeMultiplier() { + // `arguments` should refer to `makeMultiplier`'s arguments. + return (n) => [].slice.call(arguments).reduce((a, b) => a * b) * n; +} + +function toArray() { + // Intentionally nest arrow functions to ensure `arguments` is put inside + // `toArray`'s scope. + return (() => (arguments, (() => [].slice.call(arguments)).call())).call(); +} + +function returnDotArguments(object) { + // Ensure `arguments` is not treated as a reference to the magic value. + return (() => object.arguments).call(); +} + +function returnArgumentsObject() { + // Ensure `arguments` is not treated as a reference to the magic value. + return (() => ({arguments: 1})).call(); +} + +function makeArgumentsReturner() { + return (() => function() { + return [].slice.call(arguments); + }).call(); +} + +// i.e. 2 * 3 * 4 == 24, not 16 (4 * 4) +assert.equal( + makeMultiplier(2, 3)(4), + 24, + 'ensure `arguments` is hoisted out to the first non-arrow scope' +); + +assert.deepEqual( + toArray(1, 2, 3), + [1, 2, 3], + 'ensure `arguments` is hoisted out to the first non-arrow scope' +); + +assert.equal( + returnDotArguments({arguments: 1}), + 1, + 'member accesses with `arguments` property should not be replaced' +); + +assert.deepEqual( + returnArgumentsObject(), + {arguments: 1}, + 'object property keys named `arguments` should not be replaced' +); + +assert.deepEqual( + makeArgumentsReturner()(1, 2, 3), + [1, 2, 3], + 'arguments should not be hoisted from inside non-arrow functions' +); diff --git a/test/fixtures/transformation/esnext-es6-arrow-functions/does-not-bind-this-from-standard-function.js b/test/fixtures/transformation/esnext-es6-arrow-functions/does-not-bind-this-from-standard-function.js new file mode 100644 index 0000000000..c2eeddcc3e --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-arrow-functions/does-not-bind-this-from-standard-function.js @@ -0,0 +1,5 @@ +var dynamicThisGetter = () => function(){ return this; }; +assert.equal( + normalize('('+dynamicThisGetter.toString()+')'), + normalize('(function(){ return function(){ return this; }; })') +); diff --git a/test/fixtures/transformation/esnext-es6-arrow-functions/empty-arrow-function.js b/test/fixtures/transformation/esnext-es6-arrow-functions/empty-arrow-function.js new file mode 100644 index 0000000000..0b95435853 --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-arrow-functions/empty-arrow-function.js @@ -0,0 +1,2 @@ +var empty = () => {}; +assert.equal(empty(), undefined); diff --git a/test/fixtures/transformation/esnext-es6-arrow-functions/handles-nested-context-bindings.js b/test/fixtures/transformation/esnext-es6-arrow-functions/handles-nested-context-bindings.js new file mode 100644 index 0000000000..03041f0297 --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-arrow-functions/handles-nested-context-bindings.js @@ -0,0 +1,12 @@ +var obj = { + method: function() { + return () => (this, () => this); + }, + + method2: function() { + return () => () => this; + } +}; + +assert.strictEqual(obj.method()()(), obj); +assert.strictEqual(obj.method2()()(), obj); diff --git a/test/fixtures/transformation/esnext-es6-arrow-functions/no-parens-for-low-precedence-expression-body.js b/test/fixtures/transformation/esnext-es6-arrow-functions/no-parens-for-low-precedence-expression-body.js new file mode 100644 index 0000000000..66fad996e5 --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-arrow-functions/no-parens-for-low-precedence-expression-body.js @@ -0,0 +1,2 @@ +var square = x => x * x; +assert.equal(square(4), 16); diff --git a/test/fixtures/transformation/esnext-es6-arrow-functions/object-literal-needs-parens.js b/test/fixtures/transformation/esnext-es6-arrow-functions/object-literal-needs-parens.js new file mode 100644 index 0000000000..3ec553b180 --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-arrow-functions/object-literal-needs-parens.js @@ -0,0 +1,2 @@ +var keyMaker = val => ({ key: val }); +assert.deepEqual(keyMaker(9), { key: 9 }); diff --git a/test/fixtures/transformation/esnext-es6-arrow-functions/only-lexical-this-not-dynamic-this.js b/test/fixtures/transformation/esnext-es6-arrow-functions/only-lexical-this-not-dynamic-this.js new file mode 100644 index 0000000000..68f68c14dc --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-arrow-functions/only-lexical-this-not-dynamic-this.js @@ -0,0 +1,7 @@ +var obj = { + method: function() { + return () => this; + } +}; + +assert.strictEqual(obj.method()(), obj); diff --git a/test/fixtures/transformation/esnext-es6-arrow-functions/passed-to-function.js b/test/fixtures/transformation/esnext-es6-arrow-functions/passed-to-function.js new file mode 100644 index 0000000000..75fbefbacd --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-arrow-functions/passed-to-function.js @@ -0,0 +1,2 @@ +var odds = [0, 2, 4].map(v => v + 1); +assert.deepEqual(odds, [1, 3, 5]); diff --git a/test/fixtures/transformation/esnext-es6-arrow-functions/single-param-does-not-need-parens.js b/test/fixtures/transformation/esnext-es6-arrow-functions/single-param-does-not-need-parens.js new file mode 100644 index 0000000000..c2b56e7bbc --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-arrow-functions/single-param-does-not-need-parens.js @@ -0,0 +1,2 @@ +var identity = x => x; +assert.equal(identity(1), 1); diff --git a/test/fixtures/transformation/esnext-es6-classes/anonymous-class.js b/test/fixtures/transformation/esnext-es6-classes/anonymous-class.js new file mode 100644 index 0000000000..231ba49b9e --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-classes/anonymous-class.js @@ -0,0 +1,29 @@ +var Animal = class { + sayHi() { + return 'Hi, I am a '+this.type()+'.'; + } + + static getName() { + return 'Animal'; + } +}; + +var Dog = class extends Animal { + type() { return 'dog'; } + + sayHi() { + return super() + ' WOOF!'; + } + + static getName() { + return super() + '/Dog'; + } +}; + +assert.equal(new Dog().sayHi(), 'Hi, I am a dog. WOOF!'); +assert.equal(Dog.getName(), 'Animal/Dog'); + +var count = 0; +var Cat = class extends (function(){ count++; return Animal; })() {}; + +assert.equal(count, 1); diff --git a/test/fixtures/transformation/esnext-es6-classes/call-super-function.js b/test/fixtures/transformation/esnext-es6-classes/call-super-function.js new file mode 100644 index 0000000000..5c7efe0dc6 --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-classes/call-super-function.js @@ -0,0 +1,21 @@ +class Animal { + sayHi() { + return 'I am an animal.' + } + + sayOther() { + return 'WAT?!'; + } +} + +class Horse extends Animal { + sayHi() { + return super.sayOther(); + } + + sayOther() { + return 'I see dead objects.'; + } +} + +assert.equal(new Horse().sayHi(), 'WAT?!'); diff --git a/test/fixtures/transformation/esnext-es6-classes/class-expressions.js b/test/fixtures/transformation/esnext-es6-classes/class-expressions.js new file mode 100644 index 0000000000..1c2bb96a80 --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-classes/class-expressions.js @@ -0,0 +1,9 @@ +var Person = (class Person {}); +assert.equal(typeof Person, 'function'); + +assert.equal( + (function(){ return (class Person {}); })().name, + 'Person' +); + +assert.equal(typeof (class {}), 'function'); diff --git a/test/fixtures/transformation/esnext-es6-classes/class-extend.js b/test/fixtures/transformation/esnext-es6-classes/class-extend.js new file mode 100644 index 0000000000..56035dd0b6 --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-classes/class-extend.js @@ -0,0 +1,15 @@ +class Animal { + sayHi() { + return 'Hi, I am a '+this.type()+'.'; + } +} + +class Dog extends Animal { + type() { return 'dog'; } + + sayHi() { + return super() + ' WOOF!'; + } +} + +assert.equal(new Dog().sayHi(), 'Hi, I am a dog. WOOF!'); diff --git a/test/fixtures/transformation/esnext-es6-classes/class-with-constructor.js b/test/fixtures/transformation/esnext-es6-classes/class-with-constructor.js new file mode 100644 index 0000000000..4dcf3296f0 --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-classes/class-with-constructor.js @@ -0,0 +1,14 @@ +class Multiplier { + constructor(n=1) { + this.n = n; + } + + multiply(n=1) { + return n * this.n; + } +} + +assert.equal(new Multiplier().n, 1); +assert.equal(new Multiplier(6).n, 6); +assert.equal(new Multiplier().multiply(), 1); +assert.equal(new Multiplier(2).multiply(3), 6); diff --git a/test/fixtures/transformation/esnext-es6-classes/class-with-method-declaration.js b/test/fixtures/transformation/esnext-es6-classes/class-with-method-declaration.js new file mode 100644 index 0000000000..f8d9d7a207 --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-classes/class-with-method-declaration.js @@ -0,0 +1,10 @@ +class Person { + getName() { + return this.firstName + ' ' + this.lastName; + } +} + +var me = new Person(); +me.firstName = 'Brian'; +me.lastName = 'Donovan'; +assert.equal(me.getName(), 'Brian Donovan'); diff --git a/test/fixtures/transformation/esnext-es6-classes/empty-named-class.js b/test/fixtures/transformation/esnext-es6-classes/empty-named-class.js new file mode 100644 index 0000000000..602a6702d3 --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-classes/empty-named-class.js @@ -0,0 +1,5 @@ +class Foo { +} + +assert.equal(new Foo().constructor, Foo, 'Foo instances should have Foo as constructor'); +assert.ok(new Foo() instanceof Foo, 'Foo instances should be `instanceof` Foo'); diff --git a/test/fixtures/transformation/esnext-es6-classes/enumerable.js b/test/fixtures/transformation/esnext-es6-classes/enumerable.js new file mode 100644 index 0000000000..fe5c02d113 --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-classes/enumerable.js @@ -0,0 +1,20 @@ +class Point { + constructor(x, y) { + this.x = x; + this.y = y; + } + + toString() { + return '(' + this.x + ', ' + this.y + ')'; + } +} + +var point = new Point(1, 2); +var keys = []; + +for (var key in point) { + keys.push(key); +} + +assert.equal(point.toString(), '(1, 2)'); +assert.deepEqual(keys.sort(), ['x', 'y']); diff --git a/test/fixtures/transformation/esnext-es6-classes/explicit-super-in-constructor.js b/test/fixtures/transformation/esnext-es6-classes/explicit-super-in-constructor.js new file mode 100644 index 0000000000..d30f21cba5 --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-classes/explicit-super-in-constructor.js @@ -0,0 +1,15 @@ +class Point { + constructor(x, y) { + this.x = x; + this.y = y; + } +} + +class ZeroPoint extends Point { + constructor() { + super(0, 0); + } +} + +assert.equal(new ZeroPoint().x, 0); +assert.equal(new ZeroPoint().y, 0); diff --git a/test/fixtures/transformation/esnext-es6-classes/extends-null.js b/test/fixtures/transformation/esnext-es6-classes/extends-null.js new file mode 100644 index 0000000000..fa3821d8c7 --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-classes/extends-null.js @@ -0,0 +1,4 @@ +class Obj extends null {} + +assert.strictEqual(Obj.toString, Function.toString); +assert.strictEqual(new Obj().toString, undefined); diff --git a/test/fixtures/transformation/esnext-es6-classes/getter-setter-super.js b/test/fixtures/transformation/esnext-es6-classes/getter-setter-super.js new file mode 100644 index 0000000000..98d7bc0eea --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-classes/getter-setter-super.js @@ -0,0 +1,15 @@ +class Animal { + get sound() { + return 'I am a ' + this.type + '.'; + } +} + +class Cat extends Animal { + get type() { return 'cat'; } + + get sound() { + return super.sound + ' MEOW!'; + } +} + +assert.equal(new Cat().sound, 'I am a cat. MEOW!'); diff --git a/test/fixtures/transformation/esnext-es6-classes/getter-setter.js b/test/fixtures/transformation/esnext-es6-classes/getter-setter.js new file mode 100644 index 0000000000..8f9519f9ba --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-classes/getter-setter.js @@ -0,0 +1,28 @@ +class Person { + constructor(firstName, lastName) { + this.firstName = firstName; + this.lastName = lastName; + } + + get name() { + return this.firstName + ' ' + this.lastName; + } + + set name(name) { + var parts = name.split(' '); + this.firstName = parts[0]; + this.lastName = parts[1]; + } +} + +var mazer = new Person('Mazer', 'Rackham'); +assert.equal(mazer.name, 'Mazer Rackham'); +mazer.name = 'Ender Wiggin'; +assert.equal(mazer.firstName, 'Ender'); +assert.equal(mazer.lastName, 'Wiggin'); + +var forLoopProperties = []; +for (var key in mazer) { + forLoopProperties.push(key); +} +assert.ok(forLoopProperties.indexOf('name') >= 0, 'getters/setters are enumerable'); diff --git a/test/fixtures/transformation/esnext-es6-classes/implicit-superclass.js b/test/fixtures/transformation/esnext-es6-classes/implicit-superclass.js new file mode 100644 index 0000000000..96755df101 --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-classes/implicit-superclass.js @@ -0,0 +1,9 @@ +class Obj { + constructor() { + super(); + } +} + +assert.doesNotThrow(function() { + new Obj(); +}); diff --git a/test/fixtures/transformation/esnext-es6-classes/method-declaration-with-arguments.js b/test/fixtures/transformation/esnext-es6-classes/method-declaration-with-arguments.js new file mode 100644 index 0000000000..b70c56e68c --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-classes/method-declaration-with-arguments.js @@ -0,0 +1,7 @@ +class Tripler { + triple(n) { + return n * 3; + } +} + +assert.equal(new Tripler().triple(2), 6); diff --git a/test/fixtures/transformation/esnext-es6-classes/methods-are-writable.js b/test/fixtures/transformation/esnext-es6-classes/methods-are-writable.js new file mode 100644 index 0000000000..19ffd5aa73 --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-classes/methods-are-writable.js @@ -0,0 +1,12 @@ +var value; + +class Foo { + foo() { + value = 1; + } +} + +var foo = new Foo(); +foo.foo = function() { value = 2; }; +foo.foo(); +assert.equal(value, 2); diff --git a/test/fixtures/transformation/esnext-es6-classes/methods-with-rest-params.js b/test/fixtures/transformation/esnext-es6-classes/methods-with-rest-params.js new file mode 100644 index 0000000000..77b7bb0774 --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-classes/methods-with-rest-params.js @@ -0,0 +1,28 @@ +class Joiner { + constructor(string) { + this.string = string; + } + + join(...items) { + return items.join(this.string); + } + + static join(string, ...items) { + var joiner = new this(string); + // TODO: use spread params here + return joiner.join.apply(joiner, items); + } +} + +class ArrayLike { + constructor(...items) { + items.forEach(function(item, i) { + this[i] = item; + }.bind(this)); + this.length = items.length; + } +} + +var joiner = new Joiner(' & '); +assert.equal(joiner.join(4, 5, 6), '4 & 5 & 6'); +assert.equal(new ArrayLike('a', 'b')[1], 'b'); diff --git a/test/fixtures/transformation/esnext-es6-classes/static-getter.js b/test/fixtures/transformation/esnext-es6-classes/static-getter.js new file mode 100644 index 0000000000..af9fe0afe6 --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-classes/static-getter.js @@ -0,0 +1,12 @@ +class Point { + constructor(x, y) { + this.x = x; + this.y = y; + } + + static get ORIGIN() { + return new this(0, 0); + } +} + +assert.deepEqual(Point.ORIGIN, new Point(0, 0)); \ No newline at end of file diff --git a/test/fixtures/transformation/esnext-es6-classes/static-method.js b/test/fixtures/transformation/esnext-es6-classes/static-method.js new file mode 100644 index 0000000000..564fb13c5b --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-classes/static-method.js @@ -0,0 +1,30 @@ +class Tripler { + static triple(n=1) { + return n * 3; + } + + static toString() { + return '3' + super() + '3'; + } +} + +class MegaTripler extends Tripler { + static triple(n=1) { + return super(n) * super(n); + } +} + +var tripler = new Tripler(); + +assert.equal(Tripler.triple(), 3); +assert.equal(Tripler.triple(2), 6); +assert.equal(tripler.triple, undefined); + +assert.equal(Tripler.toString(), '3' + Object.toString.call(Tripler) + '3'); + +var mega = new MegaTripler(); + +assert.equal(MegaTripler.triple(2), 36); +assert.equal(mega.triple, undefined); + +assert.equal(MegaTripler.toString(), '3' + Object.toString.call(MegaTripler) + '3'); diff --git a/test/fixtures/transformation/esnext-es6-classes/static-setter.js b/test/fixtures/transformation/esnext-es6-classes/static-setter.js new file mode 100644 index 0000000000..08fae30af5 --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-classes/static-setter.js @@ -0,0 +1,7 @@ +class Person { + static set DB(value) { + assert.equal(value, 'mysql'); + } +} + +Person.DB = 'mysql'; diff --git a/test/fixtures/transformation/esnext-es6-classes/strict-mode.js b/test/fixtures/transformation/esnext-es6-classes/strict-mode.js new file mode 100644 index 0000000000..d3ece2608e --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-classes/strict-mode.js @@ -0,0 +1,23 @@ +class StrictModeTest { + test() { + var implicitThisInsideClassBody = (function() { + return this; + })(); + assert.strictEqual( + implicitThisInsideClassBody, + undefined, + 'implicit `this` inside class body is undefined' + ); + } +} + +new StrictModeTest().test(); + +var implicitThisOutsideClass = (function() { + return this; +})(); +assert.notStrictEqual( + implicitThisOutsideClass, + undefined, + 'implicit `this` outside class body is not undefined' +); diff --git a/test/fixtures/transformation/esnext-es6-classes/super-change-proto.js b/test/fixtures/transformation/esnext-es6-classes/super-change-proto.js new file mode 100644 index 0000000000..d0012cfc0b --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-classes/super-change-proto.js @@ -0,0 +1,20 @@ +var log = ''; + +class Base { + p() { log += '[Base]'; } +} + +class OtherBase { + p() { log += '[OtherBase]'; } +} +class Derived extends Base { + p() { + log += '[Derived]'; + super(); + Derived.prototype.__proto__ = OtherBase.prototype; + super(); + } +} + +new Derived().p(); +assert.equal(log, '[Derived][Base][OtherBase]'); diff --git a/test/fixtures/transformation/esnext-es6-computed-properties/accessor.js b/test/fixtures/transformation/esnext-es6-computed-properties/accessor.js new file mode 100644 index 0000000000..bedcb7785a --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-computed-properties/accessor.js @@ -0,0 +1,8 @@ +var x = 'y'; + +var foo = { + get [x]() { return this._y; }, + set [x](v) { this._y = v; } +}; + +assert.equal((foo.y = 10, foo.y), 10); diff --git a/test/fixtures/transformation/esnext-es6-computed-properties/method.js b/test/fixtures/transformation/esnext-es6-computed-properties/method.js new file mode 100644 index 0000000000..e28e4d18d5 --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-computed-properties/method.js @@ -0,0 +1,3 @@ +var x = 'y'; +assert.equal({[x]: function() { return 10; }}.y(), 10); +assert.equal({[x + 'y']() { return 10; }}.yy(), 10); diff --git a/test/fixtures/transformation/esnext-es6-computed-properties/nested.js b/test/fixtures/transformation/esnext-es6-computed-properties/nested.js new file mode 100644 index 0000000000..ea11b2c6f6 --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-computed-properties/nested.js @@ -0,0 +1,4 @@ +var x = 'y'; +var foo = {[x]: 10, z: {[x]: 10}}; +assert.equal(foo.y + foo.z.y, 20); +assert.equal({[x]: {[x]: {[x]: 10}}}.y.y.y, 10); diff --git a/test/fixtures/transformation/esnext-es6-computed-properties/simple.js b/test/fixtures/transformation/esnext-es6-computed-properties/simple.js new file mode 100644 index 0000000000..21e56afe58 --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-computed-properties/simple.js @@ -0,0 +1,3 @@ +var x = 'y'; +assert.equal({[x]: 10}.y, 10); +assert.equal({[x + 'y']: 10}.yy, 10); diff --git a/test/fixtures/transformation/esnext-es6-default-parameters/arity.js b/test/fixtures/transformation/esnext-es6-default-parameters/arity.js new file mode 100644 index 0000000000..030f3e08ea --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-default-parameters/arity.js @@ -0,0 +1,3 @@ +assert.equal((function(a){}).length, 1); +assert.equal((function(a=5){}).length, 0); +assert.equal((function(a, b, c=5){}).length, 2); diff --git a/test/fixtures/transformation/esnext-es6-default-parameters/arrow-function.js b/test/fixtures/transformation/esnext-es6-default-parameters/arrow-function.js new file mode 100644 index 0000000000..66c0068d94 --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-default-parameters/arrow-function.js @@ -0,0 +1,8 @@ +function makeMultiplier(x=1) { + return (y=1) => x * y; +} + +assert.equal(makeMultiplier()(), 1); +assert.equal(makeMultiplier(2)(3), 6); +assert.deepEqual([1, 2, 3].map(makeMultiplier(2)), [2, 4, 6]); +assert.deepEqual([undefined, null, 0].map(makeMultiplier(2)), [2, 0, 0]); diff --git a/test/fixtures/transformation/esnext-es6-default-parameters/null-vs-undefined.js b/test/fixtures/transformation/esnext-es6-default-parameters/null-vs-undefined.js new file mode 100644 index 0000000000..b028ba3e09 --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-default-parameters/null-vs-undefined.js @@ -0,0 +1,5 @@ +function foo(x=5, y=6) { + return [x, y]; +} + +assert.deepEqual(foo(undefined, null), [5, null]); diff --git a/test/fixtures/transformation/esnext-es6-default-parameters/scope.js b/test/fixtures/transformation/esnext-es6-default-parameters/scope.js new file mode 100644 index 0000000000..54848cd8f2 --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-default-parameters/scope.js @@ -0,0 +1,11 @@ +function call(fn, context=this) { + return fn.call(context); +} + +var context = {a: 99}; + +// use the default parameter +assert.strictEqual(call.call(context, function(){ return this.a; }), 99); + +// explicitly provide the default parameter value +assert.strictEqual(call(function(){ return this.a; }, context), 99); diff --git a/test/fixtures/transformation/esnext-es6-default-parameters/simple-function.js b/test/fixtures/transformation/esnext-es6-default-parameters/simple-function.js new file mode 100644 index 0000000000..d7bf1bfa1c --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-default-parameters/simple-function.js @@ -0,0 +1,4 @@ +function foo(x=5) { + return x; +} +assert.equal(foo(), 5); diff --git a/test/fixtures/transformation/esnext-es6-object-concise/method-arguments.js b/test/fixtures/transformation/esnext-es6-object-concise/method-arguments.js new file mode 100644 index 0000000000..392586fc9b --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-object-concise/method-arguments.js @@ -0,0 +1,7 @@ +var a = { + echo(c) { + return c; + } +}; + +assert.strictEqual(a.echo(1), 1); diff --git a/test/fixtures/transformation/esnext-es6-object-concise/method-context.js b/test/fixtures/transformation/esnext-es6-object-concise/method-context.js new file mode 100644 index 0000000000..53c4bf3bc7 --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-object-concise/method-context.js @@ -0,0 +1,9 @@ +var a = { + b() { + return this; + } +}; + +var context = {}; +assert.strictEqual(a.b(), a); +assert.strictEqual(a.b.call(context), context); \ No newline at end of file diff --git a/test/fixtures/transformation/esnext-es6-object-concise/method-has-name.js b/test/fixtures/transformation/esnext-es6-object-concise/method-has-name.js new file mode 100644 index 0000000000..320ec33b54 --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-object-concise/method-has-name.js @@ -0,0 +1,7 @@ +var a = { + b() { + return 'c'; + } +}; + +assert.equal(a.b.name, 'b'); diff --git a/test/fixtures/transformation/esnext-es6-object-concise/method-is-not-in-scope-inside.js b/test/fixtures/transformation/esnext-es6-object-concise/method-is-not-in-scope-inside.js new file mode 100644 index 0000000000..4f58980df0 --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-object-concise/method-is-not-in-scope-inside.js @@ -0,0 +1,9 @@ +var b = 1; + +var a = { + b() { + return b; + } +}; + +assert.equal(a.b(), 1); diff --git a/test/fixtures/transformation/esnext-es6-object-concise/method-to-string.js b/test/fixtures/transformation/esnext-es6-object-concise/method-to-string.js new file mode 100644 index 0000000000..ba3f86cb78 --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-object-concise/method-to-string.js @@ -0,0 +1,10 @@ +var a = { + b() { + return b; + } +}; + +assert.ok( + /return b/.test(a.b.toString()), + 'toString contains body' +); \ No newline at end of file diff --git a/test/fixtures/transformation/esnext-es6-object-concise/method.js b/test/fixtures/transformation/esnext-es6-object-concise/method.js new file mode 100644 index 0000000000..1707a7aebb --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-object-concise/method.js @@ -0,0 +1,7 @@ +var a = { + b() { + return 'c'; + } +}; + +assert.equal(a.b(), 'c'); diff --git a/test/fixtures/transformation/esnext-es6-rest-parameters/arrow-fn.js b/test/fixtures/transformation/esnext-es6-rest-parameters/arrow-fn.js new file mode 100644 index 0000000000..34c96f5ecb --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-rest-parameters/arrow-fn.js @@ -0,0 +1,8 @@ +/* jshint esnext: true */ +/* global expect */ + +var join = (joinStr, ...items) => { + return items.join(joinStr); +}; + +expect(join(' ', 'a', 'b', 'c')).to.equal('a b c'); diff --git a/test/fixtures/transformation/esnext-es6-rest-parameters/declaration.js b/test/fixtures/transformation/esnext-es6-rest-parameters/declaration.js new file mode 100644 index 0000000000..1cc45ac46f --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-rest-parameters/declaration.js @@ -0,0 +1,8 @@ +/* jshint esnext: true */ +/* global expect */ + +function join(joinStr, ...items) { + return items.join(joinStr); +} + +expect(join(' ', 'a', 'b', 'c')).to.equal('a b c'); diff --git a/test/fixtures/transformation/esnext-es6-rest-parameters/rest.js b/test/fixtures/transformation/esnext-es6-rest-parameters/rest.js new file mode 100644 index 0000000000..9d0e63e85d --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-rest-parameters/rest.js @@ -0,0 +1,8 @@ +/* jshint esnext: true */ +/* global expect */ + +var join = function(joinStr, ...items) { + return items.join(joinStr); +}; + +expect(join(' ', 'a', 'b', 'c')).to.equal('a b c'); diff --git a/test/fixtures/transformation/esnext-es6-spread/arguments-as-array.js b/test/fixtures/transformation/esnext-es6-spread/arguments-as-array.js new file mode 100644 index 0000000000..d0957e35b4 --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-spread/arguments-as-array.js @@ -0,0 +1,6 @@ +function arrayOf() { + return [...arguments]; +} + +assert.equal(Object.prototype.toString.call(arrayOf()), '[object Array]'); +assert.deepEqual(arrayOf(1, 2, 3), [1, 2, 3]); diff --git a/test/fixtures/transformation/esnext-es6-spread/array-literal.js b/test/fixtures/transformation/esnext-es6-spread/array-literal.js new file mode 100644 index 0000000000..3c1bea826f --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-spread/array-literal.js @@ -0,0 +1,3 @@ +var names = ['Brian', 'Madeline']; +assert.deepEqual(['Thomas', ...names], ['Thomas', 'Brian', 'Madeline']); +assert.deepEqual([1, 2, ...[3, 4, 5]], [1, 2, 3, 4, 5]); diff --git a/test/fixtures/transformation/esnext-es6-spread/call-with-array-literal.js b/test/fixtures/transformation/esnext-es6-spread/call-with-array-literal.js new file mode 100644 index 0000000000..19cffabc6d --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-spread/call-with-array-literal.js @@ -0,0 +1,5 @@ +function sum(...numbers) { + return numbers.reduce(function(sum, n) { return n + sum; }, 0); +} + +assert.equal(sum(4, 5, ...[10, 20, 30]), 69); diff --git a/test/fixtures/transformation/esnext-es6-spread/inside-function-expression.js b/test/fixtures/transformation/esnext-es6-spread/inside-function-expression.js new file mode 100644 index 0000000000..c2c06da399 --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-spread/inside-function-expression.js @@ -0,0 +1,10 @@ +var object = { + list: [], + + append: function(...items) { + this.list.push(...items); + } +}; + +object.append(1, 2, ...[3, 4]); +assert.deepEqual(object.list, [1, 2, 3, 4]); diff --git a/test/fixtures/transformation/esnext-es6-spread/iterator.js b/test/fixtures/transformation/esnext-es6-spread/iterator.js new file mode 100644 index 0000000000..438e7564de --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-spread/iterator.js @@ -0,0 +1,19 @@ +function Symbol() {} +Symbol.iterator = '@@iterator'; + +var obj = { + '@@iterator': function() { + var ttl = 3; + return { + next: function() { + if (ttl === 0) { + return { done: true, value: null }; + } else { + return { done: false, value: ttl-- }; + } + } + }; + } +}; + +assert.deepEqual([3, 2, 1], [...obj]); diff --git a/test/fixtures/transformation/esnext-es6-spread/new-object.js b/test/fixtures/transformation/esnext-es6-spread/new-object.js new file mode 100644 index 0000000000..6e4af74279 --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-spread/new-object.js @@ -0,0 +1,11 @@ +var callCount = 0; +function getArray() { + callCount++; + return Array; +} + +assert.deepEqual([1, 2, 3], new Array(...[1, 2, 3])); + +// Ensure the expression of the function being initialized is not copied. +assert.deepEqual([1, 2, 3], new (getArray())(...[1, 2, 3])); +assert.equal(callCount, 1); diff --git a/test/fixtures/transformation/esnext-es6-spread/preserve-context.js b/test/fixtures/transformation/esnext-es6-spread/preserve-context.js new file mode 100644 index 0000000000..e63f88e788 --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-spread/preserve-context.js @@ -0,0 +1,35 @@ +var MATH = { + sum: function(...numbers) { + return numbers.reduce(this.add, 0); + }, + + add: function(a, b) { + return a + b; + } +}; + +assert.equal(MATH.sum(1, ...[2, 3]), 6); + +// Ensure that the below does not expand to this: +// +// obj.getSelf().call.apply(obj.getSelf(), []); +// + +var ops = []; +var obj = { + getSelf: function() { + ops.push('getSelf'); + return this; + }, + + doCall: function() { + ops.push('doCall', this); + } +}; + +obj.getSelf().doCall(...[]); +assert.deepEqual(ops, ['getSelf', 'doCall', obj]); + +ops = []; +obj['getSelf']().doCall(...[]); +assert.deepEqual(ops, ['getSelf', 'doCall', obj]); diff --git a/test/fixtures/transformation/esnext-es6-spread/simple-function-call.js b/test/fixtures/transformation/esnext-es6-spread/simple-function-call.js new file mode 100644 index 0000000000..106bfa55be --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-spread/simple-function-call.js @@ -0,0 +1,6 @@ +function sum(...numbers) { + return numbers.reduce(function(sum, n) { return n + sum; }, 0); +} + +var numbers = [1, 2, 3]; +assert.equal(sum(...numbers), 6); diff --git a/test/fixtures/transformation/esnext-es6-templates/multi-line.js b/test/fixtures/transformation/esnext-es6-templates/multi-line.js new file mode 100644 index 0000000000..6d1be1c2bc --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-templates/multi-line.js @@ -0,0 +1,4 @@ +var s = `a + b + c`; +assert.equal(s, 'a\n b\n c'); diff --git a/test/fixtures/transformation/esnext-es6-templates/nested-interpolation.js b/test/fixtures/transformation/esnext-es6-templates/nested-interpolation.js new file mode 100644 index 0000000000..83083e9fd0 --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-templates/nested-interpolation.js @@ -0,0 +1,4 @@ +assert.strictEqual( + `a${1}b${`${1+1}c`}3`, + 'a1b2c3' +); diff --git a/test/fixtures/transformation/esnext-es6-templates/no-interpolation.js b/test/fixtures/transformation/esnext-es6-templates/no-interpolation.js new file mode 100644 index 0000000000..1854b04ff5 --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-templates/no-interpolation.js @@ -0,0 +1,2 @@ +var s = `str`; +assert.equal(s, 'str'); diff --git a/test/fixtures/transformation/esnext-es6-templates/raw-tagged-template-expression.js b/test/fixtures/transformation/esnext-es6-templates/raw-tagged-template-expression.js new file mode 100644 index 0000000000..831ad050ab --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-templates/raw-tagged-template-expression.js @@ -0,0 +1,6 @@ +function r(strings) { + assert.equal(strings.raw[0], '\\n'); + return strings.raw.join(''); +} + +assert.equal(r `\n`, '\\n'); diff --git a/test/fixtures/transformation/esnext-es6-templates/simple-interpolation.js b/test/fixtures/transformation/esnext-es6-templates/simple-interpolation.js new file mode 100644 index 0000000000..b96a02a543 --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-templates/simple-interpolation.js @@ -0,0 +1,2 @@ +var s = `1 + 1 = ${1 + 1}`; +assert.equal(s, '1 + 1 = 2'); diff --git a/test/fixtures/transformation/esnext-es6-templates/tagged-template-expression.js b/test/fixtures/transformation/esnext-es6-templates/tagged-template-expression.js new file mode 100644 index 0000000000..5b894c55ac --- /dev/null +++ b/test/fixtures/transformation/esnext-es6-templates/tagged-template-expression.js @@ -0,0 +1,26 @@ +function tag(strings) { + var values = [].slice.call(arguments, 1); + assert.equal(strings[0], 'a'); + assert.equal(strings[1], 'b'); + assert.equal(values[0], 42); + return 'whatever'; +} +assert.equal(tag `a${ 42 }b`, 'whatever'); + +function tagInterpolateFirst(strings) { + var values = [].slice.call(arguments, 1); + assert.equal(strings[0], ''); + assert.equal(strings[1], 'b'); + assert.equal(values[0], 42); + return 'whatever'; +} +assert.equal(tagInterpolateFirst `${ 42 }b`, 'whatever'); + +function tagInterpolateLast(strings) { + var values = [].slice.call(arguments, 1); + assert.equal(strings[0], 'a'); + assert.equal(strings[1], ''); + assert.equal(values[0], 42); + return 'whatever'; +} +assert.equal(tagInterpolateLast `a${ 42 }`, 'whatever');