···11+// Test function declaration hoisting inside blocks
22+// Function declarations should be hoisted to the top of their containing block
33+44+console.log("=== Test 1: Function declaration hoisted in regular block ===");
55+{
66+ foo();
77+ function foo() {
88+ console.log("foo called - hoisted in block");
99+ }
1010+}
1111+1212+console.log("\n=== Test 2: Function hoisting in arrow function body ===");
1313+const test2 = () => {
1414+ bar();
1515+ function bar() {
1616+ console.log("bar called - hoisted in arrow function");
1717+ }
1818+};
1919+test2();
2020+2121+console.log("\n=== Test 3: Function hoisting in callback ===");
2222+const arr = [1];
2323+arr.forEach((x) => {
2424+ baz();
2525+ function baz() {
2626+ console.log("baz called with", x, "- hoisted in callback");
2727+ }
2828+});
2929+3030+console.log("\n=== Test 4: Function hoisting in .map() callback ===");
3131+const result = [5].map((x) => {
3232+ return helper(x);
3333+ function helper(n) {
3434+ return n * 2;
3535+ }
3636+});
3737+console.log("result should be [10]:", result);
3838+3939+console.log("\n=== Test 5: Nested function calling before definition ===");
4040+function outer() {
4141+ inner();
4242+ function inner() {
4343+ console.log("inner called - hoisted inside outer");
4444+ }
4545+}
4646+outer();
4747+4848+console.log("\n=== Test 6: Function modifying outer variable before definition ===");
4949+function test6() {
5050+ let value = 0;
5151+ modify();
5252+ console.log("value after modify should be 42:", value);
5353+5454+ function modify() {
5555+ value = 42;
5656+ }
5757+}
5858+test6();
5959+6060+console.log("\n=== All block function hoisting tests completed ===");
+154
tests/test_class_function_hoisting.cjs
···11+// Test class function (method) hoisting behavior
22+// Class methods can be called regardless of their definition order within the class body
33+// But classes themselves are NOT hoisted like function declarations
44+55+console.log("=== Test 1: Methods calling other methods defined later ===");
66+class Calculator {
77+ calculate(x) {
88+ return this.double(x) + this.triple(x);
99+ }
1010+1111+ double(x) {
1212+ return x * 2;
1313+ }
1414+1515+ triple(x) {
1616+ return x * 3;
1717+ }
1818+}
1919+2020+let calc = new Calculator();
2121+console.log("calculate(5) should be 25:", calc.calculate(5));
2222+2323+console.log("\n=== Test 2: Constructor calling methods defined after it ===");
2424+class Greeter {
2525+ constructor(name) {
2626+ this.name = name;
2727+ this.greeting = this.makeGreeting();
2828+ }
2929+3030+ makeGreeting() {
3131+ return "Hello, " + this.name + "!";
3232+ }
3333+}
3434+3535+let greeter = new Greeter("World");
3636+console.log("greeting should be 'Hello, World!':", greeter.greeting);
3737+3838+console.log("\n=== Test 3: Method calling method defined before constructor ===");
3939+class Parser {
4040+ parse(input) {
4141+ return this.validate(input);
4242+ }
4343+4444+ constructor() {
4545+ this.initialized = true;
4646+ }
4747+4848+ validate(input) {
4949+ return input.length > 0;
5050+ }
5151+}
5252+5353+let parser = new Parser();
5454+console.log("parse('test') should be true:", parser.parse("test"));
5555+5656+console.log("\n=== Test 4: Mutual method references ===");
5757+class Counter {
5858+ increment() {
5959+ this.value = this.getValue() + 1;
6060+ }
6161+6262+ decrement() {
6363+ this.value = this.getValue() - 1;
6464+ }
6565+6666+ constructor(initial) {
6767+ this.value = initial;
6868+ }
6969+7070+ getValue() {
7171+ return this.value;
7272+ }
7373+}
7474+7575+let counter = new Counter(10);
7676+counter.increment();
7777+console.log("after increment should be 11:", counter.getValue());
7878+counter.decrement();
7979+counter.decrement();
8080+console.log("after two decrements should be 9:", counter.getValue());
8181+8282+console.log("\n=== Test 5: Deep method call chain ===");
8383+class Chain {
8484+ a() {
8585+ return this.b() + 1;
8686+ }
8787+8888+ b() {
8989+ return this.c() + 2;
9090+ }
9191+9292+ c() {
9393+ return this.d() + 3;
9494+ }
9595+9696+ d() {
9797+ return 10;
9898+ }
9999+}
100100+101101+let chain = new Chain();
102102+console.log("a() should be 16 (10+3+2+1):", chain.a());
103103+104104+console.log("\n=== Test 6: Class NOT hoisted (should error if accessed before) ===");
105105+try {
106106+ let early = new NotYetDefined();
107107+ console.log("ERROR: Should not reach here");
108108+} catch (e) {
109109+ console.log("Correctly caught error - class not hoisted");
110110+}
111111+112112+class NotYetDefined {
113113+ constructor() {
114114+ this.value = 42;
115115+ }
116116+}
117117+118118+let late = new NotYetDefined();
119119+console.log("After definition, value should be 42:", late.value);
120120+121121+console.log("\n=== Test 7: Static methods hoisting within class ===");
122122+class StaticTest {
123123+ static compute() {
124124+ return StaticTest.helper() * 2;
125125+ }
126126+127127+ static helper() {
128128+ return 21;
129129+ }
130130+}
131131+132132+console.log("StaticTest.compute() should be 42:", StaticTest.compute());
133133+134134+console.log("\n=== Test 8: Getter/setter order independence ===");
135135+class GetSet {
136136+ get doubled() {
137137+ return this._val * 2;
138138+ }
139139+140140+ constructor(val) {
141141+ this._val = val;
142142+ }
143143+144144+ set doubled(val) {
145145+ this._val = val / 2;
146146+ }
147147+}
148148+149149+let gs = new GetSet(5);
150150+console.log("doubled should be 10:", gs.doubled);
151151+gs.doubled = 20;
152152+console.log("after setting doubled=20, _val should be 10:", gs._val);
153153+154154+console.log("\n=== All class function hoisting tests completed ===");