Roll src/third_party/WebKit d9c6159:8139f33 (svn 201974:201975)
[chromium-blink-merge.git] / chrome / test / chromedriver / js / execute_async_script.js
blob8cf0a190ee07d50efa83788bee96a2a0e5bdafd5
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 /**
6  * Enum for WebDriver status codes.
7  * @enum {number}
8  */
9 var StatusCode = {
10   OK: 0,
11   UNKNOWN_ERROR: 13,
12   JAVASCRIPT_ERROR: 17,
13   SCRIPT_TIMEOUT: 28,
16 /**
17  * Dictionary key for asynchronous script info.
18  * @const
19  */
20 var ASYNC_INFO_KEY = '$chrome_asyncScriptInfo';
22 /**
23 * Return the information of asynchronous script execution.
25 * @return {Object<?>} Information of asynchronous script execution.
27 function getAsyncScriptInfo() {
28   if (!(ASYNC_INFO_KEY in document))
29     document[ASYNC_INFO_KEY] = {'id': 0};
30   return document[ASYNC_INFO_KEY];
33 /**
34 * Execute the given script and save its asynchronous result.
36 * If script1 finishes after script2 is executed, then script1's result will be
37 * discarded while script2's will be saved.
39 * @param {string} script The asynchronous script to be executed. The script
40 *     should be a proper function body. It will be wrapped in a function and
41 *     invoked with the given arguments and, as the final argument, a callback
42 *     function to invoke to report the asynchronous result.
43 * @param {!Array<*>} args Arguments to be passed to the script.
44 * @param {boolean} isUserSupplied Whether the script is supplied by the user.
45 *     If not, UnknownError will be used instead of JavaScriptError if an
46 *     exception occurs during the script, and an additional error callback will
47 *     be supplied to the script.
48 * @param {?number} opt_timeoutMillis The timeout, in milliseconds, to use.
49 *     If the timeout is exceeded and the callback has not been invoked, a error
50 *     result will be saved and future invocation of the callback will be
51 *     ignored.
53 function executeAsyncScript(script, args, isUserSupplied, opt_timeoutMillis) {
54   var info = getAsyncScriptInfo();
55   info.id++;
56   delete info.result;
57   var id = info.id;
59   function report(status, value) {
60     if (id != info.id)
61       return;
62     info.id++;
63     info.result = {status: status, value: value};
64   }
65   function reportValue(value) {
66     report(StatusCode.OK, value);
67   }
68   function reportScriptError(error) {
69     var code = isUserSupplied ? StatusCode.JAVASCRIPT_ERROR :
70                                 (error.code || StatusCode.UNKNOWN_ERROR);
71     var message = error.message;
72     if (error.stack) {
73       message += "\nJavaScript stack:\n" + error.stack;
74     }
75     report(code, message);
76   }
77   args.push(reportValue);
78   if (!isUserSupplied)
79     args.push(reportScriptError);
81   try {
82     new Function(script).apply(null, args);
83   } catch (error) {
84     reportScriptError(error);
85     return;
86   }
88   if (typeof(opt_timeoutMillis) != 'undefined') {
89     window.setTimeout(function() {
90       var code = isUserSupplied ? StatusCode.SCRIPT_TIMEOUT :
91                                   StatusCode.UNKNOWN_ERROR;
92       var errorMsg = 'result was not received in ' + opt_timeoutMillis / 1000 +
93                      ' seconds';
94       report(code, errorMsg);
95     }, opt_timeoutMillis);
96   }