@ckeditor/ckeditor5-watchdog 16.0.0 → 17.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/LICENSE.md +1 -1
- package/package.json +6 -6
- package/src/contextwatchdog.js +547 -0
- package/src/editorwatchdog.js +327 -0
- package/src/utils/areconnectedthroughproperties.js +80 -0
- package/src/utils/getsubnodes.js +89 -0
- package/src/watchdog.js +137 -282
package/src/watchdog.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Copyright (c) 2003-
|
|
2
|
+
* @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
|
|
3
3
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
4
|
*/
|
|
5
5
|
|
|
@@ -7,25 +7,21 @@
|
|
|
7
7
|
* @module watchdog/watchdog
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
/* globals
|
|
11
|
-
|
|
12
|
-
import mix from '@ckeditor/ckeditor5-utils/src/mix';
|
|
13
|
-
import ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';
|
|
14
|
-
import { throttle, cloneDeepWith, isElement } from 'lodash-es';
|
|
15
|
-
import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
|
|
16
|
-
import areConnectedThroughProperties from '@ckeditor/ckeditor5-utils/src/areconnectedthroughproperties';
|
|
10
|
+
/* globals window */
|
|
17
11
|
|
|
18
12
|
/**
|
|
19
|
-
*
|
|
13
|
+
* An abstract watchdog class that handles most of the error handling process and the state of the underlying component.
|
|
14
|
+
*
|
|
15
|
+
* See the {@glink features/watchdog Watchdog feature guide} to learn the rationale behind it and how to use it.
|
|
20
16
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
17
|
+
* @private
|
|
18
|
+
* @abstract
|
|
23
19
|
*/
|
|
24
20
|
export default class Watchdog {
|
|
25
21
|
/**
|
|
26
|
-
* @param {module:watchdog/watchdog~WatchdogConfig}
|
|
22
|
+
* @param {module:watchdog/watchdog~WatchdogConfig} config The watchdog plugin configuration.
|
|
27
23
|
*/
|
|
28
|
-
constructor( config
|
|
24
|
+
constructor( config ) {
|
|
29
25
|
/**
|
|
30
26
|
* An array of crashes saved as an object with the following properties:
|
|
31
27
|
*
|
|
@@ -43,46 +39,44 @@ export default class Watchdog {
|
|
|
43
39
|
this.crashes = [];
|
|
44
40
|
|
|
45
41
|
/**
|
|
46
|
-
* Specifies the state of the
|
|
42
|
+
* Specifies the state of the item watched by the watchdog. The state can be one of the following values:
|
|
47
43
|
*
|
|
48
|
-
* * `initializing`
|
|
49
|
-
* * `ready`
|
|
50
|
-
* * `crashed`
|
|
51
|
-
* depending on how many and how
|
|
52
|
-
* * `crashedPermanently`
|
|
53
|
-
* * `destroyed`
|
|
44
|
+
* * `initializing` – Before the first initialization, and after crashes, before the item is ready.
|
|
45
|
+
* * `ready` – A state when the user can interact with the item.
|
|
46
|
+
* * `crashed` – A state when an error occurs. It quickly changes to `initializing` or `crashedPermanently`
|
|
47
|
+
* depending on how many and how frequent errors have been caught recently.
|
|
48
|
+
* * `crashedPermanently` – A state when the watchdog stops reacting to errors and keeps the item it is watching crashed,
|
|
49
|
+
* * `destroyed` – A state when the item is manually destroyed by the user after calling `watchdog.destroy()`.
|
|
54
50
|
*
|
|
55
51
|
* @public
|
|
56
|
-
* @observable
|
|
57
52
|
* @member {'initializing'|'ready'|'crashed'|'crashedPermanently'|'destroyed'} #state
|
|
58
53
|
*/
|
|
59
|
-
this.
|
|
54
|
+
this.state = 'initializing';
|
|
60
55
|
|
|
61
56
|
/**
|
|
62
|
-
* @
|
|
57
|
+
* @protected
|
|
63
58
|
* @type {Number}
|
|
64
59
|
* @see module:watchdog/watchdog~WatchdogConfig
|
|
65
60
|
*/
|
|
66
61
|
this._crashNumberLimit = typeof config.crashNumberLimit === 'number' ? config.crashNumberLimit : 3;
|
|
67
62
|
|
|
68
63
|
/**
|
|
69
|
-
* Returns the result of `Date.now()` call. It can be overridden in tests to mock time as
|
|
70
|
-
* approaches like `sinon.useFakeTimers()`
|
|
64
|
+
* Returns the result of the `Date.now()` call. It can be overridden in tests to mock time as some popular
|
|
65
|
+
* approaches like `sinon.useFakeTimers()` do not work well with error handling.
|
|
71
66
|
*
|
|
72
67
|
* @protected
|
|
73
68
|
*/
|
|
74
69
|
this._now = Date.now;
|
|
75
70
|
|
|
76
71
|
/**
|
|
77
|
-
* @
|
|
72
|
+
* @protected
|
|
78
73
|
* @type {Number}
|
|
79
74
|
* @see module:watchdog/watchdog~WatchdogConfig
|
|
80
75
|
*/
|
|
81
76
|
this._minimumNonErrorTimePeriod = typeof config.minimumNonErrorTimePeriod === 'number' ? config.minimumNonErrorTimePeriod : 5000;
|
|
82
77
|
|
|
83
78
|
/**
|
|
84
|
-
* Checks if the event error comes from the
|
|
85
|
-
* and restarts the editor.
|
|
79
|
+
* Checks if the event error comes from the underlying item and restarts the item.
|
|
86
80
|
*
|
|
87
81
|
* @private
|
|
88
82
|
* @type {Function}
|
|
@@ -99,252 +93,171 @@ export default class Watchdog {
|
|
|
99
93
|
};
|
|
100
94
|
|
|
101
95
|
/**
|
|
102
|
-
*
|
|
103
|
-
* unless a new action happens in the meantime.
|
|
96
|
+
* The creation method.
|
|
104
97
|
*
|
|
105
|
-
* @
|
|
106
|
-
* @type {Function}
|
|
107
|
-
*/
|
|
108
|
-
this._throttledSave = throttle(
|
|
109
|
-
this._save.bind( this ),
|
|
110
|
-
typeof config.saveInterval === 'number' ? config.saveInterval : 5000
|
|
111
|
-
);
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* The current editor instance.
|
|
115
|
-
*
|
|
116
|
-
* @private
|
|
117
|
-
* @type {module:core/editor/editor~Editor}
|
|
118
|
-
*/
|
|
119
|
-
this._editor = null;
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* The editor creation method.
|
|
123
|
-
*
|
|
124
|
-
* @private
|
|
98
|
+
* @protected
|
|
125
99
|
* @member {Function} #_creator
|
|
126
100
|
* @see #setCreator
|
|
127
101
|
*/
|
|
128
102
|
|
|
129
103
|
/**
|
|
130
|
-
* The
|
|
104
|
+
* The destruction method.
|
|
131
105
|
*
|
|
132
|
-
* @
|
|
106
|
+
* @protected
|
|
133
107
|
* @member {Function} #_destructor
|
|
134
108
|
* @see #setDestructor
|
|
135
109
|
*/
|
|
136
|
-
this._destructor = editor => editor.destroy();
|
|
137
110
|
|
|
138
111
|
/**
|
|
139
|
-
* The
|
|
112
|
+
* The watched item.
|
|
140
113
|
*
|
|
141
|
-
* @
|
|
142
|
-
* @
|
|
114
|
+
* @abstract
|
|
115
|
+
* @protected
|
|
116
|
+
* @member {Object|undefined} #_item
|
|
143
117
|
*/
|
|
144
118
|
|
|
145
119
|
/**
|
|
146
|
-
* The
|
|
120
|
+
* The method responsible for restarting the watched item.
|
|
147
121
|
*
|
|
148
|
-
* @
|
|
149
|
-
* @
|
|
122
|
+
* @abstract
|
|
123
|
+
* @protected
|
|
124
|
+
* @method #_restart
|
|
150
125
|
*/
|
|
151
126
|
|
|
152
127
|
/**
|
|
153
|
-
*
|
|
128
|
+
* Traverses the error context and the watched item to find out whether the error should
|
|
129
|
+
* be handled by the given item.
|
|
154
130
|
*
|
|
155
|
-
* @
|
|
156
|
-
* @
|
|
131
|
+
* @abstract
|
|
132
|
+
* @protected
|
|
133
|
+
* @method #_isErrorComingFromThisItem
|
|
134
|
+
* @param {module:utils/ckeditorerror~CKEditorError} error
|
|
157
135
|
*/
|
|
158
136
|
|
|
159
137
|
/**
|
|
160
|
-
*
|
|
138
|
+
* A dictionary of event emitter listeners.
|
|
161
139
|
*
|
|
162
140
|
* @private
|
|
163
|
-
* @
|
|
141
|
+
* @type {Object.<String,Array.<Function>>}
|
|
164
142
|
*/
|
|
165
|
-
|
|
143
|
+
this._listeners = {};
|
|
166
144
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
get editor() {
|
|
174
|
-
return this._editor;
|
|
145
|
+
if ( !this._restart ) {
|
|
146
|
+
throw new Error(
|
|
147
|
+
'The Watchdog class was split into the abstract `Watchdog` class and the `EditorWatchdog` class. ' +
|
|
148
|
+
'Please, use `EditorWatchdog` if you have used the `Watchdog` class previously.'
|
|
149
|
+
);
|
|
150
|
+
}
|
|
175
151
|
}
|
|
176
152
|
|
|
177
153
|
/**
|
|
178
|
-
* Sets the function that is responsible for
|
|
179
|
-
* It expects a function that should return a promise.
|
|
154
|
+
* Sets the function that is responsible for creating watched items.
|
|
180
155
|
*
|
|
181
|
-
*
|
|
182
|
-
*
|
|
183
|
-
* @param {Function} creator
|
|
156
|
+
* @param {Function} creator A callback responsible for creating an item. Returns a promise
|
|
157
|
+
* that is resolved when the item is created.
|
|
184
158
|
*/
|
|
185
159
|
setCreator( creator ) {
|
|
186
160
|
this._creator = creator;
|
|
187
161
|
}
|
|
188
162
|
|
|
189
163
|
/**
|
|
190
|
-
* Sets the function that is responsible for
|
|
191
|
-
* Overrides the default destruction function, which destroys only the editor instance.
|
|
192
|
-
* It expects a function that should return a promise or `undefined`.
|
|
193
|
-
*
|
|
194
|
-
* watchdog.setDestructor( editor => {
|
|
195
|
-
* // Do something before the editor is destroyed.
|
|
164
|
+
* Sets the function that is responsible for destroying watched items.
|
|
196
165
|
*
|
|
197
|
-
*
|
|
198
|
-
*
|
|
199
|
-
* .then( () => {
|
|
200
|
-
* // Do something after the editor is destroyed.
|
|
201
|
-
* } );
|
|
202
|
-
* } );
|
|
203
|
-
*
|
|
204
|
-
* @param {Function} destructor
|
|
166
|
+
* @param {Function} destructor A callback that takes the item and returns the promise
|
|
167
|
+
* to the destroying process.
|
|
205
168
|
*/
|
|
206
169
|
setDestructor( destructor ) {
|
|
207
170
|
this._destructor = destructor;
|
|
208
171
|
}
|
|
209
172
|
|
|
210
173
|
/**
|
|
211
|
-
*
|
|
212
|
-
* the {@link module:watchdog/watchdog~Watchdog.for `Watchdog.for()`} helper.
|
|
213
|
-
*
|
|
214
|
-
* @param {HTMLElement|String|Object.<String|String>} elementOrData
|
|
215
|
-
* @param {module:core/editor/editorconfig~EditorConfig} [config]
|
|
216
|
-
*
|
|
217
|
-
* @returns {Promise}
|
|
174
|
+
* Destroys the watchdog and releases the resources.
|
|
218
175
|
*/
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
/**
|
|
222
|
-
* The watchdog's editor creator is not defined. Define it by using
|
|
223
|
-
* {@link module:watchdog/watchdog~Watchdog#setCreator `Watchdog#setCreator()`} or
|
|
224
|
-
* the {@link module:watchdog/watchdog~Watchdog.for `Watchdog.for()`} helper.
|
|
225
|
-
*
|
|
226
|
-
* @error watchdog-creator-not-defined
|
|
227
|
-
*/
|
|
228
|
-
throw new CKEditorError(
|
|
229
|
-
'watchdog-creator-not-defined: The watchdog\'s editor creator is not defined.',
|
|
230
|
-
null
|
|
231
|
-
);
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
this._elementOrData = elementOrData;
|
|
235
|
-
|
|
236
|
-
// Clone configuration because it might be shared within multiple watchdog instances. Otherwise,
|
|
237
|
-
// when an error occurs in one of these editors, the watchdog will restart all of them.
|
|
238
|
-
this._config = cloneDeepWith( config, value => {
|
|
239
|
-
// Leave DOM references.
|
|
240
|
-
return isElement( value ) ? value : undefined;
|
|
241
|
-
} );
|
|
242
|
-
|
|
243
|
-
return Promise.resolve()
|
|
244
|
-
.then( () => this._creator( elementOrData, this._config ) )
|
|
245
|
-
.then( editor => {
|
|
246
|
-
this._editor = editor;
|
|
247
|
-
|
|
248
|
-
window.addEventListener( 'error', this._boundErrorHandler );
|
|
249
|
-
window.addEventListener( 'unhandledrejection', this._boundErrorHandler );
|
|
250
|
-
|
|
251
|
-
this.listenTo( editor.model.document, 'change:data', this._throttledSave );
|
|
252
|
-
|
|
253
|
-
this._lastDocumentVersion = editor.model.document.version;
|
|
176
|
+
destroy() {
|
|
177
|
+
this._stopErrorHandling();
|
|
254
178
|
|
|
255
|
-
|
|
256
|
-
this.state = 'ready';
|
|
257
|
-
} );
|
|
179
|
+
this._listeners = {};
|
|
258
180
|
}
|
|
259
181
|
|
|
260
182
|
/**
|
|
261
|
-
*
|
|
262
|
-
*
|
|
183
|
+
* Starts listening to a specific event name by registering a callback that will be executed
|
|
184
|
+
* whenever an event with a given name fires.
|
|
185
|
+
*
|
|
186
|
+
* Note that this method differs from the CKEditor 5's default `EventEmitterMixin` implementation.
|
|
263
187
|
*
|
|
264
|
-
* @
|
|
188
|
+
* @param {String} eventName The event name.
|
|
189
|
+
* @param {Function} callback A callback which will be added to event listeners.
|
|
265
190
|
*/
|
|
266
|
-
|
|
267
|
-
this.
|
|
191
|
+
on( eventName, callback ) {
|
|
192
|
+
if ( !this._listeners[ eventName ] ) {
|
|
193
|
+
this._listeners[ eventName ] = [];
|
|
194
|
+
}
|
|
268
195
|
|
|
269
|
-
|
|
196
|
+
this._listeners[ eventName ].push( callback );
|
|
270
197
|
}
|
|
271
198
|
|
|
272
199
|
/**
|
|
273
|
-
*
|
|
200
|
+
* Stops listening to the specified event name by removing the callback from event listeners.
|
|
274
201
|
*
|
|
275
|
-
*
|
|
202
|
+
* Note that this method differs from the CKEditor 5's default `EventEmitterMixin` implementation.
|
|
203
|
+
*
|
|
204
|
+
* @param {String} eventName The event name.
|
|
205
|
+
* @param {Function} callback A callback which will be removed from event listeners.
|
|
276
206
|
*/
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
this.stopListening( this._editor.model.document, 'change:data', this._throttledSave );
|
|
282
|
-
|
|
283
|
-
// Save data if there is a remaining editor data change.
|
|
284
|
-
this._throttledSave.flush();
|
|
285
|
-
|
|
286
|
-
return Promise.resolve()
|
|
287
|
-
.then( () => this._destructor( this._editor ) )
|
|
288
|
-
.then( () => {
|
|
289
|
-
this._editor = null;
|
|
290
|
-
} );
|
|
207
|
+
off( eventName, callback ) {
|
|
208
|
+
this._listeners[ eventName ] = this._listeners[ eventName ]
|
|
209
|
+
.filter( cb => cb !== callback );
|
|
291
210
|
}
|
|
292
211
|
|
|
293
212
|
/**
|
|
294
|
-
*
|
|
295
|
-
* the moment of the crash.
|
|
213
|
+
* Fires an event with a given event name and arguments.
|
|
296
214
|
*
|
|
297
|
-
*
|
|
215
|
+
* Note that this method differs from the CKEditor 5's default `EventEmitterMixin` implementation.
|
|
216
|
+
*
|
|
217
|
+
* @protected
|
|
218
|
+
* @param {String} eventName The event name.
|
|
219
|
+
* @param {...*} args Event arguments.
|
|
298
220
|
*/
|
|
299
|
-
|
|
300
|
-
const
|
|
221
|
+
_fire( eventName, ...args ) {
|
|
222
|
+
const callbacks = this._listeners[ eventName ] || [];
|
|
301
223
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
if ( version === this._lastDocumentVersion ) {
|
|
305
|
-
return;
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
try {
|
|
309
|
-
this._data = this._getData();
|
|
310
|
-
this._lastDocumentVersion = version;
|
|
311
|
-
} catch ( err ) {
|
|
312
|
-
console.error(
|
|
313
|
-
err,
|
|
314
|
-
'An error happened during restoring editor data. ' +
|
|
315
|
-
'Editor will be restored from the previously saved data.'
|
|
316
|
-
);
|
|
224
|
+
for ( const callback of callbacks ) {
|
|
225
|
+
callback.apply( this, [ null, ...args ] );
|
|
317
226
|
}
|
|
318
227
|
}
|
|
319
228
|
|
|
320
229
|
/**
|
|
321
|
-
*
|
|
230
|
+
* Starts error handling by attaching global error handlers.
|
|
322
231
|
*
|
|
323
|
-
* @
|
|
324
|
-
* @returns {Object<String,String>}
|
|
232
|
+
* @protected
|
|
325
233
|
*/
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
for ( const rootName of this._editor.model.document.getRootNames() ) {
|
|
330
|
-
data[ rootName ] = this._editor.data.get( { rootName } );
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
return data;
|
|
234
|
+
_startErrorHandling() {
|
|
235
|
+
window.addEventListener( 'error', this._boundErrorHandler );
|
|
236
|
+
window.addEventListener( 'unhandledrejection', this._boundErrorHandler );
|
|
334
237
|
}
|
|
335
238
|
|
|
336
239
|
/**
|
|
337
|
-
*
|
|
338
|
-
* restarts the editor. It reacts to {@link module:utils/ckeditorerror~CKEditorError `CKEditorError` errors} only.
|
|
240
|
+
* Stops error handling by detaching global error handlers.
|
|
339
241
|
*
|
|
340
242
|
* @protected
|
|
243
|
+
*/
|
|
244
|
+
_stopErrorHandling() {
|
|
245
|
+
window.removeEventListener( 'error', this._boundErrorHandler );
|
|
246
|
+
window.removeEventListener( 'unhandledrejection', this._boundErrorHandler );
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Checks if an error comes from the watched item and restarts it.
|
|
251
|
+
* It reacts to {@link module:utils/ckeditorerror~CKEditorError `CKEditorError` errors} only.
|
|
252
|
+
*
|
|
253
|
+
* @private
|
|
341
254
|
* @fires error
|
|
342
255
|
* @param {Error} error Error.
|
|
343
|
-
* @param {ErrorEvent|PromiseRejectionEvent} evt
|
|
256
|
+
* @param {ErrorEvent|PromiseRejectionEvent} evt An error event.
|
|
344
257
|
*/
|
|
345
258
|
_handleError( error, evt ) {
|
|
346
259
|
// @if CK_DEBUG // if ( error.is && error.is( 'CKEditorError' ) && error.context === undefined ) {
|
|
347
|
-
// @if CK_DEBUG // console.warn( 'The error is missing its context and Watchdog cannot restart the proper
|
|
260
|
+
// @if CK_DEBUG // console.warn( 'The error is missing its context and Watchdog cannot restart the proper item.' );
|
|
348
261
|
// @if CK_DEBUG // }
|
|
349
262
|
|
|
350
263
|
if ( this._shouldReactToError( error ) ) {
|
|
@@ -359,22 +272,26 @@ export default class Watchdog {
|
|
|
359
272
|
date: this._now()
|
|
360
273
|
} );
|
|
361
274
|
|
|
362
|
-
this.
|
|
275
|
+
const causesRestart = this._shouldRestart();
|
|
276
|
+
|
|
363
277
|
this.state = 'crashed';
|
|
278
|
+
this._fire( 'stateChange' );
|
|
279
|
+
this._fire( 'error', { error, causesRestart } );
|
|
364
280
|
|
|
365
|
-
if (
|
|
281
|
+
if ( causesRestart ) {
|
|
366
282
|
this._restart();
|
|
367
283
|
} else {
|
|
368
284
|
this.state = 'crashedPermanently';
|
|
285
|
+
this._fire( 'stateChange' );
|
|
369
286
|
}
|
|
370
287
|
}
|
|
371
288
|
}
|
|
372
289
|
|
|
373
290
|
/**
|
|
374
|
-
* Checks whether
|
|
291
|
+
* Checks whether an error should be handled by the watchdog.
|
|
375
292
|
*
|
|
376
293
|
* @private
|
|
377
|
-
* @param {Error} error
|
|
294
|
+
* @param {Error} error An error that was caught by the error handling process.
|
|
378
295
|
*/
|
|
379
296
|
_shouldReactToError( error ) {
|
|
380
297
|
return (
|
|
@@ -382,21 +299,23 @@ export default class Watchdog {
|
|
|
382
299
|
error.is( 'CKEditorError' ) &&
|
|
383
300
|
error.context !== undefined &&
|
|
384
301
|
|
|
385
|
-
// In some cases the
|
|
302
|
+
// In some cases the watched item should not be restarted - e.g. during the item initialization.
|
|
386
303
|
// That's why the `null` was introduced as a correct error context which does cause restarting.
|
|
387
304
|
error.context !== null &&
|
|
388
305
|
|
|
389
306
|
// Do not react to errors if the watchdog is in states other than `ready`.
|
|
390
307
|
this.state === 'ready' &&
|
|
391
308
|
|
|
392
|
-
this.
|
|
309
|
+
this._isErrorComingFromThisItem( error )
|
|
393
310
|
);
|
|
394
311
|
}
|
|
395
312
|
|
|
396
313
|
/**
|
|
397
|
-
* Checks if the
|
|
314
|
+
* Checks if the watchdog should restart the underlying item.
|
|
315
|
+
*
|
|
316
|
+
* @private
|
|
398
317
|
*/
|
|
399
|
-
|
|
318
|
+
_shouldRestart() {
|
|
400
319
|
if ( this.crashes.length <= this._crashNumberLimit ) {
|
|
401
320
|
return true;
|
|
402
321
|
}
|
|
@@ -410,95 +329,31 @@ export default class Watchdog {
|
|
|
410
329
|
}
|
|
411
330
|
|
|
412
331
|
/**
|
|
413
|
-
*
|
|
414
|
-
* the state to `initializing`.
|
|
415
|
-
*
|
|
416
|
-
* @private
|
|
417
|
-
* @fires restart
|
|
418
|
-
* @returns {Promise}
|
|
419
|
-
*/
|
|
420
|
-
_restart() {
|
|
421
|
-
this.state = 'initializing';
|
|
422
|
-
|
|
423
|
-
return Promise.resolve()
|
|
424
|
-
.then( () => this._destroy() )
|
|
425
|
-
.catch( err => console.error( 'An error happened during the editor destructing.', err ) )
|
|
426
|
-
.then( () => {
|
|
427
|
-
if ( typeof this._elementOrData === 'string' ) {
|
|
428
|
-
return this.create( this._data, this._config );
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
const updatedConfig = Object.assign( {}, this._config, {
|
|
432
|
-
initialData: this._data
|
|
433
|
-
} );
|
|
434
|
-
|
|
435
|
-
return this.create( this._elementOrData, updatedConfig );
|
|
436
|
-
} )
|
|
437
|
-
.then( () => {
|
|
438
|
-
this.fire( 'restart' );
|
|
439
|
-
} );
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
/**
|
|
443
|
-
* Traverses both structures to find out whether the error context is connected
|
|
444
|
-
* with the current editor.
|
|
445
|
-
*
|
|
446
|
-
* @private
|
|
447
|
-
* @param {module:utils/ckeditorerror~CKEditorError} error
|
|
448
|
-
*/
|
|
449
|
-
_isErrorComingFromThisEditor( error ) {
|
|
450
|
-
return areConnectedThroughProperties( this._editor, error.context );
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
/**
|
|
454
|
-
* A shorthand method for creating an instance of the watchdog. For the full usage, see the
|
|
455
|
-
* {@link ~Watchdog `Watchdog` class description}.
|
|
456
|
-
*
|
|
457
|
-
* Usage:
|
|
458
|
-
*
|
|
459
|
-
* const watchdog = Watchdog.for( ClassicEditor );
|
|
460
|
-
*
|
|
461
|
-
* watchdog.create( elementOrData, config );
|
|
462
|
-
*
|
|
463
|
-
* @param {*} Editor The editor class.
|
|
464
|
-
* @param {module:watchdog/watchdog~WatchdogConfig} [watchdogConfig] The watchdog plugin configuration.
|
|
465
|
-
*/
|
|
466
|
-
static for( Editor, watchdogConfig ) {
|
|
467
|
-
const watchdog = new Watchdog( watchdogConfig );
|
|
468
|
-
|
|
469
|
-
watchdog.setCreator( ( elementOrData, config ) => Editor.create( elementOrData, config ) );
|
|
470
|
-
|
|
471
|
-
return watchdog;
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
/**
|
|
475
|
-
* Fired when a new {@link module:utils/ckeditorerror~CKEditorError `CKEditorError`} error connected to the watchdog editor occurs
|
|
332
|
+
* Fired when a new {@link module:utils/ckeditorerror~CKEditorError `CKEditorError`} error connected to the watchdog instance occurs
|
|
476
333
|
* and the watchdog will react to it.
|
|
477
334
|
*
|
|
478
|
-
*
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
/**
|
|
482
|
-
* Fired after the watchdog restarts the error in case of a crash.
|
|
335
|
+
* watchdog.on( 'error', ( evt, { error, causesRestart } ) => {
|
|
336
|
+
* console.log( 'An error occurred.' );
|
|
337
|
+
* } );
|
|
483
338
|
*
|
|
484
|
-
* @event
|
|
339
|
+
* @event error
|
|
485
340
|
*/
|
|
486
341
|
}
|
|
487
342
|
|
|
488
|
-
mix( Watchdog, ObservableMixin );
|
|
489
|
-
|
|
490
343
|
/**
|
|
491
344
|
* The watchdog plugin configuration.
|
|
492
345
|
*
|
|
493
346
|
* @typedef {Object} WatchdogConfig
|
|
494
347
|
*
|
|
495
|
-
* @property {Number} [crashNumberLimit=3] A threshold specifying the number of
|
|
496
|
-
* when the watchdog stops restarting the
|
|
497
|
-
* After this limit is reached and the time between last errors is shorter than `minimumNonErrorTimePeriod
|
|
498
|
-
* the watchdog changes its state to `crashedPermanently` and it stops restarting the
|
|
499
|
-
*
|
|
500
|
-
*
|
|
501
|
-
*
|
|
502
|
-
*
|
|
503
|
-
*
|
|
348
|
+
* @property {Number} [crashNumberLimit=3] A threshold specifying the number of watched item crashes
|
|
349
|
+
* when the watchdog stops restarting the item in case of errors.
|
|
350
|
+
* After this limit is reached and the time between the last errors is shorter than `minimumNonErrorTimePeriod`,
|
|
351
|
+
* the watchdog changes its state to `crashedPermanently` and it stops restarting the item. This prevents an infinite restart loop.
|
|
352
|
+
*
|
|
353
|
+
* @property {Number} [minimumNonErrorTimePeriod=5000] An average number of milliseconds between the last watched item errors
|
|
354
|
+
* (defaults to 5000). When the period of time between errors is lower than that and the `crashNumberLimit` is also reached,
|
|
355
|
+
* the watchdog changes its state to `crashedPermanently` and it stops restarting the item. This prevents an infinite restart loop.
|
|
356
|
+
*
|
|
357
|
+
* @property {Number} [saveInterval=5000] A minimum number of milliseconds between saving the editor data internally (defaults to 5000).
|
|
358
|
+
* Note that for large documents this might impact the editor performance.
|
|
504
359
|
*/
|