Comparing version 0.5.6 to 0.6.0-rc1
{ | ||
"name": "freedom", | ||
"version": "0.5.5", | ||
"version": "0.6.0-rc1", | ||
"homepage": "http://freedomjs.com", | ||
@@ -5,0 +5,0 @@ "repository": { |
@@ -12,2 +12,3 @@ /*globals freedom,importScripts */ | ||
var oauth = freedom['core.oauth'](); | ||
var external = freedom(); | ||
@@ -21,3 +22,3 @@ var buildURL = function (obj) { | ||
"state=" + encodeURIComponent(obj.state); | ||
freedom.emit("oAuth", url); | ||
external.emit("oAuth", url); | ||
}; | ||
@@ -53,7 +54,7 @@ | ||
} | ||
freedom.emit('profile', resp); | ||
external.emit('profile', resp); | ||
}; | ||
oauth.initiateOAuth(registeredRedirectURIs).then(buildURL).catch(function (msg) { | ||
freedom.emit('profile', { | ||
oauth.initiateOAuth(registeredRedirectURIs).then(buildURL, function (msg) { | ||
external.emit('profile', { | ||
name: 'oAuth Error', | ||
@@ -60,0 +61,0 @@ details: msg |
@@ -10,112 +10,101 @@ /** | ||
var social = freedom.socialprovider(); | ||
var logger; | ||
var userList = {}; //Keep track of the roster | ||
var clientList = {}; | ||
var myClientState = null; | ||
var messages = []; | ||
freedom.core().getLogger('[Chat Backend]').then(function(log) { logger = log; }); | ||
freedom.core().getLogger('[Chat Backend]').then(function (log) { logger = log; }); | ||
var Chat = function (dispatchEvent) { | ||
this.dispatchEvent = dispatchEvent; | ||
this.userList = {}; //Keep track of the roster | ||
this.clientList = {}; | ||
this.myClientState = null; | ||
this.social = freedom.socialprovider(); | ||
this.boot(); | ||
}; | ||
/** | ||
* on a 'send-message' event from the parent (the outer page) | ||
* Just forward it to the Social provider | ||
* sent messages should be forwarded to the Social provider. | ||
**/ | ||
freedom.on('send-message', function(val) { | ||
social.sendMessage(val.to, val.message).then(function(ret) { | ||
//Fulfill - sendMessage succeeded | ||
}, function(err) { | ||
freedom.emit("recv-err", err); | ||
}); | ||
}); | ||
Chat.prototype.send = function (to, message) { | ||
return this.social.sendMessage(to, message); | ||
}; | ||
freedom.on('boot', function(val) { | ||
if (myClientState !== null) { | ||
if (myClientState.status == social.STATUS["ONLINE"]) { | ||
freedom.emit('recv-uid', myClientState.clientId); | ||
freedom.emit('recv-status', "online"); | ||
Chat.prototype.boot = function () { | ||
this.social.login({ | ||
agent: 'chatdemo', | ||
version: '0.1', | ||
url: '', | ||
interactive: true, | ||
rememberLogin: false | ||
}).then(function (ret) { | ||
this.myClientState = ret; | ||
logger.log("onLogin", this.myClientState); | ||
if (ret.status === this.social.STATUS["ONLINE"]) { | ||
this.dispatchEvent('recv-uid', ret.clientId); | ||
this.dispatchEvent('recv-status', "online"); | ||
} else { | ||
freedom.emit('recv-status', "offline"); | ||
this.dispatchEvent('recv-status', "offline"); | ||
} | ||
} | ||
updateBuddyList(); | ||
for (var i=0; i<messages.length; i++) { | ||
freedom.emit('recv-message', messages[i]); | ||
} | ||
}); | ||
}.bind(this), function (err) { | ||
logger.log("Log In Failed", err); | ||
this.dispatchEvent("recv-err", err); | ||
}.bind(this)); | ||
/** | ||
* on an 'onMessage' event from the Social provider | ||
* Just forward it to the outer page | ||
*/ | ||
social.on('onMessage', function(data) { | ||
logger.info("Message Received", data); | ||
messages.push(data); | ||
freedom.emit('recv-message', data); | ||
}); | ||
this.updateBuddyList(); | ||
/** | ||
* On user profile changes, let's keep track of them | ||
**/ | ||
social.on('onUserProfile', function(data) { | ||
//Just save it for now | ||
userList[data.userId] = data; | ||
updateBuddyList(); | ||
}); | ||
/** | ||
* On newly online or offline clients, let's update the roster | ||
**/ | ||
social.on('onClientState', function(data) { | ||
logger.debug("Roster Change", data); | ||
if (data.status == social.STATUS["OFFLINE"]) { | ||
if (clientList.hasOwnProperty(data.clientId)) { | ||
delete clientList[data.clientId]; | ||
/** | ||
* on an 'onMessage' event from the Social provider | ||
* Just forward it to the outer page | ||
*/ | ||
this.social.on('onMessage', function (data) { | ||
logger.info("Message Received", data); | ||
this.dispatchEvent('recv-message', data); | ||
}.bind(this)); | ||
/** | ||
* On user profile changes, let's keep track of them | ||
**/ | ||
this.social.on('onUserProfile', function (data) { | ||
//Just save it for now | ||
this.userList[data.userId] = data; | ||
this.updateBuddyList(); | ||
}.bind(this)); | ||
/** | ||
* On newly online or offline clients, let's update the roster | ||
**/ | ||
this.social.on('onClientState', function (data) { | ||
logger.debug("Roster Change", data); | ||
if (data.status === this.social.STATUS["OFFLINE"]) { | ||
if (this.clientList.hasOwnProperty(data.clientId)) { | ||
delete this.clientList[data.clientId]; | ||
} | ||
} else { //Only track non-offline clients | ||
this.clientList[data.clientId] = data; | ||
} | ||
} else { //Only track non-offline clients | ||
clientList[data.clientId] = data; | ||
} | ||
//If mine, send to the page | ||
if (myClientState !== null && data.clientId == myClientState.clientId) { | ||
if (data.status == social.STATUS["ONLINE"]) { | ||
freedom.emit('recv-status', "online"); | ||
} else { | ||
freedom.emit('recv-status', "offline"); | ||
//If mine, send to the page | ||
if (this.myClientState !== null && data.clientId === this.myClientState.clientId) { | ||
if (data.status === this.social.STATUS["ONLINE"]) { | ||
this.dispatchEvent('recv-status', "online"); | ||
} else { | ||
this.dispatchEvent('recv-status', "offline"); | ||
} | ||
} | ||
} | ||
this.updateBuddyList(); | ||
}.bind(this)); | ||
}; | ||
updateBuddyList(); | ||
}); | ||
function updateBuddyList() { | ||
Chat.prototype.updateBuddyList = function() { | ||
// Iterate over our roster and send over user profiles where there is at least 1 client online | ||
var buddylist = {}; | ||
for (var k in clientList) { | ||
var userId = clientList[k].userId; | ||
if (userId in userList) { | ||
buddylist[userId] = userList[userId]; | ||
for (var k in this.clientList) { | ||
var userId = this.clientList[k].userId; | ||
if (userId in this.userList) { | ||
buddylist[userId] = this.userList[userId]; | ||
} | ||
} | ||
freedom.emit('recv-buddylist', buddylist); | ||
} | ||
this.dispatchEvent('recv-buddylist', buddylist); | ||
}; | ||
/** LOGIN AT START **/ | ||
social.login({ | ||
agent: 'chatdemo', | ||
version: '0.1', | ||
url: '', | ||
interactive: true, | ||
rememberLogin: false | ||
}).then(function(ret) { | ||
myClientState = ret; | ||
logger.log("onLogin", myClientState); | ||
if (ret.status == social.STATUS["ONLINE"]) { | ||
freedom.emit('recv-uid', ret.clientId); | ||
freedom.emit('recv-status', "online"); | ||
} else { | ||
freedom.emit('recv-status', "offline"); | ||
} | ||
}, function(err) { | ||
logger.log("Log In Failed", err); | ||
freedom.emit("recv-err", err); | ||
}); | ||
freedom().providePromises(Chat); |
@@ -17,3 +17,15 @@ { | ||
} | ||
}, | ||
"provides": ["chat"], | ||
"default": "chat", | ||
"api": { | ||
"chat": { | ||
"send": {"type": "method", "value": ["string", "string"]}, | ||
"recv-status": {"type": "event", "value": "string"}, | ||
"recv-err": {"type": "event", "value": {"message": "string"}}, | ||
"recv-message": {"type": "event", "value": {"message": "string", "from": {"userId": "string"}}}, | ||
"recv-buddylist": {"type": "event", "value": "object"}, | ||
"recv-uid": {"type": "event", "value": "string"} | ||
} | ||
} | ||
} |
/* | ||
* These functions provide interaction for the freedom.js chat demo. | ||
*/ | ||
window.onload = function() { | ||
window.onload = function () { | ||
freedom('manifest.json').then(start); | ||
}; | ||
function start(freedom) { | ||
var chatClient = freedom(); | ||
document.getElementById('msg-input').focus(); | ||
@@ -28,3 +34,3 @@ // If messages are going to a specific user, store that here. | ||
function makeDisplayString(buddylistEntry) { | ||
return buddylistEntry.name && buddylistEntry.name != buddylistEntry.userId ? | ||
return buddylistEntry.name && buddylistEntry.name !== buddylistEntry.userId ? | ||
buddylistEntry.name + ' (' + buddylistEntry.userId + ')' : | ||
@@ -35,3 +41,3 @@ buddylistEntry.userId; | ||
function redrawBuddylist() { | ||
var onClick = function(buddylistEntry, child) { | ||
var onClick = function (buddylistEntry, child) { | ||
console.log("Messages will be sent to: " + buddylistEntry.userId); | ||
@@ -63,3 +69,3 @@ activeBuddylistEntry = buddylistEntry; | ||
// on changes to the buddylist, redraw entire buddylist | ||
window.freedom.on('recv-buddylist', function(val) { | ||
chatClient.on('recv-buddylist', function(val) { | ||
buddylist = val; | ||
@@ -70,3 +76,3 @@ redrawBuddylist(); | ||
// On new messages, append it to our message log | ||
window.freedom.on('recv-message', function(data) { | ||
chatClient.on('recv-message', function(data) { | ||
// Show the name instead of the userId, if it's available. | ||
@@ -80,3 +86,3 @@ var userId = data.from.userId; | ||
// On new messages, append it to our message log | ||
window.freedom.on('recv-err', function(data) { | ||
chatClient.on('recv-err', function(data) { | ||
document.getElementById('uid').textContent = "Error: "+data.message; | ||
@@ -86,3 +92,3 @@ }); | ||
// Display our own userId when we get it | ||
window.freedom.on('recv-uid', function(data) { | ||
chatClient.on('recv-uid', function(data) { | ||
document.getElementById('uid').textContent = "Logged in as: " + data; | ||
@@ -92,3 +98,3 @@ }); | ||
// Display the current status of our connection to the Social provider | ||
window.freedom.on('recv-status', function(msg) { | ||
chatClient.on('recv-status', function(msg) { | ||
if (msg && msg == 'online') { | ||
@@ -112,8 +118,5 @@ document.getElementById('msg-input').disabled = false; | ||
appendLog(document.createTextNode("You: " + text)); | ||
window.freedom.emit('send-message', | ||
{to: activeBuddylistEntry.userId, message: text}); | ||
chatClient.send(activeBuddylistEntry.userId, text); | ||
} | ||
}; | ||
freedom.emit('boot'); | ||
}; | ||
} |
@@ -50,3 +50,3 @@ /** | ||
}); | ||
freedom.emit('height', data.status == social.STATUS["ONLINE"] ? 384 : 109); | ||
freedom().emit('height', data.status == social.STATUS["ONLINE"] ? 384 : 109); | ||
if (data.status != social.STATUS["ONLINE"]) { | ||
@@ -93,3 +93,3 @@ console.error('got status ' + data.status + ' from social'); | ||
}); | ||
freedom.emit('height', ret.status == social.STATUS["ONLINE"] ? 384 : 109); | ||
freedom().emit('height', ret.status == social.STATUS["ONLINE"] ? 384 : 109); | ||
}, function(err) { | ||
@@ -100,3 +100,3 @@ view.postMessage({ | ||
}); | ||
freedom.emit('height', 109); | ||
freedom().emit('height', 109); | ||
}); | ||
@@ -103,0 +103,0 @@ }; |
/** | ||
* This is the root module of our FreeDOM backend. | ||
* This is the root module of freedom.js. | ||
* It runs in an isolated thread with its own namespace. | ||
* The root module has a special object 'freedom', which | ||
* is used as a message-passing channel to its parent (the outer webpage) | ||
* is used to provide the interface defined in manifest.json | ||
**/ | ||
var n = 0; | ||
console.log("Hello World!"); | ||
var Counter = function(dispatchEvents, base) { | ||
this.num = base; | ||
}; | ||
// On 'click' events, add it to our global count | ||
// and emit the total back to the outer page | ||
freedom.on('click', function(num) { | ||
if (num === undefined) { | ||
num = 1; | ||
} | ||
n += num; | ||
freedom.emit('number', n); | ||
}); | ||
Counter.prototype.click = function(num) { | ||
this.num += num; | ||
return this.num; | ||
}; | ||
freedom().provideSynchronous(Counter); |
@@ -8,3 +8,17 @@ { | ||
"static": [ "../style.css" ] | ||
}, | ||
"provides": ["counter"], | ||
"default": "counter", | ||
"api": { | ||
"counter": { | ||
"constructor": { | ||
"value": ["number"] | ||
}, | ||
"click": { | ||
"type": "method", | ||
"value": ["number"], | ||
"ret": "number" | ||
} | ||
} | ||
} | ||
} |
var channels = []; | ||
var core = freedom.core(); | ||
freedom.on('message', function(msg) { | ||
var parent = freedom(); | ||
parent.on('message', function(msg) { | ||
if(msg.cmd === 'create') { | ||
@@ -17,4 +18,4 @@ core.bindChannel(msg.chan).then(function(id, chan) { | ||
var handler = function(cid, chan, msg) { | ||
freedom.emit('message', 'channel ' + cid + ' sent ' + msg); | ||
parent.emit('message', 'channel ' + cid + ' sent ' + msg); | ||
chan.emit('message', 'channel ' + cid + ' replies ' + msg); | ||
}; |
@@ -7,10 +7,11 @@ var friend = freedom.friend(); | ||
freedom.on('create', function() { | ||
var external = freedom(); | ||
external.on('create', function() { | ||
var thisid = id; | ||
id += 1; | ||
freedom.emit('message', 'creating custom channel ' + thisid); | ||
external.emit('message', 'creating custom channel ' + thisid); | ||
core.createChannel().then(function(id, cinfo) { | ||
channels[id] = cinfo.channel; | ||
channels[id].on('message', function(msg) {freedom.emit('message', msg);}); | ||
channels[id].on('message', function(msg) {external.emit('message', msg);}); | ||
friend.emit('message', { | ||
@@ -24,4 +25,4 @@ cmd: 'create', | ||
freedom.on('destroy', function(id) { | ||
freedom.emit('message', 'destroying channel ' + id); | ||
external.on('destroy', function(id) { | ||
external.emit('message', 'destroying channel ' + id); | ||
channels[id].close(); | ||
@@ -35,8 +36,8 @@ delete channels[id]; | ||
freedom.on('message', function(id) { | ||
freedom.emit('message', 'sending message to ' + id); | ||
external.on('message', function(id) { | ||
external.emit('message', 'sending message to ' + id); | ||
channels[id].emit('message', 'Message to chan ' + id); | ||
}); | ||
freedom.on('peer', function() { | ||
external.on('peer', function() { | ||
var thisid = id; | ||
@@ -47,3 +48,3 @@ id++; | ||
peer.on('message', function(str) { | ||
freedom.emit('message', "from provider: " + JSON.stringify(str)); | ||
external.emit('message', "from provider: " + JSON.stringify(str)); | ||
}); | ||
@@ -53,6 +54,6 @@ | ||
channels[thisid].on('message', function(m) { | ||
freedom.emit('message', "from custom: " + JSON.stringify(m)); | ||
external.emit('message', "from custom: " + JSON.stringify(m)); | ||
}); | ||
channels[thisid].onClose(function() { | ||
freedom['core.echo'].close(peer); | ||
external['core.echo'].close(peer); | ||
}); | ||
@@ -65,4 +66,4 @@ | ||
friend.on('message', function(str) { | ||
freedom.emit('message', str); | ||
external.emit('message', str); | ||
}); | ||
@@ -45,3 +45,3 @@ function FileFetcher(inSocial) { | ||
}); | ||
freedom.emit('download-data', val.data); | ||
freedom().emit('download-data', val.data); | ||
return; | ||
@@ -61,3 +61,3 @@ } | ||
console.log('social.onMessage: ' + val.msg.data); | ||
freedom.emit('download-error', val.msg.data); | ||
freedom().emit('download-error', val.msg.data); | ||
} else { | ||
@@ -64,0 +64,0 @@ console.log("social.onMessage: Unrecognized message: " + JSON.stringify(val)); |
@@ -13,3 +13,3 @@ function FileServer(inSocial) { | ||
if (myClientState.status == this.social.STATUS["ONLINE"]) { | ||
freedom.emit('serve-descriptor', { | ||
freedom().emit('serve-descriptor', { | ||
targetId: myClientState.clientId, | ||
@@ -20,3 +20,3 @@ key: key, | ||
} else { | ||
freedom.emit('serve-error', "Error connecting to server."); | ||
freedom().emit('serve-error', "Error connecting to server."); | ||
} | ||
@@ -36,3 +36,3 @@ this.updateStats(key, 0, 0); | ||
this.files[key].stats.done += done; | ||
freedom.emit('stats', this.files[key].stats); | ||
freedom().emit('stats', this.files[key].stats); | ||
}; | ||
@@ -39,0 +39,0 @@ |
@@ -28,7 +28,7 @@ /** | ||
freedom.on('serve-data', function(data) { | ||
freedom().on('serve-data', function(data) { | ||
fileServer.serve(myClientState, data.key, data.value, data.name); | ||
}); | ||
freedom.on('download', function(downloadDesc) { | ||
freedom().on('download', function(downloadDesc) { | ||
fileFetcher.download(downloadDesc); | ||
@@ -73,7 +73,7 @@ }); | ||
console.log('social.login: ERROR!'); | ||
freedom.emit("serve-error", "Failed logging in. Status: "+ret.status); | ||
freedom().emit("serve-error", "Failed logging in. Status: "+ret.status); | ||
} | ||
}, function(err) { | ||
freedom.emit("serve-error", err.message); | ||
freedom().emit("serve-error", err.message); | ||
}); | ||
@@ -55,3 +55,3 @@ // After loading freedom.js, the window is populated with a 'freedom' | ||
var key = Math.random() + ""; | ||
window.freedom.emit('serve-data', { | ||
FileRead.app.emit('serve-data', { | ||
key: key, | ||
@@ -190,4 +190,12 @@ value: evt.target.result, | ||
// Setup FreeDOM listeners | ||
window.freedom.on('serve-descriptor', function(val) { | ||
// Start freedom. | ||
freedom('manifest.json').then(function(app) { | ||
initialize(app()); | ||
}); | ||
}; | ||
function initialize(freedom) { | ||
FileRead.app = freedom; | ||
freedom.on('serve-descriptor', function(val) { | ||
var displayUrl = window.location + "#" + JSON.stringify(val); | ||
@@ -201,3 +209,3 @@ Modal.open(); | ||
window.freedom.on('serve-error', function(val) { | ||
freedom.on('serve-error', function(val) { | ||
Modal.open(); | ||
@@ -207,3 +215,3 @@ Modal.displayMessage(val); | ||
window.freedom.on('download-progress', function(val) { | ||
freedom.on('download-progress', function(val) { | ||
//val is an integer with a percentage | ||
@@ -214,3 +222,3 @@ Modal.open(); | ||
window.freedom.on('download-data', function(val) { | ||
freedom.on('download-data', function(val) { | ||
console.log("Download complete"); | ||
@@ -231,3 +239,3 @@ Modal.open(); | ||
window.freedom.on('download-error', function(val) { | ||
freedom.on('download-error', function(val) { | ||
Modal.open(); | ||
@@ -237,3 +245,3 @@ Modal.displayMessage(val); | ||
window.freedom.on('stats', Stats.update); | ||
freedom.on('stats', Stats.update); | ||
@@ -254,3 +262,2 @@ // See if there's a hash with a descriptor we can download | ||
$("#statsHeader").hide(); | ||
}; | ||
} |
@@ -9,88 +9,64 @@ /** | ||
**/ | ||
var currentBoard; | ||
// Initialize a new instance of our storage module | ||
// Note: The manifest file specifies the name of this dependency ('localstorage') | ||
// and the fact that it adheres to the FreeDOM Storage API | ||
var store = freedom.localstorage(); | ||
var Board = function (dispatchEvent) { | ||
this.dispatchEvent = dispatchEvent; | ||
currentBoard = this; | ||
// Internal State | ||
var board = null; | ||
var playerMove = true; | ||
this.score = {win: 0, lose: 0}; | ||
this.state = [0, 0, 0, 0, 0, 0, 0, 0, 0]; | ||
this.playerMove = true; | ||
this.store = freedom.localstorage(); | ||
// Startup emission of stats. | ||
function stats(player, other) { | ||
// Fetch historical score. Note that calls to FreeDOM providers | ||
// are asynchronous. It returns a promise, which you can feed a callback | ||
// to call when the method completes. | ||
var promise = store.get('stats'); | ||
promise.then(function(val) { | ||
var nv; | ||
this.loadStats(); | ||
}; | ||
// This is called by the front end. | ||
Board.prototype.move = function (spot) { | ||
if (this.playerMove && this.state[spot] === 0) { | ||
this.state[spot] = 1; | ||
this.checkWin(); | ||
this.playerMove = false; | ||
this.aiMove(); | ||
} | ||
// This sends the board state to the front-end to display | ||
this.dispatchEvent('update', this.state); | ||
}; | ||
Board.prototype.loadStats = function () { | ||
this.store.get('stats').then(function (value) { | ||
var numericScore; | ||
try { | ||
nv = JSON.parse(val); | ||
val = JSON.parse(val); | ||
} catch(e) {} | ||
if (!nv || typeof nv !== "object") { | ||
nv = { | ||
win: 0, | ||
lose: 0 | ||
}; | ||
numericScore = JSON.parse(value); | ||
} catch (e) { | ||
// Pass. | ||
} | ||
if (!nv.win) { | ||
nv.win = 0; | ||
} | ||
if (!nv.lose) { | ||
nv.lose = 0; | ||
} | ||
if (player) { | ||
nv.win += 1; | ||
} | ||
if (other) { | ||
nv.lose += 1; | ||
} | ||
if (nv !== val) { | ||
store.set('stats', JSON.stringify(nv)); | ||
} | ||
this.score.win = numericScore.win || 0; | ||
this.score.lose = numericScore.lose || 0; | ||
this.dispatchEvent('stats', this.score); | ||
}.bind(this), function () { | ||
this.finishGame(); | ||
}.bind(this)); | ||
}; | ||
// This sends the game stats to the frontend to display | ||
freedom.emit('stats', nv); | ||
}); | ||
} | ||
//setTimeout(stats, 0); | ||
stats(); | ||
Board.prototype.finishGame = function () { | ||
this.state = [0, 0, 0, 0, 0, 0, 0, 0, 0]; | ||
this.playerMove = true; | ||
// Receive moves from the frontend page | ||
freedom.on('move', function(val) { | ||
if (playerMove && board[val] === 0) { | ||
board[val] = 1; | ||
checkWin(); | ||
playerMove = false; | ||
aiMove(); | ||
} | ||
this.store.set('stats', JSON.stringify(this.score)); | ||
this.dispatchEvent('stats', this.score); | ||
}; | ||
var b = {}; | ||
for (var i = 0; i < 9; i++) { | ||
b[i] = board[i]; | ||
Board.prototype.aiMove = function () { | ||
if (this.playerMove) { | ||
return; | ||
} | ||
// This sends the board state to the front-end to display | ||
freedom.emit('board', b); | ||
}); | ||
// Reset the current global state | ||
function reset() { | ||
board = [0,0,0,0,0,0,0,0,0]; | ||
playerMove = true; | ||
} | ||
reset(); | ||
// Implements a simple TicTakToe AI | ||
function aiMove() { | ||
if (playerMove) { | ||
return; | ||
} | ||
// Center Move is good. | ||
if (board[4] === 0) { | ||
board[4] = 2; | ||
checkWin(); | ||
playerMove = true; | ||
if (this.state[4] === 0) { | ||
this.state[4] = 2; | ||
this.checkWin(); | ||
this.playerMove = true; | ||
return; | ||
@@ -103,8 +79,8 @@ } | ||
for (var p = 0; p < 3; p++) { | ||
if (board[set[p === 0 ? 1 : 0]] === 1 && | ||
board[set[p !== 2 ? 2 : 1]] === 1 && | ||
board[set[p]] === 0) { | ||
board[set[p]] = 2; | ||
checkWin(); | ||
playerMove = true; | ||
if (this.state[set[p === 0 ? 1 : 0]] === 1 && | ||
this.state[set[p !== 2 ? 2 : 1]] === 1 && | ||
this.state[set[p]] === 0) { | ||
this.state[set[p]] = 2; | ||
this.checkWin(); | ||
this.playerMove = true; | ||
return; | ||
@@ -116,28 +92,30 @@ } | ||
// Random move. | ||
while(!playerMove) { | ||
while(!this.playerMove) { | ||
var m = Math.floor(Math.random() * 9); | ||
if(board[m] === 0) { | ||
board[m] = 2; | ||
checkWin(); | ||
playerMove = true; | ||
if(this.state[m] === 0) { | ||
this.state[m] = 2; | ||
this.checkWin(); | ||
this.playerMove = true; | ||
return; | ||
} | ||
} | ||
} | ||
}; | ||
// Check for game completion | ||
function checkWin() { | ||
Board.prototype.checkWin = function () { | ||
var sets = "012,345,678,036,147,258,048,246".split(","); | ||
for (var s = 0; s < sets.length; s++) { | ||
var set = sets[s].split(""); | ||
if (board[set[0]] === board[set[1]] && | ||
board[set[1]] === board[set[2]]) { | ||
if (board[set[2]] === 1) { | ||
if (this.state[set[0]] === this.state[set[1]] && | ||
this.state[set[1]] === this.state[set[2]]) { | ||
if (this.state[set[2]] === 1) { | ||
// player wins | ||
stats(1, 0); | ||
reset(); | ||
} else if (board[set[2]] === 2) { | ||
this.score.win += 1; | ||
this.finishGame(); | ||
return; | ||
} else if (this.state[set[2]] === 2) { | ||
// other wins | ||
stats(0, 1); | ||
reset(); | ||
this.score.lose += 1; | ||
this.finishGame(); | ||
return; | ||
} | ||
@@ -148,3 +126,3 @@ } | ||
for (var i = 0; i < 9; i++) { | ||
if (board[i] === 0) { | ||
if (this.state[i] === 0) { | ||
open = 1; | ||
@@ -154,5 +132,7 @@ } | ||
if (open === 0) { | ||
stats(0,0); | ||
reset(); | ||
this.finishGame(); | ||
return; | ||
} | ||
} | ||
}; | ||
freedom().provideSynchronous(Board); |
@@ -14,3 +14,12 @@ { | ||
} | ||
}, | ||
"provides": ["board"], | ||
"default": "board", | ||
"api": { | ||
"board": { | ||
"move": {"type": "method", "value": ["number"]}, | ||
"stats": {"type": "event", "value": {"win":"number", "lose":"number"}}, | ||
"update": {"type": "event", "value": ["array", "number"]} | ||
} | ||
} | ||
} |
206
Gruntfile.js
@@ -27,18 +27,3 @@ /** | ||
var promisePath = require.resolve('es6-promise'); | ||
var promisePrefix = promisePath.substr(0, promisePath.indexOf('es6-promise')); | ||
var promiseSelector = [ | ||
promisePrefix + '/es6-promise/dist/promise-*.js', | ||
'!' + promisePrefix + '/es6-promise/dist/promise-*amd.js', | ||
'!' + promisePrefix + '/es6-promise/dist/promise-*min.js' | ||
]; | ||
var FILES = { | ||
lib: promiseSelector.concat([ | ||
'src/util/jshinthelper.js' | ||
]), | ||
srcJasmineHelper: promiseSelector.concat([ | ||
require.resolve('es5-shim'), | ||
'spec/util.js' | ||
]), | ||
srcCore: [ | ||
@@ -54,5 +39,3 @@ 'src/*.js', | ||
specCoreUnit: [ | ||
'spec/src/{a,b,c,d,e}*.spec.js', | ||
'spec/src/{f,g}*.spec.js', | ||
'spec/src/{h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z}*.spec.js' | ||
'spec/src/*.spec.js' | ||
], | ||
@@ -62,13 +45,2 @@ specPlatformUnit: [ | ||
], | ||
//Integration tests | ||
srcProviderIntegration: [ | ||
'spec/providers/social/**/*.integration.src.js', | ||
'spec/providers/storage/**/*.integration.src.js', | ||
'spec/providers/transport/**/*.integration.src.js' | ||
], | ||
specProviderIntegration: [ | ||
'spec/providers/social/**/*.integration.spec.js', | ||
'spec/providers/storage/**/*.integration.spec.js', | ||
'spec/providers/transport/**/*.integration.spec.js' | ||
], | ||
srcProvider: [ | ||
@@ -86,2 +58,6 @@ 'providers/oauth/*.js', | ||
], | ||
specProviderIntegration: [ | ||
'spec/providers/*.integration.spec.js', | ||
'spec/providers/storage/*.integration.spec.js' | ||
], | ||
specAll: ['spec/**/*.spec.js'], | ||
@@ -94,12 +70,12 @@ freedom: [ | ||
var CUSTOM_LAUNCHER = { | ||
sauce_chrome_34: { | ||
sauce_chrome_mac: { | ||
base: 'SauceLabs', | ||
browserName: 'chrome', | ||
version: '34', | ||
version: '', | ||
platform: 'OS X 10.9' | ||
}, | ||
sauce_chrome_33: { | ||
sauce_chrome_win: { | ||
base: 'SauceLabs', | ||
browserName: 'chrome', | ||
version: '33', | ||
version: '', | ||
platform: 'Windows 7' | ||
@@ -110,18 +86,6 @@ }, | ||
browserName: 'firefox', | ||
version: '29' | ||
version: '' | ||
} | ||
}; | ||
function unGlob(arr) { | ||
var include = [], exclude = []; | ||
arr.filter(function(el) { | ||
if (el.length > 0 && el.charAt(0) !== '!') { | ||
include.push(el); | ||
} else if (el.length > 0) { | ||
exclude.push(el.substr(1)); | ||
} | ||
}); | ||
return {include: include, exclude: exclude}; | ||
} | ||
module.exports = function (grunt) { | ||
@@ -136,25 +100,18 @@ /** | ||
// NOTE: need to run 'connect:default' to serve files | ||
configFile: 'karma.conf.js', | ||
configFile: 'karma.conf.js' | ||
}, | ||
single: { singleRun: true, autoWatch: false }, | ||
watch: { | ||
singleRun: false, | ||
watch: { | ||
singleRun: false, | ||
autoWatch: true, | ||
reporters: ['progress', 'story'], | ||
preprocessors: {}, | ||
reporters: ['progress', 'html'], | ||
coverageReporter: {} | ||
}, | ||
phantom: { | ||
exclude: unGlob(FILES.srcJasmineHelper).exclude.concat( | ||
FILES.specProviderIntegration | ||
), | ||
browsers: ['PhantomJS'], | ||
singleRun: true, | ||
phantom: { | ||
browsers: ['PhantomJS'], | ||
singleRun: true, | ||
autoWatch: false | ||
}, | ||
saucelabs: { | ||
exclude: unGlob(FILES.srcJasmineHelper).exclude.concat( | ||
FILES.specProviderIntegration | ||
), | ||
browsers: ['sauce_chrome_34', 'sauce_chrome_33'],//, 'sauce_firefox'], | ||
browsers: ['sauce_chrome_mac', 'sauce_chrome_win', 'sauce_firefox'], | ||
singleRun: true, | ||
@@ -173,4 +130,4 @@ autoWatch: false, | ||
'<%= gitinfo.local.branch.current.lastCommitAuthor %>', | ||
'<%= gitinfo.local.branch.current.lastCommitTime %>', | ||
], | ||
'<%= gitinfo.local.branch.current.lastCommitTime %>' | ||
] | ||
}, | ||
@@ -193,31 +150,56 @@ customLaunchers: CUSTOM_LAUNCHER | ||
}, | ||
uglify: { | ||
browserify: { | ||
freedom: { | ||
files: { | ||
'freedom.js': FILES.lib.concat(FILES.srcCore).concat(FILES.srcPlatform) | ||
'freedom.js': ['src/util/workerEntry.js'] | ||
}, | ||
options: { | ||
sourceMap: true, | ||
mangle: false, | ||
beautify: true, | ||
preserveComments: function(node, comment) { | ||
return comment.value.indexOf('jslint') !== 0; | ||
}, | ||
banner: require('fs').readFileSync('src/util/preamble.js', 'utf8'), | ||
footer: require('fs').readFileSync('src/util/postamble.js', 'utf8') | ||
postBundleCB: function (err, src, next) { | ||
next(err, require('fs').readFileSync('src/util/header.txt') + src); | ||
} | ||
} | ||
}, | ||
min: { | ||
frame: { | ||
files: { | ||
'freedom.min.js': ['freedom.js'] | ||
'spec/helper/frame.js': ['src/util/frameEntry.js'] | ||
} | ||
}, | ||
jasmine_unit: { | ||
files: { | ||
'spec.js': FILES.specCoreUnit.concat( | ||
FILES.specPlatformUnit, | ||
FILES.specProviderUnit | ||
) | ||
} | ||
}, | ||
jasmine_coverage: { | ||
files: { | ||
'spec.js': FILES.specCoreUnit.concat( | ||
FILES.specPlatformUnit, | ||
FILES.specProviderUnit | ||
) | ||
}, | ||
options: { | ||
mangle: { except: ['global'] }, | ||
preserveComments: 'some', | ||
sourceMap: true, | ||
sourceMapIn: 'freedom.js.map' | ||
transform: ['folderify', ['browserify-istanbul', { | ||
// Note: bundle must be ignored, | ||
ignore: ['**/spec/**', '**/providers/**', '**/src/bundle.js'] | ||
}]] | ||
} | ||
}, | ||
jasmine_full: { | ||
files: { | ||
'spec.js': FILES.specCoreUnit.concat( | ||
FILES.specPlatformUnit, | ||
FILES.specProviderUnit, | ||
FILES.specProviderIntegration | ||
), | ||
'spec/helper/frame.js': ['src/util/frameEntry.js'] | ||
} | ||
}, | ||
options: { | ||
ignore: ['ws'], | ||
transform: ['folderify'] | ||
} | ||
}, | ||
clean: ['freedom.js', 'freedom.js.map', 'freedom.min.js', 'freedom.min.js.map'], | ||
clean: ['freedom.js', 'freedom.js.map', 'freedom.min.js', 'freedom.min.js.map', 'spec.js', 'spec/helper/frame.js'], | ||
yuidoc: { | ||
@@ -256,3 +238,3 @@ compile: { | ||
keepalive: true, | ||
base: ["./","demo/"], | ||
base: ["./", "demo/"], | ||
open: "http://localhost:8000/demo/" | ||
@@ -281,3 +263,3 @@ } | ||
// if the workspace is dirty, abort publishing (to avoid publishing local changes) | ||
abortIfDirty: true, | ||
abortIfDirty: true | ||
} | ||
@@ -289,6 +271,6 @@ } | ||
// Load tasks. | ||
grunt.loadNpmTasks('grunt-browserify'); | ||
grunt.loadNpmTasks('grunt-contrib-jshint'); | ||
grunt.loadNpmTasks('grunt-contrib-clean'); | ||
grunt.loadNpmTasks('grunt-contrib-yuidoc'); | ||
grunt.loadNpmTasks('grunt-contrib-uglify'); | ||
grunt.loadNpmTasks('grunt-coveralls'); | ||
@@ -301,20 +283,41 @@ grunt.loadNpmTasks('grunt-contrib-connect'); | ||
grunt.registerTask('watch', 'Run browserify and karma in watch mode.', | ||
function () { | ||
grunt.config.merge({ | ||
browserify: { | ||
options: { | ||
watch: true | ||
} | ||
} | ||
}); | ||
}); | ||
// Default tasks. | ||
grunt.registerTask('build', [ | ||
'jshint', | ||
'uglify', | ||
'gitinfo', | ||
'connect:default' | ||
'browserify:freedom' | ||
]); | ||
grunt.registerTask('unit', [ | ||
'browserify:frame', | ||
'browserify:jasmine_unit', | ||
'connect:default', | ||
'karma:phantom' | ||
]); | ||
grunt.registerTask('test', [ | ||
'build', | ||
'jshint', | ||
'browserify:frame', | ||
'browserify:jasmine_full', | ||
'connect:default', | ||
'karma:single' | ||
]); | ||
grunt.registerTask('debug', [ | ||
'watch', | ||
'build', | ||
'connect:default', | ||
'browserify:jasmine_full', | ||
'karma:watch' | ||
]); | ||
grunt.registerTask('demo', [ | ||
'uglify', | ||
'connect:demo', | ||
'browserify:freedom', | ||
'connect:demo' | ||
]); | ||
@@ -325,6 +328,9 @@ | ||
//When run from Travis from jobs *.1 | ||
if (jobParts.length > 1 && jobParts[1] == '1') { | ||
if (jobParts.length > 1 && jobParts[1] === '1') { | ||
grunt.registerTask('ci', [ | ||
'build', | ||
'browserify:frame', | ||
'browserify:jasmine_coverage', | ||
'connect:default', | ||
'karma:phantom', | ||
'gitinfo', | ||
'karma:saucelabs', | ||
@@ -335,3 +341,5 @@ 'coveralls:report' | ||
grunt.registerTask('ci', [ | ||
'build', | ||
'browserify:frame', | ||
'browserify:jasmine_unit', | ||
'connect:default', | ||
'karma:phantom' | ||
@@ -342,9 +350,12 @@ ]); | ||
grunt.registerTask('ci', [ | ||
'build', | ||
'browserify:frame', | ||
'browserify:jasmine_unit', | ||
'connect:default', | ||
'karma:phantom', | ||
'karma:saucelabs', | ||
'gitinfo', | ||
'karma:saucelabs' | ||
]); | ||
} | ||
grunt.registerTask('release', function(arg) { | ||
grunt.registerTask('release', function (arg) { | ||
if (arguments.length === 0) { | ||
@@ -355,3 +366,3 @@ arg = 'patch'; | ||
'default', | ||
'bump:'+arg, | ||
'bump:' + arg, | ||
'npm-publish' | ||
@@ -362,3 +373,3 @@ ]); | ||
grunt.registerTask('default', ['build', 'karma:phantom']); | ||
grunt.registerTask('default', ['build', 'unit']); | ||
}; | ||
@@ -368,2 +379,1 @@ | ||
module.exports.CUSTOM_LAUNCHER = CUSTOM_LAUNCHER; | ||
module.exports.unGlob = unGlob; |
@@ -0,15 +1,13 @@ | ||
/*jslint node:true */ | ||
var FILES = require('./Gruntfile').FILES; | ||
var karmaFiles = require('./Gruntfile').unGlob([].concat( | ||
FILES.srcCore, | ||
FILES.srcPlatform, | ||
FILES.srcJasmineHelper, | ||
FILES.specCoreUnit, | ||
FILES.specPlatformUnit, | ||
FILES.srcProvider, | ||
FILES.specProviderUnit, | ||
FILES.srcProviderIntegration, | ||
FILES.specProviderIntegration | ||
)); | ||
module.exports = function(config) { | ||
var locate_promises = function () { | ||
'use strict'; | ||
var includer = require.resolve('es6-promise'), | ||
base = includer.substr(0, includer.lastIndexOf('es6-promise')); | ||
return base + 'es6-promise/dist/promise-1.0.0.js'; | ||
}; | ||
module.exports = function (config) { | ||
'use strict'; | ||
config.set({ | ||
@@ -26,6 +24,8 @@ | ||
// Testing Providers for now | ||
files: karmaFiles.include, | ||
// list of files to exclude | ||
exclude: karmaFiles.exclude, | ||
files: [ | ||
require.resolve('es5-shim'), | ||
locate_promises(), | ||
'spec.js', | ||
{pattern: 'spec/helper/frame.js', included: false} | ||
], | ||
@@ -57,14 +57,3 @@ // web server port | ||
// available reporters: https://npmjs.org/browse/keyword/karma-reporter | ||
reporters: ['progress', 'coverage', 'saucelabs', 'unicorn', 'story'], | ||
// preprocess matching files before serving them to the browser | ||
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor | ||
preprocessors: [].concat( | ||
FILES.srcCore, | ||
FILES.srcPlatform, | ||
FILES.srcProvider | ||
).reduce(function(prev, curr, i, arr) { | ||
prev[curr] = 'coverage'; | ||
return prev; | ||
}, {}), | ||
reporters: ['progress', 'html', 'coverage', 'saucelabs', 'unicorn', 'story'], | ||
@@ -80,4 +69,4 @@ // Coverage report options | ||
sauceLabs: {}, | ||
customLaunchers: {}, | ||
customLaunchers: {} | ||
}); | ||
}; |
{ | ||
"name": "freedom", | ||
"description": "Embracing a distributed web", | ||
"version": "0.5.6", | ||
"version": "0.6.0-rc1", | ||
"homepage": "http://freedomjs.org", | ||
@@ -20,25 +20,29 @@ "bugs": { | ||
"devDependencies": { | ||
"es5-shim": "^3.1.1", | ||
"browserify-istanbul": "^0.1.2", | ||
"es5-shim": "^4.0.0", | ||
"es6-promise": "^1.0.0", | ||
"folderify": "^0.6.0", | ||
"grunt": "~0.4.3", | ||
"grunt-browserify": "^3.0.0", | ||
"grunt-bump": "0.0.15", | ||
"grunt-contrib-clean": "~0.6.0", | ||
"grunt-contrib-connect": "~0.8.0", | ||
"grunt-contrib-jshint": "~0.10.0", | ||
"grunt-contrib-uglify": "~0.5.1", | ||
"grunt-contrib-uglify": "~0.6.0", | ||
"grunt-contrib-yuidoc": "~0.5.0", | ||
"grunt-coveralls": "~1.0.0", | ||
"grunt-gitinfo": "~0.1.6", | ||
"grunt-karma": "~0.9.0", | ||
"grunt-npm": "0.0.2", | ||
"istanbul": "~0.3.0", | ||
"karma": "~0.12.21", | ||
"grunt-karma": "~0.8.3", | ||
"karma-jasmine": "~0.2.2", | ||
"karma-chrome-launcher": "~0.1.3", | ||
"karma-coverage": "~0.2.6", | ||
"karma-firefox-launcher": "~0.1.3", | ||
"karma-jasmine": "~0.2.2", | ||
"karma-jasmine-html-reporter": "^0.1.5", | ||
"karma-phantomjs-launcher": "~0.1.4", | ||
"karma-coverage": "~0.2.6", | ||
"karma-sauce-launcher": "~0.2.8", | ||
"karma-unicorn-reporter": "^0.1.4", | ||
"karma-story-reporter": "^0.2.2", | ||
"grunt-bump": "0.0.15", | ||
"grunt-npm": "0.0.2" | ||
"karma-unicorn-reporter": "^0.1.4" | ||
}, | ||
@@ -48,3 +52,7 @@ "scripts": { | ||
"prepublish": "grunt default" | ||
}, | ||
"dependencies": { | ||
"include-folder": "^0.7.0", | ||
"node-json-minify": "^0.1.3-a" | ||
} | ||
} |
@@ -1,11 +0,12 @@ | ||
/*globals fdom:true */ | ||
/*jslint indent:2,white:true,sloppy:true,sub:true */ | ||
/*jslint indent:2,white:true,sloppy:true,node:true */ | ||
var EventInterface = require('../../src/proxy/eventInterface'); | ||
var Consumer = require('../../src/consumer'); | ||
var util = require('../../src/util'); | ||
/** | ||
* Core freedom services available to all modules. | ||
* Created by a local manager in response to a 'core' request. | ||
* Created by the environment helper in response to a 'core' request. | ||
* @Class Core_unprivileged | ||
* @constructor | ||
* @param {Port.Manager} manager The manager this core is connected with. | ||
* @param {Manager} manager The manager this core is connected with. | ||
* @private | ||
@@ -15,2 +16,3 @@ */ | ||
this.manager = manager; | ||
this.debug = this.manager.debug; | ||
}; | ||
@@ -24,3 +26,3 @@ | ||
* Create a custom channel. | ||
* Returns the structure {channel: fdom.proxy.Deferred, identifier: Object}, | ||
* Returns the structure {channel: Proxy, identifier: Object}, | ||
* where the identifier can be 'redeemed' by another module or provider using | ||
@@ -33,8 +35,8 @@ * bind channel, at which point the deferred object will resolve with a channel | ||
Core_unprivileged.prototype.createChannel = function(continuation) { | ||
var proxy = new fdom.port.Proxy(fdom.proxy.EventInterface), | ||
id = fdom.util.getId(), | ||
var proxy = new Consumer(EventInterface, this.manager.debug), | ||
id = util.getId(), | ||
chan = this.getChannel(proxy); | ||
this.manager.setup(proxy); | ||
if (this.manager.delegate && this.manager.toDelegate['core']) { | ||
if (this.manager.delegate && this.manager.toDelegate.core) { | ||
this.manager.emit(this.manager.delegate, { | ||
@@ -116,4 +118,4 @@ type: 'Delegation', | ||
if (newSource) { | ||
fdom.debug.log('making local proxy for core binding'); | ||
source = new fdom.port.Proxy(fdom.proxy.EventInterface); | ||
this.debug.debug('making local proxy for core binding'); | ||
source = new Consumer(EventInterface, this.debug); | ||
this.manager.setup(source); | ||
@@ -124,6 +126,6 @@ } | ||
if (toBind && toBind.local) { | ||
fdom.debug.log('doing local binding with ' + source); | ||
this.debug.debug('Binding a channel to port on this hub:' + source); | ||
this.manager.createLink(source, identifier, toBind.proxy, 'default'); | ||
delete Core_unprivileged.unboundChannels[identifier]; | ||
if (this.manager.delegate && this.manager.toDelegate['core']) { | ||
if (this.manager.delegate && this.manager.toDelegate.core) { | ||
this.manager.emit(this.manager.delegate, { | ||
@@ -140,3 +142,3 @@ type: 'Delegation', | ||
} else if (toBind && toBind.remote) { | ||
fdom.debug.log('doing remote binding downward'); | ||
this.debug.debug('Binding a channel into a module.'); | ||
this.manager.createLink( | ||
@@ -157,4 +159,4 @@ source, | ||
delete Core_unprivileged.unboundChannels[identifier]; | ||
} else if (this.manager.delegate && this.manager.toDelegate['core']) { | ||
fdom.debug.warn('delegating bind request for unseen ID:' + identifier); | ||
} else if (this.manager.delegate && this.manager.toDelegate.core) { | ||
this.debug.info('delegating channel bind for an unknown ID:' + identifier); | ||
this.manager.emit(this.manager.delegate, { | ||
@@ -179,4 +181,4 @@ type: 'Delegation', | ||
} else { | ||
fdom.debug.warn('Asked to bind unknown channel: ' + identifier); | ||
fdom.debug.log(Core_unprivileged.unboundChannels); | ||
this.debug.warn('Asked to bind unknown channel: ' + identifier); | ||
this.debug.log(Core_unprivileged.unboundChannels); | ||
continuation(); | ||
@@ -209,3 +211,3 @@ return; | ||
* log object with an interface similar to the standard javascript console, | ||
* which logs via fdom.debug. | ||
* which logs via debug. | ||
* @method getLogger | ||
@@ -216,14 +218,3 @@ * @param {String} name The name of the logger, used as its 'source' | ||
Core_unprivileged.prototype.getLogger = function(name, callback) { | ||
var log = function(severity, source) { | ||
var args = Array.prototype.splice.call(arguments, 2); | ||
this.format(severity, source, args); | ||
}, | ||
logger = { | ||
debug: log.bind(fdom.debug, 'debug', name), | ||
info: log.bind(fdom.debug, 'info', name), | ||
log: log.bind(fdom.debug, 'log', name), | ||
warn: log.bind(fdom.debug, 'warn', name), | ||
error: log.bind(fdom.debug, 'error', name) | ||
}; | ||
callback(logger); | ||
callback(this.manager.debug.getLogger(name)); | ||
}; | ||
@@ -241,2 +232,3 @@ | ||
fdom.apis.register("core", Core_unprivileged); | ||
exports.provider = Core_unprivileged; | ||
exports.name = "core"; |
@@ -1,3 +0,4 @@ | ||
/*globals fdom:true, console */ | ||
/*jslint indent:2,white:true,sloppy:true */ | ||
/*globals console */ | ||
/*jslint indent:2,white:true,sloppy:true, node:true */ | ||
var util = require('../../src/util'); | ||
@@ -13,6 +14,5 @@ /** | ||
var Echo_unprivileged = function(mod, dispatchEvent) { | ||
fdom.debug.log('Echo Created!'); | ||
this.mod = mod; | ||
this.dispatchEvent = dispatchEvent; | ||
fdom.util.handleEvents(this); | ||
util.handleEvents(this); | ||
@@ -75,2 +75,3 @@ // The Core object for managing channels. | ||
fdom.apis.register("core.echo", Echo_unprivileged); | ||
exports.provider = Echo_unprivileged; | ||
exports.name = "core.echo"; |
@@ -1,5 +0,7 @@ | ||
/*globals fdom, process, console */ | ||
/*jslint indent:2,sloppy:true */ | ||
/*globals process, console */ | ||
/*jslint indent:2,sloppy:true, node:true */ | ||
var util = require('../../src/util'); | ||
/** | ||
* A FreeDOM logging provider that logs to chrome, firefox, and node consoles. | ||
* A freedom.js logging provider that logs to chrome, firefox, and node consoles. | ||
* @Class Logger_console | ||
@@ -10,9 +12,9 @@ * @constructor | ||
*/ | ||
var Logger_console = function (app, dispatchEvent) { | ||
this.app = app; | ||
this.config = this.app.config; | ||
this.console = this.app.config.global.console; | ||
fdom.util.handleEvents(this); | ||
var Logger_console = function (app) { | ||
this.level = (app.config && app.config.debug) || 'log'; | ||
this.console = (app.config && app.config.global.console); | ||
util.handleEvents(this); | ||
}; | ||
/** | ||
@@ -40,9 +42,13 @@ * Logging levels, for filtering output. | ||
} | ||
if (typeof arr === 'string') { | ||
arr = [arr]; | ||
} | ||
if (Logger_console.level[this.config.debug] !== undefined && | ||
Logger_console.level[severity] < Logger_console.level[this.config.debug]) { | ||
if (Logger_console.level[this.level] !== undefined && | ||
Logger_console.level[severity] < Logger_console.level[this.level]) { | ||
return; | ||
} | ||
if (typeof process !== 'undefined' && source) { | ||
if (typeof process !== 'undefined' && | ||
{}.toString.call(process) === '[object process]' && source) { | ||
arr.unshift('\x1B[39m'); | ||
@@ -120,2 +126,3 @@ arr.unshift('\x1B[31m' + source); | ||
/** REGISTER PROVIDER **/ | ||
fdom.apis.register("core.logger", Logger_console); | ||
exports.provider = Logger_console; | ||
exports.name = 'core.logger'; |
@@ -1,3 +0,3 @@ | ||
/*globals fdom:true, console */ | ||
/*jslint indent:2,white:true,sloppy:true */ | ||
/*globals console */ | ||
/*jslint indent:2,white:true,sloppy:true,node:true */ | ||
@@ -26,3 +26,3 @@ /** | ||
OAuth.register = function(handler) { | ||
this.handlers.push(handler); | ||
OAuth.handlers.push(handler); | ||
}; | ||
@@ -55,2 +55,4 @@ | ||
fdom.apis.register("core.oauth", OAuth); | ||
exports.register = OAuth.register; | ||
exports.provider = OAuth; | ||
exports.name = 'core.oauth'; |
@@ -1,6 +0,6 @@ | ||
/*globals fdom:true, console, RTCPeerConnection, webkitRTCPeerConnection */ | ||
/*globals console, RTCPeerConnection, webkitRTCPeerConnection */ | ||
/*globals mozRTCPeerConnection, RTCSessionDescription, RTCIceCandidate */ | ||
/*globals mozRTCSessionDescription, mozRTCIceCandidate */ | ||
/*globals ArrayBuffer */ | ||
/*jslint indent:2,sloppy:true */ | ||
/*globals ArrayBuffer, Blob */ | ||
/*jslint indent:2,sloppy:true,node:true */ | ||
/** | ||
@@ -18,4 +18,4 @@ * DataPeer - a class that wraps peer connections and data channels. | ||
var constraints, | ||
config, | ||
i; | ||
config, | ||
i; | ||
this.peerName = peerName; | ||
@@ -38,3 +38,3 @@ this.channels = {}; | ||
this.RTCSessionDescription = mocks.RTCSessionDescription; | ||
} else if (typeof RTCSessionDescription !== "undefined"){ | ||
} else if (typeof RTCSessionDescription !== "undefined") { | ||
this.RTCSessionDescription = RTCSessionDescription; | ||
@@ -49,5 +49,5 @@ } else if (typeof mozRTCSessionDescription !== "undefined") { | ||
this.RTCIceCandidate = mocks.RTCIceCandidate; | ||
} else if (typeof RTCIceCandidate !== "undefined"){ | ||
} else if (typeof RTCIceCandidate !== "undefined") { | ||
this.RTCIceCandidate = RTCIceCandidate; | ||
} else if (typeof mozRTCIceCandidate !== "undefined") { | ||
} else if (typeof mozRTCIceCandidate !== "undefined") { | ||
this.RTCIceCandidate = mozRTCIceCandidate; | ||
@@ -89,3 +89,3 @@ } else { | ||
this.pcState = SimpleDataPeerState.CONNECTED; | ||
this.onConnectedQueue.map(function(callback) { callback(); }); | ||
this.onConnectedQueue.map(function (callback) { callback(); }); | ||
} | ||
@@ -102,3 +102,3 @@ }.bind(this)); | ||
SimpleDataPeer.prototype.createOffer = function (constaints, continuation) { | ||
this.pc.createOffer(continuation, function() { | ||
this.pc.createOffer(continuation, function () { | ||
console.error('core.peerconnection createOffer failed.'); | ||
@@ -127,3 +127,3 @@ }, constaints); | ||
}.bind(this); | ||
dataChannel.onerror = function(err) { | ||
dataChannel.onerror = function (err) { | ||
//@(ryscheng) todo - replace with errors that work across the interface | ||
@@ -165,3 +165,4 @@ console.error(err); | ||
//console.log(this.peerName + ": " + "handleSignalMessage: \n" + messageText); | ||
var json = JSON.parse(messageText); | ||
var json = JSON.parse(messageText), | ||
ice_candidate; | ||
@@ -193,3 +194,3 @@ // TODO: If we are offering and they are also offerring at the same time, | ||
//console.log(this.peerName + ": Adding ice candidate: " + JSON.stringify(json.candidate)); | ||
var ice_candidate = new this.RTCIceCandidate(json.candidate); | ||
ice_candidate = new this.RTCIceCandidate(json.candidate); | ||
this.pc.addIceCandidate(ice_candidate); | ||
@@ -323,3 +324,3 @@ } else { | ||
this.pcState = SimpleDataPeerState.CONNECTED; | ||
this.onConnectedQueue.map(function(callback) { callback(); }); | ||
this.onConnectedQueue.map(function (callback) { callback(); }); | ||
} | ||
@@ -394,39 +395,41 @@ }; | ||
RTCSessionDescription: this.RTCSessionDescription, | ||
RTCIceCandidate: this.RTCIceCandidate}; | ||
var self = this; | ||
var dataChannelCallbacks = { | ||
// onOpenFn is called at the point messages will actually get through. | ||
onOpenFn: function (dataChannel, info) { | ||
self.dispatchEvent("onOpenDataChannel", | ||
RTCIceCandidate: this.RTCIceCandidate}, | ||
self = this, | ||
dataChannelCallbacks = { | ||
// onOpenFn is called at the point messages will actually get through. | ||
onOpenFn: function (dataChannel, info) { | ||
self.dispatchEvent("onOpenDataChannel", | ||
{ channelId: info.label}); | ||
}, | ||
onCloseFn: function (dataChannel, info) { | ||
self.dispatchEvent("onCloseDataChannel", | ||
}, | ||
onCloseFn: function (dataChannel, info) { | ||
self.dispatchEvent("onCloseDataChannel", | ||
{ channelId: info.label}); | ||
}, | ||
// Default on real message prints it to console. | ||
onMessageFn: function (dataChannel, info, event) { | ||
if (event.data instanceof ArrayBuffer) { | ||
self.dispatchEvent('onReceived', { | ||
'channelLabel': info.label, | ||
'buffer': event.data | ||
}); | ||
} else if (event.data instanceof Blob) { | ||
self.dispatchEvent('onReceived', { | ||
'channelLabel': info.label, | ||
'binary': event.data | ||
}); | ||
} else if (typeof (event.data) === 'string') { | ||
self.dispatchEvent('onReceived', { | ||
'channelLabel': info.label, | ||
'text': event.data | ||
}); | ||
}, | ||
// Default on real message prints it to console. | ||
onMessageFn: function (dataChannel, info, event) { | ||
if (event.data instanceof ArrayBuffer) { | ||
self.dispatchEvent('onReceived', { | ||
'channelLabel': info.label, | ||
'buffer': event.data | ||
}); | ||
} else if (event.data instanceof Blob) { | ||
self.dispatchEvent('onReceived', { | ||
'channelLabel': info.label, | ||
'binary': event.data | ||
}); | ||
} else if (typeof (event.data) === 'string') { | ||
self.dispatchEvent('onReceived', { | ||
'channelLabel': info.label, | ||
'text': event.data | ||
}); | ||
} | ||
}, | ||
// Default on error, prints it. | ||
onErrorFn: function (dataChannel, info, err) { | ||
console.error(dataChannel.peerName + ": dataChannel(" + | ||
dataChannel.dataChannel.label + "): error: ", err); | ||
} | ||
}, | ||
// Default on error, prints it. | ||
onErrorFn: function (dataChannel, info, err) { | ||
console.error(dataChannel.peerName + ": dataChannel(" + | ||
dataChannel.dataChannel.label + "): error: ", err); | ||
} | ||
}; | ||
channelId, | ||
openDataChannelContinuation; | ||
@@ -454,4 +457,4 @@ this.peer = new SimpleDataPeer(this.peerName, stunServers, | ||
console.log(this.peerName + ' initiating connection'); | ||
var channelId = 'hello' + Math.random().toString(); | ||
var openDataChannelContinuation = function(success, error) { | ||
channelId = 'hello' + Math.random().toString(); | ||
openDataChannelContinuation = function (success, error) { | ||
if (error) { | ||
@@ -510,2 +513,3 @@ continuation(undefined, error); | ||
fdom.apis.register('core.peerconnection', PeerConnection); | ||
exports.provider = PeerConnection; | ||
exports.name = 'core.peerconnection'; |
@@ -1,3 +0,5 @@ | ||
/*globals fdom, localStorage */ | ||
/*jslint indent:2,sloppy:true */ | ||
/*globals localStorage */ | ||
/*jslint indent:2,sloppy:true,node:true */ | ||
var util = require('../../src/util'); | ||
/** | ||
@@ -16,3 +18,3 @@ * A FreeDOM core.storage provider that depends on localStorage | ||
this.app = app; | ||
fdom.util.handleEvents(this); | ||
util.handleEvents(this); | ||
}; | ||
@@ -79,3 +81,3 @@ | ||
/** REGISTER PROVIDER **/ | ||
fdom.apis.register("core.storage", Storage_unprivileged); | ||
exports.provider = Storage_unprivileged; | ||
exports.name = 'core.storage'; |
@@ -1,3 +0,5 @@ | ||
/*globals fdom, document */ | ||
/*jslint indent:2,sloppy:true */ | ||
/*globals document */ | ||
/*jslint indent:2,sloppy:true,node:true */ | ||
var util = require('../../src/util'); | ||
/** | ||
@@ -20,3 +22,3 @@ * A freedom.js view is the interface for user interaction. | ||
this.module = caller; | ||
fdom.util.handleEvents(this); | ||
util.handleEvents(this); | ||
}; | ||
@@ -55,3 +57,3 @@ | ||
if (what.file) { | ||
fdom.resources.get(this.module.manifestId, what.file).then( | ||
this.module.resource.get(this.module.manifestId, what.file).then( | ||
function (fname) { | ||
@@ -113,2 +115,3 @@ this.finishOpen(root, frame, fname, continuation); | ||
fdom.apis.register("core.view", View_unprivileged); | ||
exports.provider = View_unprivileged; | ||
exports.name = 'core.view'; |
@@ -1,3 +0,3 @@ | ||
/*globals freedom:true, fdom, WebSocket, console, require*/ | ||
/*jslint sloppy:true*/ | ||
/*globals WebSocket, ArrayBuffer, Blob, Uint8Array, console */ | ||
/*jslint sloppy:true, node:true */ | ||
@@ -14,3 +14,4 @@ /** | ||
var WS = function (module, dispatchEvent, url, protocols, socket) { | ||
var WSImplementation = null; | ||
var WSImplementation = null, | ||
error; | ||
this.isNode = false; | ||
@@ -37,3 +38,3 @@ if (typeof socket !== 'undefined') { | ||
} catch (e) { | ||
var error = {}; | ||
error = {}; | ||
if (e instanceof SyntaxError) { | ||
@@ -67,5 +68,6 @@ error.errcode = 'SYNTAX'; | ||
WS.prototype.send = function(data, continuation) { | ||
var toSend = data.text || data.binary || data.buffer; | ||
var errcode, message; | ||
WS.prototype.send = function (data, continuation) { | ||
var toSend = data.text || data.binary || data.buffer, | ||
errcode, | ||
message; | ||
@@ -77,4 +79,4 @@ if (toSend) { | ||
this.websocket.send( | ||
new Uint8Array(toSend), | ||
{ binary:true }, | ||
new Uint8Array(toSend), | ||
{ binary: true }, | ||
this.onError.bind(this) | ||
@@ -108,11 +110,11 @@ ); | ||
WS.prototype.getReadyState = function(continuation) { | ||
WS.prototype.getReadyState = function (continuation) { | ||
continuation(this.websocket.readyState); | ||
}; | ||
WS.prototype.getBufferedAmount = function(continuation) { | ||
WS.prototype.getBufferedAmount = function (continuation) { | ||
continuation(this.websocket.bufferedAmount); | ||
}; | ||
WS.prototype.close = function(code, reason, continuation) { | ||
WS.prototype.close = function (code, reason, continuation) { | ||
try { | ||
@@ -132,3 +134,3 @@ if (code && reason) { | ||
} | ||
continuation(undefined,{ | ||
continuation(undefined, { | ||
errcode: errorCode, | ||
@@ -140,7 +142,7 @@ message: e.message | ||
WS.prototype.onOpen = function(event) { | ||
WS.prototype.onOpen = function (event) { | ||
this.dispatchEvent('onOpen'); | ||
}; | ||
WS.prototype.onMessage = function(event, flags) { | ||
WS.prototype.onMessage = function (event, flags) { | ||
var data = {}; | ||
@@ -161,3 +163,3 @@ if (this.isNode && flags && flags.binary) { | ||
WS.prototype.onError = function(event) { | ||
WS.prototype.onError = function (event) { | ||
// Nothing to pass on | ||
@@ -168,3 +170,3 @@ // See: http://stackoverflow.com/a/18804298/300539 | ||
WS.prototype.onClose = function(event) { | ||
WS.prototype.onClose = function (event) { | ||
this.dispatchEvent('onClose', | ||
@@ -176,6 +178,3 @@ {code: event.code, | ||
/** REGISTER PROVIDER **/ | ||
if (typeof fdom !== 'undefined') { | ||
fdom.apis.register('core.websocket', WS); | ||
} | ||
exports.provider = WS; | ||
exports.name = 'core.websocket'; |
@@ -1,45 +0,47 @@ | ||
/*globals OAuth, Promise,global,console */ | ||
/*jslint indent:2,browser:true */ | ||
(function () { | ||
'use strict'; | ||
var oAuthRedirectId = 'freedom.oauth.redirect.handler', | ||
listeners = {}; | ||
/*jslint indent:2,browser:true, node:true */ | ||
var PromiseCompat = require('es6-promise').Promise; | ||
var oAuthRedirectId = 'freedom.oauth.redirect.handler', | ||
listeners = {}; | ||
/** | ||
* Listen for messages from a relay iframe. | ||
*/ | ||
function monitorFrame(src, oAuth) { | ||
return new Promise(function (resolve, reject) { | ||
var frame = global.document.createElement('iframe'), | ||
state = oAuthRedirectId + Math.random(); | ||
frame.src = src; | ||
frame.style.display = 'none'; | ||
global.document.body.appendChild(frame); | ||
frame.addEventListener('load', function () { | ||
resolve({ | ||
redirect: src, | ||
state: state | ||
}); | ||
listeners[state] = function (url) { | ||
this.dispatchEvent("oAuthEvent", url); | ||
}.bind(oAuth); | ||
/** | ||
* Listen for messages from a relay iframe. | ||
*/ | ||
function monitorFrame(src, oAuth) { | ||
'use strict'; | ||
return new PromiseCompat(function (resolve, reject) { | ||
var frame = global.document.createElement('iframe'), | ||
state = oAuthRedirectId + Math.random(); | ||
frame.src = src; | ||
frame.style.display = 'none'; | ||
frame.contentWindow.postMessage(state, '*'); | ||
global.document.body.appendChild(frame); | ||
frame.addEventListener('load', function () { | ||
resolve({ | ||
redirect: src, | ||
state: state | ||
}); | ||
listeners[state] = function (url) { | ||
this.dispatchEvent("oAuthEvent", url); | ||
}.bind(oAuth); | ||
window.addEventListener('message', function (frame, msg) { | ||
if (msg.data && msg.data.key && msg.data.url && listeners[msg.data.key]) { | ||
listeners[msg.data.key](msg.data.url); | ||
document.body.removeChild(frame); | ||
} | ||
}.bind({}, frame), false); | ||
frame.contentWindow.postMessage(state, '*'); | ||
}); | ||
} | ||
/** | ||
* If we have a local domain, and freedom.js is loaded at startup, we can use | ||
* the local page as a redirect URI. | ||
*/ | ||
window.addEventListener('message', function (frame, msg) { | ||
if (msg.data && msg.data.key && msg.data.url && listeners[msg.data.key]) { | ||
listeners[msg.data.key](msg.data.url); | ||
document.body.removeChild(frame); | ||
} | ||
}.bind({}, frame), false); | ||
}); | ||
} | ||
/** | ||
* If we have a local domain, and freedom.js is loaded at startup, we can use | ||
* the local page as a redirect URI. | ||
*/ | ||
exports.register = function (OAuth) { | ||
'use strict'; | ||
if (typeof global !== 'undefined' && global && global.document) { | ||
@@ -51,3 +53,3 @@ OAuth.register(function (redirectURIs, instance) { | ||
if ((redirectURIs[i].indexOf('http://') === 0 || | ||
redirectURIs[i].indexOf('https://') === 0) && | ||
redirectURIs[i].indexOf('https://') === 0) && | ||
redirectURIs[i].indexOf('oauth-relay.html') > 0) { | ||
@@ -58,3 +60,3 @@ promises.push(monitorFrame(redirectURIs[i], instance)); | ||
if (promises.length) { | ||
return Promise.race(promises); | ||
return PromiseCompat.race(promises); | ||
} else { | ||
@@ -65,2 +67,2 @@ return false; | ||
} | ||
}()); | ||
}; |
@@ -1,2 +0,2 @@ | ||
/*globals freedom:true */ | ||
/*globals freedom:true, exports */ | ||
/*jslint indent:2, white:true, sloppy:true, browser:true */ | ||
@@ -24,3 +24,3 @@ | ||
this.clientId = 'Test User.0'; //My clientId | ||
this.social = freedom.social(); | ||
this.social = freedom(); | ||
@@ -195,3 +195,8 @@ //Populate a fake roster | ||
if (typeof freedom !== 'undefined') { | ||
freedom.social().provideAsynchronous(LoopbackSocialProvider); | ||
freedom().provideAsynchronous(LoopbackSocialProvider); | ||
} | ||
if (typeof exports !== 'undefined') { | ||
exports.provider = LoopbackSocialProvider; | ||
exports.name = 'social'; | ||
} |
@@ -9,3 +9,4 @@ { | ||
"social" | ||
] | ||
], | ||
"default": "social" | ||
} |
@@ -29,3 +29,3 @@ /*globals freedom:true, WebSocket, DEBUG */ | ||
} | ||
this.social= freedom.social(); | ||
this.social = freedom(); | ||
@@ -274,3 +274,9 @@ this.conn = null; // Web Socket | ||
if (typeof freedom !== 'undefined') { | ||
freedom.social().provideAsynchronous(WSSocialProvider); | ||
freedom().provideAsynchronous(WSSocialProvider); | ||
} | ||
if (typeof exports !== 'undefined') { | ||
exports.provider = WSSocialProvider; | ||
exports.name = 'social'; | ||
} | ||
@@ -10,2 +10,3 @@ { | ||
], | ||
"default": "social", | ||
"permissions": [ | ||
@@ -12,0 +13,0 @@ "core.websocket" |
@@ -279,9 +279,10 @@ /** | ||
/** REGISTER PROVIDER **/ | ||
if (typeof freedom !== 'undefined' && | ||
typeof freedom.storage !== 'undefined') { | ||
freedom.storage().provideAsynchronous(IndexedDBStorageProvider); | ||
if (typeof freedom !== 'undefined') { | ||
freedom().provideAsynchronous(IndexedDBStorageProvider); | ||
} | ||
if (typeof freedom !== 'undefined' && | ||
typeof freedom.storebuffer !== 'undefined') { | ||
freedom.storebuffer().provideAsynchronous(IndexedDBStorageProvider); | ||
if (typeof exports !== 'undefined') { | ||
exports.provider = IndexedDBStorageProvider; | ||
exports.name = 'storage'; | ||
} | ||
@@ -11,3 +11,4 @@ { | ||
"permissions": [ | ||
] | ||
], | ||
"default": "storage" | ||
} |
@@ -11,3 +11,4 @@ { | ||
"permissions": [ | ||
] | ||
], | ||
"default": "storebuffer" | ||
} |
@@ -142,3 +142,8 @@ /*globals freedom:true, location */ | ||
if (typeof freedom !== 'undefined') { | ||
freedom.storage().provideAsynchronous(IsolatedStorageProvider); | ||
freedom().provideAsynchronous(IsolatedStorageProvider); | ||
} | ||
if (typeof exports !== 'undefined') { | ||
exports.provider = IsolatedStorageProvider; | ||
exports.name = 'storage'; | ||
} |
@@ -10,2 +10,3 @@ { | ||
], | ||
"default": "storage", | ||
"permissions": [ | ||
@@ -12,0 +13,0 @@ "core.storage" |
@@ -35,3 +35,8 @@ /** | ||
if (typeof freedom !== 'undefined') { | ||
freedom.storage().provideAsynchronous(SharedStorageProvider); | ||
freedom().provideAsynchronous(SharedStorageProvider); | ||
} | ||
if (typeof exports !== 'undefined') { | ||
exports.provider = SharedStorageProvider; | ||
exports.name = 'storage'; | ||
} |
@@ -10,2 +10,3 @@ { | ||
], | ||
"default": "storage", | ||
"permissions": [ | ||
@@ -12,0 +13,0 @@ "core.storage" |
@@ -5,3 +5,2 @@ /* | ||
*/ | ||
var WebRTCTransportProvider = function(dispatchEvent) { | ||
@@ -314,3 +313,8 @@ this.dispatchEvent = dispatchEvent; | ||
if (typeof freedom !== 'undefined') { | ||
freedom.transport().provideAsynchronous(WebRTCTransportProvider); | ||
freedom().provideAsynchronous(WebRTCTransportProvider); | ||
} | ||
if (typeof exports !== 'undefined') { | ||
exports.provider = WebRTCTransportProvider; | ||
exports.name = 'transport'; | ||
} |
@@ -10,2 +10,3 @@ { | ||
], | ||
"default": "transport", | ||
"permissions": [ | ||
@@ -12,0 +13,0 @@ "core.peerconnection" |
var child = freedom.child(); | ||
var log = freedom.log(); | ||
freedom.on('input', function(value) { | ||
var app = freedom(); | ||
app.on('input', function(value) { | ||
//console.log('got ' + value); | ||
freedom.emit('output', value); | ||
app.emit('output', value); | ||
}); | ||
// For testing child dependencies | ||
freedom.on('child-input', function(value) { | ||
app.on('child-input', function(value) { | ||
child.emit('input', value); | ||
}); | ||
child.on('output', function(value) { | ||
freedom.emit('child-output', value); | ||
app.emit('child-output', value); | ||
}); | ||
// For testing manifest-defined apis | ||
freedom.on('do-log', function(value) { | ||
app.on('do-log', function(value) { | ||
log.log(value); | ||
}); | ||
freedom.on('get-log', function() { | ||
app.on('get-log', function() { | ||
log.getLog().then(function(output) { | ||
freedom.emit('log', output); | ||
app.emit('log', output); | ||
}); | ||
}); |
@@ -7,3 +7,5 @@ var friend = freedom.friend(); | ||
freedom.on('create', function() { | ||
var app = freedom(); | ||
app.on('create', function() { | ||
var thisid = id; | ||
@@ -14,4 +16,4 @@ id += 1; | ||
channels[id] = cinfo.channel; | ||
freedom.emit('message', 'creating custom channel ' + thisid); | ||
cinfo.channel.on('message', function(msg) {freedom.emit('message', msg);}); | ||
app.emit('message', 'creating custom channel ' + thisid); | ||
cinfo.channel.on('message', function(msg) {app.emit('message', msg);}); | ||
friend.emit('message', { | ||
@@ -25,4 +27,4 @@ cmd: 'create', | ||
freedom.on('destroy', function(id) { | ||
freedom.emit('message', 'destroying channel ' + id); | ||
app.on('destroy', function(id) { | ||
app.emit('message', 'destroying channel ' + id); | ||
channels[id].close(); | ||
@@ -36,8 +38,8 @@ delete channels[id]; | ||
freedom.on('message', function(id) { | ||
app.on('message', function(id) { | ||
if(channels[id].peer) { | ||
freedom.emit('message', 'sending message to peer ' + id); | ||
app.emit('message', 'sending message to peer ' + id); | ||
channels[id].send({'channelLabel':'test', 'text':'message to peer ' + id}); | ||
} else { | ||
freedom.emit('message', 'sending message to ' + id); | ||
app.emit('message', 'sending message to ' + id); | ||
channels[id].emit('message', 'Message to chan ' + id); | ||
@@ -47,3 +49,3 @@ } | ||
freedom.on('peer', function() { | ||
app.on('peer', function() { | ||
var thisid = id; | ||
@@ -54,9 +56,9 @@ id++; | ||
peer.on('message', function(str) { | ||
freedom.emit('message', "from provider: " + JSON.stringify(str)); | ||
app.emit('message', "from provider: " + JSON.stringify(str)); | ||
}); | ||
channels[thisid] = cinfo.channel; | ||
freedom.emit('message', 'creating custom channel ' + thisid); | ||
app.emit('message', 'creating custom channel ' + thisid); | ||
channels[thisid].on('message', function(m) { | ||
freedom.emit('message', "from custom: " + JSON.stringify(m)); | ||
app.emit('message', "from custom: " + JSON.stringify(m)); | ||
}); | ||
@@ -71,4 +73,4 @@ | ||
friend.on('message', function(str) { | ||
freedom.emit('message', str); | ||
app.emit('message', str); | ||
}); | ||
@@ -1,4 +0,6 @@ | ||
freedom.on('input', function(value) { | ||
var app = freedom(); | ||
app.on('input', function(value) { | ||
//console.log('got ' + value); | ||
freedom.emit('output', value); | ||
app.emit('output', value); | ||
}); |
var channels = []; | ||
var core = freedom.core(); | ||
var app = freedom(); | ||
freedom.on('message', function(msg) { | ||
app.on('message', function(msg) { | ||
if(msg.cmd === 'create') { | ||
@@ -18,4 +19,4 @@ core.bindChannel(msg.chan).then(function(id, chan) { | ||
console.log('got Message!'); | ||
freedom.emit('message', 'channel ' + cid + ' sent ' + msg); | ||
app.emit('message', 'channel ' + cid + ' sent ' + msg); | ||
chan.emit('message', 'channel ' + cid + ' replies ' + msg); | ||
}; |
@@ -17,3 +17,3 @@ var Logger = function (dispatch) { | ||
if (typeof freedom !== 'undefined') { | ||
freedom.log().providePromises(Logger); | ||
freedom().providePromises(Logger); | ||
} |
@@ -10,2 +10,3 @@ { | ||
], | ||
"default": "log", | ||
"api": { | ||
@@ -12,0 +13,0 @@ "log": { |
@@ -5,2 +5,4 @@ var listeningFor = {}; | ||
var base = freedom(); | ||
// action = { | ||
@@ -10,3 +12,3 @@ // name: name to store provider under in "providers" object, | ||
// } | ||
freedom.on("create", function(action) { | ||
base.on("create", function(action) { | ||
var name = action.name; | ||
@@ -25,7 +27,7 @@ var provider = action.provider; | ||
// args: array of arguments to method} | ||
freedom.on("call", function(action){ | ||
base.on("call", function(action){ | ||
var p = providers[action.provider]; | ||
var promise = p[action.method].apply(null, action.args); | ||
promise.then(function(ret) { | ||
freedom.emit("return", { | ||
base.emit("return", { | ||
id: action.id, | ||
@@ -35,3 +37,3 @@ data: ret | ||
}, function(err) { | ||
freedom.emit("error", { | ||
base.emit("error", { | ||
id: action.id, | ||
@@ -43,3 +45,3 @@ data: err | ||
freedom.on('listenForEvent', function(listenEventInfo) { | ||
base.on('listenForEvent', function(listenEventInfo) { | ||
var providerName = listenEventInfo.provider; | ||
@@ -51,3 +53,3 @@ var eventName = listenEventInfo.event; | ||
provider.on(listenEventInfo.event, function (eventPayload) { | ||
freedom.emit('eventFired', {provider: providerName, | ||
base.emit('eventFired', {provider: providerName, | ||
event: eventName, | ||
@@ -60,3 +62,3 @@ eventPayload: eventPayload}); | ||
freedom.on("createChannel", function() { | ||
base.on("createChannel", function() { | ||
//providers.core.createChannel().done(function(chan) { | ||
@@ -66,3 +68,3 @@ freedom.core().createChannel().then(function(chan) { | ||
chan.channel.on("message", function(msg){ | ||
freedom.emit("inFromChannel", { | ||
base.emit("inFromChannel", { | ||
chanId: chan.identifier, | ||
@@ -72,3 +74,3 @@ message: msg | ||
}); | ||
freedom.emit("initChannel", chan.identifier); | ||
base.emit("initChannel", chan.identifier); | ||
}); | ||
@@ -81,4 +83,4 @@ }); | ||
// } | ||
freedom.on("outToChannel", function(action) { | ||
base.on("outToChannel", function(action) { | ||
channels[action.chanId].emit("message", action.message); | ||
}); |
@@ -0,26 +1,19 @@ | ||
var Debug = require('../../../src/debug'); | ||
var Hub = require('../../../src/hub'); | ||
var Resource = require('../../../src/resource'); | ||
var Api = require('../../../src/api'); | ||
var Bundle = require('../../../src/bundle'); | ||
var Manager = require('../../../src/manager'); | ||
var Core = require('../../../providers/core/core.unprivileged'); | ||
var testUtil = require('../../util'); | ||
describe("Core Provider Integration", function() { | ||
var freedom_src; | ||
var freedom; | ||
beforeEach(function() { | ||
freedom_src = getFreedomSource(); | ||
fdom.debug = new fdom.port.Debug(); | ||
var global = { | ||
console: { | ||
log: function() {} | ||
}, | ||
document: document | ||
}; | ||
setupResolvers(); | ||
var path = window.location.href, | ||
dir_idx = path.lastIndexOf('/'), | ||
dir = path.substr(0, dir_idx) + '/'; | ||
freedom = fdom.setup(global, undefined, { | ||
manifest: "relative://spec/helper/channel.json", | ||
portType: 'Frame', | ||
inject: dir + "node_modules/es5-shim/es5-shim.js", | ||
src: freedom_src | ||
beforeEach(function(done) { | ||
testUtil.setCoreProviders([ | ||
Core | ||
]); | ||
testUtil.setupModule('relative://spec/helper/channel.json').then(function(iface) { | ||
freedom = iface(); | ||
done(); | ||
}); | ||
@@ -30,6 +23,3 @@ }); | ||
afterEach(function() { | ||
var frames = document.getElementsByTagName('iframe'); | ||
for (var i = 0; i < frames.length; i++) { | ||
frames[i].parentNode.removeChild(frames[i]); | ||
} | ||
testUtil.cleanupIframes(); | ||
}); | ||
@@ -74,10 +64,16 @@ | ||
beforeEach(function(done) { | ||
global = {freedom: {}, document: document}; | ||
fdom.debug = new fdom.port.Debug(); | ||
hub = new fdom.Hub(); | ||
manager = new fdom.port.Manager(hub); | ||
var debug = new Debug(), | ||
hub = new Hub(debug), | ||
resource = new Resource(debug), | ||
api = new Api(debug), | ||
manager = new Manager(hub, resource, api), | ||
source = testUtil.createTestPort('test'); | ||
Bundle.register([{ | ||
'name': 'core', | ||
'provider': Core.provider | ||
}], api); | ||
hub.emit('config', { | ||
global: global | ||
global: {} | ||
}); | ||
source = createTestPort('test'); | ||
manager.setup(source); | ||
@@ -84,0 +80,0 @@ |
@@ -0,1 +1,5 @@ | ||
var testUtil = require('../../util'); | ||
var Util = require('../../../src/util'); | ||
var Echo = require('../../../providers/core/echo.unprivileged'); | ||
describe("providers/core/Echo_Unprivileged", function() { | ||
@@ -6,8 +10,5 @@ var app; | ||
beforeEach(function() { | ||
app = createTestPort('test'); | ||
app.controlChannel = 'control' | ||
echo = new Echo_unprivileged(app); | ||
// Simulate the method attached by provider. | ||
echo.dispatchEvent = app.emit.bind(app); | ||
app = testUtil.createTestPort('test'); | ||
app.controlChannel = 'control'; | ||
echo = new Echo.provider(app, app.emit.bind(app)); | ||
}); | ||
@@ -38,3 +39,3 @@ | ||
var chan = {}; | ||
fdom.util.handleEvents(chan); | ||
Util.handleEvents(chan); | ||
chan.onClose = function(c) {}; | ||
@@ -61,3 +62,3 @@ | ||
var chan = {}; | ||
fdom.util.handleEvents(chan); | ||
Util.handleEvents(chan); | ||
chan.onClose = function(c) {}; | ||
@@ -64,0 +65,0 @@ chan.close = jasmine.createSpy('close'); |
@@ -0,1 +1,3 @@ | ||
var PeerConnection = require('../../../providers/core/peerconnection.unprivileged'); | ||
function MockRTCIceCandidate() { | ||
@@ -92,3 +94,3 @@ } | ||
}; | ||
peerconnection = new PeerConnection(portApp, | ||
peerconnection = new PeerConnection.provider(portApp, | ||
undefined, | ||
@@ -95,0 +97,0 @@ MockRTCPeerConnection, |
@@ -0,1 +1,3 @@ | ||
var Provider = require('../../../providers/core/storage.localstorage'); | ||
describe("core.storage unprivileged", function() { | ||
@@ -6,12 +8,4 @@ var provider; | ||
beforeEach(function(done) { | ||
if (typeof chrome !== "undefined" && | ||
typeof chrome.storage !== "undefined" && | ||
typeof chrome.storage.local !== "undefined") { | ||
chrome.storage.local.clear(); | ||
provider = new Storage_chromeStorageLocal({}); | ||
} else { | ||
localStorage.clear(); | ||
provider = new Storage_unprivileged({}); | ||
} | ||
done(); | ||
provider = new Provider.provider({}); | ||
provider.clear(done); | ||
}); | ||
@@ -68,4 +62,3 @@ | ||
provider.set('myKey', 'myVal', callbackOne); | ||
}); | ||
}); |
@@ -0,1 +1,3 @@ | ||
var View = require('../../../providers/core/view.unprivileged'); | ||
describe("core.view", function() { | ||
@@ -14,3 +16,3 @@ var provider, app, el; | ||
}; | ||
provider = new View_unprivileged(app); | ||
provider = new View.provider(app); | ||
@@ -17,0 +19,0 @@ el = document.createElement('div'); |
@@ -0,1 +1,3 @@ | ||
var WS = require('../../../providers/core/websocket.unprivileged'); | ||
function MockWebSocket(url, protocols) { | ||
@@ -72,3 +74,3 @@ MockWebSocket.currentInstance = this; | ||
var dispatchEvent = eventManager.dispatchEvent.bind(eventManager); | ||
websocket = new WS(undefined,dispatchEvent, | ||
websocket = new WS.provider(undefined,dispatchEvent, | ||
WS_URL, undefined, | ||
@@ -75,0 +77,0 @@ MockWebSocket); |
@@ -1,17 +0,13 @@ | ||
var INTEGRATIONTEST; | ||
if (typeof INTEGRATIONTEST == 'undefined') { | ||
INTEGRATIONTEST = {}; | ||
} | ||
if (typeof INTEGRATIONTEST.social == 'undefined') { | ||
INTEGRATIONTEST.social = {}; | ||
} | ||
var testUtil = require('../../util'); | ||
INTEGRATIONTEST.social.double = function(provider_url) { | ||
module.exports = function(provider_url) { | ||
var helper; | ||
beforeEach(function(done) { | ||
helper = providerFor(provider_url, 'social'); | ||
helper.create("SocialA"); | ||
helper.create("SocialB"); | ||
done(); | ||
testUtil.providerFor(provider_url, 'social').then(function(h) { | ||
helper = h; | ||
helper.create("SocialA"); | ||
helper.create("SocialB"); | ||
done(); | ||
}); | ||
}); | ||
@@ -22,3 +18,3 @@ | ||
helper.removeListeners("SocialB"); | ||
cleanupIframes(); | ||
testUtil.cleanupIframes(); | ||
done(); | ||
@@ -25,0 +21,0 @@ }); |
@@ -0,1 +1,4 @@ | ||
var testUtil = require('../../util'); | ||
var Provider = require('../../../providers/social/loopback/social.loopback'); | ||
describe("unit: social.loopback.json", function () { | ||
@@ -7,11 +10,13 @@ var provider; | ||
spyOn(console, 'log'); | ||
var social = testUtil.getApis().get("social").definition; | ||
freedom = { | ||
social: mockIface([], [ | ||
['STATUS', fdom.apis.get("social").definition.STATUS.value], | ||
['ERRCODE', fdom.apis.get("social").definition.ERRCODE.value] | ||
freedom = function() { | ||
return testUtil.mockIface([], [ | ||
['STATUS', social.STATUS.value], | ||
['ERRCODE', social.ERRCODE.value] | ||
]) | ||
}; | ||
provider = new LoopbackSocialProvider(jasmine.createSpy('dispatchEvent')); | ||
provider = new Provider.provider(jasmine.createSpy('dispatchEvent')); | ||
}); | ||
@@ -18,0 +23,0 @@ |
@@ -1,17 +0,13 @@ | ||
var INTEGRATIONTEST; | ||
if (typeof INTEGRATIONTEST == 'undefined') { | ||
INTEGRATIONTEST = {}; | ||
} | ||
if (typeof INTEGRATIONTEST.social == 'undefined') { | ||
INTEGRATIONTEST.social = {}; | ||
} | ||
var testUtil = require('../../util'); | ||
INTEGRATIONTEST.social.single = function(provider_url) { | ||
module.exports = function(provider_url) { | ||
var helper; | ||
var ERRCODE = fdom.apis.get("social").definition.ERRCODE.value; | ||
var ERRCODE = testUtil.getApis().get("social").definition.ERRCODE.value; | ||
beforeEach(function(done) { | ||
helper = providerFor(provider_url, 'social'); | ||
helper.create("s"); | ||
done(); | ||
testUtil.providerFor(provider_url, 'social').then(function(h) { | ||
helper = h; | ||
helper.create("s"); | ||
done(); | ||
}); | ||
}); | ||
@@ -21,3 +17,3 @@ | ||
helper.removeListeners("s"); | ||
cleanupIframes(); | ||
testUtil.cleanupIframes(); | ||
done(); | ||
@@ -24,0 +20,0 @@ }); |
@@ -0,1 +1,4 @@ | ||
var testUtil = require('../../util'); | ||
var Provider = require('../../../providers/social/websocket-server/social.ws'); | ||
describe("unit: social.ws.json", function () { | ||
@@ -8,6 +11,8 @@ var provider, de, ws; | ||
freedom = { | ||
social: mockIface([], [ | ||
['STATUS', fdom.apis.get("social").definition.STATUS.value], | ||
['ERRCODE', fdom.apis.get("social").definition.ERRCODE.value] | ||
var social = testUtil.getApis().get("social").definition; | ||
freedom = function() { | ||
return testUtil.mockIface([], [ | ||
['STATUS', social.STATUS.value], | ||
['ERRCODE', social.ERRCODE.value] | ||
]) | ||
@@ -30,3 +35,3 @@ }; | ||
}; | ||
provider = new WSSocialProvider(de, wsprov); | ||
provider = new Provider.provider(de, wsprov); | ||
}); | ||
@@ -33,0 +38,0 @@ |
@@ -1,15 +0,4 @@ | ||
var INTEGRATIONTEST; | ||
if (typeof INTEGRATIONTEST == 'undefined') { | ||
INTEGRATIONTEST = {}; | ||
} | ||
var testUtil = require('../../util'); | ||
INTEGRATIONTEST.storage = function(provider_url) { | ||
INTEGRATIONTEST._storage(provider_url, false); | ||
}; | ||
INTEGRATIONTEST.storebuffer = function(provider_url) { | ||
INTEGRATIONTEST._storage(provider_url, true); | ||
}; | ||
INTEGRATIONTEST._storage = function(provider_url, useArrayBuffer) { | ||
module.exports = function(provider_url, useArrayBuffer) { | ||
var helper; | ||
@@ -41,9 +30,13 @@ | ||
beforeEach(function(done) { | ||
var promise; | ||
if (typeof useArrayBuffer == 'undefined' || useArrayBuffer == false) { | ||
helper = providerFor(provider_url, "storage") | ||
promise = testUtil.providerFor(provider_url, "storage"); | ||
} else { | ||
helper = providerFor(provider_url, "storebuffer") | ||
promise = testUtil.providerFor(provider_url, "storebuffer"); | ||
} | ||
helper.create("s"); | ||
helper.call("s", "clear", [], done); | ||
promise.then(function(h) { | ||
helper = h; | ||
helper.create("s"); | ||
helper.call("s", "clear", [], done); | ||
}); | ||
}); | ||
@@ -53,3 +46,3 @@ | ||
helper.removeListeners("s"); | ||
cleanupIframes(); | ||
testUtil.cleanupIframes(); | ||
}); | ||
@@ -56,0 +49,0 @@ |
@@ -0,1 +1,3 @@ | ||
var testUtil = require('../../util'); | ||
describe("storage.isolated.json - storage.shared.json", function() { | ||
@@ -5,11 +7,14 @@ var freedom, helper; | ||
beforeEach(function(done) { | ||
freedom = setupModule("relative://spec/helper/providers.json"); | ||
helper = new ProviderHelper(freedom); | ||
helper.createProvider("shared", "storage.shared"); | ||
helper.createProvider("isolated", "storage.isolated"); | ||
helper.call("shared", "clear", [], done); | ||
freedom = testUtil.setupModule("relative://spec/helper/providers.json"); | ||
freedom.then(function(chan) { | ||
var inst = chan(); | ||
helper = new testUtil.ProviderHelper(inst); | ||
helper.createProvider("shared", "storage.shared"); | ||
helper.createProvider("isolated", "storage.isolated"); | ||
helper.call("shared", "clear", [], done); | ||
}); | ||
}); | ||
afterEach(function() { | ||
cleanupIframes(); | ||
testUtil.cleanupIframes(); | ||
}); | ||
@@ -16,0 +21,0 @@ |
@@ -0,1 +1,5 @@ | ||
var testUtil = require('../../util'); | ||
var Provider = require('../../../providers/storage/isolated/storage.isolated'); | ||
var PromiseCompat = require('es6-promise').Promise; | ||
describe("unit: storage.isolated.json", function () { | ||
@@ -6,3 +10,3 @@ var provider, finishCore, promise; | ||
spyOn(console, "log"); | ||
promise = new Promise(function(resolve) { | ||
promise = new PromiseCompat(function(resolve) { | ||
finishCore = resolve; | ||
@@ -12,4 +16,4 @@ }); | ||
freedom = { | ||
core: mockIface([['getId', promise]]), | ||
'core.storage': mockIface([ | ||
core: testUtil.mockIface([['getId', promise]]), | ||
'core.storage': testUtil.mockIface([ | ||
['keys', ['myId;Test', 'otherTest']], | ||
@@ -21,3 +25,3 @@ ['get', 'value'], | ||
}; | ||
provider = new IsolatedStorageProvider(null); | ||
provider = new Provider.provider(null); | ||
}); | ||
@@ -24,0 +28,0 @@ |
@@ -0,1 +1,4 @@ | ||
var testUtil = require('../../util'); | ||
var Provider = require('../../../providers/storage/shared/storage.shared'); | ||
describe("unit: storage.shared.json", function () { | ||
@@ -5,4 +8,4 @@ var provider; | ||
freedom = { | ||
core: mockIface([['getId', ['myId']]]), | ||
'core.storage': mockIface([ | ||
core: testUtil.mockIface([['getId', ['myId']]]), | ||
'core.storage': testUtil.mockIface([ | ||
['keys', ['myId;Test', 'otherTest']], | ||
@@ -15,3 +18,3 @@ ['get', 'value'], | ||
}; | ||
provider = new SharedStorageProvider(); | ||
provider = new Provider.provider(); | ||
}); | ||
@@ -18,0 +21,0 @@ |
@@ -1,16 +0,17 @@ | ||
var INTEGRATIONTEST; | ||
if (typeof INTEGRATIONTEST == 'undefined') { | ||
INTEGRATIONTEST = {}; | ||
} | ||
var testUtil = require('../../util'); | ||
var util = require('../../../src/util'); | ||
INTEGRATIONTEST.transport = function(provider_url) { | ||
module.exports = function(provider_url) { | ||
var helper, signals; | ||
beforeEach(function() { | ||
helper = providerFor(provider_url, "transport") | ||
beforeEach(function(done) { | ||
signals = []; | ||
testUtil.providerFor(provider_url, "transport").then(function(h) { | ||
helper = h; | ||
done(); | ||
}); | ||
}); | ||
afterEach(function() { | ||
cleanupIframes(); | ||
testUtil.cleanupIframes(); | ||
}); | ||
@@ -55,3 +56,3 @@ | ||
}); | ||
var sendData = fdom.util.str2ab("HI"); | ||
var sendData = util.str2ab("HI"); | ||
ids[0] = helper.call('t', "setup", ["t", chanId]); | ||
@@ -67,3 +68,3 @@ ids[1] = helper.call('t', "send", ["tag", sendData]); | ||
helper.on("t2", "onData", function(result) { | ||
var resultStr = fdom.util.ab2str(result.data); | ||
var resultStr = util.ab2str(result.data); | ||
expect(signals.length).toBeGreaterThan(0); | ||
@@ -78,3 +79,3 @@ //@todo This returns false on Firefox 30 | ||
var sendData = fdom.util.str2ab(testString); | ||
var sendData = util.str2ab(testString); | ||
ids[0] = helper.call("t1", "setup", ["t1", chanId1]); | ||
@@ -100,3 +101,3 @@ ids[1] = helper.call("t2", "setup", ["t2", chanId2]); | ||
helper.on("t2", "onData", function(result) { | ||
var resultStr = fdom.util.ab2str(result.data); | ||
var resultStr = util.ab2str(result.data); | ||
expect(signals.length).toBeGreaterThan(0); | ||
@@ -111,3 +112,3 @@ //@todo This returns false on Firefox 30 | ||
var sendData = fdom.util.str2ab(testString); | ||
var sendData = util.str2ab(testString); | ||
ids[0] = helper.call("t1", "setup", ["t1", chanId1]); | ||
@@ -133,3 +134,3 @@ ids[1] = helper.call("t2", "setup", ["t2", chanId2]); | ||
onDataCount += 1; | ||
var resultStr = fdom.util.ab2str(result.data); | ||
var resultStr = util.ab2str(result.data); | ||
expect(signals.length).toBeGreaterThan(0); | ||
@@ -153,3 +154,3 @@ //@todo This returns false on Firefox 30 | ||
ids[id++] = helper.call("t1", "send", [tag, | ||
fdom.util.str2ab(toSend[tag])]); | ||
util.str2ab(toSend[tag])]); | ||
} | ||
@@ -156,0 +157,0 @@ }; |
@@ -0,5 +1,9 @@ | ||
var testUtil = require('../../util'); | ||
var util = require('../../../src/util'); | ||
var Provider = require('../../../providers/transport/webrtc/transport.webrtc'); | ||
describe("unit: transport.webrtc.json", function () { | ||
var transport, peerconnection, dispatchedEvents; | ||
var sizeToBuffer = WebRTCTransportProvider.prototype._sizeToBuffer; | ||
var bufferToSize = WebRTCTransportProvider.prototype._bufferToSize; | ||
var sizeToBuffer = Provider.provider.prototype._sizeToBuffer; | ||
var bufferToSize = Provider.provider.prototype._bufferToSize; | ||
function defineSlice(arrayBuffer) { | ||
@@ -55,7 +59,7 @@ arrayBuffer.slice = function(begin, end) { | ||
freedom = { | ||
core: mockIface([["getId", ["myId"]]]), | ||
core: testUtil.mockIface([["getId", ["myId"]]]), | ||
// We can't use mockIface alone, we need to make peerconnection | ||
// an event target. | ||
"core.peerconnection": function() { | ||
var iface = mockIface([ | ||
var iface = testUtil.mockIface([ | ||
["setup", undefined], | ||
@@ -72,3 +76,3 @@ ["send", undefined], | ||
}; | ||
transport = new WebRTCTransportProvider(); | ||
transport = new Provider.provider(); | ||
transport.dispatchEvent = function(event, data) { | ||
@@ -82,3 +86,3 @@ dispatchedEvents[event] = data; | ||
"unit-tests", | ||
WebRTCTransportProvider.stun_servers, | ||
Provider.provider.stun_servers, | ||
false); | ||
@@ -91,4 +95,4 @@ done(); | ||
var tag = "test tag"; | ||
var firstMessage = fdom.util.str2ab("Hello World"); | ||
var secondMessage = fdom.util.str2ab("Wello Horld"); | ||
var firstMessage = util.str2ab("Hello World"); | ||
var secondMessage = util.str2ab("Wello Horld"); | ||
spyOn(transport, "send").and.callThrough(); | ||
@@ -122,12 +126,12 @@ transport.send(tag, firstMessage, firstSendCallback); | ||
function printBuffer(buffer) { | ||
var test = new Uint8Array(buffer); | ||
for (var i = 0; i < buffer.byteLength; i++) { | ||
console.log(test[i]); | ||
function printBuffer(buffer) { | ||
var test = new Uint8Array(buffer); | ||
for (var i = 0; i < buffer.byteLength; i++) { | ||
console.log(test[i]); | ||
} | ||
} | ||
} | ||
xit("fires on data event", function() { | ||
var tag = "test"; | ||
var data = fdom.util.str2ab("Hello World"); | ||
var data = util.str2ab("Hello World"); | ||
var sizeAsBuffer = sizeToBuffer(data.byteLength); | ||
@@ -143,3 +147,3 @@ var toSend = new ArrayBuffer(data.byteLength + 8); | ||
console.info(dispatchedEvents.onData.data.byteLength); | ||
console.info(fdom.util.ab2str(dispatchedEvents.onData.data)); | ||
console.info(util.ab2str(dispatchedEvents.onData.data)); | ||
expect(dispatchedEvents.onData).toEqual({tag: tag, | ||
@@ -146,0 +150,0 @@ data: data}); |
@@ -1,4 +0,6 @@ | ||
describe("fdom.Port.Debug", function() { | ||
var Debug = require('../../src/debug.js'); | ||
describe("Debug", function() { | ||
var debug, activeLogger, onLogger; | ||
var logger = function() { | ||
var Logger = function() { | ||
activeLogger = this; | ||
@@ -9,12 +11,11 @@ this.spy = jasmine.createSpy('log'); | ||
onLogger(); | ||
} | ||
}; | ||
this.warn = function() { | ||
this.spy(arguments[0], arguments[1]); | ||
onLogger(); | ||
} | ||
}; | ||
}; | ||
beforeEach(function() { | ||
fdom.apis.register('core.logger', logger); | ||
fdom.debug = new fdom.port.Debug(); | ||
debug = new Debug(); | ||
}); | ||
@@ -24,11 +25,11 @@ | ||
var spy = jasmine.createSpy('cb'); | ||
fdom.debug.on('msg', spy); | ||
debug.on('msg', spy); | ||
fdom.debug.log('test1'); | ||
fdom.debug.warn('test2'); | ||
fdom.debug.error('test3'); | ||
fdom.debug.format('log', 'source', 'message'); | ||
debug.log('test1'); | ||
debug.warn('test2'); | ||
debug.error('test3'); | ||
debug.format('log', 'source', 'message'); | ||
expect(spy).not.toHaveBeenCalled(); | ||
fdom.debug.onMessage('control', { | ||
debug.onMessage('control', { | ||
channel: 'msg', | ||
@@ -46,3 +47,5 @@ config: { | ||
it("Prints to a provider", function(done) { | ||
fdom.debug.console = {log: console}; | ||
var log = new Logger(); | ||
debug.setLogger(log); | ||
var msg = { | ||
@@ -53,3 +56,3 @@ severity: 'log', | ||
} | ||
fdom.debug.print(msg); | ||
onLogger = function() { | ||
@@ -61,3 +64,5 @@ expect(activeLogger.log).toBeDefined(); | ||
}; | ||
}); | ||
}); | ||
debug.print(msg); | ||
}); | ||
}); |
@@ -0,31 +1,15 @@ | ||
var testUtil = require('../util'); | ||
describe("freedom", function() { | ||
var freedom_src; | ||
var freedom, dir; | ||
var freedom; | ||
beforeEach(function() { | ||
freedom_src = getFreedomSource(); | ||
var global = { | ||
console: { | ||
log: function() {} | ||
}, | ||
document: document | ||
}; | ||
setupResolvers(); | ||
var path = window.location.href, | ||
dir_idx = path.lastIndexOf('/'); | ||
dir = path.substr(0, dir_idx) + '/'; | ||
freedom = fdom.setup(global, undefined, { | ||
manifest: "relative://spec/helper/manifest.json", | ||
portType: 'Frame', | ||
inject: dir + "node_modules/es5-shim/es5-shim.js", | ||
src: freedom_src | ||
}); | ||
testUtil.setCoreProviders([ | ||
require('../../providers/core/core.unprivileged'), | ||
require('../../providers/core/logger.console') | ||
]); | ||
freedom = testUtil.setupModule("relative://spec/helper/manifest.json"); | ||
}); | ||
afterEach(function() { | ||
var frames = document.getElementsByTagName('iframe'); | ||
for (var i = 0; i < frames.length; i++) { | ||
frames[i].parentNode.removeChild(frames[i]); | ||
} | ||
testUtil.cleanupIframes(); | ||
freedom = null; | ||
@@ -35,78 +19,38 @@ }); | ||
it("creates modules", function(done) { | ||
freedom.on('output', function(value) { | ||
expect(value).toEqual('roundtrip'); | ||
done(); | ||
freedom.then(function(iface) { | ||
var app = iface(); | ||
app.on('output', function(value) { | ||
expect(value).toEqual('roundtrip'); | ||
done(); | ||
}); | ||
app.emit('input', 'roundtrip'); | ||
}); | ||
freedom.emit('input', 'roundtrip'); | ||
}); | ||
it("Creates child modules", function(done) { | ||
freedom.on('child-output', function(value) { | ||
expect(value).toEqual('child-roundtrip'); | ||
done(); | ||
freedom.then(function(iface) { | ||
var app = iface(); | ||
app.on('child-output', function(value) { | ||
expect(value).toEqual('child-roundtrip'); | ||
done(); | ||
}); | ||
app.emit('child-input', 'child-roundtrip'); | ||
}); | ||
freedom.emit('child-input', 'child-roundtrip'); | ||
}); | ||
it("Handles manifest-defined APIs", function(done) { | ||
freedom.on('log', function(value) { | ||
var log = JSON.parse(value); | ||
expect(log[0][1]).toEqual('log Msg'); | ||
expect(log[1][1]).toEqual('another Log'); | ||
expect(log[1][0] - log[0][0]).toBeGreaterThan(-1); | ||
done(); | ||
freedom.then(function(iface) { | ||
var app = iface(); | ||
app.on('log', function(value) { | ||
var log = JSON.parse(value); | ||
expect(log[0][1]).toEqual('log Msg'); | ||
expect(log[1][1]).toEqual('another Log'); | ||
expect(log[1][0] - log[0][0]).toBeGreaterThan(-1); | ||
done(); | ||
}); | ||
app.emit('do-log', 'log Msg'); | ||
app.emit('do-log', 'another Log'); | ||
app.emit('get-log'); | ||
}); | ||
freedom.emit('do-log', 'log Msg'); | ||
freedom.emit('do-log', 'another Log'); | ||
freedom.emit('get-log'); | ||
}); | ||
it("Can be configured in a self-contained way", function() { | ||
var script = document.createElement("script"); | ||
script.setAttribute('data-manifest', "relative://spec/helper/manifest.json"); | ||
script.innerText = "{}"; | ||
document.body.appendChild(script); | ||
var global = { | ||
document: document | ||
}; | ||
freedom = fdom.setup(global, undefined, { | ||
portType: 'Frame', | ||
inject: dir + "node_modules/es5-shim/es5-shim.js", | ||
src: freedom_src, | ||
stayLocal: true | ||
}); | ||
expect(freedom.on).toBeDefined(); | ||
document.body.removeChild(script); | ||
}); | ||
it("Requires Valid JSON", function() { | ||
var root = document.createElement('div'); | ||
var script = document.createElement("script"); | ||
script.setAttribute('data-manifest', "relative://spec/helper/manifest.json"); | ||
var contents = document.createTextNode("var x = 2; //this is not json"); | ||
script.appendChild(contents); | ||
root.appendChild(script); | ||
var global = { | ||
document: root | ||
}; | ||
freedomcfg = function() { | ||
spyOn(fdom.debug, 'warn'); | ||
} | ||
freedom = fdom.setup(global, undefined, { | ||
portType: 'Frame', | ||
inject: dir + "node_modules/es5-shim/es5-shim.js", | ||
src: freedom_src, | ||
advertise: true | ||
}); | ||
expect(fdom.debug.warn).toHaveBeenCalled(); | ||
root.removeChild(script); | ||
}); | ||
}); |
@@ -1,14 +0,15 @@ | ||
describe("freedom", function() { | ||
var freedom, global; | ||
var entry = require('../../src/entry'); | ||
var testUtil = require('../util'); | ||
var direct = require('../../src/link/direct'); | ||
describe("FreedomModule", function() { | ||
var freedom, global, h = []; | ||
beforeEach(function() { | ||
global = { | ||
addEventListener: function(msg, handler) { | ||
this['on'+msg] = handler; | ||
}, | ||
postMessage: function(msg, to) { | ||
this.lastmsg = msg; | ||
directLink: { | ||
emit: function(flow, msg) { | ||
h.push([flow, msg]); | ||
} | ||
} | ||
}; | ||
setupResolvers(); | ||
@@ -18,12 +19,13 @@ var path = window.location.href, | ||
dir = path.substr(0, dir_idx) + '/'; | ||
freedom = fdom.setup(global, undefined, { | ||
'isModule': true | ||
freedom = entry({ | ||
'portType': direct, | ||
'isModule': true, | ||
'providers': [], | ||
'global': global | ||
}); | ||
}); | ||
it("Loads an App", function() { | ||
var cb = jasmine.createSpy('cb'); | ||
freedom.emit('fromApp', 'data'); | ||
expect(global.lastmsg).toBeDefined(); | ||
it("Initiates connection outwards.", function() { | ||
expect(h.length).toBeGreaterThan(0); | ||
}); | ||
}); |
@@ -1,7 +0,10 @@ | ||
describe("fdom.Hub", function() { | ||
var hub; | ||
var Hub = require('../../src/hub'); | ||
var Debug = require('../../src/debug'); | ||
describe("Hub", function() { | ||
var hub, debug; | ||
beforeEach(function() { | ||
hub = new fdom.Hub(); | ||
fdom.debug = new fdom.port.Debug(); | ||
debug = new Debug(); | ||
hub = new Hub(debug); | ||
}); | ||
@@ -27,9 +30,9 @@ | ||
}; | ||
spyOn(fdom.debug, 'warn'); | ||
spyOn(debug, 'warn'); | ||
hub.install(app, null, 'magic'); | ||
expect(fdom.debug.warn).toHaveBeenCalled(); | ||
expect(debug.warn).toHaveBeenCalled(); | ||
hub.register(app); | ||
hub.install(app, null, 'magic'); | ||
expect(fdom.debug.warn.calls.count()).toEqual(2); | ||
expect(debug.warn.calls.count()).toEqual(2); | ||
expect(hub.register(app)).toEqual(false); | ||
@@ -66,3 +69,3 @@ | ||
spyOn(fdom.debug, 'warn'); | ||
spyOn(debug, 'warn'); | ||
@@ -72,7 +75,7 @@ hub.onMessage('test', "testing"); | ||
expect(app.onMessage).not.toHaveBeenCalled(); | ||
expect(fdom.debug.warn).toHaveBeenCalled(); | ||
expect(debug.warn).toHaveBeenCalled(); | ||
}); | ||
it("removes routes", function() { | ||
spyOn(fdom.debug, 'warn'); | ||
spyOn(debug, 'warn'); | ||
var app1 = { | ||
@@ -96,10 +99,10 @@ id: 'testApp' | ||
expect(fdom.debug.warn).not.toHaveBeenCalled(); | ||
expect(debug.warn).not.toHaveBeenCalled(); | ||
hub.onMessage(route, msg); | ||
expect(fdom.debug.warn).toHaveBeenCalled(); | ||
expect(debug.warn).toHaveBeenCalled(); | ||
}); | ||
it("Handles failures when removing routes", function() { | ||
spyOn(fdom.debug, 'warn'); | ||
spyOn(debug, 'warn'); | ||
var app1 = { | ||
@@ -117,6 +120,6 @@ id: 'testApp' | ||
hub.uninstall(app2, route); | ||
expect(fdom.debug.warn).toHaveBeenCalled(); | ||
expect(debug.warn).toHaveBeenCalled(); | ||
hub.uninstall({id: null}, route); | ||
expect(fdom.debug.warn.calls.count()).toEqual(2); | ||
expect(debug.warn.calls.count()).toEqual(2); | ||
@@ -130,5 +133,5 @@ expect(hub.uninstall(app1, route+'fake')).toEqual(false); | ||
hub.onMessage(route, {test: true}); | ||
expect(fdom.debug.warn.calls.count()).toEqual(3); | ||
expect(debug.warn.calls.count()).toEqual(3); | ||
}); | ||
}); | ||
@@ -1,13 +0,22 @@ | ||
describe("fdom.Port.Manager", function() { | ||
var hub, manager, port; | ||
var Debug = require('../../src/debug'); | ||
var Hub = require('../../src/hub'); | ||
var Manager = require('../../src/manager'); | ||
var Resource = require('../../src/resource'); | ||
var Api = require('../../src/api'); | ||
var testUtil = require('../util'); | ||
describe("Manager", function() { | ||
var debug, hub, manager, port, resource, api; | ||
beforeEach(function() { | ||
hub = new fdom.Hub(); | ||
fdom.debug = new fdom.port.Debug(); | ||
manager = new fdom.port.Manager(hub); | ||
var global = { | ||
console: { | ||
log: function() {} | ||
} | ||
}; | ||
debug = new Debug(); | ||
hub = new Hub(debug); | ||
resource = new Resource(debug); | ||
api = new Api(debug); | ||
api.set('core',{}); | ||
api.register('core',function() {}); | ||
manager = new Manager(hub, resource, api); | ||
var global = {}; | ||
hub.emit('config', { | ||
@@ -17,3 +26,3 @@ global: global, | ||
}); | ||
port = createTestPort('testing'); | ||
port = testUtil.createTestPort('testing'); | ||
manager.setup(port); | ||
@@ -23,15 +32,15 @@ }); | ||
it("Handles Debug Messages", function() { | ||
spyOn(fdom.debug, 'print'); | ||
spyOn(debug, 'print'); | ||
manager.onMessage('testing', { | ||
request: 'debug' | ||
}); | ||
expect(fdom.debug.print).toHaveBeenCalled(); | ||
expect(debug.print).toHaveBeenCalled(); | ||
manager.onMessage('unregistered', { | ||
request: 'debug' | ||
}); | ||
expect(fdom.debug.print.calls.count()).toEqual(1); | ||
expect(debug.print.calls.count()).toEqual(1); | ||
}); | ||
it("Creates Links", function() { | ||
var testPort = createTestPort('dest'); | ||
var testPort = testUtil.createTestPort('dest'); | ||
@@ -59,17 +68,4 @@ manager.onMessage('testing', { | ||
it("Creates new ports", function() { | ||
manager.onMessage('testing', { | ||
request: 'port', | ||
name: 'testPort', | ||
service: 'Debug', | ||
args: null | ||
}); | ||
// Notification of link. | ||
var notification = port.gotMessage('control', {type: 'createLink'}); | ||
expect(notification).not.toEqual(false); | ||
}); | ||
it("Supports delegation of control", function() { | ||
var testPort = createTestPort('dest'); | ||
var testPort = testUtil.createTestPort('dest'); | ||
@@ -101,6 +97,3 @@ manager.setup(testPort); | ||
}); | ||
expect(fdom.resources.contentRetrievers['testing']).toEqual('resolver'); | ||
// Reset resources | ||
fdom.resources = new Resource(); | ||
expect(resource.contentRetrievers['testing']).toEqual('resolver'); | ||
}); | ||
@@ -116,3 +109,3 @@ | ||
var otherPort = createTestPort('dest'); | ||
var otherPort = testUtil.createTestPort('dest'); | ||
manager.setup(otherPort); | ||
@@ -136,7 +129,7 @@ manager.onMessage('dest', { | ||
// Subsequent requests should fail / cause a warning. | ||
spyOn(fdom.debug, 'warn'); | ||
spyOn(debug, 'warn'); | ||
manager.onMessage('testing', { | ||
request: 'core' | ||
}); | ||
expect(fdom.debug.warn).toHaveBeenCalled(); | ||
expect(debug.warn).toHaveBeenCalled(); | ||
expect(port.gotMessage('control', {type: 'core'})).toEqual(false); | ||
@@ -143,0 +136,0 @@ }); |
@@ -1,10 +0,15 @@ | ||
describe("fdom.port.Module", function() { | ||
var module, link, port; | ||
var Module = require('../../src/module'); | ||
var testUtil = require('../util'); | ||
describe("Module", function() { | ||
var module, link, port, policy; | ||
beforeEach(function(done) { | ||
module = new fdom.port.Module("manifest://{}", {}, []); | ||
port = createTestPort('messager'); | ||
policy = testUtil.createMockPolicy(); | ||
module = new Module("manifest://{}", {}, [], policy); | ||
port = testUtil.createTestPort('messager'); | ||
module.on('control', port.onMessage.bind(port, 'control')); | ||
module.on('extport', port.onMessage.bind(port, 'extport')); | ||
link = createTestPort('modulelink'); | ||
fdom.link.test = function() { | ||
link = testUtil.createTestPort('modulelink'); | ||
var test = function() { | ||
this.addErrorHandler = function() {}; | ||
this.onMessage = link.onMessage.bind(link); | ||
@@ -18,3 +23,3 @@ this.on = link.on.bind(link); | ||
config: { | ||
portType: 'test' | ||
portType: test | ||
} | ||
@@ -25,8 +30,4 @@ }); | ||
afterEach(function() { | ||
delete fdom.link.test; | ||
}); | ||
it("Attempts Module Startup", function() { | ||
expect(link.gotMessage('control', {request: 'port'}).service).toEqual("ModuleInternal"); | ||
expect(link.gotMessage('control', {request: 'environment'})).not.toBeFalsy(); | ||
}); | ||
@@ -33,0 +34,0 @@ |
@@ -1,10 +0,23 @@ | ||
describe('fdom.port.ModuleInternal', function() { | ||
var Api = require('../../src/api'); | ||
var Debug = require('../../src/debug'); | ||
var Hub = require('../../src/hub'); | ||
var Manager = require('../../src/manager'); | ||
var ModuleInternal = require('../../src/moduleinternal'); | ||
var testUtil = require('../util'); | ||
describe('ModuleInternal', function() { | ||
var app, manager, hub, global, loc; | ||
beforeEach(function() { | ||
global = {freedom: {}}; | ||
hub = new fdom.Hub(); | ||
manager = new fdom.port.Manager(hub); | ||
app = new fdom.port.ModuleInternal(manager); | ||
hub = new Hub(new Debug()); | ||
var resource = testUtil.setupResolvers(); | ||
var api = new Api(); | ||
api.set('core', {}); | ||
api.register('core', function () {}); | ||
manager = new Manager(hub, resource, api); | ||
app = new ModuleInternal(manager); | ||
hub.emit('config', { | ||
global: global | ||
global: global, | ||
location: 'relative://' | ||
}); | ||
@@ -19,3 +32,3 @@ manager.setup(app); | ||
it('configures an app environment', function() { | ||
var source = createTestPort('test'); | ||
var source = testUtil.createTestPort('test'); | ||
manager.setup(source); | ||
@@ -44,15 +57,16 @@ manager.createLink(source, 'default', app, 'default'); | ||
it('handles script loading and attachment', function(done) { | ||
setupResolvers(); | ||
global.document = document; | ||
var script = btoa('fileIncluded = true; callback();'); | ||
callback = function() { | ||
window.callback = function() { | ||
expect(fileIncluded).toEqual(true); | ||
delete callback; | ||
done(); | ||
} | ||
app.loadScripts(loc, ['relative://spec/helper/beacon.js', 'non_existing_file']); | ||
} | ||
app.loadScripts(loc, ['data:text/javascript;base64,' + script, 'non_existing_file']); | ||
}); | ||
it('load scripts sequentially', function(done) { | ||
setupResolvers(); | ||
global.document = document; | ||
@@ -63,3 +77,4 @@ | ||
callback0 = function() { | ||
var script0 = btoa('fileIncluded0 = true; callback0();'); | ||
window.callback0 = function() { | ||
expect(fileIncluded0).toEqual(true); | ||
@@ -70,3 +85,4 @@ expect(fileIncluded).toEqual(false); | ||
callback = function() { | ||
var script = btoa('fileIncluded = true; callback();'); | ||
window.callback = function() { | ||
expect(fileIncluded0).toEqual(true); | ||
@@ -78,4 +94,4 @@ expect(fileIncluded).toEqual(true); | ||
app.loadScripts(loc, ['relative://spec/helper/beacon0.js', | ||
'relative://spec/helper/beacon.js', | ||
app.loadScripts(loc, ['data:text/javascript;base64,' + script0, | ||
'data:text/javascript;base64,' + script, | ||
'non_existing_file']); | ||
@@ -85,3 +101,3 @@ }) | ||
it('exposes dependency apis', function(done) { | ||
var source = createTestPort('test'); | ||
var source = testUtil.createTestPort('test'); | ||
manager.setup(source); | ||
@@ -91,3 +107,3 @@ manager.createLink(source, 'default', app, 'default'); | ||
// Dependencies will be requested via 'createLink' messages. resolve those. | ||
if (msg.channel && msg.name !== 'default') { | ||
if (msg.channel && msg.type === 'createLink') { | ||
hub.onMessage(msg.channel, { | ||
@@ -125,12 +141,12 @@ type: 'channel announcement', | ||
}); | ||
hub.onMessage(source.messages[1][1].channel, { | ||
type: 'manifest', | ||
name: 'test', | ||
manifest: {name: 'test manifest'} | ||
}); | ||
callback = function() { | ||
window.callback = function() { | ||
delete callback; | ||
expect(global.freedom.manifest.name).toEqual('My Module Name'); | ||
expect(global.freedom.test.api).toEqual('social'); | ||
delete callback; | ||
hub.onMessage(source.messages[1][1].channel, { | ||
type: 'manifest', | ||
name: 'test', | ||
manifest: {name: 'test manifest'} | ||
}); | ||
expect(global.freedom.test.manifest.name).toEqual('test manifest'); | ||
@@ -137,0 +153,0 @@ done(); |
@@ -1,7 +0,12 @@ | ||
describe('fdom.Policy', function() { | ||
var Debug = require('../../src/debug'); | ||
var Policy = require('../../src/policy'); | ||
var Resource = require('../../src/resource'); | ||
var util = require('../../src/util'); | ||
describe('Policy', function() { | ||
var policy, | ||
manager; | ||
beforeEach(function() { | ||
manager = {}; | ||
fdom.util.handleEvents(manager); | ||
manager = {debug: new Debug()}; | ||
util.handleEvents(manager); | ||
manager.getPort = function(id) { | ||
@@ -11,4 +16,5 @@ return { | ||
}; | ||
} | ||
policy = new fdom.Policy(manager, {}); | ||
}; | ||
var rsrc = new Resource(); | ||
policy = new Policy(manager, rsrc, {}); | ||
}); | ||
@@ -55,3 +61,3 @@ | ||
var port2 = {}; | ||
fdom.util.handleEvents(port2); | ||
util.handleEvents(port2); | ||
policy.add(port2, {}); | ||
@@ -58,0 +64,0 @@ port2.emit('moduleAdd', {lineage:['test'], id:'test'}); |
@@ -1,2 +0,5 @@ | ||
describe("fdom.Port.Provider", function() { | ||
var Provider = require('../../src/provider'); | ||
var Promise = require('es6-promise').Promise; | ||
describe("Provider", function() { | ||
var port, o, constructspy; | ||
@@ -10,3 +13,3 @@ beforeEach(function() { | ||
}; | ||
port = new fdom.port.Provider(definition); | ||
port = new Provider(definition); | ||
@@ -46,3 +49,3 @@ constructspy = jasmine.createSpy('constructor'); | ||
}; | ||
port = new fdom.port.Provider(definition); | ||
port = new Provider(definition); | ||
var iface = port.getInterface(); | ||
@@ -49,0 +52,0 @@ expect(iface['provideSynchronous']).toBeDefined(); |
@@ -1,2 +0,5 @@ | ||
describe("fdom.proxy.APIInterface", function() { | ||
var ApiInterface = require('../../src/proxy/apiInterface'); | ||
var Consumer = require('../../src/consumer'); | ||
describe("proxy/APIInterface", function() { | ||
var emit, reg, api; | ||
@@ -13,3 +16,3 @@ beforeEach(function() { | ||
}; | ||
api = new fdom.proxy.ApiInterface(iface, onMsg, emit); | ||
api = new ApiInterface(iface, onMsg, emit); | ||
}); | ||
@@ -67,3 +70,4 @@ | ||
}; | ||
var apimaker = fdom.proxy.ApiInterface.bind({}, iface, onMsg, callback); | ||
var debug = {}; | ||
var apimaker = ApiInterface.bind({}, iface, onMsg, callback, debug); | ||
var api = new apimaker('my param'); | ||
@@ -87,3 +91,4 @@ }); | ||
}; | ||
var apimaker = fdom.proxy.ApiInterface.bind({}, iface, onMsg, callback); | ||
var debug = {}; | ||
var apimaker = ApiInterface.bind({}, iface, onMsg, callback, debug); | ||
var api = new apimaker({'test':'hi'}); | ||
@@ -130,3 +135,3 @@ }); | ||
describe("fdom.proxy.recursiveFreezeObject", function() { | ||
describe("Consumer.recursiveFreezeObject", function() { | ||
it("Freezes objects", function () { | ||
@@ -139,3 +144,3 @@ var obj = { | ||
}; | ||
var frozen = fdom.proxy.recursiveFreezeObject(obj); | ||
var frozen = Consumer.recursiveFreezeObject(obj); | ||
frozen.a = 5; | ||
@@ -149,3 +154,7 @@ frozen.b = 5; | ||
describe("fdom.proxy.conform", function() { | ||
describe("Consumer.conform", function() { | ||
var debug = { | ||
error: function() {} | ||
}; | ||
it("Conforms Simple values to templates", function() { | ||
@@ -184,3 +193,3 @@ var blob = null; | ||
}; | ||
var conformed = fdom.proxy.conform(template, correct, | ||
var conformed = Consumer.conform(template, correct, | ||
[blob, new ArrayBuffer(2)], false); | ||
@@ -204,3 +213,3 @@ correct['p5'] = conformed['p5']; | ||
conformed = fdom.proxy.conform(template, incorrect, [0, blob, blob], false); | ||
conformed = Consumer.conform(template, incorrect, [0, blob, blob], false); | ||
expect(conformed).toEqual({ | ||
@@ -220,32 +229,31 @@ 'p1': '12', | ||
it("conforms simple arguments", function() { | ||
expect(fdom.proxy.conform("string", "mystring", [], false)).toEqual("mystring"); | ||
expect(fdom.proxy.conform("number", "mystring", [], false)).toEqual(jasmine.any(Number)); | ||
expect(fdom.proxy.conform("boolean", "mystring", [], false)).toEqual(false); | ||
expect(fdom.proxy.conform("", "mystring", [], false)).toEqual(undefined); | ||
expect(fdom.proxy.conform(["string", "number"], ["test", 0], [], false)) | ||
expect(Consumer.conform("string", "mystring", [], false, debug)).toEqual("mystring"); | ||
expect(Consumer.conform("number", "mystring", [], false, debug)).toEqual(jasmine.any(Number)); | ||
expect(Consumer.conform("boolean", "mystring", [], false, debug)).toEqual(false); | ||
expect(Consumer.conform("", "mystring", [], false, debug)).toEqual(undefined); | ||
expect(Consumer.conform(["string", "number"], ["test", 0], [], false, debug)) | ||
.toEqual(["test", 0]); | ||
expect(fdom.proxy.conform("number", 0, [], false)).toEqual(0); | ||
expect(Consumer.conform("number", 0, [], false, debug)).toEqual(0); | ||
}); | ||
it("conforms complex arguments", function() { | ||
expect(fdom.proxy.conform({"key":"string"}, {"key":"good", "other":"bad"},[], false)). | ||
expect(Consumer.conform({"key":"string"}, {"key":"good", "other":"bad"},[], false)). | ||
toEqual({"key":"good"}); | ||
expect(fdom.proxy.conform(["string"], ["test", 12],[], false)).toEqual(["test"]); | ||
expect(fdom.proxy.conform(["array", "string"], ["test", 12],[], false)).toEqual(["test", "12"]); | ||
expect(fdom.proxy.conform("object", {"simple":"string"},[], false)).toEqual({"simple": "string"}); | ||
expect(Consumer.conform(["string"], ["test", 12],[], false)).toEqual(["test"]); | ||
expect(Consumer.conform(["array", "string"], ["test", 12],[], false)).toEqual(["test", "12"]); | ||
expect(Consumer.conform("object", {"simple":"string"},[], false)).toEqual({"simple": "string"}); | ||
//expect(fdom.proxy.conform.bind({}, "object", function() {},[], false)).toThrow(); | ||
expect(fdom.proxy.conform("object", function() {},[], false)).not.toBeDefined(); | ||
expect(Consumer.conform("object", function() {},[], false)).not.toBeDefined(); | ||
}); | ||
it("conforms nulls", function() { | ||
expect(fdom.proxy.conform({"key": "string"}, {"key": null}, [], false)). | ||
expect(Consumer.conform({"key": "string"}, {"key": null}, [], false)). | ||
toEqual({"key": null}); | ||
expect(fdom.proxy.conform("object", null, [], false)).toEqual(null); | ||
expect(fdom.proxy.conform({"key": "string"}, {"key": undefined}, [], false)). | ||
expect(Consumer.conform("object", null, [], false)).toEqual(null); | ||
expect(Consumer.conform({"key": "string"}, {"key": undefined}, [], false)). | ||
toEqual({}); | ||
expect(fdom.proxy.conform(["string", "string", "string", "string"], | ||
expect(Consumer.conform(["string", "string", "string", "string"], | ||
[null, undefined, null, 0], [], false)). | ||
toEqual([null, undefined, null, "0"]); | ||
expect(fdom.proxy.conform("object", undefined, [], false)).toEqual(undefined); | ||
expect(Consumer.conform("object", undefined, [], false)).toEqual(undefined); | ||
}); | ||
@@ -263,7 +271,7 @@ | ||
var externals = []; | ||
expect(fdom.proxy.conform("buffer", buffer, externals, true)).toEqual(0); | ||
expect(Consumer.conform("buffer", buffer, externals, true, debug)).toEqual(0); | ||
expect(externals.length).toEqual(1); | ||
expect(fdom.proxy.conform("buffer", 0, ["string"], false)).toEqual(jasmine.any(ArrayBuffer)); | ||
expect(fdom.proxy.conform("buffer", 0, externals, false)).toEqual(buffer); | ||
expect(Consumer.conform("buffer", 0, ["string"], false, debug)).toEqual(jasmine.any(ArrayBuffer)); | ||
expect(Consumer.conform("buffer", 0, externals, false, debug)).toEqual(buffer); | ||
}); | ||
}); |
@@ -1,7 +0,10 @@ | ||
describe("fdom.resources", function() { | ||
var resources; | ||
var Debug = require('../../src/debug'); | ||
var Resource = require('../../src/resource'); | ||
beforeEach(function() { | ||
resources = new Resource(); | ||
fdom.debug = new fdom.port.Debug(); | ||
describe("Resource", function() { | ||
var resources, debug; | ||
beforeEach(function() { | ||
debug = new Debug(); | ||
resources = new Resource(debug); | ||
}); | ||
@@ -93,9 +96,9 @@ | ||
}; | ||
spyOn(fdom.debug, 'warn'); | ||
spyOn(debug, 'warn'); | ||
resources.addRetriever('http', retriever); | ||
expect(fdom.debug.warn).toHaveBeenCalled(); | ||
expect(debug.warn).toHaveBeenCalled(); | ||
}); | ||
}); | ||
describe('fdom.resources.httpResolver', function() { | ||
describe('resources.httpResolver', function() { | ||
var r, f, spy, resources; | ||
@@ -102,0 +105,0 @@ |
@@ -0,1 +1,3 @@ | ||
var util = require('../../src/util'); | ||
describe("util", function() { | ||
@@ -6,3 +8,3 @@ it("iterates over an array", function() { | ||
var ids = []; | ||
fdom.util.eachReverse(array, function(el, idx) { | ||
util.eachReverse(array, function(el, idx) { | ||
sum += el; | ||
@@ -15,3 +17,3 @@ ids.push(idx); | ||
fdom.util.eachReverse(false, function() { | ||
util.eachReverse(false, function() { | ||
sum = 100; | ||
@@ -25,3 +27,3 @@ }); | ||
var sum = 0; | ||
fdom.util.eachReverse(array, function(el) { | ||
util.eachReverse(array, function(el) { | ||
sum += el; | ||
@@ -37,3 +39,3 @@ return el % 2 != 0; | ||
expect(fdom.util.hasProp(obj, "testProp")).toBeTruthy(); | ||
expect(util.hasProp(obj, "testProp")).toBeTruthy(); | ||
}); | ||
@@ -49,3 +51,3 @@ | ||
var props = []; | ||
fdom.util.eachProp(obj, function(val, name) { | ||
util.eachProp(obj, function(val, name) { | ||
sum += val; | ||
@@ -60,3 +62,3 @@ props.push(name); | ||
sum = 0; | ||
fdom.util.eachProp(obj, function(val, name) { | ||
util.eachProp(obj, function(val, name) { | ||
sum += val; | ||
@@ -77,3 +79,3 @@ return name === 'b' | ||
it("mixes Objects together", function() { | ||
fdom.util.mixin(base, other); | ||
util.mixin(base, other); | ||
expect(base.value).toEqual(1); | ||
@@ -84,3 +86,3 @@ expect(base.other).toEqual(2); | ||
it("forcably mixes Objects together", function() { | ||
fdom.util.mixin(base, other, true); | ||
util.mixin(base, other, true); | ||
expect(base.value).toEqual(2); | ||
@@ -93,3 +95,3 @@ expect(base.other).toEqual(2); | ||
other.obj = {val: 2}; | ||
fdom.util.mixin(base, other, true); | ||
util.mixin(base, other, true); | ||
expect(base.obj.val).toEqual(2); | ||
@@ -100,3 +102,3 @@ expect(base.obj.mine).toBeUndefined(); | ||
it("handles degenerate mixins", function() { | ||
var result = fdom.util.mixin(base, null, true); | ||
var result = util.mixin(base, null, true); | ||
expect(result).toEqual({value: 1}); | ||
@@ -108,4 +110,4 @@ }); | ||
it("creates unique IDs", function() { | ||
var id1 = fdom.util.getId(); | ||
var id2 = fdom.util.getId(); | ||
var id1 = util.getId(); | ||
var id2 = util.getId(); | ||
expect(id1).not.toEqual(id2); | ||
@@ -121,3 +123,3 @@ }); | ||
cb = jasmine.createSpy('cb'); | ||
fdom.util.handleEvents(object); | ||
util.handleEvents(object); | ||
}); | ||
@@ -188,11 +190,2 @@ | ||
}); | ||
describe("ModuleContext", function() { | ||
it("Warns when source has been mangled", function() { | ||
spyOn(fdom.debug, "error"); | ||
var resp = fdom.util.forceModuleContext(""); | ||
expect(fdom.debug.error).toHaveBeenCalled(); | ||
expect(resp).toBeUndefined(); | ||
}); | ||
}); | ||
}); |
178
spec/util.js
@@ -1,2 +0,9 @@ | ||
var createTestPort = function(id) { | ||
var Api = require('../src/api'); | ||
var Bundle = require('../src/bundle'); | ||
var Resource = require('../src/resource'); | ||
var util = require('../src/util'); | ||
var Frame = require('../src/link/frame'); | ||
var PromiseCompat = require('es6-promise').Promise; | ||
exports.createTestPort = function(id) { | ||
var port = { | ||
@@ -51,3 +58,3 @@ id: id, | ||
fdom.util.handleEvents(port); | ||
util.handleEvents(port); | ||
@@ -57,3 +64,9 @@ return port; | ||
var mockIface = function(props, consts) { | ||
exports.createMockPolicy = function() { | ||
return { | ||
api: new Api() | ||
}; | ||
}; | ||
exports.mockIface = function(props, consts) { | ||
var iface = {}; | ||
@@ -67,3 +80,3 @@ props.forEach(function(p) { | ||
iface[p[0]] = function(r) { | ||
return Promise.resolve(r); | ||
return PromiseCompat.resolve(r); | ||
}.bind({}, p[1]); | ||
@@ -83,77 +96,12 @@ } | ||
var createProxyFor = function(app, api) { | ||
setupResolvers(); | ||
var global = { | ||
document: document | ||
}; | ||
fdom.debug = new fdom.port.Debug(); | ||
// Wrap the resolving subsystem to grab the child's 'freedom' object and promote it | ||
// to window before the internal script is loaded. | ||
for(var i = 0; i < fdom.resources.resolvers.length; i++) { | ||
var resolver = fdom.resources.resolvers[i]; | ||
fdom.resources.resolvers[i] = function(wrap, m, u, d) { | ||
if (u.lastIndexOf(".js") === u.length - 3) { | ||
window.freedom = global.freedom; | ||
} | ||
return wrap(m, u, d); | ||
}.bind({}, resolver); | ||
} | ||
var hub = new fdom.Hub(), | ||
site_cfg = { | ||
'debug': true, | ||
'portType': 'Direct', | ||
'moduleContext': false, | ||
'manifest': app, | ||
'resources': fdom.resources, | ||
'global': global | ||
}, | ||
manager = new fdom.port.Manager(hub), | ||
proxy; | ||
if (api) { | ||
proxy = new fdom.port.Proxy(fdom.proxy.ApiInterface.bind({}, fdom.apis.get(api).definition)); | ||
} else { | ||
proxy = new fdom.port.Proxy(fdom.proxy.EventInterface); | ||
} | ||
manager.setup(proxy); | ||
var link = location.protocol + "//" + location.host + location.pathname; | ||
fdom.resources.get(link, site_cfg.manifest).then(function(url) { | ||
fdom.resources.getContents(url).then(function(manifest) { | ||
var app = new fdom.port.Module(url, manifest, []); | ||
manager.setup(app); | ||
manager.createLink(proxy, 'default', app); | ||
}); | ||
}); | ||
hub.emit('config', site_cfg); | ||
return proxy.getProxyInterface(); | ||
exports.getApis = function() { | ||
var api = new Api(); | ||
Bundle.register([], api); | ||
return api; | ||
}; | ||
var fdom_src; | ||
var getFreedomSource = function(id) { | ||
if(typeof fdom_src === 'undefined'){ | ||
try { | ||
var xhr = new XMLHttpRequest(); | ||
xhr.open("get", "freedom.js", false); | ||
xhr.overrideMimeType("text/javascript; charset=utf-8"); | ||
xhr.send(null); | ||
fdom_src = xhr.responseText; | ||
} catch (err) { // Synchronous XHR wont work in Chrome App (Chrome Test Runner), so load from global var. | ||
if (typeof jasmine.getGlobal().freedom_src !== 'undefined') { | ||
fdom_src = jasmine.getGlobal().freedom_src; | ||
} else { | ||
throw "Could not load freedom source from XHR or global var. To work in a Chrome App, getFreedomSource() must be called from a jasmine test case or beforeEach()"; | ||
} | ||
} | ||
} | ||
return fdom_src; | ||
} | ||
// Setup resource loading for the test environment, which uses file:// urls. | ||
function setupResolvers() { | ||
fdom.resources = new Resource(); | ||
fdom.resources.addResolver(function(manifest, url, resolve) { | ||
exports.getResolvers = function() { | ||
var resolvers = []; | ||
resolvers.push({'resolver': function(manifest, url, resolve) { | ||
if (url.indexOf('relative://') === 0) { | ||
@@ -167,7 +115,7 @@ var loc = location.protocol + "//" + location.host + location.pathname; | ||
return false; | ||
}); | ||
fdom.resources.addResolver(function(manifest, url, resolve) { | ||
if (manifest.indexOf('file://') === 0) { | ||
}}); | ||
resolvers.push({'resolver': function(manifest, url, resolve) { | ||
if (manifest && manifest.indexOf('file://') === 0) { | ||
manifest = 'http' + manifest.substr(4); | ||
fdom.resources.resolve(manifest, url).then(function(addr) { | ||
rsrc.resolve(manifest, url).then(function(addr) { | ||
addr = 'file' + addr.substr(4); | ||
@@ -180,7 +128,15 @@ resolve(addr); | ||
return false; | ||
}); | ||
fdom.resources.addRetriever('file', fdom.resources.xhrRetriever); | ||
}}); | ||
var rsrc = new Resource(); | ||
resolvers.push({'proto':'file', 'retriever': rsrc.xhrRetriever}); | ||
return resolvers; | ||
} | ||
function cleanupIframes() { | ||
exports.setupResolvers = function() { | ||
var rsrc = new Resource(); | ||
rsrc.register(exports.getResolvers()); | ||
return rsrc; | ||
} | ||
exports.cleanupIframes = function() { | ||
var frames = document.getElementsByTagName('iframe'); | ||
@@ -194,19 +150,31 @@ // frames is a live HTMLCollection, so it is modified each time an | ||
function setupModule(manifest_url) { | ||
var freedom_src = getFreedomSource(); | ||
var global = {console: {log: function(){}}, document: document}; | ||
setupResolvers(); | ||
var coreProviders; | ||
exports.setCoreProviders = function(providers) { | ||
coreProviders = providers; | ||
}; | ||
var path = window.location.href; | ||
var dir_idx = path.lastIndexOf('/'); | ||
var dir = path.substr(0, dir_idx) + '/'; | ||
return fdom.setup(global, undefined, { | ||
manifest: manifest_url, | ||
portType: "Frame", | ||
inject: dir + "node_modules/es5-shim/es5-shim.js", | ||
src: freedom_src | ||
}); | ||
exports.setupModule = function(manifest_url) { | ||
var global = { | ||
document: document | ||
}; | ||
var path = window.location.href, | ||
dir_idx = path.lastIndexOf('/'); | ||
dir = path.substr(0, dir_idx) + '/'; | ||
return require('../src/entry')({ | ||
'global': global, | ||
'providers': coreProviders, | ||
'resolvers': exports.getResolvers(), | ||
'portType': Frame, | ||
'source': dir + "spec/helper/frame.js", | ||
'inject': [ | ||
dir + "node_modules/es5-shim/es5-shim.js", | ||
dir + "node_modules/es6-promise/dist/promise-1.0.0.js" | ||
], | ||
}, manifest_url, { | ||
debug: 'debug' | ||
}); | ||
} | ||
function providerFor(module, api) { | ||
exports.providerFor = function(module, api) { | ||
var manifest = { | ||
@@ -217,8 +185,11 @@ name: 'providers', | ||
}; | ||
var freedom = setupModule('manifest://' + JSON.stringify(manifest)); | ||
var provider = new ProviderHelper(freedom); | ||
provider.create = function(name) { | ||
this.freedom.emit("create", {name: name, provider: 'undertest'}); | ||
}; | ||
return provider; | ||
var freedom = exports.setupModule('manifest://' + JSON.stringify(manifest)); | ||
return freedom.then(function(chan) { | ||
var inst = chan(); | ||
var provider = new ProviderHelper(inst); | ||
provider.create = function(name) { | ||
inst.emit("create", {name: name, provider: 'undertest'}); | ||
}; | ||
return provider; | ||
}); | ||
} | ||
@@ -342,1 +313,2 @@ | ||
exports.ProviderHelper = ProviderHelper; |
179
src/entry.js
@@ -1,103 +0,104 @@ | ||
/*globals fdom:true, Promise, document, location, console */ | ||
/*jslint indent:2,sloppy:true */ | ||
/*jslint indent:2,node:true */ | ||
var PromiseCompat = require('es6-promise').Promise; | ||
/** | ||
* @module freedom | ||
*/ | ||
if (typeof fdom === 'undefined') { | ||
fdom = {}; | ||
} | ||
var Api = require('./api'); | ||
var Debug = require('./debug'); | ||
var Hub = require('./hub'); | ||
var Manager = require('./manager'); | ||
var Policy = require('./policy'); | ||
var ProxyBinder = require('./proxybinder'); | ||
var Resource = require('./resource'); | ||
var util = require('./util'); | ||
var Bundle = require('./bundle'); | ||
var freedomGlobal; | ||
var getGlobal = function () { | ||
'use strict'; | ||
// Node.js | ||
if (typeof global !== 'undefined' && global.prototype === undefined) { | ||
freedomGlobal = global; | ||
// Browsers | ||
} else { | ||
setTimeout(function () { | ||
freedomGlobal = this; | ||
}, 0); | ||
} | ||
}; | ||
getGlobal(); | ||
/** | ||
* External freedom Setup. global.freedom is set to the value returned by | ||
* setup (see preamble.js and postamble.js for that mechanism). As a result, | ||
* this is the primary entry function for the freedom library. | ||
* @for util | ||
* @method setup | ||
* @param {Object} global The window / frame / worker context freedom is in. | ||
* @param {String} freedom_src The textual code of freedom, for replication. | ||
* @param {Object} config Overriding config for freedom.js | ||
* @static | ||
* Create a new freedom context. | ||
* @param {Object} context Information about the local context. | ||
* @see {util/workerEntry.js} | ||
* @param {String} manifest The manifest to load. | ||
* @param {Object} config Configuration keys set by the user. | ||
* @returns {Promise} A promise for the module defined in the manifest. | ||
*/ | ||
fdom.setup = function (global, freedom_src, config) { | ||
fdom.debug = new fdom.port.Debug(); | ||
var hub = new fdom.Hub(), | ||
var setup = function (context, manifest, config) { | ||
'use strict'; | ||
var debug = new Debug(), | ||
hub = new Hub(debug), | ||
resource = new Resource(debug), | ||
api = new Api(debug), | ||
manager = new Manager(hub, resource, api), | ||
binder = new ProxyBinder(manager), | ||
policy, | ||
site_cfg = { | ||
'debug': true, | ||
'stayLocal': false, | ||
'portType': 'Worker', | ||
'moduleContext': (!config || typeof (config.isModule) === "undefined") ? | ||
fdom.util.isModuleContext() : | ||
config.isModule | ||
'debug': 'log', | ||
'manifest': manifest, | ||
'moduleContext': (!context || typeof (context.isModule) === "undefined") ? | ||
util.isModuleContext() : | ||
context.isModule | ||
}, | ||
manager = new fdom.port.Manager(hub), | ||
external = new fdom.port.Proxy(fdom.proxy.EventInterface), | ||
link; | ||
link, | ||
Port; | ||
Bundle.register(context.providers, api); | ||
resource.register(context.resolvers || []); | ||
manager.setup(external); | ||
if (site_cfg.moduleContext) { | ||
if (config) { | ||
fdom.util.mixin(site_cfg, config, true); | ||
} | ||
site_cfg.global = global; | ||
site_cfg.src = freedom_src; | ||
link = new fdom.link[site_cfg.portType](); | ||
manager.setup(link); | ||
manager.createLink(external, 'default', link); | ||
if (config) { | ||
util.mixin(site_cfg, config, true); | ||
} | ||
site_cfg.global = freedomGlobal; | ||
if (context) { | ||
util.mixin(site_cfg, context, true); | ||
} | ||
// Delay debug messages until delegation to the parent context is setup. | ||
manager.once('delegate', manager.setup.bind(manager, fdom.debug)); | ||
} else { | ||
manager.setup(fdom.debug); | ||
fdom.util.advertise(config ? config.advertise : undefined); | ||
return new PromiseCompat(function (resolve, reject) { | ||
if (site_cfg.moduleContext) { | ||
Port = site_cfg.portType; | ||
link = new Port('Outbound', resource); | ||
manager.setup(link); | ||
// Delay debug messages until delegation to the parent context is setup. | ||
manager.once('delegate', manager.setup.bind(manager, debug)); | ||
} else { | ||
manager.setup(debug); | ||
api.getCore('core.logger', debug).then(function (Logger) { | ||
debug.setLogger(new Logger()); | ||
}); | ||
// Configure against data-manifest. | ||
if (typeof global.document !== 'undefined') { | ||
fdom.util.eachReverse(fdom.util.scripts(global), function (script) { | ||
var manifest = script.getAttribute('data-manifest'), | ||
source = script.src; | ||
if (manifest) { | ||
site_cfg.source = source; | ||
site_cfg.manifest = manifest; | ||
if (script.textContent.trim().length) { | ||
try { | ||
fdom.util.mixin(site_cfg, JSON.parse(script.textContent), true); | ||
} catch (e) { | ||
fdom.debug.warn("Failed to parse configuration: " + e); | ||
} | ||
policy = new Policy(manager, resource, site_cfg); | ||
resource.get(site_cfg.location, site_cfg.manifest).then( | ||
function (root_manifest) { | ||
return policy.get([], root_manifest); | ||
} | ||
).then(function (root_module) { | ||
manager.setup(root_module); | ||
return binder.bindDefault(root_module, api, root_module.manifest).then( | ||
function (info) { | ||
return info.external; | ||
} | ||
return true; | ||
} | ||
}); | ||
); | ||
}, function (err) { | ||
debug.error('Failed to retrieve manifest: ' + err); | ||
}).then(resolve, reject); | ||
} | ||
site_cfg.global = global; | ||
site_cfg.src = freedom_src; | ||
site_cfg.resources = fdom.resources; | ||
if (config) { | ||
fdom.util.mixin(site_cfg, config, true); | ||
} | ||
hub.emit('config', site_cfg); | ||
}); | ||
}; | ||
if (typeof location !== 'undefined') { | ||
site_cfg.location = location.protocol + "//" + location.host + location.pathname; | ||
} | ||
site_cfg.policy = new fdom.Policy(manager, site_cfg); | ||
fdom.resources.get(site_cfg.location, site_cfg.manifest).then(function (root_mod) { | ||
site_cfg.policy.get([], root_mod) | ||
.then(manager.createLink.bind(manager, external, 'default')); | ||
}, function (err) { | ||
fdom.debug.error('Failed to retrieve manifest: ' + err); | ||
}); | ||
} | ||
hub.emit('config', site_cfg); | ||
// Enable console.log from worker contexts. | ||
if (typeof global.console === 'undefined' || site_cfg.relayConsole) { | ||
global.console = fdom.debug; | ||
} | ||
return external.getInterface(); | ||
}; | ||
module.exports = setup; |
@@ -1,6 +0,3 @@ | ||
/*globals fdom:true */ | ||
/*jslint indent:2,white:true,node:true,sloppy:true */ | ||
if (typeof fdom === 'undefined') { | ||
fdom = {}; | ||
} | ||
/*jslint indent:2,sloppy:true,node:true */ | ||
var util = require('./util'); | ||
@@ -11,6 +8,7 @@ /** | ||
* @class Hub | ||
* @param {Debug} debug Logger for debugging. | ||
* @constructor | ||
*/ | ||
fdom.Hub = function() { | ||
this.route = Math.round(Math.random() * 1000000); | ||
var Hub = function (debug) { | ||
this.debug = debug; | ||
this.config = {}; | ||
@@ -21,5 +19,5 @@ this.apps = {}; | ||
fdom.util.handleEvents(this); | ||
this.on('config', function(config) { | ||
fdom.util.mixin(this.config, config); | ||
util.handleEvents(this); | ||
this.on('config', function (config) { | ||
util.mixin(this.config, config); | ||
}.bind(this)); | ||
@@ -34,15 +32,15 @@ }; | ||
*/ | ||
fdom.Hub.prototype.onMessage = function(source, message) { | ||
Hub.prototype.onMessage = function (source, message) { | ||
var destination = this.routes[source], type; | ||
if (!destination || !destination.app) { | ||
fdom.debug.warn("Message dropped from unregistered source " + source); | ||
this.debug.warn("Message dropped from unregistered source " + source); | ||
return; | ||
} | ||
if(!this.apps[destination.app]) { | ||
fdom.debug.warn("Message dropped to destination " + destination.app); | ||
if (!this.apps[destination.app]) { | ||
this.debug.warn("Message dropped to destination " + destination.app); | ||
return; | ||
} | ||
if (!message.quiet) { | ||
if (!message.quiet && !destination.quiet) { | ||
type = message.type; | ||
@@ -59,3 +57,3 @@ if (message.type === 'message' && message.message && | ||
} | ||
fdom.debug.log(this.apps[destination.source].toString() + | ||
this.debug.debug(this.apps[destination.source].toString() + | ||
" -" + type + "-> " + | ||
@@ -74,3 +72,3 @@ this.apps[destination.app].toString() + "." + destination.flow); | ||
*/ | ||
fdom.Hub.prototype.getDestination = function(source) { | ||
Hub.prototype.getDestination = function (source) { | ||
var destination = this.routes[source]; | ||
@@ -89,3 +87,3 @@ if (!destination) { | ||
*/ | ||
fdom.Hub.prototype.getSource = function(source) { | ||
Hub.prototype.getSource = function (source) { | ||
if (!source) { | ||
@@ -95,3 +93,3 @@ return false; | ||
if (!this.apps[source.id]) { | ||
fdom.debug.warn("No registered source '" + source.id + "'"); | ||
this.debug.warn("No registered source '" + source.id + "'"); | ||
return false; | ||
@@ -109,3 +107,3 @@ } | ||
*/ | ||
fdom.Hub.prototype.register = function(app, force) { | ||
Hub.prototype.register = function (app, force) { | ||
if (!this.apps[app.id] || force) { | ||
@@ -128,4 +126,4 @@ this.apps[app.id] = app; | ||
*/ | ||
fdom.Hub.prototype.deregister = function(app) { | ||
if(!this.apps[app.id]) { | ||
Hub.prototype.deregister = function (app) { | ||
if (!this.apps[app.id]) { | ||
return false; | ||
@@ -143,5 +141,6 @@ } | ||
* @param {String} flow The flow where the destination will receive messages. | ||
* @param {Boolean} quiet Whether messages on this route should be suppressed. | ||
* @return {String} A routing source identifier for sending messages. | ||
*/ | ||
fdom.Hub.prototype.install = function(source, destination, flow) { | ||
Hub.prototype.install = function (source, destination, flow, quiet) { | ||
source = this.getSource(source); | ||
@@ -152,3 +151,3 @@ if (!source) { | ||
if (!destination) { | ||
fdom.debug.warn("Unwilling to generate blackhole flow from " + source.id); | ||
this.debug.warn("Unwilling to generate blackhole flow from " + source.id); | ||
return; | ||
@@ -161,3 +160,4 @@ } | ||
flow: flow, | ||
source: source.id | ||
source: source.id, | ||
quiet: quiet | ||
}; | ||
@@ -178,3 +178,3 @@ if (typeof source.on === 'function') { | ||
*/ | ||
fdom.Hub.prototype.uninstall = function(source, flow) { | ||
Hub.prototype.uninstall = function (source, flow) { | ||
source = this.getSource(source); | ||
@@ -189,3 +189,3 @@ if (!source) { | ||
} else if (route.source !== source.id) { | ||
fdom.debug.warn("Flow " + flow + " does not belong to port " + source.id); | ||
this.debug.warn("Flow " + flow + " does not belong to port " + source.id); | ||
return false; | ||
@@ -207,4 +207,6 @@ } | ||
*/ | ||
fdom.Hub.prototype.generateRoute = function() { | ||
return (this.route += 1); | ||
Hub.prototype.generateRoute = function () { | ||
return util.getId(); | ||
}; | ||
module.exports = Hub; |
@@ -1,6 +0,3 @@ | ||
/*globals fdom:true */ | ||
/*jslint indent:2, white:true, node:true, sloppy:true, browser:true */ | ||
if (typeof fdom === 'undefined') { | ||
fdom = {}; | ||
} | ||
/*jslint indent:2, node:true, sloppy:true */ | ||
var util = require('./util'); | ||
@@ -12,12 +9,14 @@ /** | ||
* @class Link | ||
* @extends Port | ||
* @implements Port | ||
* @constructor | ||
*/ | ||
fdom.Link = function() { | ||
var Link = function (name, resource) { | ||
this.id = 'Link' + Math.random(); | ||
this.name = name; | ||
this.resource = resource; | ||
this.config = {}; | ||
this.src = null; | ||
fdom.util.handleEvents(this); | ||
fdom.util.mixin(this, fdom.Link.prototype); | ||
util.handleEvents(this); | ||
util.mixin(this, Link.prototype); | ||
}; | ||
@@ -33,7 +32,7 @@ | ||
*/ | ||
fdom.Link.prototype.onMessage = function(flow, message) { | ||
Link.prototype.onMessage = function (flow, message) { | ||
if (flow === 'control' && !this.controlChannel) { | ||
if (!this.controlChannel && message.channel) { | ||
this.controlChannel = message.channel; | ||
fdom.util.mixin(this.config, message.config); | ||
util.mixin(this.config, message.config); | ||
this.start(); | ||
@@ -47,2 +46,20 @@ } | ||
/** | ||
* Register a handler to alert of errors on this port. | ||
* @method addErrorHandler | ||
* @param {Function} handler Method to call with errors. | ||
*/ | ||
Link.prototype.addErrorHandler = function (handler) { | ||
this.onError = handler; | ||
}; | ||
/** | ||
* Report an error on this link. | ||
* @method onerror | ||
* @param {Error} err The error that occurred. | ||
*/ | ||
Link.prototype.onError = function (err) { | ||
//Filled in by addErrorHandler | ||
}; | ||
/** | ||
* Emit messages to the the hub, mapping control channels. | ||
@@ -53,3 +70,3 @@ * @method emitMessage | ||
*/ | ||
fdom.Link.prototype.emitMessage = function(flow, message) { | ||
Link.prototype.emitMessage = function (flow, message) { | ||
if (flow === 'control' && this.controlChannel) { | ||
@@ -60,1 +77,3 @@ flow = this.controlChannel; | ||
}; | ||
module.exports = Link; |
@@ -1,7 +0,4 @@ | ||
/*globals fdom:true */ | ||
/*jslint indent:2, white:true, node:true, sloppy:true, browser:true */ | ||
if (typeof fdom === 'undefined') { | ||
fdom = {}; | ||
} | ||
fdom.link = fdom.link || {}; | ||
/*jslint indent:2, white:true, node:true, sloppy:true */ | ||
var Link = require('../link'); | ||
var entry = require('../entry'); | ||
@@ -13,9 +10,9 @@ /** | ||
* used in production without some serious though about the implications of that decision. | ||
* @class Link.Direct | ||
* @extends Port | ||
* @class Direct | ||
* @extends Link | ||
* @uses handleEvents | ||
* @constructor | ||
*/ | ||
fdom.link.Direct = function() { | ||
fdom.Link.call(this); | ||
var Direct = function(id, resource) { | ||
Link.call(this, id, resource); | ||
}; | ||
@@ -28,3 +25,3 @@ | ||
*/ | ||
fdom.link.Direct.prototype.start = function() { | ||
Direct.prototype.start = function() { | ||
if (this.config.moduleContext) { | ||
@@ -38,9 +35,6 @@ this.config.global.directLink.other = this; | ||
// Keep fdom.debug connected to parent hub. | ||
var debug = fdom.debug, | ||
child = fdom.setup(this.config.global, undefined, { | ||
var child = entry(undefined, { | ||
isModule: true, | ||
portType: 'Direct' | ||
}); | ||
fdom.debug = debug; | ||
this.config.global.freedom = child; | ||
} | ||
@@ -54,3 +48,3 @@ }; | ||
*/ | ||
fdom.link.Direct.prototype.stop = function() { | ||
Direct.prototype.stop = function() { | ||
if (this === this.config.global.directLink) { | ||
@@ -67,3 +61,3 @@ delete this.config.global.directLink; | ||
*/ | ||
fdom.link.Direct.prototype.toString = function() { | ||
Direct.prototype.toString = function() { | ||
return "[Direct" + this.id + "]"; | ||
@@ -79,3 +73,3 @@ }; | ||
*/ | ||
fdom.link.Direct.prototype.deliverMessage = function(flow, message) { | ||
Direct.prototype.deliverMessage = function(flow, message) { | ||
if (this.other) { | ||
@@ -98,1 +92,2 @@ /* //- For Debugging Purposes - | ||
module.exports = Direct; |
@@ -1,11 +0,8 @@ | ||
/*globals fdom:true */ | ||
/*jslint indent:2, white:true, node:true, sloppy:true, browser:true */ | ||
if (typeof fdom === 'undefined') { | ||
fdom = {}; | ||
} | ||
fdom.link = fdom.link || {}; | ||
/*jslint indent:2, white:true, node:true, sloppy:true */ | ||
var Link = require('../link'); | ||
var util = require('../util'); | ||
/** | ||
* A port providing message transport between two freedom contexts via iFrames. | ||
* @class link.Frame | ||
* @class Frame | ||
* @extends Link | ||
@@ -15,4 +12,4 @@ * @uses handleEvents | ||
*/ | ||
fdom.link.Frame = function() { | ||
fdom.Link.call(this); | ||
var Frame = function(id, resource) { | ||
Link.call(this, id, resource); | ||
}; | ||
@@ -25,3 +22,3 @@ | ||
*/ | ||
fdom.link.Frame.prototype.start = function() { | ||
Frame.prototype.start = function() { | ||
if (this.config.moduleContext) { | ||
@@ -42,3 +39,3 @@ this.config.global.DEBUG = true; | ||
*/ | ||
fdom.link.Frame.prototype.stop = function() { | ||
Frame.prototype.stop = function() { | ||
// Function is determined by setupListener or setupFrame as appropriate. | ||
@@ -52,3 +49,3 @@ }; | ||
*/ | ||
fdom.link.Frame.prototype.toString = function() { | ||
Frame.prototype.toString = function() { | ||
return "[Frame" + this.id + "]"; | ||
@@ -62,3 +59,3 @@ }; | ||
*/ | ||
fdom.link.Frame.prototype.setupListener = function() { | ||
Frame.prototype.setupListener = function() { | ||
var onMsg = function(msg) { | ||
@@ -76,2 +73,3 @@ if (msg.data.src !== 'in') { | ||
this.emit('started'); | ||
this.obj.postMessage("Ready For Messages", "*"); | ||
}; | ||
@@ -83,5 +81,5 @@ | ||
*/ | ||
fdom.link.Frame.prototype.setupFrame = function() { | ||
Frame.prototype.setupFrame = function() { | ||
var frame, onMsg; | ||
frame = this.makeFrame(this.config.src, this.config.inject); | ||
frame = this.makeFrame(this.config.source, this.config.inject); | ||
@@ -121,3 +119,4 @@ if (!document.body) { | ||
*/ | ||
fdom.link.Frame.prototype.makeFrame = function(src, inject) { | ||
Frame.prototype.makeFrame = function(src, inject) { | ||
// TODO(willscott): add sandboxing protection. | ||
var frame = document.createElement('iframe'), | ||
@@ -127,16 +126,19 @@ extra = '', | ||
blob; | ||
// TODO(willscott): add sandboxing protection. | ||
// TODO(willscott): survive name mangling. | ||
src = src.replace('portType: "Worker"', 'portType: "Frame"'); | ||
if (inject) { | ||
extra = '<script src="' + inject + '" onerror="' + | ||
'throw new Error(\'Injection of ' + inject +' Failed!\');' + | ||
if (!inject.length) { | ||
inject = [inject]; | ||
} | ||
inject.forEach(function(script) { | ||
extra += '<script src="' + script + '" onerror="' + | ||
'throw new Error(\'Injection of ' + script +' Failed!\');' + | ||
'"></script>'; | ||
}); | ||
} | ||
loader = '<html><meta http-equiv="Content-type" content="text/html;' + | ||
'charset=UTF-8">' + extra + '<script src="' + | ||
fdom.util.forceModuleContext(src) + '"></script></html>'; | ||
blob = fdom.util.getBlob(loader, 'text/html'); | ||
frame.src = fdom.util.getURL(blob); | ||
'charset=UTF-8">' + extra + '<script src="' + src + '" onerror="' + | ||
'throw new Error(\'Loading of ' + src +' Failed!\');' + | ||
'"></script></html>'; | ||
blob = util.getBlob(loader, 'text/html'); | ||
frame.src = util.getURL(blob); | ||
@@ -153,3 +155,3 @@ return frame; | ||
*/ | ||
fdom.link.Frame.prototype.deliverMessage = function(flow, message) { | ||
Frame.prototype.deliverMessage = function(flow, message) { | ||
if (this.obj) { | ||
@@ -167,1 +169,3 @@ //fdom.debug.log('message sent to worker: ', flow, message); | ||
module.exports = Frame; | ||
@@ -1,7 +0,4 @@ | ||
/*globals fdom:true, Worker */ | ||
/*globals Worker */ | ||
/*jslint indent:2, white:true, node:true, sloppy:true, browser:true */ | ||
if (typeof fdom === 'undefined') { | ||
fdom = {}; | ||
} | ||
fdom.link = fdom.link || {}; | ||
var Link = require('../link'); | ||
@@ -11,8 +8,8 @@ /** | ||
* @class Worker | ||
* @extends Port | ||
* @extends Link | ||
* @uses handleEvents | ||
* @constructor | ||
*/ | ||
fdom.link.Worker = function(id) { | ||
fdom.Link.call(this); | ||
var WorkerLink = function(id, resource) { | ||
Link.call(this, id, resource); | ||
if (id) { | ||
@@ -28,3 +25,3 @@ this.id = id; | ||
*/ | ||
fdom.link.Worker.prototype.start = function() { | ||
WorkerLink.prototype.start = function() { | ||
if (this.config.moduleContext) { | ||
@@ -42,3 +39,3 @@ this.setupListener(); | ||
*/ | ||
fdom.link.Worker.prototype.stop = function() { | ||
WorkerLink.prototype.stop = function() { | ||
// Function is determined by setupListener or setupFrame as appropriate. | ||
@@ -52,3 +49,3 @@ }; | ||
*/ | ||
fdom.link.Worker.prototype.toString = function() { | ||
WorkerLink.prototype.toString = function() { | ||
return "[Worker " + this.id + "]"; | ||
@@ -62,3 +59,3 @@ }; | ||
*/ | ||
fdom.link.Worker.prototype.setupListener = function() { | ||
WorkerLink.prototype.setupListener = function() { | ||
var onMsg = function(msg) { | ||
@@ -74,2 +71,3 @@ this.emitMessage(msg.data.flow, msg.data.message); | ||
this.emit('started'); | ||
this.obj.postMessage("Ready For Messages"); | ||
}; | ||
@@ -81,13 +79,11 @@ | ||
*/ | ||
fdom.link.Worker.prototype.setupWorker = function() { | ||
var worker, blob, self = this; | ||
if (typeof (window.Blob) !== typeof (Function)) { | ||
worker = new Worker(this.config.source); | ||
} else { | ||
blob = new window.Blob([this.config.src], {type: 'text/javascript'}); | ||
worker = new Worker(window.URL.createObjectURL(blob) + '#' + this.id); | ||
} | ||
WorkerLink.prototype.setupWorker = function() { | ||
var worker, | ||
blob, | ||
self = this; | ||
worker = new Worker(this.config.source + '#' + this.id); | ||
worker.addEventListener('error', function(err) { | ||
fdom.debug.error(self.toString(), err.message); | ||
}, true); | ||
this.onError(err); | ||
}.bind(this), true); | ||
worker.addEventListener('message', function(worker, msg) { | ||
@@ -97,2 +93,3 @@ if (!this.obj) { | ||
this.emit('started'); | ||
return; | ||
} | ||
@@ -102,3 +99,3 @@ this.emitMessage(msg.data.flow, msg.data.message); | ||
this.stop = function() { | ||
worker.stop(); | ||
worker.terminate(); | ||
if (this.obj) { | ||
@@ -117,3 +114,3 @@ delete this.obj; | ||
*/ | ||
fdom.link.Worker.prototype.deliverMessage = function(flow, message) { | ||
WorkerLink.prototype.deliverMessage = function(flow, message) { | ||
if (flow === 'control' && message.type === 'close' && | ||
@@ -124,3 +121,2 @@ message.channel === 'control') { | ||
if (this.obj) { | ||
//fdom.debug.log('message sent to worker: ', flow, message); | ||
this.obj.postMessage({ | ||
@@ -136,1 +132,3 @@ flow: flow, | ||
module.exports = WorkerLink; | ||
@@ -1,6 +0,5 @@ | ||
/*globals fdom:true, XMLHttpRequest, Promise */ | ||
/*globals XMLHttpRequest */ | ||
/*jslint indent:2,white:true,node:true,sloppy:true */ | ||
if (typeof fdom === 'undefined') { | ||
fdom = {}; | ||
} | ||
var Module = require('./module'); | ||
var util = require('./util'); | ||
@@ -11,6 +10,13 @@ /** | ||
* @Class Policy | ||
* @param {Manager} manager The manager of the active runtime. | ||
* @param {Resource} resource The resource loader of the active runtime. | ||
* @param {Object} config The local config. | ||
* @constructor | ||
*/ | ||
fdom.Policy = function(manager, config) { | ||
var Policy = function(manager, resource, config) { | ||
this.api = manager.api; | ||
this.debug = manager.debug; | ||
this.location = config.location; | ||
this.resource = resource; | ||
this.config = config; | ||
@@ -30,3 +36,3 @@ this.runtimes = []; | ||
*/ | ||
fdom.Policy.prototype.defaultPolicy = { | ||
Policy.prototype.defaultPolicy = { | ||
background: false, // Can this runtime run 'background' modules? | ||
@@ -43,3 +49,3 @@ interactive: true // Is there a view associated with this runtime? | ||
*/ | ||
fdom.Policy.prototype.defaultConstraints = { | ||
Policy.prototype.defaultConstraints = { | ||
isolation: "always", // values: always, app, never | ||
@@ -58,3 +64,3 @@ placement: "local" // values: local, stable, redundant | ||
*/ | ||
fdom.Policy.prototype.get = function(lineage, id) { | ||
Policy.prototype.get = function(lineage, id) { | ||
return this.loadManifest(id).then(function(manifest) { | ||
@@ -68,16 +74,16 @@ var constraints = this.overlay(this.defaultConstraints, manifest.constraints), | ||
if(constraints.isolation !== 'always' && portId) { | ||
fdom.debug.log('Reused port ' + portId); | ||
this.debug.info('Reused port ' + portId); | ||
return runtime.manager.getPort(portId); | ||
} else { | ||
return new fdom.port.Module(id, manifest, lineage); | ||
return new Module(id, manifest, lineage, this); | ||
} | ||
} else { | ||
// TODO: Create a port to go to the remote runtime. | ||
fdom.debug.error('Unexpected location selected for module placement'); | ||
this.debug.error('Unexpected location selected for module placement'); | ||
return false; | ||
} | ||
}.bind(this), function(err) { | ||
fdom.debug.error('Policy Error Resolving ' + id, err); | ||
this.debug.error('Policy Error Resolving ' + id, err); | ||
return false; | ||
}); | ||
}.bind(this)); | ||
}; | ||
@@ -94,3 +100,3 @@ | ||
*/ | ||
fdom.Policy.prototype.findDestination = function(lineage, id, constraints) { | ||
Policy.prototype.findDestination = function(lineage, id, constraints) { | ||
var i; | ||
@@ -132,3 +138,3 @@ | ||
*/ | ||
fdom.Policy.prototype.isRunning = function(runtime, id, from, fullMatch) { | ||
Policy.prototype.isRunning = function(runtime, id, from, fullMatch) { | ||
var i = 0, j = 0, okay; | ||
@@ -164,4 +170,4 @@ for (i = 0; i < runtime.modules.length; i += 1) { | ||
*/ | ||
fdom.Policy.prototype.loadManifest = function(manifest) { | ||
return fdom.resources.getContents(manifest).then(function(data) { | ||
Policy.prototype.loadManifest = function(manifest) { | ||
return this.resource.getContents(manifest).then(function(data) { | ||
var resp = {}; | ||
@@ -171,3 +177,3 @@ try { | ||
} catch(err) { | ||
fdom.debug.warn("Failed to load " + manifest + ": " + err); | ||
this.debug.warn("Failed to load " + manifest + ": " + err); | ||
return {}; | ||
@@ -184,3 +190,3 @@ } | ||
*/ | ||
fdom.Policy.prototype.add = function(port, policy) { | ||
Policy.prototype.add = function(port, policy) { | ||
var runtime = { | ||
@@ -209,3 +215,3 @@ manager: port, | ||
} | ||
fdom.debug.warn('Unknown module to remove: ', info.id); | ||
this.debug.warn('Unknown module to remove: ', info.id); | ||
}.bind(this, runtime)); | ||
@@ -223,10 +229,12 @@ }; | ||
*/ | ||
fdom.Policy.prototype.overlay = function(base, overlay) { | ||
Policy.prototype.overlay = function(base, overlay) { | ||
var ret = {}; | ||
fdom.util.mixin(ret, base); | ||
util.mixin(ret, base); | ||
if (overlay) { | ||
fdom.util.mixin(ret, overlay, true); | ||
util.mixin(ret, overlay, true); | ||
} | ||
return ret; | ||
}; | ||
module.exports = Policy; |
@@ -1,9 +0,8 @@ | ||
/*globals fdom:true, Blob, ArrayBuffer, DataView, Promise */ | ||
/*jslint indent:2, white:true, node:true, sloppy:true, browser:true */ | ||
if (typeof fdom === 'undefined') { | ||
fdom = {}; | ||
} | ||
fdom.proxy = fdom.proxy || {}; | ||
var PromiseCompat = require('es6-promise').Promise; | ||
fdom.proxy.ApiInterface = function(def, onMsg, emit) { | ||
var util = require('../util'); | ||
var Consumer = require('../consumer'); | ||
var ApiInterface = function(def, onMsg, emit, debug) { | ||
var inflight = {}, | ||
@@ -15,3 +14,3 @@ events = null, | ||
fdom.util.eachProp(def, function(prop, name) { | ||
util.eachProp(def, function(prop, name) { | ||
switch(prop.type) { | ||
@@ -23,3 +22,3 @@ case 'method': | ||
var thisReq = reqId, | ||
promise = new Promise(function(resolve, reject) { | ||
promise = new PromiseCompat(function(resolve, reject) { | ||
inflight[thisReq] = { | ||
@@ -31,4 +30,5 @@ resolve:resolve, | ||
}), | ||
streams = fdom.proxy.messageToPortable(prop.value, | ||
Array.prototype.slice.call(arguments, 0)); | ||
streams = Consumer.messageToPortable(prop.value, | ||
Array.prototype.slice.call(arguments, 0), | ||
debug); | ||
reqId += 1; | ||
@@ -47,3 +47,3 @@ emit({ | ||
if(!events) { | ||
fdom.util.handleEvents(this); | ||
util.handleEvents(this); | ||
emitter = this.emit; | ||
@@ -57,3 +57,3 @@ delete this.emit; | ||
Object.defineProperty(this, name, { | ||
value: fdom.proxy.recursiveFreezeObject(prop.value), | ||
value: Consumer.recursiveFreezeObject(prop.value), | ||
writable: false | ||
@@ -82,11 +82,12 @@ }); | ||
} else { | ||
resolver.resolve(fdom.proxy.portableToMessage(template, msg)); | ||
resolver.resolve(Consumer.portableToMessage(template, msg, debug)); | ||
} | ||
} else { | ||
fdom.debug.warn('Dropped response message with id ' + msg.reqId); | ||
debug.error('Incoming message claimed to be an RPC ' + | ||
'returning for unregistered call', msg.reqId); | ||
} | ||
} else if (msg.type === 'event') { | ||
if (events[msg.name]) { | ||
emitter(msg.name, fdom.proxy.portableToMessage(events[msg.name].value, | ||
msg)); | ||
emitter(msg.name, Consumer.portableToMessage(events[msg.name].value, | ||
msg, debug)); | ||
} | ||
@@ -96,5 +97,6 @@ } | ||
args = fdom.proxy.messageToPortable( | ||
args = Consumer.messageToPortable( | ||
(def.constructor && def.constructor.value) ? def.constructor.value : [], | ||
Array.prototype.slice.call(args, 3)); | ||
Array.prototype.slice.call(args, 4), | ||
debug); | ||
@@ -108,179 +110,2 @@ emit({ | ||
/** | ||
* Convert a structured data structure into a message stream conforming to | ||
* a template and an array of binary data elements. | ||
* @static | ||
* @method messageToPortable | ||
* @param {Object} template The template to conform to | ||
* @param {Object} value The instance of the data structure to confrom | ||
* @return {{text: Object, binary: Array}} Separated data streams. | ||
*/ | ||
fdom.proxy.messageToPortable = function(template, value) { | ||
var externals = [], | ||
message = fdom.proxy.conform(template, value, externals, true); | ||
return { | ||
text: message, | ||
binary: externals | ||
}; | ||
}; | ||
/** | ||
* Convert Structured Data streams into a data structure conforming to a | ||
* template. | ||
* @static | ||
* @method portableToMessage | ||
* @param {Object} template The template to conform to | ||
* @param {{text: Object, binary: Array}} streams The streams to conform | ||
* @return {Object} The data structure matching the template. | ||
*/ | ||
fdom.proxy.portableToMessage = function(template, streams) { | ||
return fdom.proxy.conform(template, streams.text, streams.binary, false); | ||
}; | ||
/** | ||
* Force a collection of values to look like the types and length of an API | ||
* template. | ||
* @static | ||
* @method conform | ||
* @param {Object} template The template to conform to | ||
* @param {Object} from The value to conform | ||
* @param {Array} externals Listing of binary elements in the template | ||
* @param {Boolean} Whether to to separate or combine streams. | ||
*/ | ||
fdom.proxy.conform = function(template, from, externals, separate) { | ||
/* jshint -W086 */ | ||
if (typeof(from) === 'function') { | ||
//from = undefined; | ||
//throw "Trying to conform a function"; | ||
return undefined; | ||
} else if (typeof(from) === 'undefined') { | ||
return undefined; | ||
} else if (from === null) { | ||
return null; | ||
} else if (template === undefined) { | ||
fdom.debug.error("Message discarded for not matching declared type!", from); | ||
return undefined; | ||
} | ||
switch(template) { | ||
case 'string': | ||
return String('') + from; | ||
case 'number': | ||
return Number(1) * from; | ||
case 'boolean': | ||
return Boolean(from === true); | ||
case 'object': | ||
// TODO(willscott): Allow removal if sandboxing enforces this. | ||
if (typeof from === 'undefined') { | ||
return undefined; | ||
} else { | ||
return JSON.parse(JSON.stringify(from)); | ||
} | ||
case 'blob': | ||
if (separate) { | ||
if (from instanceof Blob) { | ||
externals.push(from); | ||
return externals.length - 1; | ||
} else { | ||
fdom.debug.warn('conform expecting Blob, sees ' + (typeof from)); | ||
externals.push(new Blob([])); | ||
return externals.length - 1; | ||
} | ||
} else { | ||
return externals[from]; | ||
} | ||
case 'buffer': | ||
if (separate) { | ||
externals.push(fdom.proxy.makeArrayBuffer(from)); | ||
return externals.length - 1; | ||
} else { | ||
return fdom.proxy.makeArrayBuffer(externals[from]); | ||
} | ||
case 'proxy': | ||
return from; | ||
} | ||
var val, i; | ||
if (Array.isArray(template) && from !== undefined) { | ||
val = []; | ||
i = 0; | ||
if (template.length === 2 && template[0] === 'array') { | ||
//console.log("template is array, value is " + JSON.stringify(value)); | ||
for (i = 0; i < from.length; i += 1) { | ||
val.push(fdom.proxy.conform(template[1], from[i], externals, | ||
separate)); | ||
} | ||
} else { | ||
for (i = 0; i < template.length; i += 1) { | ||
if (from[i] !== undefined) { | ||
val.push(fdom.proxy.conform(template[i], from[i], externals, | ||
separate)); | ||
} else { | ||
val.push(undefined); | ||
} | ||
} | ||
} | ||
return val; | ||
} else if (typeof template === 'object' && from !== undefined) { | ||
val = {}; | ||
fdom.util.eachProp(template, function(prop, name) { | ||
if (from[name] !== undefined) { | ||
val[name] = fdom.proxy.conform(prop, from[name], externals, separate); | ||
} | ||
}); | ||
return val; | ||
} | ||
fdom.debug.warn('Unknown template type: ' + template); | ||
}; | ||
/** | ||
* Make a thing into an Array Buffer | ||
* @static | ||
* @method makeArrayBuffer | ||
* @param {Object} thing | ||
* @return {ArrayBuffer} An Array Buffer | ||
*/ | ||
fdom.proxy.makeArrayBuffer = function(thing) { | ||
if (!thing) { | ||
return new ArrayBuffer(0); | ||
} | ||
if (thing instanceof ArrayBuffer) { | ||
return thing; | ||
} else if (thing.constructor.name === "ArrayBuffer" && | ||
typeof thing.prototype === "undefined") { | ||
// Workaround for webkit origin ownership issue. | ||
// https://github.com/UWNetworksLab/freedom/issues/28 | ||
return new DataView(thing).buffer; | ||
} else { | ||
fdom.debug.warn('expecting ArrayBuffer, but saw ' + | ||
(typeof thing) + ': ' + JSON.stringify(thing)); | ||
return new ArrayBuffer(0); | ||
} | ||
}; | ||
/** | ||
* Recursively traverse a [nested] object and freeze its keys from being | ||
* writable. Note, the result can have new keys added to it, but existing ones | ||
* cannot be overwritten. Doesn't do anything for arrays or other collections. | ||
* | ||
* @method recursiveFreezeObject | ||
* @static | ||
* @param {Object} obj - object to be frozen | ||
* @return {Object} obj | ||
**/ | ||
fdom.proxy.recursiveFreezeObject = function(obj) { | ||
var k, ret = {}; | ||
if (typeof obj !== 'object') { | ||
return obj; | ||
} | ||
for (k in obj) { | ||
if (obj.hasOwnProperty(k)) { | ||
Object.defineProperty(ret, k, { | ||
value: fdom.proxy.recursiveFreezeObject(obj[k]), | ||
writable: false, | ||
enumerable: true | ||
}); | ||
} | ||
} | ||
return ret; | ||
}; | ||
module.exports = ApiInterface; |
@@ -1,10 +0,6 @@ | ||
/*globals fdom:true */ | ||
/*jslint indent:2, white:true, node:true, sloppy:true, browser:true */ | ||
if (typeof fdom === 'undefined') { | ||
fdom = {}; | ||
} | ||
fdom.proxy = fdom.proxy || {}; | ||
var util = require('../util'); | ||
fdom.proxy.EventInterface = function(onMsg, emit) { | ||
fdom.util.handleEvents(this); | ||
var EventInterface = function(onMsg, emit, debug) { | ||
util.handleEvents(this); | ||
@@ -19,1 +15,3 @@ onMsg(this, function(emit, type, msg) { | ||
}; | ||
module.exports = EventInterface; |
@@ -1,7 +0,7 @@ | ||
/*globals fdom:true, XMLHttpRequest, Promise */ | ||
/*jslint indent:2,white:true,node:true,sloppy:true */ | ||
if (typeof fdom === 'undefined') { | ||
fdom = {}; | ||
} | ||
/*globals XMLHttpRequest */ | ||
/*jslint indent:2,node:true,sloppy:true */ | ||
var PromiseCompat = require('es6-promise').Promise; | ||
var util = require('./util'); | ||
/** | ||
@@ -11,5 +11,7 @@ * The Resource registry for FreeDOM. Used to look up requested Resources, | ||
* @Class Resource | ||
* @param {Debug} debug The logger to use for debugging. | ||
* @constructor | ||
*/ | ||
var Resource = function() { | ||
var Resource = function (debug) { | ||
this.debug = debug; | ||
this.files = {}; | ||
@@ -23,2 +25,3 @@ this.resolvers = [this.httpResolver, this.nullResolver]; | ||
'chrome': this.xhrRetriever, | ||
'app': this.xhrRetriever, | ||
'manifest': this.manifestRetriever | ||
@@ -35,10 +38,10 @@ }; | ||
*/ | ||
Resource.prototype.get = function(manifest, url) { | ||
Resource.prototype.get = function (manifest, url) { | ||
var key = JSON.stringify([manifest, url]); | ||
return new Promise(function(resolve, reject) { | ||
return new PromiseCompat(function (resolve, reject) { | ||
if (this.files[key]) { | ||
resolve(this.files[key]); | ||
} else { | ||
this.resolve(manifest, url).then(function(key, resolve, address) { | ||
this.resolve(manifest, url).then(function (key, resolve, address) { | ||
this.files[key] = address; | ||
@@ -58,7 +61,7 @@ //fdom.debug.log('Resolved ' + key + ' to ' + address); | ||
*/ | ||
Resource.prototype.getContents = function(url) { | ||
return new Promise(function(resolve, reject) { | ||
Resource.prototype.getContents = function (url) { | ||
return new PromiseCompat(function (resolve, reject) { | ||
var prop; | ||
if (!url) { | ||
fdom.debug.warn("Asked to get contents of undefined URL."); | ||
this.debug.warn("Asked to get contents of undefined URL."); | ||
return reject(); | ||
@@ -86,4 +89,4 @@ } | ||
*/ | ||
Resource.prototype.resolve = function(manifest, url) { | ||
return new Promise(function(resolve, reject) { | ||
Resource.prototype.resolve = function (manifest, url) { | ||
return new PromiseCompat(function (resolve, reject) { | ||
var promises = []; | ||
@@ -93,7 +96,7 @@ if (url === undefined) { | ||
} | ||
fdom.util.eachReverse(this.resolvers, function(resolver) { | ||
promises.push(new Promise(resolver.bind({}, manifest, url))); | ||
util.eachReverse(this.resolvers, function (resolver) { | ||
promises.push(new PromiseCompat(resolver.bind({}, manifest, url))); | ||
}.bind(this)); | ||
//TODO this would be much cleaner if Promise.any existed | ||
Promise.all(promises).then(function(values) { | ||
PromiseCompat.all(promises).then(function (values) { | ||
var i; | ||
@@ -120,3 +123,3 @@ for (i = 0; i < values.length; i += 1) { | ||
*/ | ||
Resource.prototype.addResolver = function(resolver) { | ||
Resource.prototype.addResolver = function (resolver) { | ||
this.resolvers.push(resolver); | ||
@@ -133,5 +136,5 @@ }; | ||
*/ | ||
Resource.prototype.addRetriever = function(proto, retriever) { | ||
Resource.prototype.addRetriever = function (proto, retriever) { | ||
if (this.contentRetrievers[proto]) { | ||
fdom.debug.warn("Unwilling to override file retrieval for " + proto); | ||
this.debug.warn("Unwilling to override file retrieval for " + proto); | ||
return; | ||
@@ -143,2 +146,22 @@ } | ||
/** | ||
* Register external resolvers and retreavers | ||
* @method register | ||
* @param {{"proto":String, "resolver":Function, "retreaver":Function}[]} | ||
* resolvers The list of retreivers and resolvers. | ||
*/ | ||
Resource.prototype.register = function (resolvers) { | ||
if (!resolvers.length) { | ||
return; | ||
} | ||
resolvers.forEach(function (item) { | ||
if (item.resolver) { | ||
this.addResolver(item.resolver); | ||
} else if (item.proto && item.retriever) { | ||
this.addRetriever(item.proto, item.retriever); | ||
} | ||
}.bind(this)); | ||
}; | ||
/** | ||
* Determine if a URL is an absolute URL of a given Scheme. | ||
@@ -152,3 +175,3 @@ * @method hasScheme | ||
*/ | ||
Resource.hasScheme = function(protocols, url) { | ||
Resource.hasScheme = function (protocols, url) { | ||
var i; | ||
@@ -171,6 +194,7 @@ for (i = 0; i < protocols.length; i += 1) { | ||
**/ | ||
Resource.removeRelativePath = function(url) { | ||
Resource.removeRelativePath = function (url) { | ||
var idx = url.indexOf("://") + 3, | ||
stack, toRemove, | ||
result; | ||
stack, | ||
toRemove, | ||
result; | ||
// Remove all instances of /./ | ||
@@ -215,5 +239,11 @@ url = url.replace(/\/\.\//g, "/"); | ||
*/ | ||
Resource.prototype.httpResolver = function(manifest, url, resolve, reject) { | ||
var protocols = ["http", "https", "chrome", "chrome-extension", "resource"], | ||
dirname, protocolIdx, pathIdx, path, base, result; | ||
Resource.prototype.httpResolver = function (manifest, url, resolve, reject) { | ||
var protocols = ["http", "https", "chrome", "chrome-extension", "resource", | ||
"app"], | ||
dirname, | ||
protocolIdx, | ||
pathIdx, | ||
path, | ||
base, | ||
result; | ||
@@ -257,7 +287,10 @@ if (Resource.hasScheme(protocols, url)) { | ||
*/ | ||
Resource.prototype.nullResolver = function(manifest, url, resolve, reject) { | ||
var protocols = ["manifest", "data;base64"]; | ||
Resource.prototype.nullResolver = function (manifest, url, resolve, reject) { | ||
var protocols = ["manifest"]; | ||
if (Resource.hasScheme(protocols, url)) { | ||
resolve(url); | ||
return true; | ||
} else if (url.indexOf('data:') === 0) { | ||
resolve(url); | ||
return true; | ||
} | ||
@@ -278,3 +311,3 @@ resolve(false); | ||
*/ | ||
Resource.prototype.manifestRetriever = function(manifest, resolve, reject) { | ||
Resource.prototype.manifestRetriever = function (manifest, resolve, reject) { | ||
var data; | ||
@@ -285,4 +318,4 @@ try { | ||
resolve(data); | ||
} catch(e) { | ||
fdom.debug.warn("Invalid manifest URL referenced:" + manifest); | ||
} catch (e) { | ||
this.debug.warn("Invalid manifest URL referenced:" + manifest); | ||
reject(); | ||
@@ -300,12 +333,12 @@ } | ||
*/ | ||
Resource.prototype.xhrRetriever = function(url, resolve, reject) { | ||
Resource.prototype.xhrRetriever = function (url, resolve, reject) { | ||
var ref = new XMLHttpRequest(); | ||
ref.addEventListener("readystatechange", function(resolve, reject) { | ||
ref.addEventListener("readystatechange", function (resolve, reject) { | ||
if (ref.readyState === 4 && ref.responseText) { | ||
resolve(ref.responseText); | ||
} else if (ref.readyState === 4) { | ||
fdom.debug.warn("Failed to load file " + url + ": " + ref.status); | ||
this.debug.warn("Failed to load file " + url + ": " + ref.status); | ||
reject(ref.status); | ||
} | ||
}.bind({}, resolve, reject), false); | ||
}.bind(this, resolve, reject), false); | ||
ref.overrideMimeType("application/json"); | ||
@@ -316,5 +349,2 @@ ref.open("GET", url, true); | ||
/** | ||
* Defines fdom.resources as a singleton registry for file management. | ||
*/ | ||
fdom.resources = new Resource(); | ||
module.exports = Resource; |
@@ -1,7 +0,4 @@ | ||
/*globals fdom:true, crypto, freedomcfg, WebKitBlobBuilder, Blob, URL */ | ||
/*globals crypto, WebKitBlobBuilder, Blob, URL */ | ||
/*globals webkitURL, Uint8Array, Uint16Array, ArrayBuffer */ | ||
/*jslint indent:2,white:true,browser:true,sloppy:true */ | ||
if (typeof fdom === 'undefined') { | ||
fdom = {}; | ||
} | ||
/*jslint indent:2,white:true,browser:true,node:true,sloppy:true */ | ||
@@ -13,3 +10,3 @@ /** | ||
*/ | ||
fdom.util = {}; | ||
var util = {}; | ||
@@ -23,3 +20,3 @@ | ||
*/ | ||
fdom.util.eachReverse = function(ary, func) { | ||
util.eachReverse = function(ary, func) { | ||
if (ary) { | ||
@@ -39,3 +36,3 @@ var i; | ||
*/ | ||
fdom.util.hasProp = function(obj, prop) { | ||
util.hasProp = function(obj, prop) { | ||
return Object.prototype.hasOwnProperty.call(obj, prop); | ||
@@ -51,3 +48,3 @@ }; | ||
*/ | ||
fdom.util.eachProp = function(obj, func) { | ||
util.eachProp = function(obj, func) { | ||
var prop; | ||
@@ -72,6 +69,6 @@ for (prop in obj) { | ||
*/ | ||
fdom.util.mixin = function(target, source, force) { | ||
util.mixin = function(target, source, force) { | ||
if (source) { | ||
fdom.util.eachProp(source, function (value, prop) { | ||
if (force || !fdom.util.hasProp(target, prop)) { | ||
util.eachProp(source, function (value, prop) { | ||
if (force || !util.hasProp(target, prop)) { | ||
target[prop] = value; | ||
@@ -89,3 +86,3 @@ } | ||
*/ | ||
fdom.util.getId = function() { | ||
util.getId = function() { | ||
var guid = 'guid', | ||
@@ -97,3 +94,3 @@ domain = 12, | ||
crypto.getRandomValues(buffer); | ||
fdom.util.eachReverse(buffer, function(n) { | ||
util.eachReverse(buffer, function(n) { | ||
guid += '-' + n; | ||
@@ -119,3 +116,3 @@ }); | ||
*/ | ||
fdom.util.str2ab = function(str) { | ||
util.str2ab = function(str) { | ||
var length = str.length, | ||
@@ -139,3 +136,3 @@ buffer = new ArrayBuffer(length * 2), // 2 bytes for each char | ||
*/ | ||
fdom.util.ab2str = function(buffer) { | ||
util.ab2str = function(buffer) { | ||
return String.fromCharCode.apply(null, new Uint16Array(buffer)); | ||
@@ -150,3 +147,3 @@ }; | ||
*/ | ||
fdom.util.handleEvents = function(obj) { | ||
util.handleEvents = function(obj) { | ||
var eventState = { | ||
@@ -297,3 +294,3 @@ multiple: {}, | ||
/*!@preserve StartModuleContextDeclaration*/ | ||
fdom.util.isModuleContext = function() { | ||
util.isModuleContext = function() { | ||
return (typeof document === 'undefined'); | ||
@@ -303,25 +300,2 @@ }; | ||
/** | ||
* Provide a version of src where the 'isModuleContext' function will return | ||
* true. Used for creating module contexts which may not be able to determine | ||
* that they need to start up in that mode by themselves. | ||
* @method forceModuleContext | ||
* @static | ||
*/ | ||
fdom.util.forceModuleContext = function(src) { | ||
var definition = "function () { return true; }", | ||
idx = src.indexOf('StartModuleContextDeclaration'), | ||
funcidx = src.indexOf('function', idx), | ||
source, | ||
blob; | ||
if (idx === -1 || funcidx === -1) { | ||
fdom.debug.error('Unable to force mode, source is in unexpected condition.'); | ||
return; | ||
} | ||
source = src.substr(0, funcidx) + definition + ' || ' + | ||
src.substr(funcidx); | ||
blob = fdom.util.getBlob(source, 'text/javascript'); | ||
return fdom.util.getURL(blob); | ||
}; | ||
/** | ||
* Get a Blob object of a string. | ||
@@ -333,3 +307,3 @@ * Polyfills implementations which don't have a current Blob constructor, like | ||
*/ | ||
fdom.util.getBlob = function(data, type) { | ||
util.getBlob = function(data, type) { | ||
if (typeof Blob !== 'function' && typeof WebKitBlobBuilder !== 'undefined') { | ||
@@ -351,3 +325,3 @@ var builder = new WebKitBlobBuilder(); | ||
*/ | ||
fdom.util.getURL = function(blob) { | ||
util.getURL = function(blob) { | ||
if (typeof URL !== 'object' && typeof webkitURL !== 'undefined') { | ||
@@ -361,23 +335,2 @@ return webkitURL.createObjectURL(blob); | ||
/** | ||
* When running in a priviledged context, honor a global | ||
* 'freedomcfg' function to allow registration of additional API providers. | ||
* @method advertise | ||
* @param {Boolean} force Advertise even if not in a priviledged context. | ||
* @static | ||
*/ | ||
fdom.util.advertise = function(force) { | ||
// TODO: Determine a better mechanism than this whitelisting. | ||
if (typeof location !== 'undefined') { | ||
if ((location.protocol === 'chrome-extension:' || | ||
location.protocol === 'chrome:' || | ||
location.protocol === 'resource:' || force) && | ||
typeof freedomcfg !== "undefined") { | ||
freedomcfg(fdom.apis.register.bind(fdom.apis)); | ||
} | ||
} else if (force && typeof freedomcfg !== "undefined") { | ||
freedomcfg(fdom.apis.register.bind(fdom.apis)); | ||
} | ||
}; | ||
/** | ||
* Find all scripts on the given page. | ||
@@ -387,4 +340,6 @@ * @method scripts | ||
*/ | ||
fdom.util.scripts = function(global) { | ||
util.scripts = function(global) { | ||
return global.document.getElementsByTagName('script'); | ||
}; | ||
module.exports = util; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
174
20366
1
814618
2
27
18
+ Addedinclude-folder@^0.7.0
+ Addednode-json-minify@^0.1.3-a
+ Addedinclude-folder@0.7.0(transitive)
+ Addedlodash@2.4.2(transitive)
+ Addednode-json-minify@0.1.3-a(transitive)