Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
Fix #19.
  • Loading branch information
Tom Ashworth committed Jan 19, 2014
1 parent 4b53ec0 commit 8f43b44
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 16 deletions.
62 changes: 62 additions & 0 deletions lib/_Storage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
require('es6-shim');
var fs = require('fs');
var pathlib = require('path');
var crypto = require('crypto')
var Promise = require('rsvp').Promise;

module.exports = _Storage;

_Storage.cache = {};

_Storage.id = function () {
var tuple = process.hrtime();
var time = tuple[0] * 1e9 + tuple[1];
var shasum = crypto.createHash('sha1');
shasum.update(''+time);
return shasum.digest('hex');
};

_Storage.heapPrefix = 'heap' + String.fromCharCode(0);

/**
* _Storage
* Note: non-heap objects cannot reference each other.
* TODO: save to files
*/

function _Storage(namespace) {
this.heap = !namespace;
this.namespace = namespace || _Storage.id();
this.readyPromise = Promise.resolve();
if (this.heap) {
_Storage.cache[this.reference({ _storage: this })] = this;
}
}

_Storage.prototype.init = function(data) {
this.readyPromise = Promise.resolve(data);
return this.readyPromise;
};

_Storage.prototype.persist = function (data) {
return Promise.resolve();
};

_Storage.prototype.reference = function (storedObject) {
if (!storedObject._storage || !storedObject._storage.heap) {
return storedObject;
}
return _Storage.heapPrefix + storedObject._storage.namespace;
};

_Storage.prototype.dereference = function (storedObjectReference) {
if (!storedObjectReference.startsWith(_Storage.heapPrefix)) {
throw Error('Reference is not valid: ' + storedObjectReference)
}
// TODO: get from storage
if (_Storage.cache[namespace]) {
return Promise.resolve(_Storage.cache[namespace]);
} else {
return Promise.reject(new Error('NullPointerException: could not find that thing.'));
}
};
7 changes: 4 additions & 3 deletions lib/_Worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@ var Request = require('../spec/Request');
util.inherits(_Worker, EventEmitter);
module.exports = _Worker;

function _Worker(url, body) {
function _Worker(url, glob, body) {
EventEmitter.call(this);

var worker = this;
var loadScripts = createScriptLoader(url);
var scope = new ServiceWorker(url);
var scope = new ServiceWorker(url, glob);

this.url = url;
this.glob = glob;
this.body = body;
this.scope = scope;

Expand All @@ -46,7 +47,7 @@ function _Worker(url, body) {
console.log(chalk.red('Install failed for worker version:'), chalk.yellow(worker.scope.version));
throw err;
});

// these promises are resolved in install()
this._activateCalled = false;
this._activateResolver = null;
Expand Down
6 changes: 4 additions & 2 deletions lib/_WorkerRegistration.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
var fs = require('fs');
var pathlib = require('path');
var URL = require('dom-urls');
var chalk = require('chalk');

Expand All @@ -18,7 +20,7 @@ function _WorkerRegistration(url, glob) {

_WorkerRegistration.prototype.update = function() {
var workerRegistration = this;

console.log(chalk.blue('Fetching worker from', this.url.toString()));

// TODO: we have a race condition here
Expand All @@ -36,7 +38,7 @@ _WorkerRegistration.prototype.update = function() {
return;
}

var nextWorker = new _Worker(workerRegistration.url, body);
var nextWorker = new _Worker(workerRegistration.url, workerRegistration.glob, body);

workerRegistration.nextWorker = nextWorker;

Expand Down
2 changes: 2 additions & 0 deletions spec/Cache.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ var AsyncMap = require('../spec/AsyncMap');
var Request = require('../spec/Request');
var fetch = require('../spec/fetch');
var URL = require('dom-urls');
var _Storage = require('../lib/_Storage');

module.exports = Cache;

Expand Down Expand Up @@ -40,6 +41,7 @@ Cache.persistValue = function (key, value) {

function Cache() {
this.items = new AsyncMap();
hide(this, '_storage', new _Storage());
var args = [].slice.call(arguments);
args.forEach(function (url) {
this.add(new URL(url));
Expand Down
46 changes: 43 additions & 3 deletions spec/CacheList.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,61 @@
var util = require('util');
var hide = require('hide-key');
var Cache = require('../spec/Cache');
var URL = require('dom-urls');
var AsyncMap = require('../spec/AsyncMap');
var Promise = require('rsvp').Promise;
var _Storage = require('../lib/_Storage');

util.inherits(CacheList, AsyncMap);
module.exports = CacheList;

function CacheList() {
CacheList.makeNamespace = function (origin) {
return origin
.replace('//', '')
.replace(/[^a-z0-9]/ig, '-')
.replace(/\-{2,}/g, '');
};

/**
* CacheList
*/

function CacheList(url) {
AsyncMap.apply(this, arguments);
this.origin = 'none://none';
url = new URL(url);
this.origin = url.protocol + '//' + url.host;
hide(this, '_namespace', CacheList.makeNamespace(this.origin));
hide(this, '_storage', new _Storage(this._namespace));
this._storage.init({
caches: []
});
console.log('this._namespace', this._namespace);
console.log('this._storage', this._storage);
}

/**
* Add a cache to the CacheList. This adds a reference to the cache on the heap, not the cache
* itself. We then wrap get to dereference it.
*/
CacheList.prototype.set = function (key, cache) {
if (!(cache instanceof Cache)) {
throw Error('CacheList only accepts Caches.');
}
return AsyncMap.prototype.set.call(this, key, cache);
console.log('== CacheList#set ========================');
return this._storage.readyPromise
.then(function (data) {
data.caches.push({
key: key,
cache: this._storage.reference(cache)
});
console.log('data.caches', data.caches);
return this._storage.persist(data);
}.bind(this)).then(function () {
return AsyncMap.prototype.set.call(this, key, cache);
}.bind(this))
.catch(function (why) {
console.error(why);
});
};

CacheList.prototype.ready = function () {
Expand Down
11 changes: 3 additions & 8 deletions spec/ServiceWorker.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,10 @@ var chalk = require('chalk');

module.exports = ServiceWorker;

function ServiceWorker(workerUrl) {
function ServiceWorker(workerUrl, glob) {
this._eventListeners = [];

// TODO: replace this with a constructor param.
// Something like _CacheLists should store a CacheList per origin
this.caches = new CacheList();

// TODO: work out why this is needed, hopefully remove
this.caches.origin = workerUrl.origin;
this.caches = new CacheList(glob);

// importScripts requires execution context info, so it's handled in _Worker.js
// this.importScripts = ...
Expand Down Expand Up @@ -67,8 +62,8 @@ ServiceWorker.prototype.clearInterval = clearInterval;

ServiceWorker.prototype.Map = require('../spec/Map');
ServiceWorker.prototype.AsyncMap = require('../spec/AsyncMap');
ServiceWorker.prototype.Cache = require('../spec/Cache');
ServiceWorker.prototype.CacheList = require('../spec/CacheList');
ServiceWorker.prototype.Cache = require('../spec/Cache');
ServiceWorker.prototype.Event = require('../spec/Event');
ServiceWorker.prototype.InstallEvent = require('../spec/InstallEvent');
ServiceWorker.prototype.FetchEvent = require('../spec/FetchEvent');
Expand Down

0 comments on commit 8f43b44

Please sign in to comment.