Krinkle has uploaded a new change for review. ( 
https://gerrit.wikimedia.org/r/346491 )

Change subject: util: Simplify isPlainObject and fix two false positives
......................................................................

util: Simplify isPlainObject and fix two false positives

We already covered the following cases properly:
* Objects that inherited from any user class or built-in class
  other than Object.prototype.  (= not plain)
* Objects that inherited from another plain object. (= not plain)
* Objects created that inherit Object.prototype via 'new Object()'
  or literal '{}'. (= plain)
* Objects created without inheritance via Object.create(null)
  (= plain)

The following cases were broken, however:

* Objects that inherit an object that has no inheritance.
  > var defaults = Object.create(null);
  > // assign props to defaults
  > options = Object.create(defaults);
  This is not plain, but was wrongly detected as plain.
  Also fixed in jQuery 3.

* Objects that inherit an object that is plain.
  > var defaults = { /* .. */ };
  > options = Object.create(defaults);
  This is not plain, but was wrongly detected as plain.
  Also fixed in jQuery 3.

Also:
* Remove IE8 compat code that is now redundant.
* Upgrade from jQuery 1 to jQuery 3 must be before this
  commit as otherwise the new unit tests will fail for
  oojs.jquery.js.

Change-Id: Ibc67bbfaa35e88abcc68e09977bb7c390b1fe388
---
M src/util.js
M tests/unit/util.test.js
2 files changed, 25 insertions(+), 25 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/oojs/core refs/changes/91/346491/1

diff --git a/src/util.js b/src/util.js
index 349436f..5fdafb2 100644
--- a/src/util.js
+++ b/src/util.js
@@ -8,25 +8,20 @@
  * @return {boolean}
  */
 oo.isPlainObject = function ( obj ) {
-       // Any object or value whose internal [[Class]] property is not 
"[object Object]"
-       // Support IE8: Explicitly filter out DOM nodes
-       // Support IE8: Explicitly filter out Window object (needs loose 
comparison)
-       // eslint-disable-next-line eqeqeq
-       if ( !obj || toString.call( obj ) !== '[object Object]' || obj.nodeType 
|| ( obj != null && obj == obj.window ) ) {
+       var proto;
+
+       // Optimise for common case where internal [[Class]] property is not 
"Object"
+       if ( !obj || toString.call( obj ) !== '[object Object]' ) {
                return false;
        }
 
-       // The try/catch suppresses exceptions thrown when attempting to access
-       // the "constructor" property of certain host objects such as Location
-       // in Firefox < 20 (https://bugzilla.mozilla.org/814622)
-       try {
-               if ( obj.constructor &&
-                               !hasOwn.call( obj.constructor.prototype, 
'isPrototypeOf' ) ) {
-                       return false;
-               }
-       } catch ( e ) {
-               return false;
+       proto = Object.getPrototypeOf( obj );
+
+       // Objects without prototype (e.g., `Object.create( null )`) are 
considered plain
+       if ( !proto ) {
+               return true;
        }
 
-       return true;
+       // The 'isPrototypeOf' method is set on Object.prototype.
+       return hasOwn.call( proto, 'isPrototypeOf' );
 };
diff --git a/tests/unit/util.test.js b/tests/unit/util.test.js
index 3ae382d..0e505ae 100644
--- a/tests/unit/util.test.js
+++ b/tests/unit/util.test.js
@@ -3,19 +3,24 @@
        QUnit.module( 'util' );
 
        QUnit.test( 'isPlainObject', function ( assert ) {
+               var obj;
                function Thing() {}
 
                // Plain objects
                assert.strictEqual( oo.isPlainObject( {} ), true, 'empty plain 
object' );
                assert.strictEqual( oo.isPlainObject( { a: 1 } ), true, 
'non-empty plain object' );
-               if ( !Object.create ) {
-                       // We test Object.create(null) when the environment 
supports it for modern browsers
-                       // However Object.create(null) itself is not an OOjs 
feature and if the environment
-                       // doesn't support it, we skip the test.
-                       assert.strictEqual( true, true, '[skipped] Objects with 
no prototype from Object.create( null )' );
-               } else {
-                       assert.strictEqual( oo.isPlainObject( Object.create( 
null ) ), true, 'Objects with no prototype from Object.create( null )' );
-               }
+               assert.strictEqual( oo.isPlainObject( Object.create( null ) ), 
true, 'empty object with no prototype, via Object.create( null )' );
+               obj = Object.create( null );
+               obj.foo = true;
+               assert.strictEqual( oo.isPlainObject( obj ), true, 'non-empty 
object with no prototype' );
+
+               // Non-plain objects (any inheritance other than 
Object.prototype is not plain)
+               obj = Object.create( Object.create( null ) );
+               assert.strictEqual( oo.isPlainObject( obj ), false, 'empty 
object inheriting from object with no prototype' );
+               obj.foo = true;
+               assert.strictEqual( oo.isPlainObject( obj ), false, 'non-empty 
object inheriting from object with no prototype' );
+               obj = Object.create( {} );
+               assert.strictEqual( oo.isPlainObject( obj ), false, 'object 
inheriting from plain object' );
 
                // Primitives
                assert.strictEqual( oo.isPlainObject( undefined ), false, 
'undefined' );
@@ -89,7 +94,7 @@
                        } catch ( e ) {
                                threw = true;
                        }
-                       assert.strictEqual( threw, false, 'native host object' 
);
+                       assert.strictEqual( threw, false, 'native Location 
object' );
                } );
        }
 

-- 
To view, visit https://gerrit.wikimedia.org/r/346491
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ibc67bbfaa35e88abcc68e09977bb7c390b1fe388
Gerrit-PatchSet: 1
Gerrit-Project: oojs/core
Gerrit-Branch: master
Gerrit-Owner: Krinkle <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to