| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 | class A {}class B extends A {	function new() {		init();		Test.calls.push("B");	}	function init() {}}class C extends B {}class D extends C {	var n = "D";	override function init() Test.calls.push(n);}class E extends D {	function new() {		Test.use(this);		Test.calls.push("E");		super();	}}class F extends E {	public function new() {		super();		Test.calls.push("F");	}}extern class ExtNoCtor {	static function __init__():Void haxe.macro.Compiler.includeFile("./extern.js", "top");}class Base extends ExtNoCtor {	function new() {		Test.calls.push("BASE");	}}class Child extends Base {	public function new() {		Test.use(this);		Test.calls.push("CHILD");		super();	}}class RootNoArgs {	public function new() {}}class ChildOneArg extends RootNoArgs {	public var x:Int;	public function new(x) {		super();		this.x = x;	}}class GrandChildNoArgs extends ChildOneArg {	public function new() {		Test.use(this);		super(42);	}}class Issue9426_1 {	static function __init__() {		var sameName = Std.random(10);		Test.use(sameName);		Test.use(sameName);	}}class Issue9426_2 {	static function __init__() {		var sameName = Std.random(10);		Test.use(sameName);		Test.use(sameName);	}}class Test {	public static var calls:Array<String>;	@:pure(false) public static function use(v:Any) {}	static inline final hxCtor = "_hx_constructor";	static inline final hxSkipCtor = "_hx_skip_constructor";	static function hasCtorMethod(c:Dynamic):Bool {		return c.prototype.hasOwnProperty(hxCtor);	}	static function hasSkip(c:Dynamic) {		return c.hasOwnProperty(hxSkipCtor);	}	static var failures = 0;	static function assert(bool:Bool, ?pos:haxe.PosInfos) {		if (!bool) {			(untyped process).stderr.write(haxe.Log.formatOutput("assertion failed\n", pos));			failures++;		}	}	static function main() {		// A has no constructor, so it's safe to just call `super` first		// even if we skip ctor in the subclasses		assert(!hasCtorMethod(A));		assert(!hasSkip(A));		// B has an extracted ctor and also the static skip flag,		// as it is the first in the hierarchy who's ctor needs to be skipped		assert(hasCtorMethod(B));		assert(hasSkip(B));		// C and others down the chain should NOT have the static skip flag,		// but it can have a hxctor (although in this case it could be optimized away)		assert(!hasSkip(C));		// D must have a hxctor because it accesses this before super (for field init)		// it also supports skipping because it has children who want to skip		assert(hasCtorMethod(D));		assert(!hasSkip(D));		// E also must have a hxctor because it accesses this before super		// but it doesn't support skipping, because noone down the inheritance requires it		assert(hasCtorMethod(E));		assert(!hasSkip(E));		// F should NOT have hxctor because it doesn't access this before super and		// it has no children that require skipping		assert(!hasCtorMethod(F));		assert(!hasSkip(F));		// now for the call order		calls = [];		new F();		// E is first, because it's called before `super` in the parent class, and we call `super` before anything else		// D is second, because we call `init` before pushing `B` in the first constructor. here it's important that the field `n` is set		// before we call super(), so it's initialized at the point we call `init`		// B is the last "super" ctor in the hierarchy		// and finally F is pushed after a super call as usual		assert(calls.join("") == "EDBF");		// we also support skipping when inheriting from extern without constructors		assert(!hasCtorMethod(ExtNoCtor));		assert(!hasSkip(ExtNoCtor));		assert(hasCtorMethod(Base));		assert(hasSkip(Base));		assert(hasCtorMethod(Child));		assert(!hasSkip(Child));		calls = [];		new Child();		assert(calls.join("|") == "CHILD|BASE");		assert(new ChildOneArg(42).x == 42); // #7988		// ---		(untyped process).exit(if (failures == 0) 0 else 1);	}}
 |