Skip to content

Commit 51b6bde

Browse files
committed
Clean up some documentation and remove a few circular dependencies that
complicate static analysis.
1 parent c0411a7 commit 51b6bde

File tree

13 files changed

+319
-154
lines changed

13 files changed

+319
-154
lines changed

javascript/node/selenium-webdriver/_base.js

Lines changed: 36 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@
1717
* @fileoverview The base module responsible for bootstrapping the Closure
1818
* library and providing a means of loading Closure-based modules.
1919
*
20-
* Each script loaded by this module will be granted access to this module's
20+
* <p>Each script loaded by this module will be granted access to this module's
2121
* {@code require} function; all required non-native modules must be specified
2222
* relative to <em>this</em> module.
2323
*
24-
* This module will load all scripts from the "lib" subdirectory, unless the
24+
* <p>This module will load all scripts from the "lib" subdirectory, unless the
2525
* SELENIUM_DEV_MODE environment variable has been set to 1, in which case all
2626
* scripts will be loaded from the Selenium client containing this script.
2727
*/
@@ -44,18 +44,46 @@ var devMode = (function() {
4444
})();
4545

4646

47+
/** @return {boolean} Whether this script was loaded in dev mode. */
48+
function isDevMode() {
49+
return devMode;
50+
}
51+
52+
4753
/**
4854
* @type {string} Path to Closure's base file, relative to this module.
4955
* @const
5056
*/
51-
var CLOSURE_BASE_FILE_PATH = computeClosureBasePath();
57+
var CLOSURE_BASE_FILE_PATH = (function() {
58+
var relativePath = isDevMode() ?
59+
'../../../third_party/closure/goog/base.js' :
60+
'./lib/goog/base.js';
61+
return path.join(__dirname, relativePath);
62+
})();
5263

5364

5465
/**
5566
* @type {string} Path to Closure's base file, relative to this module.
5667
* @const
5768
*/
58-
var DEPS_FILE_PATH = computeDepsPath();
69+
var DEPS_FILE_PATH = (function() {
70+
var relativePath = isDevMode() ?
71+
'../../../javascript/deps.js' :
72+
'./lib/deps.js';
73+
return path.join(__dirname, relativePath);
74+
})();
75+
76+
77+
78+
/**
79+
* Synchronously loads a script into the protected Closure context.
80+
* @param {string} src Path to the file to load.
81+
*/
82+
function loadScript(src) {
83+
src = path.normalize(src);
84+
var contents = fs.readFileSync(src, 'utf8');
85+
vm.runInContext(contents, closure, src);
86+
}
5987

6088

