Esanders has uploaded a new change for review. https://gerrit.wikimedia.org/r/206374
Change subject: Add unregister method to ModelRegistry ...................................................................... Add unregister method to ModelRegistry Depends on Id9a5b3ecd7 in oojs core. Change-Id: I81750e7763109f530a6435dbcd7f74379450a565 --- M src/dm/ve.dm.ModelRegistry.js M tests/dm/ve.dm.ModelRegistry.test.js 2 files changed, 105 insertions(+), 10 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/74/206374/1 diff --git a/src/dm/ve.dm.ModelRegistry.js b/src/dm/ve.dm.ModelRegistry.js index 95356ee..2f394b2 100644 --- a/src/dm/ve.dm.ModelRegistry.js +++ b/src/dm/ve.dm.ModelRegistry.js @@ -56,31 +56,58 @@ */ function addType( obj ) { var i, len, + keys = Array.prototype.slice.call( arguments, 1, -1 ), + value = arguments[arguments.length - 1], o = obj; - for ( i = 1, len = arguments.length - 2; i < len; i++ ) { - if ( o[arguments[i]] === undefined ) { - o[arguments[i]] = {}; + + for ( i = 0, len = keys.length - 1; i < len; i++ ) { + if ( o[keys[i]] === undefined ) { + o[keys[i]] = {}; } - o = o[arguments[i]]; + o = o[keys[i]]; } - if ( o[arguments[i]] === undefined ) { - o[arguments[i]] = []; + o[keys[i]] = o[keys[i]] || []; + o[keys[i]].unshift( value ); + } + + /** + * Helper function for unregister(). + * + * Same arguments as addType, except removes the type from the list. + * + * @private + * @param {Object} obj Object the array resides in + * @param {string...} keys + * @param {Mixed} value to remove + */ + function removeType( obj ) { + var index, + keys = Array.prototype.slice.call( arguments, 1, -1 ), + value = arguments[arguments.length - 1], + arr = ve.getProp.apply( obj, [ obj ].concat( keys ) ); + + if ( arr ) { + index = arr.indexOf( value ); + if ( index !== -1 ) { + arr.splice( index, 1 ); + } } - o[arguments[i]].unshift( arguments[i + 1] ); } /* Public methods */ /** * Register a model type. - * @param {string} name Symbolic name for the model + * * @param {ve.dm.Model} constructor Subclass of ve.dm.Model + * @throws Model names must be strings and must not be empty * @throws Models must be subclasses of ve.dm.Model * @throws No factory associated with this ve.dm.Model subclass */ ve.dm.ModelRegistry.prototype.register = function ( constructor ) { var i, j, tags, types, name = constructor.static && constructor.static.name; + if ( typeof name !== 'string' || name === '' ) { throw new Error( 'Model names must be strings and must not be empty' ); } @@ -98,8 +125,9 @@ } else { throw new Error( 'No factory associated with this ve.dm.Model subclass' ); } + // Parent method - OO.Registry.prototype.register.call( this, name, constructor ); + ve.dm.ModelRegistry.super.prototype.register.call( this, name, constructor ); tags = constructor.static.matchTagNames === null ? [ '' ] : @@ -130,6 +158,67 @@ }; /** + * Unregister a model type. + * + * @param {ve.dm.Model} constructor Subclass of ve.dm.Model + * @throws Model names must be strings and must not be empty + * @throws Models must be subclasses of ve.dm.Model + * @throws No factory associated with this ve.dm.Model subclass + */ + ve.dm.ModelRegistry.prototype.unregister = function ( constructor ) { + var i, j, tags, types, + name = constructor.static && constructor.static.name; + + if ( typeof name !== 'string' || name === '' ) { + throw new Error( 'Model names must be strings and must not be empty' ); + } + if ( !( constructor.prototype instanceof ve.dm.Model ) ) { + throw new Error( 'Models must be subclasses of ve.dm.Model' ); + } + + // Unregister the model from the right factory + if ( constructor.prototype instanceof ve.dm.Annotation ) { + ve.dm.annotationFactory.unregister( constructor ); + } else if ( constructor.prototype instanceof ve.dm.Node ) { + ve.dm.nodeFactory.unregister( constructor ); + } else if ( constructor.prototype instanceof ve.dm.MetaItem ) { + ve.dm.metaItemFactory.unregister( constructor ); + } else { + throw new Error( 'No factory associated with this ve.dm.Model subclass' ); + } + + // Parent method + ve.dm.ModelRegistry.super.prototype.unregister.call( this, name ); + + tags = constructor.static.matchTagNames === null ? + [ '' ] : + constructor.static.matchTagNames; + types = constructor.static.getMatchRdfaTypes() === null ? + [ '' ] : + constructor.static.getMatchRdfaTypes(); + + for ( i = 0; i < tags.length; i++ ) { + // +!!foo is a shorter equivalent of Number( Boolean( foo ) ) or foo ? 1 : 0 + removeType( this.modelsByTag, +!!constructor.static.matchFunction, + tags[i], name + ); + } + for ( i = 0; i < types.length; i++ ) { + if ( types[i] instanceof RegExp ) { + removeType( this.modelsWithTypeRegExps, +!!constructor.static.matchFunction, name ); + } else { + for ( j = 0; j < tags.length; j++ ) { + removeType( this.modelsByTypeAndTag, + +!!constructor.static.matchFunction, types[i], tags[j], name + ); + } + } + } + + delete this.registrationOrder[name]; + }; + + /** * Register an extension-specific RDFa type or set of types. Unrecognized extension-specific types * skip non-type matches and are alienated. * diff --git a/tests/dm/ve.dm.ModelRegistry.test.js b/tests/dm/ve.dm.ModelRegistry.test.js index 964624c..886de58 100644 --- a/tests/dm/ve.dm.ModelRegistry.test.js +++ b/tests/dm/ve.dm.ModelRegistry.test.js @@ -100,7 +100,7 @@ /* Tests */ -QUnit.test( 'matchElement', 23, function ( assert ) { +QUnit.test( 'matchElement', 24, function ( assert ) { var registry = new ve.dm.ModelRegistry(), element = document.createElement( 'a' ); @@ -170,4 +170,10 @@ element.setAttribute( 'rel', 'ext:abbr' ); element.setAttribute( 'typeof', 'foo' ); assert.deepEqual( registry.matchElement( element ), null, 'Types split over two attributes still breaks match' ); + + registry.unregister( ve.dm.StubAbbrNode ); + element.removeAttribute( 'typeof' ); + element.setAttribute( 'rel', 'ext:abbr' ); + assert.deepEqual( registry.matchElement( element ), 'stub-regexp', 'RegExp type match after string match is unregistered' ); + } ); -- To view, visit https://gerrit.wikimedia.org/r/206374 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I81750e7763109f530a6435dbcd7f74379450a565 Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Esanders <esand...@wikimedia.org> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits