Skip to content

Commit

Permalink
Fix plugin recursive loop (#18)
Browse files Browse the repository at this point in the history
  • Loading branch information
brophdawg11 authored Feb 15, 2024
1 parent 0a207bc commit 4df304e
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 8 deletions.
43 changes: 43 additions & 0 deletions src/turbo-stream.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,3 +227,46 @@ test("should encode and decode custom type", async () => {
expect(decoded.value).toBeInstanceOf(Custom);
expect(decoded.value).toEqual(input);
});

test("should encode and decode custom type when nested alongside Promise", async () => {
class Custom {
constructor(public foo: string) {}
}
const input = {
number: 1,
array: [2, "foo", 3],
set: new Set(["bar", "baz"]),
custom: new Custom("qux"),
promise: Promise.resolve("resolved"),
};
const decoded = (await decode(
encode(input, [
(value) => {
if (value instanceof Custom) {
return ["Custom", value.foo];
}
},
]),
[
(type, foo) => {
if (type === "Custom") {
return { value: new Custom(foo as string) };
}
},
]
)) as unknown as {
value: {
number: number;
array: [];
set: Set<string>;
custom: Custom;
promise: Promise<string>;
};
};
expect(decoded.value.number).toBe(input.number);
expect(decoded.value.array).toEqual(input.array);
expect(decoded.value.set).toEqual(input.set);
expect(decoded.value.custom).toBeInstanceOf(Custom);
expect(decoded.value.custom.foo).toBe("qux");
expect(await decoded.value.promise).toBe("resolved");
});
17 changes: 9 additions & 8 deletions src/unflatten.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,6 @@ function hydrate(this: ThisDecode, index: number) {

if (Array.isArray(value)) {
if (typeof value[0] === "string") {
if (Array.isArray(plugins)) {
const args = value.slice(1).map((i) => hydrate.call(this, i));
for (const plugin of plugins) {
const result = plugin(value[0], ...args);
if (result) return (hydrated[index] = result.value);
}
}

const [type, b, c] = value;
switch (type) {
case TYPE_DATE:
Expand Down Expand Up @@ -122,6 +114,15 @@ function hydrate(this: ThisDecode, index: number) {
hydrated[index] = error;
return error;
default:
// Run plugins at the end so we have a chance to resolve primitives
// without running into a loop
if (Array.isArray(plugins)) {
const args = value.slice(1).map((i) => hydrate.call(this, i));
for (const plugin of plugins) {
const result = plugin(value[0], ...args);
if (result) return (hydrated[index] = result.value);
}
}
throw new SyntaxError();
}
} else {
Expand Down

0 comments on commit 4df304e

Please sign in to comment.