1var fs = require('fs');
2var path = require('path');
3
4var isAllowedResource = require('./is-allowed-resource');
5
6var hasProtocol = require('../utils/has-protocol');
7var isRemoteResource = require('../utils/is-remote-resource');
8
9function loadOriginalSources(context, callback) {
10  var loadContext = {
11    callback: callback,
12    fetch: context.options.fetch,
13    index: 0,
14    inline: context.options.inline,
15    inlineRequest: context.options.inlineRequest,
16    inlineTimeout: context.options.inlineTimeout,
17    localOnly: context.localOnly,
18    rebaseTo: context.options.rebaseTo,
19    sourcesContent: context.sourcesContent,
20    uriToSource: uriToSourceMapping(context.inputSourceMapTracker.all()),
21    warnings: context.warnings
22  };
23
24  return context.options.sourceMap && context.options.sourceMapInlineSources ?
25    doLoadOriginalSources(loadContext) :
26    callback();
27}
28
29function uriToSourceMapping(allSourceMapConsumers) {
30  var mapping = {};
31  var consumer;
32  var uri;
33  var source;
34  var i, l;
35
36  for (source in allSourceMapConsumers) {
37    consumer = allSourceMapConsumers[source];
38
39    for (i = 0, l = consumer.sources.length; i < l; i++) {
40      uri = consumer.sources[i];
41      source = consumer.sourceContentFor(uri, true);
42
43      mapping[uri] = source;
44    }
45  }
46
47  return mapping;
48}
49
50function doLoadOriginalSources(loadContext) {
51  var uris = Object.keys(loadContext.uriToSource);
52  var uri;
53  var source;
54  var total;
55
56  for (total = uris.length; loadContext.index < total; loadContext.index++) {
57    uri = uris[loadContext.index];
58    source = loadContext.uriToSource[uri];
59
60    if (source) {
61      loadContext.sourcesContent[uri] = source;
62    } else {
63      return loadOriginalSource(uri, loadContext);
64    }
65  }
66
67  return loadContext.callback();
68}
69
70function loadOriginalSource(uri, loadContext) {
71  var content;
72
73  if (isRemoteResource(uri)) {
74    return loadOriginalSourceFromRemoteUri(uri, loadContext, function (content) {
75      loadContext.index++;
76      loadContext.sourcesContent[uri] = content;
77      return doLoadOriginalSources(loadContext);
78    });
79  } else {
80    content = loadOriginalSourceFromLocalUri(uri, loadContext);
81    loadContext.index++;
82    loadContext.sourcesContent[uri] = content;
83    return doLoadOriginalSources(loadContext);
84  }
85}
86
87function loadOriginalSourceFromRemoteUri(uri, loadContext, whenLoaded) {
88  var isAllowed = isAllowedResource(uri, true, loadContext.inline);
89  var isRuntimeResource = !hasProtocol(uri);
90
91  if (loadContext.localOnly) {
92    loadContext.warnings.push('Cannot fetch remote resource from "' + uri + '" as no callback given.');
93    return whenLoaded(null);
94  } else if (isRuntimeResource) {
95    loadContext.warnings.push('Cannot fetch "' + uri + '" as no protocol given.');
96    return whenLoaded(null);
97  } else if (!isAllowed) {
98    loadContext.warnings.push('Cannot fetch "' + uri + '" as resource is not allowed.');
99    return whenLoaded(null);
100  }
101
102  loadContext.fetch(uri, loadContext.inlineRequest, loadContext.inlineTimeout, function (error, content) {
103    if (error) {
104      loadContext.warnings.push('Missing original source at "' + uri + '" - ' + error);
105    }
106
107    whenLoaded(content);
108  });
109}
110
111function loadOriginalSourceFromLocalUri(relativeUri, loadContext) {
112  var isAllowed = isAllowedResource(relativeUri, false, loadContext.inline);
113  var absoluteUri = path.resolve(loadContext.rebaseTo, relativeUri);
114
115  if (!fs.existsSync(absoluteUri) || !fs.statSync(absoluteUri).isFile()) {
116    loadContext.warnings.push('Ignoring local source map at "' + absoluteUri + '" as resource is missing.');
117    return null;
118  } else if (!isAllowed) {
119    loadContext.warnings.push('Cannot fetch "' + absoluteUri + '" as resource is not allowed.');
120    return null;
121  }
122
123  return fs.readFileSync(absoluteUri, 'utf8');
124}
125
126module.exports = loadOriginalSources;
127