diff --git a/.gitignore b/.gitignore
index 463dea426..eae5df6e6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,3 +10,5 @@
/dist
/node_modules
+
+/test/node_smoke_tests/lib/ensure_iterability.js
diff --git a/.jscsrc b/.jscsrc
index fa91a9d9e..14f349133 100644
--- 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" ]
}
diff --git a/.jshintignore b/.jshintignore
index 19f1b9c52..1ddafd635 100644
--- a/.jshintignore
+++ b/.jshintignore
@@ -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
diff --git a/Gruntfile.js b/Gruntfile.js
index 082bf28c8..6b8dada62 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -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
index 000000000..21d67eb0e
--- /dev/null
+++ b/build/tasks/install_jsdom.js
@@ -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
index 000000000..6c4596a3d
--- /dev/null
+++ b/build/tasks/lib/spawn_test.js
@@ -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
index 000000000..9334516d9
--- /dev/null
+++ b/build/tasks/node_smoke_tests.js
@@ -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
index 000000000..3e770a079
--- /dev/null
+++ b/build/tasks/promises_aplus_tests.js
@@ -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"
+ );
+ } );
+};
diff --git a/package.json b/package.json
index eb6c27f49..a8178ea7d 100644
--- a/package.json
+++ b/package.json
@@ -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",
@@ -46,7 +48,12 @@
"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",
diff --git a/src/.jshintrc b/src/.jshintrc
index 87dcde1cd..f1a2eb53e 100644
--- a/src/.jshintrc
+++ b/src/.jshintrc
@@ -16,11 +16,11 @@
// 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,
diff --git a/src/ajax.js b/src/ajax.js
index 24425bac6..8357d6420 100644
--- a/src/ajax.js
+++ b/src/ajax.js
@@ -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
diff --git a/src/ajax/parseXML.js b/src/ajax/parseXML.js
index 9fbd9da9a..e0b248513 100644
--- a/src/ajax/parseXML.js
+++ b/src/ajax/parseXML.js
@@ -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 );
}
diff --git a/src/ajax/script.js b/src/ajax/script.js
index 2e937fe65..1af0963f3 100644
--- a/src/ajax/script.js
+++ b/src/ajax/script.js
@@ -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
index 000000000..4c9cf4a4c
--- /dev/null
+++ b/src/ajax/var/location.js
@@ -0,0 +1,3 @@
+define(function() {
+ return window.location;
+});
diff --git a/src/ajax/xhr.js b/src/ajax/xhr.js
index 585703f44..ef68ef4c0 100644
--- a/src/ajax/xhr.js
+++ b/src/ajax/xhr.js
@@ -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)
diff --git a/src/attributes/support.js b/src/attributes/support.js
index 044e23823..6fd6827f4 100644
--- a/src/attributes/support.js
+++ b/src/attributes/support.js
@@ -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 = " a";
- a = div.getElementsByTagName("a")[ 0 ];
+ div.innerHTML = " a";
+ // Support: Windows Web Apps (WWA)
+ // `type` must use .setAttribute for WWA (#14901)
+ input.setAttribute( "type", "checkbox" );
+ div.appendChild( input );
+
+ a = div.getElementsByTagName( "a" )[ 0 ];
// First batch of tests.
- select = document.createElement("select");
- opt = select.appendChild( document.createElement("option") );
- input = div.getElementsByTagName("input")[ 0 ];
-
a.style.cssText = "top:1px";
// Get the style information from getAttribute
diff --git a/src/core.js b/src/core.js
index 6eae1990c..0c21744e2 100644
--- a/src/core.js
+++ b/src/core.js
@@ -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",
diff --git a/src/core/init.js b/src/core/init.js
index 52999d4ea..a438ea0db 100644
--- a/src/core/init.js
+++ b/src/core/init.js
@@ -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 to avoid XSS via location.hash (#9521)
// Strict HTML recognition (#11290: must start with <)
diff --git a/src/core/parseHTML.js b/src/core/parseHTML.js
index 68dd6cf8d..e7d7c63c8 100644
--- a/src/core/parseHTML.js
+++ b/src/core/parseHTML.js
@@ -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,
diff --git a/src/core/ready.js b/src/core/ready.js
index ae72fdeab..c5835a4a3 100644
--- a/src/core/ready.js
+++ b/src/core/ready.js
@@ -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 ) {
diff --git a/src/core/support.js b/src/core/support.js
index e15450275..8348ab7e3 100644
--- a/src/core/support.js
+++ b/src/core/support.js
@@ -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
diff --git a/src/css.js b/src/css.js
index 43ba09cd3..27c5ecf88 100644
--- a/src/css.js
+++ b/src/css.js
@@ -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
diff --git a/src/css/curCSS.js b/src/css/curCSS.js
index 918139631..967ce3e94 100644
--- a/src/css/curCSS.js
+++ b/src/css/curCSS.js
@@ -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;
};
diff --git a/src/css/support.js b/src/css/support.js
index 6b5731771..7eb3c7de4 100644
--- a/src/css/support.js
+++ b/src/css/support.js
@@ -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 = " a";
- 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 = "";
diff --git a/src/data/support.js b/src/data/support.js
index 9e0ba14bc..df17c5c40 100644
--- a/src/data/support.js
+++ b/src/data/support.js
@@ -1,6 +1,7 @@
define([
+ "../var/document",
"../var/support"
-], function( support ) {
+], function( document, support ) {
(function() {
var div = document.createElement( "div" );
diff --git a/src/deferred.js b/src/deferred.js
index ac6956dfb..050ad765e 100644
--- a/src/deferred.js
+++ b/src/deferred.js
@@ -176,7 +176,7 @@ jQuery.extend({
if ( depth ) {
process();
} else {
- setTimeout( process );
+ window.setTimeout( process );
}
};
}
diff --git a/src/effects.js b/src/effects.js
index a6b5748f5..9a0e4e0f1 100644
--- a/src/effects.js
+++ b/src/effects.js
@@ -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;
diff --git a/src/event.js b/src/event.js
index 165c2c0f0..f821bbda7 100644
--- a/src/event.js
+++ b/src/event.js
@@ -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/,
diff --git a/src/event/support.js b/src/event/support.js
index ed0c861aa..132575c20 100644
--- a/src/event/support.js
+++ b/src/event/support.js
@@ -1,6 +1,7 @@
define([
+ "../var/document",
"../var/support"
-], function( support ) {
+], function( document, support ) {
(function() {
var i, eventName,
diff --git a/src/manipulation.js b/src/manipulation.js
index 4fc1e0cf3..d62d480b7 100644
--- a/src/manipulation.js
+++ b/src/manipulation.js
@@ -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 ) {
diff --git a/src/manipulation/support.js b/src/manipulation/support.js
index 9bfceabe2..edf162a3f 100644
--- a/src/manipulation/support.js
+++ b/src/manipulation/support.js
@@ -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 = " ";
@@ -29,7 +31,13 @@ define([
// #11217 - WebKit loses check when the name is after the checked attribute
fragment.appendChild( div );
- div.innerHTML = "";
+ // 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
diff --git a/src/offset.js b/src/offset.js
index 43bf20b7c..5e5ce7bc7 100644
--- a/src/offset.js
+++ b/src/offset.js
@@ -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;
diff --git a/src/queue/delay.js b/src/queue/delay.js
index 037ef0998..93abd0bf2 100644
--- a/src/queue/delay.js
+++ b/src/queue/delay.js
@@ -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
index 000000000..ded014f1a
--- /dev/null
+++ b/src/var/document.js
@@ -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
index 000000000..c639670f1
--- /dev/null
+++ b/src/var/documentElement.js
@@ -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
index 000000000..1445c7b18
--- /dev/null
+++ b/test/node_smoke_tests/.jshintrc
@@ -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
index 000000000..4a0ad2e2b
--- /dev/null
+++ b/test/node_smoke_tests/document_missing.js
@@ -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
index 000000000..5999cc744
--- /dev/null
+++ b/test/node_smoke_tests/document_passed.js
@@ -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
index 000000000..f75148708
--- /dev/null
+++ b/test/node_smoke_tests/document_present_originally.js
@@ -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
index 000000000..3376ebdc5
--- /dev/null
+++ b/test/node_smoke_tests/iterable_with_native_symbol.js
@@ -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
index 000000000..dd377f19c
--- /dev/null
+++ b/test/node_smoke_tests/iterable_with_symbol_polyfill.js
@@ -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
index 000000000..7cc83b541
--- /dev/null
+++ b/test/node_smoke_tests/lib/ensure_global_not_created.js
@@ -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
index 000000000..ebe68539e
--- /dev/null
+++ b/test/node_smoke_tests/lib/ensure_iterability_es6.js
@@ -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( "" ),
+ 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
index 000000000..0933a1d33
--- /dev/null
+++ b/test/node_smoke_tests/lib/ensure_jquery.js
@@ -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
index 000000000..decc3e0f0
--- /dev/null
+++ b/test/promises_aplus_adapter.js
@@ -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 )
+ };
+ };
+} );