Skip to content
This repository has been archived by the owner on Jul 5, 2024. It is now read-only.

Commit

Permalink
not too bad
Browse files Browse the repository at this point in the history
  • Loading branch information
KATT committed Oct 3, 2023
1 parent 73cfa9b commit 60e8bbf
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 27 deletions.
18 changes: 13 additions & 5 deletions src/async/deserializeAsync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,17 @@ export function createTsonParseAsync(opts: TsonAsyncOptions): TsonParseAsync {

// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const deferred = deferreds.get(index)!;

const walkedResult = walk(result);
status === PROMISE_RESOLVED
? deferred.resolve(walk(result))
: deferred.reject(walk(result));
? deferred.resolve(walkedResult)
: deferred.reject(
walkedResult instanceof Error
? walkedResult
: new TsonError("Promise rejected on server", {
cause: walkedResult,
}),
);
}

buffer.forEach(readString);
Expand All @@ -140,13 +148,13 @@ export function createTsonParseAsync(opts: TsonAsyncOptions): TsonParseAsync {

// console.log("getting head of JSON");
let lastResult: IteratorResult<string>;
while (lines.length < 4) {
do {
lastResult = await instance.next();

lines.push(...(lastResult.value as string).split("\n").filter(Boolean));

// console.log("got line", lines);
}
} while (lines.length < 4);

const [
/**
Expand Down Expand Up @@ -176,7 +184,7 @@ export function createTsonParseAsync(opts: TsonAsyncOptions): TsonParseAsync {

const walk = walker(secondValueParsed.nonce);

void getStreamedValues(buffer, lastResult.done, walk).catch((cause) => {
void getStreamedValues(buffer, !!lastResult.done, walk).catch((cause) => {
// Something went wrong while getting the streamed values

const err = new TsonError(
Expand Down
55 changes: 39 additions & 16 deletions src/handlers/tsonPromise.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,14 @@ import { createTsonAsync, tsonPromise } from "../index.js";
import { TsonSerialized } from "../types.js";

const createPromise = <T>(result: () => T, wait = 1) => {
return new Promise<T>((resolve) => {
return new Promise<T>((resolve, reject) => {
setTimeout(() => {
resolve(result());
try {
const res = result();
resolve(res);
} catch (err) {
reject(err);
}
}, wait);
});
};
Expand Down Expand Up @@ -376,19 +381,13 @@ test("stringify and parse promise with a promise", async () => {

// let's do it over an actual network connection
test("stringify and parse promise with a promise over a network connection", async () => {
const obj = {
promise: createPromise(() => {
return {
aThirdPromise: createPromise(() => {
return 43;
}, 101),
anotherPromise: createPromise(() => {
return 42;
}, 100),
};
}, 100),
};
// create a node server
interface Obj {
promise: Promise<{
anotherPromise: Promise<number>;
rejectedPromise: Promise<number>;
}>;
}

const server = await new Promise<http.Server>((resolve) => {
const server = http.createServer((_req, res) => {
async function handle() {
Expand All @@ -397,6 +396,18 @@ test("stringify and parse promise with a promise over a network connection", asy
types: [tsonPromise],
});

const obj: Obj = {
promise: createPromise(() => {
return {
anotherPromise: createPromise(() => {
return 42;
}, 8),
rejectedPromise: createPromise<number>(() => {
throw new Error("foo");
}, 10),
};
}, 3),
};
const strIterarable = tson.stringify(obj, 4);

for await (const value of strIterarable) {
Expand Down Expand Up @@ -435,15 +446,27 @@ test("stringify and parse promise with a promise over a network connection", asy
});

const value = await tson.parse(stringIterator);
const asObj = value as typeof obj;
const asObj = value as Obj;

const firstPromise = await asObj.promise;

expect(firstPromise).toHaveProperty("anotherPromise");

// eslint-disable-next-line @typescript-eslint/no-unsafe-return
const err = await firstPromise.rejectedPromise.catch((err) => err);
assert.instanceOf(err, Error);

expect(err.cause).toMatchInlineSnapshot(`

Check failure on line 459 in src/handlers/tsonPromise.test.ts

View workflow job for this annotation

GitHub Actions / lint

Unsafe member access .cause on an `any` value
{
"name": "TsonPromiseRejectionError",
}
`);

const secondPromise = await firstPromise.anotherPromise;

expect(secondPromise).toBe(42);

expect(err).toMatchInlineSnapshot("[TsonError: Promise rejected on server]");

server.close();
});
6 changes: 3 additions & 3 deletions src/handlers/tsonUnknownObjectGuard.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { createTson } from "../index.js";
import { expectError } from "../internals/testUtils.js";
import { tsonSet } from "./index.js";
import {
UnknownObjectGuardError,
TsonUnknownObjectGuardError,
tsonUnknownObjectGuard,
} from "./tsonUnknownObjectGuard.js";

Expand Down Expand Up @@ -41,10 +41,10 @@ test("guard unwanted objects", () => {
const expected = new Map([["a", 1]]);

const err = expectError(() => t.parse(t.stringify(expected)));
assert(err instanceof UnknownObjectGuardError);
assert(err instanceof TsonUnknownObjectGuardError);

expect(err).toMatchInlineSnapshot(
"[UnknownObjectGuardError: Unknown object found]",
'[TsonUnknownObjectGuardError: Unknown object found]',
);
expect(err.value).toEqual(expected);
}
Expand Down
8 changes: 5 additions & 3 deletions src/handlers/tsonUnknownObjectGuard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { TsonError } from "../errors.js";
import { isPlainObject } from "../internals/isPlainObject.js";
import { TsonType } from "../types.js";

export class UnknownObjectGuardError extends TsonError {
export class TsonUnknownObjectGuardError extends TsonError {
/**
* The unknown object that was found
*/
Expand All @@ -12,6 +12,8 @@ export class UnknownObjectGuardError extends TsonError {
super(`Unknown object found`);
this.name = this.constructor.name;
this.value = value;

this.name = "TsonUnknownObjectGuardError";
}
}

Expand All @@ -20,12 +22,12 @@ export class UnknownObjectGuardError extends TsonError {
* @description
* Guard against unknown complex objects.
* Make sure to define this last in the list of types.
* @throws {UnknownObjectGuardError} if an unknown object is found
* @throws {TsonUnknownObjectGuardError} if an unknown object is found
*/
export const tsonUnknownObjectGuard: TsonType<unknown, never> = {
test: (v) => {
if (v && typeof v === "object" && !Array.isArray(v) && !isPlainObject(v)) {
throw new UnknownObjectGuardError(v);
throw new TsonUnknownObjectGuardError(v);
}

return false;
Expand Down
15 changes: 15 additions & 0 deletions src/internals/testUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,18 @@ export const expectError = (fn: () => unknown) => {
expect(err).toBeInstanceOf(Error);
return err as Error;
};

export const waitError = async (
fnOrPromise: (() => unknown) | Promise<unknown>,
) => {
let err: unknown;
try {
await (typeof fnOrPromise === "function" ? fnOrPromise() : fnOrPromise);
} catch (_err) {
err = _err;
}

expect(err).toBeDefined();
expect(err).toBeInstanceOf(Error);
return err as Error;
};

0 comments on commit 60e8bbf

Please sign in to comment.