From 7433b58a09fb156cd0b96843e927284adc9c2e98 Mon Sep 17 00:00:00 2001
From: Bartosz Sypytkowski <b.sypytkowski@gmail.com>
Date: Tue, 30 May 2023 11:51:36 +0200
Subject: [PATCH] first tests passing

---
 src/structs/ContentLink.js | 64 ++++++++++++++++++++++++++++++++++++--
 src/structs/Item.js        |  8 +++++
 src/types/WeakLink.js      | 55 +-------------------------------
 tests/weakLinks.tests.js   | 22 ++++++++-----
 4 files changed, 84 insertions(+), 65 deletions(-)

diff --git a/src/structs/ContentLink.js b/src/structs/ContentLink.js
index 78668a80..5598f828 100644
--- a/src/structs/ContentLink.js
+++ b/src/structs/ContentLink.js
@@ -5,7 +5,12 @@ import {
     findRootTypeKey,
     ID,
     find,
-    ContentType
+    ContentType,
+    AbstractType,
+    findMarker,
+    getItemCleanStart,
+    createID,
+    getItemCleanEnd
   } from '../internals.js'
   
   export class ContentLink {
@@ -80,7 +85,10 @@ import {
         }
 
         if (item.constructor === ID) {
-          item = find(transaction.doc.store, item)
+          item = getItemCleanStart(transaction, item)
+          if (item.length > 1) {
+            item = getItemCleanEnd(transaction, transaction.doc.store, createID(item.id.client, item.id.clock + 1))
+          }
         } else {
           key = item
           item = parent._map.get(key)
@@ -170,4 +178,54 @@ import {
     }
     return new ContentLink({parent, item})
   }
-  
\ No newline at end of file
+  
+const lengthExceeded = error.create('Length exceeded!')
+
+/**
+ * Returns a {WeakLink} to an YArray element at given index.
+ * 
+ * @param {Transaction} transaction
+ * @param {AbstractType<any>} parent
+ * @param {number} index
+ * @return {WeakLink<any>}
+ */
+export const arrayWeakLink = (transaction, parent, index) => {
+  const marker = findMarker(parent, index)
+  let n = parent._start
+  if (marker !== null) {
+    n = marker.p
+    index -= marker.index
+  }
+  for (; n !== null; n = n.right) {
+    if (!n.deleted && n.countable) {
+      if (index < n.length) {
+        if (index > 0) {
+            n = getItemCleanStart(transaction, createID(n.id.client, n.id.clock + index))
+        }
+        if (n.length > 1) {
+            n = getItemCleanEnd(transaction, transaction.doc.store, createID(n.id.client, n.id.clock + 1))
+        }
+        return new WeakLink(parent, n, null)
+      }
+      index -= n.length
+    }
+  }
+
+  throw lengthExceeded
+}
+
+/**
+ * Returns a {WeakLink} to an YMap element at given key.
+ * 
+ * @param {AbstractType<any>} parent
+ * @param {string} key
+ * @return {WeakLink<any>|undefined}
+ */
+export const mapWeakLink = (parent, key) => {
+  const item = parent._map.get(key)
+  if (item !== undefined) {
+    return new WeakLink(parent, item, key)
+  } else {
+    return undefined
+  }
+}
\ No newline at end of file
diff --git a/src/structs/Item.js b/src/structs/Item.js
index d8589dbf..3c510904 100644
--- a/src/structs/Item.js
+++ b/src/structs/Item.js
@@ -386,6 +386,14 @@ export class Item extends AbstractStruct {
     if (this.parent && this.parent.constructor === ID && this.id.client !== this.parent.client && this.parent.clock >= getState(store, this.parent.client)) {
       return this.parent.client
     }
+    if (this.content.constructor === ContentLink) {
+      const content = /** @type {ContentLink} */ (this.content)
+      if (content.link.item.constructor === ID) {
+        if (content.link.item.client !== this.id.client) {
+          return content.link.item.client
+        }
+      }
+    }
 
     // We have all missing ids, now find the items
 
diff --git a/src/types/WeakLink.js b/src/types/WeakLink.js
index f51d950e..cb705a9d 100644
--- a/src/types/WeakLink.js
+++ b/src/types/WeakLink.js
@@ -1,7 +1,5 @@
 import { AbstractType, GC, Item, createID } from "yjs"
-import { findMarker, typeMapGet } from "./AbstractType.js"
-import { error } from "lib0"
-import { Transaction, getItemCleanEnd, getItemCleanStart } from "src/internals.js"
+import { typeMapGet } from "./AbstractType.js"
 
 /**
  * @template T
@@ -37,54 +35,3 @@ export class WeakLink {
     }
   }
 }
-
-const lengthExceeded = error.create('Length exceeded!')
-
-/**
- * Returns a {WeakLink} to an YArray element at given index.
- * 
- * @param {Transaction} transaction
- * @param {AbstractType<any>} parent
- * @param {number} index
- * @return {WeakLink<any>}
- */
-export const arrayWeakLink = (transaction, parent, index) => {
-  const marker = findMarker(parent, index)
-  let n = parent._start
-  if (marker !== null) {
-    n = marker.p
-    index -= marker.index
-  }
-  for (; n !== null; n = n.right) {
-    if (!n.deleted && n.countable) {
-      if (index < n.length) {
-        if (index > 0) {
-            n = getItemCleanStart(transaction, createID(n.id.clock, n.id.clock + index))
-        }
-        if (n.length > 1) {
-            n = getItemCleanEnd(transaction, transaction.doc.store, createID(n.id.clock, n.id.clock + 1))
-        }
-        return new WeakLink(parent, n, null)
-      }
-      index -= n.length
-    }
-  }
-
-  throw lengthExceeded
-}
-
-/**
- * Returns a {WeakLink} to an YMap element at given key.
- * 
- * @param {AbstractType<any>} parent
- * @param {string} key
- * @return {WeakLink<any>|undefined}
- */
-export const mapWeakLink = (parent, key) => {
-  const item = parent._map.get(key)
-  if (item !== undefined) {
-    return new WeakLink(parent, item, key)
-  } else {
-    return undefined
-  }
-}
\ No newline at end of file
diff --git a/tests/weakLinks.tests.js b/tests/weakLinks.tests.js
index dd711fab..90a81ecb 100644
--- a/tests/weakLinks.tests.js
+++ b/tests/weakLinks.tests.js
@@ -25,15 +25,21 @@ export const testBasicMap = tc => {
  * @param {t.TestCase} tc
  */
 export const testBasicArray = tc => {
-  const doc = new Y.Doc()
-  const array = doc.getArray('array')
-  array.insert(0, [1,2,3])
-  array.insert(3, [array.link(1)])
+  const { testConnector, array0, array1 } = init(tc, {users:2})
+  array0.insert(0, [1,2,3])
+  array0.insert(3, [array0.link(1)])
 
-  t.compare(array.get(0), 1)
-  t.compare(array.get(1), 2)
-  t.compare(array.get(2), 3)
-  t.compare(array.get(3).deref(), 2)
+  t.compare(array0.get(0), 1)
+  t.compare(array0.get(1), 2)
+  t.compare(array0.get(2), 3)
+  t.compare(array0.get(3).deref(), 2)
+
+  testConnector.flushAllMessages()
+
+  t.compare(array1.get(0), 1)
+  t.compare(array1.get(1), 2)
+  t.compare(array1.get(2), 3)
+  t.compare(array1.get(3).deref(), 2)
 }
 
 /**