From 817d701f31204e2b58cef97c49a3344b952bb310 Mon Sep 17 00:00:00 2001 From: Yan Chen Date: Wed, 13 Apr 2022 11:09:01 -0700 Subject: [PATCH 1/2] fix: don't use spread operator when encoding vec --- packages/candid/src/idl.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/candid/src/idl.ts b/packages/candid/src/idl.ts index d0a49e660..88fa55bd4 100644 --- a/packages/candid/src/idl.ts +++ b/packages/candid/src/idl.ts @@ -747,8 +747,11 @@ export class VecClass extends ConstructType { if (this._blobOptimization) { return concat(len, new Uint8Array(x as unknown as number[])); } - - return concat(len, ...x.map(d => this._type.encodeValue(d))); + let res = len; + for (const d of x) { + res = concat(res, this._type.encodeValue(d)); + } + return res; } public _buildTypeTableImpl(typeTable: TypeTable) { From 2feb154ed38f375959919b907302ae57fe3bc7a2 Mon Sep 17 00:00:00 2001 From: Yan Chen Date: Wed, 13 Apr 2022 12:12:21 -0700 Subject: [PATCH 2/2] use pipe to avoid quadratic concat --- packages/candid/src/idl.test.ts | 1 + packages/candid/src/idl.ts | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/candid/src/idl.test.ts b/packages/candid/src/idl.test.ts index afd60210e..a88b26415 100644 --- a/packages/candid/src/idl.test.ts +++ b/packages/candid/src/idl.test.ts @@ -160,6 +160,7 @@ test('IDL encoding (array)', () => { '4449444c016d7c01000400010203', 'Array of Ints', ); + IDL.encode([IDL.Vec(IDL.Nat16)], [new Array(200000).fill(42)]); expect(() => IDL.encode([IDL.Vec(IDL.Int)], [BigInt(0)])).toThrow(/Invalid vec int argument/); expect(() => IDL.encode([IDL.Vec(IDL.Int)], [['fail']])).toThrow(/Invalid vec int argument/); }); diff --git a/packages/candid/src/idl.ts b/packages/candid/src/idl.ts index 88fa55bd4..8eb7531a0 100644 --- a/packages/candid/src/idl.ts +++ b/packages/candid/src/idl.ts @@ -747,11 +747,13 @@ export class VecClass extends ConstructType { if (this._blobOptimization) { return concat(len, new Uint8Array(x as unknown as number[])); } - let res = len; + const buf = new Pipe(new ArrayBuffer(len.byteLength + x.length), 0); + buf.write(len); for (const d of x) { - res = concat(res, this._type.encodeValue(d)); + const encoded = this._type.encodeValue(d); + buf.write(new Uint8Array(encoded)); } - return res; + return buf.buffer; } public _buildTypeTableImpl(typeTable: TypeTable) {