10
10
splice,
11
11
push,
12
12
toString,
13
+ objectMaxDepthInErrorMessage,
14
+ errorHandlingConfig,
15
+ isValidObjectMaxDepth,
13
16
ngMinErr,
14
17
angularModule,
15
18
uid,
@@ -125,6 +128,50 @@ var VALIDITY_STATE_PROPERTY = 'validity';
125
128
126
129
var hasOwnProperty = Object . prototype . hasOwnProperty ;
127
130
131
+ var objectMaxDepthInErrorMessage = 5 ;
132
+
133
+ /**
134
+ * @ngdoc function
135
+ * @name angular.errorHandlingConfig
136
+ * @module ng
137
+ * @kind function
138
+ *
139
+ * @description
140
+ * Configure several aspects of error handling in AngularJS if used as a setter or return the
141
+ * current configuration if used as a getter. The following options are supported:
142
+ *
143
+ * - **objectMaxDepth**: The maximum depth to which objects are traversed when stringified for error messages.
144
+ *
145
+ * Omitted or undefined options will leave the corresponding configuration values unchanged.
146
+ *
147
+ * @param {Object= } config - The configuration object. May only contain the options that need to be
148
+ * updated. Supported keys:
149
+ *
150
+ * * `objectMaxDepth` **{Number}** - The max depth for stringifying objects. Setting to a
151
+ * non-positive or non-numeric value, removes the max depth limit.
152
+ * Default: 5
153
+ */
154
+ function errorHandlingConfig ( config ) {
155
+ if ( isObject ( config ) ) {
156
+ if ( isDefined ( config . objectMaxDepth ) ) {
157
+ objectMaxDepthInErrorMessage = isValidObjectMaxDepth ( config . objectMaxDepth ) ? config . objectMaxDepth : NaN ;
158
+ }
159
+ } else {
160
+ return {
161
+ objectMaxDepth : objectMaxDepthInErrorMessage
162
+ } ;
163
+ }
164
+ }
165
+
166
+ /**
167
+ * @private
168
+ * @param {Number } maxDepth
169
+ * @return {boolean }
170
+ */
171
+ function isValidObjectMaxDepth ( maxDepth ) {
172
+ return isNumber ( maxDepth ) && maxDepth > 0 ;
173
+ }
174
+
128
175
/**
129
176
* @ngdoc function
130
177
* @name angular.lowercase
@@ -796,6 +843,7 @@ function arrayRemove(array, value) {
796
843
* are deleted and then all elements/properties from the source are copied to it.
797
844
* * If `source` is not an object or array (inc. `null` and `undefined`), `source` is returned.
798
845
* * If `source` is identical to `destination` an exception will be thrown.
846
+ * * If `maxDepth` is supplied, all properties of the source will be copied until reaching the max depth.
799
847
*
800
848
* <br />
801
849
* <div class="alert alert-warning">
@@ -807,6 +855,7 @@ function arrayRemove(array, value) {
807
855
* Can be any type, including primitives, `null`, and `undefined`.
808
856
* @param {(Object|Array)= } destination Destination into which the source is copied. If
809
857
* provided, must be of the same type as `source`.
858
+ * @param {Number= } maxDepth All properties of the source will be copied until reaching the max depth.
810
859
* @returns {* } The copy or updated `destination`, if `destination` was specified.
811
860
*
812
861
* @example
@@ -847,9 +896,10 @@ function arrayRemove(array, value) {
847
896
</file>
848
897
</example>
849
898
*/
850
- function copy ( source , destination ) {
899
+ function copy ( source , destination , maxDepth ) {
851
900
var stackSource = [ ] ;
852
901
var stackDest = [ ] ;
902
+ maxDepth = isValidObjectMaxDepth ( maxDepth ) ? maxDepth : NaN ;
853
903
854
904
if ( destination ) {
855
905
if ( isTypedArray ( destination ) || isArrayBuffer ( destination ) ) {
@@ -872,43 +922,47 @@ function copy(source, destination) {
872
922
873
923
stackSource . push ( source ) ;
874
924
stackDest . push ( destination ) ;
875
- return copyRecurse ( source , destination ) ;
925
+ return copyRecurse ( source , destination , maxDepth ) ;
876
926
}
877
927
878
- return copyElement ( source ) ;
928
+ return copyElement ( source , maxDepth ) ;
879
929
880
- function copyRecurse ( source , destination ) {
930
+ function copyRecurse ( source , destination , maxDepth ) {
931
+ maxDepth -- ;
932
+ if ( maxDepth < 0 ) {
933
+ return '...' ;
934
+ }
881
935
var h = destination . $$hashKey ;
882
936
var key ;
883
937
if ( isArray ( source ) ) {
884
938
for ( var i = 0 , ii = source . length ; i < ii ; i ++ ) {
885
- destination . push ( copyElement ( source [ i ] ) ) ;
939
+ destination . push ( copyElement ( source [ i ] , maxDepth ) ) ;
886
940
}
887
941
} else if ( isBlankObject ( source ) ) {
888
942
// createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty
889
943
for ( key in source ) {
890
- destination [ key ] = copyElement ( source [ key ] ) ;
944
+ destination [ key ] = copyElement ( source [ key ] , maxDepth ) ;
891
945
}
892
946
} else if ( source && typeof source . hasOwnProperty === 'function' ) {
893
947
// Slow path, which must rely on hasOwnProperty
894
948
for ( key in source ) {
895
949
if ( source . hasOwnProperty ( key ) ) {
896
- destination [ key ] = copyElement ( source [ key ] ) ;
950
+ destination [ key ] = copyElement ( source [ key ] , maxDepth ) ;
897
951
}
898
952
}
899
953
} else {
900
954
// Slowest path --- hasOwnProperty can't be called as a method
901
955
for ( key in source ) {
902
956
if ( hasOwnProperty . call ( source , key ) ) {
903
- destination [ key ] = copyElement ( source [ key ] ) ;
957
+ destination [ key ] = copyElement ( source [ key ] , maxDepth ) ;
904
958
}
905
959
}
906
960
}
907
961
setHashKey ( destination , h ) ;
908
962
return destination ;
909
963
}
910
964
911
- function copyElement ( source ) {
965
+ function copyElement ( source , maxDepth ) {
912
966
// Simple values
913
967
if ( ! isObject ( source ) ) {
914
968
return source ;
@@ -937,7 +991,7 @@ function copy(source, destination) {
937
991
stackDest . push ( destination ) ;
938
992
939
993
return needsRecurse
940
- ? copyRecurse ( source , destination )
994
+ ? copyRecurse ( source , destination , maxDepth )
941
995
: destination ;
942
996
}
943
997
0 commit comments