From 91acd85b167e39e05e8f4fb1be6f75cdcac9c466 Mon Sep 17 00:00:00 2001 From: Oleg Gaidarenko Date: Fri, 13 Nov 2015 19:48:45 +0300 Subject: [PATCH] Revert "Ajax: Always use script injection in globalEval" This reverts commit bbdfbb4ee859fe9319b348d88120ddc2c9efbd63. --- src/core.js | 26 +++++++++--- test/data/{ => event}/longLoadScript.php | 0 test/data/event/syncReady.html | 2 +- test/unit/ajax.js | 14 +++++-- test/unit/core.js | 15 ------- test/unit/manipulation.js | 53 ++++++++---------------- 6 files changed, 50 insertions(+), 60 deletions(-) rename test/data/{ => event}/longLoadScript.php (100%) diff --git a/src/core.js b/src/core.js index 72f4de2a0..d3c08c636 100644 --- a/src/core.js +++ b/src/core.js @@ -262,12 +262,26 @@ jQuery.extend( { }, // Evaluates a script in a global context - globalEval: function( code, context ) { - context = context || document; - var script = context.createElement( "script" ); - - script.text = code; - context.head.appendChild( script ).parentNode.removeChild( script ); + globalEval: function( code ) { + var script, + indirect = eval; + + code = jQuery.trim( code ); + + if ( code ) { + // If the code includes a valid, prologue position + // strict mode pragma, execute code by injecting a + // script tag into the document. + if ( code.indexOf("use strict") === 1 ) { + script = document.createElement("script"); + script.text = code; + document.head.appendChild( script ).parentNode.removeChild( script ); + } else { + // Otherwise, avoid the DOM node creation, insertion + // and removal by using an indirect global eval + indirect( code ); + } + } }, // Convert dashed to camelCase; used by the css and data modules diff --git a/test/data/longLoadScript.php b/test/data/event/longLoadScript.php similarity index 100% rename from test/data/longLoadScript.php rename to test/data/event/longLoadScript.php diff --git a/test/data/event/syncReady.html b/test/data/event/syncReady.html index dfa9ac337..e0885707e 100644 --- a/test/data/event/syncReady.html +++ b/test/data/event/syncReady.html @@ -17,7 +17,7 @@ jQuery( document ).ready(function () { oldIE into thinking the dom is ready, but it's not... leaving this check here for future trailblazers to attempt fixing this...--> - +
diff --git a/test/unit/ajax.js b/test/unit/ajax.js index 5110a9795..3d3bfb9aa 100644 --- a/test/unit/ajax.js +++ b/test/unit/ajax.js @@ -1624,9 +1624,17 @@ if ( typeof window.ArrayBuffer === "undefined" || typeof new XMLHttpRequest().re jQuery.ajax( { url: "data/badjson.js", dataType: "script", - throws: true - } ); - } ); + throws: true, + // Global events get confused by the exception + global: false, + success: function() { + ok( false, "Success." ); + }, + error: function() { + ok( false, "Error." ); + } + }); + }); jQuery.each( [ "method", "type" ], function( _, globalOption ) { function request( assert, option ) { diff --git a/test/unit/core.js b/test/unit/core.js index 33a98cedc..6aa2a3d63 100644 --- a/test/unit/core.js +++ b/test/unit/core.js @@ -170,21 +170,6 @@ QUnit.test( "globalEval with 'use strict'", function( assert ) { assert.equal( window.strictEvalTest, 1, "Test variable declarations are global (strict mode)" ); } ); -QUnit.test( "globalEval execution after script injection (#7862)", function( assert ) { - assert.expect( 1 ); - - var now, - script = document.createElement( "script" ); - - script.src = "data/longLoadScript.php?sleep=2"; - - now = jQuery.now(); - document.body.appendChild( script ); - - jQuery.globalEval( "var strictEvalTest = " + jQuery.now() + ";" ); - assert.ok( window.strictEvalTest - now < 500, "Code executed synchronously" ); -} ); - // This is not run in AMD mode if ( jQuery.noConflict ) { QUnit.test( "noConflict", function( assert ) { diff --git a/test/unit/manipulation.js b/test/unit/manipulation.js index 2069ee5c5..e62eae16b 100644 --- a/test/unit/manipulation.js +++ b/test/unit/manipulation.js @@ -2297,45 +2297,28 @@ QUnit.test( "Ensure oldIE creates a new set on appendTo (#8894)", function( asse assert.strictEqual( jQuery( "

" ).appendTo( "

" ).end().length, jQuery( "

test

" ).appendTo( "
" ).end().length, "Elements created with createElement and with createDocumentFragment should be treated alike" ); } ); -QUnit.asyncTest( "html() - script exceptions bubble (#11743)", 2, function( assert ) { +QUnit.test( "html() - script exceptions bubble (#11743)", function( assert ) { + assert.expect( 3 ); - // Support: Android 2.3 only - // Android 2.3 doesn't fire the window.onerror handler, just accept the reality there. - if ( /android 2\.3/i.test( navigator.userAgent ) ) { - assert.ok( true, "Test skipped, Android 2.3 doesn't fire window.onerror for " + - "errors in dynamically included scripts" ); - assert.ok( true, "Test skipped, Android 2.3 doesn't fire window.onerror for " + - "errors in dynamically included scripts" ); - QUnit.start(); - return; - } + assert.throws(function() { + jQuery("#qunit-fixture").html(""); + assert.ok( false, "Exception ignored" ); + }, "Exception bubbled from inline script" ); - var onerror = window.onerror; + if ( jQuery.ajax ) { + var onerror = window.onerror; + window.onerror = function() { + ok( true, "Exception thrown in remote script" ); + }; - setTimeout( function() { + jQuery("#qunit-fixture").html(""); + assert.ok( true, "Exception ignored" ); window.onerror = onerror; - - QUnit.start(); - }, 1000 ); - - window.onerror = function() { - assert.ok( true, "Exception thrown" ); - - if ( jQuery.ajax ) { - window.onerror = function() { - assert.ok( true, "Exception thrown in remote script" ); - }; - - jQuery( "#qunit-fixture" ).html( "" ); - assert.ok( true, "Exception ignored" ); - } else { - assert.ok( true, "No jQuery.ajax" ); - assert.ok( true, "No jQuery.ajax" ); - } - }; - - jQuery( "#qunit-fixture" ).html( "" ); -} ); + } else { + assert.ok( true, "No jQuery.ajax" ); + assert.ok( true, "No jQuery.ajax" ); + } +}); QUnit.test( "checked state is cloned with clone()", function( assert ) { -- 2.39.5