summaryrefslogtreecommitdiffhomepage
path: root/tests/custom/00_syntax/19_arrow_functions
blob: 102c527b27118f0003f36e51c358560dc1e46769 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
Besides the ordinary ES5-like function declarations, utpl supports ES6 inspired
arrow function syntax as well. Such arrow functions are useful for callbacks to functions such as replace(), map() or filter().

-- Expect stdout --
() => { ... }
test
(a, b) => { ... }
3
(...args) => { ... }
15
(a) => { ... }
10
(a) => { ... }
36
-- End --

-- Testcase --
{%

	// assign arrow function to variable
	test1_fn = () => {
		return "test";
	};

	// assign arrow function with parameters
	test2_fn = (a, b) => {
		return a + b;
	};

	// nesting functions is legal
	test3_fn = (...args) => {
		nested_fn = (a, b) => {
			return a * b;
		};

		return args[0] + nested_fn(args[0], args[1]);
	};

	// parentheses may be omitted if arrow function takes only one argument
	test4_fn = a => {
		a * 2;
	};

	// curly braces may be omitted if function body is a single expression
	test5_fn = a => a * a;

	print(join("\n", [
		test1_fn,
		test1_fn(),
		test2_fn,
		test2_fn(1, 2),
		test3_fn,
		test3_fn(3, 4),
		test4_fn,
		test4_fn(5),
		test5_fn,
		test5_fn(6)
	]), "\n");
%}
-- End --


While the main advantage of arrow functions is the compact syntax, another
important difference to normal functions is the "this" context behaviour -
arrow functions do not have an own "this" context and simply inherit it from
the outer calling scope.

-- Expect stdout --
this is set to obj: true
arrow function uses outher this: true
normal function has own this: true
arrow function as method has no this: true
-- End --

-- Testcase --
{%
	obj = {
		method: function() {
			let that = this;
			let arr = () => {
				print("arrow function uses outher this: ", that == this, "\n");
			};
			let fn = function() {
				print("normal function has own this: ", that != this, "\n");
			};

			print("this is set to obj: ", this == obj, "\n");

			arr();
			fn();
		},

		arrowfn: () => {
			print("arrow function as method has no this: ", this == null, "\n");
		}
	};

	obj.method();
	obj.arrowfn();
%}
-- End --


Due to the difficulty of recognizing arrow function expressions with an LR(1)
grammar the parser has to use a generic expression rule on the lhs argument list
and verify that it does not contain non-label nodes while building the ast. The
subsequent testcase asserts that case.

-- Expect stderr --
Syntax error: Unexpected token
Expecting ';'
In line 2, byte 10:

 `    (a + 1) => { print("test\n") }`
  Near here --^


-- End --

-- Testcase --
{%
	(a + 1) => { print("test\n") }
%}
-- End --