/** * @license * Copyright (c) 2015 The Polymer Project Authors. All rights reserved. * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt * Code distributed by Google as part of the polymer project is also * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt */ // jshint node:true 'use strict'; // jshint -W079 // Promise polyfill var Promise = global.Promise || require('es6-promise').Promise; // jshint +W079 function Deferred() { var self = this; this.promise = new Promise(function(resolve, reject) { self.resolve = resolve; self.reject = reject; }); } /** * An object that knows how to resolve resources. * @typedef {Object} Resolver * @memberof hydrolysis * @property {function(string, Deferred): boolean} accept Attempt to resolve * `deferred` with the contents the specified URL. Returns false if the * Resolver is unable to resolve the URL. */ /** * A FileLoader lets you resolve URLs with a set of potential resolvers. * @constructor * @memberof hydrolysis */ function FileLoader() { this.resolvers = []; // map url -> Deferred this.requests = {}; } FileLoader.prototype = { /** * Add an instance of a Resolver class to the list of url resolvers * * Ordering of resolvers is most to least recently added * The first resolver to "accept" the url wins. * @param {Resolver} resolver The resolver to add. */ addResolver: function(resolver) { this.resolvers.push(resolver); }, /** * Return a promise for an absolute url * * Url requests are deduplicated by the loader, returning the same Promise for * identical urls * * @param {string} url The absolute url to request. * @return {Promise.} A promise that resolves to the contents of the URL. */ request: function(uri) { var promise; if (!(uri in this.requests)) { var handled = false; var deferred = new Deferred(); this.requests[uri] = deferred; // loop backwards through resolvers until one "accepts" the request for (var i = this.resolvers.length - 1, r; i >= 0; i--) { r = this.resolvers[i]; if (r.accept(uri, deferred)) { handled = true; break; } } if (!handled) { deferred.reject(new Error('no resolver found for ' + uri)); } promise = deferred.promise; } else { promise = this.requests[uri].promise; } return promise; } }; module.exports = FileLoader;