/** If the argument is an Error, throw it. Otherwise, pass it back. */
export function assertOK<T>(value: Error | T): T { if (value instanceof Error) { throw value;
}
return value;
}
/** Options for assertReject, shouldReject, and friends. */
export type ExceptionCheckOptions = { allowMissingStack?: boolean; message?: string };
/** *Resolvesiftheprovidedpromiserejects;rejectsifitdoesnot.
*/
export async function assertReject(
expectedName: string,
p: Promise<unknown>,
{ allowMissingStack = false, message }: ExceptionCheckOptions = {}
): Promise<void> {
await p.then(
() => {
unreachable(message);
},
ex => { assert(ex instanceof Error, 'rejected with a non-Error object'); assert(ex.name === expectedName, `rejected with name ${ex.name} instead of ${expectedName}`); // Asserted as expected if (!allowMissingStack) { const m = message ? ` (${message})` : ''; assert(typeof ex.stack === 'string', 'threw as expected, but missing stack' + m);
}
}
);
}
/** *Assertthiscodeisunreachable.Unconditionallythrowsan`Error`.
*/
export function unreachable(msg?: string): never { thrownew Error(msg);
}
/** *Throwa`SkipTestCase`exception,whichskipsthetestcase.
*/
export function skipTestCase(msg: string): never { thrownew SkipTestCase(msg);
}
/** *Takesapromise`p`,andreturnsanewonewhichrejectsif`p`takestoolong, *andotherwisepassestheresultthrough.
*/
export function raceWithRejectOnTimeout<T>(p: Promise<T>, ms: number, msg: string): Promise<T> { if (globalTestConfig.noRaceWithRejectOnTimeout) {
return p;
} // Setup a promise that will reject after `ms` milliseconds. We cancel this timeout when // `p` is finalized, so the JavaScript VM doesn't hang around waiting for the timer to // complete, once the test runner has finished executing the tests. const timeoutPromise = new Promise((_resolve, reject) => { const handle = timeout(() => {
reject(new PromiseTimeoutError(msg));
}, ms);
p = p.finally(() => clearTimeout(handle));
});
return Promise.race([p, timeoutPromise]) as Promise<T>;
}
/** *MakesacopyofaJS`object`,withthekeysreorderedintosortedorder.
*/
export function sortObjectByKey(v: { [k: string]: unknown }): { [k: string]: unknown } { const sortedObject: { [k: string]: unknown } = {}; for (const k of Object.keys(v).sort()) {
sortedObject[k] = v[k];
}
return sortedObject;
}
/** *DetermineswhethertwoJSvaluesareequal,recursingintoobjectsandarrays. *NaNistreatedspecially,suchthat`objectEquals(NaN,NaN)`.+/-0.0aretreatedasequal *bydefault,butcanbeoptedtobedistinguished. *@paramxthefirstJSvaluesthatgetcompared *@paramythesecondJSvaluesthatgetcompared *@paramdistinguishSignedZeroifsettotrue,treat0.0and-0.0asunequal.Defaulttofalse.
*/
export function objectEquals(
x: unknown,
y: unknown,
distinguishSignedZero: boolean = false
): boolean { if (typeof x !== 'object' || typeof y !== 'object') { if (typeof x === 'number' && typeof y === 'number' && Number.isNaN(x) && Number.isNaN(y)) {
return true;
} // Object.is(0.0, -0.0) is false while (0.0 === -0.0) is true. Other than +/-0.0 and NaN cases, // Object.is works in the same way as ===.
return distinguishSignedZero ? Object.is(x, y) : x === y;
} if (x === null || y === null) return x === y; if (x.constructor !== y.constructor) return false; if (x instanceofFunction) return x === y; if (x instanceof RegExp) return x === y; if (x === y || x.valueOf() === y.valueOf()) return true; if (Array.isArray(x) && Array.isArray(y) && x.length !== y.length) return false; if (x instanceof Date) return false; if (!(x instanceof Object)) return false; if (!(y instanceof Object)) return false;
const x1 = x as { [k: string]: unknown }; const y1 = y as { [k: string]: unknown }; const p = Object.keys(x);
return Object.keys(y).every(i => p.indexOf(i) !== -1) && p.every(i => objectEquals(x1[i], y1[i]));
}
/** *Generatesarangeofvalues`fn(0)..fn(n-1)`.
*/
export function* iterRange<T>(n: number, fn: (i: number) => T): Iterable<T> { for (let i = 0; i < n; ++i) {
yield fn(i);
}
}
/** Creates a (reusable) iterable object that maps `f` over `xs`, lazily. */
export function mapLazy<T, R>(xs: Iterable<T>, f: (x: T) => R): Iterable<R> {
return {
*[Symbol.iterator]() { for (const x of xs) {
yield f(x);
}
},
};
}
/** Count the number of elements `x` for which `predicate(x)` is true. */
export function count<T>(xs: Iterable<T>, predicate: (x: T) => boolean): number {
let count = 0; for (const x of xs) { if (predicate(x)) count++;
}
return count;
}
/** *CreatesareorderedarrayfromtheinputarraybasedontheOrder
*/
export function reorder<R>(order: ReorderOrder, arr: R[]): R[] { switch (order) { case'forward':
return arr.slice(); case'backward':
return arr.slice().reverse(); case'shiftByHalf': { // should this be pseudo random?
return shiftByHalf(arr);
}
}
}
/** *AtypedversionofObject.entries
*/ /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
export function typedEntries<T extends Record<string, any>>(obj: T): Array<[keyof T, T[keyof T]]> { // The cast is done once, inside the helper function, // keeping the call site clean and type-safe.
return Object.entries(obj) as Array<[keyof T, T[keyof T]]>;
}
const TypedArrayBufferViewInstances = [ new Uint8Array(), new Uint8ClampedArray(), new Uint16Array(), new Uint32Array(), new Int8Array(), new Int16Array(), new Int32Array(), new Float16Array(), new Float32Array(), new Float64Array(), new BigInt64Array(), new BigUint64Array(),
] as const;
export type TypedArrayBufferView = (typeof TypedArrayBufferViewInstances)[number];
export type TypedArrayBufferViewConstructor<A extends TypedArrayBufferView = TypedArrayBufferView> =
{ // Interface copied from Uint8Array, and made generic.
readonly prototype: A;
readonly BYTES_PER_ELEMENT: number;
new (): A; new (elements: Iterable<number>): A; new (array: ArrayLike<number> | ArrayBufferLike): A; new (buffer: ArrayBufferLike, byteOffset?: number, length?: number): A; new (length: number): A;
/** Convenience helper for combinations of 1-2 usage bits from a list of usage bits. */
export function combinationsOfOneOrTwoUsages(usages: readonly number[]) { const combinations = []; for (const usage0 of usages) { for (const usage1 of usages) { if (usage0 <= usage1) {
combinations.push(usage0 | usage1);
}
}
}
return combinations;
}
/** *Checksifthebrowsersupportsimmediatedata(experimental). * *Checksfor: *-`setImmediates`methodon`GPURenderPassEncoder`,`GPUComputePassEncoder`,or`GPURenderBundleEncoder`prototypes. *-`maxImmediateSize`propertyon`GPUSupportedLimits`prototype. *-`immediate_address_space`featurein`gpu.wgslLanguageFeatures`. * *Thishelperisusedtoskiptestswhentheenvironmentdoesnotsupportimmediatedatafunctionality.
*/
export function supportsImmediateData(gpu: GPU): boolean {
return ( 'setImmediates' in GPURenderPassEncoder.prototype || 'setImmediates' in GPUComputePassEncoder.prototype || 'setImmediates' in GPURenderBundleEncoder.prototype || 'maxImmediateSize' in GPUSupportedLimits.prototype ||
gpu.wgslLanguageFeatures.has('immediate_address_space')
);
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.24 Sekunden
(vorverarbeitet am 2026-08-27)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.