function assert_eq(label, got, want) {
if (got === want) {
console.log(label, 'OK');
} else {
console.log(label, 'FAIL', 'got=', got, 'want=', want);
throw new Error(label + ' failed');
}
}
function side(n){ console.log('SIDE', n); return 'SIDE'+n; }
try {
let v1 = (null)?.f?.(side(1));
assert_eq('opt_prop_null', v1, undefined);
} catch (e) { console.log('opt_prop_null EXCEPTION', e); throw e; }
try {
let v2 = ({f: function(x){ return x; }}).f?.(side(2));
assert_eq('opt_prop_method', v2, 'SIDE2');
} catch (e) { console.log('opt_prop_method EXCEPTION', e); throw e; }
try {
let v3 = (null)?.['f']?.(side(3));
assert_eq('opt_index_null', v3, undefined);
} catch (e) { console.log('opt_index_null EXCEPTION', e); throw e; }
try {
let v4 = (function(){ return 55; })?.();
assert_eq('opt_bare_fn', v4, 55);
} catch (e) { console.log('opt_bare_fn EXCEPTION', e); throw e; }
try {
let obj = { get a(){ console.log('GETTER'); return function(){ return 7; } } };
let v5 = obj?.a?.();
assert_eq('opt_getter_call', v5, 7);
} catch (e) { console.log('opt_getter_call EXCEPTION', e); throw e; }
console.log('ALL_TESTS_PASS');