@@ -1138,6 +1138,19 @@ function encodeUriQuery(val, pctEncodeSpaces) {
1138
1138
replace ( / % 2 0 / g, ( pctEncodeSpaces ? '%20' : '+' ) ) ;
1139
1139
}
1140
1140
1141
+ var ngAttrPrefixes = [ 'ng-' , 'data-ng-' , 'ng:' , 'x-ng-' ] ;
1142
+
1143
+ function getNgAttribute ( element , ngAttr ) {
1144
+ var attr , i , ii = ngAttrPrefixes . length , j , jj ;
1145
+ element = jqLite ( element ) ;
1146
+ for ( i = 0 ; i < ii ; ++ i ) {
1147
+ attr = ngAttrPrefixes [ i ] + ngAttr ;
1148
+ if ( isString ( attr = element . attr ( attr ) ) ) {
1149
+ return attr ;
1150
+ }
1151
+ }
1152
+ return null ;
1153
+ }
1141
1154
1142
1155
/**
1143
1156
* @ngdoc directive
@@ -1147,6 +1160,11 @@ function encodeUriQuery(val, pctEncodeSpaces) {
1147
1160
* @element ANY
1148
1161
* @param {angular.Module } ngApp an optional application
1149
1162
* {@link angular.module module} name to load.
1163
+ * @param {boolean= } ngStrictDi if this attribute is present on the app element, the injector will be
1164
+ * created in "strict-di" mode. This means that the application will fail to invoke functions which
1165
+ * do not use explicit function annotation (and are thus unsuitable for minification), as described
1166
+ * in {@link guide/di the Dependency Injection guide}, and useful debugging info will assist in
1167
+ * tracking down the root of these bugs.
1150
1168
*
1151
1169
* @description
1152
1170
*
@@ -1184,12 +1202,92 @@ function encodeUriQuery(val, pctEncodeSpaces) {
1184
1202
</file>
1185
1203
</example>
1186
1204
*
1205
+ * Using `ngStrictDi`, you would see something like this:
1206
+ *
1207
+ <example ng-app-included="true">
1208
+ <file name="index.html">
1209
+ <div ng-app="ngAppStrictDemo" ng-strict-di>
1210
+ <div ng-controller="GoodController1">
1211
+ I can add: {{a}} + {{b}} = {{ a+b }}
1212
+
1213
+ <p>This renders because the controller does not fail to
1214
+ instantiate, by using explicit annotation style (see
1215
+ script.js for details)
1216
+ </p>
1217
+ </div>
1218
+
1219
+ <div ng-controller="GoodController2">
1220
+ Name: <input ng-model="name"><br />
1221
+ Hello, {{name}}!
1222
+
1223
+ <p>This renders because the controller does not fail to
1224
+ instantiate, by using explicit annotation style
1225
+ (see script.js for details)
1226
+ </p>
1227
+ </div>
1228
+
1229
+ <div ng-controller="BadController">
1230
+ I can add: {{a}} + {{b}} = {{ a+b }}
1231
+
1232
+ <p>The controller could not be instantiated, due to relying
1233
+ on automatic function annotations (which are disabled in
1234
+ strict mode). As such, the content of this section is not
1235
+ interpolated, and there should be an error in your web console.
1236
+ </p>
1237
+ </div>
1238
+ </div>
1239
+ </file>
1240
+ <file name="script.js">
1241
+ angular.module('ngAppStrictDemo', [])
1242
+ // BadController will fail to instantiate, due to relying on automatic function annotation,
1243
+ // rather than an explicit annotation
1244
+ .controller('BadController', function($scope) {
1245
+ $scope.a = 1;
1246
+ $scope.b = 2;
1247
+ })
1248
+ // Unlike BadController, GoodController1 and GoodController2 will not fail to be instantiated,
1249
+ // due to using explicit annotations using the array style and $inject property, respectively.
1250
+ .controller('GoodController1', ['$scope', function($scope) {
1251
+ $scope.a = 1;
1252
+ $scope.b = 2;
1253
+ }])
1254
+ .controller('GoodController2', GoodController2);
1255
+ function GoodController2($scope) {
1256
+ $scope.name = "World";
1257
+ }
1258
+ GoodController2.$inject = ['$scope'];
1259
+ </file>
1260
+ <file name="style.css">
1261
+ div[ng-controller] {
1262
+ margin-bottom: 1em;
1263
+ -webkit-border-radius: 4px;
1264
+ border-radius: 4px;
1265
+ border: 1px solid;
1266
+ padding: .5em;
1267
+ }
1268
+ div[ng-controller^=Good] {
1269
+ border-color: #d6e9c6;
1270
+ background-color: #dff0d8;
1271
+ color: #3c763d;
1272
+ }
1273
+ div[ng-controller^=Bad] {
1274
+ border-color: #ebccd1;
1275
+ background-color: #f2dede;
1276
+ color: #a94442;
1277
+ margin-bottom: 0;
1278
+ }
1279
+ </file>
1280
+ </example>
1187
1281
*/
1188
1282
function angularInit ( element , bootstrap ) {
1189
1283
var elements = [ element ] ,
1190
1284
appElement ,
1191
1285
module ,
1286
+ config = { } ,
1192
1287
names = [ 'ng:app' , 'ng-app' , 'x-ng-app' , 'data-ng-app' ] ,
1288
+ options = {
1289
+ 'boolean' : [ 'strict-di' ]
1290
+ } ,
1193
1291
NG_APP_CLASS_REGEXP = / \s n g [: \- ] a p p ( : \s * ( [ \w \d _ ] + ) ; ? ) ? \s / ;
1194
1292
1195
1293
function append ( element ) {
@@ -1225,7 +1323,8 @@ function angularInit(element, bootstrap) {
1225
1323
}
1226
1324
} ) ;
1227
1325
if ( appElement ) {
1228
- bootstrap ( appElement , module ? [ module ] : [ ] ) ;
1326
+ config . strictDi = getNgAttribute ( appElement , "strict-di" ) !== null ;
1327
+ bootstrap ( appElement , module ? [ module ] : [ ] , config ) ;
1229
1328
}
1230
1329
}
1231
1330
@@ -1271,9 +1370,20 @@ function angularInit(element, bootstrap) {
1271
1370
* Each item in the array should be the name of a predefined module or a (DI annotated)
1272
1371
* function that will be invoked by the injector as a run block.
1273
1372
* See: {@link angular.module modules}
1373
+ * @param {Object= } config an object for defining configuration options for the application. The
1374
+ * following keys are supported:
1375
+ *
1376
+ * - `strictDi`: disable automatic function annotation for the application. This is meant to
1377
+ * assist in finding bugs which break minified code.
1378
+ *
1274
1379
* @returns {auto.$injector } Returns the newly created injector for this app.
1275
1380
*/
1276
- function bootstrap ( element , modules ) {
1381
+ function bootstrap ( element , modules , config ) {
1382
+ if ( ! isObject ( config ) ) config = { } ;
1383
+ var defaultConfig = {
1384
+ strictDi : false
1385
+ } ;
1386
+ config = extend ( defaultConfig , config ) ;
1277
1387
var doBootstrap = function ( ) {
1278
1388
element = jqLite ( element ) ;
1279
1389
@@ -1287,7 +1397,7 @@ function bootstrap(element, modules) {
1287
1397
$provide . value ( '$rootElement' , element ) ;
1288
1398
} ] ) ;
1289
1399
modules . unshift ( 'ng' ) ;
1290
- var injector = createInjector ( modules ) ;
1400
+ var injector = createInjector ( modules , config . strictDi ) ;
1291
1401
injector . invoke ( [ '$rootScope' , '$rootElement' , '$compile' , '$injector' , '$animate' ,
1292
1402
function ( scope , element , compile , injector , animate ) {
1293
1403
scope . $apply ( function ( ) {
0 commit comments