Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit d406a15

Browse files
committed
fix(modules): allow modules to be loaded in any order when using angular-loader
Some modules used to assume that the angular helpers would always be available when their script was executed. This could be a problem when using `angular-loader` and the module file happened to get loaded before the core `angular.js` file. This commit fixes the issue by delaying the access to angular helpers, until they are guaranteed to be available. Affected modules: - `ngAnimate` - `ngMessageFormat` - `ngMessages` - `ngRoute` - `ngSanitize` Fixes #9140 Closes #14794
1 parent 4585b93 commit d406a15

19 files changed

+506
-404
lines changed

karma-modules.conf.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ module.exports = function(config) {
77
sharedConfig(config, {testName: 'AngularJS: modules', logFile: 'karma-modules.log'});
88

99
config.set({
10-
files: angularFiles.mergeFilesFor('karmaModules', 'angularSrcModules'),
10+
files: angularFiles.mergeFilesFor('karmaModules'),
1111

1212
junitReporter: {
1313
outputFile: 'test_out/modules.xml',

src/ngAnimate/.jshintrc

+65-52
Original file line numberDiff line numberDiff line change
@@ -6,68 +6,81 @@
66
"window": false,
77

88
"angular": false,
9-
"noop": false,
109

11-
"copy": false,
12-
"forEach": false,
13-
"extend": false,
14-
"jqLite": false,
15-
"isArray": false,
16-
"isString": false,
17-
"isObject": false,
18-
"isUndefined": false,
19-
"isDefined": false,
20-
"isFunction": false,
21-
"isElement": false,
10+
/* ng helpers */
11+
"copy": true,
12+
"extend": true,
13+
"forEach": true,
14+
"isArray": true,
15+
"isDefined": true,
16+
"isElement": true,
17+
"isFunction": true,
18+
"isObject": true,
19+
"isString": true,
20+
"isUndefined": true,
21+
"jqLite": true,
22+
"noop": true,
2223

23-
"ELEMENT_NODE": false,
24-
"COMMENT_NODE": false,
25-
"NG_ANIMATE_CLASSNAME": false,
26-
"NG_ANIMATE_CHILDREN_DATA": false,
24+
/* ngAnimate constants */
25+
"COMMENT_NODE": true,
26+
"ELEMENT_NODE": true,
27+
"NG_ANIMATE_CLASSNAME": true,
28+
"NG_ANIMATE_CHILDREN_DATA": true,
2729

28-
"ADD_CLASS_SUFFIX": false,
29-
"REMOVE_CLASS_SUFFIX": false,
30-
"EVENT_CLASS_PREFIX": false,
31-
"ACTIVE_CLASS_SUFFIX": false,
32-
"PREPARE_CLASS_SUFFIX": false,
30+
/* ngAnimate className constants */
31+
"ADD_CLASS_SUFFIX": true,
32+
"REMOVE_CLASS_SUFFIX": true,
33+
"EVENT_CLASS_PREFIX": true,
34+
"ACTIVE_CLASS_SUFFIX": true,
35+
"PREPARE_CLASS_SUFFIX": true,
3336

34-
"TRANSITION_DURATION_PROP": false,
35-
"TRANSITION_DELAY_PROP": false,
36-
"TRANSITION_PROP": false,
37-
"PROPERTY_KEY": false,
38-
"DURATION_KEY": false,
39-
"DELAY_KEY": false,
40-
"TIMING_KEY": false,
41-
"ANIMATION_DURATION_PROP": false,
42-
"ANIMATION_DELAY_PROP": false,
43-
"ANIMATION_PROP": false,
44-
"ANIMATION_ITERATION_COUNT_KEY": false,
45-
"SAFE_FAST_FORWARD_DURATION_VALUE": false,
46-
"TRANSITIONEND_EVENT": false,
47-
"ANIMATIONEND_EVENT": false,
37+
/* ngAnimate CSS constants */
38+
"ANIMATION_DELAY_PROP": true,
39+
"ANIMATION_DURATION_PROP": true,
40+
"ANIMATION_ITERATION_COUNT_KEY": true,
41+
"ANIMATION_PROP": true,
42+
"ANIMATIONEND_EVENT": true,
43+
"DELAY_KEY": true,
44+
"DURATION_KEY": true,
45+
"PROPERTY_KEY": true,
46+
"SAFE_FAST_FORWARD_DURATION_VALUE": true,
47+
"TIMING_KEY": true,
48+
"TRANSITION_DELAY_PROP": true,
49+
"TRANSITION_DURATION_PROP": true,
50+
"TRANSITION_PROP": true,
51+
"TRANSITIONEND_EVENT": true,
4852

49-
"assertArg": false,
50-
"isPromiseLike": false,
51-
"mergeClasses": false,
52-
"mergeAnimationDetails": false,
53-
"prepareAnimationOptions": false,
54-
"applyAnimationStyles": false,
53+
/* ngAnimate helpers */
54+
"applyAnimationClassesFactory": false,
5555
"applyAnimationFromStyles": false,
56+
"applyAnimationStyles": false,
5657
"applyAnimationToStyles": false,
57-
"applyAnimationClassesFactory": false,
58-
"pendClasses": false,
59-
"normalizeCssProp": false,
58+
"applyGeneratedPreparationClasses": false,
59+
"applyInlineStyle": false,
60+
"assertArg": false,
61+
"blockKeyframeAnimations": false,
62+
"blockTransitions": false,
63+
"clearGeneratedClasses": false,
64+
"concatWithSpace": false,
65+
"extractElementNode": false,
66+
"getDomNode": false,
67+
"mergeAnimationDetails": false,
68+
"mergeClasses": false,
6069
"packageStyles": false,
70+
"pendClasses": false,
71+
"prepareAnimationOptions": false,
6172
"removeFromArray": false,
6273
"stripCommentsFromElement": false,
63-
"extractElementNode": false,
64-
"getDomNode": false,
6574

66-
"applyGeneratedPreparationClasses": false,
67-
"clearGeneratedClasses": false,
68-
"blockTransitions": false,
69-
"blockKeyframeAnimations": false,
70-
"applyInlineStyle": false,
71-
"concatWithSpace": false
75+
/* ngAnimate directives/services */
76+
"ngAnimateSwapDirective": true,
77+
"$$rAFSchedulerFactory": true,
78+
"$$AnimateChildrenDirective": true,
79+
"$$AnimateQueueProvider": true,
80+
"$$AnimationProvider": true,
81+
"$AnimateCssProvider": true,
82+
"$$AnimateCssDriverProvider": true,
83+
"$$AnimateJsProvider": true,
84+
"$$AnimateJsDriverProvider": true
7285
}
7386
}

src/ngAnimate/animateChildrenDirective.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ var $$AnimateChildrenDirective = ['$interpolate', function($interpolate) {
8282
return {
8383
link: function(scope, element, attrs) {
8484
var val = attrs.ngAnimateChildren;
85-
if (angular.isString(val) && val.length === 0) { //empty attribute
85+
if (isString(val) && val.length === 0) { //empty attribute
8686
element.data(NG_ANIMATE_CHILDREN_DATA, true);
8787
} else {
8888
// Interpolate and set the value, so that it is available to

src/ngAnimate/animateQueue.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
241241
},
242242

243243
off: function(event, container, callback) {
244-
if (arguments.length === 1 && !angular.isString(arguments[0])) {
244+
if (arguments.length === 1 && !isString(arguments[0])) {
245245
container = arguments[0];
246246
for (var eventType in callbackRegistry) {
247247
callbackRegistry[eventType] = filterFromRegistry(callbackRegistry[eventType], container);

src/ngAnimate/module.js

+29-15
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,5 @@
11
'use strict';
22

3-
/* global angularAnimateModule: true,
4-
5-
ngAnimateSwapDirective,
6-
$$AnimateAsyncRunFactory,
7-
$$rAFSchedulerFactory,
8-
$$AnimateChildrenDirective,
9-
$$AnimateQueueProvider,
10-
$$AnimationProvider,
11-
$AnimateCssProvider,
12-
$$AnimateCssDriverProvider,
13-
$$AnimateJsProvider,
14-
$$AnimateJsDriverProvider,
15-
*/
16-
173
/**
184
* @ngdoc module
195
* @name ngAnimate
@@ -730,6 +716,19 @@
730716
* (Note that you will need to trigger a digest within the callback to get angular to notice any scope-related changes.)
731717
*/
732718

719+
var copy;
720+
var extend;
721+
var forEach;
722+
var isArray;
723+
var isDefined;
724+
var isElement;
725+
var isFunction;
726+
var isObject;
727+
var isString;
728+
var isUndefined;
729+
var jqLite;
730+
var noop;
731+
733732
/**
734733
* @ngdoc service
735734
* @name $animate
@@ -740,7 +739,22 @@
740739
*
741740
* Click here {@link ng.$animate to learn more about animations with `$animate`}.
742741
*/
743-
angular.module('ngAnimate', [])
742+
angular.module('ngAnimate', [], function initAngularHelpers() {
743+
// Access helpers from angular core.
744+
// Do it inside a `config` block to ensure `window.angular` is available.
745+
noop = angular.noop;
746+
copy = angular.copy;
747+
extend = angular.extend;
748+
jqLite = angular.element;
749+
forEach = angular.forEach;
750+
isArray = angular.isArray;
751+
isString = angular.isString;
752+
isObject = angular.isObject;
753+
isUndefined = angular.isUndefined;
754+
isDefined = angular.isDefined;
755+
isFunction = angular.isFunction;
756+
isElement = angular.isElement;
757+
})
744758
.directive('ngAnimateSwap', ngAnimateSwapDirective)
745759

746760
.directive('ngAnimateChildren', $$AnimateChildrenDirective)

src/ngAnimate/shared.js

+4-24
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,5 @@
11
'use strict';
22

3-
/* jshint ignore:start */
4-
var noop = angular.noop;
5-
var copy = angular.copy;
6-
var extend = angular.extend;
7-
var jqLite = angular.element;
8-
var forEach = angular.forEach;
9-
var isArray = angular.isArray;
10-
var isString = angular.isString;
11-
var isObject = angular.isObject;
12-
var isUndefined = angular.isUndefined;
13-
var isDefined = angular.isDefined;
14-
var isFunction = angular.isFunction;
15-
var isElement = angular.isElement;
16-
173
var ELEMENT_NODE = 1;
184
var COMMENT_NODE = 8;
195

@@ -38,7 +24,7 @@ var CSS_PREFIX = '', TRANSITION_PROP, TRANSITIONEND_EVENT, ANIMATION_PROP, ANIMA
3824
// Also, the only modern browser that uses vendor prefixes for transitions/keyframes is webkit
3925
// therefore there is no reason to test anymore for other vendor prefixes:
4026
// http://caniuse.com/#search=transition
41-
if (isUndefined(window.ontransitionend) && isDefined(window.onwebkittransitionend)) {
27+
if ((window.ontransitionend === void 0) && (window.onwebkittransitionend !== void 0)) {
4228
CSS_PREFIX = '-webkit-';
4329
TRANSITION_PROP = 'WebkitTransition';
4430
TRANSITIONEND_EVENT = 'webkitTransitionEnd transitionend';
@@ -47,7 +33,7 @@ if (isUndefined(window.ontransitionend) && isDefined(window.onwebkittransitionen
4733
TRANSITIONEND_EVENT = 'transitionend';
4834
}
4935

50-
if (isUndefined(window.onanimationend) && isDefined(window.onwebkitanimationend)) {
36+
if ((window.onanimationend === void 0) && (window.onwebkitanimationend !== void 0)) {
5137
CSS_PREFIX = '-webkit-';
5238
ANIMATION_PROP = 'WebkitAnimation';
5339
ANIMATIONEND_EVENT = 'webkitAnimationEnd animationend';
@@ -69,10 +55,6 @@ var ANIMATION_DURATION_PROP = ANIMATION_PROP + DURATION_KEY;
6955
var TRANSITION_DELAY_PROP = TRANSITION_PROP + DELAY_KEY;
7056
var TRANSITION_DURATION_PROP = TRANSITION_PROP + DURATION_KEY;
7157

72-
var isPromiseLike = function(p) {
73-
return p && p.then ? true : false;
74-
};
75-
7658
var ngMinErr = angular.$$minErr('ng');
7759
function assertArg(arg, name, reason) {
7860
if (!arg) {
@@ -128,7 +110,6 @@ function stripCommentsFromElement(element) {
128110
switch (element.length) {
129111
case 0:
130112
return element;
131-
break;
132113

133114
case 1:
134115
// there is no point of stripping anything if the element
@@ -141,7 +122,6 @@ function stripCommentsFromElement(element) {
141122

142123
default:
143124
return jqLite(extractElementNode(element));
144-
break;
145125
}
146126
}
147127

@@ -182,7 +162,7 @@ function applyAnimationClassesFactory($$jqLite) {
182162
$$removeClass($$jqLite, element, options.removeClass);
183163
options.removeClass = null;
184164
}
185-
}
165+
};
186166
}
187167

188168
function prepareAnimationOptions(options) {
@@ -318,7 +298,7 @@ function resolveElementClasses(existing, toAdd, toRemove) {
318298
}
319299

320300
function getDomNode(element) {
321-
return (element instanceof angular.element) ? element[0] : element;
301+
return (element instanceof jqLite) ? element[0] : element;
322302
}
323303

324304
function applyGeneratedPreparationClasses(element, event, options) {

src/ngMessageFormat/messageFormatCommon.js

+3-5
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,9 @@
55
// This file is compiled with Closure compiler's ADVANCED_OPTIMIZATIONS flag! Be wary of using
66
// constructs incompatible with that mode.
77

8-
var $interpolateMinErr = window['angular']['$interpolateMinErr'];
9-
10-
var noop = window['angular']['noop'],
11-
isFunction = window['angular']['isFunction'],
12-
toJson = window['angular']['toJson'];
8+
/* global isFunction: false */
9+
/* global noop: false */
10+
/* global toJson: false */
1311

1412
function stringify(value) {
1513
if (value == null /* null/undefined */) { return ''; }

src/ngMessageFormat/messageFormatService.js

+14-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
// This file is compiled with Closure compiler's ADVANCED_OPTIMIZATIONS flag! Be wary of using
66
// constructs incompatible with that mode.
77

8-
/* global $interpolateMinErr: false */
8+
/* global $interpolateMinErr: true */
9+
/* global isFunction: true */
10+
/* global noop: true */
11+
/* global toJson: true */
912
/* global MessageFormatParser: false */
1013
/* global stringify: false */
1114

@@ -207,8 +210,18 @@ var $$interpolateDecorator = ['$$messageFormat', '$delegate', function $$interpo
207210
return interpolate;
208211
}];
209212

213+
var $interpolateMinErr;
214+
var isFunction;
215+
var noop;
216+
var toJson;
217+
210218
var module = window['angular']['module']('ngMessageFormat', ['ng']);
211219
module['factory']('$$messageFormat', $$MessageFormatFactory);
212220
module['config'](['$provide', function($provide) {
221+
$interpolateMinErr = window['angular']['$interpolateMinErr'];
222+
isFunction = window['angular']['isFunction'];
223+
noop = window['angular']['noop'];
224+
toJson = window['angular']['toJson'];
225+
213226
$provide['decorator']('$interpolate', $$interpolateDecorator);
214227
}]);

src/ngMessages/.jshintrc

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"extends": "../../.jshintrc-base",
3+
"globals": {
4+
"window": false,
5+
6+
"angular": false
7+
}
8+
}

src/ngMessages/messages.js

+12-8
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
'use strict';
22

3-
/* jshint ignore:start */
4-
// this code is in the core, but not in angular-messages.js
5-
var isArray = angular.isArray;
6-
var forEach = angular.forEach;
7-
var isString = angular.isString;
8-
var jqLite = angular.element;
9-
/* jshint ignore:end */
3+
var forEach;
4+
var isArray;
5+
var isString;
6+
var jqLite;
107

118
/**
129
* @ngdoc module
@@ -262,7 +259,14 @@ var jqLite = angular.element;
262259
*
263260
* {@link ngAnimate Click here} to learn how to use JavaScript animations or to learn more about ngAnimate.
264261
*/
265-
angular.module('ngMessages', [])
262+
angular.module('ngMessages', [], function initAngularHelpers() {
263+
// Access helpers from angular core.
264+
// Do it inside a `config` block to ensure `window.angular` is available.
265+
forEach = angular.forEach;
266+
isArray = angular.isArray;
267+
isString = angular.isString;
268+
jqLite = angular.element;
269+
})
266270

267271
/**
268272
* @ngdoc directive

0 commit comments

Comments
 (0)