]> source.dussan.org Git - jquery.git/commitdiff
Manipulation: Respect script crossorigin attribute in DOM manipulation
author高灰 <www@zeroplace.cn>
Tue, 22 Sep 2020 15:30:18 +0000 (23:30 +0800)
committerGitHub <noreply@github.com>
Tue, 22 Sep 2020 15:30:18 +0000 (17:30 +0200)
Fixes gh-4542
Closes gh-4563

Co-authored-by: Michał Gołębiowski-Owczarek <m.goleb@gmail.com>
src/manipulation.js
src/manipulation/_evalUrl.js
test/data/mock.php
test/middleware-mockserver.js
test/unit/manipulation.js

index 8eca61addb61309bf72f1b80e94b95640b5f26a7..7838e2293b07565043e6c0e6bce6eb91786256ba 100644 (file)
@@ -157,7 +157,8 @@ function domManip( collection, args, callback, ignored ) {
                                                        // Optional AJAX dependency, but won't run scripts if not present
                                                        if ( jQuery._evalUrl && !node.noModule ) {
                                                                jQuery._evalUrl( node.src, {
-                                                                       nonce: node.nonce || node.getAttribute( "nonce" )
+                                                                       nonce: node.nonce || node.getAttribute( "nonce" ),
+                                                                       crossOrigin: node.crossOrigin
                                                                }, doc );
                                                        }
                                                } else {
index 0f7559ff06f137a2835d09a0ba78be4fd89b9b76..8a8d63d9d404e87ac259529efb36ec5ecda75adf 100644 (file)
@@ -10,6 +10,7 @@ jQuery._evalUrl = function( url, options, doc ) {
                cache: true,
                async: false,
                global: false,
+               scriptAttrs: options.crossOrigin ? { "crossOrigin": options.crossOrigin } : undefined,
 
                // Only evaluate the response if it is successful (gh-4126)
                // dataFilter is not invoked for failure responses, so using it instead
index b76fd521c3bd874d3387702dcc3609fc21ed6256..24302e6bcd9e59a3f048dae735bb59c033de8722 100644 (file)
@@ -54,7 +54,21 @@ class MockServer {
                } else {
                        header( 'Content-type: text/html' );
                }
-               echo 'QUnit.assert.ok( true, "mock executed" );';
+
+               if ( !empty( $req->query['cors'] ) ) {
+                       header( "Access-Control-Allow-Origin: *" );
+               }
+
+               if ( !empty( $req->query['callback'] ) ) {
+                       $headers = array_combine(
+                               array_map( 'strtolower', array_keys( $req->headers ) ),
+                               array_values( $req->headers )
+                       );
+
+                       echo $req->query['callback'] . "(" . json_encode( [ 'headers' => $headers ] ) . ")";
+               } else {
+                       echo 'QUnit.assert.ok( true, "mock executed" );';
+               }
        }
 
        // Used to be in test.js, but was renamed to testbar.php
index b3f630dd5413950dcdafd7d39925114d27261841..863aaf6bd02e3a5fa12d5cbfcf012204136fea92 100644 (file)
@@ -67,7 +67,18 @@ var mocks = {
                } else {
                        resp.writeHead( 200, { "content-type": "text/html" } );
                }
-               resp.end( "QUnit.assert.ok( true, \"mock executed\" );" );
+
+               if ( req.query.cors ) {
+                       resp.writeHead( 200, { "access-control-allow-origin": "*" } );
+               }
+
+               if ( req.query.callback ) {
+                       resp.end( req.query.callback + "(" + JSON.stringify( {
+                               headers: req.headers
+                       } ) + ")" );
+               } else {
+                       resp.end( "QUnit.assert.ok( true, \"mock executed\" );" );
+               }
        },
        testbar: function( req, resp ) {
                resp.writeHead( 200 );
index a4a46f924adff321dd05151b89349f5988074c0b..9058c1649c7c97e69a118840eb1e48e85ae98a32 100644 (file)
@@ -2295,6 +2295,39 @@ testIframe(
        QUnit[ jQuery.ajax ? "test" : "skip" ]
 );
 
+
+// We need to simulate cross-domain requests with the feature that
+// both 127.0.0.1 and localhost point to the mock http server.
+// Skip the the test if we are not in localhost but make sure we run
+// it in Karma.
+QUnit[
+       jQuery.ajax && ( window.__karma__ || location.hostname === "localhost" ) ?
+               "test" :
+               "skip"
+]( "jQuery.append with crossorigin attribute", function( assert ) {
+       assert.expect( 1 );
+
+       var done = assert.async(),
+               timeout;
+
+       Globals.register( "corsCallback" );
+       window.corsCallback = function( response ) {
+               assert.ok( typeof response.headers.origin === "string", "Origin header sent" );
+               window.clearTimeout( timeout );
+               done();
+       };
+
+       var src = baseURL + "mock.php?action=script&cors=1&callback=corsCallback";
+       src = src.replace( "localhost", "127.0.0.1" );
+       var html = "<script type=\"text/javascript\" src=\"" + src + "\" crossorigin=\"anonymous\"><\/script>";
+
+       jQuery( document.body ).append( html );
+       timeout = window.setTimeout( function() {
+               assert.ok( false, "Origin header should have been sent" );
+               done();
+       }, 2000 );
+} );
+
 QUnit.test( "jQuery.clone - no exceptions for object elements #9587", function( assert ) {
 
        assert.expect( 1 );