diff --git a/src/core.js b/src/core.js index 31d749dd1..4f5731ae1 100644 --- a/src/core.js +++ b/src/core.js @@ -10,9 +10,8 @@ import hasOwn from "./var/hasOwn.js"; import fnToString from "./var/fnToString.js"; import ObjectFunctionString from "./var/ObjectFunctionString.js"; import support from "./var/support.js"; -import isWindow from "./var/isWindow.js"; +import isArrayLike from "./core/isArrayLike.js"; import DOMEval from "./core/DOMEval.js"; -import toType from "./core/toType.js"; var version = "@VERSION", @@ -398,17 +397,4 @@ jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symb class2type[ "[object " + name + "]" ] = name.toLowerCase(); } ); -function isArrayLike( obj ) { - - var length = !!obj && obj.length, - type = toType( obj ); - - if ( typeof obj === "function" || isWindow( obj ) ) { - return false; - } - - return type === "array" || length === 0 || - typeof length === "number" && length > 0 && ( length - 1 ) in obj; -} - export default jQuery; diff --git a/src/core/init.js b/src/core/init.js index a97fc1060..8fc24d8dd 100644 --- a/src/core/init.js +++ b/src/core/init.js @@ -2,6 +2,7 @@ import jQuery from "../core.js"; import document from "../var/document.js"; import rsingleTag from "./var/rsingleTag.js"; +import isObviousHtml from "./isObviousHtml.js"; import "../traversing/findFilter.js"; @@ -26,20 +27,41 @@ var rootjQuery, // so migrate can support jQuery.sub (gh-2101) root = root || rootjQuery; - // Handle HTML strings - if ( typeof selector === "string" ) { - if ( selector[ 0 ] === "<" && - selector[ selector.length - 1 ] === ">" && - selector.length >= 3 ) { + // HANDLE: $(DOMElement) + if ( selector.nodeType ) { + this[ 0 ] = selector; + this.length = 1; + return this; - // Assume that strings that start and end with <> are HTML and skip the regex check + // HANDLE: $(function) + // Shortcut for document ready + } else if ( typeof selector === "function" ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + + } else { + + // Handle obvious HTML strings + match = selector + ""; + if ( isObviousHtml( match ) ) { + + // Assume that strings that start and end with <> are HTML and skip + // the regex check. This also handles browser-supported HTML wrappers + // like TrustedHTML. match = [ null, selector, null ]; - } else { + // Handle HTML strings or selectors + } else if ( typeof selector === "string" ) { match = rquickExpr.exec( selector ); + } else { + return jQuery.makeArray( selector, this ); } // Match html or make sure no context is specified for #id + // Note: match[1] may be a string or a TrustedHTML wrapper if ( match && ( match[ 1 ] || !context ) ) { // HANDLE: $(html) -> $(array) @@ -84,7 +106,7 @@ var rootjQuery, return this; } - // HANDLE: $(expr, $(...)) + // HANDLE: $(expr) & $(expr, $(...)) } else if ( !context || context.jquery ) { return ( context || root ).find( selector ); @@ -93,24 +115,8 @@ var rootjQuery, } else { return this.constructor( context ).find( selector ); } - - // HANDLE: $(DOMElement) - } else if ( selector.nodeType ) { - this[ 0 ] = selector; - this.length = 1; - return this; - - // HANDLE: $(function) - // Shortcut for document ready - } else if ( typeof selector === "function" ) { - return root.ready !== undefined ? - root.ready( selector ) : - - // Execute immediately if ready is not present - selector( jQuery ); } - return jQuery.makeArray( selector, this ); }; // Give the init function the jQuery prototype for later instantiation diff --git a/src/core/isArrayLike.js b/src/core/isArrayLike.js new file mode 100644 index 000000000..988c483d3 --- /dev/null +++ b/src/core/isArrayLike.js @@ -0,0 +1,17 @@ +import toType from "./toType.js"; +import isWindow from "../var/isWindow.js"; + +function isArrayLike( obj ) { + + var length = !!obj && obj.length, + type = toType( obj ); + + if ( typeof obj === "function" || isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} + +export default isArrayLike; diff --git a/src/core/isObviousHtml.js b/src/core/isObviousHtml.js new file mode 100644 index 000000000..976f81219 --- /dev/null +++ b/src/core/isObviousHtml.js @@ -0,0 +1,7 @@ +function isObviousHtml( input ) { + return input[ 0 ] === "<" && + input[ input.length - 1 ] === ">" && + input.length >= 3; +} + +export default isObviousHtml; diff --git a/src/core/parseHTML.js b/src/core/parseHTML.js index 15278fa02..b522a5f7b 100644 --- a/src/core/parseHTML.js +++ b/src/core/parseHTML.js @@ -2,13 +2,14 @@ import jQuery from "../core.js"; import document from "../var/document.js"; import rsingleTag from "./var/rsingleTag.js"; import buildFragment from "../manipulation/buildFragment.js"; +import isObviousHtml from "./isObviousHtml.js"; -// Argument "data" should be string of html +// Argument "data" should be string of html or a TrustedHTML wrapper of obvious HTML // context (optional): If specified, the fragment will be created in this context, // defaults to document // keepScripts (optional): If true, will include scripts passed in the html string jQuery.parseHTML = function( data, context, keepScripts ) { - if ( typeof data !== "string" ) { + if ( typeof data !== "string" && !isObviousHtml( data + "" ) ) { return []; } if ( typeof context === "boolean" ) { diff --git a/src/manipulation/buildFragment.js b/src/manipulation/buildFragment.js index 9ac71acc9..d6f8e5783 100644 --- a/src/manipulation/buildFragment.js +++ b/src/manipulation/buildFragment.js @@ -7,6 +7,7 @@ import rscriptType from "./var/rscriptType.js"; import wrapMap from "./wrapMap.js"; import getAll from "./getAll.js"; import setGlobalEval from "./setGlobalEval.js"; +import isArrayLike from "../core/isArrayLike.js"; var rhtml = /<|?\w+;/; @@ -23,7 +24,7 @@ function buildFragment( elems, context, scripts, selection, ignored ) { if ( elem || elem === 0 ) { // Add nodes directly - if ( toType( elem ) === "object" ) { + if ( toType( elem ) === "object" && ( elem.nodeType || isArrayLike( elem ) ) ) { jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); // Convert non-html into a text node diff --git a/test/.eslintrc.json b/test/.eslintrc.json index f52842efa..a5509180d 100644 --- a/test/.eslintrc.json +++ b/test/.eslintrc.json @@ -14,6 +14,7 @@ "require": false, "Promise": false, "Symbol": false, + "trustedTypes": false, "QUnit": false, "ajaxTest": false, "testIframe": false, diff --git a/test/data/csp.include.html b/test/data/csp.include.html index 17e2ef0d8..59b87f212 100644 --- a/test/data/csp.include.html +++ b/test/data/csp.include.html @@ -3,7 +3,7 @@