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

Reply via email to