aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--package.json2
-rw-r--r--src/index.js72
-rw-r--r--src/utils.js34
-rw-r--r--utils.js1
4 files changed, 101 insertions, 8 deletions
diff --git a/package.json b/package.json
index 2b5b1ba..7383175 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
1{ 1{
2 "name": "purs-loader", 2 "name": "purs-loader",
3 "version": "3.2.0", 3 "version": "3.3.0",
4 "description": "A webpack loader for PureScript.", 4 "description": "A webpack loader for PureScript.",
5 "main": "lib/index.js", 5 "main": "lib/index.js",
6 "files": [ 6 "files": [
diff --git a/src/index.js b/src/index.js
index cc779f7..8a2e468 100644
--- a/src/index.js
+++ b/src/index.js
@@ -26,6 +26,8 @@ const sourceMaps = require('./source-maps');
26 26
27const dargs = require('./dargs'); 27const dargs = require('./dargs');
28 28
29const utils = require('./utils');
30
29const spawn = require('cross-spawn').sync 31const spawn = require('cross-spawn').sync
30 32
31const eol = require('os').EOL 33const eol = require('os').EOL
@@ -40,6 +42,7 @@ var CACHE_VAR = {
40 errors: [], 42 errors: [],
41 compilationStarted: false, 43 compilationStarted: false,
42 compilationFinished: false, 44 compilationFinished: false,
45 compilationFailed: false,
43 installed: false, 46 installed: false,
44 srcOption: [] 47 srcOption: []
45}; 48};
@@ -147,6 +150,7 @@ module.exports = function purescriptLoader(source, map) {
147 errors: [], 150 errors: [],
148 compilationStarted: false, 151 compilationStarted: false,
149 compilationFinished: false, 152 compilationFinished: false,
153 compilationFailed: false,
150 installed: CACHE_VAR.installed, 154 installed: CACHE_VAR.installed,
151 srcOption: [] 155 srcOption: []
152 }; 156 };
@@ -184,9 +188,57 @@ module.exports = function purescriptLoader(source, map) {
184 CACHE_VAR.warnings.push(warning); 188 CACHE_VAR.warnings.push(warning);
185 } 189 }
186 }, 190 },
187 emitError: error => { 191 emitError: pscMessage => {
188 if (error.length) { 192 if (pscMessage.length) {
189 CACHE_VAR.errors.push(error); 193 const modules = [];
194
195 const matchErrorsSeparator = /\n(?=Error)/;
196 const errors = pscMessage.split(matchErrorsSeparator);
197 for (const error of errors) {
198 const matchErrLocation = /at (.+\.purs) line (\d+), column (\d+) - line (\d+), column (\d+)/;
199 const [, filename] = matchErrLocation.exec(error) || [];
200 if (!filename) continue;
201
202 const baseModulePath = path.join(this.rootContext, filename);
203 this.addDependency(baseModulePath);
204
205 const matchErrModuleName = /in module ((?:\w+\.)*\w+)/;
206 const [, baseModuleName] = matchErrModuleName.exec(error) || [];
207 if (!baseModuleName) continue;
208
209 const matchMissingModuleName = /Module ((?:\w+\.)*\w+) was not found/;
210 const matchMissingImportFromModuleName = /Cannot import value \w+ from module ((?:\w+\.)*\w+)/;
211 for (const re of [matchMissingModuleName, matchMissingImportFromModuleName]) {
212 const [, targetModuleName] = re.exec(error) || [];
213 if (targetModuleName) {
214 const resolved = utils.resolvePursModule({
215 baseModulePath,
216 baseModuleName,
217 targetModuleName
218 });
219 this.addDependency(resolved);
220 }
221 }
222
223 const desc = {
224 name: baseModuleName,
225 filename: baseModulePath
226 };
227
228 if (typeof this.describePscError === 'function') {
229 const { dependencies = [], details } = this.describePscError(error, desc);
230
231 for (const dep of dependencies) {
232 this.addDependency(dep);
233 }
234
235 Object.assign(desc, details);
236 }
237
238 modules.push(desc);
239 }
240
241 CACHE_VAR.errors.push(new utils.PscError(pscMessage, modules));
190 } 242 }
191 } 243 }
192 } 244 }
@@ -258,6 +310,8 @@ module.exports = function purescriptLoader(source, map) {
258 ) 310 )
259 ) 311 )
260 .catch(error => { 312 .catch(error => {
313 CACHE_VAR.compilationFailed = true;
314
261 CACHE_VAR.deferred[0].reject(error); 315 CACHE_VAR.deferred[0].reject(error);
262 316
263 CACHE_VAR.deferred.slice(1).forEach(psModule => { 317 CACHE_VAR.deferred.slice(1).forEach(psModule => {
@@ -265,8 +319,9 @@ module.exports = function purescriptLoader(source, map) {
265 }) 319 })
266 }) 320 })
267 ; 321 ;
268 } 322 } else if (CACHE_VAR.compilationFailed) {
269 else { 323 CACHE_VAR.deferred.pop().reject(new Error('purs-loader failed'));
324 } else {
270 // The compilation has started. We must wait until it is 325 // The compilation has started. We must wait until it is
271 // done in order to ensure the module map contains all of 326 // done in order to ensure the module map contains all of
272 // the unknown modules. 327 // the unknown modules.
@@ -318,6 +373,8 @@ module.exports = function purescriptLoader(source, map) {
318 ) 373 )
319 ) 374 )
320 .catch(error => { 375 .catch(error => {
376 CACHE_VAR.compilationFailed = true;
377
321 CACHE_VAR.deferred[0].reject(error); 378 CACHE_VAR.deferred[0].reject(error);
322 379
323 CACHE_VAR.deferred.slice(1).forEach(psModule => { 380 CACHE_VAR.deferred.slice(1).forEach(psModule => {
@@ -325,8 +382,9 @@ module.exports = function purescriptLoader(source, map) {
325 }) 382 })
326 }) 383 })
327 ; 384 ;
328 } 385 } else if (CACHE_VAR.compilationFailed) {
329 else { 386 CACHE_VAR.deferred.pop().reject(new Error('purs-loader failed'));
387 } else {
330 // The complation has started. Nothing to do but wait until it is 388 // The complation has started. Nothing to do but wait until it is
331 // done before loading all of the modules. 389 // done before loading all of the modules.
332 } 390 }
diff --git a/src/utils.js b/src/utils.js
new file mode 100644
index 0000000..671b580
--- /dev/null
+++ b/src/utils.js
@@ -0,0 +1,34 @@
1const path = require('path');
2
3exports.PscError = class PscError extends Error {
4 constructor(message, modules) {
5 super(message);
6 this.modules = modules;
7 }
8
9 static get name() {
10 return 'PscError';
11 }
12};
13
14const repeat = (value, times) =>
15 times <= 0 ? [] : [value, ...repeat(value, times - 1)];
16const diffPursModuleNames = (from, target, parts) => {
17 if (!from.length) return parts.concat(target);
18 if (!target.length) return parts.concat(repeat('..', from.length));
19 const [head_from, ...tail_from] = from;
20 const [head_target, ...tail_target] = target;
21 return head_from === head_target
22 ? diffPursModuleNames(tail_from, tail_target, parts)
23 : parts.concat(repeat('..', from.length), target);
24};
25exports.resolvePursModule = ({ baseModulePath, baseModuleName, targetModuleName }) => {
26 const parts = diffPursModuleNames(
27 baseModuleName.split('.'),
28 targetModuleName.split('.'),
29 []);
30 return parts.length
31 ? path.resolve(baseModulePath,
32 `${path.join(...parts)}.purs`)
33 : baseModulePath;
34};
diff --git a/utils.js b/utils.js
new file mode 100644
index 0000000..cec6101
--- /dev/null
+++ b/utils.js
@@ -0,0 +1 @@
module.exports = require('./lib/utils');