Add support for null values in Y.Map and Y.Array
This commit is contained in:
		
							parent
							
								
									371f2b6d55
								
							
						
					
					
						commit
						4922eeac56
					
				
							
								
								
									
										22
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								README.md
									
									
									
									
									
								
							@ -250,36 +250,36 @@ necessary.
 | 
				
			|||||||
  <dl>
 | 
					  <dl>
 | 
				
			||||||
    <b><code>parent:Y.AbstractType|null</code></b>
 | 
					    <b><code>parent:Y.AbstractType|null</code></b>
 | 
				
			||||||
    <dd></dd>
 | 
					    <dd></dd>
 | 
				
			||||||
    <b><code>insert(index:number, content:Array<object|boolean|Array|string|number|Uint8Array|Y.Type>)</code></b>
 | 
					    <b><code>insert(index:number, content:Array<object|boolean|Array|string|number|null|Uint8Array|Y.Type>)</code></b>
 | 
				
			||||||
    <dd>
 | 
					    <dd>
 | 
				
			||||||
Insert content at <var>index</var>. Note that content is an array of elements.
 | 
					Insert content at <var>index</var>. Note that content is an array of elements.
 | 
				
			||||||
I.e. <code>array.insert(0, [1])</code> splices the list and inserts 1 at
 | 
					I.e. <code>array.insert(0, [1])</code> splices the list and inserts 1 at
 | 
				
			||||||
position 0.
 | 
					position 0.
 | 
				
			||||||
    </dd>
 | 
					    </dd>
 | 
				
			||||||
    <b><code>push(Array<Object|boolean|Array|string|number|Uint8Array|Y.Type>)</code></b>
 | 
					    <b><code>push(Array<Object|boolean|Array|string|number|null|Uint8Array|Y.Type>)</code></b>
 | 
				
			||||||
    <dd></dd>
 | 
					    <dd></dd>
 | 
				
			||||||
    <b><code>unshift(Array<Object|boolean|Array|string|number|Uint8Array|Y.Type>)</code></b>
 | 
					    <b><code>unshift(Array<Object|boolean|Array|string|number|null|Uint8Array|Y.Type>)</code></b>
 | 
				
			||||||
    <dd></dd>
 | 
					    <dd></dd>
 | 
				
			||||||
    <b><code>delete(index:number, length:number)</code></b>
 | 
					    <b><code>delete(index:number, length:number)</code></b>
 | 
				
			||||||
    <dd></dd>
 | 
					    <dd></dd>
 | 
				
			||||||
    <b><code>get(index:number)</code></b>
 | 
					    <b><code>get(index:number)</code></b>
 | 
				
			||||||
    <dd></dd>
 | 
					    <dd></dd>
 | 
				
			||||||
    <b><code>slice(start:number, end:number):Array<Object|boolean|Array|string|number|Uint8Array|Y.Type></code></b>
 | 
					    <b><code>slice(start:number, end:number):Array<Object|boolean|Array|string|number|null|Uint8Array|Y.Type></code></b>
 | 
				
			||||||
    <dd>Retrieve a range of content</dd>
 | 
					    <dd>Retrieve a range of content</dd>
 | 
				
			||||||
    <b><code>length:number</code></b>
 | 
					    <b><code>length:number</code></b>
 | 
				
			||||||
    <dd></dd>
 | 
					    <dd></dd>
 | 
				
			||||||
    <b>
 | 
					    <b>
 | 
				
			||||||
      <code>
 | 
					      <code>
 | 
				
			||||||
