9090 * - [`val()`](http://api.jquery.com/val/)
9191 * - [`wrap()`](http://api.jquery.com/wrap/)
9292 *
93+ * jqLite also provides a method restoring pre-1.8 insecure treatment of XHTML-like tags.
94+ * This legacy behavior turns input like `<div /><span />` to `<div></div><span></span>`
95+ * instead of `<div><span></span></div>` like version 1.8 & newer do. To restore it, invoke:
96+ * ```js
97+ * angular.UNSAFE_restoreLegacyJqLiteXHTMLReplacement();
98+ * ```
99+ * Note that this only patches jqLite. If you use jQuery 3.5.0 or newer, please read the
100+ * [jQuery 3.5 upgrade guide](https://jquery.com/upgrade-guide/3.5/) for more details
101+ * about the workarounds.
102+ *
93103 * ## jQuery/jqLite Extras
94104 * AngularJS also provides the following additional methods and events to both jQuery and jqLite:
95105 *
@@ -169,20 +179,36 @@ var HTML_REGEXP = /<|&#?\w+;/;
169179var TAG_NAME_REGEXP = / < ( [ \w : - ] + ) / ;
170180var XHTML_TAG_REGEXP = / < (? ! a r e a | b r | c o l | e m b e d | h r | i m g | i n p u t | l i n k | m e t a | p a r a m ) ( ( [ \w : - ] + ) [ ^ > ] * ) \/ > / gi;
171181
182+ // Table parts need to be wrapped with `<table>` or they're
183+ // stripped to their contents when put in a div.
184+ // XHTML parsers do not magically insert elements in the
185+ // same way that tag soup parsers do, so we cannot shorten
186+ // this by omitting <tbody> or other required elements.
172187var wrapMap = {
173- 'option' : [ 1 , '<select multiple="multiple">' , '</select>' ] ,
174-
175- 'thead' : [ 1 , '<table>' , '</table>' ] ,
176- 'col' : [ 2 , '<table><colgroup>' , '</colgroup></table>' ] ,
177- 'tr' : [ 2 , '<table><tbody>' , '</tbody></table>' ] ,
178- 'td' : [ 3 , '<table><tbody><tr>' , '</tr></tbody></table>' ] ,
179- '_default' : [ 0 , '' , '' ]
188+ thead : [ 'table' ] ,
189+ col : [ 'colgroup' , 'table' ] ,
190+ tr : [ 'tbody' , 'table' ] ,
191+ td : [ 'tr' , 'tbody' , 'table' ]
180192} ;
181193
182- wrapMap . optgroup = wrapMap . option ;
183194wrapMap . tbody = wrapMap . tfoot = wrapMap . colgroup = wrapMap . caption = wrapMap . thead ;
184195wrapMap . th = wrapMap . td ;
185196
197+ // Support: IE <10 only
198+ // IE 9 requires an option wrapper & it needs to have the whole table structure
199+ // set up in advance; assigning `"<td></td>"` to `tr.innerHTML` doesn't work, etc.
200+ var wrapMapIE9 = {
201+ option : [ 1 , '<select multiple="multiple">' , '</select>' ] ,
202+ _default : [ 0 , '' , '' ]
203+ } ;
204+
205+ for ( var key in wrapMap ) {
206+ var wrapMapValueClosing = wrapMap [ key ] ;
207+ var wrapMapValue = wrapMapValueClosing . slice ( ) . reverse ( ) ;
208+ wrapMapIE9 [ key ] = [ wrapMapValue . length , '<' + wrapMapValue . join ( '><' ) + '>' , '</' + wrapMapValueClosing . join ( '></' ) + '>' ] ;
209+ }
210+
211+ wrapMapIE9 . optgroup = wrapMapIE9 . option ;
186212
187213function jqLiteIsTextNode ( html ) {
188214 return ! HTML_REGEXP . test ( html ) ;
@@ -203,7 +229,7 @@ function jqLiteHasData(node) {
203229}
204230
205231function jqLiteBuildFragment ( html , context ) {
206- var tmp , tag , wrap ,
232+ var tmp , tag , wrap , finalHtml ,
207233 fragment = context . createDocumentFragment ( ) ,
208234 nodes = [ ] , i ;
209235
@@ -214,13 +240,30 @@ function jqLiteBuildFragment(html, context) {
214240 // Convert html into DOM nodes
215241 tmp = fragment . appendChild ( context . createElement ( 'div' ) ) ;
216242 tag = ( TAG_NAME_REGEXP . exec ( html ) || [ '' , '' ] ) [ 1 ] . toLowerCase ( ) ;
217- wrap = wrapMap [ tag ] || wrapMap . _default ;
218- tmp . innerHTML = wrap [ 1 ] + html . replace ( XHTML_TAG_REGEXP , '<$1></$2>' ) + wrap [ 2 ] ;
243+ finalHtml = JQLite . legacyXHTMLReplacement ?
244+ html . replace ( XHTML_TAG_REGEXP , '<$1></$2>' ) :
245+ html ;
246+
247+ if ( msie < 10 ) {
248+ wrap = wrapMapIE9 [ tag ] || wrapMapIE9 . _default ;
249+ tmp . innerHTML = wrap [ 1 ] + finalHtml + wrap [ 2 ] ;
250+
251+ // Descend through wrappers to the right content
252+ i = wrap [ 0 ] ;
253+ while ( i -- ) {
254+ tmp = tmp . firstChild ;
255+ }
256+ } else {
257+ wrap = wrapMap [ tag ] || [ ] ;
219258
220- // Descend through wrappers to the right content
221- i = wrap [ 0 ] ;
222- while ( i -- ) {
223- tmp = tmp . lastChild ;
259+ // Create wrappers & descend into them
260+ i = wrap . length ;
261+ while ( -- i > - 1 ) {
262+ tmp . appendChild ( window . document . createElement ( wrap [ i ] ) ) ;
263+ tmp = tmp . firstChild ;
264+ }
265+
266+ tmp . innerHTML = finalHtml ;
224267 }
225268
226269 nodes = concat ( nodes , tmp . childNodes ) ;
0 commit comments