Home | History | Annotate | Download | only in js
      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.
      4 
      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,
     14 };
     15 
     16 /**
     17  * Dictionary key for asynchronous script info.
     18  * @const
     19  */
     20 var ASYNC_INFO_KEY = '$chrome_asyncScriptInfo';
     21 
     22 /**
     23 * Return the information of asynchronous script execution.
     24 *
     25 * @return {Object.<string, ?>} Information of asynchronous script execution.
     26 */
     27 function getAsyncScriptInfo() {
     28   if (!(ASYNC_INFO_KEY in document))
     29     document[ASYNC_INFO_KEY] = {'id': 0};
     30   return document[ASYNC_INFO_KEY];
     31 }
     32 
     33 /**
     34 * Execute the given script and save its asynchronous result.
     35 *
     36 * If script1 finishes after script2 is executed, then script1's result will be
     37 * discarded while script2's will be saved.
     38 *
     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.
     52 */
     53 function executeAsyncScript(script, args, isUserSupplied, opt_timeoutMillis) {
     54   var info = getAsyncScriptInfo();
     55   info.id++;
     56   delete info.result;
     57   var id = info.id;
     58 
     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);
     80 
     81   try {
     82     new Function(script).apply(null, args);
     83   } catch (error) {
     84     reportScriptError(error);
     85     return;
     86   }
     87 
     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   }
     97 }
     98