浏览代码

Introduces utils.mix.

Piotrek Koszuliński 10 年之前
父节点
当前提交
03705b53eb
共有 2 个文件被更改,包括 74 次插入0 次删除
  1. 24 0
      packages/ckeditor5-utils/src/utils.js
  2. 50 0
      packages/ckeditor5-utils/tests/utils.js

+ 24 - 0
packages/ckeditor5-utils/src/utils.js

@@ -107,6 +107,30 @@ const utils = {
 		}
 
 		return null;
+	},
+
+	/**
+	 * Copies enumerable properties from the objects given as 2nd+ parameters to the
+	 * prototype of the base class.
+	 *
+	 *		class SpecificEditor extends utils.mix( Editor, SomeMixin1, SomeMixin2 ) {
+	 *			...
+	 *		}
+	 *
+	 * @param {Function} [baseClass] Class which prototype will be extended.
+	 * @param {Object} [...mixins] Objects from which to get properties.
+	 */
+	mix( baseClass, ...mixins ) {
+		mixins.forEach( ( mixin ) => {
+			Object.keys( mixin ).forEach( ( key ) => {
+				Object.defineProperty( baseClass.prototype, key, {
+					enumerable: false,
+					configurable: true,
+					writable: true,
+					value: mixin[ key ]
+				} );
+			} );
+		} );
 	}
 };
 

+ 50 - 0
packages/ckeditor5-utils/tests/utils.js

@@ -143,4 +143,54 @@ describe( 'utils', () => {
 			yield 33;
 		}
 	} );
+
+	describe( 'mix', () => {
+		const MixinA = {
+			a() {
+				return 'a';
+			}
+		};
+		const MixinB = {
+			b() {
+				return 'b';
+			}
+		};
+
+		it( 'mixes 2nd+ param\'s properties into the first class', () => {
+			class Foo {}
+			utils.mix( Foo, MixinA, MixinB );
+
+			expect( Foo ).to.not.have.property( 'a' );
+			expect( Foo ).to.not.have.property( 'b' );
+
+			const foo = new Foo();
+
+			expect( foo.a() ).to.equal( 'a' );
+			expect( foo.b() ).to.equal( 'b' );
+		} );
+
+		it( 'does not break the instanceof operator', () => {
+			class Foo {}
+			utils.mix( Foo, MixinA );
+
+			let foo = new Foo();
+
+			expect( foo ).to.be.instanceof( Foo );
+		} );
+
+		it( 'defines properties with the same descriptors as native classes', () => {
+			class Foo {
+				foo() {}
+			}
+
+			utils.mix( Foo, MixinA );
+
+			const actualDescriptor = Object.getOwnPropertyDescriptor( Foo.prototype, 'a' );
+			const expectedDescriptor = Object.getOwnPropertyDescriptor( Foo.prototype, 'foo' );
+
+			expect( actualDescriptor ).to.have.property( 'writable', expectedDescriptor.writable );
+			expect( actualDescriptor ).to.have.property( 'enumerable', expectedDescriptor.enumerable );
+			expect( actualDescriptor ).to.have.property( 'configurable', expectedDescriptor.configurable );
+		} );
+	} );
 } );