Closure compiler correctness and test script.
This commit is contained in:
@@ -1,18 +1,19 @@
|
|||||||
/*
|
/**
|
||||||
Copyright 2014, Ian Gulliver
|
* @license
|
||||||
|
* Copyright 2014, Ian Gulliver
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
*
|
||||||
you may not use this file except in compliance with the License.
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
You may obtain a copy of the License at
|
* 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
|
*
|
||||||
|
* 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,
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
See the License for the specific language governing permissions and
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
limitations under the License.
|
* See the License for the specific language governing permissions and
|
||||||
*/
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
// We use long keys in many places. Provide a method to trim those down for
|
// We use long keys in many places. Provide a method to trim those down for
|
||||||
// human readability.
|
// human readability.
|
||||||
@@ -26,12 +27,16 @@ String.prototype.hashCode = function() {
|
|||||||
return hash;
|
return hash;
|
||||||
};
|
};
|
||||||
|
|
||||||
var cosmopolite = {};
|
/**
|
||||||
|
* @constructor
|
||||||
cosmopolite.Client = function(opt_callbacks, opt_urlPrefix, opt_namespace) {
|
* @param {Object=} callbacks Callback dictionary
|
||||||
this.callbacks_ = opt_callbacks || {};
|
* @param {string=} urlPrefix Absolute URL prefix for generating API URL
|
||||||
this.urlPrefix_ = opt_urlPrefix || '/cosmopolite';
|
* @param {string=} namespace Prefix for localStorage entries.
|
||||||
this.namespace_ = opt_namespace || 'cosmopolite';
|
*/
|
||||||
|
Cosmopolite = function(callbacks, urlPrefix, namespace) {
|
||||||
|
this.callbacks_ = callbacks || {};
|
||||||
|
this.urlPrefix_ = urlPrefix || '/cosmopolite';
|
||||||
|
this.namespace_ = namespace || 'cosmopolite';
|
||||||
|
|
||||||
this.subscriptions_ = {};
|
this.subscriptions_ = {};
|
||||||
|
|
||||||
@@ -48,7 +53,16 @@ cosmopolite.Client = function(opt_callbacks, opt_urlPrefix, opt_namespace) {
|
|||||||
}, this);
|
}, this);
|
||||||
};
|
};
|
||||||
|
|
||||||
cosmopolite.Client.prototype.subscribe = function(subject, messages, keys) {
|
/**
|
||||||
|
* Subscribe to a subject.
|
||||||
|
*
|
||||||
|
* Start receiving messages sent to this subject via the onMessage callback.
|
||||||
|
*
|
||||||
|
* @param {!string} subject Subject name
|
||||||
|
* @param {!number} messages Number of recent messages to request; 0 for none, -1 for all
|
||||||
|
* @param {Array.<string>=} keys Key names to ensure we receive at least 1 message defining
|
||||||
|
*/
|
||||||
|
Cosmopolite.prototype.subscribe = function(subject, messages, keys) {
|
||||||
keys = keys || [];
|
keys = keys || [];
|
||||||
if (subject in this.subscriptions_) {
|
if (subject in this.subscriptions_) {
|
||||||
console.log('Not sending duplication subscription request for subject:', subject);
|
console.log('Not sending duplication subscription request for subject:', subject);
|
||||||
@@ -64,14 +78,29 @@ cosmopolite.Client.prototype.subscribe = function(subject, messages, keys) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
cosmopolite.Client.prototype.unsubscribe = function(subject) {
|
/**
|
||||||
|
* Unsubscribe from a subject and destroy all listeners.
|
||||||
|
*
|
||||||
|
* Note that no reference counting is done, so a single call to unsubscribe()
|
||||||
|
* undoes multiple calls to subscribe().
|
||||||
|
*
|
||||||
|
* @param {!string} subject Subject name, as passed to subscribe()
|
||||||
|
*/
|
||||||
|
Cosmopolite.prototype.unsubscribe = function(subject) {
|
||||||
delete this.subscriptions_[subject];
|
delete this.subscriptions_[subject];
|
||||||
this.sendRPC_('unsubscribe', {
|
this.sendRPC_('unsubscribe', {
|
||||||
'subject': subject,
|
'subject': subject,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
cosmopolite.Client.prototype.sendMessage = function(subject, message, key) {
|
/**
|
||||||
|
* Post a message to the given subject, storing it and notifying all listeners.
|
||||||
|
*
|
||||||
|
* @param {!string} subject Subject name
|
||||||
|
* @param {!string} message Message string
|
||||||
|
* @param {string=} key Key name to associate this message with
|
||||||
|
*/
|
||||||
|
Cosmopolite.prototype.sendMessage = function(subject, message, key) {
|
||||||
args = {
|
args = {
|
||||||
'subject': subject,
|
'subject': subject,
|
||||||
'message': message,
|
'message': message,
|
||||||
@@ -82,11 +111,19 @@ cosmopolite.Client.prototype.sendMessage = function(subject, message, key) {
|
|||||||
this.sendRPC_('sendMessage', args);
|
this.sendRPC_('sendMessage', args);
|
||||||
};
|
};
|
||||||
|
|
||||||
cosmopolite.Client.prototype.getMessages = function(subject) {
|
/**
|
||||||
|
* Fetch all received messages for a subject
|
||||||
|
*
|
||||||
|
* @param {!string} subject Subject name
|
||||||
|
*/
|
||||||
|
Cosmopolite.prototype.getMessages = function(subject) {
|
||||||
return this.subscriptions_[subject].messages;
|
return this.subscriptions_[subject].messages;
|
||||||
};
|
};
|
||||||
|
|
||||||
cosmopolite.Client.prototype.onLoad_ = function() {
|
/**
|
||||||
|
* Callback when a script loads.
|
||||||
|
*/
|
||||||
|
Cosmopolite.prototype.onLoad_ = function() {
|
||||||
if (--this.numScriptsToLoad_ > 0) {
|
if (--this.numScriptsToLoad_ > 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -95,8 +132,12 @@ cosmopolite.Client.prototype.onLoad_ = function() {
|
|||||||
this.createChannel_();
|
this.createChannel_();
|
||||||
};
|
};
|
||||||
|
|
||||||
// Message from another browser window
|
/**
|
||||||
cosmopolite.Client.prototype.onReceiveMessage_ = function(data) {
|
* Callback for a message from another browser window
|
||||||
|
*
|
||||||
|
* @param {!string} data Message contents
|
||||||
|
*/
|
||||||
|
Cosmopolite.prototype.onReceiveMessage_ = function(data) {
|
||||||
switch (data) {
|
switch (data) {
|
||||||
case 'login_complete':
|
case 'login_complete':
|
||||||
this.socket.close();
|
this.socket.close();
|
||||||
@@ -113,7 +154,13 @@ cosmopolite.Client.prototype.onReceiveMessage_ = function(data) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
cosmopolite.Client.prototype.registerMessageHandlers_ = function() {
|
/**
|
||||||
|
* Register onReceiveMessage to receive callbacks
|
||||||
|
*
|
||||||
|
* Note that we share this bus with at least the channel code, so spurious
|
||||||
|
* messages are normal.
|
||||||
|
*/
|
||||||
|
Cosmopolite.prototype.registerMessageHandlers_ = function() {
|
||||||
this.$(window).on('message', this.$.proxy(function(e) {
|
this.$(window).on('message', this.$.proxy(function(e) {
|
||||||
if (e.originalEvent.origin != window.location.origin) {
|
if (e.originalEvent.origin != window.location.origin) {
|
||||||
console.log(
|
console.log(
|
||||||
@@ -125,7 +172,16 @@ cosmopolite.Client.prototype.registerMessageHandlers_ = function() {
|
|||||||
}, this));
|
}, this));
|
||||||
};
|
};
|
||||||
|
|
||||||
cosmopolite.Client.prototype.sendRPC_ = function(command, args, onSuccess) {
|
/**
|
||||||
|
* Send a single RPC to the server.
|
||||||
|
*
|
||||||
|
* See sendRPCs_()
|
||||||
|
*
|
||||||
|
* @param {!string} command Command name to call
|
||||||
|
* @param {!Object} args Arguments to pass to server
|
||||||
|
* @param {function(Object)=} onSuccess Success callback function
|
||||||
|
*/
|
||||||
|
Cosmopolite.prototype.sendRPC_ = function(command, args, onSuccess) {
|
||||||
this.sendRPCs_([
|
this.sendRPCs_([
|
||||||
{
|
{
|
||||||
'command': command,
|
'command': command,
|
||||||
@@ -135,7 +191,17 @@ cosmopolite.Client.prototype.sendRPC_ = function(command, args, onSuccess) {
|
|||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
|
||||||
cosmopolite.Client.prototype.sendRPCs_ = function(commands, delay) {
|
/**
|
||||||
|
* Send one or more RPCs to the server.
|
||||||
|
*
|
||||||
|
* Wraps handling of authentication to the server, even in cases where we need
|
||||||
|
* to retry with more data. Also retries in cases of failure with exponential
|
||||||
|
* backoff.
|
||||||
|
*
|
||||||
|
* @param {!Array.<{command:string, arguments:Object, onSuccess:function(Object)}>} commands List of commands to execute
|
||||||
|
* @param {number=} delay Seconds waited before executing this call (for backoff)
|
||||||
|
*/
|
||||||
|
Cosmopolite.prototype.sendRPCs_ = function(commands, delay) {
|
||||||
var request = {
|
var request = {
|
||||||
'commands': [],
|
'commands': [],
|
||||||
};
|
};
|
||||||
@@ -179,9 +245,9 @@ cosmopolite.Client.prototype.sendRPCs_ = function(commands, delay) {
|
|||||||
// TODO(flamingcow): Refresh the page? Show an alert?
|
// TODO(flamingcow): Refresh the page? Show an alert?
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (var i = 0; i < data.responses.length; i++) {
|
for (var i = 0; i < data['responses'].length; i++) {
|
||||||
if (commands[i]['onSuccess']) {
|
if (commands[i]['onSuccess']) {
|
||||||
this.$.proxy(commands[i]['onSuccess'], this)(data.responses[i]);
|
this.$.proxy(commands[i]['onSuccess'], this)(data['responses'][i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Handle events that were immediately available as if they came over the
|
// Handle events that were immediately available as if they came over the
|
||||||
@@ -201,7 +267,10 @@ cosmopolite.Client.prototype.sendRPCs_ = function(commands, delay) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
cosmopolite.Client.prototype.createChannel_ = function() {
|
/**
|
||||||
|
* Send RPCs to create a server -> client channel and (re-)subscribe to subjects
|
||||||
|
*/
|
||||||
|
Cosmopolite.prototype.createChannel_ = function() {
|
||||||
var rpcs = [
|
var rpcs = [
|
||||||
{
|
{
|
||||||
'command': 'createChannel',
|
'command': 'createChannel',
|
||||||
@@ -221,7 +290,14 @@ cosmopolite.Client.prototype.createChannel_ = function() {
|
|||||||
this.sendRPCs_(rpcs);
|
this.sendRPCs_(rpcs);
|
||||||
};
|
};
|
||||||
|
|
||||||
cosmopolite.Client.prototype.onCreateChannel_ = function(data) {
|
/**
|
||||||
|
* Callback for channel creation on the server side
|
||||||
|
*
|
||||||
|
* @suppress {missingProperties}
|
||||||
|
*
|
||||||
|
* @param {!Object} data Server response including channel token
|
||||||
|
*/
|
||||||
|
Cosmopolite.prototype.onCreateChannel_ = function(data) {
|
||||||
var channel = new goog.appengine.Channel(data['token']);
|
var channel = new goog.appengine.Channel(data['token']);
|
||||||
console.log('Opening channel...');
|
console.log('Opening channel...');
|
||||||
this.socket = channel.open({
|
this.socket = channel.open({
|
||||||
@@ -232,11 +308,17 @@ cosmopolite.Client.prototype.onCreateChannel_ = function(data) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
cosmopolite.Client.prototype.onSocketOpen_ = function() {
|
/**
|
||||||
|
* Callback from channel library for successful open
|
||||||
|
*/
|
||||||
|
Cosmopolite.prototype.onSocketOpen_ = function() {
|
||||||
console.log('Channel opened');
|
console.log('Channel opened');
|
||||||
};
|
};
|
||||||
|
|
||||||
cosmopolite.Client.prototype.onSocketClose_ = function() {
|
/**
|
||||||
|
* Callback from channel library for closure; reopen.
|
||||||
|
*/
|
||||||
|
Cosmopolite.prototype.onSocketClose_ = function() {
|
||||||
if (!this.socket) {
|
if (!this.socket) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -245,12 +327,22 @@ cosmopolite.Client.prototype.onSocketClose_ = function() {
|
|||||||
this.createChannel_();
|
this.createChannel_();
|
||||||
};
|
};
|
||||||
|
|
||||||
cosmopolite.Client.prototype.onSocketMessage_ = function(msg) {
|
/**
|
||||||
|
* Callback from channel library for message reception over channel
|
||||||
|
*
|
||||||
|
* @param {!Object} msg Message contents
|
||||||
|
*/
|
||||||
|
Cosmopolite.prototype.onSocketMessage_ = function(msg) {
|
||||||
this.onServerEvent_(JSON.parse(msg.data));
|
this.onServerEvent_(JSON.parse(msg.data));
|
||||||
};
|
};
|
||||||
|
|
||||||
cosmopolite.Client.prototype.onServerEvent_ = function(e) {
|
/**
|
||||||
switch (e.event_type) {
|
* Callback for Cosmopolite event (received via channel or pseudo-channel)
|
||||||
|
*
|
||||||
|
* @param {!Object} e Deserialized event object
|
||||||
|
*/
|
||||||
|
Cosmopolite.prototype.onServerEvent_ = function(e) {
|
||||||
|
switch (e['event_type']) {
|
||||||
case 'login':
|
case 'login':
|
||||||
if ('onLogin' in this.callbacks_) {
|
if ('onLogin' in this.callbacks_) {
|
||||||
this.callbacks_['onLogin'](
|
this.callbacks_['onLogin'](
|
||||||
@@ -289,7 +381,15 @@ cosmopolite.Client.prototype.onServerEvent_ = function(e) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
cosmopolite.Client.prototype.onSocketError_ = function(msg) {
|
/**
|
||||||
|
* Callback from channel library for error on channel
|
||||||
|
*
|
||||||
|
* @param {!string} msg Descriptive text
|
||||||
|
*/
|
||||||
|
Cosmopolite.prototype.onSocketError_ = function(msg) {
|
||||||
console.log('Socket error:', msg);
|
console.log('Socket error:', msg);
|
||||||
this.socket.close();
|
this.socket.close();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Exported values */
|
||||||
|
window.Cosmopolite = Cosmopolite;
|
||||||
|
|||||||
15
static/verify.sh
Executable file
15
static/verify.sh
Executable file
@@ -0,0 +1,15 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
curl \
|
||||||
|
--silent \
|
||||||
|
--data compilation_level=ADVANCED_OPTIMIZATIONS \
|
||||||
|
--data output_format=json \
|
||||||
|
--data output_info=errors \
|
||||||
|
--data output_info=warnings \
|
||||||
|
--data language=ECMASCRIPT5 \
|
||||||
|
--data warning_level=verbose \
|
||||||
|
--data externs_url=https://closure-compiler.googlecode.com/git/contrib/externs/jquery-1.8.js \
|
||||||
|
--data-urlencode "js_code@cosmopolite.js" \
|
||||||
|
http://closure-compiler.appspot.com/compile
|
||||||
|
|
||||||
|
echo
|
||||||
Reference in New Issue
Block a user