logo       

[HtmlUnit] CVS Commit: src/xdocs: Implemented window.setTimeout(function, : msg#00057

java.htmlunit.devel

Subject: [HtmlUnit] CVS Commit: src/xdocs: Implemented window.setTimeout(function, int) and

Log Message:
-----------
Implemented window.setTimeout(function, int) and window.setInterval(function,
int)

Modified Files:
--------------
htmlunit/src/java/com/gargoylesoftware/htmlunit/html:
HtmlPage.java

(http://cvs.sourceforge.net/viewcvs.py/htmlunit/htmlunit/src/java/com/gargoylesoftware/htmlunit/html/HtmlPage.java)
htmlunit/src/xdocs:
changes.xml

(http://cvs.sourceforge.net/viewcvs.py/htmlunit/htmlunit/src/xdocs/changes.xml)
htmlunit/src/java/com/gargoylesoftware/htmlunit/javascript/host:
JavaScriptBackgroundJob.java

(http://cvs.sourceforge.net/viewcvs.py/htmlunit/htmlunit/src/java/com/gargoylesoftware/htmlunit/javascript/host/JavaScriptBackgroundJob.java)
Window.java

(http://cvs.sourceforge.net/viewcvs.py/htmlunit/htmlunit/src/java/com/gargoylesoftware/htmlunit/javascript/host/Window.java)
htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host:
WindowTest.java

(http://cvs.sourceforge.net/viewcvs.py/htmlunit/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/WindowTest.java)

Revision Data
-------------
Index: JavaScriptBackgroundJob.java
===================================================================
RCS file:
/cvsroot/htmlunit/htmlunit/src/java/com/gargoylesoftware/htmlunit/javascript/host/JavaScriptBackgroundJob.java,v
retrieving revision 1.2
retrieving revision 1.3
diff
-Lsrc/java/com/gargoylesoftware/htmlunit/javascript/host/JavaScriptBackgroundJob.java

-Lsrc/java/com/gargoylesoftware/htmlunit/javascript/host/JavaScriptBackgroundJob.java
-u -d -r1.2 -r1.3
---
src/java/com/gargoylesoftware/htmlunit/javascript/host/JavaScriptBackgroundJob.java
+++
src/java/com/gargoylesoftware/htmlunit/javascript/host/JavaScriptBackgroundJob.java
@@ -39,6 +39,7 @@

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.mozilla.javascript.Function;

import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.WebWindow;
@@ -59,6 +60,7 @@
private final int timeout_;
private final String script_;
private final boolean loopForever_;
+ private final Function function_;

JavaScriptBackgroundJob(final Window window, final int timeout, final
String script,
final boolean loopForever) {
@@ -66,13 +68,27 @@
timeout_ = timeout;
loopForever_ = loopForever;
script_ = script;
+ function_ = null;
+ }
+ JavaScriptBackgroundJob(final Window window, final int timeout, final
Function function,
+ final boolean loopForever) {
+ window_ = window;
+ timeout_ = timeout;
+ loopForever_ = loopForever;
+ script_ = null;
+ function_ = function;
}
public void run() {
final Page page = window_.getWebWindow().getEnclosedPage();
try {
do {
Thread.sleep(timeout_);
- getLog().debug("Executing JavaScriptBackgroundJob: " +
script_);
+ if (function_ == null) {
+ getLog().debug("Executing JavaScriptBackgroundJob: " +
script_);
+ }
+ else {
+ getLog().debug("Executing JavaScriptBackgroundJob:
(function reference) ");
+ }

final WebWindow webWindow = window_.getWebWindow();
// test that the window is always opened and the page the same
@@ -86,11 +102,20 @@
}

final HtmlPage htmlPage = (HtmlPage)
window_.getWebWindow().getEnclosedPage();
- htmlPage.executeJavaScriptIfPossible(
- script_,
- "JavaScriptBackgroundJob",
- true,
- htmlPage.getDocumentElement());
+ if (function_ == null) {
+ htmlPage.executeJavaScriptIfPossible(
+ script_,
+ "JavaScriptBackgroundJob",
+ true,
+ htmlPage.getDocumentElement());
+ }
+ else {
+ htmlPage.executeJavaScriptFunctionIfPossible(
+ function_,
+ window_,
+ new Object[0],
+ htmlPage.getDocumentElement());
+ }
}
while (loopForever_);
}
Index: Window.java
===================================================================
RCS file:
/cvsroot/htmlunit/htmlunit/src/java/com/gargoylesoftware/htmlunit/javascript/host/Window.java,v
retrieving revision 1.85
retrieving revision 1.86
diff -Lsrc/java/com/gargoylesoftware/htmlunit/javascript/host/Window.java
-Lsrc/java/com/gargoylesoftware/htmlunit/javascript/host/Window.java -u -d
-r1.85 -r1.86
--- src/java/com/gargoylesoftware/htmlunit/javascript/host/Window.java
+++ src/java/com/gargoylesoftware/htmlunit/javascript/host/Window.java
@@ -234,22 +234,57 @@
return null;
}
}
-
+
+ /**
+ * Makes the job object for setTimeout and setInterval
+ *
+ * @param codeToExec either a Function or a String of the javascript code
+ * @param timeout time to wait
+ * @param thisWindow the window to associate the thread with
+ * @param loopForever if the thread should keep looping (setTimeout vs
setInterval)
+ * @return
+ */
+ private static JavaScriptBackgroundJob createJavaScriptBackgroundJob(final
Object codeToExec,
+ final int timeout, final Window thisWindow, final boolean
loopForever) {
+ if (codeToExec == null) {
+ throw Context.reportRuntimeError("Function not provided");
+ }
+ else if (codeToExec instanceof String) {
+ final String scriptString = (String) codeToExec;
+ return new JavaScriptBackgroundJob(thisWindow, timeout,
scriptString, loopForever);
+ }
+ else if (codeToExec instanceof Function) {
+ final Function scriptFunction = (Function) codeToExec;
+ return new JavaScriptBackgroundJob(thisWindow, timeout,
scriptFunction, loopForever);
+ }
+ else {
+ throw Context.reportRuntimeError("Unknown type for function");
+ }
+ }

/**
* Set a chunk of javascript to be invoked at some specified time later.
* 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 script the code to execute
- * @param timeout the delay in milliseconds to wait before executing the
code
+ *
+ * JavaScript param 1: The code to execute, either a String or a Function.
+ * JavaScript param 2: the delay in milliseconds to wait before executing
the code.
+ *
+ * @param context The javascript Context
+ * @param scriptable The object that the function was called on.
+ * @param args The arguments passed to the function.
+ * @param function The function object that was invoked.
* @return the id of the created timer
*/
- public int jsxFunction_setTimeout(final String script, final int timeout) {
- final Runnable setTimeoutThread = new JavaScriptBackgroundJob(this,
timeout, script, false);
- final int id =
getWebWindow().getThreadManager().startThread(setTimeoutThread);
+ public static int jsxFunction_setTimeout(final Context context, final
Scriptable scriptable,
+ final Object[] args, final Function function) {
+ final Window thisWindow = (Window) scriptable;
+ final Object codeToExec = getObjectArg(0, args, null);
+ final int timeout = getIntArg(1, args, 0);
+ final Runnable job = createJavaScriptBackgroundJob(codeToExec,
timeout, thisWindow, false);
+ final int id =
thisWindow.getWebWindow().getThreadManager().startThread(job);
return id;
- }
+ }

/**
* Cancels a time-out previously set with the <tt>setTimeout</tt> method.
@@ -710,16 +745,27 @@
/**
* Set a chunk of javascript to be invoked each time a specified number of
milliseconds has elapsed
* Current implementation does nothing.
-
- * @param script the code to execute
- * @param timeout the delay in milliseconds to wait before executing the
code
- * @return the id of the created interval
+ *
+ * JavaScript param 1: The code to execute, either a String or a Function.
+ * JavaScript param 2: the delay in milliseconds to wait before executing
the code.
+ *
* @see <a
href="http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/setinterval.asp";>
* MSDN documentation</a>
+ *
+ * @param context The javascript Context
+ * @param scriptable The object that the function was called on.
+ * @param args The arguments passed to the function.
+ * @param function The function object that was invoked.
+ * @return the id of the created interval
*/
- public int jsxFunction_setInterval(final String script, final int timeout)
{
- final Runnable setTimeoutThread = new JavaScriptBackgroundJob(this,
timeout, script, true);
- final int id =
getWebWindow().getThreadManager().startThread(setTimeoutThread);
+ public static int jsxFunction_setInterval(final Context context, final
Scriptable scriptable,
+ final Object[] args, final Function function) {
+ final Window thisWindow = (Window) scriptable;
+ final Object codeToExec = getObjectArg(0, args, null);
+ final int timeout = getIntArg(1, args, 0);
+
+ final Runnable job = createJavaScriptBackgroundJob(codeToExec,
timeout, thisWindow, true);
+ final int id =
thisWindow.getWebWindow().getThreadManager().startThread(job);
return id;
}

Index: changes.xml
===================================================================
RCS file: /cvsroot/htmlunit/htmlunit/src/xdocs/changes.xml,v
retrieving revision 1.494
retrieving revision 1.495
diff -Lsrc/xdocs/changes.xml -Lsrc/xdocs/changes.xml -u -d -r1.494 -r1.495
--- src/xdocs/changes.xml
+++ src/xdocs/changes.xml
@@ -8,6 +8,9 @@
<body>
<release version="next">
<action type="update" dev="yourgod">
+ Implemented window.setTimeout(function, int) and
window.setInterval(function, int)
+ </action>
+ <action type="update" dev="yourgod">
HtmlOption.asText() now respects the label attribute as
browsers do.
</action>
<action type="update" dev="mguillem" id="1437068">
Index: HtmlPage.java
===================================================================
RCS file:
/cvsroot/htmlunit/htmlunit/src/java/com/gargoylesoftware/htmlunit/html/HtmlPage.java,v
retrieving revision 1.135
retrieving revision 1.136
diff -Lsrc/java/com/gargoylesoftware/htmlunit/html/HtmlPage.java
-Lsrc/java/com/gargoylesoftware/htmlunit/html/HtmlPage.java -u -d -r1.135
-r1.136
--- src/java/com/gargoylesoftware/htmlunit/html/HtmlPage.java
+++ src/java/com/gargoylesoftware/htmlunit/html/HtmlPage.java
@@ -705,6 +705,8 @@
}

/**
+ * <span style="color:red">INTERNAL API - SUBJECT TO CHANGE AT ANY TIME -
USE AT YOUR OWN RISK.</span><br/>
+ *
* Execute a Function in the given context.
*
* @param function The javascript Function to call.
@@ -716,7 +718,7 @@
* @return A ScriptResult which will contain both the current page (which
may be different than
* the previous page and a javascript result object.
*/
- ScriptResult executeJavaScriptFunctionIfPossible(
+ public ScriptResult executeJavaScriptFunctionIfPossible(
final Function function,
final Scriptable thisObject,
final Object[] args,
@@ -748,7 +750,8 @@
}

/**
- * Internal use only.
+ * <span style="color:red">INTERNAL API - SUBJECT TO CHANGE AT ANY TIME -
USE AT YOUR OWN RISK.</span><br/>
+ *
* @param srcAttribute The source attribute from the script tag.
* @param charset The charset attribute from the script tag.
*/
@@ -773,7 +776,9 @@
}

/**
- * Internal use only. Return true if a script with the specified type and
language attributes
+ * <span style="color:red">INTERNAL API - SUBJECT TO CHANGE AT ANY TIME -
USE AT YOUR OWN RISK.</span><br/>
+ *
+ * Return true if a script with the specified type and language attributes
* is actually JavaScript.
* According to <a
href="http://www.w3.org/TR/REC-html40/types.html#h-6.7";>W3C recommendation</a>
* are content types case insensitive.
@@ -1366,7 +1371,8 @@
}

/**
- * For internal used only
+ * <span style="color:red">INTERNAL API - SUBJECT TO CHANGE AT ANY TIME -
USE AT YOUR OWN RISK.</span><br/>
+ *
* @param node the node that has just been added to the document.
*/
void notifyNodeAdded(final DomNode node) {
@@ -1381,7 +1387,8 @@
}

/**
- * For internal used only
+ * <span style="color:red">INTERNAL API - SUBJECT TO CHANGE AT ANY TIME -
USE AT YOUR OWN RISK.</span><br/>
+ *
* @param node the node that has just been removed from the tree
*/
void notifyNodeRemoved(final DomNode node) {
Index: WindowTest.java
===================================================================
RCS file:
/cvsroot/htmlunit/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/WindowTest.java,v
retrieving revision 1.57
retrieving revision 1.58
diff
-Lsrc/test/java/com/gargoylesoftware/htmlunit/javascript/host/WindowTest.java
-Lsrc/test/java/com/gargoylesoftware/htmlunit/javascript/host/WindowTest.java
-u -d -r1.57 -r1.58
--- src/test/java/com/gargoylesoftware/htmlunit/javascript/host/WindowTest.java
+++ src/test/java/com/gargoylesoftware/htmlunit/javascript/host/WindowTest.java
@@ -51,6 +51,7 @@
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.PromptHandler;
import com.gargoylesoftware.htmlunit.StatusHandler;
+import com.gargoylesoftware.htmlunit.ThreadManager;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.WebTestCase;
import com.gargoylesoftware.htmlunit.WebWindow;
@@ -760,6 +761,21 @@
assertTrue("thread failed to stop in 1 second",
page.getEnclosingWindow().getThreadManager().joinAll(1000));
assertEquals(Collections.singletonList("Yo!"), collectedAlerts);
}
+
+ /**
+ * @throws Exception If the test fails
+ */
+ public void testSetTimeoutByReference() throws Exception {
+ final String content = "<html><body><script language='JavaScript'>"
+ + "function doTimeout() { alert('Yo!'); }"
+ + "window.setTimeout(doTimeout,1);"
+ + "</script></body></html>";
+
+ final List collectedAlerts = Collections.synchronizedList(new
ArrayList());
+ final HtmlPage page = loadPage(content, collectedAlerts);
+ assertTrue("thread failed to stop in 1 second",
page.getEnclosingWindow().getThreadManager().joinAll(1000));
+ assertEquals(Collections.singletonList("Yo!"), collectedAlerts);
+ }

/**
* Just tests that setting and clearing an interval doesn't throw
@@ -778,6 +794,39 @@
final List collectedAlerts = Collections.synchronizedList(new
ArrayList());
loadPage(content, collectedAlerts);
}
+
+ /**
+ * @throws Exception If the test fails
+ */
+ public void testSetIntervalFunctionReference() throws Exception {
+ final String content = "<html>\n"
+ + "<head>\n"
+ + " <title>test</title>\n"
+ + " <script>\n"
+ + " var threadID;\n"
+ + " function test() {\n"
+ + " threadID = setInterval(doAlert, 100);\n"
+ + " }\n"
+ + " var iterationNumber=0;"
+ + " function doAlert() {\n"
+ + " alert('blah');\n"
+ + " if (++iterationNumber >= 3) {"
+ + " clearInterval(threadID);"
+ + " }"
+ + " }\n"
+ + " </script>\n"
+ + "</head>\n"
+ + "<body onload='test()'>\n"
+ + "</body>\n"
+ + "</html>";
+
+ final List collectedAlerts = Collections.synchronizedList(new
ArrayList());
+ final HtmlPage page = loadPage(content, collectedAlerts);
+ final ThreadManager threadManager =
page.getEnclosingWindow().getThreadManager();
+ threadManager.joinAll(1000);
+ assertEquals(0, threadManager.activeCount());
+ assertEquals(Collections.nCopies(3, "blah"), collectedAlerts);
+ }

/**
* Test that a script started by a timer is stopped if the page that
started it


-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642


<Prev in Thread] Current Thread [Next in Thread>
Google Custom Search

News | FAQ | advertise