Skip to content

Commit 3bf44b9

Browse files
committed
yjs#667 - add sanity messages when data is read before type is added to a document.
1 parent 8cd1a48 commit 3bf44b9

File tree

5 files changed

+35
-6
lines changed

5 files changed

+35
-6
lines changed

src/types/AbstractType.js

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ import * as map from 'lib0/map'
1717
import * as iterator from 'lib0/iterator'
1818
import * as error from 'lib0/error'
1919
import * as math from 'lib0/math'
20+
import * as log from 'lib0/logging'
21+
22+
/**
23+
* https://docs.yjs.dev/getting-started/working-with-shared-types#caveats
24+
*/
25+
export const warnPrematureAccess = () => { log.warn('Invalid access: Add Yjs type to a document before reading data.') }
2026

2127
const maxSearchMarker = 80
2228

@@ -215,6 +221,7 @@ export const updateMarkerChanges = (searchMarker, index, len) => {
215221
* @return {Array<Item>}
216222
*/
217223
export const getTypeChildren = t => {
224+
t.doc ?? warnPrematureAccess()
218225
let s = t._start
219226
const arr = []
220227
while (s) {
@@ -408,6 +415,7 @@ export class AbstractType {
408415
* @function
409416
*/
410417
export const typeListSlice = (type, start, end) => {
418+
type.doc ?? warnPrematureAccess()
411419
if (start < 0) {
412420
start = type._length + start
413421
}
@@ -443,6 +451,7 @@ export const typeListSlice = (type, start, end) => {
443451
* @function
444452
*/
445453
export const typeListToArray = type => {
454+
type.doc ?? warnPrematureAccess()
446455
const cs = []
447456
let n = type._start
448457
while (n !== null) {
@@ -492,6 +501,7 @@ export const typeListToArraySnapshot = (type, snapshot) => {
492501
export const typeListForEach = (type, f) => {
493502
let index = 0
494503
let n = type._start
504+
type.doc ?? warnPrematureAccess()
495505
while (n !== null) {
496506
if (n.countable && !n.deleted) {
497507
const c = n.content.getContent()
@@ -606,6 +616,7 @@ export const typeListForEachSnapshot = (type, f, snapshot) => {
606616
* @function
607617
*/
608618
export const typeListGet = (type, index) => {
619+
type.doc ?? warnPrematureAccess()
609620
const marker = findMarker(type, index)
610621
let n = type._start
611622
if (marker !== null) {
@@ -874,6 +885,7 @@ export const typeMapSet = (transaction, parent, key, value) => {
874885
* @function
875886
*/
876887
export const typeMapGet = (parent, key) => {
888+
parent.doc ?? warnPrematureAccess()
877889
const val = parent._map.get(key)
878890
return val !== undefined && !val.deleted ? val.content.getContent()[val.length - 1] : undefined
879891
}
@@ -890,6 +902,7 @@ export const typeMapGetAll = (parent) => {
890902
* @type {Object<string,any>}
891903
*/
892904
const res = {}
905+
parent.doc ?? warnPrematureAccess()
893906
parent._map.forEach((value, key) => {
894907
if (!value.deleted) {
895908
res[key] = value.content.getContent()[value.length - 1]
@@ -907,6 +920,7 @@ export const typeMapGetAll = (parent) => {
907920
* @function
908921
*/
909922
export const typeMapHas = (parent, key) => {
923+
parent.doc ?? warnPrematureAccess()
910924
const val = parent._map.get(key)
911925
return val !== undefined && !val.deleted
912926
}
@@ -957,10 +971,13 @@ export const typeMapGetAllSnapshot = (parent, snapshot) => {
957971
}
958972

959973
/**
960-
* @param {Map<string,Item>} map
974+
* @param {AbstractType<any> & { _map: Map<string, Item> }} type
961975
* @return {IterableIterator<Array<any>>}
962976
*
963977
* @private
964978
* @function
965979
*/
966-
export const createMapIterator = map => iterator.iteratorFilter(map.entries(), /** @param {any} entry */ entry => !entry[1].deleted)
980+
export const createMapIterator = type => {
981+
type.doc ?? warnPrematureAccess()
982+
return iterator.iteratorFilter(type._map.entries(), /** @param {any} entry */ entry => !entry[1].deleted)
983+
}

src/types/YArray.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
YArrayRefID,
1717
callTypeObservers,
1818
transact,
19+
warnPrematureAccess,
1920
ArraySearchMarker, UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, Doc, Transaction, Item // eslint-disable-line
2021
} from '../internals.js'
2122
import { typeListSlice } from './AbstractType.js'
@@ -104,6 +105,7 @@ export class YArray extends AbstractType {
104105
}
105106

106107
get length () {
108+
this.doc ?? warnPrematureAccess()
107109
return this._length
108110
}
109111

src/types/YMap.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
YMapRefID,
1414
callTypeObservers,
1515
transact,
16+
warnPrematureAccess,
1617
UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, Doc, Transaction, Item // eslint-disable-line
1718
} from '../internals.js'
1819

@@ -121,6 +122,7 @@ export class YMap extends AbstractType {
121122
* @return {Object<string,any>}
122123
*/
123124
toJSON () {
125+
this.doc ?? warnPrematureAccess()
124126
/**
125127
* @type {Object<string,MapType>}
126128
*/
@@ -140,7 +142,7 @@ export class YMap extends AbstractType {
140142
* @return {number}
141143
*/
142144
get size () {
143-
return [...createMapIterator(this._map)].length
145+
return [...createMapIterator(this)].length
144146
}
145147

146148
/**
@@ -149,7 +151,7 @@ export class YMap extends AbstractType {
149151
* @return {IterableIterator<string>}
150152
*/
151153
keys () {
152-
return iterator.iteratorMap(createMapIterator(this._map), /** @param {any} v */ v => v[0])
154+
return iterator.iteratorMap(createMapIterator(this), /** @param {any} v */ v => v[0])
153155
}
154156

155157
/**
@@ -158,7 +160,7 @@ export class YMap extends AbstractType {
158160
* @return {IterableIterator<MapType>}
159161
*/
160162
values () {
161-
return iterator.iteratorMap(createMapIterator(this._map), /** @param {any} v */ v => v[1].content.getContent()[v[1].length - 1])
163+
return iterator.iteratorMap(createMapIterator(this), /** @param {any} v */ v => v[1].content.getContent()[v[1].length - 1])
162164
}
163165

164166
/**
@@ -167,7 +169,7 @@ export class YMap extends AbstractType {
167169
* @return {IterableIterator<[string, MapType]>}
168170
*/
169171
entries () {
170-
return iterator.iteratorMap(createMapIterator(this._map), /** @param {any} v */ v => /** @type {any} */ ([v[0], v[1].content.getContent()[v[1].length - 1]]))
172+
return iterator.iteratorMap(createMapIterator(this), /** @param {any} v */ v => /** @type {any} */ ([v[0], v[1].content.getContent()[v[1].length - 1]]))
171173
}
172174

173175
/**
@@ -176,6 +178,7 @@ export class YMap extends AbstractType {
176178
* @param {function(MapType,string,YMap<MapType>):void} f A function to execute on every element of this YArray.
177179
*/
178180
forEach (f) {
181+
this.doc ?? warnPrematureAccess()
179182
this._map.forEach((item, key) => {
180183
if (!item.deleted) {
181184
f(item.content.getContent()[item.length - 1], key, this)

src/types/YText.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {
2626
typeMapGetAll,
2727
updateMarkerChanges,
2828
ContentType,
29+
warnPrematureAccess,
2930
ArraySearchMarker, UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, ID, Doc, Item, Snapshot, Transaction // eslint-disable-line
3031
} from '../internals.js'
3132

@@ -875,6 +876,7 @@ export class YText extends AbstractType {
875876
* @type {number}
876877
*/
877878
get length () {
879+
this.doc ?? warnPrematureAccess()
878880
return this._length
879881
}
880882

@@ -931,6 +933,7 @@ export class YText extends AbstractType {
931933
* @public
932934
*/
933935
toString () {
936+
this.doc ?? warnPrematureAccess()
934937
let str = ''
935938
/**
936939
* @type {Item|null}
@@ -1004,6 +1007,7 @@ export class YText extends AbstractType {
10041007
* @public
10051008
*/
10061009
toDelta (snapshot, prevSnapshot, computeYChange) {
1010+
this.doc ?? warnPrematureAccess()
10071011
/**
10081012
* @type{Array<any>}
10091013
*/

src/types/YXmlFragment.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
transact,
1818
typeListGet,
1919
typeListSlice,
20+
warnPrematureAccess,
2021
UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, Doc, ContentType, Transaction, Item, YXmlText, YXmlHook // eslint-disable-line
2122
} from '../internals.js'
2223

@@ -66,6 +67,7 @@ export class YXmlTreeWalker {
6667
*/
6768
this._currentNode = /** @type {Item} */ (root._start)
6869
this._firstCall = true
70+
root.doc ?? warnPrematureAccess()
6971
}
7072

7173
[Symbol.iterator] () {
@@ -177,6 +179,7 @@ export class YXmlFragment extends AbstractType {
177179
}
178180

179181
get length () {
182+
this.doc ?? warnPrematureAccess()
180183
return this._prelimContent === null ? this._length : this._prelimContent.length
181184
}
182185

0 commit comments

Comments
 (0)