6189
/**
@@ -78,18 +106,20 @@ var closure = vm.createContext({
78106
loadScript(src);
79107
return true;
80108
},
81-
CLOSURE_NO_DEPS: !isDevMode()
109+
CLOSURE_NO_DEPS: !isDevMode(),
110+
goog: {}
82111
});
83112
closure.window = closure;
84113

114+
85115
loadScript(CLOSURE_BASE_FILE_PATH);
86116
loadScript(DEPS_FILE_PATH);
87117

88118

89119
/**
90120
* Loads a symbol by name from the protected Closure context.
91121
* @param {string} symbol The symbol to load.
92-
* @return {*} The loaded symbol.
122+
* @return {?} The loaded symbol, or {@code null} if not found.
93123
* @throws {Error} If the symbol has not been defined.
94124
*/
95125
function closureRequire(symbol) {
@@ -98,42 +128,6 @@ function closureRequire(symbol) {
98128
}
99129

100130

101-
/** @return {string} Path to the closure library's base script. */
102-
function computeClosureBasePath() {
103-
var relativePath = isDevMode() ?
104-
'../../../third_party/closure/goog/base.js' :
105-
'./lib/goog/base.js';
106-
return path.join(__dirname, relativePath);
107-
}
108-
109-
110-
/** @return {string} Path to the deps file used to locate closure resources. */
111-
function computeDepsPath() {
112-
var relativePath = isDevMode() ?
113-
'../../../javascript/deps.js' :
114-
'./lib/deps.js';
115-
return path.join(__dirname, relativePath);
116-
}
117-
118-
119-
/** @return {boolean} Whether this script was loaded in dev mode. */
120-
function isDevMode() {
121-
return devMode;
122-
}
123-
exports.isDevMode = isDevMode;
124-
125-
126-
/**
127-
* Synchronously loads a script into the protected Closure context.
128-
* @param {string} src Path to the file to load.
129-
*/
130-
function loadScript(src) {
131-
src = path.normalize(src);
132-
var contents = fs.readFileSync(src, 'utf8');
133-
vm.runInContext(contents, closure, src);
134-
}
135-
136-
137131
// PUBLIC API
138132

139133

javascript/node/selenium-webdriver/builder.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ function createNativeDriver(capabilities) {
5050

5151

5252
/**
53+
* Creates new {@link webdriver.WebDriver WebDriver} instances.
5354
* @constructor
5455
* @extends {webdriver.AbstractBuilder}
5556
*/
@@ -63,7 +64,7 @@ goog.inherits(Builder, AbstractBuilder);
6364
* Sets the proxy configuration to use for WebDriver clients created by this
6465
* builder. Any calls to {@link #withCapabilities} after this function will
6566
* overwrite these settings.
66-
* @param {!ProxyConfig} config The configuration to use.
67+
* @param {!proxy.ProxyConfig} config The configuration to use.
6768
* @return {!Builder} A self reference.
6869
*/
6970
Builder.prototype.setProxy = function(config) {

javascript/node/selenium-webdriver/chrome.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ var CHROMEDRIVER_EXE =
4545
* @constructor
4646
*/
4747
var ServiceBuilder = function(opt_exe) {
48+
/** @private {string} */
4849
this.exe_ = opt_exe || io.findInPath(CHROMEDRIVER_EXE, true);
4950
if (!this.exe_) {
5051
throw Error(
@@ -58,6 +59,7 @@ var ServiceBuilder = function(opt_exe) {
5859
throw Error('File does not exist: ' + this.exe_);
5960
}
6061

62+
/** @private {!Array.<string>} */
6163
this.args_ = [];
6264
this.stdio_ = 'ignore';
6365
};
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2014 Selenium committers
2+
// Copyright 2014 Software Freedom Conservancy
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
'use strict';
17+
18+
var base = require('./_base');
19+
20+
21+
/** @type {function(new: bot.Error)} */
22+
exports.Error = base.require('bot.Error');
23+
24+
/** @type {bot.ErrorCode.} */
25+
exports.ErrorCode = base.require('bot.ErrorCode');

javascript/node/selenium-webdriver/executors.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@
1717
* {@link webdriver.CommandExecutor} implementations.
1818
*/
1919

20-
var webdriver = require('./index'),
21-
HttpClient = require('./http').HttpClient,
22-
HttpExecutor = require('./http').Executor;
20+
var HttpClient = require('./http').HttpClient,
21+
HttpExecutor = require('./http').Executor,
22+
promise = require('./_base').require('webdriver.promise');
2323

2424

2525

@@ -52,7 +52,7 @@ var DeferredExecutor = function(delegate) {
5252
* @returns {!webdriver.CommandExecutor} The new command executor.
5353
*/
5454
exports.createExecutor = function(url) {
55-
return new DeferredExecutor(webdriver.promise.when(url, function(url) {
55+
return new DeferredExecutor(promise.when(url, function(url) {
5656
var client = new HttpClient(url);
5757
return new HttpExecutor(client);
5858
}));

javascript/node/selenium-webdriver/http/index.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ var base = require('../_base'),
2525

2626

2727
/**
28-
* HTTP client for use with NodeJS.
28+
* A {@link webdriver.http.Client} implementation using Node's built-in http
29+
* module.
2930
* @param {string} serverUrl URL for the WebDriver server to send commands to.
3031
* @constructor
3132
* @implements {webdriver.http.Client}
@@ -138,9 +139,13 @@ var sendRequest = function(options, callback, opt_data) {
138139

139140
// PUBLIC API
140141

141-
142+
/** @type {webdriver.http.Executor.} */
142143
exports.Executor = base.require('webdriver.http.Executor');
144+
145+
/** @type {webdriver.http.Request.} */
143146
exports.Request = base.require('webdriver.http.Request');
147+
148+
/** @type {webdriver.http.Response.} */
144149
exports.Response = base.require('webdriver.http.Response');
150+
145151
exports.HttpClient = HttpClient;
146-
exports.util = require('./util');

javascript/node/selenium-webdriver/index.js

Lines changed: 94 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -19,42 +19,106 @@
1919
*/
2020

2121
var base = require('./_base');
22+
var builder = require('./builder');
23+
var error = require('./error');
2224

25+
26+
// NOTE: the remainder of this file is nasty and verbose, but the annotations
27+
// are necessary to guide the Closure Compiler's type analysis. Without them,
28+
// we would not be able to extract any meaningful API documentation.
29+
30+
31+
/** @type {function(new: webdriver.ActionSequence)} */
2332
exports.ActionSequence = base.require('webdriver.ActionSequence');
24-
exports.Builder = require('./builder').Builder;
25-
exports.Button = base.require('webdriver.Button');
26-
exports.By = base.require('webdriver.Locator.Strategy');
33+
34+
35+
/** @type {function(new: builder.Builder)} */
36+
exports.Builder = builder.Builder;
37+
38+
39+
/** @type {function(new: webdriver.Capabilities)} */
2740
exports.Capabilities = base.require('webdriver.Capabilities');
41+
42+
43+
/** @type {function(new: webdriver.Command)} */
2844
exports.Command = base.require('webdriver.Command');
45+
46+
47+
/** @type {function(new: webdriver.EventEmitter)} */
2948
exports.EventEmitter = base.require('webdriver.EventEmitter');
49+
50+
51+
/** @type {function(new: webdriver.Session)} */
3052
exports.Session = base.require('webdriver.Session');
53+
54+
55+
/** @type {function(new: webdriver.WebDriver)} */
3156
exports.WebDriver = base.require('webdriver.WebDriver');
57+
58+
59+
/** @type {function(new: webdriver.WebElement)} */
3260
exports.WebElement = base.require('webdriver.WebElement');
3361

34-
var closureModules = {
35-
Browser: base.require('webdriver.Browser'),
36-
Capability: base.require('webdriver.Capability'),
37-
CommandName: base.require('webdriver.CommandName'),
38-
Key: base.require('webdriver.Key'),
39-
command: {
40-
Command: base.require('webdriver.Command'),
41-
CommandName: base.require('webdriver.CommandName')
42-
},
43-
error: {
44-
Error: base.require('bot.Error'),
45-
ErrorCode: base.require('bot.ErrorCode')
46-
},
47-
events: {
48-
EventEmitter: base.require('webdriver.EventEmitter')
49-
},
50-
logging: base.exportPublicApi('webdriver.logging'),
51-
promise: base.exportPublicApi('webdriver.promise'),
52-
stacktrace: base.exportPublicApi('webdriver.stacktrace')
53-
};
54-
55-
56-
Object.keys(closureModules).forEach(function(key) {
57-
exports.__defineGetter__(key, function() {
58-
return closureModules[key];
59-
});
60-
});
62+
63+
// Export the remainder of our API through getters to keep things cleaner
64+
// when this module is used in a REPL environment.
65+
66+
67+
/** @type {webdriver.Browser.} */
68+
(exports.__defineGetter__('Browser', function() {
69+
return base.require('webdriver.Browser');
70+
}));
71+
72+
73+
/** @type {webdriver.Button.} */
74+
(exports.__defineGetter__('Button', function() {
75+
return base.require('webdriver.Button');
76+
}));
77+
78+
79+
/** @type {webdriver.Locator.Strategy.} */
80+
(exports.__defineGetter__('By', function() {
81+
return base.require('webdriver.Locator.Strategy');
82+
}));
83+
84+
85+
/** @type {webdriver.Capability.} */
86+
(exports.__defineGetter__('Capability', function() {
87+
return base.require('webdriver.Capability');
88+
}));
89+
90+
91+
/** @type {webdriver.CommandName.} */
92+
(exports.__defineGetter__('CommandName', function() {
93+
return base.require('webdriver.CommandName');
94+
}));
95+
96+
97+
/** @type {webdriver.Key.} */
98+
(exports.__defineGetter__('Key', function() {
99+
return base.require('webdriver.Key');
100+
}));
101+
102+
103+
/** @type {error.} */
104+
(exports.__defineGetter__('error', function() {
105+
return error;
106+
}));
107+
108+
109+
/** @type {error.} */
110+
(exports.__defineGetter__('error', function() {
111+
return error;
112+
}));
113+
114+
115+
/** @type {webdriver.promise.} */
116+
(exports.__defineGetter__('promise', function() {
117+
return base.exportPublicApi('webdriver.promise');
118+
}));
119+
120+
121+
/** @type {webdriver.stacktrace.} */
122+
(exports.__defineGetter__('stacktrace', function() {
123+
return base.exportPublicApi('webdriver.stacktrace');
124+
}));

javascript/node/selenium-webdriver/io/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ var PATH_SEPARATOR = process.platform === 'win32' ? ';' : ':';
2424

2525

2626
/**
27-
* Searches the PATH environment variable for the given file.
27+
* Searches the {@code PATH} environment variable for the given file.
2828
* @param {string} file The file to locate on the PATH.
2929
* @param {boolean=} opt_checkCwd Whether to always start with the search with
3030
* the current working directory, regardless of whether it is explicitly

javascript/node/selenium-webdriver/net/portprober.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,8 @@ function findWindowsPortRange() {
144144
/**
145145
* Tests if a port is free.
146146
* @param {number} port The port to test.
147+
* @param {string=} opt_host The bound host to test the {@code port} against.
148+
* Defaults to {@code INADDR_ANY}.
147149
* @return {!webdriver.promise.Promise.<boolean>} A promise that will resolve
148150
* with whether the port is free.
149151
*/
@@ -171,6 +173,8 @@ function isFree(port, opt_host) {
171173

172174

173175
/**
176+
* @param {string=} opt_host The bound host to test the {@code port} against.
177+
* Defaults to {@code INADDR_ANY}.
174178
* @return {!webdriver.promise.Promise.<number>} A promise that will resolve
175179
* to a free port. If a port cannot be found, the promise will be
176180
* rejected.

0 commit comments

Comments
 (0)