Skip to content

Call stack size exceeded error when sending large UInt8Array #126

@hansottowirtz

Description

@hansottowirtz

The library seems to have trouble sending large files. The following code throws:

Error sending file of size 112640 bytes: RangeError: Maximum call stack size exceeded
    at _Devaluator.devaluateImpl (<project>/node_modules/.pnpm/capnweb@0.4.0/node_modules/capnweb/src/serialize.ts:162:40)
    at _Devaluator.devaluateImpl (<project>/node_modules/.pnpm/capnweb@0.4.0/node_modules/capnweb/src/serialize.ts:144:28)
    at Function.devaluate (<project>/node_modules/.pnpm/capnweb@0.4.0/node_modules/capnweb/src/serialize.ts:83:25)
    at RpcSessionImpl.sendCall (<project>/node_modules/.pnpm/capnweb@0.4.0/node_modules/capnweb/src/rpc.ts:535:32)
    at RpcMainHook.call (<project>/node_modules/.pnpm/capnweb@0.4.0/node_modules/capnweb/src/rpc.ts:195:28)
    at doCall (<project>/node_modules/.pnpm/capnweb@0.4.0/node_modules/capnweb/src/core.ts:261:15)
    at Object.apply (<project>/node_modules/.pnpm/capnweb@0.4.0/node_modules/capnweb/src/core.ts:285:27)
    at <anonymous> (<project>/client.ts:10:34)
    at process.processTicksAndRejections (node:internal/process/task_queues:105:5)

Repro: https://github.com/hansottowirtz/capnweb-large-file-repro.git

server.ts:

import http from "node:http";
import { WebSocketServer } from 'ws';
import { RpcTarget, newWebSocketRpcSession } from "capnweb";

export class Api extends RpcTarget {
  async getFileSize(file: Uint8Array): Promise<number> {
    return file.length;
  }
}

const httpServer = http.createServer();

const wsServer = new WebSocketServer({ server: httpServer })
wsServer.on('connection', (ws) => {
  newWebSocketRpcSession(ws as any, new Api());
});

httpServer.listen(8000);

client.ts:

import type { Api } from "./server";
import { newWebSocketRpcSession } from "capnweb";

const session = newWebSocketRpcSession<Api>("ws://localhost:8000");

for (let i = 0; i < 100; i++) {
  const size = 1024 * (10 * i);
  try {
    const file = new Uint8Array(size);
    const result = await session.getFileSize(file);
    console.log(`Sent file of size ${size} bytes, received result ${result}`);
  } catch (error) {
    console.error(`Error sending file of size ${size} bytes:`, error);
    break;
  }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions