[HtmlUnit] SVN: [15418] trunk/htmlunit/src

rbri--- via HtmlUnit-develop <[email protected]>
Newsgroups gmane.comp.java.htmlunit.devel
Message-ID <[email protected]>
Revision: 15418
          http://sourceforge.net/p/htmlunit/code/15418
Author:   rbri
Date:     2018-06-29 19:51:23 +0000 (Fri, 29 Jun 2018)
Log Message:
-----------
Correct handling of additional parameters provided in functions setTimeout/setInterval.


Issue 1966

Modified Paths:
--------------
    trunk/htmlunit/src/changes/changes.xml
    trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/background/BackgroundJavaScriptFactory.java
    trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/background/JavaScriptFunctionJob.java
    trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Window.java

Modified: trunk/htmlunit/src/changes/changes.xml
===================================================================
--- trunk/htmlunit/src/changes/changes.xml	2018-06-29 17:33:58 UTC (rev 15417)
+++ trunk/htmlunit/src/changes/changes.xml	2018-06-29 19:51:23 UTC (rev 15418)
@@ -14,6 +14,9 @@
             <action type="remove" dev="rbri">
                 FF45 support removed.
             </action>
+            <action type="fix" dev="rbri" issue="1966" due-to="Atsushi Nakagawa">
+                Correct handling of additional parameters provided in functions setTimeout/setInterval.
+            </action>
             <action type="fix" dev="rbri" issue="1964">
                 NPE in HtmlTextArea.removeFocus().
             </action>

Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/background/BackgroundJavaScriptFactory.java
===================================================================
--- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/background/BackgroundJavaScriptFactory.java	2018-06-29 17:33:58 UTC (rev 15417)
+++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/background/BackgroundJavaScriptFactory.java	2018-06-29 19:51:23 UTC (rev 15418)
@@ -28,6 +28,7 @@
  * JavaScript engine.
  *
  * @author Ronald Brill
+ * @author Atsushi Nakagawa
  */
 public class BackgroundJavaScriptFactory {
 
@@ -73,13 +74,14 @@
      * @param label the label for the job
      * @param window the window to which the job belongs
      * @param function the JavaScript code to execute
+     * @param args the arguments to pass into the function call
      *
      * @return JavaScriptJob the created job
      */
     public JavaScriptFunctionJob createJavaScriptJob(final int initialDelay,
             final Integer period, final String label,
-            final WebWindow window, final Function function) {
-        return new JavaScriptFunctionJob(initialDelay, period, label, window, function);
+            final WebWindow window, final Function function, final Object[] args) {
+        return new JavaScriptFunctionJob(initialDelay, period, label, window, function, args);
     }
 
     /**

Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/background/JavaScriptFunctionJob.java
===================================================================
--- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/background/JavaScriptFunctionJob.java	2018-06-29 17:33:58 UTC (rev 15417)
+++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/background/JavaScriptFunctionJob.java	2018-06-29 19:51:23 UTC (rev 15418)
@@ -24,11 +24,14 @@
 /**
  * A {@link JavaScriptJob} created from a {@link Function} object.
  * @author Brad Clarke
+ * @author Ronald Brill
+ * @author Atsushi Nakagawa
  */
 class JavaScriptFunctionJob extends JavaScriptExecutionJob {
 
     /** The JavaScript code to execute. */
     private final Function function_;
+    private final Object[] args_;
 
     /**
      * Creates a new JavaScript execution job, where the JavaScript code to execute is a function.
@@ -37,11 +40,13 @@
      * @param label the label for the job
      * @param window the window to which the job belongs
      * @param function the JavaScript code to execute
+     * @param args the arguments to pass into the function call
      */
     JavaScriptFunctionJob(final int initialDelay, final Integer period, final String label,
-        final WebWindow window, final Function function) {
+        final WebWindow window, final Function function, final Object[] args) {
         super(initialDelay, period, label, window);
         function_ = function;
+        args_ = args;
     }
 
     /** {@inheritDoc} */
@@ -49,7 +54,7 @@
     protected void runJavaScript(final HtmlPage page) {
         final DomElement doc = page.getDocumentElement();
         final Scriptable scriptable = page.getEnclosingWindow().getScriptableObject();
-        page.executeJavaScriptFunction(function_, scriptable, new Object[0], doc);
+        page.executeJavaScriptFunction(function_, scriptable, args_, doc);
     }
 
 }

Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Window.java
===================================================================
--- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Window.java	2018-06-29 17:33:58 UTC (rev 15417)
+++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Window.java	2018-06-29 19:51:23 UTC (rev 15418)
@@ -24,8 +24,8 @@
 import static com.gargoylesoftware.htmlunit.javascript.configuration.SupportedBrowser.CHROME;
 import static com.gargoylesoftware.htmlunit.javascript.configuration.SupportedBrowser.EDGE;
 import static com.gargoylesoftware.htmlunit.javascript.configuration.SupportedBrowser.FF;
+import static com.gargoylesoftware.htmlunit.javascript.configuration.SupportedBrowser.FF52;
 import static com.gargoylesoftware.htmlunit.javascript.configuration.SupportedBrowser.FF60;
-import static com.gargoylesoftware.htmlunit.javascript.configuration.SupportedBrowser.FF52;
 import static com.gargoylesoftware.htmlunit.javascript.configuration.SupportedBrowser.IE;
 
 import java.io.IOException;
@@ -155,6 +155,7 @@
  * @author Frank Danek
  * @author Carsten Steul
  * @author Colin Alworth
+ * @author Atsushi Nakagawa
  * @see <a href="http://msdn.microsoft.com/en-us/library/ms535873.aspx">MSDN documentation</a>
  */
 @JsxClass
@@ -483,32 +484,77 @@
      * The invocation occurs only if the window is opened after the delay
      * and does not contain an other page than the one that originated the setTimeout.
      *
-     * @param code specifies the function pointer or string that indicates the code to be executed
-     *        when the specified interval has elapsed
-     * @param timeout specifies the number of milliseconds
-     * @param language specifies language
+     * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout">
+     * MDN web docs</a>
+     *
+     * @param context the JavaScript context
+     * @param thisObj the scriptable
+     * @param args the arguments passed into the method
+     * @param function the function
      * @return the id of the created timer
      */
     @JsxFunction
-    public int setTimeout(final Object code, int timeout, final Object language) {
+    public static Object setTimeout(final Context context, final Scriptable thisObj,
+            final Object[] args, final Function function) {
+        if (args.length < 1) {
+            throw ScriptRuntime.typeError("Function not provided");
+        }
+
+        final int timeout = ScriptRuntime.toInt32((args.length > 1) ? args[1] : Undefined.instance);
+        final Object[] params = (args.length > 2)
+                ? Arrays.copyOfRange(args, 2, args.length)
+                : ScriptRuntime.emptyArgs;
+        return ((Window) thisObj).setTimeoutIntervalImpl(args[0], timeout, true, params);
+    }
+
+    /**
+     * Sets a chunk of JavaScript to be invoked each time a specified number of milliseconds has elapsed.
+     *
+     * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval">
+     * MDN web docs</a>
+     * @param context the JavaScript context
+     * @param thisObj the scriptable
+     * @param args the arguments passed into the method
+     * @param function the function
+     * @return the id of the created interval
+     */
+    @JsxFunction
+    public static Object setInterval(final Context context, final Scriptable thisObj,
+            final Object[] args, final Function function) {
+        if (args.length < 1) {
+            throw ScriptRuntime.typeError("Function not provided");
+        }
+
+        final int timeout = ScriptRuntime.toInt32((args.length > 1) ? args[1] : Undefined.instance);
+        final Object[] params = (args.length > 2)
+                ? Arrays.copyOfRange(args, 2, args.length)
+                : ScriptRuntime.emptyArgs;
+        return ((Window) thisObj).setTimeoutIntervalImpl(args[0], timeout, false, params);
+    }
+
+    private int setTimeoutIntervalImpl(final Object code, int timeout, final boolean isTimeout, final Object[] params) {
         if (timeout < MIN_TIMER_DELAY) {
             timeout = MIN_TIMER_DELAY;
         }
-        if (code == null) {
-            throw Context.reportRuntimeError("Function not provided.");
-        }
 
-        final int id;
         final WebWindow webWindow = getWebWindow();
         final Page page = (Page) getDomNodeOrNull();
+        Integer period = null;
+        if (!isTimeout) {
+            period = Integer.valueOf(timeout);
+        }
+
         if (code instanceof String) {
             final String s = (String) code;
-            final String description = "window.setTimeout(" + s + ", " + timeout + ")";
+            final String description = "window.set"
+                                        + (isTimeout ? "Timeout" : "Interval")
+                                        + "(" + s + ", " + timeout + ")";
             final JavaScriptJob job = BackgroundJavaScriptFactory.theFactory().
-                    createJavaScriptJob(timeout, null, description, webWindow, s);
-            id = webWindow.getJobManager().addJob(job, page);
+                    createJavaScriptJob(timeout, period, description, webWindow, s);
+            return webWindow.getJobManager().addJob(job, page);
         }
-        else if (code instanceof Function) {
+
+        if (code instanceof Function) {
             final Function f = (Function) code;
             final String functionName;
             if (f instanceof FunctionObject) {
@@ -518,15 +564,15 @@
                 functionName = String.valueOf(f); // can this happen?
             }
 
-            final String description = "window.setTimeout(" + functionName + ", " + timeout + ")";
+            final String description = "window.set"
+                                        + (isTimeout ? "Timeout" : "Interval")
+                                        + "(" + functionName + ", " + timeout + ")";
             final JavaScriptJob job = BackgroundJavaScriptFactory.theFactory().
-                    createJavaScriptJob(timeout, null, description, webWindow, f);
-            id = webWindow.getJobManager().addJob(job, page);
+                    createJavaScriptJob(timeout, period, description, webWindow, f, params);
+            return webWindow.getJobManager().addJob(job, page);
         }
-        else {
-            throw Context.reportRuntimeError("Unknown type for function.");
-        }
-        return id;
+
+        throw Context.reportRuntimeError("Unknown type for function.");
     }
 
     /**
@@ -543,6 +589,21 @@
     }
 
     /**
+     * Cancels the interval previously started using the {@link #setInterval(Object, int, Object)} method.
+     * Current implementation does nothing.
+     * @param intervalID specifies the interval to cancel as returned by the
+     *        {@link #setInterval(Object, int, Object)} method
+     * @see <a href="http://msdn.microsoft.com/en-us/library/ms536353.aspx">MSDN documentation</a>
+     */
+    @JsxFunction
+    public void clearInterval(final int intervalID) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("clearInterval(" + intervalID + ")");
+        }
+        getWebWindow().getJobManager().removeJob(intervalID);
+    }
+
+    /**
      * Returns the JavaScript property {@code navigator}.
      * @return the navigator
      */
@@ -1487,61 +1548,6 @@
     }
 
     /**
-     * Sets a chunk of JavaScript to be invoked each time a specified number of milliseconds has elapsed.
-     *
-     * @see <a href="http://msdn.microsoft.com/en-us/library/ms536749.aspx">MSDN documentation</a>
-     * @param code specifies the function pointer or string that indicates the code to be executed
-     *        when the specified interval has elapsed
-     * @param timeout specifies the number of milliseconds
-     * @param language specifies language
-     * @return the id of the created interval
-     */
-    @JsxFunction
-    public int setInterval(final Object code, int timeout, final Object language) {
-        if (timeout < MIN_TIMER_DELAY) {
-            timeout = MIN_TIMER_DELAY;
-        }
-        final int id;
-        final WebWindow w = getWebWindow();
-        final Page page = (Page) getDomNodeOrNull();
-        final String description = "window.setInterval(" + timeout + ")";
-        if (code == null) {
-            throw Context.reportRuntimeError("Function not provided.");
-        }
-        else if (code instanceof String) {
-            final String s = (String) code;
-            final JavaScriptJob job = BackgroundJavaScriptFactory.theFactory().
-                createJavaScriptJob(timeout, Integer.valueOf(timeout), description, w, s);
-            id = w.getJobManager().addJob(job, page);
-        }
-        else if (code instanceof Function) {
-            final Function f = (Function) code;
-            final JavaScriptJob job = BackgroundJavaScriptFactory.theFactory().
-                createJavaScriptJob(timeout, Integer.valueOf(timeout), description, w, f);
-            id = w.getJobManager().addJob(job, page);
-        }
-        else {
-            throw Context.reportRuntimeError("Unknown type for function.");
-        }
-        return id;
-    }
-
-    /**
-     * Cancels the interval previously started using the {@link #setInterval(Object, int, Object)} method.
-     * Current implementation does nothing.
-     * @param intervalID specifies the interval to cancel as returned by the
-     *        {@link #setInterval(Object, int, Object)} method
-     * @see <a href="http://msdn.microsoft.com/en-us/library/ms536353.aspx">MSDN documentation</a>
-     */
-    @JsxFunction
-    public void clearInterval(final int intervalID) {
-        if (LOG.isDebugEnabled()) {
-            LOG.debug("clearInterval(" + intervalID + ")");
-        }
-        getWebWindow().getJobManager().removeJob(intervalID);
-    }
-
-    /**
      * Returns the {@code innerWidth}.
      * @return the {@code innerWidth}
      * @see <a href="http://www.mozilla.org/docs/dom/domref/dom_window_ref28.html">Mozilla doc</a>


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.