diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 00000000..a6048490 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,8 @@ +{ + "extends": "standard", + "rules": { + "indent": ["error", 4], + "semi": ["error", "always"], + "space-before-function-paren": ["off"], + } +} diff --git a/README.md b/README.md index c2e11753..74acab28 100644 --- a/README.md +++ b/README.md @@ -1763,14 +1763,13 @@ module.exports = function myPlugin(lasso, config) { }, // Validation checks and initialization based on properties: - init: function(context, callback) { + async init (context) { if (!this.path) { - return callback(new Error('"path" is required')); + throw new Error('"path" is required'); } // NOTE: resolvePath can be used to resolve a provided relative path to a full path this.path = this.resolvePath(this.path); - callback(); }, // Read the resource: @@ -1842,16 +1841,20 @@ The `handler` argument for a CSS dependency has the exact same interface as a ha A custom package dependency can be used to dynamically resolve additional dependencies at optimization time. The sample package dependency handler below illustrates how a package dependency can be used to automatically include every file in a directory as a dependency: ```javascript -var fs = require('fs'); -var path = require('path'); +const fs = require('fs'); +const path = require('path'); +const { promisify } = require('util'); + +promisify(fs.stat); +promisify(fs.readdir); lasso.dependencies.registerPackageType('dir', { properties: { 'path': 'string' }, - init: function(context, callback) { - var path = this.path; + async init (context) { + let path = this.path; if (!path) { callback(new Error('"path" is required')); @@ -1859,34 +1862,22 @@ lasso.dependencies.registerPackageType('dir', { this.path = path = this.resolvePath(path); // Convert the relative path to an absolute path - fs.stat(path, function(err, stat) { - if (err) { - return callback(err); - } - - if (!stat.isDirectory()) { - return callback(new Error('Directory expected: ' + path)); - } - - callback(); - }); + const stat = await fs.stat(path); + if (!stat.isDirectory()) { + throw new Error('Directory expected: ' + path); + } }, - getDependencies: function(context, callback) { - var dir = this.path; - - fs.readdir(dir, function(err, filenames) { - if (err) { - return callback(err); - } + async getDependencies (context) { + const dir = this.path; + const filenames = await fs.readdir(dir); - // Convert the filenames to full paths - var dependencies = filenames.map(function(filename) { - return path.join(dir, filename); - }); - - callback(null, dependencies); + // Convert the filenames to full paths + var dependencies = filenames.map(function(filename) { + return path.join(dir, filename); }); + + return dependencies; }, getDir: function() { diff --git a/lib/BundleConfig.js b/lib/BundleConfig.js index 0b714c9a..d53861d6 100644 --- a/lib/BundleConfig.js +++ b/lib/BundleConfig.js @@ -4,7 +4,7 @@ var DependencyList = require('./DependencyList'); var BundleConfig = function(dirname, filename) { ok(dirname, '"dirname" is required'); ok(typeof dirname === 'string', '"dirname" is required'); - + this.name = null; this.fingerprintsEnabled = undefined; this.dependencies = []; @@ -33,4 +33,4 @@ BundleConfig.prototype = { } }; -module.exports = BundleConfig; \ No newline at end of file +module.exports = BundleConfig; diff --git a/lib/Config.js b/lib/Config.js index 012ec6ef..7c562db2 100644 --- a/lib/Config.js +++ b/lib/Config.js @@ -13,8 +13,8 @@ function createFilterFromContentType(contentType) { // Include this array if the actual content type is in the array of supported content types var contentTypeArray = contentType; if (contentTypeArray.length === 0) { - return function(lassoContext, callback) { - callback(null, true); + return async function (lassoContext) { + return true; }; } @@ -25,9 +25,9 @@ function createFilterFromContentType(contentType) { contentTypeMap[contentType] = true; } - return function(lassoContext, callback) { + return async function(lassoContext) { var contentType = lassoContext.contentType; - return callback(null, contentTypeMap[contentType] === true); + return contentTypeMap[contentType] === true; }; } diff --git a/lib/DependencyList.js b/lib/DependencyList.js index aecc9c16..1eeea528 100644 --- a/lib/DependencyList.js +++ b/lib/DependencyList.js @@ -1,6 +1,5 @@ var dependenciesModule = require('./dependencies'); var ok = require('assert').ok; -var AsyncValue = require('raptor-async/AsyncValue'); function DependencyList(dependencies, dependencyRegistry, dirname, filename) { ok(dirname && typeof dirname === 'string', '"dirname" argument should be a string'); @@ -8,7 +7,7 @@ function DependencyList(dependencies, dependencyRegistry, dirname, filename) { ok(dependencyRegistry && dependenciesModule.isRegistry(dependencyRegistry), 'dependencyRegistry argument is not valid'); if (dependencies) { - if (dependencies.__DependencyList) { + if (dependencies.__DependencyList) { dependencies = dependencies._dependencies; } else if (!Array.isArray(dependencies)) { throw new Error('Invalid dependencies: ' + dependencies); @@ -17,7 +16,7 @@ function DependencyList(dependencies, dependencyRegistry, dirname, filename) { this._dependencyRegistry = dependencyRegistry; this._dependencies = dependencies || []; - this._normalizeAsyncValue = null; + this._normalized = null; this._dirname = dirname; this._filename = filename; @@ -34,27 +33,14 @@ DependencyList.prototype = { this._dependencies.push(config); }, - normalize: function(callback) { - ok(typeof callback === 'function', 'callback function expected'); - - if (!this._normalizeAsyncValue) { - var normalizeAsyncValue = this._normalizeAsyncValue = new AsyncValue(); - - this._dependencyRegistry.normalizeDependencies( + async normalize () { + if (!this._normalized) { + this._normalized = await this._dependencyRegistry.normalizeDependencies( this._dependencies, this._dirname, - this._filename, - function(err, dependencyArray) { - - if (err) { - return normalizeAsyncValue.reject(err); - } - - normalizeAsyncValue.resolve(dependencyArray); - }); + this._filename); } - - this._normalizeAsyncValue.done(callback); + return this._normalized; }, toString: function() { @@ -72,4 +58,4 @@ DependencyList.isDependencyList = function(o) { return o && o.__DependencyList; }; -module.exports = DependencyList; \ No newline at end of file +module.exports = DependencyList; diff --git a/lib/Lasso.js b/lib/Lasso.js index cc00e449..ec8fa215 100644 --- a/lib/Lasso.js +++ b/lib/Lasso.js @@ -1,5 +1,6 @@ 'use strict'; +const { promisify } = require('util'); var nodePath = require('path'); var LassoCache = require('./LassoCache'); var LassoPageResult = require('./LassoPageResult'); @@ -25,17 +26,16 @@ var perfLogger = require('raptor-logging').logger('lasso/perf'); var extend = require('raptor-util/extend'); var cachingFs = require('./caching-fs'); var createError = require('raptor-util/createError'); -var series = require('raptor-async/series'); var resolveFrom = require('resolve-from'); +const readFileAsync = promisify(fs.readFile); -var urlRegExp = /^[^:\/]{0,5}[:]?\/\//; +var urlRegExp = /^[^:\/]{0,5}[:]?\/\//; function isExternalUrl(path) { return urlRegExp.test(path); } - -function getLassoManifestFromOptions(options, dependencyRegistry, callback) { +async function getLassoManifestFromOptions (options, dependencyRegistry) { var lassoManifest; var from = options.from; var fromFilename; @@ -48,9 +48,7 @@ function getLassoManifestFromOptions(options, dependencyRegistry, callback) { } fromFilename = from.filename; fromDirname = nodePath.dirname(fromFilename); - } - else if (typeof from === 'string') { - + } else if (typeof from === 'string') { var stat = cachingFs.statSync(from); if (!stat.exists()) { throw new Error('No directory exists at given "from" path ("' + from + '")'); @@ -71,7 +69,7 @@ function getLassoManifestFromOptions(options, dependencyRegistry, callback) { var packagePath = options.packagePath; if (typeof packagePath !== 'string') { - return callback(new Error('"packagePath" option should be a string')); + throw new Error('"packagePath" option should be a string'); } if (!fromDirname) { @@ -95,21 +93,15 @@ function getLassoManifestFromOptions(options, dependencyRegistry, callback) { } if (typeof dependencies === 'function') { - dependencies(function(err, dependencies) { - if (err) { - return callback(err); - } - - callback(null, new LassoManifest({ - manifest: { - dependencies: dependencies - }, - dependencyRegistry: dependencyRegistry, - dirname: fromDirname, - filename: fromFilename - })); + const resolvedDependencies = await dependencies(); + return new LassoManifest({ + manifest: { + dependencies: resolvedDependencies + }, + dependencyRegistry, + dirname: fromDirname, + filename: fromFilename }); - return; } else if (!Array.isArray(dependencies)) { dependencies = [dependencies]; } @@ -122,7 +114,6 @@ function getLassoManifestFromOptions(options, dependencyRegistry, callback) { dirname: fromDirname, filename: fromFilename }; - } else if (options.lassoManifest) { lassoManifestOptions = { manifest: options.lassoManifest, @@ -130,7 +121,6 @@ function getLassoManifestFromOptions(options, dependencyRegistry, callback) { dirname: options.lassoManifest.dirname || process.cwd(), filename: options.lassoManifest.filename }; - } else if (options.packagePaths) { lassoManifestOptions = { manifest: { @@ -143,13 +133,13 @@ function getLassoManifestFromOptions(options, dependencyRegistry, callback) { } if (lassoManifestOptions) { - callback(null, new LassoManifest(lassoManifestOptions)); + return new LassoManifest(lassoManifestOptions); } else { - callback(null, null); + return null; } } -function doLassoPage(theLasso, options, lassoContext, callback) { +async function doLassoPage (theLasso, options, lassoContext) { var logInfoEnabled = logger.isInfoEnabled(); var perfLogInfoEnabled = perfLogger.isInfoEnabled(); @@ -162,167 +152,167 @@ function doLassoPage(theLasso, options, lassoContext, callback) { lassoContext.pageName = pageName; var config = theLasso.config; - getLassoManifestFromOptions(options, theLasso.dependencies, function(err, lassoManifest) { - if (!lassoManifest) { - callback(new Error('Invalid options. "dependencies", "packagePath" or "lassoManifest" expected. Options: ' + require('util').inspect(options))); - } - logger.debug('getLassoManifestFromOptions()'); + const lassoManifest = await getLassoManifestFromOptions(options, theLasso.dependencies); - options.lassoManifest = lassoManifest; + if (!lassoManifest) { + throw new Error('Invalid options. "dependencies", "packagePath" or "lassoManifest" expected. Options: ' + require('util').inspect(options)); + } - var pluginContext = { - context: lassoContext, - config: config, - options: options, - lasso: theLasso - }; + logger.debug('getLassoManifestFromOptions()'); - // TODO: Deprecate this - theLasso.emit('beforeOptimizePage', pluginContext); - theLasso.emit('beforeLassoPage', pluginContext); - theLasso.emit('beforeBuildPage', pluginContext); + options.lassoManifest = lassoManifest; - var lassoPageResult = new LassoPageResult(); - var slotTracker = new SlotTracker(); + var pluginContext = { + context: lassoContext, + config: config, + options: options, + lasso: theLasso + }; - lassoContext.lassoPageResult = lassoPageResult; + // TODO: Deprecate this + theLasso.emit('beforeOptimizePage', pluginContext); + theLasso.emit('beforeLassoPage', pluginContext); + theLasso.emit('beforeBuildPage', pluginContext); - var writer = lassoContext.writer; + var lassoPageResult = new LassoPageResult(); + var slotTracker = new SlotTracker(); - // Inline code fingerprinting is useful for building a Single Page App - // that is using a Content Security Policy (CSP) that prevents - // untrusted script blocks. By keeping track of inline code - // fingerprints, a build tool could provide these as part of the CSP - // so that inline code blocks created at build time will be trusted. - var fingerprintInlineCode = config.fingerprintInlineCode; - var inlineCodeFingerprints; + lassoContext.lassoPageResult = lassoPageResult; - if (fingerprintInlineCode) { - inlineCodeFingerprints = []; - } + var writer = lassoContext.writer; - function onBundleWritten(bundle) { - if (logInfoEnabled) { - logger.info('Bundle ' + bundle + ' written.'); - } - lassoPageResult.registerBundle(bundle, false, lassoContext); + // Inline code fingerprinting is useful for building a Single Page App + // that is using a Content Security Policy (CSP) that prevents + // untrusted script blocks. By keeping track of inline code + // fingerprints, a build tool could provide these as part of the CSP + // so that inline code blocks created at build time will be trusted. + var fingerprintInlineCode = config.fingerprintInlineCode; + var inlineCodeFingerprints; + + if (fingerprintInlineCode) { + inlineCodeFingerprints = []; + } + + function onBundleWritten (bundle) { + if (logInfoEnabled) { + logger.info('Bundle ' + bundle + ' written.'); } + lassoPageResult.registerBundle(bundle, false, lassoContext); + } - function onAsyncBundleWritten(bundle) { - if (logInfoEnabled) { - logger.info('Bundle ' + bundle + ' (async) written.'); - } - lassoPageResult.registerBundle(bundle, true, lassoContext); + function onAsyncBundleWritten (bundle) { + if (logInfoEnabled) { + logger.info('Bundle ' + bundle + ' (async) written.'); } + lassoPageResult.registerBundle(bundle, true, lassoContext); + } - function buildHtmlSlots(pageBundles) { - pageBundles.forEachBundle(function(bundle) { - var html, - url; + function buildHtmlSlots (pageBundles) { + pageBundles.forEachBundle(function (bundle) { + var html, + url; - var htmlAttributes = bundle.getHtmlAttributes(); + var htmlAttributes = bundle.getHtmlAttributes(); - if (bundle.isInline()) { - if (fingerprintInlineCode) { - var fingerprint = config.fingerprintInlineCode(bundle.getCode()); - if (fingerprint) { - inlineCodeFingerprints.push(fingerprint); - } + if (bundle.isInline()) { + if (fingerprintInlineCode) { + var fingerprint = config.fingerprintInlineCode(bundle.getCode()); + if (fingerprint) { + inlineCodeFingerprints.push(fingerprint); } + } - slotTracker.addInlineCode(bundle.getSlot(), bundle.getContentType(), bundle.getCode(), bundle.getInlinePos(), bundle.isMergeInline()); + slotTracker.addInlineCode( + bundle.getSlot(), + bundle.getContentType(), + bundle.getCode(), + bundle.getInlinePos(), + bundle.isMergeInline()); + } else { + url = bundle.getUrl(lassoContext); + + if (bundle.isJavaScript()) { + html = theLasso.getJavaScriptDependencyHtml(url, htmlAttributes); + } else if (bundle.isStyleSheet()) { + html = theLasso.getCSSDependencyHtml(url, htmlAttributes); + } else if (!bundle.hasContent()) { + // ignore this bundle because contentType is "none" + return; } else { - url = bundle.getUrl(lassoContext); - - if (bundle.isJavaScript()) { - html = theLasso.getJavaScriptDependencyHtml(url, htmlAttributes); - } else if (bundle.isStyleSheet()) { - html = theLasso.getCSSDependencyHtml(url, htmlAttributes); - } else if (!bundle.hasContent()) { - // ignore this bundle because contentType is "none" - return; - } else { - throw new Error('Invalid bundle content type: ' + bundle.getContentType()); - } - slotTracker.addContent(bundle.getSlot(), bundle.getContentType(), html); + throw new Error('Invalid bundle content type: ' + bundle.getContentType()); } - }); + slotTracker.addContent(bundle.getSlot(), bundle.getContentType(), html); + } + }); - lassoPageResult.setHtmlBySlot(slotTracker.getHtmlBySlot()); - lassoPageResult.setInlineCodeFingerprints(inlineCodeFingerprints); - } + lassoPageResult.setHtmlBySlot(slotTracker.getHtmlBySlot()); + lassoPageResult.setInlineCodeFingerprints(inlineCodeFingerprints); + } - var pageBundles; + var pageBundles; - var prevStartTime = startTime; + var prevStartTime = startTime; - var asyncTasks = [ - function buildPageBundles(callback) { + async function buildPageBundles () { + logger.debug('buildPageBundles BEGIN'); + pageBundles = await theLasso.buildPageBundles(options, lassoContext); + } - logger.debug('buildPageBundles BEGIN'); + async function writeAsyncBundles () { + if (perfLogInfoEnabled) { + perfLogger.info('Page bundles built in ' + (Date.now() - prevStartTime) + 'ms'); + } - theLasso.buildPageBundles(options, lassoContext, function(err, _pageBundles) { - if (err) { - return callback(err); - } + prevStartTime = Date.now(); - logger.debug('buildPageBundles COMPLETE'); + lassoContext.setPhase('write-async-page-bundles'); - pageBundles = _pageBundles; - callback(); - }); - }, - function writeAsyncBundles(callback) { - if (perfLogInfoEnabled) { - perfLogger.info('Page bundles built in ' + (Date.now() - prevStartTime) + 'ms'); - } - prevStartTime = Date.now(); + // First write out all of the async bundles + await writer.writeBundles( + pageBundles.forEachAsyncBundleIter(), + onAsyncBundleWritten, + lassoContext); + } - lassoContext.setPhase('write-async-page-bundles'); + async function writeSyncBundles () { + if (perfLogInfoEnabled) { + perfLogger.info('Async page bundles written in ' + (Date.now() - prevStartTime) + 'ms'); + } - // First write out all of the async bundles - writer.writeBundles(pageBundles.forEachAsyncBundleIter(), onAsyncBundleWritten, lassoContext, callback); - }, - function writeSyncBundles(callback) { - if (perfLogInfoEnabled) { - perfLogger.info('Async page bundles written in ' + (Date.now() - prevStartTime) + 'ms'); - } - prevStartTime = Date.now(); + prevStartTime = Date.now(); - lassoContext.setPhase('write-page-bundles'); + lassoContext.setPhase('write-page-bundles'); + // Now write out all of the non-async bundles + await writer.writeBundles( + pageBundles.forEachBundleIter(), + onBundleWritten, + lassoContext); + } - // Now write out all of the non-async bundles - writer.writeBundles(pageBundles.forEachBundleIter(), onBundleWritten, lassoContext, callback); - } - ]; + await buildPageBundles(); + await writeAsyncBundles(); + await writeSyncBundles(); - series(asyncTasks, function(err) { - if (err) { - return callback(err); - } + if (perfLogInfoEnabled) { + perfLogger.info('Page bundles written in ' + (Date.now() - prevStartTime) + 'ms'); + } - if (perfLogInfoEnabled) { - perfLogger.info('Page bundles written in ' + (Date.now() - prevStartTime) + 'ms'); - } - // All of the bundles have now been persisted, now we can - // generate all of the HTML for the page - buildHtmlSlots(pageBundles); + // All of the bundles have now been persisted, now we can + // generate all of the HTML for the page + buildHtmlSlots(pageBundles); - perfLogger.info('Built page "' + pageName + '" in ' + (Date.now() - startTime) + 'ms'); + perfLogger.info('Built page "' + pageName + '" in ' + (Date.now() - startTime) + 'ms'); - if (lassoContext.cache) { - lassoContext.cache.flushAll(); - } + if (lassoContext.cache) { + await lassoContext.cache.flushAll(); + } - callback(null, lassoPageResult); - }); - }); + return lassoPageResult; } function resolvePath(path, from) { - var firstChar = path.charAt(0); if (firstChar === '.') { // path is relative to dependency directory @@ -335,7 +325,7 @@ function resolvePath(path, from) { // and attempt relative path resolution if that fails try { return resolveFrom(from, path); - } catch(e) { + } catch (e) { // Not bothering to check error code since serverResolveRequire // should only throw error for one reason which is "module not found". // if (e.code === 'MODULE_NOT_FOUND') { @@ -366,16 +356,12 @@ function resolvePath(path, from) { } } -function doLassoResource(theLasso, path, options, lassoContext, callback) { - ok(callback != null, 'callback is required'); - ok(typeof callback === 'function', 'callback should be a function'); - +async function doLassoResource (theLasso, path, options, lassoContext) { var inputPath = path; - function done(err, result) { + function done (err, result) { if (err) { - err = createError('Error while resolving resource URL for path "' + path + '". Error: ' + err, err); - return callback(err); + throw createError('Error while resolving resource URL for path "' + path + '". Error: ' + err, err); } var url = result.url; @@ -384,28 +370,24 @@ function doLassoResource(theLasso, path, options, lassoContext, callback) { logger.debug('Resolved URL: ', inputPath, ' --> ', url); } - return callback(null, result); + return result; } if (isExternalUrl(path)) { - return done(null, { - url: path - }); + return done(null, { url: path }); } else { var writer = theLasso.writer; - var hashString = ''; var hashStart = path.indexOf('#'); - if (hashStart != -1) { - hashString = path.substring(hashStart); + if (hashStart !== -1) { path = path.substring(0, hashStart); } - var queryString = '', - queryStart = path.indexOf('?'); + var queryString = ''; + var queryStart = path.indexOf('?'); - if (queryStart != -1) { + if (queryStart !== -1) { queryString = path.substring(queryStart); path = path.substring(0, queryStart); } @@ -423,16 +405,11 @@ function doLassoResource(theLasso, path, options, lassoContext, callback) { } } - try { - path = resolvePath(path, dir); - } catch(e) { - return callback(e); - } - + path = resolvePath(path, dir); } if (!cachingFs.existsSync(path)) { - return done(new Error('File with path "' + path + '" does not exist')); + throw new Error('File with path "' + path + '" does not exist'); } var dataURIEncoding; @@ -449,17 +426,16 @@ function doLassoResource(theLasso, path, options, lassoContext, callback) { } if (dataURIEncoding) { - fs.readFile(path, null, function(err, data) { - if (err) { - return done(err); - } - - var dataUrl = 'data:' + mime.lookup(path) + ';' + dataURIEncoding + ',' + data.toString(dataURIEncoding); + try { + const fileData = await readFileAsync(path, null); + const dataUrl = 'data:' + mime.lookup(path) + ';' + dataURIEncoding + ',' + fileData.toString(dataURIEncoding); return done(null, { url: dataUrl }); - }); + } catch (err) { + return done(err); + } } else { // Record that base 64 encoding was requested for this resource (this might be helpful to the writer) if (base64Requested) { @@ -467,7 +443,8 @@ function doLassoResource(theLasso, path, options, lassoContext, callback) { lassoContext.base64EncodeUrl = true; } - writer.writeResource(path, lassoContext, done); + const writeResult = await writer.writeResource(path, lassoContext); + return done(null, writeResult); } } } @@ -510,73 +487,49 @@ Lasso.prototype = { initPlugins: function() { var plugins = this.config.getPlugins(); - for (var i=0; i { + var builder = () => { logger.debug('getAppBundleMappingsCached - BUILDER'); - this.createAppBundleMappings(bundleSetConfig, lassoContext, callback); + return this.createAppBundleMappings(bundleSetConfig, lassoContext); }; - lassoCache.getBundleMappings(cacheKey, builder, callback); + return lassoCache.getBundleMappings(cacheKey, builder); }, buildLassoCacheKey: function(lassoContext) { - //var config = this.getConfig(); var hash = 5381; var keyParts = []; - function cacheKey_add(str) { + function cacheKeyAdd (str) { keyParts.push(str); var i = str.length; - while(i) { + while (i) { hash = (hash * 33) ^ str.charCodeAt(--i); } } - //cacheKey_add() - this.emit('buildCacheKey', { context: lassoContext, config: this.config, lasso: this, cacheKey: { - add: cacheKey_add + add: cacheKeyAdd } }); var flags = lassoContext.flags; if (flags && !flags.isEmpty()) { - cacheKey_add('flags:' + flags.getKey()); + cacheKeyAdd('flags:' + flags.getKey()); } - cacheKey_add('config:' + lassoContext.config.getConfigFingerprint()); + cacheKeyAdd('config:' + lassoContext.config.getConfigFingerprint()); if (hash < 0) { hash = 0 - hash; @@ -672,11 +622,11 @@ Lasso.prototype = { cache = this.lassoCacheLookup[key]; if (!cache) { cache = this.lassoCacheLookup[key] = new LassoCache(key, { - dir: config.getCacheDir(), - keyParts: keyInfo.parts, - profile: config.getCacheProfile(), - profiles: config.getCacheProfiles() - }); + dir: config.getCacheDir(), + keyParts: keyInfo.parts, + profile: config.getCacheProfile(), + profiles: config.getCacheProfiles() + }); var pluginContext = { context: lassoContext, @@ -684,7 +634,7 @@ Lasso.prototype = { options: lassoContext.options, lasso: this, cacheKey: key, - lassoCache: cache, + lassoCache: cache }; this.emit('lassoCacheCreated', pluginContext); @@ -725,7 +675,6 @@ Lasso.prototype = { return flagSet; }, - /** * A LassoContext is created for each call to Lasso::lassoPage * The LassoContext contains the following: @@ -760,61 +709,31 @@ Lasso.prototype = { return lassoContext; }, - lassoPage: function(options, callback) { - var lassoContext = options.lassoContext || this.createLassoContext(options); + async lassoPage (options) { + const lassoContext = options.lassoContext || this.createLassoContext(options); - var promise; - - if (!callback) { - promise = new Promise((resolve, reject) => { - callback = function(err, lassoPageResult) { - if (err) { - return reject(err); - } - resolve(lassoPageResult); - }; - }); + if (options.cache === false) { + return doLassoPage(this, options, lassoContext); } - var done = (e, lassoPageResult) => { + const lassoCache = this.getLassoCache(lassoContext); + const cacheKey = options.cacheKey || options.pageName || options.name; - if (e) { - return callback(e); + const lassoPageResult = await lassoCache.getLassoPageResult(cacheKey, { + builder: async () => { + // Reuse the same lasso context + options = extend({ lassoContext }, options); + return doLassoPage(this, options, lassoContext); } + }); - this.emit('afterLassoPage', { - context: lassoContext, - lasso: this, - result: lassoPageResult - }); - - callback(null, lassoPageResult); - }; - - if (options.cache !== false) { - var lassoCache = this.getLassoCache(lassoContext); - var cacheKey = options.cacheKey || options.pageName || options.name; - - lassoCache.getLassoPageResult( - cacheKey, - { - builder: (callback) => { - options = extend({}, options); - - // Reuse the same lasso context - options.lassoContext = lassoContext; - - doLassoPage(this, options, lassoContext, callback); - } - }, - done); - - - } else { - doLassoPage(this, options, lassoContext, done); - } + this.emit('afterLassoPage', { + context: lassoContext, + lasso: this, + result: lassoPageResult + }); - return promise; + return lassoPageResult; }, /** @@ -822,39 +741,32 @@ Lasso.prototype = { * * @param {String} path The file path of the resource to bundle * @param {Object} options (see below for supported options) - * @param {Function(err, result)} callback Callback function. Result will be an object with a "url" property * - * TODO Also return a promise here */ - lassoResource: function(path, options, callback) { - var lassoContext; + async lassoResource (path, options) { + let lassoContext; + options = options || {}; - if (typeof options === 'function') { - callback = options; - options = {}; - } else if (options.LassoContext === true ){ + if (options.LassoContext === true) { lassoContext = options; options = {}; - } else if (!options) { - options = {}; } if (!lassoContext) { lassoContext = options.lassoContext || this.createLassoContext(options); } - var lassoPageResult = lassoContext.lassoPageResult; - if (lassoPageResult) { - let originalCallback = callback; - callback = function(err, result) { - if (result) { - lassoPageResult.registerResource(result); - } + const lassoPageResult = lassoContext.lassoPageResult; - originalCallback(err, result); - }; + function done (result) { + if (lassoPageResult && result) { + lassoPageResult.registerResource(result); + } + + return result; } - var _this = this; + + let lassoResourceResult; if (options.cache !== false) { var cache = this.getLassoCache(lassoContext); @@ -865,22 +777,20 @@ Lasso.prototype = { } var writer = this.writer; - var buildResourceCacheKey = writer.buildResourceCacheKey; if (buildResourceCacheKey) { cacheKey = buildResourceCacheKey.call(writer, cacheKey, lassoContext); } - cache.getLassoedResource( - cacheKey, - function(callback) { - doLassoResource(_this, path, options, lassoContext, callback); - }, - callback); + lassoResourceResult = await cache.getLassoedResource(cacheKey, async () => { + return doLassoResource(this, path, options, lassoContext); + }); } else { - doLassoResource(_this, path, options, lassoContext, callback); + lassoResourceResult = await doLassoResource(this, path, options, lassoContext); } + + return done(lassoResourceResult); }, addTransform: function(transform) { @@ -897,7 +807,6 @@ Lasso.prototype.optimizePage = Lasso.prototype.lassoPage; // TODO: Deprecate this Lasso.prototype.optimizeResource = Lasso.prototype.lassoResource; - raptorUtil.inherit(Lasso, EventEmitter); module.exports = Lasso; diff --git a/lib/LassoCache.js b/lib/LassoCache.js index 7ba759dc..3190639d 100644 --- a/lib/LassoCache.js +++ b/lib/LassoCache.js @@ -142,30 +142,27 @@ LassoCache.prototype = { return this.syncCaches[name] || (this.syncCaches[name] = new SyncCache()); }, - flushAll: function() { - raptorCache.flushAll(); + async flushAll () { + return raptorCache.flushAll(); }, - getLassoPageResult: function(cacheKey, options, callback) { - return this.lassoPageResultCache.get(cacheKey, options, callback); + async getLassoPageResult(cacheKey, options) { + return this.lassoPageResultCache.get(cacheKey, options); }, - getBundleMappings: function(id, builder, callback) { - return this.bundleMappingsCache.get(id.toString(), builder, callback); + async getBundleMappings (id, builder) { + return this.bundleMappingsCache.get(id.toString(), { builder }); }, - getLassoedResource: function(path, builder, callback) { - return this.lassoedResourcesCache.get(path, builder, callback); + async getLassoedResource (path, builder) { + return this.lassoedResourcesCache.get(path, { builder }); }, - getDependencyFingerprint: function(cacheKey, lastModified, builder, callback) { - this.dependencyFingerprintsCache.get( - cacheKey, - { - lastModified: lastModified, - builder: builder - }, - callback); + async getDependencyFingerprint (cacheKey, lastModified, builder) { + return this.dependencyFingerprintsCache.get(cacheKey, { + lastModified, + builder + }); } }; diff --git a/lib/LassoContext.js b/lib/LassoContext.js index dd784122..3bf78f0d 100644 --- a/lib/LassoContext.js +++ b/lib/LassoContext.js @@ -51,21 +51,9 @@ class LassoContext extends EventEmitter { this.data[name] = value; } - getFileLastModified(filePath, callback) { - if (typeof callback === 'function') { - lastModified.forFile(filePath, callback); - } else { - return new Promise((resolve, reject) => { - lastModified.forFile(filePath, (err, lastModified) => { - if (err) { - reject(err); - } else { - resolve(lastModified || -1); - } - }); - }); - } - + async getFileLastModified (filePath) { + const lastModifiedResult = await lastModified.forFile(filePath); + return lastModifiedResult || -1; } setPhase(phaseName) { diff --git a/lib/LassoManifest.js b/lib/LassoManifest.js index 9dc38548..b7bb1f84 100644 --- a/lib/LassoManifest.js +++ b/lib/LassoManifest.js @@ -118,17 +118,9 @@ LassoManifest.prototype = { * @param options * @returns */ - getDependencies: function(options, callback) { + async getDependencies (options) { logger.debug('getDependencies()'); - if (typeof options === 'function') { - callback = options; - options = {}; - } - - - ok(typeof callback === 'function', 'callback function expected'); - var flags = options && options.flags; if (!flags || !flags.__FlagSet) { flags = new FlagSet(flags); @@ -136,19 +128,12 @@ LassoManifest.prototype = { logger.debug('getDependencies() Normalizing dependencies BEGIN: ', this.dependencies); - this.dependencies.normalize(function(err, dependencies) { - - logger.debug('getDependencies() Normalizing dependencies DONE: ', this.dependencies); - if (err) { - return callback(err); - } - - callback(null, dependencies); - }); + const dependencies = await this.dependencies.normalize(); + logger.debug('getDependencies() Normalizing dependencies DONE: ', this.dependencies); + return dependencies; }, getRequireRemap: function(lassoContext) { - if (this.requireRemap && Array.isArray(this.requireRemap)) { var filteredRemaps = {}; var flags = lassoContext.flags; @@ -173,4 +158,4 @@ LassoManifest.isLassoManifest = function(o) { return o && o.__LassoManifest; }; -module.exports = LassoManifest; \ No newline at end of file +module.exports = LassoManifest; diff --git a/lib/LassoPageResult.js b/lib/LassoPageResult.js index 1db9fef4..9f0ac981 100644 --- a/lib/LassoPageResult.js +++ b/lib/LassoPageResult.js @@ -302,4 +302,4 @@ LassoPageResult.prototype = { } }; -module.exports = LassoPageResult; \ No newline at end of file +module.exports = LassoPageResult; diff --git a/lib/bundle-builder.js b/lib/bundle-builder.js index 4a75f5e9..1c247e8c 100644 --- a/lib/bundle-builder.js +++ b/lib/bundle-builder.js @@ -1,10 +1,8 @@ var dependencyWalker = require('./dependency-walker'); var DependencyTree = require('./DependencyTree'); var logger = require('raptor-logging').logger(module); -var series = require('raptor-async/series'); var lassoPackageRoot = require('lasso-package-root'); var nodePath = require('path'); -var ok = require('assert').ok; var recurseHandlers = { none: function(rootDependency, lassoContext) { @@ -20,7 +18,6 @@ var recurseHandlers = { }, all: function(rootDependency, lassoContext) { - return { shouldIncludeDependency: function(dependency) { return true; @@ -33,7 +30,6 @@ var recurseHandlers = { }, dir: function(rootDependency, lassoContext) { - var baseDir = rootDependency.getDir(lassoContext) || ''; return { @@ -53,7 +49,6 @@ var recurseHandlers = { }, dirtree: function(rootDependency, lassoContext) { - var baseDir = rootDependency.getDir(lassoContext); function checkDir(dependency) { @@ -115,13 +110,31 @@ var recurseHandlers = { } }; -function buildBundle(bundleMappings, dependencyRegistry, bundleConfig, lassoContext, callback) { - ok(typeof callback === 'function', 'callback function is required'); +function shouldIncludeDependency (lassoContext, rootDependency, recurseHandler, dependency) { + if (dependency === rootDependency || + (lassoContext.parentDependency && lassoContext.parentDependency === rootDependency)) { + // Always include the root dependency or any child dependencies if the top-level + // dependency was a package + return true; + } + + return recurseHandler.shouldIncludeDependency(dependency); +} + +function shouldRecurseIntoPackageDependency (rootDependency, recurseHandler, dependency) { + if (dependency === rootDependency) { + // Always recurse into top-level package dependencies + return true; + } + + return recurseHandler.shouldRecurseIntoPackageDependency(dependency); +} +async function buildBundle(bundleMappings, dependencyRegistry, bundleConfig, lassoContext) { var tree = logger.isDebugEnabled() ? new DependencyTree() : null; var flags = lassoContext.flags; - var dependencies = bundleConfig.getDependencies(dependencyRegistry); + var bundleDependencies = bundleConfig.getDependencies(dependencyRegistry); var targetBundleName = bundleConfig.name; // Each bundle should have its own phase data. Phase data is just a bucket of data that can @@ -129,122 +142,85 @@ function buildBundle(bundleMappings, dependencyRegistry, bundleConfig, lassoCont // of optimization. lassoContext.setPhase('app-bundle-mappings'); - dependencies.normalize(function(err, dependencies) { - var asyncTasks = dependencies.map(function(rootDependency) { - return function(callback) { - rootDependency.init(lassoContext, function(err) { - logger.debug('Root init'); + let dependencies = await bundleDependencies.normalize(); - if (err) { - return callback(err); - } + for (const rootDependency of dependencies) { + await rootDependency.init(lassoContext); - var recurseInto = rootDependency._recurseInto || bundleConfig.getRecurseInto(); + logger.debug('Root init'); - if (!recurseInto) { - if (rootDependency.getDir()) { - recurseInto = 'dirtree'; - } else { - recurseInto = 'all'; - } + var recurseInto = rootDependency._recurseInto || bundleConfig.getRecurseInto(); - } + if (!recurseInto) { + if (rootDependency.getDir()) { + recurseInto = 'dirtree'; + } else { + recurseInto = 'all'; + } + } - if (!recurseHandlers[recurseInto]) { - throw new Error('Invalid recursion option: ' + recurseInto); - } + if (!recurseHandlers[recurseInto]) { + throw new Error('Invalid recursion option: ' + recurseInto); + } - var recurseHandler = recurseHandlers[recurseInto](rootDependency, lassoContext); + var recurseHandler = recurseHandlers[recurseInto](rootDependency, lassoContext); - function shouldIncludeDependency(dependency) { - if (dependency === rootDependency || - (lassoContext.parentDependency && lassoContext.parentDependency === rootDependency)) { - // Always include the root dependency or any child dependencies if the top-level - // dependency was a package - return true; - } + await dependencyWalker.walk({ + lassoContext: lassoContext, + dependency: rootDependency, + flags: flags, + shouldSkipDependency (dependency) { + if (dependency.isPageBundleOnlyDependency()) { + return true; + } - return recurseHandler.shouldIncludeDependency(dependency); - } + if (bundleMappings.getBundleForDependency(dependency)) { + // The dependency has already been added to another bundle + return true; + } + + if (dependency.isPackageDependency()) { + return !shouldRecurseIntoPackageDependency(rootDependency, recurseHandler, dependency); + } else if (!dependency.read) { + // ignore non-readable dependencies during bundling phase + return true; + } - function shouldRecurseIntoPackageDependency(dependency) { - if (dependency === rootDependency) { - // Always recurse into top-level package dependencies - return true; + return false; + }, + on: { + dependency (dependency, context) { + logger.debug(module.id, 'on dependency: ' + dependency.type); + + if (dependency.isPackageDependency()) { + if (tree) { + tree.add(dependency, context.parentDependency); } - return recurseHandler.shouldRecurseIntoPackageDependency(dependency); + // We are only interested in non-package dependencies + return; } - dependencyWalker.walk({ - lassoContext: lassoContext, - dependency: rootDependency, - flags: flags, - shouldSkipDependency: function(dependency) { - if (dependency.isPageBundleOnlyDependency()) { - return true; - } - - if (bundleMappings.getBundleForDependency(dependency)) { - // The dependency has already been added to another bundle - return true; - } - - if (dependency.isPackageDependency()) { - return !shouldRecurseIntoPackageDependency(dependency); - } else if (!dependency.read) { - // ignore non-readable dependencies during bundling phase - return true; - } - - return false; - }, - on: { - dependency: function(dependency, context) { - - logger.debug(module.id, 'on dependency: ' + dependency.type); - - if (dependency.isPackageDependency()) { - if (tree) { - tree.add(dependency, context.parentDependency); - } - - // We are only interested in non-package dependencies - return; - } - - if (shouldIncludeDependency(dependency)) { - bundleMappings.addDependencyToBundle( - dependency, - targetBundleName, - context.slot, - bundleConfig, - lassoContext); - - if (tree) { - tree.add(dependency, context.parentDependency); - } - - } - } - } - }, callback); - }); - }; - }); + if (shouldIncludeDependency(lassoContext, rootDependency, recurseHandler, dependency)) { + bundleMappings.addDependencyToBundle( + dependency, + targetBundleName, + context.slot, + bundleConfig, + lassoContext); - series(asyncTasks, function(err) { - if (err) { - return callback(err); - } - - if (tree) { - logger.debug('Bundle "' + targetBundleName + '":\n' + tree.toString()); + if (tree) { + tree.add(dependency, context.parentDependency); + } + } + } } - - callback(); }); - }); + } + + if (tree) { + logger.debug('Bundle "' + targetBundleName + '":\n' + tree.toString()); + } } exports.buildBundle = buildBundle; diff --git a/lib/dependencies/Dependency.js b/lib/dependencies/Dependency.js index 8b3c6c83..2bd8daf4 100644 --- a/lib/dependencies/Dependency.js +++ b/lib/dependencies/Dependency.js @@ -28,6 +28,41 @@ function getPackagePath(d) { return d.__filename ? d.__filename : '(unknown)'; } +function doCalculateFingerprint (dependency, lassoContext) { + return new Promise((resolve, reject) => { + var input = dependency.read(lassoContext); + var cachingReadStream = util.createCachingStream(); + + var fingerprintStream = util.createFingerprintStream() + .on('error', reject) + .on('fingerprint', function(fingerprint) { + dependency._cachingReadStream = cachingReadStream; + if (logger.isDebugEnabled()) { + logger.debug('Dependency ' + dependency.toString() + ' fingerprint key: ' + fingerprint); + } + resolve(fingerprint); + }); + + // Don't buffer the data so that the stream can be drained + fingerprintStream.resume(); + + input + .on('error', function(e) { + var message = 'Unable to read dependency "' + dependency + '" referenced in "' + dependency.getParentManifestPath() + '". '; + if (e.code === 'ENOENT' && e.path) { + message += 'File does not exist: ' + e.path; + } else { + message += 'Error: ' + (e.stack || e); + } + e = new Error(message); + e.dependency = dependency; + reject(e); + }) + .pipe(cachingReadStream) + .pipe(fingerprintStream); + }); +}; + // This is a simple stream implementation that either has code available // immediately or it is waiting for code to be made available upon // callback completion @@ -48,7 +83,7 @@ function Dependency(dependencyConfig, dirname, filename) { ok(dirname, '"dirname" is a required argument'); equal(typeof dirname, 'string', '"dirname" should be a string'); - this._initAsyncValue = undefined; + this._resolvedInit = undefined; this._keyAsyncValue = undefined; this._lastModifiedAsyncValue = undefined; this._cachingReadStream = undefined; @@ -78,6 +113,7 @@ Dependency.prototype = { 'slot': 'string', 'css-slot': 'string', 'js-slot': 'string', + // TODO: Change: Should these be removed? 'if': 'string', 'if-extension': 'string', /* DEPRECRATED */ 'if-not-extension': 'string', /* DEPRECRATED */ @@ -86,48 +122,18 @@ Dependency.prototype = { 'getDefaultBundleName': 'function' }, - init: function(lassoContext, callback) { + async init (lassoContext) { this._context = lassoContext; - equal(typeof callback, 'function', 'callback function is required'); - if (this._initAsyncValue) { - return this._initAsyncValue.done(callback); + if (this._resolvedInit) { + return; } - var initAsyncValue = this._initAsyncValue = new AsyncValue(); - this._initAsyncValue.done(callback); - - if (this.doInit.length === 2) { - // Callback-style init() - // doInit(lassoContext, callback) - this.doInit(lassoContext, function(err) { - if (err) { - initAsyncValue.reject(err); - } else { - initAsyncValue.resolve(); - } - }); - - } else { - // doInit(lassoContext) - var promise = this.doInit(lassoContext); - if (promise) { - promise - .then(() => { - initAsyncValue.resolve(); - }) - .catch((err) => { - initAsyncValue.reject(err); - }); - } else { - initAsyncValue.resolve(); - } - } + await this.doInit(lassoContext); + this._resolvedInit = true; }, - doInit: function(lassoContext, callback) { - callback(); - }, + async doInit (lassoContext) {}, createReadStream: function(lassoContext) { if (this._cachingReadStream) { @@ -146,7 +152,6 @@ Dependency.prototype = { }, set: function(props) { - var propertyTypes = this.properties; for (var k in props) { @@ -245,108 +250,65 @@ Dependency.prototype = { // subclasses can override }, - getPackageManifest: function(lassoContext, callback) { + async getPackageManifest (lassoContext) { if (!this.isPackageDependency()) { throw new Error('getPackageManifest() failed. Dependency is not a package: ' + this.toString()); } - if (this._manifestAsyncValue) { - this._manifestAsyncValue.done(callback); - return; - } - - var _this = this; - - var manifestAsyncValue; - this._manifestAsyncValue = manifestAsyncValue = new AsyncValue(); - manifestAsyncValue.done(callback); + let manifest; if (typeof this.loadPackageManifest === 'function') { - this.loadPackageManifest(lassoContext, function(err, result) { - if (err) { - return manifestAsyncValue.reject(err); - } + let packageManifestResult; + packageManifestResult = await this.loadPackageManifest(lassoContext); - if (!result) { - return manifestAsyncValue.resolve(null); - } + if (!packageManifestResult) { + return null; + } - var dependencyRegistry = _this.__dependencyRegistry; - var LassoManifest = require('../LassoManifest'); - var manifest; - - if (typeof result === 'string') { - var manifestPath = result; - var from = _this.getParentManifestDir(); - - try { - manifest = _this.createPackageManifest(manifestLoader.load(manifestPath, from)); - } catch(e) { - var err2; - if (e.fileNotFound) { - err2 = new Error('Lasso manifest not found for path "' + - manifestPath + '" (searching from "' + from + '"). Dependency: ' + - this.toString()); - } else { - err2 = new Error('Unable to load lasso manifest for path "' + - manifestPath + '". Dependency: ' + _this.toString() + '. Exception: ' + - (e.stack || e)); - } - manifestAsyncValue.reject(err2); + var dependencyRegistry = this.__dependencyRegistry; + var LassoManifest = require('../LassoManifest'); + + if (typeof packageManifestResult === 'string') { + var manifestPath = packageManifestResult; + var from = this.getParentManifestDir(); + + try { + manifest = this.createPackageManifest(manifestLoader.load(manifestPath, from)); + } catch (e) { + var err; + if (e.fileNotFound) { + err = new Error('Lasso manifest not found for path "' + + manifestPath + '" (searching from "' + from + '"). Dependency: ' + + this.toString()); + } else { + err = new Error('Unable to load lasso manifest for path "' + + manifestPath + '". Dependency: ' + this.toString() + '. Exception: ' + + (e.stack || e)); } - } else if (!LassoManifest.isLassoManifest(result)) { - manifest = new LassoManifest({ - manifest: result, - dependencyRegistry: dependencyRegistry, - dirname: _this.getParentManifestDir(), - filename: _this.getParentManifestPath() - }); - } else { - manifest = result; - } - - manifestAsyncValue.resolve(manifest); - }); - } else if (typeof this.getDependencies === 'function') { - - let getDependenciesCallback = (err, dependencies) => { - // console.log('----'); - // console.log('DEPENDENCIES FOR:', this); - // console.log(module.id, 'getDependenciesCallback - DEPENDENCIES:', dependencies); - // console.log('----'); - if (err) { - return manifestAsyncValue.reject(err); - } - - var manifest = null; - if (dependencies) { - try { - manifest = _this.createPackageManifest(dependencies); - } catch(err) { - return manifestAsyncValue.reject(err); - } + throw err; } - - manifestAsyncValue.resolve(manifest); - }; - - let dependenciesPromise = this.getDependencies(lassoContext, getDependenciesCallback); - - if (dependenciesPromise) { - Promise.resolve(dependenciesPromise) - .then((dependencies) => { - process.nextTick(() => { - getDependenciesCallback(null, dependencies); - }); - }) - .catch(getDependenciesCallback); + } else if (!LassoManifest.isLassoManifest(packageManifestResult)) { + manifest = new LassoManifest({ + manifest: packageManifestResult, + dependencyRegistry: dependencyRegistry, + dirname: this.getParentManifestDir(), + filename: this.getParentManifestPath() + }); + } else { + manifest = packageManifestResult; } + return manifest; + } else if (typeof this.getDependencies === 'function') { + let dependencies = await this.getDependencies(lassoContext); + if (dependencies) { + manifest = this.createPackageManifest(dependencies); + } + return manifest; } else { - var err = new Error('getPackageManifest() failed. "getDependencies" or "loadPackageManifest" expected: ' + this.toString()); - manifestAsyncValue.reject(err); + throw new Error('getPackageManifest() failed. "getDependencies" or "loadPackageManifest" expected: ' + this.toString()); } }, @@ -385,128 +347,78 @@ Dependency.prototype = { * getReadCacheKey() must be a unique key across all lasso context since * it is flattened to single level and shared by multiple lasso instances. */ - calculateKey: function(lassoContext, callback) { - ok(typeof callback === 'function', 'callback is required'); - - var self = this; - - if (this._key !== undefined) { - return callback(null, this._key); - } - - if (this._keyAsyncValue) { - // Attach a listener to the current in-progres check - return this._keyAsyncValue.done(callback); - } + async calculateKey (lassoContext) { + // TODO: Change to fully use async/await + return new Promise((resolve, reject) => { + function callback (err, res) { + return err ? reject(err) : resolve(res); + } - // no data holder so let's create one - var keyAsyncValue; - this._keyAsyncValue = keyAsyncValue = new AsyncValue(); - this._keyAsyncValue.done(callback); - - function handleKey(key) { - if (key === null) { - key = self.type + '|' + lassoContext.uniqueId(); - } else if (typeof key !== 'string') { - keyAsyncValue.reject(new Error('Invalid key: ' + key)); - return; + if (this._key !== undefined) { + return callback(null, this._key); } - if (logger.isDebugEnabled()) { - logger.debug('Calculated key for ' + self.toString() + ': ' + key); + if (this._keyAsyncValue) { + // Attach a listener to the current in-progres check + return this._keyAsyncValue.done(callback); } - // Store resolve key in "_key" for quick lookup - self._key = key; - keyAsyncValue.resolve(key); - } + // no data holder so let's create one + var keyAsyncValue; + this._keyAsyncValue = keyAsyncValue = new AsyncValue(); + this._keyAsyncValue.done(callback); + + let handleKey = (key) => { + if (key === null) { + key = this.type + '|' + lassoContext.uniqueId(); + } else if (typeof key !== 'string') { + keyAsyncValue.reject(new Error('Invalid key: ' + key)); + return; + } - var key = this.doCalculateKey(lassoContext, function(err, key) { - if (err) { - keyAsyncValue.reject(err); - return; - } + if (logger.isDebugEnabled()) { + logger.debug('Calculated key for ' + this.toString() + ': ' + key); + } - handleKey(key); - }); + // Store resolve key in "_key" for quick lookup + this._key = key; + keyAsyncValue.resolve(key); + }; - // if doCalculateKey returned value synchronously and did not - // call the callback then resolve key - if ((key !== undefined) && !keyAsyncValue.isSettled()) { - handleKey(key); - } + this.doCalculateKey(lassoContext) + .then((key) => { + handleKey(key); + }) + .catch((err) => { + keyAsyncValue.reject(err); + }); + }); }, - - doCalculateKey: function(lassoContext, callback) { + async doCalculateKey (lassoContext) { if (this.isPackageDependency()) { - callback(null, this.calculateKeyFromProps()); + return this.calculateKeyFromProps(); } else if (this.isExternalResource()) { - var url = this.getUrl ? this.getUrl(lassoContext) : this.url; - callback(null, url); + const url = this.getUrl ? this.getUrl(lassoContext) : this.url; + return url; } else { - var _this = this; - - var doCalculateFingerprint = function(callback) { - var input = _this.read(lassoContext); - var cachingReadStream = util.createCachingStream(); - - var fingerprintStream = util.createFingerprintStream() - .on('error', callback) - .on('fingerprint', function(fingerprint) { - _this._cachingReadStream = cachingReadStream; - if (logger.isDebugEnabled()) { - logger.debug('Dependency ' + _this.toString() + ' fingerprint key: ' + fingerprint); - } - callback(null, fingerprint); - }); - - // Don't buffer the data so that the stream can be drained - fingerprintStream.resume(); - - input - .on('error', function(e) { - var message = 'Unable to read dependency "' + _this + '" referenced in "' + _this.getParentManifestPath() + '". '; - if (e.code === 'ENOENT' && e.path) { - message += 'File does not exist: ' + e.path; - } else { - message += 'Error: ' + (e.stack || e); - } - e = new Error(message); - e.dependency = _this; - callback(e); - }) - .pipe(cachingReadStream) - .pipe(fingerprintStream); - }; - if (lassoContext.cache) { - this.getLastModified(lassoContext, function(err, lastModified) { - - if (err) { - return callback(err); - } - - if (!lastModified) { - doCalculateFingerprint(callback); - return; - } - - lassoContext.cache.getDependencyFingerprint( - // cache key - _this.getPropsKey(), - - // last modified timestamp (if cache entry is older than this then builder will be called) - lastModified, - - // builder - doCalculateFingerprint, + return this.getLastModified(lassoContext) + .then((lastModified) => { + if (!lastModified) { + return doCalculateFingerprint(this, lassoContext); + } - // callback when fingerprint is found - callback); - }); + return lassoContext.cache.getDependencyFingerprint( + // cache key + this.getPropsKey(), + // last modified timestamp (if cache entry is older than this then builder will be called) + lastModified, + // builder + doCalculateFingerprint.bind(null, this, lassoContext)); + }); } else { - doCalculateFingerprint(callback); + return doCalculateFingerprint(this, lassoContext); } } }, @@ -574,44 +486,31 @@ Dependency.prototype = { return this['css-slot'] || this.slot; }, - getLastModified: function(lassoContext, callback) { - ok(typeof callback === 'function', 'callback is required'); - - if (this._lastModifiedAsyncValue) { - // Attach a listener to the current in-progres check - return this._lastModifiedAsyncValue.done(callback); + async getLastModified (lassoContext) { + if (this._lastModifiedValue) { + return this._lastModifiedValue; } - var lastModifiedAsyncValue = this._lastModifiedAsyncValue = new AsyncValue(); - lastModifiedAsyncValue.done(callback); + const getLastModified = (lastModified) => + lastModified == null || lastModified < 0 ? 0 : lastModified; - var lastModified = this.doGetLastModified(lassoContext, function(err, lastModified) { - if (err) { - lastModifiedAsyncValue.reject(err); - } else { - lastModifiedAsyncValue.resolve(lastModified == null || lastModified < 0 ? 0 : lastModified); - } - }); + const lastModified = this._lastModifiedValue = + getLastModified(await this.doGetLastModified(lassoContext)); - if ((lastModified !== undefined) && !lastModifiedAsyncValue.isSettled()) { - // if doGetLastModified returned value synchronously and did not - // call the callback then resolve key - lastModifiedAsyncValue.resolve(lastModified == null || lastModified < 0 ? 0 : lastModified); - } + return lastModified; }, - doGetLastModified: function(lassoContext, callback) { - var sourceFile = this.getSourceFile(); + async doGetLastModified (lassoContext, callback) { + const sourceFile = this.getSourceFile(); if (sourceFile) { - this.getFileLastModified(sourceFile, callback); - return; + return this.getFileLastModified(sourceFile); } else { - callback(null, 0); + return 0; } }, - getFileLastModified: function(path, callback) { - lastModified.forFile(path, callback); + async getFileLastModified (path) { + return lastModified.forFile(path); }, createPackageManifest: function(manifest, dirname, filename) { diff --git a/lib/dependencies/DependencyRegistry.js b/lib/dependencies/DependencyRegistry.js index 82fe3a27..21268d35 100644 --- a/lib/dependencies/DependencyRegistry.js +++ b/lib/dependencies/DependencyRegistry.js @@ -17,7 +17,6 @@ var logger = require('raptor-logging').logger(module); var slice = Array.prototype.slice; function createDefaultNormalizer(registry) { - function parsePath(path) { var typePathMatches = typePathRegExp.exec(path); if (typePathMatches) { @@ -190,7 +189,6 @@ DependencyRegistry.prototype = { }; } - var _this = this; function Ctor(dependencyConfig, dirname, filename) { @@ -252,8 +250,6 @@ DependencyRegistry.prototype = { equal(typeof type, 'string', '"type" should be a string'); equal(typeof options, 'object', '"options" should be a object'); - - var userRead = options.read; var userCreateReadStream = options.createReadStream; var userGetLastModified = options.getLastModified; @@ -275,7 +271,7 @@ DependencyRegistry.prototype = { } if (userGetLastModified) { - extensionOptions.getLastModified = function(path, lassoContext, callback) { + extensionOptions.getLastModified = async function (path, lassoContext) { // Chop off the first path argument return userGetLastModified.apply(this, slice.call(arguments, 1)); }; @@ -286,20 +282,20 @@ DependencyRegistry.prototype = { properties: { path: 'string' }, - init(lassoContext) { + async init(lassoContext) { this.path = this.resolvePath(this.path); }, getSourceFile() { return this.path; }, - getDependencies(lassoContext, callback) { + async getDependencies (lassoContext) { var path = this.path; - callback(null, [ + return [ { type: 'require', - path: path, + path: path } - ]); + ]; } }); }, @@ -407,17 +403,15 @@ DependencyRegistry.prototype = { return new Ctor(config, dirname, filename); }, - normalizeDependencies: function(dependencies, dirname, filename, callback) { - ok(typeof callback === 'function', 'callback function expected '); - + async normalizeDependencies (dependencies, dirname, filename) { logger.debug('normalizeDependencies() BEGIN: ', dependencies, 'count:', dependencies.length); if (dependencies.length === 0) { - return callback(null, dependencies); + return dependencies; } - var i=0; - var j=0; + var i = 0; + var j = 0; dependencies = dependencies.concat([]); @@ -429,56 +423,43 @@ DependencyRegistry.prototype = { filename: filename }; - var handleNormalizedDependency = (normalizedDependency) => { + function handleNormalizedDependency (dependencies, i, normalizedDependency) { if (normalizedDependency) { if (Array.isArray(normalizedDependency)) { - dependencies.splice.apply(dependencies, [i, 1 /* remove one */].concat(normalizedDependency)); - j=0; + // Remove one + dependencies.splice.apply(dependencies, [i, 1].concat(normalizedDependency)); + j = 0; // Continue at the same dependency index, but restart normalizing at the beginning - return; + return null; } else { dependencies[i] = normalizedDependency; - } } j++; - return normalizedDependency; }; - var go; - - var asyncNormalizeCallback = (err, d) => { - if (err) { - return callback(err); - } - handleNormalizedDependency(d); - go(); - }; - - go = () => { - while(i { + while (i < dependencies.length) { let dependency = dependencies[i]; if (!dependency.__Dependency) { - while(j { - var userPromise = userGetDependencies.call(this.userThisObject, lassoContext, (err, dependencies) => { - if (err) { - reject(err); - } else { - resolve(dependencies); - } - }); - - if (userPromise !== undefined) { - resolve(userPromise); - } - }); + return userGetDependencies.call(this.userThisObject, lassoContext); } getDefaultBundleName(pageBundleName, lassoContext) { @@ -143,4 +131,4 @@ class RequireHandler { } } -module.exports = RequireHandler; \ No newline at end of file +module.exports = RequireHandler; diff --git a/lib/dependencies/dependency-comment.js b/lib/dependencies/dependency-comment.js index 5ed1a985..d9758e24 100644 --- a/lib/dependencies/dependency-comment.js +++ b/lib/dependencies/dependency-comment.js @@ -11,7 +11,7 @@ module.exports = { return null; }, - calculateKey: function() { + async calculateKey () { return 'comment'; } -}; \ No newline at end of file +}; diff --git a/lib/dependencies/dependency-dependencies.js b/lib/dependencies/dependency-dependencies.js index 6f400918..c2fdc38c 100644 --- a/lib/dependencies/dependency-dependencies.js +++ b/lib/dependencies/dependency-dependencies.js @@ -3,14 +3,13 @@ module.exports = { dependencies: 'array' }, - init: function(lassoContext) { - }, + async init (lassoContext) {}, - getDependencies: function(lassoContext, callback) { - callback(null, this.dependencies || []); + async getDependencies (lassoContext) { + return this.dependencies || []; }, - calculateKey: function() { + async calculateKey () { return null; // A just use a unique ID for this dependency } }; diff --git a/lib/dependencies/dependency-intersection.js b/lib/dependencies/dependency-intersection.js index 242e8cf6..04988a6a 100644 --- a/lib/dependencies/dependency-intersection.js +++ b/lib/dependencies/dependency-intersection.js @@ -1,18 +1,42 @@ -'use strict'; - var dependencyWalker = require('../dependency-walker'); -var series = require('raptor-async/series'); var DependencyList = require('../DependencyList'); var thresholdRegex = /^(\d+)([%]*)$/; +function onDependency (tracking, strictIntersection, firstSet, i) { + return function (dependency, context) { + if (dependency.isPackageDependency()) { + return; + } + + var key = dependency.getKey(); + + var info = tracking[key]; + if (info === undefined) { + tracking[key] = { + dependency: dependency, + count: 1 + }; + } else { + info.count++; + } + + if ((i === 0) && strictIntersection) { + // strict intersection so only need to keep track + // dependencies from first set (which is a little + // arbitrary but will work) + firstSet.push(dependency); + } + }; +} + module.exports = { properties: { dependencies: 'array', threshold: 'object' }, - init: function(lassoContext) { + async init (lassoContext) { if (!this.dependencies) { throw new Error('"dependencies" property is required'); } @@ -52,126 +76,87 @@ module.exports = { return null; }, - getDependencies: function(lassoContext, callback) { - var self = this; + async getDependencies (lassoContext) { var tracking = {}; var flags = lassoContext.flags; var firstSet = []; - this.dependencies.normalize(function(err, dependencies) { - if (err) { - return callback(err); - } + let dependencies = await this.dependencies.normalize(); - var numDependencies = dependencies.length; - var thresholdValue; - if (self.threshold) { - thresholdValue = self.threshold.value; - if (self.threshold.units === '%') { - // A dependency will become part of the intersection if it is in at X percent of the enumerated list of dependencies - thresholdValue = thresholdValue / 100 * numDependencies; - } else { - // A dependency will become part of the intersection if it is in at least X of the enumerated list of dependencies - thresholdValue = self.threshold.value; - } + var numDependencies = dependencies.length; + var thresholdValue; + if (this.threshold) { + thresholdValue = this.threshold.value; + if (this.threshold.units === '%') { + // A dependency will become part of the intersection if it is in at X percent of the enumerated list of dependencies + thresholdValue = thresholdValue / 100 * numDependencies; } else { - // strict intersection -- only include the dependencies that are in the enumerated list of dependencies - thresholdValue = numDependencies; + // A dependency will become part of the intersection if it is in at least X of the enumerated list of dependencies + thresholdValue = this.threshold.value; } + } else { + // strict intersection -- only include the dependencies that are in the enumerated list of dependencies + thresholdValue = numDependencies; + } - var strictIntersection = (thresholdValue >= numDependencies); - - var asyncTasks = dependencies.map(function(dependency, i) { - return function(callback) { - // HACK: The built-in `dep-require` dependency type - // uses its `Deduper` instance to ignore dependencies - // within the same "phase" of a lasso operation. - // - // However, for the purposes of calculating intersection - // we should not de-duplicate across each "walk" of - // starting dependency. - // - // The `Deduper` stores a cache of "visited" dependencies in - // `lassoContext.phaseData['dependency-require']`. - // - // We reset the `phaseData` property to remove this - // cache before we walk each starting dependency. - let oldPhaseData = lassoContext.phaseData; - lassoContext.phaseData = {}; - - dependencyWalker.walk({ - lassoContext: lassoContext, - dependency: dependency, - flags: flags, - on: { - dependency: function(dependency, context) { - if (dependency.isPackageDependency()) { - return; - } - - var key = dependency.getKey(); - - var info = tracking[key]; - if (info === undefined) { - tracking[key] = { - dependency: dependency, - count: 1 - }; - } else { - info.count++; - } - - if ((i === 0) && strictIntersection) { - // strict intersection so only need to keep track - // dependencies from first set (which is a little - // arbitrary but will work) - firstSet.push(dependency); - } - } - } - }, function(err, result) { - lassoContext.phaseData = oldPhaseData; - callback(err, result); - }); - }; + var strictIntersection = (thresholdValue >= numDependencies); + + for (const [i, dependency] of dependencies.entries()) { + // HACK: The built-in `dep-require` dependency type + // uses its `Deduper` instance to ignore dependencies + // within the same "phase" of a lasso operation. + // + // However, for the purposes of calculating intersection + // we should not de-duplicate across each "walk" of + // starting dependency. + // + // The `Deduper` stores a cache of "visited" dependencies in + // `lassoContext.phaseData['dependency-require']`. + // + // We reset the `phaseData` property to remove this + // cache before we walk each starting dependency. + let oldPhaseData = lassoContext.phaseData; + lassoContext.phaseData = {}; + + await dependencyWalker.walk({ + lassoContext: lassoContext, + dependency: dependency, + flags: flags, + on: { + dependency: onDependency(tracking, strictIntersection, firstSet, i) + } }); - // Use `series` since de-duplication logic in - // phase data can interfere with results. - series(asyncTasks, function(err) { - if (err) { - return callback(err); - } + lassoContext.phaseData = oldPhaseData; + } - var intersection = []; + var intersection = []; - function checkDependency(info) { - if (info.count >= thresholdValue) { - intersection.push(info.dependency); - } - } + function checkDependency(info) { + if (info.count >= thresholdValue) { + intersection.push(info.dependency); + } + } - if (strictIntersection) { - // strict intersection - for (var i=0,len=firstSet.length; i { + match = nodePath.join(basedir, match); + return type ? type + ':' + match : match; }); - } else { - callback(); + return matches; } } -exports.normalizer = globNormalizer; \ No newline at end of file +exports.normalizer = globNormalizer; diff --git a/lib/dependency-walker.js b/lib/dependency-walker.js index ccf0fabb..3602b757 100644 --- a/lib/dependency-walker.js +++ b/lib/dependency-walker.js @@ -1,6 +1,5 @@ var EventEmitter = require('events').EventEmitter; var forEachEntry = require('raptor-util/forEachEntry'); -var series = require('raptor-async/series'); var perfLogger = require('raptor-logging').logger('lasso/perf'); var logger = require('raptor-logging').logger(module); var createError = require('raptor-util/createError'); @@ -10,7 +9,7 @@ var createError = require('raptor-util/createError'); * * @param options */ -function walk(options, callback) { +async function walk(options) { var startTime = Date.now(); var emitter = new EventEmitter(); var lassoContext = options.lassoContext || {}; @@ -23,7 +22,7 @@ function walk(options, callback) { var on = options.on; if (!on) { - return callback(new Error('"on" property is required')); + throw new Error('"on" property is required'); } forEachEntry(on, function(event, listener) { @@ -32,36 +31,19 @@ function walk(options, callback) { var foundDependencies = {}; - function walkDependencies(dependencies, parentDependency, jsSlot, cssSlot, dependencyChain, callback) { - + async function walkDependencies (dependencies, parentDependency, jsSlot, cssSlot, dependencyChain) { logger.debug('walkDependencies', dependencies); - var work = dependencies.map(function(dependency) { - return function(callback) { - walkDependency(dependency, - parentDependency, - jsSlot, - cssSlot, - dependencyChain, - callback); - }; - }); - // process each dependency in series so that we add things in correct order - series(work, function(err) { - if (err) { - return callback(err); - } - - // Use setImmediate so that we don't build excessively long stack traces while - // walking the dependency graph. Also, we use setImmediate to avoid limits - // on how many times process.nextTick can be called. setImmediate will invoke - // callbacks after the pending I/O events to avoid starvation of I/O event - // processing. - setImmediate(callback); - }); + for (const dependency of dependencies) { + await walkDependency(dependency, + parentDependency, + jsSlot, + cssSlot, + dependencyChain); + } } - function walkManifest(manifest, parentDependency, jsSlot, cssSlot, dependencyChain, callback) { + async function walkManifest(manifest, parentDependency, jsSlot, cssSlot, dependencyChain) { delete walkContext.dependency; walkContext.package = manifest; walkContext.dependencyChain = dependencyChain; @@ -69,141 +51,114 @@ function walk(options, callback) { logger.debug('walkManifest', manifest); - manifest.getDependencies({ - flags: flags, - lassoContext: options.lassoContext - }, - function(err, dependencies) { - - logger.debug('walkManifest - dependencies', dependencies); - - if (err) { - return callback(err); - } + const dependencies = await manifest.getDependencies({ + flags: flags, + lassoContext: options.lassoContext + }); - walkDependencies(dependencies, parentDependency, jsSlot, cssSlot, dependencyChain, callback); - }); + logger.debug('walkManifest - dependencies', dependencies); + await walkDependencies(dependencies, parentDependency, jsSlot, cssSlot, dependencyChain); } - function walkDependency(dependency, parentDependency, jsSlot, cssSlot, dependencyChain, callback) { + async function walkDependency(dependency, parentDependency, jsSlot, cssSlot, dependencyChain) { dependencyChain = dependencyChain.concat(dependency); - dependency.init(lassoContext, function(err) { - logger.debug('dependency init', dependency); - if (err) { - return callback(err); - } + await dependency.init(lassoContext); - if (dependency._condition && !dependency._condition(flags)) { - return callback(); - } + logger.debug('dependency init', dependency); - dependency.calculateKey(lassoContext, function(err, key) { - if (err) { - return callback(err); - } + if (dependency._condition && !dependency._condition(flags)) { + return; + } - if (foundDependencies[key]) { - return callback(); - } - foundDependencies[key] = true; - - var slot; - - if (!dependency.isPackageDependency()) { - slot = dependency.getSlot(); - if (!slot) { - if (dependency.isJavaScript()) { - slot = jsSlot || 'body'; - } - else { - slot = cssSlot || 'head'; - } - } - } + const key = await dependency.calculateKey(lassoContext); + + if (foundDependencies[key]) { + return; + } - walkContext.slot = slot; - delete walkContext.package; - walkContext.dependency = dependency; - walkContext.parentDependency = parentDependency; - walkContext.dependencyChain = dependencyChain; + foundDependencies[key] = true; - if (shouldSkipDependencyFunc && shouldSkipDependencyFunc(dependency, walkContext)) { - return callback(); - } + var slot; - emitter.emit('dependency', dependency, walkContext); - - if (dependency.isPackageDependency()) { - dependency.getPackageManifest(lassoContext, function(err, dependencyManifest) { - if (err) { - var message = 'Failed to walk dependency ' + dependency + '. Dependency chain: ' + dependencyChain.join(' → ') + '. Cause: ' + err; - var wrappedError = createError(message, err); - return callback(wrappedError); - } - - if (!dependencyManifest) { - return callback(); - } - - walkManifest( - dependencyManifest, - dependency, - dependency.getJavaScriptSlot() || jsSlot, - dependency.getStyleSheetSlot() || cssSlot, - dependencyChain, - callback); - }); + if (!dependency.isPackageDependency()) { + slot = dependency.getSlot(); + if (!slot) { + if (dependency.isJavaScript()) { + slot = jsSlot || 'body'; } else { - return callback(); + slot = cssSlot || 'head'; } - }); - }); - } + } + } - function done(err) { + walkContext.slot = slot; + delete walkContext.package; + walkContext.dependency = dependency; + walkContext.parentDependency = parentDependency; + walkContext.dependencyChain = dependencyChain; - if (err) { - return callback(err); + if (shouldSkipDependencyFunc && shouldSkipDependencyFunc(dependency, walkContext)) { + return; } - perfLogger.debug('Completed walk in ' + (Date.now() - startTime) + 'ms'); + emitter.emit('dependency', dependency, walkContext); - emitter.emit('end'); + if (dependency.isPackageDependency()) { + try { + const dependencyManifest = await dependency.getPackageManifest(lassoContext); - callback(); + if (!dependencyManifest) { + return; + } + + await walkManifest( + dependencyManifest, + dependency, + dependency.getJavaScriptSlot() || jsSlot, + dependency.getStyleSheetSlot() || cssSlot, + dependencyChain); + } catch (err) { + const message = 'Failed to walk dependency ' + dependency + '. Dependency chain: ' + dependencyChain.join(' → ') + '. Cause: ' + err; + throw createError(message, err); + } + } + } + + function done () { + perfLogger.debug('Completed walk in ' + (Date.now() - startTime) + 'ms'); + emitter.emit('end'); } var dependencyChain = []; if (options.lassoManifest) { - walkManifest( + await walkManifest( options.lassoManifest, null, // parent package null, // jsSlot null, - dependencyChain, - done); // cssSlot + dependencyChain); + done(); } else if (options.dependency) { - walkDependency( + await walkDependency( options.dependency, null, // parent package null, // jsSlot null, - dependencyChain, - done); // cssSlot + dependencyChain); + done(); } else if (options.dependencies) { - options.dependencies.normalize(function(err, dependencies) { - walkDependencies( - dependencies, - null, - null, - null, - dependencyChain, - done); - }); + const dependencies = await options.dependencies.normalize(); + await walkDependencies( + dependencies, + null, + null, + null, + dependencyChain); + done(); } else { - return callback(new Error('"lassoManifest", "dependency", "dependencies" is required')); + throw new Error('"lassoManifest", "dependency", "dependencies" is required'); } } diff --git a/lib/index.js b/lib/index.js index 06903a1f..099772ae 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,15 +1,15 @@ require('raptor-logging'); -var nodePath = require('path'); -var configLoader = require('./config-loader'); -var flags = require('./flags'); -var transforms = require('./transforms'); -var ok = require('assert').ok; -var fs = require('fs'); -var raptorCache = require('raptor-cache'); -var extend = require('raptor-util/extend'); -var getClientPath = require('lasso-modules-client/transport').getClientPath; -var stripJsonComments = require('strip-json-comments'); +const nodePath = require('path'); +const configLoader = require('./config-loader'); +const flags = require('./flags'); +const transforms = require('./transforms'); +const ok = require('assert').ok; +const fs = require('fs'); +const raptorCache = require('raptor-cache'); +const extend = require('raptor-util/extend'); +const getClientPath = require('lasso-modules-client/transport').getClientPath; +const stripJsonComments = require('strip-json-comments'); if (!getClientPath) { throw new Error('getClientPath is not defined'); @@ -110,7 +110,7 @@ function configure(config, baseDir, filename) { exports.defaultConfigFilename = filename; } -function lassoPage(pageConfig, callback) { +async function lassoPage(pageConfig) { ok(pageConfig, '"pageConfig" is required'); ok(typeof pageConfig === 'object', '"pageConfig" should be an object'); @@ -129,11 +129,11 @@ function lassoPage(pageConfig, callback) { packagePath = nodePath.resolve(process.cwd(), packagePath); } - return getDefaultLasso().lassoPage(pageConfig, callback); + return getDefaultLasso().lassoPage(pageConfig); } -function lassoResource(path, context, callback) { - return getDefaultLasso().lassoResource(path, context, callback); +async function lassoResource (path, context) { + return getDefaultLasso().lassoResource(path, context); } function clearCaches() { @@ -156,7 +156,9 @@ exports.isExtensionSet = flags.isFlagSet; // Deprecated exports.transforms = transforms; exports.writers = require('./writers'); + exports.flushAllCaches = raptorCache.flushAll; + exports.handleWatchedFileChanged = function(path) { console.log('[lasso] File modified: ' + path); clearCaches(); @@ -188,4 +190,4 @@ exports.toString = function () { // we have a circular dependency require('lasso-image').lasso = exports; -require('../browser-refresh').enable(); \ No newline at end of file +require('../browser-refresh').enable(); diff --git a/lib/last-modified.js b/lib/last-modified.js index ed5be16e..1f49bc83 100644 --- a/lib/last-modified.js +++ b/lib/last-modified.js @@ -1,5 +1,10 @@ var cachingFs = require('./caching-fs'); -exports.forFile = function(filePath, callback) { - cachingFs.lastModified(filePath, callback); +// TODO: Change in lasso-caching-fs +exports.forFile = async function (filePath) { + return new Promise((resolve, reject) => { + cachingFs.lastModified(filePath, function (err, data) { + return err ? reject(err) : resolve(data); + }); + }); }; diff --git a/lib/page-bundles-builder.js b/lib/page-bundles-builder.js index 6b03718c..57db9009 100644 --- a/lib/page-bundles-builder.js +++ b/lib/page-bundles-builder.js @@ -7,15 +7,14 @@ var DependencyTree = require('./DependencyTree'); var logger = require('raptor-logging').logger(module); var bundlingStrategies = require('./bundling-strategies'); -function build(options, config, bundleMappings, lassoContext, callback) { +async function build (options, config, bundleMappings, lassoContext) { + // TODO: Change to fully use async/await assert.ok(options, '"options" is required'); assert.ok(config, '"config" is required'); assert.ok(bundleMappings, '"bundleMappings" is required'); assert.ok(lassoContext, '"lassoContext" is required'); - assert.ok(typeof callback === 'function', 'callback function is required'); var pageName = options.name || options.pageName; - var lassoManifest = options.lassoManifest; var flags = lassoContext.flags; @@ -24,140 +23,142 @@ function build(options, config, bundleMappings, lassoContext, callback) { assert.ok(lassoManifest, '"lassoManifest" is required'); assert.ok(LassoManifest.isLassoManifest(lassoManifest), '"lassoManifest" is not a valid package'); - // this will keep track of async loader metadata - var loaderMetadata = lassoContext.loaderMetadata = new LoaderMetadata(); + return new Promise(async (resolve, reject) => { + function callback (err, data) { + return err ? reject(err) : resolve(data); + } - var pageBundles = new PageBundles(); + // this will keep track of async loader metadata + var loaderMetadata = lassoContext.loaderMetadata = new LoaderMetadata(); - var bundlingStrategyFactory = bundlingStrategies[config.getBundlingStrategy() || 'default']; + var pageBundles = new PageBundles(); - if (!bundlingStrategyFactory) { - throw new Error('Invalid "bundlingStrategy": ' + config.getBundlingStrategy() + '. Expected: ' + Object.keys(bundlingStrategies).join(', ')); - } + var bundlingStrategyFactory = bundlingStrategies[config.getBundlingStrategy() || 'default']; - var bundlingStrategy = bundlingStrategyFactory(options, config, bundleMappings, pageBundles, lassoContext); + if (!bundlingStrategyFactory) { + throw new Error('Invalid "bundlingStrategy": ' + config.getBundlingStrategy() + '. Expected: ' + Object.keys(bundlingStrategies).join(', ')); + } - var infoEnabled = logger.isInfoEnabled(); + var bundlingStrategy = bundlingStrategyFactory(options, config, bundleMappings, pageBundles, lassoContext); - var foundAsyncPackages = {}; + var infoEnabled = logger.isInfoEnabled(); - // as we discover new manifests with "async" property, we add tasks to work queue - // that will be later used to build each async package - var buildAsyncPackagesWorkQueue = require('raptor-async/work-queue').create({ - // task caused error - onTaskError: function(err) { - // on error, clear the queue of any tasks - buildAsyncPackagesWorkQueue.kill(); - callback(err); - }, + var foundAsyncPackages = {}; - onTaskComplete: function() { - if (buildAsyncPackagesWorkQueue.idle()) { - // no more work so done - callback(null, pageBundles); - } - } - }, function(task, callback) { - // this function is called when we need to run task + // as we discover new manifests with "async" property, we add tasks to work queue + // that will be later used to build each async package + var buildAsyncPackagesWorkQueue = require('raptor-async/work-queue').create({ + // task caused error + onTaskError: function(err) { + // on error, clear the queue of any tasks + buildAsyncPackagesWorkQueue.kill(); + callback(err); + }, - var asyncPackageName = task.asyncPackageName; - var debugTree = logger.isDebugEnabled() ? new DependencyTree() : null; + onTaskComplete: function() { + if (buildAsyncPackagesWorkQueue.idle()) { + // no more work so done + callback(null, pageBundles); + } + } + }, async function (task, callback) { + // this function is called when we need to run task - // register this async package name in loader metadata - loaderMetadata.addAsyncPackageName(asyncPackageName); + var asyncPackageName = task.asyncPackageName; + var debugTree = logger.isDebugEnabled() ? new DependencyTree() : null; - // Since we are building the async bundles in parallel we need to create a new - // lasso context object, each with its own phaseData - var nestedLassoContext = Object.create(lassoContext); - nestedLassoContext.phaseData = {}; + // register this async package name in loader metadata + loaderMetadata.addAsyncPackageName(asyncPackageName); - if (infoEnabled) { - logger.info('Building async package "' + asyncPackageName + '"...'); - } + // Since we are building the async bundles in parallel we need to create a new + // lasso context object, each with its own phaseData + var nestedLassoContext = Object.create(lassoContext); + nestedLassoContext.phaseData = {}; - return dependencyWalker.walk({ - dependencies: task.dependencies, - flags: flags, - lassoContext: nestedLassoContext, - on: { - // as we're building async packages, we need to watch for new async packages - manifest: handleManifest, + if (infoEnabled) { + logger.info('Building async package "' + asyncPackageName + '"...'); + } - dependency: function(dependency, walkContext) { - if (dependency.isPackageDependency()) { - if (debugTree) { - debugTree.add(dependency, walkContext.parentDependency); + try { + await dependencyWalker.walk({ + dependencies: task.dependencies, + flags: flags, + lassoContext: nestedLassoContext, + on: { + // as we're building async packages, we need to watch for new async packages + manifest: handleManifest, + + dependency: function(dependency, walkContext) { + if (dependency.isPackageDependency()) { + if (debugTree) { + debugTree.add(dependency, walkContext.parentDependency); + } + return; } - return; - } - if (!dependency.read) { - logger.debug('Ignoring dependency because it is not readable', dependency); - return; - } - - // NOTE: walkContext will contain everything that is interesting including the following: - // - dependency - // - slot - // - dependencyChain - lassoContext.emit('beforeAddDependencyToAsyncPageBundle', walkContext); + if (!dependency.read) { + logger.debug('Ignoring dependency because it is not readable', dependency); + return; + } - var bundle = bundlingStrategy.getBundleForAsyncDependency(dependency, walkContext, debugTree); - if (bundle) { - dependency.onAddToAsyncPageBundle(bundle, lassoContext); - pageBundles.addAsyncBundle(bundle); - loaderMetadata.addBundle(asyncPackageName, bundle); + // NOTE: walkContext will contain everything that is interesting including the following: + // - dependency + // - slot + // - dependencyChain + lassoContext.emit('beforeAddDependencyToAsyncPageBundle', walkContext); + + var bundle = bundlingStrategy.getBundleForAsyncDependency(dependency, walkContext, debugTree); + if (bundle) { + dependency.onAddToAsyncPageBundle(bundle, lassoContext); + pageBundles.addAsyncBundle(bundle); + loaderMetadata.addBundle(asyncPackageName, bundle); + } } } - } - }, - function(err) { + }); + // we're done walking async dependencies for this async package if (debugTree) { logger.debug('Async page bundles for "' + asyncPackageName + '":\n' + debugTree.bundlesToString()); } + } catch (err) { + logger.error('Error building bundles for async package "' + asyncPackageName + '"', err); + return callback(err); + } - if (err) { - logger.error('Error building bundles for async package "' + asyncPackageName + '"', err); - } else { - logger.info('Built async package "' + asyncPackageName + '".'); - } - - // let the work-queue know that this job is done - callback(err); - }); - }); - - // When walking a manifest, we need to check if the manifest has an "async" property - // which declares asynchronous packages - function handleManifest(manifest, walkContext) { - var async = manifest.async; - if (async) { - // create jobs to build each async package - for (var asyncName in async) { - if (async.hasOwnProperty(asyncName)) { - if (!foundAsyncPackages.hasOwnProperty(asyncName)) { - foundAsyncPackages[asyncName] = true; - buildAsyncPackagesWorkQueue.push({ - asyncPackageName: asyncName, - dependencies: async[asyncName] - }); + logger.info('Built async package "' + asyncPackageName + '".'); + callback(); + }); + + // When walking a manifest, we need to check if the manifest has an "async" property + // which declares asynchronous packages + function handleManifest(manifest, walkContext) { + var async = manifest.async; + if (async) { + // create jobs to build each async package + for (var asyncName in async) { + if (async.hasOwnProperty(asyncName)) { + if (!foundAsyncPackages.hasOwnProperty(asyncName)) { + foundAsyncPackages[asyncName] = true; + buildAsyncPackagesWorkQueue.push({ + asyncPackageName: asyncName, + dependencies: async[asyncName] + }); + } } } } } - } - /********************************************************************** - * STEP 1: Put all of the dependencies into bundles and keep track of * - * packages that are asynchronous. * - **********************************************************************/ - function buildSyncPageBundles(callback) { + /********************************************************************** + * STEP 1: Put all of the dependencies into bundles and keep track of * + * packages that are asynchronous. * + **********************************************************************/ + async function buildSyncPageBundles () { + var debugTree = logger.isDebugEnabled() ? new DependencyTree() : null; + lassoContext.setPhase('page-bundle-mappings'); - var debugTree = logger.isDebugEnabled() ? new DependencyTree() : null; - lassoContext.setPhase('page-bundle-mappings'); - - dependencyWalker.walk({ + await dependencyWalker.walk({ lassoManifest: lassoManifest, flags: flags, lassoContext: lassoContext, @@ -194,24 +195,21 @@ function build(options, config, bundleMappings, lassoContext, callback) { } } } - }, - function(err) { - if (debugTree) { - logger.debug('Page bundles:\n' + debugTree.bundlesToString()); - } - - callback(err); }); - } - buildSyncPageBundles(function(err) { - if (err) { + if (debugTree) { + logger.debug('Page bundles:\n' + debugTree.bundlesToString()); + } + } + + try { + await buildSyncPageBundles(); + } catch (err) { return callback(err); } lassoContext.setPhase('async-page-bundle-mappings'); if (buildAsyncPackagesWorkQueue.idle()) { - // no async packages so resolve promise callback(null, pageBundles); } else { // start the work to build bundles for async packages diff --git a/lib/reader.js b/lib/reader.js index 6025a26c..b48feb64 100644 --- a/lib/reader.js +++ b/lib/reader.js @@ -3,7 +3,6 @@ var through = require('through'); var logger = require('raptor-logging').logger(module); var ok = require('assert').ok; var fs = require('fs'); -//var Readable = require('stream').Readable; var CombinedStream = require('./util/CombinedStream'); var DeferredReadable = require('./util/DeferredReadable'); var nodePath = require('path'); @@ -63,34 +62,33 @@ function createReadDependencyStream(dependency, lassoContext, transformerAsyncVa readContext); } - var cache = lassoContext.cache; var cacheKey = dependency.getReadCacheKey(); if (cache && dependency.shouldCache(lassoContext) && cacheKey) { var readCache = cache.readCache; - dependency.getLastModified(lassoContext, function(err, lastModified) { - if (!lastModified || lastModified <= 0) { - // This dependency does not support caching - // so don't go through the caching layer - deferredReadable.setWrappedStream(createTransformedStream(createReadStream())); - return; - } - - var cachedReadStream = readCache.createReadStream( - cacheKey, - { - lastModified: lastModified, - builder: function (callback) { - // The read dependency has not been cached - callback(null, createReadStream); - } - }); - - deferredReadable.setWrappedStream(createTransformedStream(cachedReadStream)); - }); + dependency.getLastModified(lassoContext) + .then((lastModified) => { + if (!lastModified || lastModified <= 0) { + // This dependency does not support caching + // so don't go through the caching layer + deferredReadable.setWrappedStream(createTransformedStream(createReadStream())); + return; + } + var cachedReadStream = readCache.createReadStream( + cacheKey, + { + lastModified: lastModified, + builder: function (callback) { + // The read dependency has not been cached + callback(null, createReadStream); + } + }); + + deferredReadable.setWrappedStream(createTransformedStream(cachedReadStream)); + }); } else { deferredReadable.setWrappedStream(createTransformedStream(createReadStream())); } @@ -189,14 +187,15 @@ function createBundleReader(bundle, lassoContext) { var transformContext = Object.create(lassoContext || {}); transformContext.contentType = bundle.contentType; + // TODO: Change to fully use async/await var transformerAsyncValue = new AsyncValue(); - - transforms.createTransformer(lassoContext.config.getTransforms(), transformContext, function(err, transformer) { - if (err) { - return transformerAsyncValue.reject(err); - } - transformerAsyncValue.resolve(transformer); - }); + transforms.createTransformer(lassoContext.config.getTransforms(), transformContext) + .then((transformer) => { + transformerAsyncValue.resolve(transformer); + }) + .catch((err) => { + transformerAsyncValue.reject(err); + }); return { readBundle: function() { @@ -209,55 +208,53 @@ function createBundleReader(bundle, lassoContext) { return createReadDependencyStream(dependency, lassoContext, transformerAsyncValue); }, - readBundleFully: function(callback) { - if (!bundle.hasContent()) { - return callback(null, ''); - } + async readBundleFully () { + if (!bundle.hasContent()) return ''; - ok(typeof callback === 'function', 'Invalid callback'); + return new Promise((resolve, reject) => { + var hasError = false; - var hasError = false; + function handleError(e) { + if (hasError) { + return; + } - function handleError(e) { - if (hasError) { - return; + hasError = true; + reject(e); } - hasError = true; + var input = this.readBundle(); + var code = ''; - callback(e); - } - - var input = this.readBundle(); - var code = ''; - var captureStream = through( - function write(data) { - code += data; - }, - function end() { - if (hasError) { - return; - } + var captureStream = through( + function write (data) { + code += data; + }, + function end () { + if (hasError) { + return; + } - callback(null, code); - }); + resolve(code); + }); - input.on('error', handleError); - captureStream.on('error', handleError); + input.on('error', handleError); + captureStream.on('error', handleError); - input.pipe(captureStream); + input.pipe(captureStream); + }); } }; } function createResourceReader(path, lassoContext) { return { - readResource: function(options) { + readResource (options) { var readStream = fs.createReadStream(path, options); var filename = nodePath.basename(path); // Use the file extension as the content type - var contentType = filename.substring(filename.lastIndexOf('.')+1); + var contentType = filename.substring(filename.lastIndexOf('.') + 1); var transformContext = Object.create(lassoContext || {}); transformContext.contentType = contentType; @@ -266,22 +263,21 @@ function createResourceReader(path, lassoContext) { var readable = new DeferredReadable(); - transforms.createTransformer(lassoContext.config.getTransforms(), transformContext, function(err, transformer) { - if (err) { - readable.emit('error', err); - return; - } - - if (transformer.hasTransforms() === false) { - // simply use the input stream since there are no transforms after the filtering - readable.setWrappedStream(readStream); - return; - } + transforms.createTransformer(lassoContext.config.getTransforms(), transformContext) + .then((transformer) => { + if (transformer.hasTransforms() === false) { + // simply use the input stream since there are no transforms after the filtering + readable.setWrappedStream(readStream); + return; + } - readable.setWrappedStream(transformer.transform( - readStream, - transformContext)); - }); + readable.setWrappedStream(transformer.transform( + readStream, + transformContext)); + }) + .catch((err) => { + readable.emit('error', err); + }); return readable; } diff --git a/lib/require/dep-require-remap.js b/lib/require/dep-require-remap.js index d0bad332..f071eb9e 100644 --- a/lib/require/dep-require-remap.js +++ b/lib/require/dep-require-remap.js @@ -8,7 +8,7 @@ function create(config, lasso) { fromDirname: 'string' }, - init: function(lassoContext, callback) { + async init (lassoContext) { var fromPath = this.resolvePath(this.from); var toPath = this.resolvePath(this.to); @@ -16,7 +16,7 @@ function create(config, lasso) { this.to = toPath; }, - calculateKey: function() { + async calculateKey () { return this.from + '|' + this.to; }, @@ -24,7 +24,7 @@ function create(config, lasso) { return nodePath.dirname(this.to); }, - getDependencies: function(lassoContext, callback) { + async getDependencies (lassoContext) { return [ { type: 'commonjs-remap', diff --git a/lib/require/dep-require.js b/lib/require/dep-require.js index 968d3bf3..a0564304 100644 --- a/lib/require/dep-require.js +++ b/lib/require/dep-require.js @@ -204,7 +204,7 @@ function create(config, lasso) { requireHandler: 'object' }, - init: function(lassoContext) { + async init (lassoContext) { if (!this.path && !this.virtualModule) { let error = new Error('Invalid "require" dependency. "path" property is required'); console.error(module.id, error.stack, this); @@ -253,14 +253,13 @@ function create(config, lasso) { } ok(this.path); - }, toString: function() { return '[require: ' + this.path + ']'; }, - calculateKey() { + async calculateKey() { // This is a unique key that prevents the same dependency from being // added to the dependency graph repeatedly var key = 'modules-require:' + this.path + '@' + this.from; @@ -314,7 +313,7 @@ function create(config, lasso) { } }, - getDependencies: function(lassoContext) { + async getDependencies (lassoContext) { ok(lassoContext, '"lassoContext" argument expected'); var requireHandler; diff --git a/lib/require/dep-runtime.js b/lib/require/dep-runtime.js index b5722710..6cf81f47 100644 --- a/lib/require/dep-runtime.js +++ b/lib/require/dep-runtime.js @@ -35,7 +35,7 @@ exports.create = function(config, lasso) { return lassoModulesClientMainPath; }, - calculateKey: function() { + async calculateKey () { return 'modules-runtime'; } }; diff --git a/lib/require/dep-transport-builtin.js b/lib/require/dep-transport-builtin.js index 0602f318..62dbec51 100644 --- a/lib/require/dep-transport-builtin.js +++ b/lib/require/dep-transport-builtin.js @@ -8,9 +8,7 @@ exports.create = function(config, lasso) { target: 'string' }, - init(lassoContext) { - - }, + async init(lassoContext) {}, getDir: function() { return nodePath.dirname(this._sourceFile); @@ -25,8 +23,8 @@ exports.create = function(config, lasso) { }); }, - getLastModified: function(lassoContext, callback) { - callback(null, -1); + async getLastModified (lassoContext) { + return -1; }, getUnbundledTargetPrefix: function(lassoContext) { @@ -41,7 +39,7 @@ exports.create = function(config, lasso) { return this._sourceFile; }, - calculateKey: function() { + async calculateKey () { return 'modules-builtin:' + this.name + '>' + this.target; } }; diff --git a/lib/require/dep-transport-define.js b/lib/require/dep-transport-define.js index 3ad27813..f4b46cea 100644 --- a/lib/require/dep-transport-define.js +++ b/lib/require/dep-transport-define.js @@ -183,8 +183,8 @@ exports.create = function(config, lasso) { }); }, - getLastModified: function(lassoContext, callback) { - callback(null, this.requireLastModified); + async getLastModified (lassoContext) { + return this.requireLastModified; }, getUnbundledTargetPrefix: function(lassoContext) { @@ -195,7 +195,7 @@ exports.create = function(config, lasso) { return this.path; }, - calculateKey: function() { + async calculateKey () { return 'modules-define:' + this.path; }, diff --git a/lib/require/dep-transport-installed.js b/lib/require/dep-transport-installed.js index f5eb5653..7d4e9ca9 100644 --- a/lib/require/dep-transport-installed.js +++ b/lib/require/dep-transport-installed.js @@ -9,9 +9,7 @@ exports.create = function(config, lasso) { 'parentDir': 'string' }, - init(lassoContext) { - - }, + async init(lassoContext) {}, getDir: function() { return this.parentDir; @@ -27,8 +25,8 @@ exports.create = function(config, lasso) { }); }, - getLastModified: function(lassoContext, callback) { - callback(null, -1); + async getLastModified (lassoContext) { + return -1; }, getUnbundledTargetPrefix: function(lassoContext) { @@ -43,7 +41,7 @@ exports.create = function(config, lasso) { return this._sourceFile; }, - calculateKey: function() { + async calculateKey () { return 'modules-installed:' + this.parentPath + '|' + this.childName + '|' + this.childVersion; } }; diff --git a/lib/require/dep-transport-loader-metadata.js b/lib/require/dep-transport-loader-metadata.js index 2cbac7ed..808c7495 100644 --- a/lib/require/dep-transport-loader-metadata.js +++ b/lib/require/dep-transport-loader-metadata.js @@ -4,9 +4,7 @@ exports.create = function(config, lasso) { return { properties: {}, - init(lassoContext) { - - }, + async init(lassoContext) {}, read: function(lassoContext) { var loaderMetadata = lassoContext && lassoContext.loaderMetadata; @@ -30,16 +28,16 @@ exports.create = function(config, lasso) { return 'lasso-modules-meta'; }, - calculateKey: function() { + async calculateKey () { return 'loader-metadata'; }, - + isPageBundleOnlyDependency: function() { return true; }, - getLastModified: function(lassoContext, callback) { - callback(null, -1); + async getLastModified (lassoContext) { + return -1; } }; }; diff --git a/lib/require/dep-transport-main.js b/lib/require/dep-transport-main.js index 4a2ed90e..d310e9cb 100644 --- a/lib/require/dep-transport-main.js +++ b/lib/require/dep-transport-main.js @@ -8,9 +8,7 @@ exports.create = function(config, lasso) { 'main': 'string' }, - init() { - - }, + async init() {}, getDir: function() { return nodePath.dirname(this._sourceFile); @@ -25,15 +23,15 @@ exports.create = function(config, lasso) { }); }, - getLastModified: function(lassoContext, callback) { - callback(null, -1); + async getLastModified (lassoContext) { + return -1; }, getSourceFile: function() { return this._sourceFile; }, - calculateKey: function() { + async calculateKey () { return 'modules-main:' + this.dir + '|' + this.main; }, diff --git a/lib/require/dep-transport-ready.js b/lib/require/dep-transport-ready.js index fdce00ce..26d217a5 100644 --- a/lib/require/dep-transport-ready.js +++ b/lib/require/dep-transport-ready.js @@ -5,7 +5,7 @@ exports.create = function(config, lasso) { properties: { }, - init() { + async init() { if (!this.slot) { delete this.slot; } @@ -21,12 +21,12 @@ exports.create = function(config, lasso) { }); }, - calculateKey: function() { + async calculateKey () { return 'modules-ready'; }, - getLastModified: function(lassoContext, callback) { - callback(null, -1); + async getLastModified (lassoContext) { + return -1; } }; }; diff --git a/lib/require/dep-transport-remap.js b/lib/require/dep-transport-remap.js index d121bfc0..5af617fc 100644 --- a/lib/require/dep-transport-remap.js +++ b/lib/require/dep-transport-remap.js @@ -9,9 +9,7 @@ exports.create = function(config, lasso) { 'fromFile': 'string' }, - init(lassoContext) { - - }, + async init (lassoContext) {}, getDir: function() { return this.fromFile ? nodePath.dirname(this.fromFile) : undefined; @@ -26,15 +24,15 @@ exports.create = function(config, lasso) { }); }, - getLastModified: function(lassoContext, callback) { - callback(null, -1); + async getLastModified (lassoContext) { + return -1; }, getSourceFile: function() { return this._sourceFile; }, - calculateKey: function() { + async calculateKey () { return 'modules-remap:' + this.from + '|' + this.to; }, @@ -46,4 +44,4 @@ exports.create = function(config, lasso) { return 'lasso-modules-meta'; } }; -}; \ No newline at end of file +}; diff --git a/lib/require/dep-transport-run.js b/lib/require/dep-transport-run.js index e417291c..e7b9d0fc 100644 --- a/lib/require/dep-transport-run.js +++ b/lib/require/dep-transport-run.js @@ -9,9 +9,7 @@ exports.create = function(config, lasso) { file: 'string' // The original source file that this dependency is assocaited with }, - init(lassoContext) { - - }, + async init(lassoContext) {}, getDir: function() { return this.path ? nodePath.dirname(this.path) : undefined; @@ -35,8 +33,8 @@ exports.create = function(config, lasso) { }); }, - getLastModified: function(lassoContext, callback) { - callback(null, -1); + async getLastModified (lassoContext) { + return -1; }, getUnbundledTargetPrefix: function(lassoContext) { @@ -55,7 +53,7 @@ exports.create = function(config, lasso) { return bundleName + '-run' + ext; }, - calculateKey: function() { + async calculateKey () { return 'modules-run:' + this.path + '|' + this.wait; } }; diff --git a/lib/require/dep-transport-search-path.js b/lib/require/dep-transport-search-path.js index a89d509e..c4f70614 100644 --- a/lib/require/dep-transport-search-path.js +++ b/lib/require/dep-transport-search-path.js @@ -7,7 +7,7 @@ exports.create = function(config, lasso) { 'paths': 'string[]' }, - init: function() { + async init () { if (!this.paths) { this.paths = []; } @@ -27,8 +27,8 @@ exports.create = function(config, lasso) { }); }, - getLastModified: function(lassoContext, callback) { - callback(null, -1); + async getLastModified (lassoContext) { + return -1; }, getUnbundledTargetPrefix: function(lassoContext) { @@ -39,8 +39,8 @@ exports.create = function(config, lasso) { return 'lasso-modules-meta'; }, - calculateKey: function() { + async calculateKey () { return 'modules-search-path:' + JSON.stringify(this.paths); } }; -}; \ No newline at end of file +}; diff --git a/lib/require/index.js b/lib/require/index.js index 56055167..26fed87d 100644 --- a/lib/require/index.js +++ b/lib/require/index.js @@ -43,29 +43,29 @@ module.exports = exports = function plugin(lasso, userConfig) { function registerExtension(ext) { lasso.dependencies.registerRequireExtension(ext, { - read: function(path) { - return fs.createReadStream(path, {encoding: 'utf8'}); - }, + read: function(path) { + return fs.createReadStream(path, {encoding: 'utf8'}); + }, - getLastModified: function(path, lassoContext, callback) { - lassoContext.getFileLastModified(path, callback); - } - }); + async getLastModified (path, lassoContext) { + return lassoContext.getFileLastModified(path); + } + }); } config.extensions.forEach(registerExtension); lasso.dependencies.registerRequireExtension('json', { - object: true, + object: true, - read: function(path) { - return fs.createReadStream(path, {encoding: 'utf8'}); - }, + read: function(path) { + return fs.createReadStream(path, {encoding: 'utf8'}); + }, - getLastModified: function(path, lassoContext, callback) { - lassoContext.getFileLastModified(path, callback); - } - }); + getLastModified (path, lassoContext) { + return lassoContext.getFileLastModified(path); + } + }); lasso.dependencies.registerJavaScriptType('commonjs-def', depTransportDef.create(config, lasso)); lasso.dependencies.registerJavaScriptType('commonjs-run', depTransportRun.create(config, lasso)); @@ -124,4 +124,4 @@ module.exports = exports = function plugin(lasso, userConfig) { }); }; -// module.exports.getClientPath = require('lasso-modules-client/transport').getClientPath; \ No newline at end of file +// module.exports.getClientPath = require('lasso-modules-client/transport').getClientPath; diff --git a/lib/transforms.js b/lib/transforms.js index eb6a917b..e863af30 100644 --- a/lib/transforms.js +++ b/lib/transforms.js @@ -1,10 +1,8 @@ var inspect = require('util').inspect; var ok = require('assert').ok; -var equal = require('assert').equal; var DeferredReadable = require('./util').DeferredReadable; var PassThrough = require('stream').PassThrough; var through = require('through'); -var async = require('async'); function Transformer(transforms) { this.transforms = transforms; @@ -23,13 +21,7 @@ function handleNonStreamTransform(inStream, transform, applyTransform, handleErr outStream.push(null); } - var transformedCode = applyTransform(code, transform, function(err, transformedCode) { - if (err) { - return handleError(err); - } - - handleTransformedCode(transformedCode); - }); + var transformedCode = applyTransform(code, transform); if (transformedCode != null) { if (typeof transformedCode === 'string') { @@ -50,11 +42,11 @@ function handleNonStreamTransform(inStream, transform, applyTransform, handleErr } Transformer.prototype = { - hasTransforms: function() { + hasTransforms () { return this.transforms.length !== 0; }, - transform: function (inStream, lassoContext) { + transform (inStream, lassoContext) { var transforms = this.transforms; if (!transforms.length) { @@ -66,8 +58,8 @@ Transformer.prototype = { var config = lassoContext.config; ok(config, 'config expected in context'); - function applyTransform(input, transform, callback) { - return transform.transform(input, lassoContext, callback); + function applyTransform(input, transform) { + return transform.transform(input, lassoContext); } return new DeferredReadable(function() { @@ -114,19 +106,18 @@ Transformer.prototype = { deferredStream.push(null); }); - // Now start the flow of data at the source by piping the input stream // to the beginning of our transform chain (i.e. the initial pass thorugh stream) inStream.pipe(passThrough); - }); } }; -exports.createTransformer = function(unfilteredTransforms, lassoContext, callback) { - - equal(typeof callback, 'function', 'callback function expected'); +async function filterTransform (lassoContext, transformConfig) { + return transformConfig.filter ? transformConfig.filter(lassoContext) : true; +} +exports.createTransformer = async function (unfilteredTransforms, lassoContext) { if (unfilteredTransforms) { ok(Array.isArray(unfilteredTransforms), 'unfilteredTransforms should be an array'); } @@ -134,40 +125,13 @@ exports.createTransformer = function(unfilteredTransforms, lassoContext, callbac var contentType = lassoContext.contentType; ok(typeof contentType === 'string', '"contentType" is required'); - var completed = false; - - function done(err, filteredTransforms) { - if (completed) { - return; - } - - completed = true; - - if (err) { - return callback(err); + const filteredTransforms = []; + for (const unfilteredTransform of unfilteredTransforms) { + const keep = await filterTransform(lassoContext, unfilteredTransform); + if (keep) { + filteredTransforms.push(unfilteredTransform); } - - var transformer = new Transformer(filteredTransforms); - callback(null, transformer); } - function filter(transformConfig, callback) { - if (transformConfig.filter) { - transformConfig.filter(lassoContext, function(err, keep) { - if (err) { - return done(err); - } - return callback(keep); - }); - } else { - callback(true); - } - } - - async.filter( - unfilteredTransforms, - filter, - function(filteredTransforms) { - done(null, filteredTransforms); - }); + return new Transformer(filteredTransforms); }; diff --git a/lib/writers/Writer.js b/lib/writers/Writer.js index 5e19c446..75b5c824 100644 --- a/lib/writers/Writer.js +++ b/lib/writers/Writer.js @@ -11,7 +11,6 @@ var createError = require('raptor-util/createError'); var reader = require('../reader'); var ok = require('assert').ok; var equal = require('assert').equal; -var series = require('raptor-async/series'); function Writer(impl) { Writer.$super.call(this); @@ -69,20 +68,14 @@ Writer.prototype = { return this.getInPlaceUrlForFile(sourceFile, lassoContext); }, - writeBundle: function(bundle, onBundleWrittenCallback, lassoContext, callback) { - ok(callback, 'callback is required'); - - if (!bundle.hasContent()) { - return callback(); - } + async writeBundle (bundle, onBundleWrittenCallback, lassoContext) { + if (!bundle.hasContent()) return; ok(lassoContext, 'lassoContext is required'); - var _this = this; - function done(err) { + let done = (err) => { if (err) { - err = createError('Error while writing bundle "' + bundle + '" Error: ' + err, err); - return callback(err); + throw createError('Error while writing bundle "' + bundle + '" Error: ' + err, err); } bundle.setWritten(true); @@ -91,17 +84,15 @@ Writer.prototype = { onBundleWrittenCallback(bundle); } - const data = { - bundle: bundle - }; + const data = { bundle }; - _this.emit('bundleWritten', data); + this.emit('bundleWritten', data); lassoContext.emit('bundleWritten', data); logger.info('Bundle ' + bundle + ' written.'); - return callback(null, bundle); - } + return bundle; + }; if (bundle.isWritten() || bundle.url) { if (logger.isInfoEnabled()) { @@ -128,76 +119,54 @@ Writer.prototype = { logger.info('Writing bundle ' + bundle + '...'); - var asyncTasks = [ - function checkBundleUpToDate(callback) { - if (bundle.isInline()) { - return callback(); - } + let checkBundleUpToDate = async () => { + if (bundle.isInline()) return; + // We make the assumption that the bundle was populated with its URL + // and marked as written if it was indeed up-to-date + return this.checkBundleUpToDate(bundle, lassoContext); + }; - return _this.checkBundleUpToDate(bundle, lassoContext, function(err) { - if (err) { - return callback(err); - } + let writeBundle = async () => { + // If the bundle is written then there is nothing to do + if (bundle.isWritten()) return; - // We make the assumption that the bundle was populated with its URL - // and marked as written if it was indeed up-to-date - return callback(); - }); - }, + var completed = false; - function writeBundle(callback) { - if (bundle.isWritten()) { - // If the bundle is written then there is nothing to do - return callback(); + function handleError(e) { + if (!completed) { + completed = true; + throw e; } + } - var completed = false; - - function handleError(e) { - if (!completed) { - completed = true; - return callback(e); - } + if (bundle.isInline()) { + try { + const code = await bundleReader.readBundleFully(); + logger.info('Code for inline bundle ' + bundle.getLabel() + ' generated.'); + bundle.setCode(code); + } catch (err) { + return handleError(err); } - - if (bundle.isInline()) { - bundleReader.readBundleFully(function(err, code) { - if (err) { - return handleError(err); - } - - logger.info('Code for inline bundle ' + bundle.getLabel() + ' generated.'); - bundle.setCode(code); - return callback(); - }); - } else { - _this.impl.writeBundle(bundleReader, lassoContext, function(err) { - if (err) { - return handleError(err); - } - - logger.info('Bundle written:', bundle.getLabel()); - - return callback(); - }); + } else { + try { + await this.impl.writeBundle(bundleReader, lassoContext); + logger.info('Bundle written:', bundle.getLabel()); + } catch (err) { + return handleError(err); } } - ]; + }; - series(asyncTasks, done); + await checkBundleUpToDate(); + await writeBundle(); + + return done(); }, - writeResource: function(path, lassoContext, callback) { + async writeResource (path, lassoContext) { ok(lassoContext, 'lassoContext is required'); - equal(typeof callback, 'function', 'callback function is required'); - - var _this = this; - - function done(err, writeResult) { - if (err) { - return callback(createError('Error while writing resource "' + path + '": ' + (err.stack || err), err)); - } + const done = (writeResult) => { ok(writeResult, 'writeResult expected'); ok(writeResult.url, 'writeResult.url expected'); @@ -205,27 +174,33 @@ Writer.prototype = { sourceFile: path }); - _this.emit('resourceWritten', result); + this.emit('resourceWritten', result); lassoContext.emit('resourceWritten', result); - callback(null, result); - } - - var config = this.config; + return result; + }; + const config = this.config; if (config.isInPlaceDeploymentEnabled()) { var url = this.getInPlaceUrlForFile(path, lassoContext); if (url) { - return done(null, { url: url }); + return done({ url }); } } lassoContext = Object.create(lassoContext); lassoContext.path = path; - var resourceReader = reader.createResourceReader(path, lassoContext); - _this.impl.writeResource(resourceReader, lassoContext, done); + const resourceReader = reader.createResourceReader(path, lassoContext); + + try { + const writeResult = await this.impl.writeResource(resourceReader, lassoContext); + return done(writeResult); + } catch (err) { + throw createError('Error while writing resource "' + path + '": ' + (err.stack || err), err); + } + // this.checkResourceUpToDate(path, lassoContext, function(err, resourceInfo) { // if (err) { // return callback(err); @@ -239,24 +214,12 @@ Writer.prototype = { // }); }, - checkBundleUpToDate: function(bundle, lassoContext, callback) { + async checkBundleUpToDate (bundle, lassoContext) { ok(lassoContext, 'lassoContext is required'); - equal(typeof callback, 'function', 'callback function is required'); if (this.impl.checkBundleUpToDate) { - this.impl.checkBundleUpToDate(bundle, lassoContext, function(err, resourceInfo) { - if (err) { - return callback(err); - } - - if (resourceInfo === false) { - resourceInfo = null; - } - - return callback(null, resourceInfo); - }); - } else { - return callback(); + let resourceInfo = await this.impl.checkBundleUpToDate(bundle, lassoContext); + return resourceInfo === false ? null : resourceInfo; } }, @@ -281,23 +244,20 @@ Writer.prototype = { } }, - writeBundles: function(iteratorFunc, onBundleWrittenCallback, lassoContext, callback) { + async writeBundles (iteratorFunc, onBundleWrittenCallback, lassoContext) { ok(lassoContext, 'lassoContext is required'); - ok(callback, 'callback is required'); - - var _this = this; - var work = []; + let promise = Promise.resolve(); - iteratorFunc(function(bundle) { + iteratorFunc((bundle) => { if (bundle.hasContent()) { - work.push(function(callback) { - _this.writeBundle(bundle, onBundleWrittenCallback, lassoContext, callback); + promise = promise.then(() => { + return this.writeBundle(bundle, onBundleWrittenCallback, lassoContext); }); } }); - series(work, callback); + return promise; }, buildResourceCacheKey(cacheKey, lassoContext) { diff --git a/lib/writers/file-writer.js b/lib/writers/file-writer.js index b13487e8..14a7f1cb 100644 --- a/lib/writers/file-writer.js +++ b/lib/writers/file-writer.js @@ -6,12 +6,13 @@ require('raptor-polyfill/string/startsWith'); const MAX_FILE_LENGTH = 255; const HASH_OVERFLOW_LENGTH = 8; +const { promisify } = require('util'); var util = require('../util'); var nodePath = require('path'); var fs = require('fs'); var ok = require('assert').ok; var logger = require('raptor-logging').logger(module); -var mkdirp = require('mkdirp'); +var mkdirp = promisify(require('mkdirp')); var crypto = require('crypto'); var raptorAsync = require('raptor-async'); @@ -25,7 +26,7 @@ function filePathToUrlUnix(path) { function enforceFileLengthLimits(path) { return path.split(nodePath.sep).map(part => { - if(part.length < MAX_FILE_LENGTH) return part; + if (part.length < MAX_FILE_LENGTH) return part; var overflow = part.slice(MAX_FILE_LENGTH-HASH_OVERFLOW_LENGTH); var hash = crypto.createHash('sha1').update(overflow).digest('hex'); return part.slice(0, MAX_FILE_LENGTH-HASH_OVERFLOW_LENGTH) + hash.slice(0, HASH_OVERFLOW_LENGTH); @@ -43,9 +44,9 @@ var filePathToUrl = nodePath.sep === '/' ? filePathToUrlUnix : filePathToUrlWind * @return {String} The random characters with the specified length */ function randomStr(len) { - return crypto.randomBytes(Math.ceil(len/2)) + return crypto.randomBytes(Math.ceil(len / 2)) .toString('hex') // convert to hexadecimal format - .slice(0,len); // return required number of characters + .slice(0, len); // return required number of characters } /** @@ -56,7 +57,7 @@ function randomStr(len) { * * @param {Object} lassoContext An object with lassoContextual information needed to generate a URL */ -function Bundle_getUrl(lassoContext) { +function getBundleUrl(lassoContext) { var url = this.url; if (url) { @@ -78,62 +79,44 @@ function Bundle_getUrl(lassoContext) { url = urlPrefix + relPath; return url; } else { - var basePath = lassoContext.basePath ? nodePath.resolve(process.cwd(), lassoContext.basePath) : process.cwd(); + var basePath = lassoContext.basePath ? nodePath.resolve(process.cwd(), lassoContext.basePath) : process.cwd(); return filePathToUrl(nodePath.relative(basePath, outputFile)); } } -module.exports = function fileWriter(fileWriterConfig, lassoConfig) { - // The directory to place the built bundle and resource files - var outputDir = nodePath.resolve(process.cwd(), fileWriterConfig.outputDir || 'static'); - - // Boolean value to indicate if including fingerprints in the output files is enabled - // or not. - var fingerprintsEnabled = fileWriterConfig.fingerprintsEnabled !== false; - - // Optional URL prefix to use when generating URLs to the bundled files - var urlPrefix = fileWriterConfig.urlPrefix; - - // Boolean value to indicate if the target slot should be added to the output filename - // e.g. "head" or "body" - var includeSlotNames = fileWriterConfig.includeSlotNames; - - // If fingerprints are enabled then this flag will be used to determine how many characters - // the fingerprint should contain - var fingerprintLength = fileWriterConfig.fingerprintLength || 8; - - // Boolean value to indicate if CSS URLs should be relative - var relativeUrlsEnabled = fileWriterConfig.relativeUrlsEnabled; +/** + * Internal function help write out a file and to possibly generate a fingerprint + * in the process if fingerprints are enabled. + * + * On success, the callback will be invoked with an object that contains the following + * properties: + * - fingerprint: The string fingerprint if calculateFingerprint is set to true + * - outputFile: The output file. If calculateFingerprint is set to true then the fingerprint + * will be injected into the filename + * + * + * @param {ReadableStream} inStream The input stream to read from + * @param {string} outputFile The output file path + * @param {boolean} calculateFingerprint If true then a fingerprint will be calculated and passed to the callback + * @return void + */ +async function writeFile (inStream, outputFile, calculateFingerprint, fingerprintLength) { + var outputDir = nodePath.dirname(outputFile); + var done = false; - /** - * Internal function help write out a file and to possibly generate a fingerprint - * in the process if fingerprints are enabled. - * - * On success, the callback will be invoked with an object that contains the following - * properties: - * - fingerprint: The string fingerprint if calculateFingerprint is set to true - * - outputFile: The output file. If calculateFingerprint is set to true then the fingerprint - * will be injected into the filename - * - * - * @param {ReadableStream} inStream The input stream to read from - * @param {string} outputFile The output file path - * @param {boolean} calculateFingerprint If true then a fingerprint will be calculated and passed to the callback - * @param {Function} callback The callback function. - * @return void - */ - function writeFile(inStream, outputFile, calculateFingerprint, callback) { - var outputDir = nodePath.dirname(outputFile); + await mkdirp(outputDir); - var done = false; + var outStream; + var tempFile = outputFile + '.' + process.pid + '.' + randomStr(4); + return new Promise((resolve, reject) => { function handleError(err) { if (done) { return; } done = true; - callback(err); + reject(err); } function handleSuccess(result) { @@ -142,107 +125,116 @@ module.exports = function fileWriter(fileWriterConfig, lassoConfig) { } done = true; - callback(null, result); + resolve(result); } - mkdirp(outputDir, function(err) { - - if (err) { - return handleError(err); - } - - var outStream; + if (calculateFingerprint) { + logger.debug(`Writing bundle to temp file ${tempFile}... (calculating fingerprint)`); + // Pipe the stream to a temporary file and when the fingerprint is known, + // rename the file to include the known fingerprint + var fingerprint = fingerprint; + outStream = fs.createWriteStream(tempFile); + var fingerprintStream = util.createFingerprintStream(); - var tempFile = outputFile + '.' + process.pid + '.' + randomStr(4); + outStream + .on('close', function() { + if (done) { + return; + } - if (calculateFingerprint) { - logger.debug(`Writing bundle to temp file ${ tempFile }... (calculating fingerprint)`); + if (fingerprintLength && fingerprint.length > fingerprintLength) { + fingerprint = fingerprint.substring(0, fingerprintLength); + } - // Pipe the stream to a temporary file and when the fingerprint is known, - // rename the file to include the known fingerprint + var ext = nodePath.extname(outputFile); + outputFile = outputFile.slice(0, 0 - ext.length) + '-' + fingerprint + ext; - var fingerprint = fingerprint; - outStream = fs.createWriteStream(tempFile); - var fingerprintStream = util.createFingerprintStream(); - - outStream - .on('close', function() { - if (done) { - return; + fs.exists(outputFile, function(exists) { + if (exists) { + // If it already exists then just use that file, but delete the temp file + fs.unlink(tempFile, function() { + handleSuccess({ + fingerprint: fingerprint, + outputFile: outputFile + }); + }); + } else { + fs.rename(tempFile, outputFile, function(err) { + if (err && !fs.existsSync(outputFile)) { + return handleError(err); + } + + handleSuccess({ + fingerprint: fingerprint, + outputFile: outputFile + }); + }); } + }); + }); + + fingerprintStream + .on('fingerprint', function(_fingerprint) { + fingerprint = _fingerprint; + }) + .on('error', handleError) + .pipe(outStream); - if (fingerprintLength && fingerprint.length > fingerprintLength) { - fingerprint = fingerprint.substring(0, fingerprintLength); + inStream + .on('error', handleError) + .pipe(fingerprintStream); + } else { + logger.debug(`Writing bundle to temp file ${tempFile}... (no fingerprint)`); + + // No fingerprint is needed so simply pipe out the input stream + // to the output file + outStream = fs.createWriteStream(tempFile); + + inStream + .on('error', handleError) + .pipe(outStream) + .on('close', function() { + if (done) { + return; + } + + fs.rename(tempFile, outputFile, function(err) { + if (err && !fs.existsSync(outputFile)) { + return handleError(err); } - var ext = nodePath.extname(outputFile); - outputFile = outputFile.slice(0, 0-ext.length) + '-' + fingerprint + ext; - - fs.exists(outputFile, function(exists) { - if (exists) { - // If it already exists then just use that file, but delete the temp file - fs.unlink(tempFile, function() { - handleSuccess({ - fingerprint: fingerprint, - outputFile: outputFile - }); - }); - } else { - fs.rename(tempFile, outputFile, function(err) { - if (err && !fs.existsSync(outputFile)) { - return handleError(err); - } - - handleSuccess({ - fingerprint: fingerprint, - outputFile: outputFile - }); - }); - } + handleSuccess({ + outputFile: outputFile }); - }); + }); + } + }); +} - fingerprintStream - .on('fingerprint', function(_fingerprint) { - fingerprint = _fingerprint; - }) - .on('error', handleError) - .pipe(outStream); - - inStream - .on('error', handleError) - .pipe(fingerprintStream); - } else { - logger.debug(`Writing bundle to temp file ${ tempFile }... (no fingerprint)`); - - // No fingerprint is needed so simply pipe out the input stream - // to the output file - outStream = fs.createWriteStream(tempFile); - - inStream - .on('error', handleError) - .pipe(outStream) - .on('close', function() { - if (done) { - return; - } +module.exports = function fileWriter(fileWriterConfig, lassoConfig) { + // The directory to place the built bundle and resource files + var outputDir = nodePath.resolve(process.cwd(), fileWriterConfig.outputDir || 'static'); - fs.rename(tempFile, outputFile, function(err) { - if (err && !fs.existsSync(outputFile)) { - return handleError(err); - } + // Boolean value to indicate if including fingerprints in the output files is enabled + // or not. + var fingerprintsEnabled = fileWriterConfig.fingerprintsEnabled !== false; - handleSuccess({ - outputFile: outputFile - }); - }); - }); - } - }); - } + // Optional URL prefix to use when generating URLs to the bundled files + var urlPrefix = fileWriterConfig.urlPrefix; + + // Boolean value to indicate if the target slot should be added to the output filename + // e.g. "head" or "body" + var includeSlotNames = fileWriterConfig.includeSlotNames; + + // If fingerprints are enabled then this flag will be used to determine how many characters + // the fingerprint should contain + var fingerprintLength = fileWriterConfig.fingerprintLength || 8; + + // Boolean value to indicate if CSS URLs should be relative + var relativeUrlsEnabled = fileWriterConfig.relativeUrlsEnabled; /** * Calculate the output file for a given bundle given @@ -323,7 +315,6 @@ module.exports = function fileWriter(fileWriterConfig, lassoConfig) { outputPath = nodePath.join(outputDir, relativePath); } - if (!outputPath) { ok(filename, '"filename" or "sourceFile" expected'); outputPath = nodePath.join(outputDir, filename.replace(/^\//, '').replace(/[^A-Za-z0-9_\-\.]/g, '-')); @@ -349,7 +340,6 @@ module.exports = function fileWriter(fileWriterConfig, lassoConfig) { nameNoExt += '-' + slotName; } - basename = nameNoExt; if (ext) { basename += '.' + ext; @@ -381,7 +371,7 @@ module.exports = function fileWriter(fileWriterConfig, lassoConfig) { } return urlPrefix + relPath; } else { - basePath = lassoContext.basePath ? nodePath.resolve(process.cwd(), lassoContext.basePath) : process.cwd(); + basePath = lassoContext.basePath ? nodePath.resolve(process.cwd(), lassoContext.basePath) : process.cwd(); return filePathToUrl(nodePath.relative(basePath, path)); } } @@ -395,12 +385,10 @@ module.exports = function fileWriter(fileWriterConfig, lassoConfig) { * * @param {lasso/lib/Bundle} The bundle instance * @param {Object} Contextual information - * @param {Function} callback The callback * @return {[type]} [description] */ - checkBundleUpToDate: function(bundle, lassoContext, callback) { - callback(null, false); - + async checkBundleUpToDate (bundle, lassoContext) { + return false; // NOTE: We used to do a last modified check based on file modified datas, // but there were edge cases that caused problem. For example, even though // none of the files in the bundle were modified, a separate file that impacts @@ -416,18 +404,15 @@ module.exports = function fileWriter(fileWriterConfig, lassoConfig) { var outputFile = getOutputFileForResource(path, fingerprintsEnabled, lassoContext); var work = { - sourceLastModified: function(callback) { - lassoContext.getFileLastModified(path, callback); + async sourceLastModified () { + return lassoContext.getFileLastModified(path); }, - outputLastModified: function(callback) { - lassoContext.getFileLastModified(outputFile, callback); + async outputLastModified (callback) { + return lassoContext.getFileLastModified(outputFile); } }; - raptorAsync.parallel(work, function(err, results) { - //console.log(module.id, 'resource update-to-date'.magenta, Date.now() - ts, 'ms', path.grey); - if (err) { return callback(err); } @@ -448,75 +433,78 @@ module.exports = function fileWriter(fileWriterConfig, lassoConfig) { }); }, - writeBundle: function(reader, lassoContext, callback) { - var input = reader.readBundle(); - var bundle = lassoContext.bundle; - - ok(input, '"input" is required'); - ok(bundle, '"bundle" is required'); - - function handleError(e) { - callback(e); - } - - input.on('error', handleError); - - var calculateFingerprint = bundle.config.fingerprintsEnabled; - if (calculateFingerprint === undefined) { - calculateFingerprint = fingerprintsEnabled; - } - - calculateFingerprint = calculateFingerprint === true && !bundle.getFingerprint(); + async writeBundle (reader, lassoContext) { + return new Promise((resolve, reject) => { + var input = reader.readBundle(); + var bundle = lassoContext.bundle; - var outputFile = getOutputFileForBundle(bundle); + ok(input, '"input" is required'); + ok(bundle, '"bundle" is required'); - logger.debug('Writing bundle "' + bundle.getLabel() + '" to file "' + outputFile + '"...'); + input.on('error', reject); - writeFile(input, outputFile, calculateFingerprint, function(err, result) { - if (err) { - logger.debug('Writing bundle "' + bundle.getLabel() + '" to file "' + outputFile + '" FAILED! - Error:', err); - return handleError(err); + var calculateFingerprint = bundle.config.fingerprintsEnabled; + if (calculateFingerprint === undefined) { + calculateFingerprint = fingerprintsEnabled; } - logger.debug('Writing bundle "' + bundle.getLabel() + '" to file "' + outputFile + '" COMPLETED'); - - bundle.setFingerprint(result.fingerprint); - bundle.setWritten(true); - bundle.getUrl = Bundle_getUrl; - bundle.urlPrefix = urlPrefix; - bundle.outputDir = outputDir; - bundle.outputFile = result.outputFile; - callback(); + + calculateFingerprint = calculateFingerprint === true && !bundle.getFingerprint(); + + var outputFile = getOutputFileForBundle(bundle); + + logger.debug('Writing bundle "' + bundle.getLabel() + '" to file "' + outputFile + '"...'); + + writeFile(input, outputFile, calculateFingerprint, fingerprintLength) + .then((result) => { + logger.debug('Writing bundle "' + bundle.getLabel() + '" to file "' + outputFile + '" COMPLETED'); + bundle.setFingerprint(result.fingerprint); + bundle.setWritten(true); + bundle.getUrl = getBundleUrl; + bundle.urlPrefix = urlPrefix; + bundle.outputDir = outputDir; + bundle.outputFile = result.outputFile; + resolve(); + }).catch((err) => { + logger.debug('Writing bundle "' + bundle.getLabel() + '" to file "' + outputFile + '" FAILED! - Error:', err); + reject(err); + }); }); }, - writeResource: function(reader, lassoContext, callback) { - var input = reader.readResource(); - var path = lassoContext.path; - - ok(input, '"input" is required'); - ok(input, '"path" is required'); + async writeResource (reader, lassoContext) { + let done = false; - function handleError(e) { - callback(e); - } + const input = reader.readResource(); + const path = lassoContext.path; - input.on('error', handleError); + ok(input, '"input" is required'); + ok(path, '"path" is required'); - var calculateFingerprint = fingerprintsEnabled === true; + return new Promise((resolve, reject) => { + function handleError (err) { + if (done) { + return; + } - writeFile(input, getOutputFileForResource(path, calculateFingerprint, lassoContext), calculateFingerprint, function(err, result) { - if (err) { - handleError(err); - return; + done = true; + reject(err); } - var outputFile = result.outputFile; - - var url = getResourceUrl(outputFile, lassoContext); - callback(null, { - url: url, - outputFile: outputFile - }); + input.on('error', handleError); + + const calculateFingerprint = fingerprintsEnabled === true; + const outputFileForResource = getOutputFileForResource(path, calculateFingerprint, lassoContext); + + writeFile( + input, + outputFileForResource, + calculateFingerprint, + fingerprintLength) + .then((result) => { + const outputFile = result.outputFile; + const url = getResourceUrl(outputFile, lassoContext); + resolve({ url, outputFile }); + }).catch(handleError); }); } }; diff --git a/package.json b/package.json index 1a965c61..aa4ef897 100644 --- a/package.json +++ b/package.json @@ -15,8 +15,8 @@ "dependencies": { "app-module-path": "^1.1.0", "app-root-dir": "^1.0.2", - "async": "^0.9.2", "assert": "^1.1.2", + "async": "^0.9.2", "browser-refresh-client": "^1.1.4", "buffer": "^4.5.1", "clone": "^0.1.19", @@ -65,6 +65,12 @@ "babel-register": "^6.5.2", "chai": "^3.5.0", "deamdify": "^0.1.1", + "eslint": "^4.4.1", + "eslint-config-standard": "^10.2.1", + "eslint-plugin-import": "^2.7.0", + "eslint-plugin-node": "^5.1.1", + "eslint-plugin-promise": "^3.5.0", + "eslint-plugin-standard": "^3.0.1", "fs-extra": "~0.12.0", "jshint": "^2.9.1", "lasso-marko": "^2.2.2", diff --git a/taglib-marko2/LassoRenderContext.js b/taglib-marko2/LassoRenderContext.js deleted file mode 100644 index 446a40d0..00000000 --- a/taglib-marko2/LassoRenderContext.js +++ /dev/null @@ -1,65 +0,0 @@ -var lasso = require('../'); - -var EventEmitter = require('events').EventEmitter; - -var LassoRenderContext = function(out) { - LassoRenderContext.$super.call(this); - - this._waitFor = []; - this.data = {}; - this.out = out; -}; - -LassoRenderContext.prototype = { - onBeforeSlot: function(slotName, cb) { - this.on('beforeSlot.' + slotName, cb); - }, - - onAfterSlot: function(slotName, cb) { - this.on('afterSlot.' + slotName, cb); - }, - - emitBeforeSlot: function(slotName, context) { - this.emit('beforeSlot.' + slotName, { - context: context, - slotName: slotName - }); - }, - - emitAfterSlot: function(slotName, context) { - this.emit('afterSlot.' + slotName, { - context: context, - slotName: slotName - }); - }, - - waitFor: function(promise) { - if (!promise) { - throw new Error('Invalid waitFor promise'); - } - - if (Array.isArray(promise)) { - this._waitFor = this._waitFor.concat(promise); - } - else { - this._waitFor.push(promise); - } - }, - - getWaitFor: function() { - return this._waitFor; - }, - - getLasso: function() { - return this.data.lasso || this.out.global.lasso || lasso.defaultLasso; - }, - - getLassoConfig: function() { - var theLasso = this.getLasso(); - return theLasso.config; - } -}; - -require('raptor-util').inherit(LassoRenderContext, EventEmitter); - -module.exports = LassoRenderContext; \ No newline at end of file diff --git a/taglib-marko2/body-tag.js b/taglib-marko2/body-tag.js deleted file mode 100644 index 941940f9..00000000 --- a/taglib-marko2/body-tag.js +++ /dev/null @@ -1,11 +0,0 @@ -var slotTag = require('./slot-tag'); -var extend = require('raptor-util/extend'); - -const SLOT_DEFAULTS = { - name: 'body' -}; - -module.exports = function render(input, out) { - var slotTagInput = Object.create(SLOT_DEFAULTS); - slotTag(extend(slotTagInput, input), out); -}; diff --git a/taglib-marko2/dependencies-tag.js b/taglib-marko2/dependencies-tag.js deleted file mode 100644 index b72b03df..00000000 --- a/taglib-marko2/dependencies-tag.js +++ /dev/null @@ -1,5 +0,0 @@ -module.exports = function render(input, out) { - if (input.renderBody) { - input.renderBody(out); - } -}; \ No newline at end of file diff --git a/taglib-marko2/dependency-tag.js b/taglib-marko2/dependency-tag.js deleted file mode 100644 index 56123215..00000000 --- a/taglib-marko2/dependency-tag.js +++ /dev/null @@ -1,14 +0,0 @@ -var extend = require('raptor-util').extend; - -module.exports = function render(input, context) { - var dependenciesParent = input.dependenciesParent; - if (!dependenciesParent) { - throw new Error('Expected property "dependenciesParent"'); - } - - delete input.dependenciesParent; - - var dependency = extend({}, input['*']); - - dependenciesParent.addDependency(dependency); -}; \ No newline at end of file diff --git a/taglib-marko2/getImageInfo-node.js b/taglib-marko2/getImageInfo-node.js deleted file mode 100644 index 4a1bbee8..00000000 --- a/taglib-marko2/getImageInfo-node.js +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2011 eBay Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -'use strict'; -var getImageInfoHelperPath = require.resolve('./helper-getImageInfo'); - -function GetImageInfo(props) { - GetImageInfo.$super.call(this); - if (props) { - this.setProperties(props); - } -} -GetImageInfo.prototype = { - doGenerateCode: function (template) { - var varName = this.getProperty('var'); - - var getImageInfoRequirePath = template.getRequirePath(getImageInfoHelperPath); - - template.addStaticVar('__getImageInfo', - - 'require("' + getImageInfoRequirePath + '")'); - - var path = this.getProperty('path'); - - var funcCall = '__getImageInfo(out, ' + path + ', function(out, ' + varName + ') {'; - template.statement(funcCall).indent(function() { - this.generateCodeForChildren(template); - }, this).line('});'); - } -}; - -module.exports = GetImageInfo; diff --git a/taglib-marko2/head-tag.js b/taglib-marko2/head-tag.js deleted file mode 100644 index 225854d5..00000000 --- a/taglib-marko2/head-tag.js +++ /dev/null @@ -1,11 +0,0 @@ -var slotTag = require('./slot-tag'); -var extend = require('raptor-util/extend'); - -const SLOT_DEFAULTS = { - name: 'head' -}; - -module.exports = function render(input, out) { - var slotTagInput = Object.create(SLOT_DEFAULTS); - slotTag(extend(slotTagInput, input), out); -}; diff --git a/taglib-marko2/helper-getImageInfo.js b/taglib-marko2/helper-getImageInfo.js deleted file mode 100644 index 92480dbc..00000000 --- a/taglib-marko2/helper-getImageInfo.js +++ /dev/null @@ -1,18 +0,0 @@ -var util = require('./util'); -var lassoImage = require('lasso-image'); - -module.exports = function(out, path, callback) { - var asyncOut = out.beginAsync(); - - var lassoRenderContext = util.getLassoRenderContext(out); - var theLasso = lassoRenderContext.lasso; - - lassoImage.getImageInfo(path, { lasso: theLasso }, function(err, imageInfo) { - if (err) { - return asyncOut.error(err); - } - - callback(asyncOut, imageInfo); - asyncOut.end(); - }); -}; \ No newline at end of file diff --git a/taglib-marko2/helper-getNonce.js b/taglib-marko2/helper-getNonce.js deleted file mode 100644 index 42b8ca41..00000000 --- a/taglib-marko2/helper-getNonce.js +++ /dev/null @@ -1,11 +0,0 @@ -var util = require('./util'); - -module.exports = function(out) { - var lassoRenderContext = util.getLassoRenderContext(out); - var lassoConfig = lassoRenderContext.getLassoConfig(); - - var cspNonceProvider = lassoConfig.cspNonceProvider; - if (cspNonceProvider) { - return cspNonceProvider(out, lassoRenderContext); - } -}; \ No newline at end of file diff --git a/taglib-marko2/lasso-img-tag-transformer.js b/taglib-marko2/lasso-img-tag-transformer.js deleted file mode 100644 index 67976de8..00000000 --- a/taglib-marko2/lasso-img-tag-transformer.js +++ /dev/null @@ -1,27 +0,0 @@ -module.exports = function transform(node, compiler, template) { - if (node.tagName === 'lasso-img') { - var nextVarId = template.data.nextGetImageInfoVarId || (template.data.nextGetImageInfoVarId = 1); - var varName = 'imageInfo' + nextVarId; - var src = node.getProperty('src'); - - node.tagName = 'img'; - - var getImageInfoNode = compiler.createNode('_lasso-getImageInfo', { - 'var': varName, - path: src - }); - - node.setAttribute('src', template.makeExpression(varName + '.url')); - - if (!node.hasAttribute('width')) { - node.setAttribute('width', template.makeExpression(varName + '.width')); - } - - if (!node.hasAttribute('height')) { - node.setAttribute('height', template.makeExpression(varName + '.height')); - } - - node.parentNode.replaceChild(getImageInfoNode, node); - getImageInfoNode.appendChild(node); - } -}; \ No newline at end of file diff --git a/taglib-marko2/lasso-nonce-attr-transformer.js b/taglib-marko2/lasso-nonce-attr-transformer.js deleted file mode 100644 index eaad0299..00000000 --- a/taglib-marko2/lasso-nonce-attr-transformer.js +++ /dev/null @@ -1,16 +0,0 @@ -var getNonceHelperPath = require.resolve('./helper-getNonce'); - -module.exports = function transform(node, compiler, template) { - if (node.hasAttribute('lasso-nonce')) { - - node.removeAttribute('lasso-nonce'); - - var getNonceRequirePath = template.getRequirePath(getNonceHelperPath); - - template.addStaticVar('__getNonce', - - 'require("' + getNonceRequirePath + '")'); - - node.setAttribute('nonce', template.makeExpression('__getNonce(out)')); - } -}; \ No newline at end of file diff --git a/taglib-marko2/lasso-resource-tag-transformer.js b/taglib-marko2/lasso-resource-tag-transformer.js deleted file mode 100644 index 800d9598..00000000 --- a/taglib-marko2/lasso-resource-tag-transformer.js +++ /dev/null @@ -1,78 +0,0 @@ -/** -* This method walks up the tree from the provided node to find the -* root "_lasso-resources-root" node. The root node is what asynchronously -* loads all of the bundles and asynchronously renders the body. If a -* root "_lasso-resources-root" node is not found then a new one is created -* and made to be a child of the true root. All of the child nodes -* of the actual root node are moved to children of the newly created -* node. -* -* @param node Node to search form -* @param compiler Used to create the node if it is not found. -*/ -function findRootResourcesNode(node, compiler) { - if (node.isRoot()) { - if (node.data.lassoResourcesNode) { // Is a "_lasso-resources-root" already associated with the root node? - // If so then use that node - return node.data.lassoResourcesNode; - } else { - // Otherwise, create a new "_lasso-resources-root" node - var rootResourcesNode = - node.data.lassoResourcesNode = - compiler.createTagHandlerNode('_lasso-resources-root'); - - // *Move* all of the existing children of the root node to this node - // NOTE: A node can only have one parent so an appendChild will move the node to the new parent - node.forEachChild(function (childNode) { - // Make the node that used to be a child of the root node, a child of the 'lasso-resources' node - rootResourcesNode.appendChild(childNode); - }); - - // Now make the new "_lasso-resources" node the only child of the root node - node.appendChild(rootResourcesNode); - - // Keep up with each bundles need to be loaded in order to render the template - var pathExpressionArray = []; - var pathsExpression = function () { // This function will be called at code generation time - // to produce the expression for the "paths" property - // Convert the used bundle names to an Array expression - return compiler.makeExpression('[' + pathExpressionArray.join(', ') + ']'); - }; - - rootResourcesNode.setProperty('paths', pathsExpression); - - // Add a helper method to the data object that can be used to add additional bundle - // dependencies to the root use node - rootResourcesNode.data.addPath = function addPath(varName, pathExpression) { - // We will introduced variables by adding parameters to the compiled function that - // is used to render the body. - rootResourcesNode.addNestedVariable(varName); - - // Keep track of all of the expressions that are used to refer to bundles - pathExpressionArray.push(pathExpression.toString()); - }; - - // Return the newly created "_lasso-resources-root" node - return rootResourcesNode; - } - } else { - return findRootResourcesNode(node.parentNode, compiler); - } -} - -module.exports = function transform(node, compiler, builder) { - - // Get or create the root "_lasso-resources-root" node - var rootResourcesNode = findRootResourcesNode(node, compiler); - - if (node.tagName === 'lasso-resource') { - var varName = node.getAttribute('var'); - var bundleName = node.getProperty('path'); - - // NOTE: bundleName is actually a JavaScript expression represented as a String - rootResourcesNode.data.addPath(varName, bundleName); - - // Remove this node out of the tree since it is no longer needed - node.parentNode.removeChild(node); - } -}; \ No newline at end of file diff --git a/taglib-marko2/lasso-resource-tag.js b/taglib-marko2/lasso-resource-tag.js deleted file mode 100644 index ca16259f..00000000 --- a/taglib-marko2/lasso-resource-tag.js +++ /dev/null @@ -1,18 +0,0 @@ -'use strict'; -function ResourceTag(props) { - ResourceTag.$super.call(this, 'lasso-resource'); - if (props) { - this.setProperties(props); - } -} - -ResourceTag.nodeType = 'element'; - -ResourceTag.prototype = { - doGenerateCode: function (template) { - // This is a dummy instance that will get removed by the transform - throw new Error('Node should not be in tree after transform'); - } -}; - -module.exports = ResourceTag; \ No newline at end of file diff --git a/taglib-marko2/lasso-resources-root-tag.js b/taglib-marko2/lasso-resources-root-tag.js deleted file mode 100644 index 92c5210d..00000000 --- a/taglib-marko2/lasso-resources-root-tag.js +++ /dev/null @@ -1,62 +0,0 @@ -var async = require('async'); - -var util = require('./util'); - -module.exports = function render(input, out) { - var renderBody = input.renderBody; - - if (!renderBody) { - return; - } - - var lassoRenderContext = util.getLassoRenderContext(out); - var theLasso = input.lasso || lassoRenderContext.getLasso(); - - var lassoContext = lassoRenderContext.data.lassoContext; - - if (!lassoContext) { - lassoContext = lassoRenderContext.data.lassoContext = theLasso.createLassoContext({}); - lassoContext.renderContext = out; - } - - var paths = input.paths; - var asyncOut = null; - var done = false; - - function doRenderBody(err, bundledResources) { - done = true; - // When invoking the body we are going to either render to the async out (if - // one or more bundles needed to be asynchronously loaded) or the original - // out if all bundles were able to be loaded synchronously - var targetOut = asyncOut || out; - - if (err) { - // If bundle loading failed then emit the error on the async writer - return targetOut.error(err); - } else { - // Otherwise, all of the bundles have been loaded and we are ready to invoke - // the body function. The first argument will always be the "out" that - // all of the code will render to and the remaining arguments will be the loaded - // bundles in the order that maps to the associated variables that were found at - // compile time - renderBody.apply(this, [targetOut].concat(bundledResources)); - } - - if (asyncOut) { - // If we did start asynchronous writer then we need to end it now - asyncOut.end(); - } - } - - - async.map( - paths, - function(path, callback) { - theLasso.lassoResource(path, lassoContext, callback); - }, - doRenderBody); - - if (!done) { - asyncOut = out.beginAsync({ name: 'lasso-resources:' + paths.join(',')}); - } -}; diff --git a/taglib-marko2/page-tag-transformer.js b/taglib-marko2/page-tag-transformer.js deleted file mode 100644 index 420426d7..00000000 --- a/taglib-marko2/page-tag-transformer.js +++ /dev/null @@ -1,43 +0,0 @@ - -module.exports = function transform(node, compiler, template) { - function convertDependencyTags(parent) { - parent.forEachChild(function(child) { - if (child.isElementNode() && !child.uri) { - // Convert unnamespaced element nodes to "DependencyTag" nodes - - child.tag = compiler.taglibs.getTag('lasso-dependency'); - - if (child.localName !== 'dependency') { - child.setProperty('type', child.localName); - } - - child.forEachAttributeNS('', function(attr) { - var value = attr.value; - if (value === 'true') { - value = true; - } - else if (value === 'false') { - value = false; - } - else { - value = compiler.convertType(value, 'string', true /* allow expressins */); - } - - child.setProperty(attr.localName, value); - }); - - child.removeAttributesNS(''); - } - else { - convertDependencyTags(child); - } - }); - } - - node.forEachChild(function(child) { - if (!child.uri && (child.tagName === 'dependencies' || child.tagName === 'includes')) { - child.tag = compiler.taglibs.getTag('lasso-dependencies'); - convertDependencyTags(child); - } - }, this); -}; \ No newline at end of file diff --git a/taglib-marko2/page-tag.js b/taglib-marko2/page-tag.js deleted file mode 100644 index 5d80db8b..00000000 --- a/taglib-marko2/page-tag.js +++ /dev/null @@ -1,164 +0,0 @@ -var util = require('./util'); -var logger = require('raptor-logging').logger(module); -var raptorPromises = require('raptor-promises'); -var nodePath = require('path'); -var fs = require('fs'); -var AsyncValue = require('raptor-async/AsyncValue'); -var extend = require('raptor-util/extend'); - -module.exports = function render(input, out) { - var lassoRenderContext = util.getLassoRenderContext(out); - var theLasso = input.lasso || lassoRenderContext.getLasso(); - - var pageName = input.name || input.pageName; - var cacheKey = input.cacheKey; - - if (!pageName && input.dirname) { - if (input.dirname) { - // Use the base name of the containing directory as the page name - // Example: "myapp/src/pages/welcome/index.marko" --> "welcome" - pageName = nodePath.basename(input.dirname); - } - } - - if (!cacheKey) { - cacheKey = input.filename || pageName; // Use the filename of the template as the cache key - } - - // We need to provide the lasso with some data that it might need - // to build the page correctly. We provide "renderContext", specifically, - // because the "renderContext" also holds a response to the output stream - // which may be the HTTP response object. From the HTTP response object - // we can get to the HTTP request. From the HTTP request we can get to the user - // locale and the protocol (e.g. "http" versus "https") and all of this information - // may be needed to build the page correctly. Ultimately, during the optimization - // phase, this data can be access using the "lassoContext.data" property - var lassoContextData = { - renderContext: out - }; - - // The user of the tag may have also provided some additional data to add - // to the lasso context - var inputData = input.data; - if (inputData) { - extend(lassoContextData, inputData); - } - - // Store the theLasso into the render context in case it is needed - // later (e.g. to bundle a image resource referenced by a tag). - lassoRenderContext.data.lasso = theLasso; - - var lassoPageResultAsyncValue; - - // store lassoed page data holder in the context data (used by slot tags) - lassoRenderContext.data.lassoPageResult = lassoPageResultAsyncValue = new AsyncValue(); - lassoRenderContext.data.timeout = input.timeout || 30000 /* 30s */; - - function done(err, lassoPageResult) { - if (err) { - lassoPageResultAsyncValue.reject(err); - } else { - lassoPageResultAsyncValue.resolve(lassoPageResult); - } - } - - function doLassoPage() { - - theLasso.lassoPage({ - // Make sure the page is cached (should be the default) - cache: true, - - cacheKey: cacheKey, - - // the page name (used for naming output bundles associated with this page) - pageName: pageName, - - // properties for the lasso context - data: lassoContextData, - - // Provide base path for resolving relative top-level dependencies - from: input.module || input.dirname, - - // what is this for? - basePath: input.basePath, - - // extensions to be enabled at time of rendering - flags: input.flags || input.enabledExtensions || input.extensions, - - dependencies: function(callback) { - var dependencies = input.dependencies; - var packagePath = input.packagePath; - var packagePaths = input.packagePaths; - - if (packagePath) { - if (input.dirname) { - packagePath = nodePath.resolve(input.dirname, packagePath); - } - - dependencies = [ - { - type: 'package', - 'path': packagePath - } - ]; - } else if (dependencies) { - - } else if (packagePaths) { - dependencies = packagePaths.map(function(path) { - return { - type: 'package', - path: path - }; - }); - } else if (input.getDependencies) { - dependencies = []; - input.getDependencies({ - addDependency: function(dependency) { - dependencies.push(dependency); - } - }); - } else { - // Look for an browser.json in the same directory - if (input.dirname) { - packagePath = nodePath.join(input.dirname, 'browser.json'); - if (fs.existsSync(packagePath)) { - dependencies = [ - { - type: 'package', - path: packagePath - } - ]; - } - } - } - - if (!dependencies && !packagePath && !packagePaths) { - dependencies = []; - } - - callback(null, dependencies); - } - }, - done); - } - - var waitFor = lassoRenderContext.getWaitFor(); - - if (input.waitFor) { - if (waitFor) { - waitFor.push(input.waitFor); - } else { - waitFor = [input.waitFor]; - } - } - - if (waitFor && waitFor.length) { - logger.debug('Waiting for ' + waitFor.length + ' promise(s) to complete before optimizing page.'); - raptorPromises.all(waitFor) - .then(doLassoPage) - .done(); - } - else { - doLassoPage(); - } -}; diff --git a/taglib-marko2/slot-tag.js b/taglib-marko2/slot-tag.js deleted file mode 100644 index 24a77df8..00000000 --- a/taglib-marko2/slot-tag.js +++ /dev/null @@ -1,76 +0,0 @@ -'use strict'; - -var util = require('./util'); -var extend = require('raptor-util').extend; - -function isAttributePresent(input) { - return !!(input.inlineStyleAttrs || - input.inlineScriptAttrs || - input.externalStyleAttrs || - input.externalScriptAttrs); -} - -function renderSlot(input, lassoPageResult, out, lassoRenderContext) { - var lassoConfig = lassoRenderContext.getLassoConfig(); - - var cspNonceProvider = lassoConfig.cspNonceProvider; - var slotName = input.name; - var cspAttrs = null; - var slotData = null; - - if (cspNonceProvider) { - cspAttrs = { - nonce: cspNonceProvider(out) - }; - } - if (isAttributePresent(input) || cspAttrs) { - slotData = { - inlineScriptAttrs: extend(extend({}, input.inlineScriptAttrs), cspAttrs), - inlineStyleAttrs: extend(extend({}, input.inlineStyleAttrs), cspAttrs), - externalScriptAttrs: extend({}, input.externalScriptAttrs), - externalStyleAttrs: extend({}, input.externalStyleAttrs) - }; - } - - var slotHtml = lassoPageResult.getSlotHtml(slotName, slotData); - - if (slotHtml) { - out.write(slotHtml); - } - - lassoRenderContext.emitAfterSlot(slotName, out); -} - -module.exports = function render(input, out) { - - - var slotName = input.name; - var lassoRenderContext = util.getLassoRenderContext(out); - var lassoPageResultAsyncValue = lassoRenderContext.data.lassoPageResult; - var timeout = lassoRenderContext.data.timeout; - - if (!lassoPageResultAsyncValue) { - throw new Error('Lasso page result not found for slot "' + slotName + '". The tag should be used to lasso the page.'); - } - - lassoRenderContext.emitBeforeSlot(slotName, out); - - if (lassoPageResultAsyncValue.isResolved()) { - renderSlot(input, lassoPageResultAsyncValue.data, out, lassoRenderContext); - } else { - var asyncContext = out.beginAsync({ - name: 'lasso-slot:' + slotName, - timeout: timeout - }); - - lassoPageResultAsyncValue.done(function(err, lassoPageResult) { - if (err) { - asyncContext.error(err); - return; - } - - renderSlot(input, lassoPageResult, asyncContext, lassoRenderContext); - asyncContext.end(); - }); - } -}; diff --git a/taglib-marko2/util.js b/taglib-marko2/util.js deleted file mode 100644 index 250019b2..00000000 --- a/taglib-marko2/util.js +++ /dev/null @@ -1,10 +0,0 @@ -var LassoRenderContext = require('./LassoRenderContext'); -var CONTEXT_KEY = 'lasso/LassoRenderContext'; - -function getLassoRenderContext(out) { - var data = out.global; - return data[CONTEXT_KEY] || - (data[CONTEXT_KEY] = new LassoRenderContext(out)); -} - -exports.getLassoRenderContext = getLassoRenderContext; \ No newline at end of file diff --git a/taglib/helper-getImageInfo.js b/taglib/helper-getImageInfo.js index 30a558dd..2e4d0828 100644 --- a/taglib/helper-getImageInfo.js +++ b/taglib/helper-getImageInfo.js @@ -10,7 +10,6 @@ module.exports = function(out, path, callback) { lassoImage.getImageInfo(path, { lasso: theLasso, renderContext: out }, function(err, imageInfo) { done = true; - if (err) return targetOut.error(err); callback(targetOut, imageInfo); @@ -23,4 +22,4 @@ module.exports = function(out, path, callback) { if (!done) { targetOut = out.beginAsync(); } -}; \ No newline at end of file +}; diff --git a/taglib/lasso-resources-root-tag.js b/taglib/lasso-resources-root-tag.js index 19df05c0..a9f82266 100644 --- a/taglib/lasso-resources-root-tag.js +++ b/taglib/lasso-resources-root-tag.js @@ -1,8 +1,7 @@ -var async = require('async'); +const async = require('async'); +const getLassoRenderContext = require('./getLassoRenderContext'); -var getLassoRenderContext = require('./getLassoRenderContext'); - -module.exports = function render(input, out) { +module.exports = function render (input, out) { var renderBody = input.renderBody; if (!renderBody) { @@ -16,7 +15,6 @@ module.exports = function render(input, out) { throw new Error('Page lasso not configured for application. Use require("lasso").configureDefault(config) to configure the default page lasso or provide an lasso as input using the "lasso" attribute.'); } - var lassoContext = lassoRenderContext.data.lassoContext; if (!lassoContext) { @@ -28,7 +26,7 @@ module.exports = function render(input, out) { var asyncOut = null; var done = false; - function doRenderBody(err, bundledResources) { + function doRenderBody (err, bundledResources) { done = true; // When invoking the body we are going to either render to the async out (if // one or more bundles needed to be asynchronously loaded) or the original @@ -53,11 +51,16 @@ module.exports = function render(input, out) { } } - + // TODO: Change to fully use async/await async.map( paths, - function(path, callback) { - theLasso.lassoResource(path, lassoContext, callback); + async function (path, callback) { + try { + const lassoResourceResult = await theLasso.lassoResource(path, lassoContext); + callback(null, lassoResourceResult); + } catch (err) { + callback(err); + } }, doRenderBody); diff --git a/taglib/page-tag.js b/taglib/page-tag.js index ce048101..df7f6fb8 100644 --- a/taglib/page-tag.js +++ b/taglib/page-tag.js @@ -7,7 +7,7 @@ var extend = require('raptor-util/extend'); var util = require('./util'); -module.exports = function render(input, out) { +module.exports = function render (input, out) { var lassoRenderContext = getLassoRenderContext(out); var theLasso = lassoRenderContext.lasso; if (input.lasso) { @@ -66,9 +66,9 @@ module.exports = function render(input, out) { } } - function doLassoPage() { - - theLasso.lassoPage({ + async function doLassoPage() { + try { + const lassoPageResult = await theLasso.lassoPage({ // Make sure the page is cached (should be the default) cache: true, @@ -89,7 +89,7 @@ module.exports = function render(input, out) { // extensions to be enabled at time of rendering flags: input.flags || input.enabledExtensions || input.extensions, - dependencies: function(callback) { + async dependencies () { var dependencies = input.dependencies; var packagePath = input.packagePath; var packagePaths = input.packagePaths; @@ -109,15 +109,17 @@ module.exports = function render(input, out) { } else if (packagePaths) { dependencies = packagePaths.map(function(path) { - return { - type: 'package', - path: path - }; - }); + return { + type: 'package', + path: path + }; + }); } else { // Look for an browser.json in the same directory if (input.dirname) { packagePath = nodePath.join(input.dirname, 'browser.json'); + // TODO: Since this is an async function, is there + // any reason why this is sync? if (fs.existsSync(packagePath)) { dependencies = [ { @@ -133,10 +135,14 @@ module.exports = function render(input, out) { dependencies = []; } - callback(null, dependencies); + return dependencies; } - }, - done); + }); + + done(null, lassoPageResult); + } catch (err) { + done(err); + } } var waitFor = lassoRenderContext.getWaitFor(); @@ -154,8 +160,7 @@ module.exports = function render(input, out) { Promise.all(waitFor) .then(doLassoPage) .catch(done); - } - else { + } else { doLassoPage(); } }; diff --git a/test/api-test.js b/test/api-test.js index b27a315c..c16803fe 100644 --- a/test/api-test.js +++ b/test/api-test.js @@ -10,7 +10,7 @@ let _log = console.log; describe('lasso/api' , function() { require('./autotest').scanDir( nodePath.join(__dirname, 'autotests/api'), - function (dir, helpers, done) { + async function (dir, helpers) { var name = nodePath.basename(dir); var outputDir = nodePath.join(buildDir, name); rmdirRecursive(outputDir); @@ -22,7 +22,6 @@ describe('lasso/api' , function() { }; var main = require(nodePath.join(dir, 'test.js')); - main.check(lasso, helpers, done); + return main.check(lasso, helpers); }); - -}); \ No newline at end of file +}); diff --git a/test/autotest.js b/test/autotest.js index 8a258282..9f4212e4 100644 --- a/test/autotest.js +++ b/test/autotest.js @@ -21,7 +21,6 @@ var enabledTest = process.env.TEST; var path = require('path'); var assert = require('assert'); - function compareHelper(dir, actual, suffix) { var actualPath = path.join(dir, 'actual' + suffix); var expectedPath = path.join(dir, 'expected' + suffix); @@ -47,7 +46,7 @@ function compareHelper(dir, actual, suffix) { assert.deepEqual(actual, expected); } -function autoTest(name, dir, run, options, done) { +function autoTest (name, dir, run, options) { options = options || {}; var helpers = { @@ -56,7 +55,7 @@ function autoTest(name, dir, run, options, done) { } }; - run(dir, helpers, done); + return run(dir, helpers); } exports.scanDir = function(autoTestDir, run, options) { @@ -79,10 +78,9 @@ exports.scanDir = function(autoTestDir, run, options) { var dir = path.join(autoTestDir, name); - itFunc(`[${name}] `, function(done) { - autoTest(name, dir, run, options, done); + itFunc(`[${name}] `, function () { + return autoTest(name, dir, run, options); }); - }); }); -}; \ No newline at end of file +}; diff --git a/test/autotests/api/config-fingerprint/test.js b/test/autotests/api/config-fingerprint/test.js index 5584278c..32228488 100644 --- a/test/autotests/api/config-fingerprint/test.js +++ b/test/autotests/api/config-fingerprint/test.js @@ -1,8 +1,6 @@ +const expect = require('chai').expect; -var expect = require('chai').expect; - -exports.check = function(lasso, helpers, done) { - +exports.check = function (lasso, helpers) { var config = { bundles: [ { @@ -17,6 +15,4 @@ exports.check = function(lasso, helpers, done) { var myLasso1 = lasso.create(config); var myLasso2 = lasso.create(config); expect(myLasso1.config.getConfigFingerprint()).to.equal(myLasso2.config.getConfigFingerprint()); - done(); }; - diff --git a/test/autotests/api/lasso-lassoPage-callback/browser.json b/test/autotests/api/lasso-lassoPage-callback/browser.json deleted file mode 100644 index a69ab32b..00000000 --- a/test/autotests/api/lasso-lassoPage-callback/browser.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "dependencies": [ - "./foo.js" - ] -} \ No newline at end of file diff --git a/test/autotests/api/lasso-lassoPage-callback/foo.js b/test/autotests/api/lasso-lassoPage-callback/foo.js deleted file mode 100644 index 19102815..00000000 --- a/test/autotests/api/lasso-lassoPage-callback/foo.js +++ /dev/null @@ -1 +0,0 @@ -foo \ No newline at end of file diff --git a/test/autotests/api/lasso-lassoPage-callback/test.js b/test/autotests/api/lasso-lassoPage-callback/test.js deleted file mode 100644 index fd3adf0a..00000000 --- a/test/autotests/api/lasso-lassoPage-callback/test.js +++ /dev/null @@ -1,25 +0,0 @@ -var nodePath = require('path'); -var expect = require('chai').expect; - -exports.check = function(lasso, helpers, done) { - lasso.configure({ - bundlingEnabled: false, - fingerprintsEnabled: false, - outputDir: helpers.getOutputDir() - }); - - lasso.lassoPage({ - pageName: helpers.getName(), - dependencies: [ - nodePath.join(__dirname, 'browser.json') - ] - }, - function(err, lassoPageResult) { - if (err) { - return done(err); - } - expect(lassoPageResult.getOutputFilesWithInfo().length).to.equal(1); - done(); - }); -}; - diff --git a/test/autotests/api/lasso-lassoPage-promise/test.js b/test/autotests/api/lasso-lassoPage-promise/test.js index 4e439002..93e64b9b 100644 --- a/test/autotests/api/lasso-lassoPage-promise/test.js +++ b/test/autotests/api/lasso-lassoPage-promise/test.js @@ -1,23 +1,19 @@ -var nodePath = require('path'); -var expect = require('chai').expect; +const nodePath = require('path'); +const expect = require('chai').expect; -exports.check = function(lasso, helpers, done) { +exports.check = async function (lasso, helpers) { lasso.configure({ bundlingEnabled: false, fingerprintsEnabled: false, outputDir: helpers.getOutputDir() }); - lasso.lassoPage({ - pageName: helpers.getName(), - dependencies: [ - nodePath.join(__dirname, 'browser.json') - ] - }) - .then((lassoPageResult) => { - expect(lassoPageResult.getOutputFilesWithInfo().length).to.equal(1); - done(); - }) - .catch(done); -}; + const lassoPageResult = await lasso.lassoPage({ + pageName: helpers.getName(), + dependencies: [ + nodePath.join(__dirname, 'browser.json') + ] + }); + expect(lassoPageResult.getOutputFilesWithInfo().length).to.equal(1); +}; diff --git a/test/autotests/api/lasso-lassoResource-callback/test.js b/test/autotests/api/lasso-lassoResource-callback/test.js deleted file mode 100644 index 13c7227a..00000000 --- a/test/autotests/api/lasso-lassoResource-callback/test.js +++ /dev/null @@ -1,20 +0,0 @@ -var nodePath = require('path'); -var expect = require('chai').expect; - -exports.check = function(lasso, helpers, done) { - lasso.configure({ - bundlingEnabled: true, - fingerprintsEnabled: true, - outputDir: helpers.getOutputDir() - }); - - lasso.lassoResource(nodePath.join(__dirname, 'foo.txt'), - function(err, result) { - if (err) { - return done(err); - } - expect(result.url).to.equal('/static/foo-0beec7b5.txt'); - done(); - }); -}; - diff --git a/test/autotests/api/lasso-lassoResource-callback/foo.txt b/test/autotests/api/lasso-lassoResource-promise/foo.txt similarity index 100% rename from test/autotests/api/lasso-lassoResource-callback/foo.txt rename to test/autotests/api/lasso-lassoResource-promise/foo.txt diff --git a/test/autotests/api/lasso-lassoResource-promise/test.js b/test/autotests/api/lasso-lassoResource-promise/test.js new file mode 100644 index 00000000..b52b12fe --- /dev/null +++ b/test/autotests/api/lasso-lassoResource-promise/test.js @@ -0,0 +1,13 @@ +const nodePath = require('path'); +const expect = require('chai').expect; + +exports.check = async function (lasso, helpers) { + lasso.configure({ + bundlingEnabled: true, + fingerprintsEnabled: true, + outputDir: helpers.getOutputDir() + }); + + const result = await lasso.lassoResource(nodePath.join(__dirname, 'foo.txt')); + expect(result.url).to.equal('/static/foo-0beec7b5.txt'); +}; diff --git a/test/autotests/api/myLasso-lassoPage-callback/browser.json b/test/autotests/api/myLasso-lassoPage-callback/browser.json deleted file mode 100644 index a69ab32b..00000000 --- a/test/autotests/api/myLasso-lassoPage-callback/browser.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "dependencies": [ - "./foo.js" - ] -} \ No newline at end of file diff --git a/test/autotests/api/myLasso-lassoPage-callback/foo.js b/test/autotests/api/myLasso-lassoPage-callback/foo.js deleted file mode 100644 index 19102815..00000000 --- a/test/autotests/api/myLasso-lassoPage-callback/foo.js +++ /dev/null @@ -1 +0,0 @@ -foo \ No newline at end of file diff --git a/test/autotests/api/myLasso-lassoPage-callback/test.js b/test/autotests/api/myLasso-lassoPage-callback/test.js deleted file mode 100644 index 4927d7f2..00000000 --- a/test/autotests/api/myLasso-lassoPage-callback/test.js +++ /dev/null @@ -1,25 +0,0 @@ -var nodePath = require('path'); -var expect = require('chai').expect; - -exports.check = function(lasso, helpers, done) { - var myLasso = lasso.create({ - bundlingEnabled: false, - fingerprintsEnabled: false, - outputDir: helpers.getOutputDir() - }); - - myLasso.lassoPage({ - pageName: helpers.getName(), - dependencies: [ - nodePath.join(__dirname, 'browser.json') - ] - }, - function(err, lassoPageResult) { - if (err) { - return done(err); - } - expect(lassoPageResult.getOutputFilesWithInfo().length).to.equal(1); - done(); - }); -}; - diff --git a/test/autotests/api/myLasso-lassoPage-promise/test.js b/test/autotests/api/myLasso-lassoPage-promise/test.js index 4d3a8ff5..a06999d0 100644 --- a/test/autotests/api/myLasso-lassoPage-promise/test.js +++ b/test/autotests/api/myLasso-lassoPage-promise/test.js @@ -1,23 +1,19 @@ var nodePath = require('path'); var expect = require('chai').expect; -exports.check = function(lasso, helpers, done) { +exports.check = async function (lasso, helpers) { var myLasso = lasso.create({ bundlingEnabled: false, fingerprintsEnabled: false, outputDir: helpers.getOutputDir() }); - myLasso.lassoPage({ - pageName: helpers.getName(), - dependencies: [ - nodePath.join(__dirname, 'browser.json') - ] - }) - .then((lassoPageResult) => { - expect(lassoPageResult.getOutputFilesWithInfo().length).to.equal(1); - done(); - }) - .catch(done); -}; + const lassoPageResult = await myLasso.lassoPage({ + pageName: helpers.getName(), + dependencies: [ + nodePath.join(__dirname, 'browser.json') + ] + }); + expect(lassoPageResult.getOutputFilesWithInfo().length).to.equal(1); +}; diff --git a/test/autotests/api/myLasso-lassoResource-callback/test.js b/test/autotests/api/myLasso-lassoResource-callback/test.js deleted file mode 100644 index 828dc96d..00000000 --- a/test/autotests/api/myLasso-lassoResource-callback/test.js +++ /dev/null @@ -1,20 +0,0 @@ -var nodePath = require('path'); -var expect = require('chai').expect; - -exports.check = function(lasso, helpers, done) { - var myLasso = lasso.create({ - bundlingEnabled: true, - fingerprintsEnabled: true, - outputDir: helpers.getOutputDir() - }); - - myLasso.lassoResource(nodePath.join(__dirname, 'foo.txt'), - function(err, result) { - if (err) { - return done(err); - } - expect(result.url).to.equal('/static/foo-0beec7b5.txt'); - done(); - }); -}; - diff --git a/test/autotests/api/myLasso-lassoResource-callback/foo.txt b/test/autotests/api/myLasso-lassoResource-promise/foo.txt similarity index 100% rename from test/autotests/api/myLasso-lassoResource-callback/foo.txt rename to test/autotests/api/myLasso-lassoResource-promise/foo.txt diff --git a/test/autotests/api/myLasso-lassoResource-promise/test.js b/test/autotests/api/myLasso-lassoResource-promise/test.js new file mode 100644 index 00000000..d8e7ef77 --- /dev/null +++ b/test/autotests/api/myLasso-lassoResource-promise/test.js @@ -0,0 +1,13 @@ +const nodePath = require('path'); +const expect = require('chai').expect; + +exports.check = async function (lasso, helpers) { + const myLasso = lasso.create({ + bundlingEnabled: true, + fingerprintsEnabled: true, + outputDir: helpers.getOutputDir() + }); + + const result = await myLasso.lassoResource(nodePath.join(__dirname, 'foo.txt')); + expect(result.url).to.equal('/static/foo-0beec7b5.txt'); +}; diff --git a/test/autotests/api/pollute-default-config/test.js b/test/autotests/api/pollute-default-config/test.js index 2cc9ad44..2a91a0df 100644 --- a/test/autotests/api/pollute-default-config/test.js +++ b/test/autotests/api/pollute-default-config/test.js @@ -1,27 +1,22 @@ +const expect = require('chai').expect; -var expect = require('chai').expect; - -exports.check = function(lasso, helpers, done) { - var myLasso1 = lasso.create({ +exports.check = function (lasso, helpers) { + const myLasso1 = lasso.create({ require: { test: 'abc' } }); - var myLasso2 = lasso.create({ + const myLasso2 = lasso.create({ }); - var defaultLasso = lasso.getDefaultLasso(); - - var requirePlugin1 = myLasso1.getConfig().getPlugins()[0]; - var requirePlugin2 = myLasso2.getConfig().getPlugins()[0]; - var requirePlugin3 = defaultLasso.getConfig().getPlugins()[0]; + const defaultLasso = lasso.getDefaultLasso(); + const requirePlugin1 = myLasso1.getConfig().getPlugins()[0]; + const requirePlugin2 = myLasso2.getConfig().getPlugins()[0]; + const requirePlugin3 = defaultLasso.getConfig().getPlugins()[0]; expect(requirePlugin1.config.test).to.equal('abc'); expect(requirePlugin2.config.test).to.not.exist; expect(requirePlugin3.config.test).to.not.exist; - - done(); }; - diff --git a/test/autotests/bundling/css-inline-resource-base64/test.js b/test/autotests/bundling/css-inline-resource-base64/test.js index 7ed98b71..26f7387f 100644 --- a/test/autotests/bundling/css-inline-resource-base64/test.js +++ b/test/autotests/bundling/css-inline-resource-base64/test.js @@ -18,12 +18,12 @@ exports.getInputs = function() { }, check(lassoPageResult, writerTracker, helpers) { expect(writerTracker.getOutputFilenames()).to.deep.equal([ - 'bundling-css-inline-resource-base64-head.css' - ]); + 'bundling-css-inline-resource-base64-head.css' + ]); var actualCSS = writerTracker.getCodeForFilename('bundling-css-inline-resource-base64-head.css'); helpers.compare(actualCSS, '.css'); } } ]; -}; \ No newline at end of file +}; diff --git a/test/autotests/bundling/custom-dependency-type-no-bundling/test.js b/test/autotests/bundling/custom-dependency-type-no-bundling/test.js index 7031e878..5f557c0b 100644 --- a/test/autotests/bundling/custom-dependency-type-no-bundling/test.js +++ b/test/autotests/bundling/custom-dependency-type-no-bundling/test.js @@ -12,9 +12,7 @@ exports.getLassoConfig = function() { properties: { }, - init: function(lassoContext, callback) { - callback(); - }, + async init (lassoContext) {}, read: function(lassoContext, callback) { callback(null, 'FOO'); @@ -45,4 +43,4 @@ exports.getInputs = function() { } } ]; -}; \ No newline at end of file +}; diff --git a/test/autotests/modules/async-flags/test.js b/test/autotests/modules/async-flags/test.js index d6ae0f65..e21258d5 100644 --- a/test/autotests/modules/async-flags/test.js +++ b/test/autotests/modules/async-flags/test.js @@ -8,15 +8,17 @@ exports.getLassoOptions = function(dir) { }; }; -exports.check = function(window, done) { +exports.check = function (window) { expect(window.fooLoaded).to.equal(undefined); expect(window.main.filename).to.contain('main'); - window.main.loadFoo(function(err) { - if (err) { - return done(err); - } + return new Promise((resolve, reject) => { + window.main.loadFoo(function(err) { + if (err) { + return reject(err); + } - done(); + resolve(); + }); }); -}; \ No newline at end of file +}; diff --git a/test/autotests/modules/async-intersection/test.js b/test/autotests/modules/async-intersection/test.js index da0defb6..2c7d7c72 100644 --- a/test/autotests/modules/async-intersection/test.js +++ b/test/autotests/modules/async-intersection/test.js @@ -1,5 +1,4 @@ -var expect = require('chai').expect; - +const expect = require('chai').expect; exports.lassoConfig = { bundlingEnabled: true, @@ -27,19 +26,25 @@ exports.tests = [ 'require-run: ' + require.resolve('./main1') ] }, - check(window, done) { + check (window) { expect(window.fooLoaded).to.equal(undefined); expect(window.main.filename).to.contain('main'); - window.main.load(function(err, loaded) { - if (err) { - return done(err); - } + return new Promise((resolve, reject) => { + window.main.load(function(err, loaded) { + if (err) { + return reject(err); + } - expect(window.fooLoaded).to.equal(true); - expect(loaded.foo.isFoo).to.equal(true); - expect(loaded.helper.isMain1Helper).to.equal(true); - done(); + try { + expect(window.fooLoaded).to.equal(true); + expect(loaded.foo.isFoo).to.equal(true); + expect(loaded.helper.isMain1Helper).to.equal(true); + } catch (err) { + return reject(err); + } + resolve(); + }); }); } }, @@ -50,19 +55,26 @@ exports.tests = [ 'require-run: ' + require.resolve('./main2') ] }, - check(window, done) { + check (window) { expect(window.fooLoaded).to.equal(undefined); expect(window.main.filename).to.contain('main'); - window.main.load(function(err, loaded) { - if (err) { - return done(err); - } - expect(window.fooLoaded).to.equal(true); - expect(loaded.foo.isFoo).to.equal(true); - expect(loaded.helper.isMain2Helper).to.equal(true); - done(); + return new Promise((resolve, reject) => { + window.main.load(function(err, loaded) { + if (err) { + return reject(err); + } + + try { + expect(window.fooLoaded).to.equal(true); + expect(loaded.foo.isFoo).to.equal(true); + expect(loaded.helper.isMain2Helper).to.equal(true); + } catch (err) { + return reject(err); + } + resolve(); + }); }); } } -]; \ No newline at end of file +]; diff --git a/test/autotests/modules/async-package/test.js b/test/autotests/modules/async-package/test.js index 3f1bd8d8..e45a6abd 100644 --- a/test/autotests/modules/async-package/test.js +++ b/test/autotests/modules/async-package/test.js @@ -34,41 +34,43 @@ exports.getLassoOptions = function(dir) { }; }; -exports.check = function(window, done) { +exports.check = async function (window) { expect(window.fooLoaded).to.equal(undefined); expect(window.main.filename).to.contain('main'); - window.main.loadFoo(function(err, foo) { - if (err) { - return done(err); - } - - expect(foo.isFoo).to.equal(true); - expect(window.fooLoaded).to.equal(true); - expect(window.barLoaded).to.equal(undefined); - expect(window.somethingLoaded).to.equal(undefined); - - window.main.loadBar(function(err, bar) { + return new Promise((resolve, reject) => { + window.main.loadFoo(function(err, foo) { if (err) { - return done(err); + return reject(err); } - expect(bar.isBar).to.equal(true); + expect(foo.isFoo).to.equal(true); expect(window.fooLoaded).to.equal(true); - expect(window.barLoaded).to.equal(true); + expect(window.barLoaded).to.equal(undefined); expect(window.somethingLoaded).to.equal(undefined); - window.main.loadSomething(function(err) { + window.main.loadBar(function(err, bar) { if (err) { - return done(err); + return reject(err); } + expect(bar.isBar).to.equal(true); expect(window.fooLoaded).to.equal(true); expect(window.barLoaded).to.equal(true); - expect(window.somethingLoaded).to.equal(true); + expect(window.somethingLoaded).to.equal(undefined); + + window.main.loadSomething(function(err) { + if (err) { + return reject(err); + } - done(); + expect(window.fooLoaded).to.equal(true); + expect(window.barLoaded).to.equal(true); + expect(window.somethingLoaded).to.equal(true); + + resolve(); + }); }); }); }); -}; \ No newline at end of file +}; diff --git a/test/autotests/modules/async-raptor-loader/test.js b/test/autotests/modules/async-raptor-loader/test.js index d6ae0f65..e21258d5 100644 --- a/test/autotests/modules/async-raptor-loader/test.js +++ b/test/autotests/modules/async-raptor-loader/test.js @@ -8,15 +8,17 @@ exports.getLassoOptions = function(dir) { }; }; -exports.check = function(window, done) { +exports.check = function (window) { expect(window.fooLoaded).to.equal(undefined); expect(window.main.filename).to.contain('main'); - window.main.loadFoo(function(err) { - if (err) { - return done(err); - } + return new Promise((resolve, reject) => { + window.main.loadFoo(function(err) { + if (err) { + return reject(err); + } - done(); + resolve(); + }); }); -}; \ No newline at end of file +}; diff --git a/test/autotests/modules/async-unnecessary/test.js b/test/autotests/modules/async-unnecessary/test.js index 93bd9542..60cf984e 100644 --- a/test/autotests/modules/async-unnecessary/test.js +++ b/test/autotests/modules/async-unnecessary/test.js @@ -8,16 +8,18 @@ exports.getLassoOptions = function(dir) { }; }; -exports.check = function(window, done) { +exports.check = function (window) { expect(window.fooLoaded).to.equal(true); expect(window.main.filename).to.contain('main'); - window.main.loadFoo(function(err, foo) { - if (err) { - return done(err); - } + return new Promise((resolve, reject) => { + window.main.loadFoo(function(err, foo) { + if (err) { + return reject(err); + } - expect(foo.isFoo).to.equal(true); - done(); + expect(foo.isFoo).to.equal(true); + resolve(); + }); }); -}; \ No newline at end of file +}; diff --git a/test/autotests/modules/async/test.js b/test/autotests/modules/async/test.js index d6ae0f65..e21258d5 100644 --- a/test/autotests/modules/async/test.js +++ b/test/autotests/modules/async/test.js @@ -8,15 +8,17 @@ exports.getLassoOptions = function(dir) { }; }; -exports.check = function(window, done) { +exports.check = function (window) { expect(window.fooLoaded).to.equal(undefined); expect(window.main.filename).to.contain('main'); - window.main.loadFoo(function(err) { - if (err) { - return done(err); - } + return new Promise((resolve, reject) => { + window.main.loadFoo(function(err) { + if (err) { + return reject(err); + } - done(); + resolve(); + }); }); -}; \ No newline at end of file +}; diff --git a/test/autotests/modules/registerRequireExtension-getDependencies/test.js b/test/autotests/modules/registerRequireExtension-getDependencies/test.js index b502e0d5..ae9c1f82 100644 --- a/test/autotests/modules/registerRequireExtension-getDependencies/test.js +++ b/test/autotests/modules/registerRequireExtension-getDependencies/test.js @@ -10,13 +10,13 @@ exports.getLassoConfig = function(dir) { lasso.dependencies.registerRequireExtension( 'foo', { - getDependencies: function(lassoContext, callback) { + async getDependencies (lassoContext) { return [ require.resolve('./extra.js') ]; }, - read: function(path, lassoContext, callback) { + async read (path, lassoContext) { var src = fs.readFileSync(path, { encoding: 'utf8' }); - callback(null, 'exports.FOO = ' + JSON.stringify(src) + '; exports.filename = __filename;'); + return 'exports.FOO = ' + JSON.stringify(src) + '; exports.filename = __filename;'; } }); } @@ -41,4 +41,4 @@ exports.check = function(window) { expect(window.main.world.FOO).to.equal('world'); expect(window.main.world.filename).to.contain('world.foo'); expect(window.EXTRA).to.equal(true); -}; \ No newline at end of file +}; diff --git a/test/autotests/modules/registerRequireType-getDependencies-callback/test.js b/test/autotests/modules/registerRequireType-getDependencies-callback/test.js index 6dac1268..c03e8678 100644 --- a/test/autotests/modules/registerRequireType-getDependencies-callback/test.js +++ b/test/autotests/modules/registerRequireType-getDependencies-callback/test.js @@ -14,19 +14,16 @@ exports.getLassoConfig = function(dir) { 'path': 'string' }, - init: function(lassoContext, callback) { + async init (lassoContext) { if (!this.path) { - return callback(new Error('"path" is required for a Marko dependency')); + throw new Error('"path" is required for a Marko dependency'); } this.path = this.resolvePath(this.path); - callback(); }, - getDependencies: function(lassoContext, callback) { - callback(null, [ - require.resolve('./extra.js') - ]); + async getDependencies (lassoContext) { + return [require.resolve('./extra.js')]; }, read: function(lassoContext, callback) { @@ -57,4 +54,4 @@ exports.check = function(window) { expect(window.main.world.FOO).to.equal('world'); expect(window.main.world.filename).to.contain('world.foo'); expect(window.EXTRA).to.equal(true); -}; \ No newline at end of file +}; diff --git a/test/autotests/modules/registerRequireType-getDependencies-promise/test.js b/test/autotests/modules/registerRequireType-getDependencies-promise/test.js index 0369ed76..8dfd6586 100644 --- a/test/autotests/modules/registerRequireType-getDependencies-promise/test.js +++ b/test/autotests/modules/registerRequireType-getDependencies-promise/test.js @@ -14,17 +14,16 @@ exports.getLassoConfig = function(dir) { 'path': 'string' }, - init: function(lassoContext, callback) { + async init (lassoContext) { if (!this.path) { - return callback(new Error('"path" is required for a Marko dependency')); + throw new Error('"path" is required for a Marko dependency'); } this.path = this.resolvePath(this.path); - callback(); }, - getDependencies: function(lassoContext, callback) { - return Promise.resolve([ require.resolve('./extra.js') ]); + async getDependencies (lassoContext) { + return [ require.resolve('./extra.js') ]; }, read: function(lassoContext, callback) { @@ -55,4 +54,4 @@ exports.check = function(window) { expect(window.main.world.FOO).to.equal('world'); expect(window.main.world.filename).to.contain('world.foo'); expect(window.EXTRA).to.equal(true); -}; \ No newline at end of file +}; diff --git a/test/autotests/modules/registerRequireType-getDependencies-value/test.js b/test/autotests/modules/registerRequireType-getDependencies-value/test.js index 86013b6c..68984717 100644 --- a/test/autotests/modules/registerRequireType-getDependencies-value/test.js +++ b/test/autotests/modules/registerRequireType-getDependencies-value/test.js @@ -16,17 +16,16 @@ exports.getLassoConfig = function(dir) { 'path': 'string' }, - init: function(lassoContext, callback) { + async init (lassoContext) { if (!this.path) { - return callback(new Error('"path" is required for a Marko dependency')); + throw new Error('"path" is required for a Marko dependency'); } this.path = this.resolvePath(this.path); this.foo = true; - callback(); }, - getDependencies: function(lassoContext, callback) { + async getDependencies (lassoContext) { expect(this.foo).to.equal(true); return [ require.resolve('./extra.js') ]; }, @@ -59,4 +58,4 @@ exports.check = function(window) { expect(window.main.world.FOO).to.equal('world'); expect(window.main.world.filename).to.contain('world.foo'); expect(window.EXTRA).to.equal(true); -}; \ No newline at end of file +}; diff --git a/test/autotests/modules/registerRequireType/test.js b/test/autotests/modules/registerRequireType/test.js index 5562359d..19632e76 100644 --- a/test/autotests/modules/registerRequireType/test.js +++ b/test/autotests/modules/registerRequireType/test.js @@ -14,13 +14,12 @@ exports.getLassoConfig = function(dir) { 'path': 'string' }, - init: function(lassoContext, callback) { + async init (lassoContext) { if (!this.path) { - return callback(new Error('"path" is required for a Marko dependency')); + throw new Error('"path" is required for a Marko dependency'); } this.path = this.resolvePath(this.path); - callback(); }, read: function(lassoContext, callback) { @@ -44,10 +43,10 @@ exports.getLassoOptions = function(dir) { exports.check = function(window) { expect(window.main.filename).to.contain('main'); - + expect(window.main.hello.FOO).to.equal('hello'); expect(window.main.hello.filename).to.contain('hello.foo'); expect(window.main.world.FOO).to.equal('world'); expect(window.main.world.filename).to.contain('world.foo'); -}; \ No newline at end of file +}; diff --git a/test/autotests/modules/require-custom-ext/require-foo-plugin.js b/test/autotests/modules/require-custom-ext/require-foo-plugin.js index 701fc4a6..8b195c2e 100644 --- a/test/autotests/modules/require-custom-ext/require-foo-plugin.js +++ b/test/autotests/modules/require-custom-ext/require-foo-plugin.js @@ -15,8 +15,8 @@ module.exports = exports = function(lasso, config) { }); }, - lastModified: function(path, lassoContext, callback) { - lassoContext.getFileLastModified(path, callback); + async lastModified (path, lassoContext) { + return lassoContext.getFileLastModified(path); } }); }; diff --git a/test/autotests/modules/require-custom-type/test.js b/test/autotests/modules/require-custom-type/test.js index d36b09c9..3913dc72 100644 --- a/test/autotests/modules/require-custom-type/test.js +++ b/test/autotests/modules/require-custom-type/test.js @@ -6,13 +6,12 @@ function fooPlugins(lasso, config) { 'path': 'string' }, - init: function(context, callback) { + async init (context) { if (!this.path) { - return callback(new Error('"path" is required')); + throw new Error('"path" is required'); } this.path = this.resolvePath(this.path); - callback(); }, // Read the resource: @@ -42,4 +41,4 @@ exports.getLassoOptions = function(dir) { exports.check = function(window) { expect(window.main.filename).to.contain('main'); -}; \ No newline at end of file +}; diff --git a/test/autotests/plugins/custom-dependency-type-callback/plugin.js b/test/autotests/plugins/custom-dependency-type-callback/plugin.js index 45f177cf..9dd632eb 100644 --- a/test/autotests/plugins/custom-dependency-type-callback/plugin.js +++ b/test/autotests/plugins/custom-dependency-type-callback/plugin.js @@ -8,7 +8,7 @@ module.exports = exports = function(lasso, config) { 'path': 'string' }, - init: function() { + async init () { if (!this.path) { throw new Error('"path" is required for a less dependency'); } @@ -35,8 +35,8 @@ module.exports = exports = function(lasso, config) { return this.path; }, - lastModified: function(lassoContext, callback) { - return callback(null, -1); + async lastModified (lassoContext) { + return -1; } }); @@ -47,7 +47,7 @@ module.exports = exports = function(lasso, config) { 'path': 'string' }, - init: function() { + async init () { if (!this.path) { throw new Error('"path" is required for a less dependency'); } @@ -76,8 +76,8 @@ module.exports = exports = function(lasso, config) { return this.path; }, - lastModified: function(lassoContext, callback) { - return callback(null, -1); + async lastModified (lassoContext) { + return -1; } }); }; diff --git a/test/autotests/plugins/custom-dependency-type-promise/plugin.js b/test/autotests/plugins/custom-dependency-type-promise/plugin.js index 27dcc978..8994a04a 100644 --- a/test/autotests/plugins/custom-dependency-type-promise/plugin.js +++ b/test/autotests/plugins/custom-dependency-type-promise/plugin.js @@ -8,7 +8,7 @@ module.exports = exports = function(lasso, config) { 'path': 'string' }, - init: function() { + async init () { if (!this.path) { throw new Error('"path" is required for a less dependency'); } @@ -37,8 +37,8 @@ module.exports = exports = function(lasso, config) { return this.path; }, - lastModified: function(lassoContext, callback) { - return callback(null, -1); + async lastModified (lassoContext) { + return -1; } }); @@ -49,7 +49,7 @@ module.exports = exports = function(lasso, config) { 'path': 'string' }, - init: function() { + async init () { if (!this.path) { throw new Error('"path" is required for a less dependency'); } @@ -80,8 +80,8 @@ module.exports = exports = function(lasso, config) { return this.path; }, - lastModified: function(lassoContext, callback) { - return callback(null, -1); + async lastModified (lassoContext) { + return -1; } }); }; diff --git a/test/autotests/plugins/registerRequireType/plugin.js b/test/autotests/plugins/registerRequireType/plugin.js index ad7d21a4..ff351a6f 100644 --- a/test/autotests/plugins/registerRequireType/plugin.js +++ b/test/autotests/plugins/registerRequireType/plugin.js @@ -6,13 +6,12 @@ module.exports = exports = function(lasso, config) { 'path': 'string' }, - init: function(lassoContext, callback) { + async init (lassoContext) { if (!this.path) { - return callback(new Error('"path" is required for a Marko dependency')); + throw new Error('"path" is required for a Marko dependency'); } this.path = this.resolvePath(this.path); - callback(); }, object: true, // We are exporting a simple JavaScript object @@ -23,8 +22,8 @@ module.exports = exports = function(lasso, config) { }); }, - getLastModified: function(lassoContext, callback) { - lassoContext.getFileLastModified(this.path, callback); + async getLastModified (lassoContext) { + return lassoContext.getFileLastModified(this.path); } }); -}; \ No newline at end of file +}; diff --git a/test/autotests/resource-transforms/filter/test.js b/test/autotests/resource-transforms/filter/test.js index b027261c..80761565 100644 --- a/test/autotests/resource-transforms/filter/test.js +++ b/test/autotests/resource-transforms/filter/test.js @@ -9,17 +9,10 @@ exports.getLassoConfig = function() { plugins: [ function myPlugin(myLasso, pluginConfig) { myLasso.addTransform({ - filter: function(lassoContext, callback) { + async filter (lassoContext) { var path = lassoContext.path; - if (!path) { - return callback(null, false); - } - - if (/\.bar$/.test(path)) { - callback(null, true); - } else { - callback(null, false); - } + if (!path) return false; + return /\.bar$/.test(path); }, name: 'testTransformer', diff --git a/test/autotests/transforms/transform-css-urls-custom-type/test.js b/test/autotests/transforms/transform-css-urls-custom-type/test.js index 59f7c1e1..df378652 100644 --- a/test/autotests/transforms/transform-css-urls-custom-type/test.js +++ b/test/autotests/transforms/transform-css-urls-custom-type/test.js @@ -14,9 +14,8 @@ exports.getLassoConfig = function() { 'path': 'string' }, - init: function(lassoContext, callback) { + async init (lassoContext) { this.path = this.resolvePath(this.path); - callback(); }, read: function(lassoContext, callback) { @@ -35,8 +34,8 @@ exports.getLassoConfig = function() { return this.path; }, - getLastModified: function(lassoContext, callback) { - return callback(null, -1); + async getLastModified (lassoContext) { + return -1; } }); } @@ -61,4 +60,4 @@ exports.check = function(lassoPageResult, writerTracker) { var actual = writerTracker.getCodeForPath(lassoPageResult.getCSSFiles()[0]); // console.log(actual); expect(actual).to.equal(expected); -}; \ No newline at end of file +}; diff --git a/test/autotests/util/caching-replay-stream/test.js b/test/autotests/util/caching-replay-stream/test.js index 32ed1fe5..115242b0 100644 --- a/test/autotests/util/caching-replay-stream/test.js +++ b/test/autotests/util/caching-replay-stream/test.js @@ -2,7 +2,7 @@ var expect = require('chai').expect; var fs = require('fs'); var nodePath = require('path'); -exports.check = function(util, done) { +exports.check = function (util) { var cachingStream = util.createCachingStream(); var outputDir = nodePath.join(__dirname, 'build'); @@ -18,20 +18,21 @@ exports.check = function(util, done) { var readStream = fs.createReadStream(inFile); var outStream = fs.createWriteStream(outFile1); - outStream.on('close', function() { - - outStream = fs.createWriteStream(outFile2); + return new Promise((resolve, reject) => { outStream.on('close', function() { - var inTxt = fs.readFileSync(inFile, {encoding: 'utf8'}); - var outFile1Txt = fs.readFileSync(outFile1, {encoding: 'utf8'}); - var outFile2Txt = fs.readFileSync(outFile2, {encoding: 'utf8'}); - expect(inTxt).to.equal(outFile1Txt); - expect(inTxt).to.equal(outFile2Txt); - done(); + outStream = fs.createWriteStream(outFile2); + outStream.on('close', function() { + var inTxt = fs.readFileSync(inFile, {encoding: 'utf8'}); + var outFile1Txt = fs.readFileSync(outFile1, {encoding: 'utf8'}); + var outFile2Txt = fs.readFileSync(outFile2, {encoding: 'utf8'}); + expect(inTxt).to.equal(outFile1Txt); + expect(inTxt).to.equal(outFile2Txt); + resolve(); + }); + + cachingStream.createReplayStream().pipe(outStream); }); - cachingStream.createReplayStream().pipe(outStream); + readStream.pipe(cachingStream).pipe(outStream); }); - - readStream.pipe(cachingStream).pipe(outStream); -}; \ No newline at end of file +}; diff --git a/test/builtins-test.js b/test/builtins-test.js index 43ef34c9..f59a9e88 100644 --- a/test/builtins-test.js +++ b/test/builtins-test.js @@ -3,9 +3,7 @@ var chai = require('chai'); chai.config.includeStack = true; require('chai').should(); var expect = require('chai').expect; -var buildPluginConfig = require('../lib/require/build-plugin-config'); var createLassoContext = require('./mock/create-lasso-context'); -var MockLassoContext = require('./mock/MockLassoContext'); describe('lasso-require/builtins' , function() { it('should correctly resolve default builtins', function() { @@ -64,4 +62,4 @@ describe('lasso-require/builtins' , function() { // // // console.log('builtins:', builtins); // }); -}); \ No newline at end of file +}); diff --git a/test/bundling-test.js b/test/bundling-test.js index 989e4e22..e4db7684 100644 --- a/test/bundling-test.js +++ b/test/bundling-test.js @@ -1,18 +1,14 @@ 'use strict'; -var nodePath = require('path'); +const nodePath = require('path'); require('chai').config.includeStack = true; -var series = require('raptor-async/series'); -var WriterTracker = require('./util/WriterTracker'); -var rmdirRecursive = require('./util').rmdirRecursive; -var buildDir = nodePath.join(__dirname, 'build'); +const WriterTracker = require('./util/WriterTracker'); +const rmdirRecursive = require('./util').rmdirRecursive; +const buildDir = nodePath.join(__dirname, 'build'); +const lasso = require('../'); +const Readable = require('stream').Readable; +const urlReader = require('../lib/util/url-reader'); -var lasso = require('../'); - -var Readable = require('stream').Readable; - - -var urlReader = require('../lib/util/url-reader'); urlReader.createUrlReadStream = function(url) { var readable = new Readable(); readable.push('EXTERNAL:' + url); @@ -23,8 +19,7 @@ urlReader.createUrlReadStream = function(url) { describe('lasso/bundling' , function() { require('./autotest').scanDir( nodePath.join(__dirname, 'autotests/bundling'), - function (dir, helpers, done) { - + async function (dir, helpers) { var main = require(nodePath.join(dir, 'test.js')); var testName = nodePath.basename(dir); var pageName = 'bundling-' + testName; @@ -41,7 +36,6 @@ describe('lasso/bundling' , function() { lassoConfig.outputDir = nodePath.join(buildDir, pageName); } - rmdirRecursive(lassoConfig.outputDir); var myLasso = lasso.create(lassoConfig, dir); @@ -62,52 +56,38 @@ describe('lasso/bundling' , function() { ]; } + for (const input of inputs) { + var writerTracker = WriterTracker.create(myLasso.writer); - var asyncTasks = inputs.map((input) => { - return (callback) => { - var writerTracker = WriterTracker.create(myLasso.writer); + var lassoOptions = input.lassoOptions; + var check = input.check; + var checkError = input.checkError; - var lassoOptions = input.lassoOptions; - var check = input.check; - var checkError = input.checkError; + if (!lassoOptions.pageName) { + lassoOptions.pageName = pageName; + } - if (!lassoOptions.pageName) { - lassoOptions.pageName = pageName; - } + if (!lassoOptions.from) { + lassoOptions.from = dir; + } - if (!lassoOptions.from) { - lassoOptions.from = dir; + let lassoPageResult; + try { + lassoPageResult = await myLasso.lassoPage(lassoOptions); + } catch (err) { + if (checkError) { + checkError(err); + } else { + throw err; } - - myLasso.lassoPage(lassoOptions) - .then((lassoPageResult) => { - if (checkError) { - return done('Error expected'); - } - check(lassoPageResult, writerTracker, helpers); - lasso.flushAllCaches(callback); - }) - .catch((err) => { - if (checkError) { - checkError(err); - done(); - } else { - throw err; - } - }) - .catch(done); - }; - }); - - series(asyncTasks, (err) => { - if (err) { - return done(err); } - done(); - }); - + if (checkError) { + throw new Error('Error expected'); + } + check(lassoPageResult, writerTracker, helpers); + await lasso.flushAllCaches(); + } }); - -}); \ No newline at end of file +}); diff --git a/test/dep-require-test.js b/test/dep-require-test.js index 90bebbd8..29d491b5 100644 --- a/test/dep-require-test.js +++ b/test/dep-require-test.js @@ -1,24 +1,22 @@ 'use strict'; - -var nodePath = require('path'); -var chai = require('chai'); +const nodePath = require('path'); +const chai = require('chai'); chai.config.includeStack = true; require('chai').should(); -var createLassoContext = require('./mock/create-lasso-context'); -var normalizeOutput = require('./util/normalizeOutput'); -var moduleSearchPath = require('./util/module-search-path'); +const createLassoContext = require('./mock/create-lasso-context'); +const normalizeOutput = require('./util/normalizeOutput'); +const moduleSearchPath = require('./util/module-search-path'); -var rootDir = nodePath.join(__dirname, '..'); +const rootDir = nodePath.join(__dirname, '..'); describe('lasso-require/dependency-require' , function() { require('./autotest').scanDir( nodePath.join(__dirname, 'autotests/dep-require'), - function (dir, helpers, done) { - + async function (dir, helpers) { var main = require(nodePath.join(dir, 'test.js')); - var pluginConfig = main.getPluginConfig ? main.getPluginConfig() : {}; + pluginConfig.rootDir = dir; var dependencyFactory = require('./mock/dependency-factory').create(pluginConfig); @@ -34,25 +32,20 @@ describe('lasso-require/dependency-require' , function() { var lassoContext = createLassoContext(); dependency.init(lassoContext); - return Promise.resolve() - .then(() => { - return dependency.getDependencies(lassoContext); - }) - .then((dependencies) => { - dependencies = normalizeOutput(dependencies, rootDir); - if (patchedSearchPath) { - patchedSearchPath.restore(); - } - - helpers.compare(dependencies, '.json'); - done(); - }) - .catch((err) => { - if (patchedSearchPath) { - patchedSearchPath.restore(); - } - done(err); - }); - }); + try { + let dependencies = await dependency.getDependencies(lassoContext); + dependencies = normalizeOutput(dependencies, rootDir); + + if (patchedSearchPath) { + patchedSearchPath.restore(); + } -}); \ No newline at end of file + helpers.compare(dependencies, '.json'); + } catch (err) { + if (patchedSearchPath) { + patchedSearchPath.restore(); + } + throw err; + } + }); +}); diff --git a/test/dep-transport-define-test.js b/test/dep-transport-define-test.js index 31474c46..fa5ddc5a 100644 --- a/test/dep-transport-define-test.js +++ b/test/dep-transport-define-test.js @@ -1,17 +1,17 @@ 'use strict'; -var nodePath = require('path'); -var chai = require('chai'); +const nodePath = require('path'); +const chai = require('chai'); chai.config.includeStack = true; require('chai').should(); -var createLassoContext = require('./mock/create-lasso-context'); -var moduleSearchPath = require('./util/module-search-path'); -var normalizeOutput = require('./util/normalizeOutput'); +const createLassoContext = require('./mock/create-lasso-context'); +const moduleSearchPath = require('./util/module-search-path'); +const normalizeOutput = require('./util/normalizeOutput'); describe('lasso-require/dep-transport-define' , function() { require('./autotest').scanDir( nodePath.join(__dirname, 'autotests/dep-transport-define'), - function (dir, helpers, done) { + async function (dir, helpers) { var main = require(nodePath.join(dir, 'test.js')); var dependencyProps = main.createDependency(dir); @@ -31,39 +31,39 @@ describe('lasso-require/dep-transport-define' , function() { dependency.init(lassoContext); - return Promise.resolve() - .then(() => { - return dependency.getDependencies(lassoContext); - }) - .then((dependencies) => { - if (dependencies.dependencies) { - dependencies = dependencies.dependencies; - } + let dependencies = await dependency.getDependencies(lassoContext); + + if (dependencies.dependencies) { + dependencies = dependencies.dependencies; + } - for (var i=0; i { - if (patchedSearchPath) { - patchedSearchPath.restore(); - } - src = normalizeOutput(src, dir); + } - helpers.compare(src, '.js'); - done(); - }) - .catch((err) => { - if (patchedSearchPath) { - patchedSearchPath.restore(); - } - done(err); - }); - }); + if (patchedSearchPath) { + patchedSearchPath.restore(); + } -}); \ No newline at end of file + src = normalizeOutput(src, dir); + helpers.compare(src, '.js'); + } catch (err) { + if (patchedSearchPath) { + patchedSearchPath.restore(); + } + throw err; + } + }); +}); diff --git a/test/dep-transport-installed-test.js b/test/dep-transport-installed-test.js index abe0440d..dc92ba11 100644 --- a/test/dep-transport-installed-test.js +++ b/test/dep-transport-installed-test.js @@ -1,14 +1,15 @@ 'use strict'; -var nodePath = require('path'); -var chai = require('chai'); + +const nodePath = require('path'); +const chai = require('chai'); chai.config.includeStack = true; require('chai').should(); -var MockLassoContext = require('./mock/MockLassoContext'); +const MockLassoContext = require('./mock/MockLassoContext'); describe('lasso-require/dep-transport-installed' , function() { require('./autotest').scanDir( nodePath.join(__dirname, 'autotests/dep-transport-installed'), - function (dir, helpers, done) { + async function (dir, helpers) { var main = require(nodePath.join(dir, 'test.js')); var dependencyProps = main.createDependency(dir); @@ -16,21 +17,12 @@ describe('lasso-require/dep-transport-installed' , function() { pluginConfig.rootDir = dir; var dependencyFactory = require('./mock/dependency-factory').create(pluginConfig); - var dependency = dependencyFactory.depTransportInstalled(dependencyProps); - var lassoContext = new MockLassoContext(); dependency.init(lassoContext); - return Promise.resolve() - .then(() => { - return dependency.read(lassoContext); - }) - .then((src) => { - helpers.compare(src, '.js'); - done(); - }) - .catch(done); + const src = await dependency.read(lassoContext); + helpers.compare(src, '.js'); }); -}); \ No newline at end of file +}); diff --git a/test/dep-transport-main-test.js b/test/dep-transport-main-test.js index c6320716..735d02e9 100644 --- a/test/dep-transport-main-test.js +++ b/test/dep-transport-main-test.js @@ -1,36 +1,28 @@ 'use strict'; -var nodePath = require('path'); -var chai = require('chai'); + +const nodePath = require('path'); +const chai = require('chai'); chai.config.includeStack = true; require('chai').should(); -var MockLassoContext = require('./mock/MockLassoContext'); +const MockLassoContext = require('./mock/MockLassoContext'); -describe('lasso-require/dep-transport-main' , function() { +describe('lasso-require/dep-transport-main', function() { require('./autotest').scanDir( nodePath.join(__dirname, 'autotests/dep-transport-main'), - function (dir, helpers, done) { + async function (dir, helpers) { var main = require(nodePath.join(dir, 'test.js')); var dependencyProps = main.createDependency(dir); - var pluginConfig = main.getPluginConfig ? main.getPluginConfig() : {}; + pluginConfig.rootDir = dir; var dependencyFactory = require('./mock/dependency-factory').create(pluginConfig); - var dependency = dependencyFactory.depTransportMain(dependencyProps); - var lassoContext = new MockLassoContext(); dependency.init(lassoContext); - return Promise.resolve() - .then(() => { - return dependency.read(lassoContext); - }) - .then((src) => { - helpers.compare(src, '.js'); - done(); - }) - .catch(done); + const src = await dependency.read(lassoContext); + helpers.compare(src, '.js'); }); -}); \ No newline at end of file +}); diff --git a/test/dep-transport-ready-test.js b/test/dep-transport-ready-test.js index e3e5519a..bd5fb214 100644 --- a/test/dep-transport-ready-test.js +++ b/test/dep-transport-ready-test.js @@ -1,14 +1,15 @@ 'use strict'; -var nodePath = require('path'); -var chai = require('chai'); + +const nodePath = require('path'); +const chai = require('chai'); chai.config.includeStack = true; require('chai').should(); -var MockLassoContext = require('./mock/MockLassoContext'); +const MockLassoContext = require('./mock/MockLassoContext'); -describe('lasso-require/dep-transport-ready' , function() { +describe('lasso-require/dep-transport-ready', function() { require('./autotest').scanDir( nodePath.join(__dirname, 'autotests/dep-transport-ready'), - function (dir, helpers, done) { + async function (dir, helpers) { var main = require(nodePath.join(dir, 'test.js')); var dependencyProps = main.createDependency(dir); @@ -23,14 +24,7 @@ describe('lasso-require/dep-transport-ready' , function() { dependency.init(lassoContext); - return Promise.resolve() - .then(() => { - return dependency.read(lassoContext); - }) - .then((src) => { - helpers.compare(src, '.js'); - done(); - }) - .catch(done); + const src = await dependency.read(lassoContext); + helpers.compare(src, '.js'); }); -}); \ No newline at end of file +}); diff --git a/test/dep-transport-remap-test.js b/test/dep-transport-remap-test.js index a586e079..7d83d8c9 100644 --- a/test/dep-transport-remap-test.js +++ b/test/dep-transport-remap-test.js @@ -1,36 +1,28 @@ 'use strict'; -var nodePath = require('path'); -var chai = require('chai'); + +const nodePath = require('path'); +const chai = require('chai'); chai.config.includeStack = true; require('chai').should(); -var MockLassoContext = require('./mock/MockLassoContext'); +const MockLassoContext = require('./mock/MockLassoContext'); -describe('lasso-require/dep-transport-remap' , function() { +describe('lasso-require/dep-transport-remap', function() { require('./autotest').scanDir( nodePath.join(__dirname, 'autotests/dep-transport-remap'), - function (dir, helpers, done) { + async function (dir, helpers) { var main = require(nodePath.join(dir, 'test.js')); var dependencyProps = main.createDependency(dir); - var pluginConfig = main.getPluginConfig ? main.getPluginConfig() : {}; + pluginConfig.rootDir = dir; var dependencyFactory = require('./mock/dependency-factory').create(pluginConfig); - var dependency = dependencyFactory.depTransportRemap(dependencyProps); - var lassoContext = new MockLassoContext(); dependency.init(lassoContext); - return Promise.resolve() - .then(() => { - return dependency.read(lassoContext); - }) - .then((src) => { - helpers.compare(src, '.js'); - done(); - }) - .catch(done); + const src = await dependency.read(lassoContext); + helpers.compare(src, '.js'); }); -}); \ No newline at end of file +}); diff --git a/test/dep-transport-run-test.js b/test/dep-transport-run-test.js index 01fa8cf4..be148361 100644 --- a/test/dep-transport-run-test.js +++ b/test/dep-transport-run-test.js @@ -1,36 +1,28 @@ 'use strict'; -var nodePath = require('path'); -var chai = require('chai'); + +const nodePath = require('path'); +const chai = require('chai'); chai.config.includeStack = true; require('chai').should(); -var MockLassoContext = require('./mock/MockLassoContext'); +const MockLassoContext = require('./mock/MockLassoContext'); describe('lasso-require/dep-transport-run' , function() { require('./autotest').scanDir( nodePath.join(__dirname, 'autotests/dep-transport-run'), - function (dir, helpers, done) { + async function (dir, helpers) { var main = require(nodePath.join(dir, 'test.js')); var dependencyProps = main.createDependency(dir); - var pluginConfig = main.getPluginConfig ? main.getPluginConfig() : {}; + pluginConfig.rootDir = dir; var dependencyFactory = require('./mock/dependency-factory').create(pluginConfig); - var dependency = dependencyFactory.depTransportRun(dependencyProps); - var lassoContext = new MockLassoContext(); dependency.init(lassoContext); - return Promise.resolve() - .then(() => { - return dependency.read(lassoContext); - }) - .then((src) => { - helpers.compare(src, '.js'); - done(); - }) - .catch(done); + const src = await dependency.read(lassoContext); + helpers.compare(src, '.js'); }); -}); \ No newline at end of file +}); diff --git a/test/dependency-walker-test.js b/test/dependency-walker-test.js index cd6b44bf..331a1971 100644 --- a/test/dependency-walker-test.js +++ b/test/dependency-walker-test.js @@ -1,17 +1,17 @@ 'use strict'; -var nodePath = require('path'); + +const nodePath = require('path'); require('chai').config.includeStack = true; -var ok = require('assert').ok; -var normalizeOutput = require('./util/normalizeOutput'); +const ok = require('assert').ok; +const normalizeOutput = require('./util/normalizeOutput'); -var DependencyTree = require('../lib/DependencyTree'); -var lasso = require('../'); +const DependencyTree = require('../lib/DependencyTree'); +const lasso = require('../'); -describe('lasso/dependency-walker' , function() { +describe('lasso/dependency-walker', function() { require('./autotest').scanDir( nodePath.join(__dirname, 'autotests/dependency-walker'), - function (dir, helpers, done) { - + async function (dir, helpers) { var dependencyWalker = require('../lib/dependency-walker'); var LassoManifest = require('../lib/LassoManifest'); @@ -34,7 +34,7 @@ describe('lasso/dependency-walker' , function() { var lassoManifest = new LassoManifest({ manifest: { - dependencies:dependencies + dependencies }, dependencyRegistry: dependencyRegistry, dirname: dir @@ -49,17 +49,11 @@ describe('lasso/dependency-walker' , function() { } }; - dependencyWalker.walk(walkOptions, function(err) { - if (err) { - return done(err); - } + await dependencyWalker.walk(walkOptions); - var output = tree.toString(); - output = normalizeOutput(output, dir); + var output = tree.toString(); + output = normalizeOutput(output, dir); - helpers.compare(output, '.txt'); - done(); - }); + helpers.compare(output, '.txt'); }); - -}); \ No newline at end of file +}); diff --git a/test/flags-test.js b/test/flags-test.js index 54a055f5..b88c61b5 100644 --- a/test/flags-test.js +++ b/test/flags-test.js @@ -1,18 +1,18 @@ 'use strict'; -var nodePath = require('path'); + +const nodePath = require('path'); require('chai').config.includeStack = true; -var WriterTracker = require('./util/WriterTracker'); -var rmdirRecursive = require('./util').rmdirRecursive; -var buildDir = nodePath.join(__dirname, 'build'); +const WriterTracker = require('./util/WriterTracker'); +const rmdirRecursive = require('./util').rmdirRecursive; +const buildDir = nodePath.join(__dirname, 'build'); -var lasso = require('../'); +const lasso = require('../'); describe('lasso/flags' , function() { require('./autotest').scanDir( nodePath.join(__dirname, 'autotests/flags'), - function (dir, helpers, done) { - + async function (dir, helpers) { var main = require(nodePath.join(dir, 'test.js')); var testName = nodePath.basename(dir); var pageName = 'flags-' + testName; @@ -29,23 +29,18 @@ describe('lasso/flags' , function() { lassoConfig.outputDir = nodePath.join(buildDir, pageName); } - rmdirRecursive(lassoConfig.outputDir); var myLasso = lasso.create(lassoConfig, dir); - var lassoOptions = main.getLassoOptions(dir); + lassoOptions.pageName = pageName; lassoOptions.from = dir; var writerTracker = WriterTracker.create(myLasso.writer); - myLasso.lassoPage(lassoOptions) - .then((lassoPageResult) => { - main.check(lassoPageResult, writerTracker); - lasso.flushAllCaches(done); - }) - .catch(done); + const lassoPageResult = await myLasso.lassoPage(lassoOptions); + main.check(lassoPageResult, writerTracker); + await lasso.flushAllCaches(); }); - -}); \ No newline at end of file +}); diff --git a/test/inspect-cache-test.js b/test/inspect-cache-test.js index c3e7f917..0c990ef9 100644 --- a/test/inspect-cache-test.js +++ b/test/inspect-cache-test.js @@ -1,17 +1,16 @@ 'use strict'; -var nodePath = require('path'); -var chai = require('chai'); +const nodePath = require('path'); +const chai = require('chai'); chai.config.includeStack = true; -var expect = require('chai').expect; -var fs = require('fs'); -var inspectCache = require('../lib/require/inspect-cache'); -var nodePath = require('path'); -var buildPluginConfig = require('../lib/require/build-plugin-config'); -var MockLassoContext = require('./mock/MockLassoContext'); +const expect = require('chai').expect; +const fs = require('fs'); +const inspectCache = require('../lib/require/inspect-cache'); +const buildPluginConfig = require('../lib/require/build-plugin-config'); +const MockLassoContext = require('./mock/MockLassoContext'); -describe('lasso-require/util/inspect' , function() { - it('should read from cache with matching last modified', (done) => { +describe('lasso-require/util/inspect', function() { + it('should read from cache with matching last modified', async () => { var pluginConfig = { builtins: { foo: require.resolve('./fixtures/builtin-foo') @@ -35,23 +34,17 @@ describe('lasso-require/util/inspect' , function() { return Promise.resolve(10); } - inspectCache.inspectCached(path, {createReadStream, getLastModified}, lassoContext, mockPluginConfig) - .then((inspectResult) => { - expect(readCount).to.equal(1); - expect(inspectResult.fromCache).to.equal(undefined); + let inspectResult = await inspectCache.inspectCached(path, {createReadStream, getLastModified}, lassoContext, mockPluginConfig); + expect(readCount).to.equal(1); + expect(inspectResult.fromCache).to.equal(undefined); - // Inspect the same file... should come from the cache - return inspectCache.inspectCached(path, {createReadStream, getLastModified}, lassoContext, mockPluginConfig); - }) - .then((inspectResult) => { - expect(inspectResult.fromCache).to.equal(true); - expect(readCount).to.equal(1); - }) - .then(done) - .catch(done); + // Inspect the same file... should come from the cache + inspectResult = await inspectCache.inspectCached(path, {createReadStream, getLastModified}, lassoContext, mockPluginConfig); + expect(inspectResult.fromCache).to.equal(true); + expect(readCount).to.equal(1); }); - it('should still read from cache without getLastModified', (done) => { + it('should still read from cache without getLastModified', async () => { var pluginConfig = { builtins: { foo: require.resolve('./fixtures/builtin-foo') @@ -71,24 +64,18 @@ describe('lasso-require/util/inspect' , function() { return fs.createReadStream(path, { encoding: 'utf8' }); } + // TODO: Change should this be removed in this test? function getLastModified() { return Promise.resolve(-1); } - inspectCache.inspectCached(path, {createReadStream, getLastModified}, lassoContext, mockPluginConfig) - .then((inspectResult) => { - expect(readCount).to.equal(1); - expect(inspectResult.fromCache).to.equal(undefined); + let inspectResult = await inspectCache.inspectCached(path, {createReadStream, getLastModified}, lassoContext, mockPluginConfig); + expect(readCount).to.equal(1); + expect(inspectResult.fromCache).to.equal(undefined); - // Inspect the same file... should come from the cache - return inspectCache.inspectCached(path, {createReadStream, getLastModified}, lassoContext, mockPluginConfig); - }) - .then((inspectResult) => { - expect(inspectResult.fromCache).to.equal(true); - expect(readCount).to.equal(2); - }) - .then(done) - .catch(done); + // Inspect the same file... should come from the cache + inspectResult = await inspectCache.inspectCached(path, {createReadStream, getLastModified}, lassoContext, mockPluginConfig); + expect(inspectResult.fromCache).to.equal(true); + expect(readCount).to.equal(2); }); - -}); \ No newline at end of file +}); diff --git a/test/inspect-test.js b/test/inspect-test.js index d17cf971..cdc8d818 100644 --- a/test/inspect-test.js +++ b/test/inspect-test.js @@ -1,22 +1,18 @@ 'use strict'; - -var nodePath = require('path'); -var chai = require('chai'); +const nodePath = require('path'); +const chai = require('chai'); chai.config.includeStack = true; -var fs = require('fs'); -var inspect = require('../lib/require/util/inspect'); +const fs = require('fs'); +const inspect = require('../lib/require/util/inspect'); -describe('lasso-require/util/inspect' , function() { +describe('lasso-require/util/inspect', function() { require('./autotest').scanDir( nodePath.join(__dirname, 'autotests/inspect'), - function (dir, helpers, done) { - - var inputPath = nodePath.join(dir, 'input.js'); - var inputSrc = fs.readFileSync(inputPath, { encoding: 'utf8' }); - var inspected = inspect(inputSrc, { allowShortcircuit: false }); + async function (dir, helpers) { + const inputPath = nodePath.join(dir, 'input.js'); + const inputSrc = fs.readFileSync(inputPath, { encoding: 'utf8' }); + const inspected = inspect(inputSrc, { allowShortcircuit: false }); helpers.compare(inspected, '.json'); - return done(); }); - -}); \ No newline at end of file +}); diff --git a/test/mock/MockLassoContext.js b/test/mock/MockLassoContext.js index 06433530..19bcdd2a 100644 --- a/test/mock/MockLassoContext.js +++ b/test/mock/MockLassoContext.js @@ -101,12 +101,12 @@ class MockLassoContext { return { object: requireExt.object === true, - init() { + async init () { return Promise.resolve(); }, - getDependencies() { - return Promise.resolve([]); + async getDependencies() { + return []; }, createReadStream: requireExt.createReadStream(path, lassoContext), @@ -222,7 +222,7 @@ class MockLassoContext { return this.nextId++; } - getFileLastModified(path) { + async getFileLastModified(path) { return Promise.resolve(-1); } diff --git a/test/mock/MockRequireHandler.js b/test/mock/MockRequireHandler.js index 17f1b11c..da97d59b 100644 --- a/test/mock/MockRequireHandler.js +++ b/test/mock/MockRequireHandler.js @@ -26,10 +26,9 @@ class RequireHandler { }; this.lastModified = null; this.object = userOptions.object === true; - } - init() { + async init() { var lassoContext = this.lassoContext; var userInit = this.userOptions.init; @@ -77,7 +76,7 @@ class RequireHandler { } } - getLastModified() { + async getLastModified() { var lassoContext = this.lassoContext; var path = this.path; var lastModifiedPromise = this.lastModified; @@ -121,19 +120,8 @@ class RequireHandler { return EMPTY_ARRAY_PROMISE; } - return new Promise((resolve, reject) => { - var userPromise = userGetDependencies.call(this.userThisObject, lassoContext, (err, dependencies) => { - if (err) { - reject(err); - } else { - resolve(dependencies); - } - }); - - if (userPromise !== undefined) { - resolve(userPromise); - } - }); + console.log('THIS USER GETDEP: ', userGetDependencies); + return userGetDependencies.call(this.userThisObject, lassoContext); } getDefaultBundleName(pageBundleName, lassoContext) { @@ -144,4 +132,4 @@ class RequireHandler { } } -module.exports = RequireHandler; \ No newline at end of file +module.exports = RequireHandler; diff --git a/test/mock/create-lasso-context.js b/test/mock/create-lasso-context.js index 63962c50..d03aab6c 100644 --- a/test/mock/create-lasso-context.js +++ b/test/mock/create-lasso-context.js @@ -80,12 +80,12 @@ module.exports = function createLassoContext(config) { return { object: requireExt.object === true, - init() { + async init() { return Promise.resolve(); }, - getDependencies() { - return Promise.resolve([]); + async getDependencies() { + return []; }, createReadStream: requireExt.createReadStream(path, lassoContext), @@ -119,4 +119,4 @@ module.exports = function createLassoContext(config) { mockCaches[cacheName] = new MockMemoryCache(); }; return lassoContext; -} \ No newline at end of file +} diff --git a/test/modules-test.js b/test/modules-test.js index 44c74a9f..458727ae 100644 --- a/test/modules-test.js +++ b/test/modules-test.js @@ -1,21 +1,18 @@ 'use strict'; -var series = require('raptor-async/series'); -var nodePath = require('path'); -require('chai').config.includeStack = true; - -var sandboxLoad = require('./util').sandboxLoad; -var rmdirRecursive = require('./util').rmdirRecursive; -var writeTestHtmlPage = require('./util').writeTestHtmlPage; -var buildDir = nodePath.join(__dirname, 'build'); +const nodePath = require('path'); +require('chai').config.includeStack = true; -var lasso = require('../'); +const sandboxLoad = require('./util').sandboxLoad; +const rmdirRecursive = require('./util').rmdirRecursive; +const writeTestHtmlPage = require('./util').writeTestHtmlPage; +const buildDir = nodePath.join(__dirname, 'build'); +const lasso = require('../'); -describe('lasso/modules' , function() { +describe('lasso/modules', function() { require('./autotest').scanDir( nodePath.join(__dirname, 'autotests/modules'), - function (dir, helpers, done) { - + async function (dir, helpers) { var main = require(nodePath.join(dir, 'test.js')); var testName = nodePath.basename(dir); var pageName = 'modules-' + testName; @@ -57,54 +54,39 @@ describe('lasso/modules' , function() { throw Error('Illegal state'); } - - var testTasks = tests.map((test) => { - return function(done) { - - var lassoOptions = test.lassoOptions; - if (!lassoOptions.pageName) { - lassoOptions.pageName = pageName; + for (const test of tests) { + var lassoOptions = test.lassoOptions; + if (!lassoOptions.pageName) { + lassoOptions.pageName = pageName; + } + + lassoOptions.from = dir; + + var check = test.check; + var checkError = test.checkError; + var modulesRuntimeGlobal = myLasso.config.modulesRuntimeGlobal; + + let lassoPageResult; + try { + lassoPageResult = await myLasso.lassoPage(lassoOptions); + } catch (err) { + if (checkError) { + checkError(err); + return; + } else { + throw err; } + } - lassoOptions.from = dir; - - var check = test.check; - var checkError = test.checkError; - var modulesRuntimeGlobal = myLasso.config.modulesRuntimeGlobal; - - myLasso.lassoPage(lassoOptions) - .then((lassoPageResult) => { - - if (checkError) { - return done('Error expected'); - } - - writeTestHtmlPage(lassoPageResult, nodePath.join(buildDir, pageName + '/test.html')); - var sandbox = sandboxLoad(lassoPageResult, modulesRuntimeGlobal); - sandbox.$outputDir = lassoConfig.outputDir; - if (check.length === 2) { - check(sandbox.window, done); - } else { - check(sandbox.window); - done(); - } - - - }) - .catch((err) => { - if (checkError) { - checkError(err); - done(); - } else { - throw err; - } - }) - .catch(done); - }; - }); + if (checkError) { + throw new Error('Error expected'); + } - series(testTasks, done); + writeTestHtmlPage(lassoPageResult, nodePath.join(buildDir, pageName + '/test.html')); + var sandbox = sandboxLoad(lassoPageResult, modulesRuntimeGlobal); + sandbox.$outputDir = lassoConfig.outputDir; + await check(sandbox.window); + } }); - -}); \ No newline at end of file +}); diff --git a/test/plugins-test.js b/test/plugins-test.js index 93d3c0e7..ea4ff341 100644 --- a/test/plugins-test.js +++ b/test/plugins-test.js @@ -1,19 +1,17 @@ 'use strict'; -var nodePath = require('path'); +const nodePath = require('path'); require('chai').config.includeStack = true; -var WriterTracker = require('./util/WriterTracker'); -var rmdirRecursive = require('./util').rmdirRecursive; -var normalizeOutput = require('./util/normalizeOutput'); +const WriterTracker = require('./util/WriterTracker'); +const rmdirRecursive = require('./util').rmdirRecursive; +const normalizeOutput = require('./util/normalizeOutput'); +const buildDir = nodePath.join(__dirname, 'build'); +const lasso = require('../'); -var buildDir = nodePath.join(__dirname, 'build'); - -var lasso = require('../'); - -describe('lasso/plugins' , function() { +describe('lasso/plugins', function() { require('./autotest').scanDir( nodePath.join(__dirname, 'autotests/plugins'), - function (dir, helpers, done) { + async function (dir, helpers) { helpers.normalizeOutput = normalizeOutput; var main = require(nodePath.join(dir, 'test.js')); var testName = nodePath.basename(dir); @@ -41,12 +39,8 @@ describe('lasso/plugins' , function() { var writerTracker = WriterTracker.create(myLasso.writer); - myLasso.lassoPage(lassoOptions) - .then((lassoPageResult) => { - main.check(lassoPageResult, writerTracker, helpers); - lasso.flushAllCaches(done); - }) - .catch(done); + const lassoPageResult = await myLasso.lassoPage(lassoOptions); + main.check(lassoPageResult, writerTracker, helpers); + await lasso.flushAllCaches(); }); - -}); \ No newline at end of file +}); diff --git a/test/require-no-op-test.js b/test/require-no-op-test.js index b812f1bb..89a6af23 100644 --- a/test/require-no-op-test.js +++ b/test/require-no-op-test.js @@ -1,16 +1,15 @@ 'use strict'; -var nodePath = require('path'); + +const nodePath = require('path'); require('chai').config.includeStack = true; -var nodeRequireNoOp = require('../node-require-no-op'); +const nodeRequireNoOp = require('../node-require-no-op'); -describe('lasso/config' , function() { +describe('lasso/config', function() { require('./autotest').scanDir( nodePath.join(__dirname, 'autotests/require-no-op'), - function (dir, helpers, done) { - var main = require(nodePath.join(dir, 'test.js')); + async function (dir, helpers) { + const main = require(nodePath.join(dir, 'test.js')); main.check(nodeRequireNoOp); - done(); }); - -}); \ No newline at end of file +}); diff --git a/test/resource-transforms-test.js b/test/resource-transforms-test.js index 33c41345..2ea5430a 100644 --- a/test/resource-transforms-test.js +++ b/test/resource-transforms-test.js @@ -1,19 +1,15 @@ 'use strict'; -var nodePath = require('path'); +const nodePath = require('path'); require('chai').config.includeStack = true; -var series = require('raptor-async/series'); -var rmdirRecursive = require('./util').rmdirRecursive; +const rmdirRecursive = require('./util').rmdirRecursive; +const buildDir = nodePath.join(__dirname, 'build'); +const lasso = require('../'); -var buildDir = nodePath.join(__dirname, 'build'); - -var lasso = require('../'); - -describe('lasso/resource-transforms' , function() { +describe('lasso/resource-transforms', function() { require('./autotest').scanDir( nodePath.join(__dirname, 'autotests/resource-transforms'), - function (dir, helpers, done) { - + async function (dir, helpers) { var main = require(nodePath.join(dir, 'test.js')); var testName = nodePath.basename(dir); var pageName = 'resource-transforms-' + testName; @@ -37,38 +33,21 @@ describe('lasso/resource-transforms' , function() { rmdirRecursive(lassoConfig.outputDir); var myLasso = lasso.create(lassoConfig, dir); - var inputs = main.getInputs(); - var asyncTasks = inputs.map((input, i) => { - return (callback) => { - var path = input.path; - var options = input.options; - - myLasso.lassoResource(path, options, function(err, result) { - if (err) { - callback(err); - } - - process.nextTick(() => { - try { - input.check(result); - } catch(e) { - return callback(`The inputs at index ${i} failed: ${e.stack}`); - } + let i = 0; + for (const input of inputs) { + var path = input.path; + var options = input.options; - callback(); - }); - }); - }; - }); - - series(asyncTasks, function(err) { - if (err) { - return done(err); + const result = await myLasso.lassoResource(path, options); + try { + input.check(result); + } catch (e) { + throw new Error(`The inputs at index ${i} failed: ${e.stack}`, e); } - done(); - }); - }); -}); \ No newline at end of file + i++; + } + }); +}); diff --git a/test/taglib-marko2-test.js b/test/taglib-marko2-test.js deleted file mode 100644 index 137267bd..00000000 --- a/test/taglib-marko2-test.js +++ /dev/null @@ -1,78 +0,0 @@ -'use strict'; -var nodePath = require('path'); -require('chai').config.includeStack = true; -var marko = require('marko-v2'); -var lasso = require('../'); -var rmdirRecursive = require('./util').rmdirRecursive; -var buildDir = nodePath.join(__dirname, 'build'); -var fs = require('fs'); - -require('marko-v2/compiler').defaultOptions.checkUpToDate = false; -require('marko-v2/compiler').defaultOptions.assumeUpToDate = false; - -describe('lasso/taglib-marko2' , function() { - require('./autotest').scanDir( - nodePath.join(__dirname, 'autotests/taglib-marko2'), - function (dir, helpers, done) { - var testName = nodePath.basename(dir); - var pageName = 'taglib-' + testName; - - var mainPath = nodePath.join(dir, 'test.js'); - var main; - - if (fs.existsSync(mainPath)) { - main = require(mainPath); - } else { - main = {}; - } - - var lassoConfig = main.getLassoConfig && main.getLassoConfig(); - if (!lassoConfig) { - lassoConfig = { - bundlingEnabled: true, - fingerprintsEnabled: true - }; - } - - if (!lassoConfig.outputDir) { - lassoConfig.outputDir = nodePath.join(buildDir, pageName); - } - - rmdirRecursive(lassoConfig.outputDir); - - var theLasso = lasso.create(lassoConfig, dir); - - // var main = require(nodePath.join(dir, 'test.js')); - var templatePath = nodePath.join(dir, 'template.marko'); - var template = marko.load(templatePath); - - var templateData; - - if (main.getTemplateData) { - templateData = main.getTemplateData(); - } - - if (!templateData) { - templateData = {}; - } - - if (!templateData.$global) { - templateData.$global = {}; - } - - templateData.$global.cspNonce = 'abc123'; - templateData.$global.lasso = theLasso; - - templateData.pageName = pageName; - - template.render(templateData, function(err, html) { - if (err) { - return done(err); - } - - helpers.compare(html, '.html'); - done(); - }); - }); - -}); \ No newline at end of file diff --git a/test/taglib-test.js b/test/taglib-test.js index 80075676..0f14df7c 100644 --- a/test/taglib-test.js +++ b/test/taglib-test.js @@ -1,16 +1,17 @@ 'use strict'; -var nodePath = require('path'); + +const nodePath = require('path'); require('chai').config.includeStack = true; -var marko = require('marko'); -var lasso = require('../'); -var rmdirRecursive = require('./util').rmdirRecursive; -var buildDir = nodePath.join(__dirname, 'build'); -var fs = require('fs'); +const marko = require('marko'); +const lasso = require('../'); +const rmdirRecursive = require('./util').rmdirRecursive; +const buildDir = nodePath.join(__dirname, 'build'); +const fs = require('fs'); -describe('lasso/taglib' , function() { +describe('lasso/taglib', function() { require('./autotest').scanDir( nodePath.join(__dirname, 'autotests/taglib'), - function (dir, helpers, done) { + function (dir, helpers) { var testName = nodePath.basename(dir); var pageName = 'taglib-' + testName; @@ -63,20 +64,23 @@ describe('lasso/taglib' , function() { templateData.$global.lasso = theLasso; templateData.pageName = pageName; - template.renderToString(templateData, function(err, html) { - if (err) { - return done(err); - } + return new Promise((resolve, reject) => { + template.renderToString(templateData, function(err, html) { + if (err) { + return reject(err); + } + + html = html.replace(/\$\d+\.\d+\.\d+/g, '$*'); - html = html.replace(/\$\d+\.\d+\.\d+/g, '$*'); + if (main.check) { + main.check(html); + } else { + helpers.compare(html, '.marko'); + } - if (main.check) { - main.check(html); - } else { - helpers.compare(html, '.marko'); - } - done(); + resolve(); + }); }); }); -}); \ No newline at end of file +}); diff --git a/test/transforms-test.js b/test/transforms-test.js index 40f749d4..3e19030e 100644 --- a/test/transforms-test.js +++ b/test/transforms-test.js @@ -1,19 +1,16 @@ 'use strict'; -var nodePath = require('path'); +const nodePath = require('path'); require('chai').config.includeStack = true; -var WriterTracker = require('./util/WriterTracker'); -var rmdirRecursive = require('./util').rmdirRecursive; +const WriterTracker = require('./util/WriterTracker'); +const rmdirRecursive = require('./util').rmdirRecursive; +const buildDir = nodePath.join(__dirname, 'build'); +const lasso = require('../'); -var buildDir = nodePath.join(__dirname, 'build'); - -var lasso = require('../'); - -describe('lasso/transforms' , function() { +describe('lasso/transforms', function() { require('./autotest').scanDir( nodePath.join(__dirname, 'autotests/transforms'), - function (dir, helpers, done) { - + async function (dir, helpers) { var main = require(nodePath.join(dir, 'test.js')); var testName = nodePath.basename(dir); var pageName = 'transforms-' + testName; @@ -44,12 +41,8 @@ describe('lasso/transforms' , function() { var writerTracker = WriterTracker.create(myLasso.writer); - myLasso.lassoPage(lassoOptions) - .then((lassoPageResult) => { - main.check(lassoPageResult, writerTracker); - lasso.flushAllCaches(done); - }) - .catch(done); + const lassoPageResult = await myLasso.lassoPage(lassoOptions); + main.check(lassoPageResult, writerTracker); + await lasso.flushAllCaches(); }); - -}); \ No newline at end of file +}); diff --git a/test/util-test.js b/test/util-test.js index df3d0b13..152ce75f 100644 --- a/test/util-test.js +++ b/test/util-test.js @@ -1,14 +1,13 @@ 'use strict'; -var nodePath = require('path'); +const nodePath = require('path'); require('chai').config.includeStack = true; -var util = require('../lib/util'); +const util = require('../lib/util'); -describe('lasso/util' , function() { +describe('lasso/util', function() { require('./autotest').scanDir( nodePath.join(__dirname, 'autotests/util'), - function (dir, helpers, done) { + async function (dir, helpers) { var main = require(nodePath.join(dir, 'test.js')); - main.check(util, done); + return main.check(util); }); - -}); \ No newline at end of file +}); diff --git a/test/util/index.js b/test/util/index.js index 2a61657b..8f62c1d8 100644 --- a/test/util/index.js +++ b/test/util/index.js @@ -51,7 +51,12 @@ function sandboxLoad(lassoPageResult, modulesRuntimeGlobal) { } var path = file.path; - loadScript(path); + try { + loadScript(path); + } catch (err) { + console.error(`Error loading file ${JSON.stringify(file)}`, err); + throw err; + } }); modulesRuntimeGlobal = modulesRuntimeGlobal || '$_mod'; @@ -81,4 +86,4 @@ function writeTestHtmlPage(lassoPageResult, outputFile) { exports.rmdirRecursive = rmdirRecursive; exports.sandboxLoad = sandboxLoad; -exports.writeTestHtmlPage = writeTestHtmlPage; \ No newline at end of file +exports.writeTestHtmlPage = writeTestHtmlPage;