class-inheritance.js 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. test("method inheritance", () => {
  2. class Parent {
  3. method() {
  4. return 3;
  5. }
  6. }
  7. class Child extends Parent {}
  8. const p = new Parent();
  9. const c = new Child();
  10. expect(p.method()).toBe(3);
  11. expect(c.method()).toBe(3);
  12. });
  13. test("method overriding", () => {
  14. class Parent {
  15. method() {
  16. return 3;
  17. }
  18. }
  19. class Child extends Parent {
  20. method() {
  21. return 10;
  22. }
  23. }
  24. const p = new Parent();
  25. const c = new Child();
  26. expect(p.method()).toBe(3);
  27. expect(c.method()).toBe(10);
  28. });
  29. test("parent method reference with super", () => {
  30. class Parent {
  31. method() {
  32. return 3;
  33. }
  34. }
  35. class Child extends Parent {
  36. method() {
  37. return super.method() * 2;
  38. }
  39. }
  40. const p = new Parent();
  41. const c = new Child();
  42. expect(p.method()).toBe(3);
  43. expect(c.method()).toBe(6);
  44. });
  45. test("child class access to parent class initialized properties", () => {
  46. class Parent {
  47. constructor() {
  48. this.x = 3;
  49. }
  50. }
  51. class Child extends Parent {}
  52. const p = new Parent();
  53. const c = new Child();
  54. expect(p.x).toBe(3);
  55. expect(c.x).toBe(3);
  56. });
  57. test("child class modification of parent class properties", () => {
  58. class Parent {
  59. constructor() {
  60. this.x = 3;
  61. }
  62. }
  63. class Child extends Parent {
  64. change() {
  65. this.x = 10;
  66. }
  67. }
  68. const p = new Parent();
  69. const c = new Child();
  70. expect(p.x).toBe(3);
  71. expect(c.x).toBe(3);
  72. c.change();
  73. expect(c.x).toBe(10);
  74. });
  75. test("inheritance and hasOwnProperty", () => {
  76. class Parent {
  77. constructor() {
  78. this.x = 3;
  79. }
  80. }
  81. class Child extends Parent {
  82. method() {
  83. this.y = 10;
  84. }
  85. }
  86. const p = new Parent();
  87. const c = new Child();
  88. expect(p.hasOwnProperty("x")).toBeTrue();
  89. expect(p.hasOwnProperty("y")).toBeFalse();
  90. expect(c.hasOwnProperty("x")).toBeTrue();
  91. expect(c.hasOwnProperty("y")).toBeFalse();
  92. c.method();
  93. expect(c.hasOwnProperty("x")).toBeTrue();
  94. expect(c.hasOwnProperty("y")).toBeTrue();
  95. });
  96. test("super constructor call from child class with argument", () => {
  97. class Parent {
  98. constructor(x) {
  99. this.x = x;
  100. }
  101. }
  102. class Child extends Parent {
  103. constructor() {
  104. super(10);
  105. }
  106. }
  107. const p = new Parent(3);
  108. const c = new Child(3);
  109. expect(p.x).toBe(3);
  110. expect(c.x).toBe(10);
  111. });
  112. test("advanced 'extends' RHS", () => {
  113. const foo = {
  114. bar() {
  115. return {
  116. baz() {
  117. return function () {
  118. return function () {
  119. return { quux: Number };
  120. };
  121. };
  122. },
  123. };
  124. },
  125. };
  126. class Foo extends foo.bar()["baz"]()`qux`().quux {}
  127. expect(new Foo()).toBeInstanceOf(Number);
  128. });
  129. test("issue #7045, super constructor call from child class in catch {}", () => {
  130. class Parent {
  131. constructor(x) {
  132. this.x = x;
  133. }
  134. }
  135. class Child extends Parent {
  136. constructor() {
  137. try {
  138. throw new Error("Error in Child constructor");
  139. } catch (e) {
  140. super(e.message);
  141. }
  142. }
  143. }
  144. const c = new Child();
  145. expect(c.x).toBe("Error in Child constructor");
  146. });
  147. test("Issue #7044, super property access before super() call", () => {
  148. class Foo {
  149. constructor() {
  150. super.bar;
  151. }
  152. }
  153. new Foo();
  154. });
  155. test("Issue #8574, super property access before super() call", () => {
  156. var hit = false;
  157. class Foo extends Object {
  158. constructor() {
  159. expect(() => {
  160. const foo = super.bar();
  161. }).toThrowWithMessage(ReferenceError, "|this| has not been initialized");
  162. hit = true;
  163. }
  164. }
  165. // Note: We catch two exceptions here.
  166. expect(() => {
  167. new Foo();
  168. }).toThrowWithMessage(ReferenceError, "|this| has not been initialized");
  169. expect(hit).toBeTrue();
  170. });
  171. test("can access super via direct eval", () => {
  172. let superCalled = false;
  173. const aObject = { a: 1 };
  174. const bObject = { b: 2 };
  175. class A {
  176. constructor() {
  177. superCalled = true;
  178. }
  179. foo() {
  180. return aObject;
  181. }
  182. bar() {
  183. return bObject;
  184. }
  185. }
  186. class B extends A {
  187. constructor() {
  188. eval("super()");
  189. }
  190. }
  191. expect(() => {
  192. new B();
  193. }).not.toThrow();
  194. expect(superCalled).toBeTrue();
  195. superCalled = false;
  196. class C extends A {
  197. constructor() {
  198. eval("super()");
  199. return eval("super.foo()");
  200. }
  201. }
  202. expect(() => {
  203. new C();
  204. }).not.toThrow();
  205. expect(superCalled).toBeTrue();
  206. superCalled = false;
  207. expect(new C()).toBe(aObject);
  208. expect(superCalled).toBeTrue();
  209. superCalled = false;
  210. class D extends A {
  211. constructor() {
  212. eval("super()");
  213. return eval("super['bar']()");
  214. }
  215. }
  216. expect(() => {
  217. new D();
  218. }).not.toThrow();
  219. expect(superCalled).toBeTrue();
  220. superCalled = false;
  221. expect(new D()).toBe(bObject);
  222. expect(superCalled).toBeTrue();
  223. });
  224. test("cannot access super via indirect eval", () => {
  225. const indirect = eval;
  226. let superCalled = false;
  227. const aObject = { a: 1 };
  228. const bObject = { b: 1 };
  229. class A {
  230. constructor() {
  231. superCalled = true;
  232. this.a = aObject;
  233. this.c = bObject;
  234. }
  235. }
  236. class B extends A {
  237. constructor() {
  238. indirect("super()");
  239. }
  240. }
  241. expect(() => {
  242. new B();
  243. }).toThrowWithMessage(SyntaxError, "'super' keyword unexpected here");
  244. expect(superCalled).toBeFalse();
  245. class C extends A {
  246. constructor() {
  247. super();
  248. return indirect("super.a");
  249. }
  250. }
  251. expect(() => {
  252. new C();
  253. }).toThrowWithMessage(SyntaxError, "'super' keyword unexpected here");
  254. expect(superCalled).toBeTrue();
  255. superCalled = false;
  256. class D extends A {
  257. constructor() {
  258. super();
  259. return indirect("super['b']");
  260. }
  261. }
  262. expect(() => {
  263. new D();
  264. }).toThrowWithMessage(SyntaxError, "'super' keyword unexpected here");
  265. expect(superCalled).toBeTrue();
  266. });
  267. test("super outside of derived class fails to parse", () => {
  268. expect("super").not.toEval();
  269. expect("super()").not.toEval();
  270. expect("super.a").not.toEval();
  271. expect("super['b']").not.toEval();
  272. expect("function a() { super }").not.toEval();
  273. expect("function a() { super() }").not.toEval();
  274. expect("function a() { super.a }").not.toEval();
  275. expect("function a() { super['b'] }").not.toEval();
  276. expect("() => { super }").not.toEval();
  277. expect("() => { super() }").not.toEval();
  278. expect("() => { super.a }").not.toEval();
  279. expect("() => { super['b'] }").not.toEval();
  280. expect("class A { constructor() { super } }").not.toEval();
  281. expect("class A { constructor() { super() } }").not.toEval();
  282. expect(() => {
  283. eval("super");
  284. }).toThrowWithMessage(SyntaxError, "'super' keyword unexpected here");
  285. expect(() => {
  286. eval("super()");
  287. }).toThrowWithMessage(SyntaxError, "'super' keyword unexpected here");
  288. expect(() => {
  289. eval("super.a");
  290. }).toThrowWithMessage(SyntaxError, "'super' keyword unexpected here");
  291. expect(() => {
  292. eval("super['b']");
  293. }).toThrowWithMessage(SyntaxError, "'super' keyword unexpected here");
  294. function a() {
  295. eval("super");
  296. }
  297. expect(() => {
  298. a();
  299. }).toThrowWithMessage(SyntaxError, "'super' keyword unexpected here");
  300. expect(() => {
  301. new a();
  302. }).toThrowWithMessage(SyntaxError, "'super' keyword unexpected here");
  303. function b() {
  304. eval("super()");
  305. }
  306. expect(() => {
  307. b();
  308. }).toThrowWithMessage(SyntaxError, "'super' keyword unexpected here");
  309. expect(() => {
  310. new b();
  311. }).toThrowWithMessage(SyntaxError, "'super' keyword unexpected here");
  312. function c() {
  313. eval("super.a");
  314. }
  315. expect(() => {
  316. c();
  317. }).toThrowWithMessage(SyntaxError, "'super' keyword unexpected here");
  318. expect(() => {
  319. new c();
  320. }).toThrowWithMessage(SyntaxError, "'super' keyword unexpected here");
  321. function d() {
  322. eval("super['b']");
  323. }
  324. expect(() => {
  325. d();
  326. }).toThrowWithMessage(SyntaxError, "'super' keyword unexpected here");
  327. expect(() => {
  328. new d();
  329. }).toThrowWithMessage(SyntaxError, "'super' keyword unexpected here");
  330. const e = () => eval("super");
  331. expect(() => {
  332. e();
  333. }).toThrowWithMessage(SyntaxError, "'super' keyword unexpected here");
  334. const f = () => eval("super()");
  335. expect(() => {
  336. f();
  337. }).toThrowWithMessage(SyntaxError, "'super' keyword unexpected here");
  338. const g = () => eval("super.a");
  339. expect(() => {
  340. g();
  341. }).toThrowWithMessage(SyntaxError, "'super' keyword unexpected here");
  342. const h = () => eval("super['b']");
  343. expect(() => {
  344. h();
  345. }).toThrowWithMessage(SyntaxError, "'super' keyword unexpected here");
  346. class I {
  347. constructor() {
  348. eval("super");
  349. }
  350. }
  351. expect(() => {
  352. new I();
  353. }).toThrowWithMessage(SyntaxError, "'super' keyword unexpected here");
  354. class J {
  355. constructor() {
  356. eval("super()");
  357. }
  358. }
  359. expect(() => {
  360. new J();
  361. }).toThrowWithMessage(SyntaxError, "'super' keyword unexpected here");
  362. });