summaryrefslogtreecommitdiffstats
path: root/dom/webgpu/tests/cts/checkout/src/common/internal/query/json_param_value.ts
diff options
context:
space:
mode:
Diffstat (limited to 'dom/webgpu/tests/cts/checkout/src/common/internal/query/json_param_value.ts')
-rw-r--r--dom/webgpu/tests/cts/checkout/src/common/internal/query/json_param_value.ts83
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);
+}