@cloudpss/ubjson 0.5.55 → 0.6.0-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/dist/base/decoder.js +2 -5
  2. package/dist/base/decoder.js.map +1 -1
  3. package/dist/base/encoder.js +6 -8
  4. package/dist/base/encoder.js.map +1 -1
  5. package/dist/encoder.js +8 -5
  6. package/dist/encoder.js.map +1 -1
  7. package/dist/helper/encode.d.ts.map +1 -1
  8. package/dist/helper/encode.js +5 -2
  9. package/dist/helper/encode.js.map +1 -1
  10. package/dist/helper/string-decoder.d.ts +2 -0
  11. package/dist/helper/string-decoder.d.ts.map +1 -1
  12. package/dist/helper/string-decoder.js +16 -4
  13. package/dist/helper/string-decoder.js.map +1 -1
  14. package/dist/helper/string-encoder.d.ts +5 -0
  15. package/dist/helper/string-encoder.d.ts.map +1 -1
  16. package/dist/helper/string-encoder.js +28 -8
  17. package/dist/helper/string-encoder.js.map +1 -1
  18. package/dist/stream/decoder.js +0 -2
  19. package/dist/stream/decoder.js.map +1 -1
  20. package/dist/stream/encoder.js +0 -2
  21. package/dist/stream/encoder.js.map +1 -1
  22. package/dist/stream-helper/encoder.js +0 -1
  23. package/dist/stream-helper/encoder.js.map +1 -1
  24. package/package.json +2 -2
  25. package/src/helper/encode.ts +5 -2
  26. package/src/helper/string-decoder.ts +22 -6
  27. package/src/helper/string-encoder.ts +35 -8
  28. package/tests/{.utils.js → .utils.ts} +9 -8
  29. package/tests/{decode.js → decode.ts} +15 -17
  30. package/tests/e2e/{.data.js → .data.ts} +2 -4
  31. package/tests/e2e/{no-buffer-text.js → no-buffer-text.ts} +2 -2
  32. package/tests/e2e/{no-buffer.js → no-buffer.ts} +2 -2
  33. package/tests/e2e/{no-encode-into.js → no-encode-into.ts} +2 -2
  34. package/tests/e2e/{no-textencoder-decoder.js → no-textencoder-decoder.ts} +2 -2
  35. package/tests/e2e/{normal.js → normal.ts} +1 -1
  36. package/tests/e2e/{stream.js → stream.ts} +6 -6
  37. package/tests/{encode.js → encode.ts} +6 -6
  38. package/tests/{huge-string.js → huge-string.ts} +2 -5
  39. package/tests/rxjs/{decode.js → decode.ts} +18 -21
  40. package/tests/rxjs/{encode.js → encode.ts} +3 -5
  41. package/tests/stream/{decode.js → decode.ts} +8 -10
  42. package/tests/stream/{encode.js → encode.ts} +8 -10
  43. package/tests/stream/{many.js → many.ts} +19 -30
  44. package/tests/{string-encoding.js → string-encoding.ts} +7 -4
  45. package/jest.config.js +0 -3
  46. package/tests/tsconfig.json +0 -3
  47. package/tsconfig.json +0 -7
  48. /package/tests/{many.js → many.ts} +0 -0
@@ -114,12 +114,32 @@ export function nativeEncodeInto(v: string, buf: Uint8Array, offset: number): nu
114
114
  const encoded = TEXT_ENCODER!.encodeInto(v, buf.subarray(offset));
115
115
  return encoded.written;
116
116
  }
117
+
118
+ /** Undocumented */
119
+ type BufferUndocumented = Buffer & {
120
+ utf8Write: (this: Uint8Array, v: string, offset: number, byteLength: number) => number;
121
+ };
122
+ let utf8Write: ((this: Uint8Array, v: string, offset: number, byteLength: number) => number) | null;
123
+ /**
124
+ * Encode string into utf-8.
125
+ * Provided `buf` MUST have enough space.
126
+ */
127
+ export function nodeEncodeInto(v: string, buf: Uint8Array, offset: number): number {
128
+ const encoded = utf8Write!.call(buf, v, offset, buf.byteLength - offset);
129
+ return encoded;
130
+ }
131
+
132
+ /**
133
+ * 默认编码器阈值
134
+ * @see /benchmark/string-encoder.js
135
+ */
136
+ const DEFAULT_TEXT_ENCODER_THRESHOLD = 45;
117
137
  /**
118
138
  * Encode string into utf-8.
119
139
  * Provided `buf` MUST have enough space.
120
140
  */
