3ec1036526
This CL implements the nullish operator in bytecode as defined by: https://github.com/tc39/proposal-nullish-coalescing. It can be enabled by passing '--harmony-nullish'. Nullish is similar to logical operators, but instead of truthy/falsey values, it short circuits when it evaluates a null or undefined value. Bug: v8:9547 Change-Id: Ia0f55877fc2714482b5547942baef9733537d1b9 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1738568 Reviewed-by: Sathya Gunasekaran <gsathya@chromium.org> Reviewed-by: Leszek Swirski <leszeks@chromium.org> Commit-Queue: Joshua Litt <joshualitt@chromium.org> Cr-Commit-Position: refs/heads/master@{#63317}
144 lines
5.0 KiB
JavaScript
144 lines
5.0 KiB
JavaScript
// Copyright 2019 the V8 project authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
//
|
|
// Flags: --harmony-nullish
|
|
|
|
// Basic sanity checks.
|
|
assertTrue(true ?? false);
|
|
assertFalse(false ?? true);
|
|
assertTrue(undefined ?? true);
|
|
assertTrue(null ?? true);
|
|
assertEquals([], [] ?? true);
|
|
|
|
// Chaining nullish.
|
|
assertTrue(null ?? null ?? true);
|
|
assertTrue(null ?? null ?? true ?? null);
|
|
assertTrue(undefined ?? undefined ?? true);
|
|
assertTrue(undefined ?? undefined ?? true ?? undefined);
|
|
assertFalse(null ?? false ?? null);
|
|
assertFalse(undefined ?? false ?? undefined);
|
|
|
|
// Nullish and conditionals.
|
|
assertTrue(null ?? true ? true : false);
|
|
assertTrue(null ?? null ?? true ? true : false);
|
|
assertTrue(undefined ?? true ? true : false);
|
|
assertTrue(undefined ?? undefined ?? true ? true : false);
|
|
|
|
// Nullish mixed expressions.
|
|
assertTrue(null ?? 1 == 1);
|
|
assertTrue(undefined ?? 1 == 1);
|
|
assertTrue(null ?? null ?? 1 == 1);
|
|
assertTrue(undefined ??undefined ?? 1 == 1);
|
|
assertEquals(1, null ?? 1 | 0);
|
|
assertEquals(1, undefined ?? 1 | 0);
|
|
assertEquals(1, null ?? null ?? 1 | 0);
|
|
assertEquals(1, undefined ?? undefined ?? 1 | 0);
|
|
|
|
// Short circuit.
|
|
{
|
|
let ran = false;
|
|
let never_ran = () => { ran = true; }
|
|
let value = true ?? never_ran();
|
|
assertTrue(value);
|
|
assertFalse(ran);
|
|
}
|
|
|
|
{
|
|
let ran = false;
|
|
let never_ran = () => { ran = true; }
|
|
let value = undefined ?? true ?? never_ran();
|
|
assertTrue(value);
|
|
assertFalse(ran);
|
|
}
|
|
|
|
{
|
|
let ran = false;
|
|
let never_ran = () => { ran = true; }
|
|
let value = null ?? true ?? never_ran();
|
|
assertTrue(value);
|
|
assertFalse(ran);
|
|
}
|
|
|
|
// Nullish in tests evaluates only once.
|
|
{
|
|
let run_count = 0;
|
|
let run = () => { run_count++; return null; }
|
|
if (run() ?? true) {} else { assertUnreachable(); }
|
|
assertEquals(1, run_count);
|
|
}
|
|
|
|
// Nullish may not contain or be contained within || or &&.
|
|
assertThrows("true || true ?? true", SyntaxError);
|
|
assertThrows("true ?? true || true", SyntaxError);
|
|
assertThrows("true && true ?? true", SyntaxError);
|
|
assertThrows("true ?? true && true", SyntaxError);
|
|
|
|
// Test boolean expressions and nullish.
|
|
assertTrue((false || true) ?? false);
|
|
assertTrue(null ?? (false || true));
|
|
assertTrue((false || null) ?? true);
|
|
assertTrue((false || null) ?? (true && null) ?? true);
|
|
assertTrue((false || undefined) ?? true);
|
|
assertTrue((false || undefined) ?? (true && undefined) ?? true);
|
|
assertTrue(null ?? (false || true));
|
|
assertTrue(undefined ?? (false || true));
|
|
assertTrue(null ?? (false || null) ?? true);
|
|
assertTrue(undefined ?? (false || undefined) ?? true);
|
|
assertTrue(null ?? null ?? (false || true));
|
|
assertTrue(undefined ?? undefined ?? (false || true));
|
|
assertTrue((undefined ?? false) || true);
|
|
assertTrue((null ?? false) || true);
|
|
assertTrue((undefined ?? undefined ?? false) || false || true);
|
|
assertTrue((null ?? null ?? false) || false || true);
|
|
assertTrue(false || (undefined ?? true));
|
|
assertTrue(false || (null ?? true));
|
|
assertTrue(false || false || (undefined ?? undefined ?? true));
|
|
assertTrue(false || false || (null ?? null ?? true));
|
|
|
|
// Test use when test true.
|
|
if (undefined ?? true) {} else { assertUnreachable(); }
|
|
if (null ?? true) {} else { assertUnreachable(); }
|
|
|
|
if (undefined ?? undefined ?? true) {} else { assertUnreachable(); }
|
|
if (null ?? null ?? true) {} else { assertUnreachable(); }
|
|
|
|
// test use when test false
|
|
if (undefined ?? false) { assertUnreachable(); } else {}
|
|
if (null ?? false) { assertUnreachable(); } else {}
|
|
|
|
if (undefined ?? undefined ?? false) { assertUnreachable(); } else {}
|
|
if (null ?? null ?? false) { assertUnreachable(); } else {}
|
|
|
|
if (undefined ?? false ?? true) { assertUnreachable(); } else {}
|
|
if (null ?? false ?? true) { assertUnreachable(); } else {}
|
|
|
|
// Test use with nested boolean.
|
|
if ((false || undefined) ?? true) {} else { assertUnreachable(); }
|
|
if ((false || null) ?? true) {} else { assertUnreachable(); }
|
|
|
|
if ((false || undefined) ?? undefined ?? true) {} else { assertUnreachable(); }
|
|
if ((false || null) ?? null ?? true) {} else { assertUnreachable(); }
|
|
|
|
if (undefined ?? (false || true)) {} else { assertUnreachable(); }
|
|
if (null ?? (false || true)) {} else { assertUnreachable(); }
|
|
|
|
if (undefined ?? undefined ?? (false || true)) {} else { assertUnreachable(); }
|
|
if (null ?? null ?? (false || true)) {} else { assertUnreachable(); }
|
|
|
|
if (undefined ?? (false || undefined) ?? true) {} else { assertUnreachable(); }
|
|
if (null ?? (false || null) ?? true) {} else { assertUnreachable(); }
|
|
|
|
// Nested nullish.
|
|
if ((null ?? true) || false) {} else { assertUnreachable(); }
|
|
if ((null ?? null ?? true) || false) {} else { assertUnreachable(); }
|
|
|
|
if (false || (null ?? true)) {} else { assertUnreachable(); }
|
|
if (false || (null ?? null ?? true)) {} else { assertUnreachable(); }
|
|
|
|
if ((null ?? false) || false) { assertUnreachable(); } else {}
|
|
if ((null ?? null ?? false) || false) { assertUnreachable(); } else {}
|
|
|
|
if (false || (null ?? false)) { assertUnreachable(); } else {}
|
|
if (false || (null ?? null ?? false)) { assertUnreachable(); } else {}
|