diff options
author | Jo-Philipp Wich <jo@mein.io> | 2021-09-25 19:34:14 +0200 |
---|---|---|
committer | Jo-Philipp Wich <jo@mein.io> | 2021-10-11 09:39:12 +0200 |
commit | 4ee06d8138a107908a9fb45220fea32055b3c48a (patch) | |
tree | 2f0bd421931b2dd2daf504719beb63cc2885d23a /tests/custom/00_syntax/23_optional_chaining | |
parent | e43b751aab997c5e74a0712f7569d90bd3d6b429 (diff) |
syntax: introduce optional chaining operators
Introduce new operators `?.`, `?.[…]` and `?.(…)` to simplify looking up
deeply nested property chain in a secure manner.
The `?.` operator behaves like the `.` property access operator but yields
`null` if the left hand side is `null` or not an object.
Like `?.`, the `?.[…]` operator behaves like the `[…]` computed property
access but yields `null` if the left hand side is `null` or neither an
object or array.
Finally the `?.(…)` operator behaves like the function call operator `(…)`
but yields `null` if the left hand side is `null` or not a callable
function.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
Diffstat (limited to 'tests/custom/00_syntax/23_optional_chaining')
-rw-r--r-- | tests/custom/00_syntax/23_optional_chaining | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/tests/custom/00_syntax/23_optional_chaining b/tests/custom/00_syntax/23_optional_chaining new file mode 100644 index 0000000..8b89089 --- /dev/null +++ b/tests/custom/00_syntax/23_optional_chaining @@ -0,0 +1,99 @@ +Optional chaining operators allow accessing nested object properties +in a secure manner, without the need to check the entire reference +chain for validity. + + +1. The `?.` operator can be used to lookup a named property in a +left-hand side expression without having to check whether the lhs +value is a proper object. + +-- Expect stdout -- +true +true +-- End -- + +-- Testcase -- +{% + obj = { foo: 1 }; + + print(obj.bar?.baz == null, "\n"); // obj.bar is null + print(obj.foo?.bar == null, "\n"); // obj.foo is not an object +%} +-- End -- + + +2. The `?.[…]` operator complements the `?.` one and applies the +same semantics to computed property accesses. + +-- Expect stdout -- +true +true +true +true +-- End -- + +-- Testcase -- +{% + obj = { foo: 1 }; + arr = [ 1, 2 ]; + + print(obj["bar"]?.["baz"] == null, "\n"); // obj.bar is null + print(obj["foo"]?.["bar"] == null, "\n"); // obj.foo is not an object + print(arr[0]?.["foo"] == null, "\n"); // arr[0] is not an object + print(foo?.[1] == null, "\n"); // foo is not an array +%} +-- End -- + + +3. The `?.(…)` function call operator yields `null` when the left-hand +side value is not a callable function value. + +-- Expect stdout -- +true +true +-- End -- + +-- Testcase -- +{% + foo = 1; + + print(foo?.(1, 2, 3) == null, "\n"); // foo is not a function + print(bar?.("test") == null, "\n"); // bar is null +%} +-- End -- + + +4. Optional chaining operators cannot be used on the left-hand side of +an assignment or increment/decrement expression. + +-- Expect stderr -- +Syntax error: Invalid left-hand side expression for assignment +In line 2, byte 13: + + ` obj?.foo = 1;` + Near here -----^ + + +-- End -- + +-- Testcase -- +{% + obj?.foo = 1; +%} +-- End -- + +-- Expect stderr -- +Syntax error: Invalid increment/decrement operand +In line 2, byte 7: + + ` obj?.foo++;` + ^-- Near here + + +-- End -- + +-- Testcase -- +{% + obj?.foo++; +%} +-- End -- |