Revision: 10374
Author: zun...@google.com
Date: Tue Jun 21 14:52:10 2011
Log: Cherry picking r10362 into GWT 2.4 release
http://code.google.com/p/google-web-toolkit/source/detail?r=10374
Added:
/releases/2.4/user/src/com/google/gwt/core/client/ScriptInjector.java
/releases/2.4/user/test/com/google/gwt/core/client/ScriptInjectorTest.java
/releases/2.4/user/test/com/google/gwt/core/public
/releases/2.4/user/test/com/google/gwt/core/public/script_injector_test4.js
/releases/2.4/user/test/com/google/gwt/core/public/script_injector_test5.js
/releases/2.4/user/test/com/google/gwt/core/public/script_injector_test6.js
/releases/2.4/user/test/com/google/gwt/core/public/script_injector_test7.js
Modified:
/releases/2.4/user/test/com/google/gwt/core/CoreSuite.java
=======================================
--- /dev/null
+++ /releases/2.4/user/src/com/google/gwt/core/client/ScriptInjector.java
Tue Jun 21 14:52:10 2011
@@ -0,0 +1,300 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
not
+ * use this file except in compliance with the License. You may obtain a
copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
under
+ * the License.
+ */
+
+package com.google.gwt.core.client;
+
+/*
+ * Design note: This class intentionally does not use the GWT DOM wrappers
so
+ * that this code can pull in as few dependencies as possible and live in
the
+ * Core module.
+ */
+
+/**
+ * Dynamically create a script tag and attach it to the DOM.
+ *
+ * Usage with script as local string:
+ * <p>
+ *
+ * <pre>
+ * String scriptBody = "var foo = ...";
+ * ScriptInjector.fromString(scriptBody).inject();
+ * </pre>
+ * <p>
+ * Usage with script loaded as URL:
+ * <p>
+ *
+ * <pre>
+ * ScriptInjector.fromUrl("http://example.com/foo.js").setCallback(
+ * new Callback<Void, Exception>() {
+ * public void onFailure(Exception reason) {
+ * Window.alert("Script load failed.");
+ * }
+ * public void onSuccess(Void result) {
+ * Window.alert("Script load success.");
+ * }
+ * }).inject();
+ * </pre>
+ *
+ *
+ */
+public class ScriptInjector {
+
+ /**
+ * Builder for directly injecting a script body into the DOM.
+ */
+ public static class FromString {
+ private boolean removeTag = true;
+ private final String scriptBody;
+ private JavaScriptObject window;
+
+ /**
+ * @param scriptBody The script text to install into the document.
+ */
+ public FromString(String scriptBody) {
+ this.scriptBody = scriptBody;
+ }
+
+ /**
+ * Injects a script into the DOM. The JavaScript is evaluated and will
be
+ * available immediately when this call returns.
+ *
+ * By default, the script is installed in the same window that the GWT
code
+ * is installed in.
+ *
+ * @return the script element created for the injection. Note that it
may be
+ * removed from the DOM.
+ */
+ public JavaScriptObject inject() {
+ JavaScriptObject wnd = (window == null) ? nativeDefaultWindow() :
window;
+ assert wnd != null;
+ JavaScriptObject doc = nativeGetDocument(wnd);
+ assert doc != null;
+ JavaScriptObject scriptElement = nativeMakeScriptElement(doc);
+ assert scriptElement != null;
+ nativeSetText(scriptElement, scriptBody);
+ nativeAttachToHead(doc, scriptElement);
+ if (removeTag) {
+ nativeRemove(scriptElement);
+ }
+ return scriptElement;
+ }
+
+ /**
+ * @param removeTag If true, remove the tag immediately after
injecting the
+ * source. This shrinks the DOM, possibly at the expense of
+ * readability if you are debugging javaScript.
+ *
+ * Default value is {@code true}.
+ */
+ public FromString setRemoveTag(boolean removeTag) {
+ this.removeTag = removeTag;
+ return this;
+ }
+
+ /**
+ * @param window Specify which window to use to install the script. If
not
+ * specified, the top current window GWT is loaded in is used.
+ */
+ public FromString setWindow(JavaScriptObject window) {
+ this.window = window;
+ return this;
+ }
+ }
+
+ /**
+ * Build an injection call for adding a script by URL.
+ */
+ public static class FromUrl {
+ private Callback<Void, Exception> callback;
+ private final String scriptUrl;
+ private JavaScriptObject window;
+
+ private FromUrl(String scriptUrl) {
+ this.scriptUrl = scriptUrl;
+ }
+
+ /**
+ * Injects an external JavaScript reference into the document and
optionally
+ * calls a callback when it finishes loading.
+ *
+ * @return the script element created for the injection.
+ */
+ public JavaScriptObject inject() {
+ JavaScriptObject wnd = (window == null) ? nativeDefaultWindow() :
window;
+ assert wnd != null;
+ JavaScriptObject doc = nativeGetDocument(wnd);
+ assert doc != null;
+ JavaScriptObject scriptElement = nativeMakeScriptElement(doc);
+ assert scriptElement != null;
+ if (callback != null) {
+ attachListeners(scriptElement, callback);
+ }
+ nativeSetSrc(scriptElement, scriptUrl);
+ nativeAttachToHead(doc, scriptElement);
+ return scriptElement;
+ }
+
+ /**
+ * Specify a callback to be invoked when the script is loaded or
loading
+ * encounters an error.
+ *
+ * <b>Warning:</b> This class attempts to return onFailure() if the
browser
+ * detects a load failure and calls the script objects onFailure()
method,
+ * but it may not be reliable (doesn't work on IE7).
+ * <p>
+ * <b>Warning:</b> This class <b>does not</b> control whether or not a
URL
+ * has already been injected into the document. The client of this
class has
+ * the responsibility of keeping score of the injected JavaScript
files.
+ *
+ * @param callback callback that gets invoked asynchronously.
+ */
+ public FromUrl setCallback(Callback<Void, Exception> callback) {
+ this.callback = callback;
+ return this;
+ }
+
+ /**
+ * This call allows you to specify which DOM window object to install
the
+ * script tag in. To install into the Top level window call
+ *
+ * <code>
+ * builder.setWindow(ScriptInjector.TOP_WINDOW);
+ * </code>
+ *
+ * @param window Specifies which window to install in.
+ */
+ public FromUrl setWindow(JavaScriptObject window) {
+ this.window = window;
+ return this;
+ }
+ }
+
+ /**
+ * Returns the top level window object. Use this to inject a script so
that
+ * global variable references are available under <code>$wnd</code> in
JSNI
+ * access.
+ * <p>
+ * Note that if your GWT app is loaded from a different domain than the
top
+ * window, you may not be able to add a script element to the top window.
+ */
+ public static final JavaScriptObject TOP_WINDOW = nativeTopWindow();
+
+ /**
+ * Build an injection call for directly setting the script text in the
DOM.
+ *
+ * @param scriptBody the script text to be injected and immediately
executed.
+ */
+ public static FromString fromString(String scriptBody) {
+ return new FromString(scriptBody);
+ }
+
+ /**
+ * Build an injection call for adding a script by URL.
+ *
+ * @param scriptUrl URL of the JavaScript to be injected.
+ */
+ public static FromUrl fromUrl(String scriptUrl) {
+ return new FromUrl(scriptUrl);
+ }
+
+ /**
+ * Attaches event handlers to a script DOM element that will run just
once a
+ * callback when it gets successfully loaded.
+ * <p>
+ * <b>IE Notes:</b> Internet Explorer calls {@code onreadystatechanged}
+ * several times while varying the {@code readyState} property: in
theory,
+ * {@code "complete"} means the content is loaded, parsed and ready to be
+ * used, but in practice, {@code "complete"} happens when the JS file was
+ * already cached, and {@code "loaded"} happens when it was transferred
over
+ * the network. Other browsers just call the {@code onload} event
handler. To
+ * ensure the callback will be called at most once, we clear out both
event
+ * handlers when the callback runs for the first time. More info at the
<a
+ *
href="http://www.phpied.com/javascript-include-ready-onload/">phpied.com
+ * blog</a>.
+ * <p>
+ * In IE, do not trust the "order" of {@code readyState} values. For
instance,
+ * in IE 8 running in Vista, if the JS file is cached, only
{@code "complete"}
+ * will happen, but if the file has to be downloaded, {@code "loaded"}
can
+ * fire in parallel with {@code "loading"}.
+ *
+ *
+ * @param scriptElement element to which the event handlers will be
attached
+ * @param callback callback that runs when the script is loaded and
parsed.
+ */
+ private static native void attachListeners(JavaScriptObject
scriptElement,
+ Callback<Void, Exception> callback) /*-{
+ function clearCallbacks() {
+ scriptElement.onerror = scriptElement.onreadystatechange =
scriptElement.onload = function() {
+ };
+ }
+ scriptElement.onload = $entry(function() {
+ clearCallbacks();
+
callba...@com.google.gwt.core.client.Callback::onSuccess(Ljava/lang/Object;)(null);
+ });
+ // or possibly more portable script_tag.addEventListener('error',
function(){...}, true);
+ scriptElement.onerror = $entry(function() {
+ clearCallbacks();
+ var ex =
@com.google.gwt.core.client.CodeDownloadException::new(Ljava/lang/String;)("onerror()
called.");
+
callba...@com.google.gwt.core.client.Callback::onFailure(Ljava/lang/Object;)(ex)
+ });
+ scriptElement.onreadystatechange = $entry(function() {
+ if (scriptElement.readyState == 'complete' ||
scriptElement.readyState == 'loaded') {
+ scriptElement.onload();
+ }
+ });
+ }-*/;
+
+ private static native void nativeAttachToHead(JavaScriptObject doc,
JavaScriptObject scriptElement) /*-{
+ doc.getElementsByTagName("head")[0].appendChild(scriptElement);
+ }-*/;
+
+ private static native JavaScriptObject nativeDefaultWindow() /*-{
+ return window;
+ }-*/;
+
+ private static native JavaScriptObject
nativeGetDocument(JavaScriptObject wnd) /*-{
+ return wnd.document;
+ }-*/;
+
+ private static native JavaScriptObject
nativeMakeScriptElement(JavaScriptObject doc) /*-{
+ var element = doc.createElement("script");
+ element.type = "text/javascript";
+ return element;
+ }-*/;
+
+ private static native void nativeRemove(JavaScriptObject scriptElement)
/*-{
+ var p = scriptElement.parentNode;
+ p.removeChild(scriptElement);
+ }-*/;
+
+ private static native void nativeSetSrc(JavaScriptObject element, String
url) /*-{
+ element.src = url;
+ }-*/;
+
+ private static native void nativeSetText(JavaScriptObject element,
String scriptBody) /*-{
+ element.text = scriptBody;
+ }-*/;
+
+ private static native JavaScriptObject nativeTopWindow() /*-{
+ return $wnd;
+ }-*/;
+
+ /**
+ * Utility class - do not instantiate
+ */
+ private ScriptInjector() {
+ }
+}
=======================================
--- /dev/null
+++
/releases/2.4/user/test/com/google/gwt/core/client/ScriptInjectorTest.java
Tue Jun 21 14:52:10 2011
@@ -0,0 +1,428 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
not
+ * use this file except in compliance with the License. You may obtain a
copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
under
+ * the License.
+ */
+
+package com.google.gwt.core.client;
+
+import com.google.gwt.core.client.Scheduler.RepeatingCommand;
+import com.google.gwt.core.client.ScriptInjector.FromString;
+import com.google.gwt.junit.client.GWTTestCase;
+
+/**
+ * Tests for {@link ScriptInjector}
+ */
+public class ScriptInjectorTest extends GWTTestCase {
+ private static boolean browserChecked = false;
+ private static final int CHECK_DELAY = 100;
+
+ private static boolean isIE = false;
+ private static final int TEST_DELAY = 10000;
+
+ /**
+ * Check if the browser is IE6,7,8,9.
+ *
+ * @return <code>true</code> if the browser is IE6, IE7, IE8, IE9
+ * <code>false</code> any other browser
+ */
+ static boolean isIE() {
+ if (!browserChecked) {
+ isIE = isIEImpl();
+ browserChecked = true;
+ }
+ return isIE;
+ }
+
+ private static native boolean isIEImpl() /*-{
+ var ua = navigator.userAgent.toLowerCase();
+ if (ua.indexOf("msie") != -1) {
+ return true;
+ }
+ return false;
+ }-*/;
+
+ @Override
+ public String getModuleName() {
+ return "com.google.gwt.core.Core";
+ }
+
+ /**
+ * Install a script in the same window as GWT.
+ */
+ public void testInjectDirectThisWindow() {
+ delayTestFinish(TEST_DELAY);
+ String scriptBody = "__ti1_var__ = 1;";
+ assertFalse(nativeTest1Worked());
+ new FromString(scriptBody).inject();
+ boolean worked = nativeTest1Worked();
+ JavaScriptObject scriptElement =
findScriptTextInThisWindow(scriptBody);
+ if (!isIE()) {
+ cleanupThisWindow("__ti1_var__", scriptElement);
+ assertFalse("cleanup failed", nativeTest1Worked());
+ }
+ assertTrue("__ti1_var not set in this window", worked);
+ assertNull("script element 1 not removed by injection", scriptElement);
+ finishTest();
+ }
+
+ /**
+ * Install a script in the top window.
+ */
+ public void testInjectDirectTopWindow() {
+ String scriptBody = "__ti2_var__ = 2;";
+ assertFalse(nativeTest2Worked());
+
ScriptInjector.fromString(scriptBody).setWindow(ScriptInjector.TOP_WINDOW).inject();
+ boolean worked = nativeTest2Worked();
+ JavaScriptObject scriptElement = findScriptTextInTopWindow(scriptBody);
+ if (!isIE()) {
+ cleanupTopWindow("__ti2_var__", scriptElement);
+ assertTrue("__ti2_var not set in top window", worked);
+ }
+ assertNull("script element 2 not removed by injection", scriptElement);
+ }
+
+ /**
+ * Install a script in the same window as GWT, turn off the tag removal.
+ */
+ public void testInjectDirectWithoutRemoveTag() {
+ assertFalse(nativeTest3Worked());
+ String scriptBody = "__ti3_var__ = 3;";
+ new FromString(scriptBody).setRemoveTag(false).inject();
+ boolean worked = nativeTest3Worked();
+ JavaScriptObject scriptElement =
findScriptTextInThisWindow(scriptBody);
+ if (!isIE()) {
+ cleanupThisWindow("__ti3_var__", scriptElement);
+ assertFalse("cleanup failed", nativeTest3Worked());
+ }
+ assertTrue(worked);
+ assertNotNull("script element 3 should have been left in DOM",
scriptElement);
+ }
+
+ /**
+ * Inject an absolute URL on this window.
+ */
+ public void testInjectUrlAbsolute() {
+ delayTestFinish(TEST_DELAY);
+ final String scriptUrl = "http://www.google.com/jsapi?key=GWTUNITEST";
+ assertFalse(nativeInjectUrlAbsoluteWorked());
+ ScriptInjector.fromUrl(scriptUrl).setCallback(new Callback<Void,
Exception>() {
+
+ @Override
+ public void onFailure(Exception reason) {
+ assertNotNull(reason);
+ fail("Injection failed: " + reason.toString());
+ }
+
+ @Override
+ public void onSuccess(Void result) {
+ assertTrue(nativeInjectUrlAbsoluteWorked());
+ finishTest();
+ }
+
+ }).inject();
+ }
+
+ /**
+ * Inject an absolute URL on the top level window.
+ */
+ public void testInjectUrlAbsoluteTop() {
+ delayTestFinish(TEST_DELAY);
+ final String scriptUrl
= "http://www.google.com/jsapi?key=GWTUNITEST_ABSOLUTE";
+ assertFalse(nativeAbsoluteTopUrlIsLoaded());
+
ScriptInjector.fromUrl(scriptUrl).setWindow(ScriptInjector.TOP_WINDOW).setCallback(
+ new Callback<Void, Exception>() {
+
+ @Override
+ public void onFailure(Exception reason) {
+ assertNotNull(reason);
+ fail("Injection failed: " + reason.toString());
+ }
+
+ @Override
+ public void onSuccess(Void result) {
+ assertTrue(nativeAbsoluteTopUrlIsLoaded());
+ finishTest();
+ }
+ }).inject();
+ }
+
+ /**
+ * This script injection should fail and fire the onFailure callback.
+ *
+ * Note, this won't work on IE. The script.onerror tag has been busted
for <a
+ * href=
+
* "http://stackoverflow.com/questions/2027849/how-to-trigger-script-onerror-in-internet-explorer/2032014#2032014"
+ * >aeons</a>.
+ *
+ */
+ public void testInjectUrlFail() {
+ if (isIE()) {
+ return;
+ }
+ delayTestFinish(TEST_DELAY);
+ final String scriptUrl = "uNkNoWn_sCrIpT_404.js";
+ JavaScriptObject injectedElement =
+ ScriptInjector.fromUrl(scriptUrl).setCallback(new Callback<Void,
Exception>() {
+
+ @Override
+ public void onFailure(Exception reason) {
+ assertNotNull(reason);
+ finishTest();
+ }
+
+ @Override
+ public void onSuccess(Void result) {
+ fail("Injection unexpectedly succeeded.");
+ }
+ }).inject();
+ assertNotNull(injectedElement);
+ }
+
+ /**
+ * Install a script in the same window as GWT by URL
+ */
+ public void testInjectUrlThisWindow() {
+ this.delayTestFinish(TEST_DELAY);
+ final String scriptUrl = "script_injector_test4.js";
+ assertFalse(nativeTest4Worked());
+ final JavaScriptObject injectedElement =
ScriptInjector.fromUrl(scriptUrl).inject();
+
+ // We'll check using a callback in another test. This test will poll
to see
+ // that the script had an effect.
+ Scheduler.get().scheduleFixedDelay(new RepeatingCommand() {
+ int numLoops = 0;
+
+ @Override
+ public boolean execute() {
+ numLoops++;
+ boolean worked = nativeTest4Worked();
+ if (!worked && (numLoops * CHECK_DELAY < TEST_DELAY)) {
+ return true;
+ }
+ JavaScriptObject scriptElement =
findScriptUrlInThisWindow(scriptUrl);
+ if (!isIE()) {
+ cleanupThisWindow("__ti4_var__", scriptElement);
+ assertFalse("cleanup failed", nativeTest4Worked());
+ }
+ assertTrue("__ti4_var not set in this window", worked);
+ assertNotNull("script element 4 not found", scriptElement);
+ assertEquals(injectedElement, scriptElement);
+ finishTest();
+
+ // never reached
+ return false;
+ }
+ }, CHECK_DELAY);
+ assertNotNull(injectedElement);
+ }
+
+ /**
+ * Install a script in the same window as GWT by URL
+ */
+ public void testInjectUrlThisWindowCallback() {
+ delayTestFinish(TEST_DELAY);
+ final String scriptUrl = "script_injector_test5.js";
+ assertFalse(nativeTest5Worked());
+ JavaScriptObject injectedElement =
+ ScriptInjector.fromUrl(scriptUrl).setCallback(new Callback<Void,
Exception>() {
+ @Override
+ public void onFailure(Exception reason) {
+ assertNotNull(reason);
+ fail("Injection failed: " + reason.toString());
+ }
+
+ @Override
+ public void onSuccess(Void result) {
+ boolean worked = nativeTest5Worked();
+ JavaScriptObject scriptElement =
findScriptUrlInThisWindow(scriptUrl);
+ if (!isIE()) {
+ cleanupThisWindow("__ti5_var__", scriptElement);
+ assertFalse("cleanup failed", nativeTest5Worked());
+ }
+ assertTrue("__ti5_var not set in this window", worked);
+ assertNotNull("script element 5 not found", scriptElement);
+ finishTest();
+ }
+ }).inject();
+ assertNotNull(injectedElement);
+ }
+
+ /**
+ * Install a script in the top window by URL
+ */
+ public void testInjectUrlTopWindow() {
+ final String scriptUrl = "script_injector_test6.js";
+ assertFalse(nativeTest6Worked());
+ JavaScriptObject injectedElement =
+
ScriptInjector.fromUrl(scriptUrl).setWindow(ScriptInjector.TOP_WINDOW).inject();
+ // We'll check using a callback in another test. This test will poll
to see
+ // that the script had an effect.
+ Scheduler.get().scheduleFixedDelay(new RepeatingCommand() {
+ int numLoops = 0;
+
+ @Override
+ public boolean execute() {
+ numLoops++;
+
+ boolean worked = nativeTest6Worked();
+ if (!worked && (numLoops * CHECK_DELAY < TEST_DELAY)) {
+ return true;
+ }
+ JavaScriptObject scriptElement =
findScriptUrlInTopWindow(scriptUrl);
+ if (!isIE()) {
+ cleanupTopWindow("__ti6_var__", scriptElement);
+ assertFalse("cleanup failed", nativeTest6Worked());
+ }
+ assertTrue("__ti6_var not set in top window", worked);
+ assertNotNull("script element 6 not found", scriptElement);
+ finishTest();
+ // never reached
+ return false;
+ }
+ }, CHECK_DELAY);
+ assertNotNull(injectedElement);
+ }
+
+ /**
+ * Install a script in the top window by URL
+ */
+ public void testInjectUrlTopWindowCallback() {
+ delayTestFinish(TEST_DELAY);
+ final String scriptUrl = "script_injector_test7.js";
+ assertFalse(nativeTest7Worked());
+ JavaScriptObject injectedElement =
+
ScriptInjector.fromUrl(scriptUrl).setWindow(ScriptInjector.TOP_WINDOW).setCallback(
+ new Callback<Void, Exception>() {
+
+ @Override
+ public void onFailure(Exception reason) {
+ assertNotNull(reason);
+ fail("Injection failed: " + reason.toString());
+ }
+
+ @Override
+ public void onSuccess(Void result) {
+ boolean worked = nativeTest7Worked();
+ JavaScriptObject scriptElement =
findScriptUrlInTopWindow(scriptUrl);
+ if (!isIE()) {
+ cleanupTopWindow("__ti7_var__", scriptElement);
+ assertFalse("cleanup failed", nativeTest7Worked());
+ }
+ assertTrue("__ti7_var not set in top window", worked);
+ assertNotNull("script element 7 not found", scriptElement);
+ finishTest();
+ }
+ }).inject();
+ assertNotNull(injectedElement);
+ }
+
+ private void cleanupThisWindow(String property, JavaScriptObject
scriptElement) {
+ cleanupWindow(nativeThisWindow(), property, scriptElement);
+ }
+
+ private void cleanupTopWindow(String property, JavaScriptObject
scriptElement) {
+ cleanupWindow(nativeTopWindow(), property, scriptElement);
+ }
+
+ private native void cleanupWindow(JavaScriptObject wnd, String property,
+ JavaScriptObject scriptElement) /*-{
+ delete wnd[property];
+ if (scriptElement) {
+ scriptElement.parentNode.removeChild(scriptElement);
+ }
+ }-*/;
+
+ private JavaScriptObject findScriptTextInThisWindow(String text) {
+ return nativeFindScriptText(nativeThisWindow(), text);
+ }
+
+ private JavaScriptObject findScriptTextInTopWindow(String text) {
+ return nativeFindScriptText(nativeTopWindow(), text);
+ }
+
+ private JavaScriptObject findScriptUrlInThisWindow(String url) {
+ return nativeFindScriptUrl(nativeThisWindow(), url);
+ }
+
+ private JavaScriptObject findScriptUrlInTopWindow(String url) {
+ return nativeFindScriptUrl(nativeTopWindow(), url);
+ }
+
+ private native boolean nativeAbsoluteTopUrlIsLoaded() /*-{
+ return !!$wnd.google && !!$wnd.google.load;
+ }-*/;
+
+ private native JavaScriptObject nativeFindScriptText(JavaScriptObject
wnd, String text) /*-{
+ var scripts = wnd.document.getElementsByTagName("script");
+ for ( var i = 0; i < scripts.length; ++i) {
+ if (scripts[i].text.match("^" + text)) {
+ return scripts[i];
+ }
+ }
+ return null;
+ }-*/;
+
+ /**
+ * Won't work for all urls, uses a regular expression match
+ */
+ private native JavaScriptObject nativeFindScriptUrl(JavaScriptObject
wnd, String url) /*-{
+ var scripts = wnd.document.getElementsByTagName("script");
+ for ( var i = 0; i < scripts.length; ++i) {
+ if (scripts[i].src.match(url)) {
+ return scripts[i];
+ }
+ }
+ return null;
+ }-*/;
+
+ private native boolean nativeInjectUrlAbsoluteWorked() /*-{
+ return !!window.google && !!window.google.load;
+ }-*/;
+
+ private native boolean nativeTest1Worked() /*-{
+ return !!window["__ti1_var__"] && window["__ti1_var__"] == 1;
+ }-*/;
+
+ private native boolean nativeTest2Worked() /*-{
+ return !!$wnd["__ti2_var__"] && $wnd["__ti2_var__"] == 2;
+ }-*/;
+
+ private native boolean nativeTest3Worked() /*-{
+ return !!window["__ti3_var__"] && window["__ti3_var__"] == 3;
+ }-*/;
+
+ private native boolean nativeTest4Worked() /*-{
+ return !!window["__ti4_var__"] && window["__ti4_var__"] == 4;
+ }-*/;
+
+ private native boolean nativeTest5Worked() /*-{
+ return !!window["__ti5_var__"] && window["__ti5_var__"] == 5;
+ }-*/;
+
+ private native boolean nativeTest6Worked() /*-{
+ return !!$wnd["__ti6_var__"] && $wnd["__ti6_var__"] == 6;
+ }-*/;
+
+ private native boolean nativeTest7Worked() /*-{
+ return !!$wnd["__ti7_var__"] && $wnd["__ti7_var__"] == 7;
+ }-*/;
+
+ private native JavaScriptObject nativeThisWindow() /*-{
+ return window;
+ }-*/;
+
+ private native JavaScriptObject nativeTopWindow() /*-{
+ return $wnd;
+ }-*/;
+}
=======================================
--- /dev/null
+++
/releases/2.4/user/test/com/google/gwt/core/public/script_injector_test4.js
Tue Jun 21 14:52:10 2011
@@ -0,0 +1,1 @@
+__ti4_var__ = 4;
=======================================
--- /dev/null
+++
/releases/2.4/user/test/com/google/gwt/core/public/script_injector_test5.js
Tue Jun 21 14:52:10 2011
@@ -0,0 +1,1 @@
+__ti5_var__ = 5;
=======================================
--- /dev/null
+++
/releases/2.4/user/test/com/google/gwt/core/public/script_injector_test6.js
Tue Jun 21 14:52:10 2011
@@ -0,0 +1,1 @@
+__ti6_var__ = 6;
=======================================
--- /dev/null
+++
/releases/2.4/user/test/com/google/gwt/core/public/script_injector_test7.js
Tue Jun 21 14:52:10 2011
@@ -0,0 +1,1 @@
+__ti7_var__ = 7;
=======================================
--- /releases/2.4/user/test/com/google/gwt/core/CoreSuite.java Thu Jun 9
05:46:38 2011
+++ /releases/2.4/user/test/com/google/gwt/core/CoreSuite.java Tue Jun 21
14:52:10 2011
@@ -21,6 +21,7 @@
import com.google.gwt.core.client.JsArrayMixedTest;
import com.google.gwt.core.client.JsArrayTest;
import com.google.gwt.core.client.SchedulerTest;
+import com.google.gwt.core.client.ScriptInjectorTest;
import com.google.gwt.core.client.impl.AsyncFragmentLoaderTest;
import com.google.gwt.core.client.impl.SchedulerImplTest;
import com.google.gwt.core.client.impl.StackTraceCreatorTest;
@@ -47,6 +48,7 @@
suite.addTestSuite(JsArrayMixedTest.class);
suite.addTestSuite(SchedulerImplTest.class);
suite.addTestSuite(SchedulerTest.class);
+ suite.addTestSuite(ScriptInjectorTest.class);
suite.addTestSuite(StackTraceCreatorTest.class);
suite.addTestSuite(StrictModeTest.class);
suite.addTestSuite(XhrLoadingStrategyTest.class);
--
http://groups.google.com/group/Google-Web-Toolkit-Contributors