// Verify bytecode emitter accepts all valid optional chain first expressions. const expressions = [ // https://tc39.es/ecma262/#sec-primary-expression "this", "ident", "null", "true", "false", "123", "123n", "'str'", "[]", "{}", "function(){}", "class{}", "function*(){}", "async function(){}", "async function*(){}", "/a/", "`str`", "(a + b)", // https://tc39.es/ecma262/#sec-left-hand-side-expressions "a[b]", "a.b", "a``", "super[a]", "super.a", "new.target", "import.meta", "new C()", "new C", "f()", "super()", "a?.b", "a?.[b]", "a?.()", "a?.``", ]; function tryParse(s, f = Function) { try { f(s); } catch {} } function tryRun(s, f = Function) { try { f(s)(); } catch {} } for (let expr of expressions) { // Evaluate in an expression context. tryRun(`void (${expr}?.());`); tryRun(`void (${expr}?.p());`); // Also try parenthesized. tryRun(`void ((${expr})?.());`); tryRun(`void ((${expr})?.p());`); } function inClassConstructor(s) { return `class C { constructor() { ${s} } }`; } for (let expr of ["super[a]", "super.a", "super()"]) { // Evaluate in an expression context. tryRun(inClassConstructor(`void (${expr}?.());`)); tryRun(inClassConstructor(`void (${expr}?.p());`)); // Also try parenthesized. tryRun(inClassConstructor(`void ((${expr})?.());`)); tryRun(inClassConstructor(`void ((${expr})?.p());`)); } if (typeof parseModule === "function") { const expressions = [ "import.meta", "import('')", ]; for (let expr of expressions) { // Evaluate in an expression context. tryParse(`void (${expr}?.());`, parseModule); tryParse(`void (${expr}?.p());`, parseModule); // Also try parenthesized. tryParse(`void ((${expr})?.());`, parseModule); tryParse(`void ((${expr})?.p());`, parseModule); } } if (typeof reportCompare === "function") reportCompare(true, true);