function resolveGlobals( ast ) {
	var visitors;
	var globals;
	if ( ast.type !== 'Program' ) {
		throw new TypeError( 'invalid argument. Must provide a program AST node.' );
	}
	globals = [];

	// Resolve local scopes:
	resolveLocalScopes( ast );

	// Define callbacks for relevant AST nodes:
	visitors = {
		'VariablePattern': Identifier,
		'Identifier': Identifier,
		'ThisExpression': ThisExpression
	};

	// Walk the AST to resolve globals:
	walk( ast, visitors );

	return globals;

	/**
	* Callback invoked upon encountering an identifier AST node.
	*
	* @private
	* @param {Node} node - AST node
	* @param {Array} parents - array of parent AST nodes
	*/
	function Identifier( node, parents ) {
		var locals;
		var name;
		var i;

		name = node.name;
		if ( name === 'undefined' ) {
			return;
		}
		for ( i = 0; i < parents.length; i++ ) {
			if ( name === 'arguments' && declaresArguments( parents[ i ] ) ) {
				return;
			}
			locals = parents[ i ].locals;
			if ( locals && contains( locals.length, locals, 1, 0, name ) ) {
				return;
			}
		}
		appendUnique( globals, name );
	}

	/**
	* Callback invoked upon encountering a `ThisExpression` AST node.
	*
	* @private
	* @param {Node} node - AST node
	* @param {Array} parents - array of parent AST nodes
	*/
	function ThisExpression( node, parents ) {
		var i;
		for ( i = 0; i < parents.length; i++ ) {
			if ( declaresThis( parents[ i ] ) ) {
				return;
			}
		}
		appendUnique( globals, 'this' );
	}
}
Resolves global variables within an abstract syntax tree (AST).

@private
@param {AST} ast - abstract syntax tree (AST)
@throws {TypeError} must provide a program AST node
@returns {Array} list of global variables