123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 |
- 'use strict';
-
- var normalize = require('value-or-function');
-
- var slice = Array.prototype.slice;
-
- function createResolver(config, options) {
- // TODO: should the config object be validated?
- config = config || {};
- options = options || {};
-
- var resolver = {
- resolve: resolve,
- };
-
-
- // Keep constants separately
- var constants = {};
-
- function resolveConstant(key) {
- if (constants.hasOwnProperty(key)) {
- return constants[key];
- }
-
- var definition = config[key];
- // Ignore options that are not defined
- if (!definition) {
- return;
- }
-
- var option = options[key];
-
- if (option != null) {
- if (typeof option === 'function') {
- return;
- }
- option = normalize.call(resolver, definition.type, option);
- if (option != null) {
- constants[key] = option;
- return option;
- }
- }
-
- var fallback = definition.default;
- if (option == null && typeof fallback !== 'function') {
- constants[key] = fallback;
- return fallback;
- }
- }
-
-
- // Keep requested keys to detect (and disallow) recursive resolution
- var stack = [];
-
- function resolve(key) {
- var option = resolveConstant(key);
- if (option != null) {
- return option;
- }
-
- var definition = config[key];
- // Ignore options that are not defined
- if (!definition) {
- return;
- }
-
- if (stack.indexOf(key) >= 0) {
- throw new Error('Recursive resolution denied.');
- }
-
- option = options[key];
- var fallback = definition.default;
- var appliedArgs = slice.call(arguments, 1);
- var args = [definition.type, option].concat(appliedArgs);
-
- function toResolve() {
- stack.push(key);
- var option = normalize.apply(resolver, args);
-
- if (option == null) {
- option = fallback;
- if (typeof option === 'function') {
- option = option.apply(resolver, appliedArgs);
- }
- }
-
- return option;
- }
-
- function onResolve() {
- stack.pop();
- }
-
- return tryResolve(toResolve, onResolve);
- }
-
-
- return resolver;
- }
-
-
- function tryResolve(toResolve, onResolve) {
- try {
- return toResolve();
- } finally {
- onResolve();
- }
- }
-
-
- module.exports = createResolver;
|