accessibility-developer-tools
Version:
This is a library of accessibility-related testing and utility code.
257 lines (215 loc) • 6.22 kB
JavaScript
// Copyright 2015 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview adaptor of XhrStreamReader to the NodeReadableStream interface.
*/
goog.provide('goog.net.streams.XhrNodeReadableStream');
goog.require('goog.array');
goog.require('goog.log');
goog.require('goog.net.streams.NodeReadableStream');
goog.require('goog.net.streams.XhrStreamReader');
/**
* The XhrNodeReadableStream class.
*
* @param {!goog.net.streams.XhrStreamReader} xhrReader The XhrStreamReader
* object that handles the events of the underlying Xhr.
* @constructor
* @implements {goog.net.streams.NodeReadableStream}
* @struct
* @final
* @package
*/
goog.net.streams.XhrNodeReadableStream = function(xhrReader) {
/**
* @const
* @private {?goog.log.Logger} the logger.
*/
this.logger_ = goog.log.getLogger('goog.net.streams.XhrNodeReadableStream');
/**
* The xhr reader.
*
* @private {!goog.net.streams.XhrStreamReader} the xhr reader.
*/
this.xhrReader_ = xhrReader;
this.xhrReader_.setDataHandler(goog.bind(this.onData_, this));
this.xhrReader_.setStatusHandler(goog.bind(this.onStatusChange_, this));
/**
* The callback map, keyed by eventTypes.
*
* @private {!Object<Array<function(!Object=)>>}
*/
this.callbackMap_ = {};
/**
* The callback-once map, keyed by eventTypes.
*
* @private {!Object<Array<function(!Object=)>>}
*/
this.callbackOnceMap_ = {};
};
/**
* @override
*/
goog.net.streams.XhrNodeReadableStream.prototype.on = function(
eventType, callback) {
var callbacks = this.callbackMap_[eventType];
if (!callbacks) {
callbacks = [];
this.callbackMap_[eventType] = callbacks;
}
callbacks.push(callback);
return this;
};
/**
* @override
*/
goog.net.streams.XhrNodeReadableStream.prototype.addListener = function(
eventType, callback) {
this.on(eventType, callback);
return this;
};
/**
* @override
*/
goog.net.streams.XhrNodeReadableStream.prototype.removeListener = function(
eventType, callback) {
var callbacks = this.callbackMap_[eventType];
if (callbacks) {
goog.array.remove(callbacks, callback); // keep the empty array
}
var onceCallbacks = this.callbackOnceMap_[eventType];
if (onceCallbacks) {
goog.array.remove(onceCallbacks, callback);
}
return this;
};
/**
* @override
*/
goog.net.streams.XhrNodeReadableStream.prototype.once = function(
eventType, callback) {
var callbacks = this.callbackOnceMap_[eventType];
if (!callbacks) {
callbacks = [];
this.callbackOnceMap_[eventType] = callbacks;
}
callbacks.push(callback);
return this;
};
/**
* Handles any new data from XHR.
*
* @param {!Array<!Object>} messages New messages, to be delivered in order
* and atomically.
* @private
*/
goog.net.streams.XhrNodeReadableStream.prototype.onData_ = function(messages) {
var callbacks =
this.callbackMap_[goog.net.streams.NodeReadableStream.EventType.DATA];
if (callbacks) {
this.doMessages_(messages, callbacks);
}
var onceCallbacks =
this.callbackOnceMap_[goog.net.streams.NodeReadableStream.EventType.DATA];
if (onceCallbacks) {
this.doMessages_(messages, onceCallbacks);
}
this.callbackOnceMap_[goog.net.streams.NodeReadableStream.EventType.DATA] =
[];
};
/**
* Deliver messages to registered callbacks.
*
* Exceptions are caught and logged (debug), and ignored otherwise.
*
* @param {!Array<!Object>} messages The messages to be delivered
* @param {!Array<function(!Object=)>} callbacks The callbacks.
* @private
*/
goog.net.streams.XhrNodeReadableStream.prototype.doMessages_ = function(
messages, callbacks) {
var self = this;
for (var i = 0; i < messages.length; i++) {
var message = messages[i];
goog.array.forEach(callbacks, function(callback) {
try {
callback(message);
} catch (ex) {
self.handleError_('message-callback exception (ignored) ' + ex);
}
});
}
};
/**
* Handles any state changes from XHR.
*
* @private
*/
goog.net.streams.XhrNodeReadableStream.prototype.onStatusChange_ = function() {
var currentStatus = this.xhrReader_.getStatus();
var Status = goog.net.streams.XhrStreamReader.Status;
var EventType = goog.net.streams.NodeReadableStream.EventType;
switch (currentStatus) {
case Status.ACTIVE:
this.doStatus_(EventType.READABLE);
break;
case Status.BAD_DATA:
case Status.HANDLER_EXCEPTION:
case Status.NO_DATA:
case Status.TIMEOUT:
case Status.XHR_ERROR:
this.doStatus_(EventType.ERROR);
break;
case Status.CANCELLED:
this.doStatus_(EventType.CLOSE);
break;
case Status.SUCCESS:
this.doStatus_(EventType.END);
break;
}
};
/**
* Run status change callbacks.
*
* @param {string} eventType The event type
* @private
*/
goog.net.streams.XhrNodeReadableStream.prototype.doStatus_ = function(
eventType) {
var callbacks = this.callbackMap_[eventType];
var self = this;
if (callbacks) {
goog.array.forEach(callbacks, function(callback) {
try {
callback();
} catch (ex) {
self.handleError_('status-callback exception (ignored) ' + ex);
}
});
}
var onceCallbacks = this.callbackOnceMap_[eventType];
if (onceCallbacks) {
goog.array.forEach(onceCallbacks, function(callback) { callback(); });
}
this.callbackOnceMap_[eventType] = [];
};
/**
* Log an error
*
* @param {string} message The error message
* @private
*/
goog.net.streams.XhrNodeReadableStream.prototype.handleError_ = function(
message) {
goog.log.error(this.logger_, message);
};