forEach(function(value:object|boolean|Array|string|number|Uint8Array|Y.Type,
 | 
					forEach(function(value:object|boolean|Array|string|number|null|Uint8Array|Y.Type,
 | 
				
			||||||
 index:number, array: Y.Array))
 | 
					 index:number, array: Y.Array))
 | 
				
			||||||
      </code>
 | 
					      </code>
 | 
				
			||||||
    </b>
 | 
					    </b>
 | 
				
			||||||
    <dd></dd>
 | 
					    <dd></dd>
 | 
				
			||||||
    <b><code>map(function(T, number, YArray):M):Array<M></code></b>
 | 
					    <b><code>map(function(T, number, YArray):M):Array<M></code></b>
 | 
				
			||||||
    <dd></dd>
 | 
					    <dd></dd>
 | 
				
			||||||
    <b><code>toArray():Array<object|boolean|Array|string|number|Uint8Array|Y.Type></code></b>
 | 
					    <b><code>toArray():Array<object|boolean|Array|string|number|null|Uint8Array|Y.Type></code></b>
 | 
				
			||||||
    <dd>Copies the content of this YArray to a new Array.</dd>
 | 
					    <dd>Copies the content of this YArray to a new Array.</dd>
 | 
				
			||||||
    <b><code>toJSON():Array<Object|boolean|Array|string|number></code></b>
 | 
					    <b><code>toJSON():Array<Object|boolean|Array|string|number|null></code></b>
 | 
				
			||||||
    <dd>
 | 
					    <dd>
 | 
				
			||||||
Copies the content of this YArray to a new Array. It transforms all child types
 | 
					Copies the content of this YArray to a new Array. It transforms all child types
 | 
				
			||||||
to JSON using their <code>toJSON</code> method.
 | 
					to JSON using their <code>toJSON</code> method.
 | 
				
			||||||
@ -325,9 +325,9 @@ or any of its children.
 | 
				
			|||||||
    <dd></dd>
 | 
					    <dd></dd>
 | 
				
			||||||
    <b><code>size: number</code></b>
 | 
					    <b><code>size: number</code></b>
 | 
				
			||||||
    <dd>Total number of key/value pairs.</dd>
 | 
					    <dd>Total number of key/value pairs.</dd>
 | 
				
			||||||
    <b><code>get(key:string):object|boolean|string|number|Uint8Array|Y.Type</code></b>
 | 
					    <b><code>get(key:string):object|boolean|string|number|null|Uint8Array|Y.Type</code></b>
 | 
				
			||||||
    <dd></dd>
 | 
					    <dd></dd>
 | 
				
			||||||
    <b><code>set(key:string, value:object|boolean|string|number|Uint8Array|Y.Type)</code></b>
 | 
					    <b><code>set(key:string, value:object|boolean|string|number|null|Uint8Array|Y.Type)</code></b>
 | 
				
			||||||
    <dd></dd>
 | 
					    <dd></dd>
 | 
				
			||||||
    <b><code>delete(key:string)</code></b>
 | 
					    <b><code>delete(key:string)</code></b>
 | 
				
			||||||
    <dd></dd>
 | 
					    <dd></dd>
 | 
				
			||||||
@ -339,12 +339,12 @@ or any of its children.
 | 
				
			|||||||
    <dd>Removes all elements from this YMap.</dd>
 | 
					    <dd>Removes all elements from this YMap.</dd>
 | 
				
			||||||
    <b><code>clone():Y.Map</code></b>
 | 
					    <b><code>clone():Y.Map</code></b>
 | 
				
			||||||
    <dd>Clone this type into a fresh Yjs type.</dd>
 | 
					    <dd>Clone this type into a fresh Yjs type.</dd>
 | 
				
			||||||
    <b><code>toJSON():Object<string, Object|boolean|Array|string|number|Uint8Array></code></b>
 | 
					    <b><code>toJSON():Object<string, Object|boolean|Array|string|number|null|Uint8Array></code></b>
 | 
				
			||||||
    <dd>
 | 
					    <dd>
 | 
				
			||||||
Copies the <code>[key,value]</code> pairs of this YMap to a new Object.It
 | 
					Copies the <code>[key,value]</code> pairs of this YMap to a new Object.It
 | 
				
			||||||
transforms all child types to JSON using their <code>toJSON</code> method.
 | 
					transforms all child types to JSON using their <code>toJSON</code> method.
 | 
				
			||||||
    </dd>
 | 
					    </dd>
 | 
				
			||||||
    <b><code>forEach(function(value:object|boolean|Array|string|number|Uint8Array|Y.Type,
 | 
					    <b><code>forEach(function(value:object|boolean|Array|string|number|null|Uint8Array|Y.Type,
 | 
				
			||||||
 key:string, map: Y.Map))</code></b>
 | 
					 key:string, map: Y.Map))</code></b>
 | 
				
			||||||
    <dd>
 | 
					    <dd>
 | 
				
			||||||
      Execute the provided function once for every key-value pair.
 | 
					      Execute the provided function once for every key-value pair.
 | 
				
			||||||
 | 
				
			|||||||
