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 */ 9var 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 */ 20var 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*/ 27function 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*/ 53function 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