aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorRichard Gibson <richard.gibson@gmail.com>2017-04-24 12:39:25 -0400
committerGitHub <noreply@github.com>2017-04-24 12:39:25 -0400
commita16339b8933f115da3661f3d3f64854c3fa60bdc (patch)
treee6903c05f9949bab4ca524da7d16ed96c8fb936c /test
parent1d2df772b4d6e5dbf91df6e75f4a1809f7879ab0 (diff)
downloadjquery-a16339b8933f115da3661f3d3f64854c3fa60bdc.tar.gz
jquery-a16339b8933f115da3661f3d3f64854c3fa60bdc.zip
Core: Update isFunction to handle unusual-@@toStringTag input
Ref gh-3597 Fixes gh-3600 Fixes gh-3596 Closes gh-3617
Diffstat (limited to 'test')
-rw-r--r--test/unit/core.js64
-rw-r--r--test/unit/deferred.js44
2 files changed, 100 insertions, 8 deletions
diff --git a/test/unit/core.js b/test/unit/core.js
index adccfb58f..c717711da 100644
--- a/test/unit/core.js
+++ b/test/unit/core.js
@@ -406,7 +406,7 @@ QUnit[ "assign" in Object ? "test" : "skip" ]( "isPlainObject(Object.assign(...)
QUnit.test( "isFunction", function( assert ) {
- assert.expect( 19 );
+ assert.expect( 20 );
var mystr, myarr, myfunction, fn, obj, nodes, first, input, a;
@@ -439,9 +439,11 @@ QUnit.test( "isFunction", function( assert ) {
fn = function() {};
assert.ok( jQuery.isFunction( fn ), "Normal Function" );
+ assert.notOk( jQuery.isFunction( Object.create( fn ) ), "custom Function subclass" );
+
obj = document.createElement( "object" );
- // Firefox says this is a function
+ // Some versions of Firefox and Chrome say this is a function
assert.ok( !jQuery.isFunction( obj ), "Object Element" );
// Since 1.3, this isn't supported (#2968)
@@ -491,6 +493,64 @@ QUnit.test( "isFunction", function( assert ) {
} );
} );
+QUnit.test( "isFunction(cross-realm function)", function( assert ) {
+ assert.expect( 1 );
+
+ var iframe, doc,
+ done = assert.async();
+
+ // Functions from other windows should be matched
+ Globals.register( "iframeDone" );
+ window.iframeDone = function( fn, detail ) {
+ window.iframeDone = undefined;
+ assert.ok( jQuery.isFunction( fn ), "cross-realm function" +
+ ( detail ? " - " + detail : "" ) );
+ done();
+ };
+
+ iframe = jQuery( "#qunit-fixture" )[ 0 ].appendChild( document.createElement( "iframe" ) );
+ doc = iframe.contentDocument || iframe.contentWindow.document;
+ doc.open();
+ doc.write( "<body onload='window.parent.iframeDone( function() {} );'>" );
+ doc.close();
+} );
+
+supportjQuery.each(
+ {
+ GeneratorFunction: "function*() {}",
+ AsyncFunction: "async function() {}"
+ },
+ function( subclass, source ) {
+ var fn;
+ try {
+ fn = Function( "return " + source )();
+ } catch ( e ) {}
+
+ QUnit[ fn ? "test" : "skip" ]( "isFunction(" + subclass + ")",
+ function( assert ) {
+ assert.expect( 1 );
+
+ assert.equal( jQuery.isFunction( fn ), true, source );
+ }
+ );
+ }
+);
+
+QUnit[ typeof Symbol === "function" && Symbol.toStringTag ? "test" : "skip" ](
+ "isFunction(custom @@toStringTag)",
+ function( assert ) {
+ assert.expect( 2 );
+
+ var obj = {},
+ fn = function() {};
+ obj[ Symbol.toStringTag ] = "Function";
+ fn[ Symbol.toStringTag ] = "Object";
+
+ assert.equal( jQuery.isFunction( obj ), false, "function-mimicking object" );
+ assert.equal( jQuery.isFunction( fn ), true, "object-mimicking function" );
+ }
+);
+
QUnit.test( "isNumeric", function( assert ) {
assert.expect( 43 );
diff --git a/test/unit/deferred.js b/test/unit/deferred.js
index 426af4b5f..f64d4fec8 100644
--- a/test/unit/deferred.js
+++ b/test/unit/deferred.js
@@ -526,9 +526,10 @@ QUnit.test( "jQuery.Deferred.then - spec compatibility", function( assert ) {
assert.expect( 1 );
- var done = assert.async();
+ var done = assert.async(),
+ defer = jQuery.Deferred();
- var defer = jQuery.Deferred().done( function() {
+ defer.done( function() {
setTimeout( done );
throw new Error();
} );
@@ -542,6 +543,26 @@ QUnit.test( "jQuery.Deferred.then - spec compatibility", function( assert ) {
} catch ( _ ) {}
} );
+QUnit[ typeof Symbol === "function" && Symbol.toStringTag ? "test" : "skip" ](
+ "jQuery.Deferred.then - IsCallable determination (gh-3596)",
+ function( assert ) {
+
+ assert.expect( 1 );
+
+ var done = assert.async(),
+ defer = jQuery.Deferred();
+
+ function faker() {
+ assert.ok( true, "handler with non-'Function' @@toStringTag gets invoked" );
+ }
+ faker[ Symbol.toStringTag ] = "String";
+
+ defer.then( faker ).then( done );
+
+ defer.resolve();
+ }
+);
+
// Test fails in IE9 but is skipped there because console is not active
QUnit[ window.console ? "test" : "skip" ]( "jQuery.Deferred.exceptionHook", function( assert ) {
@@ -861,8 +882,16 @@ QUnit.test( "jQuery.when(nonThenable) - like Promise.resolve", function( assert
QUnit.test( "jQuery.when(thenable) - like Promise.resolve", function( assert ) {
"use strict";
- var CASES = 16,
- slice = [].slice,
+ var customToStringThen = {
+ then: function( onFulfilled ) {
+ onFulfilled();
+ }
+ };
+ if ( typeof Symbol === "function" ) {
+ customToStringThen.then[ Symbol.toStringTag ] = "String";
+ }
+
+ var slice = [].slice,
sentinel = { context: "explicit" },
eventuallyFulfilled = jQuery.Deferred().notify( true ),
eventuallyRejected = jQuery.Deferred().notify( true ),
@@ -870,6 +899,7 @@ QUnit.test( "jQuery.when(thenable) - like Promise.resolve", function( assert ) {
secondaryRejected = jQuery.Deferred().resolve( eventuallyRejected ),
inputs = {
promise: Promise.resolve( true ),
+ customToStringThen: customToStringThen,
rejectedPromise: Promise.reject( false ),
deferred: jQuery.Deferred().resolve( true ),
eventuallyFulfilled: eventuallyFulfilled,
@@ -894,6 +924,7 @@ QUnit.test( "jQuery.when(thenable) - like Promise.resolve", function( assert ) {
},
willSucceed = {
promise: [ true ],
+ customToStringThen: [],
deferred: [ true ],
eventuallyFulfilled: [ true ],
secondaryFulfilled: [ true ],
@@ -912,14 +943,15 @@ QUnit.test( "jQuery.when(thenable) - like Promise.resolve", function( assert ) {
rejectedDeferredWith: [ false ],
multiRejectedDeferredWith: [ "baz", "quux" ]
},
+ numCases = Object.keys( willSucceed ).length + Object.keys( willError ).length,
// Support: Android 4.0 only
// Strict mode functions invoked without .call/.apply get global-object context
defaultContext = ( function getDefaultContext() { return this; } ).call(),
- done = assert.async( CASES * 2 );
+ done = assert.async( numCases * 2 );
- assert.expect( CASES * 4 );
+ assert.expect( numCases * 4 );
jQuery.each( inputs, function( message, value ) {
var code = "jQuery.when( " + message + " )",