New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Core: Update isFunction to handle unusual-@@toStringTag input #3617

Merged
merged 11 commits into from Apr 24, 2017

Conversation

Projects
None yet
6 participants
@gibson042
Member

gibson042 commented Apr 8, 2017

Summary

Generators and async functions are still functions (cf. ECMAScript Language Specification), and we can recognize them with typeof (but still need a guard to reject elements).

Fixes gh-3600
Fixes gh-3596

Checklist

@mention-bot

This comment has been minimized.

mention-bot commented Apr 8, 2017

@gibson042, thanks for your PR! By analyzing the history of the files in this pull request, we identified @markelog, @mgol and @jeresig to be potential reviewers.

doc.write( "<body onload='window.parent.iframeDone( function() {} );'>" );
doc.close();
} catch ( e ) {
window.iframeDone( function() {}, "iframes not supported" );

This comment has been minimized.

@markelog

markelog Apr 8, 2017

Member

How this could happen?

This comment has been minimized.

@gibson042

gibson042 Apr 9, 2017

Member

The block was patterned off a similar one for isPlainObject, and is quite old as it turns out. I'll remove the try/catch.

@@ -489,8 +493,56 @@ QUnit.test( "isFunction", function( assert ) {
callme( function() {
callme( function() {} );
} );
// Functions from other windows should be matched
Globals.register( "iframeDone" );

This comment has been minimized.

@markelog

markelog Apr 8, 2017

Member

Can we move this to separate test as well?

This comment has been minimized.

@gibson042

gibson042 Apr 9, 2017

Member

I guess, but it seems to fit with the rest of these assertions pretty well. Would anyone else like to weigh in?

@@ -537,6 +539,14 @@ QUnit.test( "jQuery.Deferred.then - spec compatibility", function( assert ) {
assert.ok( true, "errors in .done callbacks don't stop .then handlers" );
} );
function faker() {

This comment has been minimized.

@markelog

markelog Apr 8, 2017

Member

Separate test?

This comment has been minimized.

@gibson042
@@ -861,7 +871,19 @@ 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,
function customToStringThen() {

This comment has been minimized.

@markelog

markelog Apr 8, 2017

Member

Separate test?

This comment has been minimized.

@gibson042

gibson042 Apr 9, 2017

Member

I'd really rather not; this test runs four assertions per input thenable.

src/core.js Outdated
// Support: Chrome <=57, Firefox <=52
// Don't classify callable <object>s as functions
return typeof obj === "function" && typeof obj.nodeType !== "number";

This comment has been minimized.

@markelog

markelog Apr 8, 2017

Member

typeof obj.nodeType !== "number", what is this? Which test is related to this change?

This comment has been minimized.

@gibson042

gibson042 Apr 9, 2017

Member

It's preexisting. This nodeType guard protects us against what would would otherwise be a regression caused by changing from jQuery.type to typeof.

This comment has been minimized.

@markelog

markelog Apr 11, 2017

Member

Would you mind adding this clarification comment there, right now it looks so bizarre :)

This comment has been minimized.

@markelog

This comment has been minimized.

@gibson042

gibson042 Apr 17, 2017

Member

It reads as Don't classify callable <object> elements as functions now; what would clarify further?

This comment has been minimized.

@markelog

markelog Apr 17, 2017

Member

If <object> is referenced to typeof result for objects, how it could bypass out initial typeof obj === "function"?

Then function type is a subtype of object so why we can't classify function object as function?
Most of all, why we check presence of nodeType property to see if object is callable and why do we care?

"elements" part provides some clarification, but only if you know that this is the reference to the DOM elements. And even so why "element"? Why not "node"? If the logic is meant only for elements indeed then how come it cannot reach this part for other nodes? I think it also deserves some explanation as well as some examples of such an input.

I think I know answers to these questions, but after some months I might forget, you might forget, and others who going to read this might not know of course

This comment has been minimized.

@gibson042

gibson042 Apr 18, 2017

Member

"Don't classify callable <object> elements as functions" is perfectly clear to me. Can you just tell me what you want to see here?

@markelog

This comment has been minimized.

Member

markelog commented Apr 10, 2017

Can we augment logic of jQuery.type instead? like jQuery.type(function *() {}) === 'object' right now.

@markelog

This comment has been minimized.

Member

markelog commented Apr 10, 2017

On tests perspective:

In my opinion: one feature – one test, one regression – one test for regression (i.e. for bug), preferably with issue number in test description.

The simpler the better, microservices or docker containers analogies come to mind since otherwise It's really hard to support monolith and god methods with potential merge conflicts if/when we would have to revert if those constructions were already changed at the time of revert. For the same reason we no longer put HTML fixtures inside the test suite, but create them inside the test.

I think we already discuss this many times?

One issue, one pull request, independent tests, one atomic change, one commit

@timmywil

This comment has been minimized.

Member

timmywil commented Apr 10, 2017

I don't think it is necessary that pull requests have one commit, but I agree with atomicity of commits. As for this particular case, I wouldn't mind rebasing all 4 of these commits into one as they all seem to address the same problem. Still, this is less important than the "how". How we address the problem is always the bigger question, and I'm wondering if we shouldn't align with Lodash here and treat generator functions as functions as well.

@gibson042

This comment has been minimized.

Member

gibson042 commented Apr 10, 2017

jQuery.type is so vague and generic that I don't want to touch it... we only use it internally for distinguishing number/string/function/object, and even that is potentially problematic as the list of special-cased objects grows. jQuery.isFunction, on the other hand, is much more clear (but broken until this PR lands).

As for testing, I really like the efficiency of table-driven tests, and want to see us move towards them where practical, rather than away. And merge conflicts wouldn't be an issue if we set expectations from the list of cases.

@gibson042

This comment has been minimized.

Member

gibson042 commented Apr 10, 2017

Tests updated. This should be good to go.

@@ -212,7 +212,10 @@ jQuery.extend( {
noop: function() {},
isFunction: function( obj ) {
return jQuery.type( obj ) === "function";
// Support: Chrome <=57, Firefox <=52

This comment has been minimized.

@mgol

mgol Apr 11, 2017

Member

Should we add only to both or not yet because Chrome 58 & Firefox 53 are not stable yet?

This comment has been minimized.

@gibson042

gibson042 Apr 11, 2017

Member

Not yet; we can update this after official releases if anyone cares.

function faker() {
assert.ok( true, "handler with non-'Function' @@toStringTag gets invoked" );
}
faker[ typeof Symbol === "function" && Symbol.toStringTag ] = "String";

This comment has been minimized.

@mgol

mgol Apr 11, 2017

Member

Why not wrap the statement with if? In the current way we'll be writing to a "false" property in non-supporting browsers which may create confusion.

These are tests so even size is not important so I don't see the gains of the current form.

onFulfilled();
}
};
promise.then[ typeof Symbol === "function" && Symbol.toStringTag ] = "String";

This comment has been minimized.

@mgol

mgol Apr 11, 2017

Member

Similarly, I'd prefer an if instead of writing to a "false" property.

This comment has been minimized.

@gibson042

gibson042 Apr 11, 2017

Member

Fair enough; updated.

onFulfilled();
}
};
if ( typeof Symbol === "function" ) {

This comment has been minimized.

@mgol

mgol Apr 11, 2017

Member

This check is not enough, many browsers (e.g. old Firefox, Edge <15) support many symbols but not @@toStringTag.

This applies to here & a few other places.

This comment has been minimized.

@gibson042

gibson042 Apr 11, 2017

Member

I don't think we care about those cases because they coincide with impossibility of setting @@toStringTag, but I'll see what I can do anyway.

This comment has been minimized.

@gibson042

gibson042 Apr 11, 2017

Member

I decided to keep this one for its harmless property set, but the others are updated to skip tests unless Symbol.toStringTag is truthy.

@mgol

mgol approved these changes Apr 11, 2017

@timmywil timmywil added this to the 3.3.0 milestone Apr 17, 2017

@@ -464,7 +467,7 @@ function isArrayLike( obj ) {
var length = !!obj && "length" in obj && obj.length,
type = jQuery.type( obj );
if ( type === "function" || jQuery.isWindow( obj ) ) {
if ( jQuery.isFunction( obj ) || jQuery.isWindow( obj ) ) {

This comment has been minimized.

@markelog

markelog Apr 17, 2017

Member

Nice, did we already deprecated isWindow btw?

This comment has been minimized.

This comment has been minimized.

@markelog

markelog Apr 17, 2017

Member

Created – #3629 :)

src/core.js Outdated
// Support: Chrome <=57, Firefox <=52
// Don't classify callable <object>s as functions
return typeof obj === "function" && typeof obj.nodeType !== "number";

This comment has been minimized.

@markelog

@yumetodo yumetodo referenced this pull request Apr 22, 2017

Closed

関数宣言、関数式、Arrow Function #20

0 of 3 tasks complete
src/core.js Outdated
return jQuery.type( obj ) === "function";
// Support: Chrome <=57, Firefox <=52
// Don't classify callable <object> elements as functions

This comment has been minimized.

@gibson042

gibson042 Apr 22, 2017

Member

@markelog ping... what do you want instead of this text?

This comment has been minimized.

@markelog

markelog Apr 23, 2017

Member

Sorry, long week. Some in the lines of

// Browsers mentioned above will erroneously equate `typeof` 
// call on some of the DOM nodes to "function":
//
// jQuery.isFunction(document.createElement("object")) === true
//
// but not
//
// jQuery.isFunction(document.createElement("div")) !== true
//
// To circumvent it we check presense of correct `nodeType` property on
// provided argument, which all DOM nodes shoud have
@@ -439,6 +439,8 @@ QUnit.test( "isFunction", function( assert ) {
fn = function() {};
assert.ok( jQuery.isFunction( fn ), "Normal Function" );
assert.ok( !jQuery.isFunction( Object.create( fn ) ), "custom Function subclass" );
obj = document.createElement( "object" );
// Firefox says this is a function

This comment has been minimized.

@markelog

markelog Apr 23, 2017

Member

Chrome does the same, correct?

@@ -439,6 +439,8 @@ QUnit.test( "isFunction", function( assert ) {
fn = function() {};
assert.ok( jQuery.isFunction( fn ), "Normal Function" );
assert.ok( !jQuery.isFunction( Object.create( fn ) ), "custom Function subclass" );

This comment has been minimized.

@markelog

markelog Apr 23, 2017

Member

We can use notOk here instead? It seems more explicit that way, nitpick of course

@gibson042 gibson042 merged commit a16339b into jquery:master Apr 24, 2017

2 checks passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details
licence/cla Contributor License Agreement is signed.
Details

immpo added a commit to immpo/jquery that referenced this pull request Feb 3, 2018

up (#1)
* Dimensions: ignore transforms when retrieving width/height

Close gh-3561
Fixes gh-3193

* CSS: remove dead code in getWidthOrHeight

- getCSS already falls back to inline styles

Ref gh-3561

* Release: update release dependencies

* Release: update AUTHORS.txt

* Release: update version to 3.2.0-pre

* Release: md5sum -> md5 -r for MAC

* Build: Updating the master version to 3.2.1-pre.

* Release: edit dist README version on release

Fixes gh-3574

* Build: update PR template

- Comment out things we don't need to see in the PR description
- Change CLA link

* Tests: move readywait to an iframe test

Close gh-3576
Fixes gh-3573

* Dimensions: fall back to offsetWidth/Height for inline elems

Close gh-3577
Fixes gh-3571

* Revert "Event: Trigger checkbox and radio click events identically"

This reverts commit b442aba.

* Revert "Event: Add radio click triggering tests"

This reverts commit 5f35b5b.

* Tests: add test for passing trigger data to radio click handler

Close gh-3581
Fixes gh-3579

* Build: Updating the master version to 3.2.2-pre.

* CSS: retrieve inline style before computed

- Fixes an issue with getting computed style on detached elements

* Revert "Build: Updating the master version to 3.2.2-pre."

This reverts commit 066bd86.

* Build: Updating the master version to 3.2.2-pre.

* Tests: Fix incorrect assert name for ensure_iterability_es6

Closes gh-3584
Ref bb026fc.

* Docs: Update links to HTML spec for stripAndCollapse (#3594)

* Offset: Use correct offset parents; include all border/scroll values

Thanks @anseki

Fixes gh-3080
Fixes gh-3107
Closes gh-3096
Closes gh-3487

* Core: Update isFunction to handle unusual-@@toStringTag input

Ref gh-3597
Fixes gh-3600
Fixes gh-3596
Closes gh-3617

* Tests: Improve offset test setup and labels

Hopefully this fixes iOS testing: http://swarm.jquery.org/job/5226

Ref 1d2df77
Closes gh-3641

* Tests: Be even more async for iOS

Ref 1d2df77
Closes gh-3643

* Tests: Attach test iframes to the body for visibility-dependent code

Ref 1d2df77
Closes gh-3645

* Tests: Allow a mock QUnit.test for perfect testIframe fidelity

Ref 1d2df77
Closes gh-3647

* Tests: Prepend test iframes for even *more* consistency

Ref 1d2df77

* Tests: Reset iframe window scroll after updating html/document position

Ref 1d2df77
Closes gh-3649

* Tests: Add debugging to investigate iOS failures

Ref 1d2df77

* Tests: Keep iframes visible in TestSwarm

Ref 1d2df77

* Tests: Adjust by actual scroll position, rather than expected

Ref 1d2df77

* Tests: Clean up offset debugging

Ref 1d2df77
Ref c0edd8d

* Tests: Correct expected assertion count

Ref e94b5b0

* Tests: Revert some testIframe changes to fix dimensions tests

Ref c0edd8d

* Revert "Tests: Revert some testIframe changes to fix dimensions tests"

This reverts commit c4368a9.

* Tests: Revert some testIframe changes to fix dimensions tests

Ref c0edd8d

* CSS: Drop the float mapping from cssProps

Firefox 35 and newer support style.float directly.

Closes #3569

* Docs:Tests: Update IE/Edge-related support comments & tests

Closes gh-3661

* Build: Test on Node.js 8, stop testing on Node.js 7

* Tests: minor typos

Close gh-3671

* Dimensions: Include scroll gutter in "padding" box

Fixes gh-3589
Closes gh-3656

* Deferred: fix memory leak of promise callbacks

Fixes gh-3606
Closes gh-3657

* Build: update node dependencies; commit package-lock.json

- Also ignore yarn.lock
Close gh-3669

* Build: Update sinon, husky, and qunitjs

* Build: fix uglify options for uglify update

- Uses new typeofs option for compression
- See mishoo/UglifyJS2#2198

Close gh-3710

* Event: `stopPropagation()` on native event-handler

Fixes gh-3693
Close gh-3694

* Core: Deprecate jQuery.isWindow

Fixes gh-3629
Close gh-3702

* Test: ensure position/offset return mutable objects

Fixes gh-3612
Closes gh-3695

* Revert "Offset: Resolve strict mode ClientRect "no setter" exception"

This reverts commit 3befe59.

* Offset: fix error from bad merge in #3695

* Dimensions: Detect and account for content-box dimension mishandling

Fixes gh-3699
Closes gh-3700

* Support: Properly check for IE9 absolute scrollbox mishandling

Ref gh-3589
Fixes gh-3699
Fixes gh-3730
Closes gh-3729

* Tests: Try extra hard to control focus

Ref gh-3732

* Tests: Abort focus tests when the environment doesn't cooperate

Ref gh-3732

* Tests: Reduce the abort timeout for simple focus testing

Ref gh-3732

* Tests: Simulate events when CI hinders use of native ones

Ref gh-3732

* Tests: Account for TestSwarm focus issues

Closes gh-3732

* Ajax: add an ontimeout handler to all requests

Fixes gh-3586
Close gh-3590

* Dimensions: Improve offsetWidth/offsetHeight fallback

Fixes gh-3698
Fixes gh-3602
Closes gh-3738

* Tests: Replace non-ASCII whitespace in source code

* Dimensions: Don't trust non-pixel computed width/height

Fixes gh-3611
Closes gh-3741

* Build: Fix comment typo

Closes gh-3747

* Build: Update my name in .mailmap

I got married! 🎉

* Build: Update my name in ATHORS.txt

I forgot .mailmap isn't everything.

* Tests: Update path calculation

Fixes gh-3756
Closes gh-3757

* CSS: Avoid unit-conversion interference from CSS upper bounds

Fixes gh-2144
Closes gh-3745

* Tests: Update lineHeight adjustments to give Android more slop

* CSS: Detect more WebKit styles erroneously reported as percentages

Ref 692f9d4
Fixes gh-3777
Closes gh-3778

* Build: Update to Babel 7, use for-of plugin instead of preset-es2015

Closes gh-3786

* Build: Drop cross-spawn, use child_process.spawn shell option

* Build: increase timeout in Promises/A+ tests 10 times

The promises-aplus-tests sets up a default 200 ms Mocha timeout. This makes
our tests randomly fail on Jenkins. 2 seconds will be safer.

Closes gh-3791

* Build: Remove package-lock.json, add it to .gitignore

npm 5, even the version included in the latest Node.js 8.5.0 re-generates
`package-lock.json` on each install. And when it does on a system that doesn't
support all the optional dependencies that are supported on the OS where the
lockfile was generated, it removes those optional deps from the lockfile.

The effect is that everyone firing `npm install` on our repo on any OS other
than macOS will immediately get a dirty state of the repo as the `fsevents`
dependency subtree gets removed from `package-lock.json`. That's a really bad
experience.

This commit removes package-lock.json from the repository and adds it to
.gitignore. We'll start committing the file again once the issue is resolved
on npm's part.

Fixes gh-3792

* Tests: Make Node tests work for paths with spaces in them

Without this patch Jenkins tests fail as jQuery job names there contain spaces,
e.g. "jQuery Core".

Closes gh-3821

* Tests: Add Safari 11 support test results

* Build: Test on Node.js 9

Closes gh-3840

* Tests: Add iOS 11 support test results

* Manipulation: Reduce size by eliminating single-use variable

Closes gh-3851

* CSS: Correctly set support properties with non-default zoom

Fixes gh-3808
Closes gh-3872

* Docs: Create CODE_OF_CONDUCT.md

Close gh-3865

* Tests: Add support for running unit tests via grunt with karma

- Update QUnit to 1.23.1
- Remove unused dl#dl from test/index.html
- Remove unused map#imgmap from test/index.html
- Ensure all urls to data use baseURI
- Add the 'grunt karma:main' task
  - customContextFile & customDebugFile
- Add 'npm run jenkins' script

Close gh-3744
Fixes gh-1999

* Build: Only run browser tests in one Node version on Travis

Ref gh-3744
Closes gh-3894

* Core: make camelCase function available only for internal usage

Close gh-3604
Fixes gh-3384

* Core: adjust data tests to ensure proper camelCasing

- Add back camelCase to the public object (deprecate not remove)
Ref #3384

* Core: deprecate jQuery.now

Fixes gh-2959
Close gh-3884

* Core: deprecate jQuery.proxy (not slated for removal)

Fixes gh-2958
Close gh-3885

* Manipulation: use `.children` to select tbody elements

- selectors beginning with a child combinator are not valid natively.
  This fixes the tests when using selector-native.js

* Attributes: allow array param in add/remove/toggleClass

+30 bytes instead of +182

Thanks to @faisaliyk for the first pass on this feature.

Fixes gh-3532
Close gh-3917

* Ajax: add unit test for getScript(Object)

Fixes gh-3736
Close gh-3918

* Tests: only run ontimeout test if ontimeout exists

Fixes gh-3742
Close gh-3919

* Build: Fix UglifyJS output in Android 4.0; update uglify

- Thanks to @mgol for first pass

Fixes gh-3743
Close gh-3920

* Tests: fix function reference for unbinding

Ref gh-2958

* Build: Remove CRLF line endings to fix builds on Windows

Close gh-3929

* Core: deprecate jQuery.isFunction

Fixes gh-3609

* Event: Move event aliases to deprecated

Fixes gh-3214

* Ajax: Don't process non-string data property on no-entity-body requests

Fixes gh-3438
Closes gh-3781

* Core: deprecate jQuery.isNumeric

Fixes gh-2960
Closes gh-3888

* Tests: fix weird failure in Edge 16 CSS

Fixes gh-3866
Close gh-3932

* Tests: fix weird flaky attributes test in Edge 16

Fixes gh-3867
Close gh-3931

* Core: deprecate jQuery.type

Fixes gh-3605
Close gh-3895

* Tests: fix number of expected assertions in basic core

* Tests: temporarily require sudo access for karma:main on travis

- This should fix the broken travis build on Node 8
- See travis-ci/travis-ci#8836

* Tests: correctly set sudo in travis config, not karma config

* Manipulation: Add support for scripts with module type

Fixes gh-3871
Close gh-3869

* Tests: fix tests in AMD mode

* Tests: ensure that module assertions run on supported browsers

- Also fixes tests for karma, where the URL for the module is different

Ref gh-3871

* Filter: Use direct filter in winnow

for both simple and complex selectors

Fixes gh-3272
Closes gh-3910

* Build: Add "-debug" suffix to name of karma debug tasks

Ref gh-3922
Close gh-3936

* Tests: skip test with invalid selector for selector-native tests

* Release: add new authors to AUTHORS.txt

* Release: update version to 3.3.0-pre

* Build: Updating the master version to 3.3.1-pre.

* Build: Updating the master version to 3.3.2-pre.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment