-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathoptional.js
30 lines (25 loc) · 1.15 KB
/
optional.js
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
import { token, expr } from '../src/parse.js'
import { operator, compile } from '../src/compile.js'
import { PREC_ACCESS } from '../src/const.js'
// a?.[, a?.( - postfix operator
token('?.', PREC_ACCESS, a => a && ['?.', a])
// a ?.
operator('?.', a => (a = compile(a), ctx => a(ctx) || (() => { })))
// a?.b, a?.() - optional chain operator
token('?.', PREC_ACCESS, (a, b) => a && (b = expr(PREC_ACCESS), !b?.map) && ['?.', a, b])
// a ?. b
operator('?.', (a, b) => b && (a = compile(a), ctx => a(ctx)?.[b]))
// a?.x() - keep context, but watch out a?.()
operator('()', (a, b, container, args, path, optional) => b !== undefined && (a[0] === '?.') && (a[2] || Array.isArray(a[1])) && (
args = !b ? () => [] : // a()
b[0] === ',' ? (b = b.slice(1).map(compile), ctx => b.map(a => a(ctx))) : // a(b,c)
(b = compile(b), ctx => [b(ctx)]), // a(b)
// a?.()
!a[2] && (optional = true, a = a[1]),
// a?.['x']?.()
a[0] === '[]' && a.length === 3 ? (path = compile(a[2])) : (path = () => a[2]),
(container = compile(a[1]), optional ?
ctx => (container(ctx)?.[path(ctx)]?.(...args(ctx))) :
ctx => (container(ctx)?.[path(ctx)](...args(ctx)))
)
))