@cloudpss/ubjson 0.5.53 → 0.6.0-alpha.1
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.
- package/dist/base/decoder.d.ts +1 -1
- package/dist/base/decoder.d.ts.map +1 -1
- package/dist/base/decoder.js +2 -5
- package/dist/base/decoder.js.map +1 -1
- package/dist/base/encoder.d.ts +1 -1
- package/dist/base/encoder.d.ts.map +1 -1
- package/dist/base/encoder.js +9 -8
- package/dist/base/encoder.js.map +1 -1
- package/dist/encoder.d.ts +2 -2
- package/dist/encoder.d.ts.map +1 -1
- package/dist/encoder.js +8 -5
- package/dist/encoder.js.map +1 -1
- package/dist/helper/decode-ae.d.ts +1 -1
- package/dist/helper/decode-ae.d.ts.map +1 -1
- package/dist/helper/decode.d.ts +1 -1
- package/dist/helper/decode.d.ts.map +1 -1
- package/dist/helper/encode.d.ts +1 -1
- package/dist/helper/encode.d.ts.map +1 -1
- package/dist/helper/string-encoder.d.ts +2 -2
- package/dist/helper/string-encoder.d.ts.map +1 -1
- package/dist/helper/string-encoder.js +1 -0
- package/dist/helper/string-encoder.js.map +1 -1
- package/dist/helper/utils.d.ts +1 -1
- package/dist/helper/utils.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/rxjs/encoder.d.ts +1 -1
- package/dist/rxjs/encoder.d.ts.map +1 -1
- package/dist/rxjs/encoder.js.map +1 -1
- package/dist/stream/decoder.js +0 -2
- package/dist/stream/decoder.js.map +1 -1
- package/dist/stream/encoder.d.ts +3 -3
- package/dist/stream/encoder.d.ts.map +1 -1
- package/dist/stream/encoder.js +0 -2
- package/dist/stream/encoder.js.map +1 -1
- package/dist/stream/index.d.ts +6 -6
- package/dist/stream/index.d.ts.map +1 -1
- package/dist/stream/index.js.map +1 -1
- package/dist/stream-helper/encoder.d.ts +3 -3
- package/dist/stream-helper/encoder.d.ts.map +1 -1
- package/dist/stream-helper/encoder.js +2 -2
- package/dist/stream-helper/encoder.js.map +1 -1
- package/package.json +3 -2
- package/src/base/decoder.ts +1 -1
- package/src/base/encoder.ts +4 -1
- package/src/encoder.ts +4 -4
- package/src/helper/decode-ae.ts +1 -1
- package/src/helper/decode.ts +1 -1
- package/src/helper/encode.ts +1 -1
- package/src/helper/string-encoder.ts +3 -2
- package/src/helper/utils.ts +1 -1
- package/src/index.ts +2 -2
- package/src/rxjs/encoder.ts +3 -3
- package/src/stream/encoder.ts +4 -4
- package/src/stream/index.ts +12 -6
- package/src/stream-helper/encoder.ts +8 -7
- package/tests/{decode.js → decode.ts} +13 -11
- package/tests/e2e/{.data.js → .data.ts} +2 -4
- package/tests/e2e/{no-buffer-text.js → no-buffer-text.ts} +2 -2
- package/tests/e2e/{no-buffer.js → no-buffer.ts} +2 -2
- package/tests/e2e/{no-encode-into.js → no-encode-into.ts} +2 -2
- package/tests/e2e/{no-textencoder-decoder.js → no-textencoder-decoder.ts} +2 -2
- package/tests/e2e/{normal.js → normal.ts} +1 -1
- package/tests/e2e/{stream.js → stream.ts} +5 -5
- package/tests/{encode.js → encode.ts} +1 -1
- package/tests/{huge-string.js → huge-string.ts} +1 -1
- package/tests/rxjs/{decode.js → decode.ts} +8 -10
- package/tests/rxjs/{encode.js → encode.ts} +2 -2
- package/tests/stream/{decode.js → decode.ts} +4 -4
- package/tests/stream/{encode.js → encode.ts} +2 -2
- /package/tests/{.utils.js → .utils.ts} +0 -0
- /package/tests/{many.js → many.ts} +0 -0
- /package/tests/stream/{many.js → many.ts} +0 -0
- /package/tests/{string-encoding.js → string-encoding.ts} +0 -0
package/src/base/encoder.ts
CHANGED
|
@@ -24,7 +24,7 @@ export abstract class EncoderBase {
|
|
|
24
24
|
/** 当前写指针位置 */
|
|
25
25
|
protected length = 0;
|
|
26
26
|
/** 数据 */
|
|
27
|
-
protected data!: Uint8Array
|
|
27
|
+
protected data!: Uint8Array<ArrayBuffer>;
|
|
28
28
|
/** buffer 的 DataView */
|
|
29
29
|
protected view!: DataView;
|
|
30
30
|
/**
|
|
@@ -43,12 +43,15 @@ export abstract class EncoderBase {
|
|
|
43
43
|
}
|
|
44
44
|
/** 写入一个对象 */
|
|
45
45
|
private write(value: unknown): void {
|
|
46
|
+
// eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
|
|
46
47
|
switch (typeof value) {
|
|
47
48
|
case 'string':
|
|
49
|
+
// eslint-disable-next-line unicorn/prefer-code-point
|
|
48
50
|
if (value.length === 1 && value.charCodeAt(0) < 0x80) {
|
|
49
51
|
// 1 byte ascii char
|
|
50
52
|
this.ensureCapacity(2);
|
|
51
53
|
this.data[this.length++] = constants.CHAR;
|
|
54
|
+
// eslint-disable-next-line unicorn/prefer-code-point
|
|
52
55
|
this.data[this.length++] = value.charCodeAt(0);
|
|
53
56
|
} else {
|
|
54
57
|
this.ensureCapacity(2);
|
package/src/encoder.ts
CHANGED
|
@@ -6,7 +6,7 @@ const MAX_SIZE = 1024 * 1024 * 128; //128 MiB
|
|
|
6
6
|
|
|
7
7
|
/** 编码至 ubjson */
|
|
8
8
|
export class Encoder extends EncoderBase {
|
|
9
|
-
private readonly flushedBuffers: Uint8Array
|
|
9
|
+
private readonly flushedBuffers: Array<Uint8Array<ArrayBuffer>> = [];
|
|
10
10
|
/** 通过内存池减少分配 */
|
|
11
11
|
private readonly pool = new Uint8Array(BLOCK_SIZE);
|
|
12
12
|
/** 缓存当前容量,避免对象访问耗时 */
|
|
@@ -55,7 +55,7 @@ export class Encoder extends EncoderBase {
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
/** 获取结果 */
|
|
58
|
-
private getResult(): Uint8Array {
|
|
58
|
+
private getResult(): Uint8Array<ArrayBuffer> {
|
|
59
59
|
if (this.flushedBuffers.length === 0) {
|
|
60
60
|
// 缓冲区为空,复制当前 buffer
|
|
61
61
|
return this.data.slice(0, this.length);
|
|
@@ -82,7 +82,7 @@ export class Encoder extends EncoderBase {
|
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
/** 获取写入结果 */
|
|
85
|
-
encode(value: unknown): Uint8Array {
|
|
85
|
+
encode(value: unknown): Uint8Array<ArrayBuffer> {
|
|
86
86
|
try {
|
|
87
87
|
this.allocUnsafe(BLOCK_SIZE);
|
|
88
88
|
this.writeValue(value);
|
|
@@ -94,7 +94,7 @@ export class Encoder extends EncoderBase {
|
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
/** 获取写入结果 */
|
|
97
|
-
encodeMany(value: Iterable<unknown>): Uint8Array {
|
|
97
|
+
encodeMany(value: Iterable<unknown>): Uint8Array<ArrayBuffer> {
|
|
98
98
|
try {
|
|
99
99
|
this.allocUnsafe(BLOCK_SIZE);
|
|
100
100
|
for (const v of value) {
|
package/src/helper/decode-ae.ts
CHANGED
package/src/helper/decode.ts
CHANGED
package/src/helper/encode.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable unicorn/prefer-code-point */
|
|
1
2
|
// https://github.com/ehmicky/string-byte-length/blob/main/src/char_code.js
|
|
2
3
|
|
|
3
4
|
// Last ASCII character (1 byte)
|
|
@@ -127,11 +128,11 @@ export function myEncodeInto(v: string, buf: Uint8Array, offset: number): number
|
|
|
127
128
|
* Encode string into utf-8.
|
|
128
129
|
* Provided `buf` MUST have enough space.
|
|
129
130
|
*/
|
|
130
|
-
export let encodeInto: (v: string, buf: Uint8Array
|
|
131
|
+
export let encodeInto: <T extends ArrayBufferLike>(v: string, buf: Uint8Array<T>, offset: number) => number;
|
|
131
132
|
/**
|
|
132
133
|
* Encode string into utf-8.
|
|
133
134
|
*/
|
|
134
|
-
export let encode: (v: string) => Uint8Array
|
|
135
|
+
export let encode: (v: string) => Uint8Array<ArrayBuffer>;
|
|
135
136
|
|
|
136
137
|
/** 重设环境 */
|
|
137
138
|
export function resetEnv(): void {
|
package/src/helper/utils.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** 支持的数据转为 Uint8Array */
|
|
2
|
-
export function toUint8Array(data: BufferSource): Uint8Array {
|
|
2
|
+
export function toUint8Array(data: BufferSource): Uint8Array<ArrayBuffer> {
|
|
3
3
|
if (data == null || typeof data != 'object' || typeof data.byteLength != 'number') {
|
|
4
4
|
throw new TypeError('Invalid data');
|
|
5
5
|
}
|
package/src/index.ts
CHANGED
|
@@ -6,12 +6,12 @@ export { UnexpectedEofError as UnexpectedEof } from './helper/errors.js';
|
|
|
6
6
|
export type { EncodeOptions, DecodeOptions };
|
|
7
7
|
|
|
8
8
|
/** 编码为 UBJSON */
|
|
9
|
-
export function encode(value: unknown, options?: EncodeOptions): Uint8Array {
|
|
9
|
+
export function encode(value: unknown, options?: EncodeOptions): Uint8Array<ArrayBuffer> {
|
|
10
10
|
return getEncoder(options).encode(value);
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
/** 编码为 UBJSON */
|
|
14
|
-
export function encodeMany(value: Iterable<unknown>, options?: EncodeOptions): Uint8Array {
|
|
14
|
+
export function encodeMany(value: Iterable<unknown>, options?: EncodeOptions): Uint8Array<ArrayBuffer> {
|
|
15
15
|
return getEncoder(options).encodeMany(value);
|
|
16
16
|
}
|
|
17
17
|
|
package/src/rxjs/encoder.ts
CHANGED
|
@@ -3,10 +3,10 @@ import { StreamEncoderHelper } from '../stream-helper/encoder.js';
|
|
|
3
3
|
import type { EncodeOptions } from '../options.js';
|
|
4
4
|
|
|
5
5
|
/** 流式编码 UBJSON */
|
|
6
|
-
export function encode(options?: EncodeOptions): OperatorFunction<unknown, Uint8Array
|
|
6
|
+
export function encode(options?: EncodeOptions): OperatorFunction<unknown, Uint8Array<ArrayBuffer>> {
|
|
7
7
|
return (observable) => {
|
|
8
|
-
return new Observable<Uint8Array
|
|
9
|
-
const helper = new StreamEncoderHelper(options, (chunk
|
|
8
|
+
return new Observable<Uint8Array<ArrayBuffer>>((subscriber) => {
|
|
9
|
+
const helper = new StreamEncoderHelper(options, (chunk) => subscriber.next(chunk));
|
|
10
10
|
const sub = observable.subscribe({
|
|
11
11
|
next(value) {
|
|
12
12
|
try {
|
package/src/stream/encoder.ts
CHANGED
|
@@ -2,23 +2,23 @@ import { StreamEncoderHelper } from '../stream-helper/encoder.js';
|
|
|
2
2
|
import type { EncodeOptions } from '../options.js';
|
|
3
3
|
|
|
4
4
|
/** 流式编码 UBJSON */
|
|
5
|
-
export class EncodeTransformer implements Transformer<unknown, Uint8Array
|
|
5
|
+
export class EncodeTransformer implements Transformer<unknown, Uint8Array<ArrayBuffer>> {
|
|
6
6
|
constructor(options?: EncodeOptions) {
|
|
7
7
|
this.helper = new StreamEncoderHelper(options, (binary) => {
|
|
8
8
|
this.controller.enqueue(binary);
|
|
9
9
|
});
|
|
10
10
|
}
|
|
11
11
|
private readonly helper;
|
|
12
|
-
private controller!: TransformStreamDefaultController<Uint8Array
|
|
12
|
+
private controller!: TransformStreamDefaultController<Uint8Array<ArrayBuffer>>;
|
|
13
13
|
|
|
14
14
|
/** @inheritdoc */
|
|
15
|
-
transform(obj: unknown, controller: TransformStreamDefaultController<Uint8Array
|
|
15
|
+
transform(obj: unknown, controller: TransformStreamDefaultController<Uint8Array<ArrayBuffer>>): void {
|
|
16
16
|
this.controller = controller;
|
|
17
17
|
this.helper.encode(obj);
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
/** @inheritdoc */
|
|
21
|
-
flush(controller: TransformStreamDefaultController<Uint8Array
|
|
21
|
+
flush(controller: TransformStreamDefaultController<Uint8Array<ArrayBuffer>>): void {
|
|
22
22
|
this.controller = controller;
|
|
23
23
|
this.helper.destroy();
|
|
24
24
|
controller.terminate();
|
package/src/stream/index.ts
CHANGED
|
@@ -7,7 +7,7 @@ export { UnexpectedEofError as UnexpectedEof } from '../helper/errors.js';
|
|
|
7
7
|
export type { EncodeOptions, DecodeOptions };
|
|
8
8
|
|
|
9
9
|
/** 编码为 UBJSON */
|
|
10
|
-
export function encode(value: unknown, options?: EncodeOptions): ReadableStream<Uint8Array
|
|
10
|
+
export function encode(value: unknown, options?: EncodeOptions): ReadableStream<Uint8Array<ArrayBuffer>> {
|
|
11
11
|
if (value == null) {
|
|
12
12
|
return new ReadableStream({
|
|
13
13
|
type: 'bytes',
|
|
@@ -27,7 +27,10 @@ export function encode(value: unknown, options?: EncodeOptions): ReadableStream<
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
/** 编码为 UBJSON */
|
|
30
|
-
export function encodeMany(
|
|
30
|
+
export function encodeMany(
|
|
31
|
+
value: AsyncIterable<unknown>,
|
|
32
|
+
options?: EncodeOptions,
|
|
33
|
+
): ReadableStream<Uint8Array<ArrayBuffer>> {
|
|
31
34
|
return new ReadableStream<unknown>({
|
|
32
35
|
async start(controller) {
|
|
33
36
|
for await (const v of value) {
|
|
@@ -40,12 +43,12 @@ export function encodeMany(value: AsyncIterable<unknown>, options?: EncodeOption
|
|
|
40
43
|
}
|
|
41
44
|
|
|
42
45
|
/** 编码为 UBJSON */
|
|
43
|
-
export function encoder(options?: EncodeOptions): TransformStream<unknown, Uint8Array
|
|
46
|
+
export function encoder(options?: EncodeOptions): TransformStream<unknown, Uint8Array<ArrayBuffer>> {
|
|
44
47
|
return new TransformStream(new EncodeTransformer(options));
|
|
45
48
|
}
|
|
46
49
|
|
|
47
50
|
/** 解码 UBJSON */
|
|
48
|
-
export async function decode(stream: ReadableStream<
|
|
51
|
+
export async function decode(stream: ReadableStream<BufferSource>, options?: DecodeOptions): Promise<unknown> {
|
|
49
52
|
const s = stream.pipeThrough(decoder(options));
|
|
50
53
|
const r = s.getReader();
|
|
51
54
|
const result = await r.read();
|
|
@@ -54,7 +57,10 @@ export async function decode(stream: ReadableStream<Uint8Array>, options?: Decod
|
|
|
54
57
|
}
|
|
55
58
|
|
|
56
59
|
/** 解码 UBJSON */
|
|
57
|
-
export async function* decodeMany(
|
|
60
|
+
export async function* decodeMany(
|
|
61
|
+
stream: ReadableStream<BufferSource>,
|
|
62
|
+
options?: DecodeOptions,
|
|
63
|
+
): AsyncIterable<unknown> {
|
|
58
64
|
const s = stream.pipeThrough(decoder(options));
|
|
59
65
|
const r = s.getReader();
|
|
60
66
|
for (;;) {
|
|
@@ -65,6 +71,6 @@ export async function* decodeMany(stream: ReadableStream<Uint8Array>, options?:
|
|
|
65
71
|
}
|
|
66
72
|
|
|
67
73
|
/** 解码 UBJSON */
|
|
68
|
-
export function decoder(options?: DecodeOptions): TransformStream<
|
|
74
|
+
export function decoder(options?: DecodeOptions): TransformStream<BufferSource, unknown> {
|
|
69
75
|
return new TransformStream(new DecodeTransformer(options));
|
|
70
76
|
}
|
|
@@ -8,10 +8,10 @@ const BLOCK_SIZE = 1024 * 64; // 64 KiB
|
|
|
8
8
|
const MAX_SIZE = 1024 * 1024 * 32; // 32 MiB
|
|
9
9
|
|
|
10
10
|
/** 保存一个内存池以减少重复分配 */
|
|
11
|
-
let POOL: Uint8Array | null = null;
|
|
11
|
+
let POOL: Uint8Array<ArrayBuffer> | null = null;
|
|
12
12
|
|
|
13
13
|
/** 获取内存池 */
|
|
14
|
-
function alloc(size: number): Uint8Array {
|
|
14
|
+
function alloc(size: number): Uint8Array<ArrayBuffer> {
|
|
15
15
|
if (POOL == null || size !== BLOCK_SIZE) {
|
|
16
16
|
return new Uint8Array(size);
|
|
17
17
|
}
|
|
@@ -21,7 +21,7 @@ function alloc(size: number): Uint8Array {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
/** 归还内存池 */
|
|
24
|
-
function free(buf: Uint8Array): boolean {
|
|
24
|
+
function free(buf: Uint8Array<ArrayBuffer>): boolean {
|
|
25
25
|
if (POOL == null && buf.byteLength === BLOCK_SIZE) {
|
|
26
26
|
POOL = buf;
|
|
27
27
|
return true;
|
|
@@ -33,7 +33,7 @@ function free(buf: Uint8Array): boolean {
|
|
|
33
33
|
export class StreamEncoderHelper extends EncoderBase {
|
|
34
34
|
constructor(
|
|
35
35
|
options: EncodeOptions | null | undefined,
|
|
36
|
-
protected readonly onChunk: (chunk: Uint8Array) => void,
|
|
36
|
+
protected readonly onChunk: (chunk: Uint8Array<ArrayBuffer>) => void,
|
|
37
37
|
) {
|
|
38
38
|
super();
|
|
39
39
|
this.sortObjectKeys = options?.sortObjectKeys ?? false;
|
|
@@ -45,9 +45,9 @@ export class StreamEncoderHelper extends EncoderBase {
|
|
|
45
45
|
*/
|
|
46
46
|
destroy(): void {
|
|
47
47
|
free(this.data);
|
|
48
|
-
const self = this as unknown as { view: DataView | null;
|
|
48
|
+
const self = this as unknown as { view: DataView | null; data: Uint8Array<ArrayBuffer> | null };
|
|
49
49
|
self.view = null;
|
|
50
|
-
self.
|
|
50
|
+
self.data = null;
|
|
51
51
|
}
|
|
52
52
|
/**
|
|
53
53
|
* 确保 buffer 还有 capacity 的空闲空间
|
|
@@ -95,6 +95,7 @@ export class StreamEncoderHelper extends EncoderBase {
|
|
|
95
95
|
for (let i = 0; i < strLen; i += BLOCK_SIZE) {
|
|
96
96
|
let end = i + BLOCK_SIZE;
|
|
97
97
|
// avoid split surrogate pair
|
|
98
|
+
// eslint-disable-next-line unicorn/prefer-code-point
|
|
98
99
|
const endAtSurrogate = end < strLen && (value.charCodeAt(end) & 0xfc00) === 0xdc00;
|
|
99
100
|
if (endAtSurrogate) {
|
|
100
101
|
end--;
|
|
@@ -107,7 +108,7 @@ export class StreamEncoderHelper extends EncoderBase {
|
|
|
107
108
|
}
|
|
108
109
|
}
|
|
109
110
|
/** @inheritdoc */
|
|
110
|
-
protected override writeLargeTypedArrayData(type: TypedArrayType, value: ArrayBufferView): void {
|
|
111
|
+
protected override writeLargeTypedArrayData(type: TypedArrayType, value: ArrayBufferView<ArrayBuffer>): void {
|
|
111
112
|
this.ensureCapacity(-1);
|
|
112
113
|
const { byteLength } = value;
|
|
113
114
|
if (type === constants.UINT8 || type === constants.INT8) {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { decode, UnexpectedEof } from '../dist/index.js';
|
|
6
|
-
import { toBuffer } from './.utils.
|
|
6
|
+
import { toBuffer } from './.utils.ts';
|
|
7
7
|
|
|
8
8
|
test('decode unsupported type', () => {
|
|
9
9
|
expect(() => decode(toBuffer('!'))).toThrow();
|
|
@@ -507,17 +507,18 @@ test('decode (eof at key)', () => {
|
|
|
507
507
|
|
|
508
508
|
describe('proto poisoning attack', () => {
|
|
509
509
|
it('should remove __proto__ key', () => {
|
|
510
|
-
const obj = /** @type {Record<string, unknown>} */ (
|
|
511
|
-
|
|
510
|
+
const obj = /** @type {Record<string, unknown>} */ decode(
|
|
511
|
+
toBuffer('{', 'i', 9, '__proto__', '{', 'i', 1, 'a', 'S', 'i', 3, 'abc', '}', '}'),
|
|
512
512
|
);
|
|
513
513
|
expect(Object.hasOwn(obj, '__proto__')).toBe(false);
|
|
514
514
|
expect(obj['__proto__']).toBe(Object.prototype);
|
|
515
515
|
});
|
|
516
516
|
it('should allow __proto__ key', () => {
|
|
517
|
-
const obj = /** @type {Record<string, unknown>} */ (
|
|
518
|
-
|
|
517
|
+
const obj = /** @type {Record<string, unknown>} */ decode(
|
|
518
|
+
toBuffer('{', 'i', 9, '__proto__', '{', 'i', 1, 'a', 'S', 'i', 3, 'abc', '}', '}'),
|
|
519
|
+
{
|
|
519
520
|
protoAction: 'allow',
|
|
520
|
-
}
|
|
521
|
+
},
|
|
521
522
|
);
|
|
522
523
|
expect(Object.hasOwn(obj, '__proto__')).toBe(true);
|
|
523
524
|
expect(obj['__proto__']).toEqual({ a: 'abc' });
|
|
@@ -533,17 +534,18 @@ describe('proto poisoning attack', () => {
|
|
|
533
534
|
|
|
534
535
|
describe('constructor poisoning attack', () => {
|
|
535
536
|
it('should remove constructor key', () => {
|
|
536
|
-
const obj = /** @type {Record<string, unknown>} */ (
|
|
537
|
-
|
|
537
|
+
const obj = /** @type {Record<string, unknown>} */ decode(
|
|
538
|
+
toBuffer('{', 'i', 11, 'constructor', '{', 'i', 1, 'a', 'S', 'i', 3, 'abc', '}', '}'),
|
|
539
|
+
{
|
|
538
540
|
constructorAction: 'remove',
|
|
539
|
-
}
|
|
541
|
+
},
|
|
540
542
|
);
|
|
541
543
|
expect(Object.hasOwn(obj, 'constructor')).toBe(false);
|
|
542
544
|
expect(obj.constructor).toBe(Object);
|
|
543
545
|
});
|
|
544
546
|
it('should allow constructor key', () => {
|
|
545
|
-
const obj = /** @type {Record<string, unknown>} */ (
|
|
546
|
-
|
|
547
|
+
const obj = /** @type {Record<string, unknown>} */ decode(
|
|
548
|
+
toBuffer('{', 'i', 11, 'constructor', '{', 'i', 1, 'a', 'S', 'i', 3, 'abc', '}', '}'),
|
|
547
549
|
);
|
|
548
550
|
expect(Object.hasOwn(obj, 'constructor')).toBe(true);
|
|
549
551
|
expect(obj.constructor).toEqual({ a: 'abc' });
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
export const
|
|
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.
|
|
2
|
-
import { INPUTS, EXPECTED } from './.data.
|
|
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.
|
|
2
|
-
import { INPUTS, EXPECTED } from './.data.
|
|
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.
|
|
2
|
-
import { INPUTS, EXPECTED } from './.data.
|
|
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.
|
|
2
|
-
import { INPUTS, EXPECTED } from './.data.
|
|
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,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.
|
|
3
|
+
import { EXPECTED, INPUTS } from './.data.ts';
|
|
4
4
|
|
|
5
5
|
describe('stream', () => {
|
|
6
6
|
it.each(Object.keys(INPUTS))('%s', async (name) => {
|
|
@@ -8,14 +8,14 @@ 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} */
|
|
11
|
+
const encoded = await Readable.fromWeb(/** @type {any} */ encodeStream(input)).toArray();
|
|
12
12
|
const decoded = await decodeStream(
|
|
13
|
-
/** @type {ReadableStream<Uint8Array>} */
|
|
13
|
+
/** @type {ReadableStream<Uint8Array>} */ Readable.toWeb(Readable.from(encoded)),
|
|
14
14
|
);
|
|
15
15
|
expect(decoded).toEqual(expected);
|
|
16
16
|
}).rejects.toThrow(expected);
|
|
17
17
|
} else {
|
|
18
|
-
const encoded = await Readable.fromWeb(/** @type {any} */
|
|
18
|
+
const encoded = await Readable.fromWeb(/** @type {any} */ encodeStream(input)).toArray();
|
|
19
19
|
const data = encoded.flatMap((/** @type {Buffer} */ chunk) => {
|
|
20
20
|
if (chunk.length < 2) return [chunk];
|
|
21
21
|
// split to random chunks
|
|
@@ -29,7 +29,7 @@ describe('stream', () => {
|
|
|
29
29
|
return chunks;
|
|
30
30
|
});
|
|
31
31
|
const decoded = await decodeStream(
|
|
32
|
-
/** @type {ReadableStream<Uint8Array>} */
|
|
32
|
+
/** @type {ReadableStream<Uint8Array>} */ Readable.toWeb(Readable.from(data)),
|
|
33
33
|
);
|
|
34
34
|
expect(decoded).toEqual(expected);
|
|
35
35
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import { encode, decode } from '../dist/index.js';
|
|
6
6
|
import { getEncoder } from '../dist/encoder.js';
|
|
7
|
-
import { toArray } from './.utils.
|
|
7
|
+
import { toArray } from './.utils.ts';
|
|
8
8
|
|
|
9
9
|
// @ts-expect-error Access private property
|
|
10
10
|
const poolInit = getEncoder().pool;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { jest } from '@jest/globals';
|
|
5
5
|
import { firstValueFrom, of, Subject } from 'rxjs';
|
|
6
6
|
import { decode as decodePipe } from '../../dist/rxjs/index.js';
|
|
7
|
-
import { toBuffer } from '../.utils.
|
|
7
|
+
import { toBuffer } from '../.utils.ts';
|
|
8
8
|
import { UnexpectedEofError as UnexpectedEof } from '../../dist/helper/errors.js';
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -23,15 +23,13 @@ async function decode(data) {
|
|
|
23
23
|
* @param {(data: unknown) => void} onData 数据回调
|
|
24
24
|
*/
|
|
25
25
|
async function decodeStream(observable, onData) {
|
|
26
|
-
return /** @type {Promise<void>} */ (
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
})
|
|
34
|
-
);
|
|
26
|
+
return /** @type {Promise<void>} */ new Promise((resolve, reject) => {
|
|
27
|
+
observable.pipe(decodePipe()).subscribe({
|
|
28
|
+
next: onData,
|
|
29
|
+
error: reject,
|
|
30
|
+
complete: resolve,
|
|
31
|
+
});
|
|
32
|
+
});
|
|
35
33
|
}
|
|
36
34
|
|
|
37
35
|
test('decode unsupported type', async () => {
|
|
@@ -4,7 +4,7 @@
|
|
|
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.
|
|
7
|
+
import { toArray } from '../.utils.ts';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* 包装为 promise
|
|
@@ -304,7 +304,7 @@ test('encode object (only null values)', async () => {
|
|
|
304
304
|
});
|
|
305
305
|
|
|
306
306
|
test('encode object (skip prototype)', async () => {
|
|
307
|
-
const obj = /** @type {Record<string, unknown>} */
|
|
307
|
+
const obj = /** @type {Record<string, unknown>} */ Object.create({ a: 2, x: 'xx' });
|
|
308
308
|
obj['a'] = 1;
|
|
309
309
|
obj['b'] = 'a';
|
|
310
310
|
obj['c'] = true;
|
|
@@ -4,7 +4,7 @@
|
|
|
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.
|
|
7
|
+
import { toBuffer } from '../.utils.ts';
|
|
8
8
|
import { UnexpectedEofError as UnexpectedEof } from '../../dist/helper/errors.js';
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -14,7 +14,7 @@ import { UnexpectedEofError as UnexpectedEof } from '../../dist/helper/errors.js
|
|
|
14
14
|
*/
|
|
15
15
|
async function decode(data) {
|
|
16
16
|
const readable = Readable.from([data], { objectMode: false });
|
|
17
|
-
return decodeAsync(/** @type {ReadableStream<Uint8Array>} */
|
|
17
|
+
return decodeAsync(/** @type {ReadableStream<Uint8Array>} */ Readable.toWeb(readable));
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
/**
|
|
@@ -456,7 +456,7 @@ test('decode object (empty key, optimized)', async () => {
|
|
|
456
456
|
});
|
|
457
457
|
|
|
458
458
|
test('decode stream', async () => {
|
|
459
|
-
const stream = Transform.fromWeb(/** @type {any} */
|
|
459
|
+
const stream = Transform.fromWeb(/** @type {any} */ decodeStream(), { objectMode: true });
|
|
460
460
|
// while decoding streaming, N will be regarded as a no-op, rather than an undefined value
|
|
461
461
|
const onData = jest.fn();
|
|
462
462
|
stream.on('data', onData);
|
|
@@ -499,7 +499,7 @@ test('decode bad stream [error]', async () => {
|
|
|
499
499
|
});
|
|
500
500
|
|
|
501
501
|
test('decode partial stream [error]', async () => {
|
|
502
|
-
const stream = Transform.fromWeb(/** @type {any} */
|
|
502
|
+
const stream = Transform.fromWeb(/** @type {any} */ decodeStream(), { objectMode: true });
|
|
503
503
|
// while decoding streaming, N will be regarded as a no-op, rather than an undefined value
|
|
504
504
|
const onData = jest.fn();
|
|
505
505
|
stream.on('data', onData);
|
|
@@ -4,7 +4,7 @@
|
|
|
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.
|
|
7
|
+
import { toArray } from '../.utils.ts';
|
|
8
8
|
import { Transform } from 'node:stream';
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -364,7 +364,7 @@ test('encode huge data (~128M)', async () => {
|
|
|
364
364
|
});
|
|
365
365
|
|
|
366
366
|
test('encode stream', async () => {
|
|
367
|
-
const stream = Transform.fromWeb(/** @type {any} */
|
|
367
|
+
const stream = Transform.fromWeb(/** @type {any} */ encoder(), { objectMode: true });
|
|
368
368
|
stream.write(undefined);
|
|
369
369
|
stream.write(true);
|
|
370
370
|
stream.write(false);
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|