| // Copyright 2018 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| // Flags: --harmony-class-fields |
| |
| // Utility function for testing that the expected strings occur |
| // in the stack trace produced when running the given function. |
| function testTrace(name, fun, expected, unexpected) { |
| var threw = false; |
| try { |
| fun(); |
| } catch (e) { |
| for (var i = 0; i < expected.length; i++) { |
| assertTrue( |
| e.stack.indexOf(expected[i]) != -1, |
| name + " doesn't contain expected[" + i + "] stack = " + e.stack |
| ); |
| } |
| if (unexpected) { |
| for (var i = 0; i < unexpected.length; i++) { |
| assertEquals( |
| e.stack.indexOf(unexpected[i]), |
| -1, |
| name + " contains unexpected[" + i + "]" |
| ); |
| } |
| } |
| threw = true; |
| } |
| assertTrue(threw, name + " didn't throw"); |
| } |
| |
| function thrower() { |
| FAIL; |
| } |
| |
| function testClassConstruction() { |
| class X { |
| static x = thrower(); |
| } |
| } |
| |
| // ReferenceError: FAIL is not defined |
| // at thrower |
| // at <static_fields_initializer> |
| // at testClassConstruction |
| // at testTrace |
| testTrace( |
| "during class construction", |
| testClassConstruction, |
| ["thrower", "<static_fields_initializer>"], |
| ["anonymous"] |
| ); |
| |
| function testClassConstruction2() { |
| class X { |
| [thrower()]; |
| } |
| } |
| |
| // ReferenceError: FAIL is not defined |
| // at thrower |
| // at testClassConstruction2 |
| // at testTrace |
| testTrace("during class construction2", testClassConstruction2, ["thrower"]); |
| |
| function testClassInstantiation() { |
| class X { |
| x = thrower(); |
| } |
| |
| new X(); |
| } |
| |
| // ReferenceError: FAIL is not defined |
| // at thrower |
| // at X.<instance_members_initializer> |
| // at new X |
| // at testClassInstantiation |
| // at testTrace |
| testTrace( |
| "during class instantiation", |
| testClassInstantiation, |
| ["thrower", "X.<instance_members_initializer>", "new X"], |
| ["anonymous"] |
| ); |
| |
| function testClassInstantiationWithSuper() { |
| class Base {} |
| |
| class X extends Base { |
| x = thrower(); |
| } |
| |
| new X(); |
| } |
| |
| // ReferenceError: FAIL is not defined |
| // at thrower |
| // at X.<instance_members_initializer> |
| // at new X |
| // at testClassInstantiation |
| // at testTrace |
| testTrace( |
| "during class instantiation with super", |
| testClassInstantiationWithSuper, |
| ["thrower", "X.<instance_members_initializer>", "new X"], |
| ["Base", "anonymous"] |
| ); |
| |
| function testClassInstantiationWithSuper2() { |
| class Base {} |
| |
| class X extends Base { |
| constructor() { |
| super(); |
| } |
| x = thrower(); |
| } |
| |
| new X(); |
| } |
| |
| // ReferenceError: FAIL is not defined |
| // at thrower |
| // at X.<instance_members_initializer> |
| // at new X |
| // at testClassInstantiation |
| // at testTrace |
| testTrace( |
| "during class instantiation with super2", |
| testClassInstantiationWithSuper2, |
| ["thrower", "X.<instance_members_initializer>", "new X"], |
| ["Base", "anonymous"] |
| ); |
| |
| function testClassInstantiationWithSuper3() { |
| class Base { |
| x = thrower(); |
| } |
| |
| class X extends Base { |
| constructor() { |
| super(); |
| } |
| } |
| |
| new X(); |
| } |
| |
| // ReferenceError: FAIL is not defined |
| // at thrower |
| // at X.<instance_members_initializer> |
| // at new Base |
| // at new X |
| // at testClassInstantiationWithSuper3 |
| // at testTrace |
| testTrace( |
| "during class instantiation with super3", |
| testClassInstantiationWithSuper3, |
| ["thrower", "X.<instance_members_initializer>", "new Base", "new X"], |
| ["anonymous"] |
| ); |
| |
| function testClassFieldCall() { |
| class X { |
| x = thrower; |
| } |
| |
| let x = new X(); |
| x.x(); |
| } |
| |
| // ReferenceError: FAIL is not defined |
| // at X.thrower [as x] |
| // at testClassFieldCall |
| // at testTrace |
| testTrace( |
| "during class field call", |
| testClassFieldCall, |
| ["X.thrower"], |
| ["anonymous"] |
| ); |
| |
| function testStaticClassFieldCall() { |
| class X { |
| static x = thrower; |
| } |
| |
| X.x(); |
| } |
| |
| // ReferenceError: FAIL is not defined |
| // at Function.thrower [as x] |
| // at testStaticClassFieldCall |
| // at testTrace |
| testTrace( |
| "during static class field call", |
| testStaticClassFieldCall, |
| ["Function.thrower"], |
| ["anonymous"] |
| ); |
| |
| function testClassFieldCallWithFNI() { |
| class X { |
| x = function() { |
| FAIL; |
| }; |
| } |
| |
| let x = new X(); |
| x.x(); |
| } |
| |
| // ReferenceError: FAIL is not defined |
| // at X.x |
| // at testClassFieldCallWithFNI |
| // at testTrace |
| testTrace( |
| "during class field call with FNI", |
| testClassFieldCallWithFNI, |
| ["X.x"], |
| ["anonymous"] |
| ); |
| |
| function testStaticClassFieldCallWithFNI() { |
| class X { |
| static x = function() { |
| FAIL; |
| }; |
| } |
| |
| X.x(); |
| } |
| |
| // ReferenceError: FAIL is not defined |
| // at Function.x |
| // at testStaticClassFieldCallWithFNI |
| // at testTrace |
| testTrace( |
| "during static class field call with FNI", |
| testStaticClassFieldCallWithFNI, |
| ["Function.x"], |
| ["anonymous"] |
| ); |