Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 1 addition & 104 deletions src/manipulation.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
import jQuery from "./core.js";
import isAttached from "./core/isAttached.js";
import flat from "./var/flat.js";
import isIE from "./var/isIE.js";
import push from "./var/push.js";
import access from "./core/access.js";
import rtagName from "./manipulation/var/rtagName.js";
import rscriptType from "./manipulation/var/rscriptType.js";
import wrapMap from "./manipulation/wrapMap.js";
import getAll from "./manipulation/getAll.js";
import domManip from "./manipulation/domManip.js";
import setGlobalEval from "./manipulation/setGlobalEval.js";
import buildFragment from "./manipulation/buildFragment.js";
import dataPriv from "./data/var/dataPriv.js";
import dataUser from "./data/var/dataUser.js";
import acceptData from "./data/var/acceptData.js";
import DOMEval from "./core/DOMEval.js";
import nodeName from "./core/nodeName.js";

import "./core/init.js";
Expand All @@ -38,21 +35,6 @@ function manipulationTarget( elem, content ) {
return elem;
}

// Replace/restore the type attribute of script elements for safe DOM manipulation
function disableScript( elem ) {
elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type;
return elem;
}
function restoreScript( elem ) {
if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) {
elem.type = elem.type.slice( 5 );
} else {
elem.removeAttribute( "type" );
}

return elem;
}

function cloneCopyEvent( src, dest ) {
var i, l, type, pdataOld, udataOld, udataCur, events;

Expand Down Expand Up @@ -85,91 +67,6 @@ function cloneCopyEvent( src, dest ) {
}
}

function domManip( collection, args, callback, ignored ) {

// Flatten any nested arrays
args = flat( args );

var fragment, first, scripts, hasScripts, node, doc,
i = 0,
l = collection.length,
iNoClone = l - 1,
value = args[ 0 ],
valueIsFunction = typeof value === "function";

if ( valueIsFunction ) {
return collection.each( function( index ) {
var self = collection.eq( index );
args[ 0 ] = value.call( this, index, self.html() );
domManip( self, args, callback, ignored );
} );
}

if ( l ) {
fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored );
first = fragment.firstChild;

if ( fragment.childNodes.length === 1 ) {
fragment = first;
}

// Require either new content or an interest in ignored elements to invoke the callback
if ( first || ignored ) {
scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
hasScripts = scripts.length;

// Use the original fragment for the last item
// instead of the first because it can end up
// being emptied incorrectly in certain situations (trac-8070).
for ( ; i < l; i++ ) {
node = fragment;

if ( i !== iNoClone ) {
node = jQuery.clone( node, true, true );

// Keep references to cloned scripts for later restoration
if ( hasScripts ) {
jQuery.merge( scripts, getAll( node, "script" ) );
}
}

callback.call( collection[ i ], node, i );
}

if ( hasScripts ) {
doc = scripts[ scripts.length - 1 ].ownerDocument;

// Reenable scripts
jQuery.map( scripts, restoreScript );

// Evaluate executable scripts on first document insertion
for ( i = 0; i < hasScripts; i++ ) {
node = scripts[ i ];
if ( rscriptType.test( node.type || "" ) &&
!dataPriv.access( node, "globalEval" ) &&
jQuery.contains( doc, node ) ) {

if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) {

// Optional AJAX dependency, but won't run scripts if not present
if ( jQuery._evalUrl && !node.noModule ) {
jQuery._evalUrl( node.src, {
nonce: node.nonce,
crossOrigin: node.crossOrigin
}, doc );
}
} else {
DOMEval( node.textContent, node, doc );
}
}
}
}
}
}

return collection;
}

function remove( elem, selector, keepData ) {
var node,
nodes = selector ? jQuery.filter( selector, elem ) : elem,
Expand Down
109 changes: 109 additions & 0 deletions src/manipulation/domManip.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import jQuery from "../core.js";
import flat from "../var/flat.js";
import rscriptType from "./var/rscriptType.js";
import getAll from "./getAll.js";
import buildFragment from "./buildFragment.js";
import dataPriv from "../data/var/dataPriv.js";
import DOMEval from "../core/DOMEval.js";

// Replace/restore the type attribute of script elements for safe DOM manipulation
function disableScript( elem ) {
elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type;
return elem;
}
function restoreScript( elem ) {
if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) {
elem.type = elem.type.slice( 5 );
} else {
elem.removeAttribute( "type" );
}

return elem;
}

function domManip( collection, args, callback, ignored ) {

// Flatten any nested arrays
args = flat( args );

var fragment, first, scripts, hasScripts, node, doc,
i = 0,
l = collection.length,
iNoClone = l - 1,
value = args[ 0 ],
valueIsFunction = typeof value === "function";

if ( valueIsFunction ) {
return collection.each( function( index ) {
var self = collection.eq( index );
args[ 0 ] = value.call( this, index, self.html() );
domManip( self, args, callback, ignored );
} );
}

if ( l ) {
fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored );
first = fragment.firstChild;

if ( fragment.childNodes.length === 1 ) {
fragment = first;
}

// Require either new content or an interest in ignored elements to invoke the callback
if ( first || ignored ) {
scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
hasScripts = scripts.length;

// Use the original fragment for the last item
// instead of the first because it can end up
// being emptied incorrectly in certain situations (trac-8070).
for ( ; i < l; i++ ) {
node = fragment;

if ( i !== iNoClone ) {
node = jQuery.clone( node, true, true );

// Keep references to cloned scripts for later restoration
if ( hasScripts ) {
jQuery.merge( scripts, getAll( node, "script" ) );
}
}

callback.call( collection[ i ], node, i );
}

if ( hasScripts ) {
doc = scripts[ scripts.length - 1 ].ownerDocument;

// Reenable scripts
jQuery.map( scripts, restoreScript );

// Evaluate executable scripts on first document insertion
for ( i = 0; i < hasScripts; i++ ) {
node = scripts[ i ];
if ( rscriptType.test( node.type || "" ) &&
!dataPriv.access( node, "globalEval" ) &&
jQuery.contains( doc, node ) ) {

if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) {

// Optional AJAX dependency, but won't run scripts if not present
if ( jQuery._evalUrl && !node.noModule ) {
jQuery._evalUrl( node.src, {
nonce: node.nonce,
crossOrigin: node.crossOrigin
}, doc );
}
} else {
DOMEval( node.textContent, node, doc );
}
}
}
}
}
}

return collection;
}

export default domManip;
6 changes: 3 additions & 3 deletions test/unit/ajax.js
Original file line number Diff line number Diff line change
Expand Up @@ -2502,9 +2502,9 @@ if ( typeof window.ArrayBuffer === "undefined" || typeof new XMLHttpRequest().re
} );
} );

//----------- jQuery.domManip()
//----------- domManip()

QUnit.test( "trac-11264 - jQuery.domManip() - no side effect because of ajaxSetup or global events", function( assert ) {
QUnit.test( "trac-11264 - domManip() - no side effect because of ajaxSetup or global events", function( assert ) {
assert.expect( 1 );

jQuery.ajaxSetup( {
Expand Down Expand Up @@ -2558,7 +2558,7 @@ if ( typeof window.ArrayBuffer === "undefined" || typeof new XMLHttpRequest().re
);

QUnit.test(
"trac-11402 - jQuery.domManip() - script in comments are properly evaluated",
"trac-11402 - domManip() - script in comments are properly evaluated",
function( assert ) {
assert.expect( 2 );
jQuery( "#qunit-fixture" ).load( baseURL + "cleanScript.html", assert.async() );
Expand Down