Skip to content

Commit 4f0f243

Browse files
committed
fix($injector): refactor module loading code and use minErr
1 parent 48eb297 commit 4f0f243

File tree

4 files changed

+44
-35
lines changed

4 files changed

+44
-35
lines changed

src/auto/injector.js

+20-21
Original file line numberDiff line numberDiff line change
@@ -494,37 +494,36 @@ function createInjector(modulesToLoad) {
494494
forEach(modulesToLoad, function(module) {
495495
if (loadedModules.get(module)) return;
496496
loadedModules.put(module, true);
497-
if (isString(module)) {
498-
var moduleFn = angularModule(module);
499-
runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);
500497

501-
try {
498+
try {
499+
if (isString(module)) {
500+
var moduleFn = angularModule(module);
501+
runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);
502+
502503
for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {
503504
var invokeArgs = invokeQueue[i],
504505
provider = providerInjector.get(invokeArgs[0]);
505506

506507
provider[invokeArgs[1]].apply(provider, invokeArgs[2]);
507508
}
508-
} catch (e) {
509-
if (e.message) e.message += ' from ' + module;
510-
throw e;
509+
} else if (isFunction(module)) {
510+
runBlocks.push(providerInjector.invoke(module));
511+
} else if (isArray(module)) {
512+
runBlocks.push(providerInjector.invoke(module));
513+
} else {
514+
assertArgFn(module, 'module');
511515
}
512-
} else if (isFunction(module)) {
513-
try {
514-
runBlocks.push(providerInjector.invoke(module));
515-
} catch (e) {
516-
if (e.message) e.message += ' from ' + module;
517-
throw e;
516+
} catch (e) {
517+
if (isArray(module)) {
518+
module = module[module.length - 1];
518519
}
519-
} else if (isArray(module)) {
520-
try {
521-
runBlocks.push(providerInjector.invoke(module));
522-
} catch (e) {
523-
if (e.message) e.message += ' from ' + String(module[module.length - 1]);
524-
throw e;
520+
if (e.message && e.stack && e.stack.indexOf(e.message) == -1) {
521+
// Safari & FF's stack traces don't contain error.message content unlike those of Chrome and IE
522+
// So if stack doesn't contain message, we create a new string that contains both.
523+
// Since error.stack is read-only in Safari, I'm overriding e and not e.stack here.
524+
e = e.message + '\n' + e.stack;
525525
}
526-
} else {
527-
assertArgFn(module, 'module');
526+
throw $injectorMinErr('modulerr', "Failed to instantiate module {0} due to:\n{1}", module, e.stack || e.message || e);
528527
}
529528
});
530529
return runBlocks;

src/minErr.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
/**
44
* @description
55
*
6-
* This object provides a utility for producing rich Error messages within
6+
* This object provides a utility for producing rich Error messages within
77
* Angular. It can be called as follows:
88
*
99
* var exampleMinErr = minErr('example');
@@ -34,14 +34,14 @@ function minErr(module) {
3434
template = arguments[1],
3535
templateArgs = arguments,
3636
message;
37-
37+
3838
message = prefix + template.replace(/\{\d+\}/g, function (match) {
3939
var index = +match.slice(1, -1), arg;
4040

4141
if (index + 2 < templateArgs.length) {
4242
arg = templateArgs[index + 2];
4343
if (isFunction(arg)) {
44-
return arg.toString().replace(/ \{[\s\S]*$/, '');
44+
return arg.toString().replace(/ ?\{[\s\S]*$/, '');
4545
} else if (isUndefined(arg)) {
4646
return 'undefined';
4747
} else if (!isString(arg)) {

test/AngularSpec.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -605,7 +605,9 @@ describe('angular', function() {
605605

606606
expect(function() {
607607
angularInit(appElement, bootstrap);
608-
}).toThrow("[$injector:nomod] Module 'doesntexist' is not available! You either misspelled the module name or forgot to load it.");
608+
}).toThrowMatching(
609+
/\[\$injector:modulerr] Failed to instantiate module doesntexist due to:\n.*\[\$injector:nomod] Module 'doesntexist' is not available! You either misspelled the module name or forgot to load it\./
610+
);
609611
});
610612
});
611613

@@ -749,7 +751,8 @@ describe('angular', function() {
749751

750752
expect(function() {
751753
angular.bootstrap(element, ['doesntexist']);
752-
}).toThrow("[$injector:nomod] Module 'doesntexist' is not available! You either misspelled the module name or forgot to load it.");
754+
}).toThrowMatching(
755+
/\[\$injector:modulerr\] Failed to instantiate module doesntexist due to:\n.*\[\$injector:nomod\] Module 'doesntexist' is not available! You either misspelled the module name or forgot to load it\./);
753756

754757
expect(element.html()).toBe('{{1+2}}');
755758
dealoc(element);

test/auto/injectorSpec.js

+16-9
Original file line numberDiff line numberDiff line change
@@ -268,8 +268,9 @@ describe('injector', function() {
268268
it('should error on invalid module name', function() {
269269
expect(function() {
270270
createInjector(['IDontExist'], {});
271-
}).toThrow("[$injector:nomod] Module 'IDontExist' is not available! You either misspelled the module name or forgot to load it.");
272-
271+
}).toThrowMatching(
272+
/\[\$injector:modulerr\].+\n.*\[\$injector:nomod] Module 'IDontExist' is not available! You either misspelled the module name or forgot to load it/
273+
);
273274
});
274275

275276

@@ -552,7 +553,7 @@ describe('injector', function() {
552553
createInjector([
553554
{}
554555
], {});
555-
}).toThrow("[ng:areq] Argument 'module' is not a function, got Object");
556+
}).toThrowMatching(/\[\$injector:modulerr\] Failed to instantiate module {} due to:\n.*\[ng\:areq] Argument 'module' is not a function, got Object/);
556557
});
557558

558559

@@ -561,31 +562,37 @@ describe('injector', function() {
561562
createInjector([function() {
562563
throw 'MyError';
563564
}], {});
564-
}).toThrow('MyError');
565+
}).toThrowMatching(/\[\$injector:modulerr\] Failed to instantiate module .+ due to:\n.*MyError/);
565566
});
566567

567568

568569
it('should decorate the missing service error with module name', function() {
569570
angular.module('TestModule', [], function(xyzzy) {});
570571
expect(function() {
571-
createInjector(['TestModule']);
572-
}).toThrow('[$injector:unpr] Unknown provider: xyzzy from TestModule');
572+
createInjector(['TestModule' ]);
573+
}).toThrowMatching(
574+
/\[\$injector:modulerr\] Failed to instantiate module TestModule due to:\n.*\[\$injector:unpr] Unknown provider: xyzzy/
575+
);
573576
});
574577

575578

576579
it('should decorate the missing service error with module function', function() {
577580
function myModule(xyzzy){}
578581
expect(function() {
579582
createInjector([myModule]);
580-
}).toThrow('[$injector:unpr] Unknown provider: xyzzy from ' + myModule);
583+
}).toThrowMatching(
584+
/\[\$injector:modulerr\] Failed to instantiate module function myModule\(xyzzy\) due to:\n.*\[\$injector:unpr] Unknown provider: xyzzy/
585+
);
581586
});
582587

583588

584589
it('should decorate the missing service error with module array function', function() {
585590
function myModule(xyzzy){}
586591
expect(function() {
587592
createInjector([['xyzzy', myModule]]);
588-
}).toThrow('[$injector:unpr] Unknown provider: xyzzy from ' + myModule);
593+
}).toThrowMatching(
594+
/\[\$injector:modulerr\] Failed to instantiate module function myModule\(xyzzy\) due to:\n.*\[\$injector:unpr] Unknown provider: xyzzy/
595+
);
589596
});
590597

591598

@@ -801,7 +808,7 @@ describe('injector', function() {
801808
createInjector([function($provide) {
802809
$provide.value('name', 'angular')
803810
}, instanceLookupInModule]);
804-
}).toThrow('[$injector:unpr] Unknown provider: name from ' + String(instanceLookupInModule));
811+
}).toThrowMatching(/\[\$injector:unpr] Unknown provider: name/);
805812
});
806813
});
807814
});

0 commit comments

Comments
 (0)