From 010161ab7c59010613b1bf430a898b12f59c1c3f Mon Sep 17 00:00:00 2001 From: Bailey Pearson Date: Thu, 30 Nov 2023 11:43:50 -0700 Subject: [PATCH] fix(node-runtime-worker-thread): remove function properties before serializing errors COMPASS-5919 (#1762) --- .../src/index.spec.ts | 44 +++++++++++++++++++ .../src/serializer.ts | 5 ++- 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/packages/node-runtime-worker-thread/src/index.spec.ts b/packages/node-runtime-worker-thread/src/index.spec.ts index 70cfb1914..7037a812f 100644 --- a/packages/node-runtime-worker-thread/src/index.spec.ts +++ b/packages/node-runtime-worker-thread/src/index.spec.ts @@ -144,6 +144,50 @@ describe('WorkerRuntime', function () { .to.have.property('stack') .matches(/SyntaxError: Syntax!/); }); + + it('COMPASS-5919 - correctly serializes babel parse errors', async function () { + /** + * babel syntax errors have a `clone()` method, which breaks structured cloning + */ + runtime = new WorkerRuntime('mongodb://nodb/', dummyOptions, { + nodb: true, + }); + + const err: Error = await runtime.evaluate('1 +* 3').catch((e) => e); + + expect(err).to.be.instanceof(Error); + expect(err).to.have.property('name', 'SyntaxError'); + }); + + context( + 'when `evaluate` returns an error that has a function property', + function () { + it('removes the function property from the error', async function () { + runtime = new WorkerRuntime('mongodb://nodb/', dummyOptions, { + nodb: true, + }); + + const script = ` + class CustomError extends Error { + constructor() { + super('custom error'); + } + foo() { + return 'hello, world'; + } + } + throw new CustomError(); + `; + + const err: Error = await runtime.evaluate(script).catch((e) => e); + + expect(err).to.be.instanceof(Error); + expect(err).to.have.property('name', 'Error'); + expect(err).not.to.have.property('foo'); + expect(err).to.have.property('message', 'custom error'); + }); + } + ); }); }); diff --git a/packages/node-runtime-worker-thread/src/serializer.ts b/packages/node-runtime-worker-thread/src/serializer.ts index 11d1bcbe2..d4b6f6b2f 100644 --- a/packages/node-runtime-worker-thread/src/serializer.ts +++ b/packages/node-runtime-worker-thread/src/serializer.ts @@ -27,7 +27,10 @@ function getNames(obj: T): (keyof T)[] { */ export function serializeError(err: Error) { // Name is the only constructor property we care about - const keys = getNames(err).concat('name'); + const keys = getNames(err) + .concat('name') + // structured cloning cannot handle functions + .filter((key) => typeof err[key] !== 'function'); return keys.reduce((acc, key) => { (acc as any)[key] = err[key]; return acc;