From a685cc8a595509c707aa692d32b1daa2fea4ca57 Mon Sep 17 00:00:00 2001 From: Mikael Grankvist Date: Thu, 19 Jun 2014 09:31:19 +0300 Subject: [PATCH] IE11 now uses synchronous loading of script instead of async with preloading. (#13956) Change-Id: Ia61d672a55f69326b37420305f0108f2d7443b70 --- .../vaadin/client/ApplicationConnection.java | 16 ++-- .../src/com/vaadin/client/ResourceLoader.java | 39 ++++++++++ .../launcher/DevelopmentServerLauncher.java | 1 + .../JavaScriptPreloading.java | 65 ++++++++++++++++ .../JavaScriptPreloadingTest.java | 74 +++++++++++++++++++ .../javascriptcomponent/js_label.js | 11 +++ .../javascriptcomponent/wholly_different.js | 3 + 7 files changed, 204 insertions(+), 5 deletions(-) create mode 100644 uitest/src/com/vaadin/tests/components/javascriptcomponent/JavaScriptPreloading.java create mode 100644 uitest/src/com/vaadin/tests/components/javascriptcomponent/JavaScriptPreloadingTest.java create mode 100755 uitest/src/com/vaadin/tests/components/javascriptcomponent/js_label.js create mode 100755 uitest/src/com/vaadin/tests/components/javascriptcomponent/wholly_different.js diff --git a/client/src/com/vaadin/client/ApplicationConnection.java b/client/src/com/vaadin/client/ApplicationConnection.java index 50f22edf81..c39beffd87 100644 --- a/client/src/com/vaadin/client/ApplicationConnection.java +++ b/client/src/com/vaadin/client/ApplicationConnection.java @@ -66,7 +66,6 @@ import com.google.gwt.user.client.Window.ClosingHandler; import com.google.gwt.user.client.ui.HasWidgets; import com.google.gwt.user.client.ui.Widget; import com.vaadin.client.ApplicationConfiguration.ErrorMessage; -import com.vaadin.client.ApplicationConnection.ApplicationStoppedEvent; import com.vaadin.client.ResourceLoader.ResourceLoadEvent; import com.vaadin.client.ResourceLoader.ResourceLoadListener; import com.vaadin.client.communication.HasJavaScriptConnectorHelper; @@ -2499,10 +2498,17 @@ public class ApplicationConnection implements HasHandlers { ApplicationConfiguration.startDependencyLoading(); loader.loadScript(url, resourceLoadListener); - // Preload all remaining - for (int i = 0; i < dependencies.length(); i++) { - String preloadUrl = translateVaadinUri(dependencies.get(i)); - loader.preloadResource(preloadUrl, null); + if (ResourceLoader.supportsInOrderScriptExecution()) { + for (int i = 0; i < dependencies.length(); i++) { + String preloadUrl = translateVaadinUri(dependencies.get(i)); + loader.loadScript(preloadUrl, null); + } + } else { + // Preload all remaining + for (int i = 0; i < dependencies.length(); i++) { + String preloadUrl = translateVaadinUri(dependencies.get(i)); + loader.preloadResource(preloadUrl, null); + } } } diff --git a/client/src/com/vaadin/client/ResourceLoader.java b/client/src/com/vaadin/client/ResourceLoader.java index 59ebd797d1..e88def1a72 100644 --- a/client/src/com/vaadin/client/ResourceLoader.java +++ b/client/src/com/vaadin/client/ResourceLoader.java @@ -204,6 +204,26 @@ public class ResourceLoader { */ public void loadScript(final String scriptUrl, final ResourceLoadListener resourceLoadListener) { + loadScript(scriptUrl, resourceLoadListener, + !supportsInOrderScriptExecution()); + } + + /** + * Load a script and notify a listener when the script is loaded. Calling + * this method when the script is currently loading or already loaded + * doesn't cause the script to be loaded again, but the listener will still + * be notified when appropriate. + * + * + * @param scriptUrl + * url of script to load + * @param resourceLoadListener + * listener to notify when script is loaded + * @param async + * What mode the script.async attribute should be set to + */ + public void loadScript(final String scriptUrl, + final ResourceLoadListener resourceLoadListener, boolean async) { final String url = Util.getAbsoluteUrl(scriptUrl); ResourceLoadEvent event = new ResourceLoadEvent(this, url, false); if (loadedResources.contains(url)) { @@ -236,6 +256,9 @@ public class ResourceLoader { ScriptElement scriptTag = Document.get().createScriptElement(); scriptTag.setSrc(url); scriptTag.setType("text/javascript"); + + scriptTag.setPropertyBoolean("async", async); + addOnloadHandler(scriptTag, new ResourceLoadListener() { @Override public void onLoad(ResourceLoadEvent event) { @@ -251,6 +274,17 @@ public class ResourceLoader { } } + /** + * The current browser supports script.async='false' for maintaining + * execution order for dynamically-added scripts. + * + * @return Browser supports script.async='false' + */ + public static boolean supportsInOrderScriptExecution() { + return BrowserInfo.get().isIE() + && BrowserInfo.get().getBrowserMajorVersion() >= 11; + } + /** * Download a resource and notify a listener when the resource is loaded * without attempting to interpret the resource. When a resource has been @@ -316,6 +350,11 @@ public class ResourceLoader { * XHR not tested - should work, probably causes other issues -*/ if (BrowserInfo.get().isIE()) { + // If ie11+ for some reason gets a preload request + if (BrowserInfo.get().getBrowserMajorVersion() >= 11) { + throw new RuntimeException( + "Browser doesn't support preloading with text/cache"); + } ScriptElement element = Document.get().createScriptElement(); element.setSrc(url); element.setType("text/cache"); diff --git a/uitest/src/com/vaadin/launcher/DevelopmentServerLauncher.java b/uitest/src/com/vaadin/launcher/DevelopmentServerLauncher.java index d94518ca9c..e6e54a57a6 100644 --- a/uitest/src/com/vaadin/launcher/DevelopmentServerLauncher.java +++ b/uitest/src/com/vaadin/launcher/DevelopmentServerLauncher.java @@ -142,6 +142,7 @@ public class DevelopmentServerLauncher { assignDefault(serverArgs, "webroot", "WebContent"); assignDefault(serverArgs, "httpPort", "" + serverPort); assignDefault(serverArgs, "context", ""); + assignDefault(serverArgs, "slowdown", "/run/APP/PUBLISHED/js_label.js"); int port = serverPort; try { diff --git a/uitest/src/com/vaadin/tests/components/javascriptcomponent/JavaScriptPreloading.java b/uitest/src/com/vaadin/tests/components/javascriptcomponent/JavaScriptPreloading.java new file mode 100644 index 0000000000..e4fd3fec68 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/javascriptcomponent/JavaScriptPreloading.java @@ -0,0 +1,65 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * 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.vaadin.tests.components.javascriptcomponent; + +import com.vaadin.annotations.JavaScript; +import com.vaadin.server.VaadinRequest; +import com.vaadin.shared.ui.JavaScriptComponentState; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.tests.util.Log; +import com.vaadin.ui.AbstractJavaScriptComponent; + +public class IEJavaScriptPreloading extends AbstractTestUI { + + public static class JsLabelState extends JavaScriptComponentState { + public String xhtml; + } + + @JavaScript({ "js_label.js", "wholly_different.js" }) + public class JsLabel extends AbstractJavaScriptComponent { + + public JsLabel(final String xhtml) { + getState().xhtml = xhtml; + } + + @Override + protected JsLabelState getState() { + return (JsLabelState) super.getState(); + } + } + + private final Log log = new Log(5); + + @Override + protected void setup(VaadinRequest request) { + addComponent(log); + + final JsLabel c = new JsLabel("Hello World!"); + c.setId("js-component"); + addComponent(c); + } + + @Override + protected String getTestDescription() { + return "Loading javascript component with multiple sourcefiles should not break IE11"; + } + + @Override + protected Integer getTicketNumber() { + return Integer.valueOf(13956); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/javascriptcomponent/JavaScriptPreloadingTest.java b/uitest/src/com/vaadin/tests/components/javascriptcomponent/JavaScriptPreloadingTest.java new file mode 100644 index 0000000000..a9e7a1bca7 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/javascriptcomponent/JavaScriptPreloadingTest.java @@ -0,0 +1,74 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * 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.vaadin.tests.components.javascriptcomponent; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import java.util.List; + +import org.junit.Test; +import org.openqa.selenium.Alert; +import org.openqa.selenium.TimeoutException; +import org.openqa.selenium.remote.DesiredCapabilities; +import org.openqa.selenium.support.ui.ExpectedConditions; +import org.openqa.selenium.support.ui.WebDriverWait; + +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * + * @since + * @author Vaadin Ltd + */ +public class JavaScriptPreloadingTest extends MultiBrowserTest { + + /* + * (non-Javadoc) + * + * @see com.vaadin.tests.tb3.MultiBrowserTest#getBrowsersToTest() + */ + @Override + public List getBrowsersToTest() { + List browsers = super.getBrowsersToTest(); + browsers.remove(Browser.PHANTOMJS.getDesiredCapabilities()); + return browsers; + } + + @Test + public void scriptsShouldPreloadAndExecuteInCorrectOrder() + throws InterruptedException { + openTestURL(); + + try { + new WebDriverWait(driver, 10).until(ExpectedConditions + .alertIsPresent()); + Alert alert = driver.switchTo().alert(); + assertEquals("First", alert.getText()); + alert.accept(); + + new WebDriverWait(driver, 10).until(ExpectedConditions + .alertIsPresent()); + alert = driver.switchTo().alert(); + assertEquals("Second", alert.getText()); + alert.accept(); + + } catch (TimeoutException te) { + fail("@Javascript widget loading halted."); + } + + } +} diff --git a/uitest/src/com/vaadin/tests/components/javascriptcomponent/js_label.js b/uitest/src/com/vaadin/tests/components/javascriptcomponent/js_label.js new file mode 100755 index 0000000000..c4900daa81 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/javascriptcomponent/js_label.js @@ -0,0 +1,11 @@ +window.com_vaadin_tests_components_javascriptcomponent_JavaScriptPreloading_JsLabel = function() { + var e = this.getElement(); + + (function() { + e.innerHTML = "Widget executed javascript"; + })(); +}; + +(function() { + window.alert("First"); +})(); diff --git a/uitest/src/com/vaadin/tests/components/javascriptcomponent/wholly_different.js b/uitest/src/com/vaadin/tests/components/javascriptcomponent/wholly_different.js new file mode 100755 index 0000000000..f22ef13a76 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/javascriptcomponent/wholly_different.js @@ -0,0 +1,3 @@ +(function() { + window.alert("Second"); +})(); -- 2.39.5