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