Selaa lähdekoodia

Fixed: Weak DOM Node check in DOMEmitterMixin fails for Nodes from different window scopes.

Aleksander Nowodzinski 10 vuotta sitten
vanhempi
sitoutus
0b707ac7f3

+ 11 - 2
packages/ckeditor5-engine/src/ui/domemittermixin.js

@@ -175,7 +175,7 @@ const DOMEmitterMixin = extend( {}, EmitterMixin, {
 
 		// Check if emitter is an instance of DOM Node. If so, replace the argument with
 		// corresponding ProxyEmitter (or create one if not existing).
-		if ( emitter instanceof Node ) {
+		if ( isDomNode( emitter ) ) {
 			args[ 0 ] = this._getProxyEmitter( emitter ) || new ProxyEmitter( emitter );
 		}
 
@@ -203,7 +203,7 @@ const DOMEmitterMixin = extend( {}, EmitterMixin, {
 		const emitter = args[ 0 ];
 
 		// Check if emitter is an instance of DOM Node. If so, replace the argument with corresponding ProxyEmitter.
-		if ( emitter instanceof Node ) {
+		if ( isDomNode( emitter ) ) {
 			let proxy = this._getProxyEmitter( emitter );
 
 			if ( proxy ) {
@@ -254,6 +254,15 @@ function getNodeUID( node ) {
 	return node[ 'data-ck-expando' ] || ( node[ 'data-ck-expando' ] = utils.uid() );
 }
 
+// Checks if given node is native DOM Node.
+//
+// @private
+// @param {Node} node
+// @return {Boolean} True when native DOM Node.
+function isDomNode( node ) {
+	return node && node.nodeType && node.nodeName;
+}
+
 /**
  * Interface representing classes which mix in {@link core.ui.DOMEmitter}.
  *

+ 31 - 0
packages/ckeditor5-engine/tests/ui/domemittermixin.js

@@ -57,6 +57,20 @@ describe( 'listenTo', () => {
 
 		sinon.assert.calledOnce( spy );
 	} );
+
+	// #187
+	it( 'should work for DOM Nodes belonging to another window', () => {
+		const spy = testUtils.sinon.spy();
+		const iframe = document.createElement( 'iframe' );
+
+		document.body.appendChild( iframe );
+		const iframeNode = iframe.contentWindow.document.createElement( 'div' );
+
+		domEmitter.listenTo( iframeNode, 'test', spy );
+		iframeNode.dispatchEvent( new Event( 'test' ) );
+
+		sinon.assert.calledOnce( spy );
+	} );
 } );
 
 describe( 'stopListening', () => {
@@ -354,4 +368,21 @@ describe( 'stopListening', () => {
 		sinon.assert.calledTwice( spy2 );
 		sinon.assert.calledTwice( spy3 );
 	} );
+
+	// #187
+	it( 'should work for DOM Nodes belonging to another window', () => {
+		const spy = testUtils.sinon.spy();
+		const iframe = document.createElement( 'iframe' );
+
+		document.body.appendChild( iframe );
+		const iframeNode = iframe.contentWindow.document.createElement( 'div' );
+
+		domEmitter.listenTo( iframeNode, 'test', spy );
+
+		iframeNode.dispatchEvent( new Event( 'test' ) );
+		domEmitter.stopListening( iframeNode );
+		iframeNode.dispatchEvent( new Event( 'test' ) );
+
+		sinon.assert.calledOnce( spy );
+	} );
 } );