]> source.dussan.org Git - jquery.git/commitdiff
Core: Support non-browser environments 2504/head
authorMichał Gołębiowski <m.goleb@gmail.com>
Tue, 28 Jul 2015 10:58:44 +0000 (12:58 +0200)
committerMichał Gołębiowski <m.goleb@gmail.com>
Sun, 16 Aug 2015 20:29:42 +0000 (22:29 +0200)
Fixes gh-2133
Fixes gh-2501
Closes gh-2504
Refs gh-1950
Refs gh-1949
Refs gh-2397
Refs gh-1537
Refs gh-2504
Refs 842958e7aecd0d75a7ee9e2aaec83457701aa2f3

45 files changed:
.gitignore
.jscsrc
.jshintignore
Gruntfile.js
build/tasks/install_jsdom.js [new file with mode: 0644]
build/tasks/lib/spawn_test.js [new file with mode: 0644]
build/tasks/node_smoke_tests.js [new file with mode: 0644]
build/tasks/promises_aplus_tests.js [new file with mode: 0644]
package.json
src/.jshintrc
src/ajax.js
src/ajax/parseXML.js
src/ajax/script.js
src/ajax/var/location.js [new file with mode: 0644]
src/ajax/xhr.js
src/attributes/support.js
src/core.js
src/core/init.js
src/core/parseHTML.js
src/core/ready.js
src/core/support.js
src/css.js
src/css/curCSS.js
src/css/support.js
src/data/support.js
src/deferred.js
src/effects.js
src/event.js
src/event/support.js
src/manipulation.js
src/manipulation/support.js
src/offset.js
src/queue/delay.js
src/var/document.js [new file with mode: 0644]
src/var/documentElement.js [new file with mode: 0644]
test/node_smoke_tests/.jshintrc [new file with mode: 0644]
test/node_smoke_tests/document_missing.js [new file with mode: 0644]
test/node_smoke_tests/document_passed.js [new file with mode: 0644]
test/node_smoke_tests/document_present_originally.js [new file with mode: 0644]
test/node_smoke_tests/iterable_with_native_symbol.js [new file with mode: 0644]
test/node_smoke_tests/iterable_with_symbol_polyfill.js [new file with mode: 0644]
test/node_smoke_tests/lib/ensure_global_not_created.js [new file with mode: 0644]
test/node_smoke_tests/lib/ensure_iterability_es6.js [new file with mode: 0644]
test/node_smoke_tests/lib/ensure_jquery.js [new file with mode: 0644]
test/promises_aplus_adapter.js [new file with mode: 0644]

index 463dea426864dc850993402a7fea140736795a60..eae5df6e6cf9b6a6bc99c00a2869c61e92149b6a 100644 (file)
@@ -10,3 +10,5 @@
 
 /dist
 /node_modules
+
+/test/node_smoke_tests/lib/ensure_iterability.js
diff --git a/.jscsrc b/.jscsrc
index fa91a9d9e59354246fa0e0dba3e89a4517a397cb..14f3491337c3d39bd88b67f370b4294bbc643bf2 100644 (file)
--- a/.jscsrc
+++ b/.jscsrc
@@ -1,5 +1,6 @@
 {
        "preset": "jquery",
 
-       "excludeFiles": [ "external", "src/intro.js", "src/outro.js" ]
+       "excludeFiles": [ "external", "src/intro.js", "src/outro.js",
+               "test/node_smoke_tests/lib/ensure_iterability.js" ]
 }
index 19f1b9c52320ceafe82100974a51d94f09e2ffe1..1ddafd635a18124198ef31a421424fb88b460b24 100644 (file)
@@ -9,3 +9,4 @@ test/data/readywaitasset.js
 test/data/readywaitloader.js
 test/data/support/csp.js
 test/data/support/getComputedSupport.js
+test/node_smoke_tests/lib/ensure_iterability.js
index 082bf28c83c25641884462854c51c0535d1b1a0e..6b8dada62eb7acf5e81449b2c410379637574798 100644 (file)
@@ -34,6 +34,18 @@ module.exports = function( grunt ) {
                                cache: "build/.sizecache.json"
                        }
                },
