Core: Fire iframe script in its context, add doc param in globalEval

1. Support passing custom document to jQuery.globalEval; the script will be
   invoked in the context of this document.
2. Fire external scripts appended to iframe contents in that iframe context;
   this was already supported & tested for inline scripts but not for external
   ones.

Fixes gh-4518
Closes gh-4601
This commit is contained in:
Michał Gołębiowski-Owczarek 2020-02-10 19:17:22 +01:00 committed by GitHub
parent 18db87172c
commit 4592595b47
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 74 additions and 10 deletions

View File

@ -231,9 +231,10 @@ jQuery.extend( {
return true;
},
// Evaluates a script in a global context
globalEval: function( code, options ) {
DOMEval( code, { nonce: options && options.nonce } );
// Evaluates a script in a provided context; falls back to the global one
// if not specified.
globalEval: function( code, options, doc ) {
DOMEval( code, { nonce: options && options.nonce }, doc );
},
each: function( obj, callback ) {

View File

@ -163,7 +163,7 @@ function domManip( collection, args, callback, ignored ) {
if ( jQuery._evalUrl && !node.noModule ) {
jQuery._evalUrl( node.src, {
nonce: node.nonce || node.getAttribute( "nonce" )
} );
}, doc );
}
} else {
DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc );

View File

@ -1,6 +1,6 @@
import jQuery from "../ajax.js";
jQuery._evalUrl = function( url, options ) {
jQuery._evalUrl = function( url, options, doc ) {
return jQuery.ajax( {
url: url,
@ -18,7 +18,7 @@ jQuery._evalUrl = function( url, options ) {
"text script": function() {}
},
dataFilter: function( response ) {
jQuery.globalEval( response, options );
jQuery.globalEval( response, options, doc );
}
} );
};

View File

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>body</title>
</head>
<body>
<div id="qunit-fixture"></div>
<script src="../../jquery.js"></script>
<script src="../iframeTest.js"></script>
<script>
startIframeTest();
</script>
</body>
</html>

View File

@ -0,0 +1,2 @@
window.scriptTest = true;
parent.finishTest();

View File

@ -254,12 +254,24 @@ this.testIframe = function( title, fileName, func, wrapper ) {
args.unshift( assert );
setTimeout( function() {
var result;
this.iframeCallback = undefined;
func.apply( this, args );
result = func.apply( this, args );
function finish() {
func = function() {};
$iframe.remove();
done();
}
// Wait for promises returned by `func`.
if ( result && result.then ) {
result.then( finish );
} else {
finish();
}
} );
};

View File

@ -197,6 +197,19 @@ QUnit.test( "globalEval execution after script injection (#7862)", function( ass
assert.ok( window.strictEvalTest - now < 500, "Code executed synchronously" );
} );
testIframe(
"globalEval with custom document context",
"core/globaleval-context.html",
function( assert, framejQuery, frameWindow, frameDocument ) {
assert.expect( 2 );
jQuery.globalEval( "window.scriptTest = true;", {}, frameDocument );
assert.ok( !window.scriptTest, "script executed in iframe context" );
assert.ok( frameWindow.scriptTest, "script executed in iframe context" );
}
);
QUnit.test( "noConflict", function( assert ) {
assert.expect( 7 );

View File

@ -2274,6 +2274,27 @@ testIframe(
}
);
testIframe(
"domManip executes external scripts in iframes in the iframes' context",
"manipulation/scripts-context.html",
function( assert, framejQuery, frameWindow, frameDocument ) {
assert.expect( 2 );
Globals.register( "finishTest" );
return new Promise( function( resolve ) {
window.finishTest = resolve;
jQuery( frameDocument.body ).append(
"<script src='" + url( "manipulation/set-global-scripttest.js" ) + "'></script>" );
assert.ok( !window.scriptTest, "script executed in iframe context" );
assert.ok( frameWindow.scriptTest, "script executed in iframe context" );
} );
},
// The AJAX module is needed for jQuery._evalUrl.
QUnit[ jQuery.ajax ? "test" : "skip" ]
);
QUnit.test( "jQuery.clone - no exceptions for object elements #9587", function( assert ) {
assert.expect( 1 );