Skip to content

Commit

Permalink
fix: reset deserialization cache on dynamic imports
Browse files Browse the repository at this point in the history
  • Loading branch information
marcus-pousette committed Apr 9, 2024
1 parent 1d8bc8c commit 987b664
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 4 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@dao-xyz/borsh",
"version": "5.2.1",
"version": "5.2.2",
"readme": "README.md",
"homepage": "https://github.com/dao-xyz/borsh-ts#README",
"description": "Binary Object Representation Serializer for Hashing simplified with decorators",
Expand Down
10 changes: 10 additions & 0 deletions src/__tests__/fixtures/enums/a.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { deserialize, serialize, variant } from "../../../index.js";
import { Base } from "./base.js";


@variant("A")
class A extends Base { }

deserialize(serialize(new A()), Base)

console.log("HERE")
9 changes: 9 additions & 0 deletions src/__tests__/fixtures/enums/b.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { deserialize, serialize, variant } from "../../../index.js";
import { Base } from "./base.js";

@variant("B")
class B extends Base { }

deserialize(serialize(new B()), Base)

console.log("HERE")
1 change: 1 addition & 0 deletions src/__tests__/fixtures/enums/base.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export class Base { }
5 changes: 5 additions & 0 deletions src/__tests__/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1312,6 +1312,11 @@ describe("enum", () => {
expect(deserialized.members[1]).toBeInstanceOf(Orangutan);
expect(deserialized.members[1].name).toEqual("Ora");
});

test("dynamic import", async () => {
await import("./fixtures/enums/b.js");
await import("./fixtures/enums/a.js");
});
});

describe("option", () => {
Expand Down
17 changes: 14 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
IntegerType,
getOffset,
StringType,
extendingClasses,
} from "./types.js";
export * from "./binary.js";
export * from "./types.js";
Expand Down Expand Up @@ -360,8 +361,10 @@ function deserializeField(
}
export function deserializeStruct(targetClazz: any, fromBuffer: boolean): (reader: BinaryReader, options?: DeserializeStructOptions) => any {

const handle = getCreateDeserializationHandle(targetClazz, 0, fromBuffer); // "compile time"
return (reader: BinaryReader, options?: DeserializeStructOptions) => { // runtime
const handle = getCreateDeserializationHandle(targetClazz, 0, fromBuffer);
// "compile time"
return (reader: BinaryReader, options?: DeserializeStructOptions) => {
// "runtime"
const result = handle({}, reader, options)
if (!options?.unchecked && !(options as any)?.object && !checkClazzesCompatible(result.constructor, targetClazz)) {
throw new BorshError(`Deserialization of ${targetClazz?.name || targetClazz} yielded another Class: ${result.constructor?.name} which are not compatible`);
Expand All @@ -375,7 +378,7 @@ export function deserializeStruct(targetClazz: any, fromBuffer: boolean): (reade
const getCreateDeserializationHandle = (clazz: any, offset: number, fromBuffer: boolean): (result: any, reader: BinaryReader, options?: DeserializeStructOptions) => any => getDeserializationHandle(clazz, offset, fromBuffer) || setDeserializationHandle(clazz, offset, fromBuffer, createDeserializeStructHandle(clazz, offset, fromBuffer))
const getDeserializationHandle = (clazz: any, offset: number, fromBuffer: boolean) => clazz.prototype[PROTOTYPE_DESERIALIZATION_HANDLER_OFFSET + offset + (fromBuffer ? MAX_PROTOTYPE_SEARCH : 0)]
const setDeserializationHandle = (clazz: any, offset: number, fromBuffer: boolean, handle: (result: any, reader: BinaryReader, options?: DeserializeStructOptions) => any) => clazz.prototype[PROTOTYPE_DESERIALIZATION_HANDLER_OFFSET + offset + (fromBuffer ? MAX_PROTOTYPE_SEARCH : 0)] = handle;

const clearDeserializeStructHandle = (clazz: any, offset: number, fromBuffer: boolean) => delete clazz.prototype[PROTOTYPE_DESERIALIZATION_HANDLER_OFFSET + offset + (fromBuffer ? MAX_PROTOTYPE_SEARCH : 0)]
const createDeserializeStructHandle = (currClazz: Constructor<any>, offset: number, fromBuffer: boolean): ((result: any, reader: BinaryReader, options?: DeserializeStructOptions) => any) => {
let handle: (result: any, reader: BinaryReader, options?: DeserializeStructOptions) => any | undefined = undefined;
let endHandle = (result: any, reader: BinaryReader, options: DeserializeStructOptions) => {
Expand Down Expand Up @@ -678,6 +681,14 @@ export const variant = (index: number | number[] | string) => {
let schemas = getOrCreateStructMeta(ctor, offset);
schemas.variant = index;

// clear deserialization handles for all dependencies since we might have made a dynamic import which breakes the deserialization path caches
for (const clazz of extendingClasses(ctor)) {
clearDeserializeStructHandle(clazz, 0, true);
clearDeserializeStructHandle(clazz, 0, false)
}



// Check for variant conficts
for (let i = offset - 1; i >= 0; i--) {
const dependencies = getDependencies(ctor, i)
Expand Down

0 comments on commit 987b664

Please sign in to comment.