'use strict';
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
var debug_ = require('debug');
var debug = debug_('purs-loader');
var debugVerbose = debug_('purs-loader:verbose');
var loaderUtils = require('loader-utils');
var Promise = require('bluebird');
var path = require('path');
var PsModuleMap = require('./purs-module-map');
var compile = require('./compile');
var bundle = require('./bundle');
var ide = require('./ide');
var toJavaScript = require('./to-javascript');
var sourceMaps = require('./source-maps');
var dargs = require('./dargs');
var utils = require('./utils');
var spawn = require('cross-spawn').sync;
var eol = require('os').EOL;
var CACHE_VAR = {
rebuild: false,
deferred: [],
bundleModules: [],
ideServer: null,
psModuleMap: null,
warnings: [],
errors: [],
compilationStarted: false,
compilationFinished: false,
compilationFailed: false,
installed: false,
srcOption: []
};
module.exports = function purescriptLoader(source, map) {
var _this = this;
this.cacheable && this.cacheable();
var webpackContext = this.options && this.options.context || this.rootContext;
var callback = this.async();
var loaderOptions = loaderUtils.getOptions(this) || {};
var srcOption = function (pscPackage) {
var srcPath = path.join('src', '**', '*.purs');
var bowerPath = path.join('bower_components', 'purescript-*', 'src', '**', '*.purs');
if (CACHE_VAR.srcOption.length > 0) {
return CACHE_VAR.srcOption;
} else if (pscPackage) {
var pscPackageCommand = 'psc-package';
var pscPackageArgs = ['sources'];
var loaderSrc = loaderOptions.src || [srcPath];
debug('psc-package %s %o', pscPackageCommand, pscPackageArgs);
var cmd = spawn(pscPackageCommand, pscPackageArgs);
if (cmd.error) {
throw new Error(cmd.error);
} else if (cmd.status !== 0) {
var error = cmd.stdout.toString();
throw new Error(error);
} else {
var result = cmd.stdout.toString().split(eol).filter(function (v) {
return v != '';
}).concat(loaderSrc);
debug('psc-package result: %o', result);
CACHE_VAR.srcOption = result;
return result;
}
} else {
var _result = loaderOptions.src || [bowerPath, srcPath];
CACHE_VAR.srcOption = _result;
return _result;
}
}(loaderOptions.pscPackage);
var options = Object.assign({
context: webpackContext,
psc: null,
pscArgs: {},
pscBundle: null,
pscBundleArgs: {},
pscIdeClient: null,
pscIdeClientArgs: {},
pscIdeServer: null,
pscIdeServerArgs: {},
pscIde: false,
pscIdeColors: loaderOptions.psc === 'psa',
pscPackage: false,
bundleOutput: 'output/bundle.js',
bundleNamespace: 'PS',
bundle: false,
warnings: true,
watch: false,
output: 'output',
src: []
}, loaderOptions, {
src: srcOption
});
if (!CACHE_VAR.installed) {
debugVerbose('installing purs-loader with options: %O', options);
CACHE_VAR.installed = true;
// invalidate loader CACHE_VAR when bundle is marked as invalid (in watch mode)
this._compiler.plugin('invalid', function () {
debugVerbose('invalidating loader CACHE_VAR');
CACHE_VAR = {
rebuild: options.pscIde,
deferred: [],
bundleModules: [],
ideServer: CACHE_VAR.ideServer,
psModuleMap: CACHE_VAR.psModuleMap,
warnings: [],
errors: [],
compilationStarted: false,
compilationFinished: false,
compilationFailed: false,
installed: CACHE_VAR.installed,
srcOption: []
};
});
// add psc warnings to webpack compilation warnings
this._compiler.plugin('after-compile', function (compilation, callback) {
CACHE_VAR.warnings.forEach(function (warning) {
compilation.warnings.push(warning);
});
CACHE_VAR.errors.forEach(function (error) {
compilation.errors.push(error);
});
callback();
});
}
var psModuleName = PsModuleMap.matchModule(source);
var psModule = {
name: psModuleName,
source: source,
load: function load(_ref) {
var js = _ref.js,
map = _ref.map;
return callback(null, js, map);
},
reject: function reject(error) {
return callback(error);
},
srcPath: this.resourcePath,
remainingRequest: loaderUtils.getRemainingRequest(this),
srcDir: path.dirname(this.resourcePath),
jsPath: path.resolve(path.join(options.output, psModuleName, 'index.js')),
options: options,
cache: CACHE_VAR,
emitWarning: function emitWarning(warning) {
if (options.warnings && warning.length) {
CACHE_VAR.warnings.push(warning);
}
},
emitError: function emitError(pscMessage) {
if (pscMessage.length) {
var modules = [];
var matchErrorsSeparator = /\n(?=Error)/;
var errors = pscMessage.split(matchErrorsSeparator);
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = errors[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var error = _step.value;
var matchErrLocation = /at (.+\.purs) line (\d+), column (\d+) - line (\d+), column (\d+)/;
var _ref2 = matchErrLocation.exec(error) || [],
_ref3 = _slicedToArray(_ref2, 2),
filename = _ref3[1];
if (!filename) continue;
var baseModulePath = path.join(_this.rootContext, filename);
_this.addDependency(baseModulePath);
var matchErrModuleName = /in module ((?:\w+\.)*\w+)/;
var _ref4 = matchErrModuleName.exec(error) || [],
_ref5 = _slicedToArray(_ref4, 2),
baseModuleName = _ref5[1];
if (!baseModuleName) continue;
var matchMissingModuleName = /Module ((?:\w+\.)*\w+) was not found/;
var matchMissingImportFromModuleName = /Cannot import value \w+ from module ((?:\w+\.)*\w+)/;
var _arr = [matchMissingModuleName, matchMissingImportFromModuleName];
for (var _i = 0; _i < _arr.length; _i++) {
var re = _arr[_i];
var _ref6 = re.exec(error) || [],
_ref7 = _slicedToArray(_ref6, 2),
targetModuleName = _ref7[1];
if (targetModuleName) {
var resolved = utils.resolvePursModule({
baseModulePath: baseModulePath,
baseModuleName: baseModuleName,
targetModuleName: targetModuleName
});
_this.addDependency(resolved);
}
}
var desc = {
name: baseModuleName,
filename: baseModulePath
};
if (typeof _this.describePscError === 'function') {
var _describePscError = _this.describePscError(error, desc),
_describePscError$dep = _describePscError.dependencies,
dependencies = _describePscError$dep === undefined ? [] : _describePscError$dep,
details = _describePscError.details;
var _iteratorNormalCompletion2 = true;
var _didIteratorError2 = false;
var _iteratorError2 = undefined;
try {
for (var _iterator2 = dependencies[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
var dep = _step2.value;
_this.addDependency(dep);
}
} catch (err) {
_didIteratorError2 = true;
_iteratorError2 = err;
} finally {
try {
if (!_iteratorNormalCompletion2 && _iterator2.return) {
_iterator2.return();
}
} finally {
if (_didIteratorError2) {
throw _iteratorError2;
}
}
}
Object.assign(desc, details);
}
modules.push(desc);
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
CACHE_VAR.errors.push(new utils.PscError(pscMessage, modules));
}
}
};
debug('loading %s', psModule.name);
if (options.bundle) {
CACHE_VAR.bundleModules.push(psModule.name);
}
if (CACHE_VAR.rebuild) {
var connect = function connect() {
if (!CACHE_VAR.ideServer) {
CACHE_VAR.ideServer = true;
return ide.connect(psModule).then(function (ideServer) {
CACHE_VAR.ideServer = ideServer;
return psModule;
}).then(ide.loadWithRetry).catch(function (error) {
if (CACHE_VAR.ideServer.kill) {
debug('ide failed to initially load modules, stopping the ide server process');
CACHE_VAR.ideServer.kill();
}
CACHE_VAR.ideServer = null;
return Promise.reject(error);
});
} else {
return Promise.resolve(psModule);
}
};
var rebuild = function rebuild() {
return ide.rebuild(psModule).then(function () {
return toJavaScript(psModule).then(function (js) {
return sourceMaps(psModule, js);
}).then(psModule.load).catch(psModule.reject);
}).catch(function (error) {
if (error instanceof ide.UnknownModuleError) {
// Store the modules that trigger a recompile due to an
// unknown module error. We need to wait until compilation is
// done before loading these files.
CACHE_VAR.deferred.push(psModule);
if (!CACHE_VAR.compilationStarted) {
CACHE_VAR.compilationStarted = true;
return compile(psModule).then(function () {
CACHE_VAR.compilationFinished = true;
}).then(function () {
return Promise.map(CACHE_VAR.deferred, function (psModule) {
return ide.load(psModule).then(function () {
return toJavaScript(psModule);
}).then(function (js) {
return sourceMaps(psModule, js);
}).then(psModule.load);
});
}).catch(function (error) {
CACHE_VAR.compilationFailed = true;
CACHE_VAR.deferred[0].reject(error);
CACHE_VAR.deferred.slice(1).forEach(function (psModule) {
psModule.reject(new Error('purs-loader failed'));
});
});
} else if (CACHE_VAR.compilationFailed) {
CACHE_VAR.deferred.pop().reject(new Error('purs-loader failed'));
} else {
// The compilation has started. We must wait until it is
// done in order to ensure the module map contains all of
// the unknown modules.
}
} else {
debug('ide rebuild failed due to an unhandled error: %o', error);
psModule.reject(error);
}
});
};
connect().then(rebuild);
} else if (CACHE_VAR.compilationFinished) {
debugVerbose('compilation is already finished, loading module %s', psModule.name);
toJavaScript(psModule).then(function (js) {
return sourceMaps(psModule, js);
}).then(psModule.load).catch(psModule.reject);
} else {
// The compilation has not finished yet. We need to wait for
// compilation to finish before the loaders run so that references
// to compiled output are valid. Push the modules into the CACHE_VAR to
// be loaded once the complation is complete.
CACHE_VAR.deferred.push(psModule);
if (!CACHE_VAR.compilationStarted) {
CACHE_VAR.compilationStarted = true;
compile(psModule).then(function () {
CACHE_VAR.compilationFinished = true;
}).then(function () {
if (options.bundle) {
return bundle(options, CACHE_VAR.bundleModules);
}
}).then(function () {
return Promise.map(CACHE_VAR.deferred, function (psModule) {
return toJavaScript(psModule).then(function (js) {
return sourceMaps(psModule, js);
}).then(psModule.load);
});
}).catch(function (error) {
CACHE_VAR.compilationFailed = true;
CACHE_VAR.deferred[0].reject(error);
CACHE_VAR.deferred.slice(1).forEach(function (psModule) {
psModule.reject(new Error('purs-loader failed'));
});
});
} else if (CACHE_VAR.compilationFailed) {
CACHE_VAR.deferred.pop().reject(new Error('purs-loader failed'));
} else {
// The complation has started. Nothing to do but wait until it is
// done before loading all of the modules.
}
}
};