react / react-0.13.3 / examples / basic-commonjs / node_modules / reactify / node_modules / jstransform / visitors / __tests__ / es6-class-visitors-test.js
81153 views/**1* Copyright 2013 Facebook, Inc.2*3* Licensed under the Apache License, Version 2.0 (the "License");4* you may not use this file except in compliance with the License.5* You may obtain a copy of the License at6*7* http://www.apache.org/licenses/LICENSE-2.08*9* Unless required by applicable law or agreed to in writing, software10* distributed under the License is distributed on an "AS IS" BASIS,11* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.12* See the License for the specific language governing permissions and13* limitations under the License.14*15* @emails [email protected]16*/1718/*jshint evil:true*/1920jest.autoMockOff();2122describe('es6-classes', function() {23var transformFn;24var classVisitors;25var arrowFunctionVisitors;26var visitors;2728beforeEach(function() {29require('mock-modules').dumpCache();3031transformFn = require('../../src/jstransform').transform;3233classVisitors = require('../es6-class-visitors').visitorList;34arrowFunctionVisitors = require('../es6-arrow-function-visitors').visitorList;3536visitors = classVisitors.concat(arrowFunctionVisitors);37});3839function transform(code, opts) {40return transformFn(visitors, code, opts).code;41}4243describe('ClassDeclarations', function() {44describe('preserves line numbers', function() {45it('does not add "use strict" unless necessary', function() {46var code = [47'function strictStuff() {',48' "use strict";',49' class A {',50' foo() {}',51' }',52'}',53'class B {',54' bar() {',55' class C {}',56' }',57'}'58].join('\n');5960var expected = [61'function strictStuff() {',62' "use strict";',63' function A(){}',64' A.prototype.foo=function() {};',65' ',66'}',67'function B(){"use strict";}',68' B.prototype.bar=function() {"use strict";',69' function C(){}',70' };',71''72].join('\n');7374expect(transform(code)).toBe(expected);75});7677it('preserves lines with no inheritance', function() {78var code = [79'"use strict";',80'class Foo {',81' foo() {',82' ',83' ',84' }',85'',86' constructor(p1,',87' p2) {',88'',89' this.p1 = p1;',90' this.p2 = p2;',91' }',92'',93' bar(){}',94' static baz() {',95'}',96'}'97].join('\n');9899var expected = [100'"use strict";',101'',102' Foo.prototype.foo=function() {',103' ',104' ',105' };',106'',107' function Foo(p1,',108' p2) {',109'',110' this.p1 = p1;',111' this.p2 = p2;',112' }',113'',114' Foo.prototype.bar=function(){};',115' Foo.baz=function() {',116'};',117''118].join('\n');119120expect(transform(code)).toBe(expected);121});122123it('preserves lines with inheritance from identifier', function() {124var code = [125'class Foo extends Bar {',126' foo() {',127' ',128' ',129' super(p1,',130' p2);',131' }',132'',133' constructor(p1,',134' p2) {',135'',136' this.p1 = p1;',137' this.p2 = p2;',138' super.blah(p1,',139' p2);',140' }',141'',142' bar(){}',143' static baz() {',144'}',145'}'146].join('\n');147148var expected = [149'for(var Bar____Key in Bar){' +150'if(Bar.hasOwnProperty(Bar____Key)){' +151'Foo[Bar____Key]=Bar[Bar____Key];' +152'}' +153'}' +154'var ____SuperProtoOfBar=' +155'Bar===null' +156'?null:' +157'Bar.prototype;' +158'Foo.prototype=Object.create(____SuperProtoOfBar);' +159'Foo.prototype.constructor=Foo;' +160'Foo.__superConstructor__=Bar;',161162' Foo.prototype.foo=function() {"use strict";',163' ',164' ',165' ____SuperProtoOfBar.foo.call(this,p1,',166' p2);',167' };',168'',169' function Foo(p1,',170' p2) {"use strict";',171'',172' this.p1 = p1;',173' this.p2 = p2;',174' ____SuperProtoOfBar.blah.call(this,p1,',175' p2);',176' }',177'',178' Foo.prototype.bar=function(){"use strict";};',179' Foo.baz=function() {"use strict";',180'};',181''182].join('\n');183184expect(transform(code)).toBe(expected);185});186187it('preserves lines with inheritance from expression', function() {188var code = [189'class Foo extends mixin(Bar, Baz) {',190' foo() {',191' ',192' ',193' }',194'',195' constructor(p1,',196' p2) {',197'',198' this.p1 = p1;',199' this.p2 = p2;',200' }',201'',202' bar(){}',203' static baz() {',204'}',205'}'206].join('\n');207208var expected = [209'var ____Class0=mixin(Bar, Baz);' +210'for(var ____Class0____Key in ____Class0){' +211'if(____Class0.hasOwnProperty(____Class0____Key)){' +212'Foo[____Class0____Key]=____Class0[____Class0____Key];' +213'}' +214'}' +215'var ____SuperProtoOf____Class0=' +216'____Class0===null' +217'?null' +218':____Class0.prototype;' +219'Foo.prototype=Object.create(____SuperProtoOf____Class0);' +220'Foo.prototype.constructor=Foo;' +221'Foo.__superConstructor__=____Class0;',222223' Foo.prototype.foo=function() {"use strict";',224' ',225' ',226' };',227'',228' function Foo(p1,',229' p2) {"use strict";',230'',231' this.p1 = p1;',232' this.p2 = p2;',233' }',234'',235' Foo.prototype.bar=function(){"use strict";};',236' Foo.baz=function() {"use strict";',237'};',238''239].join('\n');240241expect(transform(code)).toBe(expected);242});243});244245describe('functional tests', function() {246it('handles an empty body', function() {247var code = transform(248'class Foo {}'249);250251eval(code);252253var fooInst = new Foo();254expect(fooInst instanceof Foo).toBe(true);255});256257it('handles constructors without params', function() {258var code = transform([259'class Foo {',260' constructor() {',261' this.test = "testValue";',262' }',263'}'264].join('\n'));265266eval(code);267268var fooInst = new Foo();269expect(fooInst.test).toBe('testValue');270});271272it('handles constructors with params', function() {273var code = transform([274'class Foo {',275' constructor(p1, p2) {',276' this.p1 = p1;',277' this.p2 = p2;',278' }',279'}'280].join('\n'));281282eval(code);283284var fooInst = new Foo('a', 'b');285expect(fooInst.p1).toBe('a');286expect(fooInst.p2).toBe('b');287});288289it('handles prototype methods without params', function() {290var code = transform([291'class Foo {',292' bar() {',293' return "stuff";',294' }',295'}'296].join('\n'));297298eval(code);299300var fooInst = new Foo();301expect(fooInst.bar()).toBe('stuff');302});303304it('handles prototype methods with params', function() {305var code = transform([306'class Foo {',307' bar(p1, p2) {',308' this.p1 = p1;',309' this.p2 = p2;',310' }',311'}'312].join('\n'));313314eval(code);315316var fooInst = new Foo();317fooInst.bar('a', 'b');318expect(fooInst.p1).toBe('a');319expect(fooInst.p2).toBe('b');320});321322it('handles static methods without params', function() {323var code = transform([324'class Foo {',325' static bar() {',326' return "stuff";',327' }',328'}'329].join('\n'));330331eval(code);332333expect(Foo.bar()).toBe('stuff');334var fooInst = new Foo();335expect(fooInst.bar).toBe(undefined);336});337338it('handles static methods with params', function() {339var code = transform([340'class Foo {',341' static bar(p1, p2) {',342' return [p1, p2];',343' }',344'}'345].join('\n'));346347eval(code);348349expect(Foo.bar('a', 'b')).toEqual(['a', 'b']);350var fooInst = new Foo();351expect(fooInst.bar).toBe(undefined);352});353354it('handles extension from an identifier', function() {355var code = transform([356'function Parent() {}',357'Parent.prototype.protoProp = "protoProp";',358'Parent.staticProp = "staticProp";',359360'class Child extends Parent {}'361].join('\n'));362363var exports = new Function(364code + 'return {Child: Child, Parent: Parent};'365)();366var Child = exports.Child;367var Parent = exports.Parent;368369expect(Child.protoProp).toBe(undefined);370expect(Child.staticProp).toBe('staticProp');371var childInst = new Child();372expect(childInst instanceof Child).toBe(true);373expect(childInst instanceof Parent).toBe(true);374expect(childInst.protoProp).toBe('protoProp');375});376377// ES6 draft section 14.5378it('handles extension from a left hand expression', function() {379var code = transform([380'function Parent1() {}',381'Parent1.prototype.protoProp = "protoProp";',382'Parent1.staticProp = "staticProp";',383384'function Parent2() {}',385386'class Child extends (true ? Parent1 : Parent2) {}'387].join('\n'));388389var exports = new Function(390code + 'return {Parent1: Parent1, Child: Child};'391)();392var Child = exports.Child;393var Parent1 = exports.Parent1;394395expect(Child.protoProp).toBe(undefined);396expect(Child.staticProp).toBe('staticProp');397var childInst = new Child();398expect(childInst instanceof Child).toBe(true);399expect(childInst instanceof Parent1).toBe(true);400expect(childInst.protoProp).toBe('protoProp');401expect(childInst.staticProp).toBe(undefined);402});403404it('runs parent constructor when child constructor absent', function() {405var code = transform([406'class Parent {',407' constructor(p1, p2) {',408' this.p1 = p1;',409' this.p2 = p2;',410' }',411'}',412413'class Child extends Parent {}'414].join('\n'));415416var Child = new Function(code + 'return Child;')();417418var childInst = new Child('a', 'b');419expect(childInst.p1).toBe('a');420expect(childInst.p2).toBe('b');421});422423it('sets constructor property to point at constructor func', function() {424var code = transform([425'class Parent {}',426'class Child extends Parent {}'427].join('\n'));428429var Child = new Function(code + 'return Child;')();430431var childInst = new Child();432expect(childInst.constructor).toBe(Child);433});434435it('handles super CallExpressions within constructors', function() {436var code = transform([437'class Parent {',438' constructor(p1, p2) {',439' this.p1 = p1;',440' this.p2 = p2;',441' }',442'}',443444'class Child extends Parent {',445' constructor() {',446' super("a", "b");',447' this.childRan = true;',448' }',449'}'450].join('\n'));451452var Child = new Function(code + 'return Child;')();453454var childInst = new Child();455expect(childInst.p1).toBe('a');456expect(childInst.p2).toBe('b');457expect(childInst.childRan).toBe(true);458});459460it('handles super CallExpressions within proto methods', function() {461var code = transform([462'class Parent {',463' bar(p1, p2) {',464' this.p1 = p1;',465' this.p2 = p2;',466' }',467' "baz qux"(p3) {',468' this.p3 = p3;',469' }',470'}',471472'class Child extends Parent {',473' bar() {',474' super("a", "b");',475' this.barRan = true;',476' }',477' "baz qux"() {',478' super("c");',479' this["baz qux run"] = true;',480' }',481'}'482].join('\n'));483484var Child = new Function(code + 'return Child;')();485486var childInst = new Child();487expect(childInst.p1).toBe(undefined);488expect(childInst.p2).toBe(undefined);489expect(childInst.barRan).toBe(undefined);490491childInst.bar();492expect(childInst.p1).toBe('a');493expect(childInst.p2).toBe('b');494expect(childInst.barRan).toBe(true);495496expect(childInst.p3).toBe(undefined);497expect(childInst['baz qux run']).toBe(undefined);498499childInst['baz qux']();500expect(childInst.p3).toBe('c');501expect(childInst['baz qux run']).toBe(true);502});503504it('handles computed super MemberExpressions',505function() {506var code = transform([507'class Parent {',508' constructor() {',509' this.counter = 0;',510' }',511' incrementCounter(amount) {',512' this.counter += amount;',513' }',514'}',515516'class Child extends Parent {',517' childIncrement() {',518' super["increment" + "Counter"](2);',519' }',520'}'521].join('\n'));522523var Child = new Function(code + 'return Child;')();524525var childInst = new Child();526expect(childInst.counter).toBe(0);527childInst.childIncrement();528expect(childInst.counter).toBe(2);529});530531it('handles simple super MemberExpression access', function() {532var code = transform([533'class Parent {',534' getFoo(p) {',535' return "foo" + p;',536' }',537'}',538539'class Child extends Parent {',540' getChildFoo() {',541' var x = super.getFoo;',542' return x("bar");',543' }',544'}'545].join('\n'));546547var Child = new Function(code + 'return Child;')();548549var childInst = new Child();550expect(childInst.getChildFoo()).toBe('foobar');551});552553it('handles CallExpression on a super MemberExpression', function() {554var code = transform([555'class Parent {',556' getFoo(p) {',557' this.fooValue = "foo";',558' return this.fooValue + p;',559' }',560'}',561562'class Child extends Parent {',563' getChildFoo() {',564' return super.getFoo.call(this, "bar");',565' }',566'}'567].join('\n'));568569var Child = new Function(code + 'return Child;')();570571var childInst = new Child();572expect(childInst.getChildFoo()).toBe('foobar');573expect(childInst.fooValue).toBe('foo');574});575576it('handles super MemberExpressions within constructors', function() {577var code = transform([578'class Parent {',579' setParams(p1, p2) {',580' this.p1 = p1;',581' this.p2 = p2;',582' }',583'}',584585'class Child extends Parent {',586' constructor() {',587' super.setParams("a", "b");',588' }',589'}'590].join('\n'));591592var Child = new Function(code + 'return Child;')();593594var childInst = new Child();595expect(childInst.p1).toBe('a');596expect(childInst.p2).toBe('b');597});598599it('handles super MemberExpressions within proto methods', function() {600var code = transform([601'class Parent {',602' setParams(p1, p2) {',603' this.p1 = p1;',604' this.p2 = p2;',605' }',606'}',607608'class Child extends Parent {',609' bar() {',610' super.setParams("a", "b");',611' this.barRan = true;',612' }',613'}'614].join('\n'));615616var Child = new Function(code + 'return Child;')();617618var childInst = new Child();619expect(childInst.p1).toBe(undefined);620expect(childInst.p2).toBe(undefined);621expect(childInst.barRan).toBe(undefined);622childInst.bar();623expect(childInst.p1).toBe('a');624expect(childInst.p2).toBe('b');625expect(childInst.barRan).toBe(true);626});627628it('consistently munges private property identifiers', function() {629var code = transform([630'class Foo {',631' constructor(p1) {',632' this._p1 = p1;',633' }',634' getP1() {',635' return this._p1;',636' }',637'}'638].join('\n'));639640eval(code);641642var fooInst = new Foo('a');643expect(fooInst._p1).toBe(undefined);644expect(fooInst.getP1()).toBe('a');645});646647it('stores munged private properties on the instance', function() {648// Protects against subtle transform bugs like:649// `this._p1 = 42` -> `this$Foo_p1 = 42`650var code = transform([651'class Foo {',652' constructor(p1) {',653' this._p1 = p1;',654' }',655' getP1() {',656' return this._p1;',657' }',658'}'659].join('\n'));660661eval(code);662663var fooInst1 = new Foo('a');664var fooInst2 = new Foo('b');665expect(fooInst1.getP1()).toBe('a');666expect(fooInst2.getP1()).toBe('b');667});668669it('consistently munges nested private property identifiers', function() {670var code = transform([671'class Foo {',672' constructor(p1) {',673' this._data = {_p1: null};',674' this._data._p1 = p1;',675' }',676' getData() {',677' return this._data;',678' }',679' getP1() {',680' return this._data._p1;',681' }',682'}'683].join('\n'));684685eval(code);686687var fooInst = new Foo('a');688expect(fooInst.getData()._p1).toBe(undefined);689expect(fooInst.getP1()).toBe('a');690});691692it('consistently munges private method identifiers', function() {693var code = transform([694'class Foo {',695' getBar() {',696' return this._getBar();',697' }',698' _getBar() {',699' return 42;',700' }',701'}'702].join('\n'));703704eval(code);705706var fooInst = new Foo();707expect(fooInst._getBar).toBe(undefined);708expect(fooInst.getBar()).toBe(42);709});710711it('consistently munges private method params', function() {712var code = transform([713'class Foo {',714' bar(_counter, _function) {',715' this.counter = _counter;',716' _function();',717' }',718'}'719].join('\n'));720721eval(code);722723var fooInst = new Foo();724var callbackCalled = false;725fooInst.bar(42, function() { callbackCalled = true; });726expect(fooInst.counter).toBe(42);727expect(callbackCalled).toBe(true);728});729730it('consistently munges private idents in super call params', function() {731var code = transform([732'class Parent {',733' constructor(foo) {',734' this.foo = foo;',735' }',736' setBar(bar) {',737' this.bar = bar;',738' }',739'}',740'class Child extends Parent {',741' constructor(_foo, _bar) {',742' super(_foo);',743' super.setBar(_bar);',744' }',745'}'746].join('\n'));747748var Child = new Function(code + 'return Child;')();749750var childInst = new Child('foo', 'bar');751expect(childInst.foo).toBe('foo');752expect(childInst.bar).toBe('bar');753});754755it('consistently munges private idents in nested funcs', function() {756var code = transform([757'class Foo {',758' bar(_p1, p2) {',759' return function(_a) {',760' return [_p1, p2, _a];',761' };',762' }',763'}'764].join('\n'));765766eval(code);767768var fooInst = new Foo();769expect(fooInst.bar('a', 'b')('c')).toEqual(['a', 'b', 'c']);770});771772it('consistently munges private idents in nested arrow funcs', function() {773var code = transform([774'class Foo {',775' bar(_p1, p2) {',776' return (_a, b) => {',777' return [_p1, p2, _a, b];',778' };',779' }',780'}'781].join('\n'));782783eval(code);784785var fooInst = new Foo();786expect(fooInst.bar('a', 'b')('c', 'd')).toEqual(['a', 'b', 'c', 'd']);787});788789it('does not munge dunder-scored properties', function() {790var code = transform([791'class Foo {',792' constructor(p1) {',793' this.__p1 = p1;',794' }',795'}'796].join('\n'));797798eval(code);799800var fooInst = new Foo('a');801expect(fooInst.__p1).toBe('a');802});803804it('does not munge dunder-scored methods', function() {805var code = transform([806'class Foo {',807' __getBar() {',808' return 42;',809' }',810'}'811].join('\n'));812813eval(code);814815var fooInst = new Foo();816expect(fooInst.__getBar()).toBe(42);817});818819it('properly handles private vars declared in outer scope', function() {820var code = transform([821'var _bar = "outer";',822'class Foo {',823' getOuterBar() {',824' return _bar;',825' }',826'}'827].join('\n'));828829var Foo = new Function(code + 'return Foo;')();830831var fooInst = new Foo();832expect(fooInst.getOuterBar()).toBe('outer');833});834835it('does not munge outer-declared private vars when used to calculate ' +836'a computed member expression', function() {837var code = transform([838'var _privateObjKey = "pvt";',839'var outerDataStore = {pvt: 42};',840'class Foo {',841' getStuff() {',842' return outerDataStore[_privateObjKey];',843' }',844'}'845].join('\n'));846847var Foo = new Function(code + 'return Foo;')();848849var fooInst = new Foo();850expect(fooInst.getStuff()).toBe(42);851});852853it('properly handles private vars declared in inner scope', function() {854var code = transform([855'var _bar = {_private: 42};',856'class Foo {',857' getBarPrivate(p1) {',858' var _bar = {_private: p1};',859' return _bar._private;',860' }',861'}'862].join('\n'));863864eval(code);865866var fooInst = new Foo();867expect(fooInst.getBarPrivate('a')).toBe('a');868});869870it('munges properties of private vars declared out of scope', function() {871var code = transform([872'var _bar = {_private: 42}',873'class Foo {',874' getOuterPrivate() {',875' return _bar._private;',876' }',877'}'878].join('\n'));879880var exports = new Function(code + 'return {_bar: _bar, Foo: Foo};')();881var _bar = exports._bar;882var Foo = exports.Foo;883884var fooInst = new Foo();885expect(_bar._private).toBe(42);886expect(fooInst.getOuterPrivate()).toBe(undefined);887});888889it('does not munge when @preventMunge is specified', function() {890var code = transform([891'/**',892' * @preventMunge',893' */',894'class Foo {',895' constructor(p1) {',896' this._p1 = p1;',897' }',898' _privateMethod() {',899' }',900'}'901].join('\n'));902903eval(code);904905var fooInst = new Foo('a');906expect(fooInst._p1).toBe('a');907expect(fooInst._privateMethod).not.toBe(undefined);908});909910it('minifies private properties when minify opt is set', function() {911var code = transform([912'class Foo {',913' constructor(p1) {',914' this._p1 = p1;',915' }',916'}'917].join('\n'), {minify: true});918919eval(code);920921var fooInst = new Foo('a');922expect(fooInst.$Foo0).toBe('a');923});924925it('minifies private methods when minify opt is set', function() {926var code = transform([927'class Foo {',928' _bar() {',929' return 42;',930' }',931'}'932].join('\n'), {minify: true});933934eval(code);935936var fooInst = new Foo();937expect(fooInst.$Foo0()).toBe(42);938});939940it('munges child class different from parent in same file', function() {941var code = transform([942'class Parent {',943' setParentFoo(foo) {',944' this._foo = foo;',945' }',946' getParentFoo() {',947' return this._foo;',948' }',949'}',950951'class Child extends Parent {',952' setChildFoo(foo) {',953' this._foo = foo;',954' }',955' getChildFoo() {',956' return this._foo;',957' }',958'}'959].join('\n'));960961var Child = new Function(code + 'return Child;')();962963var childInst = new Child();964childInst.setParentFoo('parent');965childInst.setChildFoo('child');966expect(childInst.getParentFoo()).toBe('parent');967expect(childInst.getChildFoo()).toBe('child');968});969970it('munges child class different from parent in other file', function() {971var code1 = transform([972'class Parent {',973' setParentFoo(foo) {',974' this._foo = foo;',975' }',976' getParentFoo() {',977' return this._foo;',978' }',979'}'980].join('\n'));981982var code2 = transform([983'class Child extends Parent {',984' setChildFoo(foo) {',985' this._foo = foo;',986' }',987' getChildFoo() {',988' return this._foo;',989' }',990'}'991].join('\n'));992993var exports = new Function(994code1 + code2 + 'return {Parent: Parent, Child: Child};'995)();996var Parent = exports.Parent;997var Child = exports.Child;998999var childInst = new Child();1000childInst.setParentFoo('parent');1001childInst.setChildFoo('child');1002expect(childInst.getParentFoo()).toBe('parent');1003expect(childInst.getChildFoo()).toBe('child');1004});10051006it('makes class methods implicitly "use strict"', function() {1007var code = transform([1008'class Foo {',1009' constructor() {',1010' this.constructorIsStrict = ' +1011'(function() {return this === undefined;})();',1012' }',1013' protoFn() {',1014' return (function() {return this === undefined;})();',1015' }',1016' static staticFn() {',1017' return (function() {return this === undefined;})();',1018' }',1019'}'1020].join('\n'));10211022eval(code);10231024var fooInst = new Foo();1025expect(fooInst.constructorIsStrict).toBe(true);1026expect(fooInst.protoFn()).toBe(true);1027expect(Foo.staticFn()).toBe(true);1028});10291030it('preserves generators', function() {1031var code = transform([1032'class Foo {',1033' static *title() {',1034' yield 21;',1035' }',1036'',1037' *gen() {',1038' yield 42;',1039' }',1040'}'1041].join('\n'));10421043expect(code).toMatch(/Foo.title\s*=\s*function\*\(/);1044expect(code).toMatch(/Foo.prototype.gen\s*=\s*function\*\(/);1045});10461047it('properly handles getter methods in ES5 compat mode', function() {1048var code = transform([1049'class Foo {',1050' get title() {',1051' return 42;',1052' }',1053' get "foo bar"() {',1054' return 21;',1055' }',1056'}'1057].join('\n'), {es5: true});10581059eval(code);10601061var fooInst = new Foo();1062var descriptor =1063Object.getOwnPropertyDescriptor(Foo.prototype, 'title');10641065expect(fooInst.title).toBe(42);1066expect(descriptor.enumerable).toBe(true);1067expect(descriptor.configurable).toBe(true);1068expect(fooInst['foo bar']).toBe(21);1069});10701071it('properly handles setter methods in ES5 compat mode', function() {1072var code = transform([1073'class Foo {',1074' set title(value) {',1075' this.__title = 42;',1076' }',1077' set "foo bar"(value) {',1078' this.__fooBar = 21;',1079' }',1080'}'1081].join('\n'), {es5: true});10821083eval(code);10841085var fooInst = new Foo();1086fooInst.title = 42;1087fooInst['foo bar'] = 21;1088var descriptor =1089Object.getOwnPropertyDescriptor(Foo.prototype, 'title');10901091expect(fooInst.__title).toBe(42);1092expect(descriptor.enumerable).toBe(true);1093expect(descriptor.configurable).toBe(true);1094expect(fooInst.__fooBar).toBe(21);1095});10961097it('properly handles getters and setters in ES5 compat mode', function() {1098var code = transform([1099'class Foo {',1100' get title() {',1101' return this.__title;',1102' }',1103'',1104' set title(value) {',1105' this.__title = value;',1106' }',1107'}'1108].join('\n'), {es5: true});11091110eval(code);11111112var fooInst = new Foo();1113var descriptor =1114Object.getOwnPropertyDescriptor(Foo.prototype, 'title');1115fooInst.title = 42;11161117expect(fooInst.__title).toBe(42);1118expect(fooInst.title).toBe(42);1119expect(descriptor.enumerable).toBe(true);1120expect(descriptor.configurable).toBe(true);1121});11221123it('properly handles static and non-static getters and setters ' +1124'with the same name in ES5 compat mode', function() {1125var code = transform([1126'class Foo {',1127' static get title() {',1128' return this._title;',1129' }',1130'',1131' static set title(value) {',1132' this._title = value;',1133' }',1134'',1135' get title() {',1136' return this.__title;',1137' }',1138'',1139' set title(value) {',1140' this.__title = value;',1141' }',1142'}'1143].join('\n'), {es5: true});11441145eval(code);11461147var fooInst = new Foo();1148Foo.title = 21;1149fooInst.title = 42;11501151expect(Foo.title).toBe(21);1152expect(fooInst.title).toBe(42);1153});11541155it('properly handles private getters and setters in ES5 compat mode',1156function() {1157var code = transform([1158'class Foo {',1159' get title() {',1160' return this._private;',1161' }',1162'',1163' set title(value) {',1164' this._private = value;',1165' }',1166'',1167' get _private() {',1168' return this.__superPrivate;',1169' }',1170'',1171' set _private(value) {',1172' this.__superPrivate = value;',1173' }',1174'}'1175].join('\n'), {es5: true});11761177eval(code);11781179var fooInst = new Foo();1180fooInst.title = 42;11811182expect(fooInst.__superPrivate).toBe(42);1183});11841185it('throws upon encountering getter methods', function() {1186expect(function() {1187transform([1188'class Foo {',1189' get title() {',1190' return 42;',1191' }',1192'}'1193].join('\n'));1194}).toThrow(1195'This transform does not support getter methods for ES6 classes. ' +1196'(line: 2, col: 2)'1197);1198});11991200it('throws upon encountering setter methods', function() {1201expect(function() {1202transform([1203'class Foo {',1204' set title(value) {',1205' this._title = value;',1206' }',1207'}'1208].join('\n'));1209}).toThrow(1210'This transform does not support setter methods for ES6 classes. ' +1211'(line: 2, col: 2)'1212);1213});1214});1215});12161217describe('ClassExpressions', function() {1218describe('preserves line numbers', function() {1219it('preserves lines with no inheritance', function() {1220var code = [1221'var Foo = class {',1222' foo() {',1223' ',1224' ',1225' }',1226'',1227' constructor(p1,',1228' p2) {',1229'',1230' this.p1 = p1;',1231' this.p2 = p2;',1232' }',1233'',1234' bar(){}',1235' static baz() {',1236'}',1237'}'1238].join('\n');12391240var expected = [1241'var Foo = (function(){',1242' ____Class0.prototype.foo=function() {"use strict";',1243' ',1244' ',1245' };',1246'',1247' function ____Class0(p1,',1248' p2) {"use strict";',1249'',1250' this.p1 = p1;',1251' this.p2 = p2;',1252' }',1253'',1254' ____Class0.prototype.bar=function(){"use strict";};',1255' ____Class0.baz=function() {"use strict";',1256'};',1257'return ____Class0;})()'1258].join('\n');12591260expect(transform(code)).toBe(expected);1261});12621263it('preserves lines with inheritance from identifier', function() {1264var code = [1265'var Foo = class extends Bar {',1266' foo() {',1267' ',1268' ',1269' super(p1,',1270' p2);',1271' }',1272'',1273' constructor(p1,',1274' p2) {',1275'',1276' this.p1 = p1;',1277' this.p2 = p2;',1278' super.blah(p1,',1279' p2);',1280' }',1281'',1282' bar(){}',1283' static baz() {',1284'}',1285'}'1286].join('\n');12871288var expected = [1289'var Foo = (function(){' +1290'for(var Bar____Key in Bar){' +1291'if(Bar.hasOwnProperty(Bar____Key)){' +1292'____Class0[Bar____Key]=Bar[Bar____Key];' +1293'}' +1294'}' +1295'var ____SuperProtoOfBar=' +1296'Bar===null' +1297'?null' +1298':Bar.prototype;' +1299'____Class0.prototype=Object.create(____SuperProtoOfBar);' +1300'____Class0.prototype.constructor=____Class0;' +1301'____Class0.__superConstructor__=Bar;',13021303' ____Class0.prototype.foo=function() {"use strict";',1304' ',1305' ',1306' ____SuperProtoOfBar.foo.call(this,p1,',1307' p2);',1308' };',1309'',1310' function ____Class0(p1,',1311' p2) {"use strict";',1312'',1313' this.p1 = p1;',1314' this.p2 = p2;',1315' ____SuperProtoOfBar.blah.call(this,p1,',1316' p2);',1317' }',1318'',1319' ____Class0.prototype.bar=function(){"use strict";};',1320' ____Class0.baz=function() {"use strict";',1321'};',1322'return ____Class0;})()'1323].join('\n');13241325expect(transform(code)).toBe(expected);1326});13271328it('preserves lines with inheritance from expression', function() {1329var code = [1330'var Foo = class extends mixin(Bar, Baz) {',1331' foo() {',1332' ',1333' ',1334' }',1335'',1336' constructor(p1,',1337' p2) {',1338'',1339' this.p1 = p1;',1340' this.p2 = p2;',1341' }',1342'',1343' bar(){}',1344' static baz() {',1345'}',1346'}'1347].join('\n');13481349var expected = [1350'var Foo = (function(){' +1351'var ____Class1=mixin(Bar, Baz);' +1352'for(var ____Class1____Key in ____Class1){' +1353'if(____Class1.hasOwnProperty(____Class1____Key)){' +1354'____Class0[____Class1____Key]=____Class1[____Class1____Key];' +1355'}' +1356'}' +1357'var ____SuperProtoOf____Class1=' +1358'____Class1===null' +1359'?null' +1360':____Class1.prototype;' +1361'____Class0.prototype=Object.create(____SuperProtoOf____Class1);' +1362'____Class0.prototype.constructor=____Class0;' +1363'____Class0.__superConstructor__=____Class1;',13641365' ____Class0.prototype.foo=function() {"use strict";',1366' ',1367' ',1368' };',1369'',1370' function ____Class0(p1,',1371' p2) {"use strict";',1372'',1373' this.p1 = p1;',1374' this.p2 = p2;',1375' }',1376'',1377' ____Class0.prototype.bar=function(){"use strict";};',1378' ____Class0.baz=function() {"use strict";',1379'};',1380'return ____Class0;})()'1381].join('\n');13821383expect(transform(code)).toBe(expected);1384});1385});13861387describe('functional tests', function() {1388it('scopes each anonymous class separately', function() {1389var code = transform([1390'var Foo = class {',1391' constructor() {',1392' this._name = "foo";',1393' var properties = [];',1394' for (var key in this) {',1395' properties.push(key);',1396' }',1397' this.properties = properties',1398' }',1399'};',14001401'var Bar = class {',1402' constructor() {',1403' this._name = "bar";',1404' var properties = [];',1405' for (var key in this) {',1406' properties.push(key);',1407' }',1408' this.properties = properties',1409' }',1410'}'1411].join('\n'));14121413eval(code);14141415var fooInst = new Foo();1416var barInst = new Bar();1417expect(fooInst.properties).not.toEqual(barInst.properties);1418expect(fooInst[fooInst.properties[0]]).toBe('foo');1419expect(barInst[barInst.properties[0]]).toBe('bar');1420});1421});1422});14231424describe('handles reserved words', function() {1425it('handles reserved words', function() {1426expect(transform([1427'class Foo {',1428' delete(x, y) {',1429' bar();',1430' }',1431'}'1432].join('\n'))).toBe([1433'function Foo(){"use strict";}',1434' Foo.prototype["delete"]=function(x, y) {"use strict";',1435' bar();',1436' };',1437''1438].join('\n'))1439});1440});14411442describe('preserve newlines', function() {1443it('preserve newlines', function() {1444expect(transform([1445'class Foo {',1446' A',1447' (',1448' x, y) {',1449' bar();',1450' }',1451'}'1452].join('\n'))).toBe([1453'function Foo(){"use strict";}',1454' Foo.prototype.A=function(',1455'',1456'x, y) {"use strict";',1457' bar();',1458' };',1459''1460].join('\n'))1461});1462});1463});146414651466