|
9 | 9 | genInlineName, |
10 | 10 | cacheWrap, |
11 | 11 | parseFiles, |
| 12 | + getImportName, |
| 13 | + extractPreprocessors, |
| 14 | + asyncify, |
12 | 15 | } = require('./utils.js') |
13 | 16 |
|
14 | 17 |
|
@@ -143,10 +146,76 @@ Depper.prototype.inline = function(source, basedir, done) { |
143 | 146 | } |
144 | 147 |
|
145 | 148 | /** |
146 | | - * Add method dummy interface |
| 149 | + * Adds a shader file to the graph, including its dependencies |
| 150 | + * which are resolved in this step. Transforms are also applied |
| 151 | + * in the process too, as they may potentially add or remove dependent |
| 152 | + * modules. |
| 153 | + * |
| 154 | + * @param {String} filename The absolute path of this file. |
| 155 | + * @param {Object} [opts] The options will be pased to _resolveImports function. |
| 156 | + * @param {(err: Error, deps?: object[]) => any} [done] |
| 157 | + * |
| 158 | + * If async is defined then `done` callback will be called when the entire graph has been |
| 159 | + * resolved, and will include an array of dependencies discovered |
| 160 | + * so far as its second argument. |
| 161 | + * |
| 162 | + * If sync returns an array of dependencies discovered so far as its second argument. |
147 | 163 | */ |
148 | | -Depper.prototype.add = function(filename, cb) { |
| 164 | +Depper.prototype.add = function(filename, opts, done) { |
| 165 | + if (typeof opts === 'function') { |
| 166 | + done = opts |
| 167 | + opts = {} |
| 168 | + } |
149 | 169 |
|
| 170 | + var self = this |
| 171 | + var exports = [] |
| 172 | + var imports = [] |
| 173 | + var dep = this._addDep(filename) |
| 174 | + var resolveOpts = Object.assign({ |
| 175 | + deps: dep.deps, |
| 176 | + }, opts) |
| 177 | + |
| 178 | + var process = asyncify( |
| 179 | + function(_, next) {return self.readFile(filename, next) }, |
| 180 | + function(_, next) {return self.getTransformsForFile(filename, next) }, |
| 181 | + function(result, next) { |
| 182 | + // @ts-ignore |
| 183 | + self.emit('file', filename) |
| 184 | + return self.applyTransforms(filename, result[0], result[1], next) |
| 185 | + }, |
| 186 | + function(result, next) { |
| 187 | + extractPreprocessors(dep.source = result[2], imports, exports) |
| 188 | + return self._resolveImports(imports, resolveOpts, next) |
| 189 | + }, function(_, next) { |
| 190 | + if(next) { |
| 191 | + next(null, self._deps) |
| 192 | + } |
| 193 | + }) |
| 194 | + |
| 195 | + |
| 196 | + if (this._async) { |
| 197 | + process(done || function() { |
| 198 | + console.warn('glslify-deps: depper.add() has not a callback defined using async flow') |
| 199 | + }) |
| 200 | + return dep |
| 201 | + } else { |
| 202 | + process() |
| 203 | + return this._deps |
| 204 | + } |
| 205 | +} |
| 206 | + |
| 207 | +/** |
| 208 | + * Dummy internal function for resolve transforms for a file |
| 209 | + * @param {String} filename The absolute path of the file in question. |
| 210 | + * @param {(err: Error, transforms?: GlslTransform[]) => any} [done] Applies when async true |
| 211 | + * @returns {GlslTransform[]} List of transform for a file |
| 212 | + */ |
| 213 | +Depper.prototype.getTransformsForFile = function(filename, done) { |
| 214 | + if(done) { |
| 215 | + done(null, []) |
| 216 | + } |
| 217 | + console.warn('glslify-deps: depper.getTransformsForFile() not yet implemented') |
| 218 | + return [] |
150 | 219 | } |
151 | 220 |
|
152 | 221 | /** |
@@ -272,7 +341,7 @@ Depper.prototype.applyTransforms = function(filename, src, transforms, done) { |
272 | 341 |
|
273 | 342 | /** |
274 | 343 | * Internal method to add dependencies |
275 | | - * @param {object} extra |
| 344 | + * @param {object} [extra] |
276 | 345 | */ |
277 | 346 | Depper.prototype._addDep = function(file, extra) { |
278 | 347 | var dep = Object.assign({ |
@@ -318,6 +387,62 @@ Depper.prototype._register = function(transforms, cb) { |
318 | 387 | return result |
319 | 388 | } |
320 | 389 |
|
| 390 | +/** |
| 391 | + * Internal async method to retrieve dependencies |
| 392 | + * resolving imports using the internal cache |
| 393 | + * |
| 394 | + * @param {string[]} imports |
| 395 | + * @param {object} [opts] The options will be pased to resolve function. |
| 396 | + * @param {object} [opts.deps] Existing dependencies |
| 397 | + * @param {number} [opts.parallel=10] Parallel threads when async |
| 398 | + * @param {(err: Error) => any} [done] |
| 399 | + * @return {object} Resolved dependencies |
| 400 | + */ |
| 401 | +Depper.prototype._resolveImports = function(imports, opts, done) { |
| 402 | + if (typeof opts === 'function') { |
| 403 | + done = opts |
| 404 | + opts = {} |
| 405 | + } |
| 406 | + var self = this |
| 407 | + var deps = opts && opts.deps || {} |
| 408 | + var parallel = opts && opts.parallel || 10 |
| 409 | + |
| 410 | + var process = asyncify( |
| 411 | + function(result, next) { return self.resolve(result[0], opts, next) }, |
| 412 | + function(result, next) { |
| 413 | + var importName = result[0] |
| 414 | + var resolved = result[1] |
| 415 | + if (self._cache[resolved]) { |
| 416 | + deps[importName] = self._cache[resolved].id |
| 417 | + return next && next() |
| 418 | + } |
| 419 | + if (next) { |
| 420 | + self._cache[resolved] = self.add(resolved, function(err) { |
| 421 | + if (err) return next(err) |
| 422 | + deps[importName] = self._cache[resolved].id |
| 423 | + next() |
| 424 | + }) |
| 425 | + } else { |
| 426 | + var idx = self._i |
| 427 | + self._cache[resolved] = self.add(resolved)[idx] |
| 428 | + deps[importName] = self._cache[resolved].id |
| 429 | + } |
| 430 | + } |
| 431 | + ) |
| 432 | + |
| 433 | + if (this._async) { |
| 434 | + map(imports, parallel, function(imp, next) { |
| 435 | + process([getImportName(imp)], next) |
| 436 | + }, done) |
| 437 | + } else { |
| 438 | + imports.forEach(function (imp) { |
| 439 | + process([getImportName(imp)]) |
| 440 | + }) |
| 441 | + } |
| 442 | + |
| 443 | + return deps |
| 444 | +} |
| 445 | + |
321 | 446 | Depper.prototype.readFile = function(filename, done) { |
322 | 447 | if (path.basename(filename) !== this._inlineName) |
323 | 448 | return this._readFile(filename, done) |
|
0 commit comments