From 37f0f7f42cd158e36665066d88708ca4aa0713ac Mon Sep 17 00:00:00 2001 From: Oleg Gaidarenko Date: Mon, 16 Jun 2014 01:45:24 +0400 Subject: [PATCH] Ajax: Always use script injection in globalEval Fixes #14757 Ref bbdfbb4ee859fe9319b348d88120ddc2c9efbd63 --- src/core.js | 21 ++++++------- test/data/event/syncReady.html | 4 +-- test/data/{event => }/longLoadScript.php | 0 test/unit/ajax.js | 30 ++++++++----------- test/unit/core.js | 13 ++++++++ test/unit/manipulation.js | 38 +++++++++++++++--------- 6 files changed, 62 insertions(+), 44 deletions(-) rename test/data/{event => }/longLoadScript.php (100%) diff --git a/src/core.js b/src/core.js index 028d0ac02..9dacc48a8 100644 --- a/src/core.js +++ b/src/core.js @@ -275,17 +275,18 @@ jQuery.extend({ }, // Evaluates a script in a global context - // Workarounds based on findings by Jim Driscoll - // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context globalEval: function( data ) { - if ( data && jQuery.trim( data ) ) { - // We use execScript on Internet Explorer - // We use an anonymous function so that context is window - // rather than jQuery in Firefox - ( window.execScript || function( data ) { - window[ "eval" ].call( window, data ); - } )( data ); - } + // Inspired by code by Andrea Giammarchi + // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html + var head = document.head || jQuery( "head" )[ 0 ] || document.documentElement, + script = document.createElement( "script" ); + + script.text = data; + + // Support: IE6 + // Circumvent bugs with base elements (#2709 and #4378) by prepending + head.insertBefore( script, head.firstChild ); + head.removeChild( script ); }, // Convert dashed to camelCase; used by the css and data modules diff --git a/test/data/event/syncReady.html b/test/data/event/syncReady.html index e0885707e..0d2f8fdad 100644 --- a/test/data/event/syncReady.html +++ b/test/data/event/syncReady.html @@ -8,7 +8,7 @@ @@ -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/data/event/longLoadScript.php b/test/data/longLoadScript.php similarity index 100% rename from test/data/event/longLoadScript.php rename to test/data/longLoadScript.php diff --git a/test/unit/ajax.js b/test/unit/ajax.js index 97372c5a0..d2059bd36 100644 --- a/test/unit/ajax.js +++ b/test/unit/ajax.js @@ -1468,24 +1468,18 @@ module( "ajax", { } }); - test( "#11743 - jQuery.ajax() - script, throws exception", 1, function() { - throws(function() { - jQuery.ajax({ - url: "data/badjson.js", - dataType: "script", - "throws": true, - // TODO find a way to test this asynchronously, too - async: false, - // Global events get confused by the exception - global: false, - success: function() { - ok( false, "Success." ); - }, - error: function() { - ok( false, "Error." ); - } - }); - }, "exception bubbled" ); + asyncTest( "#11743 - jQuery.ajax() - script, throws exception", 1, function() { + var onerror = window.onerror; + window.onerror = function() { + ok( true, "Exception thrown" ); + window.onerror = onerror; + start(); + }; + jQuery.ajax({ + url: "data/badjson.js", + dataType: "script", + "throws": true + }); }); jQuery.each( [ "method", "type" ], function( _, globalOption ) { diff --git a/test/unit/core.js b/test/unit/core.js index ef49999e6..d59c4b0fa 100644 --- a/test/unit/core.js +++ b/test/unit/core.js @@ -214,6 +214,19 @@ test( "globalEval", function() { equal( window.globalEvalTest, 3, "Test context (this) is the window object" ); }); +test( "globalEval execution after script injection (#7862)", 1, function() { + 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() + ";"); + ok( window.strictEvalTest - now < 500, "Code executed synchronously" ); +}); + test("noConflict", function() { expect(7); diff --git a/test/unit/manipulation.js b/test/unit/manipulation.js index ad90df923..e2bfd75b1 100644 --- a/test/unit/manipulation.js +++ b/test/unit/manipulation.js @@ -2263,23 +2263,33 @@ test( "Ensure oldIE creates a new set on appendTo (#8894)", function() { strictEqual( jQuery("

").appendTo("

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

test

").appendTo("
").end().length, "Elements created with createElement and with createDocumentFragment should be treated alike" ); }); -test( "html() - script exceptions bubble (#11743)", function() { +asyncTest( "html() - script exceptions bubble (#11743)", 2, function() { - expect( 2 ); + var onerror = window.onerror; - throws(function() { - jQuery("#qunit-fixture").html(""); - ok( false, "Exception ignored" ); - }, "Exception bubbled from inline script" ); + setTimeout(function() { + window.onerror = onerror; - if ( jQuery.ajax ) { - throws(function() { - jQuery("#qunit-fixture").html(""); - ok( false, "Exception ignored" ); - }, "Exception thrown in remote script" ); - } else { - ok( true, "No jQuery.ajax" ); - } + start(); + }, 1000 ); + + window.onerror = function() { + ok( true, "Exception thrown" ); + + if ( jQuery.ajax ) { + window.onerror = function() { + ok( true, "Exception thrown in remote script" ); + }; + + jQuery( "#qunit-fixture" ).html( "" ); + ok( true, "Exception ignored" ); + } else { + ok( true, "No jQuery.ajax" ); + ok( true, "No jQuery.ajax" ); + } + }; + + jQuery( "#qunit-fixture" ).html( "" ); }); test( "checked state is cloned with clone()", function() {