121
141
  export function myEncodeInto(v: string, buf: Uint8Array, offset: number): number {
122
- if (v.length < 55) {
142
+ if (v.length < DEFAULT_TEXT_ENCODER_THRESHOLD) {
123
143
  return jsEncodeInto(v, buf, offset);
124
144
  }
125
145
  return nativeEncodeInto(v, buf, offset);
@@ -137,14 +157,21 @@ export let encode: (v: string) => Uint8Array<ArrayBuffer>;
137
157
  /** 重设环境 */
138
158
  export function resetEnv(): void {
139
159
  TEXT_ENCODER = typeof TextEncoder == 'function' ? new TextEncoder() : null;
140
- stringByteLength =
141
- typeof Buffer == 'function' && typeof Buffer.byteLength == 'function'
142
- ? nodeStringByteLength
143
- : jsStringByteLength;
144
- encodeInto = typeof TEXT_ENCODER?.encodeInto == 'function' ? myEncodeInto : jsEncodeInto;
160
+ const hasBuffer = typeof Buffer == 'function';
161
+ stringByteLength = hasBuffer && typeof Buffer.byteLength == 'function' ? nodeStringByteLength : jsStringByteLength;
162
+
163
+ utf8Write = hasBuffer ? (Buffer.prototype as BufferUndocumented).utf8Write : null;
164
+ encodeInto =
165
+ typeof utf8Write == 'function'
166
+ ? nodeEncodeInto
167
+ : typeof TEXT_ENCODER?.encodeInto == 'function'
168
+ ? myEncodeInto
169
+ : jsEncodeInto;
170
+ // eslint-disable-next-line @typescript-eslint/unbound-method
171
+ const from = hasBuffer ? Buffer.from : null;
145
172
  encode =
146
- typeof Buffer == 'function' && Buffer.from
147
- ? (v) => Buffer.from(v, 'utf8')
173
+ typeof from == 'function'
174
+ ? (v) => from(v, 'utf8')
148
175
  : TEXT_ENCODER
149
176
  ? (v) => TEXT_ENCODER!.encode(v)
150
177
  : (v) => {
@@ -7,7 +7,7 @@ import '../dist/options.js';
7
7
  /**
8
8
  * 重设所有环境
9
9
  */
10
- export function resetEnv() {
10
+ export function resetEnv(): void {
11
11
  resetDecoderEnv();
12
12
  resetEncoderEnv();
13
13
  resetEncoder();
@@ -15,25 +15,26 @@ export function resetEnv() {
15
15
 
16
16
  /**
17
17
  * 输入转为数字数组以便比较
18
- * @param {[ArrayBuffer] | [Uint8Array] | (number | string)[]} args 输入
19
- * @returns {number[]} 数字数组
18
+ * @param args 输入
19
+ * @returns 数字数组
20
20
  */
21
- export function toArray(...args) {
21
+ export function toArray(...args: [ArrayBuffer] | [Uint8Array] | Array<number | string>): number[] {
22
22
  if (args[0] instanceof ArrayBuffer) {
23
23
  return Array.from(new Uint8Array(args[0]));
24
24
  }
25
25
  if (args[0] instanceof Uint8Array) {
26
26
  return Array.from(args[0]);
27
27
  }
28
- return args.map((x) => (typeof x == 'number' ? x : /** @type {string} */ (x).charCodeAt(0)));
28
+ // eslint-disable-next-line unicorn/prefer-code-point
29
+ return args.map((x) => (typeof x == 'number' ? x : (x as string).charCodeAt(0)));
29
30
  }
30
31
 
31
32
  /**
32
33
  * 将数字或字符串转换为 Uint8Array
33
- * @param {...string | number} args 数字或 char 的数组
34
- * @returns {Uint8Array} Uint8Array
34
+ * @param args 数字或 char 的数组
35
+ * @returns Uint8Array
35
36
  */
36
- export function toBuffer(...args) {
37
+ export function toBuffer(...args: Array<string | number>): Uint8Array<ArrayBuffer> {
37
38
  const data = [];
38
39
  for (const x of args) {
39
40
  if (typeof x == 'number') {
@@ -3,7 +3,7 @@
3
3
  */
4
4
 
5
5
  import { decode, UnexpectedEof } from '../dist/index.js';
6
- import { toBuffer } from './.utils.js';
6
+ import { toBuffer } from './.utils.ts';
7
7
 
8
8
  test('decode unsupported type', () => {
9
9
  expect(() => decode(toBuffer('!'))).toThrow();
@@ -141,6 +141,7 @@ test('decode huge string (unexpected eof) [error]', () => {
141
141
 
142
142
  test('decode ascii string', () => {
143
143
  const header = toBuffer('S', 'I', 0x3f, 0xff);
144
+ // eslint-disable-next-line unicorn/prefer-code-point
144
145
  const payload = new Uint8Array(0x3fff + header.byteLength).fill('a'.charCodeAt(0));
145
146
  payload.set(header);
146
147
  expect(decode(payload)).toBe('a'.repeat(0x3fff));
@@ -148,6 +149,7 @@ test('decode ascii string', () => {
148
149
 
149
150
  test('decode ascii string [huge]', () => {
150
151
  const header = toBuffer('S', 'I', 0x7f, 0xff);
152
+ // eslint-disable-next-line unicorn/prefer-code-point
151
153
  const payload = new Uint8Array(0x7fff + header.byteLength).fill('a'.charCodeAt(0));
152
154
  payload.set(header);
153
155
  expect(decode(payload)).toBe('a'.repeat(0x7fff));
@@ -507,18 +509,16 @@ test('decode (eof at key)', () => {
507
509
 
508
510
  describe('proto poisoning attack', () => {
509
511
  it('should remove __proto__ key', () => {
510
- const obj = /** @type {Record<string, unknown>} */ (
511
- decode(toBuffer('{', 'i', 9, '__proto__', '{', 'i', 1, 'a', 'S', 'i', 3, 'abc', '}', '}'))
512
- );
512
+ const obj = decode(
513
+ toBuffer('{', 'i', 9, '__proto__', '{', 'i', 1, 'a', 'S', 'i', 3, 'abc', '}', '}'),
514
+ ) as Record<string, unknown>;
513
515
  expect(Object.hasOwn(obj, '__proto__')).toBe(false);
514
516
  expect(obj['__proto__']).toBe(Object.prototype);
515
517
  });
516
518
  it('should allow __proto__ key', () => {
517
- const obj = /** @type {Record<string, unknown>} */ (
518
- decode(toBuffer('{', 'i', 9, '__proto__', '{', 'i', 1, 'a', 'S', 'i', 3, 'abc', '}', '}'), {
519
- protoAction: 'allow',
520
- })
521
- );
519
+ const obj = decode(toBuffer('{', 'i', 9, '__proto__', '{', 'i', 1, 'a', 'S', 'i', 3, 'abc', '}', '}'), {
520
+ protoAction: 'allow',
521
+ }) as Record<string, unknown>;
522
522
  expect(Object.hasOwn(obj, '__proto__')).toBe(true);
523
523
  expect(obj['__proto__']).toEqual({ a: 'abc' });
524
524
  });
@@ -533,18 +533,16 @@ describe('proto poisoning attack', () => {
533
533
 
534
534
  describe('constructor poisoning attack', () => {
535
535
  it('should remove constructor key', () => {
536
- const obj = /** @type {Record<string, unknown>} */ (
537
- decode(toBuffer('{', 'i', 11, 'constructor', '{', 'i', 1, 'a', 'S', 'i', 3, 'abc', '}', '}'), {
538
- constructorAction: 'remove',
539
- })
540
- );
536
+ const obj = decode(toBuffer('{', 'i', 11, 'constructor', '{', 'i', 1, 'a', 'S', 'i', 3, 'abc', '}', '}'), {
537
+ constructorAction: 'remove',
538
+ }) as Record<string, unknown>;
541
539
  expect(Object.hasOwn(obj, 'constructor')).toBe(false);
542
540
  expect(obj.constructor).toBe(Object);
543
541
  });
544
542
  it('should allow constructor key', () => {
545
- const obj = /** @type {Record<string, unknown>} */ (
546
- decode(toBuffer('{', 'i', 11, 'constructor', '{', 'i', 1, 'a', 'S', 'i', 3, 'abc', '}', '}'))
547
- );
543
+ const obj = decode(
544
+ toBuffer('{', 'i', 11, 'constructor', '{', 'i', 1, 'a', 'S', 'i', 3, 'abc', '}', '}'),
545
+ ) as Record<string, unknown>;
548
546
  expect(Object.hasOwn(obj, 'constructor')).toBe(true);
549
547
  expect(obj.constructor).toEqual({ a: 'abc' });
550
548
  });
@@ -1,7 +1,5 @@
1
- /** @type {Record<string, unknown>} */
2
- export const INPUTS = {};
3
- /** @type {Record<string, unknown>} */
4
- export const EXPECTED = {};
1
+ export const INPUTS: Record<string, unknown> = {};
2
+ export const EXPECTED: Record<string, unknown> = {};
5
3
 
6
4
  INPUTS['number 0'] = 0;
7
5
  INPUTS['number 1'] = 1;
@@ -1,5 +1,5 @@
1
- import { resetEnv } from '../.utils.js';
2
- import { INPUTS, EXPECTED } from './.data.js';
1
+ import { resetEnv } from '../.utils.ts';
2
+ import { INPUTS, EXPECTED } from './.data.ts';
3
3
  import { encode, decode } from '../../dist/index.js';
4
4
 
5
5
  describe('no Buffer and no textencoder/decoder', () => {
@@ -1,5 +1,5 @@
1
- import { resetEnv } from '../.utils.js';
2
- import { INPUTS, EXPECTED } from './.data.js';
1
+ import { resetEnv } from '../.utils.ts';
2
+ import { INPUTS, EXPECTED } from './.data.ts';
3
3
  import { encode, decode } from '../../dist/index.js';
4
4
 
5
5
  describe('no Buffer', () => {
@@ -1,5 +1,5 @@
1
- import { resetEnv } from '../.utils.js';
2
- import { INPUTS, EXPECTED } from './.data.js';
1
+ import { resetEnv } from '../.utils.ts';
2
+ import { INPUTS, EXPECTED } from './.data.ts';
3
3
  import { encode, decode } from '../../dist/index.js';
4
4
 
5
5
  describe('no encodeInto', () => {
@@ -1,5 +1,5 @@
1
- import { resetEnv } from '../.utils.js';
2
- import { INPUTS, EXPECTED } from './.data.js';
1
+ import { resetEnv } from '../.utils.ts';
2
+ import { INPUTS, EXPECTED } from './.data.ts';
3
3
  import { encode, decode } from '../../dist/index.js';
4
4
 
5
5
  describe('no textencoder/decoder', () => {
@@ -1,4 +1,4 @@
1
- import { EXPECTED, INPUTS } from './.data.js';
1
+ import { EXPECTED, INPUTS } from './.data.ts';
2
2
  import { encode, decode } from '../../dist/index.js';
3
3
 
4
4
  it.each(Object.keys(INPUTS))('%s', (name) => {
@@ -1,6 +1,6 @@
1
1
  import { Readable } from 'node:stream';
2
2
  import { encode as encodeStream, decode as decodeStream } from '../../dist/stream/index.js';
3
- import { EXPECTED, INPUTS } from './.data.js';
3
+ import { EXPECTED, INPUTS } from './.data.ts';
4
4
 
5
5
  describe('stream', () => {
6
6
  it.each(Object.keys(INPUTS))('%s', async (name) => {
@@ -8,15 +8,15 @@ describe('stream', () => {
8
8
  const expected = EXPECTED[name] ?? input;
9
9
  if (expected instanceof Error) {
10
10
  await expect(async () => {
11
- const encoded = await Readable.fromWeb(/** @type {any} */ (encodeStream(input))).toArray();
11
+ const encoded = await Readable.fromWeb(encodeStream(input) as never).toArray();
12
12
  const decoded = await decodeStream(
13
- /** @type {ReadableStream<Uint8Array>} */ (Readable.toWeb(Readable.from(encoded))),
13
+ Readable.toWeb(Readable.from(encoded)) as ReadableStream<Uint8Array<ArrayBuffer>>,
14
14
  );
15
15
  expect(decoded).toEqual(expected);
16
16
  }).rejects.toThrow(expected);
17
17
  } else {
18
- const encoded = await Readable.fromWeb(/** @type {any} */ (encodeStream(input))).toArray();
19
- const data = encoded.flatMap((/** @type {Buffer} */ chunk) => {
18
+ const encoded = await Readable.fromWeb(encodeStream(input) as never).toArray();
19
+ const data = encoded.flatMap((chunk: Buffer<ArrayBuffer>) => {
20
20
  if (chunk.length < 2) return [chunk];
21
21
  // split to random chunks
22
22
  const chunks = [];
@@ -29,7 +29,7 @@ describe('stream', () => {
29
29
  return chunks;
30
30
  });
31
31
  const decoded = await decodeStream(
32
- /** @type {ReadableStream<Uint8Array>} */ (Readable.toWeb(Readable.from(data))),
32
+ Readable.toWeb(Readable.from(data)) as ReadableStream<Uint8Array<ArrayBuffer>>,
33
33
  );
34
34
  expect(decoded).toEqual(expected);
35
35
  }
@@ -4,10 +4,10 @@
4
4
 
5
5
  import { encode, decode } from '../dist/index.js';
6
6
  import { getEncoder } from '../dist/encoder.js';
7
- import { toArray } from './.utils.js';
7
+ import { toArray } from './.utils.ts';
8
8
 
9
9
  // @ts-expect-error Access private property
10
- const poolInit = getEncoder().pool;
10
+ const poolInit = getEncoder().pool as Uint8Array<ArrayBuffer>;
11
11
 
12
12
  test('encode function', () => {
13
13
  expect(() =>
@@ -444,10 +444,10 @@ test('encode object (only null values)', () => {
444
444
  });
445
445
 
446
446
  test('encode object (skip prototype)', () => {
447
- const obj = Object.create({ a: 2, x: 'xx' });
448
- obj.a = 1;
449
- obj.b = 'a';
450
- obj.c = true;
447
+ const obj = Object.create({ a: 2, x: 'xx' }) as Record<string, unknown>;
448
+ obj['a'] = 1;
449
+ obj['b'] = 'a';
450
+ obj['c'] = true;
451
451
  expect(toArray(encode(obj))).toEqual(
452
452
  toArray('{', 'i', 1, 'a', 'U', 1, 'i', 1, 'b', 'C', 'a', 'i', 1, 'c', 'T', '}'),
453
453
  );
@@ -1,16 +1,13 @@
1
1
  import { Buffer } from 'node:buffer';
2
2
  import { encode } from '../dist/index.js';
3
- import { toArray, resetEnv } from './.utils.js';
3
+ import { toArray, resetEnv } from './.utils.ts';
4
4
 
5
5
  const STR_BYTE_LENGTH = 128 * 1024 * 1024 - 20;
6
6
 
7
7
  /**
8
8
  * 构造测试字符串
9
- * @param {string} char 使用的字符
10
- * @param {number} byteLength 需要的长度
11
- * @returns {[Uint8Array, string]}
12
9
  */
13
- function makeString(char, byteLength) {
10
+ function makeString(char: string, byteLength: number): [Uint8Array<ArrayBuffer>, string] {
14
11
  const encoded = new TextEncoder().encode(char);
15
12
  return [encoded, char.repeat(byteLength / encoded.byteLength)];
16
13
  }
@@ -2,36 +2,30 @@
2
2
  * Tests from https://bitbucket.org/shelacek/ubjson
3
3
  */
4
4
  import { jest } from '@jest/globals';
5
- import { firstValueFrom, of, Subject } from 'rxjs';
5
+ import { firstValueFrom, type Observable, of, Subject } from 'rxjs';
6
6
  import { decode as decodePipe } from '../../dist/rxjs/index.js';
7
- import { toBuffer } from '../.utils.js';
7
+ import { toBuffer } from '../.utils.ts';
8
8
  import { UnexpectedEofError as UnexpectedEof } from '../../dist/helper/errors.js';
9
9
 
10
10
  /**
11
11
  * 包装为 promise
12
- * @param {Uint8Array} data ubjson 数据
13
- * @returns {Promise<unknown>}
14
12
  */
15
- async function decode(data) {
13
+ async function decode(data: BufferSource): Promise<unknown> {
16
14
  const readable = of(data);
17
15
  return firstValueFrom(readable.pipe(decodePipe()), { defaultValue: undefined });
18
16
  }
19
17
 
20
18
  /**
21
19
  * 包装为 promise
22
- * @param {import("rxjs").Observable<Uint8Array>} observable ubjson 数据流
23
- * @param {(data: unknown) => void} onData 数据回调
24
20
  */
25
- async function decodeStream(observable, onData) {
26
- return /** @type {Promise<void>} */ (
27
- new Promise((resolve, reject) => {
28
- observable.pipe(decodePipe()).subscribe({
29
- next: onData,
30
- error: reject,
31
- complete: resolve,
32
- });
33
- })
34
- );
21
+ async function decodeStream(observable: Observable<BufferSource>, onData: (data: unknown) => void) {
22
+ return new Promise<void>((resolve, reject) => {
23
+ observable.pipe(decodePipe()).subscribe({
24
+ next: onData,
25
+ error: reject,
26
+ complete: resolve,
27
+ });
28
+ });
35
29
  }
36
30
 
37
31
  test('decode unsupported type', async () => {
@@ -117,6 +111,7 @@ test('decode string (unexpected eof) [error]', async () => {
117
111
 
118
112
  test('decode ascii string', async () => {
119
113
  const header = toBuffer('S', 'I', 0x3f, 0xff);
114
+ // eslint-disable-next-line unicorn/prefer-code-point
120
115
  const payload = new Uint8Array(0x3fff + header.byteLength).fill('a'.charCodeAt(0));
121
116
  payload.set(header);
122
117
  expect(await decode(payload)).toBe('a'.repeat(0x3fff));
@@ -125,6 +120,7 @@ test('decode ascii string', async () => {
125
120
  test('decode ascii string 32kiB [huge]', async () => {
126
121
  const size = 0x7fff;
127
122
  const header = toBuffer('S', 'I', 0x7f, 0xff);
123
+ // eslint-disable-next-line unicorn/prefer-code-point
128
124
  const payload = new Uint8Array(size + header.byteLength).fill('a'.charCodeAt(0));
129
125
  payload.set(header);
130
126
  expect(await decode(payload)).toBe('a'.repeat(size));
@@ -133,6 +129,7 @@ test('decode ascii string 32kiB [huge]', async () => {
133
129
  test('decode ascii string 64MB [huge]', async () => {
134
130
  const size = 0x03d0_9000;
135
131
  const header = toBuffer('S', 'l', 0x03, 0xd0, 0x90, 0x00);
132
+ // eslint-disable-next-line unicorn/prefer-code-point
136
133
  const payload = new Uint8Array(size + header.byteLength).fill('a'.charCodeAt(0));
137
134
  payload.set(header);
138
135
  expect(await decode(payload)).toBe('a'.repeat(size));
@@ -469,7 +466,7 @@ test('decode object (empty key, optimized)', async () => {
469
466
  });
470
467
 
471
468
  test('decode stream', async () => {
472
- const stream = new Subject();
469
+ const stream = new Subject<BufferSource>();
473
470
  // while decoding streaming, N will be regarded as a no-op, rather than an undefined value
474
471
  const onData = jest.fn();
475
472
  const result = decodeStream(stream, onData);
@@ -487,7 +484,7 @@ test('decode stream', async () => {
487
484
  });
488
485
 
489
486
  test('decode bad stream [error]', async () => {
490
- const stream = new Subject();
487
+ const stream = new Subject<BufferSource>();
491
488
  // while decoding streaming, N will be regarded as a no-op, rather than an undefined value
492
489
  const onData = jest.fn();
493
490
  const result = decodeStream(stream, onData);
@@ -506,7 +503,7 @@ test('decode bad stream [error]', async () => {
506
503
  });
507
504
 
508
505
  test('decode partial stream [error]', async () => {
509
- const stream = new Subject();
506
+ const stream = new Subject<BufferSource>();
510
507
  // while decoding streaming, N will be regarded as a no-op, rather than an undefined value
511
508
  const onData = jest.fn();
512
509
  const result = decodeStream(stream, onData);
@@ -522,7 +519,7 @@ test('decode partial stream [error]', async () => {
522
519
  });
523
520
 
524
521
  test('decode error stream [error]', async () => {
525
- const stream = new Subject();
522
+ const stream = new Subject<BufferSource>();
526
523
  // while decoding streaming, N will be regarded as a no-op, rather than an undefined value
527
524
  const onData = jest.fn();
528
525
  const result = decodeStream(stream, onData);
@@ -4,14 +4,12 @@
4
4
  import { firstValueFrom, of, map, reduce, Subject, toArray as rxjsToArray } from 'rxjs';
5
5
  import { encode } from '../../dist/rxjs/index.js';
6
6
  import { decode, encode as encodeRef } from '../../dist/index.js';
7
- import { toArray } from '../.utils.js';
7
+ import { toArray } from '../.utils.ts';
8
8
 
9
9
  /**
10
10
  * 包装为 promise
11
- * @param {unknown} value 要编码的值
12
- * @returns {Promise<Buffer>}
13
11
  */
14
- async function encodeAsync(value) {
12
+ async function encodeAsync(value: unknown): Promise<Buffer<ArrayBuffer>> {
15
13
  return firstValueFrom(
16
14
  of(value).pipe(
17
15
  encode(),
@@ -304,7 +302,7 @@ test('encode object (only null values)', async () => {
304
302
  });
305
303
 
306
304
  test('encode object (skip prototype)', async () => {
307
- const obj = /** @type {Record<string, unknown>} */ (Object.create({ a: 2, x: 'xx' }));
305
+ const obj = Object.create({ a: 2, x: 'xx' }) as Record<string, unknown>;
308
306
  obj['a'] = 1;
309
307
  obj['b'] = 'a';
310
308
  obj['c'] = true;
@@ -4,25 +4,21 @@
4
4
  import { jest } from '@jest/globals';
5
5
  import { Readable, Transform } from 'node:stream';
6
6
  import { decoder as decodeStream, decode as decodeAsync } from '../../dist/stream/index.js';
7
- import { toBuffer } from '../.utils.js';
7
+ import { toBuffer } from '../.utils.ts';
8
8
  import { UnexpectedEofError as UnexpectedEof } from '../../dist/helper/errors.js';
9
9
 
10
10
  /**
11
11
  * 包装为 promise
12
- * @param {Uint8Array} data ubjson 数据
13
- * @returns {Promise<unknown>}
14
12
  */
15
- async function decode(data) {
13
+ async function decode(data: Uint8Array<ArrayBuffer>): Promise<unknown> {
16
14
  const readable = Readable.from([data], { objectMode: false });
17
- return decodeAsync(/** @type {ReadableStream<Uint8Array>} */ (Readable.toWeb(readable)));
15
+ return decodeAsync(Readable.toWeb(readable) as ReadableStream<Uint8Array<ArrayBuffer>>);
18
16
  }
19
17
 
20
18
  /**
21
19
  * 包装为 promise
22
- * @param {import("stream").Readable} stream ubjson 流
23
- * @returns {Promise<void>}
24
20
  */
25
- async function eos(stream) {
21
+ async function eos(stream: Readable): Promise<void> {
26
22
  return new Promise((resolve, reject) => {
27
23
  stream.on('error', reject);
28
24
  stream.on('end', resolve);
@@ -113,6 +109,7 @@ test('decode string (unexpected eof) [error]', async () => {
113
109
 
114
110
  test('decode ascii string', async () => {
115
111
  const header = toBuffer('S', 'I', 0x3f, 0xff);
112
+ // eslint-disable-next-line unicorn/prefer-code-point
116
113
  const payload = new Uint8Array(0x3fff + header.byteLength).fill('a'.charCodeAt(0));
117
114
  payload.set(header);
118
115
  expect(await decode(payload)).toBe('a'.repeat(0x3fff));
@@ -120,6 +117,7 @@ test('decode ascii string', async () => {
120
117
 
121
118
  test('decode ascii string [huge]', async () => {
122
119
  const header = toBuffer('S', 'I', 0x7f, 0xff);
120
+ // eslint-disable-next-line unicorn/prefer-code-point
123
121
  const payload = new Uint8Array(0x7fff + header.byteLength).fill('a'.charCodeAt(0));
124
122
  payload.set(header);
125
123
  expect(await decode(payload)).toBe('a'.repeat(0x7fff));
@@ -456,7 +454,7 @@ test('decode object (empty key, optimized)', async () => {
456
454
  });
457
455
 
458
456
  test('decode stream', async () => {
459
- const stream = Transform.fromWeb(/** @type {any} */ (decodeStream()), { objectMode: true });
457
+ const stream = Transform.fromWeb(decodeStream() as never, { objectMode: true });
460
458
  // while decoding streaming, N will be regarded as a no-op, rather than an undefined value
461
459
  const onData = jest.fn();
462
460
  stream.on('data', onData);
@@ -499,7 +497,7 @@ test('decode bad stream [error]', async () => {
499
497
  });
500
498
 
501
499
  test('decode partial stream [error]', async () => {
502
- const stream = Transform.fromWeb(/** @type {any} */ (decodeStream()), { objectMode: true });
500
+ const stream = Transform.fromWeb(decodeStream() as never, { objectMode: true });
503
501
  // while decoding streaming, N will be regarded as a no-op, rather than an undefined value
504
502
  const onData = jest.fn();
505
503
  stream.on('data', onData);
@@ -4,16 +4,14 @@
4
4
  import { buffer } from 'node:stream/consumers';
5
5
  import { encode, encoder } from '../../dist/stream/index.js';
6
6
  import { decode, encode as encodeRef } from '../../dist/index.js';
7
- import { toArray } from '../.utils.js';
7
+ import { toArray } from '../.utils.ts';
8
8
  import { Transform } from 'node:stream';
9
9
 
10
10
  /**
11
11
  * 包装为 promise
12
- * @param {unknown} value 值
13
- * @returns {Promise<Buffer>} 返回值
14
12
  */
15
- async function encodeAsync(value) {
16
- return buffer(encode(value));
13
+ async function encodeAsync(value: unknown): Promise<Buffer<ArrayBuffer>> {
14
+ return (await buffer(encode(value))) as Buffer<ArrayBuffer>;
17
15
  }
18
16
 
19
17
  test('encode function', async () => {
@@ -299,10 +297,10 @@ test('encode object (only null values)', async () => {
299
297
  });
300
298
 
301
299
  test('encode object (skip prototype)', async () => {
302
- const obj = Object.create({ a: 2, x: 'xx' });
303
- obj.a = 1;
304
- obj.b = 'a';
305
- obj.c = true;
300
+ const obj = Object.create({ a: 2, x: 'xx' }) as Record<string, unknown>;
301
+ obj['a'] = 1;
302
+ obj['b'] = 'a';
303
+ obj['c'] = true;
306
304
  expect(toArray(await encodeAsync(obj))).toEqual(
307
305
  toArray('{', 'i', 1, 'a', 'U', 1, 'i', 1, 'b', 'C', 'a', 'i', 1, 'c', 'T', '}'),
308
306
  );
@@ -364,7 +362,7 @@ test('encode huge data (~128M)', async () => {
364
362
  });
365
363
 
366
364
  test('encode stream', async () => {
367
- const stream = Transform.fromWeb(/** @type {any} */ (encoder()), { objectMode: true });
365
+ const stream = Transform.fromWeb(encoder() as never, { objectMode: true });
368
366
  stream.write(undefined);
369
367
  stream.write(true);
370
368
  stream.write(false);