All files / random / _test_utils.ts

70.00% Branches 7/10
70.24% Lines 59/84
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
 
 
x1
x1
 
 
 
 
 
 
 
x1
x1
x1
x1
x1
x1
x1
x1
x1
x1
x1
x1
x1
 
x1
 
x17
 
x17
 
x17
x33
x17
 
x17
x193
 
x193
 
x193
x263
x263
x263
x263
x263
 
 
x263
x263
 
 
 
 
x1883
x2193
 
 
 
x2193
x2193
 
x3193
x3193
x263
x263
x645
x715
x715
 
x957
x957
x957
x645
x263
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
x263
x263
 
 
 
 
x193
 
 
x193
 
x193
 
x369
x193
x193
 
x17
 
x17
x17

















































I





I
































I

























// Copyright 2018-2025 the Deno authors. MIT license.
// deno-lint-ignore-file no-explicit-any
import { platform } from "./_platform.ts";
import { disposableStack } from "../internal/_testing.ts";

/**
 * ```ts
 * type _NumberType = { [K in keyof DataView]: K extends `get${infer T}` ? T : never }
 * type NumberTypeName = _NumberType[keyof _NumberType]
 * ```
 */
const numberTypes = [
  "Int8",
  "Int16",
  "Int32",
  "BigInt64",
  "Uint8",
  "Uint16",
  "Uint32",
  "BigUint64",
  "Float16",
  "Float32",
  "Float64",
] as const;

export function mockLittleEndian(littleEndian: boolean) {
  // partial `DisposableStack` polyfill
  const stack = disposableStack();

  const originalLittleEndian = platform.littleEndian;

  stack.defer(() => {
    platform.littleEndian = originalLittleEndian;
  });

  for (const type of numberTypes) {
    const TypedArray = globalThis[`${type}Array`];

    const MockTypedArray = class extends TypedArray {
      // @ts-ignore missing super() call
      constructor(...args: any[]) {
        const target = new TypedArray(...args);
        const dv = new DataView(
          target.buffer,
          target.byteOffset,
          target.byteLength,
        );

        const proxy: any = new Proxy(target, {
          get(target, prop) {
            if (prop === Symbol.iterator) {
              return Array.prototype[Symbol.iterator];
            }

            if (typeof prop === "symbol" || /\D/.test(prop)) {
              const val = Reflect.get(target, prop, target);
              if (typeof val === "function") {
                return val.bind(target);
              }
              return val;
            }

            const i = Number(prop);
            return dv[`get${type}`](i * target.BYTES_PER_ELEMENT, littleEndian);
          },
          set(target, prop, val: number & bigint) {
            if (typeof prop === "symbol" || /\D/.test(prop)) {
              return Reflect.set(target, prop, val, target);
            }

            const i = Number(prop);
            dv[`set${type}`](i * target.BYTES_PER_ELEMENT, val, littleEndian);
            return true;
          },
        });

        proxy[Symbol.for("nodejs.util.inspect.custom")] = (
          _: any,
          args: any,
          inspect: typeof Deno.inspect,
        ) => {
          return `${
            littleEndian ? "LE" : "BE"
          }_${TypedArray.name}(${proxy.length}) ${inspect([...proxy], args)}`;
        };

        if (
          typeof args[0] === "object" &&
          (Symbol.iterator in args[0] || "length" in args[0])
        ) {
          for (let i = 0; i < target.length; ++i) {
            proxy[i] = target[i];
          }
        }

        return proxy;
      }

      static from(args: any[]) {
        return new this(Array.from(args));
      }
    };

    // @ts-ignore mock
    globalThis[`${type}Array`] = MockTypedArray;

    stack.defer(() => {
      // @ts-ignore restore mock
      globalThis[`${type}Array`] = TypedArray;
    });
  }

  platform.littleEndian = littleEndian;

  return stack;
}