@ -623,7 +623,7 @@ export const typeListGet = (type, index) => {
 | 
				
			|||||||
 * @param {Transaction} transaction
 | 
					 * @param {Transaction} transaction
 | 
				
			||||||
 * @param {AbstractType<any>} parent
 | 
					 * @param {AbstractType<any>} parent
 | 
				
			||||||
 * @param {Item?} referenceItem
 | 
					 * @param {Item?} referenceItem
 | 
				
			||||||
 * @param {Array<Object<string,any>|Array<any>|boolean|number|string|Uint8Array>} content
 | 
					 * @param {Array<Object<string,any>|Array<any>|boolean|number|null|string|Uint8Array>} content
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @private
 | 
					 * @private
 | 
				
			||||||
 * @function
 | 
					 * @function
 | 
				
			||||||
@ -635,7 +635,7 @@ export const typeListInsertGenericsAfter = (transaction, parent, referenceItem,
 | 
				
			|||||||
  const store = doc.store
 | 
					  const store = doc.store
 | 
				
			||||||
  const right = referenceItem === null ? parent._start : referenceItem.right
 | 
					  const right = referenceItem === null ? parent._start : referenceItem.right
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * @type {Array<Object|Array<any>|number>}
 | 
					   * @type {Array<Object|Array<any>|number|null>}
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  let jsonContent = []
 | 
					  let jsonContent = []
 | 
				
			||||||
  const packJsonContent = () => {
 | 
					  const packJsonContent = () => {
 | 
				
			||||||
@ -646,34 +646,39 @@ export const typeListInsertGenericsAfter = (transaction, parent, referenceItem,
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  content.forEach(c => {
 | 
					  content.forEach(c => {
 | 
				
			||||||
    switch (c.constructor) {
 | 
					    if(c === null) {
 | 
				
			||||||
      case Number:
 | 
					      jsonContent.push(c)
 | 
				
			||||||
      case Object:
 | 
					    } else {
 | 
				
			||||||
      case Boolean:
 | 
					      switch (c.constructor) {
 | 
				
			||||||
      case Array:
 | 
					        case Number:
 | 
				
			||||||
      case String:
 | 
					        case Object:
 | 
				
			||||||
        jsonContent.push(c)
 | 
					        case Boolean:
 | 
				
			||||||
        break
 | 
					        case Array:
 | 
				
			||||||
      default:
 | 
					        case String:
 | 
				
			||||||
        packJsonContent()
 | 
					          jsonContent.push(c)
 | 
				
			||||||
        switch (c.constructor) {
 | 
					          break
 | 
				
			||||||
          case Uint8Array:
 | 
					        default:
 | 
				
			||||||
          case ArrayBuffer:
 | 
					          packJsonContent()
 | 
				
			||||||
            left = new Item(createID(ownClientId, getState(store, ownClientId)), left, left && left.lastId, right, right && right.id, parent, null, new ContentBinary(new Uint8Array(/** @type {Uint8Array} */ (c))))
 | 
					          switch (c.constructor) {
 | 
				
			||||||
            left.integrate(transaction, 0)
 | 
					            case Uint8Array:
 | 
				
			||||||
            break
 | 
					            case ArrayBuffer:
 | 
				
			||||||
          case Doc:
 | 
					              left = new Item(createID(ownClientId, getState(store, ownClientId)), left, left && left.lastId, right, right && right.id, parent, null, new ContentBinary(new Uint8Array(/** @type {Uint8Array} */ (c))))
 | 
				
			||||||
            left = new Item(createID(ownClientId, getState(store, ownClientId)), left, left && left.lastId, right, right && right.id, parent, null, new ContentDoc(/** @type {Doc} */ (c)))
 | 
					 | 
				
			||||||
            left.integrate(transaction, 0)
 | 
					 | 
				
			||||||
            break
 | 
					 | 
				
			||||||
          default:
 | 
					 | 
				
			||||||
            if (c instanceof AbstractType) {
 | 
					 | 
				
			||||||
              left = new Item(createID(ownClientId, getState(store, ownClientId)), left, left && left.lastId, right, right && right.id, parent, null, new ContentType(c))
 | 
					 | 
				
			||||||
              left.integrate(transaction, 0)
 | 
					              left.integrate(transaction, 0)
 | 
				
			||||||
            } else {
 | 
					              break
 | 
				
			||||||
              throw new Error('Unexpected content type in insert operation')
 | 
					            case Doc:
 | 
				
			||||||
            }
 | 
					              left = new Item(createID(ownClientId, getState(store, ownClientId)), left, left && left.lastId, right, right && right.id, parent, null, new ContentDoc(/** @type {Doc} */ (c)))
 | 
				
			||||||
        }
 | 
					              left.integrate(transaction, 0)
 | 
				
			||||||
 | 
					              break
 | 
				
			||||||
 | 
					            default:
 | 
				
			||||||
 | 
					              if (c instanceof AbstractType) {
 | 
				
			||||||
 | 
					                left = new Item(createID(ownClientId, getState(store, ownClientId)), left, left && left.lastId, right, right && right.id, parent, null, new ContentType(c))
 | 
				
			||||||
 | 
					                left.integrate(transaction, 0)
 | 
				
			||||||
 | 
					              } else {
 | 
				
			||||||
 | 
					                throw new Error('Unexpected content type in insert operation')
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
  packJsonContent()
 | 
					  packJsonContent()
 | 
				
			||||||
@ -685,7 +690,7 @@ const lengthExceeded = error.create('Length exceeded!')
 | 
				
			|||||||
 * @param {Transaction} transaction
 | 
					 * @param {Transaction} transaction
 | 
				
			||||||
 * @param {AbstractType<any>} parent
 | 
					 * @param {AbstractType<any>} parent
 | 
				
			||||||
 * @param {number} index
 | 
					 * @param {number} index
 | 
				
			||||||
 * @param {Array<Object<string,any>|Array<any>|number|string|Uint8Array>} content
 | 
					 * @param {Array<Object<string,any>|Array<any>|number|null|string|Uint8Array>} content
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @private
 | 
					 * @private
 | 
				
			||||||
 * @function
 | 
					 * @function
 | 
				
			||||||
@ -797,7 +802,7 @@ export const typeMapDelete = (transaction, parent, key) => {
 | 
				
			|||||||
 * @param {Transaction} transaction
 | 
					 * @param {Transaction} transaction
 | 
				
			||||||
 * @param {AbstractType<any>} parent
 | 
					 * @param {AbstractType<any>} parent
 | 
				
			||||||
 * @param {string} key
 | 
					 * @param {string} key
 | 
				
			||||||
 * @param {Object|number|Array<any>|string|Uint8Array|AbstractType<any>} value
 | 
					 * @param {Object|number|null|Array<any>|string|Uint8Array|AbstractType<any>} value
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @private
 | 
					 * @private
 | 
				
			||||||
 * @function
 | 
					 * @function
 | 
				
			||||||
@ -838,7 +843,7 @@ export const typeMapSet = (transaction, parent, key, value) => {
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * @param {AbstractType<any>} parent
 | 
					 * @param {AbstractType<any>} parent
 | 
				
			||||||
 * @param {string} key
 | 
					 * @param {string} key
 | 
				
			||||||
 * @return {Object<string,any>|number|Array<any>|string|Uint8Array|AbstractType<any>|undefined}
 | 
					 * @return {Object<string,any>|number|null|Array<any>|string|Uint8Array|AbstractType<any>|undefined}
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @private
 | 
					 * @private
 | 
				
			||||||
 * @function
 | 
					 * @function
 | 
				
			||||||
@ -850,7 +855,7 @@ export const typeMapGet = (parent, key) => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @param {AbstractType<any>} parent
 | 
					 * @param {AbstractType<any>} parent
 | 
				
			||||||
 * @return {Object<string,Object<string,any>|number|Array<any>|string|Uint8Array|AbstractType<any>|undefined>}
 | 
					 * @return {Object<string,Object<string,any>|number|null|Array<any>|string|Uint8Array|AbstractType<any>|undefined>}
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @private
 | 
					 * @private
 | 
				
			||||||
 * @function
 | 
					 * @function
 | 
				
			||||||
@ -885,7 +890,7 @@ export const typeMapHas = (parent, key) => {
 | 
				
			|||||||
 * @param {AbstractType<any>} parent
 | 
					 * @param {AbstractType<any>} parent
 | 
				
			||||||
 * @param {string} key
 | 
					 * @param {string} key
 | 
				
			||||||
 * @param {Snapshot} snapshot
 | 
					 * @param {Snapshot} snapshot
 | 
				
			||||||
 * @return {Object<string,any>|number|Array<any>|string|Uint8Array|AbstractType<any>|undefined}
 | 
					 * @return {Object<string,any>|number|null|Array<any>|string|Uint8Array|AbstractType<any>|undefined}
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @private
 | 
					 * @private
 | 
				
			||||||
 * @function
 | 
					 * @function
 | 
				
			||||||
 | 
				
			|||||||
@ -488,6 +488,11 @@ const arrayTransactions = [
 | 
				
			|||||||
    map.set('someprop', 43)
 | 
					    map.set('someprop', 43)
 | 
				
			||||||
    map.set('someprop', 44)
 | 
					    map.set('someprop', 44)
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					  function insertTypeNull (user, gen) {
 | 
				
			||||||
 | 
					    const yarray = user.getArray('array')
 | 
				
			||||||
 | 
					    const pos = prng.int32(gen, 0, yarray.length)
 | 
				
			||||||
 | 
					    yarray.insert(pos, [null])
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
  function _delete (user, gen) {
 | 
					  function _delete (user, gen) {
 | 
				
			||||||
    const yarray = user.getArray('array')
 | 
					    const yarray = user.getArray('array')
 | 
				
			||||||
    const length = yarray.length
 | 
					    const length = yarray.length
 | 
				
			||||||
@ -496,7 +501,7 @@ const arrayTransactions = [
 | 
				
			|||||||
      let delLength = prng.int32(gen, 1, math.min(2, length - somePos))
 | 
					      let delLength = prng.int32(gen, 1, math.min(2, length - somePos))
 | 
				
			||||||
      if (prng.bool(gen)) {
 | 
					      if (prng.bool(gen)) {
 | 
				
			||||||
        const type = yarray.get(somePos)
 | 
					        const type = yarray.get(somePos)
 | 
				
			||||||
        if (type.length > 0) {
 | 
					        if (type instanceof Y.Array && type.length > 0) {
 | 
				
			||||||
          somePos = prng.int32(gen, 0, type.length - 1)
 | 
					          somePos = prng.int32(gen, 0, type.length - 1)
 | 
				
			||||||
          delLength = prng.int32(gen, 0, math.min(2, type.length - somePos))
 | 
					          delLength = prng.int32(gen, 0, math.min(2, type.length - somePos))
 | 
				
			||||||
          type.delete(somePos, delLength)
 | 
					          type.delete(somePos, delLength)
 | 
				
			||||||
 | 
				
			|||||||
@ -42,6 +42,7 @@ export const testBasicMapTests = tc => {
 | 
				
			|||||||
  const { testConnector, users, map0, map1, map2 } = init(tc, { users: 3 })
 | 
					  const { testConnector, users, map0, map1, map2 } = init(tc, { users: 3 })
 | 
				
			||||||
  users[2].disconnect()
 | 
					  users[2].disconnect()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  map0.set('null', null)
 | 
				
			||||||
  map0.set('number', 1)
 | 
					  map0.set('number', 1)
 | 
				
			||||||
  map0.set('string', 'hello Y')
 | 
					  map0.set('string', 'hello Y')
 | 
				
			||||||
  map0.set('object', { key: { key2: 'value' } })
 | 
					  map0.set('object', { key: { key2: 'value' } })
 | 
				
			||||||
@ -54,26 +55,29 @@ export const testBasicMapTests = tc => {
 | 
				
			|||||||
  array.insert(0, [0])
 | 
					  array.insert(0, [0])
 | 
				
			||||||
  array.insert(0, [-1])
 | 
					  array.insert(0, [-1])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  t.assert(map0.get('null') === null, 'client 0 computed the change (null)')
 | 
				
			||||||
  t.assert(map0.get('number') === 1, 'client 0 computed the change (number)')
 | 
					  t.assert(map0.get('number') === 1, 'client 0 computed the change (number)')
 | 
				
			||||||
  t.assert(map0.get('string') === 'hello Y', 'client 0 computed the change (string)')
 | 
					  t.assert(map0.get('string') === 'hello Y', 'client 0 computed the change (string)')
 | 
				
			||||||
  t.assert(map0.get('boolean0') === false, 'client 0 computed the change (boolean)')
 | 
					  t.assert(map0.get('boolean0') === false, 'client 0 computed the change (boolean)')
 | 
				
			||||||
  t.assert(map0.get('boolean1') === true, 'client 0 computed the change (boolean)')
 | 
					  t.assert(map0.get('boolean1') === true, 'client 0 computed the change (boolean)')
 | 
				
			||||||
  t.compare(map0.get('object'), { key: { key2: 'value' } }, 'client 0 computed the change (object)')
 | 
					  t.compare(map0.get('object'), { key: { key2: 'value' } }, 'client 0 computed the change (object)')
 | 
				
			||||||
  t.assert(map0.get('y-map').get('y-array').get(0) === -1, 'client 0 computed the change (type)')
 | 
					  t.assert(map0.get('y-map').get('y-array').get(0) === -1, 'client 0 computed the change (type)')
 | 
				
			||||||
  t.assert(map0.size === 6, 'client 0 map has correct size')
 | 
					  t.assert(map0.size === 7, 'client 0 map has correct size')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  users[2].connect()
 | 
					  users[2].connect()
 | 
				
			||||||
  testConnector.flushAllMessages()
 | 
					  testConnector.flushAllMessages()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  t.assert(map1.get('null') === null, 'client 1 received the update (null)')
 | 
				
			||||||
  t.assert(map1.get('number') === 1, 'client 1 received the update (number)')
 | 
					  t.assert(map1.get('number') === 1, 'client 1 received the update (number)')
 | 
				
			||||||
  t.assert(map1.get('string') === 'hello Y', 'client 1 received the update (string)')
 | 
					  t.assert(map1.get('string') === 'hello Y', 'client 1 received the update (string)')
 | 
				
			||||||
  t.assert(map1.get('boolean0') === false, 'client 1 computed the change (boolean)')
 | 
					  t.assert(map1.get('boolean0') === false, 'client 1 computed the change (boolean)')
 | 
				
			||||||
  t.assert(map1.get('boolean1') === true, 'client 1 computed the change (boolean)')
 | 
					  t.assert(map1.get('boolean1') === true, 'client 1 computed the change (boolean)')
 | 
				
			||||||
  t.compare(map1.get('object'), { key: { key2: 'value' } }, 'client 1 received the update (object)')
 | 
					  t.compare(map1.get('object'), { key: { key2: 'value' } }, 'client 1 received the update (object)')
 | 
				
			||||||
  t.assert(map1.get('y-map').get('y-array').get(0) === -1, 'client 1 received the update (type)')
 | 
					  t.assert(map1.get('y-map').get('y-array').get(0) === -1, 'client 1 received the update (type)')
 | 
				
			||||||
  t.assert(map1.size === 6, 'client 1 map has correct size')
 | 
					  t.assert(map1.size === 7, 'client 1 map has correct size')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // compare disconnected user
 | 
					  // compare disconnected user
 | 
				
			||||||
 | 
					  t.assert(map2.get('null') === null, 'client 2 received the update (null) - was disconnected')
 | 
				
			||||||
  t.assert(map2.get('number') === 1, 'client 2 received the update (number) - was disconnected')
 | 
					  t.assert(map2.get('number') === 1, 'client 2 received the update (number) - was disconnected')
 | 
				
			||||||
  t.assert(map2.get('string') === 'hello Y', 'client 2 received the update (string) - was disconnected')
 | 
					  t.assert(map2.get('string') === 'hello Y', 'client 2 received the update (string) - was disconnected')
 | 
				
			||||||
  t.assert(map2.get('boolean0') === false, 'client 2 computed the change (boolean)')
 | 
					  t.assert(map2.get('boolean0') === false, 'client 2 computed the change (boolean)')
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user