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