All files / random / _test_utils.ts

82.35% Branches 14/17
66.67% Functions 4/6
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
 
x16
 
x16
 
x16
x16
x16
 
x16
x176
 
x176
 
x176
x70
x70
x70
x70
x70
 
 
x70
x70
 
 
 
 
x1620
x310
 
 
 
x310
x310
 
x1310
x1310
x70
x70
x382
x70
x70
 
x312
x312
x312
x382
x70
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
x70
x70
 
 
 
 
x176
 
 
x176
 
x176
 
x176
x176
x176
 
x16
 
x16
x16

















































I





I
































I

























// Copyright 2018-2026 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;
}