Repository: blitz-js/superjson (ts)

Issue:
serialization/deserialization bug
I think I found a serialization/deserialization bug, for which there isn't an open issue. I ran this against the latest version of superjson about a week ago:

```
> x = sj.serialize({q: [9, {henlo: undefined, yee: new Date(), yee2: new Date(), foo1: new Date(), z: Symbol('cool')}]})
{
  json: { q: [ 9, [Object] ] },
  meta: {
    values: { 'q.1.henlo': [Array], 'q.1.yee': [Array], 'q.1.foo1': [Array] }
  }
}
> x.json.q
[
  9,
  {
    henlo: undefined,
    yee: '2020-09-06T22:41:57.555Z',
    yee2: '2020-09-06T22:41:57.555Z',
    foo1: '2020-09-06T22:41:57.555Z',
    z: Symbol(cool)
  }
]
> sj.deserialize(x)
{
  q: [
    9,
    {
      henlo: undefined,
      yee: 2020-09-06T22:41:57.555Z,
      yee2: '2020-09-06T22:41:57.555Z',
      foo1: 2020-09-06T22:41:57.555Z,
      z: Symbol(cool)
    }
  ]
}
```

Pull request:
Fix bug with existing prefixes in PathTree
Closes #58.

Due to how the prefix detection in `PathTree` worked, serialising and object with paths `yee` and `yee2` didn't work as expected. This PR fixes that.

Patch:
diff --git a/src/pathtree.ts b/src/pathtree.ts
index 12c7757..dc1717a 100644
--- a/src/pathtree.ts
+++ b/src/pathtree.ts
@@ -25,6 +25,14 @@ export function isTree<T>(
   return false;
 }
 
+function isPrefixOf<T>(potentialPrefix: T[], of: T[]): boolean {
+  if (potentialPrefix.length > of.length) {
+    return false;
+  }
+
+  return potentialPrefix.every((value, index) => value === of[index]);
+}
+
 export module PathTree {
   export function create<T>(value: T): Tree<T> {
     return [value];
@@ -67,12 +75,11 @@ export module PathTree {
       const [nodeValue, children] = tree;
       const availablePaths = Object.keys(children);
 
-      const stringifiedPath = stringifyPath(path);
       // due to the constraints mentioned in the functions description,
       // there may be prefixes of `path` already set, but no extensions of it.
       // If there's such a prefix, we'll find it.
       const prefix = availablePaths.find(candidate =>
-        stringifiedPath.startsWith(candidate)
+        isPrefixOf(parsePath(candidate), path)
       );
 
       if (isUndefined(prefix)) {


Test patch:
diff --git a/src/index.test.ts b/src/index.test.ts
index d9bb14f..70c694d 100644
--- a/src/index.test.ts
+++ b/src/index.test.ts
@@ -404,6 +404,46 @@ describe('stringify & parse', () => {
         },
       },
     },
+
+    'issue #58': {
+      input: () => {
+        const cool = Symbol('cool');
+        SuperJSON.registerSymbol(cool);
+        return {
+          q: [
+            9,
+            {
+              henlo: undefined,
+              yee: new Date(2020, 1, 1),
+              yee2: new Date(2020, 1, 1),
+              foo1: new Date(2020, 1, 1),
+              z: cool,
+            },
+          ],
+        };
+      },
+      output: {
+        q: [
+          9,
+          {
+            henlo: undefined,
+            yee: new Date(2020, 1, 1).toISOString(),
+            yee2: new Date(2020, 1, 1).toISOString(),
+            foo1: new Date(2020, 1, 1).toISOString(),
+            z: 'cool',
+          },
+        ],
+      },
+      outputAnnotations: {
+        values: {
+          'q.1.henlo': ['undefined'],
+          'q.1.yee': ['Date'],
+          'q.1.yee2': ['Date'],
+          'q.1.foo1': ['Date'],
+          'q.1.z': [['symbol', 'cool']],
+        },
+      },
+    },
   };
 
   function deepFreeze(object: any, alreadySeenObjects = new Set()) {