/** * @license * Copyright Google LLC All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.dev/license */ // The functions in this file verify that the assumptions we are making // about state in an instruction are correct before implementing any logic. // They are meant only to be called in dev mode as sanity checks. import {getActiveConsumer} from '../../primitives/signals'; import {stringify} from './stringify'; export function assertNumber(actual: any, msg: string): asserts actual is number { if (!(typeof actual === 'number')) { throwError(msg, typeof actual, 'number', '==='); } } export function assertNumberInRange( actual: any, minInclusive: number, maxInclusive: number, ): asserts actual is number { assertNumber(actual, 'Expected a number'); assertLessThanOrEqual(actual, maxInclusive, 'Expected number to be less than or equal to'); assertGreaterThanOrEqual(actual, minInclusive, 'Expected number to be greater than or equal to'); } export function assertString(actual: any, msg: string): asserts actual is string { if (!(typeof actual === 'string')) { throwError(msg, actual === null ? 'null' : typeof actual, 'string', '==='); } } export function assertFunction(actual: any, msg: string): asserts actual is Function { if (!(typeof actual === 'function')) { throwError(msg, actual === null ? 'null' : typeof actual, 'function', '==='); } } export function assertEqual(actual: T, expected: T, msg: string) { if (!(actual == expected)) { throwError(msg, actual, expected, '=='); } } export function assertNotEqual(actual: T, expected: T, msg: string): asserts actual is T { if (!(actual != expected)) { throwError(msg, actual, expected, '!='); } } export function assertSame(actual: T, expected: T, msg: string): asserts actual is T { if (!(actual === expected)) { throwError(msg, actual, expected, '==='); } } export function assertNotSame(actual: T, expected: T, msg: string) { if (!(actual !== expected)) { throwError(msg, actual, expected, '!=='); } } export function assertLessThan(actual: T, expected: T, msg: string): asserts actual is T { if (!(actual < expected)) { throwError(msg, actual, expected, '<'); } } export function assertLessThanOrEqual(actual: T, expected: T, msg: string): asserts actual is T { if (!(actual <= expected)) { throwError(msg, actual, expected, '<='); } } export function assertGreaterThan(actual: T, expected: T, msg: string): asserts actual is T { if (!(actual > expected)) { throwError(msg, actual, expected, '>'); } } export function assertGreaterThanOrEqual( actual: T, expected: T, msg: string, ): asserts actual is T { if (!(actual >= expected)) { throwError(msg, actual, expected, '>='); } } export function assertNotDefined(actual: T, msg: string) { if (actual != null) { throwError(msg, actual, null, '=='); } } export function assertDefined(actual: T | null | undefined, msg: string): asserts actual is T { if (actual == null) { throwError(msg, actual, null, '!='); } } export function throwError(msg: string): never; export function throwError(msg: string, actual: any, expected: any, comparison: string): never; export function throwError(msg: string, actual?: any, expected?: any, comparison?: string): never { throw new Error( `ASSERTION ERROR: ${msg}` + (comparison == null ? '' : ` [Expected=> ${expected} ${comparison} ${actual} <=Actual]`), ); } export function assertDomNode(node: any): asserts node is Node { if (!(node instanceof Node)) { throwError(`The provided value must be an instance of a DOM Node but got ${stringify(node)}`); } } export function assertElement(node: any): asserts node is Element { if (!(node instanceof Element)) { throwError(`The provided value must be an element but got ${stringify(node)}`); } } export function assertIndexInRange(arr: any[], index: number) { assertDefined(arr, 'Array must be defined.'); const maxLen = arr.length; if (index < 0 || index >= maxLen) { throwError(`Index expected to be less than ${maxLen} but got ${index}`); } } export function assertOneOf(value: any, ...validValues: any[]) { if (validValues.indexOf(value) !== -1) return true; throwError( `Expected value to be one of ${JSON.stringify(validValues)} but was ${JSON.stringify(value)}.`, ); } export function assertNotReactive(fn: string): void { if (getActiveConsumer() !== null) { throwError(`${fn}() should never be called in a reactive context.`); } }