diff options
Diffstat (limited to '')
-rw-r--r-- | dom/webgpu/tests/cts/checkout/src/common/internal/query/json_param_value.ts | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/dom/webgpu/tests/cts/checkout/src/common/internal/query/json_param_value.ts b/dom/webgpu/tests/cts/checkout/src/common/internal/query/json_param_value.ts new file mode 100644 index 0000000000..f4be7642d3 --- /dev/null +++ b/dom/webgpu/tests/cts/checkout/src/common/internal/query/json_param_value.ts @@ -0,0 +1,83 @@ +import { assert, sortObjectByKey } from '../../util/util.js'; +import { JSONWithUndefined } from '../params_utils.js'; + +// JSON can't represent various values and by default stores them as `null`. +// Instead, storing them as a magic string values in JSON. +const jsUndefinedMagicValue = '_undef_'; +const jsNaNMagicValue = '_nan_'; +const jsPositiveInfinityMagicValue = '_posinfinity_'; +const jsNegativeInfinityMagicValue = '_neginfinity_'; + +// -0 needs to be handled separately, because -0 === +0 returns true. Not +// special casing +0/0, since it behaves intuitively. Assuming that if -0 is +// being used, the differentiation from +0 is desired. +const jsNegativeZeroMagicValue = '_negzero_'; + +const toStringMagicValue = new Map<unknown, string>([ + [undefined, jsUndefinedMagicValue], + [NaN, jsNaNMagicValue], + [Number.POSITIVE_INFINITY, jsPositiveInfinityMagicValue], + [Number.NEGATIVE_INFINITY, jsNegativeInfinityMagicValue], + // No -0 handling because it is special cased. +]); + +const fromStringMagicValue = new Map<string, unknown>([ + [jsUndefinedMagicValue, undefined], + [jsNaNMagicValue, NaN], + [jsPositiveInfinityMagicValue, Number.POSITIVE_INFINITY], + [jsNegativeInfinityMagicValue, Number.NEGATIVE_INFINITY], + // -0 is handled in this direction because there is no comparison issue. + [jsNegativeZeroMagicValue, -0], +]); + +function stringifyFilter(k: string, v: unknown): unknown { + // Make sure no one actually uses a magic value as a parameter. + if (typeof v === 'string') { + assert( + !fromStringMagicValue.has(v), + `${v} is a magic value for stringification, so cannot be used` + ); + + assert( + v !== jsNegativeZeroMagicValue, + `${v} is a magic value for stringification, so cannot be used` + ); + } + + if (Object.is(v, -0)) { + return jsNegativeZeroMagicValue; + } + + return toStringMagicValue.has(v) ? toStringMagicValue.get(v) : v; +} + +export function stringifyParamValue(value: JSONWithUndefined): string { + return JSON.stringify(value, stringifyFilter); +} + +/** + * Like stringifyParamValue but sorts dictionaries by key, for hashing. + */ +export function stringifyParamValueUniquely(value: JSONWithUndefined): string { + return JSON.stringify(value, (k, v) => { + if (typeof v === 'object' && v !== null) { + return sortObjectByKey(v); + } + + return stringifyFilter(k, v); + }); +} + +// 'any' is part of the JSON.parse reviver interface, so cannot be avoided. +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function parseParamValueReviver(k: string, v: any): any { + if (fromStringMagicValue.has(v)) { + return fromStringMagicValue.get(v); + } + + return v; +} + +export function parseParamValue(s: string): JSONWithUndefined { + return JSON.parse(s, parseParamValueReviver); +} |