+               babel: {
+                       options: {
+                               sourceMap: "inline",
+                               retainLines: true
+                       },
+                       nodeSmokeTests: {
+                               files: {
+                                       "test/node_smoke_tests/lib/ensure_iterability.js":
+                                               "test/node_smoke_tests/lib/ensure_iterability_es6.js"
+                               }
+                       }
+               },
                build: {
                        all: {
                                dest: "dist/jquery.js",
@@ -159,11 +171,9 @@ module.exports = function( grunt ) {
 
        grunt.registerTask( "lint", [ "jsonlint", "jshint", "jscs" ] );
 
-       // Only defined for master at this time, but kept for cross-branch consistency
-       grunt.registerTask( "test_fast", [] );
+       grunt.registerTask( "test_fast", [ "node_smoke_tests" ] );
 
-       // gh-2133 TODO: cherry-pick 76df9e4e389d80bff410a9e5f08b848de1d21a2f for promises-aplus-tests
-       grunt.registerTask( "test", [ "test_fast"/*, "promises-aplus-tests"*/ ] );
+       grunt.registerTask( "test", [ "test_fast", "promises_aplus_tests" ] );
 
        // Short list as a high frequency watch task
        grunt.registerTask( "dev", [ "build:*:*", "lint", "uglify", "remove_map_comment", "dist:*" ] );
diff --git a/build/tasks/install_jsdom.js b/build/tasks/install_jsdom.js
new file mode 100644 (file)
index 0000000..21d67eb
--- /dev/null
@@ -0,0 +1,27 @@
+module.exports = function( grunt ) {
+       grunt.registerTask( "jsdom", function() {
+               var current,
+                       pkg = grunt.config( "pkg" ),
+                       version = pkg.jsdomVersions[
+
+                               // Unfortunately, this is currently the only
+                               // way to tell the difference between Node and iojs
+                               /^v0/.test( process.version ) ? "node" : "iojs"
+                       ];
+
+               try {
+                       current = require( "jsdom/package.json" ).version;
+                       if ( current === version ) {
+                               return;
+                       }
+               } catch ( e ) {}
+
+               // Use npm on the command-line
+               // There is no local npm
+               grunt.util.spawn( {
+                       cmd: "npm",
+                       args: [ "install", "jsdom@" + version ],
+                       opts: { stdio: "inherit" }
+               }, this.async() );
+       });
+};
diff --git a/build/tasks/lib/spawn_test.js b/build/tasks/lib/spawn_test.js
new file mode 100644 (file)
index 0000000..6c4596a
--- /dev/null
@@ -0,0 +1,16 @@
+/* jshint node: true */
+
+"use strict";
+
+// Run Node with provided parameters: the first one being the Grunt
+// done function and latter ones being files to be tested.
+// See the comment in ../node_smoke_tests.js for more information.
+module.exports = function spawnTest( done ) {
+       var testPaths = [].slice.call( arguments, 1 ),
+               spawn = require( "win-spawn" );
+
+       spawn( "node", testPaths, { stdio: "inherit" } )
+               .on( "close", function( code ) {
+                       done( code === 0 );
+               } );
+} ;
diff --git a/build/tasks/node_smoke_tests.js b/build/tasks/node_smoke_tests.js
new file mode 100644 (file)
index 0000000..9334516
--- /dev/null
@@ -0,0 +1,32 @@
+module.exports = function( grunt ) {
+
+       "use strict";
+
+       var fs = require( "fs" ),
+               spawnTest = require( "./lib/spawn_test.js" ),
+               testsDir = "./test/node_smoke_tests/",
+               nodeSmokeTests = [ "jsdom", "babel:nodeSmokeTests" ];
+
+       // Fire up all tests defined in test/node_smoke_tests/*.js in spawned sub-processes.
+       // All the files under test/node_smoke_tests/*.js are supposed to exit with 0 code
+       // on success or another one on failure. Spawning in sub-processes is
+       // important so that the tests & the main process don't interfere with
+       // each other, e.g. so that they don't share the require cache.
+
+       fs.readdirSync( testsDir )
+               .filter( function( testFilePath ) {
+                       return fs.statSync( testsDir + testFilePath ).isFile() &&
+                               /\.js$/.test( testFilePath );
+               } )
+               .forEach( function( testFilePath ) {
+                       var taskName = "node_" + testFilePath.replace( /\.js$/, "" );
+
+                       grunt.registerTask( taskName, function() {
+                               spawnTest( this.async(), "test/node_smoke_tests/" + testFilePath );
+                       } );
+
+                       nodeSmokeTests.push( taskName );
+               } );
+
+       grunt.registerTask( "node_smoke_tests", nodeSmokeTests );
+};
diff --git a/build/tasks/promises_aplus_tests.js b/build/tasks/promises_aplus_tests.js
new file mode 100644 (file)
index 0000000..3e770a0
--- /dev/null
@@ -0,0 +1,13 @@
+module.exports = function( grunt ) {
+
+       "use strict";
+
+       var spawnTest = require( "./lib/spawn_test.js" );
+
+       grunt.registerTask( "promises_aplus_tests", function() {
+               spawnTest( this.async(),
+                       "./node_modules/.bin/promises-aplus-tests",
+                       "test/promises_aplus_adapter.js"
+               );
+       } );
+};
index eb6c27f4954984c3e11ba16d1857ff7c1a0a49d7..a8178ea7d87b19ee1af3ff6a7457b6b81d20b9e7 100644 (file)
@@ -26,7 +26,9 @@
   "dependencies": {},
   "devDependencies": {
     "commitplease": "2.0.0",
+    "core-js": "0.9.17",
     "grunt": "0.4.5",
+    "grunt-babel": "5.0.1",
     "grunt-cli": "0.1.13",
     "grunt-compare-size": "0.4.0",
     "grunt-contrib-jshint": "0.11.2",
     "sinon": "1.12.2",
     "sizzle": "2.2.0",
     "strip-json-comments": "1.0.3",
-    "testswarm": "1.1.0"
+    "testswarm": "1.1.0",
+    "win-spawn": "2.0.0"
+  },
+  "jsdomVersions": {
+    "node": "3.1.2",
+    "iojs": "5.3.0"
   },
   "scripts": {
     "build": "npm install && grunt",
index 87dcde1cd0f8778a775c9485073f05c396b969f9..f1a2eb53e757829a4d8af51f0a419e20e12f91ac 100644 (file)
        // The above browsers are failing a lot of tests in the ES5
        // test suite at http://test262.ecmascript.org.
        "es3": true,
-       "browser": true,
-       "wsh": true,
 
        "globals": {
+               "window": true,
                "JSON": false,
+
                "jQuery": true,
                "define": false,
                "module": false,
index 24425bac6ba7ffe8380c8210cad3468cce868bda..8357d64208623d8994d16c0a858bc670d767e6f9 100644 (file)
@@ -1,13 +1,15 @@
 define([
        "./core",
+       "./var/document",
        "./var/rnotwhite",
+       "./ajax/var/location",
        "./ajax/var/nonce",
        "./ajax/var/rquery",
        "./core/init",
        "./ajax/parseJSON",
        "./ajax/parseXML",
        "./deferred"
-], function( jQuery, rnotwhite, nonce, rquery ) {
+], function( jQuery, document, rnotwhite, location, nonce, rquery ) {
 
 var
        rhash = /#.*$/,
@@ -643,7 +645,7 @@ jQuery.extend({
 
                        // Timeout
                        if ( s.async && s.timeout > 0 ) {
-                               timeoutTimer = setTimeout(function() {
+                               timeoutTimer = window.setTimeout(function() {
                                        jqXHR.abort("timeout");
                                }, s.timeout );
                        }
@@ -677,7 +679,7 @@ jQuery.extend({
 
                        // Clear timeout if it exists
                        if ( timeoutTimer ) {
-                               clearTimeout( timeoutTimer );
+                               window.clearTimeout( timeoutTimer );
                        }
 
                        // Dereference transport for early garbage collection
index 9fbd9da9ae0b4309a5e01885173b4ca2aefd0d60..e0b24851365a95bdb003dbb781bb0a51f1a796e7 100644 (file)
@@ -10,10 +10,10 @@ jQuery.parseXML = function( data ) {
        }
        try {
                if ( window.DOMParser ) { // Standard
-                       tmp = new DOMParser();
+                       tmp = new window.DOMParser();
                        xml = tmp.parseFromString( data, "text/xml" );
                } else { // IE
-                       xml = new ActiveXObject( "Microsoft.XMLDOM" );
+                       xml = new window.ActiveXObject( "Microsoft.XMLDOM" );
                        xml.async = "false";
                        xml.loadXML( data );
                }
index 2e937fe6574d10d0c8da386eff74df27b736cd86..1af0963f36248eb61ceb409b45f9e08b20dd18f9 100644 (file)
@@ -1,7 +1,8 @@
 define([
        "../core",
+       "../var/document",
        "../ajax"
-], function( jQuery ) {
+], function( jQuery, document ) {
 
 // Install script dataType
 jQuery.ajaxSetup({
diff --git a/src/ajax/var/location.js b/src/ajax/var/location.js
new file mode 100644 (file)
index 0000000..4c9cf4a
--- /dev/null
@@ -0,0 +1,3 @@
+define(function() {
+       return window.location;
+});
index 585703f449d144f1f6bdd7893081033f034b5e4f..ef68ef4c0583257b7513740587921f06bf3dc343 100644 (file)
@@ -1,8 +1,9 @@
 define([
        "../core",
+       "../var/document",
        "../var/support",
        "../ajax"
-], function( jQuery, support ) {
+], function( jQuery, document, support ) {
 
 // Create the request object
 // (This is still attached to ajaxSettings for backward compatibility)
index 044e23823acac0efa12f2811bbb85d56e2bcfc7e..6fd6827f46a283f7b168d4cc6ae2a5e21192c8b6 100644 (file)
@@ -1,21 +1,25 @@
 define([
+       "../var/document",
        "../var/support"
-], function( support ) {
+], function( document, support ) {
 
 (function() {
-       // Minified: var a,b,c,d,e
-       var input, div, select, a, opt;
+       var a,
+               input = document.createElement( "input" ),
+               div = document.createElement( "div" ),
+               select = document.createElement( "select" ),
+               opt = select.appendChild( document.createElement( "option" ) );
 
        // Setup
-       div = document.createElement( "div" );
-       div.innerHTML = "  <link/><a href='/a'>a</a><input type='checkbox'/>";
-       a = div.getElementsByTagName("a")[ 0 ];
+       div.innerHTML = "  <link/><a href='/a'>a</a>";
+       // Support: Windows Web Apps (WWA)
+       // `type` must use .setAttribute for WWA (#14901)
+       input.setAttribute( "type", "checkbox" );
+       div.appendChild( input );
 
-       // First batch of tests.
-       select = document.createElement("select");
-       opt = select.appendChild( document.createElement("option") );
-       input = div.getElementsByTagName("input")[ 0 ];
+       a = div.getElementsByTagName( "a" )[ 0 ];
 
+       // First batch of tests.
        a.style.cssText = "top:1px";
 
        // Get the style information from getAttribute
index 6eae1990c9845e785f9bd22d9d4d8bdc22ea09bd..0c21744e2322598a09e7f82904ad82741511d132 100644 (file)
@@ -1,5 +1,6 @@
 define([
        "./var/deletedIds",
+       "./var/document",
        "./var/slice",
        "./var/concat",
        "./var/push",
@@ -8,7 +9,8 @@ define([
        "./var/toString",
        "./var/hasOwn",
        "./var/support"
-], function( deletedIds, slice, concat, push, indexOf, class2type, toString, hasOwn, support ) {
+], function( deletedIds, document, slice, concat, push, indexOf,
+       class2type, toString, hasOwn, support ) {
 
 var
        version = "@VERSION+compat",
index 52999d4ea3109eb4919261a7e912efd332c2df1c..a438ea0db36d04917c0b228a24b905ce085309e8 100644 (file)
@@ -1,16 +1,14 @@
 // Initialize a jQuery object
 define([
        "../core",
+       "../var/document",
        "./var/rsingleTag",
        "../traversing/findFilter"
-], function( jQuery, rsingleTag ) {
+], function( jQuery, document, rsingleTag ) {
 
 // A central reference to the root jQuery(document)
 var rootjQuery,
 
-       // Use the correct document accordingly with window argument (sandbox)
-       document = window.document,
-
        // A simple way to check for HTML strings
        // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
        // Strict HTML recognition (#11290: must start with <)
index 68dd6cf8db86a816c7f2e068b907d722f59469e7..e7d7c63c848770d4b7f4f1100f1d5289183970e8 100644 (file)
@@ -1,11 +1,12 @@
 define([
        "../core",
+       "../var/document",
        "./var/rsingleTag",
        "../manipulation/buildFragment",
 
        // This is the only module that needs core/support
        "./support"
-], function( jQuery, rsingleTag, buildFragment, support ) {
+], function( jQuery, document, rsingleTag, buildFragment, support ) {
 
 // data: string of html
 // context (optional): If specified, the fragment will be created in this context,
index ae72fdeaba242a9d9bbc9bc54ed548334c0b8ad2..c5835a4a37007fb737f04f02d6a1efe92c74bd50 100644 (file)
@@ -1,7 +1,8 @@
 define([
        "../core",
+       "../var/document",
        "../deferred"
-], function( jQuery ) {
+], function( jQuery, document ) {
 
 // The deferred used on DOM ready
 var readyList;
@@ -72,7 +73,7 @@ function detach() {
 function completed() {
        // readyState === "complete" is good enough for us to call the dom ready in oldIE
        if ( document.addEventListener ||
-               event.type === "load" ||
+               window.event.type === "load" ||
                document.readyState === "complete" ) {
 
                detach();
@@ -93,7 +94,7 @@ jQuery.ready.promise = function( obj ) {
                // http://bugs.jquery.com/ticket/12282#comment:15
                if ( document.readyState === "complete" ) {
                        // Handle it asynchronously to allow scripts the opportunity to delay ready
-                       setTimeout( jQuery.ready );
+                       window.setTimeout( jQuery.ready );
 
                // Standards-based browsers support DOMContentLoaded
                } else if ( document.addEventListener ) {
index e154502752f518c94c16b82e38a39ece4d27ff09..8348ab7e363bb1587c653c418c9ab62ef3b5bb7e 100644 (file)
@@ -1,6 +1,7 @@
 define([
+       "../var/document",
        "../var/support"
-], function( support ) {
+], function( document, support ) {
 
 // Support: Safari 8+
 // In Safari 8 documents created via document.implementation.createHTMLDocument
index 43ba09cd3cbe0af5263f0a2f2d172ada458cc2d4..27c5ecf8866eec6492598cc7e2fe26d25ba8cf06 100644 (file)
@@ -3,12 +3,13 @@ define([
        "./var/pnum",
        "./core/access",
        "./css/var/rmargin",
+       "./var/document",
        "./var/rcssNum",
        "./css/var/rnumnonpx",
        "./css/var/cssExpand",
        "./css/var/isHidden",
-       "./css/curCSS",
        "./css/var/swap",
+       "./css/curCSS",
        "./css/adjustCSS",
        "./css/addGetHookIf",
        "./css/support",
@@ -17,8 +18,8 @@ define([
        "./core/init",
        "./core/ready",
        "./selector" // contains
-], function( jQuery, pnum, access, rmargin, rcssNum, rnumnonpx, cssExpand, isHidden,
-       curCSS, swap, adjustCSS, addGetHookIf, support, showHide ) {
+], function( jQuery, pnum, access, rmargin, document, rcssNum, rnumnonpx, cssExpand,
+       isHidden, swap, curCSS, adjustCSS, addGetHookIf, support, showHide ) {
 
 var
        // BuildExclude
index 918139631ff4585529d27e297722a504923ee6dd..967ce3e9418f6d6f8fedfc39c1563b3ebe26bd24 100644 (file)
@@ -1,11 +1,12 @@
 define([
        "exports",
        "../core",
+       "../var/documentElement",
        "./var/rnumnonpx",
        "./var/rmargin",
        "./support",
        "../selector" // contains
-], function( exports, jQuery, rnumnonpx, rmargin, support ) {
+], function( exports, jQuery, documentElement, rnumnonpx, rmargin, support ) {
 
 var getStyles, curCSS,
        rposition = /^(top|right|bottom|left)$/;
@@ -68,7 +69,7 @@ if ( window.getComputedStyle ) {
                        ret :
                        ret + "";
        };
-} else if ( document.documentElement.currentStyle ) {
+} else if ( documentElement.currentStyle ) {
        getStyles = function( elem ) {
                return elem.currentStyle;
        };
index 6b57317713ed21d7498bd296e47aaed889a9aac1..7eb3c7de4067bcf90cd9f41657ee2dd67f728f53 100644 (file)
@@ -1,32 +1,30 @@
 define([
        "../core",
+       "../var/document",
+       "../var/documentElement",
        "../var/support"
-], function( jQuery, support ) {
+], function( jQuery, document, documentElement, support ) {
 
 (function() {
-       var div, container, style, a, pixelPositionVal, boxSizingReliableVal, gBCRDimensionsVal,
-               pixelMarginRightVal, reliableHiddenOffsetsVal, reliableMarginRightVal;
-
-       // Setup
-       div = document.createElement( "div" );
-       div.innerHTML = "  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
-       a = div.getElementsByTagName( "a" )[ 0 ];
-       style = a && a.style;
+       var pixelPositionVal, boxSizingReliableVal, gBCRDimensionsVal,
+               pixelMarginRightVal, reliableHiddenOffsetsVal, reliableMarginRightVal,
+               container = document.createElement( "div" ),
+               div = document.createElement( "div" );
 
        // Finish early in limited (non-browser) environments
-       if ( !style ) {
+       if ( !div.style ) {
                return;
        }
 
-       style.cssText = "float:left;opacity:.5";
+       div.style.cssText = "float:left;opacity:.5";
 
        // Support: IE<9
        // Make sure that element opacity exists (as opposed to filter)
-       support.opacity = style.opacity === "0.5";
+       support.opacity = div.style.opacity === "0.5";
 
        // Verify style float existence
        // (IE uses styleFloat instead of cssFloat)
-       support.cssFloat = !!style.cssFloat;
+       support.cssFloat = !!div.style.cssFloat;
 
        div.style.backgroundClip = "content-box";
        div.cloneNode( true ).style.backgroundClip = "";
index 9e0ba14bc095f8606bad29e392afe0912b8ca9cc..df17c5c4035773bd854a2a9b8b266da24047b47f 100644 (file)
@@ -1,6 +1,7 @@
 define([
+       "../var/document",
        "../var/support"
-], function( support ) {
+], function( document, support ) {
 
 (function() {
        var div = document.createElement( "div" );
index ac6956dfbf3efba04450e34a1fb49f573bec33b0..050ad765e61f3b2fe7cc0d5db966c71763fce7dc 100644 (file)
@@ -176,7 +176,7 @@ jQuery.extend({
                                                        if ( depth ) {
                                                                process();
                                                        } else {
-                                                               setTimeout( process );
+                                                               window.setTimeout( process );
                                                        }
                                                };
                                        }
index a6b5748f5916f56d6121f753542a87fbcd2c8c48..9a0e4e0f1bafa450e4030305da4f43aa74a7de15 100644 (file)
@@ -1,5 +1,6 @@
 define([
        "./core",
+       "./var/document",
        "./var/rcssNum",
        "./var/rnotwhite",
        "./css/var/cssExpand",
@@ -15,7 +16,8 @@ define([
        "./manipulation",
        "./css",
        "./effects/Tween"
-], function( jQuery, rcssNum, rnotwhite, cssExpand, isHidden, swap, adjustCSS, showHide ) {
+], function( jQuery, document, rcssNum, rnotwhite, cssExpand, isHidden, swap,
+       adjustCSS, showHide ) {
 
 var
        fxNow, timerId,
@@ -31,7 +33,7 @@ function raf() {
 
 // Animations created synchronously will run synchronously
 function createFxNow() {
-       setTimeout(function() {
+       window.setTimeout(function() {
                fxNow = undefined;
        });
        return ( fxNow = jQuery.now() );
@@ -640,14 +642,14 @@ jQuery.fx.interval = 13;
 jQuery.fx.start = function() {
        timerId = window.requestAnimationFrame ?
                window.requestAnimationFrame( raf ) :
-               setInterval( jQuery.fx.tick, jQuery.fx.interval );
+               window.setInterval( jQuery.fx.tick, jQuery.fx.interval );
 };
 
 jQuery.fx.stop = function() {
        if ( window.cancelAnimationFrame ) {
                window.cancelAnimationFrame( timerId );
        } else {
-               clearInterval( timerId );
+               window.clearInterval( timerId );
        }
 
        timerId = null;
index 165c2c0f078fa60be1a4059926993e3f2dff6008..f821bbda75d10e017a280996746ec7a1d6ab8d7b 100644 (file)
@@ -1,5 +1,6 @@
 define([
        "./core",
+       "./var/document",
        "./var/rnotwhite",
        "./var/hasOwn",
        "./var/slice",
@@ -8,7 +9,7 @@ define([
        "./core/init",
        "./data",
        "./selector"
-], function( jQuery, rnotwhite, hasOwn, slice, support ) {
+], function( jQuery, document, rnotwhite, hasOwn, slice, support ) {
 
 var rformElems = /^(?:input|select|textarea)$/i,
        rkeyEvent = /^key/,
index ed0c861aa2e5e660703f6924eb9a077627d9440b..132575c2069d210ab0862af1c3548d8cd918998e 100644 (file)
@@ -1,6 +1,7 @@
 define([
+       "../var/document",
        "../var/support"
-], function( support ) {
+], function( document, support ) {
 
 (function() {
        var i, eventName,
index 4fc1e0cf324c8f2e8c8906b94104ad16a73f2824..d62d480b7113e3f01feca969e68e2479836478c9 100644 (file)
@@ -1,5 +1,6 @@
 define([
        "./core",
+       "./var/document",
        "./var/concat",
        "./var/push",
        "./var/deletedIds",
@@ -22,7 +23,7 @@ define([
        "./traversing",
        "./selector",
        "./event"
-], function( jQuery, concat, push, deletedIds, access,
+], function( jQuery, document, concat, push, deletedIds, access,
        rcheckableType, rtagName, rscriptType, rleadingWhitespace, nodeNames,
        createSafeFragment, wrapMap, getAll, setGlobalEval,
        buildFragment, support ) {
index 9bfceabe22f53bc12cca01a408a471041ac3c2b4..edf162a3f419d3f7fd8cecad24f5a076aebcf505 100644 (file)
@@ -1,11 +1,13 @@
 define([
        "../core",
+       "../var/document",
        "../var/support"
-], function( jQuery, support ) {
+], function( jQuery, document, support ) {
 
 (function() {
        var div = document.createElement( "div" ),
-               fragment = document.createDocumentFragment();
+               fragment = document.createDocumentFragment(),
+               input = document.createElement( "input" );
 
        // Setup
        div.innerHTML = "  <link/><a href='/a'></a>";
@@ -29,7 +31,13 @@ define([
 
        // #11217 - WebKit loses check when the name is after the checked attribute
        fragment.appendChild( div );
-       div.innerHTML = "<input type='radio' checked='checked' name='t'/>";
+       // Support: Windows Web Apps (WWA)
+       // `name` and `type` must use .setAttribute for WWA (#14901)
+       input.setAttribute( "type", "radio" );
+       input.setAttribute( "checked", "checked" );
+       input.setAttribute( "name", "t" );
+
+       div.appendChild( input );
 
        // Support: Android<4.2
        // Older WebKit doesn't clone checked state correctly in fragments
index 43bf20b7cb0e0b2736c8e50fb9f7e73f0db810b8..5e5ce7bc7fbf0272d154e7905eabd1cafbca5625 100644 (file)
@@ -1,6 +1,8 @@
 define([
        "./core",
        "./core/access",
+       "./var/document",
+       "./var/documentElement",
        "./css/var/rnumnonpx",
        "./css/curCSS",
        "./css/addGetHookIf",
@@ -9,7 +11,7 @@ define([
        "./core/init",
        "./css",
        "./selector" // contains
-], function( jQuery, access, rnumnonpx, curCSS, addGetHookIf, support ) {
+], function( jQuery, access, document, documentElement, rnumnonpx, curCSS, addGetHookIf, support ) {
 
 // BuildExclude
 curCSS = curCSS.curCSS;
index 037ef0998e345dc9e50f05cc22902226577ff2dd..93abd0bf26cda1459562120dada098bae4300fe4 100644 (file)
@@ -11,9 +11,9 @@ jQuery.fn.delay = function( time, type ) {
        type = type || "fx";
 
        return this.queue( type, function( next, hooks ) {
-               var timeout = setTimeout( next, time );
+               var timeout = window.setTimeout( next, time );
                hooks.stop = function() {
-                       clearTimeout( timeout );
+                       window.clearTimeout( timeout );
                };
        });
 };
diff --git a/src/var/document.js b/src/var/document.js
new file mode 100644 (file)
index 0000000..ded014f
--- /dev/null
@@ -0,0 +1,3 @@
+define(function() {
+       return window.document;
+});
diff --git a/src/var/documentElement.js b/src/var/documentElement.js
new file mode 100644 (file)
index 0000000..c639670
--- /dev/null
@@ -0,0 +1,5 @@
+define([
+       "./document"
+], function( document ) {
+       return document.documentElement;
+});
diff --git a/test/node_smoke_tests/.jshintrc b/test/node_smoke_tests/.jshintrc
new file mode 100644 (file)
index 0000000..1445c7b
--- /dev/null
@@ -0,0 +1,14 @@
+{
+       "boss": true,
+       "curly": true,
+       "eqeqeq": true,
+       "eqnull": true,
+       "expr": true,
+       "immed": true,
+       "noarg": true,
+       "quotmark": "double",
+       "undef": true,
+       "unused": true,
+
+       "node": true
+}
diff --git a/test/node_smoke_tests/document_missing.js b/test/node_smoke_tests/document_missing.js
new file mode 100644 (file)
index 0000000..4a0ad2e
--- /dev/null
@@ -0,0 +1,11 @@
+"use strict";
+
+var assert = require( "assert" ),
+       ensureGlobalNotCreated = require( "./lib/ensure_global_not_created" ),
+       jQueryFactory = require( "../../dist/jquery.js" );
+
+assert.throws( function () {
+       jQueryFactory( {} );
+}, /jQuery requires a window with a document/ );
+
+ensureGlobalNotCreated( module.exports );
diff --git a/test/node_smoke_tests/document_passed.js b/test/node_smoke_tests/document_passed.js
new file mode 100644 (file)
index 0000000..5999cc7
--- /dev/null
@@ -0,0 +1,14 @@
+"use strict";
+
+var assert = require( "assert" );
+
+require( "jsdom" ).env( "", function( errors, window ) {
+       assert.ifError( errors );
+
+       var ensureJQuery = require( "./lib/ensure_jquery" ),
+               ensureGlobalNotCreated = require( "./lib/ensure_global_not_created" ),
+               jQuery = require( "../../dist/jquery.js" )( window );
+
+       ensureJQuery( jQuery );
+       ensureGlobalNotCreated( module.exports );
+} );
diff --git a/test/node_smoke_tests/document_present_originally.js b/test/node_smoke_tests/document_present_originally.js
new file mode 100644 (file)
index 0000000..f751487
--- /dev/null
@@ -0,0 +1,17 @@
+"use strict";
+
+var assert = require( "assert" );
+
+require( "jsdom" ).env( "", function( errors, window ) {
+       assert.ifError( errors );
+
+       // Pretend the window is a global.
+       global.window = window;
+
+       var ensureJQuery = require( "./lib/ensure_jquery" ),
+               ensureGlobalNotCreated = require( "./lib/ensure_global_not_created" ),
+               jQuery = require( "../../dist/jquery.js" );
+
+       ensureJQuery( jQuery );
+       ensureGlobalNotCreated( module.exports, window );
+} );
diff --git a/test/node_smoke_tests/iterable_with_native_symbol.js b/test/node_smoke_tests/iterable_with_native_symbol.js
new file mode 100644 (file)
index 0000000..3376ebd
--- /dev/null
@@ -0,0 +1,8 @@
+"use strict";
+
+if ( typeof Symbol === "undefined" ) {
+       console.log( "Symbols not supported, skipping the test..." );
+       process.exit();
+}
+
+require( "./lib/ensure_iterability_es6" )();
diff --git a/test/node_smoke_tests/iterable_with_symbol_polyfill.js b/test/node_smoke_tests/iterable_with_symbol_polyfill.js
new file mode 100644 (file)
index 0000000..dd377f1
--- /dev/null
@@ -0,0 +1,13 @@
+/* jshint esnext: true */
+
+"use strict";
+
+var assert = require( "assert" );
+
+delete global.Symbol;
+require( "core-js" );
+
+assert.strictEqual( typeof Symbol, "function", "Expected Symbol to be a function" );
+assert.notEqual( typeof Symbol.iterator, "symbol", "Expected Symbol.iterator to be polyfilled" );
+
+require( "./lib/ensure_iterability" )();
diff --git a/test/node_smoke_tests/lib/ensure_global_not_created.js b/test/node_smoke_tests/lib/ensure_global_not_created.js
new file mode 100644 (file)
index 0000000..7cc83b5
--- /dev/null
@@ -0,0 +1,15 @@
+"use strict";
+
+var assert = require( "assert" );
+
+// Ensure the jQuery property on global/window/module.exports/etc. was not
+// created in a CommonJS environment.
+// `global` is always checked in addition to passed parameters.
+module.exports = function ensureGlobalNotCreated() {
+       var args = [].slice.call( arguments ).concat( global );
+
+       args.forEach( function( object ) {
+               assert.strictEqual( object.jQuery, undefined,
+                       "A jQuery global was created in a CommonJS environment." );
+       } );
+};
diff --git a/test/node_smoke_tests/lib/ensure_iterability_es6.js b/test/node_smoke_tests/lib/ensure_iterability_es6.js
new file mode 100644 (file)
index 0000000..ebe6853
--- /dev/null
@@ -0,0 +1,25 @@
+/* jshint esnext: true */
+
+"use strict";
+
+var assert = require( "assert" );
+
+module.exports = function ensureIterability() {
+       require( "jsdom" ).env( "", function( errors, window ) {
+               assert.ifError( errors );
+
+               var i,
+                       ensureJQuery = require( "./ensure_jquery" ),
+                       jQuery = require( "../../../dist/jquery.js" )( window ),
+                       elem = jQuery( "<div></div><span></span><a></a>" ),
+                       result = "";
+
+               ensureJQuery( jQuery );
+
+               for ( i of elem ) {
+                       result += i.nodeName;
+               }
+
+               assert.strictEqual( result, "DIVSPANA", "for-of doesn't work on jQuery objects" );
+       } );
+};
diff --git a/test/node_smoke_tests/lib/ensure_jquery.js b/test/node_smoke_tests/lib/ensure_jquery.js
new file mode 100644 (file)
index 0000000..0933a1d
--- /dev/null
@@ -0,0 +1,9 @@
+"use strict";
+
+var assert = require( "assert" );
+
+// Check if the object we got is the jQuery object by invoking a basic API.
+module.exports = function ensureJQuery( jQuery ) {
+       assert( /^jQuery/.test( jQuery.expando ),
+               "jQuery.expando was not detected, the jQuery bootstrap process has failed" );
+};
diff --git a/test/promises_aplus_adapter.js b/test/promises_aplus_adapter.js
new file mode 100644 (file)
index 0000000..decc3e0
--- /dev/null
@@ -0,0 +1,22 @@
+/* jshint node: true */
+
+"use strict";
+
+require( "jsdom" ).env( "", function ( errors, window ) {
+       if ( errors ) {
+               console.error( errors );
+               return;
+       }
+
+       var jQuery = require( ".." )( window );
+
+       exports.deferred = function () {
+               var deferred = jQuery.Deferred();
+
+               return {
+                       promise: deferred.promise(),
+                       resolve: deferred.resolve.bind( deferred ),
+                       reject: deferred.reject.bind( deferred )
+               };
+       };
+} );