Skip to content
This repository was archived by the owner on Feb 9, 2020. It is now read-only.

Commit f04d250

Browse files
committed
fix(loader): use the latest version with fewer modifications and fixed minErr
This commit updates `loader.js` based on `angular-loader.js` from angular/angular.js#15881, which is essentially the latest loader plus some `minErr` fixes (see angular/angular.js#15881 for more info). Additionally, the loader does a better job staying closer to the original `angular-loader` behavior for versions 1.3+ and it only modifies its behavior to support 1.2 apps. This change also fixes previously broken usecases that rely on private `angular.Module` APIs (see #88 for more info). Fixes #88 Closes #311
1 parent 4369cbc commit f04d250

File tree

5 files changed

+365
-153
lines changed

5 files changed

+365
-153
lines changed

dist/hint.js

+135-30
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*
55
* This gets loaded into the context of the app you are inspecting
66
*/
7-
require('./loader.js');
7+
require('./loader');
88
require('angular-hint');
99

1010
angular.hint.onAny(function (event, data, severity) {
@@ -25,19 +25,131 @@ angular.hint.onAny(function (event, data, severity) {
2525
}, '*');
2626
});
2727

28-
},{"./loader.js":2,"angular-hint":3}],2:[function(require,module,exports){
28+
},{"./loader":2,"angular-hint":3}],2:[function(require,module,exports){
29+
// BATARANG
30+
// Loader file based on `angular-loader.js` v1.6.5-local+sha.59dbff0c7
31+
// (https://github.com/angular/angular.js/pull/15881).
32+
// Modified regions should be marked with `// BATARANG` comments.
2933
/**
30-
* @license AngularJS v1.6.4-build.5322+sha.d96e58f
34+
* @license AngularJS v1.6.5-local+sha.59dbff0c7
3135
* (c) 2010-2017 Google, Inc. http://angularjs.org
3236
* License: MIT
3337
*/
3438

3539
(function() {'use strict';
40+
function isFunction(value) {return typeof value === 'function';}
41+
function isDefined(value) {return typeof value !== 'undefined';}
42+
function isNumber(value) {return typeof value === 'number';}
43+
function isObject(value) {return value !== null && typeof value === 'object';}
44+
function isScope(obj) {return obj && obj.$evalAsync && obj.$watch;}
45+
function isWindow(obj) {return obj && obj.window === obj;}
46+
function sliceArgs(args, startIndex) {return Array.prototype.slice.call(args, startIndex || 0);}
47+
function toJsonReplacer(key, value) {
48+
var val = value;
49+
50+
if (typeof key === 'string' && key.charAt(0) === '$' && key.charAt(1) === '$') {
51+
val = undefined;
52+
} else if (isWindow(value)) {
53+
val = '$WINDOW';
54+
} else if (value && window.document === value) {
55+
val = '$DOCUMENT';
56+
} else if (isScope(value)) {
57+
val = '$SCOPE';
58+
}
59+
60+
return val;
61+
}
62+
63+
/* exported toDebugString */
64+
65+
// This file is also included in `angular-loader`, so `copy()` might not always be available in the
66+
// closure. In such cases, it is lazily retrieved as `angular.copy()` when needed.
67+
var copyFn;
68+
69+
function serializeObject(obj, maxDepth) {
70+
var seen = [];
71+
72+
// There is no direct way to stringify object until reaching a specific depth
73+
// and a very deep object can cause a performance issue, so we copy the object
74+
// based on this specific depth and then stringify it.
75+
if (isValidObjectMaxDepth(maxDepth)) {
76+
if (!copyFn) {
77+
copyFn = copy || angular.copy;
78+
}
79+
obj = copyFn(obj, null, maxDepth);
80+
}
81+
return JSON.stringify(obj, function(key, val) {
82+
val = toJsonReplacer(key, val);
83+
if (isObject(val)) {
84+
85+
if (seen.indexOf(val) >= 0) return '...';
86+
87+
seen.push(val);
88+
}
89+
return val;
90+
});
91+
}
92+
93+
function toDebugString(obj, maxDepth) {
94+
if (typeof obj === 'function') {
95+
return obj.toString().replace(/ \{[\s\S]*$/, '');
96+
} else if (isUndefined(obj)) {
97+
return 'undefined';
98+
} else if (typeof obj !== 'string') {
99+
return serializeObject(obj, maxDepth);
100+
}
101+
return obj;
102+
}
103+
104+
/* exported
105+
minErrConfig,
106+
errorHandlingConfig,
107+
isValidObjectMaxDepth
108+
*/
109+
110+
var minErrConfig = {
111+
objectMaxDepth: 5
112+
};
36113

114+
/**
115+
* @ngdoc function
116+
* @name angular.errorHandlingConfig
117+
* @module ng
118+
* @kind function
119+
*
120+
* @description
121+
* Configure several aspects of error handling in AngularJS if used as a setter or return the
122+
* current configuration if used as a getter. The following options are supported:
123+
*
124+
* - **objectMaxDepth**: The maximum depth to which objects are traversed when stringified for error messages.
125+
*
126+
* Omitted or undefined options will leave the corresponding configuration values unchanged.
127+
*
128+
* @param {Object=} config - The configuration object. May only contain the options that need to be
129+
* updated. Supported keys:
130+
*
131+
* * `objectMaxDepth` **{Number}** - The max depth for stringifying objects. Setting to a
132+
* non-positive or non-numeric value, removes the max depth limit.
133+
* Default: 5
134+
*/
135+
function errorHandlingConfig(config) {
136+
if (isObject(config)) {
137+
if (isDefined(config.objectMaxDepth)) {
138+
minErrConfig.objectMaxDepth = isValidObjectMaxDepth(config.objectMaxDepth) ? config.objectMaxDepth : NaN;
139+
}
140+
} else {
141+
return minErrConfig;
142+
}
143+
}
37144

38-
function isFunction(value) { return typeof value === 'function'; }
39-
function isDefined(value) { return typeof value !== 'undefined'; }
40-
function isObject(value) { return value !== null && typeof value === 'object'; }
145+
/**
146+
* @private
147+
* @param {Number} maxDepth
148+
* @return {boolean}
149+
*/
150+
function isValidObjectMaxDepth(maxDepth) {
151+
return isNumber(maxDepth) && maxDepth > 0;
152+
}
41153

42154
/**
43155
* @description
@@ -69,25 +181,15 @@ function isObject(value) { return value !== null && typeof value === 'object'; }
69181
* @returns {function(code:string, template:string, ...templateArgs): Error} minErr instance
70182
*/
71183

72-
function toDebugString(obj) {
73-
if (typeof obj === 'function') {
74-
return obj.toString().replace(/ ?\{[\s\S]*$/, '');
75-
} else if (typeof obj === 'undefined') {
76-
return 'undefined';
77-
} else if (typeof obj !== 'string') {
78-
return JSON.stringify(obj);
79-
}
80-
return obj;
81-
}
82-
83184
function minErr(module, ErrorConstructor) {
84185
ErrorConstructor = ErrorConstructor || Error;
85186
return function() {
86187
var code = arguments[0],
87188
template = arguments[1],
88-
version = (angular.version && angular.version.full) || 'snapshot',
89189
message = '[' + (module ? module + ':' : '') + code + '] ',
90-
templateArgs = Array.prototype.slice.call(arguments, 2).map(toDebugString),
190+
templateArgs = sliceArgs(arguments, 2).map(function(arg) {
191+
return toDebugString(arg, minErrConfig.objectMaxDepth);
192+
}),
91193
paramPrefix, i;
92194

93195
message += template.replace(/\{\d+\}/g, function(match) {
@@ -96,9 +198,13 @@ function minErr(module, ErrorConstructor) {
96198
if (index < templateArgs.length) {
97199
return templateArgs[index];
98200
}
201+
99202
return match;
100203
});
101204

205+
// BATARANG
206+
// Use the app's version in error URLs instead of the version this file was based on.
207+
var version = (angular.version && angular.version.full) || 'snapshot';
102208
message += '\nhttp://errors.angularjs.org/' + version + '/' +
103209
(module ? module + '/' : '') + code;
104210

@@ -223,9 +329,11 @@ function setupModuleLoader(window) {
223329
/** @type {angular.Module} */
224330
var moduleInstance = {
225331
// Private state
226-
// ANGULAR HINT ALTERATION
227-
// See the definition of `_invokeQueue` below for more info.
228-
_configBlocks: [],
332+
// BATARANG
333+
// `_invokeQueue` needs to be handled in a special way in order to support both v1.2 and
334+
// v1.3+ apps. See its definition below for more details.
335+
//_invokeQueue: invokeQueue,
336+
_configBlocks: configBlocks,
229337
_runBlocks: runBlocks,
230338

231339
/**
@@ -477,16 +585,13 @@ function setupModuleLoader(window) {
477585
}
478586
};
479587

480-
/**
481-
* ANGULAR HINT ALTERATION
482-
* To make this loader compatible with apps that are running both Angular 1.2 and 1.3+, the
483-
* loader must handle 1.3+ applications that expect to initialize their config blocks after
484-
* all providers are registered. Hence, an empty `_configBlocks` array is exposed on
485-
* `moduleInstance` and the actual `configBlocks` are added to the end of the `invokeQueue`.
486-
*/
588+
// BATARANG
589+
// To make this loader compatible with both AngularJS v1.2 and v1.3+ apps, it must handle
590+
// v1.2 apps that do not know about `_configBlocks` and expect everything to be on the
591+
// `_invokeQueue`.
487592
Object.defineProperty(moduleInstance, '_invokeQueue', {
488593
get: function() {
489-
return invokeQueue.concat(configBlocks);
594+
return (angular.version.minor <= 2) ? invokeQueue.concat(configBlocks) : invokeQueue;
490595
}
491596
});
492597

hint.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* This gets loaded into the context of the app you are inspecting
55
*/
6-
require('./loader.js');
6+
require('./loader');
77
require('angular-hint');
88

99
angular.hint.onAny(function (event, data, severity) {

0 commit comments

Comments
 (0)